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

Generated on Fri Aug 11 12:48:15 2006 for rpm by  doxygen 1.4.7