rpmio/rpmrpc.c

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

Generated on Fri Aug 31 11:02:23 2007 for rpm by  doxygen 1.5.1