rpm
5.2.1
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio_internal.h> 00008 #include <rpmmacro.h> 00009 00010 #define _RPMAV_INTERNAL 00011 #define _RPMDAV_INTERNAL 00012 #include <rpmdav.h> 00013 00014 #include <rpmhash.h> 00015 #include <ugid.h> 00016 00017 #include "debug.h" 00018 00019 /*@access DIR @*/ 00020 /*@access FD_t @*/ 00021 /*@access urlinfo @*/ 00022 00023 /* =============================================================== */ 00024 static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode) 00025 /*@globals h_errno, fileSystem, internalState @*/ 00026 /*@modifies fileSystem, internalState @*/ 00027 { 00028 int rc; 00029 if ((rc = ftpCmd("MKD", path, NULL)) != 0) 00030 return rc; 00031 #if NOTYET 00032 { char buf[20]; 00033 sprintf(buf, " 0%o", mode); 00034 (void) ftpCmd("SITE CHMOD", path, buf); 00035 } 00036 #endif 00037 return rc; 00038 } 00039 00040 static int ftpChdir(const char * path) 00041 /*@globals h_errno, fileSystem, internalState @*/ 00042 /*@modifies fileSystem, internalState @*/ 00043 { 00044 return ftpCmd("CWD", path, NULL); 00045 } 00046 00047 static int ftpRmdir(const char * path) 00048 /*@globals h_errno, fileSystem, internalState @*/ 00049 /*@modifies fileSystem, internalState @*/ 00050 { 00051 return ftpCmd("RMD", path, NULL); 00052 } 00053 00054 static int ftpRename(const char * oldpath, const char * newpath) 00055 /*@globals h_errno, fileSystem, internalState @*/ 00056 /*@modifies fileSystem, internalState @*/ 00057 { 00058 int rc; 00059 if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0) 00060 return rc; 00061 return ftpCmd("RNTO", newpath, NULL); 00062 } 00063 00064 static int ftpUnlink(const char * path) 00065 /*@globals h_errno, fileSystem, internalState @*/ 00066 /*@modifies fileSystem, internalState @*/ 00067 { 00068 return ftpCmd("DELE", path, NULL); 00069 } 00070 00071 /* =============================================================== */ 00072 int Mkdir (const char * path, mode_t mode) 00073 { 00074 const char * lpath; 00075 int ut = urlPath(path, &lpath); 00076 00077 if (_rpmio_debug) 00078 fprintf(stderr, "*** Mkdir(%s, 0%o)\n", path, (unsigned)mode); 00079 switch (ut) { 00080 case URL_IS_FTP: 00081 return ftpMkdir(path, mode); 00082 /*@notreached@*/ break; 00083 case URL_IS_HTTPS: 00084 case URL_IS_HTTP: 00085 #ifdef WITH_NEON 00086 return davMkdir(path, mode); 00087 #endif 00088 /*@notreached@*/ break; 00089 case URL_IS_PATH: 00090 path = lpath; 00091 /*@fallthrough@*/ 00092 case URL_IS_UNKNOWN: 00093 break; 00094 case URL_IS_DASH: 00095 case URL_IS_HKP: 00096 default: 00097 return -2; 00098 /*@notreached@*/ break; 00099 } 00100 return mkdir(path, mode); 00101 } 00102 00103 int Chdir (const char * path) 00104 { 00105 const char * lpath; 00106 int ut = urlPath(path, &lpath); 00107 00108 if (_rpmio_debug) 00109 fprintf(stderr, "*** Chdir(%s)\n", path); 00110 switch (ut) { 00111 case URL_IS_FTP: 00112 return ftpChdir(path); 00113 /*@notreached@*/ break; 00114 case URL_IS_HTTPS: 00115 case URL_IS_HTTP: 00116 #ifdef NOTYET 00117 return davChdir(path); 00118 #else 00119 errno = EINVAL; /* XXX W2DO? */ 00120 return -2; 00121 #endif 00122 /*@notreached@*/ break; 00123 case URL_IS_PATH: 00124 path = lpath; 00125 /*@fallthrough@*/ 00126 case URL_IS_UNKNOWN: 00127 break; 00128 case URL_IS_DASH: 00129 case URL_IS_HKP: 00130 default: 00131 errno = EINVAL; /* XXX W2DO? */ 00132 return -2; 00133 /*@notreached@*/ break; 00134 } 00135 return chdir(path); 00136 } 00137 00138 int Rmdir (const char * path) 00139 { 00140 const char * lpath; 00141 int ut = urlPath(path, &lpath); 00142 00143 if (_rpmio_debug) 00144 fprintf(stderr, "*** Rmdir(%s)\n", path); 00145 switch (ut) { 00146 case URL_IS_FTP: 00147 return ftpRmdir(path); 00148 /*@notreached@*/ break; 00149 case URL_IS_HTTPS: 00150 case URL_IS_HTTP: 00151 #ifdef WITH_NEON 00152 return davRmdir(path); 00153 #endif 00154 /*@notreached@*/ break; 00155 case URL_IS_PATH: 00156 path = lpath; 00157 /*@fallthrough@*/ 00158 case URL_IS_UNKNOWN: 00159 break; 00160 case URL_IS_DASH: 00161 case URL_IS_HKP: 00162 default: 00163 return -2; 00164 /*@notreached@*/ break; 00165 } 00166 return rmdir(path); 00167 } 00168 00169 /*@unchecked@*/ 00170 const char * _chroot_prefix = NULL; 00171 00172 int Chroot(const char * path) 00173 { 00174 const char * lpath; 00175 int ut = urlPath(path, &lpath); 00176 00177 if (_rpmio_debug) 00178 fprintf(stderr, "*** Chroot(%s)\n", path); 00179 switch (ut) { 00180 case URL_IS_PATH: 00181 path = lpath; 00182 /*@fallthrough@*/ 00183 case URL_IS_UNKNOWN: 00184 break; 00185 case URL_IS_DASH: 00186 case URL_IS_HKP: 00187 case URL_IS_FTP: /* XXX TODO: implement. */ 00188 case URL_IS_HTTPS: /* XXX TODO: implement. */ 00189 case URL_IS_HTTP: /* XXX TODO: implement. */ 00190 default: 00191 errno = EINVAL; /* XXX W2DO? */ 00192 return -2; 00193 /*@notreached@*/ break; 00194 } 00195 00196 /*@-dependenttrans -modobserver -observertrans @*/ 00197 _chroot_prefix = _free(_chroot_prefix); 00198 /*@=dependenttrans =modobserver =observertrans @*/ 00199 /*@-globs -mods@*/ /* XXX hide rpmGlobalMacroContext mods for now. */ 00200 if (strcmp(path, ".")) 00201 _chroot_prefix = rpmGetPath(path, NULL); 00202 /*@=globs =mods@*/ 00203 00204 /*@-superuser@*/ 00205 return chroot(path); 00206 /*@=superuser@*/ 00207 } 00208 /*@=mods@*/ 00209 00210 int Open(const char * path, int flags, mode_t mode) 00211 { 00212 const char * lpath; 00213 int ut = urlPath(path, &lpath); 00214 int fdno; 00215 00216 if (_rpmio_debug) 00217 fprintf(stderr, "*** Open(%s, 0x%x, 0%o)\n", path, flags, (unsigned)mode); 00218 switch (ut) { 00219 case URL_IS_PATH: 00220 path = lpath; 00221 /*@fallthrough@*/ 00222 case URL_IS_UNKNOWN: 00223 break; 00224 case URL_IS_DASH: 00225 case URL_IS_HKP: 00226 case URL_IS_FTP: /* XXX TODO: implement. */ 00227 case URL_IS_HTTPS: /* XXX TODO: implement. */ 00228 case URL_IS_HTTP: /* XXX TODO: implement. */ 00229 default: 00230 errno = EINVAL; /* XXX W2DO? */ 00231 return -2; 00232 /*@notreached@*/ break; 00233 } 00234 00235 if (_chroot_prefix && _chroot_prefix[0] == '/' && _chroot_prefix[1] != '\0') 00236 { 00237 size_t nb = strlen(_chroot_prefix); 00238 size_t ob = strlen(path); 00239 while (nb > 0 && _chroot_prefix[nb-1] == '/') 00240 nb--; 00241 if (ob > nb && !strncmp(path, _chroot_prefix, nb) && path[nb] == '/') 00242 path += nb; 00243 } 00244 #ifdef NOTYET /* XXX likely sane default. */ 00245 if (mode == 0) 00246 mode = 0644; 00247 #endif 00248 fdno = open(path, flags, mode); 00249 if (fdno >= 0) { 00250 if (fcntl(fdno, F_SETFD, FD_CLOEXEC) < 0) { 00251 (void) close(fdno); 00252 fdno = -1; 00253 } 00254 } 00255 return fdno; 00256 } 00257 00258 /* XXX rpmdb.c: analogue to rename(2). */ 00259 00260 int Rename (const char * oldpath, const char * newpath) 00261 { 00262 const char *oe = NULL; 00263 const char *ne = NULL; 00264 int oldut, newut; 00265 00266 if (_rpmio_debug) 00267 fprintf(stderr, "*** Rename(%s, %s)\n", oldpath, newpath); 00268 /* XXX lib/install.c used to rely on this behavior. */ 00269 if (!strcmp(oldpath, newpath)) return 0; 00270 00271 oldut = urlPath(oldpath, &oe); 00272 switch (oldut) { 00273 case URL_IS_HTTPS: 00274 case URL_IS_HTTP: 00275 #ifdef WITH_NEON 00276 return davRename(oldpath, newpath); 00277 #endif 00278 /*@notreached@*/ break; 00279 case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ 00280 case URL_IS_PATH: 00281 case URL_IS_UNKNOWN: 00282 break; 00283 case URL_IS_DASH: 00284 case URL_IS_HKP: 00285 default: 00286 return -2; 00287 /*@notreached@*/ break; 00288 } 00289 00290 newut = urlPath(newpath, &ne); 00291 switch (newut) { 00292 case URL_IS_FTP: 00293 if (_rpmio_debug) 00294 fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath); 00295 if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) && 00296 !xstrncasecmp(oldpath, newpath, (oe - oldpath)))) 00297 return -2; 00298 return ftpRename(oldpath, newpath); 00299 /*@notreached@*/ break; 00300 case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */ 00301 case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ 00302 case URL_IS_PATH: 00303 oldpath = oe; 00304 newpath = ne; 00305 break; 00306 case URL_IS_UNKNOWN: 00307 break; 00308 case URL_IS_DASH: 00309 case URL_IS_HKP: 00310 default: 00311 return -2; 00312 /*@notreached@*/ break; 00313 } 00314 return rename(oldpath, newpath); 00315 } 00316 00317 int Link (const char * oldpath, const char * newpath) 00318 { 00319 const char *oe = NULL; 00320 const char *ne = NULL; 00321 int oldut, newut; 00322 00323 if (_rpmio_debug) 00324 fprintf(stderr, "*** Link(%s, %s)\n", oldpath, newpath); 00325 oldut = urlPath(oldpath, &oe); 00326 switch (oldut) { 00327 case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */ 00328 case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ 00329 case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ 00330 case URL_IS_PATH: 00331 case URL_IS_UNKNOWN: 00332 break; 00333 case URL_IS_DASH: 00334 case URL_IS_HKP: 00335 default: 00336 return -2; 00337 /*@notreached@*/ break; 00338 } 00339 00340 newut = urlPath(newpath, &ne); 00341 switch (newut) { 00342 case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */ 00343 case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ 00344 case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ 00345 case URL_IS_PATH: 00346 if (_rpmio_debug) 00347 fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath); 00348 if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) && 00349 !xstrncasecmp(oldpath, newpath, (oe - oldpath)))) 00350 return -2; 00351 oldpath = oe; 00352 newpath = ne; 00353 break; 00354 case URL_IS_UNKNOWN: 00355 break; 00356 case URL_IS_DASH: 00357 case URL_IS_HKP: 00358 default: 00359 return -2; 00360 /*@notreached@*/ break; 00361 } 00362 return link(oldpath, newpath); 00363 } 00364 00365 /* XXX build/build.c: analogue to unlink(2). */ 00366 00367 int Unlink(const char * path) { 00368 const char * lpath; 00369 int ut = urlPath(path, &lpath); 00370 00371 if (_rpmio_debug) 00372 fprintf(stderr, "*** Unlink(%s)\n", path); 00373 switch (ut) { 00374 case URL_IS_FTP: 00375 return ftpUnlink(path); 00376 /*@notreached@*/ break; 00377 case URL_IS_HTTPS: 00378 case URL_IS_HTTP: 00379 #ifdef WITH_NEON 00380 return davUnlink(path); 00381 #endif 00382 /*@notreached@*/ break; 00383 case URL_IS_PATH: 00384 path = lpath; 00385 /*@fallthrough@*/ 00386 case URL_IS_UNKNOWN: 00387 break; 00388 case URL_IS_DASH: 00389 case URL_IS_HKP: 00390 default: 00391 return -2; 00392 /*@notreached@*/ break; 00393 } 00394 return unlink(path); 00395 } 00396 00397 /* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */ 00398 00399 #define g_strdup xstrdup 00400 #define g_free free 00401 00402 /* 00403 * FIXME: this is broken. It depends on mc not crossing border on month! 00404 */ 00405 /*@unchecked@*/ 00406 static int current_mday; 00407 /*@unchecked@*/ 00408 static int current_mon; 00409 /*@unchecked@*/ 00410 static int current_year; 00411 00412 /* Following stuff (parse_ls_lga) is used by ftpfs and extfs */ 00413 #define MAXCOLS 30 00414 00415 /*@unchecked@*/ 00416 static char *columns [MAXCOLS]; /* Points to the string in column n */ 00417 /*@unchecked@*/ 00418 static int column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */ 00419 00420 static int 00421 vfs_split_text (char *p) 00422 /*@globals columns, column_ptr @*/ 00423 /*@modifies *p, columns, column_ptr @*/ 00424 { 00425 char *original = p; 00426 int numcols; 00427 00428 00429 for (numcols = 0; *p && numcols < MAXCOLS; numcols++){ 00430 while (*p == ' ' || *p == '\r' || *p == '\n'){ 00431 *p = '\0'; 00432 p++; 00433 } 00434 columns [numcols] = p; 00435 column_ptr [numcols] = p - original; 00436 while (*p && *p != ' ' && *p != '\r' && *p != '\n') 00437 p++; 00438 } 00439 return numcols; 00440 } 00441 00442 static int 00443 is_num (int idx) 00444 /*@*/ 00445 { 00446 if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9') 00447 return 0; 00448 return 1; 00449 } 00450 00451 static int 00452 is_dos_date(/*@null@*/ const char *str) 00453 /*@*/ 00454 { 00455 if (str != NULL && strlen(str) == 8 && 00456 str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL) 00457 return 1; 00458 return 0; 00459 } 00460 00461 static int 00462 is_week (/*@null@*/ const char * str, /*@out@*/ struct tm * tim) 00463 /*@modifies *tim @*/ 00464 { 00465 /*@observer@*/ static const char * week = "SunMonTueWedThuFriSat"; 00466 const char * pos; 00467 00468 /*@-observertrans -mayaliasunique@*/ 00469 if (str != NULL && (pos=strstr(week, str)) != NULL) { 00470 /*@=observertrans =mayaliasunique@*/ 00471 if (tim != NULL) 00472 tim->tm_wday = (pos - week)/3; 00473 return 1; 00474 } 00475 return 0; 00476 } 00477 00478 static int 00479 is_month (/*@null@*/ const char * str, /*@out@*/ struct tm * tim) 00480 /*@modifies *tim @*/ 00481 { 00482 /*@observer@*/ static const char * month = "JanFebMarAprMayJunJulAugSepOctNovDec"; 00483 const char * pos; 00484 00485 /*@-observertrans -mayaliasunique@*/ 00486 if (str != NULL && (pos = strstr(month, str)) != NULL) { 00487 /*@=observertrans -mayaliasunique@*/ 00488 if (tim != NULL) 00489 tim->tm_mon = (pos - month)/3; 00490 return 1; 00491 } 00492 return 0; 00493 } 00494 00495 static int 00496 is_time (/*@null@*/ const char * str, /*@out@*/ struct tm * tim) 00497 /*@modifies *tim @*/ 00498 { 00499 const char * p, * p2; 00500 00501 if (str != NULL && (p = strchr(str, ':')) && (p2 = strrchr(str, ':'))) { 00502 if (p != p2) { 00503 if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3) 00504 return 0; 00505 } else { 00506 if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2) 00507 return 0; 00508 } 00509 } else 00510 return 0; 00511 00512 return 1; 00513 } 00514 00515 static int is_year(/*@null@*/ const char * str, /*@out@*/ struct tm * tim) 00516 /*@modifies *tim @*/ 00517 { 00518 long year; 00519 00520 if (str == NULL) 00521 return 0; 00522 00523 if (strchr(str,':')) 00524 return 0; 00525 00526 if (strlen(str) != 4) 00527 return 0; 00528 00529 if (sscanf(str, "%ld", &year) != 1) 00530 return 0; 00531 00532 if (year < 1900 || year > 3000) 00533 return 0; 00534 00535 tim->tm_year = (int) (year - 1900); 00536 00537 return 1; 00538 } 00539 00540 /* 00541 * FIXME: this is broken. Consider following entry: 00542 * -rwx------ 1 root root 1 Aug 31 10:04 2904 1234 00543 * where "2904 1234" is filename. Well, this code decodes it as year :-(. 00544 */ 00545 00546 static int 00547 vfs_parse_filetype (char c) 00548 /*@*/ 00549 { 00550 switch (c) { 00551 case 'd': return (int)S_IFDIR; 00552 case 'b': return (int)S_IFBLK; 00553 case 'c': return (int)S_IFCHR; 00554 case 'l': return (int)S_IFLNK; 00555 case 's': 00556 #ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */ 00557 return (int)S_IFSOCK; 00558 #endif 00559 case 'p': return (int)S_IFIFO; 00560 case 'm': case 'n': /* Don't know what these are :-) */ 00561 case '-': case '?': return (int)S_IFREG; 00562 default: return -1; 00563 } 00564 } 00565 00566 static int vfs_parse_filemode (const char *p) 00567 /*@*/ 00568 { /* converts rw-rw-rw- into 0666 */ 00569 int res = 0; 00570 switch (*(p++)) { 00571 case 'r': res |= 0400; break; 00572 case '-': break; 00573 default: return -1; 00574 } 00575 switch (*(p++)) { 00576 case 'w': res |= 0200; break; 00577 case '-': break; 00578 default: return -1; 00579 } 00580 switch (*(p++)) { 00581 case 'x': res |= 0100; break; 00582 case 's': res |= 0100 | S_ISUID; break; 00583 case 'S': res |= S_ISUID; break; 00584 case '-': break; 00585 default: return -1; 00586 } 00587 switch (*(p++)) { 00588 case 'r': res |= 0040; break; 00589 case '-': break; 00590 default: return -1; 00591 } 00592 switch (*(p++)) { 00593 case 'w': res |= 0020; break; 00594 case '-': break; 00595 default: return -1; 00596 } 00597 switch (*(p++)) { 00598 case 'x': res |= 0010; break; 00599 case 's': res |= 0010 | S_ISGID; break; 00600 case 'l': /* Solaris produces these */ 00601 case 'S': res |= S_ISGID; break; 00602 case '-': break; 00603 default: return -1; 00604 } 00605 switch (*(p++)) { 00606 case 'r': res |= 0004; break; 00607 case '-': break; 00608 default: return -1; 00609 } 00610 switch (*(p++)) { 00611 case 'w': res |= 0002; break; 00612 case '-': break; 00613 default: return -1; 00614 } 00615 switch (*(p++)) { 00616 case 'x': res |= 0001; break; 00617 case 't': res |= 0001 | S_ISVTX; break; 00618 case 'T': res |= S_ISVTX; break; 00619 case '-': break; 00620 default: return -1; 00621 } 00622 return res; 00623 } 00624 00625 static int vfs_parse_filedate(int idx, /*@out@*/ time_t *t) 00626 /*@modifies *t @*/ 00627 { /* This thing parses from idx in columns[] array */ 00628 00629 char *p; 00630 struct tm tim; 00631 int d[3]; 00632 int got_year = 0; 00633 00634 /* Let's setup default time values */ 00635 tim.tm_year = current_year; 00636 tim.tm_mon = current_mon; 00637 tim.tm_mday = current_mday; 00638 tim.tm_hour = 0; 00639 tim.tm_min = 0; 00640 tim.tm_sec = 0; 00641 tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */ 00642 00643 p = columns [idx++]; 00644 00645 /* We eat weekday name in case of extfs */ 00646 if(is_week(p, &tim)) 00647 p = columns [idx++]; 00648 00649 /* Month name */ 00650 if(is_month(p, &tim)){ 00651 /* And we expect, it followed by day number */ 00652 if (is_num (idx)) 00653 tim.tm_mday = (int)atol (columns [idx++]); 00654 else 00655 return 0; /* No day */ 00656 00657 } else { 00658 /* We usually expect: 00659 Mon DD hh:mm 00660 Mon DD YYYY 00661 But in case of extfs we allow these date formats: 00662 Mon DD YYYY hh:mm 00663 Mon DD hh:mm YYYY 00664 Wek Mon DD hh:mm:ss YYYY 00665 MM-DD-YY hh:mm 00666 where Mon is Jan-Dec, DD, MM, YY two digit day, month, year, 00667 YYYY four digit year, hh, mm, ss two digit hour, minute or second. */ 00668 00669 /* Here just this special case with MM-DD-YY */ 00670 if (is_dos_date(p)){ 00671 /*@-mods@*/ 00672 p[2] = p[5] = '-'; 00673 /*@=mods@*/ 00674 00675 memset(d, 0, sizeof(d)); 00676 if (sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){ 00677 /* We expect to get: 00678 1. MM-DD-YY 00679 2. DD-MM-YY 00680 3. YY-MM-DD 00681 4. YY-DD-MM */ 00682 00683 /* Hmm... maybe, next time :)*/ 00684 00685 /* At last, MM-DD-YY */ 00686 d[0]--; /* Months are zerobased */ 00687 /* Y2K madness */ 00688 if(d[2] < 70) 00689 d[2] += 100; 00690 00691 tim.tm_mon = d[0]; 00692 tim.tm_mday = d[1]; 00693 tim.tm_year = d[2]; 00694 got_year = 1; 00695 } else 00696 return 0; /* sscanf failed */ 00697 } else 00698 return 0; /* unsupported format */ 00699 } 00700 00701 /* Here we expect to find time and/or year */ 00702 00703 if (is_num (idx)) { 00704 if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) { 00705 idx++; 00706 00707 /* This is a special case for ctime() or Mon DD YYYY hh:mm */ 00708 if(is_num (idx) && 00709 ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim))) 00710 idx++; /* time & year or reverse */ 00711 } /* only time or date */ 00712 } 00713 else 00714 return 0; /* Nor time or date */ 00715 00716 /* 00717 * If the date is less than 6 months in the past, it is shown without year 00718 * other dates in the past or future are shown with year but without time 00719 * This does not check for years before 1900 ... I don't know, how 00720 * to represent them at all 00721 */ 00722 if (!got_year && 00723 current_mon < 6 && current_mon < tim.tm_mon && 00724 tim.tm_mon - current_mon >= 6) 00725 00726 tim.tm_year--; 00727 00728 if ((*t = mktime(&tim)) < 0) 00729 *t = 0; 00730 return idx; 00731 } 00732 00733 static int 00734 vfs_parse_ls_lga (char * p, /*@out@*/ struct stat * st, 00735 /*@out@*/ const char ** filename, 00736 /*@out@*/ const char ** linkname) 00737 /*@modifies *p, *st, *filename, *linkname @*/ 00738 { 00739 int idx, idx2, num_cols; 00740 int i; 00741 char *p_copy; 00742 long n; 00743 00744 if (strncmp (p, "total", 5) == 0) 00745 return 0; 00746 00747 p_copy = g_strdup(p); 00748 /* XXX FIXME: parse out inode number from "NLST -lai ." */ 00749 /* XXX FIXME: parse out sizein blocks from "NLST -lais ." */ 00750 00751 if ((i = vfs_parse_filetype(*(p++))) == -1) 00752 goto error; 00753 00754 st->st_mode = i; 00755 if (*p == ' ') /* Notwell 4 */ 00756 p++; 00757 if (*p == '['){ 00758 if (strlen (p) <= 8 || p [8] != ']') 00759 goto error; 00760 /* Should parse here the Notwell permissions :) */ 00761 /*@-unrecog@*/ 00762 if (S_ISDIR (st->st_mode)) 00763 st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH); 00764 else 00765 st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); 00766 p += 9; 00767 /*@=unrecog@*/ 00768 } else { 00769 if ((i = vfs_parse_filemode(p)) == -1) 00770 goto error; 00771 st->st_mode |= i; 00772 p += 9; 00773 00774 /* This is for an extra ACL attribute (HP-UX) */ 00775 if (*p == '+') 00776 p++; 00777 } 00778 00779 g_free(p_copy); 00780 p_copy = g_strdup(p); 00781 num_cols = vfs_split_text (p); 00782 00783 n = atol(columns[0]); 00784 st->st_nlink = n; 00785 if (n < 0) 00786 goto error; 00787 00788 if (!is_num (1)) 00789 #ifdef HACK 00790 st->st_uid = finduid (columns [1]); 00791 #else 00792 (void) unameToUid (columns [1], &st->st_uid); 00793 #endif 00794 else 00795 st->st_uid = (uid_t) atol (columns [1]); 00796 00797 /* Mhm, the ls -lg did not produce a group field */ 00798 for (idx = 3; idx <= 5; idx++) 00799 if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx])) 00800 break; 00801 00802 if (idx == 6 || (idx == 5 && !S_ISCHR (st->st_mode) && !S_ISBLK (st->st_mode))) 00803 goto error; 00804 00805 /* We don't have gid */ 00806 if (idx == 3 || (idx == 4 && (S_ISCHR(st->st_mode) || S_ISBLK (st->st_mode)))) 00807 idx2 = 2; 00808 else { 00809 /* We have gid field */ 00810 if (is_num (2)) 00811 st->st_gid = (gid_t) atol (columns [2]); 00812 else 00813 #ifdef HACK 00814 st->st_gid = findgid (columns [2]); 00815 #else 00816 (void) gnameToGid (columns [1], &st->st_gid); 00817 #endif 00818 idx2 = 3; 00819 } 00820 00821 /* This is device */ 00822 if (S_ISCHR (st->st_mode) || S_ISBLK (st->st_mode)){ 00823 unsigned maj, min; 00824 00825 if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1) 00826 goto error; 00827 00828 if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1) 00829 goto error; 00830 00831 #ifdef HAVE_ST_RDEV 00832 st->st_rdev = ((maj & 0x000000ffU) << 8) | (min & 0x000000ffU); 00833 #endif 00834 st->st_size = 0; 00835 00836 } else { 00837 /* Common file size */ 00838 if (!is_num (idx2)) 00839 goto error; 00840 00841 st->st_size = (size_t) atol (columns [idx2]); 00842 #ifdef HAVE_ST_RDEV 00843 st->st_rdev = 0; 00844 #endif 00845 } 00846 00847 idx = vfs_parse_filedate(idx, &st->st_mtime); 00848 if (!idx) 00849 goto error; 00850 /* Use resulting time value */ 00851 st->st_atime = st->st_ctime = st->st_mtime; 00852 st->st_dev = 0; 00853 st->st_ino = 0; 00854 #ifdef HAVE_ST_BLKSIZE 00855 st->st_blksize = 512; 00856 #endif 00857 #ifdef HAVE_ST_BLOCKS 00858 st->st_blocks = (st->st_size + 511) / 512; 00859 #endif 00860 00861 for (i = idx + 1, idx2 = 0; i < num_cols; i++ ) 00862 if (strcmp (columns [i], "->") == 0){ 00863 idx2 = i; 00864 break; 00865 } 00866 00867 if (((S_ISLNK (st->st_mode) || 00868 (num_cols == idx + 3 && st->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */ 00869 && idx2) 00870 { 00871 size_t tlen; 00872 char *t; 00873 00874 if (filename){ 00875 size_t nb = column_ptr [idx2] - column_ptr [idx] - 1; 00876 t = strncpy(xcalloc(1, nb+1), p_copy + column_ptr [idx], nb); 00877 *filename = t; 00878 } 00879 if (linkname){ 00880 t = g_strdup (p_copy + column_ptr [idx2+1]); 00881 tlen = strlen (t); 00882 if (t [tlen-1] == '\r' || t [tlen-1] == '\n') 00883 t [tlen-1] = '\0'; 00884 if (t [tlen-2] == '\r' || t [tlen-2] == '\n') 00885 t [tlen-2] = '\0'; 00886 00887 *linkname = t; 00888 } 00889 } else { 00890 /* Extract the filename from the string copy, not from the columns 00891 * this way we have a chance of entering hidden directories like ". ." 00892 */ 00893 if (filename){ 00894 /* 00895 *filename = g_strdup (columns [idx++]); 00896 */ 00897 size_t tlen; 00898 char *t; 00899 00900 t = g_strdup (p_copy + column_ptr [idx]); idx++; 00901 tlen = strlen (t); 00902 /* g_strchomp(); */ 00903 if (t [tlen-1] == '\r' || t [tlen-1] == '\n') 00904 t [tlen-1] = '\0'; 00905 if (t [tlen-2] == '\r' || t [tlen-2] == '\n') 00906 t [tlen-2] = '\0'; 00907 00908 *filename = t; 00909 } 00910 if (linkname) 00911 *linkname = NULL; 00912 } 00913 g_free (p_copy); 00914 return 1; 00915 00916 error: 00917 #ifdef HACK 00918 { 00919 static int errorcount = 0; 00920 00921 if (++errorcount < 5) { 00922 message_1s (1, "Could not parse:", p_copy); 00923 } else if (errorcount == 5) 00924 message_1s (1, "More parsing errors will be ignored.", "(sorry)" ); 00925 } 00926 #endif 00927 00928 /*@-usereleased@*/ 00929 if (p_copy != p) /* Carefull! */ 00930 /*@=usereleased@*/ 00931 g_free (p_copy); 00932 return 0; 00933 } 00934 00935 typedef enum { 00936 DO_FTP_STAT = 1, 00937 DO_FTP_LSTAT = 2, 00938 DO_FTP_READLINK = 3, 00939 DO_FTP_ACCESS = 4, 00940 DO_FTP_GLOB = 5 00941 } ftpSysCall_t; 00942 00945 static size_t ftpBufAlloced; 00946 00949 /*@only@*/ /*@relnull@*/ 00950 static char * ftpBuf; 00951 00952 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) 00953 00954 static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall, 00955 /*@out@*/ /*@null@*/ struct stat * st, 00956 /*@out@*/ /*@null@*/ char * rlbuf, size_t rlbufsiz) 00957 /*@globals ftpBufAlloced, ftpBuf, 00958 h_errno, fileSystem, internalState @*/ 00959 /*@modifies *st, *rlbuf, ftpBufAlloced, ftpBuf, 00960 fileSystem, internalState @*/ 00961 { 00962 FD_t fd; 00963 const char * path; 00964 int bufLength, moretodo; 00965 const char *n, *ne, *o, *oe; 00966 char * s; 00967 char * se; 00968 const char * urldn; 00969 char * bn = NULL; 00970 size_t nbn = 0; 00971 urlinfo u; 00972 int rc; 00973 00974 n = ne = o = oe = NULL; 00975 (void) urlPath(url, &path); 00976 if (*path == '\0') 00977 return -2; 00978 00979 switch (ftpSysCall) { 00980 case DO_FTP_GLOB: 00981 fd = ftpOpen(url, 0, 0, &u); 00982 if (fd == NULL || u == NULL) 00983 return -1; 00984 00985 u->openError = ftpReq(fd, "LIST", path); 00986 break; 00987 default: 00988 urldn = alloca_strdup(url); 00989 if ((bn = strrchr(urldn, '/')) == NULL) 00990 return -2; 00991 else if (bn == path) 00992 bn = "."; 00993 else 00994 *bn++ = '\0'; 00995 nbn = strlen(bn); 00996 00997 rc = ftpChdir(urldn); /* XXX don't care about CWD */ 00998 if (rc < 0) 00999 return rc; 01000 01001 fd = ftpOpen(url, 0, 0, &u); 01002 if (fd == NULL || u == NULL) 01003 return -1; 01004 01005 /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */ 01006 u->openError = ftpReq(fd, "NLST", "-la"); 01007 01008 if (bn == NULL || nbn == 0) { 01009 rc = -2; 01010 goto exit; 01011 } 01012 break; 01013 } 01014 01015 if (u->openError < 0) { 01016 fd = fdLink(fd, "error data (ftpStat)"); 01017 rc = -2; 01018 goto exit; 01019 } 01020 01021 if (ftpBufAlloced == 0 || ftpBuf == NULL) { 01022 ftpBufAlloced = _url_iobuf_size; 01023 ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0])); 01024 } 01025 *ftpBuf = '\0'; 01026 01027 bufLength = 0; 01028 moretodo = 1; 01029 01030 do { 01031 01032 /* XXX FIXME: realloc ftpBuf if < ~128 chars remain */ 01033 if ((ftpBufAlloced - bufLength) < (1024+80)) { 01034 ftpBufAlloced <<= 2; 01035 assert(ftpBufAlloced < (8*1024*1024)); 01036 ftpBuf = xrealloc(ftpBuf, ftpBufAlloced); 01037 } 01038 s = se = ftpBuf + bufLength; 01039 *se = '\0'; 01040 01041 rc = fdFgets(fd, se, (ftpBufAlloced - bufLength)); 01042 if (rc <= 0) { 01043 moretodo = 0; 01044 break; 01045 } 01046 if (ftpSysCall == DO_FTP_GLOB) { /* XXX HACK */ 01047 bufLength += strlen(se); 01048 continue; 01049 } 01050 01051 for (s = se; *s != '\0'; s = se) { 01052 int bingo; 01053 01054 while (*se && *se != '\n') se++; 01055 if (se > s && se[-1] == '\r') se[-1] = '\0'; 01056 if (*se == '\0') 01057 /*@innerbreak@*/ break; 01058 *se++ = '\0'; 01059 01060 if (!strncmp(s, "total ", sizeof("total ")-1)) 01061 /*@innercontinue@*/ continue; 01062 01063 o = NULL; 01064 for (bingo = 0, n = se; n >= s; n--) { 01065 switch (*n) { 01066 case '\0': 01067 oe = ne = n; 01068 /*@switchbreak@*/ break; 01069 case ' ': 01070 if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) { 01071 while (*(++n) == ' ') 01072 {}; 01073 bingo++; 01074 /*@switchbreak@*/ break; 01075 } 01076 for (o = n + 1; *o == ' '; o++) 01077 {}; 01078 n -= 3; 01079 ne = n; 01080 /*@switchbreak@*/ break; 01081 default: 01082 /*@switchbreak@*/ break; 01083 } 01084 if (bingo) 01085 /*@innerbreak@*/ break; 01086 } 01087 01088 if (nbn != (size_t)(ne - n)) /* Same name length? */ 01089 /*@innercontinue@*/ continue; 01090 if (strncmp(n, bn, nbn)) /* Same name? */ 01091 /*@innercontinue@*/ continue; 01092 01093 moretodo = 0; 01094 /*@innerbreak@*/ break; 01095 } 01096 01097 if (moretodo && se > s) { 01098 bufLength = se - s - 1; 01099 if (s != ftpBuf) 01100 memmove(ftpBuf, s, bufLength); 01101 } else { 01102 bufLength = 0; 01103 } 01104 } while (moretodo); 01105 01106 switch (ftpSysCall) { 01107 case DO_FTP_STAT: 01108 if (o && oe) { 01109 /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */ 01110 } 01111 /*@fallthrough@*/ 01112 case DO_FTP_LSTAT: 01113 if (st == NULL || !(n && ne)) { 01114 rc = -1; 01115 } else { 01116 rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1); 01117 } 01118 break; 01119 case DO_FTP_READLINK: 01120 if (rlbuf == NULL || !(o && oe)) { 01121 rc = -1; 01122 } else { 01123 rc = oe - o; 01124 assert(rc >= 0); 01125 if (rc > (int)rlbufsiz) 01126 rc = (int)rlbufsiz; 01127 memcpy(rlbuf, o, (size_t)rc); 01128 if (rc < (int)rlbufsiz) 01129 rlbuf[rc] = '\0'; 01130 } 01131 break; 01132 case DO_FTP_ACCESS: 01133 rc = 0; /* XXX WRONG WRONG WRONG */ 01134 break; 01135 case DO_FTP_GLOB: 01136 rc = 0; /* XXX WRONG WRONG WRONG */ 01137 break; 01138 } 01139 01140 exit: 01141 (void) ufdClose(fd); 01142 return rc; 01143 } 01144 01145 static const char * statstr(const struct stat * st, 01146 /*@returned@*/ /*@out@*/ char * buf) 01147 /*@modifies *buf @*/ 01148 { 01149 char * t = buf; 01150 sprintf(t, "*** dev %x", (unsigned int)st->st_dev); 01151 t += strlen(t); 01152 sprintf(t, " ino %x", (unsigned int)st->st_ino); 01153 t += strlen(t); 01154 sprintf(t, " mode %0o", (unsigned int)st->st_mode); 01155 t += strlen(t); 01156 sprintf(t, " nlink %d", (unsigned int)st->st_nlink); 01157 t += strlen(t); 01158 sprintf(t, " uid %d", (unsigned int)st->st_uid); 01159 t += strlen(t); 01160 sprintf(t, " gid %d", (unsigned int)st->st_gid); 01161 t += strlen(t); 01162 sprintf(t, " rdev %x", (unsigned int)st->st_rdev); 01163 t += strlen(t); 01164 sprintf(t, " size %x", (unsigned int)st->st_size); 01165 t += strlen(t); 01166 sprintf(t, "\n"); 01167 return buf; 01168 } 01169 01170 /* FIXME: borked for path with trailing '/' */ 01171 static int ftpStat(const char * path, /*@out@*/ struct stat *st) 01172 /*@globals ftpBufAlloced, ftpBuf, h_errno, fileSystem, internalState @*/ 01173 /*@modifies ftpBufAlloced, ftpBuf, *st, fileSystem, internalState @*/ 01174 { 01175 char buf[1024]; 01176 int rc; 01177 rc = ftpNLST(path, DO_FTP_STAT, st, NULL, 0); 01178 01179 /* XXX fts(3) needs/uses st_ino. */ 01180 /* Hash the path to generate a st_ino analogue. */ 01181 if (st->st_ino == 0) 01182 st->st_ino = hashFunctionString(0, path, 0); 01183 01184 if (_ftp_debug) 01185 fprintf(stderr, "*** ftpStat(%s) rc %d\n%s", path, rc, statstr(st, buf)); 01186 return rc; 01187 } 01188 01189 /* FIXME: borked for path with trailing '/' */ 01190 static int ftpLstat(const char * path, /*@out@*/ struct stat *st) 01191 /*@globals ftpBufAlloced, ftpBuf, h_errno, fileSystem, internalState @*/ 01192 /*@modifies ftpBufAlloced, ftpBuf, *st, fileSystem, internalState @*/ 01193 { 01194 char buf[1024]; 01195 int rc; 01196 rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0); 01197 01198 /* XXX fts(3) needs/uses st_ino. */ 01199 /* Hash the path to generate a st_ino analogue. */ 01200 if (st->st_ino == 0) 01201 st->st_ino = hashFunctionString(0, path, 0); 01202 01203 if (_ftp_debug) 01204 fprintf(stderr, "*** ftpLstat(%s) rc %d\n%s\n", path, rc, statstr(st, buf)); 01205 return rc; 01206 } 01207 01208 static int ftpReadlink(const char * path, /*@out@*/ char * buf, size_t bufsiz) 01209 /*@globals ftpBufAlloced, ftpBuf, h_errno, fileSystem, internalState @*/ 01210 /*@modifies ftpBufAlloced, ftpBuf, *buf, fileSystem, internalState @*/ 01211 { 01212 int rc; 01213 rc = ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz); 01214 if (_ftp_debug) 01215 fprintf(stderr, "*** ftpReadlink(%s) rc %d\n", path, rc); 01216 return rc; 01217 } 01218 01219 /*@null@*/ 01220 static DIR * ftpOpendir(const char * path) 01221 /*@globals ftpBufAlloced, ftpBuf, h_errno, errno, 01222 fileSystem, internalState @*/ 01223 /*@modifies ftpBufAlloced, ftpBuf, errno, 01224 fileSystem, internalState @*/ 01225 { 01226 AVDIR avdir; 01227 avContext ctx; 01228 struct stat * st = NULL; 01229 const char * s, * sb, * se; 01230 int nac; 01231 int c; 01232 int rc; 01233 01234 if (_ftp_debug) 01235 fprintf(stderr, "*** ftpOpendir(%s)\n", path); 01236 01237 /* Load FTP collection into argv. */ 01238 ctx = avContextCreate(path, st); 01239 if (ctx == NULL) { 01240 errno = ENOENT; /* Note: ctx is NULL iff urlSplit() fails. */ 01241 return NULL; 01242 } 01243 01244 rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0); 01245 if (rc) 01246 return NULL; 01247 01248 nac = 0; 01249 sb = NULL; 01250 s = se = ftpBuf; 01251 while ((c = (int) *se++) != (int) '\0') { 01252 switch (c) { 01253 case '/': 01254 sb = se; 01255 /*@switchbreak@*/ break; 01256 case '\r': 01257 if (sb == NULL) { 01258 for (sb = se; sb > s && sb[-1] != ' '; sb--) 01259 {}; 01260 } 01261 nac++; 01262 01263 if (*se == '\n') se++; 01264 sb = NULL; 01265 s = se; 01266 /*@switchbreak@*/ break; 01267 default: 01268 /*@switchbreak@*/ break; 01269 } 01270 } 01271 01272 ctx->av = xcalloc(nac+1, sizeof(*ctx->av)); 01273 ctx->modes = xcalloc(nac, sizeof(*ctx->modes)); 01274 01275 nac = 0; 01276 sb = NULL; 01277 s = se = ftpBuf; 01278 while ((c = (int) *se) != (int) '\0') { 01279 se++; 01280 switch (c) { 01281 case '/': 01282 sb = se; 01283 /*@switchbreak@*/ break; 01284 case '\r': 01285 if (sb == NULL) { 01286 ctx->modes[nac] = (*s == 'd' ? 0755 : 0644); 01287 /*@-unrecog@*/ 01288 switch(*s) { 01289 case 'p': ctx->modes[nac] |= S_IFIFO; /*@innerbreak@*/ break; 01290 case 'c': ctx->modes[nac] |= S_IFCHR; /*@innerbreak@*/ break; 01291 case 'd': ctx->modes[nac] |= S_IFDIR; /*@innerbreak@*/ break; 01292 case 'b': ctx->modes[nac] |= S_IFBLK; /*@innerbreak@*/ break; 01293 case '-': ctx->modes[nac] |= S_IFREG; /*@innerbreak@*/ break; 01294 case 'l': ctx->modes[nac] |= S_IFLNK; /*@innerbreak@*/ break; 01295 case 's': ctx->modes[nac] |= S_IFSOCK; /*@innerbreak@*/ break; 01296 default: ctx->modes[nac] |= S_IFREG; /*@innerbreak@*/ break; 01297 } 01298 /*@=unrecog@*/ 01299 for (sb = se; sb > s && sb[-1] != ' '; sb--) 01300 {}; 01301 } 01302 ctx->av[nac++] = strncpy(xcalloc(1, (se-sb-1)+1), sb, (se-sb-1)); 01303 if (*se == '\n') se++; 01304 sb = NULL; 01305 s = se; 01306 /*@switchbreak@*/ break; 01307 default: 01308 /*@switchbreak@*/ break; 01309 } 01310 } 01311 01312 avdir = (AVDIR) avOpendir(path, ctx->av, ctx->modes); 01313 01314 ctx = avContextDestroy(ctx); 01315 01316 /*@-kepttrans@*/ 01317 return (DIR *) avdir; 01318 /*@=kepttrans@*/ 01319 } 01320 01321 static char * ftpRealpath(const char * path, /*@null@*/ char * resolved_path) 01322 /*@*/ 01323 { 01324 assert(resolved_path == NULL); /* XXX no POSIXly broken realpath(3) here. */ 01325 /* XXX TODO: handle redirects. For now, just dupe the path. */ 01326 return xstrdup(path); 01327 } 01328 01329 int Stat(const char * path, struct stat * st) 01330 /*@globals ftpBufAlloced, ftpBuf @*/ 01331 /*@modifies ftpBufAlloced, ftpBuf @*/ 01332 { 01333 const char * lpath; 01334 int ut = urlPath(path, &lpath); 01335 01336 if (_rpmio_debug) 01337 fprintf(stderr, "*** Stat(%s,%p)\n", path, st); 01338 switch (ut) { 01339 case URL_IS_FTP: 01340 return ftpStat(path, st); 01341 /*@notreached@*/ break; 01342 case URL_IS_HTTPS: 01343 case URL_IS_HTTP: 01344 #ifdef WITH_NEON 01345 return davStat(path, st); 01346 #endif 01347 /*@notreached@*/ break; 01348 case URL_IS_PATH: 01349 path = lpath; 01350 /*@fallthrough@*/ 01351 case URL_IS_UNKNOWN: 01352 break; 01353 case URL_IS_DASH: 01354 case URL_IS_HKP: 01355 default: 01356 errno = ENOENT; 01357 return -2; 01358 /*@notreached@*/ break; 01359 } 01360 return stat(path, st); 01361 } 01362 01363 int Lstat(const char * path, struct stat * st) 01364 /*@globals ftpBufAlloced, ftpBuf @*/ 01365 /*@modifies ftpBufAlloced, ftpBuf @*/ 01366 { 01367 const char * lpath; 01368 int ut = urlPath(path, &lpath); 01369 01370 if (_rpmio_debug) 01371 fprintf(stderr, "*** Lstat(%s,%p)\n", path, st); 01372 switch (ut) { 01373 case URL_IS_FTP: 01374 return ftpLstat(path, st); 01375 /*@notreached@*/ break; 01376 case URL_IS_HTTPS: 01377 case URL_IS_HTTP: 01378 #ifdef WITH_NEON 01379 return davLstat(path, st); 01380 #endif 01381 /*@notreached@*/ break; 01382 case URL_IS_PATH: 01383 path = lpath; 01384 /*@fallthrough@*/ 01385 case URL_IS_UNKNOWN: 01386 break; 01387 case URL_IS_DASH: 01388 case URL_IS_HKP: 01389 default: 01390 errno = ENOENT; 01391 return -2; 01392 /*@notreached@*/ break; 01393 } 01394 return lstat(path, st); 01395 } 01396 01397 int Fstat(FD_t fd, struct stat * st) 01398 { 01399 const char * path = fdGetOPath(fd); 01400 const char * lpath; 01401 int ut = urlPath(path, &lpath); 01402 01403 if (_rpmio_debug) 01404 fprintf(stderr, "*** Fstat(%p,%p) path %s\n", fd, st, path); 01405 if (fd == NULL || path == NULL || *path == '\0' || st == NULL) { 01406 errno = ENOENT; 01407 return -2; 01408 } 01409 01410 switch (ut) { 01411 case URL_IS_DASH: 01412 case URL_IS_PATH: 01413 case URL_IS_UNKNOWN: 01414 break; 01415 case URL_IS_FTP: 01416 case URL_IS_HTTPS: 01417 case URL_IS_HTTP: 01418 case URL_IS_HKP: 01419 if (fd->contentLength < 0) { 01420 errno = ENOENT; 01421 return -2; 01422 } 01423 memset(st, 0, sizeof(*st)); 01424 if (path[strlen(path)-1] == '/') { 01425 st->st_nlink = 2; 01426 st->st_mode = (S_IFDIR | 0755); 01427 } else { 01428 st->st_nlink = 1; 01429 st->st_mode = (S_IFREG | 0644); 01430 } 01431 st->st_ino = hashFunctionString(0, path, 0);; 01432 st->st_size = fd->contentLength; 01433 st->st_mtime = fd->lastModified; 01434 01435 st->st_atime = st->st_ctime = st->st_mtime; 01436 st->st_blksize = 4 * 1024; /* HACK correct for linux ext */ 01437 st->st_blocks = (st->st_size + 511)/512; 01438 break; 01439 default: 01440 errno = ENOENT; 01441 return -2; 01442 /*@notreached@*/ break; 01443 } 01444 return fstat(Fileno(fd), st); 01445 } 01446 01447 int Chown(const char * path, uid_t owner, gid_t group) 01448 { 01449 const char * lpath; 01450 int ut = urlPath(path, &lpath); 01451 01452 if (_rpmio_debug) 01453 fprintf(stderr, "*** Chown(%s,%u,%u)\n", path, (unsigned)owner, (unsigned)group); 01454 switch (ut) { 01455 case URL_IS_PATH: 01456 path = lpath; 01457 /*@fallthrough@*/ 01458 case URL_IS_UNKNOWN: 01459 break; 01460 case URL_IS_DASH: 01461 case URL_IS_HKP: 01462 case URL_IS_FTP: /* XXX TODO: implement. */ 01463 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01464 case URL_IS_HTTP: /* XXX TODO: implement. */ 01465 default: 01466 errno = EINVAL; /* XXX W2DO? */ 01467 return -2; 01468 /*@notreached@*/ break; 01469 } 01470 return chown(path, owner, group); 01471 } 01472 01473 int Fchown(FD_t fd, uid_t owner, gid_t group) 01474 { 01475 const char * path = fdGetOPath(fd); 01476 const char * lpath; 01477 int ut = urlPath(path, &lpath); 01478 01479 if (_rpmio_debug) 01480 fprintf(stderr, "*** Fchown(%p,%u,%u) path %s\n", fd, (unsigned)owner, (unsigned)group, path); 01481 switch (ut) { 01482 case URL_IS_PATH: 01483 path = lpath; 01484 /*@fallthrough@*/ 01485 case URL_IS_UNKNOWN: 01486 break; 01487 case URL_IS_DASH: 01488 case URL_IS_HKP: 01489 case URL_IS_FTP: /* XXX TODO: implement. */ 01490 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01491 case URL_IS_HTTP: /* XXX TODO: implement. */ 01492 default: 01493 errno = EINVAL; /* XXX W2DO? */ 01494 return -2; 01495 /*@notreached@*/ break; 01496 } 01497 return fchown(Fileno(fd), owner, group); 01498 } 01499 01500 int Lchown(const char * path, uid_t owner, gid_t group) 01501 { 01502 const char * lpath; 01503 int ut = urlPath(path, &lpath); 01504 01505 if (_rpmio_debug) 01506 fprintf(stderr, "*** Lchown(%s,%u,%u)\n", path, (unsigned)owner, (unsigned)group); 01507 switch (ut) { 01508 case URL_IS_PATH: 01509 path = lpath; 01510 /*@fallthrough@*/ 01511 case URL_IS_UNKNOWN: 01512 break; 01513 case URL_IS_DASH: 01514 case URL_IS_HKP: 01515 case URL_IS_FTP: /* XXX TODO: implement. */ 01516 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01517 case URL_IS_HTTP: /* XXX TODO: implement. */ 01518 default: 01519 errno = EINVAL; /* XXX W2DO? */ 01520 return -2; 01521 /*@notreached@*/ break; 01522 } 01523 return lchown(path, owner, group); 01524 } 01525 01526 int Chmod(const char * path, mode_t mode) 01527 { 01528 const char * lpath; 01529 int ut = urlPath(path, &lpath); 01530 01531 if (_rpmio_debug) 01532 fprintf(stderr, "*** Chmod(%s,%0o)\n", path, (int)mode); 01533 switch (ut) { 01534 case URL_IS_PATH: 01535 path = lpath; 01536 /*@fallthrough@*/ 01537 case URL_IS_UNKNOWN: 01538 break; 01539 case URL_IS_DASH: 01540 case URL_IS_HKP: 01541 case URL_IS_FTP: /* XXX TODO: implement. */ 01542 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01543 case URL_IS_HTTP: /* XXX TODO: implement. */ 01544 default: 01545 errno = EINVAL; /* XXX W2DO? */ 01546 return -2; 01547 /*@notreached@*/ break; 01548 } 01549 return chmod(path, mode); 01550 } 01551 01552 int Fchmod(FD_t fd, mode_t mode) 01553 { 01554 const char * path = fdGetOPath(fd); 01555 const char * lpath; 01556 int ut = urlPath(path, &lpath); 01557 01558 if (_rpmio_debug) 01559 fprintf(stderr, "*** Fchmod(%p,%0o) path %s\n", fd, (int)mode, path); 01560 switch (ut) { 01561 case URL_IS_PATH: 01562 path = lpath; 01563 /*@fallthrough@*/ 01564 case URL_IS_UNKNOWN: 01565 break; 01566 case URL_IS_DASH: 01567 case URL_IS_HKP: 01568 case URL_IS_FTP: /* XXX TODO: implement. */ 01569 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01570 case URL_IS_HTTP: /* XXX TODO: implement. */ 01571 default: 01572 errno = EINVAL; /* XXX W2DO? */ 01573 return -2; 01574 /*@notreached@*/ break; 01575 } 01576 return fchmod(Fileno(fd), mode); 01577 } 01578 01579 int Mkfifo(const char * path, mode_t mode) 01580 { 01581 const char * lpath; 01582 int ut = urlPath(path, &lpath); 01583 01584 if (_rpmio_debug) 01585 fprintf(stderr, "*** Mkfifo(%s,%0o)\n", path, (int)mode); 01586 switch (ut) { 01587 case URL_IS_PATH: 01588 path = lpath; 01589 /*@fallthrough@*/ 01590 case URL_IS_UNKNOWN: 01591 break; 01592 case URL_IS_DASH: 01593 case URL_IS_HKP: 01594 case URL_IS_FTP: /* XXX TODO: implement. */ 01595 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01596 case URL_IS_HTTP: /* XXX TODO: implement. */ 01597 default: 01598 errno = EINVAL; /* XXX W2DO? */ 01599 return -2; 01600 /*@notreached@*/ break; 01601 } 01602 return mkfifo(path, mode); 01603 } 01604 01605 int Mknod(const char * path, mode_t mode, dev_t dev) 01606 { 01607 const char * lpath; 01608 int ut = urlPath(path, &lpath); 01609 01610 if (_rpmio_debug) 01611 fprintf(stderr, "*** Mknod(%s,%0o, 0x%x)\n", path, (int)mode, (int)dev); 01612 switch (ut) { 01613 case URL_IS_PATH: 01614 path = lpath; 01615 /*@fallthrough@*/ 01616 case URL_IS_UNKNOWN: 01617 break; 01618 case URL_IS_DASH: 01619 case URL_IS_HKP: 01620 case URL_IS_FTP: /* XXX TODO: implement. */ 01621 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01622 case URL_IS_HTTP: /* XXX TODO: implement. */ 01623 default: 01624 errno = EINVAL; /* XXX W2DO? */ 01625 return -2; 01626 /*@notreached@*/ break; 01627 } 01628 /*@-portability@*/ 01629 return mknod(path, mode, dev); 01630 /*@=portability@*/ 01631 } 01632 01633 int Utime(const char * path, const struct utimbuf *buf) 01634 { 01635 const char * lpath; 01636 int ut = urlPath(path, &lpath); 01637 01638 if (_rpmio_debug) 01639 fprintf(stderr, "*** Utime(%s,%p)\n", path, buf); 01640 switch (ut) { 01641 case URL_IS_PATH: 01642 path = lpath; 01643 /*@fallthrough@*/ 01644 case URL_IS_UNKNOWN: 01645 break; 01646 case URL_IS_DASH: 01647 case URL_IS_HKP: 01648 case URL_IS_FTP: /* XXX TODO: implement. */ 01649 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01650 case URL_IS_HTTP: /* XXX TODO: implement. */ 01651 default: 01652 errno = EINVAL; /* XXX W2DO? */ 01653 return -2; 01654 /*@notreached@*/ break; 01655 } 01656 return utime(path, buf); 01657 } 01658 01659 /*@-fixedformalarray@*/ 01660 int Utimes(const char * path, const struct timeval times[2]) 01661 { 01662 const char * lpath; 01663 int ut = urlPath(path, &lpath); 01664 01665 if (_rpmio_debug) 01666 fprintf(stderr, "*** Utimes(%s,%p)\n", path, times); 01667 switch (ut) { 01668 case URL_IS_PATH: 01669 path = lpath; 01670 /*@fallthrough@*/ 01671 case URL_IS_UNKNOWN: 01672 break; 01673 case URL_IS_DASH: 01674 case URL_IS_HKP: 01675 case URL_IS_FTP: /* XXX TODO: implement. */ 01676 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01677 case URL_IS_HTTP: /* XXX TODO: implement. */ 01678 default: 01679 errno = EINVAL; /* XXX W2DO? */ 01680 return -2; 01681 /*@notreached@*/ break; 01682 } 01683 return utimes(path, times); 01684 } 01685 /*@=fixedformalarray@*/ 01686 01687 int Symlink(const char * oldpath, const char * newpath) 01688 { 01689 const char * opath; 01690 int out = urlPath(oldpath, &opath); 01691 const char * npath; 01692 int nut = urlPath(newpath, &npath); 01693 01694 nut = 0; /* XXX keep gcc quiet. */ 01695 if (_rpmio_debug) 01696 fprintf(stderr, "*** Symlink(%s,%s)\n", oldpath, newpath); 01697 switch (out) { 01698 case URL_IS_PATH: 01699 oldpath = opath; 01700 newpath = npath; 01701 /*@fallthrough@*/ 01702 case URL_IS_UNKNOWN: 01703 break; 01704 case URL_IS_DASH: 01705 case URL_IS_HKP: 01706 case URL_IS_FTP: /* XXX TODO: implement. */ 01707 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01708 case URL_IS_HTTP: /* XXX TODO: implement. */ 01709 default: 01710 errno = EINVAL; /* XXX W2DO? */ 01711 return -2; 01712 /*@notreached@*/ break; 01713 } 01714 return symlink(oldpath, newpath); 01715 } 01716 01717 int Readlink(const char * path, char * buf, size_t bufsiz) 01718 /*@globals ftpBufAlloced, ftpBuf @*/ 01719 /*@modifies ftpBufAlloced, ftpBuf @*/ 01720 { 01721 const char * lpath; 01722 int ut = urlPath(path, &lpath); 01723 01724 if (_rpmio_debug) 01725 fprintf(stderr, "*** Readlink(%s,%p[%u])\n", path, buf, (unsigned)bufsiz); 01726 switch (ut) { 01727 case URL_IS_FTP: 01728 return ftpReadlink(path, buf, bufsiz); 01729 /*@notreached@*/ break; 01730 case URL_IS_HTTPS: 01731 case URL_IS_HTTP: 01732 #ifdef NOTYET 01733 return davReadlink(path, buf, bufsiz); 01734 #else 01735 return -2; 01736 #endif 01737 /*@notreached@*/ break; 01738 case URL_IS_PATH: 01739 path = lpath; 01740 /*@fallthrough@*/ 01741 case URL_IS_UNKNOWN: 01742 break; 01743 case URL_IS_DASH: 01744 case URL_IS_HKP: 01745 default: 01746 errno = EINVAL; /* XXX W2DO? */ 01747 return -2; 01748 /*@notreached@*/ break; 01749 } 01750 /*@-compdef@*/ /* FIX: *buf is undefined */ 01751 return readlink(path, buf, bufsiz); 01752 /*@=compdef@*/ 01753 } 01754 01755 int Access(const char * path, int amode) 01756 { 01757 const char * lpath; 01758 int ut = urlPath(path, &lpath); 01759 01760 if (_rpmio_debug) 01761 fprintf(stderr, "*** Access(%s,%d)\n", path, amode); 01762 switch (ut) { 01763 case URL_IS_PATH: 01764 path = lpath; 01765 /*@fallthrough@*/ 01766 case URL_IS_UNKNOWN: 01767 break; 01768 case URL_IS_DASH: 01769 case URL_IS_HKP: 01770 case URL_IS_HTTPS: /* XXX TODO: implement. */ 01771 case URL_IS_HTTP: /* XXX TODO: implement. */ 01772 case URL_IS_FTP: /* XXX TODO: implement. */ 01773 default: 01774 errno = EINVAL; /* XXX W2DO? */ 01775 return -2; 01776 /*@notreached@*/ break; 01777 } 01778 return access(path, amode); 01779 } 01780 01781 /* glob_pattern_p() taken from bash 01782 * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc. 01783 * 01784 * Return nonzero if PATTERN has any special globbing chars in it. 01785 */ 01786 int Glob_pattern_p (const char * pattern, int quote) 01787 { 01788 const char *p; 01789 int ut = urlPath(pattern, &p); 01790 int open = 0; 01791 char c; 01792 01793 while ((c = *p++) != '\0') 01794 switch (c) { 01795 case '?': 01796 /* Don't treat '?' as a glob char in HTTP URL's */ 01797 if (ut == URL_IS_HTTPS || ut == URL_IS_HTTP || ut == URL_IS_HKP) 01798 continue; 01799 /*@fallthrough@*/ 01800 case '*': 01801 return (1); 01802 case '\\': 01803 if (quote && *p != '\0') 01804 p++; 01805 continue; 01806 01807 case '[': 01808 open = 1; 01809 continue; 01810 case ']': 01811 if (open) 01812 return (1); 01813 continue; 01814 01815 case '+': 01816 case '@': 01817 case '!': 01818 if (*p == '(') 01819 return (1); 01820 continue; 01821 } 01822 01823 return (0); 01824 } 01825 01826 int Glob_error(/*@unused@*/ const char * epath, 01827 /*@unused@*/ int eerrno) 01828 { 01829 return 1; 01830 } 01831 01832 int Glob(const char *pattern, int flags, 01833 int errfunc(const char * epath, int eerrno), void *_pglob) 01834 { 01835 glob_t *pglob = _pglob; 01836 const char * lpath; 01837 int ut = urlPath(pattern, &lpath); 01838 const char *home = getenv("HOME"); 01839 01840 /*@-castfcnptr@*/ 01841 if (_rpmio_debug) 01842 fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", pattern, (unsigned)flags, (void *)errfunc, pglob); 01843 /*@=castfcnptr@*/ 01844 switch (ut) { 01845 case URL_IS_HTTPS: 01846 case URL_IS_HTTP: 01847 case URL_IS_FTP: 01848 /*@-type@*/ 01849 pglob->gl_closedir = (void *) Closedir; 01850 pglob->gl_readdir = (void *) Readdir; 01851 pglob->gl_opendir = (void *) Opendir; 01852 pglob->gl_lstat = Lstat; 01853 pglob->gl_stat = Stat; 01854 /*@=type@*/ 01855 flags |= GLOB_ALTDIRFUNC; 01856 flags &= ~GLOB_TILDE; 01857 break; 01858 case URL_IS_PATH: 01859 pattern = lpath; 01860 /*@fallthrough@*/ 01861 case URL_IS_UNKNOWN: 01862 if (home && home[0]) 01863 flags |= GLOB_TILDE; 01864 else 01865 flags &= ~GLOB_TILDE; 01866 break; 01867 case URL_IS_DASH: 01868 case URL_IS_HKP: 01869 default: 01870 return -2; 01871 /*@notreached@*/ break; 01872 } 01873 return glob(pattern, flags, errfunc, pglob); 01874 } 01875 01876 void Globfree(void *_pglob) 01877 { 01878 glob_t *pglob = _pglob; 01879 if (_rpmio_debug) 01880 fprintf(stderr, "*** Globfree(%p)\n", pglob); 01881 globfree(pglob); 01882 } 01883 01884 DIR * Opendir(const char * path) 01885 /*@globals ftpBufAlloced, ftpBuf @*/ 01886 /*@modifies ftpBufAlloced, ftpBuf @*/ 01887 { 01888 const char * lpath; 01889 int ut = urlPath(path, &lpath); 01890 01891 if (_rpmio_debug) 01892 fprintf(stderr, "*** Opendir(%s)\n", path); 01893 switch (ut) { 01894 case URL_IS_FTP: 01895 return ftpOpendir(path); 01896 /*@notreached@*/ break; 01897 case URL_IS_HTTPS: 01898 case URL_IS_HTTP: 01899 #ifdef WITH_NEON 01900 return davOpendir(path); 01901 #endif 01902 /*@notreached@*/ break; 01903 case URL_IS_PATH: 01904 path = lpath; 01905 /*@fallthrough@*/ 01906 case URL_IS_UNKNOWN: 01907 break; 01908 case URL_IS_DASH: 01909 case URL_IS_HKP: 01910 default: 01911 return NULL; 01912 /*@notreached@*/ break; 01913 } 01914 /*@-dependenttrans@*/ 01915 return opendir(path); 01916 /*@=dependenttrans@*/ 01917 } 01918 01919 struct dirent * Readdir(DIR * dir) 01920 { 01921 if (_rpmio_debug) 01922 fprintf(stderr, "*** Readdir(%p)\n", (void *)dir); 01923 if (dir == NULL) 01924 return NULL; 01925 if (ISAVMAGIC(dir)) 01926 return avReaddir(dir); 01927 return readdir(dir); 01928 } 01929 01930 int Closedir(DIR * dir) 01931 { 01932 if (_rpmio_debug) 01933 fprintf(stderr, "*** Closedir(%p)\n", (void *)dir); 01934 if (dir == NULL) 01935 return 0; 01936 if (ISAVMAGIC(dir)) 01937 return avClosedir(dir); 01938 return closedir(dir); 01939 } 01940 01941 char * Realpath(const char * path, /*@null@*/ char * resolved_path) 01942 { 01943 const char * lpath; 01944 int ut = urlPath(path, &lpath); 01945 char * rpath = NULL; 01946 01947 if (_rpmio_debug) 01948 fprintf(stderr, "*** Realpath(%s, %s)\n", path, (resolved_path ? resolved_path : "NULL")); 01949 #if !defined(__LCLINT__) /* XXX LCL: realpath(3) annotations are buggy. */ 01950 /*@-nullpass@*/ 01951 /* XXX if POSIXly broken realpath(3) is desired, do that. */ 01952 /* XXX note: preserves current rpmlib realpath(3) usage cases. */ 01953 if (path == NULL || resolved_path != NULL) 01954 return realpath(path, resolved_path); 01955 /*@=nullpass@*/ 01956 #endif /* !__LCLINT__ */ 01957 01958 switch (ut) { 01959 case URL_IS_FTP: 01960 return ftpRealpath(path, resolved_path); 01961 /*@notreached@*/ break; 01962 case URL_IS_HTTPS: 01963 case URL_IS_HTTP: 01964 case URL_IS_HKP: 01965 #ifdef WITH_NEON 01966 return davRealpath(path, resolved_path); 01967 /*@notreached@*/ break; 01968 #endif 01969 /*@fallthrough@*/ 01970 default: 01971 return xstrdup(path); 01972 /*@notreached@*/ break; 01973 case URL_IS_DASH: 01974 /* non-GLIBC systems => EINVAL. non-linux systems => EINVAL */ 01975 #if defined(__linux__) 01976 lpath = "/dev/stdin"; 01977 #else 01978 lpath = NULL; 01979 #endif 01980 break; 01981 case URL_IS_PATH: /* XXX note: file:/// prefix is dropped. */ 01982 case URL_IS_UNKNOWN: 01983 path = lpath; 01984 break; 01985 } 01986 01987 #if !defined(__LCLINT__) /* XXX LCL: realpath(3) annotations are buggy. */ 01988 if (lpath == NULL || *lpath == '/') 01989 /*@-nullpass@*/ /* XXX glibc extension */ 01990 rpath = realpath(lpath, resolved_path); 01991 /*@=nullpass@*/ 01992 else { 01993 char * t; 01994 #if defined(__GLIBC__) 01995 char * dn = NULL; 01996 #else 01997 char dn[PATH_MAX]; 01998 dn[0] = '\0'; 01999 #endif 02000 /* 02001 * Using realpath on lpath isn't correct if the lpath is a symlink, 02002 * especially if the symlink is a dangling link. What we 02003 * do instead is use realpath() on `.' and then append lpath to 02004 * the result. 02005 */ 02006 if ((t = realpath(".", dn)) != NULL) { 02007 /*@-globs -mods@*/ /* XXX no rpmGlobalMacroContext mods please. */ 02008 rpath = (char *) rpmGetPath(t, "/", lpath, NULL); 02009 /* XXX preserve the pesky trailing '/' */ 02010 if (lpath[strlen(lpath)-1] == '/') { 02011 char * s = rpath; 02012 rpath = rpmExpand(s, "/", NULL); 02013 s = _free(s); 02014 } 02015 /*@=globs =mods@*/ 02016 } else 02017 rpath = NULL; 02018 #if defined(__GLIBC__) 02019 t = _free(t); 02020 #endif 02021 } 02022 #endif /* !__LCLINT__ */ 02023 02024 return rpath; 02025 } 02026 02027 off_t Lseek(int fdno, off_t offset, int whence) 02028 { 02029 if (_rpmio_debug) 02030 fprintf(stderr, "*** Lseek(%d,0x%lx,%d)\n", fdno, (long)offset, whence); 02031 return lseek(fdno, offset, whence); 02032 }