rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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