rpm
4.5
|
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 }