Main Page Modules Data Structures File List Data Fields Globals Related Pages

# lib/cpio.c

Go to the documentation of this file.

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