• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 }

Generated on Mon Nov 29 2010 05:18:42 for rpm by  doxygen 1.7.2