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