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