ReactOS  0.4.14-dev-49-gfb4591c
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 
10 static 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 
42 static void
43 RemoteGlobCollapse(const char *pattern, LineListPtr fileList)
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. */
102 static void
103 CheckForLS_d(FTPCIPtr cip)
104 {
105  LineList lines;
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 
134 static 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 
174 static int
175 UnDosLine( 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  *
192 0123456789012345678901234567890123456789012345678901234567890123456789
193 04-27-99 10:32PM 270158 Game booklet.pdf
194 03-11-99 10:03PM <DIR> Get A3d Banner
195 
196 We also try to parse the format from CMD.EXE, which is similar:
197 
198 03/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 
352 static int
353 UnLslRLine( 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 
560 int
561 UnLslR(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;
573  time_t ftime, now;
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 
692 int
693 UnMlsT(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 
826 int
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
942 static void
943 print1(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 
954 static void
955 print2(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 
970 static void
971 SortRecursiveFileList(FileInfoListPtr files)
972 {
973  VectorizeFileInfoList(files);
974  SortFileInfoList(files, 'b', '?');
976 } /* SortRecursiveFileList */
977 #endif
978 
979 
980 
981 
982 int
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 
1031 int
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 
1076 goback:
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 
1088 static void
1089 Traverse(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 
1159 next:
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 
1183 static void
1184 Traverse(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 
1275 int
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 
1332 int
1334 {
1335  return (FTPLocalRecursiveFileList2(cip, fileList, files, 0));
1336 } /* FTPLocalRecursiveFileList */
1337 
1338 
1339 
1340 int
1341 FTPRemoteGlob(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  */
1428 static void
1429 ExpandTilde(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 
1479 static int
1480 WinLocalGlob(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 
1538 static int
1539 LazyUnixLocalGlob(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 
1579 int
1580 FTPLocalGlob(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 
1623 static int
1624 FTPFtwL2(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 
1705 int
1706 FTPFtw(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) {
1718  result = cip->errNo = kErrNotADirectory;
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. */
1756  cip->errNo = kErrCannotGoToPrevDir;
1757  return (result);
1758  }
1759 
1760  if ((result2 != kNoErr) && (result == kNoErr))
1761  result = result2;
1762 
1763  return (result);
1764 } /* FTPFtw */
1765 
1766 /* eof */
int ComputeRNames(FileInfoListPtr dst, const char *dstdir, int pflag, int nochop)
Definition: linelist.c:579
LinePtr last
Definition: ncftp.h:85
#define IsLocalPathDelim(c)
Definition: ncftp.h:497
#define isspace(c)
Definition: acclib.h:69
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
int tm_min
Definition: time.h:78
void SortFileInfoList(FileInfoListPtr list, int sortKey, int sortOrder)
Definition: linelist.c:353
int UnMlsT(const char *const line0, const MLstItemPtr mlip)
Definition: glob.c:693
#define kErrBadParameter
Definition: ncftp_errno.h:56
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define kCommandAvailable
Definition: ncftp.h:380
size_t relnameLen
Definition: ncftp.h:261
HRESULT hr
Definition: shlfolder.c:183
int FTPLocalRecursiveFileList(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files)
Definition: glob.c:1333
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
Definition: ftp_var.h:139
int FTPFtw(const FTPCIPtr cip, const char *const dir, FTPFtwProc proc, int maxdepth)
Definition: glob.c:1706
char fname[512]
Definition: ncftp.h:276
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
static void ExpandTilde(char *pattern, size_t siz)
Definition: glob.c:1429
#define free
Definition: debug_ros.c:5
int tm_mday
Definition: time.h:80
#define kCommandAvailabilityUnknown
Definition: ncftp.h:379
time_t UnMDTMDate(char *)
Definition: util.c:486
GLdouble n
Definition: glext.h:7729
LinePtr next
Definition: ncftp.h:80
#define ISTRNEQ(a, b, s)
Definition: util.h:34
#define snprintf
Definition: wintirpc.h:48
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
void VectorizeFileInfoList(FileInfoListPtr list)
Definition: linelist.c:423
longest_int fsize
Definition: ncftp.h:279
char * cmd
Definition: vfdcmd.c:85
char owner[16]
Definition: ncftp.h:285
char linkto[512]
Definition: ncftp.h:277
GLuint GLuint end
Definition: gl.h:1545
static HANDLE proc()
Definition: pdb.c:32
int FTPLocalRecursiveFileList2(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files, int erelative)
Definition: glob.c:1276
int tm_year
Definition: time.h:82
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define kErrGlobFailed
Definition: ncftp_errno.h:68
__u16 time
Definition: mkdosfs.c:366
char * lname
Definition: ncftp.h:256
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
char * rname
Definition: ncftp.h:254
int gid
Definition: ncftp.h:283
char magic[16]
Definition: ncftp.h:135
int mode
Definition: ncftp.h:281
const GLfloat * m
Definition: glext.h:10848
Definition: fatfs.h:198
#define ISTREQ(a, b)
Definition: util.h:33
int ConcatFileInfoList(FileInfoListPtr dst, FileInfoListPtr src)
Definition: linelist.c:556
#define kErrGlobNoMatch
Definition: ncftp_errno.h:89
char perm[16]
Definition: ncftp.h:284
char * plug
Definition: ncftp.h:257
#define S_ISLNK(m)
Definition: ext2fs.h:368
#define sprintf(buf, format,...)
Definition: sprintf.c:55
DIR *__cdecl opendir(const char *)
char * Strncat(char *const, const char *const, const size_t)
Definition: Strncat.c:13
#define StrDup
Definition: shlwapi.h:1533
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
void UnvectorizeFileInfoList(FileInfoListPtr list)
Definition: linelist.c:441
int ConcatFileToFileInfoList(FileInfoListPtr dst, char *rfile)
Definition: linelist.c:740
int UnLslR(FileInfoListPtr filp, LineListPtr llp, int serverType)
Definition: glob.c:561
time_t now
Definition: finger.c:65
#define _MAX_PATH
Definition: utility.h:77
static int LsMonthNameToNum(char *cp)
Definition: glob.c:135
#define pp
Definition: hlsl.yy.c:978
Definition: dirent.h:39
int FTPLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
Definition: glob.c:1580
smooth NULL
Definition: ftsmooth.c:416
unsigned char
Definition: typeof.h:29
#define kServerTypeMicrosoftFTP
Definition: ncftp.h:465
char group[16]
Definition: ncftp.h:286
Definition: parser.c:48
FileInfoPtr AddFileInfo(FileInfoListPtr list, FileInfoPtr src)
Definition: linelist.c:530
char * rlinkto
Definition: ncftp.h:255
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
int tm_mon
Definition: time.h:81
unsigned int dir
Definition: maze.c:112
#define SCANF_LONG_LONG
Definition: wincfg.h:30
#define FindFirstFile
Definition: winbase.h:3599
char * relname
Definition: ncftp.h:253
#define isdigit(c)
Definition: acclib.h:68
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121
void InitFileInfoList(FileInfoListPtr list)
Definition: linelist.c:193
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
GLuint GLfloat * val
Definition: glext.h:7180
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define kFtwDir
Definition: ncftp.h:414
char * d_name
Definition: dirent.h:29
DWORD dwErr
Definition: service.c:36
#define STREQ(a, b)
Definition: util.h:20
#define STRNCAT(d, s)
Definition: Strn.h:48
eMaj lines
Definition: tritemp.h:206
__kernel_size_t size_t
Definition: linux.h:237
char * FGets(char *, size_t, FILE *)
Definition: util.c:111
int FTPRemoteRecursiveFileList1(FTPCIPtr cip, char *const rdir, FileInfoListPtr files)
Definition: glob.c:983
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define isupper(c)
Definition: acclib.h:71
#define FindNextFile
Definition: winbase.h:3605
static int LazyUnixLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *const pattern)
Definition: glob.c:1539
#define S_ISDIR(mode)
Definition: various.h:18
#define longest_int
Definition: ncftp.h:68
#define kErrBadMagic
Definition: ncftp_errno.h:55
const char file[]
Definition: icontest.c:11
#define kGlobYes
Definition: ncftp.h:360
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
LinePtr AddLine(LineListPtr list, const char *buf1)
Definition: linelist.c:94
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL Error
Definition: chkdsk.c:66
size_t maxFileLen
Definition: ncftp.h:267
void(* FTPSigProc)(int)
Definition: ncftp.h:76
size_t maxPlugLen
Definition: ncftp.h:268
time_t ftime
Definition: ncftp.h:280
Definition: ncftp.h:79
#define kErrNotADirectory
Definition: ncftp_errno.h:108
#define kFtwFile
Definition: ncftp.h:413
#define kErrCannotGoToPrevDir
Definition: ncftp_errno.h:58
#define SIGPIPE
Definition: signal.h:35
char line[200]
Definition: main.c:97
Definition: ncftp.h:84
#define kGlobChars
Definition: ncftp.h:357
int FTPRemoteRecursiveFileList(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files)
Definition: glob.c:1032
static const WCHAR L[]
Definition: oid.c:1250
#define Lstat
Definition: syshdrs.h:80
#define kDoPerror
Definition: util.h:44
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
LinePtr first
Definition: ncftp.h:85
Definition: time.h:76
#define islower(c)
Definition: acclib.h:72
_CRTIMP struct tm *__cdecl localtime(const time_t *_Time)
Definition: time.h:424
#define pclose
Definition: syshdrs.h:73
int __cdecl closedir(DIR *)
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
#define kCommandNotAvailable
Definition: ncftp.h:381
int ftype
Definition: ncftp.h:278
struct dirent *__cdecl readdir(DIR *)
int type
Definition: ncftp.h:258
int FTPChdir(const FTPCIPtr cip, const char *const cdCwd)
Definition: cmds.c:11
time_t mdtm
Definition: ncftp.h:259
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
#define NcSignal
Definition: ncftp.h:604
int FTPRemoteGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
Definition: glob.c:1341
#define kErrRecursionLimitReached
Definition: ncftp_errno.h:109
__CRT_INLINE void __cdecl ftime(struct timeb *_Tmb)
Definition: timeb.h:96
void PrintF(const FTPCIPtr cip, const char *const fmt,...)
Definition: util.c:340
void DisposeFileInfoListContents(FileInfoListPtr list)
Definition: linelist.c:152
#define Stat
Definition: syshdrs.h:78
int UnMlsD(FileInfoListPtr filp, LineListPtr llp)
Definition: glob.c:827
static unsigned __int64 next
Definition: rand_nt.c:6
__kernel_mode_t mode_t
Definition: linux.h:199
__kernel_time_t time_t
Definition: linux.h:252
#define popen
Definition: syshdrs.h:72
char * Strnpcat(char *const, const char *const, size_t)
Definition: Strnpcat.c:16
#define GLOBCHARSINSTR(a)
Definition: ncftp.h:358
char * Strncpy(char *const, const char *const, const size_t)
Definition: Strncpy.c:11
#define LOCAL_PATH_DELIM_STR
Definition: ncftp.h:493
LinePtr RemoveLine(LineListPtr list, LinePtr killMe)
Definition: linelist.c:63
void InitLineList(LineListPtr list)
Definition: linelist.c:54
_CRTIMP time_t __cdecl mktime(struct tm *_Tm)
Definition: time.h:426
int FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize)
Definition: cmds.c:254
#define min(a, b)
Definition: monoChain.cc:55
int FTPIsDir(const FTPCIPtr cip, const char *const dir)
Definition: cmds.c:1531
#define LOCAL_PATH_DELIM
Definition: ncftp.h:492
char * strchr(const char *String, int ch)
Definition: utclib.c:501
char longstring[512]
Definition: util.h:12
void GetHomeDir(char *, size_t)
Definition: util.c:240
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define kModTimeUnknown
Definition: ncftp.h:377
POINT cp
Definition: magnifier.c:59
#define calloc
Definition: rosglue.h:14
#define kSizeUnknown
Definition: ncftp.h:376
#define kErrBadLineList
Definition: ncftp_errno.h:44
#define kLibraryMagic
Definition: ncftp.h:65
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
int tm_hour
Definition: time.h:79
#define kNoErr
Definition: ncftp_errno.h:9
#define StrRFindLocalPathDelim(a)
Definition: ncftp.h:495
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int readlink(const char *path, char *buf, size_t size)
static const WCHAR sp[]
Definition: suminfo.c:288
#define malloc
Definition: debug_ros.c:4
int(* FTPFtwProc)(const FTPCIPtr cip, const char *fn, int flag)
Definition: ncftp.h:131
_Check_return_ _CRTIMP int __cdecl ispunct(_In_ int _C)
void DisposeLineListContents(LineListPtr list)
Definition: linelist.c:33
static int FTPFtwL2(const FTPCIPtr cip, char *dir, char *end, size_t dirsize, FTPFtwProc proc, int maxdepth)
Definition: glob.c:1624
static void Traverse(FTPCIPtr cip, char *fullpath, struct Stat *st, char *relpath, FileInfoListPtr filp)
Definition: glob.c:1184
#define SIG_IGN
Definition: signal.h:48
int tm_isdst
Definition: time.h:85
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
#define S_ISREG(mode)
Definition: various.h:17
char * line
Definition: ncftp.h:81
#define StrFindLocalPathDelim(a)
Definition: ncftp.h:494
#define glberr(a)
longest_int size
Definition: ncftp.h:260
static const char * rwx[9]
Definition: glob.c:10
int uid
Definition: ncftp.h:282
GLubyte * pattern
Definition: glext.h:7787
#define printf
Definition: config.h:203
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
Definition: fci.c:126
FileInfoPtr next
Definition: ncftp.h:252
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
GLint fsize
Definition: glext.h:9408
static void RemoteGlobCollapse(const char *pattern, LineListPtr fileList)
Definition: glob.c:43