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