rpm 5.2.1

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

- File List
- Globals

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

    00001
    00005 #undef  JBJ_WRITEPAD
    00006
    00007 #include "system.h"
    00008
    00009 #include <rpmio.h>
    00010 #include <ugid.h>
    00011 #include <cpio.h>
    00012 #define _IOSM_INTERNAL
    00013 #include <iosm.h>
    00014
    00015 #include "debug.h"
    00016
    00017 /*@access IOSM_t @*/
    00018
    00019 /*@unchecked@*/
    00020 int _cpio_debug = 0;
    00021
    00030 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr,
    00031                 int base, size_t num)
    00032         /*@modifies *endptr @*/
    00033         /*@requires maxSet(endptr) >= 0 @*/
    00034 {
    00035     char * buf, * end;
    00036     unsigned long ret;
    00037
    00038     buf = alloca(num + 1);
    00039     strncpy(buf, str, num);
    00040     buf[num] = '\0';
    00041
    00042     ret = strtoul(buf, &end, base);
    00043     if (endptr != NULL) {
    00044         if (*end != '\0')
    00045             *endptr = ((char *)str) + (end - buf);      /* XXX discards const */
    00046         else
    00047             *endptr = ((char *)str) + strlen(buf);
    00048     }
    00049
    00050     return ret;
    00051 }
    00052
    00053 /* Translate archive read/write ssize_t return for iosmStage(). */
    00054 #define _IOSMRC(_rc)    \
    00055         if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER)
    00056
    00057 static ssize_t cpioRead(void * _iosm, void * buf, size_t count)
    00058         /*@globals fileSystem @*/
    00059         /*@modifies _iosm, *buf, fileSystem @*/
    00060 {
    00061     IOSM_t iosm = _iosm;
    00062     char * t = buf;
    00063     size_t nb = 0;
    00064     size_t rc;
    00065
    00066 if (_cpio_debug)
    00067 fprintf(stderr, "          cpioRead(%p, %p[%u])\n", iosm, buf, (unsigned)count);
    00068
    00069     while (count > 0) {
    00070
    00071         /* Read next cpio block. */
    00072         iosm->wrlen = count;
    00073         rc = _iosmNext(iosm, IOSM_DREAD);
    00074         if (!rc && iosm->rdnb != iosm->wrlen)
    00075             rc = IOSMERR_READ_FAILED;
    00076         if (rc) return -rc;
    00077
    00078         /* Append to buffer. */
    00079         rc = (count > iosm->rdnb ? iosm->rdnb : count);
    00080         if (buf != iosm->wrbuf)
    00081              memcpy(t + nb, iosm->wrbuf, rc);
    00082         nb += rc;
    00083         count -= rc;
    00084     }
    00085     return nb;
    00086 }
    00087
    00088 #define GET_NUM_FIELD(phys, log) \
    00089         log = strntoul(phys, &end, 16, sizeof(phys)); \
    00090         if ( (end - phys) != sizeof(phys) ) return IOSMERR_BAD_HEADER;
    00091 #define SET_NUM_FIELD(phys, val, space) \
    00092         sprintf(space, "%8.8lx", (unsigned long) (val)); \
    00093         memcpy(phys, space, 8)
    00094
    00095 int cpioHeaderRead(void * _iosm, struct stat * st)
    00096 {
    00097     IOSM_t iosm = _iosm;
    00098     cpioHeader hdr = (cpioHeader) iosm->wrbuf;
    00099     size_t nb;
    00100     char * end;
    00101     int major, minor;
    00102     ssize_t rc = 0;
    00103
    00104 if (_cpio_debug)
    00105 fprintf(stderr, "    cpioHeaderRead(%p, %p)\n", iosm, st);
    00106
    00107     /* Read next header. */
    00108     rc = cpioRead(iosm, hdr, PHYS_HDR_SIZE);
    00109     _IOSMRC(rc);
    00110
    00111     /* Verify header magic. */
    00112     if (strncmp(CPIO_CRC_MAGIC, hdr->magic, sizeof(CPIO_CRC_MAGIC)-1) &&
    00113         strncmp(CPIO_NEWC_MAGIC, hdr->magic, sizeof(CPIO_NEWC_MAGIC)-1))
    00114         return IOSMERR_BAD_MAGIC;
    00115
    00116     /* Convert header to stat(2). */
    00117     GET_NUM_FIELD(hdr->inode, st->st_ino);
    00118     GET_NUM_FIELD(hdr->mode, st->st_mode);
    00119     GET_NUM_FIELD(hdr->uid, st->st_uid);
    00120     GET_NUM_FIELD(hdr->gid, st->st_gid);
    00121     GET_NUM_FIELD(hdr->nlink, st->st_nlink);
    00122     GET_NUM_FIELD(hdr->mtime, st->st_mtime);
    00123     GET_NUM_FIELD(hdr->filesize, st->st_size);
    00124
    00125     GET_NUM_FIELD(hdr->devMajor, major);
    00126     GET_NUM_FIELD(hdr->devMinor, minor);
    00127     /*@-shiftimplementation@*/
    00128     st->st_dev = Makedev(major, minor);
    00129     /*@=shiftimplementation@*/
    00130
    00131     GET_NUM_FIELD(hdr->rdevMajor, major);
    00132     GET_NUM_FIELD(hdr->rdevMinor, minor);
    00133     /*@-shiftimplementation@*/
    00134     st->st_rdev = Makedev(major, minor);
    00135     /*@=shiftimplementation@*/
    00136
    00137     GET_NUM_FIELD(hdr->namesize, nb);
    00138     if (nb >= iosm->wrsize)
    00139         return IOSMERR_BAD_HEADER;
    00140
    00141     /* Read file name. */
    00142     {   char * t = xmalloc(nb + 1);
    00143         rc = cpioRead(iosm, t, nb);
    00144         if (rc < 0) {
    00145             t = _free(t);
    00146             iosm->path = NULL;
    00147         } else {
    00148             _IOSMRC(rc);
    00149             t[nb] = '\0';
    00150             iosm->path = t;
    00151         }
    00152     }
    00153
    00154     /* Read link name. */
    00155     if (S_ISLNK(st->st_mode)) {
    00156         char * t;
    00157
    00158         /* Make sure block aligned. */
    00159         rc = _iosmNext(iosm, IOSM_POS);
    00160         if (rc) return (int) -rc;
    00161
    00162         nb = (size_t) st->st_size;
    00163         t = xmalloc(nb + 1);
    00164         rc = cpioRead(iosm, t, nb);
    00165         if (rc < 0) {
    00166             t = _free(t);
    00167             iosm->lpath = NULL;
    00168         } else {
    00169             _IOSMRC(rc);
    00170             t[nb] = '\0';
    00171             iosm->lpath = t;
    00172         }
    00173     }
    00174
    00175     rc = 0;
    00176
    00177 /*@-usereleased@*/
    00178 if (_cpio_debug)
    00179 fprintf(stderr, "\t     %06o%3d (%4d,%4d)%12lu %s\n\t-> %s\n",
    00180                 (unsigned)st->st_mode, (int)st->st_nlink,
    00181                 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
    00182                 (iosm->path ? iosm->path : ""), (iosm->lpath ? iosm->lpath : ""));
    00183 /*@=usereleased@*/
    00184
    00185     return (int) rc;
    00186 }
    00187
    00188 static ssize_t cpioWrite(void * _iosm, const void *buf, size_t count)
    00189         /*@globals fileSystem @*/
    00190         /*@modifies _iosm, fileSystem @*/
    00191 {
    00192     IOSM_t iosm = _iosm;
    00193     const char * s = buf;
    00194     size_t nb = 0;
    00195     size_t rc;
    00196
    00197 if (_cpio_debug)
    00198 fprintf(stderr, "\t  cpioWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count);
    00199
    00200     while (count > 0) {
    00201
    00202         /* XXX DWRITE uses rdnb for I/O length. */
    00203         iosm->rdnb = count;
    00204         if (s != iosm->rdbuf)
    00205             memmove(iosm->rdbuf, s + nb, iosm->rdnb);
    00206
    00207         rc = _iosmNext(iosm, IOSM_DWRITE);
    00208         if (!rc && iosm->rdnb != iosm->wrnb)
    00209                 rc = IOSMERR_WRITE_FAILED;
    00210         if (rc) return -rc;
    00211
    00212         nb += iosm->rdnb;
    00213         count -= iosm->rdnb;
    00214     }
    00215
    00216 #if defined(JBJ_WRITEPAD)
    00217     /* Pad to next block boundary. */
    00218     if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return -rc;
    00219 #endif
    00220
    00221     return nb;
    00222 }
    00223
    00224 int cpioHeaderWrite(void * _iosm, struct stat * st)
    00225 {
    00226     IOSM_t iosm = _iosm;
    00227     cpioHeader hdr = (cpioHeader) iosm->rdbuf;
    00228     char field[64];
    00229     size_t nb;
    00230     dev_t dev;
    00231     ssize_t rc = 0;
    00232
    00233 if (_cpio_debug)
    00234 fprintf(stderr, "    cpioHeaderWrite(%p, %p)\n", iosm, st);
    00235
    00236     memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
    00237     SET_NUM_FIELD(hdr->inode, st->st_ino, field);
    00238     SET_NUM_FIELD(hdr->mode, st->st_mode, field);
    00239     SET_NUM_FIELD(hdr->uid, st->st_uid, field);
    00240     SET_NUM_FIELD(hdr->gid, st->st_gid, field);
    00241     SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
    00242     SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
    00243     SET_NUM_FIELD(hdr->filesize, st->st_size, field);
    00244
    00245     dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
    00246     dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
    00247     dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
    00248     dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
    00249
    00250     nb = strlen(iosm->path) + 1; SET_NUM_FIELD(hdr->namesize, nb, field);
    00251     memcpy(hdr->checksum, "00000000", 8);
    00252
    00253     /* XXX Coalesce hdr+name into single I/O. */
    00254     memcpy(iosm->rdbuf + PHYS_HDR_SIZE, iosm->path, nb);
    00255     nb += PHYS_HDR_SIZE;
    00256     rc = cpioWrite(iosm, hdr, nb);
    00257     _IOSMRC(rc);
    00258
    00259     if (S_ISLNK(st->st_mode)) {
    00260 assert(iosm->lpath != NULL);
    00261 #if !defined(JBJ_WRITEPAD)
    00262         rc = _iosmNext(iosm, IOSM_PAD);
    00263         if (rc) return (int) rc;
    00264 #endif
    00265
    00266         nb = strlen(iosm->lpath);
    00267         rc = cpioWrite(iosm, iosm->lpath, nb);
    00268         _IOSMRC(rc);
    00269     }
    00270
    00271 #if !defined(JBJ_WRITEPAD)
    00272     rc = _iosmNext(iosm, IOSM_PAD);
    00273 #endif
    00274
    00275     return (int) rc;
    00276 }
    00277
    00278 int cpioTrailerWrite(void * _iosm)
    00279 {
    00280     IOSM_t iosm = _iosm;
    00281     cpioHeader hdr = (cpioHeader) iosm->rdbuf;
    00282     size_t nb;
    00283     ssize_t rc = 0;
    00284
    00285 if (_cpio_debug)
    00286 fprintf(stderr, "   cpioTrailerWrite(%p)\n", iosm);
    00287
    00288     memset(hdr, (int)'0', PHYS_HDR_SIZE);
    00289     memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
    00290     memcpy(hdr->nlink, "00000001", 8);
    00291     memcpy(hdr->namesize, "0000000b", 8);
    00292
    00293     nb = sizeof(CPIO_TRAILER);
    00294     /* XXX Coalesce hdr+trailer into single I/O. */
    00295     memcpy(iosm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, nb);
    00296     nb += PHYS_HDR_SIZE;
    00297
    00298     rc = cpioWrite(iosm, hdr, nb);
    00299     _IOSMRC(rc);
    00300
    00301     /*
    00302      * GNU cpio pads to 512 bytes here, but we don't. This may matter for
    00303      * tape device(s) and/or concatenated cpio archives. <shrug>
    00304      */
    00305 #if !defined(JBJ_WRITEPAD)
    00306     rc = _iosmNext(iosm, IOSM_PAD);
    00307 #endif
    00308     rc = 0;
    00309
    00310     return (int) rc;
    00311 }
    00312