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

Generated on Fri Oct 12 08:44:55 2007 for rpm by  doxygen 1.5.2