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