rpm 5.2.1
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio_internal.h> /* XXX urlPath, fdGetCpioPos */ 00009 #include <rpmcb.h> /* XXX fnpyKey */ 00010 #include <ugid.h> /* XXX unameToUid() and gnameToGid() */ 00011 00012 #include <rpmsq.h> /* XXX rpmsqJoin()/rpmsqThread() */ 00013 #include <rpmsw.h> /* XXX rpmswAdd() */ 00014 00015 #include "../rpmdb/rpmtag.h" 00016 00017 typedef /*@abstract@*/ /*@refcounted@*/ struct rpmts_s * rpmts; 00018 typedef /*@abstract@*/ struct rpmte_s * rpmte; 00019 00020 #define _IOSM_INTERNAL 00021 #include <iosm.h> 00022 #define iosmUNSAFE iosmStage 00023 00024 #include "cpio.h" 00025 #include "tar.h" 00026 #include "ar.h" 00027 00028 typedef iosmMapFlags cpioMapFlags; 00029 #define _RPMFI_INTERNAL 00030 #define _RPMFI_NOMETHODS 00031 #include "../lib/rpmfi.h" 00032 00033 typedef /*@abstract@*/ /*@refcounted@*/ struct rpmds_s * rpmds; 00034 typedef struct rpmRelocation_s * rpmRelocation; 00035 #undef _USE_RPMTE 00036 #if defined(_USE_RPMTE) 00037 typedef /*@abstract@*/ void * alKey; 00038 #include "rpmte.h" 00039 #endif 00040 00041 #undef _USE_RPMSX 00042 #if defined(_USE_RPMSX) 00043 #include "../lib/rpmsx.h" /* XXX rpmsx rpmsxFContext rpmsxFree */ 00044 #endif 00045 00046 typedef /*@abstract@*/ /*@refcounted@*/ struct rpmdb_s * rpmdb; 00047 typedef /*@abstract@*/ struct rpmmi_s * rpmmi; 00048 typedef struct rpmPRCO_s * rpmPRCO; 00049 typedef struct Spec_s * Spec; 00050 #undef _USE_RPMTS 00051 #if defined(_USE_RPMTS) 00052 #include "rpmts.h" 00053 #endif 00054 00055 #include "debug.h" 00056 00057 /*@access FD_t @*/ /* XXX void ptr args */ 00058 /*@access IOSMI_t @*/ 00059 /*@access IOSM_t @*/ 00060 00061 /*@access rpmfi @*/ 00062 00063 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) 00064 00065 #define _IOSM_DEBUG 0 00066 /*@unchecked@*/ 00067 int _iosm_debug = _IOSM_DEBUG; 00068 00069 /*@-exportheadervar@*/ 00070 /*@unchecked@*/ 00071 int _iosm_threads = 0; 00072 /*@=exportheadervar@*/ 00073 00074 /*@-redecl@*/ 00075 int (*_iosmNext) (IOSM_t iosm, iosmFileStage nstage) 00076 /*@modifies iosm @*/ = &iosmNext; 00077 /*@=redecl@*/ 00078 00079 #if defined(_USE_RPMTS) 00080 void * iosmGetTs(const IOSM_t iosm) 00081 { 00082 const IOSMI_t iter = iosm->iter; 00083 /*@-compdef -refcounttrans -retexpose -usereleased @*/ 00084 return (iter ? iter->ts : NULL); 00085 /*@=compdef =refcounttrans =retexpose =usereleased @*/ 00086 } 00087 #endif 00088 00089 void * iosmGetFi(const IOSM_t iosm) 00090 { 00091 const IOSMI_t iter = iosm->iter; 00092 /*@-compdef -refcounttrans -retexpose -usereleased @*/ 00093 return (iter ? iter->fi : NULL); 00094 /*@=compdef =refcounttrans =retexpose =usereleased @*/ 00095 } 00096 00097 #define SUFFIX_RPMORIG ".rpmorig" 00098 #define SUFFIX_RPMSAVE ".rpmsave" 00099 #define SUFFIX_RPMNEW ".rpmnew" 00100 00109 static /*@only@*//*@null@*/ 00110 const char * iosmFsPath(/*@special@*/ /*@null@*/ const IOSM_t iosm, 00111 /*@null@*/ const struct stat * st, 00112 /*@null@*/ const char * subdir, 00113 /*@null@*/ const char * suffix) 00114 /*@uses iosm->dirName, iosm->baseName */ 00115 /*@*/ 00116 { 00117 const char * s = NULL; 00118 00119 if (iosm) { 00120 char * t; 00121 int nb; 00122 nb = strlen(iosm->dirName) + 00123 (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : 0) : 0) + 00124 (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : 0) : 0) + 00125 strlen(iosm->baseName) + 1; 00126 s = t = xmalloc(nb); 00127 t = stpcpy(t, iosm->dirName); 00128 if (st && !S_ISDIR(st->st_mode)) 00129 if (subdir) t = stpcpy(t, subdir); 00130 t = stpcpy(t, iosm->baseName); 00131 if (st && !S_ISDIR(st->st_mode)) 00132 if (suffix) t = stpcpy(t, suffix); 00133 } 00134 return s; 00135 } 00136 00142 static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ void * p) 00143 /*@modifies p @*/ 00144 { 00145 IOSMI_t iter = p; 00146 if (iter) { 00147 #if !defined(_RPMFI_NOMETHODS) 00148 iter->fi = rpmfiUnlink(iter->fi, "mapIterator"); 00149 #endif 00150 iter->fi = NULL; 00151 } 00152 return _free(p); 00153 } 00154 00161 /*@-mustmod@*/ 00162 static void * 00163 mapInitIterator(rpmfi fi, int reverse) 00164 /*@modifies fi @*/ 00165 { 00166 IOSMI_t iter = NULL; 00167 00168 iter = xcalloc(1, sizeof(*iter)); 00169 #if !defined(_RPMFI_NOMETHODS) 00170 iter->fi = rpmfiLink(fi, "mapIterator"); 00171 #else 00172 /*@i@*/ iter->fi = fi; 00173 #endif 00174 iter->reverse = reverse; 00175 iter->i = (iter->reverse ? (fi->fc - 1) : 0); 00176 iter->isave = iter->i; 00177 return iter; 00178 } 00179 /*@=mustmod@*/ 00180 00186 static int mapNextIterator(/*@null@*/ void * a) 00187 /*@*/ 00188 { 00189 IOSMI_t iter = a; 00190 int i = -1; 00191 00192 if (iter) { 00193 if (iter->reverse) { 00194 if (iter->i >= 0) i = iter->i--; 00195 } else { 00196 if (iter->i < (int) ((rpmfi)iter->fi)->fc) i = iter->i++; 00197 } 00198 iter->isave = i; 00199 } 00200 return i; 00201 } 00202 00205 static int iosmStrCmp(const void * a, const void * b) 00206 /*@*/ 00207 { 00208 const char * aurl = *(const char **)a; 00209 const char * burl = *(const char **)b; 00210 const char * afn = NULL; 00211 const char * bfn = NULL; 00212 00213 (void) urlPath(aurl, &afn); 00214 (void) urlPath(burl, &bfn); 00215 00216 #ifdef VERY_OLD_BUGGY_RPM_PACKAGES 00217 /* XXX Some rpm-2.4 packages from 1997 have basename only in payloads. */ 00218 if (strchr(afn, '/') == NULL) 00219 bfn = strrchr(bfn, '/') + 1; 00220 #endif 00221 00222 /* Match rpm-4.0 payloads with ./ prefixes. */ 00223 if (afn[0] == '.' && afn[1] == '/') afn += 2; 00224 if (bfn[0] == '.' && bfn[1] == '/') bfn += 2; 00225 00226 /* If either path is absolute, make it relative to '/'. */ 00227 if (afn[0] == '/') afn += 1; 00228 if (bfn[0] == '/') bfn += 1; 00229 00230 return strcmp(afn, bfn); 00231 } 00232 00239 static int mapFind(/*@null@*/ IOSMI_t iter, const char * iosmPath) 00240 /*@modifies iter @*/ 00241 { 00242 int ix = -1; 00243 00244 if (iter) { 00245 /*@-onlytrans@*/ 00246 const rpmfi fi = iter->fi; 00247 /*@=onlytrans@*/ 00248 #if !defined(_RPMFI_NOMETHODS) 00249 size_t fc = rpmfiFC(fi); 00250 #else 00251 size_t fc = (fi ? fi->fc : 0); 00252 #endif 00253 if (fi && fc > 0 && fi->apath && iosmPath && *iosmPath) { 00254 const char ** p = NULL; 00255 00256 if (fi->apath != NULL) 00257 p = bsearch(&iosmPath, fi->apath, fc, sizeof(iosmPath), 00258 iosmStrCmp); 00259 if (p) { 00260 iter->i = p - fi->apath; 00261 ix = mapNextIterator(iter); 00262 } 00263 } 00264 } 00265 return ix; 00266 } 00267 00271 typedef struct dnli_s { 00272 rpmfi fi; 00273 /*@only@*/ /*@null@*/ 00274 char * active; 00275 int reverse; 00276 int isave; 00277 int i; 00278 } * DNLI_t; 00279 00285 static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ const void * a) 00286 /*@modifies a @*/ 00287 { 00288 if (a) { 00289 DNLI_t dnli = (void *)a; 00290 if (dnli->active) free(dnli->active); 00291 } 00292 return _free(a); 00293 } 00294 00297 static inline int dnlCount(/*@null@*/ const DNLI_t dnli) 00298 /*@*/ 00299 { 00300 return (int) (dnli ? dnli->fi->dc : 0); 00301 } 00302 00305 static inline int dnlIndex(/*@null@*/ const DNLI_t dnli) 00306 /*@*/ 00307 { 00308 return (dnli ? dnli->isave : -1); 00309 } 00310 00317 /*@-usereleased@*/ 00318 static /*@only@*/ /*@null@*/ 00319 void * dnlInitIterator(/*@special@*/ const IOSM_t iosm, 00320 int reverse) 00321 /*@uses iosm->iter @*/ 00322 /*@*/ 00323 { 00324 rpmfi fi = iosmGetFi(iosm); 00325 const char * dnl; 00326 DNLI_t dnli; 00327 int i, j; 00328 00329 if (fi == NULL) 00330 return NULL; 00331 dnli = xcalloc(1, sizeof(*dnli)); 00332 dnli->fi = fi; 00333 dnli->reverse = reverse; 00334 dnli->i = (int) (reverse ? fi->dc : 0); 00335 00336 if (fi->dc) { 00337 dnli->active = xcalloc(fi->dc, sizeof(*dnli->active)); 00338 00339 /* Identify parent directories not skipped. */ 00340 #if !defined(_RPMFI_NOMETHODS) 00341 if ((fi = rpmfiInit(fi, 0)) != NULL) 00342 while ((i = rpmfiNext(fi)) >= 0) 00343 #else 00344 for (i = 0; i < (int)fi->fc; i++) 00345 #endif 00346 { 00347 if (!iosmFileActionSkipped(fi->actions[i])) 00348 dnli->active[fi->dil[i]] = (char)1; 00349 } 00350 00351 /* Exclude parent directories that are explicitly included. */ 00352 #if !defined(_RPMFI_NOMETHODS) 00353 if ((fi = rpmfiInit(fi, 0)) != NULL) 00354 while ((i = rpmfiNext(fi)) >= 0) 00355 #else 00356 for (i = 0; i < (int)fi->fc; i++) 00357 #endif 00358 { 00359 rpmuint32_t dil; 00360 size_t dnlen, bnlen; 00361 00362 if (!S_ISDIR(fi->fmodes[i])) 00363 continue; 00364 00365 dil = fi->dil[i]; 00366 dnlen = strlen(fi->dnl[dil]); 00367 bnlen = strlen(fi->bnl[i]); 00368 00369 for (j = 0; j < (int)fi->dc; j++) { 00370 size_t jlen; 00371 00372 if (!dnli->active[j] || j == (int)dil) 00373 /*@innercontinue@*/ continue; 00374 (void) urlPath(fi->dnl[j], &dnl); 00375 jlen = strlen(dnl); 00376 if (jlen != (dnlen+bnlen+1)) 00377 /*@innercontinue@*/ continue; 00378 if (strncmp(dnl, fi->dnl[dil], dnlen)) 00379 /*@innercontinue@*/ continue; 00380 if (strncmp(dnl+dnlen, fi->bnl[i], bnlen)) 00381 /*@innercontinue@*/ continue; 00382 if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') 00383 /*@innercontinue@*/ continue; 00384 /* This directory is included in the package. */ 00385 dnli->active[j] = (char)0; 00386 /*@innerbreak@*/ break; 00387 } 00388 } 00389 00390 /* Print only once per package. */ 00391 if (!reverse) { 00392 j = 0; 00393 for (i = 0; i < (int)fi->dc; i++) { 00394 if (!dnli->active[i]) continue; 00395 if (j == 0) { 00396 j = 1; 00397 rpmlog(RPMLOG_DEBUG, 00398 D_("========== Directories not explicitly included in package:\n")); 00399 } 00400 (void) urlPath(fi->dnl[i], &dnl); 00401 rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, dnl); 00402 } 00403 if (j) 00404 rpmlog(RPMLOG_DEBUG, "==========\n"); 00405 } 00406 } 00407 return dnli; 00408 } 00409 /*@=usereleased@*/ 00410 00416 static /*@observer@*/ /*@null@*/ 00417 const char * dnlNextIterator(/*@null@*/ DNLI_t dnli) 00418 /*@modifies dnli @*/ 00419 { 00420 const char * dn = NULL; 00421 00422 if (dnli) { 00423 rpmfi fi = dnli->fi; 00424 int i = -1; 00425 00426 if (dnli->active) 00427 do { 00428 i = (!dnli->reverse ? dnli->i++ : --dnli->i); 00429 } while (i >= 0 && i < (int)fi->dc && !dnli->active[i]); 00430 00431 if (i >= 0 && i < (int)fi->dc) 00432 dn = fi->dnl[i]; 00433 else 00434 i = -1; 00435 dnli->isave = i; 00436 } 00437 return dn; 00438 } 00439 00440 #if defined(WITH_PTHREADS) 00441 static void * iosmThread(void * arg) 00442 /*@globals h_errno, fileSystem, internalState @*/ 00443 /*@modifies arg, fileSystem, internalState @*/ 00444 { 00445 IOSM_t iosm = arg; 00446 /*@-unqualifiedtrans@*/ 00447 return ((void *) ((long)iosmStage(iosm, iosm->nstage))); 00448 /*@=unqualifiedtrans@*/ 00449 } 00450 #endif 00451 00452 int iosmNext(IOSM_t iosm, iosmFileStage nstage) 00453 /*@globals h_errno, fileSystem, internalState @*/ 00454 /*@modifies iosm, fileSystem, internalState @*/ 00455 { 00456 iosm->nstage = nstage; 00457 #if defined(WITH_PTHREADS) 00458 if (iosm->multithreaded) 00459 return rpmsqJoin( rpmsqThread(iosmThread, iosm) ); 00460 #endif 00461 return iosmStage(iosm, iosm->nstage); 00462 } 00463 00469 static int saveHardLink(/*@special@*/ /*@partial@*/ IOSM_t iosm) 00470 /*@uses iosm->links, iosm->ix, iosm->sb, iosm->goal, iosm->nsuffix @*/ 00471 /*@defines iosm->li @*/ 00472 /*@releases iosm->path @*/ 00473 /*@globals h_errno, fileSystem, internalState @*/ 00474 /*@modifies iosm, fileSystem, internalState @*/ 00475 { 00476 struct stat * st = &iosm->sb; 00477 int rc = 0; 00478 int ix = -1; 00479 int j; 00480 00481 /* Find hard link set. */ 00482 for (iosm->li = iosm->links; iosm->li; iosm->li = iosm->li->next) { 00483 if (iosm->li->sb.st_ino == st->st_ino && iosm->li->sb.st_dev == st->st_dev) 00484 break; 00485 } 00486 00487 /* New hard link encountered, add new link to set. */ 00488 if (iosm->li == NULL) { 00489 iosm->li = xcalloc(1, sizeof(*iosm->li)); 00490 iosm->li->next = NULL; 00491 iosm->li->sb = *st; /* structure assignment */ 00492 iosm->li->nlink = (int) st->st_nlink; 00493 iosm->li->linkIndex = iosm->ix; 00494 iosm->li->createdPath = -1; 00495 00496 iosm->li->filex = xcalloc(st->st_nlink, sizeof(iosm->li->filex[0])); 00497 memset(iosm->li->filex, -1, (st->st_nlink * sizeof(iosm->li->filex[0]))); 00498 iosm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*iosm->li->nsuffix)); 00499 00500 if (iosm->goal == IOSM_PKGBUILD) 00501 iosm->li->linksLeft = (int) st->st_nlink; 00502 if (iosm->goal == IOSM_PKGINSTALL) 00503 iosm->li->linksLeft = 0; 00504 00505 /*@-kepttrans@*/ 00506 iosm->li->next = iosm->links; 00507 /*@=kepttrans@*/ 00508 iosm->links = iosm->li; 00509 } 00510 00511 if (iosm->goal == IOSM_PKGBUILD) --iosm->li->linksLeft; 00512 iosm->li->filex[iosm->li->linksLeft] = iosm->ix; 00513 /*@-observertrans -dependenttrans@*/ 00514 iosm->li->nsuffix[iosm->li->linksLeft] = iosm->nsuffix; 00515 /*@=observertrans =dependenttrans@*/ 00516 if (iosm->goal == IOSM_PKGINSTALL) iosm->li->linksLeft++; 00517 00518 if (iosm->goal == IOSM_PKGBUILD) 00519 return (iosm->li->linksLeft > 0); 00520 00521 if (iosm->goal != IOSM_PKGINSTALL) 00522 return 0; 00523 00524 if (!(st->st_size || iosm->li->linksLeft == (int) st->st_nlink)) 00525 return 1; 00526 00527 /* Here come the bits, time to choose a non-skipped file name. */ 00528 { rpmfi fi = iosmGetFi(iosm); 00529 00530 for (j = iosm->li->linksLeft - 1; j >= 0; j--) { 00531 ix = iosm->li->filex[j]; 00532 if (ix < 0 || iosmFileActionSkipped(fi->actions[ix])) 00533 continue; 00534 break; 00535 } 00536 } 00537 00538 /* Are all links skipped or not encountered yet? */ 00539 if (ix < 0 || j < 0) 00540 return 1; /* XXX W2DO? */ 00541 00542 /* Save the non-skipped file name and map index. */ 00543 iosm->li->linkIndex = j; 00544 iosm->path = _free(iosm->path); 00545 iosm->ix = ix; 00546 rc = iosmNext(iosm, IOSM_MAP); 00547 return rc; 00548 } 00549 00555 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink_s * li) 00556 /*@modifies li @*/ 00557 { 00558 if (li) { 00559 li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */ 00560 li->filex = _free(li->filex); 00561 } 00562 return _free(li); 00563 } 00564 00565 IOSM_t newIOSM(void) 00566 { 00567 IOSM_t iosm = xcalloc(1, sizeof(*iosm)); 00568 return iosm; 00569 } 00570 00571 IOSM_t freeIOSM(IOSM_t iosm) 00572 { 00573 if (iosm) { 00574 iosm->path = _free(iosm->path); 00575 while ((iosm->li = iosm->links) != NULL) { 00576 iosm->links = iosm->li->next; 00577 iosm->li->next = NULL; 00578 iosm->li = freeHardLink(iosm->li); 00579 } 00580 iosm->dnlx = _free(iosm->dnlx); 00581 iosm->ldn = _free(iosm->ldn); 00582 iosm->iter = mapFreeIterator(iosm->iter); 00583 } 00584 return _free(iosm); 00585 } 00586 00587 static int arSetup(IOSM_t iosm, rpmfi fi) 00588 /*@modifies iosm @*/ 00589 { 00590 const char * path; 00591 char * t; 00592 size_t lmtablen = 0; 00593 size_t nb; 00594 00595 /* Calculate size of ar(1) long member table. */ 00596 #if !defined(_RPMFI_NOMETHODS) 00597 if ((fi = rpmfiInit(fi, 0)) != NULL) 00598 while (rpmfiNext(fi) >= 0) 00599 #else 00600 int i; 00601 if (fi != NULL) 00602 for (i = 0; i < (int)fi->fc; i++) 00603 #endif 00604 { 00605 #ifdef NOTYET 00606 if (fi->apath) { 00607 const char * apath = NULL; 00608 (void) urlPath(fi->apath[ix], &apath); 00609 path = apath + fi->striplen; 00610 } else 00611 #endif 00612 #if !defined(_RPMFI_NOMETHODS) 00613 path = rpmfiBN(fi); 00614 #else 00615 path = fi->bnl[i]; 00616 #endif 00617 if ((nb = strlen(path)) < 15) 00618 continue; 00619 lmtablen += nb + 1; /* trailing \n */ 00620 } 00621 00622 /* Anything to do? */ 00623 if (lmtablen == 0) 00624 return 0; 00625 00626 /* Create and load ar(1) long member table. */ 00627 iosm->lmtab = t = xmalloc(lmtablen + 1); /* trailing \0 */ 00628 iosm->lmtablen = lmtablen; 00629 iosm->lmtaboff = 0; 00630 #if !defined(_RPMFI_NOMETHODS) 00631 if ((fi = rpmfiInit(fi, 0)) != NULL) 00632 while (rpmfiNext(fi) >= 0) 00633 #else 00634 if (fi != NULL) 00635 for (i = 0; i < (int)fi->fc; i++) 00636 #endif 00637 { 00638 #ifdef NOTYET 00639 if (fi->apath) { 00640 const char * apath = NULL; 00641 (void) urlPath(fi->apath[ix], &apath); 00642 path = apath + fi->striplen; 00643 } else 00644 #endif 00645 #if !defined(_RPMFI_NOMETHODS) 00646 path = rpmfiBN(fi); 00647 #else 00648 path = fi->bnl[i]; 00649 #endif 00650 if ((nb = strlen(path)) < 15) 00651 continue; 00652 t = stpcpy(t, path); 00653 *t++ = '\n'; 00654 } 00655 *t = '\0'; 00656 00657 return 0; 00658 } 00659 00660 int iosmSetup(IOSM_t iosm, iosmFileStage goal, const char * afmt, 00661 const void * _ts, const void * _fi, FD_t cfd, 00662 unsigned int * archiveSize, const char ** failedFile) 00663 { 00664 #if defined(_USE_RPMTS) 00665 const rpmts ts = (const rpmts) _ts; 00666 #endif 00667 /*@i@*/ const rpmfi fi = (const rpmfi) _fi; 00668 #if defined(_USE_RPMTE) 00669 int reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT); 00670 int adding = (rpmteType(fi->te) == TR_ADDED); 00671 #else 00672 int reverse = 0; /* XXX HACK: devise alternative means */ 00673 int adding = 1; /* XXX HACK: devise alternative means */ 00674 #endif 00675 size_t pos = 0; 00676 int rc, ec = 0; 00677 00678 iosm->debug = _iosm_debug; 00679 iosm->multithreaded = _iosm_threads; 00680 iosm->adding = adding; 00681 00682 /*@+voidabstract -nullpass@*/ 00683 if (iosm->debug < 0) 00684 fprintf(stderr, "--> iosmSetup(%p, 0x%x, \"%s\", %p, %p, %p, %p, %p)\n", iosm, goal, afmt, (void *)_ts, _fi, cfd, archiveSize, failedFile); 00685 /*@=voidabstract =nullpass@*/ 00686 00687 _iosmNext = &iosmNext; 00688 if (iosm->headerRead == NULL) { 00689 if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, "ustar"))) { 00690 if (iosm->debug < 0) 00691 fprintf(stderr, "\ttar vectors set\n"); 00692 iosm->headerRead = &tarHeaderRead; 00693 iosm->headerWrite = &tarHeaderWrite; 00694 iosm->trailerWrite = &tarTrailerWrite; 00695 iosm->blksize = TAR_BLOCK_SIZE; 00696 } else 00697 if (afmt != NULL && !strcmp(afmt, "ar")) { 00698 if (iosm->debug < 0) 00699 fprintf(stderr, "\tar vectors set\n"); 00700 iosm->headerRead = &arHeaderRead; 00701 iosm->headerWrite = &arHeaderWrite; 00702 iosm->trailerWrite = &arTrailerWrite; 00703 iosm->blksize = 2; 00704 if (goal == IOSM_PKGBUILD || goal == IOSM_PKGERASE) 00705 (void) arSetup(iosm, fi); 00706 } else 00707 { 00708 if (iosm->debug < 0) 00709 fprintf(stderr, "\tcpio vectors set\n"); 00710 iosm->headerRead = &cpioHeaderRead; 00711 iosm->headerWrite = &cpioHeaderWrite; 00712 iosm->trailerWrite = &cpioTrailerWrite; 00713 iosm->blksize = 4; 00714 } 00715 } 00716 00717 iosm->goal = goal; 00718 if (cfd != NULL) { 00719 /*@-assignexpose@*/ 00720 iosm->cfd = fdLink(cfd, "persist (iosm)"); 00721 /*@=assignexpose@*/ 00722 pos = fdGetCpioPos(iosm->cfd); 00723 fdSetCpioPos(iosm->cfd, 0); 00724 } 00725 /*@-mods@*/ /* WTF? */ 00726 iosm->iter = mapInitIterator(fi, reverse); 00727 /*@=mods@*/ 00728 #if defined(_USE_RPMTS) 00729 iosm->iter->ts = rpmtsLink(ts, "mapIterator"); 00730 iosm->nofcontexts = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS); 00731 iosm->nofdigests = 00732 (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOFDIGESTS)) 00733 ? 0 : 1; 00734 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT) 00735 iosm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) && 00736 iosm->goal != IOSM_PKGCOMMIT) ? 0 : 1); 00737 #undef _tsmask 00738 #else 00739 /*@-assignexpose -temptrans @*/ 00740 iosm->iter->ts = (void *)_ts; 00741 /*@=assignexpose =temptrans @*/ 00742 iosm->nofcontexts = 1; 00743 iosm->nofdigests = 1; 00744 iosm->commit = 1; 00745 #endif 00746 00747 if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) { 00748 fi->archivePos = 0; 00749 #if defined(_USE_RPMTS) 00750 (void) rpmtsNotify(ts, fi->te, 00751 RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize); 00752 #endif 00753 } 00754 00755 /*@-assignexpose@*/ 00756 iosm->archiveSize = archiveSize; 00757 if (iosm->archiveSize) 00758 *iosm->archiveSize = 0; 00759 iosm->failedFile = failedFile; 00760 if (iosm->failedFile) 00761 *iosm->failedFile = NULL; 00762 /*@=assignexpose@*/ 00763 00764 memset(iosm->sufbuf, 0, sizeof(iosm->sufbuf)); 00765 if (iosm->goal == IOSM_PKGINSTALL) { 00766 rpmuint32_t tid; 00767 #if defined(_USE_RPMTS) 00768 tid = (ts != NULL ? rpmtsGetTid(ts) : 0); 00769 #else 00770 static time_t now = 0; 00771 if (now == 0) now = time(NULL); 00772 tid = (rpmuint32_t) now; 00773 #endif 00774 if (tid > 0 && tid < 0xffffffff) 00775 sprintf(iosm->sufbuf, ";%08x", (unsigned)tid); 00776 } 00777 00778 ec = iosm->rc = 0; 00779 rc = iosmUNSAFE(iosm, IOSM_CREATE); 00780 if (rc && !ec) ec = rc; 00781 00782 rc = iosmUNSAFE(iosm, iosm->goal); 00783 if (rc && !ec) ec = rc; 00784 00785 if (iosm->archiveSize && ec == 0) 00786 *iosm->archiveSize = (fdGetCpioPos(iosm->cfd) - pos); 00787 00788 /*@-nullstate@*/ /* FIX: *iosm->failedFile may be NULL */ 00789 return ec; 00790 /*@=nullstate@*/ 00791 } 00792 00793 int iosmTeardown(IOSM_t iosm) 00794 { 00795 int rc = iosm->rc; 00796 00797 if (iosm->debug < 0) 00798 fprintf(stderr, "--> iosmTeardown(%p)\n", iosm); 00799 if (!rc) 00800 rc = iosmUNSAFE(iosm, IOSM_DESTROY); 00801 00802 iosm->lmtab = _free(iosm->lmtab); 00803 00804 #if defined(_USE_RPMTS) 00805 (void) rpmswAdd(rpmtsOp(iosmGetTs(iosm), RPMTS_OP_DIGEST), 00806 &iosm->op_digest); 00807 (void)rpmtsFree(iter->ts); 00808 iter->ts = NULL; 00809 #else 00810 iosm->iter->ts = NULL; 00811 #endif 00812 iosm->iter = mapFreeIterator(iosm->iter); 00813 if (iosm->cfd != NULL) { 00814 iosm->cfd = fdFree(iosm->cfd, "persist (iosm)"); 00815 iosm->cfd = NULL; 00816 } 00817 iosm->failedFile = NULL; 00818 return rc; 00819 } 00820 00821 /* 00822 * Set file security context (if not disabled). 00823 * @param iosm file state machine data 00824 * @return 0 always 00825 */ 00826 static int iosmMapFContext(IOSM_t iosm) 00827 /*@modifies iosm @*/ 00828 { 00829 /* 00830 * Find file security context (if not disabled). 00831 */ 00832 iosm->fcontext = NULL; 00833 if (!iosm->nofcontexts) { 00834 security_context_t scon = NULL; 00835 int xx = matchpathcon(iosm->path, iosm->sb.st_mode, &scon); 00836 00837 /*@-moduncon@*/ 00838 if (!xx && scon != NULL) 00839 iosm->fcontext = scon; 00840 #ifdef DYING /* XXX SELinux file contexts not set from package content. */ 00841 else { 00842 rpmfi fi = iosmGetFi(iosm); 00843 int i = iosm->ix; 00844 00845 /* Get file security context from package. */ 00846 if (fi && i >= 0 && i < (int)fi->fc) 00847 iosm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL); 00848 } 00849 #endif 00850 /*@=moduncon@*/ 00851 } 00852 return 0; 00853 } 00854 00855 int iosmMapPath(IOSM_t iosm) 00856 { 00857 rpmfi fi = iosmGetFi(iosm); /* XXX const except for fstates */ 00858 int teAdding = iosm->adding; 00859 int rc = 0; 00860 int i = iosm->ix; 00861 00862 iosm->osuffix = NULL; 00863 iosm->nsuffix = NULL; 00864 iosm->astriplen = 0; 00865 iosm->action = FA_UNKNOWN; 00866 iosm->mapFlags = fi->mapflags; 00867 00868 if (fi && i >= 0 && i < (int)fi->fc) { 00869 00870 iosm->astriplen = fi->astriplen; 00871 iosm->action = (fi->actions ? fi->actions[i] : fi->action); 00872 iosm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags); 00873 iosm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags); 00874 00875 /* src rpms have simple base name in payload. */ 00876 iosm->dirName = fi->dnl[fi->dil[i]]; 00877 iosm->baseName = fi->bnl[i]; 00878 00879 switch (iosm->action) { 00880 case FA_SKIP: 00881 break; 00882 case FA_UNKNOWN: 00883 break; 00884 00885 case FA_COPYOUT: 00886 break; 00887 case FA_COPYIN: 00888 case FA_CREATE: 00889 assert(teAdding); 00890 break; 00891 00892 case FA_SKIPNSTATE: 00893 if (fi->fstates && teAdding) 00894 fi->fstates[i] = (rpmuint8_t)RPMFILE_STATE_NOTINSTALLED; 00895 break; 00896 00897 case FA_SKIPNETSHARED: 00898 if (fi->fstates && teAdding) 00899 fi->fstates[i] = (rpmuint8_t)RPMFILE_STATE_NETSHARED; 00900 break; 00901 00902 case FA_SKIPCOLOR: 00903 if (fi->fstates && teAdding) 00904 fi->fstates[i] = (rpmuint8_t)RPMFILE_STATE_WRONGCOLOR; 00905 break; 00906 00907 case FA_BACKUP: 00908 if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00909 iosm->osuffix = (teAdding ? SUFFIX_RPMORIG : SUFFIX_RPMSAVE); 00910 break; 00911 00912 case FA_ALTNAME: 00913 assert(teAdding); 00914 if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00915 iosm->nsuffix = SUFFIX_RPMNEW; 00916 break; 00917 00918 case FA_SAVE: 00919 assert(teAdding); 00920 if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00921 iosm->osuffix = SUFFIX_RPMSAVE; 00922 break; 00923 case FA_ERASE: 00924 #if 0 /* XXX is this a genhdlist fix? */ 00925 assert(rpmteType(fi->te) == TR_REMOVED); 00926 #endif 00927 /* 00928 * XXX TODO: %ghost probably shouldn't be removed, but that changes 00929 * legacy rpm behavior. 00930 */ 00931 break; 00932 default: 00933 break; 00934 } 00935 00936 if ((iosm->mapFlags & IOSM_MAP_PATH) || iosm->nsuffix) { 00937 const struct stat * st = &iosm->sb; 00938 iosm->path = _free(iosm->path); 00939 iosm->path = iosmFsPath(iosm, st, iosm->subdir, 00940 (iosm->suffix ? iosm->suffix : iosm->nsuffix)); 00941 } 00942 } 00943 return rc; 00944 } 00945 00946 int iosmMapAttrs(IOSM_t iosm) 00947 { 00948 struct stat * st = &iosm->sb; 00949 rpmfi fi = iosmGetFi(iosm); 00950 int i = iosm->ix; 00951 00952 if (fi && i >= 0 && i < (int)fi->fc) { 00953 mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms); 00954 mode_t finalMode = (fi->fmodes ? (mode_t)fi->fmodes[i] : perms); 00955 dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0); 00956 rpmuint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0); 00957 uid_t uid = fi->uid; 00958 gid_t gid = fi->gid; 00959 00960 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00961 /* Make sure OpenPKG/Mandriva RPM does not try to set file owner/group on files during 00962 installation of _source_ RPMs. Instead, let it use the current 00963 run-time owner/group, because most of the time the owner/group in 00964 the source RPM (which is the owner/group of the files as staying on 00965 the package author system) is not existing on the target system, of 00966 course. */ 00967 #endif 00968 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) { 00969 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00970 if (!fi->isSource) { 00971 #endif 00972 if (iosm->goal == IOSM_PKGINSTALL) 00973 rpmlog(RPMLOG_WARNING, 00974 _("user %s does not exist - using root\n"), fi->fuser[i]); 00975 uid = 0; 00976 finalMode &= ~S_ISUID; /* turn off suid bit */ 00977 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00978 } 00979 #endif 00980 } 00981 00982 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) { 00983 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00984 if (!fi->isSource) { 00985 #endif 00986 if (iosm->goal == IOSM_PKGINSTALL) 00987 rpmlog(RPMLOG_WARNING, 00988 _("group %s does not exist - using root\n"), fi->fgroup[i]); 00989 gid = 0; 00990 finalMode &= ~S_ISGID; /* turn off sgid bit */ 00991 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00992 } 00993 #endif 00994 } 00995 00996 if (iosm->mapFlags & IOSM_MAP_MODE) 00997 st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT); 00998 if (iosm->mapFlags & IOSM_MAP_TYPE) { 00999 st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT); 01000 if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) 01001 && st->st_nlink == 0) 01002 st->st_nlink = 1; 01003 st->st_rdev = finalRdev; 01004 st->st_mtime = finalMtime; 01005 } 01006 if (iosm->mapFlags & IOSM_MAP_UID) 01007 st->st_uid = uid; 01008 if (iosm->mapFlags & IOSM_MAP_GID) 01009 st->st_gid = gid; 01010 01011 /* 01012 * Set file digest (if not disabled). 01013 */ 01014 if (!iosm->nofdigests) { 01015 iosm->fdigestalgo = fi->digestalgo; 01016 iosm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL); 01017 iosm->digestlen = fi->digestlen; 01018 iosm->digest = (fi->digests ? (fi->digests + (iosm->digestlen * i)) : NULL); 01019 } else { 01020 iosm->fdigestalgo = 0; 01021 iosm->fdigest = NULL; 01022 iosm->digestlen = 0; 01023 iosm->digest = NULL; 01024 } 01025 } 01026 return 0; 01027 } 01028 01034 /*@-compdef@*/ 01035 static int extractRegular(/*@special@*/ IOSM_t iosm) 01036 /*@uses iosm->fdigest, iosm->digest, iosm->sb, iosm->wfd @*/ 01037 /*@globals h_errno, fileSystem, internalState @*/ 01038 /*@modifies iosm, fileSystem, internalState @*/ 01039 { 01040 const struct stat * st = &iosm->sb; 01041 size_t left = (size_t) st->st_size; 01042 int rc = 0; 01043 int xx; 01044 01045 rc = iosmNext(iosm, IOSM_WOPEN); 01046 if (rc) 01047 goto exit; 01048 01049 if (st->st_size > 0 && (iosm->fdigest != NULL || iosm->digest != NULL)) 01050 fdInitDigest(iosm->wfd, iosm->fdigestalgo, 0); 01051 01052 while (left) { 01053 01054 iosm->wrlen = (left > iosm->wrsize ? iosm->wrsize : left); 01055 rc = iosmNext(iosm, IOSM_DREAD); 01056 if (rc) 01057 goto exit; 01058 01059 rc = iosmNext(iosm, IOSM_WRITE); 01060 if (rc) 01061 goto exit; 01062 01063 left -= iosm->wrnb; 01064 01065 /* Notify iff progress, completion is done elsewhere */ 01066 if (!rc && left) 01067 (void) iosmNext(iosm, IOSM_NOTIFY); 01068 } 01069 01070 xx = fsync(Fileno(iosm->wfd)); 01071 01072 if (st->st_size > 0 && (iosm->fdigest || iosm->digest)) { 01073 void * digest = NULL; 01074 int asAscii = (iosm->digest == NULL ? 1 : 0); 01075 01076 (void) Fflush(iosm->wfd); 01077 fdFiniDigest(iosm->wfd, iosm->fdigestalgo, &digest, NULL, asAscii); 01078 01079 if (digest == NULL) { 01080 rc = IOSMERR_DIGEST_MISMATCH; 01081 goto exit; 01082 } 01083 01084 if (iosm->digest != NULL) { 01085 if (memcmp(digest, iosm->digest, iosm->digestlen)) 01086 rc = IOSMERR_DIGEST_MISMATCH; 01087 } else { 01088 if (strcmp(digest, iosm->fdigest)) 01089 rc = IOSMERR_DIGEST_MISMATCH; 01090 } 01091 digest = _free(digest); 01092 } 01093 01094 exit: 01095 (void) iosmNext(iosm, IOSM_WCLOSE); 01096 return rc; 01097 } 01098 /*@=compdef@*/ 01099 01106 /*@-compdef -compmempass@*/ 01107 static int writeFile(/*@special@*/ /*@partial@*/ IOSM_t iosm, int writeData) 01108 /*@uses iosm->path, iosm->opath, iosm->sb, iosm->osb, iosm->cfd @*/ 01109 /*@globals h_errno, fileSystem, internalState @*/ 01110 /*@modifies iosm, fileSystem, internalState @*/ 01111 { 01112 const char * path = iosm->path; 01113 const char * opath = iosm->opath; 01114 struct stat * st = &iosm->sb; 01115 struct stat * ost = &iosm->osb; 01116 size_t left; 01117 int xx; 01118 int rc; 01119 01120 st->st_size = (writeData ? ost->st_size : 0); 01121 01122 if (S_ISDIR(st->st_mode)) { 01123 st->st_size = 0; 01124 } else if (S_ISLNK(st->st_mode)) { 01125 /* 01126 * While linux puts the size of a symlink in the st_size field, 01127 * I don't think that's a specified standard. 01128 */ 01129 /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */ 01130 rc = iosmUNSAFE(iosm, IOSM_READLINK); 01131 if (rc) goto exit; 01132 st->st_size = iosm->rdnb; 01133 iosm->lpath = xstrdup(iosm->rdbuf); /* XXX save readlink return. */ 01134 } 01135 01136 if (iosm->mapFlags & IOSM_MAP_ABSOLUTE) { 01137 size_t nb=strlen(iosm->dirName) + strlen(iosm->baseName) + sizeof("."); 01138 char * t = alloca(nb); 01139 *t = '\0'; 01140 iosm->path = t; 01141 if (iosm->mapFlags & IOSM_MAP_ADDDOT) 01142 *t++ = '.'; 01143 t = stpcpy( stpcpy(t, iosm->dirName), iosm->baseName); 01144 } else if (iosm->mapFlags & IOSM_MAP_PATH) { 01145 rpmfi fi = iosmGetFi(iosm); 01146 if (fi->apath) { 01147 const char * apath = NULL; 01148 (void) urlPath(fi->apath[iosm->ix], &apath); 01149 iosm->path = apath + fi->striplen; 01150 } else 01151 iosm->path = fi->bnl[iosm->ix]; 01152 } 01153 01154 rc = iosmNext(iosm, IOSM_HWRITE); 01155 iosm->path = path; 01156 if (rc) goto exit; 01157 01158 if (writeData && S_ISREG(st->st_mode)) { 01159 #if defined(HAVE_MMAP) 01160 char * rdbuf = NULL; 01161 void * mapped = (void *)-1; 01162 size_t nmapped = 0; 01163 /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */ 01164 int use_mmap = (st->st_size <= 0x07ffffff); 01165 #endif 01166 01167 rc = iosmNext(iosm, IOSM_ROPEN); 01168 if (rc) goto exit; 01169 01170 /* XXX unbuffered mmap generates *lots* of fdio debugging */ 01171 #if defined(HAVE_MMAP) 01172 if (use_mmap) { 01173 mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(iosm->rfd), 0); 01174 if (mapped != (void *)-1) { 01175 rdbuf = iosm->rdbuf; 01176 iosm->rdbuf = (char *) mapped; 01177 iosm->rdlen = nmapped = st->st_size; 01178 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED) 01179 xx = madvise(mapped, nmapped, MADV_DONTNEED); 01180 #endif 01181 } 01182 } 01183 #endif 01184 01185 left = st->st_size; 01186 01187 while (left) { 01188 #if defined(HAVE_MMAP) 01189 if (mapped != (void *)-1) { 01190 iosm->rdnb = nmapped; 01191 } else 01192 #endif 01193 { 01194 iosm->rdlen = (left > iosm->rdsize ? iosm->rdsize : left), 01195 rc = iosmNext(iosm, IOSM_READ); 01196 if (rc) goto exit; 01197 } 01198 01199 /* XXX DWRITE uses rdnb for I/O length. */ 01200 rc = iosmNext(iosm, IOSM_DWRITE); 01201 if (rc) goto exit; 01202 01203 left -= iosm->wrnb; 01204 } 01205 01206 #if defined(HAVE_MMAP) 01207 if (mapped != (void *)-1) { 01208 /* XXX splint misses size_t 2nd arg. */ 01209 /*@i@*/ xx = msync(mapped, nmapped, MS_ASYNC); 01210 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED) 01211 xx = madvise(mapped, nmapped, MADV_DONTNEED); 01212 #endif 01213 xx = munmap(mapped, nmapped); 01214 iosm->rdbuf = rdbuf; 01215 } else 01216 #endif 01217 xx = fsync(Fileno(iosm->rfd)); 01218 01219 } 01220 01221 rc = iosmNext(iosm, IOSM_PAD); 01222 if (rc) goto exit; 01223 01224 rc = 0; 01225 01226 exit: 01227 if (iosm->rfd != NULL) 01228 (void) iosmNext(iosm, IOSM_RCLOSE); 01229 /*@-dependenttrans@*/ 01230 iosm->opath = opath; 01231 iosm->path = path; 01232 /*@=dependenttrans@*/ 01233 return rc; 01234 } 01235 /*@=compdef =compmempass@*/ 01236 01242 static int writeLinkedFile(/*@special@*/ /*@partial@*/ IOSM_t iosm) 01243 /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->li, iosm->failedFile @*/ 01244 /*@globals h_errno, fileSystem, internalState @*/ 01245 /*@modifies iosm, fileSystem, internalState @*/ 01246 { 01247 const char * path = iosm->path; 01248 const char * lpath = iosm->lpath; 01249 const char * nsuffix = iosm->nsuffix; 01250 int iterIndex = iosm->ix; 01251 int ec = 0; 01252 int rc; 01253 int i; 01254 const char * linkpath = NULL; 01255 int firstfile = 1; 01256 01257 iosm->path = NULL; 01258 iosm->lpath = NULL; 01259 iosm->nsuffix = NULL; 01260 iosm->ix = -1; 01261 01262 for (i = iosm->li->nlink - 1; i >= 0; i--) { 01263 01264 if (iosm->li->filex[i] < 0) continue; 01265 01266 iosm->ix = iosm->li->filex[i]; 01267 /*@-compdef@*/ 01268 rc = iosmNext(iosm, IOSM_MAP); 01269 /*@=compdef@*/ 01270 01271 /* XXX tar and cpio have to do things differently. */ 01272 if (iosm->headerWrite == tarHeaderWrite) { 01273 if (firstfile) { 01274 const char * apath = NULL; 01275 char *t; 01276 (void) urlPath(iosm->path, &apath); 01277 /* Remove the buildroot prefix. */ 01278 t = xmalloc(sizeof(".") + strlen(apath + iosm->astriplen)); 01279 (void) stpcpy( stpcpy(t, "."), apath + iosm->astriplen); 01280 linkpath = t; 01281 firstfile = 0; 01282 } else 01283 iosm->lpath = linkpath; 01284 01285 /* Write data after first link for tar. */ 01286 rc = writeFile(iosm, (iosm->lpath == NULL)); 01287 } else { 01288 /* Write data after last link for cpio. */ 01289 rc = writeFile(iosm, (i == 0)); 01290 } 01291 if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) { 01292 ec = rc; 01293 *iosm->failedFile = xstrdup(iosm->path); 01294 } 01295 01296 iosm->path = _free(iosm->path); 01297 iosm->li->filex[i] = -1; 01298 } 01299 01300 /*@-dependenttrans@*/ 01301 linkpath = _free(linkpath); 01302 /*@=dependenttrans@*/ 01303 iosm->ix = iterIndex; 01304 iosm->nsuffix = nsuffix; 01305 iosm->lpath = lpath; 01306 iosm->path = path; 01307 return ec; 01308 } 01309 01315 /*@-compdef@*/ 01316 static int iosmMakeLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm) 01317 /*@uses iosm->path, iosm->opath, iosm->nsuffix, iosm->ix, iosm->li @*/ 01318 /*@globals h_errno, fileSystem, internalState @*/ 01319 /*@modifies iosm, fileSystem, internalState @*/ 01320 { 01321 const char * path = iosm->path; 01322 const char * opath = iosm->opath; 01323 const char * nsuffix = iosm->nsuffix; 01324 int iterIndex = iosm->ix; 01325 int ec = 0; 01326 int rc; 01327 int i; 01328 01329 iosm->path = NULL; 01330 iosm->opath = NULL; 01331 iosm->nsuffix = NULL; 01332 iosm->ix = -1; 01333 01334 iosm->ix = iosm->li->filex[iosm->li->createdPath]; 01335 rc = iosmNext(iosm, IOSM_MAP); 01336 iosm->opath = iosm->path; 01337 iosm->path = NULL; 01338 for (i = 0; i < iosm->li->nlink; i++) { 01339 if (iosm->li->filex[i] < 0) continue; 01340 if (iosm->li->createdPath == i) continue; 01341 01342 iosm->ix = iosm->li->filex[i]; 01343 iosm->path = _free(iosm->path); 01344 rc = iosmNext(iosm, IOSM_MAP); 01345 if (iosmFileActionSkipped(iosm->action)) continue; 01346 01347 rc = iosmUNSAFE(iosm, IOSM_VERIFY); 01348 if (!rc) continue; 01349 if (!(rc == IOSMERR_ENOENT)) break; 01350 01351 /* XXX link(iosm->opath, iosm->path) */ 01352 rc = iosmNext(iosm, IOSM_LINK); 01353 if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) { 01354 ec = rc; 01355 *iosm->failedFile = xstrdup(iosm->path); 01356 } 01357 01358 iosm->li->linksLeft--; 01359 } 01360 iosm->path = _free(iosm->path); 01361 iosm->opath = _free(iosm->opath); 01362 01363 iosm->ix = iterIndex; 01364 iosm->nsuffix = nsuffix; 01365 iosm->path = path; 01366 iosm->opath = opath; 01367 return ec; 01368 } 01369 /*@=compdef@*/ 01370 01376 /*@-compdef@*/ 01377 static int iosmCommitLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm) 01378 /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->sb, 01379 iosm->li, iosm->links @*/ 01380 /*@globals h_errno, fileSystem, internalState @*/ 01381 /*@modifies iosm, fileSystem, internalState @*/ 01382 { 01383 const char * path = iosm->path; 01384 const char * nsuffix = iosm->nsuffix; 01385 int iterIndex = iosm->ix; 01386 struct stat * st = &iosm->sb; 01387 int rc = 0; 01388 int i; 01389 01390 iosm->path = NULL; 01391 iosm->nsuffix = NULL; 01392 iosm->ix = -1; 01393 01394 for (iosm->li = iosm->links; iosm->li; iosm->li = iosm->li->next) { 01395 if (iosm->li->sb.st_ino == st->st_ino && iosm->li->sb.st_dev == st->st_dev) 01396 break; 01397 } 01398 01399 for (i = 0; i < iosm->li->nlink; i++) { 01400 if (iosm->li->filex[i] < 0) continue; 01401 iosm->ix = iosm->li->filex[i]; 01402 rc = iosmNext(iosm, IOSM_MAP); 01403 if (!iosmFileActionSkipped(iosm->action)) 01404 rc = iosmNext(iosm, IOSM_COMMIT); 01405 iosm->path = _free(iosm->path); 01406 iosm->li->filex[i] = -1; 01407 } 01408 01409 iosm->ix = iterIndex; 01410 iosm->nsuffix = nsuffix; 01411 iosm->path = path; 01412 return rc; 01413 } 01414 /*@=compdef@*/ 01415 01421 static int iosmRmdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm) 01422 /*@uses iosm->path, iosm->dnlx, iosm->ldn, iosm->rdbuf, iosm->iter @*/ 01423 /*@globals h_errno, fileSystem, internalState @*/ 01424 /*@modifies iosm, fileSystem, internalState @*/ 01425 { 01426 const char * path = iosm->path; 01427 void * dnli = dnlInitIterator(iosm, 1); 01428 char * dn = iosm->rdbuf; 01429 int dc = dnlCount(dnli); 01430 int rc = 0; 01431 01432 iosm->path = NULL; 01433 dn[0] = '\0'; 01434 /*@-observertrans -dependenttrans@*/ 01435 if (iosm->ldn != NULL && iosm->dnlx != NULL) 01436 while ((iosm->path = dnlNextIterator(dnli)) != NULL) { 01437 size_t dnlen = strlen(iosm->path); 01438 char * te; 01439 01440 dc = dnlIndex(dnli); 01441 if (iosm->dnlx[dc] < 1 || (size_t)iosm->dnlx[dc] >= dnlen) 01442 continue; 01443 01444 /* Copy to avoid const on iosm->path. */ 01445 te = stpcpy(dn, iosm->path) - 1; 01446 iosm->path = dn; 01447 01448 /* Remove generated directories. */ 01449 /*@-usereleased@*/ /* LCL: te used after release? */ 01450 do { 01451 if (*te == '/') { 01452 *te = '\0'; 01453 /*@-compdef@*/ 01454 rc = iosmNext(iosm, IOSM_RMDIR); 01455 /*@=compdef@*/ 01456 *te = '/'; 01457 } 01458 if (rc) 01459 /*@innerbreak@*/ break; 01460 te--; 01461 } while ((te - iosm->path) > iosm->dnlx[dc]); 01462 /*@=usereleased@*/ 01463 } 01464 dnli = dnlFreeIterator(dnli); 01465 /*@=observertrans =dependenttrans@*/ 01466 01467 iosm->path = path; 01468 return rc; 01469 } 01470 01476 static int iosmMkdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm) 01477 /*@uses iosm->path, iosm->sb, iosm->osb, iosm->rdbuf, iosm->iter, 01478 iosm->ldn, iosm->ldnlen, iosm->ldnalloc @*/ 01479 /*@defines iosm->dnlx, iosm->ldn @*/ 01480 /*@globals h_errno, fileSystem, internalState @*/ 01481 /*@modifies iosm, fileSystem, internalState @*/ 01482 { 01483 struct stat * st = &iosm->sb; 01484 struct stat * ost = &iosm->osb; 01485 const char * path = iosm->path; 01486 mode_t st_mode = st->st_mode; 01487 void * dnli = dnlInitIterator(iosm, 0); 01488 char * dn = iosm->rdbuf; 01489 int dc = dnlCount(dnli); 01490 int rc = 0; 01491 size_t i; 01492 01493 iosm->path = NULL; 01494 01495 dn[0] = '\0'; 01496 iosm->dnlx = (dc ? xcalloc(dc, sizeof(*iosm->dnlx)) : NULL); 01497 /*@-observertrans -dependenttrans@*/ 01498 if (iosm->dnlx != NULL) 01499 while ((iosm->path = dnlNextIterator(dnli)) != NULL) { 01500 size_t dnlen = strlen(iosm->path); 01501 char * te; 01502 01503 dc = dnlIndex(dnli); 01504 if (dc < 0) continue; 01505 iosm->dnlx[dc] = (unsigned short) dnlen; 01506 if (dnlen <= 1) 01507 continue; 01508 01509 /*@-compdef -nullpass@*/ /* FIX: iosm->ldn not defined ??? */ 01510 if (dnlen <= iosm->ldnlen && !strcmp(iosm->path, iosm->ldn)) 01511 continue; 01512 /*@=compdef =nullpass@*/ 01513 01514 /* Copy to avoid const on iosm->path. */ 01515 (void) stpcpy(dn, iosm->path); 01516 iosm->path = dn; 01517 01518 /* Assume '/' directory exists, "mkdir -p" for others if non-existent */ 01519 (void) urlPath(dn, (const char **)&te); 01520 for (i = 1, te++; *te != '\0'; te++, i++) { 01521 if (*te != '/') 01522 /*@innercontinue@*/ continue; 01523 01524 *te = '\0'; 01525 01526 /* Already validated? */ 01527 /*@-usedef -compdef -nullpass -nullderef@*/ 01528 if (i < iosm->ldnlen && 01529 (iosm->ldn[i] == '/' || iosm->ldn[i] == '\0') && 01530 !strncmp(iosm->path, iosm->ldn, i)) 01531 { 01532 *te = '/'; 01533 /* Move pre-existing path marker forward. */ 01534 iosm->dnlx[dc] = (te - dn); 01535 /*@innercontinue@*/ continue; 01536 } 01537 /*@=usedef =compdef =nullpass =nullderef@*/ 01538 01539 /* Validate next component of path. */ 01540 rc = iosmUNSAFE(iosm, IOSM_LSTAT); 01541 *te = '/'; 01542 01543 /* Directory already exists? */ 01544 if (rc == 0 && S_ISDIR(ost->st_mode)) { 01545 /* Move pre-existing path marker forward. */ 01546 iosm->dnlx[dc] = (te - dn); 01547 } else if (rc == IOSMERR_ENOENT) { 01548 rpmfi fi = iosmGetFi(iosm); 01549 *te = '\0'; 01550 st->st_mode = S_IFDIR | (fi->dperms & 07777); 01551 rc = iosmNext(iosm, IOSM_MKDIR); 01552 if (!rc) { 01553 #if defined(_USE_RPMSX) 01554 security_context_t scon = NULL; 01555 /* XXX FIXME? only new dir will have context set. */ 01556 /* Get file security context from patterns. */ 01557 if (!fsm->nofcontexts 01558 && !matchpathcon(iosm->path, st->st_mode, &scon) 01559 && scon != NULL) 01560 { 01561 iosm->fcontext = scon; 01562 rc = iosmNext(iosm, IOSM_LSETFCON); 01563 } else 01564 #endif 01565 iosm->fcontext = NULL; 01566 if (iosm->fcontext == NULL) 01567 rpmlog(RPMLOG_DEBUG, 01568 D_("%s directory created with perms %04o, no context.\n"), 01569 iosm->path, (unsigned)(st->st_mode & 07777)); 01570 else { 01571 rpmlog(RPMLOG_DEBUG, 01572 D_("%s directory created with perms %04o, context %s.\n"), 01573 iosm->path, (unsigned)(st->st_mode & 07777), 01574 iosm->fcontext); 01575 #if defined(_USE_RPMSX) 01576 iosm->fcontext = NULL; 01577 scon = _free(scon); 01578 #endif 01579 } 01580 } 01581 *te = '/'; 01582 } 01583 if (rc) 01584 /*@innerbreak@*/ break; 01585 } 01586 if (rc) break; 01587 01588 /* Save last validated path. */ 01589 /*@-compdef@*/ /* FIX: ldn/path annotations ? */ 01590 if (iosm->ldnalloc < (dnlen + 1)) { 01591 iosm->ldnalloc = dnlen + 100; 01592 iosm->ldn = xrealloc(iosm->ldn, iosm->ldnalloc); 01593 } 01594 if (iosm->ldn != NULL) { /* XXX can't happen */ 01595 strcpy(iosm->ldn, iosm->path); 01596 iosm->ldnlen = dnlen; 01597 } 01598 /*@=compdef@*/ 01599 } 01600 dnli = dnlFreeIterator(dnli); 01601 /*@=observertrans =dependenttrans@*/ 01602 01603 iosm->path = path; 01604 st->st_mode = st_mode; /* XXX restore st->st_mode */ 01605 /*@-compdef@*/ /* FIX: ldn/path annotations ? */ 01606 return rc; 01607 /*@=compdef@*/ 01608 } 01609 01610 #ifdef NOTYET 01611 01616 static int iosmStat(/*@special@*/ /*@partial@*/ IOSM_t iosm) 01617 /*@globals fileSystem, internalState @*/ 01618 /*@modifies iosm, fileSystem, internalState @*/ 01619 { 01620 int rc = 0; 01621 01622 if (iosm->path != NULL) { 01623 int saveernno = errno; 01624 rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & IOSM_FOLLOW_SYMLINKS) 01625 ? IOSM_LSTAT : IOSM_STAT)); 01626 if (rc == IOSMERR_ENOENT) { 01627 errno = saveerrno; 01628 rc = 0; 01629 iosm->exists = 0; 01630 } else if (rc == 0) { 01631 iosm->exists = 1; 01632 } 01633 } else { 01634 /* Skip %ghost files on build. */ 01635 iosm->exists = 0; 01636 } 01637 return rc; 01638 } 01639 #endif 01640 01641 #define IS_DEV_LOG(_x) \ 01642 ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \ 01643 !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \ 01644 ((_x)[sizeof("/dev/log")-1] == '\0' || \ 01645 (_x)[sizeof("/dev/log")-1] == ';')) 01646 01647 /*@-compmempass@*/ 01648 int iosmStage(IOSM_t iosm, iosmFileStage stage) 01649 { 01650 #ifdef NOTUSED 01651 iosmFileStage prevStage = iosm->stage; 01652 const char * const prev = iosmFileStageString(prevStage); 01653 #endif 01654 const char * const cur = iosmFileStageString(stage); 01655 struct stat * st = &iosm->sb; 01656 struct stat * ost = &iosm->osb; 01657 int saveerrno = errno; 01658 int rc = iosm->rc; 01659 size_t left; 01660 int i; 01661 01662 #define _fafilter(_a) \ 01663 (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \ 01664 ? iosmFileActionString(_a) : "") 01665 01666 if (stage & IOSM_DEAD) { 01667 /* do nothing */ 01668 } else if (stage & IOSM_INTERNAL) { 01669 if (iosm->debug && !(stage & IOSM_SYSCALL)) 01670 rpmlog(RPMLOG_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n", 01671 cur, 01672 (unsigned)st->st_mode, (int)st->st_nlink, 01673 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, 01674 (iosm->path ? iosm->path : ""), 01675 _fafilter(iosm->action)); 01676 } else { 01677 const char * apath = NULL; 01678 if (iosm->path) 01679 (void) urlPath(iosm->path, &apath); 01680 iosm->stage = stage; 01681 if (iosm->debug || !(stage & IOSM_VERBOSE)) 01682 rpmlog(RPMLOG_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n", 01683 cur, 01684 (unsigned)st->st_mode, (int)st->st_nlink, 01685 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, 01686 (apath ? apath + iosm->astriplen : ""), 01687 _fafilter(iosm->action)); 01688 } 01689 #undef _fafilter 01690 01691 switch (stage) { 01692 case IOSM_UNKNOWN: 01693 break; 01694 case IOSM_PKGINSTALL: 01695 while (1) { 01696 /* Clean iosm, free'ing memory. Read next archive header. */ 01697 rc = iosmUNSAFE(iosm, IOSM_INIT); 01698 01699 /* Exit on end-of-payload. */ 01700 if (rc == IOSMERR_HDR_TRAILER) { 01701 rc = 0; 01702 /*@loopbreak@*/ break; 01703 } 01704 01705 /* Exit on error. */ 01706 if (rc) { 01707 iosm->postpone = 1; 01708 (void) iosmNext(iosm, IOSM_UNDO); 01709 /*@loopbreak@*/ break; 01710 } 01711 01712 /* Extract file from archive. */ 01713 rc = iosmNext(iosm, IOSM_PROCESS); 01714 if (rc) { 01715 (void) iosmNext(iosm, IOSM_UNDO); 01716 /*@loopbreak@*/ break; 01717 } 01718 01719 /* Notify on success. */ 01720 (void) iosmNext(iosm, IOSM_NOTIFY); 01721 01722 rc = iosmNext(iosm, IOSM_FINI); 01723 if (rc) { 01724 /*@loopbreak@*/ break; 01725 } 01726 } 01727 break; 01728 case IOSM_PKGERASE: 01729 case IOSM_PKGCOMMIT: 01730 while (1) { 01731 /* Clean iosm, free'ing memory. */ 01732 rc = iosmUNSAFE(iosm, IOSM_INIT); 01733 01734 /* Exit on end-of-payload. */ 01735 if (rc == IOSMERR_HDR_TRAILER) { 01736 rc = 0; 01737 /*@loopbreak@*/ break; 01738 } 01739 01740 /* Rename/erase next item. */ 01741 if (iosmNext(iosm, IOSM_FINI)) 01742 /*@loopbreak@*/ break; 01743 } 01744 break; 01745 case IOSM_PKGBUILD: 01746 while (1) { 01747 01748 rc = iosmUNSAFE(iosm, IOSM_INIT); 01749 01750 /* Exit on end-of-payload. */ 01751 if (rc == IOSMERR_HDR_TRAILER) { 01752 rc = 0; 01753 /*@loopbreak@*/ break; 01754 } 01755 01756 /* Exit on error. */ 01757 if (rc) { 01758 iosm->postpone = 1; 01759 (void) iosmNext(iosm, IOSM_UNDO); 01760 /*@loopbreak@*/ break; 01761 } 01762 01763 /* Copy file into archive. */ 01764 rc = iosmNext(iosm, IOSM_PROCESS); 01765 if (rc) { 01766 (void) iosmNext(iosm, IOSM_UNDO); 01767 /*@loopbreak@*/ break; 01768 } 01769 01770 /* Notify on success. */ 01771 (void) iosmNext(iosm, IOSM_NOTIFY); 01772 01773 if (iosmNext(iosm, IOSM_FINI)) 01774 /*@loopbreak@*/ break; 01775 } 01776 01777 /* Flush partial sets of hard linked files. */ 01778 if (!(iosm->mapFlags & IOSM_ALL_HARDLINKS)) { 01779 int nlink, j; 01780 while ((iosm->li = iosm->links) != NULL) { 01781 iosm->links = iosm->li->next; 01782 iosm->li->next = NULL; 01783 01784 /* Re-calculate link count for archive header. */ 01785 for (j = -1, nlink = 0, i = 0; i < iosm->li->nlink; i++) { 01786 if (iosm->li->filex[i] < 0) 01787 /*@innercontinue@*/ continue; 01788 nlink++; 01789 if (j == -1) j = i; 01790 } 01791 /* XXX force the contents out as well. */ 01792 if (j != 0) { 01793 iosm->li->filex[0] = iosm->li->filex[j]; 01794 iosm->li->filex[j] = -1; 01795 } 01796 iosm->li->sb.st_nlink = nlink; 01797 01798 iosm->sb = iosm->li->sb; /* structure assignment */ 01799 iosm->osb = iosm->sb; /* structure assignment */ 01800 01801 if (!rc) rc = writeLinkedFile(iosm); 01802 01803 iosm->li = freeHardLink(iosm->li); 01804 } 01805 } 01806 01807 if (!rc) 01808 rc = iosmNext(iosm, IOSM_TRAILER); 01809 01810 break; 01811 case IOSM_CREATE: 01812 iosm->path = _free(iosm->path); 01813 iosm->lpath = _free(iosm->lpath); 01814 iosm->opath = _free(iosm->opath); 01815 iosm->dnlx = _free(iosm->dnlx); 01816 01817 iosm->ldn = _free(iosm->ldn); 01818 iosm->ldnalloc = iosm->ldnlen = 0; 01819 01820 iosm->rdsize = iosm->wrsize = 0; 01821 iosm->rdbuf = iosm->rdb = _free(iosm->rdb); 01822 iosm->wrbuf = iosm->wrb = _free(iosm->wrb); 01823 if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) { 01824 iosm->rdsize = 16 * BUFSIZ; 01825 iosm->rdbuf = iosm->rdb = xmalloc(iosm->rdsize); 01826 iosm->wrsize = 16 * BUFSIZ; 01827 iosm->wrbuf = iosm->wrb = xmalloc(iosm->wrsize); 01828 } 01829 01830 iosm->mkdirsdone = 0; 01831 iosm->ix = -1; 01832 iosm->links = NULL; 01833 iosm->li = NULL; 01834 errno = 0; /* XXX get rid of EBADF */ 01835 01836 /* Detect and create directories not explicitly in package. */ 01837 if (iosm->goal == IOSM_PKGINSTALL) { 01838 /*@-compdef@*/ 01839 rc = iosmNext(iosm, IOSM_MKDIRS); 01840 /*@=compdef@*/ 01841 if (!rc) iosm->mkdirsdone = 1; 01842 } 01843 01844 break; 01845 case IOSM_INIT: 01846 iosm->path = _free(iosm->path); 01847 iosm->lpath = _free(iosm->lpath); 01848 iosm->postpone = 0; 01849 iosm->diskchecked = iosm->exists = 0; 01850 iosm->subdir = NULL; 01851 iosm->suffix = (iosm->sufbuf[0] != '\0' ? iosm->sufbuf : NULL); 01852 iosm->action = FA_UNKNOWN; 01853 iosm->osuffix = NULL; 01854 iosm->nsuffix = NULL; 01855 01856 if (iosm->goal == IOSM_PKGINSTALL) { 01857 /* Read next header from payload, checking for end-of-payload. */ 01858 rc = iosmUNSAFE(iosm, IOSM_NEXT); 01859 } 01860 if (rc) break; 01861 01862 /* Identify mapping index. */ 01863 iosm->ix = ((iosm->goal == IOSM_PKGINSTALL) 01864 ? mapFind(iosm->iter, iosm->path) : mapNextIterator(iosm->iter)); 01865 01866 { rpmfi fi = iosmGetFi(iosm); 01867 if (!(fi->mapflags & IOSM_PAYLOAD_LIST)) { 01868 /* Detect end-of-loop and/or mapping error. */ 01869 if (!(fi->mapflags & IOSM_PAYLOAD_EXTRACT)) { 01870 if (iosm->ix < 0) { 01871 if (iosm->goal == IOSM_PKGINSTALL) { 01872 #if 0 01873 rpmlog(RPMLOG_WARNING, 01874 _("archive file %s was not found in header file list\n"), 01875 iosm->path); 01876 #endif 01877 if (iosm->failedFile && *iosm->failedFile == NULL) 01878 *iosm->failedFile = xstrdup(iosm->path); 01879 rc = IOSMERR_UNMAPPED_FILE; 01880 } else { 01881 rc = IOSMERR_HDR_TRAILER; 01882 } 01883 break; 01884 } 01885 } 01886 01887 /* On non-install, mode must be known so that dirs don't get suffix. */ 01888 if (iosm->goal != IOSM_PKGINSTALL) { 01889 st->st_mode = fi->fmodes[iosm->ix]; 01890 } 01891 } 01892 } 01893 01894 /* Generate file path. */ 01895 rc = iosmNext(iosm, IOSM_MAP); 01896 if (rc) break; 01897 01898 /* Perform lstat/stat for disk file. */ 01899 #ifdef NOTYET 01900 rc = iosmStat(iosm); 01901 #else 01902 if (iosm->path != NULL && 01903 !(iosm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode))) 01904 { 01905 rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & IOSM_FOLLOW_SYMLINKS) 01906 ? IOSM_LSTAT : IOSM_STAT)); 01907 if (rc == IOSMERR_ENOENT) { 01908 errno = saveerrno; 01909 rc = 0; 01910 iosm->exists = 0; 01911 } else if (rc == 0) { 01912 iosm->exists = 1; 01913 } 01914 } else { 01915 /* Skip %ghost files on build. */ 01916 iosm->exists = 0; 01917 } 01918 #endif 01919 iosm->diskchecked = 1; 01920 if (rc) break; 01921 01922 /* On non-install, the disk file stat is what's remapped. */ 01923 if (iosm->goal != IOSM_PKGINSTALL) 01924 *st = *ost; /* structure assignment */ 01925 01926 /* Remap file perms, owner, and group. */ 01927 rc = iosmMapAttrs(iosm); 01928 if (rc) break; 01929 01930 iosm->postpone = iosmFileActionSkipped(iosm->action); 01931 if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) { 01932 /*@-evalorder@*/ /* FIX: saveHardLink can modify iosm */ 01933 if (S_ISREG(st->st_mode) && st->st_nlink > 1) 01934 iosm->postpone = saveHardLink(iosm); 01935 /*@=evalorder@*/ 01936 } 01937 { rpmfi fi = iosmGetFi(iosm); 01938 if (fi->mapflags & IOSM_PAYLOAD_LIST) iosm->postpone = 1; 01939 } 01940 break; 01941 case IOSM_PRE: 01942 break; 01943 case IOSM_MAP: 01944 rc = iosmMapPath(iosm); 01945 break; 01946 case IOSM_MKDIRS: 01947 rc = iosmMkdirs(iosm); 01948 break; 01949 case IOSM_RMDIRS: 01950 if (iosm->dnlx) 01951 rc = iosmRmdirs(iosm); 01952 break; 01953 case IOSM_PROCESS: 01954 if (iosm->postpone) { 01955 if (iosm->goal == IOSM_PKGINSTALL) { 01956 /* XXX Skip over file body, archive headers already done. */ 01957 if (S_ISREG(st->st_mode)) 01958 rc = iosmNext(iosm, IOSM_EAT); 01959 } 01960 break; 01961 } 01962 01963 if (iosm->goal == IOSM_PKGBUILD) { 01964 if (iosm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */ 01965 break; 01966 if (S_ISREG(st->st_mode) && st->st_nlink > 1) { 01967 struct hardLink_s * li, * prev; 01968 01969 if (!(iosm->mapFlags & IOSM_ALL_HARDLINKS)) break; 01970 rc = writeLinkedFile(iosm); 01971 if (rc) break; /* W2DO? */ 01972 01973 for (li = iosm->links, prev = NULL; li; prev = li, li = li->next) 01974 if (li == iosm->li) 01975 /*@loopbreak@*/ break; 01976 01977 if (prev == NULL) 01978 iosm->links = iosm->li->next; 01979 else 01980 prev->next = iosm->li->next; 01981 iosm->li->next = NULL; 01982 iosm->li = freeHardLink(iosm->li); 01983 } else { 01984 rc = writeFile(iosm, 1); 01985 } 01986 break; 01987 } 01988 01989 if (iosm->goal != IOSM_PKGINSTALL) 01990 break; 01991 01992 if (S_ISREG(st->st_mode) && iosm->lpath != NULL) { 01993 const char * opath = iosm->opath; 01994 char * t = xmalloc(strlen(iosm->lpath+1) + strlen(iosm->suffix) + 1); 01995 (void) stpcpy(t, iosm->lpath+1); 01996 iosm->opath = t; 01997 /* XXX link(iosm->opath, iosm->path) */ 01998 rc = iosmNext(iosm, IOSM_LINK); 01999 if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) { 02000 *iosm->failedFile = xstrdup(iosm->path); 02001 } 02002 iosm->opath = _free(iosm->opath); 02003 iosm->opath = opath; 02004 break; /* XXX so that delayed hard links get skipped. */ 02005 } 02006 if (S_ISREG(st->st_mode)) { 02007 const char * path = iosm->path; 02008 if (iosm->osuffix) 02009 iosm->path = iosmFsPath(iosm, st, NULL, NULL); 02010 rc = iosmUNSAFE(iosm, IOSM_VERIFY); 02011 02012 if (rc == 0 && iosm->osuffix) { 02013 const char * opath = iosm->opath; 02014 iosm->opath = iosm->path; 02015 iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix); 02016 rc = iosmNext(iosm, IOSM_RENAME); 02017 if (!rc) 02018 rpmlog(RPMLOG_WARNING, 02019 _("%s saved as %s\n"), 02020 (iosm->opath ? iosm->opath : ""), 02021 (iosm->path ? iosm->path : "")); 02022 iosm->path = _free(iosm->path); 02023 iosm->opath = opath; 02024 } 02025 02026 /*@-dependenttrans@*/ 02027 iosm->path = path; 02028 /*@=dependenttrans@*/ 02029 if (!(rc == IOSMERR_ENOENT)) return rc; 02030 rc = extractRegular(iosm); 02031 } else if (S_ISDIR(st->st_mode)) { 02032 mode_t st_mode = st->st_mode; 02033 rc = iosmUNSAFE(iosm, IOSM_VERIFY); 02034 if (rc == IOSMERR_ENOENT) { 02035 st->st_mode &= ~07777; /* XXX abuse st->st_mode */ 02036 st->st_mode |= 00700; 02037 rc = iosmNext(iosm, IOSM_MKDIR); 02038 st->st_mode = st_mode; /* XXX restore st->st_mode */ 02039 } 02040 } else if (S_ISLNK(st->st_mode)) { 02041 assert(iosm->lpath != NULL); 02042 rc = iosmUNSAFE(iosm, IOSM_VERIFY); 02043 if (rc == IOSMERR_ENOENT) 02044 rc = iosmNext(iosm, IOSM_SYMLINK); 02045 } else if (S_ISFIFO(st->st_mode)) { 02046 mode_t st_mode = st->st_mode; 02047 /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */ 02048 rc = iosmUNSAFE(iosm, IOSM_VERIFY); 02049 if (rc == IOSMERR_ENOENT) { 02050 st->st_mode = 0000; /* XXX abuse st->st_mode */ 02051 rc = iosmNext(iosm, IOSM_MKFIFO); 02052 st->st_mode = st_mode; /* XXX restore st->st_mode */ 02053 } 02054 } else if (S_ISCHR(st->st_mode) || 02055 S_ISBLK(st->st_mode) || 02056 /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/) 02057 { 02058 rc = iosmUNSAFE(iosm, IOSM_VERIFY); 02059 if (rc == IOSMERR_ENOENT) 02060 rc = iosmNext(iosm, IOSM_MKNOD); 02061 } else { 02062 /* XXX Repackaged payloads may be missing files. */ 02063 if (iosm->repackaged) 02064 break; 02065 02066 /* XXX Special case /dev/log, which shouldn't be packaged anyways */ 02067 if (!IS_DEV_LOG(iosm->path)) 02068 rc = IOSMERR_UNKNOWN_FILETYPE; 02069 } 02070 if (S_ISREG(st->st_mode) && st->st_nlink > 1) { 02071 iosm->li->createdPath = iosm->li->linkIndex; 02072 rc = iosmMakeLinks(iosm); 02073 } 02074 break; 02075 case IOSM_POST: 02076 break; 02077 case IOSM_MKLINKS: 02078 rc = iosmMakeLinks(iosm); 02079 break; 02080 case IOSM_NOTIFY: /* XXX move from iosm to psm -> tsm */ 02081 if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == IOSM_PKGBUILD) { 02082 rpmfi fi = iosmGetFi(iosm); 02083 rpmuint64_t archivePos = fdGetCpioPos(iosm->cfd); 02084 if (archivePos > fi->archivePos) { 02085 fi->archivePos = (unsigned long long) archivePos; 02086 #if defined(_USE_RPMTS) 02087 (void) rpmtsNotify(iosmGetTs(iosm), fi->te,RPMCALLBACK_INST_PROGRESS, 02088 fi->archivePos, fi->archiveSize); 02089 #endif 02090 } 02091 } 02092 break; 02093 case IOSM_UNDO: 02094 if (iosm->postpone) 02095 break; 02096 if (iosm->goal == IOSM_PKGINSTALL) { 02097 /* XXX only erase if temp fn w suffix is in use */ 02098 if (iosm->sufbuf[0] != '\0') 02099 (void) iosmNext(iosm, 02100 (S_ISDIR(st->st_mode) ? IOSM_RMDIR : IOSM_UNLINK)); 02101 02102 #ifdef NOTYET /* XXX remove only dirs just created, not all. */ 02103 if (iosm->dnlx) 02104 (void) iosmNext(iosm, IOSM_RMDIRS); 02105 #endif 02106 errno = saveerrno; 02107 } 02108 if (iosm->failedFile && *iosm->failedFile == NULL) 02109 *iosm->failedFile = xstrdup(iosm->path); 02110 break; 02111 case IOSM_FINI: 02112 if (!iosm->postpone && iosm->commit) { 02113 if (iosm->goal == IOSM_PKGINSTALL) 02114 rc = ((S_ISREG(st->st_mode) && st->st_nlink > 1) 02115 ? iosmCommitLinks(iosm) : iosmNext(iosm, IOSM_COMMIT)); 02116 if (iosm->goal == IOSM_PKGCOMMIT) 02117 rc = iosmNext(iosm, IOSM_COMMIT); 02118 if (iosm->goal == IOSM_PKGERASE) 02119 rc = iosmNext(iosm, IOSM_COMMIT); 02120 } 02121 iosm->path = _free(iosm->path); 02122 iosm->lpath = _free(iosm->lpath); 02123 iosm->opath = _free(iosm->opath); 02124 memset(st, 0, sizeof(*st)); 02125 memset(ost, 0, sizeof(*ost)); 02126 break; 02127 case IOSM_COMMIT: 02128 /* Rename pre-existing modified or unmanaged file. */ 02129 if (iosm->osuffix && iosm->diskchecked && 02130 (iosm->exists || (iosm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode)))) 02131 { 02132 const char * opath = iosm->opath; 02133 const char * path = iosm->path; 02134 iosm->opath = iosmFsPath(iosm, st, NULL, NULL); 02135 iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix); 02136 rc = iosmNext(iosm, IOSM_RENAME); 02137 if (!rc) { 02138 rpmlog(RPMLOG_WARNING, _("%s saved as %s\n"), 02139 (iosm->opath ? iosm->opath : ""), 02140 (iosm->path ? iosm->path : "")); 02141 } 02142 iosm->path = _free(iosm->path); 02143 iosm->path = path; 02144 iosm->opath = _free(iosm->opath); 02145 iosm->opath = opath; 02146 } 02147 02148 /* Remove erased files. */ 02149 if (iosm->goal == IOSM_PKGERASE) { 02150 if (iosm->action == FA_ERASE) { 02151 if (S_ISDIR(st->st_mode)) { 02152 rc = iosmNext(iosm, IOSM_RMDIR); 02153 if (!rc) break; 02154 switch (rc) { 02155 case IOSMERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */ 02156 case IOSMERR_ENOTEMPTY: 02157 /* XXX make sure that build side permits %missingok on directories. */ 02158 if (iosm->fflags & RPMFILE_MISSINGOK) 02159 /*@innerbreak@*/ break; 02160 02161 /* XXX common error message. */ 02162 rpmlog( 02163 (iosm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), 02164 _("rmdir of %s failed: Directory not empty\n"), 02165 iosm->path); 02166 /*@innerbreak@*/ break; 02167 default: 02168 rpmlog( 02169 (iosm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), 02170 _("rmdir of %s failed: %s\n"), 02171 iosm->path, strerror(errno)); 02172 /*@innerbreak@*/ break; 02173 } 02174 } else { 02175 rc = iosmNext(iosm, IOSM_UNLINK); 02176 if (!rc) break; 02177 switch (rc) { 02178 case IOSMERR_ENOENT: 02179 if (iosm->fflags & RPMFILE_MISSINGOK) 02180 /*@innerbreak@*/ break; 02181 /*@fallthrough@*/ 02182 default: 02183 rpmlog( 02184 (iosm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), 02185 _("unlink of %s failed: %s\n"), 02186 iosm->path, strerror(errno)); 02187 /*@innerbreak@*/ break; 02188 } 02189 } 02190 } 02191 /* XXX Failure to remove is not (yet) cause for failure. */ 02192 if (!iosm->strict_erasures) rc = 0; 02193 break; 02194 } 02195 02196 /* XXX Special case /dev/log, which shouldn't be packaged anyways */ 02197 { rpmfi fi = iosmGetFi(iosm); 02198 if (!(fi->mapflags & IOSM_PAYLOAD_EXTRACT)) { 02199 if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(iosm->path)) { 02200 /* Rename temporary to final file name. */ 02201 if (!S_ISDIR(st->st_mode) && 02202 (iosm->subdir || iosm->suffix || iosm->nsuffix)) 02203 { 02204 iosm->opath = iosm->path; 02205 iosm->path = iosmFsPath(iosm, st, NULL, iosm->nsuffix); 02206 rc = iosmNext(iosm, IOSM_RENAME); 02207 if (rc) 02208 (void) Unlink(iosm->opath); 02209 else if (iosm->nsuffix) { 02210 const char * opath = iosmFsPath(iosm, st, NULL, NULL); 02211 rpmlog(RPMLOG_WARNING, _("%s created as %s\n"), 02212 (opath ? opath : ""), 02213 (iosm->path ? iosm->path : "")); 02214 opath = _free(opath); 02215 } 02216 iosm->opath = _free(iosm->opath); 02217 } 02218 /* 02219 * Set file security context (if not disabled). 02220 */ 02221 if (!rc && !getuid()) { 02222 rc = iosmMapFContext(iosm); 02223 if (!rc) 02224 rc = iosmNext(iosm, IOSM_LSETFCON); 02225 iosm->fcontext = NULL; 02226 } 02227 if (S_ISLNK(st->st_mode)) { 02228 if (!rc && !getuid()) 02229 rc = iosmNext(iosm, IOSM_LCHOWN); 02230 } else { 02231 if (!rc && !getuid()) 02232 rc = iosmNext(iosm, IOSM_CHOWN); 02233 if (!rc) 02234 rc = iosmNext(iosm, IOSM_CHMOD); 02235 if (!rc) { 02236 time_t mtime = st->st_mtime; 02237 if (fi->fmtimes) 02238 st->st_mtime = fi->fmtimes[iosm->ix]; 02239 rc = iosmNext(iosm, IOSM_UTIME); 02240 st->st_mtime = mtime; 02241 } 02242 } 02243 } 02244 } 02245 } 02246 02247 /* Notify on success. */ 02248 if (!rc) rc = iosmNext(iosm, IOSM_NOTIFY); 02249 else if (iosm->failedFile && *iosm->failedFile == NULL) { 02250 *iosm->failedFile = iosm->path; 02251 iosm->path = NULL; 02252 } 02253 break; 02254 case IOSM_DESTROY: 02255 iosm->path = _free(iosm->path); 02256 02257 /* Check for hard links missing from payload. */ 02258 while ((iosm->li = iosm->links) != NULL) { 02259 iosm->links = iosm->li->next; 02260 iosm->li->next = NULL; 02261 if (iosm->goal == IOSM_PKGINSTALL && 02262 iosm->commit && iosm->li->linksLeft) 02263 { 02264 for (i = 0 ; i < iosm->li->linksLeft; i++) { 02265 if (iosm->li->filex[i] < 0) 02266 /*@innercontinue@*/ continue; 02267 rc = IOSMERR_MISSING_HARDLINK; 02268 if (iosm->failedFile && *iosm->failedFile == NULL) { 02269 iosm->ix = iosm->li->filex[i]; 02270 if (!iosmNext(iosm, IOSM_MAP)) { 02271 *iosm->failedFile = iosm->path; 02272 iosm->path = NULL; 02273 } 02274 } 02275 /*@loopbreak@*/ break; 02276 } 02277 } 02278 if (iosm->goal == IOSM_PKGBUILD && 02279 (iosm->mapFlags & IOSM_ALL_HARDLINKS)) 02280 { 02281 rc = IOSMERR_MISSING_HARDLINK; 02282 } 02283 iosm->li = freeHardLink(iosm->li); 02284 } 02285 iosm->ldn = _free(iosm->ldn); 02286 iosm->ldnalloc = iosm->ldnlen = 0; 02287 iosm->rdbuf = iosm->rdb = _free(iosm->rdb); 02288 iosm->wrbuf = iosm->wrb = _free(iosm->wrb); 02289 break; 02290 case IOSM_VERIFY: 02291 if (iosm->diskchecked && !iosm->exists) { 02292 rc = IOSMERR_ENOENT; 02293 break; 02294 } 02295 if (S_ISREG(st->st_mode)) { 02296 char * path = alloca(strlen(iosm->path) + sizeof("-RPMDELETE")); 02297 (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE"); 02298 /* 02299 * XXX HP-UX (and other os'es) don't permit unlink on busy 02300 * XXX files. 02301 */ 02302 iosm->opath = iosm->path; 02303 iosm->path = path; 02304 rc = iosmNext(iosm, IOSM_RENAME); 02305 if (!rc) 02306 (void) iosmNext(iosm, IOSM_UNLINK); 02307 else 02308 rc = IOSMERR_UNLINK_FAILED; 02309 iosm->path = iosm->opath; 02310 iosm->opath = NULL; 02311 return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */ 02312 /*@notreached@*/ break; 02313 } else if (S_ISDIR(st->st_mode)) { 02314 if (S_ISDIR(ost->st_mode)) return 0; 02315 if (S_ISLNK(ost->st_mode)) { 02316 rc = iosmUNSAFE(iosm, IOSM_STAT); 02317 if (rc == IOSMERR_ENOENT) rc = 0; 02318 if (rc) break; 02319 errno = saveerrno; 02320 if (S_ISDIR(ost->st_mode)) return 0; 02321 } 02322 } else if (S_ISLNK(st->st_mode)) { 02323 if (S_ISLNK(ost->st_mode)) { 02324 /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */ 02325 rc = iosmUNSAFE(iosm, IOSM_READLINK); 02326 errno = saveerrno; 02327 if (rc) break; 02328 if (!strcmp(iosm->lpath, iosm->rdbuf)) return 0; 02329 } 02330 } else if (S_ISFIFO(st->st_mode)) { 02331 if (S_ISFIFO(ost->st_mode)) return 0; 02332 } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { 02333 if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) && 02334 (ost->st_rdev == st->st_rdev)) return 0; 02335 } else if (S_ISSOCK(st->st_mode)) { 02336 if (S_ISSOCK(ost->st_mode)) return 0; 02337 } 02338 /* XXX shouldn't do this with commit/undo. */ 02339 rc = 0; 02340 if (iosm->stage == IOSM_PROCESS) rc = iosmNext(iosm, IOSM_UNLINK); 02341 if (rc == 0) rc = IOSMERR_ENOENT; 02342 return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */ 02343 /*@notreached@*/ break; 02344 02345 case IOSM_UNLINK: 02346 /* XXX Remove setuid/setgid bits on possibly hard linked files. */ 02347 if (iosm->mapFlags & IOSM_SBIT_CHECK) { 02348 struct stat stb; 02349 if (Lstat(iosm->path, &stb) == 0 && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0) { 02350 /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */ 02351 (void)Chmod(iosm->path, stb.st_mode & 0777); 02352 } 02353 } 02354 rc = Unlink(iosm->path); 02355 if (iosm->debug && (stage & IOSM_SYSCALL)) 02356 rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur, 02357 iosm->path, (rc < 0 ? strerror(errno) : "")); 02358 if (rc < 0) 02359 rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_UNLINK_FAILED); 02360 break; 02361 case IOSM_RENAME: 02362 /* XXX Remove setuid/setgid bits on possibly hard linked files. */ 02363 if (iosm->mapFlags & IOSM_SBIT_CHECK) { 02364 struct stat stb; 02365 if (Lstat(iosm->path, &stb) == 0 && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0) { 02366 /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */ 02367 (void)Chmod(iosm->path, stb.st_mode & 0777); 02368 } 02369 } 02370 rc = Rename(iosm->opath, iosm->path); 02371 /* XXX Repackaged payloads may be missing files. */ 02372 if (iosm->repackaged) 02373 rc = 0; 02374 #if defined(ETXTBSY) 02375 if (rc && errno == ETXTBSY) { 02376 char * path = alloca(strlen(iosm->path) + sizeof("-RPMDELETE")); 02377 (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE"); 02378 /* 02379 * XXX HP-UX (and other os'es) don't permit rename to busy 02380 * XXX files. 02381 */ 02382 rc = Rename(iosm->path, path); 02383 if (!rc) rc = Rename(iosm->opath, iosm->path); 02384 } 02385 #endif 02386 if (iosm->debug && (stage & IOSM_SYSCALL)) 02387 rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur, 02388 iosm->opath, iosm->path, (rc < 0 ? strerror(errno) : "")); 02389 if (rc < 0) rc = IOSMERR_RENAME_FAILED; 02390 break; 02391 case IOSM_MKDIR: 02392 rc = Mkdir(iosm->path, (st->st_mode & 07777)); 02393 if (iosm->debug && (stage & IOSM_SYSCALL)) 02394 rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur, 02395 iosm->path, (unsigned)(st->st_mode & 07777), 02396 (rc < 0 ? strerror(errno) : "")); 02397 if (rc < 0) rc = IOSMERR_MKDIR_FAILED; 02398 break; 02399 case IOSM_RMDIR: 02400 rc = Rmdir(iosm->path); 02401 if (iosm->debug && (stage & IOSM_SYSCALL)) 02402 rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur, 02403 iosm->path, (rc < 0 ? strerror(errno) : "")); 02404 if (rc < 0) 02405 switch (errno) { 02406 case ENOENT: rc = IOSMERR_ENOENT; /*@switchbreak@*/ break; 02407 case ENOTEMPTY: rc = IOSMERR_ENOTEMPTY; /*@switchbreak@*/ break; 02408 default: rc = IOSMERR_RMDIR_FAILED; /*@switchbreak@*/ break; 02409 } 02410 break; 02411 case IOSM_LSETFCON: 02412 { const char * iosmpath = NULL; 02413 if (iosm->fcontext == NULL || *iosm->fcontext == '\0' 02414 || !strcmp(iosm->fcontext, "<<none>>")) 02415 break; 02416 (void) urlPath(iosm->path, &iosmpath); /* XXX iosm->path */ 02417 rc = lsetfilecon(iosmpath, (security_context_t)iosm->fcontext); 02418 if (iosm->debug && (stage & IOSM_SYSCALL)) 02419 rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur, 02420 iosm->path, iosm->fcontext, 02421 (rc < 0 ? strerror(errno) : "")); 02422 if (rc < 0) rc = (errno == EOPNOTSUPP ? 0 : IOSMERR_LSETFCON_FAILED); 02423 } break; 02424 case IOSM_CHOWN: 02425 rc = Chown(iosm->path, st->st_uid, st->st_gid); 02426 if (iosm->debug && (stage & IOSM_SYSCALL)) 02427 rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, %d) %s\n", cur, 02428 iosm->path, (int)st->st_uid, (int)st->st_gid, 02429 (rc < 0 ? strerror(errno) : "")); 02430 if (rc < 0) rc = IOSMERR_CHOWN_FAILED; 02431 break; 02432 case IOSM_LCHOWN: 02433 #if ! CHOWN_FOLLOWS_SYMLINK 02434 rc = Lchown(iosm->path, st->st_uid, st->st_gid); 02435 if (iosm->debug && (stage & IOSM_SYSCALL)) 02436 rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, %d) %s\n", cur, 02437 iosm->path, (int)st->st_uid, (int)st->st_gid, 02438 (rc < 0 ? strerror(errno) : "")); 02439 if (rc < 0) rc = IOSMERR_CHOWN_FAILED; 02440 #endif 02441 break; 02442 case IOSM_CHMOD: 02443 rc = Chmod(iosm->path, (st->st_mode & 07777)); 02444 if (iosm->debug && (stage & IOSM_SYSCALL)) 02445 rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur, 02446 iosm->path, (unsigned)(st->st_mode & 07777), 02447 (rc < 0 ? strerror(errno) : "")); 02448 if (rc < 0) rc = IOSMERR_CHMOD_FAILED; 02449 break; 02450 case IOSM_UTIME: 02451 { struct utimbuf stamp; 02452 stamp.actime = st->st_mtime; 02453 stamp.modtime = st->st_mtime; 02454 rc = Utime(iosm->path, &stamp); 02455 if (iosm->debug && (stage & IOSM_SYSCALL)) 02456 rpmlog(RPMLOG_DEBUG, " %8s (%s, 0x%x) %s\n", cur, 02457 iosm->path, (unsigned)st->st_mtime, 02458 (rc < 0 ? strerror(errno) : "")); 02459 if (rc < 0) rc = IOSMERR_UTIME_FAILED; 02460 } 02461 break; 02462 case IOSM_SYMLINK: 02463 rc = Symlink(iosm->lpath, iosm->path); 02464 if (iosm->debug && (stage & IOSM_SYSCALL)) 02465 rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur, 02466 iosm->lpath, iosm->path, (rc < 0 ? strerror(errno) : "")); 02467 if (rc < 0) rc = IOSMERR_SYMLINK_FAILED; 02468 break; 02469 case IOSM_LINK: 02470 rc = Link(iosm->opath, iosm->path); 02471 if (iosm->debug && (stage & IOSM_SYSCALL)) 02472 rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur, 02473 iosm->opath, iosm->path, (rc < 0 ? strerror(errno) : "")); 02474 if (rc < 0) rc = IOSMERR_LINK_FAILED; 02475 break; 02476 case IOSM_MKFIFO: 02477 rc = Mkfifo(iosm->path, (st->st_mode & 07777)); 02478 if (iosm->debug && (stage & IOSM_SYSCALL)) 02479 rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur, 02480 iosm->path, (unsigned)(st->st_mode & 07777), 02481 (rc < 0 ? strerror(errno) : "")); 02482 if (rc < 0) rc = IOSMERR_MKFIFO_FAILED; 02483 break; 02484 case IOSM_MKNOD: 02485 /*@-unrecog -portability @*/ /* FIX: check S_IFIFO or dev != 0 */ 02486 rc = Mknod(iosm->path, (st->st_mode & ~07777), st->st_rdev); 02487 /*@=unrecog =portability @*/ 02488 if (iosm->debug && (stage & IOSM_SYSCALL)) 02489 rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur, 02490 iosm->path, (unsigned)(st->st_mode & ~07777), 02491 (unsigned)st->st_rdev, 02492 (rc < 0 ? strerror(errno) : "")); 02493 if (rc < 0) rc = IOSMERR_MKNOD_FAILED; 02494 break; 02495 case IOSM_LSTAT: 02496 rc = Lstat(iosm->path, ost); 02497 if (iosm->debug && (stage & IOSM_SYSCALL) && rc && errno != ENOENT) 02498 rpmlog(RPMLOG_DEBUG, " %8s (%s, ost) %s\n", cur, 02499 iosm->path, (rc < 0 ? strerror(errno) : "")); 02500 if (rc < 0) { 02501 rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_LSTAT_FAILED); 02502 memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */ 02503 } 02504 break; 02505 case IOSM_STAT: 02506 rc = Stat(iosm->path, ost); 02507 if (iosm->debug && (stage & IOSM_SYSCALL) && rc && errno != ENOENT) 02508 rpmlog(RPMLOG_DEBUG, " %8s (%s, ost) %s\n", cur, 02509 iosm->path, (rc < 0 ? strerror(errno) : "")); 02510 if (rc < 0) { 02511 rc = (errno == ENOENT ? IOSMERR_ENOENT : IOSMERR_STAT_FAILED); 02512 memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */ 02513 } 02514 break; 02515 case IOSM_READLINK: 02516 /* XXX NUL terminated result in iosm->rdbuf, len in iosm->rdnb. */ 02517 rc = Readlink(iosm->path, iosm->rdbuf, iosm->rdsize - 1); 02518 if (iosm->debug && (stage & IOSM_SYSCALL)) 02519 rpmlog(RPMLOG_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur, 02520 iosm->path, (int)(iosm->rdsize -1), (rc < 0 ? strerror(errno) : "")); 02521 if (rc < 0) rc = IOSMERR_READLINK_FAILED; 02522 else { 02523 iosm->rdnb = rc; 02524 iosm->rdbuf[iosm->rdnb] = '\0'; 02525 rc = 0; 02526 } 02527 break; 02528 case IOSM_CHROOT: 02529 break; 02530 02531 case IOSM_NEXT: 02532 rc = iosmUNSAFE(iosm, IOSM_HREAD); 02533 if (rc) break; 02534 if (!strcmp(iosm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */ 02535 iosm->path = _free(iosm->path); 02536 rc = IOSMERR_HDR_TRAILER; 02537 } 02538 if (!rc) 02539 rc = iosmNext(iosm, IOSM_POS); 02540 break; 02541 case IOSM_EAT: 02542 for (left = st->st_size; left > 0; left -= iosm->rdnb) { 02543 iosm->wrlen = (left > iosm->wrsize ? iosm->wrsize : left); 02544 rc = iosmNext(iosm, IOSM_DREAD); 02545 if (rc) 02546 /*@loopbreak@*/ break; 02547 } 02548 break; 02549 case IOSM_POS: 02550 left = (iosm->blksize - (fdGetCpioPos(iosm->cfd) % iosm->blksize)) % iosm->blksize; 02551 if (left) { 02552 iosm->wrlen = left; 02553 (void) iosmNext(iosm, IOSM_DREAD); 02554 } 02555 break; 02556 case IOSM_PAD: 02557 left = (iosm->blksize - (fdGetCpioPos(iosm->cfd) % iosm->blksize)) % iosm->blksize; 02558 if (left) { 02559 if (iosm->blksize == 2) 02560 iosm->rdbuf[0] = '\n'; /* XXX ar(1) pads with '\n' */ 02561 else 02562 memset(iosm->rdbuf, 0, left); 02563 /* XXX DWRITE uses rdnb for I/O length. */ 02564 iosm->rdnb = left; 02565 (void) iosmNext(iosm, IOSM_DWRITE); 02566 } 02567 break; 02568 case IOSM_TRAILER: 02569 rc = (*iosm->trailerWrite) (iosm); /* Write payload trailer. */ 02570 break; 02571 case IOSM_HREAD: 02572 rc = iosmNext(iosm, IOSM_POS); 02573 if (!rc) 02574 rc = (*iosm->headerRead) (iosm, st); /* Read next payload header. */ 02575 break; 02576 case IOSM_HWRITE: 02577 rc = (*iosm->headerWrite) (iosm, st); /* Write next payload header. */ 02578 break; 02579 case IOSM_DREAD: 02580 iosm->rdnb = Fread(iosm->wrbuf, sizeof(*iosm->wrbuf), iosm->wrlen, iosm->cfd); 02581 if (iosm->debug && (stage & IOSM_SYSCALL)) 02582 rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n", 02583 cur, (iosm->wrbuf == iosm->wrb ? "wrbuf" : "mmap"), 02584 (int)iosm->wrlen, (int)iosm->rdnb); 02585 if (iosm->rdnb != iosm->wrlen || Ferror(iosm->cfd)) 02586 rc = IOSMERR_READ_FAILED; 02587 if (iosm->rdnb > 0) 02588 fdSetCpioPos(iosm->cfd, fdGetCpioPos(iosm->cfd) + iosm->rdnb); 02589 break; 02590 case IOSM_DWRITE: 02591 iosm->wrnb = Fwrite(iosm->rdbuf, sizeof(*iosm->rdbuf), iosm->rdnb, iosm->cfd); 02592 if (iosm->debug && (stage & IOSM_SYSCALL)) 02593 rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n", 02594 cur, (iosm->rdbuf == iosm->rdb ? "rdbuf" : "mmap"), 02595 (int)iosm->rdnb, (int)iosm->wrnb); 02596 if (iosm->rdnb != iosm->wrnb || Ferror(iosm->cfd)) 02597 rc = IOSMERR_WRITE_FAILED; 02598 if (iosm->wrnb > 0) 02599 fdSetCpioPos(iosm->cfd, fdGetCpioPos(iosm->cfd) + iosm->wrnb); 02600 break; 02601 02602 case IOSM_ROPEN: 02603 iosm->rfd = Fopen(iosm->path, "r.fdio"); 02604 if (iosm->rfd == NULL || Ferror(iosm->rfd)) { 02605 if (iosm->rfd != NULL) (void) iosmNext(iosm, IOSM_RCLOSE); 02606 iosm->rfd = NULL; 02607 rc = IOSMERR_OPEN_FAILED; 02608 break; 02609 } 02610 if (iosm->debug && (stage & IOSM_SYSCALL)) 02611 rpmlog(RPMLOG_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur, 02612 iosm->path, iosm->rfd, iosm->rdbuf); 02613 break; 02614 case IOSM_READ: 02615 iosm->rdnb = Fread(iosm->rdbuf, sizeof(*iosm->rdbuf), iosm->rdlen, iosm->rfd); 02616 if (iosm->debug && (stage & IOSM_SYSCALL)) 02617 rpmlog(RPMLOG_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n", 02618 cur, (int)iosm->rdlen, (int)iosm->rdnb); 02619 if (iosm->rdnb != iosm->rdlen || Ferror(iosm->rfd)) 02620 rc = IOSMERR_READ_FAILED; 02621 break; 02622 case IOSM_RCLOSE: 02623 if (iosm->rfd != NULL) { 02624 if (iosm->debug && (stage & IOSM_SYSCALL)) 02625 rpmlog(RPMLOG_DEBUG, " %8s (%p)\n", cur, iosm->rfd); 02626 (void) rpmswAdd(&iosm->op_digest, 02627 fdstat_op(iosm->rfd, FDSTAT_DIGEST)); 02628 (void) Fclose(iosm->rfd); 02629 errno = saveerrno; 02630 } 02631 iosm->rfd = NULL; 02632 break; 02633 case IOSM_WOPEN: 02634 iosm->wfd = Fopen(iosm->path, "w.fdio"); 02635 if (iosm->wfd == NULL || Ferror(iosm->wfd)) { 02636 if (iosm->wfd != NULL) (void) iosmNext(iosm, IOSM_WCLOSE); 02637 iosm->wfd = NULL; 02638 rc = IOSMERR_OPEN_FAILED; 02639 } 02640 if (iosm->debug && (stage & IOSM_SYSCALL)) 02641 rpmlog(RPMLOG_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur, 02642 iosm->path, iosm->wfd, iosm->wrbuf); 02643 break; 02644 case IOSM_WRITE: 02645 iosm->wrnb = Fwrite(iosm->wrbuf, sizeof(*iosm->wrbuf), iosm->rdnb, iosm->wfd); 02646 if (iosm->debug && (stage & IOSM_SYSCALL)) 02647 rpmlog(RPMLOG_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n", 02648 cur, (int)iosm->rdnb, (int)iosm->wrnb); 02649 if (iosm->rdnb != iosm->wrnb || Ferror(iosm->wfd)) 02650 rc = IOSMERR_WRITE_FAILED; 02651 break; 02652 case IOSM_WCLOSE: 02653 if (iosm->wfd != NULL) { 02654 if (iosm->debug && (stage & IOSM_SYSCALL)) 02655 rpmlog(RPMLOG_DEBUG, " %8s (%p)\n", cur, iosm->wfd); 02656 (void) rpmswAdd(&iosm->op_digest, 02657 fdstat_op(iosm->wfd, FDSTAT_DIGEST)); 02658 (void) Fclose(iosm->wfd); 02659 errno = saveerrno; 02660 } 02661 iosm->wfd = NULL; 02662 break; 02663 02664 default: 02665 break; 02666 } 02667 02668 if (!(stage & IOSM_INTERNAL)) { 02669 iosm->rc = (rc == IOSMERR_HDR_TRAILER ? 0 : rc); 02670 } 02671 return rc; 02672 } 02673 /*@=compmempass@*/ 02674 02675 #define IOSM_SKIPPING(_a) \ 02676 ((_a) == FA_SKIP || (_a) == FA_SKIPNSTATE || (_a) == FA_SKIPNETSHARED || (_a) == FA_SKIPCOLOR) 02677 02678 int iosmFileActionSkipped(iosmFileAction action) 02679 { 02680 return IOSM_SKIPPING(action); 02681 } 02682 02683 /*@observer@*/ const char * iosmFileActionString(iosmFileAction a) 02684 { 02685 switch (a) { 02686 case FA_UNKNOWN: return "unknown"; 02687 case FA_CREATE: return "create"; 02688 case FA_COPYOUT: return "copyout"; 02689 case FA_COPYIN: return "copyin"; 02690 case FA_BACKUP: return "backup"; 02691 case FA_SAVE: return "save"; 02692 case FA_SKIP: return "skip"; 02693 case FA_ALTNAME: return "altname"; 02694 case FA_ERASE: return "erase"; 02695 case FA_SKIPNSTATE: return "skipnstate"; 02696 case FA_SKIPNETSHARED: return "skipnetshared"; 02697 case FA_SKIPCOLOR: return "skipcolor"; 02698 default: return "???"; 02699 } 02700 /*@notreached@*/ 02701 } 02702 02703 /*@observer@*/ const char * iosmFileStageString(iosmFileStage a) { 02704 switch(a) { 02705 case IOSM_UNKNOWN: return "unknown"; 02706 02707 case IOSM_PKGINSTALL:return "INSTALL"; 02708 case IOSM_PKGERASE: return "ERASE"; 02709 case IOSM_PKGBUILD: return "BUILD"; 02710 case IOSM_PKGCOMMIT: return "COMMIT"; 02711 case IOSM_PKGUNDO: return "UNDO"; 02712 02713 case IOSM_CREATE: return "create"; 02714 case IOSM_INIT: return "init"; 02715 case IOSM_MAP: return "map"; 02716 case IOSM_MKDIRS: return "mkdirs"; 02717 case IOSM_RMDIRS: return "rmdirs"; 02718 case IOSM_PRE: return "pre"; 02719 case IOSM_PROCESS: return "process"; 02720 case IOSM_POST: return "post"; 02721 case IOSM_MKLINKS: return "mklinks"; 02722 case IOSM_NOTIFY: return "notify"; 02723 case IOSM_UNDO: return "undo"; 02724 case IOSM_FINI: return "fini"; 02725 case IOSM_COMMIT: return "commit"; 02726 case IOSM_DESTROY: return "destroy"; 02727 case IOSM_VERIFY: return "verify"; 02728 02729 case IOSM_UNLINK: return "Unlink"; 02730 case IOSM_RENAME: return "Rename"; 02731 case IOSM_MKDIR: return "Mkdir"; 02732 case IOSM_RMDIR: return "Rmdir"; 02733 case IOSM_LSETFCON: return "lsetfcon"; 02734 case IOSM_CHOWN: return "Chown"; 02735 case IOSM_LCHOWN: return "Lchown"; 02736 case IOSM_CHMOD: return "Chmod"; 02737 case IOSM_UTIME: return "Utime"; 02738 case IOSM_SYMLINK: return "Symlink"; 02739 case IOSM_LINK: return "Link"; 02740 case IOSM_MKFIFO: return "Mkfifo"; 02741 case IOSM_MKNOD: return "Mknod"; 02742 case IOSM_LSTAT: return "Lstat"; 02743 case IOSM_STAT: return "Stat"; 02744 case IOSM_READLINK: return "Readlink"; 02745 case IOSM_CHROOT: return "Chroot"; 02746 02747 case IOSM_NEXT: return "next"; 02748 case IOSM_EAT: return "eat"; 02749 case IOSM_POS: return "pos"; 02750 case IOSM_PAD: return "pad"; 02751 case IOSM_TRAILER: return "trailer"; 02752 case IOSM_HREAD: return "hread"; 02753 case IOSM_HWRITE: return "hwrite"; 02754 case IOSM_DREAD: return "Fread"; 02755 case IOSM_DWRITE: return "Fwrite"; 02756 02757 case IOSM_ROPEN: return "Fopen"; 02758 case IOSM_READ: return "Fread"; 02759 case IOSM_RCLOSE: return "Fclose"; 02760 case IOSM_WOPEN: return "Fopen"; 02761 case IOSM_WRITE: return "Fwrite"; 02762 case IOSM_WCLOSE: return "Fclose"; 02763 02764 default: return "???"; 02765 } 02766 /*@noteached@*/ 02767 } 02768 02769 char * iosmStrerror(int rc) 02770 { 02771 char msg[256]; 02772 char *s; 02773 int l, myerrno = errno; 02774 02775 strcpy(msg, "cpio: "); 02776 switch (rc) { 02777 default: 02778 s = msg + strlen(msg); 02779 sprintf(s, _("(error 0x%x)"), (unsigned)rc); 02780 s = NULL; 02781 break; 02782 case IOSMERR_BAD_MAGIC: s = _("Bad magic"); break; 02783 case IOSMERR_BAD_HEADER: s = _("Bad/unreadable header"); break; 02784 02785 case IOSMERR_OPEN_FAILED: s = "open"; break; 02786 case IOSMERR_CHMOD_FAILED: s = "chmod"; break; 02787 case IOSMERR_CHOWN_FAILED: s = "chown"; break; 02788 case IOSMERR_WRITE_FAILED: s = "write"; break; 02789 case IOSMERR_UTIME_FAILED: s = "utime"; break; 02790 case IOSMERR_UNLINK_FAILED: s = "unlink"; break; 02791 case IOSMERR_RENAME_FAILED: s = "rename"; break; 02792 case IOSMERR_SYMLINK_FAILED: s = "symlink"; break; 02793 case IOSMERR_STAT_FAILED: s = "stat"; break; 02794 case IOSMERR_LSTAT_FAILED: s = "lstat"; break; 02795 case IOSMERR_MKDIR_FAILED: s = "mkdir"; break; 02796 case IOSMERR_RMDIR_FAILED: s = "rmdir"; break; 02797 case IOSMERR_MKNOD_FAILED: s = "mknod"; break; 02798 case IOSMERR_MKFIFO_FAILED: s = "mkfifo"; break; 02799 case IOSMERR_LINK_FAILED: s = "link"; break; 02800 case IOSMERR_READLINK_FAILED: s = "readlink"; break; 02801 case IOSMERR_READ_FAILED: s = "read"; break; 02802 case IOSMERR_COPY_FAILED: s = "copy"; break; 02803 case IOSMERR_LSETFCON_FAILED: s = "lsetfilecon"; break; 02804 02805 case IOSMERR_HDR_SIZE: s = _("Header size too big"); break; 02806 case IOSMERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break; 02807 case IOSMERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break; 02808 case IOSMERR_DIGEST_MISMATCH: s = _("File digest mismatch"); break; 02809 case IOSMERR_INTERNAL: s = _("Internal error"); break; 02810 case IOSMERR_UNMAPPED_FILE: s = _("Archive file not in header"); break; 02811 case IOSMERR_ENOENT: s = strerror(ENOENT); break; 02812 case IOSMERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break; 02813 } 02814 02815 l = sizeof(msg) - strlen(msg) - 1; 02816 if (s != NULL) { 02817 if (l > 0) strncat(msg, s, l); 02818 l -= strlen(s); 02819 } 02820 if ((rc & IOSMERR_CHECK_ERRNO) && myerrno) { 02821 s = _(" failed - "); 02822 if (l > 0) strncat(msg, s, l); 02823 l -= strlen(s); 02824 if (l > 0) strncat(msg, strerror(myerrno), l); 02825 } 02826 return xstrdup(msg); 02827 }