• 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 

Generated on Fri Dec 3 2010 20:54:17 for rpm by  doxygen 1.7.2