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 = fsmNext(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 = fsmNext(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 = fsmNext(fsm, FSM_DWRITE);
00123     if (!rc && fsm->rdnb != fsm->wrnb)
00124         rc = CPIOERR_WRITE_FAILED;
00125     if (!rc)
00126         rc = fsmNext(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 = fsmNext(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 = fsmNext(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     case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon";    break;
00232 
00233     case CPIOERR_HDR_SIZE:      s = _("Header size too big");   break;
00234     case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type");  break;
00235     case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
00236     case CPIOERR_MD5SUM_MISMATCH: s = _("MD5 sum mismatch");    break;
00237     case CPIOERR_INTERNAL:      s = _("Internal error");        break;
00238     case CPIOERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
00239     case CPIOERR_ENOENT:        s = strerror(ENOENT); break;
00240     case CPIOERR_ENOTEMPTY:     s = strerror(ENOTEMPTY); break;
00241     }
00242     /*@=branchstate@*/
00243 
00244     l = sizeof(msg) - strlen(msg) - 1;
00245     if (s != NULL) {
00246         if (l > 0) strncat(msg, s, l);
00247         l -= strlen(s);
00248     }
00249     /*@-branchstate@*/
00250     if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
00251         s = _(" failed - ");
00252         if (l > 0) strncat(msg, s, l);
00253         l -= strlen(s);
00254         if (l > 0) strncat(msg, strerror(myerrno), l);
00255     }
00256     /*@=branchstate@*/
00257     return msg;
00258 }

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2