rpm 5.3.12
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio_internal.h> /* XXX urlPath, fdGetCpioPos */ 00009 #include <rpmcb.h> /* XXX fnpyKey */ 00010 #include "rpmsq.h" 00011 #include <rpmsx.h> 00012 #if defined(SUPPORT_AR_PAYLOADS) 00013 #include "ar.h" 00014 #endif 00015 #include "cpio.h" 00016 #include "tar.h" 00017 #include "ugid.h" /* XXX unameToUid() and gnameToGid() */ 00018 00019 #include <rpmtag.h> 00020 #include <rpmtypes.h> 00021 #define _RPMDB_INTERNAL 00022 #include <rpmdb.h> 00023 00024 #define _RPMFI_INTERNAL 00025 #include "rpmfi.h" 00026 00027 #define _IOSM_INTERNAL 00028 #include <fsm.h> 00029 #define fsmUNSAFE fsmStage 00030 00031 #define _USE_RPMTE 00032 #if defined(_USE_RPMTE) 00033 #include "rpmte.h" 00034 #endif 00035 #include "rpmts.h" 00036 00037 #include "debug.h" 00038 00039 /*@access FD_t @*/ /* XXX void ptr args */ 00040 /*@access FSMI_t @*/ 00041 /*@access IOSM_t @*/ 00042 /*@access IOSMI_t @*/ 00043 00044 /*@access rpmfi @*/ 00045 00046 /*@access rpmsx @*/ /* XXX cast */ 00047 /*@access rpmte @*/ /* XXX cast */ 00048 /*@access rpmts @*/ /* XXX cast */ 00049 00050 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) 00051 00052 #define _FSM_DEBUG 0 00053 /*@unchecked@*/ 00054 int _fsm_debug = _FSM_DEBUG; 00055 00056 /*@-exportheadervar@*/ 00057 /*@unchecked@*/ 00058 int _fsm_threads = 0; 00059 /*@=exportheadervar@*/ 00060 00066 static rpmts fsmGetTs(const IOSM_t fsm) 00067 /*@*/ 00068 { 00069 const FSMI_t iter = fsm->iter; 00070 /*@-compdef -refcounttrans -retexpose -usereleased @*/ 00071 return (iter ? iter->ts : NULL); 00072 /*@=compdef =refcounttrans =retexpose =usereleased @*/ 00073 } 00074 00080 static rpmfi fsmGetFi(const IOSM_t fsm) 00081 /*@*/ 00082 { 00083 const FSMI_t iter = fsm->iter; 00084 /*@-compdef -refcounttrans -retexpose -usereleased @*/ 00085 return (iter ? iter->fi : NULL); 00086 /*@=compdef =refcounttrans =retexpose =usereleased @*/ 00087 } 00088 00089 #define SUFFIX_RPMORIG ".rpmorig" 00090 #define SUFFIX_RPMSAVE ".rpmsave" 00091 #define SUFFIX_RPMNEW ".rpmnew" 00092 00101 static /*@only@*//*@null@*/ 00102 const char * fsmFsPath(/*@special@*/ /*@null@*/ const IOSM_t fsm, 00103 /*@null@*/ const struct stat * st, 00104 /*@null@*/ const char * subdir, 00105 /*@null@*/ const char * suffix) 00106 /*@uses fsm->dirName, fsm->baseName */ 00107 /*@*/ 00108 { 00109 const char * s = NULL; 00110 00111 if (fsm) { 00112 char * t; 00113 int nb; 00114 nb = strlen(fsm->dirName) + 00115 (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : 0) : 0) + 00116 (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : 0) : 0) + 00117 strlen(fsm->baseName) + 1; 00118 s = t = xmalloc(nb); 00119 t = stpcpy(t, fsm->dirName); 00120 if (st && !S_ISDIR(st->st_mode)) 00121 if (subdir) t = stpcpy(t, subdir); 00122 t = stpcpy(t, fsm->baseName); 00123 if (st && !S_ISDIR(st->st_mode)) 00124 if (suffix) t = stpcpy(t, suffix); 00125 } 00126 return s; 00127 } 00128 00134 static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ void * p) 00135 /*@globals fileSystem @*/ 00136 /*@modifies fileSystem @*/ 00137 { 00138 FSMI_t iter = p; 00139 if (iter) { 00140 iter->fi = rpmfiUnlink(iter->fi, "mapIterator"); 00141 /*@-internalglobs@*/ /* XXX rpmswExit() */ 00142 (void)rpmtsFree(iter->ts); 00143 iter->ts = NULL; 00144 /*@=internalglobs@*/ 00145 } 00146 return _free(p); 00147 } 00148 00155 static void * 00156 mapInitIterator(rpmfi fi, int reverse) 00157 /*@modifies fi @*/ 00158 { 00159 FSMI_t iter = NULL; 00160 00161 iter = xcalloc(1, sizeof(*iter)); 00162 /*@-assignexpose -castexpose @*/ 00163 iter->fi = rpmfiLink(fi, "mapIterator"); 00164 /*@=assignexpose =castexpose @*/ 00165 iter->reverse = reverse; 00166 iter->i = (iter->reverse ? (fi->fc - 1) : 0); 00167 iter->isave = iter->i; 00168 return iter; 00169 } 00170 00176 static int mapNextIterator(/*@null@*/ void * a) 00177 /*@*/ 00178 { 00179 FSMI_t iter = a; 00180 int i = -1; 00181 00182 if (iter) { 00183 /*@-onlytrans@*/ 00184 const rpmfi fi = iter->fi; 00185 /*@=onlytrans@*/ 00186 if (iter->reverse) { 00187 if (iter->i >= 0) i = iter->i--; 00188 } else { 00189 if (iter->i < (int)fi->fc) i = iter->i++; 00190 } 00191 iter->isave = i; 00192 } 00193 return i; 00194 } 00195 00198 static int cpioStrCmp(const void * a, const void * b) 00199 /*@*/ 00200 { 00201 const char * aurl = *(const char **)a; 00202 const char * burl = *(const char **)b; 00203 const char * afn = NULL; 00204 const char * bfn = NULL; 00205 00206 (void) urlPath(aurl, &afn); 00207 (void) urlPath(burl, &bfn); 00208 00209 #ifdef VERY_OLD_BUGGY_RPM_PACKAGES 00210 /* XXX Some rpm-2.4 packages from 1997 have basename only in payloads. */ 00211 if (strchr(afn, '/') == NULL) 00212 bfn = strrchr(bfn, '/') + 1; 00213 #endif 00214 00215 /* Match rpm-4.0 payloads with ./ prefixes. */ 00216 if (afn[0] == '.' && afn[1] == '/') afn += 2; 00217 if (bfn[0] == '.' && bfn[1] == '/') bfn += 2; 00218 00219 /* If either path is absolute, make it relative to '/'. */ 00220 if (afn[0] == '/') afn += 1; 00221 if (bfn[0] == '/') bfn += 1; 00222 00223 return strcmp(afn, bfn); 00224 } 00225 00232 static int mapFind(/*@null@*/ FSMI_t iter, const char * fsmPath) 00233 /*@modifies iter @*/ 00234 { 00235 int ix = -1; 00236 00237 if (iter) { 00238 /*@-onlytrans@*/ 00239 const rpmfi fi = iter->fi; 00240 /*@=onlytrans@*/ 00241 size_t fc = rpmfiFC(fi); 00242 if (fi && fc > 0 && fi->apath && fsmPath && *fsmPath) { 00243 const char ** p = NULL; 00244 00245 if (fi->apath != NULL) 00246 p = bsearch(&fsmPath, fi->apath, fc, sizeof(fsmPath), 00247 cpioStrCmp); 00248 if (p) { 00249 iter->i = p - fi->apath; 00250 ix = mapNextIterator(iter); 00251 } 00252 } 00253 } 00254 return ix; 00255 } 00256 00260 typedef struct dnli_s { 00261 rpmfi fi; 00262 /*@only@*/ /*@null@*/ 00263 char * active; 00264 int reverse; 00265 int isave; 00266 int i; 00267 } * DNLI_t; 00268 00274 static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ const void * a) 00275 /*@modifies a @*/ 00276 { 00277 if (a) { 00278 DNLI_t dnli = (void *)a; 00279 if (dnli->active) free(dnli->active); 00280 } 00281 return _free(a); 00282 } 00283 00286 static inline int dnlCount(/*@null@*/ const DNLI_t dnli) 00287 /*@*/ 00288 { 00289 return (int) (dnli ? dnli->fi->dc : 0); 00290 } 00291 00294 static inline int dnlIndex(/*@null@*/ const DNLI_t dnli) 00295 /*@*/ 00296 { 00297 return (dnli ? dnli->isave : -1); 00298 } 00299 00306 /*@-usereleased@*/ 00307 static /*@only@*/ /*@null@*/ 00308 void * dnlInitIterator(/*@special@*/ const IOSM_t fsm, 00309 int reverse) 00310 /*@uses fsm->iter @*/ 00311 /*@*/ 00312 { 00313 rpmfi fi = fsmGetFi(fsm); 00314 const char * dnl; 00315 DNLI_t dnli; 00316 int i, j; 00317 00318 if (fi == NULL) 00319 return NULL; 00320 dnli = xcalloc(1, sizeof(*dnli)); 00321 dnli->fi = fi; 00322 dnli->reverse = reverse; 00323 dnli->i = (int) (reverse ? fi->dc : 0); 00324 00325 if (fi->dc) { 00326 dnli->active = xcalloc(fi->dc, sizeof(*dnli->active)); 00327 00328 /* Identify parent directories not skipped. */ 00329 if ((fi = rpmfiInit(fi, 0)) != NULL) 00330 while ((i = rpmfiNext(fi)) >= 0) { 00331 if (!iosmFileActionSkipped(fi->actions[i])) dnli->active[fi->dil[i]] = 1; 00332 } 00333 00334 /* Exclude parent directories that are explicitly included. */ 00335 if ((fi = rpmfiInit(fi, 0)) != NULL) 00336 while ((i = rpmfiNext(fi)) >= 0) { 00337 rpmuint32_t dil; 00338 size_t dnlen, bnlen; 00339 00340 if (!S_ISDIR(fi->fmodes[i])) 00341 continue; 00342 00343 dil = fi->dil[i]; 00344 dnlen = strlen(fi->dnl[dil]); 00345 bnlen = strlen(fi->bnl[i]); 00346 00347 for (j = 0; j < (int)fi->dc; j++) { 00348 size_t jlen; 00349 00350 if (!dnli->active[j] || j == (int)dil) 00351 /*@innercontinue@*/ continue; 00352 (void) urlPath(fi->dnl[j], &dnl); 00353 jlen = strlen(dnl); 00354 if (jlen != (dnlen+bnlen+1)) 00355 /*@innercontinue@*/ continue; 00356 if (strncmp(dnl, fi->dnl[dil], dnlen)) 00357 /*@innercontinue@*/ continue; 00358 if (strncmp(dnl+dnlen, fi->bnl[i], bnlen)) 00359 /*@innercontinue@*/ continue; 00360 if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') 00361 /*@innercontinue@*/ continue; 00362 /* This directory is included in the package. */ 00363 dnli->active[j] = 0; 00364 /*@innerbreak@*/ break; 00365 } 00366 } 00367 00368 /* Print only once per package. */ 00369 if (!reverse) { 00370 j = 0; 00371 for (i = 0; i < (int)fi->dc; i++) { 00372 if (!dnli->active[i]) continue; 00373 if (j == 0) { 00374 j = 1; 00375 rpmlog(RPMLOG_DEBUG, 00376 D_("========== Directories not explicitly included in package:\n")); 00377 } 00378 (void) urlPath(fi->dnl[i], &dnl); 00379 rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, dnl); 00380 } 00381 if (j) 00382 rpmlog(RPMLOG_DEBUG, "==========\n"); 00383 } 00384 } 00385 return dnli; 00386 } 00387 /*@=usereleased@*/ 00388 00394 static /*@observer@*/ /*@null@*/ 00395 const char * dnlNextIterator(/*@null@*/ DNLI_t dnli) 00396 /*@modifies dnli @*/ 00397 { 00398 const char * dn = NULL; 00399 00400 if (dnli) { 00401 rpmfi fi = dnli->fi; 00402 int i = -1; 00403 00404 if (dnli->active) 00405 do { 00406 i = (!dnli->reverse ? dnli->i++ : --dnli->i); 00407 } while (i >= 0 && i < (int)fi->dc && !dnli->active[i]); 00408 00409 if (i >= 0 && i < (int)fi->dc) 00410 dn = fi->dnl[i]; 00411 else 00412 i = -1; 00413 dnli->isave = i; 00414 } 00415 return dn; 00416 } 00417 00418 #if defined(WITH_PTHREADS) 00419 static void * fsmThread(void * arg) 00420 /*@globals h_errno, fileSystem, internalState @*/ 00421 /*@modifies arg, fileSystem, internalState @*/ 00422 { 00423 IOSM_t fsm = arg; 00424 /*@-unqualifiedtrans@*/ 00425 return ((void *) ((long)fsmStage(fsm, fsm->nstage))); 00426 /*@=unqualifiedtrans@*/ 00427 } 00428 #endif 00429 00430 int fsmNext(IOSM_t fsm, iosmFileStage nstage) 00431 /*@globals h_errno, fileSystem, internalState @*/ 00432 /*@modifies fsm, fileSystem, internalState @*/ 00433 { 00434 fsm->nstage = nstage; 00435 #if defined(WITH_PTHREADS) 00436 if (fsm->multithreaded) 00437 return rpmsqJoin( rpmsqThread(fsmThread, fsm) ); 00438 #endif 00439 return fsmStage(fsm, fsm->nstage); 00440 } 00441 00447 static int saveHardLink(/*@special@*/ /*@partial@*/ IOSM_t fsm) 00448 /*@uses fsm->links, fsm->ix, fsm->sb, fsm->goal, fsm->nsuffix @*/ 00449 /*@defines fsm->li @*/ 00450 /*@releases fsm->path @*/ 00451 /*@globals h_errno, fileSystem, internalState @*/ 00452 /*@modifies fsm, fileSystem, internalState @*/ 00453 { 00454 struct stat * st = &fsm->sb; 00455 int rc = 0; 00456 int ix = -1; 00457 int j; 00458 00459 /* Find hard link set. */ 00460 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { 00461 if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev) 00462 break; 00463 } 00464 00465 /* New hard link encountered, add new link to set. */ 00466 if (fsm->li == NULL) { 00467 fsm->li = xcalloc(1, sizeof(*fsm->li)); 00468 fsm->li->next = NULL; 00469 fsm->li->sb = *st; /* structure assignment */ 00470 fsm->li->nlink = (int) st->st_nlink; 00471 fsm->li->linkIndex = fsm->ix; 00472 fsm->li->createdPath = -1; 00473 00474 fsm->li->filex = xcalloc(st->st_nlink, sizeof(fsm->li->filex[0])); 00475 memset(fsm->li->filex, -1, (st->st_nlink * sizeof(fsm->li->filex[0]))); 00476 fsm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*fsm->li->nsuffix)); 00477 00478 if (fsm->goal == IOSM_PKGBUILD) 00479 fsm->li->linksLeft = (int) st->st_nlink; 00480 if (fsm->goal == IOSM_PKGINSTALL) 00481 fsm->li->linksLeft = 0; 00482 00483 /*@-kepttrans@*/ 00484 fsm->li->next = fsm->links; 00485 /*@=kepttrans@*/ 00486 fsm->links = fsm->li; 00487 } 00488 00489 if (fsm->goal == IOSM_PKGBUILD) --fsm->li->linksLeft; 00490 fsm->li->filex[fsm->li->linksLeft] = fsm->ix; 00491 /*@-observertrans -dependenttrans@*/ 00492 fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix; 00493 /*@=observertrans =dependenttrans@*/ 00494 if (fsm->goal == IOSM_PKGINSTALL) fsm->li->linksLeft++; 00495 00496 if (fsm->goal == IOSM_PKGBUILD) 00497 return (fsm->li->linksLeft > 0); 00498 00499 if (fsm->goal != IOSM_PKGINSTALL) 00500 return 0; 00501 00502 if (!(st->st_size || fsm->li->linksLeft == (int) st->st_nlink)) 00503 return 1; 00504 00505 /* Here come the bits, time to choose a non-skipped file name. */ 00506 { rpmfi fi = fsmGetFi(fsm); 00507 00508 for (j = fsm->li->linksLeft - 1; j >= 0; j--) { 00509 ix = fsm->li->filex[j]; 00510 if (ix < 0 || iosmFileActionSkipped(fi->actions[ix])) 00511 continue; 00512 break; 00513 } 00514 } 00515 00516 /* Are all links skipped or not encountered yet? */ 00517 if (ix < 0 || j < 0) 00518 return 1; /* XXX W2DO? */ 00519 00520 /* Save the non-skipped file name and map index. */ 00521 fsm->li->linkIndex = j; 00522 fsm->path = _free(fsm->path); 00523 fsm->ix = ix; 00524 rc = fsmNext(fsm, IOSM_MAP); 00525 return rc; 00526 } 00527 00533 static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink_s * li) 00534 /*@modifies li @*/ 00535 { 00536 if (li) { 00537 li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */ 00538 li->filex = _free(li->filex); 00539 } 00540 return _free(li); 00541 } 00542 00543 IOSM_t newFSM(void) 00544 { 00545 IOSM_t fsm = xcalloc(1, sizeof(*fsm)); 00546 return fsm; 00547 } 00548 00549 IOSM_t freeFSM(IOSM_t fsm) 00550 { 00551 if (fsm) { 00552 fsm->path = _free(fsm->path); 00553 while ((fsm->li = fsm->links) != NULL) { 00554 fsm->links = fsm->li->next; 00555 fsm->li->next = NULL; 00556 fsm->li = freeHardLink(fsm->li); 00557 } 00558 fsm->dnlx = _free(fsm->dnlx); 00559 fsm->ldn = _free(fsm->ldn); 00560 fsm->iter = mapFreeIterator(fsm->iter); 00561 } 00562 return _free(fsm); 00563 } 00564 00565 #if defined(SUPPORT_AR_PAYLOADS) 00566 static int arSetup(IOSM_t fsm, rpmfi fi) 00567 /*@modifies fsm @*/ 00568 { 00569 const char * path; 00570 char * t; 00571 size_t lmtablen = 0; 00572 size_t nb; 00573 00574 /* Calculate size of ar(1) long member table. */ 00575 if ((fi = rpmfiInit(fi, 0)) != NULL) 00576 while (rpmfiNext(fi) >= 0) { 00577 #ifdef NOTYET 00578 if (fi->apath) { 00579 const char * apath = NULL; 00580 (void) urlPath(fi->apath[ix], &apath); 00581 path = apath + fi->striplen; 00582 } else 00583 #endif 00584 path = rpmfiBN(fi); 00585 if ((nb = strlen(path)) < 15) 00586 continue; 00587 lmtablen += nb + 1; /* trailing \n */ 00588 } 00589 00590 /* Anything to do? */ 00591 if (lmtablen == 0) 00592 return 0; 00593 00594 /* Create and load ar(1) long member table. */ 00595 fsm->lmtab = t = xmalloc(lmtablen + 1); /* trailing \0 */ 00596 fsm->lmtablen = lmtablen; 00597 fsm->lmtaboff = 0; 00598 if ((fi = rpmfiInit(fi, 0)) != NULL) 00599 while (rpmfiNext(fi) >= 0) { 00600 #ifdef NOTYET 00601 if (fi->apath) { 00602 const char * apath = NULL; 00603 (void) urlPath(fi->apath[ix], &apath); 00604 path = apath + fi->striplen; 00605 } else 00606 #endif 00607 path = rpmfiBN(fi); 00608 if ((nb = strlen(path)) < 15) 00609 continue; 00610 t = stpcpy(t, path); 00611 *t++ = '\n'; 00612 } 00613 *t = '\0'; 00614 00615 return 0; 00616 } 00617 #endif 00618 00619 int fsmSetup(void * _fsm, iosmFileStage goal, const char * afmt, 00620 const void * _ts, const void * _fi, FD_t cfd, 00621 unsigned int * archiveSize, const char ** failedFile) 00622 { 00623 IOSM_t fsm = _fsm; 00624 /*@-castexpose@*/ 00625 const rpmts ts = (const rpmts) _ts; 00626 const rpmfi fi = (const rpmfi) _fi; 00627 /*@=castexpose@*/ 00628 #if defined(_USE_RPMTE) 00629 int reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT); 00630 int adding = (rpmteType(fi->te) == TR_ADDED); 00631 #else 00632 int reverse = 0; /* XXX HACK: devise alternative means */ 00633 int adding = 1; /* XXX HACK: devise alternative means */ 00634 #endif 00635 size_t pos = 0; 00636 int rc, ec = 0; 00637 00638 fsm->debug = _fsm_debug; 00639 fsm->multithreaded = _fsm_threads; 00640 fsm->adding = adding; 00641 00642 /*@+voidabstract -nullpass@*/ 00643 if (fsm->debug < 0) 00644 fprintf(stderr, "--> fsmSetup(%p, 0x%x, \"%s\", %p, %p, %p, %p, %p)\n", fsm, goal, afmt, (void *)ts, fi, cfd, archiveSize, failedFile); 00645 /*@=voidabstract =nullpass@*/ 00646 00647 _iosmNext = &fsmNext; 00648 if (fsm->headerRead == NULL) { 00649 if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, "ustar"))) { 00650 if (fsm->debug < 0) 00651 fprintf(stderr, "\ttar vectors set\n"); 00652 fsm->headerRead = &tarHeaderRead; 00653 fsm->headerWrite = &tarHeaderWrite; 00654 fsm->trailerWrite = &tarTrailerWrite; 00655 fsm->blksize = TAR_BLOCK_SIZE; 00656 } else 00657 #if defined(SUPPORT_AR_PAYLOADS) 00658 if (afmt != NULL && !strcmp(afmt, "ar")) { 00659 if (fsm->debug < 0) 00660 fprintf(stderr, "\tar vectors set\n"); 00661 fsm->headerRead = &arHeaderRead; 00662 fsm->headerWrite = &arHeaderWrite; 00663 fsm->trailerWrite = &arTrailerWrite; 00664 fsm->blksize = 2; 00665 if (goal == IOSM_PKGBUILD || goal == IOSM_PKGERASE) 00666 (void) arSetup(fsm, fi); 00667 } else 00668 #endif 00669 { 00670 if (fsm->debug < 0) 00671 fprintf(stderr, "\tcpio vectors set\n"); 00672 fsm->headerRead = &cpioHeaderRead; 00673 fsm->headerWrite = &cpioHeaderWrite; 00674 fsm->trailerWrite = &cpioTrailerWrite; 00675 fsm->blksize = 4; 00676 } 00677 } 00678 00679 fsm->goal = goal; 00680 if (cfd != NULL) { 00681 /*@-assignexpose -castexpose @*/ 00682 fsm->cfd = fdLink(cfd, "persist (fsm)"); 00683 /*@=assignexpose =castexpose @*/ 00684 pos = fdGetCpioPos(fsm->cfd); 00685 fdSetCpioPos(fsm->cfd, 0); 00686 } 00687 /*@-mods@*/ /* LCL: avoid void * _ts/_fi annotations for now. */ 00688 fsm->iter = mapInitIterator(fi, reverse); 00689 /*@-assignexpose -castexpose @*/ 00690 fsm->iter->ts = rpmtsLink(ts, "mapIterator"); 00691 /*@=assignexpose =castexpose @*/ 00692 fsm->nofcontexts = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS); 00693 /*@=mods@*/ 00694 fsm->nofdigests = 00695 (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOFDIGESTS)) 00696 ? 0 : 1; 00697 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT) 00698 fsm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) && 00699 fsm->goal != IOSM_PKGCOMMIT) ? 0 : 1); 00700 #undef _tsmask 00701 00702 if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) { 00703 void * ptr; 00704 fi->archivePos = 0; 00705 ptr = rpmtsNotify(ts, fi->te, 00706 RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize); 00707 } 00708 00709 /*@-assignexpose@*/ 00710 fsm->archiveSize = archiveSize; 00711 if (fsm->archiveSize) 00712 *fsm->archiveSize = 0; 00713 fsm->failedFile = failedFile; 00714 if (fsm->failedFile) 00715 *fsm->failedFile = NULL; 00716 /*@=assignexpose@*/ 00717 00718 memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf)); 00719 if (fsm->goal == IOSM_PKGINSTALL) { 00720 if (ts && rpmtsGetTid(ts) != (rpmuint32_t)-1) 00721 sprintf(fsm->sufbuf, ";%08x", (unsigned)rpmtsGetTid(ts)); 00722 } 00723 00724 ec = fsm->rc = 0; 00725 /*@-mods@*/ /* LCL: avoid void * _fsm annotation for now. */ 00726 rc = fsmUNSAFE(fsm, IOSM_CREATE); 00727 /*@=mods@*/ 00728 if (rc && !ec) ec = rc; 00729 00730 /*@-mods@*/ /* LCL: avoid void * _fsm annotation for now. */ 00731 rc = fsmUNSAFE(fsm, fsm->goal); 00732 /*@=mods@*/ 00733 if (rc && !ec) ec = rc; 00734 00735 if (fsm->archiveSize && ec == 0) 00736 *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos); 00737 00738 /*@-nullstate@*/ /* FIX: *fsm->failedFile may be NULL */ 00739 return ec; 00740 /*@=nullstate@*/ 00741 } 00742 00743 int fsmTeardown(void * _fsm) 00744 { 00745 IOSM_t fsm = _fsm; 00746 int rc = fsm->rc; 00747 00748 if (fsm->debug < 0) 00749 fprintf(stderr, "--> fsmTeardown(%p)\n", fsm); 00750 if (!rc) 00751 rc = fsmUNSAFE(fsm, IOSM_DESTROY); 00752 00753 (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST), 00754 &fsm->op_digest); 00755 00756 fsm->lmtab = _free(fsm->lmtab); 00757 (void)rpmtsFree(fsm->iter->ts); 00758 fsm->iter->ts = NULL; 00759 fsm->iter = mapFreeIterator(fsm->iter); 00760 if (fsm->cfd != NULL) { 00761 /*@-refcounttrans@*/ /* FIX: XfdFree annotation */ 00762 fsm->cfd = fdFree(fsm->cfd, "persist (fsm)"); 00763 /*@=refcounttrans@*/ 00764 fsm->cfd = NULL; 00765 } 00766 fsm->failedFile = NULL; 00767 return rc; 00768 } 00769 00770 /* 00771 * Set file security context (if not disabled). 00772 * @param fsm file state machine data 00773 * @return 0 always 00774 */ 00775 static int fsmMapFContext(IOSM_t fsm) 00776 /*@modifies fsm @*/ 00777 { 00778 fsm->fcontext = NULL; 00779 if (!fsm->nofcontexts) { 00780 fsm->fcontext = rpmsxMatch(NULL, fsm->path, fsm->sb.st_mode); 00781 #ifdef DYING /* XXX SELinux file contexts not set from package content. */ 00782 { rpmfi fi = fsmGetFi(fsm); 00783 int i = fsm->ix; 00784 00785 /* Get file security context from package. */ 00786 if (fi && i >= 0 && i < (int)fi->fc) 00787 fsm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL); 00788 } 00789 #endif 00790 } 00791 return 0; 00792 } 00793 00794 int fsmMapPath(IOSM_t fsm) 00795 { 00796 rpmfi fi = fsmGetFi(fsm); /* XXX const except for fstates */ 00797 int teAdding = fsm->adding; 00798 int rc = 0; 00799 int i = fsm->ix; 00800 00801 fsm->osuffix = NULL; 00802 fsm->nsuffix = NULL; 00803 fsm->astriplen = 0; 00804 fsm->action = FA_UNKNOWN; 00805 fsm->mapFlags = fi->mapflags; 00806 00807 if (fi && i >= 0 && i < (int)fi->fc) { 00808 00809 fsm->astriplen = fi->astriplen; 00810 fsm->action = (fi->actions ? fi->actions[i] : fi->action); 00811 fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags); 00812 fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags); 00813 00814 /* src rpms have simple base name in payload. */ 00815 fsm->dirName = fi->dnl[fi->dil[i]]; 00816 fsm->baseName = fi->bnl[i]; 00817 00818 switch (fsm->action) { 00819 case FA_SKIP: 00820 break; 00821 case FA_UNKNOWN: 00822 break; 00823 00824 case FA_COPYOUT: 00825 break; 00826 case FA_COPYIN: 00827 case FA_CREATE: 00828 assert(teAdding); 00829 break; 00830 00831 case FA_SKIPNSTATE: 00832 if (fi->fstates && teAdding) 00833 fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED; 00834 break; 00835 00836 case FA_SKIPNETSHARED: 00837 if (fi->fstates && teAdding) 00838 fi->fstates[i] = RPMFILE_STATE_NETSHARED; 00839 break; 00840 00841 case FA_SKIPCOLOR: 00842 if (fi->fstates && teAdding) 00843 fi->fstates[i] = RPMFILE_STATE_WRONGCOLOR; 00844 break; 00845 00846 case FA_BACKUP: 00847 if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00848 fsm->osuffix = (teAdding ? SUFFIX_RPMORIG : SUFFIX_RPMSAVE); 00849 break; 00850 00851 case FA_ALTNAME: 00852 assert(teAdding); 00853 if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00854 fsm->nsuffix = SUFFIX_RPMNEW; 00855 break; 00856 00857 case FA_SAVE: 00858 assert(teAdding); 00859 if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */ 00860 fsm->osuffix = SUFFIX_RPMSAVE; 00861 break; 00862 case FA_ERASE: 00863 #if 0 /* XXX is this a genhdlist fix? */ 00864 assert(rpmteType(fi->te) == TR_REMOVED); 00865 #endif 00866 /* 00867 * XXX TODO: %ghost probably shouldn't be removed, but that changes 00868 * legacy rpm behavior. 00869 */ 00870 break; 00871 default: 00872 break; 00873 } 00874 00875 if ((fsm->mapFlags & IOSM_MAP_PATH) || fsm->nsuffix) { 00876 const struct stat * st = &fsm->sb; 00877 fsm->path = _free(fsm->path); 00878 fsm->path = fsmFsPath(fsm, st, fsm->subdir, 00879 (fsm->suffix ? fsm->suffix : fsm->nsuffix)); 00880 } 00881 } 00882 return rc; 00883 } 00884 00885 int fsmMapAttrs(IOSM_t fsm) 00886 { 00887 struct stat * st = &fsm->sb; 00888 rpmfi fi = fsmGetFi(fsm); 00889 int i = fsm->ix; 00890 00891 if (fi && i >= 0 && i < (int) fi->fc) { 00892 mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms); 00893 mode_t finalMode = (fi->fmodes ? (mode_t)fi->fmodes[i] : perms); 00894 dev_t finalRdev = (dev_t)(fi->frdevs ? fi->frdevs[i] : 0); 00895 rpmuint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0); 00896 uid_t uid = fi->uid; 00897 gid_t gid = fi->gid; 00898 00899 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00900 /* Make sure OpenPKG/Mandriva RPM does not try to set file owner/group on files during 00901 installation of _source_ RPMs. Instead, let it use the current 00902 run-time owner/group, because most of the time the owner/group in 00903 the source RPM (which is the owner/group of the files as staying on 00904 the package author system) is not existing on the target system, of 00905 course. */ 00906 #endif 00907 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) { 00908 #if defined(RPM_VENDOR_OPENPKG) ||defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00909 if (!fi->isSource) { 00910 #endif 00911 if (fsm->goal == IOSM_PKGINSTALL) 00912 rpmlog(RPMLOG_WARNING, 00913 _("user %s does not exist - using root\n"), fi->fuser[i]); 00914 uid = 0; 00915 finalMode &= ~S_ISUID; /* turn off suid bit */ 00916 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00917 } 00918 #endif 00919 } 00920 00921 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) { 00922 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00923 if (!fi->isSource) { 00924 #endif 00925 if (fsm->goal == IOSM_PKGINSTALL) 00926 rpmlog(RPMLOG_WARNING, 00927 _("group %s does not exist - using root\n"), fi->fgroup[i]); 00928 gid = 0; 00929 finalMode &= ~S_ISGID; /* turn off sgid bit */ 00930 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-owner-group-on-srpm-install */ 00931 } 00932 #endif 00933 } 00934 00935 if (fsm->mapFlags & IOSM_MAP_MODE) 00936 st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT); 00937 if (fsm->mapFlags & IOSM_MAP_TYPE) { 00938 st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT); 00939 if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) 00940 && st->st_nlink == 0) 00941 st->st_nlink = 1; 00942 st->st_rdev = finalRdev; 00943 st->st_mtime = finalMtime; 00944 } 00945 if (fsm->mapFlags & IOSM_MAP_UID) 00946 st->st_uid = uid; 00947 if (fsm->mapFlags & IOSM_MAP_GID) 00948 st->st_gid = gid; 00949 00950 /* 00951 * Set file digest (if not disabled). 00952 */ 00953 if (!fsm->nofdigests) { 00954 fsm->fdigestalgo = fi->digestalgo; 00955 fsm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL); 00956 fsm->digestlen = fi->digestlen; 00957 fsm->digest = (fi->digests ? (fi->digests + (fsm->digestlen * i)) : NULL); 00958 } else { 00959 fsm->fdigestalgo = 0; 00960 fsm->fdigest = NULL; 00961 fsm->digestlen = 0; 00962 fsm->digest = NULL; 00963 } 00964 } 00965 return 0; 00966 } 00967 00973 /*@-compdef@*/ 00974 static int extractRegular(/*@special@*/ IOSM_t fsm) 00975 /*@uses fsm->fdigest, fsm->digest, fsm->sb, fsm->wfd @*/ 00976 /*@globals h_errno, fileSystem, internalState @*/ 00977 /*@modifies fsm, fileSystem, internalState @*/ 00978 { 00979 const struct stat * st = &fsm->sb; 00980 size_t left = (size_t) st->st_size; 00981 int rc = 0; 00982 int xx; 00983 00984 { const char * fn = fsm->path; 00985 mode_t mode = st->st_mode; 00986 uint8_t * b = (uint8_t *)""; 00987 size_t blen = 1; 00988 const uint8_t * d = fsm->digest; 00989 size_t dlen = fsm->digestlen; 00990 uint32_t dalgo = fsm->fdigestalgo; 00991 00992 xx = rpmlioCreat(rpmtsGetRdb(fsmGetTs(fsm)), fn, mode, b, blen, d, dlen, dalgo); 00993 } 00994 00995 rc = fsmNext(fsm, IOSM_WOPEN); 00996 if (rc) 00997 goto exit; 00998 00999 if (st->st_size > 0 && (fsm->fdigest != NULL || fsm->digest != NULL)) 01000 fdInitDigest(fsm->wfd, fsm->fdigestalgo, 0); 01001 01002 while (left) { 01003 01004 fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); 01005 rc = fsmNext(fsm, IOSM_DREAD); 01006 if (rc) 01007 goto exit; 01008 01009 rc = fsmNext(fsm, IOSM_WRITE); 01010 if (rc) 01011 goto exit; 01012 01013 left -= fsm->wrnb; 01014 01015 /* Notify iff progress, completion is done elsewhere */ 01016 if (!rc && left) 01017 (void) fsmNext(fsm, IOSM_NOTIFY); 01018 } 01019 01020 #ifdef DYING 01021 /* Measurements from installing kernel-source package: 01022 * +fsync 01023 * total: 1 0.000000 MB 640.854524 secs 01024 * +fdatasync 01025 * total: 1 0.000000 MB 419.983200 secs 01026 * w/o fsync/fdsatasync: 01027 * total: 1 0.000000 MB 12.492918 secs 01028 */ 01029 xx = fsync(Fileno(fsm->wfd)); 01030 #endif 01031 01032 if (st->st_size > 0 && (fsm->fdigest || fsm->digest)) { 01033 void * digest = NULL; 01034 int asAscii = (fsm->digest == NULL ? 1 : 0); 01035 01036 (void) Fflush(fsm->wfd); 01037 fdFiniDigest(fsm->wfd, fsm->fdigestalgo, &digest, NULL, asAscii); 01038 01039 if (digest == NULL) { 01040 rc = IOSMERR_DIGEST_MISMATCH; 01041 goto exit; 01042 } 01043 01044 if (fsm->digest != NULL) { 01045 if (memcmp(digest, fsm->digest, fsm->digestlen)) 01046 rc = IOSMERR_DIGEST_MISMATCH; 01047 } else { 01048 if (strcmp(digest, fsm->fdigest)) 01049 rc = IOSMERR_DIGEST_MISMATCH; 01050 } 01051 digest = _free(digest); 01052 } 01053 01054 exit: 01055 (void) fsmNext(fsm, IOSM_WCLOSE); 01056 01057 return rc; 01058 } 01059 /*@=compdef@*/ 01060 01067 /*@-compdef -compmempass@*/ 01068 static int writeFile(/*@special@*/ /*@partial@*/ IOSM_t fsm, int writeData) 01069 /*@uses fsm->path, fsm->opath, fsm->sb, fsm->osb, fsm->cfd @*/ 01070 /*@globals h_errno, fileSystem, internalState @*/ 01071 /*@modifies fsm, fileSystem, internalState @*/ 01072 { 01073 const char * path = fsm->path; 01074 const char * opath = fsm->opath; 01075 struct stat * st = &fsm->sb; 01076 struct stat * ost = &fsm->osb; 01077 size_t left; 01078 int xx; 01079 int rc; 01080 01081 st->st_size = (writeData ? ost->st_size : 0); 01082 01083 if (S_ISDIR(st->st_mode)) { 01084 st->st_size = 0; 01085 } else if (S_ISLNK(st->st_mode)) { 01086 /* 01087 * While linux puts the size of a symlink in the st_size field, 01088 * I don't think that's a specified standard. 01089 */ 01090 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ 01091 rc = fsmUNSAFE(fsm, IOSM_READLINK); 01092 if (rc) goto exit; 01093 st->st_size = fsm->rdnb; 01094 fsm->lpath = xstrdup(fsm->rdbuf); /* XXX save readlink return. */ 01095 } 01096 01097 if (fsm->mapFlags & IOSM_MAP_ABSOLUTE) { 01098 size_t nb= strlen(fsm->dirName) + strlen(fsm->baseName) + sizeof("."); 01099 char * t = alloca(nb); 01100 *t = '\0'; 01101 fsm->path = t; 01102 if (fsm->mapFlags & IOSM_MAP_ADDDOT) 01103 *t++ = '.'; 01104 t = stpcpy( stpcpy(t, fsm->dirName), fsm->baseName); 01105 } else if (fsm->mapFlags & IOSM_MAP_PATH) { 01106 rpmfi fi = fsmGetFi(fsm); 01107 if (fi->apath) { 01108 const char * apath = NULL; 01109 (void) urlPath(fi->apath[fsm->ix], &apath); 01110 fsm->path = apath + fi->striplen; 01111 } else 01112 fsm->path = fi->bnl[fsm->ix]; 01113 } 01114 01115 rc = fsmNext(fsm, IOSM_HWRITE); 01116 fsm->path = path; 01117 if (rc) goto exit; 01118 01119 if (writeData && S_ISREG(st->st_mode)) { 01120 #if defined(HAVE_MMAP) 01121 char * rdbuf = NULL; 01122 void * mapped = (void *)-1; 01123 size_t nmapped = 0; 01124 /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED better. */ 01125 int use_mmap = (st->st_size <= 0x07ffffff); 01126 #endif 01127 01128 rc = fsmNext(fsm, IOSM_ROPEN); 01129 if (rc) goto exit; 01130 01131 /* XXX unbuffered mmap generates *lots* of fdio debugging */ 01132 #if defined(HAVE_MMAP) 01133 if (use_mmap) { 01134 mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0); 01135 if (mapped != (void *)-1) { 01136 rdbuf = fsm->rdbuf; 01137 fsm->rdbuf = (char *) mapped; 01138 fsm->rdlen = nmapped = st->st_size; 01139 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED) 01140 xx = madvise(mapped, nmapped, MADV_DONTNEED); 01141 #endif 01142 } 01143 } 01144 #endif 01145 01146 left = st->st_size; 01147 01148 while (left) { 01149 #if defined(HAVE_MMAP) 01150 if (mapped != (void *)-1) { 01151 fsm->rdnb = nmapped; 01152 } else 01153 #endif 01154 { 01155 fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left), 01156 rc = fsmNext(fsm, IOSM_READ); 01157 if (rc) goto exit; 01158 } 01159 01160 /* XXX DWRITE uses rdnb for I/O length. */ 01161 rc = fsmNext(fsm, IOSM_DWRITE); 01162 if (rc) goto exit; 01163 01164 left -= fsm->wrnb; 01165 } 01166 01167 #if defined(HAVE_MMAP) 01168 if (mapped != (void *)-1) { 01169 /* XXX splint misses size_t 2nd arg. */ 01170 /*@i@*/ xx = msync(mapped, nmapped, MS_ASYNC); 01171 #if defined(HAVE_MADVISE) && defined(MADV_DONTNEED) 01172 xx = madvise(mapped, nmapped, MADV_DONTNEED); 01173 #endif 01174 xx = munmap(mapped, nmapped); 01175 fsm->rdbuf = rdbuf; 01176 } else 01177 #endif 01178 xx = fsync(Fileno(fsm->rfd)); 01179 01180 } 01181 01182 rc = fsmNext(fsm, IOSM_PAD); 01183 if (rc) goto exit; 01184 01185 rc = 0; 01186 01187 exit: 01188 if (fsm->rfd != NULL) 01189 (void) fsmNext(fsm, IOSM_RCLOSE); 01190 /*@-dependenttrans@*/ 01191 fsm->opath = opath; 01192 fsm->path = path; 01193 /*@=dependenttrans@*/ 01194 return rc; 01195 } 01196 /*@=compdef =compmempass@*/ 01197 01203 static int writeLinkedFile(/*@special@*/ /*@partial@*/ IOSM_t fsm) 01204 /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->li, fsm->failedFile @*/ 01205 /*@globals h_errno, fileSystem, internalState @*/ 01206 /*@modifies fsm, fileSystem, internalState @*/ 01207 { 01208 const char * path = fsm->path; 01209 const char * lpath = fsm->lpath; 01210 const char * nsuffix = fsm->nsuffix; 01211 int iterIndex = fsm->ix; 01212 int ec = 0; 01213 int rc; 01214 int i; 01215 const char * linkpath = NULL; 01216 int firstfile = 1; 01217 01218 fsm->path = NULL; 01219 fsm->lpath = NULL; 01220 fsm->nsuffix = NULL; 01221 fsm->ix = -1; 01222 01223 for (i = fsm->li->nlink - 1; i >= 0; i--) { 01224 01225 if (fsm->li->filex[i] < 0) continue; 01226 01227 fsm->ix = fsm->li->filex[i]; 01228 /*@-compdef@*/ 01229 rc = fsmNext(fsm, IOSM_MAP); 01230 /*@=compdef@*/ 01231 01232 /* XXX tar and cpio have to do things differently. */ 01233 if (fsm->headerWrite == tarHeaderWrite) { 01234 if (firstfile) { 01235 const char * apath = NULL; 01236 char *t; 01237 (void) urlPath(fsm->path, &apath); 01238 /* Remove the buildroot prefix. */ 01239 t = xmalloc(sizeof(".") + strlen(apath + fsm->astriplen)); 01240 (void) stpcpy( stpcpy(t, "."), apath + fsm->astriplen); 01241 linkpath = t; 01242 firstfile = 0; 01243 } else 01244 fsm->lpath = linkpath; 01245 01246 /* Write data after first link for tar. */ 01247 rc = writeFile(fsm, (fsm->lpath == NULL)); 01248 } else { 01249 /* Write data after last link for cpio. */ 01250 rc = writeFile(fsm, (i == 0)); 01251 } 01252 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) { 01253 ec = rc; 01254 *fsm->failedFile = xstrdup(fsm->path); 01255 } 01256 01257 fsm->path = _free(fsm->path); 01258 fsm->li->filex[i] = -1; 01259 } 01260 01261 /*@-dependenttrans@*/ 01262 linkpath = _free(linkpath); 01263 /*@=dependenttrans@*/ 01264 fsm->ix = iterIndex; 01265 fsm->nsuffix = nsuffix; 01266 fsm->lpath = lpath; 01267 fsm->path = path; 01268 return ec; 01269 } 01270 01276 /*@-compdef@*/ 01277 static int fsmMakeLinks(/*@special@*/ /*@partial@*/ IOSM_t fsm) 01278 /*@uses fsm->path, fsm->opath, fsm->nsuffix, fsm->ix, fsm->li @*/ 01279 /*@globals h_errno, fileSystem, internalState @*/ 01280 /*@modifies fsm, fileSystem, internalState @*/ 01281 { 01282 const char * path = fsm->path; 01283 const char * opath = fsm->opath; 01284 const char * nsuffix = fsm->nsuffix; 01285 int iterIndex = fsm->ix; 01286 int ec = 0; 01287 int rc; 01288 int i; 01289 01290 fsm->path = NULL; 01291 fsm->opath = NULL; 01292 fsm->nsuffix = NULL; 01293 fsm->ix = -1; 01294 01295 fsm->ix = fsm->li->filex[fsm->li->createdPath]; 01296 rc = fsmNext(fsm, IOSM_MAP); 01297 fsm->opath = fsm->path; 01298 fsm->path = NULL; 01299 for (i = 0; i < fsm->li->nlink; i++) { 01300 if (fsm->li->filex[i] < 0) continue; 01301 if (fsm->li->createdPath == i) continue; 01302 01303 fsm->ix = fsm->li->filex[i]; 01304 fsm->path = _free(fsm->path); 01305 rc = fsmNext(fsm, IOSM_MAP); 01306 if (iosmFileActionSkipped(fsm->action)) continue; 01307 01308 rc = fsmUNSAFE(fsm, IOSM_VERIFY); 01309 if (!rc) continue; 01310 if (!(rc == IOSMERR_ENOENT)) break; 01311 01312 /* XXX link(fsm->opath, fsm->path) */ 01313 rc = fsmNext(fsm, IOSM_LINK); 01314 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) { 01315 ec = rc; 01316 *fsm->failedFile = xstrdup(fsm->path); 01317 } 01318 01319 fsm->li->linksLeft--; 01320 } 01321 fsm->path = _free(fsm->path); 01322 fsm->opath = _free(fsm->opath); 01323 01324 fsm->ix = iterIndex; 01325 fsm->nsuffix = nsuffix; 01326 fsm->path = path; 01327 fsm->opath = opath; 01328 return ec; 01329 } 01330 /*@=compdef@*/ 01331 01337 /*@-compdef@*/ 01338 static int fsmCommitLinks(/*@special@*/ /*@partial@*/ IOSM_t fsm) 01339 /*@uses fsm->path, fsm->nsuffix, fsm->ix, fsm->sb, 01340 fsm->li, fsm->links @*/ 01341 /*@globals h_errno, fileSystem, internalState @*/ 01342 /*@modifies fsm, fileSystem, internalState @*/ 01343 { 01344 const char * path = fsm->path; 01345 const char * nsuffix = fsm->nsuffix; 01346 int iterIndex = fsm->ix; 01347 struct stat * st = &fsm->sb; 01348 int rc = 0; 01349 int i; 01350 01351 fsm->path = NULL; 01352 fsm->nsuffix = NULL; 01353 fsm->ix = -1; 01354 01355 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { 01356 if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev) 01357 break; 01358 } 01359 01360 for (i = 0; i < fsm->li->nlink; i++) { 01361 if (fsm->li->filex[i] < 0) continue; 01362 fsm->ix = fsm->li->filex[i]; 01363 rc = fsmNext(fsm, IOSM_MAP); 01364 if (!iosmFileActionSkipped(fsm->action)) 01365 rc = fsmNext(fsm, IOSM_COMMIT); 01366 fsm->path = _free(fsm->path); 01367 fsm->li->filex[i] = -1; 01368 } 01369 01370 fsm->ix = iterIndex; 01371 fsm->nsuffix = nsuffix; 01372 fsm->path = path; 01373 return rc; 01374 } 01375 /*@=compdef@*/ 01376 01382 static int fsmRmdirs(/*@special@*/ /*@partial@*/ IOSM_t fsm) 01383 /*@uses fsm->path, fsm->dnlx, fsm->ldn, fsm->rdbuf, fsm->iter @*/ 01384 /*@globals h_errno, fileSystem, internalState @*/ 01385 /*@modifies fsm, fileSystem, internalState @*/ 01386 { 01387 const char * path = fsm->path; 01388 void * dnli = dnlInitIterator(fsm, 1); 01389 char * dn = fsm->rdbuf; 01390 int dc = dnlCount(dnli); 01391 int rc = 0; 01392 01393 fsm->path = NULL; 01394 dn[0] = '\0'; 01395 /*@-observertrans -dependenttrans@*/ 01396 if (fsm->ldn != NULL && fsm->dnlx != NULL) 01397 while ((fsm->path = dnlNextIterator(dnli)) != NULL) { 01398 size_t dnlen = strlen(fsm->path); 01399 char * te; 01400 01401 dc = dnlIndex(dnli); 01402 if (fsm->dnlx[dc] < 1 || (size_t)fsm->dnlx[dc] >= dnlen) 01403 continue; 01404 01405 /* Copy to avoid const on fsm->path. */ 01406 te = stpcpy(dn, fsm->path) - 1; 01407 fsm->path = dn; 01408 01409 /* Remove generated directories. */ 01410 /*@-usereleased@*/ /* LCL: te used after release? */ 01411 do { 01412 if (*te == '/') { 01413 *te = '\0'; 01414 /*@-compdef@*/ 01415 rc = fsmNext(fsm, IOSM_RMDIR); 01416 /*@=compdef@*/ 01417 *te = '/'; 01418 } 01419 if (rc) 01420 /*@innerbreak@*/ break; 01421 te--; 01422 } while ((te - fsm->path) > fsm->dnlx[dc]); 01423 /*@=usereleased@*/ 01424 } 01425 dnli = dnlFreeIterator(dnli); 01426 /*@=observertrans =dependenttrans@*/ 01427 01428 fsm->path = path; 01429 return rc; 01430 } 01431 01437 static int fsmMkdirs(/*@special@*/ /*@partial@*/ IOSM_t fsm) 01438 /*@uses fsm->path, fsm->sb, fsm->osb, fsm->rdbuf, fsm->iter, 01439 fsm->ldn, fsm->ldnlen, fsm->ldnalloc @*/ 01440 /*@defines fsm->dnlx, fsm->ldn @*/ 01441 /*@globals h_errno, fileSystem, internalState @*/ 01442 /*@modifies fsm, fileSystem, internalState @*/ 01443 { 01444 struct stat * st = &fsm->sb; 01445 struct stat * ost = &fsm->osb; 01446 const char * path = fsm->path; 01447 mode_t st_mode = st->st_mode; 01448 void * dnli = dnlInitIterator(fsm, 0); 01449 char * dn = fsm->rdbuf; 01450 int dc = dnlCount(dnli); 01451 int rc = 0; 01452 size_t i; 01453 01454 fsm->path = NULL; 01455 01456 dn[0] = '\0'; 01457 fsm->dnlx = (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL); 01458 /*@-observertrans -dependenttrans@*/ 01459 if (fsm->dnlx != NULL) 01460 while ((fsm->path = dnlNextIterator(dnli)) != NULL) { 01461 size_t dnlen = strlen(fsm->path); 01462 char * te; 01463 01464 dc = dnlIndex(dnli); 01465 if (dc < 0) continue; 01466 fsm->dnlx[dc] = (unsigned short) dnlen; 01467 if (dnlen <= 1) 01468 continue; 01469 01470 /*@-compdef -nullpass@*/ /* FIX: fsm->ldn not defined ??? */ 01471 if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn)) 01472 continue; 01473 /*@=compdef =nullpass@*/ 01474 01475 /* Copy to avoid const on fsm->path. */ 01476 (void) stpcpy(dn, fsm->path); 01477 fsm->path = dn; 01478 01479 /* Assume '/' directory exists, "mkdir -p" for others if non-existent */ 01480 (void) urlPath(dn, (const char **)&te); 01481 for (i = 1, te++; *te != '\0'; te++, i++) { 01482 if (*te != '/') 01483 /*@innercontinue@*/ continue; 01484 01485 *te = '\0'; 01486 01487 /* Already validated? */ 01488 /*@-usedef -compdef -nullpass -nullderef@*/ 01489 if (i < fsm->ldnlen && 01490 (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') && 01491 !strncmp(fsm->path, fsm->ldn, i)) 01492 { 01493 *te = '/'; 01494 /* Move pre-existing path marker forward. */ 01495 fsm->dnlx[dc] = (te - dn); 01496 /*@innercontinue@*/ continue; 01497 } 01498 /*@=usedef =compdef =nullpass =nullderef@*/ 01499 01500 /* Validate next component of path. */ 01501 rc = fsmUNSAFE(fsm, IOSM_LSTAT); 01502 *te = '/'; 01503 01504 /* Directory already exists? */ 01505 if (rc == 0 && S_ISDIR(ost->st_mode)) { 01506 /* Move pre-existing path marker forward. */ 01507 fsm->dnlx[dc] = (te - dn); 01508 } else if (rc == IOSMERR_ENOENT) { 01509 rpmfi fi = fsmGetFi(fsm); 01510 *te = '\0'; 01511 st->st_mode = S_IFDIR | (fi->dperms & 07777); 01512 rc = fsmNext(fsm, IOSM_MKDIR); 01513 if (!rc) { 01514 /* XXX FIXME? only new dir will have context set. */ 01515 /* Get file security context from patterns. */ 01516 if (!fsm->nofcontexts) { 01517 fsm->fcontext = 01518 rpmsxMatch(NULL, fsm->path, st->st_mode); 01519 if (fsm->fcontext != NULL) 01520 rc = fsmNext(fsm, IOSM_LSETFCON); 01521 } else 01522 fsm->fcontext = NULL; 01523 rpmlog(RPMLOG_DEBUG, 01524 D_("%s directory created with perms %04o, context %s.\n"), 01525 fsm->path, (unsigned)(st->st_mode & 07777), 01526 (fsm->fcontext ? fsm->fcontext : "(no context)")); 01527 fsm->fcontext = _free(fsm->fcontext); 01528 } 01529 *te = '/'; 01530 } 01531 if (rc) 01532 /*@innerbreak@*/ break; 01533 } 01534 if (rc) break; 01535 01536 /* Save last validated path. */ 01537 /*@-compdef@*/ /* FIX: ldn/path annotations ? */ 01538 if (fsm->ldnalloc < (dnlen + 1)) { 01539 fsm->ldnalloc = dnlen + 100; 01540 fsm->ldn = xrealloc(fsm->ldn, fsm->ldnalloc); 01541 } 01542 if (fsm->ldn != NULL) { /* XXX can't happen */ 01543 strcpy(fsm->ldn, fsm->path); 01544 fsm->ldnlen = dnlen; 01545 } 01546 /*@=compdef@*/ 01547 } 01548 dnli = dnlFreeIterator(dnli); 01549 /*@=observertrans =dependenttrans@*/ 01550 01551 fsm->path = path; 01552 st->st_mode = st_mode; /* XXX restore st->st_mode */ 01553 /*@-compdef@*/ /* FIX: ldn/path annotations ? */ 01554 return rc; 01555 /*@=compdef@*/ 01556 } 01557 01558 #ifdef NOTYET 01559 01564 static int fsmStat(/*@special@*/ /*@partial@*/ IOSM_t fsm) 01565 /*@globals fileSystem, internalState @*/ 01566 /*@modifies fsm, fileSystem, internalState @*/ 01567 { 01568 int rc = 0; 01569 01570 if (fsm->path != NULL) { 01571 int saveernno = errno; 01572 rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & IOSM_FOLLOW_SYMLINKS) 01573 ? IOSM_LSTAT : IOSM_STAT)); 01574 if (rc == IOSMERR_ENOENT) { 01575 errno = saveerrno; 01576 rc = 0; 01577 fsm->exists = 0; 01578 } else if (rc == 0) { 01579 fsm->exists = 1; 01580 } 01581 } else { 01582 /* Skip %ghost files on build. */ 01583 fsm->exists = 0; 01584 } 01585 return rc; 01586 } 01587 #endif 01588 01589 #define IS_DEV_LOG(_x) \ 01590 ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \ 01591 !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \ 01592 ((_x)[sizeof("/dev/log")-1] == '\0' || \ 01593 (_x)[sizeof("/dev/log")-1] == ';')) 01594 01595 /*@-compmempass@*/ 01596 int fsmStage(IOSM_t fsm, iosmFileStage stage) 01597 { 01598 #ifdef NOTUSED 01599 iosmFileStage prevStage = fsm->stage; 01600 const char * const prev = iosmFileStageString(prevStage); 01601 #endif 01602 const char * const cur = iosmFileStageString(stage); 01603 struct stat * st = &fsm->sb; 01604 struct stat * ost = &fsm->osb; 01605 int saveerrno = errno; 01606 int rc = fsm->rc; 01607 int i; 01608 01609 #define _fafilter(_a) \ 01610 (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \ 01611 ? iosmFileActionString(_a) : "") 01612 01613 if (stage & IOSM_DEAD) { 01614 /* do nothing */ 01615 } else if (stage & IOSM_INTERNAL) { 01616 if (fsm->debug && !(stage & IOSM_SYSCALL)) 01617 rpmlog(RPMLOG_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n", 01618 cur, 01619 (unsigned)st->st_mode, (int)st->st_nlink, 01620 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, 01621 (fsm->path ? fsm->path : ""), 01622 _fafilter(fsm->action)); 01623 } else { 01624 const char * apath = NULL; 01625 if (fsm->path) 01626 (void) urlPath(fsm->path, &apath); 01627 fsm->stage = stage; 01628 if (fsm->debug || !(stage & IOSM_VERBOSE)) 01629 rpmlog(RPMLOG_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n", 01630 cur, 01631 (unsigned)st->st_mode, (int)st->st_nlink, 01632 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, 01633 (apath ? apath + fsm->astriplen : ""), 01634 _fafilter(fsm->action)); 01635 } 01636 #undef _fafilter 01637 01638 switch (stage) { 01639 case IOSM_UNKNOWN: 01640 break; 01641 case IOSM_PKGINSTALL: 01642 while (1) { 01643 /* Clean fsm, free'ing memory. Read next archive header. */ 01644 rc = fsmUNSAFE(fsm, IOSM_INIT); 01645 01646 /* Exit on end-of-payload. */ 01647 if (rc == IOSMERR_HDR_TRAILER) { 01648 rc = 0; 01649 /*@loopbreak@*/ break; 01650 } 01651 01652 /* Exit on error. */ 01653 if (rc) { 01654 fsm->postpone = 1; 01655 (void) fsmNext(fsm, IOSM_UNDO); 01656 /*@loopbreak@*/ break; 01657 } 01658 01659 /* Extract file from archive. */ 01660 rc = fsmNext(fsm, IOSM_PROCESS); 01661 if (rc) { 01662 (void) fsmNext(fsm, IOSM_UNDO); 01663 /*@loopbreak@*/ break; 01664 } 01665 01666 /* Notify on success. */ 01667 (void) fsmNext(fsm, IOSM_NOTIFY); 01668 01669 rc = fsmNext(fsm, IOSM_FINI); 01670 if (rc) { 01671 /*@loopbreak@*/ break; 01672 } 01673 } 01674 break; 01675 case IOSM_PKGERASE: 01676 case IOSM_PKGCOMMIT: 01677 while (1) { 01678 /* Clean fsm, free'ing memory. */ 01679 rc = fsmUNSAFE(fsm, IOSM_INIT); 01680 01681 /* Exit on end-of-payload. */ 01682 if (rc == IOSMERR_HDR_TRAILER) { 01683 rc = 0; 01684 /*@loopbreak@*/ break; 01685 } 01686 01687 /* Rename/erase next item. */ 01688 if (fsmNext(fsm, IOSM_FINI)) 01689 /*@loopbreak@*/ break; 01690 } 01691 break; 01692 case IOSM_PKGBUILD: 01693 while (1) { 01694 01695 rc = fsmUNSAFE(fsm, IOSM_INIT); 01696 01697 /* Exit on end-of-payload. */ 01698 if (rc == IOSMERR_HDR_TRAILER) { 01699 rc = 0; 01700 /*@loopbreak@*/ break; 01701 } 01702 01703 /* Exit on error. */ 01704 if (rc) { 01705 fsm->postpone = 1; 01706 (void) fsmNext(fsm, IOSM_UNDO); 01707 /*@loopbreak@*/ break; 01708 } 01709 01710 /* Copy file into archive. */ 01711 rc = fsmNext(fsm, IOSM_PROCESS); 01712 if (rc) { 01713 (void) fsmNext(fsm, IOSM_UNDO); 01714 /*@loopbreak@*/ break; 01715 } 01716 01717 /* Notify on success. */ 01718 (void) fsmNext(fsm, IOSM_NOTIFY); 01719 01720 if (fsmNext(fsm, IOSM_FINI)) 01721 /*@loopbreak@*/ break; 01722 } 01723 01724 /* Flush partial sets of hard linked files. */ 01725 if (!(fsm->mapFlags & IOSM_ALL_HARDLINKS)) { 01726 int nlink, j; 01727 while ((fsm->li = fsm->links) != NULL) { 01728 fsm->links = fsm->li->next; 01729 fsm->li->next = NULL; 01730 01731 /* Re-calculate link count for archive header. */ 01732 for (j = -1, nlink = 0, i = 0; i < fsm->li->nlink; i++) { 01733 if (fsm->li->filex[i] < 0) 01734 /*@innercontinue@*/ continue; 01735 nlink++; 01736 if (j == -1) j = i; 01737 } 01738 /* XXX force the contents out as well. */ 01739 if (j != 0) { 01740 fsm->li->filex[0] = fsm->li->filex[j]; 01741 fsm->li->filex[j] = -1; 01742 } 01743 fsm->li->sb.st_nlink = nlink; 01744 01745 fsm->sb = fsm->li->sb; /* structure assignment */ 01746 fsm->osb = fsm->sb; /* structure assignment */ 01747 01748 if (!rc) rc = writeLinkedFile(fsm); 01749 01750 fsm->li = freeHardLink(fsm->li); 01751 } 01752 } 01753 01754 if (!rc) 01755 rc = fsmNext(fsm, IOSM_TRAILER); 01756 01757 break; 01758 case IOSM_CREATE: 01759 fsm->path = _free(fsm->path); 01760 fsm->lpath = _free(fsm->lpath); 01761 fsm->opath = _free(fsm->opath); 01762 fsm->dnlx = _free(fsm->dnlx); 01763 01764 fsm->ldn = _free(fsm->ldn); 01765 fsm->ldnalloc = fsm->ldnlen = 0; 01766 01767 fsm->rdsize = fsm->wrsize = 0; 01768 fsm->rdbuf = fsm->rdb = _free(fsm->rdb); 01769 fsm->wrbuf = fsm->wrb = _free(fsm->wrb); 01770 if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) { 01771 fsm->rdsize = 16 * BUFSIZ; 01772 fsm->rdbuf = fsm->rdb = xmalloc(fsm->rdsize); 01773 fsm->wrsize = 16 * BUFSIZ; 01774 fsm->wrbuf = fsm->wrb = xmalloc(fsm->wrsize); 01775 } 01776 01777 fsm->mkdirsdone = 0; 01778 fsm->ix = -1; 01779 fsm->links = NULL; 01780 fsm->li = NULL; 01781 errno = 0; /* XXX get rid of EBADF */ 01782 01783 /* Detect and create directories not explicitly in package. */ 01784 if (fsm->goal == IOSM_PKGINSTALL) { 01785 /*@-compdef@*/ 01786 rc = fsmNext(fsm, IOSM_MKDIRS); 01787 /*@=compdef@*/ 01788 if (!rc) fsm->mkdirsdone = 1; 01789 } 01790 01791 break; 01792 case IOSM_INIT: 01793 fsm->path = _free(fsm->path); 01794 fsm->lpath = _free(fsm->lpath); 01795 fsm->postpone = 0; 01796 fsm->diskchecked = fsm->exists = 0; 01797 fsm->subdir = NULL; 01798 fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL); 01799 fsm->action = FA_UNKNOWN; 01800 fsm->osuffix = NULL; 01801 fsm->nsuffix = NULL; 01802 01803 if (fsm->goal == IOSM_PKGINSTALL) { 01804 /* Read next header from payload, checking for end-of-payload. */ 01805 rc = fsmUNSAFE(fsm, IOSM_NEXT); 01806 } 01807 if (rc) break; 01808 01809 /* Identify mapping index. */ 01810 fsm->ix = ((fsm->goal == IOSM_PKGINSTALL) 01811 ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter)); 01812 01813 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_LIST)) { 01814 /* Detect end-of-loop and/or mapping error. */ 01815 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_EXTRACT)) { 01816 if (fsm->ix < 0) { 01817 if (fsm->goal == IOSM_PKGINSTALL) { 01818 #if 0 01819 rpmlog(RPMLOG_WARNING, 01820 _("archive file %s was not found in header file list\n"), 01821 fsm->path); 01822 #endif 01823 if (fsm->failedFile && *fsm->failedFile == NULL) 01824 *fsm->failedFile = xstrdup(fsm->path); 01825 rc = IOSMERR_UNMAPPED_FILE; 01826 } else { 01827 rc = IOSMERR_HDR_TRAILER; 01828 } 01829 break; 01830 } 01831 } 01832 01833 /* On non-install, mode must be known so that dirs don't get suffix. */ 01834 if (fsm->goal != IOSM_PKGINSTALL) { 01835 rpmfi fi = fsmGetFi(fsm); 01836 st->st_mode = fi->fmodes[fsm->ix]; 01837 } 01838 } 01839 01840 /* Generate file path. */ 01841 rc = fsmNext(fsm, IOSM_MAP); 01842 if (rc) break; 01843 01844 /* Perform lstat/stat for disk file. */ 01845 #ifdef NOTYET 01846 rc = fsmStat(fsm); 01847 #else 01848 if (fsm->path != NULL && 01849 !(fsm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode))) 01850 { 01851 rc = fsmUNSAFE(fsm, (!(fsm->mapFlags & IOSM_FOLLOW_SYMLINKS) 01852 ? IOSM_LSTAT : IOSM_STAT)); 01853 if (rc == IOSMERR_ENOENT) { 01854 errno = saveerrno; 01855 rc = 0; 01856 fsm->exists = 0; 01857 } else if (rc == 0) { 01858 fsm->exists = 1; 01859 } 01860 } else { 01861 /* Skip %ghost files on build. */ 01862 fsm->exists = 0; 01863 } 01864 #endif 01865 fsm->diskchecked = 1; 01866 if (rc) break; 01867 01868 /* On non-install, the disk file stat is what's remapped. */ 01869 if (fsm->goal != IOSM_PKGINSTALL) 01870 *st = *ost; /* structure assignment */ 01871 01872 /* Remap file perms, owner, and group. */ 01873 rc = fsmMapAttrs(fsm); 01874 if (rc) break; 01875 01876 fsm->postpone = iosmFileActionSkipped(fsm->action); 01877 if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) { 01878 /*@-evalorder@*/ /* FIX: saveHardLink can modify fsm */ 01879 if (S_ISREG(st->st_mode) && st->st_nlink > 1) 01880 fsm->postpone = saveHardLink(fsm); 01881 /*@=evalorder@*/ 01882 } 01883 if (fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_LIST) fsm->postpone = 1; 01884 break; 01885 case IOSM_PRE: 01886 break; 01887 case IOSM_MAP: 01888 rc = fsmMapPath(fsm); 01889 break; 01890 case IOSM_MKDIRS: 01891 rc = fsmMkdirs(fsm); 01892 break; 01893 case IOSM_RMDIRS: 01894 if (fsm->dnlx) 01895 rc = fsmRmdirs(fsm); 01896 break; 01897 case IOSM_PROCESS: 01898 if (fsm->postpone) { 01899 if (fsm->goal == IOSM_PKGINSTALL) { 01900 /* XXX Skip over file body, archive headers already done. */ 01901 if (S_ISREG(st->st_mode)) 01902 rc = fsmNext(fsm, IOSM_EAT); 01903 } 01904 break; 01905 } 01906 01907 if (fsm->goal == IOSM_PKGBUILD) { 01908 if (fsm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */ 01909 break; 01910 if (S_ISREG(st->st_mode) && st->st_nlink > 1) { 01911 struct hardLink_s * li, * prev; 01912 01913 if (!(fsm->mapFlags & IOSM_ALL_HARDLINKS)) break; 01914 rc = writeLinkedFile(fsm); 01915 if (rc) break; /* W2DO? */ 01916 01917 for (li = fsm->links, prev = NULL; li; prev = li, li = li->next) 01918 if (li == fsm->li) 01919 /*@loopbreak@*/ break; 01920 01921 if (prev == NULL) 01922 fsm->links = fsm->li->next; 01923 else 01924 prev->next = fsm->li->next; 01925 fsm->li->next = NULL; 01926 fsm->li = freeHardLink(fsm->li); 01927 } else { 01928 rc = writeFile(fsm, 1); 01929 } 01930 break; 01931 } 01932 01933 if (fsm->goal != IOSM_PKGINSTALL) 01934 break; 01935 01936 if (S_ISREG(st->st_mode) && fsm->lpath != NULL) { 01937 const char * opath = fsm->opath; 01938 char * t = xmalloc(strlen(fsm->lpath+1) + strlen(fsm->suffix) + 1); 01939 (void) stpcpy(t, fsm->lpath+1); 01940 fsm->opath = t; 01941 /* XXX link(fsm->opath, fsm->path) */ 01942 rc = fsmNext(fsm, IOSM_LINK); 01943 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) { 01944 *fsm->failedFile = xstrdup(fsm->path); 01945 } 01946 fsm->opath = _free(fsm->opath); 01947 fsm->opath = opath; 01948 break; /* XXX so that delayed hard links get skipped. */ 01949 } 01950 if (S_ISREG(st->st_mode)) { 01951 const char * path = fsm->path; 01952 if (fsm->osuffix) 01953 fsm->path = fsmFsPath(fsm, st, NULL, NULL); 01954 rc = fsmUNSAFE(fsm, IOSM_VERIFY); 01955 01956 if (rc == 0 && fsm->osuffix) { 01957 const char * opath = fsm->opath; 01958 fsm->opath = fsm->path; 01959 fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); 01960 rc = fsmNext(fsm, IOSM_RENAME); 01961 if (!rc) 01962 rpmlog(RPMLOG_WARNING, 01963 _("%s saved as %s\n"), 01964 (fsm->opath ? fsm->opath : ""), 01965 (fsm->path ? fsm->path : "")); 01966 fsm->path = _free(fsm->path); 01967 fsm->opath = opath; 01968 } 01969 01970 /*@-dependenttrans@*/ 01971 fsm->path = path; 01972 /*@=dependenttrans@*/ 01973 if (!(rc == IOSMERR_ENOENT)) return rc; 01974 rc = extractRegular(fsm); 01975 } else if (S_ISDIR(st->st_mode)) { 01976 mode_t st_mode = st->st_mode; 01977 rc = fsmUNSAFE(fsm, IOSM_VERIFY); 01978 if (rc == IOSMERR_ENOENT) { 01979 st->st_mode &= ~07777; /* XXX abuse st->st_mode */ 01980 st->st_mode |= 00700; 01981 rc = fsmNext(fsm, IOSM_MKDIR); 01982 st->st_mode = st_mode; /* XXX restore st->st_mode */ 01983 } 01984 } else if (S_ISLNK(st->st_mode)) { 01985 assert(fsm->lpath != NULL); 01986 /*@=dependenttrans@*/ 01987 rc = fsmUNSAFE(fsm, IOSM_VERIFY); 01988 if (rc == IOSMERR_ENOENT) 01989 rc = fsmNext(fsm, IOSM_SYMLINK); 01990 } else if (S_ISFIFO(st->st_mode)) { 01991 mode_t st_mode = st->st_mode; 01992 /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */ 01993 rc = fsmUNSAFE(fsm, IOSM_VERIFY); 01994 if (rc == IOSMERR_ENOENT) { 01995 st->st_mode = 0000; /* XXX abuse st->st_mode */ 01996 rc = fsmNext(fsm, IOSM_MKFIFO); 01997 st->st_mode = st_mode; /* XXX restore st->st_mode */ 01998 } 01999 } else if (S_ISCHR(st->st_mode) || 02000 S_ISBLK(st->st_mode) || 02001 /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/) 02002 { 02003 rc = fsmUNSAFE(fsm, IOSM_VERIFY); 02004 if (rc == IOSMERR_ENOENT) 02005 rc = fsmNext(fsm, IOSM_MKNOD); 02006 } else { 02007 /* XXX Repackaged payloads may be missing files. */ 02008 if (fsm->repackaged) 02009 break; 02010 02011 /* XXX Special case /dev/log, which shouldn't be packaged anyways */ 02012 if (!IS_DEV_LOG(fsm->path)) 02013 rc = IOSMERR_UNKNOWN_FILETYPE; 02014 } 02015 if (S_ISREG(st->st_mode) && st->st_nlink > 1) { 02016 fsm->li->createdPath = fsm->li->linkIndex; 02017 rc = fsmMakeLinks(fsm); 02018 } 02019 break; 02020 case IOSM_POST: 02021 break; 02022 case IOSM_MKLINKS: 02023 rc = fsmMakeLinks(fsm); 02024 break; 02025 case IOSM_NOTIFY: /* XXX move from fsm to psm -> tsm */ 02026 if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) { 02027 rpmts ts = fsmGetTs(fsm); 02028 rpmfi fi = fsmGetFi(fsm); 02029 void * ptr; 02030 rpmuint64_t archivePos = fdGetCpioPos(fsm->cfd); 02031 if (archivePos > fi->archivePos) { 02032 fi->archivePos = (unsigned long long) archivePos; 02033 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, 02034 fi->archivePos, fi->archiveSize); 02035 } 02036 } 02037 break; 02038 case IOSM_UNDO: 02039 if (fsm->postpone) 02040 break; 02041 if (fsm->goal == IOSM_PKGINSTALL) { 02042 /* XXX only erase if temp fn w suffix is in use */ 02043 if (fsm->sufbuf[0] != '\0') 02044 (void) fsmNext(fsm, 02045 (S_ISDIR(st->st_mode) ? IOSM_RMDIR : IOSM_UNLINK)); 02046 02047 #ifdef NOTYET /* XXX remove only dirs just created, not all. */ 02048 if (fsm->dnlx) 02049 (void) fsmNext(fsm, IOSM_RMDIRS); 02050 #endif 02051 errno = saveerrno; 02052 } 02053 if (fsm->failedFile && *fsm->failedFile == NULL) 02054 *fsm->failedFile = xstrdup(fsm->path); 02055 break; 02056 case IOSM_FINI: 02057 if (!fsm->postpone && fsm->commit) { 02058 if (fsm->goal == IOSM_PKGINSTALL) 02059 rc = ((S_ISREG(st->st_mode) && st->st_nlink > 1) 02060 ? fsmCommitLinks(fsm) : fsmNext(fsm, IOSM_COMMIT)); 02061 if (fsm->goal == IOSM_PKGCOMMIT) 02062 rc = fsmNext(fsm, IOSM_COMMIT); 02063 if (fsm->goal == IOSM_PKGERASE) 02064 rc = fsmNext(fsm, IOSM_COMMIT); 02065 } 02066 fsm->path = _free(fsm->path); 02067 fsm->lpath = _free(fsm->lpath); 02068 fsm->opath = _free(fsm->opath); 02069 memset(st, 0, sizeof(*st)); 02070 memset(ost, 0, sizeof(*ost)); 02071 break; 02072 case IOSM_COMMIT: 02073 /* Rename pre-existing modified or unmanaged file. */ 02074 if (fsm->osuffix && fsm->diskchecked && 02075 (fsm->exists || (fsm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode)))) 02076 { 02077 const char * opath = fsm->opath; 02078 const char * path = fsm->path; 02079 fsm->opath = fsmFsPath(fsm, st, NULL, NULL); 02080 fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); 02081 rc = fsmNext(fsm, IOSM_RENAME); 02082 if (!rc) { 02083 rpmlog(RPMLOG_WARNING, _("%s saved as %s\n"), 02084 (fsm->opath ? fsm->opath : ""), 02085 (fsm->path ? fsm->path : "")); 02086 } 02087 fsm->path = _free(fsm->path); 02088 fsm->path = path; 02089 fsm->opath = _free(fsm->opath); 02090 fsm->opath = opath; 02091 } 02092 02093 /* Remove erased files. */ 02094 if (fsm->goal == IOSM_PKGERASE) { 02095 if (fsm->action == FA_ERASE) { 02096 rpmfi fi = fsmGetFi(fsm); 02097 if (S_ISDIR(st->st_mode)) { 02098 rc = fsmNext(fsm, IOSM_RMDIR); 02099 if (!rc) break; 02100 switch (rc) { 02101 case IOSMERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */ 02102 case IOSMERR_ENOTEMPTY: 02103 /* XXX make sure that build side permits %missingok on directories. */ 02104 if (fsm->fflags & RPMFILE_MISSINGOK) 02105 /*@innerbreak@*/ break; 02106 02107 /* XXX common error message. */ 02108 rpmlog( 02109 (fsm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), 02110 _("%s rmdir of %s failed: Directory not empty\n"), 02111 rpmfiTypeString(fi), fsm->path); 02112 /*@innerbreak@*/ break; 02113 default: 02114 rpmlog( 02115 (fsm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), 02116 _("%s rmdir of %s failed: %s\n"), 02117 rpmfiTypeString(fi), fsm->path, strerror(errno)); 02118 /*@innerbreak@*/ break; 02119 } 02120 } else { 02121 rc = fsmNext(fsm, IOSM_UNLINK); 02122 if (!rc) break; 02123 switch (rc) { 02124 case IOSMERR_ENOENT: 02125 if (fsm->fflags & RPMFILE_MISSINGOK) 02126 /*@innerbreak@*/ break; 02127 /*@fallthrough@*/ 02128 default: 02129 rpmlog( 02130 (fsm->strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), 02131 _(" %s: unlink of %s failed: %s\n"), 02132 rpmfiTypeString(fi), fsm->path, strerror(errno)); 02133 /*@innerbreak@*/ break; 02134 } 02135 } 02136 } 02137 /* XXX Failure to remove is not (yet) cause for failure. */ 02138 if (!fsm->strict_erasures) rc = 0; 02139 break; 02140 } 02141 02142 /* XXX Special case /dev/log, which shouldn't be packaged anyways */ 02143 if (!(fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_EXTRACT)) { 02144 if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(fsm->path)) { 02145 /* Rename temporary to final file name. */ 02146 if (!S_ISDIR(st->st_mode) && 02147 (fsm->subdir || fsm->suffix || fsm->nsuffix)) 02148 { 02149 fsm->opath = fsm->path; 02150 fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix); 02151 rc = fsmNext(fsm, IOSM_RENAME); 02152 if (rc) 02153 (void) Unlink(fsm->opath); 02154 else if (fsm->nsuffix) { 02155 const char * opath = fsmFsPath(fsm, st, NULL, NULL); 02156 rpmlog(RPMLOG_WARNING, _("%s created as %s\n"), 02157 (opath ? opath : ""), 02158 (fsm->path ? fsm->path : "")); 02159 opath = _free(opath); 02160 } 02161 fsm->opath = _free(fsm->opath); 02162 } 02163 /* 02164 * Set file security context (if not disabled). 02165 */ 02166 if (!rc && !getuid()) { 02167 rc = fsmMapFContext(fsm); 02168 if (!rc) 02169 rc = fsmNext(fsm, IOSM_LSETFCON); 02170 /*@-dependenttrans -observertrans @*/ /* FIX: use the SELinux free wrapper */ 02171 fsm->fcontext = _free(fsm->fcontext); 02172 /*@=dependenttrans =observertrans @*/ 02173 } 02174 if (S_ISLNK(st->st_mode)) { 02175 if (!rc && !getuid()) 02176 rc = fsmNext(fsm, IOSM_LCHOWN); 02177 } else { 02178 if (!rc && !getuid()) 02179 rc = fsmNext(fsm, IOSM_CHOWN); 02180 if (!rc) 02181 rc = fsmNext(fsm, IOSM_CHMOD); 02182 if (!rc) { 02183 time_t mtime = st->st_mtime; 02184 rpmfi fi = fsmGetFi(fsm); 02185 if (fi->fmtimes) 02186 st->st_mtime = fi->fmtimes[fsm->ix]; 02187 rc = fsmNext(fsm, IOSM_UTIME); 02188 st->st_mtime = mtime; 02189 } 02190 } 02191 } 02192 } 02193 02194 /* Notify on success. */ 02195 if (!rc) rc = fsmNext(fsm, IOSM_NOTIFY); 02196 else if (fsm->failedFile && *fsm->failedFile == NULL) { 02197 *fsm->failedFile = fsm->path; 02198 fsm->path = NULL; 02199 } 02200 break; 02201 case IOSM_DESTROY: 02202 fsm->path = _free(fsm->path); 02203 02204 /* Check for hard links missing from payload. */ 02205 while ((fsm->li = fsm->links) != NULL) { 02206 fsm->links = fsm->li->next; 02207 fsm->li->next = NULL; 02208 if (fsm->goal == IOSM_PKGINSTALL && 02209 fsm->commit && fsm->li->linksLeft) 02210 { 02211 for (i = 0 ; i < fsm->li->linksLeft; i++) { 02212 if (fsm->li->filex[i] < 0) 02213 /*@innercontinue@*/ continue; 02214 rc = IOSMERR_MISSING_HARDLINK; 02215 if (fsm->failedFile && *fsm->failedFile == NULL) { 02216 fsm->ix = fsm->li->filex[i]; 02217 if (!fsmNext(fsm, IOSM_MAP)) { 02218 *fsm->failedFile = fsm->path; 02219 fsm->path = NULL; 02220 } 02221 } 02222 /*@loopbreak@*/ break; 02223 } 02224 } 02225 if (fsm->goal == IOSM_PKGBUILD && 02226 (fsm->mapFlags & IOSM_ALL_HARDLINKS)) 02227 { 02228 rc = IOSMERR_MISSING_HARDLINK; 02229 } 02230 fsm->li = freeHardLink(fsm->li); 02231 } 02232 fsm->ldn = _free(fsm->ldn); 02233 fsm->ldnalloc = fsm->ldnlen = 0; 02234 fsm->rdbuf = fsm->rdb = _free(fsm->rdb); 02235 fsm->wrbuf = fsm->wrb = _free(fsm->wrb); 02236 break; 02237 case IOSM_VERIFY: 02238 if (fsm->diskchecked && !fsm->exists) { 02239 rc = IOSMERR_ENOENT; 02240 break; 02241 } 02242 if (S_ISREG(st->st_mode)) { 02243 char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE")); 02244 (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE"); 02245 /* 02246 * XXX HP-UX (and other os'es) don't permit unlink on busy 02247 * XXX files. 02248 */ 02249 fsm->opath = fsm->path; 02250 fsm->path = path; 02251 rc = fsmNext(fsm, IOSM_RENAME); 02252 if (!rc) 02253 (void) fsmNext(fsm, IOSM_UNLINK); 02254 else 02255 rc = IOSMERR_UNLINK_FAILED; 02256 fsm->path = fsm->opath; 02257 fsm->opath = NULL; 02258 return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */ 02259 /*@notreached@*/ break; 02260 } else if (S_ISDIR(st->st_mode)) { 02261 if (S_ISDIR(ost->st_mode)) return 0; 02262 if (S_ISLNK(ost->st_mode)) { 02263 rc = fsmUNSAFE(fsm, IOSM_STAT); 02264 if (rc == IOSMERR_ENOENT) rc = 0; 02265 if (rc) break; 02266 errno = saveerrno; 02267 if (S_ISDIR(ost->st_mode)) return 0; 02268 } 02269 } else if (S_ISLNK(st->st_mode)) { 02270 if (S_ISLNK(ost->st_mode)) { 02271 /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ 02272 rc = fsmUNSAFE(fsm, IOSM_READLINK); 02273 errno = saveerrno; 02274 if (rc) break; 02275 if (!strcmp(fsm->lpath, fsm->rdbuf)) return 0; 02276 } 02277 } else if (S_ISFIFO(st->st_mode)) { 02278 if (S_ISFIFO(ost->st_mode)) return 0; 02279 } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { 02280 if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) && 02281 (ost->st_rdev == st->st_rdev)) return 0; 02282 } else if (S_ISSOCK(st->st_mode)) { 02283 if (S_ISSOCK(ost->st_mode)) return 0; 02284 } 02285 /* XXX shouldn't do this with commit/undo. */ 02286 rc = 0; 02287 if (fsm->stage == IOSM_PROCESS) rc = fsmNext(fsm, IOSM_UNLINK); 02288 if (rc == 0) rc = IOSMERR_ENOENT; 02289 return (rc ? rc : IOSMERR_ENOENT); /* XXX HACK */ 02290 /*@notreached@*/ break; 02291 02292 case IOSM_UNLINK: 02293 { const char * fn = fsm->path; 02294 uint8_t * b = (uint8_t *)""; 02295 size_t blen = 0; 02296 uint8_t * d = NULL; 02297 size_t dlen = 0; 02298 uint32_t dalgo = 0; 02299 FD_t fd = NULL; 02300 struct stat sb; 02301 mode_t mode; 02302 sb.st_mode = 0; 02303 if (!Lstat(fn, &sb) && S_ISREG(sb.st_mode)) { 02304 fd = Fopen(fn, "r.fdio"); 02305 blen = sb.st_size; 02306 b = mmap(NULL, blen, PROT_READ, MAP_SHARED, Fileno(fd), 0); 02307 } 02308 mode = sb.st_mode; 02309 rc = rpmlioUnlink(rpmtsGetRdb(fsmGetTs(fsm)), fn, mode, b, blen, d, dlen, dalgo); 02310 if (fd != NULL) { 02311 /*@-observertrans@*/ /* FIX: b should be initialized to NULL, not "" */ 02312 (void)munmap(b, blen); 02313 /*@=observertrans@*/ 02314 (void) Fclose(fd); 02315 fd = NULL; 02316 } 02317 } goto iosmcall; 02318 case IOSM_RENAME: 02319 { const char * ofn = fsm->opath; 02320 const char * fn = fsm->path; 02321 uint8_t * b = NULL; 02322 size_t blen = 0; 02323 uint8_t * d = NULL; 02324 size_t dlen = 0; 02325 uint32_t dalgo = 0; 02326 FD_t fd = NULL; 02327 struct stat sb; 02328 mode_t mode; 02329 sb.st_mode = 0; 02330 if (!Lstat(fn, &sb) && S_ISREG(sb.st_mode)) { 02331 fd = Fopen(fn, "r.fdio"); 02332 blen = sb.st_size; 02333 b = mmap(NULL, blen, PROT_READ, MAP_SHARED, Fileno(fd), 0); 02334 } 02335 mode = sb.st_mode; 02336 rc = rpmlioRename(rpmtsGetRdb(fsmGetTs(fsm)), ofn, fn, mode, b, blen, d, dlen, dalgo); 02337 if (fd != NULL) { 02338 (void)munmap(b, blen); 02339 (void) Fclose(fd); 02340 fd = NULL; 02341 } 02342 } goto iosmcall; 02343 case IOSM_MKDIR: 02344 rc = rpmlioMkdir(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode); 02345 goto iosmcall; 02346 case IOSM_RMDIR: 02347 rc = rpmlioRmdir(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode); 02348 goto iosmcall; 02349 case IOSM_LSETFCON: 02350 /* Log iff lsetfilecon() will actually be called. */ 02351 if (fsm->fcontext && *fsm->fcontext 02352 && strcmp(fsm->fcontext, "<<none>>")) 02353 rc = rpmlioLsetfilecon(rpmtsGetRdb(fsmGetTs(fsm)), 02354 fsm->path, fsm->fcontext); 02355 goto iosmcall; 02356 case IOSM_CHOWN: 02357 rc = rpmlioChown(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_uid, st->st_gid); 02358 goto iosmcall; 02359 case IOSM_LCHOWN: 02360 rc = rpmlioLchown(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_uid, st->st_gid); 02361 goto iosmcall; 02362 case IOSM_CHMOD: 02363 rc = rpmlioChmod(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode); 02364 goto iosmcall; 02365 case IOSM_UTIME: 02366 rc = rpmlioUtime(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mtime, st->st_mtime); 02367 goto iosmcall; 02368 case IOSM_SYMLINK: 02369 rc = rpmlioSymlink(rpmtsGetRdb(fsmGetTs(fsm)), fsm->lpath, fsm->path); 02370 goto iosmcall; 02371 case IOSM_LINK: 02372 rc = rpmlioLink(rpmtsGetRdb(fsmGetTs(fsm)), fsm->opath, fsm->path); 02373 goto iosmcall; 02374 case IOSM_MKFIFO: 02375 rc = rpmlioMkfifo(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode); 02376 goto iosmcall; 02377 case IOSM_MKNOD: 02378 rc = rpmlioMknod(rpmtsGetRdb(fsmGetTs(fsm)), fsm->path, st->st_mode, st->st_rdev); 02379 goto iosmcall; 02380 case IOSM_LSTAT: 02381 case IOSM_STAT: 02382 case IOSM_READLINK: 02383 case IOSM_CHROOT: 02384 iosmcall: 02385 rc = iosmStage(fsm, stage); 02386 break; 02387 02388 case IOSM_NEXT: 02389 case IOSM_EAT: 02390 case IOSM_POS: 02391 case IOSM_PAD: 02392 case IOSM_TRAILER: 02393 case IOSM_HREAD: 02394 case IOSM_HWRITE: 02395 case IOSM_DREAD: 02396 case IOSM_DWRITE: 02397 rc = iosmStage(fsm, stage); 02398 break; 02399 02400 case IOSM_ROPEN: 02401 case IOSM_READ: 02402 case IOSM_RCLOSE: 02403 rc = iosmStage(fsm, stage); 02404 break; 02405 case IOSM_WOPEN: 02406 case IOSM_WRITE: 02407 case IOSM_WCLOSE: 02408 rc = iosmStage(fsm, stage); 02409 break; 02410 02411 default: 02412 break; 02413 } 02414 02415 if (!(stage & IOSM_INTERNAL)) { 02416 fsm->rc = (rc == IOSMERR_HDR_TRAILER ? 0 : rc); 02417 } 02418 return rc; 02419 } 02420 /*@=compmempass@*/