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