1 /* rglobr.c
2  *
3  * Copyright (c) 1996-2005 Mike Gleason, NcFTP Software.
4  * All rights reserved.
5  *
6  */
7 
8 #include "syshdrs.h"
9 #ifdef PRAGMA_HDRSTOP
10 #	pragma hdrstop
11 #endif
12 
13 #if 0
14 static void
15 printls(LineListPtr list)
16 {
17 	LinePtr fip;
18 	int i;
19 
20 	for (i = 1, fip = list->first; fip != NULL; fip = fip->next, i++)
21 		printf("%4d: %s\n", i, fip->line == NULL ? "NULL" : fip->line);
22 }
23 
24 static void
25 print1(FTPFileInfoListPtr list)
26 {
27 	FTPFileInfoPtr fip;
28 	int i;
29 
30 	for (i = 1, fip = list->first; fip != NULL; fip = fip->next, i++)
31 		printf("%4d: %s\n", i, fip->relname == NULL ? "NULL" : fip->relname);
32 }
33 
34 
35 
36 static void
37 print2(FTPFileInfoListPtr list)
38 {
39 	FTPFileInfoPtr fip;
40 	int i, n;
41 
42 	n = list->nFileInfos;
43 	for (i=0; i<n; i++) {
44 		fip = list->vec[i];
45 		printf("%4d: %s\n", i + 1, fip->relname == NULL ? "NULL" : fip->relname);
46 	}
47 }
48 
49 
50 
51 
52 static void
53 SortRecursiveFileList(FTPFileInfoListPtr files)
54 {
55 	VectorizeFileInfoList(files);
56 	SortFileInfoList(files, 'b', '?');
57 	UnvectorizeFileInfoList(files);
58 }	/* SortRecursiveFileList */
59 #endif
60 
61 struct MyFtwExtraInfo {
62 	size_t limitMaxDirs;
63 	size_t limitMaxFiles;
64 	size_t limitMaxDepth;
65 	FTPFileInfoListPtr fileList;
66 };
67 
68 int
FTPRemoteFtwProc(const FtwInfoPtr ftwip)69 FTPRemoteFtwProc(const FtwInfoPtr ftwip)
70 {
71 	struct MyFtwExtraInfo *xinfop = (struct MyFtwExtraInfo *) ftwip->userdata;
72 	FTPCIPtr cip = (FTPCIPtr) ftwip->cip;
73 	FTPFileInfo fi;
74 
75 	if ((xinfop->limitMaxDepth != 0) && (ftwip->depth >= xinfop->limitMaxDepth)) {
76 		FTPLogError(cip, kDontPerror, "Depth limit reached (%u dirs deep).\n", (unsigned int) ftwip->depth);
77 		return (-1);
78 	}
79 
80 	InitFileInfo(&fi);
81 	if (strncmp(ftwip->curPath, "./", 2) == 0) {
82 		fi.relnameLen = ftwip->curPathLen - 2;
83 		fi.relname = StrDup(ftwip->curPath + 2);
84 	} else if (strcmp(ftwip->curPath, ".") == 0) {
85 		/* Don't need starting directory */
86 		return (0);
87 	} else {
88 		fi.relnameLen = ftwip->curPathLen;
89 		fi.relname = StrDup(ftwip->curPath);
90 	}
91 	fi.rname = NULL;
92 	fi.lname = NULL;
93 	fi.rlinkto = (ftwip->rlinkto == NULL) ? NULL : StrDup(ftwip->rlinkto);
94 	fi.mdtm = ftwip->curStat.st_mtime;
95 	fi.size = (longest_int) ftwip->curStat.st_size;
96 	fi.type = ftwip->curType;
97 	fi.mode = (int) ftwip->curStat.st_mode;
98 	AddFileInfo(xinfop->fileList, &fi);
99 
100 	/*
101 fprintf(stderr, "(%c) relname [%s], rlinkto [%s], mdtm %lld, size %lld, mode %08o\n", fi.type, fi.relname, fi.rlinkto == NULL ? "" : fi.rlinkto, fi.mdtm, fi.size, fi.mode);
102 	*/
103 
104 	if ((xinfop->limitMaxDirs != 0) && (ftwip->numDirs >= xinfop->limitMaxDirs)) {
105 		FTPLogError(cip, kDontPerror, "Max subdirs limit (%u) reached.\n", (unsigned int) ftwip->numDirs);
106 		return (-1);
107 	}
108 	if ((xinfop->limitMaxFiles != 0) && (ftwip->numFiles >= xinfop->limitMaxFiles)) {
109 		FTPLogError(cip, kDontPerror, "Max files limit (%u) reached.\n", (unsigned int) ftwip->numFiles);
110 		return (-1);
111 	}
112 	return (0);
113 }	/* FTPRemoteFtwProc */
114 
115 
116 
117 
118 int
FTPRemoteRecursiveFileList2(FTPCIPtr cip,char * const rdir,FTPFileInfoListPtr files)119 FTPRemoteRecursiveFileList2(FTPCIPtr cip, char *const rdir, FTPFileInfoListPtr files)
120 {
121 	int result;
122 	char rcwd[512];
123 	FtwInfo ftwi;
124 	struct MyFtwExtraInfo xinfo;
125 
126 	if ((result = FTPGetCWD(cip, rcwd, sizeof(rcwd))) < 0)
127 		return (result);
128 
129 	InitFileInfoList(files);
130 
131 	if (rdir == NULL)
132 		return (-1);
133 
134 	if (FTPChdir(cip, rdir) < 0) {
135 		/* Probably not a directory.
136 		 * Just add it as a plain file
137 		 * to the list.
138 		 */
139 		(void) ConcatFileToFileInfoList(files, rdir);
140 		return (kNoErr);
141 	}
142 
143 	FtwInit(&ftwi);
144 
145 	xinfo.limitMaxDirs = 0;
146 	xinfo.limitMaxFiles = 0;
147 	xinfo.limitMaxDepth = 50;
148 	xinfo.fileList = files;
149 	ftwi.userdata = &xinfo;
150 
151 	/* Paths collected must be relative. */
152 	if ((result = FTPFtw(cip, &ftwi, ".", FTPRemoteFtwProc)) != 0) {
153 		FTPPerror(cip, cip->errNo, kErrCWDFailed, "Could not traverse directory", NULL);
154 		if ((result = FTPChdir(cip, rcwd)) < 0) {
155 			rcwd[0] = '\0';
156 		}
157 		FtwDispose(&ftwi);
158 		return (result);
159 	}
160 	FtwDispose(&ftwi);
161 
162 	/* print1(&fil); */
163 	/* Could sort it to breadth-first here. */
164 	/* (void) SortRecursiveFileList(&fil); */
165 	(void) ComputeRNames(files, rdir, 1, 1);
166 
167 	if ((result = FTPChdir(cip, rcwd)) < 0) {
168 		rcwd[0] = '\0';
169 		return (result);
170 	}
171 	return (kNoErr);
172 }	/* FTPRemoteRecursiveFileList2 */
173 
174 
175 
176 
177 int
FTPRemoteRecursiveFileList1(FTPCIPtr cip,char * const rdir,FTPFileInfoListPtr files)178 FTPRemoteRecursiveFileList1(FTPCIPtr cip, char *const rdir, FTPFileInfoListPtr files)
179 {
180 	FTPLineList dirContents;
181 	FTPFileInfoList fil;
182 	int result;
183 	char rcwd[512];
184 
185 	if ((result = FTPGetCWD(cip, rcwd, sizeof(rcwd))) < 0)
186 		return (result);
187 
188 	InitFileInfoList(files);
189 
190 	if (rdir == NULL)
191 		return (-1);
192 
193 	if (FTPChdir(cip, rdir) < 0) {
194 		/* Probably not a directory.
195 		 * Just add it as a plain file
196 		 * to the list.
197 		 */
198 		(void) ConcatFileToFileInfoList(files, rdir);
199 		return (kNoErr);
200 	}
201 
202 	/* Paths collected must be relative. */
203 	if ((result = FTPListToMemory2(cip, "", &dirContents, "-lRa", 1, (int *) 0)) < 0) {
204 		if ((result = FTPChdir(cip, rcwd)) < 0) {
205 			rcwd[0] = '\0';
206 		}
207 		return (result);
208 	}
209 
210 #if 0
211 DisposeLineListContents(&dirContents);
212 InitLineList(&dirContents);
213 AddLine(&dirContents, "drwx------   2 ftpuser  ftpuser       4096 Oct 13 02:12 in");
214 AddLine(&dirContents, "drwx------   2 ftpuser  ftpuser       4096 Oct 13 02:07 ../out");
215 AddLine(&dirContents, "drwx------   2 ftpuser  ftpuser       4096 Oct 13 02:11 out2");
216 AddLine(&dirContents, "drwx------   2 ftpuser  ftpuser       4096 Oct 13 02:11 /usr/tmp/zzzin");
217 AddLine(&dirContents, "");
218 AddLine(&dirContents, "./in:");
219 AddLine(&dirContents, "-rw-r--r--   1 ftpuser  ftpuser      18475 Oct 13 01:58 test_dos.txt");
220 AddLine(&dirContents, "-rw-r--r--   1 ftpuser  ftpuser      17959 Oct 13 01:57 ../test_mac.txt");
221 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17959 Oct 13 01:56 test_unix.txt");
222 AddLine(&dirContents, "");
223 AddLine(&dirContents, "./../out:");
224 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17969 Oct 13 01:58 test_dos.txt");
225 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17959 Oct 13 01:57 test_mac.txt");
226 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17959 Oct 13 01:56 test_unix.txt");
227 AddLine(&dirContents, "");
228 AddLine(&dirContents, "./out2/../foob:");
229 /* AddLine(&dirContents, "/tmp/out2:"); */
230 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17969 Oct 13 02:08 test_dos.txt");
231 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17959 Oct 13 02:08 test_mac.txt");
232 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17959 Oct 13 02:08 test_unix.txt");
233 AddLine(&dirContents, "");
234 AddLine(&dirContents, "/usr/tmp/zzzin:");
235 AddLine(&dirContents, "-rw-r--r--   1 ftpuser  ftpuser      18475 Oct 13 01:58 test_dos.txt");
236 AddLine(&dirContents, "-rw-r--r--   1 ftpuser  ftpuser      17959 Oct 13 01:57 test_mac.txt");
237 AddLine(&dirContents, "-rw-------   1 ftpuser  ftpuser      17959 Oct 13 01:56 test_unix.txt");
238 #endif
239 
240 	/* printls(&dirContents); */
241 	(void) UnLslR(cip, &fil, &dirContents, cip->serverType);
242 	DisposeLineListContents(&dirContents);
243 	/* print1(&fil); */
244 	/* Could sort it to breadth-first here. */
245 	/* (void) SortRecursiveFileList(&fil); */
246 	(void) ComputeRNames(&fil, rdir, 1, 1);
247 	(void) ConcatFileInfoList(files, &fil);
248 	DisposeFileInfoListContents(&fil);
249 
250 	if ((result = FTPChdir(cip, rcwd)) < 0) {
251 		rcwd[0] = '\0';
252 		return (result);
253 	}
254 	return (kNoErr);
255 }	/* FTPRemoteRecursiveFileList1 */
256 
257 
258 
259 
260 int
FTPRemoteRecursiveFileList(FTPCIPtr cip,FTPLineListPtr fileList,FTPFileInfoListPtr files)261 FTPRemoteRecursiveFileList(FTPCIPtr cip, FTPLineListPtr fileList, FTPFileInfoListPtr files)
262 {
263 	FTPLinePtr filePtr, nextFilePtr;
264 	FTPLineList dirContents;
265 	FTPFileInfoList fil;
266 	int result;
267 	char *rdir;
268 	char rcwd[512];
269 
270 	if ((result = FTPGetCWD(cip, rcwd, sizeof(rcwd))) < 0)
271 		return (result);
272 
273 	InitFileInfoList(files);
274 
275 	for (filePtr = fileList->first;
276 		filePtr != NULL;
277 		filePtr = nextFilePtr)
278 	{
279 		nextFilePtr = filePtr->next;
280 
281 		rdir = filePtr->line;
282 		if (rdir == NULL)
283 			continue;
284 
285 		if (FTPChdir(cip, rdir) < 0) {
286 			/* Probably not a directory.
287 			 * Just add it as a plain file
288 			 * to the list.
289 			 */
290 			(void) ConcatFileToFileInfoList(files, rdir);
291 			continue;
292 		}
293 
294 		/* Paths collected must be relative. */
295 		if ((result = FTPListToMemory2(cip, "", &dirContents, "-lRa", 1, (int *) 0)) < 0) {
296 			goto goback;
297 		}
298 
299 		(void) UnLslR(cip, &fil, &dirContents, cip->serverType);
300 		DisposeLineListContents(&dirContents);
301 		(void) ComputeRNames(&fil, rdir, 1, 1);
302 		(void) ConcatFileInfoList(files, &fil);
303 		DisposeFileInfoListContents(&fil);
304 
305 goback:
306 		if ((result = FTPChdir(cip, rcwd)) < 0) {
307 			rcwd[0] = '\0';
308 			return (result);
309 		}
310 	}
311 	return (kNoErr);
312 }	/* FTPRemoteRecursiveFileList */
313