Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

rpmio/rpmrpc.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include <rpmio_internal.h>
00007 #include <popt.h>
00008 #include "ugid.h"
00009 #include "debug.h"
00010 
00011 /*@access FD_t@*/
00012 /*@access urlinfo@*/
00013 
00014 extern int _rpmio_debug;
00015 
00016 /* =============================================================== */
00017 static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode) {
00018     int rc;
00019     if ((rc = ftpCmd("MKD", path, NULL)) != 0)
00020         return rc;
00021 #if NOTYET
00022     {   char buf[20];
00023         sprintf(buf, " 0%o", mode);
00024         (void) ftpCmd("SITE CHMOD", path, buf);
00025     }
00026 #endif
00027     return rc;
00028 }
00029 
00030 static int ftpChdir(const char * path) {
00031     return ftpCmd("CWD", path, NULL);
00032 }
00033 
00034 static int ftpRmdir(const char * path) {
00035     return ftpCmd("RMD", path, NULL);
00036 }
00037 
00038 static int ftpRename(const char * oldpath, const char * newpath) {
00039     int rc;
00040     if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0)
00041         return rc;
00042     return ftpCmd("RNTO", newpath, NULL);
00043 }
00044 
00045 static int ftpUnlink(const char * path) {
00046     return ftpCmd("DELE", path, NULL);
00047 }
00048 
00049 /* =============================================================== */
00050 /* XXX rebuilddb.c: analogues to mkdir(2)/rmdir(2). */
00051 int Mkdir (const char *path, mode_t mode) {
00052     const char * lpath;
00053     int ut = urlPath(path, &lpath);
00054 
00055     switch (ut) {
00056     case URL_IS_FTP:
00057         return ftpMkdir(path, mode);
00058         /*@notreached@*/ break;
00059     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00060     case URL_IS_PATH:
00061         path = lpath;
00062         /*@fallthrough@*/
00063     case URL_IS_UNKNOWN:
00064         break;
00065     case URL_IS_DASH:
00066     default:
00067         return -2;
00068         /*@notreached@*/ break;
00069     }
00070     return mkdir(path, mode);
00071 }
00072 
00073 int Chdir (const char *path) {
00074     const char * lpath;
00075     int ut = urlPath(path, &lpath);
00076 
00077     switch (ut) {
00078     case URL_IS_FTP:
00079         return ftpChdir(path);
00080         /*@notreached@*/ break;
00081     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00082     case URL_IS_PATH:
00083         path = lpath;
00084         /*@fallthrough@*/
00085     case URL_IS_UNKNOWN:
00086         break;
00087     case URL_IS_DASH:
00088     default:
00089         return -2;
00090         /*@notreached@*/ break;
00091     }
00092     return chdir(path);
00093 }
00094 
00095 int Rmdir (const char *path) {
00096     const char * lpath;
00097     int ut = urlPath(path, &lpath);
00098 
00099     switch (ut) {
00100     case URL_IS_FTP:
00101         return ftpRmdir(path);
00102         /*@notreached@*/ break;
00103     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00104     case URL_IS_PATH:
00105         path = lpath;
00106         /*@fallthrough@*/
00107     case URL_IS_UNKNOWN:
00108         break;
00109     case URL_IS_DASH:
00110     default:
00111         return -2;
00112         /*@notreached@*/ break;
00113     }
00114     return rmdir(path);
00115 }
00116 
00117 /* XXX rpmdb.c: analogue to rename(2). */
00118 
00119 int Rename (const char *oldpath, const char * newpath) {
00120     const char *oe = NULL;
00121     const char *ne = NULL;
00122     int oldut, newut;
00123 
00124     /* XXX lib/install.c used to rely on this behavior. */
00125     if (!strcmp(oldpath, newpath)) return 0;
00126 
00127     oldut = urlPath(oldpath, &oe);
00128     switch (oldut) {
00129     case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
00130     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00131     case URL_IS_PATH:
00132     case URL_IS_UNKNOWN:
00133         break;
00134     case URL_IS_DASH:
00135     default:
00136         return -2;
00137         /*@notreached@*/ break;
00138     }
00139 
00140     newut = urlPath(newpath, &ne);
00141     switch (newut) {
00142     case URL_IS_FTP:
00143 if (_rpmio_debug)
00144 fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
00145         if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
00146             !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
00147             return -2;
00148         return ftpRename(oldpath, newpath);
00149         /*@notreached@*/ break;
00150     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00151     case URL_IS_PATH:
00152         oldpath = oe;
00153         newpath = ne;
00154         break;
00155     case URL_IS_UNKNOWN:
00156         break;
00157     case URL_IS_DASH:
00158     default:
00159         return -2;
00160         /*@notreached@*/ break;
00161     }
00162     return rename(oldpath, newpath);
00163 }
00164 
00165 int Link (const char *oldpath, const char * newpath) {
00166     const char *oe = NULL;
00167     const char *ne = NULL;
00168     int oldut, newut;
00169 
00170     oldut = urlPath(oldpath, &oe);
00171     switch (oldut) {
00172     case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
00173     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00174     case URL_IS_PATH:
00175     case URL_IS_UNKNOWN:
00176         break;
00177     case URL_IS_DASH:
00178     default:
00179         return -2;
00180         /*@notreached@*/ break;
00181     }
00182 
00183     newut = urlPath(newpath, &ne);
00184     switch (newut) {
00185     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00186     case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
00187     case URL_IS_PATH:
00188 if (_rpmio_debug)
00189 fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
00190         if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
00191             !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
00192             return -2;
00193         oldpath = oe;
00194         newpath = ne;
00195         break;
00196     case URL_IS_UNKNOWN:
00197         break;
00198     case URL_IS_DASH:
00199     default:
00200         return -2;
00201         /*@notreached@*/ break;
00202     }
00203     return link(oldpath, newpath);
00204 }
00205 
00206 /* XXX build/build.c: analogue to unlink(2). */
00207 
00208 int Unlink(const char * path) {
00209     const char * lpath;
00210     int ut = urlPath(path, &lpath);
00211 
00212     switch (ut) {
00213     case URL_IS_FTP:
00214         return ftpUnlink(path);
00215         /*@notreached@*/ break;
00216     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00217     case URL_IS_PATH:
00218         path = lpath;
00219         /*@fallthrough@*/
00220     case URL_IS_UNKNOWN:
00221         break;
00222     case URL_IS_DASH:
00223     default:
00224         return -2;
00225         /*@notreached@*/ break;
00226     }
00227     return unlink(path);
00228 }
00229 
00230 /* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */
00231 
00232 #define g_strdup        xstrdup
00233 #define g_free          free
00234 
00235 /*
00236  * FIXME: this is broken. It depends on mc not crossing border on month!
00237  */
00238 static int current_mday;
00239 static int current_mon;
00240 static int current_year;
00241 
00242 /* Following stuff (parse_ls_lga) is used by ftpfs and extfs */
00243 #define MAXCOLS         30
00244 
00245 static char *columns [MAXCOLS]; /* Points to the string in column n */
00246 static int   column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */
00247 
00248 static int
00249 vfs_split_text (char *p)
00250 {
00251     char *original = p;
00252     int  numcols;
00253 
00254 
00255     for (numcols = 0; *p && numcols < MAXCOLS; numcols++){
00256         while (*p == ' ' || *p == '\r' || *p == '\n'){
00257             *p = 0;
00258             p++;
00259         }
00260         columns [numcols] = p;
00261         column_ptr [numcols] = p - original;
00262         while (*p && *p != ' ' && *p != '\r' && *p != '\n')
00263             p++;
00264     }
00265     return numcols;
00266 }
00267 
00268 static int
00269 is_num (int idx)
00270 {
00271     if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9')
00272         return 0;
00273     return 1;
00274 }
00275 
00276 static int
00277 is_dos_date(char *str)
00278 {
00279     if (strlen(str) == 8 && str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL)
00280         return (1);
00281 
00282     return (0);
00283 }
00284 
00285 static int
00286 is_week (char *str, struct tm *tim)
00287 {
00288     static char *week = "SunMonTueWedThuFriSat";
00289     char *pos;
00290 
00291     if((pos=strstr(week, str)) != NULL){
00292         if(tim != NULL)
00293             tim->tm_wday = (pos - week)/3;
00294         return (1);
00295     }
00296     return (0);    
00297 }
00298 
00299 static int
00300 is_month (char *str, struct tm *tim)
00301 {
00302     static char *month = "JanFebMarAprMayJunJulAugSepOctNovDec";
00303     char *pos;
00304     
00305     if((pos=strstr(month, str)) != NULL){
00306         if(tim != NULL)
00307             tim->tm_mon = (pos - month)/3;
00308         return (1);
00309     }
00310     return (0);
00311 }
00312 
00313 static int
00314 is_time (char *str, struct tm *tim)
00315 {
00316     char *p, *p2;
00317 
00318     if ((p=strchr(str, ':')) && (p2=strrchr(str, ':'))) {
00319         if (p != p2) {
00320             if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3)
00321                 return (0);
00322         }
00323         else {
00324             if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2)
00325                 return (0);
00326         }
00327     }
00328     else 
00329         return (0);
00330     
00331     return (1);
00332 }
00333 
00334 static int is_year(char *str, struct tm *tim)
00335 {
00336     long year;
00337 
00338     if (strchr(str,':'))
00339         return (0);
00340 
00341     if (strlen(str)!=4)
00342         return (0);
00343 
00344     if (sscanf(str, "%ld", &year) != 1)
00345         return (0);
00346 
00347     if (year < 1900 || year > 3000)
00348         return (0);
00349 
00350     tim->tm_year = (int) (year - 1900);
00351 
00352     return (1);
00353 }
00354 
00355 /*
00356  * FIXME: this is broken. Consider following entry:
00357  * -rwx------   1 root     root            1 Aug 31 10:04 2904 1234
00358  * where "2904 1234" is filename. Well, this code decodes it as year :-(.
00359  */
00360 
00361 static int
00362 vfs_parse_filetype (char c)
00363 {
00364     switch (c){
00365         case 'd': return S_IFDIR; 
00366         case 'b': return S_IFBLK;
00367         case 'c': return S_IFCHR;
00368         case 'l': return S_IFLNK;
00369         case 's':
00370 #ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */
00371                   return S_IFSOCK;
00372 #endif
00373         case 'p': return S_IFIFO;
00374         case 'm': case 'n':             /* Don't know what these are :-) */
00375         case '-': case '?': return S_IFREG;
00376         default: return -1;
00377     }
00378 }
00379 
00380 static int vfs_parse_filemode (char *p)
00381 {       /* converts rw-rw-rw- into 0666 */
00382     int res = 0;
00383     switch (*(p++)){
00384         case 'r': res |= 0400; break;
00385         case '-': break;
00386         default: return -1;
00387     }
00388     switch (*(p++)){
00389         case 'w': res |= 0200; break;
00390         case '-': break;
00391         default: return -1;
00392     }
00393     switch (*(p++)){
00394         case 'x': res |= 0100; break;
00395         case 's': res |= 0100 | S_ISUID; break;
00396         case 'S': res |= S_ISUID; break;
00397         case '-': break;
00398         default: return -1;
00399     }
00400     switch (*(p++)){
00401         case 'r': res |= 0040; break;
00402         case '-': break;
00403         default: return -1;
00404     }
00405     switch (*(p++)){
00406         case 'w': res |= 0020; break;
00407         case '-': break;
00408         default: return -1;
00409     }
00410     switch (*(p++)){
00411         case 'x': res |= 0010; break;
00412         case 's': res |= 0010 | S_ISGID; break;
00413         case 'l': /* Solaris produces these */
00414         case 'S': res |= S_ISGID; break;
00415         case '-': break;
00416         default: return -1;
00417     }
00418     switch (*(p++)){
00419         case 'r': res |= 0004; break;
00420         case '-': break;
00421         default: return -1;
00422     }
00423     switch (*(p++)){
00424         case 'w': res |= 0002; break;
00425         case '-': break;
00426         default: return -1;
00427     }
00428     switch (*(p++)){
00429         case 'x': res |= 0001; break;
00430         case 't': res |= 0001 | S_ISVTX; break;
00431         case 'T': res |= S_ISVTX; break;
00432         case '-': break;
00433         default: return -1;
00434     }
00435     return res;
00436 }
00437 
00438 static int vfs_parse_filedate(int idx, time_t *t)
00439 {       /* This thing parses from idx in columns[] array */
00440 
00441     char *p;
00442     struct tm tim;
00443     int d[3];
00444     int got_year = 0;
00445 
00446     /* Let's setup default time values */
00447     tim.tm_year = current_year;
00448     tim.tm_mon  = current_mon;
00449     tim.tm_mday = current_mday;
00450     tim.tm_hour = 0;
00451     tim.tm_min  = 0;
00452     tim.tm_sec  = 0;
00453     tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */
00454     
00455     p = columns [idx++];
00456     
00457     /* We eat weekday name in case of extfs */
00458     if(is_week(p, &tim))
00459         p = columns [idx++];
00460 
00461     /* Month name */
00462     if(is_month(p, &tim)){
00463         /* And we expect, it followed by day number */
00464         if (is_num (idx))
00465             tim.tm_mday = (int)atol (columns [idx++]);
00466         else
00467             return 0; /* No day */
00468 
00469     } else {
00470         /* We usually expect:
00471            Mon DD hh:mm
00472            Mon DD  YYYY
00473            But in case of extfs we allow these date formats:
00474            Mon DD YYYY hh:mm
00475            Mon DD hh:mm YYYY
00476            Wek Mon DD hh:mm:ss YYYY
00477            MM-DD-YY hh:mm
00478            where Mon is Jan-Dec, DD, MM, YY two digit day, month, year,
00479            YYYY four digit year, hh, mm, ss two digit hour, minute or second. */
00480 
00481         /* Here just this special case with MM-DD-YY */
00482         if (is_dos_date(p)){
00483             p[2] = p[5] = '-';
00484             
00485             if(sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){
00486             /*  We expect to get:
00487                 1. MM-DD-YY
00488                 2. DD-MM-YY
00489                 3. YY-MM-DD
00490                 4. YY-DD-MM  */
00491                 
00492                 /* Hmm... maybe, next time :)*/
00493                 
00494                 /* At last, MM-DD-YY */
00495                 d[0]--; /* Months are zerobased */
00496                 /* Y2K madness */
00497                 if(d[2] < 70)
00498                     d[2] += 100;
00499 
00500                 tim.tm_mon  = d[0];
00501                 tim.tm_mday = d[1];
00502                 tim.tm_year = d[2];
00503                 got_year = 1;
00504             } else
00505                 return 0; /* sscanf failed */
00506         } else
00507             return 0; /* unsupported format */
00508     }
00509 
00510     /* Here we expect to find time and/or year */
00511     
00512     if (is_num (idx)) {
00513         if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) {
00514         idx++;
00515 
00516         /* This is a special case for ctime() or Mon DD YYYY hh:mm */
00517         if(is_num (idx) && 
00518             ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
00519                 idx++; /* time & year or reverse */
00520         } /* only time or date */
00521     }
00522     else 
00523         return 0; /* Nor time or date */
00524 
00525     /*
00526      * If the date is less than 6 months in the past, it is shown without year
00527      * other dates in the past or future are shown with year but without time
00528      * This does not check for years before 1900 ... I don't know, how
00529      * to represent them at all
00530      */
00531     if (!got_year &&
00532         current_mon < 6 && current_mon < tim.tm_mon && 
00533         tim.tm_mon - current_mon >= 6)
00534 
00535         tim.tm_year--;
00536 
00537     if ((*t = mktime(&tim)) < 0)
00538         *t = 0;
00539     return idx;
00540 }
00541 
00542 static int
00543 vfs_parse_ls_lga (char *p, struct stat *st, char **filename, char **linkname)
00544 {
00545     int idx, idx2, num_cols;
00546     int i;
00547     char *p_copy;
00548     
00549     if (strncmp (p, "total", 5) == 0)
00550         return 0;
00551 
00552     p_copy = g_strdup(p);
00553 /* XXX FIXME: parse out inode number from "NLST -lai ." */
00554 /* XXX FIXME: parse out sizein blocks from "NLST -lais ." */
00555 
00556     if ((i = vfs_parse_filetype(*(p++))) == -1)
00557         goto error;
00558 
00559     st->st_mode = i;
00560     if (*p == ' ')      /* Notwell 4 */
00561         p++;
00562     if (*p == '['){
00563         if (strlen (p) <= 8 || p [8] != ']')
00564             goto error;
00565         /* Should parse here the Notwell permissions :) */
00566         if (S_ISDIR (st->st_mode))
00567             st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH);
00568         else
00569             st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
00570         p += 9;
00571     } else {
00572         if ((i = vfs_parse_filemode(p)) == -1)
00573             goto error;
00574         st->st_mode |= i;
00575         p += 9;
00576 
00577         /* This is for an extra ACL attribute (HP-UX) */
00578         if (*p == '+')
00579             p++;
00580     }
00581 
00582     g_free(p_copy);
00583     p_copy = g_strdup(p);
00584     num_cols = vfs_split_text (p);
00585 
00586     st->st_nlink = atol (columns [0]);
00587     if (st->st_nlink < 0)
00588         goto error;
00589 
00590     if (!is_num (1))
00591 #ifdef  HACK
00592         st->st_uid = finduid (columns [1]);
00593 #else
00594         unameToUid (columns [1], &st->st_uid);
00595 #endif
00596     else
00597         st->st_uid = (uid_t) atol (columns [1]);
00598 
00599     /* Mhm, the ls -lg did not produce a group field */
00600     for (idx = 3; idx <= 5; idx++) 
00601         if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx]))
00602             break;
00603 
00604     if (idx == 6 || (idx == 5 && !S_ISCHR (st->st_mode) && !S_ISBLK (st->st_mode)))
00605         goto error;
00606 
00607     /* We don't have gid */     
00608     if (idx == 3 || (idx == 4 && (S_ISCHR(st->st_mode) || S_ISBLK (st->st_mode))))
00609         idx2 = 2;
00610     else { 
00611         /* We have gid field */
00612         if (is_num (2))
00613             st->st_gid = (gid_t) atol (columns [2]);
00614         else
00615 #ifdef  HACK
00616             st->st_gid = findgid (columns [2]);
00617 #else
00618             gnameToGid (columns [1], &st->st_gid);
00619 #endif
00620         idx2 = 3;
00621     }
00622 
00623     /* This is device */
00624     if (S_ISCHR (st->st_mode) || S_ISBLK (st->st_mode)){
00625         int maj, min;
00626         
00627         if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1)
00628             goto error;
00629         
00630         if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1)
00631             goto error;
00632         
00633 #ifdef HAVE_ST_RDEV
00634         st->st_rdev = ((maj & 0xff) << 8) | (min & 0xffff00ff);
00635 #endif
00636         st->st_size = 0;
00637         
00638     } else {
00639         /* Common file size */
00640         if (!is_num (idx2))
00641             goto error;
00642         
00643         st->st_size = (size_t) atol (columns [idx2]);
00644 #ifdef HAVE_ST_RDEV
00645         st->st_rdev = 0;
00646 #endif
00647     }
00648 
00649     idx = vfs_parse_filedate(idx, &st->st_mtime);
00650     if (!idx)
00651         goto error;
00652     /* Use resulting time value */
00653     st->st_atime = st->st_ctime = st->st_mtime;
00654     st->st_dev = 0;
00655     st->st_ino = 0;
00656 #ifdef HAVE_ST_BLKSIZE
00657     st->st_blksize = 512;
00658 #endif
00659 #ifdef HAVE_ST_BLOCKS
00660     st->st_blocks = (st->st_size + 511) / 512;
00661 #endif
00662 
00663     for (i = idx + 1, idx2 = 0; i < num_cols; i++ ) 
00664         if (strcmp (columns [i], "->") == 0){
00665             idx2 = i;
00666             break;
00667         }
00668     
00669     if (((S_ISLNK (st->st_mode) || 
00670         (num_cols == idx + 3 && st->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */
00671         && idx2){
00672         int tlen;
00673         char *t;
00674             
00675         if (filename){
00676 #ifdef HACK
00677             t = g_strndup (p_copy + column_ptr [idx], column_ptr [idx2] - column_ptr [idx] - 1);
00678 #else
00679             int nb = column_ptr [idx2] - column_ptr [idx] - 1;
00680             t = xmalloc(nb+1);
00681             strncpy(t, p_copy + column_ptr [idx], nb);
00682 #endif
00683             *filename = t;
00684         }
00685         if (linkname){
00686             t = g_strdup (p_copy + column_ptr [idx2+1]);
00687             tlen = strlen (t);
00688             if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
00689                 t [tlen-1] = 0;
00690             if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
00691                 t [tlen-2] = 0;
00692                 
00693             *linkname = t;
00694         }
00695     } else {
00696         /* Extract the filename from the string copy, not from the columns
00697          * this way we have a chance of entering hidden directories like ". ."
00698          */
00699         if (filename){
00700             /* 
00701             *filename = g_strdup (columns [idx++]);
00702             */
00703             int tlen;
00704             char *t;
00705             
00706             t = g_strdup (p_copy + column_ptr [idx++]);
00707             tlen = strlen (t);
00708             /* g_strchomp(); */
00709             if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
00710                 t [tlen-1] = 0;
00711             if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
00712                 t [tlen-2] = 0;
00713             
00714             *filename = t;
00715         }
00716         if (linkname)
00717             *linkname = NULL;
00718     }
00719     g_free (p_copy);
00720     return 1;
00721 
00722 error:
00723 #ifdef  HACK
00724     {
00725       static int errorcount = 0;
00726 
00727       if (++errorcount < 5) {
00728         message_1s (1, "Could not parse:", p_copy);
00729       } else if (errorcount == 5)
00730         message_1s (1, "More parsing errors will be ignored.", "(sorry)" );
00731     }
00732 #endif
00733 
00734     if (p_copy != p)            /* Carefull! */
00735         g_free (p_copy);
00736     return 0;
00737 }
00738 
00739 typedef enum {
00740         DO_FTP_STAT     = 1,
00741         DO_FTP_LSTAT    = 2,
00742         DO_FTP_READLINK = 3,
00743         DO_FTP_ACCESS   = 4,
00744         DO_FTP_GLOB     = 5
00745 } ftpSysCall_t;
00746 static size_t ftpBufAlloced = 0;
00747 static /*@only@*/ char * ftpBuf = NULL;
00748         
00749 #define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
00750 
00751 static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall,
00752         struct stat * st, char * rlbuf, size_t rlbufsiz)
00753 {
00754     FD_t fd;
00755     const char * path;
00756     int bufLength, moretodo;
00757     const char *n, *ne, *o, *oe;
00758     char * s;
00759     char * se;
00760     const char * urldn;
00761     char * bn = NULL;
00762     int nbn = 0;
00763     urlinfo u;
00764     int rc;
00765 
00766     n = ne = o = oe = NULL;
00767     (void) urlPath(url, &path);
00768     if (*path == '\0')
00769         return -2;
00770 
00771     switch (ftpSysCall) {
00772     case DO_FTP_GLOB:
00773         fd = ftpOpen(url, 0, 0, &u);
00774         if (fd == NULL || u == NULL)
00775             return -1;
00776 
00777         u->openError = ftpReq(fd, "NLST", path);
00778         break;
00779     default:
00780         urldn = alloca_strdup(url);
00781         if ((bn = strrchr(urldn, '/')) == NULL)
00782             return -2;
00783         else if (bn == path)
00784             bn = ".";
00785         else
00786             *bn++ = '\0';
00787         nbn = strlen(bn);
00788 
00789         rc = ftpChdir(urldn);           /* XXX don't care about CWD */
00790         if (rc < 0)
00791             return rc;
00792 
00793         fd = ftpOpen(url, 0, 0, &u);
00794         if (fd == NULL || u == NULL)
00795             return -1;
00796 
00797         /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */
00798         u->openError = ftpReq(fd, "NLST", "-la");
00799         break;
00800     }
00801 
00802     if (u->openError < 0) {
00803         fd = fdLink(fd, "error data (ftpStat)");
00804         rc = -2;
00805         goto exit;
00806     }
00807 
00808     if (ftpBufAlloced == 0 || ftpBuf == NULL) {
00809         ftpBufAlloced = url_iobuf_size;
00810         ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0]));
00811     }
00812     *ftpBuf = '\0';
00813 
00814     bufLength = 0;
00815     moretodo = 1;
00816 
00817     do {
00818 
00819         /* XXX FIXME: realloc ftpBuf is < ~128 chars remain */
00820         if ((ftpBufAlloced - bufLength) < (1024+80)) {
00821             ftpBufAlloced <<= 2;
00822             ftpBuf = xrealloc(ftpBuf, ftpBufAlloced);
00823         }
00824         s = se = ftpBuf + bufLength;
00825         *se = '\0';
00826 
00827         rc = fdFgets(fd, se, (ftpBufAlloced - bufLength));
00828         if (rc <= 0) {
00829             moretodo = 0;
00830             break;
00831         }
00832         if (ftpSysCall == DO_FTP_GLOB) {        /* XXX HACK */
00833             bufLength += strlen(se);
00834             continue;
00835         }
00836 
00837         for (s = se; *s != '\0'; s = se) {
00838             int bingo;
00839 
00840             while (*se && *se != '\n') se++;
00841             if (se > s && se[-1] == '\r') se[-1] = '\0';
00842             if (*se == '\0') break;
00843             *se++ = '\0';
00844 
00845             if (!strncmp(s, "total ", sizeof("total ")-1)) continue;
00846 
00847             o = NULL;
00848             for (bingo = 0, n = se; n >= s; n--) {
00849                 switch (*n) {
00850                 case '\0':
00851                     oe = ne = n;
00852                     break;
00853                 case ' ':
00854                     if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) {
00855                         while (*(++n) == ' ');
00856                         bingo++;
00857                         break;
00858                     }
00859                     for (o = n + 1; *o == ' '; o++);
00860                     n -= 3;
00861                     ne = n;
00862                     break;
00863                 default:
00864                     break;
00865                 }
00866                 if (bingo) break;
00867             }
00868 
00869             if (nbn != (ne - n))        continue;       /* Same name length? */
00870             if (strncmp(n, bn, nbn))    continue;       /* Same name? */
00871 
00872             moretodo = 0;
00873             break;
00874         }
00875 
00876         if (moretodo && se > s) {
00877             bufLength = se - s - 1;
00878             if (s != ftpBuf)
00879                 memmove(ftpBuf, s, bufLength);
00880         } else {
00881             bufLength = 0;
00882         }
00883     } while (moretodo);
00884 
00885     switch (ftpSysCall) {
00886     case DO_FTP_STAT:
00887         if (o && oe) {
00888             /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */
00889         }
00890         /*@fallthrough@*/
00891     case DO_FTP_LSTAT:
00892         if (st == NULL || !(n && ne)) {
00893             rc = -1;
00894         } else {
00895             rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1);
00896         }
00897         break;
00898     case DO_FTP_READLINK:
00899         if (rlbuf == NULL || !(o && oe)) {
00900             rc = -1;
00901         } else {
00902             rc = oe - o;
00903             if (rc > rlbufsiz)
00904                 rc = rlbufsiz;
00905             memcpy(rlbuf, o, rc);
00906             if (rc < rlbufsiz)
00907                 rlbuf[rc] = '\0';
00908         }
00909         break;
00910     case DO_FTP_ACCESS:
00911         rc = 0;         /* XXX WRONG WRONG WRONG */
00912         break;
00913     case DO_FTP_GLOB:
00914         rc = 0;         /* XXX WRONG WRONG WRONG */
00915         break;
00916     }
00917 
00918 exit:
00919     ufdClose(fd);
00920     return rc;
00921 }
00922 
00923 static int ftpStat(const char * path, struct stat *st)
00924 {
00925     return ftpNLST(path, DO_FTP_STAT, st, NULL, 0);
00926 }
00927 
00928 static int ftpLstat(const char * path, struct stat *st) {
00929     int rc;
00930     rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0);
00931 if (_rpmio_debug)
00932 fprintf(stderr, "*** ftpLstat(%s) rc %d\n", path, rc);
00933     return rc;
00934 }
00935 
00936 static int ftpReadlink(const char * path, char * buf, size_t bufsiz) {
00937     return ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz);
00938 }
00939 
00940 static int ftpGlob(const char * path, int flags,
00941                 int errfunc(const char * epath, int eerno), glob_t * pglob)
00942 {
00943     int rc;
00944 
00945     if (pglob == NULL)
00946         return -2;
00947     rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0);
00948 if (_rpmio_debug)
00949 fprintf(stderr, "*** ftpGlob(%s,0x%x,%p,%p) ftpNLST rc %d\n", path, (unsigned)flags, errfunc, pglob, rc);
00950     if (rc)
00951         return rc;
00952     rc = poptParseArgvString(ftpBuf, &pglob->gl_pathc, (const char ***)&pglob->gl_pathv);
00953     pglob->gl_offs = -1;        /* XXX HACK HACK HACK */
00954     return rc;
00955 }
00956 
00957 static void ftpGlobfree(glob_t * pglob) {
00958 if (_rpmio_debug)
00959 fprintf(stderr, "*** ftpGlobfree(%p)\n", pglob);
00960     if (pglob->gl_offs == -1)   /* XXX HACK HACK HACK */
00961         free((void *)pglob->gl_pathv);
00962 }
00963 
00964 int Stat(const char * path, struct stat * st) {
00965     const char * lpath;
00966     int ut = urlPath(path, &lpath);
00967 
00968 if (_rpmio_debug)
00969 fprintf(stderr, "*** Stat(%s,%p)\n", path, st);
00970     switch (ut) {
00971     case URL_IS_FTP:
00972         return ftpStat(path, st);
00973         /*@notreached@*/ break;
00974     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00975     case URL_IS_PATH:
00976         path = lpath;
00977         /*@fallthrough@*/
00978     case URL_IS_UNKNOWN:
00979         break;
00980     case URL_IS_DASH:
00981     default:
00982         return -2;
00983         /*@notreached@*/ break;
00984     }
00985     return stat(path, st);
00986 }
00987 
00988 int Lstat(const char * path, struct stat * st) {
00989     const char * lpath;
00990     int ut = urlPath(path, &lpath);
00991 
00992 if (_rpmio_debug)
00993 fprintf(stderr, "*** Lstat(%s,%p)\n", path, st);
00994     switch (ut) {
00995     case URL_IS_FTP:
00996         return ftpLstat(path, st);
00997         /*@notreached@*/ break;
00998     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
00999     case URL_IS_PATH:
01000         path = lpath;
01001         /*@fallthrough@*/
01002     case URL_IS_UNKNOWN:
01003         break;
01004     case URL_IS_DASH:
01005     default:
01006         return -2;
01007         /*@notreached@*/ break;
01008     }
01009     return lstat(path, st);
01010 }
01011 
01012 int Readlink(const char * path, char * buf, size_t bufsiz) {
01013     const char * lpath;
01014     int ut = urlPath(path, &lpath);
01015 
01016     switch (ut) {
01017     case URL_IS_FTP:
01018         return ftpReadlink(path, buf, bufsiz);
01019         /*@notreached@*/ break;
01020     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
01021     case URL_IS_PATH:
01022         path = lpath;
01023         /*@fallthrough@*/
01024     case URL_IS_UNKNOWN:
01025         break;
01026     case URL_IS_DASH:
01027     default:
01028         return -2;
01029         /*@notreached@*/ break;
01030     }
01031     return readlink(path, buf, bufsiz);
01032 }
01033 
01034 int Access(const char * path, int amode) {
01035     const char * lpath;
01036     int ut = urlPath(path, &lpath);
01037 
01038 if (_rpmio_debug)
01039 fprintf(stderr, "*** Access(%s,%d)\n", path, amode);
01040     switch (ut) {
01041     case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
01042     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
01043     case URL_IS_PATH:
01044         path = lpath;
01045         /*@fallthrough@*/
01046     case URL_IS_UNKNOWN:
01047         break;
01048     case URL_IS_DASH:
01049     default:
01050         return -2;
01051         /*@notreached@*/ break;
01052     }
01053     return access(path, amode);
01054 }
01055 
01056 int Glob(const char *path, int flags,
01057         int errfunc(const char * epath, int eerrno), glob_t *pglob)
01058 {
01059     const char * lpath;
01060     int ut = urlPath(path, &lpath);
01061 
01062 if (_rpmio_debug)
01063 fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", path, (unsigned)flags, errfunc, pglob);
01064     switch (ut) {
01065     case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
01066         return ftpGlob(path, flags, errfunc, pglob);
01067         /*@notreached@*/ break;
01068     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
01069     case URL_IS_PATH:
01070         path = lpath;
01071         /*@fallthrough@*/
01072     case URL_IS_UNKNOWN:
01073         break;
01074     case URL_IS_DASH:
01075     default:
01076         return -2;
01077         /*@notreached@*/ break;
01078     }
01079     return glob(path, flags, errfunc, pglob);
01080 }
01081 
01082 void Globfree(glob_t *pglob)
01083 {
01084 if (_rpmio_debug)
01085 fprintf(stderr, "*** Globfree(%p)\n", pglob);
01086     if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */
01087         ftpGlobfree(pglob);
01088     else
01089         globfree(pglob);
01090 }
01091 
01092 DIR * Opendir(const char * path)
01093 {
01094     const char * lpath;
01095     int ut = urlPath(path, &lpath);
01096 
01097 if (_rpmio_debug)
01098 fprintf(stderr, "*** Opendir(%s)\n", path);
01099     switch (ut) {
01100     case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
01101     case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
01102     case URL_IS_PATH:
01103         path = lpath;
01104         /*@fallthrough@*/
01105     case URL_IS_UNKNOWN:
01106         break;
01107     case URL_IS_DASH:
01108     default:
01109         return NULL;
01110         /*@notreached@*/ break;
01111     }
01112     return opendir(path);
01113 }
01114 
01115 struct dirent * Readdir(DIR * dir)
01116 {
01117 if (_rpmio_debug)
01118 fprintf(stderr, "*** Readdir(%p)\n", dir);
01119     return readdir(dir);
01120 }
01121 
01122 int Closedir(DIR * dir)
01123 {
01124 if (_rpmio_debug)
01125 fprintf(stderr, "*** Closedir(%p)\n", dir);
01126     return closedir(dir);
01127 }

Generated at Sun Apr 8 18:43:02 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000