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

Generated on Mon Aug 3 15:25:07 2009 for rpm by  doxygen 1.4.4