rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

rpmio/ar.c
Go to the documentation of this file.

    00001
    00006 #undef  JBJ_WRITEPAD
    00007
    00008 #include "system.h"
    00009
    00010 #include <rpmio_internal.h>     /* XXX fdGetCpioPos writing AR_MAGIC */
    00011
    00012 #include <rpmmacro.h>
    00013 #include <ugid.h>
    00014 #include <ar.h>
    00015 #define _IOSM_INTERNAL
    00016 #include <iosm.h>
    00017
    00018 #include "debug.h"
    00019
    00020 /*@access IOSM_t @*/
    00021
    00022 /*@unchecked@*/
    00023 int _ar_debug = 0;
    00024
    00033 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr,
    00034                 int base, size_t num)
    00035         /*@modifies *endptr @*/
    00036 {
    00037     char * buf, * end;
    00038     unsigned long ret;
    00039
    00040     buf = alloca(num + 1);
    00041     strncpy(buf, str, num);
    00042     buf[num] = '\0';
    00043
    00044     ret = strtoul(buf, &end, base);
    00045     if (endptr != NULL) {
    00046         if (*end != '\0')
    00047             *endptr = ((char *)str) + (end - buf);      /* XXX discards const */
    00048         else
    00049             *endptr = ((char *)str) + strlen(buf);
    00050     }
    00051
    00052     return ret;
    00053 }
    00054
    00055 /* Translate archive read/write ssize_t return for iosmStage(). */
    00056 #define _IOSMRC(_rc)    \
    00057         if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER)
    00058
    00059 static ssize_t arRead(void * _iosm, void * buf, size_t count)
    00060         /*@globals fileSystem @*/
    00061         /*@modifies _iosm, *buf, fileSystem @*/
    00062 {
    00063     IOSM_t iosm = _iosm;
    00064     char * t = buf;
    00065     size_t nb = 0;
    00066     size_t rc;
    00067
    00068 if (_ar_debug)
    00069 fprintf(stderr, "\t  arRead(%p, %p[%u])\n", iosm, buf, (unsigned)count);
    00070
    00071     while (count > 0) {
    00072
    00073         /* Read next ar block. */
    00074         iosm->wrlen = count;
    00075         rc = _iosmNext(iosm, IOSM_DREAD);
    00076         if (!rc && iosm->rdnb != iosm->wrlen) {
    00077             if (iosm->rdnb == 0) return -IOSMERR_HDR_TRAILER;   /* EOF */
    00078             rc = IOSMERR_READ_FAILED;
    00079         }
    00080         if (rc) return -rc;
    00081
    00082         /* Append to buffer. */
    00083         rc = (count > iosm->rdnb ? iosm->rdnb : count);
    00084         if (buf != iosm->wrbuf)
    00085              memcpy(t + nb, iosm->wrbuf, rc);
    00086         nb += rc;
    00087         count -= rc;
    00088     }
    00089     return nb;
    00090 }
    00091
    00092 int arHeaderRead(void * _iosm, struct stat * st)
    00093         /*@modifies _iosm, *st @*/
    00094 {
    00095     IOSM_t iosm = _iosm;
    00096     arHeader hdr = (arHeader) iosm->wrbuf;
    00097     ssize_t rc = 0;
    00098
    00099 if (_ar_debug)
    00100 fprintf(stderr, "    arHeaderRead(%p, %p)\n", iosm, st);
    00101
    00102     /* XXX Read AR_MAGIC to beginning of ar(1) archive. */
    00103     if (fdGetCpioPos(iosm->cfd) == 0) {
    00104         rc = arRead(iosm, iosm->wrbuf, sizeof(AR_MAGIC)-1);
    00105         _IOSMRC(rc);
    00106
    00107         /* Verify archive magic. */
    00108         if (strncmp(iosm->wrbuf, AR_MAGIC, sizeof(AR_MAGIC)-1))
    00109             return IOSMERR_BAD_MAGIC;
    00110     }
    00111
    00112 top:
    00113     /* Make sure block aligned. */
    00114     rc = _iosmNext(iosm, IOSM_POS);
    00115     if (rc) return (int) rc;
    00116
    00117     rc = arRead(iosm, hdr, sizeof(*hdr));
    00118     _IOSMRC(rc);
    00119 if (_ar_debug)
    00120 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr)-2, (char *)hdr);
    00121
    00122     /* Verify header marker. */
    00123     if (strncmp(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1))
    00124         return IOSMERR_BAD_MAGIC;
    00125
    00126     st->st_size = strntoul(hdr->filesize, NULL, 10, sizeof(hdr->filesize));
    00127
    00128     /* Special ar(1) archive members. */
    00129     if (hdr->name[0] == '/') {
    00130         /* GNU: on "//":        Read long member name string table. */
    00131         if (hdr->name[1] == '/' && hdr->name[2] == ' ') {
    00132             char * t;
    00133             size_t i;
    00134
    00135             rc = arRead(iosm, iosm->wrbuf, st->st_size);
    00136             _IOSMRC(rc);
    00137
    00138             iosm->wrbuf[rc] = '\0';
    00139             iosm->lmtab = t = xstrdup(iosm->wrbuf);
    00140             iosm->lmtablen = rc;
    00141             iosm->lmtaboff = 0;
    00142
    00143             for (i = 1; i < iosm->lmtablen; i++) {
    00144                 t++;
    00145                 if (t[0] != '\n') continue;
    00146                 t[0] = '\0';
    00147                 /* GNU: trailing '/' to permit file names with trailing ' '. */
    00148                 if (t[-1] == '/') t[-1] = '\0';
    00149             }
    00150             goto top;
    00151         }
    00152         /* GNU: on "/": Skip symbol table. */
    00153         if (hdr->name[1] == ' ') {
    00154             rc = arRead(iosm, iosm->wrbuf, st->st_size);
    00155             _IOSMRC(rc);
    00156             goto top;
    00157         }
    00158         /* GNU: on "/123": Read "123" offset to substitute long member name. */
    00159         if (xisdigit((int)hdr->name[1])) {
    00160             char * te = NULL;
    00161             int i = strntoul(&hdr->name[1], &te, 10, sizeof(hdr->name)-2);
    00162             if (*te == ' ' && iosm->lmtab != NULL && i < (int)iosm->lmtablen)
    00163                 iosm->path = xstrdup(iosm->lmtab + i);
    00164         }
    00165     } else
    00166     if (hdr->name[0] != ' ') {  /* Short member name. */
    00167         size_t nb = sizeof(hdr->name);
    00168         char t[sizeof(hdr->name)+1];
    00169         memcpy(t, hdr->name, nb);
    00170         t[nb] = '\0';
    00171         while (nb > 0 && t[nb-1] == ' ')
    00172             t[--nb] = '\0';
    00173         /* GNU: trailing '/' to permit file names with trailing ' '. */
    00174         if (nb > 0 && t[nb - 1] == '/')
    00175             t[--nb] = '\0';
    00176         iosm->path = xstrdup(t);
    00177     }
    00178
    00179     st->st_mtime = strntoul(hdr->mtime, NULL, 10, sizeof(hdr->mtime));
    00180     st->st_ctime = st->st_atime = st->st_mtime;
    00181
    00182     st->st_uid = strntoul(hdr->uid, NULL, 10, sizeof(hdr->uid));
    00183     st->st_gid = strntoul(hdr->gid, NULL, 10, sizeof(hdr->gid));
    00184
    00185     st->st_mode = strntoul(hdr->mode, NULL, 8, sizeof(hdr->mode));
    00186
    00187     st->st_nlink = 1;
    00188     rc = 0;
    00189
    00190 if (_ar_debug)
    00191 fprintf(stderr, "\t     %06o%3d (%4d,%4d)%12lu %s\n",
    00192                 (unsigned)st->st_mode, (int)st->st_nlink,
    00193                 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
    00194                 (iosm->path ? iosm->path : ""));
    00195
    00196     return (int) rc;
    00197 }
    00198
    00199 static ssize_t arWrite(void * _iosm, const void *buf, size_t count)
    00200         /*@globals fileSystem @*/
    00201         /*@modifies _iosm, fileSystem @*/
    00202 {
    00203     IOSM_t iosm = _iosm;
    00204     const char * s = buf;
    00205     size_t nb = 0;
    00206     size_t rc;
    00207
    00208 if (_ar_debug)
    00209 fprintf(stderr, "\tarWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count);
    00210
    00211     while (count > 0) {
    00212
    00213         /* XXX DWRITE uses rdnb for I/O length. */
    00214         iosm->rdnb = count;
    00215         if (s != iosm->rdbuf)
    00216             memmove(iosm->rdbuf, s + nb, iosm->rdnb);
    00217
    00218         rc = _iosmNext(iosm, IOSM_DWRITE);
    00219         if (!rc && iosm->rdnb != iosm->wrnb)
    00220                 rc = IOSMERR_WRITE_FAILED;
    00221         if (rc) return -rc;
    00222
    00223         nb += iosm->rdnb;
    00224         count -= iosm->rdnb;
    00225     }
    00226
    00227 #if defined(JBJ_WRITEPAD)
    00228     /* Pad to next block boundary. */
    00229     if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return -rc;
    00230 #endif
    00231
    00232     return nb;
    00233 }
    00234
    00235 int arHeaderWrite(void * _iosm, struct stat * st)
    00236 {
    00237     IOSM_t iosm = _iosm;
    00238     arHeader hdr = (arHeader) iosm->rdbuf;
    00239     size_t nb;
    00240     ssize_t rc = 0;
    00241
    00242 if (_ar_debug)
    00243 fprintf(stderr, "    arHeaderWrite(%p, %p)\n", iosm, st);
    00244
    00245     /* At beginning of ar(1) archive, write magic and long member table. */
    00246     if (fdGetCpioPos(iosm->cfd) == 0) {
    00247         /* Write ar(1) magic. */
    00248         rc = arWrite(iosm, AR_MAGIC, sizeof(AR_MAGIC)-1);
    00249         _IOSMRC(rc);
    00250         /* GNU: on "//":        Write long member name string table. */
    00251         if (iosm->lmtab != NULL) {
    00252             memset(hdr, (int) ' ', sizeof(*hdr));
    00253             hdr->name[0] = '/';
    00254             hdr->name[1] = '/';
    00255             sprintf(hdr->filesize, "%-10d", (unsigned) (iosm->lmtablen & 037777777777));
    00256             strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
    00257
    00258             rc = arWrite(iosm, hdr, sizeof(*hdr));
    00259             _IOSMRC(rc);
    00260             rc = arWrite(iosm, iosm->lmtab, iosm->lmtablen);
    00261             _IOSMRC(rc);
    00262 #if !defined(JBJ_WRITEPAD)
    00263             rc = _iosmNext(iosm, IOSM_PAD);
    00264             if (rc) return (int)rc;
    00265 #endif
    00266         }
    00267     }
    00268
    00269     memset(hdr, (int)' ', sizeof(*hdr));
    00270
    00271     nb = strlen(iosm->path);
    00272     if (nb >= sizeof(hdr->name)) {
    00273         const char * t;
    00274         const char * te;
    00275 assert(iosm->lmtab != NULL);
    00276         t = iosm->lmtab + iosm->lmtaboff;
    00277         te = strchr(t, '\n');
    00278         /* GNU: on "/123": Write "/123" offset for long member name. */
    00279         nb = snprintf(hdr->name, sizeof(hdr->name)-1, "/%u", (unsigned)iosm->lmtaboff);
    00280         hdr->name[nb] = ' ';
    00281         if (te != NULL)
    00282             iosm->lmtaboff += (te - t) + 1;
    00283     } else {
    00284         strncpy(hdr->name, iosm->path, nb);
    00285         hdr->name[nb] = '/';
    00286     }
    00287
    00288     sprintf(hdr->mtime, "%-12u", (unsigned) (st->st_mtime & 037777777777));
    00289     sprintf(hdr->uid, "%-6u", (unsigned int)(st->st_uid & 07777777));
    00290     sprintf(hdr->gid, "%-6u", (unsigned int)(st->st_gid & 07777777));
    00291
    00292     sprintf(hdr->mode, "%-8o", (unsigned int)(st->st_mode & 07777777));
    00293     sprintf(hdr->filesize, "%-10u", (unsigned) (st->st_size & 037777777777));
    00294
    00295     strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
    00296
    00297 rc = (int) sizeof(*hdr);
    00298 if (_ar_debug)
    00299 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr), (char *)hdr);
    00300
    00301     rc = arWrite(iosm, hdr, sizeof(*hdr));
    00302     _IOSMRC(rc);
    00303     rc = 0;
    00304
    00305     return (int) rc;
    00306 }
    00307
    00308 int arTrailerWrite(void * _iosm)
    00309 {
    00310     IOSM_t iosm = _iosm;
    00311     size_t rc = 0;
    00312
    00313 if (_ar_debug)
    00314 fprintf(stderr, "    arTrailerWrite(%p)\n", iosm);
    00315
    00316 #if defined(JBJ_WRITEPAD)
    00317     rc = arWrite(iosm, NULL, 0);        /* XXX _iosmNext(iosm, IOSM_PAD) */
    00318     _IOSMRC(rc);
    00319 #else
    00320     rc = _iosmNext(iosm, IOSM_PAD);     /* XXX likely unnecessary. */
    00321 #endif
    00322
    00323     return (int) rc;
    00324 }