rpm
4.5
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio_internal.h> 00009 #include <rpmlib.h> 00010 00011 #include "cpio.h" 00012 #include "tar.h" 00013 00014 #include "fsm.h" 00015 #define fsmUNSAFE fsmStage 00016 00017 #include "rpmerr.h" 00018 00019 #define _RPMFI_INTERNAL 00020 #include "rpmfi.h" 00021 #include "rpmte.h" 00022 #include "rpmts.h" 00023 #include "rpmsq.h" 00024 00025 #include "ugid.h" /* XXX unameToUid() and gnameToGid() */ 00026 00027 #include "debug.h" 00028 00029 /*@access FD_t @*/ /* XXX void ptr args */ 00030 /*@access FSMI_t @*/ 00031 /*@access FSM_t @*/ 00032 00033 /*@access rpmfi @*/ 00034 00035 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) 00036 00037 #define _FSM_DEBUG 0 00038 /*@unchecked@*/ 00039 int _fsm_debug = _FSM_DEBUG; 00040 00041 /*@-exportheadervar@*/ 00042 /*@unchecked@*/ 00043 int _fsm_threads = 0; 00044 /*@=exportheadervar@*/ 00045 00046 /* XXX Failure to remove is not (yet) cause for failure. */ 00047 /*@-exportlocal -exportheadervar@*/ 00048 /*@unchecked@*/ 00049 int strict_erasures = 0; 00050 /*@=exportlocal =exportheadervar@*/ 00051 00052 rpmts fsmGetTs(const FSM_t fsm) { 00053 const FSMI_t iter = fsm->iter; 00054 /*@-compdef -refcounttrans -retexpose -usereleased @*/ 00055 return (iter ? iter->ts : NULL); 00056 /*@=compdef =refcounttrans =retexpose =usereleased @*/ 00057 } 00058 00059 rpmfi fsmGetFi(const FSM_t fsm) 00060 { 00061 const FSMI_t iter = fsm->iter; 00062 /*@-compdef -refcounttrans -retexpose -usereleased @*/ 00063 return (iter ? iter->fi : NULL); 00064 /*@=compdef =refcounttrans =retexpose =usereleased @*/ 00065 } 00066 00067 #define SUFFIX_RPMORIG ".rpmorig" 00068 #define SUFFIX_RPMSAVE ".rpmsave" 00069 #define SUFFIX_RPMNEW ".rpmnew" 00070 00079 static /*@only@*//*@null@*/ 00080 const char * fsmFsPath(/*@special@*/ /*@null@*/ const FSM_t fsm, 00081 /*@null@*/ const struct stat * st, 00082 /*@null@*/ const char * subdir, 00083 /*@null@*/ const char * suffix) 00084 /*@uses fsm->dirName, fsm->baseName */ 00085 /*@*/ 00086 { 00087 const char * s = NULL; 00088 00089 if (fsm) { 00090 char * t; 00091 int nb; 00092 nb = strlen(fsm->dirName) + 00093 (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : 0) : 0) + 00094 (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : 0) : 0) + 00095 strlen(fsm->baseName) + 1; 00096 /*@-boundswrite@*/ 00097 s = t = xmalloc(nb); 00098 t = stpcpy(t, fsm->dirName); 00099 if (st && !S_ISDIR(st->st_mode)) 00100 if (subdir) t = stpcpy(t, subdir); 00101 t = stpcpy(t, fsm->baseName); 00102 if (st && !S_ISDIR(st->st_mode)) 00103 if (suffix) t = stpcpy(t, suffix); 00104 /*@=boundswrite@*/ 00105 } 00106 return s; 00107 } 00108 00114 static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ void * p) 00115 /*@globals fileSystem @*/ 00116 /*@modifies fileSystem @*/ 00117 { 00118 FSMI_t iter = p; 00119 if (iter) { 00120 /*@-internalglobs@*/ /* XXX rpmswExit() */ 00121 iter->ts = rpmtsFree(iter->ts); 00122 /*@=internalglobs@*/ 00123 iter->fi = rpmfiUnlink(iter->fi, "mapIterator"); 00124 } 00125 return _free(p); 00126 } 00127 00134 static void * 00135 mapInitIterator(rpmts ts, rpmfi fi) 00136 /*@modifies ts, fi @*/ 00137 { 00138 FSMI_t iter = NULL; 00139 00140 iter = xcalloc(1, sizeof(*iter)); 00141 iter->ts = rpmtsLink(ts, "mapIterator"); 00142 iter->fi = rpmfiLink(fi, "mapIterator"); 00143 iter->reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT); 00144 iter->i = (iter->reverse ? (fi->fc - 1) : 0); 00145 iter->isave = iter->i; 00146 return iter; 00147 } 00148 00154 static int mapNextIterator(/*@null@*/ void * a) 00155 /*@*/ 00156 { 00157 FSMI_t iter = a; 00158 int i = -1; 00159 00160 if (iter) { 00161 const rpmfi fi = iter->fi; 00162 if (iter->reverse) { 00163 if (iter->i >= 0) i = iter->i--; 00164 } else { 00165 if (iter->i < fi->fc) i = iter->i++; 00166 } 00167 iter->isave = i; 00168 } 00169 return i; 00170 } 00171 00174 /*@-boundsread@*/ 00175 static int cpioStrCmp(const void * a, const void * b) 00176 /*@*/ 00177 { 00178 const char * aurl = *(const char **)a; 00179 const char * burl = *(const char **)b; 00180 const char * afn = NULL; 00181 const char * bfn = NULL; 00182 00183 (void) urlPath(aurl, &afn); 00184 (void) urlPath(burl, &bfn); 00185 00186 /* XXX Some 4+ year old rpm packages have basename only in payloads. */ 00187 #ifdef VERY_OLD_BUGGY_RPM_PACKAGES 00188 if (strchr(afn, '/') == NULL) 00189 bfn = strrchr(bfn, '/') + 1; 00190 #endif 00191 00192 /* Match rpm-4.0 payloads with ./ prefixes. */ 00193 if (afn[0] == '.' && afn[1] == '/') afn += 2; 00194 if (bfn[0] == '.' && bfn[1] == '/') bfn += 2; 00195 00196 /* If either path is absolute, make it relative. */ 00197 if (afn[0] == '/') afn += 1; 00198 if (bfn[0] == '/') bfn += 1; 00199 00200 return strcmp(afn, bfn); 00201 } 00202 /*@=boundsread@*/ 00203 00210 /*@-boundsread@*/ 00211 static int mapFind(/*@null@*/ FSMI_t iter, const char * fsmPath) 00212 /*@modifies iter @*/ 00213 { 00214 int ix = -1; 00215 00216 if (iter) { 00217 const rpmfi fi = iter->fi; 00218 if (fi && fi->fc > 0 && fi->apath && fsmPath && *fsmPath) { 00219 const char ** p = NULL; 00220 00221 /*@-boundswrite@*/ 00222 if (fi->apath != NULL) 00223 p = bsearch(&fsmPath, fi->apath, fi->fc, sizeof(fsmPath), 00224 cpioStrCmp); 00225 /*@=boundswrite@*/ 00226 if (p) { 00227 iter->i = p - fi->apath; 00228 ix = mapNextIterator(iter); 00229 } 00230 } 00231 } 00232 return ix; 00233 } 00234 /*@=boundsread@*/ 00235 00239 typedef struct dnli_s { 00240 rpmfi fi; 00241 /*@only@*/ /*@null@*/ 00242 char * active; 00243 int reverse; 00244 int isave; 00245 int i; 00246 } * DNLI_t; 00247 00253 static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ const void * a) 00254 /*@modifies a @*/ 00255 { 00256 if (a) { 00257 DNLI_t dnli = (void *)a; 00258 if (dnli->active) free(dnli->active); 00259 } 00260 return _free(a); 00261 } 00262 00265 static inline int dnlCount(/*@null@*/ const DNLI_t dnli) 00266 /*@*/ 00267 { 00268 return (dnli ? dnli->fi->dc : 0); 00269 } 00270 00273 static inline int dnlIndex(/*@null@*/ const DNLI_t dnli) 00274 /*@*/ 00275 { 00276 return (dnli ? dnli->isave : -1); 00277 } 00278 00285 /*@-boundsread@*/ 00286 /*@-usereleased@*/ 00287 static /*@only@*/ /*@null@*/ 00288 void * dnlInitIterator(/*@special@*/ const FSM_t fsm, 00289 int reverse) 00290 /*@uses fsm->iter @*/ 00291 /*@*/ 00292 { 00293 rpmfi fi = fsmGetFi(fsm); 00294 const char * dnl; 00295 DNLI_t dnli; 00296 int i, j; 00297 00298 if (fi == NULL) 00299 return NULL; 00300 dnli = xcalloc(1, sizeof(*dnli)); 00301 dnli->fi = fi; 00302 dnli->reverse = reverse; 00303 /*@-branchstate@*/ 00304 dnli->i = (reverse ? fi->dc : 0); 00305 /*@=branchstate@*/ 00306 00307 if (fi->dc) { 00308 dnli->active = xcalloc(fi->dc, sizeof(*dnli->active)); 00309 00310 /* Identify parent directories not skipped. */ 00311 /*@-boundswrite@*/ 00312 for (i = 0; i < fi->fc; i++) 00313 if (!XFA_SKIPPING(fi->actions[i])) dnli->active[fi->dil[i]] = 1; 00314 /*@=boundswrite@*/ 00315 00316 /* Exclude parent directories that are explicitly included. */ 00317 for (i = 0; i < fi->fc; i++) { 00318 int dil, dnlen, bnlen; 00319 00320 if (!S_ISDIR(fi->fmodes[i])) 00321 continue; 00322 00323 dil = fi->dil[i]; 00324 dnlen = strlen(fi->dnl[dil]); 00325 bnlen = strlen(fi->bnl[i]); 00326 00327 for (j = 0; j < fi->dc; j++) { 00328 int jlen; 00329 00330 if (!dnli->active[j] || j == dil) 00331 /*@innercontinue@*/ continue; 00332 (void) urlPath(fi->dnl[j], &dnl); 00333 jlen = strlen(dnl); 00334 if (jlen != (dnlen+bnlen+1)) 00335 /*@innercontinue@*/ continue; 00336 if (strncmp(dnl, fi->dnl[dil], dnlen)) 00337 /*@innercontinue@*/ continue; 00338 if (strncmp(dnl+dnlen, fi->bnl[i], bnlen)) 00339 /*@innercontinue@*/ continue; 00340 if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') 00341 /*@innercontinue@*/ continue; 00342 /* This directory is included in the package. */ 00343 /*@-boundswrite@*/ 00344 dnli->active[j] = 0; 00345 /*@=boundswrite@*/ 00346 /*@innerbreak@*/ break; 00347 } 00348 } 00349 00350 /* Print only once per package. */ 00351 if (!reverse) { 00352 j = 0; 00353 for (i = 0; i < fi->dc; i++) { 00354 if (!dnli->active[i]) continue; 00355 if (j == 0) { 00356 j = 1; 00357 rpmMessage(RPMMESS_DEBUG, 00358 D_("========== Directories not explicitly included in package:\n")); 00359 } 00360 (void) urlPath(fi->dnl[i], &dnl); 00361 rpmMessage(RPMMESS_DEBUG, "%10d %s\n", i, dnl); 00362 } 00363 if (j) 00364 rpmMessage(RPMMESS_DEBUG, "==========\n"); 00365 } 00366 } 00367 return dnli; 00368 } 00369 /*@=usereleased@*/ 00370 /*@=boundsread@*/ 00371 00377 /*@-boundsread@*/ 00378 static /*@observer@*/ /*@null@*/ 00379 const char * dnlNextIterator(/*@null@*/ DNLI_t dnli) 00380 /*@modifies dnli @*/ 00381 { 00382 const char * dn = NULL; 00383 00384 if (dnli) { 00385 rpmfi fi = dnli->fi; 00386 int i = -1; 00387 00388 if (dnli->active) 00389 do { 00390 i = (!dnli->reverse ? dnli->i++ : --dnli->i); 00391 } while (i >= 0 && i < fi->dc && !dnli->active[i]); 00392 00393 if (i >= 0 && i < fi->dc) 00394 dn = fi->dnl[i]; 00395 else 00396 i = -1; 00397 dnli->isave = i; 00398 } 00399 return dn; 00400 } 00401 /*@=boundsread@*/ 00402 00403 static void * fsmThread(void * arg) 00404 /*@globals h_errno, fileSystem, internalState @*/ 00405 /*@modifies arg, fileSystem, internalState @*/ 00406 { 00407 FSM_t fsm = arg; 00408 /*@-unqualifiedtrans@*/ 00409 return ((void *) ((long)fsmStage(fsm, fsm->nstage))); 00410 /*@=unqualifiedtrans@*/ 00411 } 00412 00413 int fsmNext(FSM_t fsm, fileStage nstage) 00414 /*@globals h_errno, fileSystem, internalState @*/ 00415 /*@modifies fsm, fileSystem, internalState @*/ 00416 { 00417 fsm->nstage = nstage; 00418 if (_fsm_threads) 00419 return rpmsqJoin( rpmsqThread(fsmThread, fsm) ); 00420 return fsmStage(fsm, fsm->nstage); 00421 } 00422 00428 /*@-boundsread@*/ 00429 static int saveHardLink(/*@special@*/ /*@partial@*/ FSM_t fsm) 00430 /*@uses fsm->links, fsm->ix, fsm->sb, fsm->goal, fsm->nsuffix @*/ 00431 /*@defines fsm->li @*/ 00432 /*@releases fsm->path @*/ 00433 /*@globals h_errno, fileSystem, internalState @*/ 00434 /*@modifies fsm, fileSystem, internalState @*/ 00435 { 00436 struct stat * st = &fsm->sb; 00437 int rc = 0; 00438 int ix = -1; 00439 int j; 00440 00441 /* Find hard link set. */ 00442 /*@-branchstate@*/ 00443 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { 00444 if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev) 00445 break; 00446 } 00447 /*@=branchstate@*/ 00448 00449 /* New hard link encountered, add new link to set. */ 00450 /*@-boundswrite@*/ 00451 /*@-branchstate@*/ 00452 if (fsm->li == NULL) { 00453 fsm->li = xcalloc(1, sizeof(*fsm->li)); 00454 fsm->li->next = NULL; 00455 fsm->li->sb = *st; /* structure assignment */ 00456 fsm->li->nlink = st->st_nlink; 00457 fsm->li->linkIndex = fsm->ix; 00458 fsm->li->createdPath = -1; 00459 00460 fsm->li->filex = xcalloc(st->st_nlink, sizeof(fsm->li->filex[0])); 00461 memset(fsm->li->filex, -1, (st->st_nlink * sizeof(fsm->li->filex[0]))); 00462 fsm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*fsm->li->nsuffix)); 00463 00464 if (fsm->goal == FSM_PKGBUILD) 00465 fsm->li->linksLeft = st->st_nlink; 00466 if (fsm->goal == FSM_PKGINSTALL) 00467 fsm->li->linksLeft = 0; 00468 00469 /*@-kepttrans@*/ 00470 fsm->li->next = fsm->links; 00471 /*@=kepttrans@*/ 00472 fsm->links = fsm->li; 00473 } 00474 /*@=branchstate@*/ 00475 /*@=boundswrite@*/ 00476 00477 if (fsm->goal == FSM_PKGBUILD) --fsm->li->linksLeft; 00478 /*@-boundswrite@*/ 00479 fsm->li->filex[fsm->li->linksLeft] = fsm->ix; 00480 /*@-observertrans -dependenttrans@*/ 00481 fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix; 00482 /*@=observertrans =dependenttrans@*/ 00483 /*@=boundswrite@*/ 00484 if (fsm->goal == FSM_PKGINSTALL) fsm->li->linksLeft++; 00485 00486 if (fsm->goal == FSM_PKGBUILD) 00487 return (fsm->li->linksLeft > 0); 00488 00489 if (fsm->goal != FSM_PKGINSTALL) 00490 return 0; 00491 00492 if (!(st->st_size || fsm->li->linksLeft == st->st_nlink)) 00493 return 1; 00494 00495 /* Here come the bits, time to choose a non-skipped file name. */ 00496 { rpmfi fi = fsmGetFi(fsm); 00497 00498 for (j = fsm->li->linksLeft - 1; j >= 0; j--) { 00499 ix = fsm->li->filex[j]; 00500 if (ix < 0 || XFA_SKIPPING(fi->actions[ix])) 00501 continue; 00502 break; 00503 } 00504 } 00505 00506 /* Are all links skipped or not encountered yet? */ 00507 if (ix < 0 || j < 0) 00508 return 1; /* XXX W2DO? */ 00509 00510 /* Save the non-skipped file name and map index. */ 00511 fsm->li->linkIndex = j; 00512 fsm->path = _free(fsm->path); 00513 fsm->ix = ix; 00514 rc = fsmNext(fsm, FSM_MAP); 00515 return rc; 00516 } 00517 /*@=boundsread@*/ 00518 00524 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink_s * li) 00525 /*@modifies li @*/ 00526 { 00527 if (li) { 00528 li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */ 00529 li->filex = _free(li->filex); 00530 } 00531 return _free(li); 00532 } 00533 00534 FSM_t newFSM(void) 00535 { 00536 FSM_t fsm = xcalloc(1, sizeof(*fsm)); 00537 return fsm; 00538 } 00539 00540 FSM_t freeFSM(FSM_t fsm) 00541 { 00542 if (fsm) { 00543 fsm->path = _free(fsm->path); 00544 /*@-branchstate@*/ 00545 while ((fsm->li = fsm->links) != NULL) { 00546 fsm->links = fsm->li->next; 00547 fsm->li->next = NULL; 00548 fsm->li = freeHardLink(fsm->li); 00549 } 00550 /*@=branchstate@*/ 00551 fsm->dnlx = _free(fsm->dnlx); 00552 fsm->ldn = _free(fsm->ldn); 00553 fsm->iter = mapFreeIterator(fsm->iter); 00554 } 00555 return _free(fsm); 00556 } 00557 00558 int fsmSetup(FSM_t fsm, fileStage goal, const char * afmt, 00559 const rpmts ts, const rpmfi fi, FD_t cfd, 00560 unsigned int * archiveSize, const char ** failedFile) 00561 { 00562 size_t pos = 0; 00563 int rc, ec = 0; 00564 00565 /*@+voidabstract -nullpass@*/ 00566 if (_fsm_debug < 0) 00567 fprintf(stderr, "--> %s(%p, 0x%x, \"%s\", %p, %p, %p, %p, %p)\n", __FUNCTION__, fsm, goal, afmt, (void *)ts, fi, cfd, archiveSize, failedFile); 00568 /*@=voidabstract =nullpass@*/ 00569 00570 if (fsm->headerRead == NULL) { 00571 if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, "ustar"))) { 00572 if (_fsm_debug < 0) 00573 fprintf(stderr, "\ttar vectors set\n"); 00574 fsm->headerRead = &tarHeaderRead; 00575 fsm->headerWrite = &tarHeaderWrite; 00576 fsm->trailerWrite = &tarTrailerWrite; 00577 fsm->blksize = TAR_BLOCK_SIZE; 00578 } else { 00579 if (_fsm_debug < 0) 00580 fprintf(stderr, "\tcpio vectors set\n"); 00581 fsm->headerRead = &cpioHeaderRead; 00582 fsm->headerWrite = &cpioHeaderWrite; 00583 fsm->trailerWrite = &cpioTrailerWrite; 00584 fsm->blksize = 4; 00585 } 00586 } 00587 00588 fsm->goal = goal; 00589 if (cfd != NULL) { 00590 fsm->cfd = fdLink(cfd, "persist (fsm)"); 00591 pos = fdGetCpioPos(fsm->cfd); 00592 fdSetCpioPos(fsm->cfd, 0); 00593 } 00594 fsm->iter = mapInitIterator(ts, fi); 00595 00596 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { 00597 void * ptr; 00598 fi->archivePos = 0; 00599 ptr = rpmtsNotify(ts, fi->te, 00600 RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize); 00601 } 00602 00603 /*@-boundswrite@*/ 00604 /*@-assignexpose@*/ 00605 fsm->archiveSize = archiveSize; 00606 if (fsm->archiveSize) 00607 *fsm->archiveSize = 0; 00608 fsm->failedFile = failedFile; 00609 if (fsm->failedFile) 00610 *fsm->failedFile = NULL; 00611 /*@=assignexpose@*/ 00612 /*@=boundswrite@*/ 00613 00614 memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf)); 00615 if (fsm->goal == FSM_PKGINSTALL) { 00616 if (ts && rpmtsGetTid(ts) != -1) 00617 sprintf(fsm->sufbuf, ";%08x", (unsigned)rpmtsGetTid(ts)); 00618 } 00619 00620 ec = fsm->rc = 0; 00621 rc = fsmUNSAFE(fsm, FSM_CREATE); 00622 if (rc && !ec) ec = rc; 00623 00624 rc = fsmUNSAFE(fsm, fsm->goal); 00625 if (rc && !ec) ec = rc; 00626 00627 /*@-boundswrite@*/ 00628 if (fsm->archiveSize && ec == 0) 00629 *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos); 00630 /*@=boundswrite@*/ 00631 00632 /*@-nullstate@*/ /* FIX: *fsm->failedFile may be NULL */ 00633 return ec; 00634 /*@=nullstate@*/ 00635 } 00636 00637 int fsmTeardown(FSM_t fsm) 00638 { 00639 int rc = fsm->rc; 00640 00641 if (_fsm_debug < 0) 00642 fprintf(stderr, "--> %s(%p)\n", __FUNCTION__, fsm); 00643 if (!rc) 00644 rc = fsmUNSAFE(fsm, FSM_DESTROY); 00645 00646 fsm->iter = mapFreeIterator(fsm->iter); 00647 if (fsm->cfd != NULL) { 00648 fsm->cfd = fdFree(fsm->cfd, "persist (fsm)"); 00649 fsm->cfd = NULL; 00650 } 00651 fsm->failedFile = NULL; 00652 return rc; 00653 } 00654 00655 static int fsmMapFContext(FSM_t fsm) 00656 /*@modifies fsm @*/ 00657 { 00658 rpmts ts = fsmGetTs(fsm); 00659 rpmfi fi = fsmGetFi(fsm); 00660 struct stat * st = &fsm->sb; 00661 00662 /* 00663 * Find file security context (if not disabled). 00664 */ 00665 fsm->fcontext = NULL; 00666 if (ts != NULL && rpmtsSELinuxEnabled(ts) == 1 && 00667 !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) 00668 { 00669 security_context_t scon = NULL; 00670 00671 if (matchpathcon(fsm->path, st->st_mode, &scon) == 0 && scon != NULL) 00672 fsm->fcontext = scon; 00673 else { 00674 int i = fsm->ix; 00675 00676 /* Get file security context from package. */ 00677 if (fi && i >= 0 && i < fi->fc) 00678 fsm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL); 00679 } 00680 } 00681 return 0; 00682 } 00683 00684 int fsmMapPath(FSM_t fsm) 00685 { 00686 rpmfi fi = fsmGetFi(fsm); /* XXX const except for fstates */ 00687 int rc = 0; 00688 int i; 00689 00690 fsm->osuffix = NULL; 00691 fsm->nsuffix = NULL; 00692 fsm->astriplen = 0; 00693 fsm->action = FA_UNKNOWN; 00694 fsm->mapFlags = fi->mapflags; 00695 00696 i = fsm->ix; 00697 if (fi && i >= 0 && i < fi->fc) { 00698 00699 /*@-boundsread@*/ 00700 fsm->astriplen = fi->astriplen; 00701 fsm->action = (fi->actions ? fi->actions[i] : fi->action); 00702 fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags); 00703 fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags); 00704 00705 /* src rpms have simple base name in payload. */ 00706 fsm->dirName = fi->dnl[fi->dil[i]]; 00707 fsm->baseName = fi->bnl[i]; 00708 /*@=boundsread@*/ 00709 00710 /*@-boundswrite@*/ 00711 switch (fsm->action) { 00712 case FA_SKIP: 00713 break; 00714 case FA_UNKNOWN: 00715 break; 00716 00717 case FA_COPYOUT: 00718 break; 00719 case FA_COPYIN: 00720 case FA_CREATE: 00721 assert(rpmteType(fi->te) == TR_ADDED); 00722 break; 00723 00724 case FA_SKIPNSTATE: 00725 if (fi->fstates && rpmteType(fi->te) == TR_ADDED) 00726 fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED; 00727 break; 00728 00729 case FA_SKIPNETSHARED: 00730 if (fi->fstates && rpmteType(fi->te) == TR_ADDED) 00731 fi->fstates[i] = RPMFILE_STATE_NETSHARED; 00732 break; 00733 00734 case FA_SKIPCOLOR: 00735 if (fi->fstates && rpmteType(fi->te) == TR_ADDED) 00736 fi->fstates[i] = RPMFILE_STATE_WRONGCOLOR; 00737 break; 00738 00739 case FA_BACKUP: 00740 if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00741 switch (rpmteType(fi->te)) { 00742 case TR_ADDED: 00743 fsm->osuffix = SUFFIX_RPMORIG; 00744 /*@innerbreak@*/ break; 00745 case TR_REMOVED: 00746 fsm->osuffix = SUFFIX_RPMSAVE; 00747 /*@innerbreak@*/ break; 00748 } 00749 break; 00750 00751 case FA_ALTNAME: 00752 assert(rpmteType(fi->te) == TR_ADDED); 00753 if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00754 fsm->nsuffix = SUFFIX_RPMNEW; 00755 break; 00756 00757 case FA_SAVE: 00758 assert(rpmteType(fi->te) == TR_ADDED); 00759 if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00760 fsm->osuffix = SUFFIX_RPMSAVE; 00761 break; 00762 case FA_ERASE: 00763 #if 0 /* XXX is this a genhdlist fix? */ 00764 assert(rpmteType(fi->te) == TR_REMOVED); 00765 #endif 00766 /* 00767 * XXX TODO: %ghost probably shouldn't be removed, but that changes 00768 * legacy rpm behavior. 00769 */ 00770 break; 00771 default: 00772 break; 00773 } 00774 /*@=boundswrite@*/ 00775 00776 if ((fsm->mapFlags & CPIO_MAP_PATH) || fsm->nsuffix) { 00777 const struct stat * st = &fsm->sb; 00778 fsm->path = _free(fsm->path); 00779 fsm->path = fsmFsPath(fsm, st, fsm->subdir, 00780 (fsm->suffix ? fsm->suffix : fsm->nsuffix)); 00781 } 00782 } 00783 return rc; 00784 } 00785 00786 int fsmMapAttrs(FSM_t fsm) 00787 { 00788 struct stat * st = &fsm->sb; 00789 rpmfi fi = fsmGetFi(fsm); 00790 int i = fsm->ix; 00791 00792 if (fi && i >= 0 && i < fi->fc) { 00793 mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms); 00794 mode_t finalMode = (fi->fmodes ? fi->fmodes[i] : perms); 00795 dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0); 00796 int_32 finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0); 00797 uid_t uid = fi->uid; 00798 gid_t gid = fi->gid; 00799 00800 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) { 00801 if (fsm->goal == FSM_PKGINSTALL) 00802 rpmMessage(RPMMESS_WARNING, 00803 _("user %s does not exist - using root\n"), fi->fuser[i]); 00804 uid = 0; 00805 finalMode &= ~S_ISUID; /* turn off suid bit */ 00806 } 00807 00808 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) { 00809 if (fsm->goal == FSM_PKGINSTALL) 00810 rpmMessage(RPMMESS_WARNING, 00811 _("group %s does not exist - using root\n"), fi->fgroup[i]); 00812 gid = 0; 00813 finalMode &= ~S_ISGID; /* turn off sgid bit */ 00814 } 00815 00816 if (fsm->mapFlags & CPIO_MAP_MODE) 00817 st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT); 00818 if (fsm->mapFlags & CPIO_MAP_TYPE) { 00819 st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT); 00820 if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) 00821 && st->st_nlink == 0) 00822 st->st_nlink = 1; 00823 st->st_rdev = finalRdev; 00824 st->st_mtime = finalMtime; 00825 } 00826 if (fsm->mapFlags & CPIO_MAP_UID) 00827 st->st_uid = uid; 00828 if (fsm->mapFlags & CPIO_MAP_GID) 00829 st->st_gid = gid; 00830 00831 { rpmts ts = fsmGetTs(fsm); 00832 00833 /* 00834 * Set file digest (if not disabled). 00835 */ 00836 if (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOFDIGESTS)) { 00837 fsm->fdigestalgo = fi->digestalgo; 00838 fsm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL); 00839 fsm->digestlen = fi->digestlen; 00840 fsm->digest = (fi->digests ? (fi->digests + (fsm->digestlen * i)) : NULL); 00841 } else { 00842 fsm->fdigestalgo = 0; 00843 fsm->fdigest = NULL; 00844 fsm->digestlen = 0; 00845 fsm->digest = NULL; 00846 } 00847 } 00848 00849 } 00850 return 0; 00851 } 00852 00858 /*@-compdef@*/ 00859 static int extractRegular(/*@special@*/ FSM_t fsm) 00860 /*@uses fsm->fdigest, fsm->digest, fsm->sb, fsm->wfd @*/ 00861 /*@globals h_errno, fileSystem, internalState @*/ 00862 /*@modifies fsm, fileSystem, internalState @*/ 00863 { 00864 const struct stat * st = &fsm->sb; 00865 int left = st->st_size; 00866 int rc = 0; 00867 00868 rc = fsmNext(fsm, FSM_WOPEN); 00869 if (rc) 00870 goto exit; 00871 00872 if (st->st_size > 0 && (fsm->fdigest != NULL || fsm->digest != NULL)) 00873 fdInitDigest(fsm->wfd, fsm->fdigestalgo, 0); 00874 00875 while (left) { 00876 00877 fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); 00878 rc = fsmNext(fsm, FSM_DREAD); 00879 if (rc) 00880 goto exit; 00881 00882 rc = fsmNext(fsm, FSM_WRITE); 00883 if (rc) 00884 goto exit; 00885 00886 left -= fsm->wrnb; 00887 00888 /* Notify iff progress, completion is done elsewhere */ 00889 if (!rc && left) 00890 (void) fsmNext(fsm, FSM_NOTIFY); 00891 } 00892 00893 if (st->st_size > 0 && (fsm->fdigest || fsm->digest)) { 00894 void * digest = NULL; 00895 int asAscii = (fsm->digest == NULL ? 1 : 0); 00896 00897 (void) Fflush(fsm->wfd); 00898 fdFiniDigest(fsm->wfd, fsm->fdigestalgo, &digest, NULL, asAscii); 00899 00900 if (digest == NULL) { 00901 rc = CPIOERR_DIGEST_MISMATCH; 00902 goto exit; 00903 } 00904 00905 if (fsm->digest != NULL) { 00906 if (memcmp(digest, fsm->digest, fsm->digestlen)) 00907 rc = CPIOERR_DIGEST_MISMATCH; 00908 } else { 00909 if (strcmp(digest, fsm->fdigest)) 00910 rc = CPIOERR_DIGEST_MISMATCH; 00911 } 00912 digest = _free(digest); 00913 } 00914 00915 exit: 00916 (void) fsmNext(fsm, FSM_WCLOSE); 00917 return rc; 00918 } 00919 /*@=compdef@*/ 00920 00927 /*@-compdef -compmempass@*/ 00928 static int writeFile(/*@special@*/ /*@partial@*/ FSM_t fsm, int writeData) 00929 /*@uses fsm->path, fsm->opath, fsm->sb, fsm->osb, fsm->cfd @*/ 00930 /*@globals h_errno, fileSystem, internalState @*/ 00931 /*@modifies fsm, fileSystem, internalState @*/ 00932 { 00933 const char * path = fsm->path; 00934 const char * opath = fsm->opath; 00935 struct stat * st = &fsm->sb; 00936 struct stat * ost = &fsm->osb; 00937 size_t left; 00938 int xx; 00939 int rc; 00940 00941 st->st_size = (writeData ? ost->st_size : 0); 00942 00943 /*@-branchstate@*/ 00944 if (S_ISDIR(st->st_mode)) { 00945 st->st_size = 0; 00946 } else if (S_ISLNK(st->st_mode)) { 00947 /* 00948 * While linux puts the size of a symlink in the st_size field, 00949 * I don't think that's a specified standard. 00950 */ 00951 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ 00952 rc = fsmUNSAFE(fsm, FSM_READLINK); 00953 if (rc) goto exit; 00954 st->st_size = fsm->rdnb; 00955 fsm->lpath = xstrdup(fsm->rdbuf); /* XXX save readlink return. */ 00956 } 00957 /*@=branchstate@*/ 00958 00959 if (fsm->mapFlags & CPIO_MAP_ABSOLUTE) { 00960 /*@-boundswrite@*/ 00961 int nb = strlen(fsm->dirName) + strlen(fsm->baseName) + sizeof("."); 00962 char * t = alloca(nb); 00963 *t = '\0'; 00964 fsm->path = t; 00965 if (fsm->mapFlags & CPIO_MAP_ADDDOT) 00966 *t++ = '.'; 00967 t = stpcpy( stpcpy(t, fsm->dirName), fsm->baseName); 00968 /*@=boundswrite@*/ 00969 } else if (fsm->mapFlags & CPIO_MAP_PATH) { 00970 rpmfi fi = fsmGetFi(fsm); 00971 if (fi->apath) { 00972 const char * apath = NULL; 00973 (void) urlPath(fi->apath[fsm->ix], &apath); 00974 fsm->path = apath + fi->striplen; 00975 } else 00976 fsm->path = fi->bnl[fsm->ix]; 00977 } 00978 00979 rc = fsmNext(fsm, FSM_HWRITE); 00980 fsm->path = path; 00981 if (rc) goto exit; 00982 00983 if (writeData && S_ISREG(st->st_mode)) { 00984 #if HAVE_MMAP 00985 char * rdbuf = NULL; 00986 void * mapped = (void *)-1; 00987 size_t nmapped = 0; 00988 /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */ 00989 int use_mmap = (st->st_size <= 0x07ffffff); 00990 #endif 00991 00992 rc = fsmNext(fsm, FSM_ROPEN); 00993 if (rc) goto exit; 00994 00995 /* XXX unbuffered mmap generates *lots* of fdio debugging */ 00996 #if HAVE_MMAP 00997 if (use_mmap) { 00998 mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0); 00999 if (mapped != (void *)-1) { 01000 rdbuf = fsm->rdbuf; 01001 fsm->rdbuf = (char *) mapped; 01002 fsm->rdlen = nmapped = st->st_size; 01003 #if defined(MADV_DONTNEED) 01004 xx = madvise(mapped, nmapped, MADV_DONTNEED); 01005 #endif 01006 } 01007 } 01008 #endif 01009 01010 left = st->st_size; 01011 01012 while (left) { 01013 #if HAVE_MMAP 01014 if (mapped != (void *)-1) { 01015 fsm->rdnb = nmapped; 01016 } else 01017 #endif 01018 { 01019 fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left), 01020 rc = fsmNext(fsm, FSM_READ); 01021 if (rc) goto exit; 01022 } 01023 01024 /* XXX DWRITE uses rdnb for I/O length. */ 01025 rc = fsmNext(fsm, FSM_DWRITE); 01026 if (rc) goto exit; 01027 01028 left -= fsm->wrnb; 01029 } 01030 01031 #if HAVE_MMAP 01032 /*@-branchstate@*/ 01033 if (mapped != (void *)-1) { 01034 xx = msync(mapped, nmapped, MS_ASYNC); 01035 #if defined(MADV_DONTNEED) 01036 xx = madvise(mapped, nmapped, MADV_DONTNEED); 01037 #endif 01038 /*@-noeffect@*/ 01039 xx = munmap(mapped, nmapped); 01040 /*@=noeffect@*/ 01041 fsm->rdbuf = rdbuf; 01042 } else 01043 /*@=branchstate@*/ 01044 #endif 01045 xx = fsync(Fileno(fsm->rfd)); 01046 } 01047 01048 rc = fsmNext(fsm, FSM_PAD); 01049 if (rc) goto exit; 01050 01051 rc = 0; 01052 01053 exit: 01054 if (fsm->rfd != NULL) 01055 (void) fsmNext(fsm, FSM_RCLOSE); 01056 /*@-dependenttrans@*/ 01057 fsm->opath = opath; 01058 fsm->path = path; 01059 /*@=dependenttrans@*/ 01060 return rc; 01061 } 01062 /*@=compdef =compmempass@*/ 01063 01069 static int writeLinkedFile(/*@special@*/ /*@partial@*/ FSM_t fsm) 01070 /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->li, fsm->failedFile @*/ 01071 /*@globals h_errno, fileSystem, internalState @*/ 01072 /*@modifies fsm, fileSystem, internalState @*/ 01073 { 01074 const char * path = fsm->path; 01075 const char * lpath = fsm->lpath; 01076 const char * nsuffix = fsm->nsuffix; 01077 int iterIndex = fsm->ix; 01078 int ec = 0; 01079 int rc; 01080 int i; 01081 const char * linkpath = NULL; 01082 int firstfile = 1; 01083 01084 fsm->path = NULL; 01085 fsm->lpath = NULL; 01086 fsm->nsuffix = NULL; 01087 fsm->ix = -1; 01088 01089 /*@-boundswrite@*/ 01090 /*@-branchstate@*/ 01091 for (i = fsm->li->nlink - 1; i >= 0; i--) { 01092 01093 if (fsm->li->filex[i] < 0) continue; 01094 01095 fsm->ix = fsm->li->filex[i]; 01096 /*@-compdef@*/ 01097 rc = fsmNext(fsm, FSM_MAP); 01098 /*@=compdef@*/ 01099 01100 /* XXX tar and cpio have to do things differently. */ 01101 if (fsm->headerWrite == tarHeaderWrite) { 01102 if (firstfile) { 01103 const char * apath = NULL; 01104 char *t; 01105 (void) urlPath(fsm->path, &apath); 01106 /* Remove the buildroot prefix. */ 01107 t = xmalloc(sizeof(".") + strlen(apath + fsm->astriplen)); 01108 (void) stpcpy( stpcpy(t, "."), apath + fsm->astriplen); 01109 linkpath = t; 01110 firstfile = 0; 01111 } else 01112 fsm->lpath = linkpath; 01113 01114 /* Write data after first link for tar. */ 01115 rc = writeFile(fsm, (fsm->lpath == NULL)); 01116 } else { 01117 /* Write data after last link for cpio. */ 01118 rc = writeFile(fsm, (i == 0)); 01119 } 01120 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) { 01121 ec = rc; 01122 *fsm->failedFile = xstrdup(fsm->path); 01123 } 01124 01125 fsm->path = _free(fsm->path); 01126 fsm->li->filex[i] = -1; 01127 } 01128 /*@=branchstate@*/ 01129 /*@=boundswrite@*/ 01130 01131 /*@-dependenttrans@*/ 01132 linkpath = _free(linkpath); 01133 /*@=dependenttrans@*/ 01134 fsm->ix = iterIndex; 01135 fsm->nsuffix = nsuffix; 01136 fsm->lpath = lpath; 01137 fsm->path = path; 01138 return ec; 01139 } 01140 01146 /*@-boundsread@*/ 01147 /*@-compdef@*/ 01148 static int fsmMakeLinks(/*@special@*/ /*@partial@*/ FSM_t fsm) 01149 /*@uses fsm->path, fsm->opath, fsm->nsuffix, fsm->ix, fsm->li @*/ 01150 /*@globals h_errno, fileSystem, internalState @*/ 01151 /*@modifies fsm, fileSystem, internalState @*/ 01152 { 01153 const char * path = fsm->path; 01154 const char * opath = fsm->opath; 01155 const char * nsuffix = fsm->nsuffix; 01156 int iterIndex = fsm->ix; 01157 int ec = 0; 01158 int rc; 01159 int i; 01160 01161 fsm->path = NULL; 01162 fsm->opath = NULL; 01163 fsm->nsuffix = NULL; 01164 fsm->ix = -1; 01165 01166 fsm->ix = fsm->li->filex[fsm->li->createdPath]; 01167 rc = fsmNext(fsm, FSM_MAP); 01168 fsm->opath = fsm->path; 01169 fsm->path = NULL; 01170 /*@-branchstate@*/ 01171 for (i = 0; i < fsm->li->nlink; i++) { 01172 if (fsm->li->filex[i] < 0) continue; 01173 if (fsm->li->createdPath == i) continue; 01174 01175 fsm->ix = fsm->li->filex[i]; 01176 fsm->path = _free(fsm->path); 01177 rc = fsmNext(fsm, FSM_MAP); 01178 if (XFA_SKIPPING(fsm->action)) continue; 01179 01180 rc = fsmUNSAFE(fsm, FSM_VERIFY); 01181 if (!rc) continue; 01182 if (!(rc == CPIOERR_ENOENT)) break; 01183 01184 /* XXX link(fsm->opath, fsm->path) */ 01185 rc = fsmNext(fsm, FSM_LINK); 01186 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) { 01187 ec = rc; 01188 /*@-boundswrite@*/ 01189 *fsm->failedFile = xstrdup(fsm->path); 01190 /*@=boundswrite@*/ 01191 } 01192 01193 fsm->li->linksLeft--; 01194 } 01195 /*@=branchstate@*/ 01196 fsm->path = _free(fsm->path); 01197 fsm->opath = _free(fsm->opath); 01198 01199 fsm->ix = iterIndex; 01200 fsm->nsuffix = nsuffix; 01201 fsm->path = path; 01202 fsm->opath = opath; 01203 return ec; 01204 } 01205 /*@=compdef@*/ 01206 /*@=boundsread@*/ 01207 01213 /*@-compdef@*/ 01214 static int fsmCommitLinks(/*@special@*/ /*@partial@*/ FSM_t fsm) 01215 /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->sb, 01216 fsm->li, fsm->links @*/ 01217 /*@globals h_errno, fileSystem, internalState @*/ 01218 /*@modifies fsm, fileSystem, internalState @*/ 01219 { 01220 const char * path = fsm->path; 01221 const char * nsuffix = fsm->nsuffix; 01222 int iterIndex = fsm->ix; 01223 struct stat * st = &fsm->sb; 01224 int rc = 0; 01225 int i; 01226 01227 fsm->path = NULL; 01228 fsm->nsuffix = NULL; 01229 fsm->ix = -1; 01230 01231 /*@-branchstate@*/ 01232 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { 01233 if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev) 01234 break; 01235 } 01236 /*@=branchstate@*/ 01237 01238 /*@-boundswrite@*/ 01239 for (i = 0; i < fsm->li->nlink; i++) { 01240 if (fsm->li->filex[i] < 0) continue; 01241 fsm->ix = fsm->li->filex[i]; 01242 rc = fsmNext(fsm, FSM_MAP); 01243 if (!XFA_SKIPPING(fsm->action)) 01244 rc = fsmNext(fsm, FSM_COMMIT); 01245 fsm->path = _free(fsm->path); 01246 fsm->li->filex[i] = -1; 01247 } 01248 /*@=boundswrite@*/ 01249 01250 fsm->ix = iterIndex; 01251 fsm->nsuffix = nsuffix; 01252 fsm->path = path; 01253 return rc; 01254 } 01255 /*@=compdef@*/ 01256 01262 static int fsmRmdirs(/*@special@*/ /*@partial@*/ FSM_t fsm) 01263 /*@uses fsm->path, fsm->dnlx, fsm->ldn, fsm->rdbuf, fsm->iter @*/ 01264 /*@globals h_errno, fileSystem, internalState @*/ 01265 /*@modifies fsm, fileSystem, internalState @*/ 01266 { 01267 const char * path = fsm->path; 01268 void * dnli = dnlInitIterator(fsm, 1); 01269 char * dn = fsm->rdbuf; 01270 int dc = dnlCount(dnli); 01271 int rc = 0; 01272 01273 fsm->path = NULL; 01274 /*@-boundswrite@*/ 01275 dn[0] = '\0'; 01276 /*@-observertrans -dependenttrans@*/ 01277 if (fsm->ldn != NULL && fsm->dnlx != NULL) 01278 while ((fsm->path = dnlNextIterator(dnli)) != NULL) { 01279 int dnlen = strlen(fsm->path); 01280 char * te; 01281 01282 dc = dnlIndex(dnli); 01283 if (fsm->dnlx[dc] < 1 || fsm->dnlx[dc] >= dnlen) 01284 continue; 01285 01286 /* Copy to avoid const on fsm->path. */ 01287 te = stpcpy(dn, fsm->path) - 1; 01288 fsm->path = dn; 01289 01290 /* Remove generated directories. */ 01291 /*@-usereleased@*/ /* LCL: te used after release? */ 01292 do { 01293 if (*te == '/') { 01294 *te = '\0'; 01295 /*@-compdef@*/ 01296 rc = fsmNext(fsm, FSM_RMDIR); 01297 /*@=compdef@*/ 01298 *te = '/'; 01299 } 01300 if (rc) 01301 /*@innerbreak@*/ break; 01302 te--; 01303 } while ((te - fsm->path) > fsm->dnlx[dc]); 01304 /*@=usereleased@*/ 01305 } 01306 /*@=boundswrite@*/ 01307 dnli = dnlFreeIterator(dnli); 01308 /*@=observertrans =dependenttrans@*/ 01309 01310 fsm->path = path; 01311 return rc; 01312 } 01313 01319 static int fsmMkdirs(/*@special@*/ /*@partial@*/ FSM_t fsm) 01320 /*@uses fsm->path, fsm->sb, fsm->osb, fsm->rdbuf, fsm->iter, 01321 fsm->ldn, fsm->ldnlen, fsm->ldnalloc @*/ 01322 /*@defines fsm->dnlx, fsm->ldn @*/ 01323 /*@globals h_errno, fileSystem, internalState @*/ 01324 /*@modifies fsm, fileSystem, internalState @*/ 01325 { 01326 struct stat * st = &fsm->sb; 01327 struct stat * ost = &fsm->osb; 01328 const char * path = fsm->path; 01329 mode_t st_mode = st->st_mode; 01330 void * dnli = dnlInitIterator(fsm, 0); 01331 char * dn = fsm->rdbuf; 01332 int dc = dnlCount(dnli); 01333 int rc = 0; 01334 int i; 01335 /*@-compdef@*/ 01336 rpmts ts = fsmGetTs(fsm); 01337 /*@=compdef@*/ 01338 rpmsx sx = NULL; 01339 01340 /* XXX Set file contexts on non-packaged dirs iff selinux enabled. */ 01341 if (ts != NULL && rpmtsSELinuxEnabled(ts) == 1 && 01342 !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) 01343 sx = rpmtsREContext(ts); 01344 01345 fsm->path = NULL; 01346 01347 /*@-boundswrite@*/ 01348 dn[0] = '\0'; 01349 fsm->dnlx = (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL); 01350 /*@-observertrans -dependenttrans@*/ 01351 if (fsm->dnlx != NULL) 01352 while ((fsm->path = dnlNextIterator(dnli)) != NULL) { 01353 int dnlen = strlen(fsm->path); 01354 char * te; 01355 01356 dc = dnlIndex(dnli); 01357 if (dc < 0) continue; 01358 fsm->dnlx[dc] = dnlen; 01359 if (dnlen <= 1) 01360 continue; 01361 01362 /*@-compdef -nullpass@*/ /* FIX: fsm->ldn not defined ??? */ 01363 if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn)) 01364 continue; 01365 /*@=compdef =nullpass@*/ 01366 01367 /* Copy to avoid const on fsm->path. */ 01368 (void) stpcpy(dn, fsm->path); 01369 fsm->path = dn; 01370 01371 /* Assume '/' directory exists, "mkdir -p" for others if non-existent */ 01372 (void) urlPath(dn, (const char **)&te); 01373 for (i = 1, te++; *te != '\0'; te++, i++) { 01374 if (*te != '/') 01375 /*@innercontinue@*/ continue; 01376 01377 *te = '\0'; 01378 01379 /* Already validated? */ 01380 /*@-usedef -compdef -nullpass -nullderef@*/ 01381 if (i < fsm->ldnlen && 01382 (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') && 01383 !strncmp(fsm->path, fsm->ldn, i)) 01384 { 01385 *te = '/'; 01386 /* Move pre-existing path marker forward. */ 01387 fsm->dnlx[dc] = (te - dn); 01388 /*@innercontinue@*/ continue; 01389 } 01390 /*@=usedef =compdef =nullpass =nullderef@*/ 01391 01392 /* Validate next component of path. */ 01393 rc = fsmUNSAFE(fsm, FSM_LSTAT); 01394 *te = '/'; 01395 01396 /* Directory already exists? */ 01397 if (rc == 0 && S_ISDIR(ost->st_mode)) { 01398 /* Move pre-existing path marker forward. */ 01399 fsm->dnlx[dc] = (te - dn); 01400 } else if (rc == CPIOERR_ENOENT) { 01401 rpmfi fi = fsmGetFi(fsm); 01402 *te = '\0'; 01403 st->st_mode = S_IFDIR | (fi->dperms & 07777); 01404 rc = fsmNext(fsm, FSM_MKDIR); 01405 if (!rc) { 01406 /* XXX FIXME? only new dir will have context set. */ 01407 /* Get file security context from patterns. */ 01408 if (sx != NULL) { 01409 fsm->fcontext = rpmsxFContext(sx, fsm->path, st->st_mode); 01410 rc = fsmNext(fsm, FSM_LSETFCON); 01411 } 01412 if (fsm->fcontext == NULL) 01413 rpmMessage(RPMMESS_DEBUG, 01414 D_("%s directory created with perms %04o, no context.\n"), 01415 fsm->path, (unsigned)(st->st_mode & 07777)); 01416 else 01417 rpmMessage(RPMMESS_DEBUG, 01418 D_("%s directory created with perms %04o, context %s.\n"), 01419 fsm->path, (unsigned)(st->st_mode & 07777), 01420 fsm->fcontext); 01421 fsm->fcontext = NULL; 01422 } 01423 *te = '/'; 01424 } 01425 if (rc) 01426 /*@innerbreak@*/ break; 01427 } 01428 if (rc) break; 01429 01430 /* Save last validated path. */ 01431 /*@-compdef@*/ /* FIX: ldn/path annotations ? */ 01432 if (fsm->ldnalloc < (dnlen + 1)) { 01433 fsm->ldnalloc = dnlen + 100; 01434 fsm->ldn = xrealloc(fsm->ldn, fsm->ldnalloc); 01435 } 01436 if (fsm->ldn != NULL) { /* XXX can't happen */ 01437 strcpy(fsm->ldn, fsm->path); 01438 fsm->ldnlen = dnlen; 01439 } 01440 /*@=compdef@*/ 01441 } 01442 /*@=boundswrite@*/ 01443 dnli = dnlFreeIterator(dnli); 01444 sx = rpmsxFree(sx); 01445 /*@=observertrans =dependenttrans@*/ 01446 01447 fsm->path = path; 01448 st->st_mode = st_mode; /* XXX restore st->st_mode */ 01449 /*@-compdef@*/ /* FIX: ldn/path annotations ? */ 01450 return rc; 01451 /*@=compdef@*/ 01452 } 01453 01454 #ifdef NOTYET 01455 01460 static int fsmStat(/*@special@*/ /*@partial@*/ FSM_t fsm) 01461 /*@globals fileSystem, internalState @*/ 01462 /*@modifies fsm, fileSystem, internalState @*/ 01463 { 01464 int rc = 0; 01465 01466 if (fsm->path != NULL) { 01467 int saveernno = errno; 01468 rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS) 01469 ? FSM_LSTAT : FSM_STAT)); 01470 if (rc == CPIOERR_ENOENT) { 01471 errno = saveerrno; 01472 rc = 0; 01473 fsm->exists = 0; 01474 } else if (rc == 0) { 01475 fsm->exists = 1; 01476 } 01477 } else { 01478 /* Skip %ghost files on build. */ 01479 fsm->exists = 0; 01480 } 01481 return rc; 01482 } 01483 #endif 01484 01485 #define IS_DEV_LOG(_x) \ 01486 ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \ 01487 !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \ 01488 ((_x)[sizeof("/dev/log")-1] == '\0' || \ 01489 (_x)[sizeof("/dev/log")-1] == ';')) 01490 01491 /*@-boundsread@*/ 01492 /*@-compmempass@*/ 01493 int fsmStage(FSM_t fsm, fileStage stage) 01494 { 01495 #ifdef UNUSED 01496 fileStage prevStage = fsm->stage; 01497 const char * const prev = fileStageString(prevStage); 01498 #endif 01499 const char * const cur = fileStageString(stage); 01500 struct stat * st = &fsm->sb; 01501 struct stat * ost = &fsm->osb; 01502 int saveerrno = errno; 01503 int rc = fsm->rc; 01504 size_t left; 01505 int i; 01506 01507 #define _fafilter(_a) \ 01508 (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \ 01509 ? fileActionString(_a) : "") 01510 01511 if (stage & FSM_DEAD) { 01512 /* do nothing */ 01513 } else if (stage & FSM_INTERNAL) { 01514 if (_fsm_debug && !(stage & FSM_SYSCALL)) 01515 rpmMessage(RPMMESS_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n", 01516 cur, 01517 (unsigned)st->st_mode, (int)st->st_nlink, 01518 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, 01519 (fsm->path ? fsm->path : ""), 01520 _fafilter(fsm->action)); 01521 } else { 01522 const char * apath = NULL; 01523 if (fsm->path) 01524 (void) urlPath(fsm->path, &apath); 01525 fsm->stage = stage; 01526 if (_fsm_debug || !(stage & FSM_VERBOSE)) 01527 rpmMessage(RPMMESS_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n", 01528 cur, 01529 (unsigned)st->st_mode, (int)st->st_nlink, 01530 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, 01531 (fsm->path ? apath + fsm->astriplen : ""), 01532 _fafilter(fsm->action)); 01533 } 01534 #undef _fafilter 01535 01536 /*@-branchstate@*/ 01537 switch (stage) { 01538 case FSM_UNKNOWN: 01539 break; 01540 case FSM_PKGINSTALL: 01541 while (1) { 01542 /* Clean fsm, free'ing memory. Read next archive header. */ 01543 rc = fsmUNSAFE(fsm, FSM_INIT); 01544 01545 /* Exit on end-of-payload. */ 01546 if (rc == CPIOERR_HDR_TRAILER) { 01547 rc = 0; 01548 /*@loopbreak@*/ break; 01549 } 01550 01551 /* Exit on error. */ 01552 if (rc) { 01553 fsm->postpone = 1; 01554 (void) fsmNext(fsm, FSM_UNDO); 01555 /*@loopbreak@*/ break; 01556 } 01557 01558 /* Extract file from archive. */ 01559 rc = fsmNext(fsm, FSM_PROCESS); 01560 if (rc) { 01561 (void) fsmNext(fsm, FSM_UNDO); 01562 /*@loopbreak@*/ break; 01563 } 01564 01565 /* Notify on success. */ 01566 (void) fsmNext(fsm, FSM_NOTIFY); 01567 01568 rc = fsmNext(fsm, FSM_FINI); 01569 if (rc) { 01570 /*@loopbreak@*/ break; 01571 } 01572 } 01573 break; 01574 case FSM_PKGERASE: 01575 case FSM_PKGCOMMIT: 01576 while (1) { 01577 /* Clean fsm, free'ing memory. */ 01578 rc = fsmUNSAFE(fsm, FSM_INIT); 01579 01580 /* Exit on end-of-payload. */ 01581 if (rc == CPIOERR_HDR_TRAILER) { 01582 rc = 0; 01583 /*@loopbreak@*/ break; 01584 } 01585 01586 /* Rename/erase next item. */ 01587 if (fsmNext(fsm, FSM_FINI)) 01588 /*@loopbreak@*/ break; 01589 } 01590 break; 01591 case FSM_PKGBUILD: 01592 while (1) { 01593 01594 rc = fsmUNSAFE(fsm, FSM_INIT); 01595 01596 /* Exit on end-of-payload. */ 01597 if (rc == CPIOERR_HDR_TRAILER) { 01598 rc = 0; 01599 /*@loopbreak@*/ break; 01600 } 01601 01602 /* Exit on error. */ 01603 if (rc) { 01604 fsm->postpone = 1; 01605 (void) fsmNext(fsm, FSM_UNDO); 01606 /*@loopbreak@*/ break; 01607 } 01608 01609 /* Copy file into archive. */ 01610 rc = fsmNext(fsm, FSM_PROCESS); 01611 if (rc) { 01612 (void) fsmNext(fsm, FSM_UNDO); 01613 /*@loopbreak@*/ break; 01614 } 01615 01616 /* Notify on success. */ 01617 (void) fsmNext(fsm, FSM_NOTIFY); 01618 01619 if (fsmNext(fsm, FSM_FINI)) 01620 /*@loopbreak@*/ break; 01621 } 01622 01623 /* Flush partial sets of hard linked files. */ 01624 if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) { 01625 int nlink, j; 01626 while ((fsm->li = fsm->links) != NULL) { 01627 fsm->links = fsm->li->next; 01628 fsm->li->next = NULL; 01629 01630 /* Re-calculate link count for archive header. */ 01631 for (j = -1, nlink = 0, i = 0; i < fsm->li->nlink; i++) { 01632 if (fsm->li->filex[i] < 0) 01633 /*@innercontinue@*/ continue; 01634 nlink++; 01635 if (j == -1) j = i; 01636 } 01637 /* XXX force the contents out as well. */ 01638 /*@-boundswrite@*/ 01639 if (j != 0) { 01640 fsm->li->filex[0] = fsm->li->filex[j]; 01641 fsm->li->filex[j] = -1; 01642 } 01643 /*@=boundswrite@*/ 01644 fsm->li->sb.st_nlink = nlink; 01645 01646 fsm->sb = fsm->li->sb; /* structure assignment */ 01647 fsm->osb = fsm->sb; /* structure assignment */ 01648 01649 if (!rc) rc = writeLinkedFile(fsm); 01650 01651 fsm->li = freeHardLink(fsm->li); 01652 } 01653 } 01654 01655 if (!rc) 01656 rc = fsmNext(fsm, FSM_TRAILER); 01657 01658 break; 01659 case FSM_CREATE: 01660 { rpmts ts = fsmGetTs(fsm); 01661 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT) 01662 fsm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) && 01663 fsm->goal != FSM_PKGCOMMIT) ? 0 : 1); 01664 #undef _tsmask 01665 } 01666 fsm->path = _free(fsm->path); 01667 fsm->lpath = _free(fsm->lpath); 01668 fsm->opath = _free(fsm->opath); 01669 fsm->dnlx = _free(fsm->dnlx); 01670 01671 fsm->ldn = _free(fsm->ldn); 01672 fsm->ldnalloc = fsm->ldnlen = 0; 01673 01674 fsm->rdsize = fsm->wrsize = 0; 01675 fsm->rdbuf = fsm->rdb = _free(fsm->rdb); 01676 fsm->wrbuf = fsm->wrb = _free(fsm->wrb); 01677 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { 01678 fsm->rdsize = 8 * BUFSIZ; 01679 fsm->rdbuf = fsm->rdb = xmalloc(fsm->rdsize); 01680 fsm->wrsize = 8 * BUFSIZ; 01681 fsm->wrbuf = fsm->wrb = xmalloc(fsm->wrsize); 01682 } 01683 01684 fsm->mkdirsdone = 0; 01685 fsm->ix = -1; 01686 fsm->links = NULL; 01687 fsm->li = NULL; 01688 errno = 0; /* XXX get rid of EBADF */ 01689 01690 /* Detect and create directories not explicitly in package. */ 01691 if (fsm->goal == FSM_PKGINSTALL) { 01692 /*@-compdef@*/ 01693 rc = fsmNext(fsm, FSM_MKDIRS); 01694 /*@=compdef@*/ 01695 if (!rc) fsm->mkdirsdone = 1; 01696 } 01697 01698 break; 01699 case FSM_INIT: 01700 fsm->path = _free(fsm->path); 01701 fsm->lpath = _free(fsm->lpath); 01702 fsm->postpone = 0; 01703 fsm->diskchecked = fsm->exists = 0; 01704 fsm->subdir = NULL; 01705 fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL); 01706 fsm->action = FA_UNKNOWN; 01707 fsm->osuffix = NULL; 01708 fsm->nsuffix = NULL; 01709 01710 if (fsm->goal == FSM_PKGINSTALL) { 01711 /* Read next header from payload, checking for end-of-payload. */ 01712 rc = fsmUNSAFE(fsm, FSM_NEXT); 01713 } 01714 if (rc) break; 01715 01716 /* Identify mapping index. */ 01717 fsm->ix = ((fsm->goal == FSM_PKGINSTALL) 01718 ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter)); 01719 01720 if (!(fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_LIST)) { 01721 /* Detect end-of-loop and/or mapping error. */ 01722 if (!(fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_EXTRACT)) { 01723 if (fsm->ix < 0) { 01724 if (fsm->goal == FSM_PKGINSTALL) { 01725 #if 0 01726 rpmMessage(RPMMESS_WARNING, 01727 _("archive file %s was not found in header file list\n"), 01728 fsm->path); 01729 #endif 01730 /*@-boundswrite@*/ 01731 if (fsm->failedFile && *fsm->failedFile == NULL) 01732 *fsm->failedFile = xstrdup(fsm->path); 01733 /*@=boundswrite@*/ 01734 rc = CPIOERR_UNMAPPED_FILE; 01735 } else { 01736 rc = CPIOERR_HDR_TRAILER; 01737 } 01738 break; 01739 } 01740 } 01741 01742 /* On non-install, mode must be known so that dirs don't get suffix. */ 01743 if (fsm->goal != FSM_PKGINSTALL) { 01744 rpmfi fi = fsmGetFi(fsm); 01745 st->st_mode = fi->fmodes[fsm->ix]; 01746 } 01747 } 01748 01749 /* Generate file path. */ 01750 rc = fsmNext(fsm, FSM_MAP); 01751 if (rc) break; 01752 01753 /* Perform lstat/stat for disk file. */ 01754 #ifdef NOTYET 01755 rc = fsmStat(fsm); 01756 #else 01757 if (fsm->path != NULL && 01758 !(fsm->goal == FSM_PKGINSTALL && S_ISREG(st->st_mode))) 01759 { 01760 rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS) 01761 ? FSM_LSTAT : FSM_STAT)); 01762 if (rc == CPIOERR_ENOENT) { 01763 errno = saveerrno; 01764 rc = 0; 01765 fsm->exists = 0; 01766 } else if (rc == 0) { 01767 fsm->exists = 1; 01768 } 01769 } else { 01770 /* Skip %ghost files on build. */ 01771 fsm->exists = 0; 01772 } 01773 #endif 01774 fsm->diskchecked = 1; 01775 if (rc) break; 01776 01777 /* On non-install, the disk file stat is what's remapped. */ 01778 /*@-boundswrite@*/ 01779 if (fsm->goal != FSM_PKGINSTALL) 01780 *st = *ost; /* structure assignment */ 01781 /*@=boundswrite@*/ 01782 01783 /* Remap file perms, owner, and group. */ 01784 rc = fsmMapAttrs(fsm); 01785 if (rc) break; 01786 01787 fsm->postpone = XFA_SKIPPING(fsm->action); 01788 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { 01789 /*@-evalorder@*/ /* FIX: saveHardLink can modify fsm */ 01790 if (!(S_ISDIR(st->st_mode) || S_ISLNK(st->st_mode)) 01791 && (st->st_nlink > 1 || fsm->lpath != NULL)) 01792 fsm->postpone = saveHardLink(fsm); 01793 /*@=evalorder@*/ 01794 } 01795 if (fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_LIST) fsm->postpone = 1; 01796 break; 01797 case FSM_PRE: 01798 break; 01799 case FSM_MAP: 01800 rc = fsmMapPath(fsm); 01801 break; 01802 case FSM_MKDIRS: 01803 rc = fsmMkdirs(fsm); 01804 break; 01805 case FSM_RMDIRS: 01806 if (fsm->dnlx) 01807 rc = fsmRmdirs(fsm); 01808 break; 01809 case FSM_PROCESS: 01810 if (fsm->postpone) { 01811 if (fsm->goal == FSM_PKGINSTALL) { 01812 /* XXX Skip over file body, archive headers already done. */ 01813 if (S_ISREG(st->st_mode)) 01814 rc = fsmNext(fsm, FSM_EAT); 01815 } 01816 break; 01817 } 01818 01819 if (fsm->goal == FSM_PKGBUILD) { 01820 if (fsm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */ 01821 break; 01822 if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { 01823 struct hardLink_s * li, * prev; 01824 01825 if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break; 01826 rc = writeLinkedFile(fsm); 01827 if (rc) break; /* W2DO? */ 01828 01829 for (li = fsm->links, prev = NULL; li; prev = li, li = li->next) 01830 if (li == fsm->li) 01831 /*@loopbreak@*/ break; 01832 01833 if (prev == NULL) 01834 fsm->links = fsm->li->next; 01835 else 01836 prev->next = fsm->li->next; 01837 fsm->li->next = NULL; 01838 fsm->li = freeHardLink(fsm->li); 01839 } else { 01840 rc = writeFile(fsm, 1); 01841 } 01842 break; 01843 } 01844 01845 if (fsm->goal != FSM_PKGINSTALL) 01846 break; 01847 01848 if (S_ISREG(st->st_mode) && fsm->lpath != NULL) { 01849 const char * opath = fsm->opath; 01850 char * t = xmalloc(strlen(fsm->lpath+1) + strlen(fsm->suffix) + 1); 01851 (void) stpcpy(t, fsm->lpath+1); 01852 fsm->opath = t; 01853 /* XXX link(fsm->opath, fsm->path) */ 01854 rc = fsmNext(fsm, FSM_LINK); 01855 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) { 01856 /*@-boundswrite@*/ 01857 *fsm->failedFile = xstrdup(fsm->path); 01858 /*@=boundswrite@*/ 01859 } 01860 fsm->opath = _free(fsm->opath); 01861 fsm->opath = opath; 01862 break; /* XXX so that delayed hard links get skipped. */ 01863 } 01864 if (S_ISREG(st->st_mode)) { 01865 const char * path = fsm->path; 01866 if (fsm->osuffix) 01867 fsm->path = fsmFsPath(fsm, st, NULL, NULL); 01868 rc = fsmUNSAFE(fsm, FSM_VERIFY); 01869 01870 if (rc == 0 && fsm->osuffix) { 01871 const char * opath = fsm->opath; 01872 fsm->opath = fsm->path; 01873 fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); 01874 rc = fsmNext(fsm, FSM_RENAME); 01875 if (!rc) 01876 rpmMessage(RPMMESS_WARNING, 01877 _("%s saved as %s\n"), 01878 (fsm->opath ? fsm->opath : ""), 01879 (fsm->path ? fsm->path : "")); 01880 fsm->path = _free(fsm->path); 01881 fsm->opath = opath; 01882 } 01883 01884 /*@-dependenttrans@*/ 01885 fsm->path = path; 01886 /*@=dependenttrans@*/ 01887 if (!(rc == CPIOERR_ENOENT)) return rc; 01888 rc = extractRegular(fsm); 01889 } else if (S_ISDIR(st->st_mode)) { 01890 mode_t st_mode = st->st_mode; 01891 rc = fsmUNSAFE(fsm, FSM_VERIFY); 01892 if (rc == CPIOERR_ENOENT) { 01893 st->st_mode &= ~07777; /* XXX abuse st->st_mode */ 01894 st->st_mode |= 00700; 01895 rc = fsmNext(fsm, FSM_MKDIR); 01896 st->st_mode = st_mode; /* XXX restore st->st_mode */ 01897 } 01898 } else if (S_ISLNK(st->st_mode)) { 01899 assert(fsm->lpath != NULL); 01900 /*@=dependenttrans@*/ 01901 rc = fsmUNSAFE(fsm, FSM_VERIFY); 01902 if (rc == CPIOERR_ENOENT) 01903 rc = fsmNext(fsm, FSM_SYMLINK); 01904 } else if (S_ISFIFO(st->st_mode)) { 01905 mode_t st_mode = st->st_mode; 01906 /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */ 01907 rc = fsmUNSAFE(fsm, FSM_VERIFY); 01908 if (rc == CPIOERR_ENOENT) { 01909 st->st_mode = 0000; /* XXX abuse st->st_mode */ 01910 rc = fsmNext(fsm, FSM_MKFIFO); 01911 st->st_mode = st_mode; /* XXX restore st->st_mode */ 01912 } 01913 } else if (S_ISCHR(st->st_mode) || 01914 S_ISBLK(st->st_mode) || 01915 /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/) 01916 { 01917 rc = fsmUNSAFE(fsm, FSM_VERIFY); 01918 if (rc == CPIOERR_ENOENT) 01919 rc = fsmNext(fsm, FSM_MKNOD); 01920 } else { 01921 /* XXX Repackaged payloads may be missing files. */ 01922 if (fsm->repackaged) 01923 break; 01924 01925 /* XXX Special case /dev/log, which shouldn't be packaged anyways */ 01926 if (!IS_DEV_LOG(fsm->path)) 01927 rc = CPIOERR_UNKNOWN_FILETYPE; 01928 } 01929 if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { 01930 fsm->li->createdPath = fsm->li->linkIndex; 01931 rc = fsmMakeLinks(fsm); 01932 } 01933 break; 01934 case FSM_POST: 01935 break; 01936 case FSM_MKLINKS: 01937 rc = fsmMakeLinks(fsm); 01938 break; 01939 case FSM_NOTIFY: /* XXX move from fsm to psm -> tsm */ 01940 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { 01941 rpmts ts = fsmGetTs(fsm); 01942 rpmfi fi = fsmGetFi(fsm); 01943 void * ptr; 01944 unsigned long long archivePos = fdGetCpioPos(fsm->cfd); 01945 if (archivePos > fi->archivePos) { 01946 fi->archivePos = archivePos; 01947 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, 01948 fi->archivePos, fi->archiveSize); 01949 } 01950 } 01951 break; 01952 case FSM_UNDO: 01953 if (fsm->postpone) 01954 break; 01955 if (fsm->goal == FSM_PKGINSTALL) { 01956 /* XXX only erase if temp fn w suffix is in use */ 01957 if (fsm->sufbuf[0] != '\0') 01958 (void) fsmNext(fsm, 01959 (S_ISDIR(st->st_mode) ? FSM_RMDIR : FSM_UNLINK)); 01960 01961 #ifdef NOTYET /* XXX remove only dirs just created, not all. */ 01962 if (fsm->dnlx) 01963 (void) fsmNext(fsm, FSM_RMDIRS); 01964 #endif 01965 errno = saveerrno; 01966 } 01967 /*@-boundswrite@*/ 01968 if (fsm->failedFile && *fsm->failedFile == NULL) 01969 *fsm->failedFile = xstrdup(fsm->path); 01970 /*@=boundswrite@*/ 01971 break; 01972 case FSM_FINI: 01973 if (!fsm->postpone && fsm->commit) { 01974 if (fsm->goal == FSM_PKGINSTALL) 01975 rc = ((!S_ISDIR(st->st_mode) && st->st_nlink > 1) 01976 ? fsmCommitLinks(fsm) : fsmNext(fsm, FSM_COMMIT)); 01977 if (fsm->goal == FSM_PKGCOMMIT) 01978 rc = fsmNext(fsm, FSM_COMMIT); 01979 if (fsm->goal == FSM_PKGERASE) 01980 rc = fsmNext(fsm, FSM_COMMIT); 01981 } 01982 fsm->path = _free(fsm->path); 01983 fsm->lpath = _free(fsm->lpath); 01984 fsm->opath = _free(fsm->opath); 01985 /*@-boundswrite@*/ 01986 memset(st, 0, sizeof(*st)); 01987 memset(ost, 0, sizeof(*ost)); 01988 /*@=boundswrite@*/ 01989 break; 01990 case FSM_COMMIT: 01991 /* Rename pre-existing modified or unmanaged file. */ 01992 if (fsm->osuffix && fsm->diskchecked && 01993 (fsm->exists || (fsm->goal == FSM_PKGINSTALL && S_ISREG(st->st_mode)))) 01994 { 01995 const char * opath = fsm->opath; 01996 const char * path = fsm->path; 01997 fsm->opath = fsmFsPath(fsm, st, NULL, NULL); 01998 fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); 01999 rc = fsmNext(fsm, FSM_RENAME); 02000 if (!rc) { 02001 rpmMessage(RPMMESS_WARNING, _("%s saved as %s\n"), 02002 (fsm->opath ? fsm->opath : ""), 02003 (fsm->path ? fsm->path : "")); 02004 } 02005 fsm->path = _free(fsm->path); 02006 fsm->path = path; 02007 fsm->opath = _free(fsm->opath); 02008 fsm->opath = opath; 02009 } 02010 02011 /* Remove erased files. */ 02012 if (fsm->goal == FSM_PKGERASE) { 02013 if (fsm->action == FA_ERASE) { 02014 rpmfi fi = fsmGetFi(fsm); 02015 if (S_ISDIR(st->st_mode)) { 02016 rc = fsmNext(fsm, FSM_RMDIR); 02017 if (!rc) break; 02018 switch (rc) { 02019 case CPIOERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */ 02020 case CPIOERR_ENOTEMPTY: 02021 /* XXX make sure that build side permits %missingok on directories. */ 02022 if (fsm->fflags & RPMFILE_MISSINGOK) 02023 /*@innerbreak@*/ break; 02024 02025 /* XXX common error message. */ 02026 rpmError( 02027 (strict_erasures ? RPMERR_RMDIR : RPMDEBUG_RMDIR), 02028 _("%s rmdir of %s failed: Directory not empty\n"), 02029 rpmfiTypeString(fi), fsm->path); 02030 /*@innerbreak@*/ break; 02031 default: 02032 rpmError( 02033 (strict_erasures ? RPMERR_RMDIR : RPMDEBUG_RMDIR), 02034 _("%s rmdir of %s failed: %s\n"), 02035 rpmfiTypeString(fi), fsm->path, strerror(errno)); 02036 /*@innerbreak@*/ break; 02037 } 02038 } else { 02039 rc = fsmNext(fsm, FSM_UNLINK); 02040 if (!rc) break; 02041 switch (rc) { 02042 case CPIOERR_ENOENT: 02043 if (fsm->fflags & RPMFILE_MISSINGOK) 02044 /*@innerbreak@*/ break; 02045 /*@fallthrough@*/ 02046 default: 02047 rpmError( 02048 (strict_erasures ? RPMERR_UNLINK : RPMDEBUG_UNLINK), 02049 _(" %s: unlink of %s failed: %s\n"), 02050 rpmfiTypeString(fi), fsm->path, strerror(errno)); 02051 /*@innerbreak@*/ break; 02052 } 02053 } 02054 } 02055 /* XXX Failure to remove is not (yet) cause for failure. */ 02056 if (!strict_erasures) rc = 0; 02057 break; 02058 } 02059 02060 /* XXX Special case /dev/log, which shouldn't be packaged anyways */ 02061 if (!(fsmGetFi(fsm)->mapflags & CPIO_PAYLOAD_EXTRACT)) { 02062 if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(fsm->path)) { 02063 /* Rename temporary to final file name. */ 02064 if (!S_ISDIR(st->st_mode) && 02065 (fsm->subdir || fsm->suffix || fsm->nsuffix)) 02066 { 02067 fsm->opath = fsm->path; 02068 fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix); 02069 rc = fsmNext(fsm, FSM_RENAME); 02070 if (rc) 02071 (void) Unlink(fsm->opath); 02072 else if (fsm->nsuffix) { 02073 const char * opath = fsmFsPath(fsm, st, NULL, NULL); 02074 rpmMessage(RPMMESS_WARNING, _("%s created as %s\n"), 02075 (opath ? opath : ""), 02076 (fsm->path ? fsm->path : "")); 02077 opath = _free(opath); 02078 } 02079 fsm->opath = _free(fsm->opath); 02080 } 02081 /* 02082 * Set file security context (if not disabled). 02083 */ 02084 if (!rc && !getuid()) { 02085 rc = fsmMapFContext(fsm); 02086 if (!rc) 02087 rc = fsmNext(fsm, FSM_LSETFCON); 02088 fsm->fcontext = NULL; 02089 } 02090 if (S_ISLNK(st->st_mode)) { 02091 if (!rc && !getuid()) 02092 rc = fsmNext(fsm, FSM_LCHOWN); 02093 } else { 02094 if (!rc && !getuid()) 02095 rc = fsmNext(fsm, FSM_CHOWN); 02096 if (!rc) 02097 rc = fsmNext(fsm, FSM_CHMOD); 02098 if (!rc) { 02099 time_t mtime = st->st_mtime; 02100 rpmfi fi = fsmGetFi(fsm); 02101 if (fi->fmtimes) 02102 st->st_mtime = fi->fmtimes[fsm->ix]; 02103 rc = fsmNext(fsm, FSM_UTIME); 02104 st->st_mtime = mtime; 02105 } 02106 } 02107 } 02108 } 02109 02110 /* Notify on success. */ 02111 if (!rc) rc = fsmNext(fsm, FSM_NOTIFY); 02112 else if (fsm->failedFile && *fsm->failedFile == NULL) { 02113 /*@-boundswrite@*/ 02114 *fsm->failedFile = fsm->path; 02115 /*@=boundswrite@*/ 02116 fsm->path = NULL; 02117 } 02118 break; 02119 case FSM_DESTROY: 02120 fsm->path = _free(fsm->path); 02121 02122 /* Check for hard links missing from payload. */ 02123 while ((fsm->li = fsm->links) != NULL) { 02124 fsm->links = fsm->li->next; 02125 fsm->li->next = NULL; 02126 if (fsm->goal == FSM_PKGINSTALL && 02127 fsm->commit && fsm->li->linksLeft) 02128 { 02129 for (i = 0 ; i < fsm->li->linksLeft; i++) { 02130 if (fsm->li->filex[i] < 0) 02131 /*@innercontinue@*/ continue; 02132 rc = CPIOERR_MISSING_HARDLINK; 02133 if (fsm->failedFile && *fsm->failedFile == NULL) { 02134 fsm->ix = fsm->li->filex[i]; 02135 if (!fsmNext(fsm, FSM_MAP)) { 02136 /*@-boundswrite@*/ 02137 *fsm->failedFile = fsm->path; 02138 /*@=boundswrite@*/ 02139 fsm->path = NULL; 02140 } 02141 } 02142 /*@loopbreak@*/ break; 02143 } 02144 } 02145 if (fsm->goal == FSM_PKGBUILD && 02146 (fsm->mapFlags & CPIO_ALL_HARDLINKS)) 02147 { 02148 rc = CPIOERR_MISSING_HARDLINK; 02149 } 02150 fsm->li = freeHardLink(fsm->li); 02151 } 02152 fsm->ldn = _free(fsm->ldn); 02153 fsm->ldnalloc = fsm->ldnlen = 0; 02154 fsm->rdbuf = fsm->rdb = _free(fsm->rdb); 02155 fsm->wrbuf = fsm->wrb = _free(fsm->wrb); 02156 break; 02157 case FSM_VERIFY: 02158 if (fsm->diskchecked && !fsm->exists) { 02159 rc = CPIOERR_ENOENT; 02160 break; 02161 } 02162 if (S_ISREG(st->st_mode)) { 02163 char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE")); 02164 /*@-boundswrite@*/ 02165 (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE"); 02166 /*@=boundswrite@*/ 02167 /* 02168 * XXX HP-UX (and other os'es) don't permit unlink on busy 02169 * XXX files. 02170 */ 02171 fsm->opath = fsm->path; 02172 fsm->path = path; 02173 rc = fsmNext(fsm, FSM_RENAME); 02174 if (!rc) 02175 (void) fsmNext(fsm, FSM_UNLINK); 02176 else 02177 rc = CPIOERR_UNLINK_FAILED; 02178 fsm->path = fsm->opath; 02179 fsm->opath = NULL; 02180 return (rc ? rc : CPIOERR_ENOENT); /* XXX HACK */ 02181 /*@notreached@*/ break; 02182 } else if (S_ISDIR(st->st_mode)) { 02183 if (S_ISDIR(ost->st_mode)) return 0; 02184 if (S_ISLNK(ost->st_mode)) { 02185 rc = fsmUNSAFE(fsm, FSM_STAT); 02186 if (rc == CPIOERR_ENOENT) rc = 0; 02187 if (rc) break; 02188 errno = saveerrno; 02189 if (S_ISDIR(ost->st_mode)) return 0; 02190 } 02191 } else if (S_ISLNK(st->st_mode)) { 02192 if (S_ISLNK(ost->st_mode)) { 02193 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ 02194 rc = fsmUNSAFE(fsm, FSM_READLINK); 02195 errno = saveerrno; 02196 if (rc) break; 02197 if (!strcmp(fsm->lpath, fsm->rdbuf)) return 0; 02198 } 02199 } else if (S_ISFIFO(st->st_mode)) { 02200 if (S_ISFIFO(ost->st_mode)) return 0; 02201 } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { 02202 if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) && 02203 (ost->st_rdev == st->st_rdev)) return 0; 02204 } else if (S_ISSOCK(st->st_mode)) { 02205 if (S_ISSOCK(ost->st_mode)) return 0; 02206 } 02207 /* XXX shouldn't do this with commit/undo. */ 02208 rc = 0; 02209 if (fsm->stage == FSM_PROCESS) rc = fsmNext(fsm, FSM_UNLINK); 02210 if (rc == 0) rc = CPIOERR_ENOENT; 02211 return (rc ? rc : CPIOERR_ENOENT); /* XXX HACK */ 02212 /*@notreached@*/ break; 02213 02214 case FSM_UNLINK: 02215 /* XXX Remove setuid/setgid bits on possibly hard linked files. */ 02216 if (fsm->mapFlags & CPIO_SBIT_CHECK) { 02217 struct stat stb; 02218 if (Lstat(fsm->path, &stb) == 0 && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0) { 02219 /* XXX rc = fsmNext(fsm, FSM_CHMOD); instead */ 02220 int xx = chmod(fsm->path, stb.st_mode & 0777); 02221 } 02222 } 02223 rc = Unlink(fsm->path); 02224 if (_fsm_debug && (stage & FSM_SYSCALL)) 02225 rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur, 02226 fsm->path, (rc < 0 ? strerror(errno) : "")); 02227 if (rc < 0) 02228 rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_UNLINK_FAILED); 02229 break; 02230 case FSM_RENAME: 02231 /* XXX Remove setuid/setgid bits on possibly hard linked files. */ 02232 if (fsm->mapFlags & CPIO_SBIT_CHECK) { 02233 struct stat stb; 02234 if (Lstat(fsm->path, &stb) == 0 && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0) { 02235 /* XXX rc = fsmNext(fsm, FSM_CHMOD); instead */ 02236 int xx = chmod(fsm->path, stb.st_mode & 0777); 02237 } 02238 } 02239 rc = Rename(fsm->opath, fsm->path); 02240 /* XXX Repackaged payloads may be missing files. */ 02241 if (fsm->repackaged) 02242 rc = 0; 02243 #if defined(ETXTBSY) 02244 if (rc && errno == ETXTBSY) { 02245 char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE")); 02246 (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE"); 02247 /* 02248 * XXX HP-UX (and other os'es) don't permit rename to busy 02249 * XXX files. 02250 */ 02251 rc = Rename(fsm->path, path); 02252 if (!rc) rc = Rename(fsm->opath, fsm->path); 02253 } 02254 #endif 02255 if (_fsm_debug && (stage & FSM_SYSCALL)) 02256 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, 02257 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); 02258 if (rc < 0) rc = CPIOERR_RENAME_FAILED; 02259 break; 02260 case FSM_MKDIR: 02261 rc = Mkdir(fsm->path, (st->st_mode & 07777)); 02262 if (_fsm_debug && (stage & FSM_SYSCALL)) 02263 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, 02264 fsm->path, (unsigned)(st->st_mode & 07777), 02265 (rc < 0 ? strerror(errno) : "")); 02266 if (rc < 0) rc = CPIOERR_MKDIR_FAILED; 02267 break; 02268 case FSM_RMDIR: 02269 rc = Rmdir(fsm->path); 02270 if (_fsm_debug && (stage & FSM_SYSCALL)) 02271 rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur, 02272 fsm->path, (rc < 0 ? strerror(errno) : "")); 02273 if (rc < 0) 02274 switch (errno) { 02275 case ENOENT: rc = CPIOERR_ENOENT; /*@switchbreak@*/ break; 02276 case ENOTEMPTY: rc = CPIOERR_ENOTEMPTY; /*@switchbreak@*/ break; 02277 default: rc = CPIOERR_RMDIR_FAILED; /*@switchbreak@*/ break; 02278 } 02279 break; 02280 case FSM_LSETFCON: 02281 { const char * fsmpath = NULL; 02282 if (fsm->fcontext == NULL || *fsm->fcontext == '\0' 02283 || !strcmp(fsm->fcontext, "<<none>>")) 02284 break; 02285 (void) urlPath(fsm->path, &fsmpath); /* XXX fsm->path */ 02286 rc = lsetfilecon(fsmpath, (security_context_t)fsm->fcontext); 02287 if (_fsm_debug && (stage & FSM_SYSCALL)) 02288 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, 02289 fsm->path, fsm->fcontext, 02290 (rc < 0 ? strerror(errno) : "")); 02291 if (rc < 0) rc = (errno == EOPNOTSUPP ? 0 : CPIOERR_LSETFCON_FAILED); 02292 } break; 02293 case FSM_CHOWN: 02294 rc = Chown(fsm->path, st->st_uid, st->st_gid); 02295 if (_fsm_debug && (stage & FSM_SYSCALL)) 02296 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur, 02297 fsm->path, (int)st->st_uid, (int)st->st_gid, 02298 (rc < 0 ? strerror(errno) : "")); 02299 if (rc < 0) rc = CPIOERR_CHOWN_FAILED; 02300 break; 02301 case FSM_LCHOWN: 02302 #if ! CHOWN_FOLLOWS_SYMLINK 02303 rc = Lchown(fsm->path, st->st_uid, st->st_gid); 02304 if (_fsm_debug && (stage & FSM_SYSCALL)) 02305 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur, 02306 fsm->path, (int)st->st_uid, (int)st->st_gid, 02307 (rc < 0 ? strerror(errno) : "")); 02308 if (rc < 0) rc = CPIOERR_CHOWN_FAILED; 02309 #endif 02310 break; 02311 case FSM_CHMOD: 02312 rc = Chmod(fsm->path, (st->st_mode & 07777)); 02313 if (_fsm_debug && (stage & FSM_SYSCALL)) 02314 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, 02315 fsm->path, (unsigned)(st->st_mode & 07777), 02316 (rc < 0 ? strerror(errno) : "")); 02317 if (rc < 0) rc = CPIOERR_CHMOD_FAILED; 02318 break; 02319 case FSM_UTIME: 02320 { struct utimbuf stamp; 02321 stamp.actime = st->st_mtime; 02322 stamp.modtime = st->st_mtime; 02323 rc = Utime(fsm->path, &stamp); 02324 if (_fsm_debug && (stage & FSM_SYSCALL)) 02325 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0x%x) %s\n", cur, 02326 fsm->path, (unsigned)st->st_mtime, 02327 (rc < 0 ? strerror(errno) : "")); 02328 if (rc < 0) rc = CPIOERR_UTIME_FAILED; 02329 } 02330 break; 02331 case FSM_SYMLINK: 02332 rc = Symlink(fsm->lpath, fsm->path); 02333 if (_fsm_debug && (stage & FSM_SYSCALL)) 02334 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, 02335 fsm->lpath, fsm->path, (rc < 0 ? strerror(errno) : "")); 02336 if (rc < 0) rc = CPIOERR_SYMLINK_FAILED; 02337 break; 02338 case FSM_LINK: 02339 rc = Link(fsm->opath, fsm->path); 02340 if (_fsm_debug && (stage & FSM_SYSCALL)) 02341 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, 02342 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); 02343 if (rc < 0) rc = CPIOERR_LINK_FAILED; 02344 break; 02345 case FSM_MKFIFO: 02346 rc = Mkfifo(fsm->path, (st->st_mode & 07777)); 02347 if (_fsm_debug && (stage & FSM_SYSCALL)) 02348 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, 02349 fsm->path, (unsigned)(st->st_mode & 07777), 02350 (rc < 0 ? strerror(errno) : "")); 02351 if (rc < 0) rc = CPIOERR_MKFIFO_FAILED; 02352 break; 02353 case FSM_MKNOD: 02354 /*@-unrecog -portability @*/ /* FIX: check S_IFIFO or dev != 0 */ 02355 rc = Mknod(fsm->path, (st->st_mode & ~07777), st->st_rdev); 02356 /*@=unrecog =portability @*/ 02357 if (_fsm_debug && (stage & FSM_SYSCALL)) 02358 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur, 02359 fsm->path, (unsigned)(st->st_mode & ~07777), 02360 (unsigned)st->st_rdev, 02361 (rc < 0 ? strerror(errno) : "")); 02362 if (rc < 0) rc = CPIOERR_MKNOD_FAILED; 02363 break; 02364 case FSM_LSTAT: 02365 rc = Lstat(fsm->path, ost); 02366 if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT) 02367 rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur, 02368 fsm->path, (rc < 0 ? strerror(errno) : "")); 02369 if (rc < 0) { 02370 rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_LSTAT_FAILED); 02371 memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */ 02372 } 02373 break; 02374 case FSM_STAT: 02375 rc = Stat(fsm->path, ost); 02376 if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT) 02377 rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur, 02378 fsm->path, (rc < 0 ? strerror(errno) : "")); 02379 if (rc < 0) { 02380 rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_STAT_FAILED); 02381 memset(ost, 0, sizeof(*ost)); /* XXX s390x hackery */ 02382 } 02383 break; 02384 case FSM_READLINK: 02385 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ 02386 /*@-boundswrite@*/ 02387 rc = Readlink(fsm->path, fsm->rdbuf, fsm->rdsize - 1); 02388 /*@=boundswrite@*/ 02389 if (_fsm_debug && (stage & FSM_SYSCALL)) 02390 rpmMessage(RPMMESS_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur, 02391 fsm->path, (int)(fsm->rdsize -1), (rc < 0 ? strerror(errno) : "")); 02392 if (rc < 0) rc = CPIOERR_READLINK_FAILED; 02393 else { 02394 fsm->rdnb = rc; 02395 /*@-boundswrite@*/ 02396 fsm->rdbuf[fsm->rdnb] = '\0'; 02397 /*@=boundswrite@*/ 02398 rc = 0; 02399 } 02400 break; 02401 case FSM_CHROOT: 02402 break; 02403 02404 case FSM_NEXT: 02405 rc = fsmUNSAFE(fsm, FSM_HREAD); 02406 if (rc) break; 02407 if (!strcmp(fsm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */ 02408 fsm->path = _free(fsm->path); 02409 rc = CPIOERR_HDR_TRAILER; 02410 } 02411 if (!rc) 02412 rc = fsmNext(fsm, FSM_POS); 02413 break; 02414 case FSM_EAT: 02415 for (left = st->st_size; left > 0; left -= fsm->rdnb) { 02416 fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); 02417 rc = fsmNext(fsm, FSM_DREAD); 02418 if (rc) 02419 /*@loopbreak@*/ break; 02420 } 02421 break; 02422 case FSM_POS: 02423 left = (fsm->blksize - (fdGetCpioPos(fsm->cfd) % fsm->blksize)) % fsm->blksize; 02424 if (left) { 02425 fsm->wrlen = left; 02426 (void) fsmNext(fsm, FSM_DREAD); 02427 } 02428 break; 02429 case FSM_PAD: 02430 left = (fsm->blksize - (fdGetCpioPos(fsm->cfd) % fsm->blksize)) % fsm->blksize; 02431 if (left) { 02432 /*@-boundswrite@*/ 02433 memset(fsm->rdbuf, 0, left); 02434 /*@=boundswrite@*/ 02435 /* XXX DWRITE uses rdnb for I/O length. */ 02436 fsm->rdnb = left; 02437 (void) fsmNext(fsm, FSM_DWRITE); 02438 } 02439 break; 02440 case FSM_TRAILER: 02441 rc = (*fsm->trailerWrite) (fsm); /* Write payload trailer. */ 02442 break; 02443 case FSM_HREAD: 02444 rc = fsmNext(fsm, FSM_POS); 02445 if (!rc) 02446 rc = (*fsm->headerRead) (fsm, st); /* Read next payload header. */ 02447 break; 02448 case FSM_HWRITE: 02449 rc = (*fsm->headerWrite) (fsm, st); /* Write next payload header. */ 02450 break; 02451 case FSM_DREAD: 02452 /*@-boundswrite@*/ 02453 fsm->rdnb = Fread(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->wrlen, fsm->cfd); 02454 /*@=boundswrite@*/ 02455 if (_fsm_debug && (stage & FSM_SYSCALL)) 02456 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n", 02457 cur, (fsm->wrbuf == fsm->wrb ? "wrbuf" : "mmap"), 02458 (int)fsm->wrlen, (int)fsm->rdnb); 02459 if (fsm->rdnb != fsm->wrlen || Ferror(fsm->cfd)) 02460 rc = CPIOERR_READ_FAILED; 02461 if (fsm->rdnb > 0) 02462 fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->rdnb); 02463 break; 02464 case FSM_DWRITE: 02465 fsm->wrnb = Fwrite(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdnb, fsm->cfd); 02466 if (_fsm_debug && (stage & FSM_SYSCALL)) 02467 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n", 02468 cur, (fsm->rdbuf == fsm->rdb ? "rdbuf" : "mmap"), 02469 (int)fsm->rdnb, (int)fsm->wrnb); 02470 if (fsm->rdnb != fsm->wrnb || Ferror(fsm->cfd)) 02471 rc = CPIOERR_WRITE_FAILED; 02472 if (fsm->wrnb > 0) 02473 fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->wrnb); 02474 break; 02475 02476 case FSM_ROPEN: 02477 fsm->rfd = Fopen(fsm->path, "r"); 02478 if (fsm->rfd == NULL || Ferror(fsm->rfd)) { 02479 if (fsm->rfd != NULL) (void) fsmNext(fsm, FSM_RCLOSE); 02480 fsm->rfd = NULL; 02481 rc = CPIOERR_OPEN_FAILED; 02482 break; 02483 } 02484 if (_fsm_debug && (stage & FSM_SYSCALL)) 02485 rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur, 02486 fsm->path, fsm->rfd, fsm->rdbuf); 02487 break; 02488 case FSM_READ: 02489 /*@-boundswrite@*/ 02490 fsm->rdnb = Fread(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdlen, fsm->rfd); 02491 /*@=boundswrite@*/ 02492 if (_fsm_debug && (stage & FSM_SYSCALL)) 02493 rpmMessage(RPMMESS_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n", 02494 cur, (int)fsm->rdlen, (int)fsm->rdnb); 02495 if (fsm->rdnb != fsm->rdlen || Ferror(fsm->rfd)) 02496 rc = CPIOERR_READ_FAILED; 02497 break; 02498 case FSM_RCLOSE: 02499 if (fsm->rfd != NULL) { 02500 if (_fsm_debug && (stage & FSM_SYSCALL)) 02501 rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->rfd); 02502 (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST), 02503 fdstat_op(fsm->rfd, FDSTAT_DIGEST)); 02504 (void) Fclose(fsm->rfd); 02505 errno = saveerrno; 02506 } 02507 fsm->rfd = NULL; 02508 break; 02509 case FSM_WOPEN: 02510 fsm->wfd = Fopen(fsm->path, "w"); 02511 if (fsm->wfd == NULL || Ferror(fsm->wfd)) { 02512 if (fsm->wfd != NULL) (void) fsmNext(fsm, FSM_WCLOSE); 02513 fsm->wfd = NULL; 02514 rc = CPIOERR_OPEN_FAILED; 02515 } 02516 if (_fsm_debug && (stage & FSM_SYSCALL)) 02517 rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur, 02518 fsm->path, fsm->wfd, fsm->wrbuf); 02519 break; 02520 case FSM_WRITE: 02521 fsm->wrnb = Fwrite(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->rdnb, fsm->wfd); 02522 if (_fsm_debug && (stage & FSM_SYSCALL)) 02523 rpmMessage(RPMMESS_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n", 02524 cur, (int)fsm->rdnb, (int)fsm->wrnb); 02525 if (fsm->rdnb != fsm->wrnb || Ferror(fsm->wfd)) 02526 rc = CPIOERR_WRITE_FAILED; 02527 break; 02528 case FSM_WCLOSE: 02529 if (fsm->wfd != NULL) { 02530 if (_fsm_debug && (stage & FSM_SYSCALL)) 02531 rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->wfd); 02532 (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST), 02533 fdstat_op(fsm->wfd, FDSTAT_DIGEST)); 02534 (void) Fclose(fsm->wfd); 02535 errno = saveerrno; 02536 } 02537 fsm->wfd = NULL; 02538 break; 02539 02540 default: 02541 break; 02542 } 02543 /*@=branchstate@*/ 02544 02545 if (!(stage & FSM_INTERNAL)) { 02546 fsm->rc = (rc == CPIOERR_HDR_TRAILER ? 0 : rc); 02547 } 02548 return rc; 02549 } 02550 /*@=compmempass@*/ 02551 /*@=boundsread@*/ 02552 02553 /*@observer@*/ const char * fileActionString(fileAction a) 02554 { 02555 switch (a) { 02556 case FA_UNKNOWN: return "unknown"; 02557 case FA_CREATE: return "create"; 02558 case FA_COPYOUT: return "copyout"; 02559 case FA_COPYIN: return "copyin"; 02560 case FA_BACKUP: return "backup"; 02561 case FA_SAVE: return "save"; 02562 case FA_SKIP: return "skip"; 02563 case FA_ALTNAME: return "altname"; 02564 case FA_ERASE: return "erase"; 02565 case FA_SKIPNSTATE: return "skipnstate"; 02566 case FA_SKIPNETSHARED: return "skipnetshared"; 02567 case FA_SKIPCOLOR: return "skipcolor"; 02568 default: return "???"; 02569 } 02570 /*@notreached@*/ 02571 } 02572 02573 /*@observer@*/ const char * fileStageString(fileStage a) { 02574 switch(a) { 02575 case FSM_UNKNOWN: return "unknown"; 02576 02577 case FSM_PKGINSTALL:return "INSTALL"; 02578 case FSM_PKGERASE: return "ERASE"; 02579 case FSM_PKGBUILD: return "BUILD"; 02580 case FSM_PKGCOMMIT: return "COMMIT"; 02581 case FSM_PKGUNDO: return "UNDO"; 02582 02583 case FSM_CREATE: return "create"; 02584 case FSM_INIT: return "init"; 02585 case FSM_MAP: return "map"; 02586 case FSM_MKDIRS: return "mkdirs"; 02587 case FSM_RMDIRS: return "rmdirs"; 02588 case FSM_PRE: return "pre"; 02589 case FSM_PROCESS: return "process"; 02590 case FSM_POST: return "post"; 02591 case FSM_MKLINKS: return "mklinks"; 02592 case FSM_NOTIFY: return "notify"; 02593 case FSM_UNDO: return "undo"; 02594 case FSM_FINI: return "fini"; 02595 case FSM_COMMIT: return "commit"; 02596 case FSM_DESTROY: return "destroy"; 02597 case FSM_VERIFY: return "verify"; 02598 02599 case FSM_UNLINK: return "Unlink"; 02600 case FSM_RENAME: return "Rename"; 02601 case FSM_MKDIR: return "Mkdir"; 02602 case FSM_RMDIR: return "rmdir"; 02603 case FSM_LSETFCON: return "lsetfcon"; 02604 case FSM_CHOWN: return "chown"; 02605 case FSM_LCHOWN: return "lchown"; 02606 case FSM_CHMOD: return "chmod"; 02607 case FSM_UTIME: return "utime"; 02608 case FSM_SYMLINK: return "symlink"; 02609 case FSM_LINK: return "Link"; 02610 case FSM_MKFIFO: return "mkfifo"; 02611 case FSM_MKNOD: return "mknod"; 02612 case FSM_LSTAT: return "Lstat"; 02613 case FSM_STAT: return "Stat"; 02614 case FSM_READLINK: return "Readlink"; 02615 case FSM_CHROOT: return "chroot"; 02616 02617 case FSM_NEXT: return "next"; 02618 case FSM_EAT: return "eat"; 02619 case FSM_POS: return "pos"; 02620 case FSM_PAD: return "pad"; 02621 case FSM_TRAILER: return "trailer"; 02622 case FSM_HREAD: return "hread"; 02623 case FSM_HWRITE: return "hwrite"; 02624 case FSM_DREAD: return "Fread"; 02625 case FSM_DWRITE: return "Fwrite"; 02626 02627 case FSM_ROPEN: return "Fopen"; 02628 case FSM_READ: return "Fread"; 02629 case FSM_RCLOSE: return "Fclose"; 02630 case FSM_WOPEN: return "Fopen"; 02631 case FSM_WRITE: return "Fwrite"; 02632 case FSM_WCLOSE: return "Fclose"; 02633 02634 default: return "???"; 02635 } 02636 /*@noteached@*/ 02637 }