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

rpmio/rpmrpc.c

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

Generated at Thu Sep 6 11:25:44 2001 for rpm by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001