• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

rpmio/rpmrpc.c

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

Generated on Mon Nov 29 2010 05:18:48 for rpm by  doxygen 1.7.2