rpm  5.4.15
rpmrpc.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio_internal.h>
8 #include <rpmmacro.h>
9 
10 #define _RPMDIR_INTERNAL
11 #include <rpmdir.h>
12 #define _RPMDAV_INTERNAL
13 #include <rpmdav.h>
14 
15 #include <rpmhash.h>
16 #include <ugid.h>
17 
18 #include "debug.h"
19 
20 /*@access DIR @*/
21 /*@access FD_t @*/
22 /*@access urlinfo @*/
23 
24 /* =============================================================== */
25 static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode)
26  /*@globals h_errno, fileSystem, internalState @*/
27  /*@modifies fileSystem, internalState @*/
28 {
29  int rc;
30  if ((rc = ftpCmd("MKD", path, NULL)) != 0)
31  return rc;
32 #if NOTYET
33  { char buf[20];
34  sprintf(buf, " 0%o", mode);
35  (void) ftpCmd("SITE CHMOD", path, buf);
36  }
37 #endif
38  return rc;
39 }
40 
41 static int ftpChdir(const char * path)
42  /*@globals h_errno, fileSystem, internalState @*/
43  /*@modifies fileSystem, internalState @*/
44 {
45  return ftpCmd("CWD", path, NULL);
46 }
47 
48 static int ftpRmdir(const char * path)
49  /*@globals h_errno, fileSystem, internalState @*/
50  /*@modifies fileSystem, internalState @*/
51 {
52  return ftpCmd("RMD", path, NULL);
53 }
54 
55 static int ftpRename(const char * oldpath, const char * newpath)
56  /*@globals h_errno, fileSystem, internalState @*/
57  /*@modifies fileSystem, internalState @*/
58 {
59  int rc;
60  if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0)
61  return rc;
62  return ftpCmd("RNTO", newpath, NULL);
63 }
64 
65 static int ftpUnlink(const char * path)
66  /*@globals h_errno, fileSystem, internalState @*/
67  /*@modifies fileSystem, internalState @*/
68 {
69  return ftpCmd("DELE", path, NULL);
70 }
71 
72 /* =============================================================== */
73 int Mkdir (const char * path, mode_t mode)
74 {
75  const char * lpath;
76  int ut = urlPath(path, &lpath);
77 
78 if (_rpmio_debug)
79 fprintf(stderr, "*** Mkdir(%s, 0%o)\n", path, (unsigned)mode);
80  switch (ut) {
81  case URL_IS_FTP:
82  return ftpMkdir(path, mode);
83  /*@notreached@*/ break;
84  case URL_IS_HTTPS:
85  case URL_IS_HTTP:
86 #ifdef WITH_NEON
87  return davMkdir(path, mode);
88 #endif
89  /*@notreached@*/ break;
90  case URL_IS_PATH:
91  path = lpath;
92  /*@fallthrough@*/
93  case URL_IS_UNKNOWN:
94  break;
95  case URL_IS_DASH:
96  case URL_IS_HKP:
97  case URL_IS_MONGO: /* XXX FIXME */
98  default:
99  return -2;
100  /*@notreached@*/ break;
101  }
102  return mkdir(path, mode);
103 }
104 
105 int Chdir (const char * path)
106 {
107  const char * lpath;
108  int ut = urlPath(path, &lpath);
109 
110 if (_rpmio_debug)
111 fprintf(stderr, "*** Chdir(%s)\n", path);
112  switch (ut) {
113  case URL_IS_FTP:
114  return ftpChdir(path);
115  /*@notreached@*/ break;
116  case URL_IS_HTTPS:
117  case URL_IS_HTTP:
118 #ifdef NOTYET
119  return davChdir(path);
120 #else
121  errno = EINVAL; /* XXX W2DO? */
122  return -2;
123 #endif
124  /*@notreached@*/ break;
125  case URL_IS_PATH:
126  path = lpath;
127  /*@fallthrough@*/
128  case URL_IS_UNKNOWN:
129  break;
130  case URL_IS_DASH:
131  case URL_IS_HKP:
132  case URL_IS_MONGO: /* XXX FIXME */
133  default:
134  errno = EINVAL; /* XXX W2DO? */
135  return -2;
136  /*@notreached@*/ break;
137  }
138  return chdir(path);
139 }
140 
141 int Rmdir (const char * path)
142 {
143  const char * lpath;
144  int ut = urlPath(path, &lpath);
145 
146 if (_rpmio_debug)
147 fprintf(stderr, "*** Rmdir(%s)\n", path);
148  switch (ut) {
149  case URL_IS_FTP:
150  return ftpRmdir(path);
151  /*@notreached@*/ break;
152  case URL_IS_HTTPS:
153  case URL_IS_HTTP:
154 #ifdef WITH_NEON
155  return davRmdir(path);
156 #endif
157  /*@notreached@*/ break;
158  case URL_IS_PATH:
159  path = lpath;
160  /*@fallthrough@*/
161  case URL_IS_UNKNOWN:
162  break;
163  case URL_IS_DASH:
164  case URL_IS_HKP:
165  case URL_IS_MONGO: /* XXX FIXME */
166  default:
167  return -2;
168  /*@notreached@*/ break;
169  }
170  return rmdir(path);
171 }
172 
173 /*@unchecked@*/
174 const char * _chroot_prefix = NULL;
175 
176 int Chroot(const char * path)
177 {
178  const char * lpath;
179  int ut = urlPath(path, &lpath);
180  int rc;
181 
182  switch (ut) {
183  case URL_IS_PATH:
184  path = lpath;
185  /*@fallthrough@*/
186  case URL_IS_UNKNOWN:
187  break;
188  case URL_IS_DASH:
189  case URL_IS_HKP:
190  case URL_IS_FTP: /* XXX TODO: implement. */
191  case URL_IS_HTTP: /* XXX TODO: implement. */
192  case URL_IS_HTTPS: /* XXX TODO: implement. */
193  case URL_IS_MONGO: /* XXX FIXME */
194  default:
195  errno = EINVAL; /* XXX W2DO? */
196  return -2;
197  /*@notreached@*/ break;
198  }
199 
200 /*@-dependenttrans -modobserver -observertrans @*/
202 /*@=dependenttrans =modobserver =observertrans @*/
203 /*@-globs -mods@*/ /* XXX hide rpmGlobalMacroContext mods for now. */
204  if (strcmp(path, "."))
205  _chroot_prefix = rpmGetPath(path, NULL);
206 /*@=globs =mods@*/
207 
208 /*@-superuser@*/
209  rc = chroot(path);
210 /*@=superuser@*/
211 
212 if (_rpmio_debug)
213 fprintf(stderr, "<-- %s(%s) prefix %s rc %d\n", __FUNCTION__, path, _chroot_prefix, rc);
214 
215  return rc;
216 }
217 /*@=mods@*/
218 
219 int Open(const char * path, int flags, mode_t mode)
220 {
221  const char * lpath;
222  int ut = urlPath(path, &lpath);
223  int fdno;
224 
225  switch (ut) {
226  case URL_IS_PATH:
227  path = lpath;
228  /*@fallthrough@*/
229  case URL_IS_UNKNOWN:
230  break;
231  case URL_IS_DASH:
232  case URL_IS_HKP:
233  case URL_IS_FTP: /* XXX TODO: implement. */
234  case URL_IS_HTTP: /* XXX TODO: implement. */
235  case URL_IS_HTTPS: /* XXX TODO: implement. */
236  case URL_IS_MONGO: /* XXX FIXME */
237  default:
238  errno = EINVAL; /* XXX W2DO? */
239  return -2;
240  /*@notreached@*/ break;
241  }
242 
243  if (_chroot_prefix && _chroot_prefix[0] == '/' && _chroot_prefix[1] != '\0')
244  {
245  size_t nb = strlen(_chroot_prefix);
246  size_t ob = strlen(path);
247  while (nb > 0 && _chroot_prefix[nb-1] == '/')
248  nb--;
249  if (ob > nb && !strncmp(path, _chroot_prefix, nb) && path[nb] == '/')
250  path += nb;
251  }
252 #ifdef NOTYET /* XXX likely sane default. */
253  if (mode == 0)
254  mode = 0644;
255 #endif
256  fdno = open(path, flags, mode);
257  /* XXX if the open(2) fails, try to strip a possible chroot(2) prefix. */
258  if (fdno < 0 && errno == ENOENT) {
259  const char *dbpath = rpmExpand("%{?_dbpath}/", NULL);
260  const char * fn = strstr(path + 1, dbpath);
261  if (fn)
262  fdno = open(fn, flags, mode);
263  dbpath = _free(dbpath);
264  }
265  if (fdno >= 0) {
266  if (fcntl(fdno, F_SETFD, FD_CLOEXEC) < 0) {
267  (void) close(fdno);
268  fdno = -1;
269  }
270  }
271 
272 #ifdef NOTYET /* XXX db-5.0.26 is slower using POSIX_FADV_RANDOM. */
273 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_RANDOM)
274  (void) posix_fadvise(fdno, 0, 0, POSIX_FADV_RANDOM);
275 #endif
276 #endif
277 
278 if (_rpmio_debug)
279 fprintf(stderr, "<-- %s(%s, 0x%x, 0%o) prefix %s fdno %d\n", __FUNCTION__, path, flags, (unsigned)mode, _chroot_prefix, fdno);
280 
281  return fdno;
282 }
283 
284 /* XXX rpmdb.c: analogue to rename(2). */
285 
286 int Rename (const char * oldpath, const char * newpath)
287 {
288  const char *oe = NULL;
289  const char *ne = NULL;
290  int oldut, newut;
291 
292 if (_rpmio_debug)
293 fprintf(stderr, "*** Rename(%s, %s)\n", oldpath, newpath);
294  /* XXX lib/install.c used to rely on this behavior. */
295  if (!strcmp(oldpath, newpath)) return 0;
296 
297  oldut = urlPath(oldpath, &oe);
298  switch (oldut) {
299  case URL_IS_HTTPS:
300  case URL_IS_HTTP:
301 #ifdef WITH_NEON
302  return davRename(oldpath, newpath);
303 #endif
304  /*@notreached@*/ break;
305  case URL_IS_FTP: /* XXX WRONG WRONG WRONG */
306  case URL_IS_PATH:
307  case URL_IS_UNKNOWN:
308  break;
309  case URL_IS_DASH:
310  case URL_IS_HKP:
311  case URL_IS_MONGO: /* XXX FIXME */
312  default:
313  return -2;
314  /*@notreached@*/ break;
315  }
316 
317  newut = urlPath(newpath, &ne);
318  switch (newut) {
319  case URL_IS_FTP:
320 if (_rpmio_debug)
321 fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
322  if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
323  !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
324  return -2;
325  return ftpRename(oldpath, newpath);
326  /*@notreached@*/ break;
327  case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */
328  case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */
329  case URL_IS_PATH:
330  oldpath = oe;
331  newpath = ne;
332  break;
333  case URL_IS_UNKNOWN:
334  break;
335  case URL_IS_DASH:
336  case URL_IS_HKP:
337  case URL_IS_MONGO: /* XXX FIXME */
338  default:
339  return -2;
340  /*@notreached@*/ break;
341  }
342  return rename(oldpath, newpath);
343 }
344 
345 int Link (const char * oldpath, const char * newpath)
346 {
347  const char *oe = NULL;
348  const char *ne = NULL;
349  int oldut, newut;
350 
351 if (_rpmio_debug)
352 fprintf(stderr, "*** Link(%s, %s)\n", oldpath, newpath);
353  oldut = urlPath(oldpath, &oe);
354  switch (oldut) {
355  case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */
356  case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */
357  case URL_IS_FTP: /* XXX WRONG WRONG WRONG */
358  case URL_IS_PATH:
359  case URL_IS_UNKNOWN:
360  break;
361  case URL_IS_DASH:
362  case URL_IS_HKP:
363  case URL_IS_MONGO: /* XXX FIXME */
364  default:
365  return -2;
366  /*@notreached@*/ break;
367  }
368 
369  newut = urlPath(newpath, &ne);
370  switch (newut) {
371  case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */
372  case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */
373  case URL_IS_FTP: /* XXX WRONG WRONG WRONG */
374  case URL_IS_PATH:
375 if (_rpmio_debug)
376 fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
377  if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
378  !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
379  return -2;
380  oldpath = oe;
381  newpath = ne;
382  break;
383  case URL_IS_UNKNOWN:
384  break;
385  case URL_IS_DASH:
386  case URL_IS_HKP:
387  case URL_IS_MONGO: /* XXX FIXME */
388  default:
389  return -2;
390  /*@notreached@*/ break;
391  }
392  return link(oldpath, newpath);
393 }
394 
395 /* XXX build/build.c: analogue to unlink(2). */
396 
397 int Unlink(const char * path) {
398  const char * lpath;
399  int ut = urlPath(path, &lpath);
400  int rc = -2;
401 
402  switch (ut) {
403  case URL_IS_FTP:
404  rc = ftpUnlink(path);
405  /*@notreached@*/ break;
406  case URL_IS_HTTPS:
407  case URL_IS_HTTP:
408 #ifdef WITH_NEON
409  rc = davUnlink(path);
410 #endif
411  /*@notreached@*/ break;
412  case URL_IS_PATH:
413  path = lpath;
414  /*@fallthrough@*/
415  case URL_IS_UNKNOWN:
416  break;
417  case URL_IS_DASH:
418  case URL_IS_HKP:
419  case URL_IS_MONGO: /* XXX FIXME */
420  default:
421  errno = EINVAL;
422  goto exit;
423  /*@notreached@*/ break;
424  }
425  rc = unlink(path);
426 exit:
427 if (_rpmio_debug)
428 fprintf(stderr, "<-- %s(%s) rc %d\n", __FUNCTION__, path, rc);
429  return rc;
430 }
431 
432 /* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */
433 
434 #define g_strdup xstrdup
435 #define g_free free
436 
437 /*
438  * FIXME: this is broken. It depends on mc not crossing border on month!
439  */
440 /*@unchecked@*/
441 static int current_mday;
442 /*@unchecked@*/
443 static int current_mon;
444 /*@unchecked@*/
445 static int current_year;
446 
447 /* Following stuff (parse_ls_lga) is used by ftpfs and extfs */
448 #define MAXCOLS 30
449 
450 /*@unchecked@*/
451 static char *columns [MAXCOLS]; /* Points to the string in column n */
452 /*@unchecked@*/
453 static int column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */
454 
455 static int
456 vfs_split_text (char *p)
457  /*@globals columns, column_ptr @*/
458  /*@modifies *p, columns, column_ptr @*/
459 {
460  char *original = p;
461  int numcols;
462 
463 
464  for (numcols = 0; *p && numcols < MAXCOLS; numcols++){
465  while (*p == ' ' || *p == '\r' || *p == '\n'){
466  *p = '\0';
467  p++;
468  }
469  columns [numcols] = p;
470  column_ptr [numcols] = p - original;
471  while (*p && *p != ' ' && *p != '\r' && *p != '\n')
472  p++;
473  }
474  return numcols;
475 }
476 
477 static int
478 is_num (int idx)
479  /*@*/
480 {
481  if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9')
482  return 0;
483  return 1;
484 }
485 
486 static int
487 is_dos_date(/*@null@*/ const char *str)
488  /*@*/
489 {
490  if (str != NULL && strlen(str) == 8 &&
491  str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL)
492  return 1;
493  return 0;
494 }
495 
496 static int
497 is_week (/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
498  /*@modifies *tim @*/
499 {
500 /*@observer@*/ static const char * week = "SunMonTueWedThuFriSat";
501  const char * pos;
502 
503  /*@-observertrans -mayaliasunique@*/
504  if (str != NULL && (pos=strstr(week, str)) != NULL) {
505  /*@=observertrans =mayaliasunique@*/
506  if (tim != NULL)
507  tim->tm_wday = (pos - week)/3;
508  return 1;
509  }
510  return 0;
511 }
512 
513 static int
514 is_month (/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
515  /*@modifies *tim @*/
516 {
517 /*@observer@*/ static const char * month = "JanFebMarAprMayJunJulAugSepOctNovDec";
518  const char * pos;
519 
520  /*@-observertrans -mayaliasunique@*/
521  if (str != NULL && (pos = strstr(month, str)) != NULL) {
522  /*@=observertrans -mayaliasunique@*/
523  if (tim != NULL)
524  tim->tm_mon = (pos - month)/3;
525  return 1;
526  }
527  return 0;
528 }
529 
530 static int
531 is_time (/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
532  /*@modifies *tim @*/
533 {
534  const char * p, * p2;
535 
536  if (str != NULL && (p = strchr(str, ':')) && (p2 = strrchr(str, ':'))) {
537  if (p != p2) {
538  if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3)
539  return 0;
540  } else {
541  if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2)
542  return 0;
543  }
544  } else
545  return 0;
546 
547  return 1;
548 }
549 
550 static int is_year(/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
551  /*@modifies *tim @*/
552 {
553  long year;
554 
555  if (str == NULL)
556  return 0;
557 
558  if (strchr(str,':'))
559  return 0;
560 
561  if (strlen(str) != 4)
562  return 0;
563 
564  if (sscanf(str, "%ld", &year) != 1)
565  return 0;
566 
567  if (year < 1900 || year > 3000)
568  return 0;
569 
570  tim->tm_year = (int) (year - 1900);
571 
572  return 1;
573 }
574 
575 /*
576  * FIXME: this is broken. Consider following entry:
577  * -rwx------ 1 root root 1 Aug 31 10:04 2904 1234
578  * where "2904 1234" is filename. Well, this code decodes it as year :-(.
579  */
580 
581 static int
583  /*@*/
584 {
585  switch (c) {
586  case 'd': return (int)S_IFDIR;
587  case 'b': return (int)S_IFBLK;
588  case 'c': return (int)S_IFCHR;
589  case 'l': return (int)S_IFLNK;
590  case 's':
591 #ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */
592  return (int)S_IFSOCK;
593 #endif
594  case 'p': return (int)S_IFIFO;
595  case 'm': case 'n': /* Don't know what these are :-) */
596  case '-': case '?': return (int)S_IFREG;
597  default: return -1;
598  }
599 }
600 
601 static int vfs_parse_filemode (const char *p)
602  /*@*/
603 { /* converts rw-rw-rw- into 0666 */
604  int res = 0;
605  switch (*(p++)) {
606  case 'r': res |= 0400; break;
607  case '-': break;
608  default: return -1;
609  }
610  switch (*(p++)) {
611  case 'w': res |= 0200; break;
612  case '-': break;
613  default: return -1;
614  }
615  switch (*(p++)) {
616  case 'x': res |= 0100; break;
617  case 's': res |= 0100 | S_ISUID; break;
618  case 'S': res |= S_ISUID; break;
619  case '-': break;
620  default: return -1;
621  }
622  switch (*(p++)) {
623  case 'r': res |= 0040; break;
624  case '-': break;
625  default: return -1;
626  }
627  switch (*(p++)) {
628  case 'w': res |= 0020; break;
629  case '-': break;
630  default: return -1;
631  }
632  switch (*(p++)) {
633  case 'x': res |= 0010; break;
634  case 's': res |= 0010 | S_ISGID; break;
635  case 'l': /* Solaris produces these */
636  case 'S': res |= S_ISGID; break;
637  case '-': break;
638  default: return -1;
639  }
640  switch (*(p++)) {
641  case 'r': res |= 0004; break;
642  case '-': break;
643  default: return -1;
644  }
645  switch (*(p++)) {
646  case 'w': res |= 0002; break;
647  case '-': break;
648  default: return -1;
649  }
650  switch (*(p++)) {
651  case 'x': res |= 0001; break;
652  case 't': res |= 0001 | S_ISVTX; break;
653  case 'T': res |= S_ISVTX; break;
654  case '-': break;
655  default: return -1;
656  }
657  return res;
658 }
659 
660 static int vfs_parse_filedate(int idx, /*@out@*/ time_t *t)
661  /*@modifies *t @*/
662 { /* This thing parses from idx in columns[] array */
663 
664  char *p;
665  struct tm tim;
666  int d[3];
667  int got_year = 0;
668 
669  /* Let's setup default time values */
670  tim.tm_year = current_year;
671  tim.tm_mon = current_mon;
672  tim.tm_mday = current_mday;
673  tim.tm_hour = 0;
674  tim.tm_min = 0;
675  tim.tm_sec = 0;
676  tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */
677 
678  p = columns [idx++];
679 
680  /* We eat weekday name in case of extfs */
681  if(is_week(p, &tim))
682  p = columns [idx++];
683 
684  /* Month name */
685  if(is_month(p, &tim)){
686  /* And we expect, it followed by day number */
687  if (is_num (idx))
688  tim.tm_mday = (int)atol (columns [idx++]);
689  else
690  return 0; /* No day */
691 
692  } else {
693  /* We usually expect:
694  Mon DD hh:mm
695  Mon DD YYYY
696  But in case of extfs we allow these date formats:
697  Mon DD YYYY hh:mm
698  Mon DD hh:mm YYYY
699  Wek Mon DD hh:mm:ss YYYY
700  MM-DD-YY hh:mm
701  where Mon is Jan-Dec, DD, MM, YY two digit day, month, year,
702  YYYY four digit year, hh, mm, ss two digit hour, minute or second. */
703 
704  /* Here just this special case with MM-DD-YY */
705  if (is_dos_date(p)){
706 /*@-mods@*/
707  p[2] = p[5] = '-';
708 /*@=mods@*/
709 
710  memset(d, 0, sizeof(d));
711  if (sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){
712  /* We expect to get:
713  1. MM-DD-YY
714  2. DD-MM-YY
715  3. YY-MM-DD
716  4. YY-DD-MM */
717 
718  /* Hmm... maybe, next time :)*/
719 
720  /* At last, MM-DD-YY */
721  d[0]--; /* Months are zerobased */
722  /* Y2K madness */
723  if(d[2] < 70)
724  d[2] += 100;
725 
726  tim.tm_mon = d[0];
727  tim.tm_mday = d[1];
728  tim.tm_year = d[2];
729  got_year = 1;
730  } else
731  return 0; /* sscanf failed */
732  } else
733  return 0; /* unsupported format */
734  }
735 
736  /* Here we expect to find time and/or year */
737 
738  if (is_num (idx)) {
739  if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) {
740  idx++;
741 
742  /* This is a special case for ctime() or Mon DD YYYY hh:mm */
743  if(is_num (idx) &&
744  ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
745  idx++; /* time & year or reverse */
746  } /* only time or date */
747  }
748  else
749  return 0; /* Nor time or date */
750 
751  /*
752  * If the date is less than 6 months in the past, it is shown without year
753  * other dates in the past or future are shown with year but without time
754  * This does not check for years before 1900 ... I don't know, how
755  * to represent them at all
756  */
757  if (!got_year &&
758  current_mon < 6 && current_mon < tim.tm_mon &&
759  tim.tm_mon - current_mon >= 6)
760 
761  tim.tm_year--;
762 
763  if ((*t = mktime(&tim)) < 0)
764  *t = 0;
765  return idx;
766 }
767 
768 static int
769 vfs_parse_ls_lga (char * p, /*@out@*/ struct stat * st,
770  /*@out@*/ const char ** filename,
771  /*@out@*/ const char ** linkname)
772  /*@modifies *p, *st, *filename, *linkname @*/
773 {
774  int idx, idx2, num_cols;
775  int i;
776  char *p_copy;
777  long n;
778 
779  if (strncmp (p, "total", 5) == 0)
780  return 0;
781 
782  p_copy = g_strdup(p);
783 /* XXX FIXME: parse out inode number from "NLST -lai ." */
784 /* XXX FIXME: parse out sizein blocks from "NLST -lais ." */
785 
786  if ((i = vfs_parse_filetype(*(p++))) == -1)
787  goto error;
788 
789  st->st_mode = i;
790  if (*p == ' ') /* Notwell 4 */
791  p++;
792  if (*p == '['){
793  if (strlen (p) <= 8 || p [8] != ']')
794  goto error;
795  /* Should parse here the Notwell permissions :) */
796  /*@-unrecog@*/
797  if (S_ISDIR (st->st_mode))
798  st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH);
799  else
800  st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
801  p += 9;
802  /*@=unrecog@*/
803  } else {
804  if ((i = vfs_parse_filemode(p)) == -1)
805  goto error;
806  st->st_mode |= i;
807  p += 9;
808 
809  /* This is for an extra ACL attribute (HP-UX) */
810  if (*p == '+')
811  p++;
812  }
813 
814  g_free(p_copy);
815  p_copy = g_strdup(p);
816  num_cols = vfs_split_text (p);
817 
818  n = atol(columns[0]);
819  st->st_nlink = n;
820  if (n < 0)
821  goto error;
822 
823  if (!is_num (1))
824 #ifdef HACK
825  st->st_uid = finduid (columns [1]);
826 #else
827  (void) unameToUid (columns [1], &st->st_uid);
828 #endif
829  else
830  st->st_uid = (uid_t) atol (columns [1]);
831 
832  /* Mhm, the ls -lg did not produce a group field */
833  for (idx = 3; idx <= 5; idx++)
834  if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx]))
835  break;
836 
837  if (idx == 6 || (idx == 5 && !S_ISCHR (st->st_mode) && !S_ISBLK (st->st_mode)))
838  goto error;
839 
840  /* We don't have gid */
841  if (idx == 3 || (idx == 4 && (S_ISCHR(st->st_mode) || S_ISBLK (st->st_mode))))
842  idx2 = 2;
843  else {
844  /* We have gid field */
845  if (is_num (2))
846  st->st_gid = (gid_t) atol (columns [2]);
847  else
848 #ifdef HACK
849  st->st_gid = findgid (columns [2]);
850 #else
851  (void) gnameToGid (columns [1], &st->st_gid);
852 #endif
853  idx2 = 3;
854  }
855 
856  /* This is device */
857  if (S_ISCHR (st->st_mode) || S_ISBLK (st->st_mode)){
858  unsigned maj, min;
859 
860  if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1)
861  goto error;
862 
863  if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1)
864  goto error;
865 
866 #ifdef HAVE_ST_RDEV
867  st->st_rdev = ((maj & 0x000000ffU) << 8) | (min & 0x000000ffU);
868 #endif
869  st->st_size = 0;
870 
871  } else {
872  /* Common file size */
873  if (!is_num (idx2))
874  goto error;
875 
876  st->st_size = (size_t) atol (columns [idx2]);
877 #ifdef HAVE_ST_RDEV
878  st->st_rdev = 0;
879 #endif
880  }
881 
882  idx = vfs_parse_filedate(idx, &st->st_mtime);
883  if (!idx)
884  goto error;
885  /* Use resulting time value */
886  st->st_atime = st->st_ctime = st->st_mtime;
887  st->st_dev = 0;
888  st->st_ino = 0;
889 #ifdef HAVE_ST_BLKSIZE
890  st->st_blksize = 512;
891 #endif
892 #ifdef HAVE_ST_BLOCKS
893  st->st_blocks = (st->st_size + 511) / 512;
894 #endif
895 
896  for (i = idx + 1, idx2 = 0; i < num_cols; i++ )
897  if (strcmp (columns [i], "->") == 0){
898  idx2 = i;
899  break;
900  }
901 
902  if (((S_ISLNK (st->st_mode) ||
903  (num_cols == idx + 3 && st->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */
904  && idx2)
905  {
906  size_t tlen;
907  char *t;
908 
909  if (filename){
910  size_t nb = column_ptr [idx2] - column_ptr [idx] - 1;
911  t = strncpy((char *)xcalloc(1, nb+1), p_copy + column_ptr [idx], nb);
912  *filename = t;
913  }
914  if (linkname){
915  t = g_strdup (p_copy + column_ptr [idx2+1]);
916  tlen = strlen (t);
917  if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
918  t [tlen-1] = '\0';
919  if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
920  t [tlen-2] = '\0';
921 
922  *linkname = t;
923  }
924  } else {
925  /* Extract the filename from the string copy, not from the columns
926  * this way we have a chance of entering hidden directories like ". ."
927  */
928  if (filename){
929  /*
930  *filename = g_strdup (columns [idx++]);
931  */
932  size_t tlen;
933  char *t;
934 
935  t = g_strdup (p_copy + column_ptr [idx]); idx++;
936  tlen = strlen (t);
937  /* g_strchomp(); */
938  if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
939  t [tlen-1] = '\0';
940  if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
941  t [tlen-2] = '\0';
942 
943  *filename = t;
944  }
945  if (linkname)
946  *linkname = NULL;
947  }
948  g_free (p_copy);
949  return 1;
950 
951 error:
952 #ifdef HACK
953  {
954  static int errorcount = 0;
955 
956  if (++errorcount < 5) {
957  message_1s (1, "Could not parse:", p_copy);
958  } else if (errorcount == 5)
959  message_1s (1, "More parsing errors will be ignored.", "(sorry)" );
960  }
961 #endif
962 
963  /*@-usereleased@*/
964  if (p_copy != p) /* Carefull! */
965  /*@=usereleased@*/
966  g_free (p_copy);
967  return 0;
968 }
969 
970 typedef enum {
976 } ftpSysCall_t;
977 
980 static size_t ftpBufAlloced;
981 
984 /*@only@*/ /*@relnull@*/
985 static char * ftpBuf;
986 
987 #define alloca_strdup(_s) strcpy((char *)alloca(strlen(_s)+1), (_s))
988 
989 static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall,
990  /*@out@*/ /*@null@*/ struct stat * st,
991  /*@out@*/ /*@null@*/ char * rlbuf, size_t rlbufsiz)
992  /*@globals ftpBufAlloced, ftpBuf,
993  h_errno, fileSystem, internalState @*/
994  /*@modifies *st, *rlbuf, ftpBufAlloced, ftpBuf,
995  fileSystem, internalState @*/
996 {
997  FD_t fd;
998  const char * path;
999  int bufLength, moretodo;
1000  const char *n, *ne, *o, *oe;
1001  char * s;
1002  char * se;
1003  const char * urldn;
1004  char * bn = NULL;
1005  size_t nbn = 0;
1006  urlinfo u;
1007  int rc;
1008 
1009  n = ne = o = oe = NULL;
1010  (void) urlPath(url, &path);
1011  if (*path == '\0')
1012  return -2;
1013 
1014  switch (ftpSysCall) {
1015  case DO_FTP_GLOB:
1016  fd = ftpOpen(url, 0, 0, &u);
1017  if (fd == NULL || u == NULL)
1018  return -1;
1019 
1020  u->openError = ftpReq(fd, "LIST", path);
1021  break;
1022  default:
1023  urldn = alloca_strdup(url);
1024  if ((bn = (char *) strrchr(urldn, '/')) == NULL)
1025  return -2;
1026  else if (bn == path)
1027  bn = (char *) ".";
1028  else
1029  *bn++ = '\0';
1030  nbn = strlen(bn);
1031 
1032  rc = ftpChdir(urldn); /* XXX don't care about CWD */
1033  if (rc < 0)
1034  return rc;
1035 
1036  fd = ftpOpen(url, 0, 0, &u);
1037  if (fd == NULL || u == NULL)
1038  return -1;
1039 
1040  /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */
1041  u->openError = ftpReq(fd, "NLST", "-la");
1042 
1043  if (bn == NULL || nbn == 0) {
1044  rc = -2;
1045  goto exit;
1046  }
1047  break;
1048  }
1049 
1050  if (u->openError < 0) {
1051  fd = fdLink(fd, "error data (ftpStat)");
1052  rc = -2;
1053  goto exit;
1054  }
1055 
1056  if (ftpBufAlloced == 0 || ftpBuf == NULL) {
1058  ftpBuf = (char *) xcalloc(ftpBufAlloced, sizeof(ftpBuf[0]));
1059  }
1060  *ftpBuf = '\0';
1061 
1062  bufLength = 0;
1063  moretodo = 1;
1064 
1065  do {
1066 
1067  /* XXX FIXME: realloc ftpBuf if < ~128 chars remain */
1068  if ((ftpBufAlloced - bufLength) < (1024+80)) {
1069  ftpBufAlloced <<= 2;
1070  assert(ftpBufAlloced < (8*1024*1024));
1071  ftpBuf = (char *) xrealloc(ftpBuf, ftpBufAlloced);
1072  }
1073  s = se = ftpBuf + bufLength;
1074  *se = '\0';
1075 
1076  rc = fdFgets(fd, se, (ftpBufAlloced - bufLength));
1077  if (rc <= 0) {
1078  moretodo = 0;
1079  break;
1080  }
1081  if (ftpSysCall == DO_FTP_GLOB) { /* XXX HACK */
1082  bufLength += strlen(se);
1083  continue;
1084  }
1085 
1086  for (s = se; *s != '\0'; s = se) {
1087  int bingo;
1088 
1089  while (*se && *se != '\n') se++;
1090  if (se > s && se[-1] == '\r') se[-1] = '\0';
1091  if (*se == '\0')
1092  /*@innerbreak@*/ break;
1093  *se++ = '\0';
1094 
1095  if (!strncmp(s, "total ", sizeof("total ")-1))
1096  /*@innercontinue@*/ continue;
1097 
1098  o = NULL;
1099  for (bingo = 0, n = se; n >= s; n--) {
1100  switch (*n) {
1101  case '\0':
1102  oe = ne = n;
1103  /*@switchbreak@*/ break;
1104  case ' ':
1105  if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) {
1106  while (*(++n) == ' ')
1107  {};
1108  bingo++;
1109  /*@switchbreak@*/ break;
1110  }
1111  for (o = n + 1; *o == ' '; o++)
1112  {};
1113  n -= 3;
1114  ne = n;
1115  /*@switchbreak@*/ break;
1116  default:
1117  /*@switchbreak@*/ break;
1118  }
1119  if (bingo)
1120  /*@innerbreak@*/ break;
1121  }
1122 
1123  if (nbn != (size_t)(ne - n)) /* Same name length? */
1124  /*@innercontinue@*/ continue;
1125  if (strncmp(n, bn, nbn)) /* Same name? */
1126  /*@innercontinue@*/ continue;
1127 
1128  moretodo = 0;
1129  /*@innerbreak@*/ break;
1130  }
1131 
1132  if (moretodo && se > s) {
1133  bufLength = se - s - 1;
1134  if (s != ftpBuf)
1135  memmove(ftpBuf, s, bufLength);
1136  } else {
1137  bufLength = 0;
1138  }
1139  } while (moretodo);
1140 
1141  switch (ftpSysCall) {
1142  case DO_FTP_STAT:
1143  if (o && oe) {
1144  /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */
1145  }
1146  /*@fallthrough@*/
1147  case DO_FTP_LSTAT:
1148  if (st == NULL || !(n && ne)) {
1149  rc = -1;
1150  } else {
1151  rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1);
1152  }
1153  break;
1154  case DO_FTP_READLINK:
1155  if (rlbuf == NULL || !(o && oe)) {
1156  rc = -1;
1157  } else {
1158  rc = oe - o;
1159 assert(rc >= 0);
1160  if (rc > (int)rlbufsiz)
1161  rc = (int)rlbufsiz;
1162  memcpy(rlbuf, o, (size_t)rc);
1163  if (rc < (int)rlbufsiz)
1164  rlbuf[rc] = '\0';
1165  }
1166  break;
1167  case DO_FTP_ACCESS:
1168  rc = 0; /* XXX WRONG WRONG WRONG */
1169  break;
1170  case DO_FTP_GLOB:
1171  rc = 0; /* XXX WRONG WRONG WRONG */
1172  break;
1173  }
1174 
1175 exit:
1176  (void) ufdClose(fd);
1177  return rc;
1178 }
1179 
1180 static const char * statstr(const struct stat * st,
1181  /*@returned@*/ /*@out@*/ char * buf)
1182  /*@modifies *buf @*/
1183 {
1184  char * t = buf;
1185  sprintf(t, "*** dev %x", (unsigned int)st->st_dev);
1186  t += strlen(t);
1187  sprintf(t, " ino %x", (unsigned int)st->st_ino);
1188  t += strlen(t);
1189  sprintf(t, " mode %0o", (unsigned int)st->st_mode);
1190  t += strlen(t);
1191  sprintf(t, " nlink %d", (unsigned int)st->st_nlink);
1192  t += strlen(t);
1193  sprintf(t, " uid %d", (unsigned int)st->st_uid);
1194  t += strlen(t);
1195  sprintf(t, " gid %d", (unsigned int)st->st_gid);
1196  t += strlen(t);
1197  sprintf(t, " rdev %x", (unsigned int)st->st_rdev);
1198  t += strlen(t);
1199  sprintf(t, " size %x", (unsigned int)st->st_size);
1200  t += strlen(t);
1201  sprintf(t, "\n");
1202  return buf;
1203 }
1204 
1205 /* FIXME: borked for path with trailing '/' */
1206 static int ftpStat(const char * path, /*@out@*/ struct stat *st)
1207  /*@globals ftpBufAlloced, ftpBuf, h_errno, fileSystem, internalState @*/
1208  /*@modifies ftpBufAlloced, ftpBuf, *st, fileSystem, internalState @*/
1209 {
1210  char buf[1024];
1211  int rc;
1212  rc = ftpNLST(path, DO_FTP_STAT, st, NULL, 0);
1213 
1214  /* XXX fts(3) needs/uses st_ino. */
1215  /* Hash the path to generate a st_ino analogue. */
1216  if (st->st_ino == 0)
1217  st->st_ino = hashFunctionString(0, path, 0);
1218 
1219 if (_ftp_debug)
1220 fprintf(stderr, "<-- %s(%s) rc %d\n%s", __FUNCTION__, path, rc, statstr(st, buf));
1221  return rc;
1222 }
1223 
1224 /* FIXME: borked for path with trailing '/' */
1225 static int ftpLstat(const char * path, /*@out@*/ struct stat *st)
1226  /*@globals ftpBufAlloced, ftpBuf, h_errno, fileSystem, internalState @*/
1227  /*@modifies ftpBufAlloced, ftpBuf, *st, fileSystem, internalState @*/
1228 {
1229  char buf[1024];
1230  int rc;
1231  rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0);
1232 
1233  /* XXX fts(3) needs/uses st_ino. */
1234  /* Hash the path to generate a st_ino analogue. */
1235  if (st->st_ino == 0)
1236  st->st_ino = hashFunctionString(0, path, 0);
1237 
1238 if (_ftp_debug)
1239 fprintf(stderr, "<-- %s(%s) rc %d\n%s\n", __FUNCTION__, path, rc, statstr(st, buf));
1240  return rc;
1241 }
1242 
1243 static int ftpReadlink(const char * path, /*@out@*/ char * buf, size_t bufsiz)
1244  /*@globals ftpBufAlloced, ftpBuf, h_errno, fileSystem, internalState @*/
1245  /*@modifies ftpBufAlloced, ftpBuf, *buf, fileSystem, internalState @*/
1246 {
1247  int rc;
1248  rc = ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz);
1249 if (_ftp_debug)
1250 fprintf(stderr, "<-- %s(%s) rc %d\n", __FUNCTION__, path, rc);
1251  return rc;
1252 }
1253 
1254 DIR * ftpOpendir(const char * path)
1255  /*@globals ftpBufAlloced, ftpBuf @*/
1256  /*@modifies ftpBufAlloced, ftpBuf @*/
1257 {
1258  AVDIR avdir;
1259  rpmavx avx;
1260  struct stat * st = NULL;
1261  const char * s, * sb, * se;
1262  int nac;
1263  int c;
1264  int rc;
1265 
1266 if (_ftp_debug)
1267 fprintf(stderr, "*** ftpOpendir(%s)\n", path);
1268 
1269  /* Load FTP collection into argv. */
1270  avx = (rpmavx) rpmavxNew(path, st);
1271  if (avx == NULL) {
1272  errno = ENOENT; /* Note: avx is NULL iff urlSplit() fails. */
1273  return NULL;
1274  }
1275 
1276  rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0);
1277  if (rc)
1278  return NULL;
1279 
1280  nac = 0;
1281  sb = NULL;
1282  s = se = ftpBuf;
1283  while ((c = (int) *se++) != (int) '\0') {
1284  switch (c) {
1285  case '/':
1286  sb = se;
1287  /*@switchbreak@*/ break;
1288  case '\r':
1289  if (sb == NULL) {
1290  for (sb = se; sb > s && sb[-1] != ' '; sb--)
1291  {};
1292  }
1293  nac++;
1294 
1295  if (*se == '\n') se++;
1296  sb = NULL;
1297  s = se;
1298  /*@switchbreak@*/ break;
1299  default:
1300  /*@switchbreak@*/ break;
1301  }
1302  }
1303 
1304  avx->av = (const char **) xcalloc(nac+1, sizeof(*avx->av));
1305  avx->modes = (rpmuint16_t *) xcalloc(nac, sizeof(*avx->modes));
1306 
1307  nac = 0;
1308  sb = NULL;
1309  s = se = ftpBuf;
1310  while ((c = (int) *se) != (int) '\0') {
1311  se++;
1312  switch (c) {
1313  case '/':
1314  sb = se;
1315  /*@switchbreak@*/ break;
1316  case '\r':
1317  if (sb == NULL) {
1318  avx->modes[nac] = (*s == 'd' ? 0755 : 0644);
1319  /*@-unrecog@*/
1320  switch(*s) {
1321  case 'p': avx->modes[nac] |= S_IFIFO; /*@innerbreak@*/ break;
1322  case 'c': avx->modes[nac] |= S_IFCHR; /*@innerbreak@*/ break;
1323  case 'd': avx->modes[nac] |= S_IFDIR; /*@innerbreak@*/ break;
1324  case 'b': avx->modes[nac] |= S_IFBLK; /*@innerbreak@*/ break;
1325  case '-': avx->modes[nac] |= S_IFREG; /*@innerbreak@*/ break;
1326  case 'l': avx->modes[nac] |= S_IFLNK; /*@innerbreak@*/ break;
1327  case 's': avx->modes[nac] |= S_IFSOCK; /*@innerbreak@*/ break;
1328  default: avx->modes[nac] |= S_IFREG; /*@innerbreak@*/ break;
1329  }
1330  /*@=unrecog@*/
1331  for (sb = se; sb > s && sb[-1] != ' '; sb--)
1332  {};
1333  }
1334  avx->av[nac++] = strncpy((char *)xcalloc(1, (se-sb-1)+1), sb, (se-sb-1));
1335  if (*se == '\n') se++;
1336  sb = NULL;
1337  s = se;
1338  /*@switchbreak@*/ break;
1339  default:
1340  /*@switchbreak@*/ break;
1341  }
1342  }
1343 
1344  avdir = (AVDIR) avOpendir(path, avx->av, avx->modes);
1345 
1346  avx = rpmavxFree(avx);
1347 
1348 /*@-kepttrans@*/
1349  return (DIR *) avdir;
1350 /*@=kepttrans@*/
1351 }
1352 
1353 static char * ftpRealpath(const char * path, /*@null@*/ char * resolved_path)
1354  /*@*/
1355 {
1356 assert(resolved_path == NULL); /* XXX no POSIXly broken realpath(3) here. */
1357  /* XXX TODO: handle redirects. For now, just dupe the path. */
1358  return xstrdup(path);
1359 }
1360 
1361 int Stat(const char * path, struct stat * st)
1362  /*@globals ftpBufAlloced, ftpBuf @*/
1363  /*@modifies ftpBufAlloced, ftpBuf @*/
1364 {
1365  const char * lpath;
1366  int ut = urlPath(path, &lpath);
1367  int rc = -2;
1368 
1369  switch (ut) {
1370  case URL_IS_FTP:
1371  rc = ftpStat(path, st);
1372  goto exit;
1373  /*@notreached@*/ break;
1374  case URL_IS_HTTPS:
1375  case URL_IS_HTTP:
1376 #ifdef WITH_NEON
1377  rc = davStat(path, st);
1378 #endif
1379  goto exit;
1380  /*@notreached@*/ break;
1381  case URL_IS_PATH:
1382  path = lpath;
1383  /*@fallthrough@*/
1384  case URL_IS_UNKNOWN:
1385  break;
1386  case URL_IS_DASH:
1387  case URL_IS_HKP:
1388  case URL_IS_MONGO: /* XXX FIXME */
1389  default:
1390  errno = ENOENT;
1391  goto exit;
1392  /*@notreached@*/ break;
1393  }
1394  rc = stat(path, st);
1395 exit:
1396 if (_rpmio_debug)
1397 fprintf(stderr, "<-- %s(%s,%p) rc %d\n", __FUNCTION__, path, st, rc);
1398  return rc;
1399 }
1400 
1401 int Lstat(const char * path, struct stat * st)
1402  /*@globals ftpBufAlloced, ftpBuf @*/
1403  /*@modifies ftpBufAlloced, ftpBuf @*/
1404 {
1405  const char * lpath;
1406  int ut = urlPath(path, &lpath);
1407  int rc = -2;
1408 
1409  switch (ut) {
1410  case URL_IS_FTP:
1411  rc = ftpLstat(path, st);
1412  goto exit;
1413  /*@notreached@*/ break;
1414  case URL_IS_HTTPS:
1415  case URL_IS_HTTP:
1416 #ifdef WITH_NEON
1417  rc = davLstat(path, st);
1418 #endif
1419  goto exit;
1420  /*@notreached@*/ break;
1421  case URL_IS_PATH:
1422  path = lpath;
1423  /*@fallthrough@*/
1424  case URL_IS_UNKNOWN:
1425  break;
1426  case URL_IS_DASH:
1427  case URL_IS_HKP:
1428  case URL_IS_MONGO: /* XXX FIXME */
1429  default:
1430  errno = ENOENT;
1431  goto exit;
1432  /*@notreached@*/ break;
1433  }
1434  rc = lstat(path, st);
1435 exit:
1436 if (_rpmio_debug)
1437 fprintf(stderr, "<-- %s(%s,%p) rc %d\n", __FUNCTION__, path, st, rc);
1438  return rc;
1439 }
1440 
1441 int Fstat(FD_t fd, struct stat * st)
1442 {
1443  const char * path = fdGetOPath(fd);
1444  const char * lpath;
1445  int ut = urlPath(path, &lpath);
1446  int rc = -2;
1447 
1448  if (fd == NULL || path == NULL || *path == '\0' || st == NULL) {
1449  errno = ENOENT;
1450  goto exit;
1451  }
1452 
1453  switch (ut) {
1454  case URL_IS_DASH:
1455  case URL_IS_PATH:
1456  case URL_IS_UNKNOWN:
1457  break;
1458  case URL_IS_FTP:
1459  case URL_IS_HTTPS:
1460  case URL_IS_HTTP:
1461  case URL_IS_HKP:
1462  if (fd->contentLength < 0) {
1463  errno = ENOENT;
1464  goto exit;
1465  }
1466  memset(st, 0, sizeof(*st));
1467  if (path[strlen(path)-1] == '/') {
1468  st->st_nlink = 2;
1469  st->st_mode = (S_IFDIR | 0755);
1470  } else {
1471  st->st_nlink = 1;
1472  st->st_mode = (S_IFREG | 0644);
1473  }
1474  st->st_ino = hashFunctionString(0, path, 0);;
1475  st->st_size = fd->contentLength;
1476  st->st_mtime = fd->lastModified;
1477 
1478  st->st_atime = st->st_ctime = st->st_mtime;
1479  st->st_blksize = 4 * 1024; /* HACK correct for linux ext */
1480  st->st_blocks = (st->st_size + 511)/512;
1481  break;
1482  case URL_IS_MONGO: /* XXX FIXME */
1483  default:
1484  errno = ENOENT;
1485  goto exit;
1486  /*@notreached@*/ break;
1487  }
1488  rc = fstat(Fileno(fd), st);
1489 exit:
1490 if (_rpmio_debug)
1491 fprintf(stderr, "<-- %s(%p,%p) path %s rc %d\n", __FUNCTION__, fd, st, path, rc);
1492  return rc;
1493 }
1494 
1495 int Fadvise(FD_t fd, off_t offset, off_t len, int advice)
1496 {
1497  const char * path = fdGetOPath(fd);
1498  const char * lpath;
1499  int ut = urlPath(path, &lpath);
1500  int fdno = Fileno(fd);
1501  int rc;
1502 
1503 if (_rpmio_debug)
1504 fprintf(stderr, "*** %s(%p,0x%x,0x%x,0x%x) fdno %d path %s\n", __FUNCTION__, fd, (unsigned)offset, (unsigned)len, advice, fdno, path);
1505 
1506  /* XXX errno is not set by fallocate/posix_fallocate */
1507  if (fd == NULL || fdno < 0) {
1508  rc = EBADF;
1509  return rc;
1510  }
1511 
1512  switch (ut) {
1513  case URL_IS_PATH:
1514  case URL_IS_UNKNOWN:
1515  break;
1516  default:
1517  rc = ENODEV;
1518  return rc;
1519  /*@notreached@*/ break;
1520  }
1521 
1522  switch (advice) {
1523 #if defined(HAVE_POSIX_FADVISE)
1524  case POSIX_FADV_NORMAL:
1525  case POSIX_FADV_SEQUENTIAL:
1526  case POSIX_FADV_RANDOM:
1527  case POSIX_FADV_NOREUSE:
1528  case POSIX_FADV_WILLNEED:
1529  case POSIX_FADV_DONTNEED:
1530  rc = posix_fadvise(fdno, offset, len, advice);
1531 #else
1532  rc = ENOSYS;
1533 #endif
1534  break;
1535  default:
1536  rc = EINVAL;
1537  break;
1538  }
1539 
1540  if (rc != 0)
1541  rpmlog(RPMLOG_DEBUG, _("%s(%d,0x%x,0x%x) failed: rc %d\n"),
1542  __FUNCTION__, fdno, (unsigned)offset, (unsigned)len, rc);
1543 
1544  return rc;
1545 }
1546 
1547 #undef HAVE_FALLOCATE /* XXX hmmm, fallocate64 is AWOL in F11. */
1548 int Fallocate(FD_t fd, off_t offset, off_t len)
1549 {
1550  const char * path = fdGetOPath(fd);
1551  const char * lpath;
1552  int ut = urlPath(path, &lpath);
1553  int fdno = Fileno(fd);
1554  int rc;
1555 
1556 if (_rpmio_debug)
1557 fprintf(stderr, "*** %s(%p,0x%x,0x%x) fdno %d path %s\n", __FUNCTION__, fd, (unsigned)offset, (unsigned)len, fdno, path);
1558 
1559  /* XXX errno is not set by fallocate/posix_fallocate */
1560  if (fd == NULL || fdno < 0) {
1561  rc = EBADF;
1562  return rc;
1563  }
1564 
1565  switch (ut) {
1566  case URL_IS_PATH:
1567  case URL_IS_UNKNOWN:
1568  break;
1569  default:
1570  rc = ENODEV;
1571  return rc;
1572  /*@notreached@*/ break;
1573  }
1574 
1575 #if defined(HAVE_FALLOCATE)
1576  /* XXX linux FALLOC_FL_KEEP_SIZE zeroes allocated blocks */
1577  rc = (int) fallocate(fdno, 0, (loff_t)offset, (loff_t)len);
1578 #elif defined(HAVE_POSIX_FALLOCATE)
1579  rc = posix_fallocate(fdno, offset, len);
1580 #else
1581  rc = ENOSYS;
1582 #endif
1583 
1584  if (rc != 0)
1585  rpmlog(RPMLOG_DEBUG, _("%s(%d,0x%x,0x%x) failed: rc %d\n"),
1586  __FUNCTION__, fdno, (unsigned)offset, (unsigned)len, rc);
1587 
1588  return rc;
1589 }
1590 
1591 #ifdef NOTYET /* XXX figger mmap or posix_memalign first */
1592 void *Mmap(void *addr, size_t length, int prot, int flags,
1593  FD_t fd, off_t offset)
1594 {
1595  int fdno = (fd ? Fileno(fd) : -1);
1596  void * ret = mmap(addr, length, prot, flags, fdno, offset);
1597  if (ret == NULL || ret == (void *)-1)
1598  rpmlog(RPMLOG_ERR, _("%s(%p[%u],0x%x,0x%x,%p,0x%x) failed: %m\n"),
1599  __FUNCTION__, addr, (unsigned)len, prot, flags, fd,
1600  (unsigned)offset);
1601 if (_rpmio_debug)
1602 fprintf(stderr, "<-- %s(%p[%u],0x%x,0x%x,%p,0x%x) ret %p\n", __FUNCTION__, addr, (unsigned)len, prot, flags, fd, (unsigned)offset, ret);
1603  return ret;
1604 }
1605 
1606 int Munmap(const void * addr, size_t len)
1607 {
1608  int rc = munmap(addr, len);
1609  if (rc < 0)
1610  rpmlog(RPMLOG_ERR, _("%s(%p[%u]) failed: %m\n"),
1611  __FUNCTION__, addr, (unsigned)len);
1612 if (_rpmio_debug)
1613 fprintf(stderr, "<-- %s(%p[%u]) rc %d\n", __FUNCTION__, addr, (unsigned)len, rc);
1614  return rc;
1615 }
1616 
1617 int Mprotect(const void * addr, size_t len, int prot)
1618 {
1619  int rc = mprotect(addr, len, prot);
1620  if (rc < 0)
1621  rpmlog(RPMLOG_ERR, _("%s(%p[%u],%d) failed: %m\n"),
1622  __FUNCTION__, addr, (unsigned)len, prot);
1623 if (_rpmio_debug)
1624 fprintf(stderr, "<-- %s(%p[%u],%d) rc %d\n", __FUNCTION__, addr, len, prot, rc);
1625  return rc;
1626 }
1627 #endif
1628 
1629 #ifdef NOTYET /* XXX figger posix_fadvise or posix_madvise first */
1630 int Madvise(void *addr, size_t len, int advice)
1631 {
1632  int rc = madvise(addr, len, advice);
1633  if (rc < 0)
1634  rpmlog(RPMLOG_ERR, _("%s(%p[%u],%d) failed: %m\n"),
1635  __FUNCTION__, addr, (unsigned)len, advice);
1636 if (_rpmio_debug)
1637 fprintf(stderr, "<-- %s(%p[%u],%d) rc %d\n", __FUNCTION__, addr, len, advice, rc);
1638  return rc;
1639 }
1640 
1641 int Fadvise(FD_t fd, off_t offset, off_t len, int advice)
1642 {
1643  const char * path = fdGetOPath(fd);
1644  const char * lpath;
1645  int ut = urlPath(path, &lpath);
1646  int fdno = Fileno(fd);
1647  int rc = -2;
1648 
1649  if (fd == NULL || fdno < 0) {
1650  errno = EBADF;
1651  goto exit;
1652  }
1653 
1654  switch (ut) {
1655  case URL_IS_PATH:
1656  case URL_IS_UNKNOWN:
1657  break;
1658  default:
1659  errno = EINVAL;
1660  goto exit;
1661  /*@notreached@*/ break;
1662  }
1663  rc = posix_fadvise(fdno, offset, len, advice);
1664  if (rc != 0)
1665  rpmlog(RPMLOG_ERR, _("%s(%d,%d,0x%x,0x%x) failed: %m\n"),
1666  __FUNCTION__, fdno, (unsigned)offset, (unsigned)len, advice);
1667 exit:
1668 if (_rpmio_debug)
1669 fprintf(stderr, "<-- %s(%p,0x%x,0x%x,%d) fdno %d path %s rc %d\n", __FUNCTION__, fd, (unsigned)offset, (unsigned)len, advice, fdno, path, rc);
1670  return rc;
1671 }
1672 #endif
1673 
1674 int Chown(const char * path, uid_t owner, gid_t group)
1675 {
1676  const char * lpath;
1677  int ut = urlPath(path, &lpath);
1678  int rc = -2;
1679 
1680  switch (ut) {
1681  case URL_IS_PATH:
1682  path = lpath;
1683  /*@fallthrough@*/
1684  case URL_IS_UNKNOWN:
1685  break;
1686  case URL_IS_DASH:
1687  case URL_IS_HKP:
1688  case URL_IS_FTP: /* XXX TODO: implement. */
1689  case URL_IS_HTTP: /* XXX TODO: implement. */
1690  case URL_IS_HTTPS: /* XXX TODO: implement. */
1691  case URL_IS_MONGO: /* XXX FIXME */
1692  default:
1693  errno = EINVAL; /* XXX W2DO? */
1694  goto exit;
1695  /*@notreached@*/ break;
1696  }
1697  rc = chown(path, owner, group);
1698 exit:
1699 if (_rpmio_debug)
1700 fprintf(stderr, "<-- %s(%s,%u,%u) rc %d\n", __FUNCTION__, path, (unsigned)owner, (unsigned)group, rc);
1701  return rc;
1702 }
1703 
1704 int Fchown(FD_t fd, uid_t owner, gid_t group)
1705 {
1706  const char * path = fdGetOPath(fd);
1707  const char * lpath;
1708  int ut = urlPath(path, &lpath);
1709  int rc = -2;
1710 
1711  switch (ut) {
1712  case URL_IS_PATH:
1713  path = lpath;
1714  /*@fallthrough@*/
1715  case URL_IS_UNKNOWN:
1716  break;
1717  case URL_IS_DASH:
1718  case URL_IS_HKP:
1719  case URL_IS_FTP: /* XXX TODO: implement. */
1720  case URL_IS_HTTP: /* XXX TODO: implement. */
1721  case URL_IS_HTTPS: /* XXX TODO: implement. */
1722  case URL_IS_MONGO: /* XXX FIXME */
1723  default:
1724  errno = EINVAL; /* XXX W2DO? */
1725  goto exit;
1726  /*@notreached@*/ break;
1727  }
1728  rc = fchown(Fileno(fd), owner, group);
1729 exit:
1730 if (_rpmio_debug)
1731 fprintf(stderr, "<-- %s(%p,%u,%u) path %s rc %d\n", __FUNCTION__, fd, (unsigned)owner, (unsigned)group, path, rc);
1732  return rc;
1733 }
1734 
1735 int Lchown(const char * path, uid_t owner, gid_t group)
1736 {
1737  const char * lpath;
1738  int ut = urlPath(path, &lpath);
1739  int rc = -2;
1740 
1741  switch (ut) {
1742  case URL_IS_PATH:
1743  path = lpath;
1744  /*@fallthrough@*/
1745  case URL_IS_UNKNOWN:
1746  break;
1747  case URL_IS_DASH:
1748  case URL_IS_HKP:
1749  case URL_IS_FTP: /* XXX TODO: implement. */
1750  case URL_IS_HTTP: /* XXX TODO: implement. */
1751  case URL_IS_HTTPS: /* XXX TODO: implement. */
1752  case URL_IS_MONGO: /* XXX FIXME */
1753  default:
1754  errno = EINVAL; /* XXX W2DO? */
1755  goto exit;
1756  /*@notreached@*/ break;
1757  }
1758  rc = lchown(path, owner, group);
1759 exit:
1760 if (_rpmio_debug)
1761 fprintf(stderr, "*** %s(%s,%u,%u)\n", __FUNCTION__, path, (unsigned)owner, (unsigned)group);
1762  return rc;
1763 }
1764 
1765 int Chmod(const char * path, mode_t mode)
1766 {
1767  const char * lpath;
1768  int ut = urlPath(path, &lpath);
1769  int rc = -2;
1770 
1771  switch (ut) {
1772  case URL_IS_PATH:
1773  path = lpath;
1774  /*@fallthrough@*/
1775  case URL_IS_UNKNOWN:
1776  break;
1777  case URL_IS_DASH:
1778  case URL_IS_HKP:
1779  case URL_IS_FTP: /* XXX TODO: implement. */
1780  case URL_IS_HTTP: /* XXX TODO: implement. */
1781  case URL_IS_HTTPS: /* XXX TODO: implement. */
1782  case URL_IS_MONGO: /* XXX FIXME */
1783  default:
1784  errno = EINVAL; /* XXX W2DO? */
1785  goto exit;
1786  /*@notreached@*/ break;
1787  }
1788  rc = chmod(path, mode);
1789 exit:
1790 if (_rpmio_debug)
1791 fprintf(stderr, "<-- %s(%s,%0o) rc %d\n", __FUNCTION__, path, (int)mode, rc);
1792  return rc;
1793 }
1794 
1795 int Lchmod(const char * path, mode_t mode)
1796 {
1797 #if defined(HAVE_LCHMOD)
1798  const char * lpath;
1799  int ut = urlPath(path, &lpath);
1800  int rc = -2;
1801 
1802  switch (ut) {
1803  case URL_IS_PATH:
1804  path = lpath;
1805  /*@fallthrough@*/
1806  case URL_IS_UNKNOWN:
1807  break;
1808  case URL_IS_DASH:
1809  case URL_IS_HKP:
1810  case URL_IS_FTP: /* XXX TODO: implement. */
1811  case URL_IS_HTTP: /* XXX TODO: implement. */
1812  case URL_IS_HTTPS: /* XXX TODO: implement. */
1813  case URL_IS_MONGO: /* XXX FIXME */
1814  default:
1815  errno = EINVAL; /* XXX W2DO? */
1816  goto exit;
1817  /*@notreached@*/ break;
1818  }
1819  rc = lchmod(path, mode);
1820 exit:
1821 if (_rpmio_debug)
1822 fprintf(stderr, "<-- %s(%s,%0o) rc %d\n", __FUNCTION__, path, (int)mode, rc);
1823  return rc;
1824 #else
1825  errno = ENOSYS;
1826  return -2;
1827 #endif
1828 }
1829 
1830 int Fchmod(FD_t fd, mode_t mode)
1831 {
1832  const char * path = fdGetOPath(fd);
1833  const char * lpath;
1834  int ut = urlPath(path, &lpath);
1835  int rc = -2;
1836 
1837  switch (ut) {
1838  case URL_IS_PATH:
1839  path = lpath;
1840  /*@fallthrough@*/
1841  case URL_IS_UNKNOWN:
1842  break;
1843  case URL_IS_DASH:
1844  case URL_IS_HKP:
1845  case URL_IS_FTP: /* XXX TODO: implement. */
1846  case URL_IS_HTTP: /* XXX TODO: implement. */
1847  case URL_IS_HTTPS: /* XXX TODO: implement. */
1848  case URL_IS_MONGO: /* XXX FIXME */
1849  default:
1850  errno = EINVAL; /* XXX W2DO? */
1851  goto exit;
1852  /*@notreached@*/ break;
1853  }
1854  rc = fchmod(Fileno(fd), mode);
1855 exit:
1856 if (_rpmio_debug)
1857 fprintf(stderr, "*** %s(%p,%0o) path %s rc %d\n", __FUNCTION__, fd, (int)mode, path, rc);
1858  return rc;
1859 }
1860 
1861 int Chflags(const char * path, unsigned int flags)
1862 {
1863 #if defined(HAVE_CHFLAGS)
1864  const char * lpath;
1865  int ut = urlPath(path, &lpath);
1866 
1867 if (_rpmio_debug)
1868 fprintf(stderr, "*** Chflags(%s,0x%x)\n", path, flags);
1869  switch (ut) {
1870  case URL_IS_PATH:
1871  path = lpath;
1872  /*@fallthrough@*/
1873  case URL_IS_UNKNOWN:
1874  break;
1875  case URL_IS_DASH:
1876  case URL_IS_HKP:
1877  case URL_IS_FTP: /* XXX TODO: implement. */
1878  case URL_IS_HTTP: /* XXX TODO: implement. */
1879  case URL_IS_HTTPS: /* XXX TODO: implement. */
1880  case URL_IS_MONGO: /* XXX FIXME */
1881  default:
1882  errno = EINVAL; /* XXX W2DO? */
1883  return -2;
1884  /*@notreached@*/ break;
1885  }
1886  return chflags(path, flags);
1887 #else
1888  errno = ENOSYS;
1889  return -2;
1890 #endif
1891 }
1892 
1893 int Lchflags(const char * path, unsigned int flags)
1894 {
1895  const char * lpath;
1896  int ut = urlPath(path, &lpath);
1897  int rc = -2;
1898 
1899 #if defined(HAVE_LCHFLAGS)
1900 if (_rpmio_debug)
1901 fprintf(stderr, "*** Lchflags(%s,0x%x)\n", path, flags);
1902  switch (ut) {
1903  case URL_IS_PATH:
1904  path = lpath;
1905  /*@fallthrough@*/
1906  case URL_IS_UNKNOWN:
1907  break;
1908  case URL_IS_DASH:
1909  case URL_IS_HKP:
1910  case URL_IS_FTP: /* XXX TODO: implement. */
1911  case URL_IS_HTTP: /* XXX TODO: implement. */
1912  case URL_IS_HTTPS: /* XXX TODO: implement. */
1913  case URL_IS_MONGO: /* XXX FIXME */
1914  default:
1915  errno = EINVAL; /* XXX W2DO? */
1916  return -2;
1917  /*@notreached@*/ break;
1918  }
1919  return lchflags(path, flags);
1920 #else
1921  ut = ut; /* keep gcc happy */
1922  errno = ENOSYS;
1923 #endif
1924  return rc;
1925 }
1926 
1927 int Fchflags(FD_t fd, unsigned int flags)
1928 {
1929 #if defined(HAVE_FCHFLAGS)
1930  const char * path = fdGetOPath(fd);
1931  const char * lpath;
1932  int ut = urlPath(path, &lpath);
1933 
1934 if (_rpmio_debug)
1935 fprintf(stderr, "*** Fchflags(%p,0x%x) path %s\n", fd, flags, path);
1936  switch (ut) {
1937  case URL_IS_PATH:
1938  path = lpath;
1939  /*@fallthrough@*/
1940  case URL_IS_UNKNOWN:
1941  break;
1942  case URL_IS_DASH:
1943  case URL_IS_HKP:
1944  case URL_IS_FTP: /* XXX TODO: implement. */
1945  case URL_IS_HTTP: /* XXX TODO: implement. */
1946  case URL_IS_HTTPS: /* XXX TODO: implement. */
1947  case URL_IS_MONGO: /* XXX FIXME */
1948  default:
1949  errno = EINVAL; /* XXX W2DO? */
1950  return -2;
1951  /*@notreached@*/ break;
1952  }
1953  return fchflags(Fileno(fd), flags);
1954 #else
1955  errno = ENOSYS;
1956  return -2;
1957 #endif
1958 }
1959 int Mkfifo(const char * path, mode_t mode)
1960 {
1961  const char * lpath;
1962  int ut = urlPath(path, &lpath);
1963  int rc = -2;
1964 
1965  switch (ut) {
1966  case URL_IS_PATH:
1967  path = lpath;
1968  /*@fallthrough@*/
1969  case URL_IS_UNKNOWN:
1970  break;
1971  case URL_IS_DASH:
1972  case URL_IS_HKP:
1973  case URL_IS_FTP: /* XXX TODO: implement. */
1974  case URL_IS_HTTP: /* XXX TODO: implement. */
1975  case URL_IS_HTTPS: /* XXX TODO: implement. */
1976  case URL_IS_MONGO: /* XXX FIXME */
1977  default:
1978  errno = EINVAL; /* XXX W2DO? */
1979  goto exit;
1980  /*@notreached@*/ break;
1981  }
1982  rc = mkfifo(path, mode);
1983 exit:
1984 if (_rpmio_debug)
1985 fprintf(stderr, "<-- %s(%s,%0o) rc %d\n", __FUNCTION__, path, (int)mode, rc);
1986  return rc;
1987 }
1988 
1989 int Mknod(const char * path, mode_t mode, dev_t dev)
1990 {
1991  const char * lpath;
1992  int ut = urlPath(path, &lpath);
1993  int rc = -2;
1994 
1995  switch (ut) {
1996  case URL_IS_PATH:
1997  path = lpath;
1998  /*@fallthrough@*/
1999  case URL_IS_UNKNOWN:
2000  break;
2001  case URL_IS_DASH:
2002  case URL_IS_HKP:
2003  case URL_IS_FTP: /* XXX TODO: implement. */
2004  case URL_IS_HTTP: /* XXX TODO: implement. */
2005  case URL_IS_HTTPS: /* XXX TODO: implement. */
2006  case URL_IS_MONGO: /* XXX FIXME */
2007  default:
2008  errno = EINVAL; /* XXX W2DO? */
2009  goto exit;
2010  /*@notreached@*/ break;
2011  }
2012 /*@-portability@*/
2013  rc = mknod(path, mode, dev);
2014 /*@=portability@*/
2015 exit:
2016 if (_rpmio_debug)
2017 fprintf(stderr, "<-- %s(%s,%0o, 0x%x) rc %d\n", __FUNCTION__, path, (int)mode, (int)dev, rc);
2018  return rc;
2019 }
2020 
2021 int Utime(const char * path, const struct utimbuf *buf)
2022 {
2023  const char * lpath;
2024  int ut = urlPath(path, &lpath);
2025  int rc = -2;
2026 
2027  switch (ut) {
2028  case URL_IS_PATH:
2029  path = lpath;
2030  /*@fallthrough@*/
2031  case URL_IS_UNKNOWN:
2032  break;
2033  case URL_IS_DASH:
2034  case URL_IS_HKP:
2035  case URL_IS_FTP: /* XXX TODO: implement. */
2036  case URL_IS_HTTP: /* XXX TODO: implement. */
2037  case URL_IS_HTTPS: /* XXX TODO: implement. */
2038  case URL_IS_MONGO: /* XXX FIXME */
2039  default:
2040  errno = EINVAL; /* XXX W2DO? */
2041  goto exit;
2042  /*@notreached@*/ break;
2043  }
2044  rc = utime(path, buf);
2045 exit:
2046 if (_rpmio_debug)
2047 fprintf(stderr, "<-- %s(%s,%p) rc %d\n", __FUNCTION__, path, buf, rc);
2048  return rc;
2049 }
2050 
2051 /*@-fixedformalarray@*/
2052 int Utimes(const char * path, const struct timeval times[2])
2053 {
2054  const char * lpath;
2055  int ut = urlPath(path, &lpath);
2056  int rc = -2;
2057 
2058  switch (ut) {
2059  case URL_IS_PATH:
2060  path = lpath;
2061  /*@fallthrough@*/
2062  case URL_IS_UNKNOWN:
2063  break;
2064  case URL_IS_DASH:
2065  case URL_IS_HKP:
2066  case URL_IS_FTP: /* XXX TODO: implement. */
2067  case URL_IS_HTTP: /* XXX TODO: implement. */
2068  case URL_IS_HTTPS: /* XXX TODO: implement. */
2069  case URL_IS_MONGO: /* XXX FIXME */
2070  default:
2071  errno = EINVAL; /* XXX W2DO? */
2072  goto exit;
2073  /*@notreached@*/ break;
2074  }
2075  rc = utimes(path, times);
2076 exit:
2077 if (_rpmio_debug)
2078 fprintf(stderr, "<-- %s(%s,%p) rc %d\n", __FUNCTION__, path, times, rc);
2079  return rc;
2080 }
2081 /*@=fixedformalarray@*/
2082 
2083 /*@-fixedformalarray@*/
2084 int Lutimes(const char * path, const struct timeval times[2])
2085 {
2086 #ifdef HAVE_LUTIMES
2087  const char * lpath;
2088  int ut = urlPath(path, &lpath);
2089  int rc = -2;
2090 
2091  switch (ut) {
2092  case URL_IS_PATH:
2093  path = lpath;
2094  /*@fallthrough@*/
2095  case URL_IS_UNKNOWN:
2096  break;
2097  case URL_IS_DASH:
2098  case URL_IS_HKP:
2099  case URL_IS_FTP: /* XXX TODO: implement. */
2100  case URL_IS_HTTP: /* XXX TODO: implement. */
2101  case URL_IS_HTTPS: /* XXX TODO: implement. */
2102  case URL_IS_MONGO: /* XXX FIXME */
2103  default:
2104  errno = EINVAL; /* XXX W2DO? */
2105  goto exit;
2106  /*@notreached@*/ break;
2107  }
2108  rc = lutimes(path, times);
2109 exit:
2110 if (_rpmio_debug)
2111 fprintf(stderr, "<-- %s(%s,%p) rc %d\n", __FUNCTION__, path, times, rc);
2112  return rc;
2113 #else
2114  errno = ENOSYS;
2115  return -2;
2116 #endif
2117 }
2118 /*@=fixedformalarray@*/
2119 
2120 int Symlink(const char * oldpath, const char * newpath)
2121 {
2122  const char * opath;
2123  int out = urlPath(oldpath, &opath);
2124  const char * npath;
2125  int nut = urlPath(newpath, &npath);
2126  int rc = -2;
2127 
2128  nut = nut; /* XXX keep gcc quiet. */
2129  switch (out) {
2130  case URL_IS_PATH:
2131  oldpath = opath;
2132  newpath = npath;
2133  /*@fallthrough@*/
2134  case URL_IS_UNKNOWN:
2135  break;
2136  case URL_IS_DASH:
2137  case URL_IS_HKP:
2138  case URL_IS_FTP: /* XXX TODO: implement. */
2139  case URL_IS_HTTP: /* XXX TODO: implement. */
2140  case URL_IS_HTTPS: /* XXX TODO: implement. */
2141  case URL_IS_MONGO: /* XXX FIXME */
2142  default:
2143  errno = EINVAL; /* XXX W2DO? */
2144  goto exit;
2145  /*@notreached@*/ break;
2146  }
2147  rc = symlink(oldpath, newpath);
2148 exit:
2149 if (_rpmio_debug)
2150 fprintf(stderr, "<-- %s(%s,%s) rc %d\n", __FUNCTION__, oldpath, newpath, rc);
2151  return rc;
2152 }
2153 
2154 int Readlink(const char * path, char * buf, size_t bufsiz)
2155  /*@globals ftpBufAlloced, ftpBuf @*/
2156  /*@modifies ftpBufAlloced, ftpBuf @*/
2157 {
2158  const char * lpath;
2159  int ut = urlPath(path, &lpath);
2160  int rc = -2;
2161 
2162  switch (ut) {
2163  case URL_IS_FTP:
2164  rc = ftpReadlink(path, buf, bufsiz);
2165  goto exit;
2166  /*@notreached@*/ break;
2167  case URL_IS_HTTPS:
2168  case URL_IS_HTTP:
2169 #ifdef NOTYET
2170  rc = davReadlink(path, buf, bufsiz);
2171 #endif
2172  goto exit;
2173  /*@notreached@*/ break;
2174  case URL_IS_PATH:
2175  path = lpath;
2176  /*@fallthrough@*/
2177  case URL_IS_UNKNOWN:
2178  break;
2179  case URL_IS_DASH:
2180  case URL_IS_HKP:
2181  case URL_IS_MONGO: /* XXX FIXME */
2182  default:
2183  errno = EINVAL; /* XXX W2DO? */
2184  goto exit;
2185  /*@notreached@*/ break;
2186  }
2187 /*@-compdef@*/ /* FIX: *buf is undefined */
2188  rc = readlink(path, buf, bufsiz);
2189 /*@=compdef@*/
2190 exit:
2191 if (_rpmio_debug)
2192 fprintf(stderr, "<-- %s(%s,%p[%u]) rc %d\n", __FUNCTION__, path, buf, (unsigned)bufsiz, rc);
2193  return rc;
2194 }
2195 
2196 int Access(const char * path, int amode)
2197 {
2198  const char * lpath;
2199  int ut = urlPath(path, &lpath);
2200  int rc = -2;
2201 
2202  switch (ut) {
2203  case URL_IS_PATH:
2204  path = lpath;
2205  /*@fallthrough@*/
2206  case URL_IS_UNKNOWN:
2207  break;
2208  case URL_IS_DASH:
2209  case URL_IS_HKP:
2210  case URL_IS_FTP: /* XXX TODO: implement. */
2211  case URL_IS_HTTP: /* XXX TODO: implement. */
2212  case URL_IS_HTTPS: /* XXX TODO: implement. */
2213  case URL_IS_MONGO: /* XXX FIXME */
2214  default:
2215  errno = EINVAL; /* XXX W2DO? */
2216  goto exit;
2217  /*@notreached@*/ break;
2218  }
2219  rc = access(path, amode);
2220 exit:
2221 if (_rpmio_debug)
2222 fprintf(stderr, "<-- %s(%s,%d) rc %d\n", __FUNCTION__, path, amode, rc);
2223  return rc;
2224 }
2225 
2226 /* glob_pattern_p() taken from bash
2227  * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
2228  *
2229  * Return nonzero if PATTERN has any special globbing chars in it.
2230  */
2231 int Glob_pattern_p (const char * pattern, int quote)
2232 {
2233  const char *p;
2234  int ut = urlPath(pattern, &p);
2235  int open = 0;
2236  char c;
2237 
2238  while ((c = *p++) != '\0')
2239  switch (c) {
2240  case '?':
2241  /* Don't treat '?' as a glob char in HTTP URL's */
2242  if (ut == URL_IS_HTTPS || ut == URL_IS_HTTP || ut == URL_IS_HKP)
2243  continue;
2244  /*@fallthrough@*/
2245  case '*':
2246  return (1);
2247  case '\\':
2248  if (quote && *p != '\0')
2249  p++;
2250  continue;
2251 
2252  case '[':
2253  open = 1;
2254  continue;
2255  case ']':
2256  if (open)
2257  return (1);
2258  continue;
2259 
2260  case '+':
2261  case '@':
2262  case '!':
2263  if (*p == '(')
2264  return (1);
2265  continue;
2266  }
2267 
2268  return (0);
2269 }
2270 
2271 int Glob_error(/*@unused@*/ const char * epath,
2272  /*@unused@*/ int eerrno)
2273 {
2274  return 1;
2275 }
2276 
2277 int Glob(const char *pattern, int flags,
2278  int errfunc(const char * epath, int eerrno), void *_pglob)
2279 {
2280  glob_t *pglob = (glob_t *) _pglob;
2281  const char * lpath;
2282  int ut = urlPath(pattern, &lpath);
2283  const char *home = getenv("HOME");
2284 
2285 /*@-castfcnptr@*/
2286 if (_rpmio_debug)
2287 fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", pattern, (unsigned)flags, (void *)errfunc, pglob);
2288 /*@=castfcnptr@*/
2289  switch (ut) {
2290  case URL_IS_HTTPS:
2291  case URL_IS_HTTP:
2292  case URL_IS_FTP:
2293 /*@-type@*/
2294  pglob->gl_closedir = (void (*)(void *)) Closedir;
2295  pglob->gl_readdir = (struct dirent * (*)(void *)) Readdir;
2296  pglob->gl_opendir = (void * (*)(const char *)) Opendir;
2297  pglob->gl_lstat = Lstat;
2298  pglob->gl_stat = Stat;
2299 /*@=type@*/
2300  flags |= GLOB_ALTDIRFUNC;
2301  flags &= ~GLOB_TILDE;
2302  break;
2303  case URL_IS_PATH:
2304  pattern = lpath;
2305  /*@fallthrough@*/
2306  case URL_IS_UNKNOWN:
2307  if (home && home[0])
2308  flags |= GLOB_TILDE;
2309  else
2310  flags &= ~GLOB_TILDE;
2311  break;
2312  case URL_IS_DASH:
2313  case URL_IS_HKP:
2314  case URL_IS_MONGO: /* XXX FIXME */
2315  default:
2316  return -2;
2317  /*@notreached@*/ break;
2318  }
2319  return glob(pattern, flags, errfunc, pglob);
2320 }
2321 
2322 void Globfree(void *_pglob)
2323 {
2324  glob_t *pglob = (glob_t *) _pglob;
2325 if (_rpmio_debug)
2326 fprintf(stderr, "*** Globfree(%p)\n", pglob);
2327  globfree(pglob);
2328 }
2329 
2330 char * Realpath(const char * path, /*@null@*/ char * resolved_path)
2331 {
2332  const char * lpath;
2333  int ut = urlPath(path, &lpath);
2334  char * rpath = NULL;
2335 
2336 if (_rpmio_debug)
2337 fprintf(stderr, "*** Realpath(%s, %s)\n", path, (resolved_path ? resolved_path : "NULL"));
2338 #if !defined(__LCLINT__) /* XXX LCL: realpath(3) annotations are buggy. */
2339 /*@-nullpass@*/
2340  /* XXX if POSIXly broken realpath(3) is desired, do that. */
2341  /* XXX note: preserves current rpmlib realpath(3) usage cases. */
2342  if (path == NULL || resolved_path != NULL)
2343  return realpath(path, resolved_path);
2344 /*@=nullpass@*/
2345 #endif /* !__LCLINT__ */
2346 
2347  switch (ut) {
2348  case URL_IS_FTP:
2349  return ftpRealpath(path, resolved_path);
2350  /*@notreached@*/ break;
2351  case URL_IS_HTTPS:
2352  case URL_IS_HTTP:
2353  case URL_IS_HKP:
2354 #ifdef WITH_NEON
2355  return davRealpath(path, resolved_path);
2356  /*@notreached@*/ break;
2357 #endif
2358  /*@fallthrough@*/
2359  case URL_IS_MONGO: /* XXX FIXME */
2360  default:
2361  return xstrdup(path);
2362  /*@notreached@*/ break;
2363  case URL_IS_DASH:
2364  /* non-GLIBC systems => EINVAL. non-linux systems => EINVAL */
2365 #if defined(__linux__)
2366  lpath = "/dev/stdin";
2367 #else
2368  lpath = NULL;
2369 #endif
2370  break;
2371  case URL_IS_PATH: /* XXX note: file:/// prefix is dropped. */
2372  case URL_IS_UNKNOWN:
2373  path = lpath;
2374  break;
2375  }
2376 
2377 #if !defined(__LCLINT__) /* XXX LCL: realpath(3) annotations are buggy. */
2378  if (lpath == NULL || *lpath == '/')
2379 /*@-nullpass@*/ /* XXX glibc extension */
2380  rpath = realpath(lpath, resolved_path);
2381 /*@=nullpass@*/
2382  else {
2383  char * t;
2384 #if defined(__GLIBC__)
2385  char * dn = NULL;
2386 #else
2387  char dn[PATH_MAX];
2388  dn[0] = '\0';
2389 #endif
2390  /*
2391  * Using realpath on lpath isn't correct if the lpath is a symlink,
2392  * especially if the symlink is a dangling link. What we
2393  * do instead is use realpath() on `.' and then append lpath to
2394  * the result.
2395  */
2396  if ((t = realpath(".", dn)) != NULL) {
2397 /*@-globs -mods@*/ /* XXX no rpmGlobalMacroContext mods please. */
2398  rpath = (char *) rpmGetPath(t, "/", lpath, NULL);
2399  /* XXX preserve the pesky trailing '/' */
2400  if (lpath[strlen(lpath)-1] == '/') {
2401  char * s = rpath;
2402  rpath = rpmExpand(s, "/", NULL);
2403  s = _free(s);
2404  }
2405 /*@=globs =mods@*/
2406  } else
2407  rpath = NULL;
2408 #if defined(__GLIBC__)
2409  t = _free(t);
2410 #endif
2411  }
2412 #endif /* !__LCLINT__ */
2413 
2414  return rpath;
2415 }
2416 
2417 off_t Lseek(int fdno, off_t offset, int whence)
2418 {
2419 if (_rpmio_debug)
2420 fprintf(stderr, "*** Lseek(%d,0x%lx,%d)\n", fdno, (long)offset, whence);
2421  return lseek(fdno, offset, whence);
2422 }
const char const double d
Definition: bson.h:800
int Lchmod(const char *path, mode_t mode)
lchmod(2) clone.
Definition: rpmrpc.c:1795
int Fstat(FD_t fd, struct stat *st)
fstat(2) clone.
Definition: rpmrpc.c:1441
int Fchflags(FD_t fd, unsigned int flags)
fchflags(2) clone.
Definition: rpmrpc.c:1927
static int ftpLstat(const char *path, struct stat *st)
Definition: rpmrpc.c:1225
int ftpCmd(const char *cmd, const char *url, const char *arg2)
Definition: rpmio.c:1674
int Rename(const char *oldpath, const char *newpath)
rename(2) clone.
Definition: rpmrpc.c:286
int davMkdir(const char *path, mode_t mode)
int Link(const char *oldpath, const char *newpath)
link(2) clone.
Definition: rpmrpc.c:345
static int is_week(const char *str, struct tm *tim)
Definition: rpmrpc.c:497
int _url_iobuf_size
Definition: url.c:66
static int current_mday
Definition: rpmrpc.c:441
int Mkdir(const char *path, mode_t mode)
mkdir(2) clone.
Definition: rpmrpc.c:73
const char const char size_t len
Definition: bson.h:823
int _ftp_debug
Definition: rpmio.c:190
char * getenv(const char *name)
static int is_month(const char *str, struct tm *tim)
Definition: rpmrpc.c:514
#define GLOB_ALTDIRFUNC
Definition: glob.h:85
time_t lastModified
static int ftpReadlink(const char *path, char *buf, size_t bufsiz)
Definition: rpmrpc.c:1243
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
int Chflags(const char *path, unsigned int flags)
chflags(2) clone.
Definition: rpmrpc.c:1861
#define g_strdup
Definition: rpmrpc.c:434
URL control structure.
Definition: rpmurl.h:52
int davLstat(const char *path, struct stat *st)
lstat(2) clone.
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
Definition: macro.c:3445
static const char * fdGetOPath(FD_t fd)
int(* gl_stat)()
Definition: glob.h:134
int xstrncasecmp(const char *s1, const char *s2, size_t n)
Locale insensitive strncasecmp(3).
Definition: strcasecmp.c:30
int Chown(const char *path, uid_t owner, gid_t group)
chown(2) clone.
Definition: rpmrpc.c:1674
#define g_free
Definition: rpmrpc.c:435
static int is_num(int idx)
Definition: rpmrpc.c:478
void globfree(glob_t *pglob)
Definition: glob.c:877
char *(* gl_opendir)()
Definition: glob.h:130
FD_t fdLink(void *cookie, const char *msg)
#define S_ISLNK(mode)
Definition: system.h:651
int fdFgets(FD_t fd, char *buf, size_t len)
Definition: rpmio.c:687
Hash table implemenation.
int errno
static int vfs_parse_filedate(int idx, time_t *t)
Definition: rpmrpc.c:660
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
int ufdClose(void *cookie)
Definition: rpmio.c:2093
static int ftpStat(const char *path, struct stat *st)
Definition: rpmrpc.c:1206
unsigned short rpmuint16_t
Definition: rpmiotypes.h:27
DIR * ftpOpendir(const char *path)
Create an argv directory from an ftp:// URI.
Definition: rpmrpc.c:1254
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
int Lutimes(const char *path, const struct timeval times[2])
Definition: rpmrpc.c:2084
int Mknod(const char *path, mode_t mode, dev_t dev)
mknod(3) clone.
Definition: rpmrpc.c:1989
Definition: glob.h:117
void * rpmavxNew(const char *uri, struct stat *st)
Definition: rpmdir.c:64
FD_t ftpOpen(const char *url, int flags, mode_t mode, urlinfo *uret)
Definition: rpmio.c:2212
int Fchown(FD_t fd, uid_t owner, gid_t group)
fchown(2) clone.
Definition: rpmrpc.c:1704
int(* gl_lstat)()
Definition: glob.h:132
static int vfs_parse_ls_lga(char *p, struct stat *st, const char **filename, const char **linkname)
Definition: rpmrpc.c:769
int Open(const char *path, int flags, mode_t mode)
open(2) clone.
Definition: rpmrpc.c:219
int Access(const char *path, int amode)
access(2) clone.
Definition: rpmrpc.c:2196
int Chdir(const char *path)
chdir(2) clone.
Definition: rpmrpc.c:105
int Symlink(const char *oldpath, const char *newpath)
symlink(3) clone.
Definition: rpmrpc.c:2120
int Glob_error(const char *epath, int eerrno)
glob_error(3) clone.
Definition: rpmrpc.c:2271
int openError
Definition: rpmurl.h:116
const char * str
Definition: bson.h:593
static int vfs_parse_filemode(const char *p)
Definition: rpmrpc.c:601
static int ftpUnlink(const char *path)
Definition: rpmrpc.c:65
int Chroot(const char *path)
chroot(2) clone.
Definition: rpmrpc.c:176
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
int Glob(const char *pattern, int flags, int errfunc(const char *epath, int eerrno), void *_pglob)
glob(3) clone.
Definition: rpmrpc.c:2277
off_t Lseek(int fdno, off_t offset, int whence)
lseek(2) clone.
Definition: rpmrpc.c:2417
int Lstat(const char *path, struct stat *st)
lstat(2) clone.
Definition: rpmrpc.c:1401
const char * mode
Definition: mongo.h:440
char * realpath(const char *path, char resolved_path[])
int gnameToGid(const char *thisGname, gid_t *gid)
Definition: ugid.c:71
char * Realpath(const char *path, char *resolved_path)
realpath(3) clone.
Definition: rpmrpc.c:2330
int Lchflags(const char *path, unsigned int flags)
lchflags(2) clone.
Definition: rpmrpc.c:1893
int Utimes(const char *path, const struct timeval times[2])
Definition: rpmrpc.c:2052
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397
#define MAXCOLS
Definition: rpmrpc.c:448
int Fchmod(FD_t fd, mode_t mode)
fchmod(2) clone.
Definition: rpmrpc.c:1830
static int vfs_split_text(char *p)
Definition: rpmrpc.c:456
The FD_t File Handle data structure.
ssize_t contentLength
int Glob_pattern_p(const char *pattern, int quote)
glob_pattern_p(3) clone.
Definition: rpmrpc.c:2231
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3252
int Readlink(const char *path, char *buf, size_t bufsiz)
readlink(2) clone.
Definition: rpmrpc.c:2154
static int is_year(const char *str, struct tm *tim)
Definition: rpmrpc.c:550
void(* gl_closedir)()
Definition: glob.h:126
static int ftpRmdir(const char *path)
Definition: rpmrpc.c:48
#define lchown
Definition: system.h:682
#define dirent
Definition: system.h:245
static int vfs_parse_filetype(char c)
Definition: rpmrpc.c:582
static const char * statstr(const struct stat *st, char *buf)
Definition: rpmrpc.c:1180
static int is_time(const char *str, struct tm *tim)
Definition: rpmrpc.c:531
struct dirent *(* gl_readdir)()
Definition: glob.h:128
int davUnlink(const char *path)
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
int davRmdir(const char *path)
char * davRealpath(const char *path, char *resolved_path)
realpath(3) clone.
static char * ftpRealpath(const char *path, char *resolved_path)
Definition: rpmrpc.c:1353
#define S_IFSOCK
Definition: system.h:647
struct __dirstream * AVDIR
Definition: rpmdir.h:21
#define GLOB_TILDE
Definition: glob.h:88
int Utime(const char *path, const struct utimbuf *buf)
Definition: rpmrpc.c:2021
DIR * avOpendir(const char *path, const char **av, rpmuint16_t *modes)
Definition: rpmdir.c:135
int Lchown(const char *path, uid_t owner, gid_t group)
lchown(2) clone.
Definition: rpmrpc.c:1735
static int current_mon
Definition: rpmrpc.c:443
static int is_dos_date(const char *str)
Definition: rpmrpc.c:487
const char const int i
Definition: bson.h:778
static int ftpNLST(const char *url, ftpSysCall_t ftpSysCall, struct stat *st, char *rlbuf, size_t rlbufsiz)
Definition: rpmrpc.c:989
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
int Fallocate(FD_t fd, off_t offset, off_t len)
posix_fallocate(3)/fallocate(2) clone.
Definition: rpmrpc.c:1548
const char const bson const bson bson * out
Definition: mongo.h:678
int _rpmio_debug
Definition: rpmio.c:180
static char * ftpBuf
Definition: rpmrpc.c:985
struct dirent * Readdir(DIR *dir)
readdir(3) clone.
Definition: rpmdir.c:432
ftpSysCall_t
Definition: rpmrpc.c:970
int Fadvise(FD_t fd, off_t offset, off_t len, int advice)
posix_fadvise(2) clone.
Definition: rpmrpc.c:1495
#define alloca_strdup(_s)
Definition: rpmrpc.c:987
int Chmod(const char *path, mode_t mode)
chmod(2) clone.
Definition: rpmrpc.c:1765
int glob(const char *pattern, int flags, int(*errfunc) __P((const char *, int)), glob_t *pglob)
Definition: glob.c:176
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
static int ftpMkdir(const char *path, mode_t mode)
Definition: rpmrpc.c:25
int davRename(const char *oldpath, const char *newpath)
int Fileno(FD_t fd)
fileno(3) clone.
Definition: rpmio.c:2998
int Closedir(DIR *dir)
closedir(3) clone.
Definition: rpmdir.c:385
int Rmdir(const char *path)
rmdir(2) clone.
Definition: rpmrpc.c:141
rpmuint32_t hashFunctionString(rpmuint32_t h, const void *data, size_t size)
Return hash value of a string.
Definition: rpmhash.c:83
static int ftpChdir(const char *path)
Definition: rpmrpc.c:41
#define _(Text)
Definition: system.h:29
const char const char * pattern
Definition: bson.h:971
int Mkfifo(const char *path, mode_t mode)
mkfifo(3) clone.
Definition: rpmrpc.c:1959
DIR * Opendir(const char *path)
opendir(3) clone.
Definition: rpmdir.c:396
static char * columns[30]
Definition: rpmrpc.c:451
void Globfree(void *_pglob)
globfree(3) clone.
Definition: rpmrpc.c:2322
int unameToUid(const char *thisUname, uid_t *uid)
Definition: ugid.c:16
#define PATH_MAX
Definition: query.c:10
static int ftpRename(const char *oldpath, const char *newpath)
Definition: rpmrpc.c:55
int davStat(const char *path, struct stat *st)
stat(2) clone.
int ftpReq(FD_t data, const char *ftpCmd, const char *ftpArg)
Definition: rpmio.c:1277
#define xrealloc
Definition: system.h:35
static int current_year
Definition: rpmrpc.c:445
const char * _chroot_prefix
Definition: rpmrpc.c:174
static int column_ptr[30]
Definition: rpmrpc.c:453
static size_t ftpBufAlloced
Definition: rpmrpc.c:980