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