# lib/cpio.c

Go to the documentation of this file.

    00001
    00010 #include "system.h"
    00011
    00012 #include "fsm.h"
    00013 #include "rpmerr.h"
    00014 #include "debug.h"
    00015
    00016 /*@access FSM_t @*/
    00017
    00018 /*@-exportheadervar@*/
    00019 extern int _fsm_debug;
    00020 /*@=exportheadervar@*/
    00021
    00030 static int strntoul(const char *str, /*@out@*/char **endptr, int base, int num)
    00031         /*@modifies *endptr @*/
    00032 {
    00033     char * buf, * end;
    00034     unsigned long ret;
    00035
    00036     buf = alloca(num + 1);
    00037     strncpy(buf, str, num);
    00038     buf[num] = '\0';
    00039
    00040     ret = strtoul(buf, &end, base);
    00041     if (*end != '\0')
    00042         *endptr = ((char *)str) + (end - buf);  /* XXX discards const */
    00043     else
    00044         *endptr = ((char *)str) + strlen(buf);
    00045
    00046     return ret;
    00047 }
    00048
    00049 #define GET_NUM_FIELD(phys, log) \
    00050         log = strntoul(phys, &end, 16, sizeof(phys)); \
    00051         if ( (end - phys) != sizeof(phys) ) return CPIOERR_BAD_HEADER;
    00052 #define SET_NUM_FIELD(phys, val, space) \
    00053         sprintf(space, "%8.8lx", (unsigned long) (val)); \
    00054         memcpy(phys, space, 8);
    00055
    00056 int cpioTrailerWrite(FSM_t fsm)
    00057 {
    00058     struct cpioCrcPhysicalHeader * hdr =
    00059         (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
    00060     int rc;
    00061
    00062     memset(hdr, '0', PHYS_HDR_SIZE);
    00063     memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
    00064     memcpy(hdr->nlink, "00000001", 8);
    00065     memcpy(hdr->namesize, "0000000b", 8);
    00066     memcpy(fsm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, sizeof(CPIO_TRAILER));
    00067
    00068     /* XXX DWRITE uses rdnb for I/O length. */
    00069     fsm->rdnb = PHYS_HDR_SIZE + sizeof(CPIO_TRAILER);
    00070     rc = fsmStage(fsm, FSM_DWRITE);
    00071
    00072     /*
    00073      * GNU cpio pads to 512 bytes here, but we don't. This may matter for
    00074      * tape device(s) and/or concatenated cpio archives. <shrug>
    00075      */
    00076     if (!rc)
    00077         rc = fsmStage(fsm, FSM_PAD);
    00078
    00079     return rc;
    00080 }
    00081
    00082 int cpioHeaderWrite(FSM_t fsm, struct stat * st)
    00083 {
    00084     struct cpioCrcPhysicalHeader * hdr = (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
    00085     char field[64];
    00086     size_t len;
    00087     dev_t dev;
    00088     int rc = 0;
    00089
    00090     memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
    00091     SET_NUM_FIELD(hdr->inode, st->st_ino, field);
    00092     SET_NUM_FIELD(hdr->mode, st->st_mode, field);
    00093     SET_NUM_FIELD(hdr->uid, st->st_uid, field);
    00094     SET_NUM_FIELD(hdr->gid, st->st_gid, field);
    00095     SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
    00096     SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
    00097     SET_NUM_FIELD(hdr->filesize, st->st_size, field);
    00098
    00099     dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
    00100     dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
    00101     dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
    00102     dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
    00103
    00104     len = strlen(fsm->path) + 1; SET_NUM_FIELD(hdr->namesize, len, field);
    00105     memcpy(hdr->checksum, "00000000", 8);
    00106     memcpy(fsm->rdbuf + PHYS_HDR_SIZE, fsm->path, len);
    00107
    00108     /* XXX DWRITE uses rdnb for I/O length. */
    00109     fsm->rdnb = PHYS_HDR_SIZE + len;
    00110     rc = fsmStage(fsm, FSM_DWRITE);
    00111     if (!rc && fsm->rdnb != fsm->wrnb)
    00112         rc = CPIOERR_WRITE_FAILED;
    00113     if (!rc)
    00114         rc = fsmStage(fsm, FSM_PAD);
    00115     return rc;
    00116 }
    00117
    00118 int cpioHeaderRead(FSM_t fsm, struct stat * st)
    00119         /*@modifies fsm, *st @*/
    00120 {
    00121     struct cpioCrcPhysicalHeader hdr;
    00122     int nameSize;
    00123     char * end;
    00124     int major, minor;
    00125     int rc = 0;
    00126
    00127     fsm->wrlen = PHYS_HDR_SIZE;
    00128     rc = fsmStage(fsm, FSM_DREAD);
    00129     if (!rc && fsm->rdnb != fsm->wrlen)
    00130         rc = CPIOERR_READ_FAILED;
    00131     if (rc) return rc;
    00132     memcpy(&hdr, fsm->wrbuf, fsm->rdnb);
    00133
    00134     if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
    00135         strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1))
    00136         return CPIOERR_BAD_MAGIC;
    00137
    00138     GET_NUM_FIELD(hdr.inode, st->st_ino);
    00139     GET_NUM_FIELD(hdr.mode, st->st_mode);
    00140     GET_NUM_FIELD(hdr.uid, st->st_uid);
    00141     GET_NUM_FIELD(hdr.gid, st->st_gid);
    00142     GET_NUM_FIELD(hdr.nlink, st->st_nlink);
    00143     GET_NUM_FIELD(hdr.mtime, st->st_mtime);
    00144     GET_NUM_FIELD(hdr.filesize, st->st_size);
    00145
    00146     GET_NUM_FIELD(hdr.devMajor, major);
    00147     GET_NUM_FIELD(hdr.devMinor, minor);
    00148     /*@-shiftimplementation@*/
    00149     st->st_dev = makedev(major, minor);
    00150     /*@=shiftimplementation@*/
    00151
    00152     GET_NUM_FIELD(hdr.rdevMajor, major);
    00153     GET_NUM_FIELD(hdr.rdevMinor, minor);
    00154     /*@-shiftimplementation@*/
    00155     st->st_rdev = makedev(major, minor);
    00156     /*@=shiftimplementation@*/
    00157
    00158     GET_NUM_FIELD(hdr.namesize, nameSize);
    00159     if (nameSize >= fsm->wrsize)
    00160         return CPIOERR_BAD_HEADER;
    00161
    00162     {   char * t = xmalloc(nameSize + 1);
    00163         fsm->wrlen = nameSize;
    00164         rc = fsmStage(fsm, FSM_DREAD);
    00165         if (!rc && fsm->rdnb != fsm->wrlen)
    00166             rc = CPIOERR_BAD_HEADER;
    00167         if (rc) {
    00168             t = _free(t);
    00169             fsm->path = NULL;
    00170             return rc;
    00171         }
    00172         memcpy(t, fsm->wrbuf, fsm->rdnb);
    00173         t[nameSize] = '\0';
    00174         fsm->path = t;
    00175     }
    00176
    00177     return 0;
    00178 }
    00179
    00180 const char *const cpioStrerror(int rc)
    00181 {
    00182     static char msg[256];
    00183     char *s;
    00184     int l, myerrno = errno;
    00185
    00186     strcpy(msg, "cpio: ");
    00187     /*@-branchstate@*/
    00188     switch (rc) {
    00189     default:
    00190         s = msg + strlen(msg);
    00191         sprintf(s, _("(error 0x%x)"), (unsigned)rc);
    00192         s = NULL;
    00193         break;
    00194     case CPIOERR_BAD_MAGIC:     s = _("Bad magic");             break;
    00195     case CPIOERR_BAD_HEADER:    s = _("Bad/unreadable  header");break;
    00196
    00197     case CPIOERR_OPEN_FAILED:   s = "open";     break;
    00198     case CPIOERR_CHMOD_FAILED:  s = "chmod";    break;
    00199     case CPIOERR_CHOWN_FAILED:  s = "chown";    break;
    00200     case CPIOERR_WRITE_FAILED:  s = "write";    break;
    00201     case CPIOERR_UTIME_FAILED:  s = "utime";    break;
    00202     case CPIOERR_UNLINK_FAILED: s = "unlink";   break;
    00203     case CPIOERR_RENAME_FAILED: s = "rename";   break;
    00204     case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
    00205     case CPIOERR_STAT_FAILED:   s = "stat";     break;
    00206     case CPIOERR_LSTAT_FAILED:  s = "lstat";    break;
    00207     case CPIOERR_MKDIR_FAILED:  s = "mkdir";    break;
    00208     case CPIOERR_RMDIR_FAILED:  s = "rmdir";    break;
    00209     case CPIOERR_MKNOD_FAILED:  s = "mknod";    break;
    00210     case CPIOERR_MKFIFO_FAILED: s = "mkfifo";   break;
    00211     case CPIOERR_LINK_FAILED:   s = "link";     break;
    00212     case CPIOERR_READLINK_FAILED: s = "readlink";       break;
    00213     case CPIOERR_READ_FAILED:   s = "read";     break;
    00214     case CPIOERR_COPY_FAILED:   s = "copy";     break;
    00215
    00216     case CPIOERR_HDR_SIZE:      s = _("Header size too big");   break;
    00217     case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type");  break;
    00218     case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
    00219     case CPIOERR_MD5SUM_MISMATCH: s = _("MD5 sum mismatch");    break;
    00220     case CPIOERR_INTERNAL:      s = _("Internal error");        break;
    00221     case CPIOERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
    00222     }
    00223     /*@=branchstate@*/
    00224
    00225     l = sizeof(msg) - strlen(msg) - 1;
    00226     if (s != NULL) {
    00227         if (l > 0) strncat(msg, s, l);
    00228         l -= strlen(s);
    00229     }
    00230     /*@-branchstate@*/
    00231     if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
    00232         s = _(" failed - ");
    00233         if (l > 0) strncat(msg, s, l);
    00234         l -= strlen(s);
    00235         if (l > 0) strncat(msg, strerror(myerrno), l);
    00236     }
    00237     /*@=branchstate@*/
    00238     return msg;
    00239 }