rpm 5.3.7
|
00001 00005 #undef JBJ_WRITEPAD 00006 00007 #include "system.h" 00008 00009 #include <rpmio.h> 00010 #include <ugid.h> 00011 #include <cpio.h> 00012 #define _IOSM_INTERNAL 00013 #include <iosm.h> 00014 00015 #include "debug.h" 00016 00017 /*@access IOSM_t @*/ 00018 00019 /*@unchecked@*/ 00020 int _cpio_debug = 0; 00021 00030 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr, 00031 int base, size_t 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 if (endptr != NULL) { 00044 if (*end != '\0') 00045 *endptr = ((char *)str) + (end - buf); /* XXX discards const */ 00046 else 00047 *endptr = ((char *)str) + strlen(buf); 00048 } 00049 00050 return ret; 00051 } 00052 00053 /* Translate archive read/write ssize_t return for iosmStage(). */ 00054 #define _IOSMRC(_rc) \ 00055 if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER) 00056 00057 static ssize_t cpioRead(void * _iosm, void * buf, size_t count) 00058 /*@globals fileSystem @*/ 00059 /*@modifies _iosm, *buf, fileSystem @*/ 00060 { 00061 IOSM_t iosm = _iosm; 00062 char * t = buf; 00063 size_t nb = 0; 00064 size_t rc; 00065 00066 if (_cpio_debug) 00067 fprintf(stderr, " cpioRead(%p, %p[%u])\n", iosm, buf, (unsigned)count); 00068 00069 while (count > 0) { 00070 00071 /* Read next cpio block. */ 00072 iosm->wrlen = count; 00073 rc = _iosmNext(iosm, IOSM_DREAD); 00074 if (!rc && iosm->rdnb != iosm->wrlen) 00075 rc = IOSMERR_READ_FAILED; 00076 if (rc) return -rc; 00077 00078 /* Append to buffer. */ 00079 rc = (count > iosm->rdnb ? iosm->rdnb : count); 00080 if (buf != iosm->wrbuf) 00081 memcpy(t + nb, iosm->wrbuf, rc); 00082 nb += rc; 00083 count -= rc; 00084 } 00085 return nb; 00086 } 00087 00088 #define GET_NUM_FIELD(phys, log) \ 00089 log = strntoul(phys, &end, 16, sizeof(phys)); \ 00090 if ( (end - phys) != sizeof(phys) ) return IOSMERR_BAD_HEADER; 00091 #define SET_NUM_FIELD(phys, val, space) \ 00092 sprintf(space, "%8.8lx", (unsigned long) (val)); \ 00093 memcpy(phys, space, 8) 00094 00095 int cpioHeaderRead(void * _iosm, struct stat * st) 00096 { 00097 IOSM_t iosm = _iosm; 00098 cpioHeader hdr = (cpioHeader) iosm->wrbuf; 00099 size_t nb; 00100 char * end; 00101 int major, minor; 00102 ssize_t rc = 0; 00103 00104 if (_cpio_debug) 00105 fprintf(stderr, " cpioHeaderRead(%p, %p)\n", iosm, st); 00106 00107 /* Read next header. */ 00108 rc = cpioRead(iosm, hdr, PHYS_HDR_SIZE); 00109 _IOSMRC(rc); 00110 00111 /* Verify header magic. */ 00112 if (strncmp(CPIO_CRC_MAGIC, hdr->magic, sizeof(CPIO_CRC_MAGIC)-1) && 00113 strncmp(CPIO_NEWC_MAGIC, hdr->magic, sizeof(CPIO_NEWC_MAGIC)-1)) 00114 return IOSMERR_BAD_MAGIC; 00115 00116 /* Convert header to stat(2). */ 00117 GET_NUM_FIELD(hdr->inode, st->st_ino); 00118 GET_NUM_FIELD(hdr->mode, st->st_mode); 00119 GET_NUM_FIELD(hdr->uid, st->st_uid); 00120 GET_NUM_FIELD(hdr->gid, st->st_gid); 00121 GET_NUM_FIELD(hdr->nlink, st->st_nlink); 00122 GET_NUM_FIELD(hdr->mtime, st->st_mtime); 00123 GET_NUM_FIELD(hdr->filesize, st->st_size); 00124 00125 GET_NUM_FIELD(hdr->devMajor, major); 00126 GET_NUM_FIELD(hdr->devMinor, minor); 00127 /*@-shiftimplementation@*/ 00128 st->st_dev = Makedev(major, minor); 00129 /*@=shiftimplementation@*/ 00130 00131 GET_NUM_FIELD(hdr->rdevMajor, major); 00132 GET_NUM_FIELD(hdr->rdevMinor, minor); 00133 /*@-shiftimplementation@*/ 00134 st->st_rdev = Makedev(major, minor); 00135 /*@=shiftimplementation@*/ 00136 00137 GET_NUM_FIELD(hdr->namesize, nb); 00138 if (nb >= iosm->wrsize) 00139 return IOSMERR_BAD_HEADER; 00140 00141 /* Read file name. */ 00142 { char * t = xmalloc(nb + 1); 00143 rc = cpioRead(iosm, t, nb); 00144 if (rc < 0) { 00145 t = _free(t); 00146 iosm->path = NULL; 00147 } else { 00148 _IOSMRC(rc); 00149 t[nb] = '\0'; 00150 iosm->path = t; 00151 } 00152 } 00153 00154 /* Read link name. */ 00155 if (S_ISLNK(st->st_mode)) { 00156 char * t; 00157 00158 /* Make sure block aligned. */ 00159 rc = _iosmNext(iosm, IOSM_POS); 00160 if (rc) return (int) -rc; 00161 00162 nb = (size_t) st->st_size; 00163 t = xmalloc(nb + 1); 00164 rc = cpioRead(iosm, t, nb); 00165 if (rc < 0) { 00166 t = _free(t); 00167 iosm->lpath = NULL; 00168 } else { 00169 _IOSMRC(rc); 00170 t[nb] = '\0'; 00171 iosm->lpath = t; 00172 } 00173 } 00174 00175 rc = 0; 00176 00177 /*@-usereleased@*/ 00178 if (_cpio_debug) 00179 fprintf(stderr, "\t %06o%3d (%4d,%4d)%12lu %s\n\t-> %s\n", 00180 (unsigned)st->st_mode, (int)st->st_nlink, 00181 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, 00182 (iosm->path ? iosm->path : ""), (iosm->lpath ? iosm->lpath : "")); 00183 /*@=usereleased@*/ 00184 00185 return (int) rc; 00186 } 00187 00188 static ssize_t cpioWrite(void * _iosm, const void *buf, size_t count) 00189 /*@globals fileSystem @*/ 00190 /*@modifies _iosm, fileSystem @*/ 00191 { 00192 IOSM_t iosm = _iosm; 00193 const char * s = buf; 00194 size_t nb = 0; 00195 size_t rc; 00196 00197 if (_cpio_debug) 00198 fprintf(stderr, "\t cpioWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count); 00199 00200 while (count > 0) { 00201 00202 /* XXX DWRITE uses rdnb for I/O length. */ 00203 iosm->rdnb = count; 00204 if (s != iosm->rdbuf) 00205 memmove(iosm->rdbuf, s + nb, iosm->rdnb); 00206 00207 rc = _iosmNext(iosm, IOSM_DWRITE); 00208 if (!rc && iosm->rdnb != iosm->wrnb) 00209 rc = IOSMERR_WRITE_FAILED; 00210 if (rc) return -rc; 00211 00212 nb += iosm->rdnb; 00213 count -= iosm->rdnb; 00214 } 00215 00216 #if defined(JBJ_WRITEPAD) 00217 /* Pad to next block boundary. */ 00218 if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return -rc; 00219 #endif 00220 00221 return nb; 00222 } 00223 00224 int cpioHeaderWrite(void * _iosm, struct stat * st) 00225 { 00226 IOSM_t iosm = _iosm; 00227 cpioHeader hdr = (cpioHeader) iosm->rdbuf; 00228 const char * path = (iosm && iosm->path ? iosm->path : ""); 00229 const char * lpath = (iosm && iosm->lpath ? iosm->lpath : ""); 00230 char field[64]; 00231 size_t nb; 00232 dev_t dev; 00233 ssize_t rc = 0; 00234 00235 if (_cpio_debug) 00236 fprintf(stderr, " cpioHeaderWrite(%p, %p)\n", iosm, st); 00237 00238 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic)); 00239 SET_NUM_FIELD(hdr->inode, st->st_ino, field); 00240 SET_NUM_FIELD(hdr->mode, st->st_mode, field); 00241 SET_NUM_FIELD(hdr->uid, st->st_uid, field); 00242 SET_NUM_FIELD(hdr->gid, st->st_gid, field); 00243 SET_NUM_FIELD(hdr->nlink, st->st_nlink, field); 00244 SET_NUM_FIELD(hdr->mtime, st->st_mtime, field); 00245 SET_NUM_FIELD(hdr->filesize, st->st_size, field); 00246 00247 dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field); 00248 dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field); 00249 dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field); 00250 dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field); 00251 00252 nb = strlen(path) + 1; SET_NUM_FIELD(hdr->namesize, nb, field); 00253 memcpy(hdr->checksum, "00000000", 8); 00254 00255 /* XXX Coalesce hdr+name into single I/O. */ 00256 memcpy(iosm->rdbuf + PHYS_HDR_SIZE, path, nb); 00257 nb += PHYS_HDR_SIZE; 00258 rc = cpioWrite(iosm, hdr, nb); 00259 _IOSMRC(rc); 00260 00261 if (S_ISLNK(st->st_mode)) { 00262 #if !defined(JBJ_WRITEPAD) 00263 rc = _iosmNext(iosm, IOSM_PAD); 00264 if (rc) return (int) rc; 00265 #endif 00266 00267 nb = strlen(lpath); 00268 rc = cpioWrite(iosm, lpath, nb); 00269 _IOSMRC(rc); 00270 } 00271 00272 #if !defined(JBJ_WRITEPAD) 00273 rc = _iosmNext(iosm, IOSM_PAD); 00274 #endif 00275 00276 return (int) rc; 00277 } 00278 00279 int cpioTrailerWrite(void * _iosm) 00280 { 00281 IOSM_t iosm = _iosm; 00282 cpioHeader hdr = (cpioHeader) iosm->rdbuf; 00283 size_t nb; 00284 ssize_t rc = 0; 00285 00286 if (_cpio_debug) 00287 fprintf(stderr, " cpioTrailerWrite(%p)\n", iosm); 00288 00289 memset(hdr, (int)'0', PHYS_HDR_SIZE); 00290 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic)); 00291 memcpy(hdr->nlink, "00000001", 8); 00292 memcpy(hdr->namesize, "0000000b", 8); 00293 00294 nb = sizeof(CPIO_TRAILER); 00295 /* XXX Coalesce hdr+trailer into single I/O. */ 00296 memcpy(iosm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, nb); 00297 nb += PHYS_HDR_SIZE; 00298 00299 rc = cpioWrite(iosm, hdr, nb); 00300 _IOSMRC(rc); 00301 00302 /* 00303 * GNU cpio pads to 512 bytes here, but we don't. This may matter for 00304 * tape device(s) and/or concatenated cpio archives. <shrug> 00305 */ 00306 #if !defined(JBJ_WRITEPAD) 00307 rc = _iosmNext(iosm, IOSM_PAD); 00308 #endif 00309 rc = 0; 00310 00311 return (int) rc; 00312 } 00313