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

# lib/cpio.c

Go to the documentation of this file.

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