rpmio/rpmrpc.c

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

Generated on Fri Sep 7 01:07:26 2007 for rpm by  doxygen 1.5.1