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