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

rpmio/rpmrpc.c

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

Generated on Sun Feb 2 23:32:06 2003 for rpm by doxygen1.2.18