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
00020
00021
00022
00028 static inline void *
00029 _free( const void * p)
00030
00031 {
00032 if (p != NULL) free((void *)p);
00033 return NULL;
00034 }
00035
00036
00037 static int ftpMkdir(const char * path, mode_t mode)
00038
00039
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
00055
00056 {
00057 return ftpCmd("CWD", path, NULL);
00058 }
00059
00060 static int ftpRmdir(const char * path)
00061
00062
00063 {
00064 return ftpCmd("RMD", path, NULL);
00065 }
00066
00067 static int ftpRename(const char * oldpath, const char * newpath)
00068
00069
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
00079
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 break;
00094 case URL_IS_PATH:
00095 path = lpath;
00096
00097 case URL_IS_UNKNOWN:
00098 break;
00099 case URL_IS_DASH:
00100 case URL_IS_HKP:
00101 default:
00102 return -2;
00103 break;
00104 }
00105 return mkdir(path, mode);
00106 }
00107
00108 int Chdir (const char * path)
00109 {
00110 const char * lpath;
00111 int ut = urlPath(path, &lpath);
00112
00113 switch (ut) {
00114 case URL_IS_FTP:
00115 return ftpChdir(path);
00116 break;
00117 case URL_IS_PATH:
00118 path = lpath;
00119
00120 case URL_IS_UNKNOWN:
00121 break;
00122 case URL_IS_DASH:
00123 case URL_IS_HKP:
00124 default:
00125 errno = EINVAL;
00126 return -2;
00127 break;
00128 }
00129 return chdir(path);
00130 }
00131
00132 int Rmdir (const char * path)
00133 {
00134 const char * lpath;
00135 int ut = urlPath(path, &lpath);
00136
00137 switch (ut) {
00138 case URL_IS_FTP:
00139 return ftpRmdir(path);
00140 break;
00141 case URL_IS_PATH:
00142 path = lpath;
00143
00144 case URL_IS_UNKNOWN:
00145 break;
00146 case URL_IS_DASH:
00147 case URL_IS_HKP:
00148 default:
00149 return -2;
00150 break;
00151 }
00152 return rmdir(path);
00153 }
00154
00155
00156 const char * _chroot_prefix = NULL;
00157
00158 int Chroot(const char * path)
00159 {
00160 const char * lpath;
00161 int ut = urlPath(path, &lpath);
00162
00163 if (_rpmio_debug)
00164 fprintf(stderr, "*** Chroot(%s)\n", path);
00165 switch (ut) {
00166 case URL_IS_PATH:
00167 path = lpath;
00168
00169 case URL_IS_UNKNOWN:
00170 break;
00171 case URL_IS_DASH:
00172 case URL_IS_HKP:
00173 case URL_IS_FTP:
00174 default:
00175 errno = EINVAL;
00176 return -2;
00177 break;
00178 }
00179
00180 _chroot_prefix = _free(_chroot_prefix);
00181 if (strcmp(path, "."))
00182 _chroot_prefix = rpmGetPath(path, NULL);
00183
00184
00185 return chroot(path);
00186
00187 }
00188
00189 int Open(const char * path, int flags, mode_t mode)
00190 {
00191 const char * lpath;
00192 int ut = urlPath(path, &lpath);
00193
00194 if (_rpmio_debug)
00195 fprintf(stderr, "*** Open(%s, 0x%x, 0%o)\n", path, flags, mode);
00196 switch (ut) {
00197 case URL_IS_PATH:
00198 path = lpath;
00199
00200 case URL_IS_UNKNOWN:
00201 break;
00202 case URL_IS_DASH:
00203 case URL_IS_HKP:
00204 case URL_IS_FTP:
00205 case URL_IS_HTTPS:
00206 case URL_IS_HTTP:
00207 default:
00208 errno = EINVAL;
00209 return -2;
00210 break;
00211 }
00212
00213 if (_chroot_prefix && _chroot_prefix[0] == '/' && _chroot_prefix[1] != '\0')
00214 {
00215 size_t nb = strlen(_chroot_prefix);
00216 size_t ob = strlen(path);
00217 while (nb > 0 && _chroot_prefix[nb-1] == '/')
00218 nb--;
00219 if (ob > nb && !strncmp(path, _chroot_prefix, nb) && path[nb] == '/')
00220 path += nb;
00221 }
00222 #ifdef NOTYET
00223 if (mode == 0)
00224 mode = 0644;
00225 #endif
00226 return open(path, flags, mode);
00227 }
00228
00229
00230
00231 int Rename (const char * oldpath, const char * newpath)
00232 {
00233 const char *oe = NULL;
00234 const char *ne = NULL;
00235 int oldut, newut;
00236
00237
00238 if (!strcmp(oldpath, newpath)) return 0;
00239
00240 oldut = urlPath(oldpath, &oe);
00241 switch (oldut) {
00242 case URL_IS_FTP:
00243 case URL_IS_PATH:
00244 case URL_IS_UNKNOWN:
00245 break;
00246 case URL_IS_DASH:
00247 case URL_IS_HKP:
00248 default:
00249 return -2;
00250 break;
00251 }
00252
00253 newut = urlPath(newpath, &ne);
00254 switch (newut) {
00255 case URL_IS_FTP:
00256 if (_rpmio_debug)
00257 fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
00258 if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
00259 !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
00260 return -2;
00261 return ftpRename(oldpath, newpath);
00262 break;
00263 case URL_IS_PATH:
00264 oldpath = oe;
00265 newpath = ne;
00266 break;
00267 case URL_IS_UNKNOWN:
00268 break;
00269 case URL_IS_DASH:
00270 case URL_IS_HKP:
00271 default:
00272 return -2;
00273 break;
00274 }
00275 return rename(oldpath, newpath);
00276 }
00277
00278 int Link (const char * oldpath, const char * newpath)
00279 {
00280 const char *oe = NULL;
00281 const char *ne = NULL;
00282 int oldut, newut;
00283
00284 oldut = urlPath(oldpath, &oe);
00285 switch (oldut) {
00286 case URL_IS_FTP:
00287 case URL_IS_PATH:
00288 case URL_IS_UNKNOWN:
00289 break;
00290 case URL_IS_DASH:
00291 case URL_IS_HKP:
00292 default:
00293 return -2;
00294 break;
00295 }
00296
00297 newut = urlPath(newpath, &ne);
00298 switch (newut) {
00299 case URL_IS_FTP:
00300 case URL_IS_PATH:
00301 if (_rpmio_debug)
00302 fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
00303 if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
00304 !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
00305 return -2;
00306 oldpath = oe;
00307 newpath = ne;
00308 break;
00309 case URL_IS_UNKNOWN:
00310 break;
00311 case URL_IS_DASH:
00312 case URL_IS_HKP:
00313 default:
00314 return -2;
00315 break;
00316 }
00317 return link(oldpath, newpath);
00318 }
00319
00320
00321
00322 int Unlink(const char * path) {
00323 const char * lpath;
00324 int ut = urlPath(path, &lpath);
00325
00326 switch (ut) {
00327 case URL_IS_FTP:
00328 return ftpUnlink(path);
00329 break;
00330 case URL_IS_PATH:
00331 path = lpath;
00332
00333 case URL_IS_UNKNOWN:
00334 break;
00335 case URL_IS_DASH:
00336 case URL_IS_HKP:
00337 default:
00338 return -2;
00339 break;
00340 }
00341 return unlink(path);
00342 }
00343
00344
00345
00346 #define g_strdup xstrdup
00347 #define g_free free
00348
00349
00350
00351
00352
00353 static int current_mday;
00354
00355 static int current_mon;
00356
00357 static int current_year;
00358
00359
00360 #define MAXCOLS 30
00361
00362
00363 static char *columns [MAXCOLS];
00364
00365 static int column_ptr [MAXCOLS];
00366
00367
00368 static int
00369 vfs_split_text (char *p)
00370
00371
00372 {
00373 char *original = p;
00374 int numcols;
00375
00376
00377 for (numcols = 0; *p && numcols < MAXCOLS; numcols++){
00378 while (*p == ' ' || *p == '\r' || *p == '\n'){
00379 *p = 0;
00380 p++;
00381 }
00382 columns [numcols] = p;
00383 column_ptr [numcols] = p - original;
00384 while (*p && *p != ' ' && *p != '\r' && *p != '\n')
00385 p++;
00386 }
00387 return numcols;
00388 }
00389
00390
00391
00392 static int
00393 is_num (int idx)
00394
00395 {
00396 if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9')
00397 return 0;
00398 return 1;
00399 }
00400
00401
00402
00403 static int
00404 is_dos_date( const char *str)
00405
00406 {
00407 if (str != NULL && strlen(str) == 8 &&
00408 str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL)
00409 return 1;
00410 return 0;
00411 }
00412
00413
00414 static int
00415 is_week ( const char * str, struct tm * tim)
00416
00417 {
00418 static const char * week = "SunMonTueWedThuFriSat";
00419 const char * pos;
00420
00421
00422 if (str != NULL && (pos=strstr(week, str)) != NULL) {
00423
00424 if (tim != NULL)
00425 tim->tm_wday = (pos - week)/3;
00426 return 1;
00427 }
00428 return 0;
00429 }
00430
00431 static int
00432 is_month ( const char * str, struct tm * tim)
00433
00434 {
00435 static const char * month = "JanFebMarAprMayJunJulAugSepOctNovDec";
00436 const char * pos;
00437
00438
00439 if (str != NULL && (pos = strstr(month, str)) != NULL) {
00440
00441 if (tim != NULL)
00442 tim->tm_mon = (pos - month)/3;
00443 return 1;
00444 }
00445 return 0;
00446 }
00447
00448 static int
00449 is_time ( const char * str, struct tm * tim)
00450
00451 {
00452 const char * p, * p2;
00453
00454 if (str != NULL && (p = strchr(str, ':')) && (p2 = strrchr(str, ':'))) {
00455 if (p != p2) {
00456 if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3)
00457 return 0;
00458 } else {
00459 if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2)
00460 return 0;
00461 }
00462 } else
00463 return 0;
00464
00465 return 1;
00466 }
00467
00468 static int is_year( const char * str, struct tm * tim)
00469
00470 {
00471 long year;
00472
00473 if (str == NULL)
00474 return 0;
00475
00476 if (strchr(str,':'))
00477 return 0;
00478
00479 if (strlen(str) != 4)
00480 return 0;
00481
00482 if (sscanf(str, "%ld", &year) != 1)
00483 return 0;
00484
00485 if (year < 1900 || year > 3000)
00486 return 0;
00487
00488 tim->tm_year = (int) (year - 1900);
00489
00490 return 1;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499 static int
00500 vfs_parse_filetype (char c)
00501
00502 {
00503 switch (c) {
00504 case 'd': return S_IFDIR;
00505 case 'b': return S_IFBLK;
00506 case 'c': return S_IFCHR;
00507 case 'l': return S_IFLNK;
00508 case 's':
00509 #ifdef IS_IFSOCK
00510 return S_IFSOCK;
00511 #endif
00512 case 'p': return S_IFIFO;
00513 case 'm': case 'n':
00514 case '-': case '?': return S_IFREG;
00515 default: return -1;
00516 }
00517 }
00518
00519 static int vfs_parse_filemode (const char *p)
00520
00521 {
00522 int res = 0;
00523 switch (*(p++)) {
00524 case 'r': res |= 0400; break;
00525 case '-': break;
00526 default: return -1;
00527 }
00528 switch (*(p++)) {
00529 case 'w': res |= 0200; break;
00530 case '-': break;
00531 default: return -1;
00532 }
00533 switch (*(p++)) {
00534 case 'x': res |= 0100; break;
00535 case 's': res |= 0100 | S_ISUID; break;
00536 case 'S': res |= S_ISUID; break;
00537 case '-': break;
00538 default: return -1;
00539 }
00540 switch (*(p++)) {
00541 case 'r': res |= 0040; break;
00542 case '-': break;
00543 default: return -1;
00544 }
00545 switch (*(p++)) {
00546 case 'w': res |= 0020; break;
00547 case '-': break;
00548 default: return -1;
00549 }
00550 switch (*(p++)) {
00551 case 'x': res |= 0010; break;
00552 case 's': res |= 0010 | S_ISGID; break;
00553 case 'l':
00554 case 'S': res |= S_ISGID; break;
00555 case '-': break;
00556 default: return -1;
00557 }
00558 switch (*(p++)) {
00559 case 'r': res |= 0004; break;
00560 case '-': break;
00561 default: return -1;
00562 }
00563 switch (*(p++)) {
00564 case 'w': res |= 0002; break;
00565 case '-': break;
00566 default: return -1;
00567 }
00568 switch (*(p++)) {
00569 case 'x': res |= 0001; break;
00570 case 't': res |= 0001 | S_ISVTX; break;
00571 case 'T': res |= S_ISVTX; break;
00572 case '-': break;
00573 default: return -1;
00574 }
00575 return res;
00576 }
00577
00578
00579 static int vfs_parse_filedate(int idx, time_t *t)
00580
00581 {
00582
00583 char *p;
00584 struct tm tim;
00585 int d[3];
00586 int got_year = 0;
00587
00588
00589 tim.tm_year = current_year;
00590 tim.tm_mon = current_mon;
00591 tim.tm_mday = current_mday;
00592 tim.tm_hour = 0;
00593 tim.tm_min = 0;
00594 tim.tm_sec = 0;
00595 tim.tm_isdst = -1;
00596
00597 p = columns [idx++];
00598
00599
00600 if(is_week(p, &tim))
00601 p = columns [idx++];
00602
00603
00604 if(is_month(p, &tim)){
00605
00606 if (is_num (idx))
00607 tim.tm_mday = (int)atol (columns [idx++]);
00608 else
00609 return 0;
00610
00611 } else {
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 if (is_dos_date(p)){
00625
00626 p[2] = p[5] = '-';
00627
00628
00629 memset(d, 0, sizeof(d));
00630 if (sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 d[0]--;
00641
00642 if(d[2] < 70)
00643 d[2] += 100;
00644
00645 tim.tm_mon = d[0];
00646 tim.tm_mday = d[1];
00647 tim.tm_year = d[2];
00648 got_year = 1;
00649 } else
00650 return 0;
00651 } else
00652 return 0;
00653 }
00654
00655
00656
00657 if (is_num (idx)) {
00658 if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) {
00659 idx++;
00660
00661
00662 if(is_num (idx) &&
00663 ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
00664 idx++;
00665 }
00666 }
00667 else
00668 return 0;
00669
00670
00671
00672
00673
00674
00675
00676 if (!got_year &&
00677 current_mon < 6 && current_mon < tim.tm_mon &&
00678 tim.tm_mon - current_mon >= 6)
00679
00680 tim.tm_year--;
00681
00682 if ((*t = mktime(&tim)) < 0)
00683 *t = 0;
00684 return idx;
00685 }
00686
00687
00688
00689 static int
00690 vfs_parse_ls_lga (char * p, struct stat * st,
00691 const char ** filename,
00692 const char ** linkname)
00693
00694 {
00695 int idx, idx2, num_cols;
00696 int i;
00697 char *p_copy;
00698
00699 if (strncmp (p, "total", 5) == 0)
00700 return 0;
00701
00702 p_copy = g_strdup(p);
00703
00704
00705
00706 if ((i = vfs_parse_filetype(*(p++))) == -1)
00707 goto error;
00708
00709 st->st_mode = i;
00710 if (*p == ' ')
00711 p++;
00712 if (*p == '['){
00713 if (strlen (p) <= 8 || p [8] != ']')
00714 goto error;
00715
00716
00717 if (S_ISDIR (st->st_mode))
00718 st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH);
00719 else
00720 st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
00721 p += 9;
00722
00723 } else {
00724 if ((i = vfs_parse_filemode(p)) == -1)
00725 goto error;
00726 st->st_mode |= i;
00727 p += 9;
00728
00729
00730 if (*p == '+')
00731 p++;
00732 }
00733
00734 g_free(p_copy);
00735 p_copy = g_strdup(p);
00736 num_cols = vfs_split_text (p);
00737
00738 st->st_nlink = atol (columns [0]);
00739 if (st->st_nlink < 0)
00740 goto error;
00741
00742 if (!is_num (1))
00743 #ifdef HACK
00744 st->st_uid = finduid (columns [1]);
00745 #else
00746 (void) unameToUid (columns [1], &st->st_uid);
00747 #endif
00748 else
00749 st->st_uid = (uid_t) atol (columns [1]);
00750
00751
00752 for (idx = 3; idx <= 5; idx++)
00753 if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx]))
00754 break;
00755
00756 if (idx == 6 || (idx == 5 && !S_ISCHR (st->st_mode) && !S_ISBLK (st->st_mode)))
00757 goto error;
00758
00759
00760 if (idx == 3 || (idx == 4 && (S_ISCHR(st->st_mode) || S_ISBLK (st->st_mode))))
00761 idx2 = 2;
00762 else {
00763
00764 if (is_num (2))
00765 st->st_gid = (gid_t) atol (columns [2]);
00766 else
00767 #ifdef HACK
00768 st->st_gid = findgid (columns [2]);
00769 #else
00770 (void) gnameToGid (columns [1], &st->st_gid);
00771 #endif
00772 idx2 = 3;
00773 }
00774
00775
00776 if (S_ISCHR (st->st_mode) || S_ISBLK (st->st_mode)){
00777 unsigned maj, min;
00778
00779 if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1)
00780 goto error;
00781
00782 if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1)
00783 goto error;
00784
00785 #ifdef HAVE_ST_RDEV
00786 st->st_rdev = ((maj & 0x000000ffU) << 8) | (min & 0x000000ffU);
00787 #endif
00788 st->st_size = 0;
00789
00790 } else {
00791
00792 if (!is_num (idx2))
00793 goto error;
00794
00795 st->st_size = (size_t) atol (columns [idx2]);
00796 #ifdef HAVE_ST_RDEV
00797 st->st_rdev = 0;
00798 #endif
00799 }
00800
00801 idx = vfs_parse_filedate(idx, &st->st_mtime);
00802 if (!idx)
00803 goto error;
00804
00805 st->st_atime = st->st_ctime = st->st_mtime;
00806 st->st_dev = 0;
00807 st->st_ino = 0;
00808 #ifdef HAVE_ST_BLKSIZE
00809 st->st_blksize = 512;
00810 #endif
00811 #ifdef HAVE_ST_BLOCKS
00812 st->st_blocks = (st->st_size + 511) / 512;
00813 #endif
00814
00815 for (i = idx + 1, idx2 = 0; i < num_cols; i++ )
00816 if (strcmp (columns [i], "->") == 0){
00817 idx2 = i;
00818 break;
00819 }
00820
00821 if (((S_ISLNK (st->st_mode) ||
00822 (num_cols == idx + 3 && st->st_nlink > 1)))
00823 && idx2){
00824 int tlen;
00825 char *t;
00826
00827 if (filename){
00828 #ifdef HACK
00829 t = g_strndup (p_copy + column_ptr [idx], column_ptr [idx2] - column_ptr [idx] - 1);
00830 #else
00831 int nb = column_ptr [idx2] - column_ptr [idx] - 1;
00832 t = xmalloc(nb+1);
00833 strncpy(t, p_copy + column_ptr [idx], nb);
00834 #endif
00835 *filename = t;
00836 }
00837 if (linkname){
00838 t = g_strdup (p_copy + column_ptr [idx2+1]);
00839 tlen = strlen (t);
00840 if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
00841 t [tlen-1] = 0;
00842 if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
00843 t [tlen-2] = 0;
00844
00845 *linkname = t;
00846 }
00847 } else {
00848
00849
00850
00851 if (filename){
00852
00853
00854
00855 int tlen;
00856 char *t;
00857
00858 t = g_strdup (p_copy + column_ptr [idx]); idx++;
00859 tlen = strlen (t);
00860
00861 if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
00862 t [tlen-1] = 0;
00863 if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
00864 t [tlen-2] = 0;
00865
00866 *filename = t;
00867 }
00868 if (linkname)
00869 *linkname = NULL;
00870 }
00871 g_free (p_copy);
00872 return 1;
00873
00874 error:
00875 #ifdef HACK
00876 {
00877 static int errorcount = 0;
00878
00879 if (++errorcount < 5) {
00880 message_1s (1, "Could not parse:", p_copy);
00881 } else if (errorcount == 5)
00882 message_1s (1, "More parsing errors will be ignored.", "(sorry)" );
00883 }
00884 #endif
00885
00886
00887 if (p_copy != p)
00888
00889 g_free (p_copy);
00890 return 0;
00891 }
00892
00893
00894 typedef enum {
00895 DO_FTP_STAT = 1,
00896 DO_FTP_LSTAT = 2,
00897 DO_FTP_READLINK = 3,
00898 DO_FTP_ACCESS = 4,
00899 DO_FTP_GLOB = 5
00900 } ftpSysCall_t;
00901
00904
00905 static size_t ftpBufAlloced = 0;
00906
00909
00910 static char * ftpBuf = NULL;
00911
00912 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
00913
00914
00915 static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall,
00916 struct stat * st,
00917 char * rlbuf, size_t rlbufsiz)
00918
00919
00920
00921
00922 {
00923 FD_t fd;
00924 const char * path;
00925 int bufLength, moretodo;
00926 const char *n, *ne, *o, *oe;
00927 char * s;
00928 char * se;
00929 const char * urldn;
00930 char * bn = NULL;
00931 int nbn = 0;
00932 urlinfo u;
00933 int rc;
00934
00935 n = ne = o = oe = NULL;
00936 (void) urlPath(url, &path);
00937 if (*path == '\0')
00938 return -2;
00939
00940 switch (ftpSysCall) {
00941 case DO_FTP_GLOB:
00942 fd = ftpOpen(url, 0, 0, &u);
00943 if (fd == NULL || u == NULL)
00944 return -1;
00945
00946 u->openError = ftpReq(fd, "LIST", path);
00947 break;
00948 default:
00949 urldn = alloca_strdup(url);
00950
00951 if ((bn = strrchr(urldn, '/')) == NULL)
00952 return -2;
00953 else if (bn == path)
00954 bn = ".";
00955 else
00956 *bn++ = '\0';
00957
00958 nbn = strlen(bn);
00959
00960 rc = ftpChdir(urldn);
00961 if (rc < 0)
00962 return rc;
00963
00964 fd = ftpOpen(url, 0, 0, &u);
00965 if (fd == NULL || u == NULL)
00966 return -1;
00967
00968
00969 u->openError = ftpReq(fd, "NLST", "-la");
00970
00971 if (bn == NULL || nbn <= 0) {
00972 rc = -2;
00973 goto exit;
00974 }
00975 break;
00976 }
00977
00978 if (u->openError < 0) {
00979 fd = fdLink(fd, "error data (ftpStat)");
00980 rc = -2;
00981 goto exit;
00982 }
00983
00984 if (ftpBufAlloced == 0 || ftpBuf == NULL) {
00985 ftpBufAlloced = _url_iobuf_size;
00986 ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0]));
00987 }
00988 *ftpBuf = '\0';
00989
00990 bufLength = 0;
00991 moretodo = 1;
00992
00993 do {
00994
00995
00996 if ((ftpBufAlloced - bufLength) < (1024+80)) {
00997 ftpBufAlloced <<= 2;
00998 assert(ftpBufAlloced < (8*1024*1024));
00999 ftpBuf = xrealloc(ftpBuf, ftpBufAlloced);
01000 }
01001 s = se = ftpBuf + bufLength;
01002 *se = '\0';
01003
01004 rc = fdFgets(fd, se, (ftpBufAlloced - bufLength));
01005 if (rc <= 0) {
01006 moretodo = 0;
01007 break;
01008 }
01009 if (ftpSysCall == DO_FTP_GLOB) {
01010 bufLength += strlen(se);
01011 continue;
01012 }
01013
01014 for (s = se; *s != '\0'; s = se) {
01015 int bingo;
01016
01017 while (*se && *se != '\n') se++;
01018 if (se > s && se[-1] == '\r') se[-1] = '\0';
01019 if (*se == '\0')
01020 break;
01021 *se++ = '\0';
01022
01023 if (!strncmp(s, "total ", sizeof("total ")-1))
01024 continue;
01025
01026 o = NULL;
01027 for (bingo = 0, n = se; n >= s; n--) {
01028 switch (*n) {
01029 case '\0':
01030 oe = ne = n;
01031 break;
01032 case ' ':
01033 if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) {
01034 while (*(++n) == ' ')
01035 {};
01036 bingo++;
01037 break;
01038 }
01039 for (o = n + 1; *o == ' '; o++)
01040 {};
01041 n -= 3;
01042 ne = n;
01043 break;
01044 default:
01045 break;
01046 }
01047 if (bingo)
01048 break;
01049 }
01050
01051 if (nbn != (ne - n))
01052 continue;
01053 if (strncmp(n, bn, nbn))
01054 continue;
01055
01056 moretodo = 0;
01057 break;
01058 }
01059
01060 if (moretodo && se > s) {
01061 bufLength = se - s - 1;
01062 if (s != ftpBuf)
01063 memmove(ftpBuf, s, bufLength);
01064 } else {
01065 bufLength = 0;
01066 }
01067 } while (moretodo);
01068
01069 switch (ftpSysCall) {
01070 case DO_FTP_STAT:
01071 if (o && oe) {
01072
01073 }
01074
01075 case DO_FTP_LSTAT:
01076 if (st == NULL || !(n && ne)) {
01077 rc = -1;
01078 } else {
01079 rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1);
01080 }
01081 break;
01082 case DO_FTP_READLINK:
01083 if (rlbuf == NULL || !(o && oe)) {
01084 rc = -1;
01085 } else {
01086 rc = oe - o;
01087 if (rc > rlbufsiz)
01088 rc = rlbufsiz;
01089 memcpy(rlbuf, o, rc);
01090 if (rc < rlbufsiz)
01091 rlbuf[rc] = '\0';
01092 }
01093 break;
01094 case DO_FTP_ACCESS:
01095 rc = 0;
01096 break;
01097 case DO_FTP_GLOB:
01098 rc = 0;
01099 break;
01100 }
01101
01102 exit:
01103 (void) ufdClose(fd);
01104 return rc;
01105 }
01106
01107
01108 static const char * statstr(const struct stat * st,
01109 char * buf)
01110
01111 {
01112 sprintf(buf,
01113 "*** dev %x ino %x mode %0o nlink %d uid %d gid %d rdev %x size %x\n",
01114 (unsigned int)st->st_dev,
01115 (unsigned int)st->st_ino,
01116 (unsigned int)st->st_mode,
01117 (unsigned int)st->st_nlink,
01118 (unsigned int)st->st_uid,
01119 (unsigned int)st->st_gid,
01120 (unsigned int)st->st_rdev,
01121 (unsigned int)st->st_size);
01122 return buf;
01123 }
01124
01125
01126 static int ftp_st_ino = 0xdead0000;
01127
01128
01129 static int ftpStat(const char * path, struct stat *st)
01130
01131
01132 {
01133 char buf[1024];
01134 int rc;
01135 rc = ftpNLST(path, DO_FTP_STAT, st, NULL, 0);
01136
01137 if (st->st_ino == 0)
01138 st->st_ino = ftp_st_ino++;
01139 if (_ftp_debug)
01140 fprintf(stderr, "*** ftpStat(%s) rc %d\n%s", path, rc, statstr(st, buf));
01141 return rc;
01142 }
01143
01144
01145 static int ftpLstat(const char * path, struct stat *st)
01146
01147
01148 {
01149 char buf[1024];
01150 int rc;
01151 rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0);
01152
01153 if (st->st_ino == 0)
01154 st->st_ino = ftp_st_ino++;
01155 if (_ftp_debug)
01156 fprintf(stderr, "*** ftpLstat(%s) rc %d\n%s\n", path, rc, statstr(st, buf));
01157 return rc;
01158 }
01159
01160 static int ftpReadlink(const char * path, char * buf, size_t bufsiz)
01161
01162
01163 {
01164 int rc;
01165 rc = ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz);
01166 if (_ftp_debug)
01167 fprintf(stderr, "*** ftpReadlink(%s) rc %d\n", path, rc);
01168 return rc;
01169 }
01170
01171
01172
01173 static DIR * ftpOpendir(const char * path)
01174
01175
01176 {
01177 AVDIR avdir;
01178 struct dirent * dp;
01179 size_t nb;
01180 const char * s, * sb, * se;
01181 const char ** av;
01182 unsigned char * dt;
01183 char * t;
01184 int ac;
01185 int c;
01186 int rc;
01187
01188 if (_ftp_debug)
01189 fprintf(stderr, "*** ftpOpendir(%s)\n", path);
01190 rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0);
01191 if (rc)
01192 return NULL;
01193
01194
01195
01196
01197
01198 nb = sizeof(".") + sizeof("..");
01199 ac = 2;
01200 sb = NULL;
01201 s = se = ftpBuf;
01202 while ((c = *se) != '\0') {
01203 se++;
01204 switch (c) {
01205 case '/':
01206 sb = se;
01207 break;
01208 case '\r':
01209 if (sb == NULL) {
01210 for (sb = se; sb > s && sb[-1] != ' '; sb--)
01211 {};
01212 }
01213 ac++;
01214 nb += (se - sb);
01215
01216 if (*se == '\n') se++;
01217 sb = NULL;
01218 s = se;
01219 break;
01220 default:
01221 break;
01222 }
01223 }
01224
01225 nb += sizeof(*avdir) + sizeof(*dp) + ((ac + 1) * sizeof(*av)) + (ac + 1);
01226 avdir = xcalloc(1, nb);
01227
01228 dp = (struct dirent *) (avdir + 1);
01229 av = (const char **) (dp + 1);
01230 dt = (char *) (av + (ac + 1));
01231 t = (char *) (dt + ac + 1);
01232
01233
01234 avdir->fd = avmagicdir;
01235
01236 avdir->data = (char *) dp;
01237
01238 avdir->allocation = nb;
01239 avdir->size = ac;
01240 avdir->offset = -1;
01241 avdir->filepos = 0;
01242
01243 #if defined(HAVE_PTHREAD_H)
01244
01245 (void) pthread_mutex_init(&avdir->lock, NULL);
01246
01247 #endif
01248
01249 ac = 0;
01250
01251 dt[ac] = DT_DIR; av[ac++] = t; t = stpcpy(t, "."); t++;
01252 dt[ac] = DT_DIR; av[ac++] = t; t = stpcpy(t, ".."); t++;
01253
01254 sb = NULL;
01255 s = se = ftpBuf;
01256 while ((c = *se) != '\0') {
01257 se++;
01258 switch (c) {
01259 case '/':
01260 sb = se;
01261 break;
01262 case '\r':
01263
01264 av[ac] = t;
01265
01266 if (sb == NULL) {
01267
01268 switch(*s) {
01269 case 'p':
01270 dt[ac] = DT_FIFO;
01271 break;
01272 case 'c':
01273 dt[ac] = DT_CHR;
01274 break;
01275 case 'd':
01276 dt[ac] = DT_DIR;
01277 break;
01278 case 'b':
01279 dt[ac] = DT_BLK;
01280 break;
01281 case '-':
01282 dt[ac] = DT_REG;
01283 break;
01284 case 'l':
01285 dt[ac] = DT_LNK;
01286 break;
01287 case 's':
01288 dt[ac] = DT_SOCK;
01289 break;
01290 default:
01291 dt[ac] = DT_UNKNOWN;
01292 break;
01293 }
01294
01295 for (sb = se; sb > s && sb[-1] != ' '; sb--)
01296 {};
01297 }
01298 ac++;
01299 t = stpncpy(t, sb, (se - sb));
01300 t[-1] = '\0';
01301 if (*se == '\n') se++;
01302 sb = NULL;
01303 s = se;
01304 break;
01305 default:
01306 break;
01307 }
01308 }
01309 av[ac] = NULL;
01310
01311
01312 return (DIR *) avdir;
01313
01314 }
01315
01316
01317 int Stat(const char * path, struct stat * st)
01318 {
01319 const char * lpath;
01320 int ut = urlPath(path, &lpath);
01321
01322 if (_rpmio_debug)
01323 fprintf(stderr, "*** Stat(%s,%p)\n", path, st);
01324 switch (ut) {
01325 case URL_IS_FTP:
01326 return ftpStat(path, st);
01327 break;
01328 case URL_IS_PATH:
01329 path = lpath;
01330
01331 case URL_IS_UNKNOWN:
01332 break;
01333 case URL_IS_DASH:
01334 case URL_IS_HKP:
01335 default:
01336 errno = EINVAL;
01337 return -2;
01338 break;
01339 }
01340 return stat(path, st);
01341 }
01342
01343 int Lstat(const char * path, struct stat * st)
01344 {
01345 const char * lpath;
01346 int ut = urlPath(path, &lpath);
01347
01348 if (_rpmio_debug)
01349 fprintf(stderr, "*** Lstat(%s,%p)\n", path, st);
01350 switch (ut) {
01351 case URL_IS_FTP:
01352 return ftpLstat(path, st);
01353 break;
01354 case URL_IS_PATH:
01355 path = lpath;
01356
01357 case URL_IS_UNKNOWN:
01358 break;
01359 case URL_IS_DASH:
01360 case URL_IS_HKP:
01361 default:
01362 errno = EINVAL;
01363 return -2;
01364 break;
01365 }
01366 return lstat(path, st);
01367 }
01368
01369 int Chown(const char * path, uid_t owner, gid_t group)
01370 {
01371 const char * lpath;
01372 int ut = urlPath(path, &lpath);
01373
01374 if (_rpmio_debug)
01375 fprintf(stderr, "*** Chown(%s,%d,%d)\n", path, (int)owner, (int)group);
01376 switch (ut) {
01377 case URL_IS_PATH:
01378 path = lpath;
01379
01380 case URL_IS_UNKNOWN:
01381 break;
01382 case URL_IS_DASH:
01383 case URL_IS_HKP:
01384 case URL_IS_FTP:
01385 default:
01386 errno = EINVAL;
01387 return -2;
01388 break;
01389 }
01390 return chown(path, owner, group);
01391 }
01392
01393 int Lchown(const char * path, uid_t owner, gid_t group)
01394 {
01395 const char * lpath;
01396 int ut = urlPath(path, &lpath);
01397
01398 if (_rpmio_debug)
01399 fprintf(stderr, "*** Lchown(%s,%d,%d)\n", path, (int)owner, (int)group);
01400 switch (ut) {
01401 case URL_IS_PATH:
01402 path = lpath;
01403
01404 case URL_IS_UNKNOWN:
01405 break;
01406 case URL_IS_DASH:
01407 case URL_IS_HKP:
01408 case URL_IS_FTP:
01409 default:
01410 errno = EINVAL;
01411 return -2;
01412 break;
01413 }
01414 return lchown(path, owner, group);
01415 }
01416
01417 int Chmod(const char * path, mode_t mode)
01418 {
01419 const char * lpath;
01420 int ut = urlPath(path, &lpath);
01421
01422 if (_rpmio_debug)
01423 fprintf(stderr, "*** Chmod(%s,%0o)\n", path, (int)mode);
01424 switch (ut) {
01425 case URL_IS_PATH:
01426 path = lpath;
01427
01428 case URL_IS_UNKNOWN:
01429 break;
01430 case URL_IS_DASH:
01431 case URL_IS_HKP:
01432 case URL_IS_FTP:
01433 default:
01434 errno = EINVAL;
01435 return -2;
01436 break;
01437 }
01438 return chmod(path, mode);
01439 }
01440
01441 int Mkfifo(const char * path, mode_t mode)
01442 {
01443 const char * lpath;
01444 int ut = urlPath(path, &lpath);
01445
01446 if (_rpmio_debug)
01447 fprintf(stderr, "*** Mkfifo(%s,%0o)\n", path, (int)mode);
01448 switch (ut) {
01449 case URL_IS_PATH:
01450 path = lpath;
01451
01452 case URL_IS_UNKNOWN:
01453 break;
01454 case URL_IS_DASH:
01455 case URL_IS_HKP:
01456 case URL_IS_FTP:
01457 default:
01458 errno = EINVAL;
01459 return -2;
01460 break;
01461 }
01462 return mkfifo(path, mode);
01463 }
01464
01465 int Mknod(const char * path, mode_t mode, dev_t dev)
01466 {
01467 const char * lpath;
01468 int ut = urlPath(path, &lpath);
01469
01470 if (_rpmio_debug)
01471 fprintf(stderr, "*** Mknod(%s,%0o, 0x%x)\n", path, (int)mode, (int)dev);
01472 switch (ut) {
01473 case URL_IS_PATH:
01474 path = lpath;
01475
01476 case URL_IS_UNKNOWN:
01477 break;
01478 case URL_IS_DASH:
01479 case URL_IS_HKP:
01480 case URL_IS_FTP:
01481 default:
01482 errno = EINVAL;
01483 return -2;
01484 break;
01485 }
01486
01487 return mknod(path, mode, dev);
01488
01489 }
01490
01491 int Utime(const char * path, const struct utimbuf *buf)
01492 {
01493 const char * lpath;
01494 int ut = urlPath(path, &lpath);
01495
01496 if (_rpmio_debug)
01497 fprintf(stderr, "*** Utime(%s,%p)\n", path, buf);
01498 switch (ut) {
01499 case URL_IS_PATH:
01500 path = lpath;
01501
01502 case URL_IS_UNKNOWN:
01503 break;
01504 case URL_IS_DASH:
01505 case URL_IS_HKP:
01506 case URL_IS_FTP:
01507 default:
01508 errno = EINVAL;
01509 return -2;
01510 break;
01511 }
01512 return utime(path, buf);
01513 }
01514
01515
01516 int Utimes(const char * path, const struct timeval times[2])
01517 {
01518 const char * lpath;
01519 int ut = urlPath(path, &lpath);
01520
01521 if (_rpmio_debug)
01522 fprintf(stderr, "*** Utimes(%s,%p)\n", path, times);
01523 switch (ut) {
01524 case URL_IS_PATH:
01525 path = lpath;
01526
01527 case URL_IS_UNKNOWN:
01528 break;
01529 case URL_IS_DASH:
01530 case URL_IS_HKP:
01531 case URL_IS_FTP:
01532 default:
01533 errno = EINVAL;
01534 return -2;
01535 break;
01536 }
01537 return utimes(path, times);
01538 }
01539
01540
01541 int Symlink(const char * oldpath, const char * newpath)
01542 {
01543 const char * opath;
01544 int out = urlPath(oldpath, &opath);
01545 const char * npath;
01546 int nut = urlPath(newpath, &npath);
01547
01548 if (_rpmio_debug)
01549 fprintf(stderr, "*** Symlink(%s,%s)\n", oldpath, newpath);
01550 switch (out) {
01551 case URL_IS_PATH:
01552 oldpath = opath;
01553 newpath = npath;
01554
01555 case URL_IS_UNKNOWN:
01556 break;
01557 case URL_IS_DASH:
01558 case URL_IS_HKP:
01559 case URL_IS_FTP:
01560 default:
01561 errno = EINVAL;
01562 return -2;
01563 break;
01564 }
01565 return symlink(oldpath, newpath);
01566 }
01567
01568 int Readlink(const char * path, char * buf, size_t bufsiz)
01569 {
01570 const char * lpath;
01571 int ut = urlPath(path, &lpath);
01572
01573 switch (ut) {
01574 case URL_IS_FTP:
01575 return ftpReadlink(path, buf, bufsiz);
01576 break;
01577 case URL_IS_PATH:
01578 path = lpath;
01579
01580 case URL_IS_UNKNOWN:
01581 break;
01582 case URL_IS_DASH:
01583 case URL_IS_HKP:
01584 default:
01585 errno = EINVAL;
01586 return -2;
01587 break;
01588 }
01589
01590 return readlink(path, buf, bufsiz);
01591
01592 }
01593
01594 int Access(const char * path, int amode)
01595 {
01596 const char * lpath;
01597 int ut = urlPath(path, &lpath);
01598
01599 if (_rpmio_debug)
01600 fprintf(stderr, "*** Access(%s,%d)\n", path, amode);
01601 switch (ut) {
01602 case URL_IS_PATH:
01603 path = lpath;
01604
01605 case URL_IS_UNKNOWN:
01606 break;
01607 case URL_IS_DASH:
01608 case URL_IS_HKP:
01609 case URL_IS_FTP:
01610 default:
01611 errno = EINVAL;
01612 return -2;
01613 break;
01614 }
01615 return access(path, amode);
01616 }
01617
01618
01619
01620
01621
01622
01623 int Glob_pattern_p (const char * pattern, int quote)
01624 {
01625 const char *p;
01626 int ut = urlPath(pattern, &p);
01627 int open = 0;
01628 char c;
01629
01630 while ((c = *p++) != '\0')
01631 switch (c) {
01632 case '?':
01633
01634 if (ut == URL_IS_HTTPS || ut == URL_IS_HTTP || ut == URL_IS_HKP)
01635 continue;
01636
01637 case '*':
01638 return (1);
01639 case '\\':
01640 if (quote && *p != '\0')
01641 p++;
01642 continue;
01643
01644 case '[':
01645 open = 1;
01646 continue;
01647 case ']':
01648 if (open)
01649 return (1);
01650 continue;
01651
01652 case '+':
01653 case '@':
01654 case '!':
01655 if (*p == '(')
01656 return (1);
01657 continue;
01658 }
01659
01660 return (0);
01661 }
01662
01663 int Glob_error(const char * epath, int eerrno)
01664 {
01665 return 1;
01666 }
01667
01668 int Glob(const char *pattern, int flags,
01669 int errfunc(const char * epath, int eerrno), glob_t *pglob)
01670 {
01671 const char * lpath;
01672 int ut = urlPath(pattern, &lpath);
01673
01674
01675 if (_rpmio_debug)
01676 fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", pattern, (unsigned)flags, (void *)errfunc, pglob);
01677
01678 switch (ut) {
01679 case URL_IS_FTP:
01680
01681 pglob->gl_closedir = Closedir;
01682 pglob->gl_readdir = Readdir;
01683 pglob->gl_opendir = Opendir;
01684 pglob->gl_lstat = Lstat;
01685 pglob->gl_stat = Stat;
01686
01687 flags |= GLOB_ALTDIRFUNC;
01688 flags &= ~GLOB_TILDE;
01689 break;
01690 case URL_IS_PATH:
01691 pattern = lpath;
01692
01693 case URL_IS_UNKNOWN:
01694 break;
01695 case URL_IS_DASH:
01696 case URL_IS_HKP:
01697 default:
01698 return -2;
01699 break;
01700 }
01701 return glob(pattern, flags, errfunc, pglob);
01702 }
01703
01704 void Globfree(glob_t *pglob)
01705 {
01706 if (_rpmio_debug)
01707 fprintf(stderr, "*** Globfree(%p)\n", pglob);
01708 globfree(pglob);
01709 }
01710
01711 DIR * Opendir(const char * path)
01712 {
01713 const char * lpath;
01714 int ut = urlPath(path, &lpath);
01715
01716 if (_rpmio_debug)
01717 fprintf(stderr, "*** Opendir(%s)\n", path);
01718 switch (ut) {
01719 case URL_IS_FTP:
01720 return ftpOpendir(path);
01721 break;
01722 case URL_IS_PATH:
01723 path = lpath;
01724
01725 case URL_IS_UNKNOWN:
01726 break;
01727 case URL_IS_DASH:
01728 case URL_IS_HKP:
01729 default:
01730 return NULL;
01731 break;
01732 }
01733
01734 return opendir(path);
01735
01736 }
01737
01738 struct dirent * Readdir(DIR * dir)
01739 {
01740 if (_rpmio_debug)
01741 fprintf(stderr, "*** Readdir(%p)\n", (void *)dir);
01742 if (dir == NULL)
01743 return NULL;
01744 if (ISAVMAGIC(dir))
01745 return avReaddir(dir);
01746 return readdir(dir);
01747 }
01748
01749 int Closedir(DIR * dir)
01750 {
01751 if (_rpmio_debug)
01752 fprintf(stderr, "*** Closedir(%p)\n", (void *)dir);
01753 if (dir == NULL)
01754 return 0;
01755 if (ISAVMAGIC(dir))
01756 return avClosedir(dir);
01757 return closedir(dir);
01758 }
01759
01760 off_t Lseek(int fdno, off_t offset, int whence)
01761 {
01762 if (_rpmio_debug)
01763 fprintf(stderr, "*** Lseek(%d,0x%lx,%d)\n", fdno, (long)offset, whence);
01764 return lseek(fdno, offset, whence);
01765 }