Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

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     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 }

Generated on Sat Oct 1 20:21:37 2011 for rpm by  doxygen 1.4.4