• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

lib/fsm.c

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

Generated on Mon Nov 29 2010 05:18:43 for rpm by  doxygen 1.7.2