ReactOS 0.4.16-dev-336-gb667d82
glob.c
Go to the documentation of this file.
1/* glob.c
2 *
3 * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
4 * All rights reserved.
5 *
6 */
7
8#include "syshdrs.h"
9
10static const char *rwx[9] = { "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx", NULL };
11
12
13
14/* We need to use this because using NLST gives us more stuff than
15 * we want back sometimes. For example, say we have:
16 *
17 * /a (directory)
18 * /a/b (directory)
19 * /a/b/b1
20 * /a/b/b2
21 * /a/b/b3
22 * /a/c (directory)
23 * /a/c/c1
24 * /a/c/c2
25 * /a/c/c3
26 * /a/file
27 *
28 * If you did an "echo /a/<star>" in a normal unix shell, you would expect
29 * to get back /a/b /a/c /a/file. But NLST gives back:
30 *
31 * /a/b/b1
32 * /a/b/b2
33 * /a/b/b3
34 * /a/c/c1
35 * /a/c/c2
36 * /a/c/c3
37 * /a/file
38 *
39 * So we use the following routine to convert into the format I expect.
40 */
41
42static void
44{
45 LinePtr lp, nextLine;
46 string patPrefix;
47 string cur, prev;
48 char *endp, *cp, *dp;
49 const char *pp;
50 int wasGlobChar;
51 size_t plen;
52
53 /* Copy all characters before the first glob-char. */
54 dp = patPrefix;
55 endp = dp + sizeof(patPrefix) - 1;
56 wasGlobChar = 0;
57 for (cp = (char *) pattern; dp < endp; ) {
58 for (pp=kGlobChars; *pp != '\0'; pp++) {
59 if (*pp == *cp) {
60 wasGlobChar = 1;
61 break;
62 }
63 }
64 if (wasGlobChar)
65 break;
66 *dp++ = *cp++;
67 }
68 *dp = '\0';
69 plen = (size_t) (dp - patPrefix);
70
71 *prev = '\0';
72 for (lp=fileList->first; lp != NULL; lp = nextLine) {
73 nextLine = lp->next;
74 if (strncmp(lp->line, patPrefix, plen) == 0) {
75 (void) STRNCPY(cur, lp->line + plen);
76 cp = strchr(cur, '/');
77 if (cp == NULL)
78 cp = strchr(cur, '\\');
79 if (cp != NULL)
80 *cp = '\0';
81 if ((*prev != '\0') && (STREQ(cur, prev))) {
82 nextLine = RemoveLine(fileList, lp);
83 } else {
84 (void) STRNCPY(prev, cur);
85 /* We are playing with a dynamically
86 * allocated string, but since the
87 * following expression is guaranteed
88 * to be the same or shorter, we won't
89 * overwrite the bounds.
90 */
91 (void) sprintf(lp->line, "%s%s", patPrefix, cur);
92 }
93 }
94 }
95} /* RemoteGlobCollapse */
96
97
98
99
100#if 0
101/* May need this later. */
102static void
103CheckForLS_d(FTPCIPtr cip)
104{
106 char *cp;
107
109 if (FTPListToMemory2(cip, ".", &lines, "-d ", 0, (int *) 0) == kNoErr) {
110 if ((lines.first != NULL) && (lines.first == lines.last)) {
111 /* If we have only one item in the list, see if it really was
112 * an error message we would recognize.
113 */
114 cp = strchr(lines.first->line, ':');
115 if ((cp != NULL) && STREQ(cp, ": No such file or directory")) {
117 } else {
119 }
120 } else {
122 }
123 } else {
125 }
127 }
128} /* CheckForLS_d */
129#endif
130
131
132
133
134static int
136{
137 int mon; /* 0..11 */
138
139 switch (*cp++) {
140 case 'A':
141 mon = (*cp == 'u') ? 7 : 3;
142 break;
143 case 'D':
144 mon = 11;
145 break;
146 case 'F':
147 mon = 1;
148 break;
149 default:
150 case 'J':
151 if (*cp++ == 'u')
152 mon = (*cp == 'l') ? 6 : 5;
153 else
154 mon = 0;
155 break;
156 case 'M':
157 mon = (*++cp == 'r') ? 2 : 4;
158 break;
159 case 'N':
160 mon = 10;
161 break;
162 case 'O':
163 mon = 9;
164 break;
165 case 'S':
166 mon = 8;
167 }
168 return (mon);
169} /* LsMonthNameToNum */
170
171
172
173
174static int
175UnDosLine( char *const line,
176 const char *const curdir,
177 size_t curdirlen,
178 char *fname,
179 size_t fnamesize,
180 int *ftype,
182 time_t *ftime)
183{
184 char *cp;
185 int hour, year;
186 char *filestart;
187 char *sizestart;
188 struct tm ftm;
189
190 /*
191 *
1920123456789012345678901234567890123456789012345678901234567890123456789
19304-27-99 10:32PM 270158 Game booklet.pdf
19403-11-99 10:03PM <DIR> Get A3d Banner
195
196We also try to parse the format from CMD.EXE, which is similar:
197
19803/22/2001 06:23p 62,325 cls.pdf
199
200 *
201 */
202 cp = line;
203 if (
204 isdigit((int) cp[0])
205 && isdigit((int) cp[1])
206 && ispunct((int) cp[2])
207 && isdigit((int) cp[3])
208 && isdigit((int) cp[4])
209 && ispunct((int) cp[5])
210 && isdigit((int) cp[6])
211 && isdigit((int) cp[7])
212 ) {
213 (void) memset(&ftm, 0, sizeof(struct tm));
214 ftm.tm_isdst = -1;
215 cp[2] = '\0';
216 ftm.tm_mon = atoi(cp + 0);
217 if (ftm.tm_mon > 0)
218 ftm.tm_mon -= 1;
219 cp[5] = '\0';
220 ftm.tm_mday = atoi(cp + 3);
221 if ((isdigit((int) cp[8])) && (isdigit((int) cp[9]))) {
222 /* Four-digit year */
223 cp[10] = '\0';
224 year = atoi(cp + 6);
225 if (year > 1900)
226 year -= 1900;
227 ftm.tm_year = year; /* years since 1900 */
228 cp += 11;
229 } else {
230 /* Two-digit year */
231 cp[8] = '\0';
232 year = atoi(cp + 6);
233 if (year < 98)
234 year += 100;
235 ftm.tm_year = year; /* years since 1900 */
236 cp += 9;
237 }
238
239 for (;;) {
240 if (*cp == '\0')
241 return (-1);
242 if (isdigit(*cp))
243 break;
244 cp++;
245 }
246
247 cp[2] = '\0';
248 hour = atoi(cp);
249 if (((cp[5] == 'P') || (cp[5] == 'p')) && (hour < 12))
250 hour += 12;
251 else if (((cp[5] == 'A') || (cp[5] == 'a')) && (hour == 12))
252 hour -= 12;
253 ftm.tm_hour = hour;
254 cp[5] = '\0';
255 ftm.tm_min = atoi(cp + 3);
256 *ftime = mktime(&ftm);
257 if (*ftype == (time_t) -1)
258 return (-1);
259
260 cp += 6;
261 *ftype = '-';
262 for (;;) {
263 if (*cp == '\0')
264 return (-1);
265 if ((*cp == '<') && (cp[1] == 'D')) {
266 /* found <DIR> */
267 *ftype = 'd';
268 cp += 5;
269 break; /* size field will end up being empty string */
270 } else if ((*cp == '<') && (cp[1] == 'J')) {
271 /* found <JUNCTION>
272 *
273 * Will we ever really see this?
274 * IIS from Win2000sp1 sends <DIR>
275 * for FTP, but CMD.EXE prints
276 * <JUNCTION>.
277 */
278 *ftype = 'd';
279 cp += 10;
280 break;
281 } else if (isdigit(*cp)) {
282 break;
283 } else {
284 cp++;
285 }
286 }
287
288 sizestart = cp;
289 for (;;) {
290 if (*cp == '\0')
291 return (-1);
292#ifdef HAVE_MEMMOVE
293 if (*cp == ',') {
294 /* Yuck -- US Locale dependency */
295 memmove(cp, cp + 1, strlen(cp + 1) + 1);
296 }
297#endif
298 if (!isdigit(*cp)) {
299 *cp++ = '\0';
300 break;
301 }
302 cp++;
303 }
304
305 if (fsize != NULL) {
306#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
307 if (*ftype == 'd')
308 *fsize = 0;
309 else
310 (void) sscanf(sizestart, SCANF_LONG_LONG, fsize);
311#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
312 if (*ftype == 'd')
313 *fsize = 0;
314 else
315 *fsize = (longest_int) strtoq(sizestart, NULL, 0);
316#else
317 *fsize = (longest_int) 0;
318 if (*ftype != 'd') {
319 long fsize2 = 0L;
320
321 (void) sscanf(sizestart, "%ld", &fsize2);
322 *fsize = (longest_int) fsize2;
323 }
324#endif
325 }
326
327 for (;;) {
328 if (*cp == '\0')
329 return (-1);
330 if (!isspace(*cp)) {
331 break;
332 }
333 cp++;
334 }
335
336 filestart = cp;
337 if (curdirlen == 0) {
338 (void) Strncpy(fname, filestart, fnamesize);
339 } else {
340 (void) Strncpy(fname, curdir, fnamesize);
341 (void) Strncat(fname, filestart, fnamesize);
342 }
343
344 return (0);
345 }
346 return (-1);
347} /* UnDosLine */
348
349
350
351
352static int
353UnLslRLine( char *const line,
354 const char *const curdir,
355 size_t curdirlen,
356 char *fname,
357 size_t fnamesize,
358 char *linkto,
359 size_t linktosize,
360 int *ftype,
362 time_t *ftime,
363 time_t now,
364 int thisyear,
365 int *plugend)
366{
367 char *cp;
368 int mon = 0, dd = 0, hr = 0, min = 0, year = 0;
369 char *monstart, *ddstart, *hrstart, *minstart, *yearstart;
370 char *linktostart, *filestart = NULL;
371 char *sizestart;
372 char *pe;
373 struct tm ftm;
374
375 /*
376 * Look for the digit just before the space
377 * before the month name.
378 *
379-rw-rw---- 1 gleason sysdev 33404 Mar 24 01:29 RCmd.o
380-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
381-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
382-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
383-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
384 *
385 *------------------------------^
386 * 0123456789012345
387 *------plugend--------^
388 * 9876543210
389 *
390 */
391 for (cp = line; *cp != '\0'; cp++) {
392 if ( (isdigit((int) *cp))
393 && (isspace((int) cp[1]))
394 && (isupper((int) cp[2]))
395 && (islower((int) cp[3]))
396 /* && (islower((int) cp[4])) */
397 && (isspace((int) cp[5]))
398 && (
399((isdigit((int) cp[6])) && (isdigit((int) cp[7])))
400|| ((isdigit((int) cp[6])) && (isspace((int) cp[7])))
401|| ((isspace((int) cp[6])) && (isdigit((int) cp[7])))
402 )
403 && (isspace((int) cp[8]))
404 ) {
405 monstart = cp + 2;
406 ddstart = cp + 6;
407 if ( ((isspace((int) cp[9])) || (isdigit((int) cp[9])))
408 && (isdigit((int) cp[10]))
409 && (isdigit((int) cp[11]))
410 && (isdigit((int) cp[12]))
411 && ((isdigit((int) cp[13])) || (isspace((int) cp[13])))
412 ) {
413 /* "Mon DD YYYY" form */
414 yearstart = cp + 9;
415 if (isspace((int) *yearstart))
416 yearstart++;
417 hrstart = NULL;
418 minstart = NULL;
419 filestart = cp + 15;
420 cp[1] = '\0'; /* end size */
421 cp[5] = '\0'; /* end mon */
422 cp[8] = '\0'; /* end dd */
423 cp[14] = '\0'; /* end year */
424 mon = LsMonthNameToNum(monstart);
425 dd = atoi(ddstart);
426 hr = 23;
427 min = 59;
428 year = atoi(yearstart);
429
430 pe = cp;
431 while (isdigit((int) *pe))
432 pe--;
433 while (isspace((int) *pe))
434 pe--;
435 *plugend = (int) (pe - line) + 1;
436 break;
437 } else if ( /*
438 * Windows NT does not 0 pad.
439 (isdigit((int) cp[9])) &&
440 */
441 (isdigit((int) cp[10]))
442 && (cp[11] == ':')
443 && (isdigit((int) cp[12]))
444 && (isdigit((int) cp[13]))
445 ) {
446 /* "Mon DD HH:MM" form */
447 yearstart = NULL;
448 hrstart = cp + 9;
449 minstart = cp + 12;
450 filestart = cp + 15;
451 cp[1] = '\0'; /* end size */
452 cp[5] = '\0'; /* end mon */
453 cp[8] = '\0'; /* end dd */
454 cp[11] = '\0'; /* end hr */
455 cp[14] = '\0'; /* end min */
456 mon = LsMonthNameToNum(monstart);
457 dd = atoi(ddstart);
458 hr = atoi(hrstart);
459 min = atoi(minstart);
460 year = 0;
461
462 pe = cp;
463 while (isdigit((int) *pe))
464 pe--;
465 while (isspace((int) *pe))
466 pe--;
467 *plugend = (int) (pe - line) + 1;
468 break;
469 }
470 }
471 }
472
473 if (*cp == '\0')
474 return (-1);
475
476 linktostart = strstr(filestart, " -> ");
477 if (linktostart != NULL) {
478 *linktostart = '\0';
479 linktostart += 4;
480 (void) Strncpy(linkto, linktostart, linktosize);
481 } else {
482 *linkto = '\0';
483 }
484
485 if (curdirlen == 0) {
486 (void) Strncpy(fname, filestart, fnamesize);
487 } else {
488 (void) Strncpy(fname, curdir, fnamesize);
489 (void) Strncat(fname, filestart, fnamesize);
490 }
491
492 if (ftime != NULL) {
493 (void) memset(&ftm, 0, sizeof(struct tm));
494 ftm.tm_mon = mon;
495 ftm.tm_mday = dd;
496 ftm.tm_hour = hr;
497 ftm.tm_min = min;
498 ftm.tm_isdst = -1;
499 if (year == 0) {
500 /* We guess the year, based on what the
501 * current year is. We know the file
502 * on the remote server is either less
503 * than six months old or less than
504 * one hour into the future.
505 */
506 ftm.tm_year = thisyear - 1900;
507 *ftime = mktime(&ftm);
508 if (*ftime == (time_t) -1) {
509 /* panic */
510 } else if (*ftime > (now + (15552000L + 86400L))) {
511 --ftm.tm_year;
512 *ftime = mktime(&ftm);
513 } else if (*ftime < (now - (15552000L + 86400L))) {
514 ++ftm.tm_year;
515 *ftime = mktime(&ftm);
516 }
517 } else {
518 ftm.tm_year = year - 1900;
519 *ftime = mktime(&ftm);
520 }
521 }
522
523 if (fsize != NULL) {
524 while ((cp > line) && (isdigit((int) *cp)))
525 --cp;
526 sizestart = cp + 1;
527#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
528 (void) sscanf(sizestart, SCANF_LONG_LONG, fsize);
529#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
530 *fsize = (longest_int) strtoq(sizestart, NULL, 0);
531#else
532 {
533 long fsize2 = 0L;
534
535 (void) sscanf(sizestart, "%ld", &fsize2);
536 *fsize = (longest_int) fsize2;
537 }
538#endif
539 }
540
541 switch (line[0]) {
542 case 'd':
543 case 'l':
544 *ftype = (int) line[0];
545 break;
546 case 'b':
547 case 'c':
548 case 's':
549 *ftype = (int) line[0];
550 return (-1);
551 default:
552 *ftype = '-';
553 }
554
555 return (0);
556} /* UnLslRLine */
557
558
559
560int
561UnLslR(FileInfoListPtr filp, LineListPtr llp, int serverType)
562{
563 char curdir[256];
564 char line[256];
565 int hadblankline = 0;
566 int len;
567 size_t curdirlen = 0;
568 char fname[256];
569 char linkto[256];
570 char *cp;
572 int ftype;
574 int thisyear;
575 struct tm *nowtm;
576 int rc;
577 LinePtr lp;
578 FileInfo fi;
579 int linesread = 0;
580 int linesconverted = 0;
581 size_t maxFileLen = 0;
582 size_t maxPlugLen = 0;
583 size_t fileLen;
584 int plugend;
585
586 (void) time(&now);
587 nowtm = localtime(&now);
588 if (nowtm == NULL)
589 thisyear = 1970; /* should never happen */
590 else
591 thisyear = nowtm->tm_year + 1900;
592
593 curdir[0] = '\0';
594
595 InitFileInfoList(filp);
596 for (lp = llp->first; lp != NULL; lp = lp->next) {
597 len = (int) strlen(STRNCPY(line, lp->line));
598 if ((line[0] == 't') && (strncmp(line, "total", 5) == 0)) {
599 /* total XX line? */
600 if (line[len - 1] != ':') {
601 hadblankline = 0;
602 continue;
603 }
604 /* else it was a subdir named total */
605 } else {
606 for (cp = line; ; cp++) {
607 if ((*cp == '\0') || (!isspace((int) *cp)))
608 break;
609 }
610 if (*cp == '\0') {
611 /* Entire line was blank. */
612 /* separator line between dirs */
613 hadblankline = 1;
614 continue;
615 }
616 }
617
618 if ((hadblankline != 0) && (line[len - 1] == ':')) {
619 /* newdir */
620 hadblankline = 0;
621 if ((line[0] == '.') && (line[1] == '/')) {
622 line[len - 1] = '/';
623 (void) memcpy(curdir, line + 2, (size_t) len + 1 - 2);
624 curdirlen = (size_t) (len - 2);
625 } else if ((line[0] == '.') && (line[1] == '\\')) {
626 line[len - 1] = '\\';
627 (void) memcpy(curdir, line + 2, (size_t) len + 1 - 2);
628 curdirlen = (size_t) (len - 2);
629 } else {
630 line[len - 1] = '/';
631 (void) memcpy(curdir, line, (size_t) len + 1);
632 curdirlen = (size_t) len;
633 }
634 continue;
635 }
636
637 linesread++;
638 rc = UnLslRLine(line, curdir, curdirlen, fname, sizeof(fname), linkto, sizeof(linkto), &ftype, &fsize, &ftime, now, thisyear, &plugend);
639 if ((rc < 0) && (serverType == kServerTypeMicrosoftFTP)) {
640 rc = UnDosLine(line, curdir, curdirlen, fname, sizeof(fname), &ftype, &fsize, &ftime);
641 if (rc == 0) {
642 *linkto = '\0';
643 plugend = 0;
644 }
645 }
646 if (rc == 0) {
647 linesconverted++;
648 fileLen = strlen(fname);
649 if (fileLen > maxFileLen)
650 maxFileLen = fileLen;
651 fi.relnameLen = fileLen;
652 fi.relname = StrDup(fname);
653 fi.rname = NULL;
654 fi.lname = NULL;
655 fi.rlinkto = (linkto[0] == '\0') ? NULL : StrDup(linkto);
656 fi.mdtm = ftime;
657 fi.size = (longest_int) fsize;
658 fi.type = ftype;
659 if (plugend > 0) {
660 fi.plug = (char *) malloc((size_t) plugend + 1);
661 if (fi.plug != NULL) {
662 (void) memcpy(fi.plug, line, (size_t) plugend);
663 fi.plug[plugend] = '\0';
664 if ((size_t) plugend > maxPlugLen)
665 maxPlugLen = (size_t) plugend;
666 }
667 } else {
668 fi.plug = (char *) malloc(32);
669 if (fi.plug != NULL) {
670 strcpy(fi.plug, "---------- 1 ftpuser ftpusers");
671 fi.plug[0] = (char) ftype;
672 if (30 > maxPlugLen)
673 maxPlugLen = (size_t) 30;
674 }
675 }
676 (void) AddFileInfo(filp, &fi);
677 }
678
679 hadblankline = 0;
680 }
681
682 filp->maxFileLen = maxFileLen;
683 filp->maxPlugLen = maxPlugLen;
684 if (linesread == 0)
685 return (0);
686 return ((linesconverted > 0) ? linesconverted : (-1));
687} /* UnLslR */
688
689
690
691
692int
693UnMlsT(const char *const line0, const MLstItemPtr mlip)
694{
695 char *cp, *val, *fact;
696 int ec;
697 size_t len;
698 char line[1024];
699
700 memset(mlip, 0, sizeof(MLstItem));
701 mlip->mode = -1;
702 mlip->fsize = kSizeUnknown;
703 mlip->ftype = '-';
704 mlip->ftime = kModTimeUnknown;
705
706 len = strlen(line0);
707 if (len > (sizeof(line) - 1))
708 return (-1); /* Line too long, sorry. */
709 /* This should be re-coded so does not need to make a
710 * copy of the buffer; it could be done in place.
711 */
712 memcpy(line, line0, len + 1);
713
714 /* Skip leading whitespace. */
715 for (cp = line; *cp != '\0'; cp++) {
716 if (! isspace(*cp))
717 break;
718 }
719
720 while (*cp != '\0') {
721 for (fact = cp; ; cp++) {
722 if ((*cp == '\0') || (*cp == ' ')) {
723 /* protocol violation */
724 return (-1);
725 }
726 if (*cp == '=') {
727 /* End of fact name. */
728 *cp++ = '\0';
729 break;
730 }
731 }
732 for (val = cp; ; cp++) {
733 if (*cp == '\0') {
734 /* protocol violation */
735 return (-1);
736 }
737 if (*cp == ' ') {
738 ec = ' ';
739 *cp++ = '\0';
740 break;
741 } else if (*cp == ';') {
742 if (cp[1] == ' ') {
743 ec = ' ';
744 *cp++ = '\0';
745 *cp++ = '\0';
746 } else {
747 ec = ';';
748 *cp++ = '\0';
749 }
750 break;
751 }
752 }
753 if (ISTRNEQ(fact, "OS.", 3))
754 fact += 3;
755 if (ISTREQ(fact, "type")) {
756 if (ISTREQ(val, "file")) {
757 mlip->ftype = '-';
758 } else if (ISTREQ(val, "dir")) {
759 mlip->ftype = 'd';
760 } else if (ISTREQ(val, "cdir")) {
761 /* not supported: current directory */
762 return (-2);
763 } else if (ISTREQ(val, "pdir")) {
764 /* not supported: parent directory */
765 return (-2);
766 } else {
767 /* ? */
768 return (-1);
769 }
770 } else if (ISTREQ(fact, "UNIX.mode")) {
771 if (val[0] == '0')
772 sscanf(val, "%o", &mlip->mode);
773 else
774 sscanf(val, "%i", &mlip->mode);
775 if (mlip->mode != (-1))
776 mlip->mode &= 00777;
777 } else if (ISTREQ(fact, "perm")) {
778 STRNCPY(mlip->perm, val);
779 } else if (ISTREQ(fact, "size")) {
780#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
781 (void) sscanf(val, SCANF_LONG_LONG, &mlip->fsize);
782#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
783 mlip->fsize = (longest_int) strtoq(val, NULL, 0);
784#else
785 {
786 long fsize2 = 0L;
787
788 (void) sscanf(val, "%ld", &fsize2);
789 mlip->fsize = (longest_int) fsize2;
790 }
791#endif
792 } else if (ISTREQ(fact, "modify")) {
793 mlip->ftime = UnMDTMDate(val);
794 } else if (ISTREQ(fact, "UNIX.owner")) {
795 STRNCPY(mlip->owner, val);
796 } else if (ISTREQ(fact, "UNIX.group")) {
797 STRNCPY(mlip->group, val);
798 } else if (ISTREQ(fact, "UNIX.uid")) {
799 mlip->uid = atoi(val);
800 } else if (ISTREQ(fact, "UNIX.gid")) {
801 mlip->gid = atoi(val);
802 } else if (ISTREQ(fact, "perm")) {
803 STRNCPY(mlip->perm, val);
804 }
805
806 /* End of facts? */
807 if (ec == ' ')
808 break;
809 }
810
811 len = strlen(cp);
812 if (len > (sizeof(mlip->fname) - 1)) {
813 /* Filename too long */
814 return (-1);
815 }
816 memcpy(mlip->fname, cp, len);
817
818 /* also set linkto here if used */
819
820 return (0);
821} /* UnMlsT */
822
823
824
825
826int
828{
829 MLstItem mli;
830 char plug[64];
831 char og[32];
832 int rc;
833 LinePtr lp;
834 FileInfo fi;
835 int linesread = 0;
836 int linesconverted = 0;
837 int linesignored = 0;
838 size_t maxFileLen = 0;
839 size_t maxPlugLen = 0;
840 size_t fileLen, plugLen;
841 int m1, m2, m3;
842 const char *cm1, *cm2, *cm3;
843
844 InitFileInfoList(filp);
845 for (lp = llp->first; lp != NULL; lp = lp->next) {
846 linesread++;
847 rc = UnMlsT(lp->line, &mli);
848 if (rc == 0) {
849 linesconverted++;
850 fileLen = strlen(mli.fname);
851 if (fileLen > maxFileLen)
852 maxFileLen = fileLen;
853 fi.relnameLen = fileLen;
854 fi.relname = StrDup(mli.fname);
855 fi.rname = NULL;
856 fi.lname = NULL;
857 fi.rlinkto = (mli.linkto[0] == '\0') ? NULL : StrDup(mli.linkto);
858 fi.mdtm = mli.ftime;
859 fi.size = (longest_int) mli.fsize;
860 fi.type = mli.ftype;
861 plug[0] = (char) mli.ftype;
862 plug[1] = '\0';
863 m1 = 0;
864 m2 = 0;
865 m3 = -1;
866 if (mli.mode != (-1)) {
867 m1 = (mli.mode & 00700) >> 6;
868 m2 = (mli.mode & 00070) >> 3;
869 m3 = (mli.mode & 00007);
870 }
871 if (mli.perm[0] != '\0') {
872 m3 = 0;
873 if (fi.type == 'd') {
874 if (strchr(mli.perm, 'e') != NULL) {
875 /* execute -> execute */
876 m3 |= 00001;
877 }
878 if (strchr(mli.perm, 'c') != NULL) {
879 /* create -> write */
880 m3 |= 00002;
881 }
882 if (strchr(mli.perm, 'l') != NULL) {
883 /* list -> read */
884 m3 |= 00004;
885 }
886 } else {
887 if (strchr(mli.perm, 'w') != NULL) {
888 /* write -> write */
889 m3 |= 00002;
890 }
891 if (strchr(mli.perm, 'r') != NULL) {
892 /* read -> read */
893 m3 |= 00004;
894 }
895 }
896 }
897 if (m3 != (-1)) {
898 cm1 = rwx[m1];
899 cm2 = rwx[m2];
900 cm3 = rwx[m3];
901 sprintf(plug + 1, "%s%s%s", cm1, cm2, cm3);
902 }
903 if (mli.owner[0] != '\0') {
904 if (mli.group[0] != '\0') {
905#ifdef HAVE_SNPRINTF
906 snprintf(og, sizeof(og) - 1,
907#else
908 sprintf(og,
909#endif /* HAVE_SNPRINTF */
910 " %-8.8s %s",
911 mli.owner, mli.group
912 );
913 STRNCAT(plug, og);
914 } else {
915 STRNCAT(plug, " ");
916 STRNCAT(plug, mli.owner);
917 }
918 }
919 fi.plug = StrDup(plug);
920 if (fi.plug != NULL) {
921 plugLen = strlen(plug);
922 if (plugLen > maxPlugLen)
923 maxPlugLen = plugLen;
924 }
925 (void) AddFileInfo(filp, &fi);
926 } else if (rc == (-2)) {
927 linesignored++;
928 }
929 }
930
931 filp->maxFileLen = maxFileLen;
932 filp->maxPlugLen = maxPlugLen;
933 if (linesread == 0)
934 return (0);
935 linesconverted += linesignored;
936 return ((linesconverted > 0) ? linesconverted : (-1));
937} /* UnMlsD */
938
939
940
941#if 0
942static void
943print1(FileInfoListPtr list)
944{
945 FileInfoPtr fip;
946 int i;
947
948 for (i = 1, fip = list->first; fip != NULL; fip = fip->next, i++)
949 printf("%d: %s\n", i, fip->relname == NULL ? "NULL" : fip->relname);
950}
951
952
953
954static void
955print2(FileInfoListPtr list)
956{
957 FileInfoPtr fip;
958 int i, n;
959
960 n = list->nFileInfos;
961 for (i=0; i<n; i++) {
962 fip = list->vec[i];
963 printf("%d: %s\n", i + 1, fip->relname == NULL ? "NULL" : fip->relname);
964 }
965}
966
967
968
969
970static void
971SortRecursiveFileList(FileInfoListPtr files)
972{
974 SortFileInfoList(files, 'b', '?');
976} /* SortRecursiveFileList */
977#endif
978
979
980
981
982int
984{
985 LineList dirContents;
986 FileInfoList fil;
987 char cwd[512];
988 int result;
989
990 if ((result = FTPGetCWD(cip, cwd, sizeof(cwd))) < 0)
991 return (result);
992
993 InitFileInfoList(files);
994
995 if (rdir == NULL)
996 return (-1);
997
998 if (FTPChdir(cip, rdir) < 0) {
999 /* Probably not a directory.
1000 * Just add it as a plain file
1001 * to the list.
1002 */
1003 (void) ConcatFileToFileInfoList(files, rdir);
1004 return (kNoErr);
1005 }
1006
1007 /* Paths collected must be relative. */
1008 if ((result = FTPListToMemory2(cip, "", &dirContents, "-lRa", 1, (int *) 0)) < 0) {
1009 if ((result = FTPChdir(cip, cwd)) < 0) {
1010 return (result);
1011 }
1012 }
1013
1014 (void) UnLslR(&fil, &dirContents, cip->serverType);
1015 DisposeLineListContents(&dirContents);
1016 /* Could sort it to breadth-first here. */
1017 /* (void) SortRecursiveFileList(&fil); */
1018 (void) ComputeRNames(&fil, rdir, 1, 1);
1019 (void) ConcatFileInfoList(files, &fil);
1021
1022 if ((result = FTPChdir(cip, cwd)) < 0) {
1023 return (result);
1024 }
1025 return (kNoErr);
1026} /* FTPRemoteRecursiveFileList1 */
1027
1028
1029
1030
1031int
1033{
1034 LinePtr filePtr, nextFilePtr;
1035 LineList dirContents;
1036 FileInfoList fil;
1037 char cwd[512];
1038 int result;
1039 char *rdir;
1040
1041 if ((result = FTPGetCWD(cip, cwd, sizeof(cwd))) < 0)
1042 return (result);
1043
1044 InitFileInfoList(files);
1045
1046 for (filePtr = fileList->first;
1047 filePtr != NULL;
1048 filePtr = nextFilePtr)
1049 {
1050 nextFilePtr = filePtr->next;
1051
1052 rdir = filePtr->line;
1053 if (rdir == NULL)
1054 continue;
1055
1056 if (FTPChdir(cip, rdir) < 0) {
1057 /* Probably not a directory.
1058 * Just add it as a plain file
1059 * to the list.
1060 */
1061 (void) ConcatFileToFileInfoList(files, rdir);
1062 continue;
1063 }
1064
1065 /* Paths collected must be relative. */
1066 if ((result = FTPListToMemory2(cip, "", &dirContents, "-lRa", 1, (int *) 0)) < 0) {
1067 goto goback;
1068 }
1069
1070 (void) UnLslR(&fil, &dirContents, cip->serverType);
1071 DisposeLineListContents(&dirContents);
1072 (void) ComputeRNames(&fil, rdir, 1, 1);
1073 (void) ConcatFileInfoList(files, &fil);
1075
1076goback:
1077 if ((result = FTPChdir(cip, cwd)) < 0) {
1078 return (result);
1079 }
1080 }
1081 return (kNoErr);
1082} /* FTPRemoteRecursiveFileList */
1083
1084
1085
1086#if defined(WIN32) || defined(_WINDOWS)
1087
1088static void
1089Traverse(FTPCIPtr cip, char *fullpath, struct Stat *st, char *relpath, FileInfoListPtr filp)
1090{
1091 WIN32_FIND_DATA ffd;
1092 HANDLE searchHandle;
1093 DWORD dwErr;
1094 char *cp, *c2;
1095 const char *file;
1096 FileInfo fi;
1097
1098 /* Handle directory entry first. */
1099 if (relpath[0] != '\0') {
1100 fi.relname = StrDup(relpath);
1101 fi.rname = NULL;
1102 fi.lname = StrDup(fullpath);
1103 fi.rlinkto = NULL;
1104 fi.plug = NULL;
1105 fi.mdtm = st->st_mtime;
1106 fi.size = (longest_int) st->st_size;
1107 fi.type = 'd';
1108 (void) AddFileInfo(filp, &fi);
1109 }
1110
1111 cp = fullpath + strlen(fullpath);
1112 *cp++ = LOCAL_PATH_DELIM;
1113 strcpy(cp, "*.*");
1114
1115 c2 = relpath + strlen(relpath);
1116 *c2++ = LOCAL_PATH_DELIM;
1117 *c2 = '\0';
1118
1119 memset(&ffd, 0, sizeof(ffd));
1120
1121 /* "Open" the directory. */
1122 searchHandle = FindFirstFile(fullpath, &ffd);
1123 if (searchHandle == INVALID_HANDLE_VALUE) {
1124 return;
1125 }
1126
1127 for (;;) {
1128
1129 file = ffd.cFileName;
1130 if ((*file == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0')))) {
1131 /* It was "." or "..", so skip it. */
1132 goto next;
1133 }
1134
1135 (void) strcpy(cp, file); /* append name after slash */
1136 (void) strcpy(c2, file);
1137
1138 if (Lstat(fullpath, st) < 0) {
1139 Error(cip, kDoPerror, "could not stat %s.\n", fullpath);
1140 goto next;
1141 }
1142
1143 fi.relname = StrDup(relpath + (((relpath[0] == '/') || (relpath[0] == '\\')) ? 1 : 0));
1144 fi.rname = NULL;
1145 fi.lname = StrDup(fullpath);
1146 fi.mdtm = st->st_mtime;
1147 fi.size = (longest_int) st->st_size;
1148 fi.rlinkto = NULL;
1149 fi.plug = NULL;
1150
1151 if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1152 Traverse(cip, fullpath, st, relpath, filp);
1153 } else {
1154 /* file */
1155 fi.type = '-';
1156 (void) AddFileInfo(filp, &fi);
1157 }
1158
1159next:
1160#ifndef __REACTOS__
1161#if _DEBUG
1162 memset(&ffd, 0, sizeof(ffd));
1163#endif
1164#else // __REACTOS__
1165#ifdef _DEBUG
1166 memset(&ffd, 0, sizeof(ffd));
1167#endif
1168#endif // __REACTOS__
1169 if (!FindNextFile(searchHandle, &ffd)) {
1170 dwErr = GetLastError();
1171 if (dwErr != ERROR_NO_MORE_FILES) {
1172 FindClose(searchHandle);
1173 return;
1174 }
1175 break;
1176 }
1177 }
1178 FindClose(searchHandle);
1179} // Traverse
1180
1181#else
1182
1183static void
1184Traverse(FTPCIPtr cip, char *fullpath, struct Stat *st, char *relpath, FileInfoListPtr filp)
1185{
1186 char *dname;
1187 struct dirent *dirp;
1188 mode_t m;
1189 DIR *dp;
1190 char *cp;
1191 char *c2;
1192 FileInfo fi;
1193
1194 if (relpath[0] != '\0') {
1195 fi.relname = StrDup(relpath);
1196 fi.rname = NULL;
1197 fi.lname = StrDup(fullpath);
1198 fi.rlinkto = NULL;
1199 fi.plug = NULL;
1200 fi.mdtm = st->st_mtime;
1201 fi.size = (longest_int) st->st_size;
1202 fi.type = 'd';
1203 (void) AddFileInfo(filp, &fi);
1204 }
1205
1206 /* Handle directory entry first. */
1207 cp = fullpath + strlen(fullpath);
1208 *cp++ = '/';
1209 *cp = '\0';
1210
1211 c2 = relpath + strlen(relpath);
1212 *c2++ = '/';
1213 *c2 = '\0';
1214
1215 if ((dp = opendir(fullpath)) == NULL) {
1216 cp[-1] = '\0';
1217 c2[-1] = '\0';
1218 Error(cip, kDoPerror, "could not opendir %s.\n", fullpath);
1219 return;
1220 }
1221
1222 while ((dirp = readdir(dp)) != NULL) {
1223 dname = dirp->d_name;
1224 if ((dname[0] == '.') && ((dname[1] == '\0') || ((dname[1] == '.') && (dname[2] == '\0'))))
1225 continue; /* skip "." and ".." directories. */
1226
1227 (void) strcpy(cp, dirp->d_name); /* append name after slash */
1228 (void) strcpy(c2, dirp->d_name);
1229 if (Lstat(fullpath, st) < 0) {
1230 Error(cip, kDoPerror, "could not stat %s.\n", fullpath);
1231 continue;
1232 }
1233
1234 fi.relname = StrDup(relpath + (((relpath[0] == '/') || (relpath[0] == '\\')) ? 1 : 0));
1235 fi.rname = NULL;
1236 fi.lname = StrDup(fullpath);
1237 fi.mdtm = st->st_mtime;
1238 fi.size = (longest_int) st->st_size;
1239 fi.rlinkto = NULL;
1240 fi.plug = NULL;
1241
1242 m = st->st_mode;
1243 if (S_ISREG(m) != 0) {
1244 /* file */
1245 fi.type = '-';
1246 (void) AddFileInfo(filp, &fi);
1247 } else if (S_ISDIR(m)) {
1248 Traverse(cip, fullpath, st, relpath, filp);
1249#ifdef S_ISLNK
1250 } else if (S_ISLNK(m)) {
1251 fi.type = 'l';
1252 fi.rlinkto = calloc(128, 1);
1253 if (fi.rlinkto != NULL) {
1254 if (readlink(fullpath, fi.rlinkto, 127) < 0) {
1255 free(fi.rlinkto);
1256 } else {
1257 (void) AddFileInfo(filp, &fi);
1258 }
1259 }
1260#endif /* S_ISLNK */
1261 }
1262 }
1263 cp[-1] = '\0';
1264 c2[-1] = '\0';
1265
1266 (void) closedir(dp);
1267} /* Traverse */
1268
1269#endif
1270
1271
1272
1273
1274
1275int
1277{
1278 LinePtr filePtr, nextFilePtr;
1279#if defined(WIN32) || defined(_WINDOWS)
1280 char fullpath[_MAX_PATH + 1];
1281 char relpath[_MAX_PATH + 1];
1282#else
1283 char fullpath[512];
1284 char relpath[512];
1285#endif
1286 struct Stat st;
1287 FileInfo fi;
1288 char *cp;
1289
1290 InitFileInfoList(files);
1291
1292 for (filePtr = fileList->first;
1293 filePtr != NULL;
1294 filePtr = nextFilePtr)
1295 {
1296 nextFilePtr = filePtr->next;
1297
1298 (void) STRNCPY(fullpath, filePtr->line); /* initialize fullpath */
1299 if ((erelative != 0) || (strcmp(filePtr->line, ".") == 0) || (filePtr->line[0] == '\0'))
1300 (void) STRNCPY(relpath, "");
1301 else if ((cp = StrRFindLocalPathDelim(filePtr->line)) == NULL)
1302 (void) STRNCPY(relpath, filePtr->line);
1303 else
1304 (void) STRNCPY(relpath, cp + 1);
1305 if (Lstat(fullpath, &st) < 0) {
1306 Error(cip, kDoPerror, "could not stat %s.\n", fullpath);
1307 continue;
1308 }
1309
1310 if (S_ISDIR(st.st_mode) == 0) {
1311 fi.relname = StrDup(relpath);
1312 fi.rname = NULL;
1313 fi.lname = StrDup(fullpath);
1314 fi.mdtm = st.st_mtime;
1315 fi.size = (longest_int) st.st_size;
1316 fi.rlinkto = NULL;
1317 fi.plug = NULL;
1318 fi.type = '-';
1319 (void) AddFileInfo(files, &fi);
1320 continue; /* wasn't a directory */
1321 }
1322
1323 /* Paths collected must be relative. */
1324 Traverse(cip, fullpath, &st, relpath, files);
1325 }
1326 return (kNoErr);
1327} /* FTPLocalRecursiveFileList */
1328
1329
1330
1331
1332int
1334{
1335 return (FTPLocalRecursiveFileList2(cip, fileList, files, 0));
1336} /* FTPLocalRecursiveFileList */
1337
1338
1339
1340int
1341FTPRemoteGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
1342{
1343 char *cp;
1344 const char *lsflags;
1345 LinePtr lp;
1346 int result;
1347
1348 if (cip == NULL)
1349 return (kErrBadParameter);
1350 if (strcmp(cip->magic, kLibraryMagic))
1351 return (kErrBadMagic);
1352
1353 if (fileList == NULL)
1354 return (kErrBadParameter);
1355 InitLineList(fileList);
1356
1357 if ((pattern == NULL) || (pattern[0] == '\0'))
1358 return (kErrBadParameter);
1359
1360 /* Note that we do attempt to use glob characters even if the remote
1361 * host isn't UNIX. Most non-UNIX remote FTP servers look for UNIX
1362 * style wildcards.
1363 */
1364 if ((doGlob == 1) && (GLOBCHARSINSTR(pattern))) {
1365 /* Use NLST, which lists files one per line. */
1366 lsflags = "";
1367
1368 /* Optimize for "NLST *" case which is same as "NLST". */
1369 if (strcmp(pattern, "*") == 0) {
1370 pattern = "";
1371 } else if (strcmp(pattern, "**") == 0) {
1372 /* Hack; Lets you try "NLST -a" if you're daring. */
1373 pattern = "";
1374 lsflags = "-a";
1375 }
1376
1377 if ((result = FTPListToMemory2(cip, pattern, fileList, lsflags, 0, (int *) 0)) < 0) {
1378 if (*lsflags == '\0')
1379 return (result);
1380 /* Try again, without "-a" */
1381 lsflags = "";
1382 if ((result = FTPListToMemory2(cip, pattern, fileList, lsflags, 0, (int *) 0)) < 0) {
1383 return (result);
1384 }
1385 }
1386 if (fileList->first == NULL) {
1387 cip->errNo = kErrGlobNoMatch;
1388 return (kErrGlobNoMatch);
1389 }
1390 if (fileList->first == fileList->last) {
1391#define glberr(a) (ISTRNEQ(cp, a, strlen(a)))
1392 /* If we have only one item in the list, see if it really was
1393 * an error message we would recognize.
1394 */
1395 cp = strchr(fileList->first->line, ':');
1396 if (cp != NULL) {
1397 if (glberr(": No such file or directory")) {
1398 (void) RemoveLine(fileList, fileList->first);
1399 cip->errNo = kErrGlobFailed;
1400 return (kErrGlobFailed);
1401 } else if (glberr(": No match")) {
1402 cip->errNo = kErrGlobNoMatch;
1403 return (kErrGlobNoMatch);
1404 }
1405 }
1406 }
1407 RemoteGlobCollapse(pattern, fileList);
1408 for (lp=fileList->first; lp != NULL; lp = lp->next)
1409 PrintF(cip, " Rglob [%s]\n", lp->line);
1410 } else {
1411 /* Or, if there were no globbing characters in 'pattern', then the
1412 * pattern is really just a filename. So for this case the
1413 * file list is really just a single file.
1414 */
1415 fileList->first = fileList->last = NULL;
1416 (void) AddLine(fileList, pattern);
1417 }
1418 return (kNoErr);
1419} /* FTPRemoteGlob */
1420
1421
1422
1423
1424/* This does "tilde-expansion." Examples:
1425 * ~/pub --> /usr/gleason/pub
1426 * ~pdietz/junk --> /usr/pdietz/junk
1427 */
1428static void
1429ExpandTilde(char *pattern, size_t siz)
1430{
1431 string pat;
1432 char *cp, *rest, *firstent;
1433#if defined(WIN32) || defined(_WINDOWS)
1434#else
1435 struct passwd *pw;
1436#endif
1437 string hdir;
1438
1439 if ((pattern[0] == '~') &&
1440 (isalnum((int) pattern[1]) || IsLocalPathDelim(pattern[1]) || (pattern[1] == '\0'))) {
1441 (void) STRNCPY(pat, pattern);
1442 if ((cp = StrFindLocalPathDelim(pat)) != NULL) {
1443 *cp = 0;
1444 rest = cp + 1; /* Remember stuff after the ~/ part. */
1445 } else {
1446 rest = NULL; /* Was just a ~ or ~username. */
1447 }
1448 if (pat[1] == '\0') {
1449 /* Was just a ~ or ~/rest type. */
1450 GetHomeDir(hdir, sizeof(hdir));
1451 firstent = hdir;
1452 } else {
1453#if defined(WIN32) || defined(_WINDOWS)
1454 return;
1455#else
1456 /* Was just a ~username or ~username/rest type. */
1457 pw = getpwnam(pat + 1);
1458 if (pw != NULL)
1459 firstent = pw->pw_dir;
1460 else
1461 return; /* Bad user -- leave it alone. */
1462#endif
1463 }
1464
1465 (void) Strncpy(pattern, firstent, siz);
1466 if (rest != NULL) {
1468 (void) Strncat(pattern, rest, siz);
1469 }
1470 }
1471} /* ExpandTilde */
1472
1473
1474
1475
1476
1477#if defined(WIN32) || defined(_WINDOWS)
1478
1479static int
1480WinLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *const srcpat)
1481{
1482 char pattern[_MAX_PATH];
1483 WIN32_FIND_DATA ffd;
1484 HANDLE searchHandle;
1485 DWORD dwErr;
1486 char *cp;
1487 const char *file;
1488 int result;
1489
1490 STRNCPY(pattern, srcpat);
1491
1492 /* Get rid of trailing slashes. */
1493 cp = pattern + strlen(pattern) - 1;
1494 while ((cp >= pattern) && IsLocalPathDelim(*cp))
1495 *cp-- = '\0';
1496
1497 memset(&ffd, 0, sizeof(ffd));
1498
1499 /* "Open" the directory. */
1500 searchHandle = FindFirstFile(pattern, &ffd);
1501 if (searchHandle == INVALID_HANDLE_VALUE) {
1502 dwErr = GetLastError();
1503 return ((dwErr == 0) ? 0 : -1);
1504 }
1505
1506 /* Get rid of basename. */
1508 if (cp == NULL)
1509 cp = pattern;
1510 else
1511 cp++;
1512 *cp = '\0';
1513
1514 for (result = 0;;) {
1515 file = ffd.cFileName;
1516 if ((file[0] == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0')))) {
1517 /* skip */
1518 } else {
1519 Strncpy(cp, ffd.cFileName, sizeof(pattern) - (cp - pattern));
1520 PrintF(cip, " Lglob [%s]\n", pattern);
1521 (void) AddLine(fileList, pattern);
1522 }
1523
1524 if (!FindNextFile(searchHandle, &ffd)) {
1525 dwErr = GetLastError();
1526 if (dwErr != ERROR_NO_MORE_FILES) {
1527 result = ((dwErr == 0) ? 0 : -1);
1528 }
1529 break;
1530 }
1531 }
1532
1533 return (result);
1534} // WinLocalGlob
1535
1536#else
1537
1538static int
1539LazyUnixLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *const pattern)
1540{
1541 string cmd;
1542 longstring gfile;
1543 FILE *fp;
1544 FTPSigProc sp;
1545
1546 /* Do it the easy way and have the shell do the dirty
1547 * work for us.
1548 */
1549#ifdef HAVE_SNPRINTF
1550 (void) snprintf(cmd, sizeof(cmd) - 1, "%s -c \"%s %s %s\"", "/bin/sh", "/bin/ls",
1551 "-d", pattern);
1552 cmd[sizeof(cmd) - 1] = '\0';
1553#else
1554 (void) sprintf(cmd, "%s -c \"%s %s %s\"", "/bin/sh", "/bin/ls",
1555 "-d", pattern);
1556#endif
1557
1558 fp = (FILE *) popen(cmd, "r");
1559 if (fp == NULL) {
1560 Error(cip, kDoPerror, "Could not Lglob: [%s]\n", cmd);
1561 cip->errNo = kErrGlobFailed;
1562 return (kErrGlobFailed);
1563 }
1565 while (FGets(gfile, sizeof(gfile), (FILE *) fp) != NULL) {
1566 PrintF(cip, " Lglob [%s]\n", gfile);
1567 (void) AddLine(fileList, gfile);
1568 }
1569 (void) pclose(fp);
1570 (void) NcSignal(SIGPIPE, sp);
1571 return (kNoErr);
1572} /* LazyUnixLocalGlob */
1573
1574#endif
1575
1576
1577
1578
1579int
1580FTPLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
1581{
1582 string pattern2;
1583 int result;
1584
1585 if (cip == NULL)
1586 return (kErrBadParameter);
1587 if (strcmp(cip->magic, kLibraryMagic))
1588 return (kErrBadMagic);
1589
1590 if (fileList == NULL)
1591 return (kErrBadParameter);
1592 InitLineList(fileList);
1593
1594 if ((pattern == NULL) || (pattern[0] == '\0'))
1595 return (kErrBadParameter);
1596
1597 (void) STRNCPY(pattern2, pattern); /* Don't nuke the original. */
1598
1599 /* Pre-process for ~'s. */
1600 ExpandTilde(pattern2, sizeof(pattern2));
1601 InitLineList(fileList);
1602 result = kNoErr;
1603
1604 if ((doGlob == 1) && (GLOBCHARSINSTR(pattern2))) {
1605#if defined(WIN32) || defined(_WINDOWS)
1606 result = WinLocalGlob(cip, fileList, pattern2);
1607#else
1608 result = LazyUnixLocalGlob(cip, fileList, pattern2);
1609#endif
1610 } else {
1611 /* Or, if there were no globbing characters in 'pattern', then
1612 * the pattern is really just a single pathname.
1613 */
1614 (void) AddLine(fileList, pattern2);
1615 }
1616
1617 return (result);
1618} /* FTPLocalGlob */
1619
1620
1621
1622
1623static int
1624FTPFtwL2(const FTPCIPtr cip, char *dir, char *end, size_t dirsize, FTPFtwProc proc, int maxdepth)
1625{
1626 LineList fileList;
1627 LinePtr filePtr;
1628 char *file, *cp;
1629 int result;
1630
1631 if (maxdepth <= 0) {
1633 return (result);
1634 }
1635
1636 result = FTPRemoteGlob(cip, &fileList, "**", kGlobYes);
1637 if (result != kNoErr) {
1638 if (result == kErrGlobNoMatch)
1639 result = kNoErr; /* empty directory is okay. */
1640 return (result);
1641 }
1642
1643 for (filePtr = fileList.first;
1644 filePtr != NULL;
1645 filePtr = filePtr->next)
1646 {
1647 file = filePtr->line;
1648 if (file == NULL) {
1649 cip->errNo = kErrBadLineList;
1650 break;
1651 }
1652
1653 if ((file[0] == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0'))))
1654 continue; /* Skip . and .. */
1655
1656 result = FTPIsDir(cip, file);
1657 if (result < 0) {
1658 /* error */
1659 /* could be just a stat error, so continue */
1660 continue;
1661 } else if (result == 1) {
1662 /* directory */
1663 cp = Strnpcat(dir, file, dirsize);
1664 result = (*proc)(cip, dir, kFtwDir);
1665 if (result != kNoErr)
1666 break;
1667
1668 if ((strchr(dir, '/') == NULL) && (strrchr(dir, '\\') != NULL))
1669 *cp++ = '\\';
1670 else
1671 *cp++ = '/';
1672 *cp = '\0';
1673
1674 result = FTPChdir(cip, file);
1675 if (result == kNoErr) {
1676 result = FTPFtwL2(cip, dir, cp, dirsize, proc, maxdepth - 1);
1677 if (result != kNoErr)
1678 break;
1679 if (FTPChdir(cip, "..") < 0) {
1681 cip->errNo = kErrCannotGoToPrevDir;
1682 break;
1683 }
1684 }
1685
1686 *end = '\0';
1687 if (result != 0)
1688 break;
1689 } else {
1690 /* file */
1691 cp = Strnpcat(dir, file, dirsize);
1692 result = (*proc)(cip, dir, kFtwFile);
1693 *end = '\0';
1694 if (result != 0)
1695 break;
1696 }
1697 }
1698 DisposeLineListContents(&fileList);
1699
1700 return (result);
1701} /* FTPFtwL2 */
1702
1703
1704
1705int
1706FTPFtw(const FTPCIPtr cip, const char *const dir, FTPFtwProc proc, int maxdepth)
1707{
1708 int result, result2;
1709 char *cp;
1710 char savedcwd[1024];
1711 char curcwd[2048];
1712
1713 result = FTPIsDir(cip, dir);
1714 if (result < 0) {
1715 /* error */
1716 return result;
1717 } else if (result == 0) {
1719 return (result);
1720 }
1721
1722 /* Preserve old working directory. */
1723 (void) FTPGetCWD(cip, savedcwd, sizeof(savedcwd));
1724
1725 result = FTPChdir(cip, dir);
1726 if (result != kNoErr) {
1727 return (result);
1728 }
1729
1730 /* Get full working directory we just changed to. */
1731 result = FTPGetCWD(cip, curcwd, sizeof(curcwd) - 3);
1732 if (result != kNoErr) {
1733 if (FTPChdir(cip, savedcwd) != kNoErr) {
1736 }
1737 return (result);
1738 }
1739
1740 result2 = (*proc)(cip, curcwd, kFtwDir);
1741 if (result2 == kNoErr) {
1742 cp = curcwd + strlen(curcwd);
1743
1744 if ((strchr(curcwd, '/') == NULL) && (strrchr(curcwd, '\\') != NULL))
1745 *cp++ = '\\';
1746 else
1747 *cp++ = '/';
1748 *cp = '\0';
1749 result = FTPFtwL2(cip, curcwd, cp, sizeof(curcwd), proc, maxdepth - 1);
1750 }
1751
1752
1753 if (FTPChdir(cip, savedcwd) != kNoErr) {
1754 /* Could not cd back to the original user directory -- bad. */
1757 return (result);
1758 }
1759
1760 if ((result2 != kNoErr) && (result == kNoErr))
1761 result = result2;
1762
1763 return (result);
1764} /* FTPFtw */
1765
1766/* eof */
#define STRNCAT(d, s)
Definition: Strn.h:48
char * Strncat(char *const, const char *const, const size_t)
Definition: Strncat.c:13
char * Strncpy(char *const, const char *const, const size_t)
Definition: Strncpy.c:11
char * Strnpcat(char *const, const char *const, size_t)
Definition: Strnpcat.c:16
#define isspace(c)
Definition: acclib.h:69
#define islower(c)
Definition: acclib.h:72
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
#define isdigit(c)
Definition: acclib.h:68
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define isupper(c)
Definition: acclib.h:71
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
unsigned int dir
Definition: maze.c:112
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
#define S_ISDIR(mode)
Definition: various.h:18
#define S_ISREG(mode)
Definition: various.h:17
DWORD dwErr
Definition: service.c:36
BOOL Error
Definition: chkdsk.c:66
Definition: list.h:37
#define SIGPIPE
Definition: signal.h:35
#define SIG_IGN
Definition: signal.h:48
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned char
Definition: typeof.h:29
__kernel_size_t size_t
Definition: linux.h:237
__kernel_time_t time_t
Definition: linux.h:252
__kernel_mode_t mode_t
Definition: linux.h:199
#define S_ISLNK(m)
Definition: ext2fs.h:373
unsigned long DWORD
Definition: ntddk_ex.h:95
time_t now
Definition: finger.c:65
#define printf
Definition: freeldr.h:97
FxCollectionEntry * cur
GLuint GLuint end
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
GLubyte * pattern
Definition: glext.h:7787
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
const GLfloat * m
Definition: glext.h:10848
GLint fsize
Definition: glext.h:9408
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void Traverse(FTPCIPtr cip, char *fullpath, struct Stat *st, char *relpath, FileInfoListPtr filp)
Definition: glob.c:1184
int FTPFtw(const FTPCIPtr cip, const char *const dir, FTPFtwProc proc, int maxdepth)
Definition: glob.c:1706
int FTPRemoteRecursiveFileList(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files)
Definition: glob.c:1032
static int LsMonthNameToNum(char *cp)
Definition: glob.c:135
int UnMlsT(const char *const line0, const MLstItemPtr mlip)
Definition: glob.c:693
int FTPLocalRecursiveFileList(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files)
Definition: glob.c:1333
int UnMlsD(FileInfoListPtr filp, LineListPtr llp)
Definition: glob.c:827
#define glberr(a)
static int LazyUnixLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *const pattern)
Definition: glob.c:1539
int FTPLocalRecursiveFileList2(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files, int erelative)
Definition: glob.c:1276
static int UnLslRLine(char *const line, const char *const curdir, size_t curdirlen, char *fname, size_t fnamesize, char *linkto, size_t linktosize, int *ftype, longest_int *fsize, time_t *ftime, time_t now, int thisyear, int *plugend)
Definition: glob.c:353
int FTPRemoteRecursiveFileList1(FTPCIPtr cip, char *const rdir, FileInfoListPtr files)
Definition: glob.c:983
static int FTPFtwL2(const FTPCIPtr cip, char *dir, char *end, size_t dirsize, FTPFtwProc proc, int maxdepth)
Definition: glob.c:1624
static int UnDosLine(char *const line, const char *const curdir, size_t curdirlen, char *fname, size_t fnamesize, int *ftype, longest_int *fsize, time_t *ftime)
Definition: glob.c:175
static void RemoteGlobCollapse(const char *pattern, LineListPtr fileList)
Definition: glob.c:43
int UnLslR(FileInfoListPtr filp, LineListPtr llp, int serverType)
Definition: glob.c:561
int FTPLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
Definition: glob.c:1580
int FTPRemoteGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
Definition: glob.c:1341
static const char * rwx[9]
Definition: glob.c:10
static void ExpandTilde(char *pattern, size_t siz)
Definition: glob.c:1429
_Check_return_ _CRTIMP int __cdecl ispunct(_In_ int _C)
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
int __cdecl closedir(DIR *)
DIR *__cdecl opendir(const char *)
struct dirent *__cdecl readdir(DIR *)
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define Lstat
Definition: syshdrs.h:80
#define Stat
Definition: syshdrs.h:78
#define SCANF_LONG_LONG
Definition: wincfg.h:30
void UnvectorizeFileInfoList(FileInfoListPtr list)
Definition: linelist.c:441
int ConcatFileInfoList(FileInfoListPtr dst, FileInfoListPtr src)
Definition: linelist.c:556
void InitLineList(LineListPtr list)
Definition: linelist.c:54
LinePtr RemoveLine(LineListPtr list, LinePtr killMe)
Definition: linelist.c:63
void InitFileInfoList(FileInfoListPtr list)
Definition: linelist.c:193
int ConcatFileToFileInfoList(FileInfoListPtr dst, char *rfile)
Definition: linelist.c:740
FileInfoPtr AddFileInfo(FileInfoListPtr list, FileInfoPtr src)
Definition: linelist.c:530
int ComputeRNames(FileInfoListPtr dst, const char *dstdir, int pflag, int nochop)
Definition: linelist.c:579
void DisposeFileInfoListContents(FileInfoListPtr list)
Definition: linelist.c:152
void VectorizeFileInfoList(FileInfoListPtr list)
Definition: linelist.c:423
void DisposeLineListContents(LineListPtr list)
Definition: linelist.c:33
LinePtr AddLine(LineListPtr list, const char *buf1)
Definition: linelist.c:94
void SortFileInfoList(FileInfoListPtr list, int sortKey, int sortOrder)
Definition: linelist.c:353
if(dx< 0)
Definition: linetemp.h:194
POINT cp
Definition: magnifier.c:59
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define _MAX_PATH
Definition: utility.h:77
int FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize)
Definition: cmds.c:254
int FTPIsDir(const FTPCIPtr cip, const char *const dir)
Definition: cmds.c:1531
int FTPChdir(const FTPCIPtr cip, const char *const cdCwd)
Definition: cmds.c:11
int FTPListToMemory2(const FTPCIPtr cip, const char *const pattern, const LineListPtr llines, const char *const lsflags, const int blankLines, int *const tryMLSD)
Definition: io.c:366
void PrintF(const FTPCIPtr cip, const char *const fmt,...)
Definition: util.c:340
#define ISTREQ(a, b)
Definition: util.h:33
char longstring[512]
Definition: util.h:12
#define kDoPerror
Definition: util.h:44
#define ISTRNEQ(a, b, s)
Definition: util.h:34
#define STREQ(a, b)
Definition: util.h:20
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static const WCHAR sp[]
Definition: suminfo.c:287
int readlink(const char *path, char *buf, size_t size)
#define min(a, b)
Definition: monoChain.cc:55
#define popen
Definition: syshdrs.h:72
#define pclose
Definition: syshdrs.h:73
#define LOCAL_PATH_DELIM
Definition: ncftp.h:492
#define StrRFindLocalPathDelim(a)
Definition: ncftp.h:495
void GetHomeDir(char *, size_t)
Definition: util.c:240
void(* FTPSigProc)(int)
Definition: ncftp.h:76
#define kFtwDir
Definition: ncftp.h:414
#define kSizeUnknown
Definition: ncftp.h:376
#define kCommandAvailable
Definition: ncftp.h:380
#define kModTimeUnknown
Definition: ncftp.h:377
#define longest_int
Definition: ncftp.h:68
#define StrFindLocalPathDelim(a)
Definition: ncftp.h:494
#define kGlobYes
Definition: ncftp.h:360
#define GLOBCHARSINSTR(a)
Definition: ncftp.h:358
#define kGlobChars
Definition: ncftp.h:357
#define NcSignal
Definition: ncftp.h:604
time_t UnMDTMDate(char *)
Definition: util.c:486
#define kCommandAvailabilityUnknown
Definition: ncftp.h:379
#define kFtwFile
Definition: ncftp.h:413
#define kLibraryMagic
Definition: ncftp.h:65
#define IsLocalPathDelim(c)
Definition: ncftp.h:497
int(* FTPFtwProc)(const FTPCIPtr cip, const char *fn, int flag)
Definition: ncftp.h:131
#define kServerTypeMicrosoftFTP
Definition: ncftp.h:465
#define kCommandNotAvailable
Definition: ncftp.h:381
#define LOCAL_PATH_DELIM_STR
Definition: ncftp.h:493
char * FGets(char *, size_t, FILE *)
Definition: util.c:111
#define kNoErr
Definition: ncftp_errno.h:9
#define kErrGlobNoMatch
Definition: ncftp_errno.h:89
#define kErrGlobFailed
Definition: ncftp_errno.h:68
#define kErrNotADirectory
Definition: ncftp_errno.h:108
#define kErrRecursionLimitReached
Definition: ncftp_errno.h:109
#define kErrBadMagic
Definition: ncftp_errno.h:55
#define kErrBadParameter
Definition: ncftp_errno.h:56
#define kErrCannotGoToPrevDir
Definition: ncftp_errno.h:58
#define kErrBadLineList
Definition: ncftp_errno.h:44
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define L(x)
Definition: ntvdm.h:50
static HANDLE proc()
Definition: pdb.c:34
static unsigned __int64 next
Definition: rand_nt.c:6
#define calloc
Definition: rosglue.h:14
_CRT_RESTORE_GCC_WARNINGS _CRT_DISABLE_GCC_WARNINGS _Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
_CRTIMP time_t __cdecl mktime(struct tm *_Tm)
Definition: time.h:418
_CRTIMP struct tm *__cdecl localtime(const time_t *_Time)
Definition: time.h:416
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
#define StrDup
Definition: shlwapi.h:1559
Definition: dirent.h:40
char magic[16]
Definition: ncftp.h:135
size_t maxFileLen
Definition: ncftp.h:267
size_t maxPlugLen
Definition: ncftp.h:268
longest_int size
Definition: ncftp.h:260
size_t relnameLen
Definition: ncftp.h:261
int type
Definition: ncftp.h:258
char * lname
Definition: ncftp.h:256
char * rlinkto
Definition: ncftp.h:255
time_t mdtm
Definition: ncftp.h:259
char * plug
Definition: ncftp.h:257
FileInfoPtr next
Definition: ncftp.h:252
char * rname
Definition: ncftp.h:254
char * relname
Definition: ncftp.h:253
Definition: ncftp.h:84
LinePtr first
Definition: ncftp.h:85
LinePtr last
Definition: ncftp.h:85
Definition: ncftp.h:79
char * line
Definition: ncftp.h:81
LinePtr next
Definition: ncftp.h:80
longest_int fsize
Definition: ncftp.h:279
time_t ftime
Definition: ncftp.h:280
char fname[512]
Definition: ncftp.h:276
char perm[16]
Definition: ncftp.h:284
int gid
Definition: ncftp.h:283
int ftype
Definition: ncftp.h:278
int mode
Definition: ncftp.h:281
int uid
Definition: ncftp.h:282
char owner[16]
Definition: ncftp.h:285
char group[16]
Definition: ncftp.h:286
char linkto[512]
Definition: ncftp.h:277
Definition: ftp_var.h:139
Definition: fatfs.h:198
char * d_name
Definition: dirent.h:29
Definition: fci.c:127
Definition: parser.c:49
Definition: time.h:68
int tm_mon
Definition: time.h:73
int tm_year
Definition: time.h:74
int tm_hour
Definition: time.h:71
int tm_isdst
Definition: time.h:77
int tm_mday
Definition: time.h:72
int tm_min
Definition: time.h:70
__CRT_INLINE void __cdecl ftime(struct timeb *_Tmb)
Definition: timeb.h:96
eMaj lines
Definition: tritemp.h:206
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FindNextFile
Definition: winbase.h:3813
#define FindFirstFile
Definition: winbase.h:3807
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121
#define snprintf
Definition: wintirpc.h:48