rpm 5.3.7
|
00001 00006 #undef JBJ_WRITEPAD 00007 00008 #include "system.h" 00009 00010 #include <rpmio_internal.h> /* XXX fdGetCpioPos writing AR_MAGIC */ 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 /*@access IOSM_t @*/ 00021 00022 /*@unchecked@*/ 00023 int _ar_debug = 0; 00024 00033 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr, 00034 int base, size_t num) 00035 /*@modifies *endptr @*/ 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); /* XXX discards const */ 00048 else 00049 *endptr = ((char *)str) + strlen(buf); 00050 } 00051 00052 return ret; 00053 } 00054 00055 /* Translate archive read/write ssize_t return for iosmStage(). */ 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 /*@globals fileSystem @*/ 00061 /*@modifies _iosm, *buf, fileSystem @*/ 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 /* Read next ar block. */ 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; /* EOF */ 00078 rc = IOSMERR_READ_FAILED; 00079 } 00080 if (rc) return -rc; 00081 00082 /* Append to buffer. */ 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 /*@modifies _iosm, *st @*/ 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 /* XXX Read AR_MAGIC to beginning of ar(1) archive. */ 00103 if (fdGetCpioPos(iosm->cfd) == 0) { 00104 rc = arRead(iosm, iosm->wrbuf, sizeof(AR_MAGIC)-1); 00105 _IOSMRC(rc); 00106 00107 /* Verify archive magic. */ 00108 if (strncmp(iosm->wrbuf, AR_MAGIC, sizeof(AR_MAGIC)-1)) 00109 return IOSMERR_BAD_MAGIC; 00110 } 00111 00112 top: 00113 /* Make sure block aligned. */ 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 /* Verify header marker. */ 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 /* Special ar(1) archive members. */ 00129 if (hdr->name[0] == '/') { 00130 /* GNU: on "//": Read long member name string table. */ 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 /* GNU: trailing '/' to permit file names with trailing ' '. */ 00148 if (t[-1] == '/') t[-1] = '\0'; 00149 } 00150 goto top; 00151 } 00152 /* GNU: on "/": Skip symbol table. */ 00153 if (hdr->name[1] == ' ') { 00154 rc = arRead(iosm, iosm->wrbuf, st->st_size); 00155 _IOSMRC(rc); 00156 goto top; 00157 } 00158 /* GNU: on "/123": Read "123" offset to substitute long member name. */ 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] != ' ') { /* Short member name. */ 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 /* GNU: trailing '/' to permit file names with trailing ' '. */ 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 /*@globals fileSystem @*/ 00201 /*@modifies _iosm, fileSystem @*/ 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 /* XXX DWRITE uses rdnb for I/O length. */ 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 /* Pad to next block boundary. */ 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 const char * path = (iosm && iosm->path ? iosm->path : ""); 00240 size_t nb; 00241 ssize_t rc = 0; 00242 00243 if (_ar_debug) 00244 fprintf(stderr, " arHeaderWrite(%p, %p)\n", iosm, st); 00245 00246 /* At beginning of ar(1) archive, write magic and long member table. */ 00247 if (fdGetCpioPos(iosm->cfd) == 0) { 00248 /* Write ar(1) magic. */ 00249 rc = arWrite(iosm, AR_MAGIC, sizeof(AR_MAGIC)-1); 00250 _IOSMRC(rc); 00251 /* GNU: on "//": Write long member name string table. */ 00252 if (iosm->lmtab != NULL) { 00253 memset(hdr, (int) ' ', sizeof(*hdr)); 00254 hdr->name[0] = '/'; 00255 hdr->name[1] = '/'; 00256 sprintf(hdr->filesize, "%-10d", (unsigned) (iosm->lmtablen & 037777777777)); 00257 strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1); 00258 00259 rc = arWrite(iosm, hdr, sizeof(*hdr)); 00260 _IOSMRC(rc); 00261 rc = arWrite(iosm, iosm->lmtab, iosm->lmtablen); 00262 _IOSMRC(rc); 00263 #if !defined(JBJ_WRITEPAD) 00264 rc = _iosmNext(iosm, IOSM_PAD); 00265 if (rc) return (int)rc; 00266 #endif 00267 } 00268 } 00269 00270 memset(hdr, (int)' ', sizeof(*hdr)); 00271 00272 nb = strlen(path); 00273 if (nb >= sizeof(hdr->name)) { 00274 const char * t; 00275 const char * te; 00276 assert(iosm->lmtab != NULL); 00277 t = iosm->lmtab + iosm->lmtaboff; 00278 te = strchr(t, '\n'); 00279 /* GNU: on "/123": Write "/123" offset for long member name. */ 00280 nb = snprintf(hdr->name, sizeof(hdr->name)-1, "/%u", (unsigned)iosm->lmtaboff); 00281 hdr->name[nb] = ' '; 00282 if (te != NULL) 00283 iosm->lmtaboff += (te - t) + 1; 00284 } else { 00285 strncpy(hdr->name, path, nb); 00286 hdr->name[nb] = '/'; 00287 } 00288 00289 sprintf(hdr->mtime, "%-12u", (unsigned) (st->st_mtime & 037777777777)); 00290 sprintf(hdr->uid, "%-6u", (unsigned int)(st->st_uid & 07777777)); 00291 sprintf(hdr->gid, "%-6u", (unsigned int)(st->st_gid & 07777777)); 00292 00293 sprintf(hdr->mode, "%-8o", (unsigned int)(st->st_mode & 07777777)); 00294 sprintf(hdr->filesize, "%-10u", (unsigned) (st->st_size & 037777777777)); 00295 00296 strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1); 00297 00298 rc = (int) sizeof(*hdr); 00299 if (_ar_debug) 00300 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr), (char *)hdr); 00301 00302 rc = arWrite(iosm, hdr, sizeof(*hdr)); 00303 _IOSMRC(rc); 00304 rc = 0; 00305 00306 return (int) rc; 00307 } 00308 00309 int arTrailerWrite(void * _iosm) 00310 { 00311 IOSM_t iosm = _iosm; 00312 size_t rc = 0; 00313 00314 if (_ar_debug) 00315 fprintf(stderr, " arTrailerWrite(%p)\n", iosm); 00316 00317 #if defined(JBJ_WRITEPAD) 00318 rc = arWrite(iosm, NULL, 0); /* XXX _iosmNext(iosm, IOSM_PAD) */ 00319 _IOSMRC(rc); 00320 #else 00321 rc = _iosmNext(iosm, IOSM_PAD); /* XXX likely unnecessary. */ 00322 #endif 00323 00324 return (int) rc; 00325 }