00001
00006 #include "system.h"
00007
00008 #include <rpmio_internal.h>
00009 #include <rpmlib.h>
00010
00011 #include "cpio.h"
00012
00013 #include "fsm.h"
00014
00015 #include "rpmerr.h"
00016
00017 #define _RPMFI_INTERNAL
00018 #include "rpmfi.h"
00019 #include "rpmte.h"
00020 #include "rpmts.h"
00021 #include "rpmsq.h"
00022
00023 #include "ugid.h"
00024
00025 #include "debug.h"
00026
00027
00028
00029
00030
00031
00032
00033 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
00034
00035 #define _FSM_DEBUG 0
00036
00037 int _fsm_debug = _FSM_DEBUG;
00038
00039
00040
00041 int _fsm_threads = 0;
00042
00043
00044
00045
00046
00047 int strict_erasures = 0;
00048
00049
00050 rpmts fsmGetTs(const FSM_t fsm) {
00051 const FSMI_t iter = fsm->iter;
00052
00053 return (iter ? iter->ts : NULL);
00054
00055 }
00056
00057 rpmfi fsmGetFi(const FSM_t fsm)
00058 {
00059 const FSMI_t iter = fsm->iter;
00060
00061 return (iter ? iter->fi : NULL);
00062
00063 }
00064
00065 #define SUFFIX_RPMORIG ".rpmorig"
00066 #define SUFFIX_RPMSAVE ".rpmsave"
00067 #define SUFFIX_RPMNEW ".rpmnew"
00068
00077 static
00078 const char * fsmFsPath( const FSM_t fsm,
00079 const struct stat * st,
00080 const char * subdir,
00081 const char * suffix)
00082
00083
00084 {
00085 const char * s = NULL;
00086
00087 if (fsm) {
00088 int nb;
00089 char * t;
00090 nb = strlen(fsm->dirName) +
00091 (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : 0) : 0) +
00092 (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : 0) : 0) +
00093 strlen(fsm->baseName) + 1;
00094
00095 s = t = xmalloc(nb);
00096 t = stpcpy(t, fsm->dirName);
00097 if (st && !S_ISDIR(st->st_mode))
00098 if (subdir) t = stpcpy(t, subdir);
00099 t = stpcpy(t, fsm->baseName);
00100 if (st && !S_ISDIR(st->st_mode))
00101 if (suffix) t = stpcpy(t, suffix);
00102
00103 }
00104 return s;
00105 }
00106
00112 static void * mapFreeIterator( void * p)
00113
00114
00115 {
00116 FSMI_t iter = p;
00117 if (iter) {
00118
00119 iter->ts = rpmtsFree(iter->ts);
00120
00121 iter->fi = rpmfiUnlink(iter->fi, "mapIterator");
00122 }
00123 return _free(p);
00124 }
00125
00132 static void *
00133 mapInitIterator(rpmts ts, rpmfi fi)
00134
00135 {
00136 FSMI_t iter = NULL;
00137
00138 iter = xcalloc(1, sizeof(*iter));
00139 iter->ts = rpmtsLink(ts, "mapIterator");
00140 iter->fi = rpmfiLink(fi, "mapIterator");
00141 iter->reverse = (rpmteType(fi->te) == TR_REMOVED && fi->action != FA_COPYOUT);
00142 iter->i = (iter->reverse ? (fi->fc - 1) : 0);
00143 iter->isave = iter->i;
00144 return iter;
00145 }
00146
00152 static int mapNextIterator( void * a)
00153
00154 {
00155 FSMI_t iter = a;
00156 int i = -1;
00157
00158 if (iter) {
00159 const rpmfi fi = iter->fi;
00160 if (iter->reverse) {
00161 if (iter->i >= 0) i = iter->i--;
00162 } else {
00163 if (iter->i < fi->fc) i = iter->i++;
00164 }
00165 iter->isave = i;
00166 }
00167 return i;
00168 }
00169
00172
00173 static int cpioStrCmp(const void * a, const void * b)
00174
00175 {
00176 const char * afn = *(const char **)a;
00177 const char * bfn = *(const char **)b;
00178
00179
00180 #ifdef VERY_OLD_BUGGY_RPM_PACKAGES
00181 if (strchr(afn, '/') == NULL)
00182 bfn = strrchr(bfn, '/') + 1;
00183 #endif
00184
00185
00186 if (afn[0] == '.' && afn[1] == '/') afn += 2;
00187 if (bfn[0] == '.' && bfn[1] == '/') bfn += 2;
00188
00189
00190 if (afn[0] == '/') afn += 1;
00191 if (bfn[0] == '/') bfn += 1;
00192
00193 return strcmp(afn, bfn);
00194 }
00195
00196
00203
00204 static int mapFind( FSMI_t iter, const char * fsmPath)
00205
00206 {
00207 int ix = -1;
00208
00209 if (iter) {
00210 const rpmfi fi = iter->fi;
00211 if (fi && fi->fc > 0 && fi->apath && fsmPath && *fsmPath) {
00212 const char ** p = NULL;
00213
00214
00215 if (fi->apath != NULL)
00216 p = bsearch(&fsmPath, fi->apath, fi->fc, sizeof(fsmPath),
00217 cpioStrCmp);
00218
00219 if (p) {
00220 iter->i = p - fi->apath;
00221 ix = mapNextIterator(iter);
00222 }
00223 }
00224 }
00225 return ix;
00226 }
00227
00228
00232 typedef struct dnli_s {
00233 rpmfi fi;
00234
00235 char * active;
00236 int reverse;
00237 int isave;
00238 int i;
00239 } * DNLI_t;
00240
00246 static void * dnlFreeIterator( const void * a)
00247
00248 {
00249 if (a) {
00250 DNLI_t dnli = (void *)a;
00251 if (dnli->active) free(dnli->active);
00252 }
00253 return _free(a);
00254 }
00255
00258 static inline int dnlCount( const DNLI_t dnli)
00259
00260 {
00261 return (dnli ? dnli->fi->dc : 0);
00262 }
00263
00266 static inline int dnlIndex( const DNLI_t dnli)
00267
00268 {
00269 return (dnli ? dnli->isave : -1);
00270 }
00271
00278
00279
00280 static
00281 void * dnlInitIterator( const FSM_t fsm,
00282 int reverse)
00283
00284
00285 {
00286 rpmfi fi = fsmGetFi(fsm);
00287 DNLI_t dnli;
00288 int i, j;
00289
00290 if (fi == NULL)
00291 return NULL;
00292 dnli = xcalloc(1, sizeof(*dnli));
00293 dnli->fi = fi;
00294 dnli->reverse = reverse;
00295
00296 dnli->i = (reverse ? fi->dc : 0);
00297
00298
00299 if (fi->dc) {
00300 dnli->active = xcalloc(fi->dc, sizeof(*dnli->active));
00301
00302
00303
00304 for (i = 0; i < fi->fc; i++)
00305 if (!XFA_SKIPPING(fi->actions[i])) dnli->active[fi->dil[i]] = 1;
00306
00307
00308
00309 for (i = 0; i < fi->fc; i++) {
00310 int dil, dnlen, bnlen;
00311
00312 if (!S_ISDIR(fi->fmodes[i]))
00313 continue;
00314
00315 dil = fi->dil[i];
00316 dnlen = strlen(fi->dnl[dil]);
00317 bnlen = strlen(fi->bnl[i]);
00318
00319 for (j = 0; j < fi->dc; j++) {
00320 const char * dnl;
00321 int jlen;
00322
00323 if (!dnli->active[j] || j == dil)
00324 continue;
00325 dnl = fi->dnl[j];
00326 jlen = strlen(dnl);
00327 if (jlen != (dnlen+bnlen+1))
00328 continue;
00329 if (strncmp(dnl, fi->dnl[dil], dnlen))
00330 continue;
00331 if (strncmp(dnl+dnlen, fi->bnl[i], bnlen))
00332 continue;
00333 if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0')
00334 continue;
00335
00336
00337 dnli->active[j] = 0;
00338
00339 break;
00340 }
00341 }
00342
00343
00344 if (!reverse) {
00345 j = 0;
00346 for (i = 0; i < fi->dc; i++) {
00347 if (!dnli->active[i]) continue;
00348 if (j == 0) {
00349 j = 1;
00350 rpmMessage(RPMMESS_DEBUG,
00351 _("========== Directories not explicitly included in package:\n"));
00352 }
00353 rpmMessage(RPMMESS_DEBUG, _("%10d %s\n"), i, fi->dnl[i]);
00354 }
00355 if (j)
00356 rpmMessage(RPMMESS_DEBUG, "==========\n");
00357 }
00358 }
00359 return dnli;
00360 }
00361
00362
00363
00369
00370 static
00371 const char * dnlNextIterator( DNLI_t dnli)
00372
00373 {
00374 const char * dn = NULL;
00375
00376 if (dnli) {
00377 rpmfi fi = dnli->fi;
00378 int i = -1;
00379
00380 if (dnli->active)
00381 do {
00382 i = (!dnli->reverse ? dnli->i++ : --dnli->i);
00383 } while (i >= 0 && i < fi->dc && !dnli->active[i]);
00384
00385 if (i >= 0 && i < fi->dc)
00386 dn = fi->dnl[i];
00387 else
00388 i = -1;
00389 dnli->isave = i;
00390 }
00391 return dn;
00392 }
00393
00394
00395 #if NOTYET
00396 static void * fsmThread(void * arg)
00397
00398
00399 {
00400 FSM_t fsm = arg;
00401
00402 return ((void *) fsmStage(fsm, fsm->nstage));
00403
00404 }
00405
00406 int fsmNext(FSM_t fsm, fileStage nstage)
00407
00408
00409 {
00410 fsm->nstage = nstage;
00411 if (_fsm_threads)
00412 return rpmsqJoin( rpmsqThread(fsmThread, fsm) );
00413 return fsmStage(fsm, fsm->nstage);
00414 }
00415 #endif
00416
00422
00423 static int saveHardLink( FSM_t fsm)
00424
00425
00426
00427
00428
00429 {
00430 struct stat * st = &fsm->sb;
00431 int rc = 0;
00432 int ix = -1;
00433 int j;
00434
00435
00436
00437 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
00438 if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev)
00439 break;
00440 }
00441
00442
00443
00444
00445
00446 if (fsm->li == NULL) {
00447 fsm->li = xcalloc(1, sizeof(*fsm->li));
00448 fsm->li->next = NULL;
00449 fsm->li->sb = *st;
00450 fsm->li->nlink = st->st_nlink;
00451 fsm->li->linkIndex = fsm->ix;
00452 fsm->li->createdPath = -1;
00453
00454 fsm->li->filex = xcalloc(st->st_nlink, sizeof(fsm->li->filex[0]));
00455 memset(fsm->li->filex, -1, (st->st_nlink * sizeof(fsm->li->filex[0])));
00456 fsm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*fsm->li->nsuffix));
00457
00458 if (fsm->goal == FSM_PKGBUILD)
00459 fsm->li->linksLeft = st->st_nlink;
00460 if (fsm->goal == FSM_PKGINSTALL)
00461 fsm->li->linksLeft = 0;
00462
00463
00464 fsm->li->next = fsm->links;
00465
00466 fsm->links = fsm->li;
00467 }
00468
00469
00470
00471 if (fsm->goal == FSM_PKGBUILD) --fsm->li->linksLeft;
00472
00473 fsm->li->filex[fsm->li->linksLeft] = fsm->ix;
00474
00475 fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix;
00476
00477
00478 if (fsm->goal == FSM_PKGINSTALL) fsm->li->linksLeft++;
00479
00480 if (fsm->goal == FSM_PKGBUILD)
00481 return (fsm->li->linksLeft > 0);
00482
00483 if (fsm->goal != FSM_PKGINSTALL)
00484 return 0;
00485
00486 if (!(st->st_size || fsm->li->linksLeft == st->st_nlink))
00487 return 1;
00488
00489
00490 { rpmfi fi = fsmGetFi(fsm);
00491
00492 for (j = fsm->li->linksLeft - 1; j >= 0; j--) {
00493 ix = fsm->li->filex[j];
00494 if (ix < 0 || XFA_SKIPPING(fi->actions[ix]))
00495 continue;
00496 break;
00497 }
00498 }
00499
00500
00501 if (ix < 0 || j < 0)
00502 return 1;
00503
00504
00505 fsm->li->linkIndex = j;
00506 fsm->path = _free(fsm->path);
00507 fsm->ix = ix;
00508 rc = fsmStage(fsm, FSM_MAP);
00509 return rc;
00510 }
00511
00512
00518 static void * freeHardLink( struct hardLink_s * li)
00519
00520 {
00521 if (li) {
00522 li->nsuffix = _free(li->nsuffix);
00523 li->filex = _free(li->filex);
00524 }
00525 return _free(li);
00526 }
00527
00528 FSM_t newFSM(void)
00529 {
00530 FSM_t fsm = xcalloc(1, sizeof(*fsm));
00531 return fsm;
00532 }
00533
00534 FSM_t freeFSM(FSM_t fsm)
00535 {
00536 if (fsm) {
00537 fsm->path = _free(fsm->path);
00538
00539 while ((fsm->li = fsm->links) != NULL) {
00540 fsm->links = fsm->li->next;
00541 fsm->li->next = NULL;
00542 fsm->li = freeHardLink(fsm->li);
00543 }
00544
00545 fsm->dnlx = _free(fsm->dnlx);
00546 fsm->ldn = _free(fsm->ldn);
00547 fsm->iter = mapFreeIterator(fsm->iter);
00548 }
00549 return _free(fsm);
00550 }
00551
00552 int fsmSetup(FSM_t fsm, fileStage goal,
00553 const rpmts ts, const rpmfi fi, FD_t cfd,
00554 unsigned int * archiveSize, const char ** failedFile)
00555 {
00556 size_t pos = 0;
00557 int rc, ec = 0;
00558
00559 fsm->goal = goal;
00560 if (cfd != NULL) {
00561 fsm->cfd = fdLink(cfd, "persist (fsm)");
00562 pos = fdGetCpioPos(fsm->cfd);
00563 fdSetCpioPos(fsm->cfd, 0);
00564 }
00565 fsm->iter = mapInitIterator(ts, fi);
00566
00567 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
00568 void * ptr;
00569 fi->archivePos = 0;
00570 ptr = rpmtsNotify(ts, fi->te,
00571 RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize);
00572 }
00573
00574
00575
00576 fsm->archiveSize = archiveSize;
00577 if (fsm->archiveSize)
00578 *fsm->archiveSize = 0;
00579 fsm->failedFile = failedFile;
00580 if (fsm->failedFile)
00581 *fsm->failedFile = NULL;
00582
00583
00584
00585 memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf));
00586 if (fsm->goal == FSM_PKGINSTALL) {
00587 if (ts && rpmtsGetTid(ts) > 0)
00588 sprintf(fsm->sufbuf, ";%08x", (unsigned)rpmtsGetTid(ts));
00589 }
00590
00591 ec = fsm->rc = 0;
00592 rc = fsmStage(fsm, FSM_CREATE);
00593 if (rc && !ec) ec = rc;
00594
00595 rc = fsmStage(fsm, fsm->goal);
00596 if (rc && !ec) ec = rc;
00597
00598
00599 if (fsm->archiveSize && ec == 0)
00600 *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos);
00601
00602
00603
00604 return ec;
00605
00606 }
00607
00608 int fsmTeardown(FSM_t fsm)
00609 {
00610 int rc = fsm->rc;
00611
00612 if (!rc)
00613 rc = fsmStage(fsm, FSM_DESTROY);
00614
00615 fsm->iter = mapFreeIterator(fsm->iter);
00616 if (fsm->cfd != NULL) {
00617 fsm->cfd = fdFree(fsm->cfd, "persist (fsm)");
00618 fsm->cfd = NULL;
00619 }
00620 fsm->failedFile = NULL;
00621 return rc;
00622 }
00623
00624 int fsmMapPath(FSM_t fsm)
00625 {
00626 rpmfi fi = fsmGetFi(fsm);
00627 int rc = 0;
00628 int i;
00629
00630 fsm->osuffix = NULL;
00631 fsm->nsuffix = NULL;
00632 fsm->astriplen = 0;
00633 fsm->action = FA_UNKNOWN;
00634 fsm->mapFlags = 0;
00635
00636 i = fsm->ix;
00637 if (fi && i >= 0 && i < fi->fc) {
00638
00639
00640 fsm->astriplen = fi->astriplen;
00641 fsm->action = (fi->actions ? fi->actions[i] : fi->action);
00642 fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags);
00643 fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags);
00644
00645
00646 fsm->dirName = fi->dnl[fi->dil[i]];
00647 fsm->baseName = fi->bnl[i];
00648
00649
00650
00651 switch (fsm->action) {
00652 case FA_SKIP:
00653 break;
00654 case FA_UNKNOWN:
00655 break;
00656
00657 case FA_COPYOUT:
00658 break;
00659 case FA_COPYIN:
00660 case FA_CREATE:
00661 assert(rpmteType(fi->te) == TR_ADDED);
00662 break;
00663
00664 case FA_SKIPNSTATE:
00665 if (fi->fstates && rpmteType(fi->te) == TR_ADDED)
00666 fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED;
00667 break;
00668
00669 case FA_SKIPNETSHARED:
00670 if (fi->fstates && rpmteType(fi->te) == TR_ADDED)
00671 fi->fstates[i] = RPMFILE_STATE_NETSHARED;
00672 break;
00673
00674 case FA_SKIPCOLOR:
00675 if (fi->fstates && rpmteType(fi->te) == TR_ADDED)
00676 fi->fstates[i] = RPMFILE_STATE_WRONGCOLOR;
00677 break;
00678
00679 case FA_BACKUP:
00680 if (!(fsm->fflags & RPMFILE_GHOST))
00681 switch (rpmteType(fi->te)) {
00682 case TR_ADDED:
00683 fsm->osuffix = SUFFIX_RPMORIG;
00684 break;
00685 case TR_REMOVED:
00686 fsm->osuffix = SUFFIX_RPMSAVE;
00687 break;
00688 }
00689 break;
00690
00691 case FA_ALTNAME:
00692 assert(rpmteType(fi->te) == TR_ADDED);
00693 if (!(fsm->fflags & RPMFILE_GHOST))
00694 fsm->nsuffix = SUFFIX_RPMNEW;
00695 break;
00696
00697 case FA_SAVE:
00698 assert(rpmteType(fi->te) == TR_ADDED);
00699 if (!(fsm->fflags & RPMFILE_GHOST))
00700 fsm->osuffix = SUFFIX_RPMSAVE;
00701 break;
00702 case FA_ERASE:
00703 #if 0
00704 assert(rpmteType(fi->te) == TR_REMOVED);
00705 #endif
00706
00707
00708
00709
00710 break;
00711 default:
00712 break;
00713 }
00714
00715
00716 if ((fsm->mapFlags & CPIO_MAP_PATH) || fsm->nsuffix) {
00717 const struct stat * st = &fsm->sb;
00718 fsm->path = _free(fsm->path);
00719 fsm->path = fsmFsPath(fsm, st, fsm->subdir,
00720 (fsm->suffix ? fsm->suffix : fsm->nsuffix));
00721 }
00722 }
00723 return rc;
00724 }
00725
00726 int fsmMapAttrs(FSM_t fsm)
00727 {
00728 struct stat * st = &fsm->sb;
00729 rpmfi fi = fsmGetFi(fsm);
00730 int i = fsm->ix;
00731
00732 if (fi && i >= 0 && i < fi->fc) {
00733 mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms);
00734 mode_t finalMode = (fi->fmodes ? fi->fmodes[i] : perms);
00735 dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0);
00736 int_32 finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0);
00737 uid_t uid = fi->uid;
00738 gid_t gid = fi->gid;
00739
00740 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
00741 if (fsm->goal == FSM_PKGINSTALL)
00742 rpmMessage(RPMMESS_WARNING,
00743 _("user %s does not exist - using root\n"), fi->fuser[i]);
00744 uid = 0;
00745 finalMode &= ~S_ISUID;
00746 }
00747
00748 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
00749 if (fsm->goal == FSM_PKGINSTALL)
00750 rpmMessage(RPMMESS_WARNING,
00751 _("group %s does not exist - using root\n"), fi->fgroup[i]);
00752 gid = 0;
00753 finalMode &= ~S_ISGID;
00754 }
00755
00756 if (fsm->mapFlags & CPIO_MAP_MODE)
00757 st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT);
00758 if (fsm->mapFlags & CPIO_MAP_TYPE) {
00759 st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT);
00760 if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00761 && st->st_nlink == 0)
00762 st->st_nlink = 1;
00763 st->st_rdev = finalRdev;
00764 st->st_mtime = finalMtime;
00765 }
00766 if (fsm->mapFlags & CPIO_MAP_UID)
00767 st->st_uid = uid;
00768 if (fsm->mapFlags & CPIO_MAP_GID)
00769 st->st_gid = gid;
00770
00771 { rpmts ts = fsmGetTs(fsm);
00772
00773 if (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOMD5)) {
00774 fsm->fmd5sum = (fi->fmd5s ? fi->fmd5s[i] : NULL);
00775 fsm->md5sum = (fi->md5s ? (fi->md5s + (16 * i)) : NULL);
00776 } else {
00777 fsm->fmd5sum = NULL;
00778 fsm->md5sum = NULL;
00779 }
00780 }
00781
00782 }
00783 return 0;
00784 }
00785
00791
00792 static int expandRegular( FSM_t fsm)
00793
00794
00795
00796 {
00797 const struct stat * st = &fsm->sb;
00798 int left = st->st_size;
00799 int rc = 0;
00800
00801 rc = fsmStage(fsm, FSM_WOPEN);
00802 if (rc)
00803 goto exit;
00804
00805 if (st->st_size > 0 && (fsm->fmd5sum != NULL || fsm->md5sum != NULL))
00806 fdInitDigest(fsm->wfd, PGPHASHALGO_MD5, 0);
00807
00808 while (left) {
00809
00810 fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
00811 rc = fsmStage(fsm, FSM_DREAD);
00812 if (rc)
00813 goto exit;
00814
00815 rc = fsmStage(fsm, FSM_WRITE);
00816 if (rc)
00817 goto exit;
00818
00819 left -= fsm->wrnb;
00820
00821
00822 if (!rc && left)
00823 (void) fsmStage(fsm, FSM_NOTIFY);
00824 }
00825
00826 if (st->st_size > 0 && (fsm->fmd5sum || fsm->md5sum)) {
00827 void * md5sum = NULL;
00828 int asAscii = (fsm->md5sum == NULL ? 1 : 0);
00829
00830 (void) Fflush(fsm->wfd);
00831 fdFiniDigest(fsm->wfd, PGPHASHALGO_MD5, &md5sum, NULL, asAscii);
00832
00833 if (md5sum == NULL) {
00834 rc = CPIOERR_MD5SUM_MISMATCH;
00835 goto exit;
00836 }
00837
00838 if (fsm->md5sum != NULL) {
00839 if (memcmp(md5sum, fsm->md5sum, 16))
00840 rc = CPIOERR_MD5SUM_MISMATCH;
00841 } else {
00842 if (strcmp(md5sum, fsm->fmd5sum))
00843 rc = CPIOERR_MD5SUM_MISMATCH;
00844 }
00845 md5sum = _free(md5sum);
00846 }
00847
00848 exit:
00849 (void) fsmStage(fsm, FSM_WCLOSE);
00850 return rc;
00851 }
00852
00853
00860
00861 static int writeFile( FSM_t fsm, int writeData)
00862
00863
00864
00865 {
00866 const char * path = fsm->path;
00867 const char * opath = fsm->opath;
00868 struct stat * st = &fsm->sb;
00869 struct stat * ost = &fsm->osb;
00870 char * symbuf = NULL;
00871 int left;
00872 int xx;
00873 int rc;
00874
00875 st->st_size = (writeData ? ost->st_size : 0);
00876
00877
00878 if (S_ISDIR(st->st_mode)) {
00879 st->st_size = 0;
00880 } else if (S_ISLNK(st->st_mode)) {
00881
00882
00883
00884
00885
00886 rc = fsmStage(fsm, FSM_READLINK);
00887 if (rc) goto exit;
00888 st->st_size = fsm->rdnb;
00889 symbuf = alloca_strdup(fsm->rdbuf);
00890 }
00891
00892
00893 if (fsm->mapFlags & CPIO_MAP_ABSOLUTE) {
00894
00895 int nb = strlen(fsm->dirName) + strlen(fsm->baseName) + sizeof(".");
00896 char * t = alloca(nb);
00897 *t = '\0';
00898 fsm->path = t;
00899 if (fsm->mapFlags & CPIO_MAP_ADDDOT)
00900 *t++ = '.';
00901 t = stpcpy( stpcpy(t, fsm->dirName), fsm->baseName);
00902
00903 } else if (fsm->mapFlags & CPIO_MAP_PATH) {
00904 rpmfi fi = fsmGetFi(fsm);
00905 fsm->path =
00906 (fi->apath ? fi->apath[fsm->ix] + fi->striplen : fi->bnl[fsm->ix]);
00907 }
00908
00909 rc = fsmStage(fsm, FSM_HWRITE);
00910 fsm->path = path;
00911 if (rc) goto exit;
00912
00913 if (writeData && S_ISREG(st->st_mode)) {
00914 #if HAVE_MMAP
00915 char * rdbuf = NULL;
00916 void * mapped = (void *)-1;
00917 size_t nmapped;
00918 #endif
00919
00920 rc = fsmStage(fsm, FSM_ROPEN);
00921 if (rc) goto exit;
00922
00923
00924 #if HAVE_MMAP
00925 nmapped = 0;
00926 mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0);
00927 if (mapped != (void *)-1) {
00928 rdbuf = fsm->rdbuf;
00929 fsm->rdbuf = (char *) mapped;
00930 fsm->rdlen = nmapped = st->st_size;
00931 #if defined(MADV_DONTNEED)
00932 xx = madvise(mapped, nmapped, MADV_DONTNEED);
00933 #endif
00934 }
00935 #endif
00936
00937 left = st->st_size;
00938
00939 while (left) {
00940 #if HAVE_MMAP
00941 if (mapped != (void *)-1) {
00942 fsm->rdnb = nmapped;
00943 } else
00944 #endif
00945 {
00946 fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left),
00947 rc = fsmStage(fsm, FSM_READ);
00948 if (rc) goto exit;
00949 }
00950
00951
00952 rc = fsmStage(fsm, FSM_DWRITE);
00953 if (rc) goto exit;
00954
00955 left -= fsm->wrnb;
00956 }
00957
00958 #if HAVE_MMAP
00959
00960 if (mapped != (void *)-1) {
00961 xx = msync(mapped, nmapped, MS_ASYNC);
00962 #if defined(MADV_DONTNEED)
00963 xx = madvise(mapped, nmapped, MADV_DONTNEED);
00964 #endif
00965
00966 xx = munmap(mapped, nmapped);
00967
00968 fsm->rdbuf = rdbuf;
00969 }
00970
00971 #endif
00972
00973 } else if (writeData && S_ISLNK(st->st_mode)) {
00974
00975
00976 strcpy(fsm->rdbuf, symbuf);
00977
00978 fsm->rdnb = strlen(symbuf);
00979 rc = fsmStage(fsm, FSM_DWRITE);
00980 if (rc) goto exit;
00981 }
00982
00983 rc = fsmStage(fsm, FSM_PAD);
00984 if (rc) goto exit;
00985
00986 rc = 0;
00987
00988 exit:
00989 if (fsm->rfd != NULL)
00990 (void) fsmStage(fsm, FSM_RCLOSE);
00991
00992 fsm->opath = opath;
00993 fsm->path = path;
00994
00995 return rc;
00996 }
00997
00998
01004 static int writeLinkedFile( FSM_t fsm)
01005
01006
01007
01008 {
01009 const char * path = fsm->path;
01010 const char * nsuffix = fsm->nsuffix;
01011 int iterIndex = fsm->ix;
01012 int ec = 0;
01013 int rc;
01014 int i;
01015
01016 fsm->path = NULL;
01017 fsm->nsuffix = NULL;
01018 fsm->ix = -1;
01019
01020
01021
01022 for (i = fsm->li->nlink - 1; i >= 0; i--) {
01023
01024 if (fsm->li->filex[i] < 0) continue;
01025
01026 fsm->ix = fsm->li->filex[i];
01027
01028 rc = fsmStage(fsm, FSM_MAP);
01029
01030
01031
01032 rc = writeFile(fsm, (i == 0));
01033 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
01034 ec = rc;
01035 *fsm->failedFile = xstrdup(fsm->path);
01036 }
01037
01038 fsm->path = _free(fsm->path);
01039 fsm->li->filex[i] = -1;
01040 }
01041
01042
01043
01044 fsm->ix = iterIndex;
01045 fsm->nsuffix = nsuffix;
01046 fsm->path = path;
01047 return ec;
01048 }
01049
01055
01056
01057 static int fsmMakeLinks( FSM_t fsm)
01058
01059
01060
01061 {
01062 const char * path = fsm->path;
01063 const char * opath = fsm->opath;
01064 const char * nsuffix = fsm->nsuffix;
01065 int iterIndex = fsm->ix;
01066 int ec = 0;
01067 int rc;
01068 int i;
01069
01070 fsm->path = NULL;
01071 fsm->opath = NULL;
01072 fsm->nsuffix = NULL;
01073 fsm->ix = -1;
01074
01075 fsm->ix = fsm->li->filex[fsm->li->createdPath];
01076 rc = fsmStage(fsm, FSM_MAP);
01077 fsm->opath = fsm->path;
01078 fsm->path = NULL;
01079
01080 for (i = 0; i < fsm->li->nlink; i++) {
01081 if (fsm->li->filex[i] < 0) continue;
01082 if (fsm->li->createdPath == i) continue;
01083
01084 fsm->ix = fsm->li->filex[i];
01085 fsm->path = _free(fsm->path);
01086 rc = fsmStage(fsm, FSM_MAP);
01087 if (XFA_SKIPPING(fsm->action)) continue;
01088
01089 rc = fsmStage(fsm, FSM_VERIFY);
01090 if (!rc) continue;
01091 if (!(rc == CPIOERR_ENOENT)) break;
01092
01093
01094 rc = fsmStage(fsm, FSM_LINK);
01095 if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
01096 ec = rc;
01097
01098 *fsm->failedFile = xstrdup(fsm->path);
01099
01100 }
01101
01102 fsm->li->linksLeft--;
01103 }
01104
01105 fsm->path = _free(fsm->path);
01106 fsm->opath = _free(fsm->opath);
01107
01108 fsm->ix = iterIndex;
01109 fsm->nsuffix = nsuffix;
01110 fsm->path = path;
01111 fsm->opath = opath;
01112 return ec;
01113 }
01114
01115
01116
01122
01123 static int fsmCommitLinks( FSM_t fsm)
01124
01125
01126
01127
01128 {
01129 const char * path = fsm->path;
01130 const char * nsuffix = fsm->nsuffix;
01131 int iterIndex = fsm->ix;
01132 struct stat * st = &fsm->sb;
01133 int rc = 0;
01134 int i;
01135
01136 fsm->path = NULL;
01137 fsm->nsuffix = NULL;
01138 fsm->ix = -1;
01139
01140
01141 for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) {
01142 if (fsm->li->sb.st_ino == st->st_ino && fsm->li->sb.st_dev == st->st_dev)
01143 break;
01144 }
01145
01146
01147
01148 for (i = 0; i < fsm->li->nlink; i++) {
01149 if (fsm->li->filex[i] < 0) continue;
01150 fsm->ix = fsm->li->filex[i];
01151 rc = fsmStage(fsm, FSM_MAP);
01152 if (!XFA_SKIPPING(fsm->action))
01153 rc = fsmStage(fsm, FSM_COMMIT);
01154 fsm->path = _free(fsm->path);
01155 fsm->li->filex[i] = -1;
01156 }
01157
01158
01159 fsm->ix = iterIndex;
01160 fsm->nsuffix = nsuffix;
01161 fsm->path = path;
01162 return rc;
01163 }
01164
01165
01171 static int fsmRmdirs( FSM_t fsm)
01172
01173
01174
01175 {
01176 const char * path = fsm->path;
01177 void * dnli = dnlInitIterator(fsm, 1);
01178 char * dn = fsm->rdbuf;
01179 int dc = dnlCount(dnli);
01180 int rc = 0;
01181
01182 fsm->path = NULL;
01183
01184 dn[0] = '\0';
01185
01186 if (fsm->ldn != NULL && fsm->dnlx != NULL)
01187 while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
01188 int dnlen = strlen(fsm->path);
01189 char * te;
01190
01191 dc = dnlIndex(dnli);
01192 if (fsm->dnlx[dc] < 1 || fsm->dnlx[dc] >= dnlen)
01193 continue;
01194
01195
01196 te = stpcpy(dn, fsm->path) - 1;
01197 fsm->path = dn;
01198
01199
01200
01201 do {
01202 if (*te == '/') {
01203 *te = '\0';
01204
01205 rc = fsmStage(fsm, FSM_RMDIR);
01206
01207 *te = '/';
01208 }
01209 if (rc)
01210 break;
01211 te--;
01212 } while ((te - fsm->path) > fsm->dnlx[dc]);
01213
01214 }
01215
01216 dnli = dnlFreeIterator(dnli);
01217
01218
01219 fsm->path = path;
01220 return rc;
01221 }
01222
01228 static int fsmMkdirs( FSM_t fsm)
01229
01230
01231
01232
01233
01234 {
01235 struct stat * st = &fsm->sb;
01236 struct stat * ost = &fsm->osb;
01237 const char * path = fsm->path;
01238 mode_t st_mode = st->st_mode;
01239 void * dnli = dnlInitIterator(fsm, 0);
01240 char * dn = fsm->rdbuf;
01241 int dc = dnlCount(dnli);
01242 int rc = 0;
01243 int i;
01244
01245 fsm->path = NULL;
01246
01247
01248 dn[0] = '\0';
01249 fsm->dnlx = (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL);
01250
01251 if (fsm->dnlx != NULL)
01252 while ((fsm->path = dnlNextIterator(dnli)) != NULL) {
01253 int dnlen = strlen(fsm->path);
01254 char * te;
01255
01256 dc = dnlIndex(dnli);
01257 if (dc < 0) continue;
01258 fsm->dnlx[dc] = dnlen;
01259 if (dnlen <= 1)
01260 continue;
01261
01262
01263 if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn))
01264 continue;
01265
01266
01267
01268 (void) stpcpy(dn, fsm->path);
01269 fsm->path = dn;
01270
01271
01272 for (i = 1, te = dn + 1; *te != '\0'; te++, i++) {
01273 if (*te != '/')
01274 continue;
01275
01276 *te = '\0';
01277
01278
01279
01280 if (i < fsm->ldnlen &&
01281 (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') &&
01282 !strncmp(fsm->path, fsm->ldn, i))
01283 {
01284 *te = '/';
01285
01286 fsm->dnlx[dc] = (te - dn);
01287 continue;
01288 }
01289
01290
01291
01292 rc = fsmStage(fsm, FSM_LSTAT);
01293 *te = '/';
01294
01295
01296 if (rc == 0 && S_ISDIR(ost->st_mode)) {
01297
01298 fsm->dnlx[dc] = (te - dn);
01299 } else if (rc == CPIOERR_ENOENT) {
01300 rpmfi fi = fsmGetFi(fsm);
01301 *te = '\0';
01302 st->st_mode = S_IFDIR | (fi->dperms & 07777);
01303 rc = fsmStage(fsm, FSM_MKDIR);
01304 if (!rc)
01305 rpmMessage(RPMMESS_DEBUG,
01306 _("%s directory created with perms %04o.\n"),
01307 fsm->path, (unsigned)(st->st_mode & 07777));
01308 *te = '/';
01309 }
01310 if (rc)
01311 break;
01312 }
01313 if (rc) break;
01314
01315
01316
01317 if (fsm->ldnalloc < (dnlen + 1)) {
01318 fsm->ldnalloc = dnlen + 100;
01319 fsm->ldn = xrealloc(fsm->ldn, fsm->ldnalloc);
01320 }
01321 if (fsm->ldn != NULL) {
01322 strcpy(fsm->ldn, fsm->path);
01323 fsm->ldnlen = dnlen;
01324 }
01325
01326 }
01327
01328 dnli = dnlFreeIterator(dnli);
01329
01330
01331 fsm->path = path;
01332 st->st_mode = st_mode;
01333
01334 return rc;
01335
01336 }
01337
01338 #ifdef NOTYET
01339
01344 static int fsmStat( FSM_t fsm)
01345
01346
01347 {
01348 int rc = 0;
01349
01350 if (fsm->path != NULL) {
01351 int saveernno = errno;
01352 rc = fsmStage(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS)
01353 ? FSM_LSTAT : FSM_STAT));
01354 if (rc == CPIOERR_ENOENT) {
01355 errno = saveerrno;
01356 rc = 0;
01357 fsm->exists = 0;
01358 } else if (rc == 0) {
01359 fsm->exists = 1;
01360 }
01361 } else {
01362
01363 fsm->exists = 0;
01364 }
01365 return rc;
01366 }
01367 #endif
01368
01369 #define IS_DEV_LOG(_x) \
01370 ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \
01371 !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \
01372 ((_x)[sizeof("/dev/log")-1] == '\0' || \
01373 (_x)[sizeof("/dev/log")-1] == ';'))
01374
01375
01376
01377 int fsmStage(FSM_t fsm, fileStage stage)
01378 {
01379 #ifdef UNUSED
01380 fileStage prevStage = fsm->stage;
01381 const char * const prev = fileStageString(prevStage);
01382 #endif
01383 static int modulo = 4;
01384 const char * const cur = fileStageString(stage);
01385 struct stat * st = &fsm->sb;
01386 struct stat * ost = &fsm->osb;
01387 int saveerrno = errno;
01388 int rc = fsm->rc;
01389 size_t left;
01390 int i;
01391
01392 #define _fafilter(_a) \
01393 (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \
01394 ? fileActionString(_a) : "")
01395
01396 if (stage & FSM_DEAD) {
01397
01398 } else if (stage & FSM_INTERNAL) {
01399 if (_fsm_debug && !(stage & FSM_SYSCALL))
01400 rpmMessage(RPMMESS_DEBUG, " %8s %06o%3d (%4d,%4d)%10d %s %s\n",
01401 cur,
01402 (unsigned)st->st_mode, (int)st->st_nlink,
01403 (int)st->st_uid, (int)st->st_gid, (int)st->st_size,
01404 (fsm->path ? fsm->path : ""),
01405 _fafilter(fsm->action));
01406 } else {
01407 fsm->stage = stage;
01408 if (_fsm_debug || !(stage & FSM_VERBOSE))
01409 rpmMessage(RPMMESS_DEBUG, "%-8s %06o%3d (%4d,%4d)%10d %s %s\n",
01410 cur,
01411 (unsigned)st->st_mode, (int)st->st_nlink,
01412 (int)st->st_uid, (int)st->st_gid, (int)st->st_size,
01413 (fsm->path ? fsm->path + fsm->astriplen : ""),
01414 _fafilter(fsm->action));
01415 }
01416 #undef _fafilter
01417
01418
01419 switch (stage) {
01420 case FSM_UNKNOWN:
01421 break;
01422 case FSM_PKGINSTALL:
01423 while (1) {
01424
01425 rc = fsmStage(fsm, FSM_INIT);
01426
01427
01428 if (rc == CPIOERR_HDR_TRAILER) {
01429 rc = 0;
01430 break;
01431 }
01432
01433
01434 if (rc) {
01435 fsm->postpone = 1;
01436 (void) fsmStage(fsm, FSM_UNDO);
01437 break;
01438 }
01439
01440
01441 rc = fsmStage(fsm, FSM_PROCESS);
01442 if (rc) {
01443 (void) fsmStage(fsm, FSM_UNDO);
01444 break;
01445 }
01446
01447
01448 (void) fsmStage(fsm, FSM_NOTIFY);
01449
01450 rc = fsmStage(fsm, FSM_FINI);
01451 if (rc) {
01452 break;
01453 }
01454 }
01455 break;
01456 case FSM_PKGERASE:
01457 case FSM_PKGCOMMIT:
01458 while (1) {
01459
01460 rc = fsmStage(fsm, FSM_INIT);
01461
01462
01463 if (rc == CPIOERR_HDR_TRAILER) {
01464 rc = 0;
01465 break;
01466 }
01467
01468
01469 if (fsmStage(fsm, FSM_FINI))
01470 break;
01471 }
01472 break;
01473 case FSM_PKGBUILD:
01474 while (1) {
01475
01476 rc = fsmStage(fsm, FSM_INIT);
01477
01478
01479 if (rc == CPIOERR_HDR_TRAILER) {
01480 rc = 0;
01481 break;
01482 }
01483
01484
01485 if (rc) {
01486 fsm->postpone = 1;
01487 (void) fsmStage(fsm, FSM_UNDO);
01488 break;
01489 }
01490
01491
01492 rc = fsmStage(fsm, FSM_PROCESS);
01493 if (rc) {
01494 (void) fsmStage(fsm, FSM_UNDO);
01495 break;
01496 }
01497
01498
01499 (void) fsmStage(fsm, FSM_NOTIFY);
01500
01501 if (fsmStage(fsm, FSM_FINI))
01502 break;
01503 }
01504
01505
01506 if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) {
01507 int nlink, j;
01508 while ((fsm->li = fsm->links) != NULL) {
01509 fsm->links = fsm->li->next;
01510 fsm->li->next = NULL;
01511
01512
01513 for (j = -1, nlink = 0, i = 0; i < fsm->li->nlink; i++) {
01514 if (fsm->li->filex[i] < 0)
01515 continue;
01516 nlink++;
01517 if (j == -1) j = i;
01518 }
01519
01520
01521 if (j != 0) {
01522 fsm->li->filex[0] = fsm->li->filex[j];
01523 fsm->li->filex[j] = -1;
01524 }
01525
01526 fsm->li->sb.st_nlink = nlink;
01527
01528 fsm->sb = fsm->li->sb;
01529 fsm->osb = fsm->sb;
01530
01531 if (!rc) rc = writeLinkedFile(fsm);
01532
01533 fsm->li = freeHardLink(fsm->li);
01534 }
01535 }
01536
01537 if (!rc)
01538 rc = fsmStage(fsm, FSM_TRAILER);
01539
01540 break;
01541 case FSM_CREATE:
01542 { rpmts ts = fsmGetTs(fsm);
01543 #define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT)
01544 fsm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) &&
01545 fsm->goal != FSM_PKGCOMMIT) ? 0 : 1);
01546 #undef _tsmask
01547 }
01548 fsm->path = _free(fsm->path);
01549 fsm->opath = _free(fsm->opath);
01550 fsm->dnlx = _free(fsm->dnlx);
01551
01552 fsm->ldn = _free(fsm->ldn);
01553 fsm->ldnalloc = fsm->ldnlen = 0;
01554
01555 fsm->rdsize = fsm->wrsize = 0;
01556 fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
01557 fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
01558 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
01559 fsm->rdsize = 8 * BUFSIZ;
01560 fsm->rdbuf = fsm->rdb = xmalloc(fsm->rdsize);
01561 fsm->wrsize = 8 * BUFSIZ;
01562 fsm->wrbuf = fsm->wrb = xmalloc(fsm->wrsize);
01563 }
01564
01565 fsm->mkdirsdone = 0;
01566 fsm->ix = -1;
01567 fsm->links = NULL;
01568 fsm->li = NULL;
01569 errno = 0;
01570
01571
01572 if (fsm->goal == FSM_PKGINSTALL) {
01573
01574 rc = fsmStage(fsm, FSM_MKDIRS);
01575
01576 if (!rc) fsm->mkdirsdone = 1;
01577 }
01578
01579 break;
01580 case FSM_INIT:
01581 fsm->path = _free(fsm->path);
01582 fsm->postpone = 0;
01583 fsm->diskchecked = fsm->exists = 0;
01584 fsm->subdir = NULL;
01585 fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL);
01586 fsm->action = FA_UNKNOWN;
01587 fsm->osuffix = NULL;
01588 fsm->nsuffix = NULL;
01589
01590 if (fsm->goal == FSM_PKGINSTALL) {
01591
01592 rc = fsmStage(fsm, FSM_NEXT);
01593 }
01594 if (rc) break;
01595
01596
01597 fsm->ix = ((fsm->goal == FSM_PKGINSTALL)
01598 ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter));
01599
01600
01601 if (fsm->ix < 0) {
01602 if (fsm->goal == FSM_PKGINSTALL) {
01603 #if 0
01604 rpmMessage(RPMMESS_WARNING,
01605 _("archive file %s was not found in header file list\n"),
01606 fsm->path);
01607 #endif
01608
01609 if (fsm->failedFile && *fsm->failedFile == NULL)
01610 *fsm->failedFile = xstrdup(fsm->path);
01611
01612 rc = CPIOERR_UNMAPPED_FILE;
01613 } else {
01614 rc = CPIOERR_HDR_TRAILER;
01615 }
01616 break;
01617 }
01618
01619
01620 if (fsm->goal != FSM_PKGINSTALL) {
01621 rpmfi fi = fsmGetFi(fsm);
01622 st->st_mode = fi->fmodes[fsm->ix];
01623 }
01624
01625
01626 rc = fsmStage(fsm, FSM_MAP);
01627 if (rc) break;
01628
01629
01630 #ifdef NOTYET
01631 rc = fsmStat(fsm);
01632 #else
01633 if (fsm->path != NULL &&
01634 !(fsm->goal == FSM_PKGINSTALL && S_ISREG(st->st_mode)))
01635 {
01636 rc = fsmStage(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS)
01637 ? FSM_LSTAT : FSM_STAT));
01638 if (rc == CPIOERR_ENOENT) {
01639 errno = saveerrno;
01640 rc = 0;
01641 fsm->exists = 0;
01642 } else if (rc == 0) {
01643 fsm->exists = 1;
01644 }
01645 } else {
01646
01647 fsm->exists = 0;
01648 }
01649 #endif
01650 fsm->diskchecked = 1;
01651 if (rc) break;
01652
01653
01654
01655 if (fsm->goal != FSM_PKGINSTALL)
01656 *st = *ost;
01657
01658
01659
01660 rc = fsmMapAttrs(fsm);
01661 if (rc) break;
01662
01663 fsm->postpone = XFA_SKIPPING(fsm->action);
01664 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
01665
01666 if (!S_ISDIR(st->st_mode) && st->st_nlink > 1)
01667 fsm->postpone = saveHardLink(fsm);
01668
01669 }
01670 break;
01671 case FSM_PRE:
01672 break;
01673 case FSM_MAP:
01674 rc = fsmMapPath(fsm);
01675 break;
01676 case FSM_MKDIRS:
01677 rc = fsmMkdirs(fsm);
01678 break;
01679 case FSM_RMDIRS:
01680 if (fsm->dnlx)
01681 rc = fsmRmdirs(fsm);
01682 break;
01683 case FSM_PROCESS:
01684 if (fsm->postpone) {
01685 if (fsm->goal == FSM_PKGINSTALL)
01686 rc = fsmStage(fsm, FSM_EAT);
01687 break;
01688 }
01689
01690 if (fsm->goal == FSM_PKGBUILD) {
01691 if (fsm->fflags & RPMFILE_GHOST)
01692 break;
01693 if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
01694 struct hardLink_s * li, * prev;
01695
01696 if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
01697 rc = writeLinkedFile(fsm);
01698 if (rc) break;
01699
01700 for (li = fsm->links, prev = NULL; li; prev = li, li = li->next)
01701 if (li == fsm->li)
01702 break;
01703
01704 if (prev == NULL)
01705 fsm->links = fsm->li->next;
01706 else
01707 prev->next = fsm->li->next;
01708 fsm->li->next = NULL;
01709 fsm->li = freeHardLink(fsm->li);
01710 } else {
01711 rc = writeFile(fsm, 1);
01712 }
01713 break;
01714 }
01715
01716 if (fsm->goal != FSM_PKGINSTALL)
01717 break;
01718
01719 if (S_ISREG(st->st_mode)) {
01720 const char * path = fsm->path;
01721 if (fsm->osuffix)
01722 fsm->path = fsmFsPath(fsm, st, NULL, NULL);
01723 rc = fsmStage(fsm, FSM_VERIFY);
01724
01725 if (rc == 0 && fsm->osuffix) {
01726 const char * opath = fsm->opath;
01727 fsm->opath = fsm->path;
01728 fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
01729 rc = fsmStage(fsm, FSM_RENAME);
01730 if (!rc)
01731 rpmMessage(RPMMESS_WARNING,
01732 _("%s saved as %s\n"),
01733 (fsm->opath ? fsm->opath : ""),
01734 (fsm->path ? fsm->path : ""));
01735 fsm->path = _free(fsm->path);
01736 fsm->opath = opath;
01737 }
01738
01739
01740 fsm->path = path;
01741
01742 if (!(rc == CPIOERR_ENOENT)) return rc;
01743 rc = expandRegular(fsm);
01744 } else if (S_ISDIR(st->st_mode)) {
01745 mode_t st_mode = st->st_mode;
01746 rc = fsmStage(fsm, FSM_VERIFY);
01747 if (rc == CPIOERR_ENOENT) {
01748 st->st_mode &= ~07777;
01749 st->st_mode |= 00700;
01750 rc = fsmStage(fsm, FSM_MKDIR);
01751 st->st_mode = st_mode;
01752 }
01753 } else if (S_ISLNK(st->st_mode)) {
01754 const char * opath = fsm->opath;
01755
01756 if ((st->st_size + 1) > fsm->rdsize) {
01757 rc = CPIOERR_HDR_SIZE;
01758 break;
01759 }
01760
01761 fsm->wrlen = st->st_size;
01762 rc = fsmStage(fsm, FSM_DREAD);
01763 if (!rc && fsm->rdnb != fsm->wrlen)
01764 rc = CPIOERR_READ_FAILED;
01765 if (rc) break;
01766
01767
01768 fsm->wrbuf[st->st_size] = '\0';
01769
01770
01771
01772 fsm->opath = fsm->wrbuf;
01773
01774 rc = fsmStage(fsm, FSM_VERIFY);
01775 if (rc == CPIOERR_ENOENT)
01776 rc = fsmStage(fsm, FSM_SYMLINK);
01777 fsm->opath = opath;
01778 } else if (S_ISFIFO(st->st_mode)) {
01779 mode_t st_mode = st->st_mode;
01780
01781 rc = fsmStage(fsm, FSM_VERIFY);
01782 if (rc == CPIOERR_ENOENT) {
01783 st->st_mode = 0000;
01784 rc = fsmStage(fsm, FSM_MKFIFO);
01785 st->st_mode = st_mode;
01786 }
01787 } else if (S_ISCHR(st->st_mode) ||
01788 S_ISBLK(st->st_mode) ||
01789 S_ISSOCK(st->st_mode) )
01790 {
01791 rc = fsmStage(fsm, FSM_VERIFY);
01792 if (rc == CPIOERR_ENOENT)
01793 rc = fsmStage(fsm, FSM_MKNOD);
01794 } else {
01795
01796 if (!IS_DEV_LOG(fsm->path))
01797 rc = CPIOERR_UNKNOWN_FILETYPE;
01798 }
01799 if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
01800 fsm->li->createdPath = fsm->li->linkIndex;
01801 rc = fsmMakeLinks(fsm);
01802 }
01803 break;
01804 case FSM_POST:
01805 break;
01806 case FSM_MKLINKS:
01807 rc = fsmMakeLinks(fsm);
01808 break;
01809 case FSM_NOTIFY:
01810 if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) {
01811 rpmts ts = fsmGetTs(fsm);
01812 rpmfi fi = fsmGetFi(fsm);
01813 void * ptr;
01814 unsigned int archivePos = fdGetCpioPos(fsm->cfd);
01815 if (archivePos > fi->archivePos) {
01816 fi->archivePos = archivePos;
01817 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS,
01818 fi->archivePos, fi->archiveSize);
01819 }
01820 }
01821 break;
01822 case FSM_UNDO:
01823 if (fsm->postpone)
01824 break;
01825 if (fsm->goal == FSM_PKGINSTALL) {
01826 (void) fsmStage(fsm,
01827 (S_ISDIR(st->st_mode) ? FSM_RMDIR : FSM_UNLINK));
01828
01829 #ifdef NOTYET
01830 if (fsm->dnlx)
01831 (void) fsmStage(fsm, FSM_RMDIRS);
01832 #endif
01833 errno = saveerrno;
01834 }
01835
01836 if (fsm->failedFile && *fsm->failedFile == NULL)
01837 *fsm->failedFile = xstrdup(fsm->path);
01838
01839 break;
01840 case FSM_FINI:
01841 if (!fsm->postpone && fsm->commit) {
01842 if (fsm->goal == FSM_PKGINSTALL)
01843 rc = ((!S_ISDIR(st->st_mode) && st->st_nlink > 1)
01844 ? fsmCommitLinks(fsm) : fsmStage(fsm, FSM_COMMIT));
01845 if (fsm->goal == FSM_PKGCOMMIT)
01846 rc = fsmStage(fsm, FSM_COMMIT);
01847 if (fsm->goal == FSM_PKGERASE)
01848 rc = fsmStage(fsm, FSM_COMMIT);
01849 }
01850 fsm->path = _free(fsm->path);
01851 fsm->opath = _free(fsm->opath);
01852
01853 memset(st, 0, sizeof(*st));
01854 memset(ost, 0, sizeof(*ost));
01855
01856 break;
01857 case FSM_COMMIT:
01858
01859 if (fsm->osuffix && fsm->diskchecked &&
01860 (fsm->exists || (fsm->goal == FSM_PKGINSTALL && S_ISREG(st->st_mode))))
01861 {
01862 const char * opath = fsm->opath;
01863 const char * path = fsm->path;
01864 fsm->opath = fsmFsPath(fsm, st, NULL, NULL);
01865 fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
01866 rc = fsmStage(fsm, FSM_RENAME);
01867 if (!rc) {
01868 rpmMessage(RPMMESS_WARNING, _("%s saved as %s\n"),
01869 (fsm->opath ? fsm->opath : ""),
01870 (fsm->path ? fsm->path : ""));
01871 }
01872 fsm->path = _free(fsm->path);
01873 fsm->path = path;
01874 fsm->opath = _free(fsm->opath);
01875 fsm->opath = opath;
01876 }
01877
01878
01879 if (fsm->goal == FSM_PKGERASE) {
01880 if (fsm->action == FA_ERASE) {
01881 rpmfi fi = fsmGetFi(fsm);
01882 if (S_ISDIR(st->st_mode)) {
01883 rc = fsmStage(fsm, FSM_RMDIR);
01884 if (!rc) break;
01885 switch (rc) {
01886 case CPIOERR_ENOENT:
01887 case CPIOERR_ENOTEMPTY:
01888
01889 if (fsm->fflags & RPMFILE_MISSINGOK)
01890 break;
01891
01892
01893 rpmError(
01894 (strict_erasures ? RPMERR_RMDIR : RPMDEBUG_RMDIR),
01895 _("%s rmdir of %s failed: Directory not empty\n"),
01896 rpmfiTypeString(fi), fsm->path);
01897 break;
01898 default:
01899 rpmError(
01900 (strict_erasures ? RPMERR_RMDIR : RPMDEBUG_RMDIR),
01901 _("%s rmdir of %s failed: %s\n"),
01902 rpmfiTypeString(fi), fsm->path, strerror(errno));
01903 break;
01904 }
01905 } else {
01906 rc = fsmStage(fsm, FSM_UNLINK);
01907 if (!rc) break;
01908 switch (rc) {
01909 case CPIOERR_ENOENT:
01910 if (fsm->fflags & RPMFILE_MISSINGOK)
01911 break;
01912
01913 default:
01914 rpmError(
01915 (strict_erasures ? RPMERR_UNLINK : RPMDEBUG_UNLINK),
01916 _("%s unlink of %s failed: %s\n"),
01917 rpmfiTypeString(fi), fsm->path, strerror(errno));
01918 break;
01919 }
01920 }
01921 }
01922
01923 if (!strict_erasures) rc = 0;
01924 break;
01925 }
01926
01927
01928 if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(fsm->path)) {
01929
01930 if (!S_ISDIR(st->st_mode) &&
01931 (fsm->subdir || fsm->suffix || fsm->nsuffix))
01932 {
01933 fsm->opath = fsm->path;
01934 fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix);
01935 rc = fsmStage(fsm, FSM_RENAME);
01936 if (!rc && fsm->nsuffix) {
01937 const char * opath = fsmFsPath(fsm, st, NULL, NULL);
01938 rpmMessage(RPMMESS_WARNING, _("%s created as %s\n"),
01939 (opath ? opath : ""),
01940 (fsm->path ? fsm->path : ""));
01941 opath = _free(opath);
01942 }
01943 fsm->opath = _free(fsm->opath);
01944 }
01945 if (S_ISLNK(st->st_mode)) {
01946 if (!rc && !getuid())
01947 rc = fsmStage(fsm, FSM_LCHOWN);
01948 } else {
01949 if (!rc && !getuid())
01950 rc = fsmStage(fsm, FSM_CHOWN);
01951 if (!rc)
01952 rc = fsmStage(fsm, FSM_CHMOD);
01953 if (!rc) {
01954 time_t mtime = st->st_mtime;
01955 rpmfi fi = fsmGetFi(fsm);
01956 if (fi->fmtimes)
01957 st->st_mtime = fi->fmtimes[fsm->ix];
01958 rc = fsmStage(fsm, FSM_UTIME);
01959 st->st_mtime = mtime;
01960 }
01961 }
01962 }
01963
01964
01965 if (!rc) rc = fsmStage(fsm, FSM_NOTIFY);
01966 else if (fsm->failedFile && *fsm->failedFile == NULL) {
01967
01968 *fsm->failedFile = fsm->path;
01969
01970 fsm->path = NULL;
01971 }
01972 break;
01973 case FSM_DESTROY:
01974 fsm->path = _free(fsm->path);
01975
01976
01977 while ((fsm->li = fsm->links) != NULL) {
01978 fsm->links = fsm->li->next;
01979 fsm->li->next = NULL;
01980 if (fsm->goal == FSM_PKGINSTALL &&
01981 fsm->commit && fsm->li->linksLeft)
01982 {
01983 for (i = 0 ; i < fsm->li->linksLeft; i++) {
01984 if (fsm->li->filex[i] < 0)
01985 continue;
01986 rc = CPIOERR_MISSING_HARDLINK;
01987 if (fsm->failedFile && *fsm->failedFile == NULL) {
01988 fsm->ix = fsm->li->filex[i];
01989 if (!fsmStage(fsm, FSM_MAP)) {
01990
01991 *fsm->failedFile = fsm->path;
01992
01993 fsm->path = NULL;
01994 }
01995 }
01996 break;
01997 }
01998 }
01999 if (fsm->goal == FSM_PKGBUILD &&
02000 (fsm->mapFlags & CPIO_ALL_HARDLINKS))
02001 {
02002 rc = CPIOERR_MISSING_HARDLINK;
02003 }
02004 fsm->li = freeHardLink(fsm->li);
02005 }
02006 fsm->ldn = _free(fsm->ldn);
02007 fsm->ldnalloc = fsm->ldnlen = 0;
02008 fsm->rdbuf = fsm->rdb = _free(fsm->rdb);
02009 fsm->wrbuf = fsm->wrb = _free(fsm->wrb);
02010 break;
02011 case FSM_VERIFY:
02012 if (fsm->diskchecked && !fsm->exists) {
02013 rc = CPIOERR_ENOENT;
02014 break;
02015 }
02016 if (S_ISREG(st->st_mode)) {
02017 char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE"));
02018
02019 (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE");
02020
02021
02022
02023
02024
02025 fsm->opath = fsm->path;
02026 fsm->path = path;
02027 rc = fsmStage(fsm, FSM_RENAME);
02028 if (!rc)
02029 (void) fsmStage(fsm, FSM_UNLINK);
02030 else
02031 rc = CPIOERR_UNLINK_FAILED;
02032 fsm->path = fsm->opath;
02033 fsm->opath = NULL;
02034 return (rc ? rc : CPIOERR_ENOENT);
02035 break;
02036 } else if (S_ISDIR(st->st_mode)) {
02037 if (S_ISDIR(ost->st_mode)) return 0;
02038 if (S_ISLNK(ost->st_mode)) {
02039 rc = fsmStage(fsm, FSM_STAT);
02040 if (rc == CPIOERR_ENOENT) rc = 0;
02041 if (rc) break;
02042 errno = saveerrno;
02043 if (S_ISDIR(ost->st_mode)) return 0;
02044 }
02045 } else if (S_ISLNK(st->st_mode)) {
02046 if (S_ISLNK(ost->st_mode)) {
02047
02048 rc = fsmStage(fsm, FSM_READLINK);
02049 errno = saveerrno;
02050 if (rc) break;
02051 if (!strcmp(fsm->opath, fsm->rdbuf)) return 0;
02052 }
02053 } else if (S_ISFIFO(st->st_mode)) {
02054 if (S_ISFIFO(ost->st_mode)) return 0;
02055 } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
02056 if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
02057 (ost->st_rdev == st->st_rdev)) return 0;
02058 } else if (S_ISSOCK(st->st_mode)) {
02059 if (S_ISSOCK(ost->st_mode)) return 0;
02060 }
02061
02062 rc = 0;
02063 if (fsm->stage == FSM_PROCESS) rc = fsmStage(fsm, FSM_UNLINK);
02064 if (rc == 0) rc = CPIOERR_ENOENT;
02065 return (rc ? rc : CPIOERR_ENOENT);
02066 break;
02067
02068 case FSM_UNLINK:
02069 rc = Unlink(fsm->path);
02070 if (_fsm_debug && (stage & FSM_SYSCALL))
02071 rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur,
02072 fsm->path, (rc < 0 ? strerror(errno) : ""));
02073 if (rc < 0)
02074 rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_UNLINK_FAILED);
02075 break;
02076 case FSM_RENAME:
02077 rc = Rename(fsm->opath, fsm->path);
02078 #if defined(ETXTBSY)
02079 if (rc && errno == ETXTBSY) {
02080 char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE"));
02081 (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE");
02082
02083
02084
02085
02086 rc = Rename(fsm->path, path);
02087 if (!rc) rc = Rename(fsm->opath, fsm->path);
02088 }
02089 #endif
02090 if (_fsm_debug && (stage & FSM_SYSCALL))
02091 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
02092 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
02093 if (rc < 0) rc = CPIOERR_RENAME_FAILED;
02094 break;
02095 case FSM_MKDIR:
02096 rc = Mkdir(fsm->path, (st->st_mode & 07777));
02097 if (_fsm_debug && (stage & FSM_SYSCALL))
02098 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
02099 fsm->path, (unsigned)(st->st_mode & 07777),
02100 (rc < 0 ? strerror(errno) : ""));
02101 if (rc < 0) rc = CPIOERR_MKDIR_FAILED;
02102 break;
02103 case FSM_RMDIR:
02104 rc = Rmdir(fsm->path);
02105 if (_fsm_debug && (stage & FSM_SYSCALL))
02106 rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur,
02107 fsm->path, (rc < 0 ? strerror(errno) : ""));
02108 if (rc < 0)
02109 switch (errno) {
02110 case ENOENT: rc = CPIOERR_ENOENT; break;
02111 case ENOTEMPTY: rc = CPIOERR_ENOTEMPTY; break;
02112 default: rc = CPIOERR_RMDIR_FAILED; break;
02113 }
02114 break;
02115 case FSM_CHOWN:
02116 rc = chown(fsm->path, st->st_uid, st->st_gid);
02117 if (_fsm_debug && (stage & FSM_SYSCALL))
02118 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
02119 fsm->path, (int)st->st_uid, (int)st->st_gid,
02120 (rc < 0 ? strerror(errno) : ""));
02121 if (rc < 0) rc = CPIOERR_CHOWN_FAILED;
02122 break;
02123 case FSM_LCHOWN:
02124 #if ! CHOWN_FOLLOWS_SYMLINK
02125 rc = lchown(fsm->path, st->st_uid, st->st_gid);
02126 if (_fsm_debug && (stage & FSM_SYSCALL))
02127 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur,
02128 fsm->path, (int)st->st_uid, (int)st->st_gid,
02129 (rc < 0 ? strerror(errno) : ""));
02130 if (rc < 0) rc = CPIOERR_CHOWN_FAILED;
02131 #endif
02132 break;
02133 case FSM_CHMOD:
02134 rc = chmod(fsm->path, (st->st_mode & 07777));
02135 if (_fsm_debug && (stage & FSM_SYSCALL))
02136 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
02137 fsm->path, (unsigned)(st->st_mode & 07777),
02138 (rc < 0 ? strerror(errno) : ""));
02139 if (rc < 0) rc = CPIOERR_CHMOD_FAILED;
02140 break;
02141 case FSM_UTIME:
02142 { struct utimbuf stamp;
02143 stamp.actime = st->st_mtime;
02144 stamp.modtime = st->st_mtime;
02145 rc = utime(fsm->path, &stamp);
02146 if (_fsm_debug && (stage & FSM_SYSCALL))
02147 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0x%x) %s\n", cur,
02148 fsm->path, (unsigned)st->st_mtime,
02149 (rc < 0 ? strerror(errno) : ""));
02150 if (rc < 0) rc = CPIOERR_UTIME_FAILED;
02151 }
02152 break;
02153 case FSM_SYMLINK:
02154 rc = symlink(fsm->opath, fsm->path);
02155 if (_fsm_debug && (stage & FSM_SYSCALL))
02156 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
02157 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
02158 if (rc < 0) rc = CPIOERR_SYMLINK_FAILED;
02159 break;
02160 case FSM_LINK:
02161 rc = Link(fsm->opath, fsm->path);
02162 if (_fsm_debug && (stage & FSM_SYSCALL))
02163 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur,
02164 fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : ""));
02165 if (rc < 0) rc = CPIOERR_LINK_FAILED;
02166 break;
02167 case FSM_MKFIFO:
02168 rc = mkfifo(fsm->path, (st->st_mode & 07777));
02169 if (_fsm_debug && (stage & FSM_SYSCALL))
02170 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur,
02171 fsm->path, (unsigned)(st->st_mode & 07777),
02172 (rc < 0 ? strerror(errno) : ""));
02173 if (rc < 0) rc = CPIOERR_MKFIFO_FAILED;
02174 break;
02175 case FSM_MKNOD:
02176
02177 rc = mknod(fsm->path, (st->st_mode & ~07777), st->st_rdev);
02178
02179 if (_fsm_debug && (stage & FSM_SYSCALL))
02180 rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur,
02181 fsm->path, (unsigned)(st->st_mode & ~07777),
02182 (unsigned)st->st_rdev,
02183 (rc < 0 ? strerror(errno) : ""));
02184 if (rc < 0) rc = CPIOERR_MKNOD_FAILED;
02185 break;
02186 case FSM_LSTAT:
02187 rc = Lstat(fsm->path, ost);
02188 if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT)
02189 rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur,
02190 fsm->path, (rc < 0 ? strerror(errno) : ""));
02191 if (rc < 0) {
02192 rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_LSTAT_FAILED);
02193 memset(ost, 0, sizeof(*ost));
02194 }
02195 break;
02196 case FSM_STAT:
02197 rc = Stat(fsm->path, ost);
02198 if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT)
02199 rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur,
02200 fsm->path, (rc < 0 ? strerror(errno) : ""));
02201 if (rc < 0) {
02202 rc = (errno == ENOENT ? CPIOERR_ENOENT : CPIOERR_STAT_FAILED);
02203 memset(ost, 0, sizeof(*ost));
02204 }
02205 break;
02206 case FSM_READLINK:
02207
02208
02209 rc = Readlink(fsm->path, fsm->rdbuf, fsm->rdsize - 1);
02210
02211 if (_fsm_debug && (stage & FSM_SYSCALL))
02212 rpmMessage(RPMMESS_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur,
02213 fsm->path, (int)(fsm->rdsize -1), (rc < 0 ? strerror(errno) : ""));
02214 if (rc < 0) rc = CPIOERR_READLINK_FAILED;
02215 else {
02216 fsm->rdnb = rc;
02217
02218 fsm->rdbuf[fsm->rdnb] = '\0';
02219
02220 rc = 0;
02221 }
02222 break;
02223 case FSM_CHROOT:
02224 break;
02225
02226 case FSM_NEXT:
02227 rc = fsmStage(fsm, FSM_HREAD);
02228 if (rc) break;
02229 if (!strcmp(fsm->path, CPIO_TRAILER)) {
02230 fsm->path = _free(fsm->path);
02231 rc = CPIOERR_HDR_TRAILER;
02232 }
02233 if (!rc)
02234 rc = fsmStage(fsm, FSM_POS);
02235 break;
02236 case FSM_EAT:
02237 for (left = st->st_size; left > 0; left -= fsm->rdnb) {
02238 fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
02239 rc = fsmStage(fsm, FSM_DREAD);
02240 if (rc)
02241 break;
02242 }
02243 break;
02244 case FSM_POS:
02245 left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo;
02246 if (left) {
02247 fsm->wrlen = left;
02248 (void) fsmStage(fsm, FSM_DREAD);
02249 }
02250 break;
02251 case FSM_PAD:
02252 left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo;
02253 if (left) {
02254
02255 memset(fsm->rdbuf, 0, left);
02256
02257
02258 fsm->rdnb = left;
02259 (void) fsmStage(fsm, FSM_DWRITE);
02260 }
02261 break;
02262 case FSM_TRAILER:
02263 rc = cpioTrailerWrite(fsm);
02264 break;
02265 case FSM_HREAD:
02266 rc = fsmStage(fsm, FSM_POS);
02267 if (!rc)
02268 rc = cpioHeaderRead(fsm, st);
02269 break;
02270 case FSM_HWRITE:
02271 rc = cpioHeaderWrite(fsm, st);
02272 break;
02273 case FSM_DREAD:
02274
02275 fsm->rdnb = Fread(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->wrlen, fsm->cfd);
02276
02277 if (_fsm_debug && (stage & FSM_SYSCALL))
02278 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n",
02279 cur, (fsm->wrbuf == fsm->wrb ? "wrbuf" : "mmap"),
02280 (int)fsm->wrlen, (int)fsm->rdnb);
02281 if (fsm->rdnb != fsm->wrlen || Ferror(fsm->cfd))
02282 rc = CPIOERR_READ_FAILED;
02283 if (fsm->rdnb > 0)
02284 fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->rdnb);
02285 break;
02286 case FSM_DWRITE:
02287 fsm->wrnb = Fwrite(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdnb, fsm->cfd);
02288 if (_fsm_debug && (stage & FSM_SYSCALL))
02289 rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n",
02290 cur, (fsm->rdbuf == fsm->rdb ? "rdbuf" : "mmap"),
02291 (int)fsm->rdnb, (int)fsm->wrnb);
02292 if (fsm->rdnb != fsm->wrnb || Ferror(fsm->cfd))
02293 rc = CPIOERR_WRITE_FAILED;
02294 if (fsm->wrnb > 0)
02295 fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->wrnb);
02296 break;
02297
02298 case FSM_ROPEN:
02299 fsm->rfd = Fopen(fsm->path, "r.ufdio");
02300 if (fsm->rfd == NULL || Ferror(fsm->rfd)) {
02301 if (fsm->rfd != NULL) (void) fsmStage(fsm, FSM_RCLOSE);
02302 fsm->rfd = NULL;
02303 rc = CPIOERR_OPEN_FAILED;
02304 break;
02305 }
02306 if (_fsm_debug && (stage & FSM_SYSCALL))
02307 rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur,
02308 fsm->path, fsm->rfd, fsm->rdbuf);
02309 break;
02310 case FSM_READ:
02311
02312 fsm->rdnb = Fread(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdlen, fsm->rfd);
02313
02314 if (_fsm_debug && (stage & FSM_SYSCALL))
02315 rpmMessage(RPMMESS_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n",
02316 cur, (int)fsm->rdlen, (int)fsm->rdnb);
02317 if (fsm->rdnb != fsm->rdlen || Ferror(fsm->rfd))
02318 rc = CPIOERR_READ_FAILED;
02319 break;
02320 case FSM_RCLOSE:
02321 if (fsm->rfd != NULL) {
02322 if (_fsm_debug && (stage & FSM_SYSCALL))
02323 rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->rfd);
02324 (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST),
02325 fdstat_op(fsm->rfd, FDSTAT_DIGEST));
02326 (void) Fclose(fsm->rfd);
02327 errno = saveerrno;
02328 }
02329 fsm->rfd = NULL;
02330 break;
02331 case FSM_WOPEN:
02332 fsm->wfd = Fopen(fsm->path, "w.ufdio");
02333 if (fsm->wfd == NULL || Ferror(fsm->wfd)) {
02334 if (fsm->wfd != NULL) (void) fsmStage(fsm, FSM_WCLOSE);
02335 fsm->wfd = NULL;
02336 rc = CPIOERR_OPEN_FAILED;
02337 }
02338 if (_fsm_debug && (stage & FSM_SYSCALL))
02339 rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur,
02340 fsm->path, fsm->wfd, fsm->wrbuf);
02341 break;
02342 case FSM_WRITE:
02343 fsm->wrnb = Fwrite(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->rdnb, fsm->wfd);
02344 if (_fsm_debug && (stage & FSM_SYSCALL))
02345 rpmMessage(RPMMESS_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n",
02346 cur, (int)fsm->rdnb, (int)fsm->wrnb);
02347 if (fsm->rdnb != fsm->wrnb || Ferror(fsm->wfd))
02348 rc = CPIOERR_WRITE_FAILED;
02349 break;
02350 case FSM_WCLOSE:
02351 if (fsm->wfd != NULL) {
02352 if (_fsm_debug && (stage & FSM_SYSCALL))
02353 rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->wfd);
02354 (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST),
02355 fdstat_op(fsm->wfd, FDSTAT_DIGEST));
02356 (void) Fclose(fsm->wfd);
02357 errno = saveerrno;
02358 }
02359 fsm->wfd = NULL;
02360 break;
02361
02362 default:
02363 break;
02364 }
02365
02366
02367 if (!(stage & FSM_INTERNAL)) {
02368 fsm->rc = (rc == CPIOERR_HDR_TRAILER ? 0 : rc);
02369 }
02370 return rc;
02371 }
02372
02373
02374
02375 const char *const fileActionString(fileAction a)
02376 {
02377 switch (a) {
02378 case FA_UNKNOWN: return "unknown";
02379 case FA_CREATE: return "create";
02380 case FA_COPYOUT: return "copyout";
02381 case FA_COPYIN: return "copyin";
02382 case FA_BACKUP: return "backup";
02383 case FA_SAVE: return "save";
02384 case FA_SKIP: return "skip";
02385 case FA_ALTNAME: return "altname";
02386 case FA_ERASE: return "erase";
02387 case FA_SKIPNSTATE: return "skipnstate";
02388 case FA_SKIPNETSHARED: return "skipnetshared";
02389 case FA_SKIPCOLOR: return "skipcolor";
02390 default: return "???";
02391 }
02392
02393 }
02394
02395 const char *const fileStageString(fileStage a) {
02396 switch(a) {
02397 case FSM_UNKNOWN: return "unknown";
02398
02399 case FSM_PKGINSTALL:return "INSTALL";
02400 case FSM_PKGERASE: return "ERASE";
02401 case FSM_PKGBUILD: return "BUILD";
02402 case FSM_PKGCOMMIT: return "COMMIT";
02403 case FSM_PKGUNDO: return "UNDO";
02404
02405 case FSM_CREATE: return "create";
02406 case FSM_INIT: return "init";
02407 case FSM_MAP: return "map";
02408 case FSM_MKDIRS: return "mkdirs";
02409 case FSM_RMDIRS: return "rmdirs";
02410 case FSM_PRE: return "pre";
02411 case FSM_PROCESS: return "process";
02412 case FSM_POST: return "post";
02413 case FSM_MKLINKS: return "mklinks";
02414 case FSM_NOTIFY: return "notify";
02415 case FSM_UNDO: return "undo";
02416 case FSM_FINI: return "fini";
02417 case FSM_COMMIT: return "commit";
02418 case FSM_DESTROY: return "destroy";
02419 case FSM_VERIFY: return "verify";
02420
02421 case FSM_UNLINK: return "Unlink";
02422 case FSM_RENAME: return "Rename";
02423 case FSM_MKDIR: return "Mkdir";
02424 case FSM_RMDIR: return "rmdir";
02425 case FSM_CHOWN: return "chown";
02426 case FSM_LCHOWN: return "lchown";
02427 case FSM_CHMOD: return "chmod";
02428 case FSM_UTIME: return "utime";
02429 case FSM_SYMLINK: return "symlink";
02430 case FSM_LINK: return "Link";
02431 case FSM_MKFIFO: return "mkfifo";
02432 case FSM_MKNOD: return "mknod";
02433 case FSM_LSTAT: return "Lstat";
02434 case FSM_STAT: return "Stat";
02435 case FSM_READLINK: return "Readlink";
02436 case FSM_CHROOT: return "chroot";
02437
02438 case FSM_NEXT: return "next";
02439 case FSM_EAT: return "eat";
02440 case FSM_POS: return "pos";
02441 case FSM_PAD: return "pad";
02442 case FSM_TRAILER: return "trailer";
02443 case FSM_HREAD: return "hread";
02444 case FSM_HWRITE: return "hwrite";
02445 case FSM_DREAD: return "Fread";
02446 case FSM_DWRITE: return "Fwrite";
02447
02448 case FSM_ROPEN: return "Fopen";
02449 case FSM_READ: return "Fread";
02450 case FSM_RCLOSE: return "Fclose";
02451 case FSM_WOPEN: return "Fopen";
02452 case FSM_WRITE: return "Fwrite";
02453 case FSM_WCLOSE: return "Fclose";
02454
02455 default: return "???";
02456 }
02457
02458 }