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

Generated on Fri Aug 31 10:38:31 2007 for rpm by  doxygen 1.5.1