00001
00006 #undef JBJ_WRITEPAD
00007
00008 #include "system.h"
00009
00010 #include <rpmio_internal.h>
00011
00012 #include <rpmmacro.h>
00013 #include <ugid.h>
00014 #include <ar.h>
00015 #define _IOSM_INTERNAL
00016 #include <iosm.h>
00017
00018 #include "debug.h"
00019
00020
00021
00022
00023 int _ar_debug = 0;
00024
00033 static int strntoul(const char *str, char **endptr,
00034 int base, size_t num)
00035
00036 {
00037 char * buf, * end;
00038 unsigned long ret;
00039
00040 buf = alloca(num + 1);
00041 strncpy(buf, str, num);
00042 buf[num] = '\0';
00043
00044 ret = strtoul(buf, &end, base);
00045 if (endptr != NULL) {
00046 if (*end != '\0')
00047 *endptr = ((char *)str) + (end - buf);
00048 else
00049 *endptr = ((char *)str) + strlen(buf);
00050 }
00051
00052 return ret;
00053 }
00054
00055
00056 #define _IOSMRC(_rc) \
00057 if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER)
00058
00059 static ssize_t arRead(void * _iosm, void * buf, size_t count)
00060
00061
00062 {
00063 IOSM_t iosm = _iosm;
00064 char * t = buf;
00065 size_t nb = 0;
00066 size_t rc;
00067
00068 if (_ar_debug)
00069 fprintf(stderr, "\t arRead(%p, %p[%u])\n", iosm, buf, (unsigned)count);
00070
00071 while (count > 0) {
00072
00073
00074 iosm->wrlen = count;
00075 rc = _iosmNext(iosm, IOSM_DREAD);
00076 if (!rc && iosm->rdnb != iosm->wrlen) {
00077 if (iosm->rdnb == 0) return -IOSMERR_HDR_TRAILER;
00078 rc = IOSMERR_READ_FAILED;
00079 }
00080 if (rc) return -rc;
00081
00082
00083 rc = (count > iosm->rdnb ? iosm->rdnb : count);
00084 if (buf != iosm->wrbuf)
00085 memcpy(t + nb, iosm->wrbuf, rc);
00086 nb += rc;
00087 count -= rc;
00088 }
00089 return nb;
00090 }
00091
00092 int arHeaderRead(void * _iosm, struct stat * st)
00093
00094 {
00095 IOSM_t iosm = _iosm;
00096 arHeader hdr = (arHeader) iosm->wrbuf;
00097 ssize_t rc = 0;
00098
00099 if (_ar_debug)
00100 fprintf(stderr, " arHeaderRead(%p, %p)\n", iosm, st);
00101
00102
00103 if (fdGetCpioPos(iosm->cfd) == 0) {
00104 rc = arRead(iosm, iosm->wrbuf, sizeof(AR_MAGIC)-1);
00105 _IOSMRC(rc);
00106
00107
00108 if (strncmp(iosm->wrbuf, AR_MAGIC, sizeof(AR_MAGIC)-1))
00109 return IOSMERR_BAD_MAGIC;
00110 }
00111
00112 top:
00113
00114 rc = _iosmNext(iosm, IOSM_POS);
00115 if (rc) return (int) rc;
00116
00117 rc = arRead(iosm, hdr, sizeof(*hdr));
00118 _IOSMRC(rc);
00119 if (_ar_debug)
00120 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr)-2, (char *)hdr);
00121
00122
00123 if (strncmp(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1))
00124 return IOSMERR_BAD_MAGIC;
00125
00126 st->st_size = strntoul(hdr->filesize, NULL, 10, sizeof(hdr->filesize));
00127
00128
00129 if (hdr->name[0] == '/') {
00130
00131 if (hdr->name[1] == '/' && hdr->name[2] == ' ') {
00132 char * t;
00133 size_t i;
00134
00135 rc = arRead(iosm, iosm->wrbuf, st->st_size);
00136 _IOSMRC(rc);
00137
00138 iosm->wrbuf[rc] = '\0';
00139 iosm->lmtab = t = xstrdup(iosm->wrbuf);
00140 iosm->lmtablen = rc;
00141 iosm->lmtaboff = 0;
00142
00143 for (i = 1; i < iosm->lmtablen; i++) {
00144 t++;
00145 if (t[0] != '\n') continue;
00146 t[0] = '\0';
00147
00148 if (t[-1] == '/') t[-1] = '\0';
00149 }
00150 goto top;
00151 }
00152
00153 if (hdr->name[1] == ' ') {
00154 rc = arRead(iosm, iosm->wrbuf, st->st_size);
00155 _IOSMRC(rc);
00156 goto top;
00157 }
00158
00159 if (xisdigit((int)hdr->name[1])) {
00160 char * te = NULL;
00161 int i = strntoul(&hdr->name[1], &te, 10, sizeof(hdr->name)-2);
00162 if (*te == ' ' && iosm->lmtab != NULL && i < (int)iosm->lmtablen)
00163 iosm->path = xstrdup(iosm->lmtab + i);
00164 }
00165 } else
00166 if (hdr->name[0] != ' ') {
00167 size_t nb = sizeof(hdr->name);
00168 char t[sizeof(hdr->name)+1];
00169 memcpy(t, hdr->name, nb);
00170 t[nb] = '\0';
00171 while (nb > 0 && t[nb-1] == ' ')
00172 t[--nb] = '\0';
00173
00174 if (nb > 0 && t[nb - 1] == '/')
00175 t[--nb] = '\0';
00176 iosm->path = xstrdup(t);
00177 }
00178
00179 st->st_mtime = strntoul(hdr->mtime, NULL, 10, sizeof(hdr->mtime));
00180 st->st_ctime = st->st_atime = st->st_mtime;
00181
00182 st->st_uid = strntoul(hdr->uid, NULL, 10, sizeof(hdr->uid));
00183 st->st_gid = strntoul(hdr->gid, NULL, 10, sizeof(hdr->gid));
00184
00185 st->st_mode = strntoul(hdr->mode, NULL, 8, sizeof(hdr->mode));
00186
00187 st->st_nlink = 1;
00188 rc = 0;
00189
00190 if (_ar_debug)
00191 fprintf(stderr, "\t %06o%3d (%4d,%4d)%12lu %s\n",
00192 (unsigned)st->st_mode, (int)st->st_nlink,
00193 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
00194 (iosm->path ? iosm->path : ""));
00195
00196 return (int) rc;
00197 }
00198
00199 static ssize_t arWrite(void * _iosm, const void *buf, size_t count)
00200
00201
00202 {
00203 IOSM_t iosm = _iosm;
00204 const char * s = buf;
00205 size_t nb = 0;
00206 size_t rc;
00207
00208 if (_ar_debug)
00209 fprintf(stderr, "\tarWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count);
00210
00211 while (count > 0) {
00212
00213
00214 iosm->rdnb = count;
00215 if (s != iosm->rdbuf)
00216 memmove(iosm->rdbuf, s + nb, iosm->rdnb);
00217
00218 rc = _iosmNext(iosm, IOSM_DWRITE);
00219 if (!rc && iosm->rdnb != iosm->wrnb)
00220 rc = IOSMERR_WRITE_FAILED;
00221 if (rc) return -rc;
00222
00223 nb += iosm->rdnb;
00224 count -= iosm->rdnb;
00225 }
00226
00227 #if defined(JBJ_WRITEPAD)
00228
00229 if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return -rc;
00230 #endif
00231
00232 return nb;
00233 }
00234
00235 int arHeaderWrite(void * _iosm, struct stat * st)
00236 {
00237 IOSM_t iosm = _iosm;
00238 arHeader hdr = (arHeader) iosm->rdbuf;
00239 size_t nb;
00240 ssize_t rc = 0;
00241
00242 if (_ar_debug)
00243 fprintf(stderr, " arHeaderWrite(%p, %p)\n", iosm, st);
00244
00245
00246 if (fdGetCpioPos(iosm->cfd) == 0) {
00247
00248 rc = arWrite(iosm, AR_MAGIC, sizeof(AR_MAGIC)-1);
00249 _IOSMRC(rc);
00250
00251 if (iosm->lmtab != NULL) {
00252 memset(hdr, (int) ' ', sizeof(*hdr));
00253 hdr->name[0] = '/';
00254 hdr->name[1] = '/';
00255 sprintf(hdr->filesize, "%-10d", (unsigned) (iosm->lmtablen & 037777777777));
00256 strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
00257
00258 rc = arWrite(iosm, hdr, sizeof(*hdr));
00259 _IOSMRC(rc);
00260 rc = arWrite(iosm, iosm->lmtab, iosm->lmtablen);
00261 _IOSMRC(rc);
00262 #if !defined(JBJ_WRITEPAD)
00263 rc = _iosmNext(iosm, IOSM_PAD);
00264 if (rc) return (int)rc;
00265 #endif
00266 }
00267 }
00268
00269 memset(hdr, (int)' ', sizeof(*hdr));
00270
00271 nb = strlen(iosm->path);
00272 if (nb >= sizeof(hdr->name)) {
00273 const char * t;
00274 const char * te;
00275 assert(iosm->lmtab != NULL);
00276 t = iosm->lmtab + iosm->lmtaboff;
00277 te = strchr(t, '\n');
00278
00279 nb = snprintf(hdr->name, sizeof(hdr->name)-1, "/%u", (unsigned)iosm->lmtaboff);
00280 hdr->name[nb] = ' ';
00281 if (te != NULL)
00282 iosm->lmtaboff += (te - t) + 1;
00283 } else {
00284 strncpy(hdr->name, iosm->path, nb);
00285 hdr->name[nb] = '/';
00286 }
00287
00288 sprintf(hdr->mtime, "%-12u", (unsigned) (st->st_mtime & 037777777777));
00289 sprintf(hdr->uid, "%-6u", (unsigned int)(st->st_uid & 07777777));
00290 sprintf(hdr->gid, "%-6u", (unsigned int)(st->st_gid & 07777777));
00291
00292 sprintf(hdr->mode, "%-8o", (unsigned int)(st->st_mode & 07777777));
00293 sprintf(hdr->filesize, "%-10u", (unsigned) (st->st_size & 037777777777));
00294
00295 strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
00296
00297 rc = (int) sizeof(*hdr);
00298 if (_ar_debug)
00299 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr), (char *)hdr);
00300
00301 rc = arWrite(iosm, hdr, sizeof(*hdr));
00302 _IOSMRC(rc);
00303 rc = 0;
00304
00305 return (int) rc;
00306 }
00307
00308 int arTrailerWrite(void * _iosm)
00309 {
00310 IOSM_t iosm = _iosm;
00311 size_t rc = 0;
00312
00313 if (_ar_debug)
00314 fprintf(stderr, " arTrailerWrite(%p)\n", iosm);
00315
00316 #if defined(JBJ_WRITEPAD)
00317 rc = arWrite(iosm, NULL, 0);
00318 _IOSMRC(rc);
00319 #else
00320 rc = _iosmNext(iosm, IOSM_PAD);
00321 #endif
00322
00323 return (int) rc;
00324 }