rpmio/rpmrpc.c

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

Generated on Wed Oct 29 02:19:52 2008 for rpm by  doxygen 1.5.1