~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to rpmio/rpmrpc.c

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** \ingroup rpmio
 
2
 * \file rpmio/rpmrpc.c
 
3
 */
 
4
 
 
5
#include "system.h"
 
6
#include <rpmio_internal.h>
 
7
#include <popt.h>
 
8
#include "ugid.h"
 
9
#include "debug.h"
 
10
 
 
11
/*@access FD_t@*/
 
12
/*@access urlinfo@*/
 
13
 
 
14
/*@-redecl@*/
 
15
extern int _rpmio_debug;
 
16
/*@=redecl@*/
 
17
 
 
18
/* =============================================================== */
 
19
static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode)
 
20
        /*@modifies fileSystem @*/
 
21
{
 
22
    int rc;
 
23
    if ((rc = ftpCmd("MKD", path, NULL)) != 0)
 
24
        return rc;
 
25
#if NOTYET
 
26
    {   char buf[20];
 
27
        sprintf(buf, " 0%o", mode);
 
28
        (void) ftpCmd("SITE CHMOD", path, buf);
 
29
    }
 
30
#endif
 
31
    return rc;
 
32
}
 
33
 
 
34
static int ftpChdir(const char * path)
 
35
        /*@modifies fileSystem @*/
 
36
{
 
37
    return ftpCmd("CWD", path, NULL);
 
38
}
 
39
 
 
40
static int ftpRmdir(const char * path)
 
41
        /*@modifies fileSystem @*/
 
42
{
 
43
    return ftpCmd("RMD", path, NULL);
 
44
}
 
45
 
 
46
static int ftpRename(const char * oldpath, const char * newpath)
 
47
        /*@modifies fileSystem @*/
 
48
{
 
49
    int rc;
 
50
    if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0)
 
51
        return rc;
 
52
    return ftpCmd("RNTO", newpath, NULL);
 
53
}
 
54
 
 
55
static int ftpUnlink(const char * path)
 
56
        /*@modifies fileSystem @*/
 
57
{
 
58
    return ftpCmd("DELE", path, NULL);
 
59
}
 
60
 
 
61
/* =============================================================== */
 
62
/* XXX rebuilddb.c: analogues to mkdir(2)/rmdir(2). */
 
63
int Mkdir (const char * path, mode_t mode)
 
64
{
 
65
    const char * lpath;
 
66
    int ut = urlPath(path, &lpath);
 
67
 
 
68
    switch (ut) {
 
69
    case URL_IS_FTP:
 
70
        return ftpMkdir(path, mode);
 
71
        /*@notreached@*/ break;
 
72
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
73
    case URL_IS_PATH:
 
74
        path = lpath;
 
75
        /*@fallthrough@*/
 
76
    case URL_IS_UNKNOWN:
 
77
        break;
 
78
    case URL_IS_DASH:
 
79
    default:
 
80
        return -2;
 
81
        /*@notreached@*/ break;
 
82
    }
 
83
    return mkdir(path, mode);
 
84
}
 
85
 
 
86
int Chdir (const char * path)
 
87
{
 
88
    const char * lpath;
 
89
    int ut = urlPath(path, &lpath);
 
90
 
 
91
    switch (ut) {
 
92
    case URL_IS_FTP:
 
93
        return ftpChdir(path);
 
94
        /*@notreached@*/ break;
 
95
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
96
    case URL_IS_PATH:
 
97
        path = lpath;
 
98
        /*@fallthrough@*/
 
99
    case URL_IS_UNKNOWN:
 
100
        break;
 
101
    case URL_IS_DASH:
 
102
    default:
 
103
        return -2;
 
104
        /*@notreached@*/ break;
 
105
    }
 
106
    return chdir(path);
 
107
}
 
108
 
 
109
int Rmdir (const char * path)
 
110
{
 
111
    const char * lpath;
 
112
    int ut = urlPath(path, &lpath);
 
113
 
 
114
    switch (ut) {
 
115
    case URL_IS_FTP:
 
116
        return ftpRmdir(path);
 
117
        /*@notreached@*/ break;
 
118
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
119
    case URL_IS_PATH:
 
120
        path = lpath;
 
121
        /*@fallthrough@*/
 
122
    case URL_IS_UNKNOWN:
 
123
        break;
 
124
    case URL_IS_DASH:
 
125
    default:
 
126
        return -2;
 
127
        /*@notreached@*/ break;
 
128
    }
 
129
    return rmdir(path);
 
130
}
 
131
 
 
132
/* XXX rpmdb.c: analogue to rename(2). */
 
133
 
 
134
int Rename (const char * oldpath, const char * newpath)
 
135
{
 
136
    const char *oe = NULL;
 
137
    const char *ne = NULL;
 
138
    int oldut, newut;
 
139
 
 
140
    /* XXX lib/install.c used to rely on this behavior. */
 
141
    if (!strcmp(oldpath, newpath)) return 0;
 
142
 
 
143
    oldut = urlPath(oldpath, &oe);
 
144
    switch (oldut) {
 
145
    case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
 
146
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
147
    case URL_IS_PATH:
 
148
    case URL_IS_UNKNOWN:
 
149
        break;
 
150
    case URL_IS_DASH:
 
151
    default:
 
152
        return -2;
 
153
        /*@notreached@*/ break;
 
154
    }
 
155
 
 
156
    newut = urlPath(newpath, &ne);
 
157
    switch (newut) {
 
158
    case URL_IS_FTP:
 
159
if (_rpmio_debug)
 
160
fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
 
161
        if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
 
162
            !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
 
163
            return -2;
 
164
        return ftpRename(oldpath, newpath);
 
165
        /*@notreached@*/ break;
 
166
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
167
    case URL_IS_PATH:
 
168
        oldpath = oe;
 
169
        newpath = ne;
 
170
        break;
 
171
    case URL_IS_UNKNOWN:
 
172
        break;
 
173
    case URL_IS_DASH:
 
174
    default:
 
175
        return -2;
 
176
        /*@notreached@*/ break;
 
177
    }
 
178
    return rename(oldpath, newpath);
 
179
}
 
180
 
 
181
int Link (const char * oldpath, const char * newpath)
 
182
{
 
183
    const char *oe = NULL;
 
184
    const char *ne = NULL;
 
185
    int oldut, newut;
 
186
 
 
187
    oldut = urlPath(oldpath, &oe);
 
188
    switch (oldut) {
 
189
    case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
 
190
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
191
    case URL_IS_PATH:
 
192
    case URL_IS_UNKNOWN:
 
193
        break;
 
194
    case URL_IS_DASH:
 
195
    default:
 
196
        return -2;
 
197
        /*@notreached@*/ break;
 
198
    }
 
199
 
 
200
    newut = urlPath(newpath, &ne);
 
201
    switch (newut) {
 
202
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
203
    case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
 
204
    case URL_IS_PATH:
 
205
if (_rpmio_debug)
 
206
fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
 
207
        if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
 
208
            !xstrncasecmp(oldpath, newpath, (oe - oldpath))))
 
209
            return -2;
 
210
        oldpath = oe;
 
211
        newpath = ne;
 
212
        break;
 
213
    case URL_IS_UNKNOWN:
 
214
        break;
 
215
    case URL_IS_DASH:
 
216
    default:
 
217
        return -2;
 
218
        /*@notreached@*/ break;
 
219
    }
 
220
    return link(oldpath, newpath);
 
221
}
 
222
 
 
223
/* XXX build/build.c: analogue to unlink(2). */
 
224
 
 
225
int Unlink(const char * path) {
 
226
    const char * lpath;
 
227
    int ut = urlPath(path, &lpath);
 
228
 
 
229
    switch (ut) {
 
230
    case URL_IS_FTP:
 
231
        return ftpUnlink(path);
 
232
        /*@notreached@*/ break;
 
233
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
234
    case URL_IS_PATH:
 
235
        path = lpath;
 
236
        /*@fallthrough@*/
 
237
    case URL_IS_UNKNOWN:
 
238
        break;
 
239
    case URL_IS_DASH:
 
240
    default:
 
241
        return -2;
 
242
        /*@notreached@*/ break;
 
243
    }
 
244
    return unlink(path);
 
245
}
 
246
 
 
247
/* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */
 
248
 
 
249
#define g_strdup        xstrdup
 
250
#define g_free          free
 
251
 
 
252
/*
 
253
 * FIXME: this is broken. It depends on mc not crossing border on month!
 
254
 */
 
255
static int current_mday;
 
256
static int current_mon;
 
257
static int current_year;
 
258
 
 
259
/* Following stuff (parse_ls_lga) is used by ftpfs and extfs */
 
260
#define MAXCOLS         30
 
261
 
 
262
static char *columns [MAXCOLS]; /* Points to the string in column n */
 
263
static int   column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */
 
264
 
 
265
static int
 
266
vfs_split_text (char *p)
 
267
        /*@modifies *p, columns, column_ptr @*/
 
268
{
 
269
    char *original = p;
 
270
    int  numcols;
 
271
 
 
272
 
 
273
    for (numcols = 0; *p && numcols < MAXCOLS; numcols++){
 
274
        while (*p == ' ' || *p == '\r' || *p == '\n'){
 
275
            *p = 0;
 
276
            p++;
 
277
        }
 
278
        columns [numcols] = p;
 
279
        column_ptr [numcols] = p - original;
 
280
        while (*p && *p != ' ' && *p != '\r' && *p != '\n')
 
281
            p++;
 
282
    }
 
283
    return numcols;
 
284
}
 
285
 
 
286
static int
 
287
is_num (int idx)
 
288
        /*@*/
 
289
{
 
290
    if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9')
 
291
        return 0;
 
292
    return 1;
 
293
}
 
294
 
 
295
static int
 
296
is_dos_date(/*@null@*/ const char *str)
 
297
        /*@*/
 
298
{
 
299
    if (str != NULL && strlen(str) == 8 &&
 
300
                str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL)
 
301
        return 1;
 
302
    return 0;
 
303
}
 
304
 
 
305
static int
 
306
is_week (/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
 
307
        /*@modifies *tim @*/
 
308
{
 
309
/*@observer@*/ static const char * week = "SunMonTueWedThuFriSat";
 
310
    const char * pos;
 
311
 
 
312
    /*@-observertrans -mayaliasunique@*/
 
313
    if (str != NULL && (pos=strstr(week, str)) != NULL) {
 
314
    /*@=observertrans =mayaliasunique@*/
 
315
        if (tim != NULL)
 
316
            tim->tm_wday = (pos - week)/3;
 
317
        return 1;
 
318
    }
 
319
    return 0;    
 
320
}
 
321
 
 
322
static int
 
323
is_month (/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
 
324
        /*@modifies *tim @*/
 
325
{
 
326
/*@observer@*/ static const char * month = "JanFebMarAprMayJunJulAugSepOctNovDec";
 
327
    const char * pos;
 
328
    
 
329
    /*@-observertrans -mayaliasunique@*/
 
330
    if (str != NULL && (pos = strstr(month, str)) != NULL) {
 
331
    /*@=observertrans -mayaliasunique@*/
 
332
        if (tim != NULL)
 
333
            tim->tm_mon = (pos - month)/3;
 
334
        return 1;
 
335
    }
 
336
    return 0;
 
337
}
 
338
 
 
339
static int
 
340
is_time (/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
 
341
        /*@modifies *tim @*/
 
342
{
 
343
    const char * p, * p2;
 
344
 
 
345
    if (str != NULL && (p = strchr(str, ':')) && (p2 = strrchr(str, ':'))) {
 
346
        if (p != p2) {
 
347
            if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3)
 
348
                return 0;
 
349
        } else {
 
350
            if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2)
 
351
                return 0;
 
352
        }
 
353
    } else 
 
354
        return 0;
 
355
    
 
356
    return 1;
 
357
}
 
358
 
 
359
static int is_year(/*@null@*/ const char * str, /*@out@*/ struct tm * tim)
 
360
        /*@modifies *tim @*/
 
361
{
 
362
    long year;
 
363
 
 
364
    if (str == NULL)
 
365
        return 0;
 
366
 
 
367
    if (strchr(str,':'))
 
368
        return 0;
 
369
 
 
370
    if (strlen(str) != 4)
 
371
        return 0;
 
372
 
 
373
    if (sscanf(str, "%ld", &year) != 1)
 
374
        return 0;
 
375
 
 
376
    if (year < 1900 || year > 3000)
 
377
        return 0;
 
378
 
 
379
    tim->tm_year = (int) (year - 1900);
 
380
 
 
381
    return 1;
 
382
}
 
383
 
 
384
/*
 
385
 * FIXME: this is broken. Consider following entry:
 
386
 * -rwx------   1 root     root            1 Aug 31 10:04 2904 1234
 
387
 * where "2904 1234" is filename. Well, this code decodes it as year :-(.
 
388
 */
 
389
 
 
390
static int
 
391
vfs_parse_filetype (char c)
 
392
        /*@*/
 
393
{
 
394
    switch (c) {
 
395
        case 'd': return S_IFDIR; 
 
396
        case 'b': return S_IFBLK;
 
397
        case 'c': return S_IFCHR;
 
398
        case 'l': return S_IFLNK;
 
399
        case 's':
 
400
#ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */
 
401
                  return S_IFSOCK;
 
402
#endif
 
403
        case 'p': return S_IFIFO;
 
404
        case 'm': case 'n':             /* Don't know what these are :-) */
 
405
        case '-': case '?': return S_IFREG;
 
406
        default: return -1;
 
407
    }
 
408
}
 
409
 
 
410
static int vfs_parse_filemode (const char *p)
 
411
        /*@*/
 
412
{       /* converts rw-rw-rw- into 0666 */
 
413
    int res = 0;
 
414
    switch (*(p++)) {
 
415
        case 'r': res |= 0400; break;
 
416
        case '-': break;
 
417
        default: return -1;
 
418
    }
 
419
    switch (*(p++)) {
 
420
        case 'w': res |= 0200; break;
 
421
        case '-': break;
 
422
        default: return -1;
 
423
    }
 
424
    switch (*(p++)) {
 
425
        case 'x': res |= 0100; break;
 
426
        case 's': res |= 0100 | S_ISUID; break;
 
427
        case 'S': res |= S_ISUID; break;
 
428
        case '-': break;
 
429
        default: return -1;
 
430
    }
 
431
    switch (*(p++)) {
 
432
        case 'r': res |= 0040; break;
 
433
        case '-': break;
 
434
        default: return -1;
 
435
    }
 
436
    switch (*(p++)) {
 
437
        case 'w': res |= 0020; break;
 
438
        case '-': break;
 
439
        default: return -1;
 
440
    }
 
441
    switch (*(p++)) {
 
442
        case 'x': res |= 0010; break;
 
443
        case 's': res |= 0010 | S_ISGID; break;
 
444
        case 'l': /* Solaris produces these */
 
445
        case 'S': res |= S_ISGID; break;
 
446
        case '-': break;
 
447
        default: return -1;
 
448
    }
 
449
    switch (*(p++)) {
 
450
        case 'r': res |= 0004; break;
 
451
        case '-': break;
 
452
        default: return -1;
 
453
    }
 
454
    switch (*(p++)) {
 
455
        case 'w': res |= 0002; break;
 
456
        case '-': break;
 
457
        default: return -1;
 
458
    }
 
459
    switch (*(p++)) {
 
460
        case 'x': res |= 0001; break;
 
461
        case 't': res |= 0001 | S_ISVTX; break;
 
462
        case 'T': res |= S_ISVTX; break;
 
463
        case '-': break;
 
464
        default: return -1;
 
465
    }
 
466
    return res;
 
467
}
 
468
 
 
469
static int vfs_parse_filedate(int idx, /*@out@*/ time_t *t)
 
470
        /*@modifies *t @*/
 
471
{       /* This thing parses from idx in columns[] array */
 
472
 
 
473
    char *p;
 
474
    struct tm tim;
 
475
    int d[3];
 
476
    int got_year = 0;
 
477
 
 
478
    /* Let's setup default time values */
 
479
    tim.tm_year = current_year;
 
480
    tim.tm_mon  = current_mon;
 
481
    tim.tm_mday = current_mday;
 
482
    tim.tm_hour = 0;
 
483
    tim.tm_min  = 0;
 
484
    tim.tm_sec  = 0;
 
485
    tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */
 
486
    
 
487
    p = columns [idx++];
 
488
    
 
489
    /* We eat weekday name in case of extfs */
 
490
    if(is_week(p, &tim))
 
491
        p = columns [idx++];
 
492
 
 
493
    /* Month name */
 
494
    if(is_month(p, &tim)){
 
495
        /* And we expect, it followed by day number */
 
496
        if (is_num (idx))
 
497
            tim.tm_mday = (int)atol (columns [idx++]);
 
498
        else
 
499
            return 0; /* No day */
 
500
 
 
501
    } else {
 
502
        /* We usually expect:
 
503
           Mon DD hh:mm
 
504
           Mon DD  YYYY
 
505
           But in case of extfs we allow these date formats:
 
506
           Mon DD YYYY hh:mm
 
507
           Mon DD hh:mm YYYY
 
508
           Wek Mon DD hh:mm:ss YYYY
 
509
           MM-DD-YY hh:mm
 
510
           where Mon is Jan-Dec, DD, MM, YY two digit day, month, year,
 
511
           YYYY four digit year, hh, mm, ss two digit hour, minute or second. */
 
512
 
 
513
        /* Here just this special case with MM-DD-YY */
 
514
        if (is_dos_date(p)){
 
515
            p[2] = p[5] = '-';
 
516
            
 
517
            memset(d, 0, sizeof(d));
 
518
            if (sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){
 
519
            /*  We expect to get:
 
520
                1. MM-DD-YY
 
521
                2. DD-MM-YY
 
522
                3. YY-MM-DD
 
523
                4. YY-DD-MM  */
 
524
                
 
525
                /* Hmm... maybe, next time :)*/
 
526
                
 
527
                /* At last, MM-DD-YY */
 
528
                d[0]--; /* Months are zerobased */
 
529
                /* Y2K madness */
 
530
                if(d[2] < 70)
 
531
                    d[2] += 100;
 
532
 
 
533
                tim.tm_mon  = d[0];
 
534
                tim.tm_mday = d[1];
 
535
                tim.tm_year = d[2];
 
536
                got_year = 1;
 
537
            } else
 
538
                return 0; /* sscanf failed */
 
539
        } else
 
540
            return 0; /* unsupported format */
 
541
    }
 
542
 
 
543
    /* Here we expect to find time and/or year */
 
544
    
 
545
    if (is_num (idx)) {
 
546
        if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) {
 
547
        idx++;
 
548
 
 
549
        /* This is a special case for ctime() or Mon DD YYYY hh:mm */
 
550
        if(is_num (idx) && 
 
551
            ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
 
552
                idx++; /* time & year or reverse */
 
553
        } /* only time or date */
 
554
    }
 
555
    else 
 
556
        return 0; /* Nor time or date */
 
557
 
 
558
    /*
 
559
     * If the date is less than 6 months in the past, it is shown without year
 
560
     * other dates in the past or future are shown with year but without time
 
561
     * This does not check for years before 1900 ... I don't know, how
 
562
     * to represent them at all
 
563
     */
 
564
    if (!got_year &&
 
565
        current_mon < 6 && current_mon < tim.tm_mon && 
 
566
        tim.tm_mon - current_mon >= 6)
 
567
 
 
568
        tim.tm_year--;
 
569
 
 
570
    if ((*t = mktime(&tim)) < 0)
 
571
        *t = 0;
 
572
    return idx;
 
573
}
 
574
 
 
575
static int
 
576
vfs_parse_ls_lga (char * p, /*@out@*/ struct stat * st,
 
577
                /*@out@*/ const char ** filename,
 
578
                /*@out@*/ const char ** linkname)
 
579
        /*@modifies *st, *filename, *linkname @*/
 
580
{
 
581
    int idx, idx2, num_cols;
 
582
    int i;
 
583
    char *p_copy;
 
584
    
 
585
    if (strncmp (p, "total", 5) == 0)
 
586
        return 0;
 
587
 
 
588
    p_copy = g_strdup(p);
 
589
/* XXX FIXME: parse out inode number from "NLST -lai ." */
 
590
/* XXX FIXME: parse out sizein blocks from "NLST -lais ." */
 
591
 
 
592
    if ((i = vfs_parse_filetype(*(p++))) == -1)
 
593
        goto error;
 
594
 
 
595
    st->st_mode = i;
 
596
    if (*p == ' ')      /* Notwell 4 */
 
597
        p++;
 
598
    if (*p == '['){
 
599
        if (strlen (p) <= 8 || p [8] != ']')
 
600
            goto error;
 
601
        /* Should parse here the Notwell permissions :) */
 
602
        /*@-unrecog@*/
 
603
        if (S_ISDIR (st->st_mode))
 
604
            st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH);
 
605
        else
 
606
            st->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
 
607
        p += 9;
 
608
        /*@=unrecog@*/
 
609
    } else {
 
610
        if ((i = vfs_parse_filemode(p)) == -1)
 
611
            goto error;
 
612
        st->st_mode |= i;
 
613
        p += 9;
 
614
 
 
615
        /* This is for an extra ACL attribute (HP-UX) */
 
616
        if (*p == '+')
 
617
            p++;
 
618
    }
 
619
 
 
620
    g_free(p_copy);
 
621
    p_copy = g_strdup(p);
 
622
    num_cols = vfs_split_text (p);
 
623
 
 
624
    st->st_nlink = atol (columns [0]);
 
625
    if (st->st_nlink < 0)
 
626
        goto error;
 
627
 
 
628
    if (!is_num (1))
 
629
#ifdef  HACK
 
630
        st->st_uid = finduid (columns [1]);
 
631
#else
 
632
        (void) unameToUid (columns [1], &st->st_uid);
 
633
#endif
 
634
    else
 
635
        st->st_uid = (uid_t) atol (columns [1]);
 
636
 
 
637
    /* Mhm, the ls -lg did not produce a group field */
 
638
    for (idx = 3; idx <= 5; idx++) 
 
639
        if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx]))
 
640
            break;
 
641
 
 
642
    if (idx == 6 || (idx == 5 && !S_ISCHR (st->st_mode) && !S_ISBLK (st->st_mode)))
 
643
        goto error;
 
644
 
 
645
    /* We don't have gid */     
 
646
    if (idx == 3 || (idx == 4 && (S_ISCHR(st->st_mode) || S_ISBLK (st->st_mode))))
 
647
        idx2 = 2;
 
648
    else { 
 
649
        /* We have gid field */
 
650
        if (is_num (2))
 
651
            st->st_gid = (gid_t) atol (columns [2]);
 
652
        else
 
653
#ifdef  HACK
 
654
            st->st_gid = findgid (columns [2]);
 
655
#else
 
656
            (void) gnameToGid (columns [1], &st->st_gid);
 
657
#endif
 
658
        idx2 = 3;
 
659
    }
 
660
 
 
661
    /* This is device */
 
662
    if (S_ISCHR (st->st_mode) || S_ISBLK (st->st_mode)){
 
663
        int maj, min;
 
664
        
 
665
        if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1)
 
666
            goto error;
 
667
        
 
668
        if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1)
 
669
            goto error;
 
670
        
 
671
#ifdef HAVE_ST_RDEV
 
672
        st->st_rdev = ((maj & 0xff) << 8) | (min & 0xffff00ff);
 
673
#endif
 
674
        st->st_size = 0;
 
675
        
 
676
    } else {
 
677
        /* Common file size */
 
678
        if (!is_num (idx2))
 
679
            goto error;
 
680
        
 
681
        st->st_size = (size_t) atol (columns [idx2]);
 
682
#ifdef HAVE_ST_RDEV
 
683
        st->st_rdev = 0;
 
684
#endif
 
685
    }
 
686
 
 
687
    idx = vfs_parse_filedate(idx, &st->st_mtime);
 
688
    if (!idx)
 
689
        goto error;
 
690
    /* Use resulting time value */
 
691
    st->st_atime = st->st_ctime = st->st_mtime;
 
692
    st->st_dev = 0;
 
693
    st->st_ino = 0;
 
694
#ifdef HAVE_ST_BLKSIZE
 
695
    st->st_blksize = 512;
 
696
#endif
 
697
#ifdef HAVE_ST_BLOCKS
 
698
    st->st_blocks = (st->st_size + 511) / 512;
 
699
#endif
 
700
 
 
701
    for (i = idx + 1, idx2 = 0; i < num_cols; i++ ) 
 
702
        if (strcmp (columns [i], "->") == 0){
 
703
            idx2 = i;
 
704
            break;
 
705
        }
 
706
    
 
707
    if (((S_ISLNK (st->st_mode) || 
 
708
        (num_cols == idx + 3 && st->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */
 
709
        && idx2){
 
710
        int tlen;
 
711
        char *t;
 
712
            
 
713
        if (filename){
 
714
#ifdef HACK
 
715
            t = g_strndup (p_copy + column_ptr [idx], column_ptr [idx2] - column_ptr [idx] - 1);
 
716
#else
 
717
            int nb = column_ptr [idx2] - column_ptr [idx] - 1;
 
718
            t = xmalloc(nb+1);
 
719
            strncpy(t, p_copy + column_ptr [idx], nb);
 
720
#endif
 
721
            *filename = t;
 
722
        }
 
723
        if (linkname){
 
724
            t = g_strdup (p_copy + column_ptr [idx2+1]);
 
725
            tlen = strlen (t);
 
726
            if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
 
727
                t [tlen-1] = 0;
 
728
            if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
 
729
                t [tlen-2] = 0;
 
730
                
 
731
            *linkname = t;
 
732
        }
 
733
    } else {
 
734
        /* Extract the filename from the string copy, not from the columns
 
735
         * this way we have a chance of entering hidden directories like ". ."
 
736
         */
 
737
        if (filename){
 
738
            /* 
 
739
            *filename = g_strdup (columns [idx++]);
 
740
            */
 
741
            int tlen;
 
742
            char *t;
 
743
            
 
744
            t = g_strdup (p_copy + column_ptr [idx++]);
 
745
            tlen = strlen (t);
 
746
            /* g_strchomp(); */
 
747
            if (t [tlen-1] == '\r' || t [tlen-1] == '\n')
 
748
                t [tlen-1] = 0;
 
749
            if (t [tlen-2] == '\r' || t [tlen-2] == '\n')
 
750
                t [tlen-2] = 0;
 
751
            
 
752
            *filename = t;
 
753
        }
 
754
        if (linkname)
 
755
            *linkname = NULL;
 
756
    }
 
757
    g_free (p_copy);
 
758
    return 1;
 
759
 
 
760
error:
 
761
#ifdef  HACK
 
762
    {
 
763
      static int errorcount = 0;
 
764
 
 
765
      if (++errorcount < 5) {
 
766
        message_1s (1, "Could not parse:", p_copy);
 
767
      } else if (errorcount == 5)
 
768
        message_1s (1, "More parsing errors will be ignored.", "(sorry)" );
 
769
    }
 
770
#endif
 
771
 
 
772
    /*@-usereleased@*/
 
773
    if (p_copy != p)            /* Carefull! */
 
774
    /*@=usereleased@*/
 
775
        g_free (p_copy);
 
776
    return 0;
 
777
}
 
778
 
 
779
typedef enum {
 
780
        DO_FTP_STAT     = 1,
 
781
        DO_FTP_LSTAT    = 2,
 
782
        DO_FTP_READLINK = 3,
 
783
        DO_FTP_ACCESS   = 4,
 
784
        DO_FTP_GLOB     = 5
 
785
} ftpSysCall_t;
 
786
static size_t ftpBufAlloced = 0;
 
787
static /*@only@*/ char * ftpBuf = NULL;
 
788
        
 
789
#define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
 
790
 
 
791
static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall,
 
792
                /*@out@*/ /*@null@*/ struct stat * st,
 
793
                /*@out@*/ /*@null@*/ char * rlbuf, size_t rlbufsiz)
 
794
        /*@modifies *st, *rlbuf, fileSystem @*/
 
795
{
 
796
    FD_t fd;
 
797
    const char * path;
 
798
    int bufLength, moretodo;
 
799
    const char *n, *ne, *o, *oe;
 
800
    char * s;
 
801
    char * se;
 
802
    const char * urldn;
 
803
    char * bn = NULL;
 
804
    int nbn = 0;
 
805
    urlinfo u;
 
806
    int rc;
 
807
 
 
808
    n = ne = o = oe = NULL;
 
809
    (void) urlPath(url, &path);
 
810
    if (*path == '\0')
 
811
        return -2;
 
812
 
 
813
    switch (ftpSysCall) {
 
814
    case DO_FTP_GLOB:
 
815
        fd = ftpOpen(url, 0, 0, &u);
 
816
        if (fd == NULL || u == NULL)
 
817
            return -1;
 
818
 
 
819
        u->openError = ftpReq(fd, "NLST", path);
 
820
        break;
 
821
    default:
 
822
        urldn = alloca_strdup(url);
 
823
        if ((bn = strrchr(urldn, '/')) == NULL)
 
824
            return -2;
 
825
        else if (bn == path)
 
826
            bn = ".";
 
827
        else
 
828
            *bn++ = '\0';
 
829
        nbn = strlen(bn);
 
830
 
 
831
        rc = ftpChdir(urldn);           /* XXX don't care about CWD */
 
832
        if (rc < 0)
 
833
            return rc;
 
834
 
 
835
        fd = ftpOpen(url, 0, 0, &u);
 
836
        if (fd == NULL || u == NULL)
 
837
            return -1;
 
838
 
 
839
        /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */
 
840
        u->openError = ftpReq(fd, "NLST", "-la");
 
841
 
 
842
        if (bn == NULL || nbn <= 0) {
 
843
            rc = -2;
 
844
            goto exit;
 
845
        }
 
846
        break;
 
847
    }
 
848
 
 
849
    if (u->openError < 0) {
 
850
        fd = fdLink(fd, "error data (ftpStat)");
 
851
        rc = -2;
 
852
        goto exit;
 
853
    }
 
854
 
 
855
    if (ftpBufAlloced == 0 || ftpBuf == NULL) {
 
856
        ftpBufAlloced = url_iobuf_size;
 
857
        ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0]));
 
858
    }
 
859
    *ftpBuf = '\0';
 
860
 
 
861
    bufLength = 0;
 
862
    moretodo = 1;
 
863
 
 
864
    do {
 
865
 
 
866
        /* XXX FIXME: realloc ftpBuf is < ~128 chars remain */
 
867
        if ((ftpBufAlloced - bufLength) < (1024+80)) {
 
868
            ftpBufAlloced <<= 2;
 
869
            ftpBuf = xrealloc(ftpBuf, ftpBufAlloced);
 
870
        }
 
871
        s = se = ftpBuf + bufLength;
 
872
        *se = '\0';
 
873
 
 
874
        rc = fdFgets(fd, se, (ftpBufAlloced - bufLength));
 
875
        if (rc <= 0) {
 
876
            moretodo = 0;
 
877
            break;
 
878
        }
 
879
        if (ftpSysCall == DO_FTP_GLOB) {        /* XXX HACK */
 
880
            bufLength += strlen(se);
 
881
            continue;
 
882
        }
 
883
 
 
884
        for (s = se; *s != '\0'; s = se) {
 
885
            int bingo;
 
886
 
 
887
            while (*se && *se != '\n') se++;
 
888
            if (se > s && se[-1] == '\r') se[-1] = '\0';
 
889
            if (*se == '\0') 
 
890
                /*@innerbreak@*/ break;
 
891
            *se++ = '\0';
 
892
 
 
893
            if (!strncmp(s, "total ", sizeof("total ")-1)) continue;
 
894
 
 
895
            o = NULL;
 
896
            for (bingo = 0, n = se; n >= s; n--) {
 
897
                switch (*n) {
 
898
                case '\0':
 
899
                    oe = ne = n;
 
900
                    break;
 
901
                case ' ':
 
902
                    if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) {
 
903
                        while (*(++n) == ' ')
 
904
                            {};
 
905
                        bingo++;
 
906
                        break;
 
907
                    }
 
908
                    for (o = n + 1; *o == ' '; o++)
 
909
                        {};
 
910
                    n -= 3;
 
911
                    ne = n;
 
912
                    break;
 
913
                default:
 
914
                    break;
 
915
                }
 
916
                if (bingo)
 
917
                    /*@innerbreak@*/ break;
 
918
            }
 
919
 
 
920
            if (nbn != (ne - n))        continue;       /* Same name length? */
 
921
            if (strncmp(n, bn, nbn))    continue;       /* Same name? */
 
922
 
 
923
            moretodo = 0;
 
924
            /*@innerbreak@*/ break;
 
925
        }
 
926
 
 
927
        if (moretodo && se > s) {
 
928
            bufLength = se - s - 1;
 
929
            if (s != ftpBuf)
 
930
                memmove(ftpBuf, s, bufLength);
 
931
        } else {
 
932
            bufLength = 0;
 
933
        }
 
934
    } while (moretodo);
 
935
 
 
936
    switch (ftpSysCall) {
 
937
    case DO_FTP_STAT:
 
938
        if (o && oe) {
 
939
            /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */
 
940
        }
 
941
        /*@fallthrough@*/
 
942
    case DO_FTP_LSTAT:
 
943
        if (st == NULL || !(n && ne)) {
 
944
            rc = -1;
 
945
        } else {
 
946
            rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1);
 
947
        }
 
948
        break;
 
949
    case DO_FTP_READLINK:
 
950
        if (rlbuf == NULL || !(o && oe)) {
 
951
            rc = -1;
 
952
        } else {
 
953
            rc = oe - o;
 
954
            if (rc > rlbufsiz)
 
955
                rc = rlbufsiz;
 
956
            memcpy(rlbuf, o, rc);
 
957
            if (rc < rlbufsiz)
 
958
                rlbuf[rc] = '\0';
 
959
        }
 
960
        break;
 
961
    case DO_FTP_ACCESS:
 
962
        rc = 0;         /* XXX WRONG WRONG WRONG */
 
963
        break;
 
964
    case DO_FTP_GLOB:
 
965
        rc = 0;         /* XXX WRONG WRONG WRONG */
 
966
        break;
 
967
    }
 
968
 
 
969
exit:
 
970
    (void) ufdClose(fd);
 
971
    return rc;
 
972
}
 
973
 
 
974
static int ftpStat(const char * path, /*@out@*/ struct stat *st)
 
975
        /*@modifies *st @*/
 
976
{
 
977
    return ftpNLST(path, DO_FTP_STAT, st, NULL, 0);
 
978
}
 
979
 
 
980
static int ftpLstat(const char * path, /*@out@*/ struct stat *st)
 
981
        /*@modifies *st @*/
 
982
{
 
983
    int rc;
 
984
    rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0);
 
985
if (_rpmio_debug)
 
986
fprintf(stderr, "*** ftpLstat(%s) rc %d\n", path, rc);
 
987
    return rc;
 
988
}
 
989
 
 
990
static int ftpReadlink(const char * path, /*@out@*/ char * buf, size_t bufsiz)
 
991
        /*@modifies *buf @*/
 
992
{
 
993
    return ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz);
 
994
}
 
995
 
 
996
static int ftpGlob(const char * path, int flags,
 
997
                int errfunc(const char * epath, int eerno),
 
998
                /*@out@*/ glob_t * pglob)
 
999
        /*@modifies *pglob, fileSystem @*/
 
1000
{
 
1001
    int rc;
 
1002
 
 
1003
    if (pglob == NULL)
 
1004
        return -2;
 
1005
    rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0);
 
1006
/*@-castfcnptr@*/
 
1007
if (_rpmio_debug)
 
1008
fprintf(stderr, "*** ftpGlob(%s,0x%x,%p,%p) ftpNLST rc %d\n", path, (unsigned)flags, (void *)errfunc, pglob, rc);
 
1009
/*@=castfcnptr@*/
 
1010
    if (rc)
 
1011
        return rc;
 
1012
    rc = poptParseArgvString(ftpBuf, &pglob->gl_pathc, (const char ***)&pglob->gl_pathv);
 
1013
    pglob->gl_offs = -1;        /* XXX HACK HACK HACK */
 
1014
    return rc;
 
1015
}
 
1016
 
 
1017
static void ftpGlobfree(glob_t * pglob)
 
1018
        /*@modifies *pglob @*/
 
1019
{
 
1020
if (_rpmio_debug)
 
1021
fprintf(stderr, "*** ftpGlobfree(%p)\n", pglob);
 
1022
    if (pglob->gl_offs == -1) { /* XXX HACK HACK HACK */
 
1023
        free((void *)pglob->gl_pathv);
 
1024
        pglob->gl_pathv = NULL;
 
1025
    }
 
1026
}
 
1027
 
 
1028
int Stat(const char * path, struct stat * st)
 
1029
{
 
1030
    const char * lpath;
 
1031
    int ut = urlPath(path, &lpath);
 
1032
 
 
1033
if (_rpmio_debug)
 
1034
fprintf(stderr, "*** Stat(%s,%p)\n", path, st);
 
1035
    switch (ut) {
 
1036
    case URL_IS_FTP:
 
1037
        return ftpStat(path, st);
 
1038
        /*@notreached@*/ break;
 
1039
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
1040
    case URL_IS_PATH:
 
1041
        path = lpath;
 
1042
        /*@fallthrough@*/
 
1043
    case URL_IS_UNKNOWN:
 
1044
        break;
 
1045
    case URL_IS_DASH:
 
1046
    default:
 
1047
        return -2;
 
1048
        /*@notreached@*/ break;
 
1049
    }
 
1050
    return stat(path, st);
 
1051
}
 
1052
 
 
1053
int Lstat(const char * path, struct stat * st)
 
1054
{
 
1055
    const char * lpath;
 
1056
    int ut = urlPath(path, &lpath);
 
1057
 
 
1058
if (_rpmio_debug)
 
1059
fprintf(stderr, "*** Lstat(%s,%p)\n", path, st);
 
1060
    switch (ut) {
 
1061
    case URL_IS_FTP:
 
1062
        return ftpLstat(path, st);
 
1063
        /*@notreached@*/ break;
 
1064
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
1065
    case URL_IS_PATH:
 
1066
        path = lpath;
 
1067
        /*@fallthrough@*/
 
1068
    case URL_IS_UNKNOWN:
 
1069
        break;
 
1070
    case URL_IS_DASH:
 
1071
    default:
 
1072
        return -2;
 
1073
        /*@notreached@*/ break;
 
1074
    }
 
1075
    return lstat(path, st);
 
1076
}
 
1077
 
 
1078
int Readlink(const char * path, char * buf, size_t bufsiz)
 
1079
{
 
1080
    const char * lpath;
 
1081
    int ut = urlPath(path, &lpath);
 
1082
 
 
1083
    switch (ut) {
 
1084
    case URL_IS_FTP:
 
1085
        return ftpReadlink(path, buf, bufsiz);
 
1086
        /*@notreached@*/ break;
 
1087
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
1088
    case URL_IS_PATH:
 
1089
        path = lpath;
 
1090
        /*@fallthrough@*/
 
1091
    case URL_IS_UNKNOWN:
 
1092
        break;
 
1093
    case URL_IS_DASH:
 
1094
    default:
 
1095
        return -2;
 
1096
        /*@notreached@*/ break;
 
1097
    }
 
1098
    return readlink(path, buf, bufsiz);
 
1099
}
 
1100
 
 
1101
int Access(const char * path, int amode)
 
1102
{
 
1103
    const char * lpath;
 
1104
    int ut = urlPath(path, &lpath);
 
1105
 
 
1106
if (_rpmio_debug)
 
1107
fprintf(stderr, "*** Access(%s,%d)\n", path, amode);
 
1108
    switch (ut) {
 
1109
    case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
 
1110
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
1111
    case URL_IS_PATH:
 
1112
        path = lpath;
 
1113
        /*@fallthrough@*/
 
1114
    case URL_IS_UNKNOWN:
 
1115
        break;
 
1116
    case URL_IS_DASH:
 
1117
    default:
 
1118
        return -2;
 
1119
        /*@notreached@*/ break;
 
1120
    }
 
1121
    return access(path, amode);
 
1122
}
 
1123
 
 
1124
int Glob(const char *path, int flags,
 
1125
        int errfunc(const char * epath, int eerrno), glob_t *pglob)
 
1126
{
 
1127
    const char * lpath;
 
1128
    int ut = urlPath(path, &lpath);
 
1129
 
 
1130
/*@-castfcnptr@*/
 
1131
if (_rpmio_debug)
 
1132
fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", path, (unsigned)flags, (void *)errfunc, pglob);
 
1133
/*@=castfcnptr@*/
 
1134
    switch (ut) {
 
1135
    case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
 
1136
        return ftpGlob(path, flags, errfunc, pglob);
 
1137
        /*@notreached@*/ break;
 
1138
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
1139
    case URL_IS_PATH:
 
1140
        path = lpath;
 
1141
        /*@fallthrough@*/
 
1142
    case URL_IS_UNKNOWN:
 
1143
        break;
 
1144
    case URL_IS_DASH:
 
1145
    default:
 
1146
        return -2;
 
1147
        /*@notreached@*/ break;
 
1148
    }
 
1149
    return glob(path, flags, errfunc, pglob);
 
1150
}
 
1151
 
 
1152
void Globfree(glob_t *pglob)
 
1153
{
 
1154
if (_rpmio_debug)
 
1155
fprintf(stderr, "*** Globfree(%p)\n", pglob);
 
1156
    if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */
 
1157
        ftpGlobfree(pglob);
 
1158
    else
 
1159
        globfree(pglob);
 
1160
}
 
1161
 
 
1162
DIR * Opendir(const char * path)
 
1163
{
 
1164
    const char * lpath;
 
1165
    int ut = urlPath(path, &lpath);
 
1166
 
 
1167
if (_rpmio_debug)
 
1168
fprintf(stderr, "*** Opendir(%s)\n", path);
 
1169
    switch (ut) {
 
1170
    case URL_IS_FTP:            /* XXX WRONG WRONG WRONG */
 
1171
    case URL_IS_HTTP:           /* XXX WRONG WRONG WRONG */
 
1172
    case URL_IS_PATH:
 
1173
        path = lpath;
 
1174
        /*@fallthrough@*/
 
1175
    case URL_IS_UNKNOWN:
 
1176
        break;
 
1177
    case URL_IS_DASH:
 
1178
    default:
 
1179
        return NULL;
 
1180
        /*@notreached@*/ break;
 
1181
    }
 
1182
    return opendir(path);
 
1183
}
 
1184
 
 
1185
/*@+voidabstract@*/
 
1186
struct dirent * Readdir(DIR * dir)
 
1187
{
 
1188
if (_rpmio_debug)
 
1189
fprintf(stderr, "*** Readdir(%p)\n", (void *)dir);
 
1190
    return readdir(dir);
 
1191
}
 
1192
 
 
1193
int Closedir(DIR * dir)
 
1194
{
 
1195
if (_rpmio_debug)
 
1196
fprintf(stderr, "*** Closedir(%p)\n", (void *)dir);
 
1197
    return closedir(dir);
 
1198
}
 
1199
/*@=voidabstract@*/