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
00018
00019
00020 int _cpio_debug = 0;
00021
00030 static int strntoul(const char *str, char **endptr,
00031 int base, size_t num)
00032
00033
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);
00046 else
00047 *endptr = ((char *)str) + strlen(buf);
00048 }
00049
00050 return ret;
00051 }
00052
00053
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
00059
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
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
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
00108 rc = cpioRead(iosm, hdr, PHYS_HDR_SIZE);
00109 _IOSMRC(rc);
00110
00111
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
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
00128 st->st_dev = Makedev(major, minor);
00129
00130
00131 GET_NUM_FIELD(hdr->rdevMajor, major);
00132 GET_NUM_FIELD(hdr->rdevMinor, minor);
00133
00134 st->st_rdev = Makedev(major, minor);
00135
00136
00137 GET_NUM_FIELD(hdr->namesize, nb);
00138 if (nb >= iosm->wrsize)
00139 return IOSMERR_BAD_HEADER;
00140
00141
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
00155 if (S_ISLNK(st->st_mode)) {
00156 char * t;
00157
00158
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
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
00184
00185 return (int) rc;
00186 }
00187
00188 static ssize_t cpioWrite(void * _iosm, const void *buf, size_t count)
00189
00190
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
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
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 char field[64];
00229 size_t nb;
00230 dev_t dev;
00231 ssize_t rc = 0;
00232
00233 if (_cpio_debug)
00234 fprintf(stderr, " cpioHeaderWrite(%p, %p)\n", iosm, st);
00235
00236 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
00237 SET_NUM_FIELD(hdr->inode, st->st_ino, field);
00238 SET_NUM_FIELD(hdr->mode, st->st_mode, field);
00239 SET_NUM_FIELD(hdr->uid, st->st_uid, field);
00240 SET_NUM_FIELD(hdr->gid, st->st_gid, field);
00241 SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
00242 SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
00243 SET_NUM_FIELD(hdr->filesize, st->st_size, field);
00244
00245 dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
00246 dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
00247 dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
00248 dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
00249
00250 nb = strlen(iosm->path) + 1; SET_NUM_FIELD(hdr->namesize, nb, field);
00251 memcpy(hdr->checksum, "00000000", 8);
00252
00253
00254 memcpy(iosm->rdbuf + PHYS_HDR_SIZE, iosm->path, nb);
00255 nb += PHYS_HDR_SIZE;
00256 rc = cpioWrite(iosm, hdr, nb);
00257 _IOSMRC(rc);
00258
00259 if (S_ISLNK(st->st_mode)) {
00260 assert(iosm->lpath != NULL);
00261 #if !defined(JBJ_WRITEPAD)
00262 rc = _iosmNext(iosm, IOSM_PAD);
00263 if (rc) return (int) rc;
00264 #endif
00265
00266 nb = strlen(iosm->lpath);
00267 rc = cpioWrite(iosm, iosm->lpath, nb);
00268 _IOSMRC(rc);
00269 }
00270
00271 #if !defined(JBJ_WRITEPAD)
00272 rc = _iosmNext(iosm, IOSM_PAD);
00273 #endif
00274
00275 return (int) rc;
00276 }
00277
00278 int cpioTrailerWrite(void * _iosm)
00279 {
00280 IOSM_t iosm = _iosm;
00281 cpioHeader hdr = (cpioHeader) iosm->rdbuf;
00282 size_t nb;
00283 ssize_t rc = 0;
00284
00285 if (_cpio_debug)
00286 fprintf(stderr, " cpioTrailerWrite(%p)\n", iosm);
00287
00288 memset(hdr, (int)'0', PHYS_HDR_SIZE);
00289 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
00290 memcpy(hdr->nlink, "00000001", 8);
00291 memcpy(hdr->namesize, "0000000b", 8);
00292
00293 nb = sizeof(CPIO_TRAILER);
00294
00295 memcpy(iosm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, nb);
00296 nb += PHYS_HDR_SIZE;
00297
00298 rc = cpioWrite(iosm, hdr, nb);
00299 _IOSMRC(rc);
00300
00301
00302
00303
00304
00305 #if !defined(JBJ_WRITEPAD)
00306 rc = _iosmNext(iosm, IOSM_PAD);
00307 #endif
00308 rc = 0;
00309
00310 return (int) rc;
00311 }
00312