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