From eccb6f66fc6cc5ecdebf40a6a8150a804f870fe5 Mon Sep 17 00:00:00 2001 From: jbj Date: Sat, 10 Feb 2001 16:47:40 +0000 Subject: [PATCH] Reorganize sources before implementing --repackage. CVS patchset: 4543 CVS date: 2001/02/10 16:47:40 --- Doxyfile.in | 8 +- build.c | 1 - build/buildio.h | 2 +- lib/Makefile.am | 10 +- lib/cpio.c | 1895 +-------------------------------------- lib/fsm.c | 1905 ++++++++++++++++++++++++++++++++++++++++ lib/fsm.h | 255 ++++++ lib/{install.c => psm.c} | 372 +++++++- lib/psm.h | 152 ++++ lib/rollback.c | 335 ------- lib/rollback.h | 336 ------- lib/rpmlib.h | 50 ++ lib/scriptlet.c | 453 ++++++++++ lib/{install.h => scriptlet.h} | 46 +- lib/transaction.c | 14 +- lib/uninstall.c | 115 --- lib/verify.c | 4 +- po/POTFILES.in | 5 +- po/rpm.pot | 928 +++++++++---------- rpm.c | 1 - rpmqv.c | 1 - 21 files changed, 3680 insertions(+), 3208 deletions(-) create mode 100644 lib/fsm.c create mode 100644 lib/fsm.h rename lib/{install.c => psm.c} (70%) create mode 100644 lib/psm.h delete mode 100644 lib/rollback.c delete mode 100644 lib/rollback.h create mode 100644 lib/scriptlet.c rename lib/{install.h => scriptlet.h} (59%) delete mode 100644 lib/uninstall.c diff --git a/Doxyfile.in b/Doxyfile.in index c9ec29b..e4ee04b 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -286,12 +286,12 @@ INPUT = \ ./lib/fprint.c \ ./lib/fprint.h \ ./lib/fs.c \ + ./lib/fsm.c \ + ./lib/fsm.h \ ./lib/hash.c \ ./lib/hash.h \ ./lib/header.c \ ./lib/header.h \ - ./lib/install.c \ - ./lib/install.h \ ./lib/md5.c \ ./lib/md5.h \ ./lib/md5sum.c \ @@ -301,8 +301,9 @@ INPUT = \ ./lib/poptBT.c \ ./lib/poptQV.c \ ./lib/problems.c \ + ./lib/psm.c \ + ./lib/psm.h \ ./lib/query.c \ - ./lib/rollback.c \ ./lib/rpmchecksig.c \ ./lib/rpmdb.c \ ./lib/rpmdb.h \ @@ -320,7 +321,6 @@ INPUT = \ ./lib/tagName.c \ ./lib/tagtable.c \ ./lib/transaction.c \ - ./lib/uninstall.c \ ./lib/verify.c \ ./rpmio/base64.c \ ./rpmio/base64.h \ diff --git a/build.c b/build.c index 573e9f4..b8f73dd 100644 --- a/build.c +++ b/build.c @@ -4,7 +4,6 @@ #include #include "build.h" -#include "install.h" #include "debug.h" static int checkSpec(Header h) diff --git a/build/buildio.h b/build/buildio.h index 887e62d..dd80378 100644 --- a/build/buildio.h +++ b/build/buildio.h @@ -6,7 +6,7 @@ * XXX this information will move elsewhere eventually */ -#include "rollback.h" +#include "psm.h" /** */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 0d784ae..e3ab735 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,8 +11,8 @@ pkgincdir = $(pkgincludedir) pkginc_HEADERS = \ header.h misc.h rpmlib.h stringbuf.h noinst_HEADERS = \ - cpio.h depends.h falloc.h fprint.h hash.h install.h \ - md5.h rollback.h \ + cpio.h depends.h falloc.h fprint.h fsm.h hash.h \ + md5.h psm.h \ rpmdb.h rpmlead.h signature.h mylibpaths = -L$(top_builddir)/lib/.libs -L$(top_builddir)/rpmio/.libs \ @@ -23,12 +23,12 @@ LIBS = lib_LTLIBRARIES = librpm.la librpm_la_SOURCES = \ cpio.c $(DBLIBSRCS) depends.c \ - formats.c fprint.c fs.c hash.c header.c install.c \ + formats.c fprint.c fs.c fsm.c hash.c header.c \ md5.c md5sum.c misc.c package.c problems.c \ - poptBT.c poptQV.c query.c rollback.c \ + poptBT.c poptQV.c psm.c query.c \ rpmchecksig.c rpmdb.c rpminstall.c \ rpmlead.c rpmlibprov.c rpmrc.c scriptlet.c signature.c stringbuf.c \ - tagName.c tagtable.c transaction.c uninstall.c verify.c + tagName.c tagtable.c transaction.c verify.c librpm_la_LDFLAGS = @libdb3@ @libdb2@ @libdb1@ librpm_la_LIBADD = $(DBLIBOBJS) librpm_la_DEPENDENCIES = $(DBLIBOBJS) diff --git a/lib/cpio.c b/lib/cpio.c index fead7f6..f633e66 100644 --- a/lib/cpio.c +++ b/lib/cpio.c @@ -1,4 +1,4 @@ -/** \ingroup payload rpmio +/** \ingroup payload * \file lib/cpio.c * Handle cpio payloads within rpm packages. * @@ -10,465 +10,24 @@ #include "system.h" #include -#include "rollback.h" +#include "fsm.h" #include "rpmerr.h" #include "debug.h" -/*@access FD_t @*/ -/*@access rpmTransactionSet @*/ -/*@access TFI_t @*/ /*@access FSM_t @*/ -#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) +extern int _fsm_debug; +/** + * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL. + * @param this memory to free + * @retval NULL always + */ static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) { if (this) free((void *)this); return NULL; } -int _fsm_debug = 0; - -/** \ingroup payload - * Keeps track of the set of all hard links to a file in an archive. - */ -struct hardLink { -/*@owned@*/ struct hardLink * next; -/*@owned@*/ const char ** nsuffix; -/*@owned@*/ int * filex; - dev_t dev; - ino_t inode; - int nlink; - int linksLeft; - int linkIndex; - int createdPath; -}; - -/** - */ -typedef struct fsmIterator_s { -/*@kept@*/ rpmTransactionSet ts; /*!< transaction set. */ -/*@kept@*/ TFI_t fi; /*!< transaction element file info. */ - int isave; /*!< last returned iterator index. */ - int i; /*!< iterator index. */ -} * FSMI_t; - -/** \ingroup payload - * File name and stat information. - */ -struct fsm_s { -/*@owned@*/ const char * path; /*!< Current file name. */ -/*@owned@*/ const char * opath; /*!< Original file name. */ - FD_t cfd; /*!< Payload file handle. */ - FD_t rfd; /*!< read: File handle. */ -/*@dependent@*/ char * rdbuf; /*!< read: Buffer. */ -/*@owned@*/ char * rdb; /*!< read: Buffer allocated. */ - size_t rdsize; /*!< read: Buffer allocated size. */ - size_t rdlen; /*!< read: Number of bytes requested. */ - size_t rdnb; /*!< read: Number of bytes returned. */ - FD_t wfd; /*!< write: File handle. */ -/*@dependent@*/ char * wrbuf; /*!< write: Buffer. */ -/*@owned@*/ char * wrb; /*!< write: Buffer allocated. */ - size_t wrsize; /*!< write: Buffer allocated size. */ - size_t wrlen; /*!< write: Number of bytes requested. */ - size_t wrnb; /*!< write: Number of bytes returned. */ -/*@only@*/ FSMI_t iter; /*!< File iterator. */ - int ix; /*!< Current file iterator index. */ -/*@only@*/ struct hardLink * links; /*!< Pending hard linked file(s). */ -/*@only@*/ struct hardLink * li; /*!< Current hard linked file(s). */ -/*@kept@*/ unsigned int * archiveSize; /*!< Pointer to archive size. */ -/*@kept@*/ const char ** failedFile; /*!< First file name that failed. */ -/*@shared@*/ const char * subdir; /*!< Current file sub-directory. */ - char subbuf[64]; /* XXX eliminate */ -/*@observer@*/ const char * osuffix; /*!< Old, preserved, file suffix. */ -/*@observer@*/ const char * nsuffix; /*!< New, created, file suffix. */ -/*@shared@*/ const char * suffix; /*!< Current file suffix. */ - char sufbuf[64]; /* XXX eliminate */ -/*@only@*/ short * dnlx; /*!< Last dirpath verified indexes. */ -/*@only@*/ char * ldn; /*!< Last dirpath verified. */ - int ldnlen; /*!< Last dirpath current length. */ - int ldnalloc; /*!< Last dirpath allocated length. */ - int postpone; /*!< Skip remaining stages? */ - int diskchecked; /*!< Has stat(2) been performed? */ - int exists; /*!< Does current file exist on disk? */ - int mkdirsdone; /*!< Have "orphan" dirs been created? */ - int astriplen; /*!< Length of buildroot prefix. */ - int rc; /*!< External file stage return code. */ - int commit; /*!< Commit synchronously? */ - cpioMapFlags mapFlags; /*!< Bit(s) to control mapping. */ -/*@shared@*/ const char * archivePath; /*!< Path to store in cpio archive. */ -/*@shared@*/ const char * dirName; /*!< File directory name. */ -/*@shared@*/ const char * baseName; /*!< File base name. */ -/*@shared@*/ const char * fmd5sum; /*!< File MD5 sum (NULL disables). */ - unsigned fflags; /*!< File flags. */ - fileAction action; /*!< File disposition. */ - fileStage goal; /*!< Package state machine goal. */ - fileStage stage; /*!< External file stage. */ - struct stat sb; /*!< Current file stat(2) info. */ - struct stat osb; /*!< Original file stat(2) info. */ -}; - -rpmTransactionSet fsmGetTs(const FSM_t fsm) { - const FSMI_t iter = fsm->iter; - return (iter ? iter->ts : NULL); -} - -TFI_t fsmGetFi(const FSM_t fsm) { - const FSMI_t iter = fsm->iter; - return (iter ? iter->fi : NULL); -} - -#define SUFFIX_RPMORIG ".rpmorig" -#define SUFFIX_RPMSAVE ".rpmsave" -#define SUFFIX_RPMNEW ".rpmnew" - -/** - */ -static /*@only@*//*@null@*/ const char * fsmFsPath(/*@null@*/ const FSM_t fsm, - /*@null@*/ const struct stat * st, - /*@null@*/ const char * subdir, - /*@null@*/ const char * suffix) -{ - const char * s = NULL; - - if (fsm) { - int nb; - char * t; - nb = strlen(fsm->dirName) + - (st && subdir && !S_ISDIR(st->st_mode) ? strlen(subdir) : 0) + - (st && suffix && !S_ISDIR(st->st_mode) ? strlen(suffix) : 0) + - strlen(fsm->baseName) + 1; - s = t = xmalloc(nb); - t = stpcpy(t, fsm->dirName); - if (st && subdir && !S_ISDIR(st->st_mode)) - t = stpcpy(t, subdir); - t = stpcpy(t, fsm->baseName); - if (st && suffix && !S_ISDIR(st->st_mode)) - t = stpcpy(t, suffix); - } - return s; -} - -/** - */ -static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/const void * this) { - return _free((void *)this); -} - -/** - */ -static void * -mapInitIterator(/*@kept@*/ const void * this, /*@kept@*/ const void * that) -{ - rpmTransactionSet ts = (void *)this; - TFI_t fi = (void *)that; - FSMI_t iter = NULL; - - iter = xcalloc(1, sizeof(*iter)); - iter->ts = ts; - iter->fi = fi; - switch (fi->type) { - case TR_ADDED: iter->i = 0; break; - case TR_REMOVED: iter->i = fi->fc - 1; break; - } - iter->isave = iter->i; - return iter; -} - -/** - */ -static int mapNextIterator(void * this) { - FSMI_t iter = this; - const TFI_t fi = iter->fi; - int i = -1; - - switch (fi->type) { - case TR_ADDED: if (iter->i < fi->fc) i = iter->i++; break; - case TR_REMOVED: if (iter->i >= 0) i = iter->i--; break; - } - iter->isave = i; - return i; -} - -/** - */ -typedef struct dnli_s { -/*@dependent@*/ TFI_t fi; -/*@only@*/ /*@null@*/ char * active; - int reverse; - int isave; - int i; -} * DNLI_t; - -/** - */ -static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ const void * this) -{ - if (this) { - DNLI_t dnli = (void *)this; - if (dnli->active) free(dnli->active); - } - return _free(this); -} - -/** - */ -static inline int dnlCount(const DNLI_t dnli) { - return (dnli ? dnli->fi->dc : 0); -} - -/** - */ -static inline int dnlIndex(const DNLI_t dnli) { - return (dnli ? dnli->isave : -1); -} - -/** - */ -static /*@only@*/ void * dnlInitIterator(const FSM_t fsm, int reverse) -{ - TFI_t fi = fsmGetFi(fsm); - DNLI_t dnli; - int i, j; - - if (fi == NULL) - return NULL; - dnli = xcalloc(1, sizeof(*dnli)); - dnli->fi = fi; - dnli->reverse = reverse; - dnli->i = (reverse ? fi->dc : 0); - - if (fi->dc) { - dnli->active = xcalloc(fi->dc, sizeof(*dnli->active)); - - /* Identify parent directories not skipped. */ - for (i = 0; i < fi->fc; i++) - if (!XFA_SKIPPING(fi->actions[i])) dnli->active[fi->dil[i]] = 1; - - /* Exclude parent directories that are explicitly included. */ - for (i = 0; i < fi->fc; i++) { - int dil, dnlen, bnlen; - - if (!S_ISDIR(fi->fmodes[i])) - continue; - - dil = fi->dil[i]; - dnlen = strlen(fi->dnl[dil]); - bnlen = strlen(fi->bnl[i]); - - for (j = 0; j < fi->dc; j++) { - const char * dnl; - int jlen; - - if (!dnli->active[j] || j == dil) continue; - dnl = fi->dnl[j]; - jlen = strlen(dnl); - if (jlen != (dnlen+bnlen+1)) continue; - if (strncmp(dnl, fi->dnl[dil], dnlen)) continue; - if (strncmp(dnl+dnlen, fi->bnl[i], bnlen)) continue; - if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') - continue; - /* This directory is included in the package. */ - dnli->active[j] = 0; - break; - } - } - - /* Print only once per package. */ - if (!reverse) { - j = 0; - for (i = 0; i < fi->dc; i++) { - if (!dnli->active[i]) continue; - if (j == 0) { - j = 1; - rpmMessage(RPMMESS_DEBUG, - _("========= Directories not explictly included in package:\n")); - } - rpmMessage(RPMMESS_DEBUG, _("%9d %s\n"), i, fi->dnl[i]); - } - if (j) - rpmMessage(RPMMESS_DEBUG, "=========\n"); - } - } - return dnli; -} - -/** - */ -static const char * dnlNextIterator(/*@null@*/ DNLI_t dnli) { - const char * dn = NULL; - - if (dnli && dnli->active) { - TFI_t fi = dnli->fi; - int i = -1; - - do { - i = (!dnli->reverse ? dnli->i++ : --dnli->i); - } while (i >= 0 && i < fi->dc && !dnli->active[i]); - - if (i >= 0 && i < fi->dc) - dn = fi->dnl[i]; - else - i = -1; - dnli->isave = i; - } - return dn; -} - -/** - */ -static int cpioStrCmp(const void * a, const void * b) { - const char * afn = *(const char **)a; - const char * bfn = *(const char **)b; - - /* Match rpm-4.0 payloads with ./ prefixes. */ - if (afn[0] == '.' && afn[1] == '/') afn += 2; - if (bfn[0] == '.' && bfn[1] == '/') bfn += 2; - - /* If either path is absolute, make it relative. */ - if (afn[0] == '/') afn += 1; - if (bfn[0] == '/') bfn += 1; - - return strcmp(afn, bfn); -} - -/** - */ -static int mapFind(void * this, const char * fsmPath) { - FSMI_t iter = this; - const TFI_t fi = iter->fi; - int ix = -1; - - if (fi) { - const char ** p; - - p = bsearch(&fsmPath, fi->apath, fi->fc, sizeof(fsmPath), cpioStrCmp); - if (p == NULL) { - fprintf(stderr, "*** not mapped %s\n", fsmPath); - } else { - iter->i = p - fi->apath; - ix = mapNextIterator(iter); - } - } - return ix; -} - -/** - * Save hard link in chain. - * @return Is chain only partially filled? - */ -static int saveHardLink(FSM_t fsm) -{ - struct stat * st = &fsm->sb; - int rc = 0; - int ix = -1; - int j; - - /* Find hard link set. */ - for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { - if (fsm->li->inode == st->st_ino && fsm->li->dev == st->st_dev) - break; - } - - /* New hard link encountered, add new link to set. */ - if (fsm->li == NULL) { - fsm->li = xcalloc(1, sizeof(*fsm->li)); - fsm->li->next = NULL; - fsm->li->nlink = st->st_nlink; - fsm->li->dev = st->st_dev; - fsm->li->inode = st->st_ino; - fsm->li->linkIndex = -1; - fsm->li->createdPath = -1; - - fsm->li->filex = xcalloc(st->st_nlink, sizeof(fsm->li->filex[0])); - memset(fsm->li->filex, -1, (st->st_nlink * sizeof(fsm->li->filex[0]))); - fsm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*fsm->li->nsuffix)); - - if (fsm->goal == FSM_PKGBUILD) - fsm->li->linksLeft = st->st_nlink; - if (fsm->goal == FSM_PKGINSTALL) - fsm->li->linksLeft = 0; - - fsm->li->next = fsm->links; - fsm->links = fsm->li; - } - - if (fsm->goal == FSM_PKGBUILD) --fsm->li->linksLeft; - fsm->li->filex[fsm->li->linksLeft] = fsm->ix; - /*@-observertrans@*/ - fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix; - /*@=observertrans@*/ - if (fsm->goal == FSM_PKGINSTALL) fsm->li->linksLeft++; - -#if 0 -fprintf(stderr, "*** %p link[%d:%d] %d filex %d %s\n", fsm->li, fsm->li->linksLeft, st->st_nlink, (int)st->st_size, fsm->li->filex[fsm->li->linksLeft], fsm->li->files[fsm->li->linksLeft]); -#endif - - if (fsm->goal == FSM_PKGBUILD) - return (fsm->li->linksLeft > 0); - - if (fsm->goal != FSM_PKGINSTALL) - return 0; - - if (!(st->st_size || fsm->li->linksLeft == st->st_nlink)) - return 1; - - /* Here come the bits, time to choose a non-skipped file name. */ - { TFI_t fi = fsmGetFi(fsm); - - for (j = fsm->li->linksLeft - 1; j >= 0; j--) { - ix = fsm->li->filex[j]; - if (ix < 0 || XFA_SKIPPING(fi->actions[ix])) - continue; - break; - } - } - - /* Are all links skipped or not encountered yet? */ - if (ix < 0 || j < 0) - return 1; /* XXX W2DO? */ - - /* Save the non-skipped file name and map index. */ - fsm->li->linkIndex = j; - fsm->path = _free(fsm->path); - fsm->ix = ix; - rc = fsmStage(fsm, FSM_MAP); - return rc; -} - -/** - * Destroy set of hard links. - * @param li set of hard links - */ -static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink * li) -{ - if (li) { - li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */ - li->filex = _free(li->filex); - } - return _free(li); -} - -FSM_t newFSM(void) { - FSM_t fsm = xcalloc(1, sizeof(*fsm)); - return fsm; -} - -FSM_t freeFSM(FSM_t fsm) -{ - if (fsm) { - if (fsm->path) free((void *)fsm->path); - while ((fsm->li = fsm->links) != NULL) { - fsm->links = fsm->li->next; - fsm->li->next = NULL; - fsm->li = freeHardLink(fsm->li); - } - fsm->dnlx = _free(fsm->dnlx); - fsm->ldn = _free(fsm->ldn); - fsm->iter = mapFreeIterator(fsm->iter); - } - return _free(fsm); -} - /** * Convert string to unsigned integer (with buffer size check). * @param input string @@ -611,7 +170,7 @@ int cpioHeaderRead(FSM_t fsm, struct stat * st) if (!rc && fsm->rdnb != fsm->wrlen) rc = CPIOERR_BAD_HEADER; if (rc) { - free(t); + t = _free(t); fsm->path = NULL; return rc; } @@ -623,1442 +182,6 @@ int cpioHeaderRead(FSM_t fsm, struct stat * st) return 0; } -int fsmSetup(FSM_t fsm, fileStage goal, - const rpmTransactionSet ts, const TFI_t fi, FD_t cfd, - unsigned int * archiveSize, const char ** failedFile) -{ - size_t pos = 0; - int rc; - - fsm->goal = goal; - if (cfd) { - fsm->cfd = fdLink(cfd, "persist (fsm)"); - pos = fdGetCpioPos(fsm->cfd); - fdSetCpioPos(fsm->cfd, 0); - } - fsm->iter = mapInitIterator(ts, fi); - - if (fsm->goal == FSM_PKGINSTALL) { - if (ts && ts->notify) { - (void)ts->notify(fi->h, RPMCALLBACK_INST_START, 0, fi->archiveSize, - (fi->ap ? fi->ap->key : NULL), ts->notifyData); - } - } - - fsm->archiveSize = archiveSize; - if (fsm->archiveSize) - *fsm->archiveSize = 0; - fsm->failedFile = failedFile; - if (fsm->failedFile) - *fsm->failedFile = NULL; - - memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf)); - if (fsm->goal == FSM_PKGINSTALL) { - if (ts->id > 0) - sprintf(fsm->sufbuf, ";%08x", (unsigned)ts->id); - } - - rc = fsm->rc = 0; - rc = fsmStage(fsm, FSM_CREATE); - - rc = fsmStage(fsm, fsm->goal); - - if (!rc && fsm->archiveSize) - *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos); - - return rc; -} - -int fsmTeardown(FSM_t fsm) { - int rc = fsm->rc; - - if (!rc) - rc = fsmStage(fsm, FSM_DESTROY); - - fsm->iter = mapFreeIterator(fsm->iter); - if (fsm->cfd) { - fsm->cfd = fdFree(fsm->cfd, "persist (fsm)"); - fsm->cfd = NULL; - } - fsm->failedFile = NULL; - return rc; -} - -int fsmMapPath(FSM_t fsm) -{ - TFI_t fi = fsmGetFi(fsm); /* XXX const except for fstates */ - int rc = 0; - int i; - - fsm->osuffix = NULL; - fsm->nsuffix = NULL; - fsm->astriplen = 0; - fsm->action = FA_UNKNOWN; - fsm->mapFlags = 0; - - i = fsm->ix; - if (fi && i >= 0 && i < fi->fc) { - - fsm->astriplen = fi->astriplen; - fsm->action = (fi->actions ? fi->actions[i] : fi->action); - fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags); - fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags); - - /* src rpms have simple base name in payload. */ - fsm->archivePath = - (fi->apath ? fi->apath[i] + fi->striplen : fi->bnl[i]); - fsm->dirName = fi->dnl[fi->dil[i]]; - fsm->baseName = fi->bnl[i]; - - switch (fsm->action) { - case FA_SKIP: - break; - case FA_SKIPMULTILIB: /* XXX RPMFILE_STATE_MULTILIB? */ -fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); - break; - case FA_UNKNOWN: -fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); - break; - - case FA_CREATE: - assert(fi->type == TR_ADDED); - break; - - case FA_SKIPNSTATE: -fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); - if (fi->type == TR_ADDED) - fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED; - break; - - case FA_SKIPNETSHARED: - if (fi->type == TR_ADDED) - fi->fstates[i] = RPMFILE_STATE_NETSHARED; - break; - - case FA_BACKUP: -fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); - switch (fi->type) { - case TR_ADDED: - fsm->osuffix = SUFFIX_RPMORIG; - break; - case TR_REMOVED: - fsm->osuffix = SUFFIX_RPMSAVE; - break; - } - break; - - case FA_ALTNAME: - assert(fi->type == TR_ADDED); - fsm->nsuffix = SUFFIX_RPMNEW; - break; - - case FA_SAVE: -fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); - assert(fi->type == TR_ADDED); - fsm->osuffix = SUFFIX_RPMSAVE; - break; - case FA_ERASE: - assert(fi->type == TR_REMOVED); - break; - default: -fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); - break; - } - - if ((fsm->mapFlags & CPIO_MAP_PATH) || fsm->nsuffix) { - const struct stat * st = &fsm->sb; - fsm->path = _free(fsm->path); - fsm->path = fsmFsPath(fsm, st, fsm->subdir, - (fsm->suffix ? fsm->suffix : fsm->nsuffix)); - } - } - return rc; -} - -int fsmMapAttrs(FSM_t fsm) -{ - struct stat * st = &fsm->sb; - TFI_t fi = fsmGetFi(fsm); - int i = fsm->ix; - - if (fi && i >= 0 && i < fi->fc) { - mode_t perms = - (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms); - mode_t finalMode = - (fi->fmodes ? fi->fmodes[i] : perms); - uid_t finalUid = - (fi->fuids ? fi->fuids[i] : fi->uid); /* XXX chmod u-s */ - gid_t finalGid = - (fi->fgids ? fi->fgids[i] : fi->gid); /* XXX chmod g-s */ - - if (fsm->mapFlags & CPIO_MAP_MODE) - st->st_mode = (st->st_mode & S_IFMT) | finalMode; - if (fsm->mapFlags & CPIO_MAP_UID) - st->st_uid = finalUid; - if (fsm->mapFlags & CPIO_MAP_GID) - st->st_gid = finalGid; - - fsm->fmd5sum = (fi->fmd5s ? fi->fmd5s[i] : NULL); - - } - return 0; -} - -/** - * Create file from payload stream. - * @todo Legacy: support brokenEndian MD5 checks? - * @param fsm file path and stat info - * @return 0 on success - */ -static int expandRegular(FSM_t fsm) - /*@modifies fileSystem, fsm @*/ -{ - const char * fmd5sum; - const struct stat * st = &fsm->sb; - int left = st->st_size; - int rc = 0; - - rc = fsmStage(fsm, FSM_WOPEN); - if (rc) - goto exit; - - /* XXX md5sum's will break on repackaging that includes modified files. */ - fmd5sum = fsm->fmd5sum; - - /* XXX This doesn't support brokenEndian checks. */ - if (st->st_size > 0 && fmd5sum) - fdInitMD5(fsm->wfd, 0); - - while (left) { - - fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); - rc = fsmStage(fsm, FSM_DREAD); - if (rc) - goto exit; - - rc = fsmStage(fsm, FSM_WRITE); - if (rc) - goto exit; - - left -= fsm->wrnb; - - /* don't call this with fileSize == fileComplete */ - if (!rc && left) - (void) fsmStage(fsm, FSM_NOTIFY); - } - - if (st->st_size > 0 && fmd5sum) { - const char * md5sum = NULL; - - Fflush(fsm->wfd); - fdFiniMD5(fsm->wfd, (void **)&md5sum, NULL, 1); - - if (md5sum == NULL) { - rc = CPIOERR_MD5SUM_MISMATCH; - } else { - if (strcmp(md5sum, fmd5sum)) - rc = CPIOERR_MD5SUM_MISMATCH; - md5sum = _free(md5sum); - } - } - -exit: - (void) fsmStage(fsm, FSM_WCLOSE); - return rc; -} - -/** - * Write next item to payload stream. - * @retval sizep address of no. bytes written - * @param writeData should data be written? - * @return 0 on success - */ -static int writeFile(FSM_t fsm, int writeData) - /*@modifies fsm @*/ -{ - const char * path = fsm->path; - const char * opath = fsm->opath; - struct stat * st = &fsm->sb; - struct stat * ost = &fsm->osb; - size_t pos = fdGetCpioPos(fsm->cfd); - int left; - int rc; - - st->st_size = (writeData ? ost->st_size : 0); - if (S_ISDIR(st->st_mode)) { - st->st_size = 0; - } else if (S_ISLNK(st->st_mode)) { - /* - * While linux puts the size of a symlink in the st_size field, - * I don't think that's a specified standard. - */ - /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ - rc = fsmStage(fsm, FSM_READLINK); - if (rc) goto exit; - st->st_size = fsm->rdnb; - } - - if (fsm->mapFlags & CPIO_MAP_PATH) - fsm->path = fsm->archivePath; - rc = fsmStage(fsm, FSM_HWRITE); - fsm->path = path; - if (rc) goto exit; - - if (writeData && S_ISREG(st->st_mode)) { -#if HAVE_MMAP - char * rdbuf = NULL; - void * mapped = (void *)-1; - size_t nmapped; -#endif - - rc = fsmStage(fsm, FSM_ROPEN); - if (rc) goto exit; - - /* XXX unbuffered mmap generates *lots* of fdio debugging */ -#if HAVE_MMAP - nmapped = 0; - mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0); - if (mapped != (void *)-1) { - rdbuf = fsm->rdbuf; - fsm->rdbuf = (char *) mapped; - fsm->rdlen = nmapped = st->st_size; - } -#endif - - left = st->st_size; - - while (left) { -#if HAVE_MMAP - if (mapped != (void *)-1) { - fsm->rdnb = nmapped; - } else -#endif - { - fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left), - rc = fsmStage(fsm, FSM_READ); - if (rc) goto exit; - } - - /* XXX DWRITE uses rdnb for I/O length. */ - rc = fsmStage(fsm, FSM_DWRITE); - if (rc) goto exit; - - left -= fsm->wrnb; - } - -#if HAVE_MMAP - if (mapped != (void *)-1) { - /*@-noeffect@*/ munmap(mapped, nmapped) /*@=noeffect@*/; - fsm->rdbuf = rdbuf; - } -#endif - - } else if (writeData && S_ISLNK(st->st_mode)) { - /* XXX DWRITE uses rdnb for I/O length. */ - rc = fsmStage(fsm, FSM_DWRITE); - if (rc) goto exit; - } - - rc = fsmStage(fsm, FSM_PAD); - if (rc) goto exit; - - { const rpmTransactionSet ts = fsmGetTs(fsm); - TFI_t fi = fsmGetFi(fsm); - if (ts && fi && ts->notify) { - size_t size = (fdGetCpioPos(fsm->cfd) - pos); - (void)ts->notify(fi->h, RPMCALLBACK_INST_PROGRESS, size, size, - (fi->ap ? fi->ap->key : NULL), ts->notifyData); - } - } - - rc = 0; - -exit: - if (fsm->rfd) - (void) fsmStage(fsm, FSM_RCLOSE); - fsm->opath = opath; - fsm->path = path; - return rc; -} - -/** - * Write set of linked files to payload stream. - * @return 0 on success - */ -static int writeLinkedFile(FSM_t fsm) - /*@modifies fsm @*/ -{ - const char * path = fsm->path; - const char * nsuffix = fsm->nsuffix; - int iterIndex = fsm->ix; - int ec = 0; - int rc; - int i; - - fsm->path = NULL; - fsm->nsuffix = NULL; - fsm->ix = -1; - - for (i = fsm->li->nlink - 1; i >= 0; i--) { - if (fsm->li->filex[i] < 0) continue; - - fsm->ix = fsm->li->filex[i]; - rc = fsmStage(fsm, FSM_MAP); - - /* Write data after last link. */ - rc = writeFile(fsm, (i == 0)); - if (rc && fsm->failedFile && *fsm->failedFile == NULL) { - ec = rc; - *fsm->failedFile = xstrdup(fsm->path); - } - - fsm->path = _free(fsm->path); - fsm->li->filex[i] = -1; - } - - fsm->ix = iterIndex; - fsm->nsuffix = nsuffix; - fsm->path = path; - return ec; -} - -/** - */ -static int fsmMakeLinks(FSM_t fsm) -{ - const char * path = fsm->path; - const char * opath = fsm->opath; - const char * nsuffix = fsm->nsuffix; - int iterIndex = fsm->ix; - int ec = 0; - int rc; - int i; - - fsm->path = NULL; - fsm->opath = NULL; - fsm->nsuffix = NULL; - fsm->ix = -1; - - fsm->ix = fsm->li->filex[fsm->li->createdPath]; - rc = fsmStage(fsm, FSM_MAP); - fsm->opath = fsm->path; - fsm->path = NULL; - for (i = 0; i < fsm->li->nlink; i++) { - if (fsm->li->filex[i] < 0) continue; - if (i == fsm->li->createdPath) continue; - - fsm->ix = fsm->li->filex[i]; - rc = fsmStage(fsm, FSM_MAP); - rc = fsmStage(fsm, FSM_VERIFY); - if (!rc) continue; - if (rc != CPIOERR_LSTAT_FAILED) break; - - /* XXX link(fsm->opath, fsm->path) */ - rc = fsmStage(fsm, FSM_LINK); - if (rc && fsm->failedFile && *fsm->failedFile == NULL) { - ec = rc; - *fsm->failedFile = xstrdup(fsm->path); - } - - fsm->li->linksLeft--; - } - fsm->opath = _free(fsm->opath); - - fsm->ix = iterIndex; - fsm->nsuffix = nsuffix; - fsm->path = path; - fsm->opath = opath; - return ec; -} - -/** - */ -static int fsmCommitLinks(FSM_t fsm) -{ - const char * path = fsm->path; - const char * nsuffix = fsm->nsuffix; - int iterIndex = fsm->ix; - struct stat * st = &fsm->sb; - int rc = 0; - int i; - - fsm->path = NULL; - fsm->nsuffix = NULL; - fsm->ix = -1; - - for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { - if (fsm->li->inode == st->st_ino && fsm->li->dev == st->st_dev) - break; - } - - for (i = 0; i < fsm->li->nlink; i++) { - if (fsm->li->filex[i] < 0) continue; - fsm->ix = fsm->li->filex[i]; - rc = fsmStage(fsm, FSM_MAP); - rc = fsmStage(fsm, FSM_COMMIT); - fsm->path = _free(fsm->path); - fsm->li->filex[i] = -1; - } - - fsm->ix = iterIndex; - fsm->nsuffix = nsuffix; - fsm->path = path; - return rc; -} - -int fsmStage(FSM_t fsm, fileStage stage) -{ -#ifdef UNUSED - fileStage prevStage = fsm->stage; - const char * const prev = fileStageString(prevStage); -#endif - static int modulo = 4; - const char * const cur = fileStageString(stage); - struct stat * st = &fsm->sb; - struct stat * ost = &fsm->osb; - int saveerrno = errno; - int rc = fsm->rc; - int left; - int i; - - if (stage & FSM_DEAD) { - /* do nothing */ - } else if (stage & FSM_INTERNAL) { - if (_fsm_debug && !(stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s %06o%3d (%4d,%4d)%10d %s %s\n", - cur, - st->st_mode, st->st_nlink, st->st_uid, st->st_gid, st->st_size, - (fsm->path ? fsm->path : ""), - ((fsm->action != FA_UNKNOWN && fsm->action != FA_CREATE) - ? fileActionString(fsm->action) : "")); - } else { - fsm->stage = stage; - if (_fsm_debug || !(stage & FSM_VERBOSE)) - rpmMessage(RPMMESS_DEBUG, "%-8s %06o%3d (%4d,%4d)%10d %s %s\n", - cur, - st->st_mode, st->st_nlink, st->st_uid, st->st_gid, st->st_size, - (fsm->path ? fsm->path + fsm->astriplen : ""), - ((fsm->action != FA_UNKNOWN && fsm->action != FA_CREATE) - ? fileActionString(fsm->action) : "")); - } - - switch (stage) { - case FSM_UNKNOWN: - break; - case FSM_PKGINSTALL: - while (1) { - /* Clean fsm, free'ing memory. Read next archive header. */ - rc = fsmStage(fsm, FSM_INIT); - - /* Exit on end-of-payload. */ - if (rc == CPIOERR_HDR_TRAILER) { - rc = 0; - break; - } - - /* Exit on error. */ - if (rc) { - fsm->postpone = 1; - (void) fsmStage(fsm, FSM_UNDO); - break; - } - - /* Extract file from archive. */ - rc = fsmStage(fsm, FSM_PROCESS); - if (rc) { - (void) fsmStage(fsm, FSM_UNDO); - break; - } - - /* Notify on success. */ - (void) fsmStage(fsm, FSM_NOTIFY); - - if (fsmStage(fsm, FSM_FINI)) - break; - } - break; - case FSM_PKGERASE: - case FSM_PKGCOMMIT: - while (1) { - /* Clean fsm, free'ing memory. */ - rc = fsmStage(fsm, FSM_INIT); - - /* Exit on end-of-payload. */ - if (rc == CPIOERR_HDR_TRAILER) { - rc = 0; - break; - } - - /* Rename/erase next item. */ - if (fsmStage(fsm, FSM_FINI)) - break; - } - break; - case FSM_PKGBUILD: - while (1) { - - rc = fsmStage(fsm, FSM_INIT); - - /* Exit on end-of-payload. */ - if (rc == CPIOERR_HDR_TRAILER) { - rc = 0; - break; - } - - /* Exit on error. */ - if (rc) { - fsm->postpone = 1; - (void) fsmStage(fsm, FSM_UNDO); - break; - } - - /* Copy file into archive. */ - rc = fsmStage(fsm, FSM_PROCESS); - if (rc) { - (void) fsmStage(fsm, FSM_UNDO); - break; - } - - if (fsmStage(fsm, FSM_FINI)) - break; - } - - if (!rc) - rc = fsmStage(fsm, FSM_TRAILER); - break; - case FSM_CREATE: - { rpmTransactionSet ts = fsmGetTs(fsm); -#define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT) - fsm->commit = ((ts && (ts->transFlags & _tsmask) && - fsm->goal != FSM_PKGCOMMIT) ? 0 : 1); -#undef _tsmask - } - fsm->path = _free(fsm->path); - fsm->opath = _free(fsm->opath); - fsm->dnlx = _free(fsm->dnlx); - - fsm->ldn = _free(fsm->ldn); - fsm->ldnalloc = fsm->ldnlen = 0; - - fsm->rdsize = fsm->wrsize = 0; - fsm->rdbuf = fsm->rdb = _free(fsm->rdb); - fsm->wrbuf = fsm->wrb = _free(fsm->wrb); - if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { - fsm->rdsize = 8 * BUFSIZ; - fsm->rdbuf = fsm->rdb = xmalloc(fsm->rdsize); - fsm->wrsize = 8 * BUFSIZ; - fsm->wrbuf = fsm->wrb = xmalloc(fsm->wrsize); - } - - fsm->mkdirsdone = 0; - fsm->ix = -1; - fsm->links = NULL; - fsm->li = NULL; - errno = 0; /* XXX get rid of EBADF */ - - /* Detect and create directories not explicitly in package. */ - if (fsm->goal == FSM_PKGINSTALL) { - rc = fsmStage(fsm, FSM_MKDIRS); - if (!rc) fsm->mkdirsdone = 1; - } - - break; - case FSM_INIT: - fsm->path = _free(fsm->path); - fsm->postpone = 0; - fsm->diskchecked = fsm->exists = 0; - fsm->subdir = NULL; - fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL); - fsm->action = FA_UNKNOWN; - fsm->osuffix = NULL; - fsm->nsuffix = NULL; - - if (fsm->goal == FSM_PKGINSTALL) { - /* Read next header from payload, checking for end-of-payload. */ - rc = fsmStage(fsm, FSM_NEXT); - } - if (rc) break; - - /* Identify mapping index. */ - fsm->ix = ((fsm->goal == FSM_PKGINSTALL) - ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter)); - - /* On non-install, detect end-of-loop. */ - if (fsm->goal != FSM_PKGINSTALL && fsm->ix < 0) { - rc = CPIOERR_HDR_TRAILER; - break; - } - - /* On non-install, mode must be known so that dirs don't get suffix. */ - if (fsm->goal != FSM_PKGINSTALL) { - TFI_t fi = fsmGetFi(fsm); - st->st_mode = fi->fmodes[fsm->ix]; - } - - /* Generate file path. */ - rc = fsmStage(fsm, FSM_MAP); - if (rc) break; - - /* Perform lstat/stat for disk file. */ - rc = fsmStage(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS) - ? FSM_LSTAT : FSM_STAT)); - if (rc == CPIOERR_LSTAT_FAILED && errno == ENOENT) { - errno = saveerrno; - rc = 0; - fsm->exists = 0; - } else if (rc == 0) { - fsm->exists = 1; - } - fsm->diskchecked = 1; - if (rc) break; - - /* On non-install, the disk file stat is what's remapped. */ - if (fsm->goal != FSM_PKGINSTALL) - *st = *ost; /* structure assignment */ - - /* Remap file perms, owner, and group. */ - rc = fsmMapAttrs(fsm); - if (rc) break; - - fsm->postpone = XFA_SKIPPING(fsm->action); - if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { - if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) - fsm->postpone = saveHardLink(fsm); - } - break; - case FSM_PRE: - break; - case FSM_MAP: - rc = fsmMapPath(fsm); - break; - case FSM_MKDIRS: - { const char * path = fsm->path; - mode_t st_mode = st->st_mode; - void * dnli = dnlInitIterator(fsm, 0); - char * dn = fsm->rdbuf; - int dc = dnlCount(dnli); - - fsm->path = NULL; - dn[0] = '\0'; - fsm->dnlx = (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL); - while ((fsm->path = dnlNextIterator(dnli)) != NULL) { - int dnlen = strlen(fsm->path); - char * te; - - dc = dnlIndex(dnli); - if (dc < 0) continue; - fsm->dnlx[dc] = dnlen; - if (dnlen <= 1) - continue; - if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn)) - continue; - - /* Copy to avoid const on fsm->path. */ - (void) stpcpy(dn, fsm->path); - fsm->path = dn; - - /* Initial mode for created dirs is 0700 */ - st->st_mode &= ~07777; /* XXX abuse st->st_mode */ - st->st_mode |= 00700; - - /* Assume '/' directory, otherwise "mkdir -p" */ - for (i = 1, te = dn + 1; *te; te++, i++) { - if (*te != '/') continue; - - *te = '\0'; - - /* Already validated? */ - if (i < fsm->ldnlen && - (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') && - !strncmp(fsm->path, fsm->ldn, i)) - { - *te = '/'; - /* Move pre-existing path marker forward. */ - fsm->dnlx[dc] = (te - dn); - continue; - } - - /* Validate next component of path. */ - rc = fsmStage(fsm, FSM_LSTAT); - *te = '/'; - - /* Directory already exists? */ - if (rc == 0 && S_ISDIR(ost->st_mode)) { - /* Move pre-existing path marker forward. */ - fsm->dnlx[dc] = (te - dn); - } else if (rc == CPIOERR_LSTAT_FAILED) { - TFI_t fi = fsmGetFi(fsm); - mode_t st_mode = st->st_mode; - *te = '\0'; - st->st_mode = S_IFDIR | (fi->dperms & 07777); - rc = fsmStage(fsm, FSM_MKDIR); - if (!rc) - rpmMessage(RPMMESS_WARNING, - _("%s directory created with perms %04o.\n"), - fsm->path, (st->st_mode & 07777)); - *te = '/'; - st->st_mode = st_mode; - } - if (rc) break; - } - if (rc) break; - - /* Save last validated path. */ - if (fsm->ldnalloc < (dnlen + 1)) { - fsm->ldnalloc = dnlen + 100; - fsm->ldn = xrealloc(fsm->ldn, fsm->ldnalloc); - } - strcpy(fsm->ldn, fsm->path); - fsm->ldnlen = dnlen; - } - dnli = dnlFreeIterator(dnli); - fsm->path = path; - st->st_mode = st_mode; /* XXX restore st->st_mode */ - } - break; - case FSM_RMDIRS: - if (fsm->dnlx) { - const char * path = fsm->path; - void * dnli = dnlInitIterator(fsm, 1); - char * dn = fsm->rdbuf; - int dc = dnlCount(dnli); - - fsm->path = NULL; - dn[0] = '\0'; - while ((fsm->path = dnlNextIterator(dnli)) != NULL) { - int dnlen = strlen(fsm->path); - char * te; - - dc = dnlIndex(dnli); - if (fsm->dnlx[dc] < 1 || fsm->dnlx[dc] >= dnlen) - continue; - - /* Copy to avoid const on fsm->path. */ - te = stpcpy(dn, fsm->path) - 1; - fsm->path = dn; - - /* Remove generated directories. */ - do { - if (*te == '/') { - *te = '\0'; - rc = fsmStage(fsm, FSM_RMDIR); - *te = '/'; - } - if (rc) break; - te--; - } while ((te - dn) > fsm->dnlx[dc]); - } - dnli = dnlFreeIterator(dnli); - fsm->path = path; - } - break; - case FSM_PROCESS: - if (fsm->postpone) { - if (fsm->goal == FSM_PKGINSTALL) - rc = fsmStage(fsm, FSM_EAT); - break; - } - - if (fsm->goal == FSM_PKGBUILD) { - if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { - struct hardLink * li, * prev; - rc = writeLinkedFile(fsm); - if (rc) break; /* W2DO? */ - - for (li = fsm->links, prev = NULL; li; prev = li, li = li->next) - if (li == fsm->li) break; - - if (prev == NULL) - fsm->links = fsm->li->next; - else - prev->next = fsm->li->next; - fsm->li->next = NULL; - fsm->li = freeHardLink(fsm->li); - } else { - rc = writeFile(fsm, 1); - } - break; - } - - if (fsm->goal != FSM_PKGINSTALL) - break; - - if (S_ISREG(st->st_mode)) { - const char * path = fsm->path; - if (fsm->osuffix) - fsm->path = fsmFsPath(fsm, st, NULL, NULL); - rc = fsmStage(fsm, FSM_VERIFY); - - if (rc == 0 && fsm->osuffix) { - const char * opath = fsm->opath; - fsm->opath = fsm->path; - fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); - rc = fsmStage(fsm, FSM_RENAME); - if (!rc) - rpmMessage(RPMMESS_WARNING, - _("%s saved as %s\n"), fsm->opath, fsm->path); - fsm->path = _free(fsm->path); - fsm->opath = opath; - } - - fsm->path = path; - if (rc != CPIOERR_LSTAT_FAILED) return rc; - rc = expandRegular(fsm); - } else if (S_ISDIR(st->st_mode)) { - mode_t st_mode = st->st_mode; - rc = fsmStage(fsm, FSM_VERIFY); - if (rc == CPIOERR_LSTAT_FAILED) { - st->st_mode &= ~07777; /* XXX abuse st->st_mode */ - st->st_mode |= 00700; - rc = fsmStage(fsm, FSM_MKDIR); - st->st_mode = st_mode; /* XXX restore st->st_mode */ - } - } else if (S_ISLNK(st->st_mode)) { - const char * opath = fsm->opath; - - if ((st->st_size + 1) > fsm->rdsize) { - rc = CPIOERR_HDR_SIZE; - break; - } - - fsm->wrlen = st->st_size; - rc = fsmStage(fsm, FSM_DREAD); - if (!rc && fsm->rdnb != fsm->wrlen) - rc = CPIOERR_READ_FAILED; - if (rc) break; - - fsm->wrbuf[st->st_size] = '\0'; - /* XXX symlink(fsm->opath, fsm->path) */ - fsm->opath = fsm->wrbuf; /* XXX abuse fsm->path */ - rc = fsmStage(fsm, FSM_VERIFY); - if (rc == CPIOERR_LSTAT_FAILED) - rc = fsmStage(fsm, FSM_SYMLINK); - fsm->opath = opath; /* XXX restore fsm->path */ - } else if (S_ISFIFO(st->st_mode)) { - mode_t st_mode = st->st_mode; - /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */ - rc = fsmStage(fsm, FSM_VERIFY); - if (rc == CPIOERR_LSTAT_FAILED) { - st->st_mode = 0000; /* XXX abuse st->st_mode */ - rc = fsmStage(fsm, FSM_MKFIFO); - st->st_mode = st_mode; /* XXX restore st->st_mode */ - } - } else if (S_ISCHR(st->st_mode) || - S_ISBLK(st->st_mode) || - S_ISSOCK(st->st_mode)) - { - rc = fsmStage(fsm, FSM_VERIFY); - if (rc == CPIOERR_LSTAT_FAILED) - rc = fsmStage(fsm, FSM_MKNOD); - } else { - rc = CPIOERR_UNKNOWN_FILETYPE; - } - if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { - fsm->li->createdPath = fsm->li->linkIndex; - rc = fsmMakeLinks(fsm); - } - break; - case FSM_POST: - break; - case FSM_MKLINKS: - break; - case FSM_NOTIFY: /* XXX move from fsm to psm -> tsm */ - if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { - rpmTransactionSet ts = fsmGetTs(fsm); - TFI_t fi = fsmGetFi(fsm); - if (ts && ts->notify && fi) - (void)ts->notify(fi->h, RPMCALLBACK_INST_PROGRESS, - fdGetCpioPos(fsm->cfd), fi->archiveSize, - (fi->ap ? fi->ap->key : NULL), ts->notifyData); - } - break; - case FSM_UNDO: - if (fsm->postpone) - break; - if (fsm->goal == FSM_PKGINSTALL) { - (void) fsmStage(fsm, - (S_ISDIR(st->st_mode) ? FSM_RMDIR : FSM_UNLINK)); - -#ifdef NOTYET /* XXX remove only dirs just created, not all. */ - if (fsm->dnlx) - (void) fsmStage(fsm, FSM_RMDIRS); -#endif - errno = saveerrno; - } - if (fsm->failedFile && *fsm->failedFile == NULL) - *fsm->failedFile = xstrdup(fsm->path); - break; - case FSM_FINI: - if (!fsm->postpone && fsm->commit) { - if (fsm->goal == FSM_PKGINSTALL) - rc = ((!S_ISDIR(st->st_mode) && st->st_nlink > 1) - ? fsmCommitLinks(fsm) : fsmStage(fsm, FSM_COMMIT)); - if (fsm->goal == FSM_PKGCOMMIT) - rc = fsmStage(fsm, FSM_COMMIT); - if (fsm->goal == FSM_PKGERASE) - rc = fsmStage(fsm, FSM_COMMIT); - } - fsm->path = _free(fsm->path); - fsm->opath = _free(fsm->opath); - memset(st, 0, sizeof(*st)); - memset(ost, 0, sizeof(*ost)); - break; - case FSM_COMMIT: - /* Rename pre-existing modified or unmanaged file. */ - if (fsm->diskchecked && fsm->exists && fsm->osuffix) { - const char * opath = fsm->opath; - const char * path = fsm->path; - fsm->opath = fsmFsPath(fsm, st, NULL, NULL); - fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); - rc = fsmStage(fsm, FSM_RENAME); - if (!rc) { - rpmMessage(RPMMESS_WARNING, _("%s saved as %s\n"), - fsm->opath, fsm->path); - } - fsm->path = _free(fsm->path); - fsm->path = path; - fsm->opath = _free(fsm->opath); - fsm->opath = opath; - } - - /* Remove erased files. */ - if (fsm->goal == FSM_PKGERASE) { - if (fsm->action == FA_ERASE) { - TFI_t fi = fsmGetFi(fsm); - if (S_ISDIR(st->st_mode)) { - rc = fsmStage(fsm, FSM_RMDIR); - if (!rc) break; - switch (errno) { - case ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */ - case ENOTEMPTY: - /* XXX make sure that build side permits %missingok on directories. */ - if (fsm->fflags & RPMFILE_MISSINGOK) - break; - - /* XXX common error message. */ - rpmError(RPMERR_RMDIR, - _("%s rmdir of %s failed: Directory not empty\n"), - fiTypeString(fi), fsm->path); - break; - default: - rpmError(RPMERR_RMDIR, - _("%s rmdir of %s failed: %s\n"), - fiTypeString(fi), fsm->path, strerror(errno)); - break; - } - } else { - rc = fsmStage(fsm, FSM_UNLINK); - if (!rc) break; - if (!(errno == ENOENT && (fsm->fflags & RPMFILE_MISSINGOK))) - rpmError(RPMERR_UNLINK, - _("%s unlink of %s failed: %s\n"), - fiTypeString(fi), fsm->path, strerror(errno)); - } - } - break; - } - - if (!S_ISSOCK(st->st_mode)) { /* XXX /dev/log et al are skipped */ - /* Rename temporary to final file name. */ - if (!S_ISDIR(st->st_mode) && - (fsm->subdir || fsm->suffix || fsm->nsuffix)) - { - fsm->opath = fsm->path; - fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix); - rc = fsmStage(fsm, FSM_RENAME); - if (!rc && fsm->nsuffix) { - const char * opath = fsmFsPath(fsm, st, NULL, NULL); - rpmMessage(RPMMESS_WARNING, _("%s created as %s\n"), - opath, fsm->path); - opath = _free(opath); - } - fsm->opath = _free(fsm->opath); - } - if (S_ISLNK(st->st_mode)) { - if (!rc && !getuid()) - rc = fsmStage(fsm, FSM_LCHOWN); - } else { - if (!rc && !getuid()) - rc = fsmStage(fsm, FSM_CHOWN); - if (!rc) - rc = fsmStage(fsm, FSM_CHMOD); - if (!rc) { - time_t st_mtime = st->st_mtime; - TFI_t fi = fsmGetFi(fsm); - if (fi->fmtimes) - st->st_mtime = fi->fmtimes[fsm->ix]; - rc = fsmStage(fsm, FSM_UTIME); - st->st_mtime = st_mtime; - } - } - } - - /* Notify on success. */ - if (!rc) rc = fsmStage(fsm, FSM_NOTIFY); - break; - case FSM_DESTROY: - fsm->path = _free(fsm->path); - - /* Create any remaining links (if no error), and clean up. */ - while ((fsm->li = fsm->links) != NULL) { - fsm->links = fsm->li->next; - fsm->li->next = NULL; - if (fsm->goal == FSM_PKGINSTALL && fsm->commit && fsm->li->linksLeft) - { - for (i = 0 ; i < fsm->li->linksLeft; i++) { - if (fsm->li->filex[i] < 0) continue; - rc = CPIOERR_MISSING_HARDLINK; - if (fsm->failedFile && *fsm->failedFile == NULL) { - fsm->ix = fsm->li->filex[i]; - if (!fsmStage(fsm, FSM_MAP)) { - *fsm->failedFile = fsm->path; - fsm->path = NULL; - } - } - break; - } - } - if (fsm->goal == FSM_PKGBUILD) { - rc = CPIOERR_MISSING_HARDLINK; - } - fsm->li = freeHardLink(fsm->li); - } - fsm->ldn = _free(fsm->ldn); - fsm->ldnalloc = fsm->ldnlen = 0; - fsm->rdbuf = fsm->rdb = _free(fsm->rdb); - fsm->wrbuf = fsm->wrb = _free(fsm->wrb); - break; - case FSM_VERIFY: - if (fsm->diskchecked && !fsm->exists) { - rc = CPIOERR_LSTAT_FAILED; - break; - } - if (S_ISREG(st->st_mode)) { - char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE")); - (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE"); - /* - * XXX HP-UX (and other os'es) don't permit unlink on busy - * XXX files. - */ - fsm->opath = fsm->path; - fsm->path = path; - rc = fsmStage(fsm, FSM_RENAME); - if (!rc) - (void) fsmStage(fsm, FSM_UNLINK); - else - rc = CPIOERR_UNLINK_FAILED; - fsm->path = fsm->opath; - fsm->opath = NULL; - return (rc ? rc : CPIOERR_LSTAT_FAILED); /* XXX HACK */ - /*@notreached@*/ break; - } else if (S_ISDIR(st->st_mode)) { - if (S_ISDIR(ost->st_mode)) return 0; - if (S_ISLNK(ost->st_mode)) { - rc = fsmStage(fsm, FSM_STAT); - if (rc == CPIOERR_STAT_FAILED && errno == ENOENT) rc = 0; - if (rc) break; - errno = saveerrno; - if (S_ISDIR(ost->st_mode)) return 0; - } - } else if (S_ISLNK(st->st_mode)) { - if (S_ISLNK(ost->st_mode)) { - /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ - rc = fsmStage(fsm, FSM_READLINK); - errno = saveerrno; - if (rc) break; - if (!strcmp(fsm->opath, fsm->rdbuf)) return 0; - } - } else if (S_ISFIFO(st->st_mode)) { - if (S_ISFIFO(ost->st_mode)) return 0; - } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { - if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) && - (ost->st_rdev == st->st_rdev)) return 0; - } else if (S_ISSOCK(st->st_mode)) { - if (S_ISSOCK(ost->st_mode)) return 0; - } - /* XXX shouldn't do this with commit/undo. */ - rc = 0; - if (fsm->stage == FSM_PROCESS) rc = fsmStage(fsm, FSM_UNLINK); - if (rc == 0) rc = CPIOERR_LSTAT_FAILED; - return (rc ? rc : CPIOERR_LSTAT_FAILED); /* XXX HACK */ - /*@notreached@*/ break; - - case FSM_UNLINK: - rc = Unlink(fsm->path); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur, - fsm->path, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_UNLINK_FAILED; - break; - case FSM_RENAME: - rc = Rename(fsm->opath, fsm->path); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, - fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_RENAME_FAILED; - break; - case FSM_MKDIR: - rc = Mkdir(fsm->path, (st->st_mode & 07777)); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, - fsm->path, (st->st_mode & 07777), - (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_MKDIR_FAILED; - break; - case FSM_RMDIR: - rc = Rmdir(fsm->path); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur, - fsm->path, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_RMDIR_FAILED; - break; - case FSM_CHOWN: - rc = chown(fsm->path, st->st_uid, st->st_gid); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur, - fsm->path, st->st_uid, st->st_gid, - (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_CHOWN_FAILED; - break; - case FSM_LCHOWN: -#if ! CHOWN_FOLLOWS_SYMLINK - rc = lchown(fsm->path, st->st_uid, st->st_gid); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur, - fsm->path, st->st_uid, st->st_gid, - (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_CHOWN_FAILED; -#endif - break; - case FSM_CHMOD: - rc = chmod(fsm->path, (st->st_mode & 07777)); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, - fsm->path, (st->st_mode & 07777), - (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_CHMOD_FAILED; - break; - case FSM_UTIME: - { struct utimbuf stamp; - stamp.actime = st->st_mtime; - stamp.modtime = st->st_mtime; - rc = utime(fsm->path, &stamp); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0x%x) %s\n", cur, - fsm->path, (unsigned)st->st_mtime, - (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_UTIME_FAILED; - } - break; - case FSM_SYMLINK: - rc = symlink(fsm->opath, fsm->path); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, - fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_SYMLINK_FAILED; - break; - case FSM_LINK: - rc = Link(fsm->opath, fsm->path); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, - fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_LINK_FAILED; - break; - case FSM_MKFIFO: - rc = mkfifo(fsm->path, (st->st_mode & 07777)); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, - fsm->path, (st->st_mode & 07777), - (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_MKFIFO_FAILED; - break; - case FSM_MKNOD: - /*@-unrecog@*/ - rc = mknod(fsm->path, (st->st_mode & ~07777), st->st_rdev); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur, - fsm->path, (st->st_mode & ~07777), (unsigned)st->st_rdev, - (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_MKNOD_FAILED; - /*@=unrecog@*/ - break; - case FSM_LSTAT: - rc = Lstat(fsm->path, ost); - if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur, - fsm->path, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_LSTAT_FAILED; - break; - case FSM_STAT: - rc = Stat(fsm->path, ost); - if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur, - fsm->path, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_STAT_FAILED; - break; - case FSM_READLINK: - /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ - rc = Readlink(fsm->path, fsm->rdbuf, fsm->rdsize - 1); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur, - fsm->path, fsm->rdlen, (rc < 0 ? strerror(errno) : "")); - if (rc < 0) rc = CPIOERR_READLINK_FAILED; - else { - fsm->rdnb = rc; - fsm->rdbuf[fsm->rdnb] = '\0'; - rc = 0; - } - break; - case FSM_CHROOT: - break; - - case FSM_NEXT: - rc = fsmStage(fsm, FSM_HREAD); - if (rc) break; - if (!strcmp(fsm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */ - fsm->path = _free(fsm->path); - rc = CPIOERR_HDR_TRAILER; - } - if (!rc) - rc = fsmStage(fsm, FSM_POS); - break; - case FSM_EAT: - for (left = st->st_size; left > 0; left -= fsm->rdnb) { - fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); - rc = fsmStage(fsm, FSM_DREAD); - if (rc) break; - } - break; - case FSM_POS: - left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo; - if (left) { - fsm->wrlen = left; - (void) fsmStage(fsm, FSM_DREAD); - } - break; - case FSM_PAD: - left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo; - if (left) { - memset(fsm->rdbuf, 0, left); - /* XXX DWRITE uses rdnb for I/O length. */ - fsm->rdnb = left; - (void) fsmStage(fsm, FSM_DWRITE); - } - break; - case FSM_TRAILER: - rc = cpioTrailerWrite(fsm); - break; - case FSM_HREAD: - rc = fsmStage(fsm, FSM_POS); - if (!rc) - rc = cpioHeaderRead(fsm, st); /* Read next payload header. */ - break; - case FSM_HWRITE: - rc = cpioHeaderWrite(fsm, st); /* Write next payload header. */ - break; - case FSM_DREAD: - fsm->rdnb = Fread(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->wrlen, fsm->cfd); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n", - cur, (fsm->wrbuf == fsm->wrb ? "wrbuf" : "mmap"), - fsm->wrlen, fsm->rdnb); -if (fsm->rdnb != fsm->wrlen) fprintf(stderr, "*** short read, had %d, got %d\n", (int)fsm->rdnb, (int)fsm->wrlen); -#ifdef NOTYET - if (Ferror(fsm->rfd)) - rc = CPIOERR_READ_FAILED; -#endif - if (fsm->rdnb > 0) - fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->rdnb); - break; - case FSM_DWRITE: - fsm->wrnb = Fwrite(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdnb, fsm->cfd); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n", - cur, (fsm->rdbuf == fsm->rdb ? "rdbuf" : "mmap"), - fsm->rdnb, fsm->wrnb); -if (fsm->rdnb != fsm->wrnb) fprintf(stderr, "*** short write, had %d, got %d\n", (int)fsm->rdnb, (int)fsm->wrnb); -#ifdef NOTYET - if (Ferror(fsm->wfd)) - rc = CPIOERR_WRITE_FAILED; -#endif - if (fsm->wrnb > 0) - fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->wrnb); - break; - - case FSM_ROPEN: - fsm->rfd = Fopen(fsm->path, "r.ufdio"); - if (fsm->rfd == NULL || Ferror(fsm->rfd)) { - if (fsm->rfd) (void) fsmStage(fsm, FSM_RCLOSE); - fsm->rfd = NULL; - rc = CPIOERR_OPEN_FAILED; - break; - } - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur, - fsm->path, fsm->rfd, fsm->rdbuf); - break; - case FSM_READ: - fsm->rdnb = Fread(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdlen, fsm->rfd); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n", - cur, fsm->rdlen, fsm->rdnb); -if (fsm->rdnb != fsm->rdlen) fprintf(stderr, "*** short read, had %d, got %d\n", (int)fsm->rdnb, (int)fsm->rdlen); -#ifdef NOTYET - if (Ferror(fsm->rfd)) - rc = CPIOERR_READ_FAILED; -#endif - break; - case FSM_RCLOSE: - if (fsm->rfd) { - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->rfd); - (void) Fclose(fsm->rfd); - errno = saveerrno; - } - fsm->rfd = NULL; - break; - case FSM_WOPEN: - fsm->wfd = Fopen(fsm->path, "w.ufdio"); - if (fsm->wfd == NULL || Ferror(fsm->wfd)) { - if (fsm->wfd) (void) fsmStage(fsm, FSM_WCLOSE); - fsm->wfd = NULL; - rc = CPIOERR_OPEN_FAILED; - } - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur, - fsm->path, fsm->wfd, fsm->wrbuf); - break; - case FSM_WRITE: - fsm->wrnb = Fwrite(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->rdnb, fsm->wfd); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n", - cur, fsm->rdnb, fsm->wrnb); -if (fsm->rdnb != fsm->wrnb) fprintf(stderr, "*** short write: had %d, got %d\n", (int)fsm->rdnb, (int)fsm->wrnb); -#ifdef NOTYET - if (Ferror(fsm->wfd)) - rc = CPIOERR_WRITE_FAILED; -#endif - break; - case FSM_WCLOSE: - if (fsm->wfd) { - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->wfd); - (void) Fclose(fsm->wfd); - errno = saveerrno; - } - fsm->wfd = NULL; - break; - - default: - break; - } - - if (!(stage & FSM_INTERNAL)) { - fsm->rc = (rc == CPIOERR_HDR_TRAILER ? 0 : rc); - } - return rc; -} - const char *const cpioStrerror(int rc) { static char msg[256]; diff --git a/lib/fsm.c b/lib/fsm.c new file mode 100644 index 0000000..195cc17 --- /dev/null +++ b/lib/fsm.c @@ -0,0 +1,1905 @@ +/** \ingroup payload + * \file lib/fsm.c + * Handle payloads within rpm packages. + */ + +#include "system.h" + +#include "psm.h" +#include "rpmerr.h" +#include "debug.h" + +/*@access FD_t @*/ +/*@access rpmTransactionSet @*/ +/*@access TFI_t @*/ +/*@access FSM_t @*/ + +#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) + +/** + * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL. + * @param this memory to free + * @retval NULL always + */ +static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) { + if (this) free((void *)this); + return NULL; +} + +int _fsm_debug = 0; + +rpmTransactionSet fsmGetTs(const FSM_t fsm) { + const FSMI_t iter = fsm->iter; + return (iter ? iter->ts : NULL); +} + +TFI_t fsmGetFi(const FSM_t fsm) { + const FSMI_t iter = fsm->iter; + return (iter ? iter->fi : NULL); +} + +#define SUFFIX_RPMORIG ".rpmorig" +#define SUFFIX_RPMSAVE ".rpmsave" +#define SUFFIX_RPMNEW ".rpmnew" + +/** \ingroup payload + * Build path to file from file info, ornamented with subdir and suffix. + * @param fsm file state machine data + * @param st file stat info + * @param subdir subdir to use (NULL disables) + * @param suffix suffix to use (NULL disables) + * @retval path to file + */ +static /*@only@*//*@null@*/ const char * fsmFsPath(/*@null@*/ const FSM_t fsm, + /*@null@*/ const struct stat * st, + /*@null@*/ const char * subdir, + /*@null@*/ const char * suffix) +{ + const char * s = NULL; + + if (fsm) { + int nb; + char * t; + nb = strlen(fsm->dirName) + + (st && subdir && !S_ISDIR(st->st_mode) ? strlen(subdir) : 0) + + (st && suffix && !S_ISDIR(st->st_mode) ? strlen(suffix) : 0) + + strlen(fsm->baseName) + 1; + s = t = xmalloc(nb); + t = stpcpy(t, fsm->dirName); + if (st && subdir && !S_ISDIR(st->st_mode)) + t = stpcpy(t, subdir); + t = stpcpy(t, fsm->baseName); + if (st && suffix && !S_ISDIR(st->st_mode)) + t = stpcpy(t, suffix); + } + return s; +} + +/** \ingroup payload + * Destroy file info iterator. + * @retval NULL always + */ +static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/const void * this) { + return _free((void *)this); +} + +/** \ingroup payload + */ +static void * +mapInitIterator(/*@kept@*/ const void * this, /*@kept@*/ const void * that) +{ + rpmTransactionSet ts = (void *)this; + TFI_t fi = (void *)that; + FSMI_t iter = NULL; + + iter = xcalloc(1, sizeof(*iter)); + iter->ts = ts; + iter->fi = fi; + switch (fi->type) { + case TR_ADDED: iter->i = 0; break; + case TR_REMOVED: iter->i = fi->fc - 1; break; + } + iter->isave = iter->i; + return iter; +} + +/** \ingroup payload + */ +static int mapNextIterator(void * this) { + FSMI_t iter = this; + const TFI_t fi = iter->fi; + int i = -1; + + switch (fi->type) { + case TR_ADDED: if (iter->i < fi->fc) i = iter->i++; break; + case TR_REMOVED: if (iter->i >= 0) i = iter->i--; break; + } + iter->isave = i; + return i; +} + +/** \ingroup payload + */ +typedef struct dnli_s { +/*@dependent@*/ TFI_t fi; +/*@only@*/ /*@null@*/ char * active; + int reverse; + int isave; + int i; +} * DNLI_t; + +/** \ingroup payload + */ +static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ const void * this) +{ + if (this) { + DNLI_t dnli = (void *)this; + if (dnli->active) free(dnli->active); + } + return _free(this); +} + +/** \ingroup payload + */ +static inline int dnlCount(const DNLI_t dnli) { + return (dnli ? dnli->fi->dc : 0); +} + +/** \ingroup payload + */ +static inline int dnlIndex(const DNLI_t dnli) { + return (dnli ? dnli->isave : -1); +} + +/** \ingroup payload + * @param fsm file state machine data + */ +static /*@only@*/ void * dnlInitIterator(const FSM_t fsm, int reverse) +{ + TFI_t fi = fsmGetFi(fsm); + DNLI_t dnli; + int i, j; + + if (fi == NULL) + return NULL; + dnli = xcalloc(1, sizeof(*dnli)); + dnli->fi = fi; + dnli->reverse = reverse; + dnli->i = (reverse ? fi->dc : 0); + + if (fi->dc) { + dnli->active = xcalloc(fi->dc, sizeof(*dnli->active)); + + /* Identify parent directories not skipped. */ + for (i = 0; i < fi->fc; i++) + if (!XFA_SKIPPING(fi->actions[i])) dnli->active[fi->dil[i]] = 1; + + /* Exclude parent directories that are explicitly included. */ + for (i = 0; i < fi->fc; i++) { + int dil, dnlen, bnlen; + + if (!S_ISDIR(fi->fmodes[i])) + continue; + + dil = fi->dil[i]; + dnlen = strlen(fi->dnl[dil]); + bnlen = strlen(fi->bnl[i]); + + for (j = 0; j < fi->dc; j++) { + const char * dnl; + int jlen; + + if (!dnli->active[j] || j == dil) continue; + dnl = fi->dnl[j]; + jlen = strlen(dnl); + if (jlen != (dnlen+bnlen+1)) continue; + if (strncmp(dnl, fi->dnl[dil], dnlen)) continue; + if (strncmp(dnl+dnlen, fi->bnl[i], bnlen)) continue; + if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') + continue; + /* This directory is included in the package. */ + dnli->active[j] = 0; + break; + } + } + + /* Print only once per package. */ + if (!reverse) { + j = 0; + for (i = 0; i < fi->dc; i++) { + if (!dnli->active[i]) continue; + if (j == 0) { + j = 1; + rpmMessage(RPMMESS_DEBUG, + _("========= Directories not explictly included in package:\n")); + } + rpmMessage(RPMMESS_DEBUG, _("%9d %s\n"), i, fi->dnl[i]); + } + if (j) + rpmMessage(RPMMESS_DEBUG, "=========\n"); + } + } + return dnli; +} + +/** \ingroup payload + */ +static const char * dnlNextIterator(/*@null@*/ DNLI_t dnli) { + const char * dn = NULL; + + if (dnli && dnli->active) { + TFI_t fi = dnli->fi; + int i = -1; + + do { + i = (!dnli->reverse ? dnli->i++ : --dnli->i); + } while (i >= 0 && i < fi->dc && !dnli->active[i]); + + if (i >= 0 && i < fi->dc) + dn = fi->dnl[i]; + else + i = -1; + dnli->isave = i; + } + return dn; +} + +/** \ingroup payload + */ +static int cpioStrCmp(const void * a, const void * b) { + const char * afn = *(const char **)a; + const char * bfn = *(const char **)b; + + /* Match rpm-4.0 payloads with ./ prefixes. */ + if (afn[0] == '.' && afn[1] == '/') afn += 2; + if (bfn[0] == '.' && bfn[1] == '/') bfn += 2; + + /* If either path is absolute, make it relative. */ + if (afn[0] == '/') afn += 1; + if (bfn[0] == '/') bfn += 1; + + return strcmp(afn, bfn); +} + +/** \ingroup payload + */ +static int mapFind(void * this, const char * fsmPath) { + FSMI_t iter = this; + const TFI_t fi = iter->fi; + int ix = -1; + + if (fi) { + const char ** p; + + p = bsearch(&fsmPath, fi->apath, fi->fc, sizeof(fsmPath), cpioStrCmp); + if (p == NULL) { + fprintf(stderr, "*** not mapped %s\n", fsmPath); + } else { + iter->i = p - fi->apath; + ix = mapNextIterator(iter); + } + } + return ix; +} + +/** \ingroup payload + * Save hard link in chain. + * @param fsm file state machine data + * @return Is chain only partially filled? + */ +static int saveHardLink(FSM_t fsm) +{ + struct stat * st = &fsm->sb; + int rc = 0; + int ix = -1; + int j; + + /* Find hard link set. */ + for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { + if (fsm->li->inode == st->st_ino && fsm->li->dev == st->st_dev) + break; + } + + /* New hard link encountered, add new link to set. */ + if (fsm->li == NULL) { + fsm->li = xcalloc(1, sizeof(*fsm->li)); + fsm->li->next = NULL; + fsm->li->nlink = st->st_nlink; + fsm->li->dev = st->st_dev; + fsm->li->inode = st->st_ino; + fsm->li->linkIndex = -1; + fsm->li->createdPath = -1; + + fsm->li->filex = xcalloc(st->st_nlink, sizeof(fsm->li->filex[0])); + memset(fsm->li->filex, -1, (st->st_nlink * sizeof(fsm->li->filex[0]))); + fsm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*fsm->li->nsuffix)); + + if (fsm->goal == FSM_PKGBUILD) + fsm->li->linksLeft = st->st_nlink; + if (fsm->goal == FSM_PKGINSTALL) + fsm->li->linksLeft = 0; + + fsm->li->next = fsm->links; + fsm->links = fsm->li; + } + + if (fsm->goal == FSM_PKGBUILD) --fsm->li->linksLeft; + fsm->li->filex[fsm->li->linksLeft] = fsm->ix; + /*@-observertrans@*/ + fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix; + /*@=observertrans@*/ + if (fsm->goal == FSM_PKGINSTALL) fsm->li->linksLeft++; + +#if 0 +fprintf(stderr, "*** %p link[%d:%d] %d filex %d %s\n", fsm->li, fsm->li->linksLeft, st->st_nlink, (int)st->st_size, fsm->li->filex[fsm->li->linksLeft], fsm->li->files[fsm->li->linksLeft]); +#endif + + if (fsm->goal == FSM_PKGBUILD) + return (fsm->li->linksLeft > 0); + + if (fsm->goal != FSM_PKGINSTALL) + return 0; + + if (!(st->st_size || fsm->li->linksLeft == st->st_nlink)) + return 1; + + /* Here come the bits, time to choose a non-skipped file name. */ + { TFI_t fi = fsmGetFi(fsm); + + for (j = fsm->li->linksLeft - 1; j >= 0; j--) { + ix = fsm->li->filex[j]; + if (ix < 0 || XFA_SKIPPING(fi->actions[ix])) + continue; + break; + } + } + + /* Are all links skipped or not encountered yet? */ + if (ix < 0 || j < 0) + return 1; /* XXX W2DO? */ + + /* Save the non-skipped file name and map index. */ + fsm->li->linkIndex = j; + fsm->path = _free(fsm->path); + fsm->ix = ix; + rc = fsmStage(fsm, FSM_MAP); + return rc; +} + +/** \ingroup payload + * Destroy set of hard links. + * @param li set of hard links + */ +static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ struct hardLink * li) +{ + if (li) { + li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */ + li->filex = _free(li->filex); + } + return _free(li); +} + +FSM_t newFSM(void) { + FSM_t fsm = xcalloc(1, sizeof(*fsm)); + return fsm; +} + +FSM_t freeFSM(FSM_t fsm) +{ + if (fsm) { + if (fsm->path) free((void *)fsm->path); + while ((fsm->li = fsm->links) != NULL) { + fsm->links = fsm->li->next; + fsm->li->next = NULL; + fsm->li = freeHardLink(fsm->li); + } + fsm->dnlx = _free(fsm->dnlx); + fsm->ldn = _free(fsm->ldn); + fsm->iter = mapFreeIterator(fsm->iter); + } + return _free(fsm); +} + +int fsmSetup(FSM_t fsm, fileStage goal, + const rpmTransactionSet ts, const TFI_t fi, FD_t cfd, + unsigned int * archiveSize, const char ** failedFile) +{ + size_t pos = 0; + int rc; + + fsm->goal = goal; + if (cfd) { + fsm->cfd = fdLink(cfd, "persist (fsm)"); + pos = fdGetCpioPos(fsm->cfd); + fdSetCpioPos(fsm->cfd, 0); + } + fsm->iter = mapInitIterator(ts, fi); + + if (fsm->goal == FSM_PKGINSTALL) { + if (ts && ts->notify) { + (void)ts->notify(fi->h, RPMCALLBACK_INST_START, 0, fi->archiveSize, + (fi->ap ? fi->ap->key : NULL), ts->notifyData); + } + } + + fsm->archiveSize = archiveSize; + if (fsm->archiveSize) + *fsm->archiveSize = 0; + fsm->failedFile = failedFile; + if (fsm->failedFile) + *fsm->failedFile = NULL; + + memset(fsm->sufbuf, 0, sizeof(fsm->sufbuf)); + if (fsm->goal == FSM_PKGINSTALL) { + if (ts->id > 0) + sprintf(fsm->sufbuf, ";%08x", (unsigned)ts->id); + } + + rc = fsm->rc = 0; + rc = fsmStage(fsm, FSM_CREATE); + + rc = fsmStage(fsm, fsm->goal); + + if (!rc && fsm->archiveSize) + *fsm->archiveSize = (fdGetCpioPos(fsm->cfd) - pos); + + return rc; +} + +int fsmTeardown(FSM_t fsm) { + int rc = fsm->rc; + + if (!rc) + rc = fsmStage(fsm, FSM_DESTROY); + + fsm->iter = mapFreeIterator(fsm->iter); + if (fsm->cfd) { + fsm->cfd = fdFree(fsm->cfd, "persist (fsm)"); + fsm->cfd = NULL; + } + fsm->failedFile = NULL; + return rc; +} + +int fsmMapPath(FSM_t fsm) +{ + TFI_t fi = fsmGetFi(fsm); /* XXX const except for fstates */ + int rc = 0; + int i; + + fsm->osuffix = NULL; + fsm->nsuffix = NULL; + fsm->astriplen = 0; + fsm->action = FA_UNKNOWN; + fsm->mapFlags = 0; + + i = fsm->ix; + if (fi && i >= 0 && i < fi->fc) { + + fsm->astriplen = fi->astriplen; + fsm->action = (fi->actions ? fi->actions[i] : fi->action); + fsm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags); + fsm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi->mapflags); + + /* src rpms have simple base name in payload. */ + fsm->archivePath = + (fi->apath ? fi->apath[i] + fi->striplen : fi->bnl[i]); + fsm->dirName = fi->dnl[fi->dil[i]]; + fsm->baseName = fi->bnl[i]; + + switch (fsm->action) { + case FA_SKIP: + break; + case FA_SKIPMULTILIB: /* XXX RPMFILE_STATE_MULTILIB? */ +fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); + break; + case FA_UNKNOWN: +fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); + break; + + case FA_CREATE: + assert(fi->type == TR_ADDED); + break; + + case FA_SKIPNSTATE: +fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); + if (fi->type == TR_ADDED) + fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED; + break; + + case FA_SKIPNETSHARED: + if (fi->type == TR_ADDED) + fi->fstates[i] = RPMFILE_STATE_NETSHARED; + break; + + case FA_BACKUP: +fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); + switch (fi->type) { + case TR_ADDED: + fsm->osuffix = SUFFIX_RPMORIG; + break; + case TR_REMOVED: + fsm->osuffix = SUFFIX_RPMSAVE; + break; + } + break; + + case FA_ALTNAME: + assert(fi->type == TR_ADDED); + fsm->nsuffix = SUFFIX_RPMNEW; + break; + + case FA_SAVE: +fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); + assert(fi->type == TR_ADDED); + fsm->osuffix = SUFFIX_RPMSAVE; + break; + case FA_ERASE: + assert(fi->type == TR_REMOVED); + break; + default: +fprintf(stderr, "*** %s:%s %s\n", fiTypeString(fi), fileActionString(fsm->action), (fsm->path ? fsm->path : "")); + break; + } + + if ((fsm->mapFlags & CPIO_MAP_PATH) || fsm->nsuffix) { + const struct stat * st = &fsm->sb; + fsm->path = _free(fsm->path); + fsm->path = fsmFsPath(fsm, st, fsm->subdir, + (fsm->suffix ? fsm->suffix : fsm->nsuffix)); + } + } + return rc; +} + +int fsmMapAttrs(FSM_t fsm) +{ + struct stat * st = &fsm->sb; + TFI_t fi = fsmGetFi(fsm); + int i = fsm->ix; + + if (fi && i >= 0 && i < fi->fc) { + mode_t perms = + (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms); + mode_t finalMode = + (fi->fmodes ? fi->fmodes[i] : perms); + uid_t finalUid = + (fi->fuids ? fi->fuids[i] : fi->uid); /* XXX chmod u-s */ + gid_t finalGid = + (fi->fgids ? fi->fgids[i] : fi->gid); /* XXX chmod g-s */ + + if (fsm->mapFlags & CPIO_MAP_MODE) + st->st_mode = (st->st_mode & S_IFMT) | finalMode; + if (fsm->mapFlags & CPIO_MAP_UID) + st->st_uid = finalUid; + if (fsm->mapFlags & CPIO_MAP_GID) + st->st_gid = finalGid; + + fsm->fmd5sum = (fi->fmd5s ? fi->fmd5s[i] : NULL); + + } + return 0; +} + +/** \ingroup payload + * Create file from payload stream. + * @todo Legacy: support brokenEndian MD5 checks? + * @param fsm file state machine data + * @return 0 on success + */ +static int expandRegular(FSM_t fsm) + /*@modifies fileSystem, fsm @*/ +{ + const char * fmd5sum; + const struct stat * st = &fsm->sb; + int left = st->st_size; + int rc = 0; + + rc = fsmStage(fsm, FSM_WOPEN); + if (rc) + goto exit; + + /* XXX md5sum's will break on repackaging that includes modified files. */ + fmd5sum = fsm->fmd5sum; + + /* XXX This doesn't support brokenEndian checks. */ + if (st->st_size > 0 && fmd5sum) + fdInitMD5(fsm->wfd, 0); + + while (left) { + + fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); + rc = fsmStage(fsm, FSM_DREAD); + if (rc) + goto exit; + + rc = fsmStage(fsm, FSM_WRITE); + if (rc) + goto exit; + + left -= fsm->wrnb; + + /* don't call this with fileSize == fileComplete */ + if (!rc && left) + (void) fsmStage(fsm, FSM_NOTIFY); + } + + if (st->st_size > 0 && fmd5sum) { + const char * md5sum = NULL; + + Fflush(fsm->wfd); + fdFiniMD5(fsm->wfd, (void **)&md5sum, NULL, 1); + + if (md5sum == NULL) { + rc = CPIOERR_MD5SUM_MISMATCH; + } else { + if (strcmp(md5sum, fmd5sum)) + rc = CPIOERR_MD5SUM_MISMATCH; + md5sum = _free(md5sum); + } + } + +exit: + (void) fsmStage(fsm, FSM_WCLOSE); + return rc; +} + +/** \ingroup payload + * Write next item to payload stream. + * @param fsm file state machine data + * @param writeData should data be written? + * @return 0 on success + */ +static int writeFile(FSM_t fsm, int writeData) + /*@modifies fsm @*/ +{ + const char * path = fsm->path; + const char * opath = fsm->opath; + struct stat * st = &fsm->sb; + struct stat * ost = &fsm->osb; + size_t pos = fdGetCpioPos(fsm->cfd); + int left; + int rc; + + st->st_size = (writeData ? ost->st_size : 0); + if (S_ISDIR(st->st_mode)) { + st->st_size = 0; + } else if (S_ISLNK(st->st_mode)) { + /* + * While linux puts the size of a symlink in the st_size field, + * I don't think that's a specified standard. + */ + /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ + rc = fsmStage(fsm, FSM_READLINK); + if (rc) goto exit; + st->st_size = fsm->rdnb; + } + + if (fsm->mapFlags & CPIO_MAP_PATH) + fsm->path = fsm->archivePath; + rc = fsmStage(fsm, FSM_HWRITE); + fsm->path = path; + if (rc) goto exit; + + if (writeData && S_ISREG(st->st_mode)) { +#if HAVE_MMAP + char * rdbuf = NULL; + void * mapped = (void *)-1; + size_t nmapped; +#endif + + rc = fsmStage(fsm, FSM_ROPEN); + if (rc) goto exit; + + /* XXX unbuffered mmap generates *lots* of fdio debugging */ +#if HAVE_MMAP + nmapped = 0; + mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(fsm->rfd), 0); + if (mapped != (void *)-1) { + rdbuf = fsm->rdbuf; + fsm->rdbuf = (char *) mapped; + fsm->rdlen = nmapped = st->st_size; + } +#endif + + left = st->st_size; + + while (left) { +#if HAVE_MMAP + if (mapped != (void *)-1) { + fsm->rdnb = nmapped; + } else +#endif + { + fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left), + rc = fsmStage(fsm, FSM_READ); + if (rc) goto exit; + } + + /* XXX DWRITE uses rdnb for I/O length. */ + rc = fsmStage(fsm, FSM_DWRITE); + if (rc) goto exit; + + left -= fsm->wrnb; + } + +#if HAVE_MMAP + if (mapped != (void *)-1) { + /*@-noeffect@*/ munmap(mapped, nmapped) /*@=noeffect@*/; + fsm->rdbuf = rdbuf; + } +#endif + + } else if (writeData && S_ISLNK(st->st_mode)) { + /* XXX DWRITE uses rdnb for I/O length. */ + rc = fsmStage(fsm, FSM_DWRITE); + if (rc) goto exit; + } + + rc = fsmStage(fsm, FSM_PAD); + if (rc) goto exit; + + { const rpmTransactionSet ts = fsmGetTs(fsm); + TFI_t fi = fsmGetFi(fsm); + if (ts && fi && ts->notify) { + size_t size = (fdGetCpioPos(fsm->cfd) - pos); + (void)ts->notify(fi->h, RPMCALLBACK_INST_PROGRESS, size, size, + (fi->ap ? fi->ap->key : NULL), ts->notifyData); + } + } + + rc = 0; + +exit: + if (fsm->rfd) + (void) fsmStage(fsm, FSM_RCLOSE); + fsm->opath = opath; + fsm->path = path; + return rc; +} + +/** \ingroup payload + * Write set of linked files to payload stream. + * @param fsm file state machine data + * @return 0 on success + */ +static int writeLinkedFile(FSM_t fsm) + /*@modifies fsm @*/ +{ + const char * path = fsm->path; + const char * nsuffix = fsm->nsuffix; + int iterIndex = fsm->ix; + int ec = 0; + int rc; + int i; + + fsm->path = NULL; + fsm->nsuffix = NULL; + fsm->ix = -1; + + for (i = fsm->li->nlink - 1; i >= 0; i--) { + if (fsm->li->filex[i] < 0) continue; + + fsm->ix = fsm->li->filex[i]; + rc = fsmStage(fsm, FSM_MAP); + + /* Write data after last link. */ + rc = writeFile(fsm, (i == 0)); + if (rc && fsm->failedFile && *fsm->failedFile == NULL) { + ec = rc; + *fsm->failedFile = xstrdup(fsm->path); + } + + fsm->path = _free(fsm->path); + fsm->li->filex[i] = -1; + } + + fsm->ix = iterIndex; + fsm->nsuffix = nsuffix; + fsm->path = path; + return ec; +} + +/** \ingroup payload + * @param fsm file state machine data + */ +static int fsmMakeLinks(FSM_t fsm) +{ + const char * path = fsm->path; + const char * opath = fsm->opath; + const char * nsuffix = fsm->nsuffix; + int iterIndex = fsm->ix; + int ec = 0; + int rc; + int i; + + fsm->path = NULL; + fsm->opath = NULL; + fsm->nsuffix = NULL; + fsm->ix = -1; + + fsm->ix = fsm->li->filex[fsm->li->createdPath]; + rc = fsmStage(fsm, FSM_MAP); + fsm->opath = fsm->path; + fsm->path = NULL; + for (i = 0; i < fsm->li->nlink; i++) { + if (fsm->li->filex[i] < 0) continue; + if (i == fsm->li->createdPath) continue; + + fsm->ix = fsm->li->filex[i]; + rc = fsmStage(fsm, FSM_MAP); + rc = fsmStage(fsm, FSM_VERIFY); + if (!rc) continue; + if (rc != CPIOERR_LSTAT_FAILED) break; + + /* XXX link(fsm->opath, fsm->path) */ + rc = fsmStage(fsm, FSM_LINK); + if (rc && fsm->failedFile && *fsm->failedFile == NULL) { + ec = rc; + *fsm->failedFile = xstrdup(fsm->path); + } + + fsm->li->linksLeft--; + } + fsm->opath = _free(fsm->opath); + + fsm->ix = iterIndex; + fsm->nsuffix = nsuffix; + fsm->path = path; + fsm->opath = opath; + return ec; +} + +/** \ingroup payload + * @param fsm file state machine data + */ +static int fsmCommitLinks(FSM_t fsm) +{ + const char * path = fsm->path; + const char * nsuffix = fsm->nsuffix; + int iterIndex = fsm->ix; + struct stat * st = &fsm->sb; + int rc = 0; + int i; + + fsm->path = NULL; + fsm->nsuffix = NULL; + fsm->ix = -1; + + for (fsm->li = fsm->links; fsm->li; fsm->li = fsm->li->next) { + if (fsm->li->inode == st->st_ino && fsm->li->dev == st->st_dev) + break; + } + + for (i = 0; i < fsm->li->nlink; i++) { + if (fsm->li->filex[i] < 0) continue; + fsm->ix = fsm->li->filex[i]; + rc = fsmStage(fsm, FSM_MAP); + rc = fsmStage(fsm, FSM_COMMIT); + fsm->path = _free(fsm->path); + fsm->li->filex[i] = -1; + } + + fsm->ix = iterIndex; + fsm->nsuffix = nsuffix; + fsm->path = path; + return rc; +} + +int fsmStage(FSM_t fsm, fileStage stage) +{ +#ifdef UNUSED + fileStage prevStage = fsm->stage; + const char * const prev = fileStageString(prevStage); +#endif + static int modulo = 4; + const char * const cur = fileStageString(stage); + struct stat * st = &fsm->sb; + struct stat * ost = &fsm->osb; + int saveerrno = errno; + int rc = fsm->rc; + int left; + int i; + + if (stage & FSM_DEAD) { + /* do nothing */ + } else if (stage & FSM_INTERNAL) { + if (_fsm_debug && !(stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s %06o%3d (%4d,%4d)%10d %s %s\n", + cur, + st->st_mode, st->st_nlink, st->st_uid, st->st_gid, st->st_size, + (fsm->path ? fsm->path : ""), + ((fsm->action != FA_UNKNOWN && fsm->action != FA_CREATE) + ? fileActionString(fsm->action) : "")); + } else { + fsm->stage = stage; + if (_fsm_debug || !(stage & FSM_VERBOSE)) + rpmMessage(RPMMESS_DEBUG, "%-8s %06o%3d (%4d,%4d)%10d %s %s\n", + cur, + st->st_mode, st->st_nlink, st->st_uid, st->st_gid, st->st_size, + (fsm->path ? fsm->path + fsm->astriplen : ""), + ((fsm->action != FA_UNKNOWN && fsm->action != FA_CREATE) + ? fileActionString(fsm->action) : "")); + } + + switch (stage) { + case FSM_UNKNOWN: + break; + case FSM_PKGINSTALL: + while (1) { + /* Clean fsm, free'ing memory. Read next archive header. */ + rc = fsmStage(fsm, FSM_INIT); + + /* Exit on end-of-payload. */ + if (rc == CPIOERR_HDR_TRAILER) { + rc = 0; + break; + } + + /* Exit on error. */ + if (rc) { + fsm->postpone = 1; + (void) fsmStage(fsm, FSM_UNDO); + break; + } + + /* Extract file from archive. */ + rc = fsmStage(fsm, FSM_PROCESS); + if (rc) { + (void) fsmStage(fsm, FSM_UNDO); + break; + } + + /* Notify on success. */ + (void) fsmStage(fsm, FSM_NOTIFY); + + if (fsmStage(fsm, FSM_FINI)) + break; + } + break; + case FSM_PKGERASE: + case FSM_PKGCOMMIT: + while (1) { + /* Clean fsm, free'ing memory. */ + rc = fsmStage(fsm, FSM_INIT); + + /* Exit on end-of-payload. */ + if (rc == CPIOERR_HDR_TRAILER) { + rc = 0; + break; + } + + /* Rename/erase next item. */ + if (fsmStage(fsm, FSM_FINI)) + break; + } + break; + case FSM_PKGBUILD: + while (1) { + + rc = fsmStage(fsm, FSM_INIT); + + /* Exit on end-of-payload. */ + if (rc == CPIOERR_HDR_TRAILER) { + rc = 0; + break; + } + + /* Exit on error. */ + if (rc) { + fsm->postpone = 1; + (void) fsmStage(fsm, FSM_UNDO); + break; + } + + /* Copy file into archive. */ + rc = fsmStage(fsm, FSM_PROCESS); + if (rc) { + (void) fsmStage(fsm, FSM_UNDO); + break; + } + + if (fsmStage(fsm, FSM_FINI)) + break; + } + + if (!rc) + rc = fsmStage(fsm, FSM_TRAILER); + break; + case FSM_CREATE: + { rpmTransactionSet ts = fsmGetTs(fsm); +#define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT) + fsm->commit = ((ts && (ts->transFlags & _tsmask) && + fsm->goal != FSM_PKGCOMMIT) ? 0 : 1); +#undef _tsmask + } + fsm->path = _free(fsm->path); + fsm->opath = _free(fsm->opath); + fsm->dnlx = _free(fsm->dnlx); + + fsm->ldn = _free(fsm->ldn); + fsm->ldnalloc = fsm->ldnlen = 0; + + fsm->rdsize = fsm->wrsize = 0; + fsm->rdbuf = fsm->rdb = _free(fsm->rdb); + fsm->wrbuf = fsm->wrb = _free(fsm->wrb); + if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { + fsm->rdsize = 8 * BUFSIZ; + fsm->rdbuf = fsm->rdb = xmalloc(fsm->rdsize); + fsm->wrsize = 8 * BUFSIZ; + fsm->wrbuf = fsm->wrb = xmalloc(fsm->wrsize); + } + + fsm->mkdirsdone = 0; + fsm->ix = -1; + fsm->links = NULL; + fsm->li = NULL; + errno = 0; /* XXX get rid of EBADF */ + + /* Detect and create directories not explicitly in package. */ + if (fsm->goal == FSM_PKGINSTALL) { + rc = fsmStage(fsm, FSM_MKDIRS); + if (!rc) fsm->mkdirsdone = 1; + } + + break; + case FSM_INIT: + fsm->path = _free(fsm->path); + fsm->postpone = 0; + fsm->diskchecked = fsm->exists = 0; + fsm->subdir = NULL; + fsm->suffix = (fsm->sufbuf[0] != '\0' ? fsm->sufbuf : NULL); + fsm->action = FA_UNKNOWN; + fsm->osuffix = NULL; + fsm->nsuffix = NULL; + + if (fsm->goal == FSM_PKGINSTALL) { + /* Read next header from payload, checking for end-of-payload. */ + rc = fsmStage(fsm, FSM_NEXT); + } + if (rc) break; + + /* Identify mapping index. */ + fsm->ix = ((fsm->goal == FSM_PKGINSTALL) + ? mapFind(fsm->iter, fsm->path) : mapNextIterator(fsm->iter)); + + /* On non-install, detect end-of-loop. */ + if (fsm->goal != FSM_PKGINSTALL && fsm->ix < 0) { + rc = CPIOERR_HDR_TRAILER; + break; + } + + /* On non-install, mode must be known so that dirs don't get suffix. */ + if (fsm->goal != FSM_PKGINSTALL) { + TFI_t fi = fsmGetFi(fsm); + st->st_mode = fi->fmodes[fsm->ix]; + } + + /* Generate file path. */ + rc = fsmStage(fsm, FSM_MAP); + if (rc) break; + + /* Perform lstat/stat for disk file. */ + rc = fsmStage(fsm, (!(fsm->mapFlags & CPIO_FOLLOW_SYMLINKS) + ? FSM_LSTAT : FSM_STAT)); + if (rc == CPIOERR_LSTAT_FAILED && errno == ENOENT) { + errno = saveerrno; + rc = 0; + fsm->exists = 0; + } else if (rc == 0) { + fsm->exists = 1; + } + fsm->diskchecked = 1; + if (rc) break; + + /* On non-install, the disk file stat is what's remapped. */ + if (fsm->goal != FSM_PKGINSTALL) + *st = *ost; /* structure assignment */ + + /* Remap file perms, owner, and group. */ + rc = fsmMapAttrs(fsm); + if (rc) break; + + fsm->postpone = XFA_SKIPPING(fsm->action); + if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { + if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) + fsm->postpone = saveHardLink(fsm); + } + break; + case FSM_PRE: + break; + case FSM_MAP: + rc = fsmMapPath(fsm); + break; + case FSM_MKDIRS: + { const char * path = fsm->path; + mode_t st_mode = st->st_mode; + void * dnli = dnlInitIterator(fsm, 0); + char * dn = fsm->rdbuf; + int dc = dnlCount(dnli); + + fsm->path = NULL; + dn[0] = '\0'; + fsm->dnlx = (dc ? xcalloc(dc, sizeof(*fsm->dnlx)) : NULL); + while ((fsm->path = dnlNextIterator(dnli)) != NULL) { + int dnlen = strlen(fsm->path); + char * te; + + dc = dnlIndex(dnli); + if (dc < 0) continue; + fsm->dnlx[dc] = dnlen; + if (dnlen <= 1) + continue; + if (dnlen <= fsm->ldnlen && !strcmp(fsm->path, fsm->ldn)) + continue; + + /* Copy to avoid const on fsm->path. */ + (void) stpcpy(dn, fsm->path); + fsm->path = dn; + + /* Initial mode for created dirs is 0700 */ + st->st_mode &= ~07777; /* XXX abuse st->st_mode */ + st->st_mode |= 00700; + + /* Assume '/' directory, otherwise "mkdir -p" */ + for (i = 1, te = dn + 1; *te; te++, i++) { + if (*te != '/') continue; + + *te = '\0'; + + /* Already validated? */ + if (i < fsm->ldnlen && + (fsm->ldn[i] == '/' || fsm->ldn[i] == '\0') && + !strncmp(fsm->path, fsm->ldn, i)) + { + *te = '/'; + /* Move pre-existing path marker forward. */ + fsm->dnlx[dc] = (te - dn); + continue; + } + + /* Validate next component of path. */ + rc = fsmStage(fsm, FSM_LSTAT); + *te = '/'; + + /* Directory already exists? */ + if (rc == 0 && S_ISDIR(ost->st_mode)) { + /* Move pre-existing path marker forward. */ + fsm->dnlx[dc] = (te - dn); + } else if (rc == CPIOERR_LSTAT_FAILED) { + TFI_t fi = fsmGetFi(fsm); + mode_t st_mode = st->st_mode; + *te = '\0'; + st->st_mode = S_IFDIR | (fi->dperms & 07777); + rc = fsmStage(fsm, FSM_MKDIR); + if (!rc) + rpmMessage(RPMMESS_WARNING, + _("%s directory created with perms %04o.\n"), + fsm->path, (st->st_mode & 07777)); + *te = '/'; + st->st_mode = st_mode; + } + if (rc) break; + } + if (rc) break; + + /* Save last validated path. */ + if (fsm->ldnalloc < (dnlen + 1)) { + fsm->ldnalloc = dnlen + 100; + fsm->ldn = xrealloc(fsm->ldn, fsm->ldnalloc); + } + strcpy(fsm->ldn, fsm->path); + fsm->ldnlen = dnlen; + } + dnli = dnlFreeIterator(dnli); + fsm->path = path; + st->st_mode = st_mode; /* XXX restore st->st_mode */ + } + break; + case FSM_RMDIRS: + if (fsm->dnlx) { + const char * path = fsm->path; + void * dnli = dnlInitIterator(fsm, 1); + char * dn = fsm->rdbuf; + int dc = dnlCount(dnli); + + fsm->path = NULL; + dn[0] = '\0'; + while ((fsm->path = dnlNextIterator(dnli)) != NULL) { + int dnlen = strlen(fsm->path); + char * te; + + dc = dnlIndex(dnli); + if (fsm->dnlx[dc] < 1 || fsm->dnlx[dc] >= dnlen) + continue; + + /* Copy to avoid const on fsm->path. */ + te = stpcpy(dn, fsm->path) - 1; + fsm->path = dn; + + /* Remove generated directories. */ + do { + if (*te == '/') { + *te = '\0'; + rc = fsmStage(fsm, FSM_RMDIR); + *te = '/'; + } + if (rc) break; + te--; + } while ((te - dn) > fsm->dnlx[dc]); + } + dnli = dnlFreeIterator(dnli); + fsm->path = path; + } + break; + case FSM_PROCESS: + if (fsm->postpone) { + if (fsm->goal == FSM_PKGINSTALL) + rc = fsmStage(fsm, FSM_EAT); + break; + } + + if (fsm->goal == FSM_PKGBUILD) { + if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { + struct hardLink * li, * prev; + rc = writeLinkedFile(fsm); + if (rc) break; /* W2DO? */ + + for (li = fsm->links, prev = NULL; li; prev = li, li = li->next) + if (li == fsm->li) break; + + if (prev == NULL) + fsm->links = fsm->li->next; + else + prev->next = fsm->li->next; + fsm->li->next = NULL; + fsm->li = freeHardLink(fsm->li); + } else { + rc = writeFile(fsm, 1); + } + break; + } + + if (fsm->goal != FSM_PKGINSTALL) + break; + + if (S_ISREG(st->st_mode)) { + const char * path = fsm->path; + if (fsm->osuffix) + fsm->path = fsmFsPath(fsm, st, NULL, NULL); + rc = fsmStage(fsm, FSM_VERIFY); + + if (rc == 0 && fsm->osuffix) { + const char * opath = fsm->opath; + fsm->opath = fsm->path; + fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); + rc = fsmStage(fsm, FSM_RENAME); + if (!rc) + rpmMessage(RPMMESS_WARNING, + _("%s saved as %s\n"), fsm->opath, fsm->path); + fsm->path = _free(fsm->path); + fsm->opath = opath; + } + + fsm->path = path; + if (rc != CPIOERR_LSTAT_FAILED) return rc; + rc = expandRegular(fsm); + } else if (S_ISDIR(st->st_mode)) { + mode_t st_mode = st->st_mode; + rc = fsmStage(fsm, FSM_VERIFY); + if (rc == CPIOERR_LSTAT_FAILED) { + st->st_mode &= ~07777; /* XXX abuse st->st_mode */ + st->st_mode |= 00700; + rc = fsmStage(fsm, FSM_MKDIR); + st->st_mode = st_mode; /* XXX restore st->st_mode */ + } + } else if (S_ISLNK(st->st_mode)) { + const char * opath = fsm->opath; + + if ((st->st_size + 1) > fsm->rdsize) { + rc = CPIOERR_HDR_SIZE; + break; + } + + fsm->wrlen = st->st_size; + rc = fsmStage(fsm, FSM_DREAD); + if (!rc && fsm->rdnb != fsm->wrlen) + rc = CPIOERR_READ_FAILED; + if (rc) break; + + fsm->wrbuf[st->st_size] = '\0'; + /* XXX symlink(fsm->opath, fsm->path) */ + fsm->opath = fsm->wrbuf; /* XXX abuse fsm->path */ + rc = fsmStage(fsm, FSM_VERIFY); + if (rc == CPIOERR_LSTAT_FAILED) + rc = fsmStage(fsm, FSM_SYMLINK); + fsm->opath = opath; /* XXX restore fsm->path */ + } else if (S_ISFIFO(st->st_mode)) { + mode_t st_mode = st->st_mode; + /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */ + rc = fsmStage(fsm, FSM_VERIFY); + if (rc == CPIOERR_LSTAT_FAILED) { + st->st_mode = 0000; /* XXX abuse st->st_mode */ + rc = fsmStage(fsm, FSM_MKFIFO); + st->st_mode = st_mode; /* XXX restore st->st_mode */ + } + } else if (S_ISCHR(st->st_mode) || + S_ISBLK(st->st_mode) || + S_ISSOCK(st->st_mode)) + { + rc = fsmStage(fsm, FSM_VERIFY); + if (rc == CPIOERR_LSTAT_FAILED) + rc = fsmStage(fsm, FSM_MKNOD); + } else { + rc = CPIOERR_UNKNOWN_FILETYPE; + } + if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { + fsm->li->createdPath = fsm->li->linkIndex; + rc = fsmMakeLinks(fsm); + } + break; + case FSM_POST: + break; + case FSM_MKLINKS: + break; + case FSM_NOTIFY: /* XXX move from fsm to psm -> tsm */ + if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { + rpmTransactionSet ts = fsmGetTs(fsm); + TFI_t fi = fsmGetFi(fsm); + if (ts && ts->notify && fi) + (void)ts->notify(fi->h, RPMCALLBACK_INST_PROGRESS, + fdGetCpioPos(fsm->cfd), fi->archiveSize, + (fi->ap ? fi->ap->key : NULL), ts->notifyData); + } + break; + case FSM_UNDO: + if (fsm->postpone) + break; + if (fsm->goal == FSM_PKGINSTALL) { + (void) fsmStage(fsm, + (S_ISDIR(st->st_mode) ? FSM_RMDIR : FSM_UNLINK)); + +#ifdef NOTYET /* XXX remove only dirs just created, not all. */ + if (fsm->dnlx) + (void) fsmStage(fsm, FSM_RMDIRS); +#endif + errno = saveerrno; + } + if (fsm->failedFile && *fsm->failedFile == NULL) + *fsm->failedFile = xstrdup(fsm->path); + break; + case FSM_FINI: + if (!fsm->postpone && fsm->commit) { + if (fsm->goal == FSM_PKGINSTALL) + rc = ((!S_ISDIR(st->st_mode) && st->st_nlink > 1) + ? fsmCommitLinks(fsm) : fsmStage(fsm, FSM_COMMIT)); + if (fsm->goal == FSM_PKGCOMMIT) + rc = fsmStage(fsm, FSM_COMMIT); + if (fsm->goal == FSM_PKGERASE) + rc = fsmStage(fsm, FSM_COMMIT); + } + fsm->path = _free(fsm->path); + fsm->opath = _free(fsm->opath); + memset(st, 0, sizeof(*st)); + memset(ost, 0, sizeof(*ost)); + break; + case FSM_COMMIT: + /* Rename pre-existing modified or unmanaged file. */ + if (fsm->diskchecked && fsm->exists && fsm->osuffix) { + const char * opath = fsm->opath; + const char * path = fsm->path; + fsm->opath = fsmFsPath(fsm, st, NULL, NULL); + fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix); + rc = fsmStage(fsm, FSM_RENAME); + if (!rc) { + rpmMessage(RPMMESS_WARNING, _("%s saved as %s\n"), + fsm->opath, fsm->path); + } + fsm->path = _free(fsm->path); + fsm->path = path; + fsm->opath = _free(fsm->opath); + fsm->opath = opath; + } + + /* Remove erased files. */ + if (fsm->goal == FSM_PKGERASE) { + if (fsm->action == FA_ERASE) { + TFI_t fi = fsmGetFi(fsm); + if (S_ISDIR(st->st_mode)) { + rc = fsmStage(fsm, FSM_RMDIR); + if (!rc) break; + switch (errno) { + case ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */ + case ENOTEMPTY: + /* XXX make sure that build side permits %missingok on directories. */ + if (fsm->fflags & RPMFILE_MISSINGOK) + break; + + /* XXX common error message. */ + rpmError(RPMERR_RMDIR, + _("%s rmdir of %s failed: Directory not empty\n"), + fiTypeString(fi), fsm->path); + break; + default: + rpmError(RPMERR_RMDIR, + _("%s rmdir of %s failed: %s\n"), + fiTypeString(fi), fsm->path, strerror(errno)); + break; + } + } else { + rc = fsmStage(fsm, FSM_UNLINK); + if (!rc) break; + if (!(errno == ENOENT && (fsm->fflags & RPMFILE_MISSINGOK))) + rpmError(RPMERR_UNLINK, + _("%s unlink of %s failed: %s\n"), + fiTypeString(fi), fsm->path, strerror(errno)); + } + } + break; + } + + if (!S_ISSOCK(st->st_mode)) { /* XXX /dev/log et al are skipped */ + /* Rename temporary to final file name. */ + if (!S_ISDIR(st->st_mode) && + (fsm->subdir || fsm->suffix || fsm->nsuffix)) + { + fsm->opath = fsm->path; + fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix); + rc = fsmStage(fsm, FSM_RENAME); + if (!rc && fsm->nsuffix) { + const char * opath = fsmFsPath(fsm, st, NULL, NULL); + rpmMessage(RPMMESS_WARNING, _("%s created as %s\n"), + opath, fsm->path); + opath = _free(opath); + } + fsm->opath = _free(fsm->opath); + } + if (S_ISLNK(st->st_mode)) { + if (!rc && !getuid()) + rc = fsmStage(fsm, FSM_LCHOWN); + } else { + if (!rc && !getuid()) + rc = fsmStage(fsm, FSM_CHOWN); + if (!rc) + rc = fsmStage(fsm, FSM_CHMOD); + if (!rc) { + time_t st_mtime = st->st_mtime; + TFI_t fi = fsmGetFi(fsm); + if (fi->fmtimes) + st->st_mtime = fi->fmtimes[fsm->ix]; + rc = fsmStage(fsm, FSM_UTIME); + st->st_mtime = st_mtime; + } + } + } + + /* Notify on success. */ + if (!rc) rc = fsmStage(fsm, FSM_NOTIFY); + break; + case FSM_DESTROY: + fsm->path = _free(fsm->path); + + /* Create any remaining links (if no error), and clean up. */ + while ((fsm->li = fsm->links) != NULL) { + fsm->links = fsm->li->next; + fsm->li->next = NULL; + if (fsm->goal == FSM_PKGINSTALL && fsm->commit && fsm->li->linksLeft) + { + for (i = 0 ; i < fsm->li->linksLeft; i++) { + if (fsm->li->filex[i] < 0) continue; + rc = CPIOERR_MISSING_HARDLINK; + if (fsm->failedFile && *fsm->failedFile == NULL) { + fsm->ix = fsm->li->filex[i]; + if (!fsmStage(fsm, FSM_MAP)) { + *fsm->failedFile = fsm->path; + fsm->path = NULL; + } + } + break; + } + } + if (fsm->goal == FSM_PKGBUILD) { + rc = CPIOERR_MISSING_HARDLINK; + } + fsm->li = freeHardLink(fsm->li); + } + fsm->ldn = _free(fsm->ldn); + fsm->ldnalloc = fsm->ldnlen = 0; + fsm->rdbuf = fsm->rdb = _free(fsm->rdb); + fsm->wrbuf = fsm->wrb = _free(fsm->wrb); + break; + case FSM_VERIFY: + if (fsm->diskchecked && !fsm->exists) { + rc = CPIOERR_LSTAT_FAILED; + break; + } + if (S_ISREG(st->st_mode)) { + char * path = alloca(strlen(fsm->path) + sizeof("-RPMDELETE")); + (void) stpcpy( stpcpy(path, fsm->path), "-RPMDELETE"); + /* + * XXX HP-UX (and other os'es) don't permit unlink on busy + * XXX files. + */ + fsm->opath = fsm->path; + fsm->path = path; + rc = fsmStage(fsm, FSM_RENAME); + if (!rc) + (void) fsmStage(fsm, FSM_UNLINK); + else + rc = CPIOERR_UNLINK_FAILED; + fsm->path = fsm->opath; + fsm->opath = NULL; + return (rc ? rc : CPIOERR_LSTAT_FAILED); /* XXX HACK */ + /*@notreached@*/ break; + } else if (S_ISDIR(st->st_mode)) { + if (S_ISDIR(ost->st_mode)) return 0; + if (S_ISLNK(ost->st_mode)) { + rc = fsmStage(fsm, FSM_STAT); + if (rc == CPIOERR_STAT_FAILED && errno == ENOENT) rc = 0; + if (rc) break; + errno = saveerrno; + if (S_ISDIR(ost->st_mode)) return 0; + } + } else if (S_ISLNK(st->st_mode)) { + if (S_ISLNK(ost->st_mode)) { + /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ + rc = fsmStage(fsm, FSM_READLINK); + errno = saveerrno; + if (rc) break; + if (!strcmp(fsm->opath, fsm->rdbuf)) return 0; + } + } else if (S_ISFIFO(st->st_mode)) { + if (S_ISFIFO(ost->st_mode)) return 0; + } else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { + if ((S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) && + (ost->st_rdev == st->st_rdev)) return 0; + } else if (S_ISSOCK(st->st_mode)) { + if (S_ISSOCK(ost->st_mode)) return 0; + } + /* XXX shouldn't do this with commit/undo. */ + rc = 0; + if (fsm->stage == FSM_PROCESS) rc = fsmStage(fsm, FSM_UNLINK); + if (rc == 0) rc = CPIOERR_LSTAT_FAILED; + return (rc ? rc : CPIOERR_LSTAT_FAILED); /* XXX HACK */ + /*@notreached@*/ break; + + case FSM_UNLINK: + rc = Unlink(fsm->path); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur, + fsm->path, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_UNLINK_FAILED; + break; + case FSM_RENAME: + rc = Rename(fsm->opath, fsm->path); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, + fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_RENAME_FAILED; + break; + case FSM_MKDIR: + rc = Mkdir(fsm->path, (st->st_mode & 07777)); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, + fsm->path, (st->st_mode & 07777), + (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_MKDIR_FAILED; + break; + case FSM_RMDIR: + rc = Rmdir(fsm->path); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur, + fsm->path, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_RMDIR_FAILED; + break; + case FSM_CHOWN: + rc = chown(fsm->path, st->st_uid, st->st_gid); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur, + fsm->path, st->st_uid, st->st_gid, + (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_CHOWN_FAILED; + break; + case FSM_LCHOWN: +#if ! CHOWN_FOLLOWS_SYMLINK + rc = lchown(fsm->path, st->st_uid, st->st_gid); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, %d) %s\n", cur, + fsm->path, st->st_uid, st->st_gid, + (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_CHOWN_FAILED; +#endif + break; + case FSM_CHMOD: + rc = chmod(fsm->path, (st->st_mode & 07777)); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, + fsm->path, (st->st_mode & 07777), + (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_CHMOD_FAILED; + break; + case FSM_UTIME: + { struct utimbuf stamp; + stamp.actime = st->st_mtime; + stamp.modtime = st->st_mtime; + rc = utime(fsm->path, &stamp); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0x%x) %s\n", cur, + fsm->path, (unsigned)st->st_mtime, + (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_UTIME_FAILED; + } + break; + case FSM_SYMLINK: + rc = symlink(fsm->opath, fsm->path); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, + fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_SYMLINK_FAILED; + break; + case FSM_LINK: + rc = Link(fsm->opath, fsm->path); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, %s) %s\n", cur, + fsm->opath, fsm->path, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_LINK_FAILED; + break; + case FSM_MKFIFO: + rc = mkfifo(fsm->path, (st->st_mode & 07777)); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%04o) %s\n", cur, + fsm->path, (st->st_mode & 07777), + (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_MKFIFO_FAILED; + break; + case FSM_MKNOD: + /*@-unrecog@*/ + rc = mknod(fsm->path, (st->st_mode & ~07777), st->st_rdev); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n", cur, + fsm->path, (st->st_mode & ~07777), (unsigned)st->st_rdev, + (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_MKNOD_FAILED; + /*@=unrecog@*/ + break; + case FSM_LSTAT: + rc = Lstat(fsm->path, ost); + if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur, + fsm->path, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_LSTAT_FAILED; + break; + case FSM_STAT: + rc = Stat(fsm->path, ost); + if (_fsm_debug && (stage & FSM_SYSCALL) && rc && errno != ENOENT) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, ost) %s\n", cur, + fsm->path, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_STAT_FAILED; + break; + case FSM_READLINK: + /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ + rc = Readlink(fsm->path, fsm->rdbuf, fsm->rdsize - 1); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, rdbuf, %d) %s\n", cur, + fsm->path, fsm->rdlen, (rc < 0 ? strerror(errno) : "")); + if (rc < 0) rc = CPIOERR_READLINK_FAILED; + else { + fsm->rdnb = rc; + fsm->rdbuf[fsm->rdnb] = '\0'; + rc = 0; + } + break; + case FSM_CHROOT: + break; + + case FSM_NEXT: + rc = fsmStage(fsm, FSM_HREAD); + if (rc) break; + if (!strcmp(fsm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */ + fsm->path = _free(fsm->path); + rc = CPIOERR_HDR_TRAILER; + } + if (!rc) + rc = fsmStage(fsm, FSM_POS); + break; + case FSM_EAT: + for (left = st->st_size; left > 0; left -= fsm->rdnb) { + fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); + rc = fsmStage(fsm, FSM_DREAD); + if (rc) break; + } + break; + case FSM_POS: + left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo; + if (left) { + fsm->wrlen = left; + (void) fsmStage(fsm, FSM_DREAD); + } + break; + case FSM_PAD: + left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo; + if (left) { + memset(fsm->rdbuf, 0, left); + /* XXX DWRITE uses rdnb for I/O length. */ + fsm->rdnb = left; + (void) fsmStage(fsm, FSM_DWRITE); + } + break; + case FSM_TRAILER: + rc = cpioTrailerWrite(fsm); + break; + case FSM_HREAD: + rc = fsmStage(fsm, FSM_POS); + if (!rc) + rc = cpioHeaderRead(fsm, st); /* Read next payload header. */ + break; + case FSM_HWRITE: + rc = cpioHeaderWrite(fsm, st); /* Write next payload header. */ + break; + case FSM_DREAD: + fsm->rdnb = Fread(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->wrlen, fsm->cfd); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n", + cur, (fsm->wrbuf == fsm->wrb ? "wrbuf" : "mmap"), + fsm->wrlen, fsm->rdnb); +if (fsm->rdnb != fsm->wrlen) fprintf(stderr, "*** short read, had %d, got %d\n", (int)fsm->rdnb, (int)fsm->wrlen); +#ifdef NOTYET + if (Ferror(fsm->rfd)) + rc = CPIOERR_READ_FAILED; +#endif + if (fsm->rdnb > 0) + fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->rdnb); + break; + case FSM_DWRITE: + fsm->wrnb = Fwrite(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdnb, fsm->cfd); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n", + cur, (fsm->rdbuf == fsm->rdb ? "rdbuf" : "mmap"), + fsm->rdnb, fsm->wrnb); +if (fsm->rdnb != fsm->wrnb) fprintf(stderr, "*** short write, had %d, got %d\n", (int)fsm->rdnb, (int)fsm->wrnb); +#ifdef NOTYET + if (Ferror(fsm->wfd)) + rc = CPIOERR_WRITE_FAILED; +#endif + if (fsm->wrnb > 0) + fdSetCpioPos(fsm->cfd, fdGetCpioPos(fsm->cfd) + fsm->wrnb); + break; + + case FSM_ROPEN: + fsm->rfd = Fopen(fsm->path, "r.ufdio"); + if (fsm->rfd == NULL || Ferror(fsm->rfd)) { + if (fsm->rfd) (void) fsmStage(fsm, FSM_RCLOSE); + fsm->rfd = NULL; + rc = CPIOERR_OPEN_FAILED; + break; + } + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"r\") rfd %p rdbuf %p\n", cur, + fsm->path, fsm->rfd, fsm->rdbuf); + break; + case FSM_READ: + fsm->rdnb = Fread(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdlen, fsm->rfd); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (rdbuf, %d, rfd)\trdnb %d\n", + cur, fsm->rdlen, fsm->rdnb); +if (fsm->rdnb != fsm->rdlen) fprintf(stderr, "*** short read, had %d, got %d\n", (int)fsm->rdnb, (int)fsm->rdlen); +#ifdef NOTYET + if (Ferror(fsm->rfd)) + rc = CPIOERR_READ_FAILED; +#endif + break; + case FSM_RCLOSE: + if (fsm->rfd) { + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->rfd); + (void) Fclose(fsm->rfd); + errno = saveerrno; + } + fsm->rfd = NULL; + break; + case FSM_WOPEN: + fsm->wfd = Fopen(fsm->path, "w.ufdio"); + if (fsm->wfd == NULL || Ferror(fsm->wfd)) { + if (fsm->wfd) (void) fsmStage(fsm, FSM_WCLOSE); + fsm->wfd = NULL; + rc = CPIOERR_OPEN_FAILED; + } + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%s, \"w\") wfd %p wrbuf %p\n", cur, + fsm->path, fsm->wfd, fsm->wrbuf); + break; + case FSM_WRITE: + fsm->wrnb = Fwrite(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->rdnb, fsm->wfd); + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (wrbuf, %d, wfd)\twrnb %d\n", + cur, fsm->rdnb, fsm->wrnb); +if (fsm->rdnb != fsm->wrnb) fprintf(stderr, "*** short write: had %d, got %d\n", (int)fsm->rdnb, (int)fsm->wrnb); +#ifdef NOTYET + if (Ferror(fsm->wfd)) + rc = CPIOERR_WRITE_FAILED; +#endif + break; + case FSM_WCLOSE: + if (fsm->wfd) { + if (_fsm_debug && (stage & FSM_SYSCALL)) + rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->wfd); + (void) Fclose(fsm->wfd); + errno = saveerrno; + } + fsm->wfd = NULL; + break; + + default: + break; + } + + if (!(stage & FSM_INTERNAL)) { + fsm->rc = (rc == CPIOERR_HDR_TRAILER ? 0 : rc); + } + return rc; +} + +/*@observer@*/ const char *const fileStageString(fileStage a) { + switch(a) { + case FSM_UNKNOWN: return "unknown"; + + case FSM_PKGINSTALL:return "pkginstall"; + case FSM_PKGERASE: return "pkgerase"; + case FSM_PKGBUILD: return "pkgbuild"; + case FSM_PKGCOMMIT: return "pkgcommit"; + case FSM_PKGUNDO: return "pkgundo"; + + case FSM_CREATE: return "create"; + case FSM_INIT: return "init"; + case FSM_MAP: return "map"; + case FSM_MKDIRS: return "mkdirs"; + case FSM_RMDIRS: return "rmdirs"; + case FSM_PRE: return "pre"; + case FSM_PROCESS: return "process"; + case FSM_POST: return "post"; + case FSM_MKLINKS: return "mklinks"; + case FSM_NOTIFY: return "notify"; + case FSM_UNDO: return "undo"; + case FSM_FINI: return "fini"; + case FSM_COMMIT: return "commit"; + case FSM_DESTROY: return "destroy"; + case FSM_VERIFY: return "verify"; + + case FSM_UNLINK: return "Unlink"; + case FSM_RENAME: return "Rename"; + case FSM_MKDIR: return "Mkdir"; + case FSM_RMDIR: return "rmdir"; + case FSM_CHOWN: return "chown"; + case FSM_LCHOWN: return "lchown"; + case FSM_CHMOD: return "chmod"; + case FSM_UTIME: return "utime"; + case FSM_SYMLINK: return "symlink"; + case FSM_LINK: return "Link"; + case FSM_MKFIFO: return "mkfifo"; + case FSM_MKNOD: return "mknod"; + case FSM_LSTAT: return "Lstat"; + case FSM_STAT: return "Stat"; + case FSM_READLINK: return "Readlink"; + case FSM_CHROOT: return "chroot"; + + case FSM_NEXT: return "next"; + case FSM_EAT: return "eat"; + case FSM_POS: return "pos"; + case FSM_PAD: return "pad"; + case FSM_TRAILER: return "trailer"; + case FSM_HREAD: return "hread"; + case FSM_HWRITE: return "hwrite"; + case FSM_DREAD: return "Fread"; + case FSM_DWRITE: return "Fwrite"; + + case FSM_ROPEN: return "Fopen"; + case FSM_READ: return "Fread"; + case FSM_RCLOSE: return "Fclose"; + case FSM_WOPEN: return "Fopen"; + case FSM_WRITE: return "Fwrite"; + case FSM_WCLOSE: return "Fclose"; + + default: return "???"; + } + /*@noteached@*/ +} diff --git a/lib/fsm.h b/lib/fsm.h new file mode 100644 index 0000000..f2c7513 --- /dev/null +++ b/lib/fsm.h @@ -0,0 +1,255 @@ +#ifndef H_FSM +#define H_FSM + +/** \file lib/fsm.h + */ + +#include +#include "cpio.h" + +/** + */ +#define FSM_VERBOSE 0x8000 +#define FSM_INTERNAL 0x4000 +#define FSM_SYSCALL 0x2000 +#define FSM_DEAD 0x1000 +#define _fv(_a) ((_a) | FSM_VERBOSE) +#define _fi(_a) ((_a) | FSM_INTERNAL) +#define _fs(_a) ((_a) | (FSM_INTERNAL | FSM_SYSCALL)) +#define _fd(_a) ((_a) | (FSM_INTERNAL | FSM_DEAD)) +typedef enum fileStage_e { + FSM_UNKNOWN = 0, + FSM_INIT = _fd(1), + FSM_PRE = _fd(2), + FSM_PROCESS = _fv(3), + FSM_POST = _fd(4), + FSM_UNDO = 5, + FSM_FINI = 6, + + FSM_PKGINSTALL = _fd(7), + FSM_PKGERASE = _fd(8), + FSM_PKGBUILD = _fd(9), + FSM_PKGCOMMIT = _fd(10), + FSM_PKGUNDO = _fd(11), + + FSM_CREATE = _fd(17), + FSM_MAP = _fd(18), + FSM_MKDIRS = _fi(19), + FSM_RMDIRS = _fi(20), + FSM_MKLINKS = _fi(21), + FSM_NOTIFY = _fd(22), + FSM_DESTROY = _fd(23), + FSM_VERIFY = _fd(24), + FSM_COMMIT = _fd(25), + + FSM_UNLINK = _fs(33), + FSM_RENAME = _fs(34), + FSM_MKDIR = _fs(35), + FSM_RMDIR = _fs(36), + FSM_CHOWN = _fs(37), + FSM_LCHOWN = _fs(38), + FSM_CHMOD = _fs(39), + FSM_UTIME = _fs(40), + FSM_SYMLINK = _fs(41), + FSM_LINK = _fs(42), + FSM_MKFIFO = _fs(43), + FSM_MKNOD = _fs(44), + FSM_LSTAT = _fs(45), + FSM_STAT = _fs(46), + FSM_READLINK= _fs(47), + FSM_CHROOT = _fs(48), + + FSM_NEXT = _fd(65), + FSM_EAT = _fd(66), + FSM_POS = _fd(67), + FSM_PAD = _fd(68), + FSM_TRAILER = _fd(69), + FSM_HREAD = _fd(70), + FSM_HWRITE = _fd(71), + FSM_DREAD = _fs(72), + FSM_DWRITE = _fs(73), + + FSM_ROPEN = _fs(129), + FSM_READ = _fs(130), + FSM_RCLOSE = _fs(131), + FSM_WOPEN = _fs(132), + FSM_WRITE = _fs(133), + FSM_WCLOSE = _fs(134), +} fileStage; +#undef _fv +#undef _fi +#undef _fs +#undef _fd + +/** \ingroup payload + * Keeps track of the set of all hard links to a file in an archive. + */ +struct hardLink { +/*@owned@*/ struct hardLink * next; +/*@owned@*/ const char ** nsuffix; +/*@owned@*/ int * filex; + dev_t dev; + ino_t inode; + int nlink; + int linksLeft; + int linkIndex; + int createdPath; +}; + +/** \ingroup payload + * Iterator across package file info, forward on install, backward on erase. + */ +struct fsmIterator_s { +/*@kept@*/ rpmTransactionSet ts; /*!< transaction set. */ +/*@kept@*/ TFI_t fi; /*!< transaction element file info. */ + int isave; /*!< last returned iterator index. */ + int i; /*!< iterator index. */ +}; + +/** \ingroup payload + * File name and stat information. + */ +struct fsm_s { +/*@owned@*/ const char * path; /*!< Current file name. */ +/*@owned@*/ const char * opath; /*!< Original file name. */ + FD_t cfd; /*!< Payload file handle. */ + FD_t rfd; /*!< read: File handle. */ +/*@dependent@*/ char * rdbuf; /*!< read: Buffer. */ +/*@owned@*/ char * rdb; /*!< read: Buffer allocated. */ + size_t rdsize; /*!< read: Buffer allocated size. */ + size_t rdlen; /*!< read: Number of bytes requested. */ + size_t rdnb; /*!< read: Number of bytes returned. */ + FD_t wfd; /*!< write: File handle. */ +/*@dependent@*/ char * wrbuf; /*!< write: Buffer. */ +/*@owned@*/ char * wrb; /*!< write: Buffer allocated. */ + size_t wrsize; /*!< write: Buffer allocated size. */ + size_t wrlen; /*!< write: Number of bytes requested. */ + size_t wrnb; /*!< write: Number of bytes returned. */ +/*@only@*/ FSMI_t iter; /*!< File iterator. */ + int ix; /*!< Current file iterator index. */ +/*@only@*/ struct hardLink * links; /*!< Pending hard linked file(s). */ +/*@only@*/ struct hardLink * li; /*!< Current hard linked file(s). */ +/*@kept@*/ unsigned int * archiveSize; /*!< Pointer to archive size. */ +/*@kept@*/ const char ** failedFile; /*!< First file name that failed. */ +/*@shared@*/ const char * subdir; /*!< Current file sub-directory. */ + char subbuf[64]; /* XXX eliminate */ +/*@observer@*/ const char * osuffix; /*!< Old, preserved, file suffix. */ +/*@observer@*/ const char * nsuffix; /*!< New, created, file suffix. */ +/*@shared@*/ const char * suffix; /*!< Current file suffix. */ + char sufbuf[64]; /* XXX eliminate */ +/*@only@*/ short * dnlx; /*!< Last dirpath verified indexes. */ +/*@only@*/ char * ldn; /*!< Last dirpath verified. */ + int ldnlen; /*!< Last dirpath current length. */ + int ldnalloc; /*!< Last dirpath allocated length. */ + int postpone; /*!< Skip remaining stages? */ + int diskchecked; /*!< Has stat(2) been performed? */ + int exists; /*!< Does current file exist on disk? */ + int mkdirsdone; /*!< Have "orphan" dirs been created? */ + int astriplen; /*!< Length of buildroot prefix. */ + int rc; /*!< External file stage return code. */ + int commit; /*!< Commit synchronously? */ + cpioMapFlags mapFlags; /*!< Bit(s) to control mapping. */ +/*@shared@*/ const char * archivePath; /*!< Path to store in cpio archive. */ +/*@shared@*/ const char * dirName; /*!< File directory name. */ +/*@shared@*/ const char * baseName; /*!< File base name. */ +/*@shared@*/ const char * fmd5sum; /*!< File MD5 sum (NULL disables). */ + unsigned fflags; /*!< File flags. */ + fileAction action; /*!< File disposition. */ + fileStage goal; /*!< Package state machine goal. */ + fileStage stage; /*!< External file stage. */ + struct stat sb; /*!< Current file stat(2) info. */ + struct stat osb; /*!< Original file stat(2) info. */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Return formatted string representation of file stages. + * @param a file stage + * @return formatted string + */ +/*@observer@*/ const char *const fileStageString(fileStage a); + +/** + * Create file state machine instance. + * @return file state machine data + */ +/*@only@*/ /*@null@*/ FSM_t newFSM(void); + +/** + * Destroy file state machine instance. + * @param fsm file state machine data + * @return always NULL + */ +/*@null@*/ FSM_t freeFSM(/*@only@*/ /*@null@*/ FSM_t fsm); + +/** + * Load external data into file state machine. + * @param fsm file state machine data + * @param goal + * @param ts transaction set + * @param fi transaction element file info + * @param archiveSize pointer to archive size + * @param failedFile pointer to first file name that failed. + * @return 0 on success + */ +int fsmSetup(FSM_t fsm, fileStage goal, + /*@kept@*/ const rpmTransactionSet ts, + /*@kept@*/ const TFI_t fi, + FD_t cfd, + /*@out@*/ unsigned int * archiveSize, + /*@out@*/ const char ** failedFile) + /*@modifies fsm, *archiveSize, *failedFile @*/; + +/** + * Clean file state machine. + * @param fsm file state machine data + * @return 0 on success + */ +int fsmTeardown(FSM_t fsm) + /*@modifies fsm @*/; + +/** + * Retrieve transaction set from file state machine iterator. + * @param fsm file state machine data + * @return transaction set + */ +/*@kept@*/ rpmTransactionSet fsmGetTs(const FSM_t fsm) /*@*/; + +/** + * Retrieve transaction element file info from file state machine iterator. + * @param fsm file state machine data + * @return transaction element file info + */ +/*@kept@*/ TFI_t fsmGetFi(const FSM_t fsm) /*@*/; + +/** + * Map next file path and action. + * @param fsm file state machine data + */ +int fsmMapPath(FSM_t fsm) + /*@modifies fsm @*/; + +/** + * Map file stat(2) info. + * @param fsm file state machine data + */ +int fsmMapAttrs(FSM_t fsm) + /*@modifies fsm @*/; + +/** + * File state machine driver. + * @param fsm file state machine data + * @param stage next stage + * @return 0 on success + */ +int fsmStage(FSM_t fsm, fileStage stage) + /*@modifies fsm @*/; + +#ifdef __cplusplus +} +#endif + +#endif /* H_FSM */ diff --git a/lib/install.c b/lib/psm.c similarity index 70% rename from lib/install.c rename to lib/psm.c index 8f8f7c8..b086483 100644 --- a/lib/install.c +++ b/lib/psm.c @@ -1,5 +1,5 @@ /** \ingroup rpmtrans payload - * \file lib/install.c + * \file lib/psm.c */ #include "system.h" @@ -8,12 +8,276 @@ #include #include -#include "rollback.h" +#include "psm.h" #include "misc.h" #include "debug.h" -/*@access Header @*/ /* XXX compared with NULL */ -/*@access rpmTransactionSet @*/ /* XXX compared with NULL */ +/*@access Header @*/ /* compared with NULL */ +/*@access rpmTransactionSet @*/ /* compared with NULL */ +/*@access TFI_t @*/ /* compared with NULL */ + +extern int _fsm_debug; + +/** + * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL. + * @param this memory to free + * @retval NULL always + */ +static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) { + if (this) free((void *)this); + return NULL; +} + +void loadFi(Header h, TFI_t fi) +{ + HGE_t hge; + HFD_t hfd; + uint_32 * uip; + int len; + int rc; + int i; + + if (fi->fsm == NULL) + fi->fsm = newFSM(); + + /* XXX avoid gcc noise on pointer (4th arg) cast(s) */ + hge = (fi->type == TR_ADDED) + ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry; + fi->hge = hge; + + fi->hfd = hfd = headerFreeData; + + if (h && fi->h == NULL) fi->h = headerLink(h); + + /* Duplicate name-version-release so that headers can be free'd. */ + hge(fi->h, RPMTAG_NAME, NULL, (void **) &fi->name, NULL); + fi->name = xstrdup(fi->name); + hge(fi->h, RPMTAG_VERSION, NULL, (void **) &fi->version, NULL); + fi->version = xstrdup(fi->version); + hge(fi->h, RPMTAG_RELEASE, NULL, (void **) &fi->release, NULL); + fi->release = xstrdup(fi->release); + + /* -1 means not found */ + rc = hge(fi->h, RPMTAG_EPOCH, NULL, (void **) &uip, NULL); + fi->epoch = (rc ? *uip : -1); + /* 0 means unknown */ + rc = hge(fi->h, RPMTAG_ARCHIVESIZE, NULL, (void **) &uip, NULL); + fi->archiveSize = (rc ? *uip : 0); + + if (!hge(fi->h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc)) { + fi->dc = 0; + fi->fc = 0; + return; + } + + hge(fi->h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL); + hge(fi->h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc); + hge(fi->h, RPMTAG_FILEMODES, NULL, (void **) &fi->fmodes, NULL); + hge(fi->h, RPMTAG_FILEFLAGS, NULL, (void **) &fi->fflags, NULL); + hge(fi->h, RPMTAG_FILESIZES, NULL, (void **) &fi->fsizes, NULL); + hge(fi->h, RPMTAG_FILESTATES, NULL, (void **) &fi->fstates, NULL); + + fi->action = FA_UNKNOWN; + fi->flags = 0; + + /* actions is initialized earlier for added packages */ + if (fi->actions == NULL) + fi->actions = xcalloc(fi->fc, sizeof(*fi->actions)); + + switch (fi->type) { + case TR_ADDED: + fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID; + hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL); + hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL); + hge(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fi->flangs, NULL); + hge(fi->h, RPMTAG_FILEMTIMES, NULL, (void **) &fi->fmtimes, NULL); + + /* 0 makes for noops */ + fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes)); + + break; + case TR_REMOVED: + fi->mapflags = CPIO_MAP_PATH; + hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL); + hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL); + fi->fsizes = memcpy(xmalloc(fi->fc * sizeof(*fi->fsizes)), + fi->fsizes, fi->fc * sizeof(*fi->fsizes)); + fi->fflags = memcpy(xmalloc(fi->fc * sizeof(*fi->fflags)), + fi->fflags, fi->fc * sizeof(*fi->fflags)); + fi->fmodes = memcpy(xmalloc(fi->fc * sizeof(*fi->fmodes)), + fi->fmodes, fi->fc * sizeof(*fi->fmodes)); + /* XXX there's a tedious segfault here for some version(s) of rpm */ + if (fi->fstates) + fi->fstates = memcpy(xmalloc(fi->fc * sizeof(*fi->fstates)), + fi->fstates, fi->fc * sizeof(*fi->fstates)); + else + fi->fstates = xcalloc(1, fi->fc * sizeof(*fi->fstates)); + fi->dil = memcpy(xmalloc(fi->fc * sizeof(*fi->dil)), + fi->dil, fi->fc * sizeof(*fi->dil)); + headerFree(fi->h); + fi->h = NULL; + break; + } + + fi->dnlmax = -1; + for (i = 0; i < fi->dc; i++) { + if ((len = strlen(fi->dnl[i])) > fi->dnlmax) + fi->dnlmax = len; + } + + fi->bnlmax = -1; + for (i = 0; i < fi->fc; i++) { + if ((len = strlen(fi->bnl[i])) > fi->bnlmax) + fi->bnlmax = len; + } + + fi->dperms = 0755; + fi->fperms = 0644; + + return; +} + +void freeFi(TFI_t fi) +{ + HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData); + + fi->name = _free(fi->name); + fi->version = _free(fi->version); + fi->release = _free(fi->release); + fi->actions = _free(fi->actions); + fi->replacedSizes = _free(fi->replacedSizes); + fi->replaced = _free(fi->replaced); + + fi->bnl = hfd(fi->bnl, -1); + fi->dnl = hfd(fi->dnl, -1); + fi->obnl = hfd(fi->obnl, -1); + fi->odnl = hfd(fi->odnl, -1); + fi->flinks = hfd(fi->flinks, -1); + fi->fmd5s = hfd(fi->fmd5s, -1); + fi->fuser = hfd(fi->fuser, -1); + fi->fgroup = hfd(fi->fgroup, -1); + fi->flangs = hfd(fi->flangs, -1); + + fi->apath = _free(fi->apath); + fi->fuids = _free(fi->fuids); + fi->fgids = _free(fi->fgids); + fi->fmapflags = _free(fi->fmapflags); + + fi->fsm = freeFSM(fi->fsm); + + switch (fi->type) { + case TR_ADDED: + break; + case TR_REMOVED: + fi->fsizes = hfd(fi->fsizes, -1); + fi->fflags = hfd(fi->fflags, -1); + fi->fmodes = hfd(fi->fmodes, -1); + fi->fstates = hfd(fi->fstates, -1); + fi->dil = hfd(fi->dil, -1); + break; + } + if (fi->h) { + headerFree(fi->h); fi->h = NULL; + } +} + +/*@observer@*/ const char *const fiTypeString(TFI_t fi) { + switch(fi->type) { + case TR_ADDED: return " install"; + case TR_REMOVED: return " erase"; + default: return "???"; + } + /*@noteached@*/ +} + +/*@obserever@*/ const char *const fileActionString(fileAction a) +{ + switch (a) { + case FA_UNKNOWN: return "unknown"; + case FA_CREATE: return "create"; + case FA_BACKUP: return "backup"; + case FA_SAVE: return "save"; + case FA_SKIP: return "skip"; + case FA_ALTNAME: return "altname"; + case FA_ERASE: return "erase"; + case FA_SKIPNSTATE: return "skipnstate"; + case FA_SKIPNETSHARED: return "skipnetshared"; + case FA_SKIPMULTILIB: return "skipmultilib"; + default: return "???"; + } + /*@notreached@*/ +} + +#ifdef DYING +/** + */ +struct pkgIterator { +/*@dependent@*/ /*@kept@*/ TFI_t fi; + int i; +}; + +/** + */ +static /*@null@*/ void * pkgFreeIterator(/*@only@*/ /*@null@*/ void * this) { + return _free(this); +} + +/** + */ +static /*@only@*/ void * pkgInitIterator(/*@kept@*/ rpmTransactionSet ts, + /*@kept@*/ TFI_t fi) +{ + struct pkgIterator * pi = NULL; + if (ts && fi) { + pi = xcalloc(sizeof(*pi), 1); + pi->fi = fi; + switch (fi->type) { + case TR_ADDED: pi->i = 0; break; + case TR_REMOVED: pi->i = fi->fc; break; + } + } + return pi; +} + +/** + */ +static int pkgNextIterator(/*@null@*/ void * this) { + struct pkgIterator * pi = this; + int i = -1; + + if (pi) { + TFI_t fi = pi->fi; + switch (fi->type) { + case TR_ADDED: + if (pi->i < fi->fc) + i = pi->i++; + break; + case TR_REMOVED: + if (pi->i >= 0) + i = --pi->i; + break; + } + } + return i; +} + +int pkgActions(const rpmTransactionSet ts, TFI_t fi, fileStage a) +{ + int rc = 0; + + if (fi->actions) { + void * pi = pkgInitIterator(ts, fi); + int i; + while ((i = pkgNextIterator(pi)) != -1) { + if (pkgAction(ts, fi, i, a)) + rc++; + } + pi = pkgFreeIterator(pi); + } + return rc; +} +#endif + /** * Macros to be defined from per-header tag values. @@ -911,3 +1175,103 @@ exit: headerFree(oldH); return ec; } + +int removeBinaryPackage(const rpmTransactionSet ts, TFI_t fi) +{ +/*@observer@*/ static char * stepName = " erase"; + Header h; + int chrootDone = 0; + const char * failedFile = NULL; + const void * pkgKey = NULL; + int rc = 0; + + rpmMessage(RPMMESS_DEBUG, _("%s: %s-%s-%s has %d files, test = %d\n"), + stepName, fi->name, fi->version, fi->release, + fi->fc, (ts->transFlags & RPMTRANS_FLAG_TEST)); + + /* + * When we run scripts, we pass an argument which is the number of + * versions of this package that will be installed when we are finished. + */ + fi->scriptArg = rpmdbCountPackages(ts->rpmdb, fi->name) - 1; + if (fi->scriptArg < 0) + return 1; + + { rpmdbMatchIterator mi = NULL; + + mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, + &fi->record, sizeof(fi->record)); + + h = rpmdbNextIterator(mi); + if (h == NULL) { + rpmdbFreeIterator(mi); + return 2; + } + h = headerLink(h); + rpmdbFreeIterator(mi); + } + + if (ts->rootDir && !ts->chrootDone) { + chdir("/"); + /*@-unrecog@*/ chroot(ts->rootDir); /*@=unrecog@*/ + chrootDone = ts->chrootDone = 1; + } + + if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERS)) { + /* run triggers from this package which are keyed on installed + packages */ + if (runImmedTriggers(ts, RPMSENSE_TRIGGERUN, h, -1)) + return 2; + + /* run triggers which are set off by the removal of this package */ + if (runTriggers(ts, RPMSENSE_TRIGGERUN, h, -1)) + return 1; + } + + rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"), + stepName, "pre-erase"); + + rc = runInstScript(ts, h, RPMTAG_PREUN, RPMTAG_PREUNPROG, fi->scriptArg, + (ts->transFlags & RPMTRANS_FLAG_NOSCRIPTS)); + if (rc) + return 1; + + if (fi->fc > 0 && !(ts->transFlags & RPMTRANS_FLAG_JUSTDB)) { + + if (ts->notify) + (void)ts->notify(h, RPMCALLBACK_UNINST_START, fi->fc, fi->fc, + pkgKey, ts->notifyData); + + rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi, NULL, NULL, &failedFile); + (void) fsmTeardown(fi->fsm); + + if (ts->notify) + (void)ts->notify(h, RPMCALLBACK_UNINST_STOP, 0, fi->fc, + pkgKey, ts->notifyData); + } + + rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"), + stepName, "post-erase"); + + rc = runInstScript(ts, h, RPMTAG_POSTUN, RPMTAG_POSTUNPROG, + fi->scriptArg, (ts->transFlags & RPMTRANS_FLAG_NOSCRIPTS)); + /* XXX postun failures are not cause for erasure failure. */ + + if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERS)) { + /* Run postun triggers which are set off by this package's removal. */ + rc = runTriggers(ts, RPMSENSE_TRIGGERPOSTUN, h, -1); + if (rc) + return 2; + } + + if (ts->rootDir && chrootDone) { + /*@-unrecog@*/ chroot("."); /*@=unrecog@*/ + chrootDone = ts->chrootDone = 0; + chdir(ts->currDir); + } + + if (!(ts->transFlags & RPMTRANS_FLAG_TEST)) + rpmdbRemove(ts->rpmdb, ts->id, fi->record); + + return 0; +} diff --git a/lib/psm.h b/lib/psm.h new file mode 100644 index 0000000..8b18a90 --- /dev/null +++ b/lib/psm.h @@ -0,0 +1,152 @@ +#ifndef H_PSM +#define H_PSM + +/** \file lib/psm.h + */ + +#include +#include "depends.h" +#include "scriptlet.h" +#include "fsm.h" + +/** + */ +typedef enum rollbackDir_e { + ROLLBACK_SAVE = 1, /*!< Save files. */ + ROLLBACK_RESTORE = 2, /*!< Restore files. */ +} rollbackDir; + +/** + */ +struct sharedFile { + int mainFileNumber; + int secRecOffset; + int secFileNumber; +} ; + +/** + */ +struct sharedFileInfo { + int pkgFileNum; + int otherFileNum; + int otherPkg; + int isRemoved; +}; + +/** + */ +struct transactionFileInfo_s { + /* for all packages */ + enum rpmTransactionType type; + fileAction action; /*!< File disposition default. */ +/*@owned@*/ fileAction * actions; /*!< File disposition(s) */ +/*@owned@*/ struct fingerPrint_s * fps; /*!< File fingerprint(s) */ + HGE_t hge; /*!< Vector to headerGetEntry() */ + HFD_t hfd; /*!< Vector to headerFreeData() */ + Header h; /*!< Package header */ +/*@owned@*/ const char * name; +/*@owned@*/ const char * version; +/*@owned@*/ const char * release; + int_32 epoch; + uint_32 flags; /*!< File flag default. */ + const uint_32 * fflags; /*!< File flag(s) (from header) */ + const uint_32 * fsizes; /*!< File size(s) (from header) */ + const uint_32 * fmtimes; /*!< File modification time(s) (from header) */ +/*@owned@*/ const char ** bnl; /*!< Base name(s) (from header) */ +/*@owned@*/ const char ** dnl; /*!< Directory name(s) (from header) */ + int_32 * dil; /*!< Directory indice(s) (from header) */ +/*@owned@*/ const char ** obnl; /*!< Original base name(s) (from header) */ +/*@owned@*/ const char ** odnl; /*!< Original directory name(s) (from header) */ + int_32 * odil; /*!< Original directory indice(s) (from header) */ +/*@owned@*/ const char ** fmd5s;/*!< File MD5 sum(s) (from header) */ +/*@owned@*/ const char ** flinks; /*!< File link(s) (from header) */ +/* XXX setuid/setgid bits are turned off if fuser/fgroup doesn't map. */ + uint_16 * fmodes; /*!< File mode(s) (from header) */ +/*@owned@*/ char * fstates; /*!< File state(s) (from header) */ +/*@owned@*/ const char ** fuser; /*!< File owner(s) */ +/*@owned@*/ const char ** fgroup; /*!< File group(s) */ +/*@owned@*/ const char ** flangs; /*!< File lang(s) */ + int fc; /*!< No. of files. */ + int dc; /*!< No. of directories. */ + int bnlmax; /*!< Length (in bytes) of longest base name. */ + int dnlmax; /*!< Length (in bytes) of longest dir name. */ + int astriplen; + int striplen; + int scriptArg; + unsigned int archiveSize; + mode_t dperms; /*!< Directory perms (0755) if not mapped. */ + mode_t fperms; /*!< File perms (0644) if not mapped. */ +/*@owned@*/ const char ** apath; + int mapflags; +/*@owned@*/ int * fmapflags; + uid_t uid; +/*@owned@*/ /*@null@*/ uid_t * fuids; /*!< File uid(s) */ + gid_t gid; +/*@owned@*/ /*@null@*/ gid_t * fgids; /*!< File gid(s) */ + int magic; +#define TFIMAGIC 0x09697923 +/*@owned@*/ FSM_t fsm; /*!< File state machine data. */ + + /* these are for TR_ADDED packages */ +/*@dependent@*/ struct availablePackage * ap; +/*@owned@*/ struct sharedFileInfo * replaced; +/*@owned@*/ uint_32 * replacedSizes; + /* for TR_REMOVED packages */ + unsigned int record; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Load data from header into transaction file element info. + * @param h header + * @param fi transaction element file info + */ +void loadFi(Header h, TFI_t fi) + /*@modifies h, fi @*/; + +/** + * Destroy transaction element file info. + * @param fi transaction element file info + */ +void freeFi(TFI_t fi) + /*@modifies fi @*/; + +/** + * Return formatted string representation of package disposition. + * @param a package dispostion + * @return formatted string + */ +/*@observer@*/ const char *const fiTypeString(TFI_t fi); + +/** + * Return formatted string representation of file disposition. + * @param a file dispostion + * @return formatted string + */ +/*@observer@*/ const char *const fileActionString(fileAction a); + +/** + * Install binary package (from transaction set). + * @param ts transaction set + * @param fi transaction element file info + * @return 0 on success, 1 on bad magic, 2 on error + */ +int installBinaryPackage(const rpmTransactionSet ts, TFI_t fi); + +/** + * Erase binary package (from transaction set). + * @param ts transaction set + * @param fi transaction element file info + * @param pkgKey package private data + * @return 0 on success + */ +int removeBinaryPackage(const rpmTransactionSet ts, TFI_t fi); + +#ifdef __cplusplus +} +#endif + +#endif /* H_ROLLBACK */ diff --git a/lib/rollback.c b/lib/rollback.c deleted file mode 100644 index 6fadd03..0000000 --- a/lib/rollback.c +++ /dev/null @@ -1,335 +0,0 @@ -/** \ingroup rpmtrans payload - * \file lib/rollback.c - */ - -#include "system.h" - -#include - -#include "rollback.h" - -#include "debug.h" - -/*@access Header @*/ /* compared with NULL */ -/*@access rpmTransactionSet @*/ /* compared with NULL */ -/*@access TFI_t @*/ /* compared with NULL */ - -static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) { - if (this) free((void *)this); - return NULL; -} - -void loadFi(Header h, TFI_t fi) -{ - HGE_t hge; - HFD_t hfd; - uint_32 * uip; - int len; - int rc; - int i; - - if (fi->fsm == NULL) - fi->fsm = newFSM(); - - /* XXX avoid gcc noise on pointer (4th arg) cast(s) */ - hge = (fi->type == TR_ADDED) - ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry; - fi->hge = hge; - - fi->hfd = hfd = headerFreeData; - - if (h && fi->h == NULL) fi->h = headerLink(h); - - /* Duplicate name-version-release so that headers can be free'd. */ - hge(fi->h, RPMTAG_NAME, NULL, (void **) &fi->name, NULL); - fi->name = xstrdup(fi->name); - hge(fi->h, RPMTAG_VERSION, NULL, (void **) &fi->version, NULL); - fi->version = xstrdup(fi->version); - hge(fi->h, RPMTAG_RELEASE, NULL, (void **) &fi->release, NULL); - fi->release = xstrdup(fi->release); - - /* -1 means not found */ - rc = hge(fi->h, RPMTAG_EPOCH, NULL, (void **) &uip, NULL); - fi->epoch = (rc ? *uip : -1); - /* 0 means unknown */ - rc = hge(fi->h, RPMTAG_ARCHIVESIZE, NULL, (void **) &uip, NULL); - fi->archiveSize = (rc ? *uip : 0); - - if (!hge(fi->h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc)) { - fi->dc = 0; - fi->fc = 0; - return; - } - - hge(fi->h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL); - hge(fi->h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc); - hge(fi->h, RPMTAG_FILEMODES, NULL, (void **) &fi->fmodes, NULL); - hge(fi->h, RPMTAG_FILEFLAGS, NULL, (void **) &fi->fflags, NULL); - hge(fi->h, RPMTAG_FILESIZES, NULL, (void **) &fi->fsizes, NULL); - hge(fi->h, RPMTAG_FILESTATES, NULL, (void **) &fi->fstates, NULL); - - fi->action = FA_UNKNOWN; - fi->flags = 0; - - /* actions is initialized earlier for added packages */ - if (fi->actions == NULL) - fi->actions = xcalloc(fi->fc, sizeof(*fi->actions)); - - switch (fi->type) { - case TR_ADDED: - fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID; - hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL); - hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL); - hge(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fi->flangs, NULL); - hge(fi->h, RPMTAG_FILEMTIMES, NULL, (void **) &fi->fmtimes, NULL); - - /* 0 makes for noops */ - fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes)); - - break; - case TR_REMOVED: - fi->mapflags = CPIO_MAP_PATH; - hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL); - hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL); - fi->fsizes = memcpy(xmalloc(fi->fc * sizeof(*fi->fsizes)), - fi->fsizes, fi->fc * sizeof(*fi->fsizes)); - fi->fflags = memcpy(xmalloc(fi->fc * sizeof(*fi->fflags)), - fi->fflags, fi->fc * sizeof(*fi->fflags)); - fi->fmodes = memcpy(xmalloc(fi->fc * sizeof(*fi->fmodes)), - fi->fmodes, fi->fc * sizeof(*fi->fmodes)); - /* XXX there's a tedious segfault here for some version(s) of rpm */ - if (fi->fstates) - fi->fstates = memcpy(xmalloc(fi->fc * sizeof(*fi->fstates)), - fi->fstates, fi->fc * sizeof(*fi->fstates)); - else - fi->fstates = xcalloc(1, fi->fc * sizeof(*fi->fstates)); - fi->dil = memcpy(xmalloc(fi->fc * sizeof(*fi->dil)), - fi->dil, fi->fc * sizeof(*fi->dil)); - headerFree(fi->h); - fi->h = NULL; - break; - } - - fi->dnlmax = -1; - for (i = 0; i < fi->dc; i++) { - if ((len = strlen(fi->dnl[i])) > fi->dnlmax) - fi->dnlmax = len; - } - - fi->bnlmax = -1; - for (i = 0; i < fi->fc; i++) { - if ((len = strlen(fi->bnl[i])) > fi->bnlmax) - fi->bnlmax = len; - } - - fi->dperms = 0755; - fi->fperms = 0644; - - return; -} - -void freeFi(TFI_t fi) -{ - HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData); - - fi->name = _free(fi->name); - fi->version = _free(fi->version); - fi->release = _free(fi->release); - fi->actions = _free(fi->actions); - fi->replacedSizes = _free(fi->replacedSizes); - fi->replaced = _free(fi->replaced); - - fi->bnl = hfd(fi->bnl, -1); - fi->dnl = hfd(fi->dnl, -1); - fi->obnl = hfd(fi->obnl, -1); - fi->odnl = hfd(fi->odnl, -1); - fi->flinks = hfd(fi->flinks, -1); - fi->fmd5s = hfd(fi->fmd5s, -1); - fi->fuser = hfd(fi->fuser, -1); - fi->fgroup = hfd(fi->fgroup, -1); - fi->flangs = hfd(fi->flangs, -1); - - fi->apath = _free(fi->apath); - fi->fuids = _free(fi->fuids); - fi->fgids = _free(fi->fgids); - fi->fmapflags = _free(fi->fmapflags); - - fi->fsm = freeFSM(fi->fsm); - - switch (fi->type) { - case TR_ADDED: - break; - case TR_REMOVED: - fi->fsizes = hfd(fi->fsizes, -1); - fi->fflags = hfd(fi->fflags, -1); - fi->fmodes = hfd(fi->fmodes, -1); - fi->fstates = hfd(fi->fstates, -1); - fi->dil = hfd(fi->dil, -1); - break; - } - if (fi->h) { - headerFree(fi->h); fi->h = NULL; - } -} - -/*@observer@*/ const char *const fiTypeString(TFI_t fi) { - switch(fi->type) { - case TR_ADDED: return " install"; - case TR_REMOVED: return " erase"; - default: return "???"; - } - /*@noteached@*/ -} - -/*@observer@*/ const char *const fileStageString(fileStage a) { - switch(a) { - case FSM_UNKNOWN: return "unknown"; - - case FSM_PKGINSTALL:return "pkginstall"; - case FSM_PKGERASE: return "pkgerase"; - case FSM_PKGBUILD: return "pkgbuild"; - case FSM_PKGCOMMIT: return "pkgcommit"; - case FSM_PKGUNDO: return "pkgundo"; - - case FSM_CREATE: return "create"; - case FSM_INIT: return "init"; - case FSM_MAP: return "map"; - case FSM_MKDIRS: return "mkdirs"; - case FSM_RMDIRS: return "rmdirs"; - case FSM_PRE: return "pre"; - case FSM_PROCESS: return "process"; - case FSM_POST: return "post"; - case FSM_MKLINKS: return "mklinks"; - case FSM_NOTIFY: return "notify"; - case FSM_UNDO: return "undo"; - case FSM_FINI: return "fini"; - case FSM_COMMIT: return "commit"; - case FSM_DESTROY: return "destroy"; - case FSM_VERIFY: return "verify"; - - case FSM_UNLINK: return "Unlink"; - case FSM_RENAME: return "Rename"; - case FSM_MKDIR: return "Mkdir"; - case FSM_RMDIR: return "rmdir"; - case FSM_CHOWN: return "chown"; - case FSM_LCHOWN: return "lchown"; - case FSM_CHMOD: return "chmod"; - case FSM_UTIME: return "utime"; - case FSM_SYMLINK: return "symlink"; - case FSM_LINK: return "Link"; - case FSM_MKFIFO: return "mkfifo"; - case FSM_MKNOD: return "mknod"; - case FSM_LSTAT: return "Lstat"; - case FSM_STAT: return "Stat"; - case FSM_READLINK: return "Readlink"; - case FSM_CHROOT: return "chroot"; - - case FSM_NEXT: return "next"; - case FSM_EAT: return "eat"; - case FSM_POS: return "pos"; - case FSM_PAD: return "pad"; - case FSM_TRAILER: return "trailer"; - case FSM_HREAD: return "hread"; - case FSM_HWRITE: return "hwrite"; - case FSM_DREAD: return "Fread"; - case FSM_DWRITE: return "Fwrite"; - - case FSM_ROPEN: return "Fopen"; - case FSM_READ: return "Fread"; - case FSM_RCLOSE: return "Fclose"; - case FSM_WOPEN: return "Fopen"; - case FSM_WRITE: return "Fwrite"; - case FSM_WCLOSE: return "Fclose"; - - default: return "???"; - } - /*@noteached@*/ -} - -/*@obserever@*/ const char *const fileActionString(fileAction a) -{ - switch (a) { - case FA_UNKNOWN: return "unknown"; - case FA_CREATE: return "create"; - case FA_BACKUP: return "backup"; - case FA_SAVE: return "save"; - case FA_SKIP: return "skip"; - case FA_ALTNAME: return "altname"; - case FA_ERASE: return "erase"; - case FA_SKIPNSTATE: return "skipnstate"; - case FA_SKIPNETSHARED: return "skipnetshared"; - case FA_SKIPMULTILIB: return "skipmultilib"; - default: return "???"; - } - /*@notreached@*/ -} - -#ifdef DYING -/** - */ -struct pkgIterator { -/*@dependent@*/ /*@kept@*/ TFI_t fi; - int i; -}; - -/** - */ -static /*@null@*/ void * pkgFreeIterator(/*@only@*/ /*@null@*/ void * this) { - return _free(this); -} - -/** - */ -static /*@only@*/ void * pkgInitIterator(/*@kept@*/ rpmTransactionSet ts, - /*@kept@*/ TFI_t fi) -{ - struct pkgIterator * pi = NULL; - if (ts && fi) { - pi = xcalloc(sizeof(*pi), 1); - pi->fi = fi; - switch (fi->type) { - case TR_ADDED: pi->i = 0; break; - case TR_REMOVED: pi->i = fi->fc; break; - } - } - return pi; -} - -/** - */ -static int pkgNextIterator(/*@null@*/ void * this) { - struct pkgIterator * pi = this; - int i = -1; - - if (pi) { - TFI_t fi = pi->fi; - switch (fi->type) { - case TR_ADDED: - if (pi->i < fi->fc) - i = pi->i++; - break; - case TR_REMOVED: - if (pi->i >= 0) - i = --pi->i; - break; - } - } - return i; -} - -int pkgActions(const rpmTransactionSet ts, TFI_t fi, fileStage a) -{ - int rc = 0; - - if (fi->actions) { - void * pi = pkgInitIterator(ts, fi); - int i; - while ((i = pkgNextIterator(pi)) != -1) { - if (pkgAction(ts, fi, i, a)) - rc++; - } - pi = pkgFreeIterator(pi); - } - return rc; -} -#endif diff --git a/lib/rollback.h b/lib/rollback.h deleted file mode 100644 index a772c9a..0000000 --- a/lib/rollback.h +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef H_ROLLBACK -#define H_ROLLBACK - -/** \file lib/rollback.h - */ - -#include "depends.h" -#include "install.h" - -/** - */ -typedef /*@abstract@*/ struct fsm_s * FSM_t; - -#include "cpio.h" - -/** - */ -#define FSM_VERBOSE 0x8000 -#define FSM_INTERNAL 0x4000 -#define FSM_SYSCALL 0x2000 -#define FSM_DEAD 0x1000 -#define _fv(_a) ((_a) | FSM_VERBOSE) -#define _fi(_a) ((_a) | FSM_INTERNAL) -#define _fs(_a) ((_a) | (FSM_INTERNAL | FSM_SYSCALL)) -#define _fd(_a) ((_a) | (FSM_INTERNAL | FSM_DEAD)) -typedef enum fileStage_e { - FSM_UNKNOWN = 0, - FSM_INIT = _fd(1), - FSM_PRE = _fd(2), - FSM_PROCESS = _fv(3), - FSM_POST = _fd(4), - FSM_UNDO = 5, - FSM_FINI = 6, - - FSM_PKGINSTALL = _fd(7), - FSM_PKGERASE = _fd(8), - FSM_PKGBUILD = _fd(9), - FSM_PKGCOMMIT = _fd(10), - FSM_PKGUNDO = _fd(11), - - FSM_CREATE = _fd(17), - FSM_MAP = _fd(18), - FSM_MKDIRS = _fi(19), - FSM_RMDIRS = _fi(20), - FSM_MKLINKS = _fi(21), - FSM_NOTIFY = _fd(22), - FSM_DESTROY = _fd(23), - FSM_VERIFY = _fd(24), - FSM_COMMIT = _fd(25), - - FSM_UNLINK = _fs(33), - FSM_RENAME = _fs(34), - FSM_MKDIR = _fs(35), - FSM_RMDIR = _fs(36), - FSM_CHOWN = _fs(37), - FSM_LCHOWN = _fs(38), - FSM_CHMOD = _fs(39), - FSM_UTIME = _fs(40), - FSM_SYMLINK = _fs(41), - FSM_LINK = _fs(42), - FSM_MKFIFO = _fs(43), - FSM_MKNOD = _fs(44), - FSM_LSTAT = _fs(45), - FSM_STAT = _fs(46), - FSM_READLINK= _fs(47), - FSM_CHROOT = _fs(48), - - FSM_NEXT = _fd(65), - FSM_EAT = _fd(66), - FSM_POS = _fd(67), - FSM_PAD = _fd(68), - FSM_TRAILER = _fd(69), - FSM_HREAD = _fd(70), - FSM_HWRITE = _fd(71), - FSM_DREAD = _fs(72), - FSM_DWRITE = _fs(73), - - FSM_ROPEN = _fs(129), - FSM_READ = _fs(130), - FSM_RCLOSE = _fs(131), - FSM_WOPEN = _fs(132), - FSM_WRITE = _fs(133), - FSM_WCLOSE = _fs(134), -} fileStage; -#undef _fi - -/** - * File disposition(s) during package install/erase transaction. - */ -typedef enum fileAction_e { - FA_UNKNOWN = 0, /*!< initial action (default action for source rpm) */ - FA_CREATE, /*!< ... to be replaced. */ - FA_BACKUP, /*!< ... renamed with ".rpmorig" extension. */ - FA_SAVE, /*!< ... renamed with ".rpmsave" extension. */ - FA_SKIP, /*!< ... already replaced, don't remove. */ - FA_ALTNAME, /*!< ... create with ".rpmnew" extension. */ - FA_ERASE, /*!< ... to be removed. */ - FA_SKIPNSTATE, /*!< ... untouched, state "not installed". */ - FA_SKIPNETSHARED, /*!< ... untouched, state "netshared". */ - FA_SKIPMULTILIB, /*!< ... untouched. @todo state "multilib" ???. */ -} fileAction; - - -#define XFA_SKIPPING(_a) \ - ((_a) == FA_SKIP || (_a) == FA_SKIPNSTATE || (_a) == FA_SKIPNETSHARED || (_a) == FA_SKIPMULTILIB) - -/** - */ -typedef enum rollbackDir_e { - ROLLBACK_SAVE = 1, /*!< Save files. */ - ROLLBACK_RESTORE = 2, /*!< Restore files. */ -} rollbackDir; - -/** - * File types. - * These are the types of files used internally by rpm. The file - * type is determined by applying stat(2) macros like S_ISDIR to - * the file mode tag from a header. The values are arbitrary, - * but are identical to the linux stat(2) file types. - */ -enum fileTypes { - PIPE = 1, /*!< pipe/fifo */ - CDEV = 2, /*!< character device */ - XDIR = 4, /*!< directory */ - BDEV = 6, /*!< block device */ - REG = 8, /*!< regular file */ - LINK = 10, /*!< hard link */ - SOCK = 12, /*!< socket */ -}; - -/** - */ -struct transactionFileInfo_s { - /* for all packages */ - enum rpmTransactionType type; - fileAction action; /*!< File disposition default. */ -/*@owned@*/ fileAction * actions; /*!< File disposition(s) */ -/*@owned@*/ struct fingerPrint_s * fps; /*!< File fingerprint(s) */ - HGE_t hge; /*!< Vector to headerGetEntry() */ - HFD_t hfd; /*!< Vector to headerFreeData() */ - Header h; /*!< Package header */ -/*@owned@*/ const char * name; -/*@owned@*/ const char * version; -/*@owned@*/ const char * release; - int_32 epoch; - uint_32 flags; /*!< File flag default. */ - const uint_32 * fflags; /*!< File flag(s) (from header) */ - const uint_32 * fsizes; /*!< File size(s) (from header) */ - const uint_32 * fmtimes; /*!< File modification time(s) (from header) */ -/*@owned@*/ const char ** bnl; /*!< Base name(s) (from header) */ -/*@owned@*/ const char ** dnl; /*!< Directory name(s) (from header) */ - int_32 * dil; /*!< Directory indice(s) (from header) */ -/*@owned@*/ const char ** obnl; /*!< Original base name(s) (from header) */ -/*@owned@*/ const char ** odnl; /*!< Original directory name(s) (from header) */ - int_32 * odil; /*!< Original directory indice(s) (from header) */ -/*@owned@*/ const char ** fmd5s;/*!< File MD5 sum(s) (from header) */ -/*@owned@*/ const char ** flinks; /*!< File link(s) (from header) */ -/* XXX setuid/setgid bits are turned off if fuser/fgroup doesn't map. */ - uint_16 * fmodes; /*!< File mode(s) (from header) */ -/*@owned@*/ char * fstates; /*!< File state(s) (from header) */ -/*@owned@*/ const char ** fuser; /*!< File owner(s) */ -/*@owned@*/ const char ** fgroup; /*!< File group(s) */ -/*@owned@*/ const char ** flangs; /*!< File lang(s) */ - int fc; /*!< No. of files. */ - int dc; /*!< No. of directories. */ - int bnlmax; /*!< Length (in bytes) of longest base name. */ - int dnlmax; /*!< Length (in bytes) of longest dir name. */ - int astriplen; - int striplen; - int scriptArg; - unsigned int archiveSize; - mode_t dperms; /*!< Directory perms (0755) if not mapped. */ - mode_t fperms; /*!< File perms (0644) if not mapped. */ -/*@owned@*/ const char ** apath; - int mapflags; -/*@owned@*/ int * fmapflags; - uid_t uid; -/*@owned@*/ /*@null@*/ uid_t * fuids; /*!< File uid(s) */ - gid_t gid; -/*@owned@*/ /*@null@*/ gid_t * fgids; /*!< File gid(s) */ - int magic; -#define TFIMAGIC 0x09697923 -/*@owned@*/ FSM_t fsm; /*!< File state machine data. */ - - /* these are for TR_ADDED packages */ -/*@dependent@*/ struct availablePackage * ap; -/*@owned@*/ struct sharedFileInfo * replaced; -/*@owned@*/ uint_32 * replacedSizes; - /* for TR_REMOVED packages */ - unsigned int record; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Create file state machine instance. - * @return file state machine data - */ -/*@only@*/ /*@null@*/ FSM_t newFSM(void); - -/** - * Destroy file state machine instance. - * @param fsm file state machine data - * @return always NULL - */ -/*@null@*/ FSM_t freeFSM(/*@only@*/ /*@null@*/ FSM_t fsm); - -/** - * Load data from header into transaction file element info. - * @param h header - * @param fi transaction element file info - */ -void loadFi(Header h, TFI_t fi) - /*@modifies h, fi @*/; - -/** - * Destroy transaction element file info. - * @param fi transaction element file info - */ -void freeFi(TFI_t fi) - /*@modifies fi @*/; - -/** - * Return formatted string representation of package disposition. - * @param a package dispostion - * @return formatted string - */ -/*@observer@*/ const char *const fiTypeString(TFI_t fi); - -/** - * Return formatted string representation of file stages. - * @param a file stage - * @return formatted string - */ -/*@observer@*/ const char *const fileStageString(fileStage a); - -/** - * Return formatted string representation of file disposition. - * @param a file dispostion - * @return formatted string - */ -/*@observer@*/ const char *const fileActionString(fileAction a); - -#ifdef DYING -/** - * Perform package install/remove actions for s single file. - * @todo Eliminate. - * @param ts transaction set - * @param fi transaction element file info - * @param i file index - * @param a file stage - * @return 0 on success, 1 on failure - */ -int pkgAction(const rpmTransactionSet ts, TFI_t fi, int i, fileStage a); - -/** - * Perform package pre-install and remove actions. - * @todo Eliminate. - * @param ts transaction set - * @param fi transaction element file info - * @param a file stage - * @return 0 on success, otherwise no. of failures - */ -int pkgActions(const rpmTransactionSet ts, TFI_t fi, fileStage a); -#endif - -/** - * Load external data into file state machine. - * @param fsm file state machine data - * @param goal - * @param ts transaction set - * @param fi transaction element file info - * @param archiveSize pointer to archive size - * @param failedFile pointer to first file name that failed. - * @return 0 on success - */ -int fsmSetup(FSM_t fsm, fileStage goal, - /*@kept@*/ const rpmTransactionSet ts, - /*@kept@*/ const TFI_t fi, - FD_t cfd, - /*@out@*/ unsigned int * archiveSize, - /*@out@*/ const char ** failedFile) - /*@modifies fsm, *archiveSize, *failedFile @*/; - -/** - * Clean file state machine. - * @param fsm file state machine data - * @return 0 on success - */ -int fsmTeardown(FSM_t fsm) - /*@modifies fsm @*/; - -/** - * Retrieve transaction set from file state machine iterator. - * @param fsm file state machine data - * @return transaction set - */ -/*@kept@*/ rpmTransactionSet fsmGetTs(const FSM_t fsm) /*@*/; - -/** - * Retrieve transaction element file info from file state machine iterator. - * @param fsm file state machine data - * @return transaction element file info - */ -/*@kept@*/ TFI_t fsmGetFi(const FSM_t fsm) /*@*/; - -/** - * Map next file path and action. - * @param fsm file state machine data - */ -int fsmMapPath(FSM_t fsm) - /*@modifies fsm @*/; - -/** - * Map file stat(2) info. - * @param fsm file state machine data - */ -int fsmMapAttrs(FSM_t fsm) - /*@modifies fsm @*/; - -/** - * File state machine driver. - * @param fsm file state machine data - * @param stage next stage - * @return 0 on success - */ -int fsmStage(FSM_t fsm, fileStage stage) - /*@modifies fsm @*/; - -#ifdef __cplusplus -} -#endif - -#endif /* H_ROLLBACK */ diff --git a/lib/rpmlib.h b/lib/rpmlib.h index b1eb8ea..1ce0029 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -868,6 +868,56 @@ int rpmInstallSourcePackage(const char * root, FD_t fd, */ int rpmVersionCompare(Header first, Header second); +/** + * File disposition(s) during package install/erase transaction. + */ +typedef enum fileAction_e { + FA_UNKNOWN = 0, /*!< initial action for file ... */ + FA_CREATE, /*!< ... to be replaced. */ + FA_BACKUP, /*!< ... renamed with ".rpmorig" extension. */ + FA_SAVE, /*!< ... renamed with ".rpmsave" extension. */ + FA_SKIP, /*!< ... already replaced, don't remove. */ + FA_ALTNAME, /*!< ... create with ".rpmnew" extension. */ + FA_ERASE, /*!< ... to be removed. */ + FA_SKIPNSTATE, /*!< ... untouched, state "not installed". */ + FA_SKIPNETSHARED, /*!< ... untouched, state "netshared". */ + FA_SKIPMULTILIB, /*!< ... untouched. @todo state "multilib" ???. */ +} fileAction; + +#define XFA_SKIPPING(_a) \ + ((_a) == FA_SKIP || (_a) == FA_SKIPNSTATE || (_a) == FA_SKIPNETSHARED || (_a) == FA_SKIPMULTILIB) + +/** + * File types. + * These are the types of files used internally by rpm. The file + * type is determined by applying stat(2) macros like S_ISDIR to + * the file mode tag from a header. The values are arbitrary, + * but are identical to the linux stat(2) file types. + */ +typedef enum fileTypes_e { + PIPE = 1, /*!< pipe/fifo */ + CDEV = 2, /*!< character device */ + XDIR = 4, /*!< directory */ + BDEV = 6, /*!< block device */ + REG = 8, /*!< regular file */ + LINK = 10, /*!< hard link */ + SOCK = 12, /*!< socket */ +} fileTypes; + +/** \ingroup payload + * Iterator across package file info, forward on install, backward on erase. + */ +typedef /*@abstract@*/ struct fsmIterator_s * FSMI_t; + +/** \ingroup payload + * File state machine data. + */ +typedef /*@abstract@*/ struct fsm_s * FSM_t; + +/** \ingroup rpmtrans + */ +typedef /*@abstract@*/ struct transactionFileInfo_s * TFI_t; + /** \ingroup rpmtrans * The RPM Transaction Set. * Transaction sets are inherently unordered! RPM may reorder transaction diff --git a/lib/scriptlet.c b/lib/scriptlet.c new file mode 100644 index 0000000..d37c0fc --- /dev/null +++ b/lib/scriptlet.c @@ -0,0 +1,453 @@ +/** \ingroup rpmtrans payload + * \file lib/scriptlet.c + */ + +#include "system.h" + +#include +#include +#include /* XXX for rpmExpand */ + +#include "depends.h" /* XXX for headerMatchesDepFlags */ +#include "scriptlet.h" +#include "misc.h" /* XXX for makeTempFile, doputenv */ +#include "debug.h" + +/*@access Header@*/ /* XXX compared with NULL */ + +static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin"; + +/** + * Return scriptlet name from tag. + * @param tag scriptlet tag + * @return name of scriptlet + */ +static /*@observer@*/ const char * const tag2sln(int tag) +{ + switch (tag) { + case RPMTAG_PREIN: return "%pre"; + case RPMTAG_POSTIN: return "%post"; + case RPMTAG_PREUN: return "%preun"; + case RPMTAG_POSTUN: return "%postun"; + case RPMTAG_VERIFYSCRIPT: return "%verify"; + } + return "%unknownscript"; +} + +/** + * Run scriptlet with args. + * + * Run a script with an interpreter. If the interpreter is not specified, + * /bin/sh will be used. If the interpreter is /bin/sh, then the args from + * the header will be ignored, passing instead arg1 and arg2. + * + * @param ts transaction set + * @param h header + * @param sln name of scriptlet section + * @param progArgc no. of args from header + * @param progArgv args from header, progArgv[0] is the interpreter to use + * @param script scriptlet from header + * @param arg1 no. instances of package installed after scriptlet exec + * (-1 is no arg) + * @param arg2 ditto, but for the target package + * @return 0 on success, 1 on error + */ +static int runScript(const rpmTransactionSet ts, Header h, + const char * sln, + int progArgc, const char ** progArgv, + const char * script, int arg1, int arg2) +{ + const char ** argv = NULL; + int argc = 0; + const char ** prefixes = NULL; + int numPrefixes; + const char * oldPrefix; + int maxPrefixLength; + int len; + char * prefixBuf = NULL; + pid_t child; + int status = 0; + const char * fn = NULL; + int i; + int freePrefixes = 0; + FD_t out; + int rc = 0; + const char *n, *v, *r; + + if (!progArgv && !script) + return 0; + + if (!progArgv) { + argv = alloca(5 * sizeof(char *)); + argv[0] = "/bin/sh"; + argc = 1; + } else { + argv = alloca((progArgc + 4) * sizeof(char *)); + memcpy(argv, progArgv, progArgc * sizeof(char *)); + argc = progArgc; + } + + headerNVR(h, &n, &v, &r); + if (headerGetEntry(h, RPMTAG_INSTPREFIXES, NULL, (void **) &prefixes, + &numPrefixes)) { + freePrefixes = 1; + } else if (headerGetEntry(h, RPMTAG_INSTALLPREFIX, NULL, + (void **) &oldPrefix, NULL)) + { + prefixes = &oldPrefix; + numPrefixes = 1; + } else { + numPrefixes = 0; + } + + maxPrefixLength = 0; + for (i = 0; i < numPrefixes; i++) { + len = strlen(prefixes[i]); + if (len > maxPrefixLength) maxPrefixLength = len; + } + prefixBuf = alloca(maxPrefixLength + 50); + + if (script) { + FD_t fd; + if (makeTempFile((!ts->chrootDone ? ts->rootDir : "/"), &fn, &fd)) { + if (freePrefixes) free(prefixes); + return 1; + } + + if (rpmIsDebug() && + (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash"))) + (void)Fwrite("set -x\n", sizeof(char), 7, fd); + + (void)Fwrite(script, sizeof(script[0]), strlen(script), fd); + Fclose(fd); + + { const char * sn = fn; + if (!ts->chrootDone && + !(ts->rootDir[0] == '/' && ts->rootDir[1] == '\0')) + { + sn += strlen(ts->rootDir)-1; + } + argv[argc++] = sn; + } + + if (arg1 >= 0) { + char *av = alloca(20); + sprintf(av, "%d", arg1); + argv[argc++] = av; + } + if (arg2 >= 0) { + char *av = alloca(20); + sprintf(av, "%d", arg2); + argv[argc++] = av; + } + } + + argv[argc] = NULL; + + if (ts->scriptFd != NULL) { + if (rpmIsVerbose()) { + out = fdDup(Fileno(ts->scriptFd)); + } else { + out = Fopen("/dev/null", "w.fdio"); + if (Ferror(out)) { + out = fdDup(Fileno(ts->scriptFd)); + } + } + } else { + out = fdDup(STDOUT_FILENO); + out = fdLink(out, "runScript persist"); + } + + if (!(child = fork())) { + const char * rootDir; + int pipes[2]; + + pipes[0] = pipes[1] = 0; + /* make stdin inaccessible */ + pipe(pipes); + close(pipes[1]); + dup2(pipes[0], STDIN_FILENO); + close(pipes[0]); + + if (ts->scriptFd != NULL) { + if (Fileno(ts->scriptFd) != STDERR_FILENO) + dup2(Fileno(ts->scriptFd), STDERR_FILENO); + if (Fileno(out) != STDOUT_FILENO) + dup2(Fileno(out), STDOUT_FILENO); + /* make sure we don't close stdin/stderr/stdout by mistake! */ + if (Fileno(out) > STDERR_FILENO && Fileno(out) != Fileno(ts->scriptFd)) { + Fclose (out); + } + if (Fileno(ts->scriptFd) > STDERR_FILENO) { + Fclose (ts->scriptFd); + } + } + + { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL); + const char *path = SCRIPT_PATH; + + if (ipath && ipath[5] != '%') + path = ipath; + doputenv(path); + if (ipath) free((void *)ipath); + } + + for (i = 0; i < numPrefixes; i++) { + sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]); + doputenv(prefixBuf); + + /* backwards compatibility */ + if (i == 0) { + sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]); + doputenv(prefixBuf); + } + } + + rootDir = ts->rootDir; + switch(urlIsURL(rootDir)) { + case URL_IS_PATH: + rootDir += sizeof("file://") - 1; + rootDir = strchr(rootDir, '/'); + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + if (!ts->chrootDone && !(rootDir[0] == '/' && rootDir[1] == '\0')) { + /*@-unrecog@*/ chroot(rootDir); /*@=unrecog@*/ + } + chdir("/"); + execv(argv[0], (char *const *)argv); + break; + default: + break; + } + + _exit(-1); + /*@notreached@*/ + } + + if (waitpid(child, &status, 0) < 0) { + rpmError(RPMERR_SCRIPT, + _("execution of %s scriptlet from %s-%s-%s failed, waitpid returned %s\n"), + sln, n, v, r, strerror (errno)); + /* XXX what to do here? */ + rc = 0; + } else { + if (!WIFEXITED(status) || WEXITSTATUS(status)) { + rpmError(RPMERR_SCRIPT, + _("execution of %s scriptlet from %s-%s-%s failed, exit status %d\n"), + sln, n, v, r, WEXITSTATUS(status)); + rc = 1; + } + } + + if (freePrefixes) free(prefixes); + + Fclose(out); /* XXX dup'd STDOUT_FILENO */ + + if (script) { + if (!rpmIsDebug()) unlink(fn); + free((void *)fn); + } + + return rc; +} + +int runInstScript(const rpmTransactionSet ts, Header h, + int scriptTag, int progTag, int arg, int norunScripts) +{ + void ** programArgv; + int programArgc; + const char ** argv; + int programType; + char * script; + int rc; + + if (norunScripts) return 0; + + /* headerGetEntry() sets the data pointer to NULL if the entry does + not exist */ + headerGetEntry(h, progTag, &programType, (void **) &programArgv, + &programArgc); + headerGetEntry(h, scriptTag, NULL, (void **) &script, NULL); + + if (programArgv && programType == RPM_STRING_TYPE) { + argv = alloca(sizeof(char *)); + *argv = (const char *) programArgv; + } else { + argv = (const char **) programArgv; + } + + rc = runScript(ts, h, tag2sln(scriptTag), programArgc, argv, script, + arg, -1); + programArgv = headerFreeData(programArgv, programType); + return rc; +} + +/** + * @param ts transaction set + * @param sense + * @param sourceH + * @param triggeredH + * @param arg1correction + * @param arg2 + * @param triggersAlreadyRun + * @return + */ +static int handleOneTrigger(const rpmTransactionSet ts, int sense, + Header sourceH, Header triggeredH, + int arg1correction, int arg2, + char * triggersAlreadyRun) +{ + const char ** triggerNames; + const char ** triggerEVR; + const char ** triggerScripts; + const char ** triggerProgs; + int_32 * triggerFlags; + int_32 * triggerIndices; + const char * triggerPackageName; + const char * sourceName; + int numTriggers; + int rc = 0; + int i; + int skip; + + if (!headerGetEntry(triggeredH, RPMTAG_TRIGGERNAME, NULL, + (void **) &triggerNames, &numTriggers)) { + return 0; + } + + headerNVR(sourceH, &sourceName, NULL, NULL); + + headerGetEntry(triggeredH, RPMTAG_TRIGGERFLAGS, NULL, + (void **) &triggerFlags, NULL); + headerGetEntry(triggeredH, RPMTAG_TRIGGERVERSION, NULL, + (void **) &triggerEVR, NULL); + + for (i = 0; i < numTriggers; i++) { + + if (!(triggerFlags[i] & sense)) continue; + if (strcmp(triggerNames[i], sourceName)) continue; + + /* + * For some reason, the TRIGGERVERSION stuff includes the name of + * the package which the trigger is based on. We need to skip + * over that here. I suspect that we'll change our minds on this + * and remove that, so I'm going to just 'do the right thing'. + */ + skip = strlen(triggerNames[i]); + if (!strncmp(triggerEVR[i], triggerNames[i], skip) && + (triggerEVR[i][skip] == '-')) + skip++; + else + skip = 0; + + if (!headerMatchesDepFlags(sourceH, triggerNames[i], + triggerEVR[i] + skip, triggerFlags[i])) + continue; + + headerGetEntry(triggeredH, RPMTAG_TRIGGERINDEX, NULL, + (void **) &triggerIndices, NULL); + headerGetEntry(triggeredH, RPMTAG_TRIGGERSCRIPTS, NULL, + (void **) &triggerScripts, NULL); + headerGetEntry(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, NULL, + (void **) &triggerProgs, NULL); + + headerNVR(triggeredH, &triggerPackageName, NULL, NULL); + + { int arg1; + int index; + + if ((arg1 = rpmdbCountPackages(ts->rpmdb, triggerPackageName)) < 0) { + rc = 1; /* XXX W2DO? same as "execution of script failed" */ + } else { + arg1 += arg1correction; + index = triggerIndices[i]; + if (!triggersAlreadyRun || !triggersAlreadyRun[index]) { + rc = runScript(ts, triggeredH, "%trigger", 1, + triggerProgs + index, triggerScripts[index], + arg1, arg2); + if (triggersAlreadyRun) triggersAlreadyRun[index] = 1; + } + } + } + + free(triggerScripts); + free(triggerProgs); + + /* each target/source header pair can only result in a single + script being run */ + break; + } + + free(triggerNames); + + return rc; +} + +int runTriggers(const rpmTransactionSet ts, int sense, Header h, + int countCorrection) +{ + const char * name; + int numPackage; + int rc = 0; + + headerNVR(h, &name, NULL, NULL); + + numPackage = rpmdbCountPackages(ts->rpmdb, name) + countCorrection; + if (numPackage < 0) + return 1; + + { Header triggeredH; + rpmdbMatchIterator mi; + + mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_TRIGGERNAME, name, 0); + while((triggeredH = rpmdbNextIterator(mi)) != NULL) { + rc |= handleOneTrigger(ts, sense, h, triggeredH, 0, numPackage, + NULL); + } + + rpmdbFreeIterator(mi); + } + + return rc; +} + +int runImmedTriggers(const rpmTransactionSet ts, int sense, Header h, + int countCorrection) +{ + const char ** triggerNames; + int numTriggers; + int_32 * triggerIndices; + int numTriggerIndices; + char * triggersRun; + int rc = 0; + + if (!headerGetEntry(h, RPMTAG_TRIGGERNAME, NULL, (void **) &triggerNames, + &numTriggers)) + return 0; + headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &triggerIndices, + &numTriggerIndices); + triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices); + memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices); + + { Header sourceH = NULL; + int i; + + for (i = 0; i < numTriggers; i++) { + rpmdbMatchIterator mi; + const char * name = triggerNames[i]; + + if (triggersRun[triggerIndices[i]]) continue; + + mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, name, 0); + + while((sourceH = rpmdbNextIterator(mi)) != NULL) { + rc |= handleOneTrigger(ts, sense, sourceH, h, + countCorrection, rpmdbGetIteratorCount(mi), + triggersRun); + } + + rpmdbFreeIterator(mi); + } + } + return rc; +} diff --git a/lib/install.h b/lib/scriptlet.h similarity index 59% rename from lib/install.h rename to lib/scriptlet.h index c8860f5..6bc4f19 100644 --- a/lib/install.h +++ b/lib/scriptlet.h @@ -1,32 +1,11 @@ -#ifndef H_INSTALL -#define H_INSTALL +#ifndef H_SCRIPTLET +#define H_SCRIPTLET -/** \file lib/install.h +/** \file lib/scriptlet.h */ #include -/** - */ -struct sharedFile { - int mainFileNumber; - int secRecOffset; - int secFileNumber; -} ; - -/** - */ -struct sharedFileInfo { - int pkgFileNum; - int otherFileNum; - int otherPkg; - int isRemoved; -}; - -/** - */ -typedef /*@abstract@*/ struct transactionFileInfo_s * TFI_t; - #ifdef __cplusplus extern "C" { #endif @@ -66,25 +45,8 @@ int runTriggers(const rpmTransactionSet ts, int sense, Header h, int runImmedTriggers(const rpmTransactionSet ts, int sense, Header h, int countCorrection); -/** - * Install binary package (from transaction set). - * @param ts transaction set - * @param fi transaction element file info - * @return 0 on success, 1 on bad magic, 2 on error - */ -int installBinaryPackage(const rpmTransactionSet ts, TFI_t fi); - -/** - * Erase binary package (from transaction set). - * @param ts transaction set - * @param fi transaction element file info - * @param pkgKey package private data - * @return 0 on success - */ -int removeBinaryPackage(const rpmTransactionSet ts, TFI_t fi); - #ifdef __cplusplus } #endif -#endif /* H_INSTALL */ +#endif /* H_SCRIPTLET */ diff --git a/lib/transaction.c b/lib/transaction.c index a2b6260..f13d9ed 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -7,7 +7,7 @@ #include #include /* XXX for rpmExpand */ -#include "rollback.h" +#include "psm.h" #include "fprint.h" #include "hash.h" #include "md5.h" @@ -242,7 +242,7 @@ void rpmProblemSetFree(rpmProblemSet probs) free(probs); } -static /*@observer@*/ const char *const ftstring (enum fileTypes ft) +static /*@observer@*/ const char *const ftstring (fileTypes ft) { switch (ft) { case XDIR: return "directory"; @@ -257,7 +257,7 @@ static /*@observer@*/ const char *const ftstring (enum fileTypes ft) /*@notreached@*/ } -static enum fileTypes whatis(uint_16 mode) +static fileTypes whatis(uint_16 mode) { if (S_ISDIR(mode)) return XDIR; if (S_ISCHR(mode)) return CDEV; @@ -502,7 +502,7 @@ static Header relocateFileList(const rpmTransactionSet ts, /* On install, a relocate to NULL means skip the path. */ if (relocations[j].newPath == NULL) { - enum fileTypes ft = whatis(fModes[i]); + fileTypes ft = whatis(fModes[i]); int k; if (ft == XDIR) { /* Start with the parent, looking for directory to exclude. */ @@ -711,7 +711,7 @@ static fileAction decideFileFate(const char * dirName, { char buffer[1024]; const char * dbAttr, * newAttr; - enum fileTypes dbWhat, newWhat, diskWhat; + fileTypes dbWhat, newWhat, diskWhat; struct stat sb; int i, rc; int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE; @@ -802,8 +802,8 @@ static fileAction decideFileFate(const char * dirName, static int filecmp(short mode1, const char * md51, const char * link1, short mode2, const char * md52, const char * link2) { - enum fileTypes what1 = whatis(mode1); - enum fileTypes what2 = whatis(mode2); + fileTypes what1 = whatis(mode1); + fileTypes what2 = whatis(mode2); if (what1 != what2) return 1; diff --git a/lib/uninstall.c b/lib/uninstall.c deleted file mode 100644 index 11f4e8d..0000000 --- a/lib/uninstall.c +++ /dev/null @@ -1,115 +0,0 @@ -/** \ingroup rpmtrans payload - * \file lib/uninstall.c - */ - -#include "system.h" - -#include -#include -#include /* XXX for rpmExpand */ - -#include "rollback.h" -#include "misc.h" /* XXX for makeTempFile, doputenv */ -#include "debug.h" - -/*@access Header@*/ /* XXX compared with NULL */ - -int removeBinaryPackage(const rpmTransactionSet ts, TFI_t fi) -{ -/*@observer@*/ static char * stepName = " erase"; - Header h; - int chrootDone = 0; - const char * failedFile = NULL; - const void * pkgKey = NULL; - int rc = 0; - - rpmMessage(RPMMESS_DEBUG, _("%s: %s-%s-%s has %d files, test = %d\n"), - stepName, fi->name, fi->version, fi->release, - fi->fc, (ts->transFlags & RPMTRANS_FLAG_TEST)); - - /* - * When we run scripts, we pass an argument which is the number of - * versions of this package that will be installed when we are finished. - */ - fi->scriptArg = rpmdbCountPackages(ts->rpmdb, fi->name) - 1; - if (fi->scriptArg < 0) - return 1; - - { rpmdbMatchIterator mi = NULL; - - mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, - &fi->record, sizeof(fi->record)); - - h = rpmdbNextIterator(mi); - if (h == NULL) { - rpmdbFreeIterator(mi); - return 2; - } - h = headerLink(h); - rpmdbFreeIterator(mi); - } - - if (ts->rootDir && !ts->chrootDone) { - chdir("/"); - /*@-unrecog@*/ chroot(ts->rootDir); /*@=unrecog@*/ - chrootDone = ts->chrootDone = 1; - } - - if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERS)) { - /* run triggers from this package which are keyed on installed - packages */ - if (runImmedTriggers(ts, RPMSENSE_TRIGGERUN, h, -1)) - return 2; - - /* run triggers which are set off by the removal of this package */ - if (runTriggers(ts, RPMSENSE_TRIGGERUN, h, -1)) - return 1; - } - - rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"), - stepName, "pre-erase"); - - rc = runInstScript(ts, h, RPMTAG_PREUN, RPMTAG_PREUNPROG, fi->scriptArg, - (ts->transFlags & RPMTRANS_FLAG_NOSCRIPTS)); - if (rc) - return 1; - - if (fi->fc > 0 && !(ts->transFlags & RPMTRANS_FLAG_JUSTDB)) { - - if (ts->notify) - (void)ts->notify(h, RPMCALLBACK_UNINST_START, fi->fc, fi->fc, - pkgKey, ts->notifyData); - - rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi, NULL, NULL, &failedFile); - (void) fsmTeardown(fi->fsm); - - if (ts->notify) - (void)ts->notify(h, RPMCALLBACK_UNINST_STOP, 0, fi->fc, - pkgKey, ts->notifyData); - } - - rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"), - stepName, "post-erase"); - - rc = runInstScript(ts, h, RPMTAG_POSTUN, RPMTAG_POSTUNPROG, - fi->scriptArg, (ts->transFlags & RPMTRANS_FLAG_NOSCRIPTS)); - /* XXX postun failures are not cause for erasure failure. */ - - if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERS)) { - /* Run postun triggers which are set off by this package's removal. */ - rc = runTriggers(ts, RPMSENSE_TRIGGERPOSTUN, h, -1); - if (rc) - return 2; - } - - if (ts->rootDir && chrootDone) { - /*@-unrecog@*/ chroot("."); /*@=unrecog@*/ - chrootDone = ts->chrootDone = 0; - chdir(ts->currDir); - } - - if (!(ts->transFlags & RPMTRANS_FLAG_TEST)) - rpmdbRemove(ts->rpmdb, ts->id, fi->record); - - return 0; -} diff --git a/lib/verify.c b/lib/verify.c index 39ce0e0..2a9e3f7 100644 --- a/lib/verify.c +++ b/lib/verify.c @@ -5,11 +5,9 @@ #include "system.h" #include -#include #include -#include "depends.h" -#include "install.h" +#include "psm.h" #include "md5.h" #include "misc.h" #include "debug.h" diff --git a/po/POTFILES.in b/po/POTFILES.in index e07092c..6f32c31 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -33,9 +33,9 @@ lib/falloc.c lib/formats.c lib/fprint.c lib/fs.c +lib/fsm.c lib/hash.c lib/header.c -lib/install.c lib/md5.c lib/md5sum.c lib/misc.c @@ -43,8 +43,8 @@ lib/package.c lib/poptBT.c lib/poptQV.c lib/problems.c +lib/psm.c lib/query.c -lib/rollback.c lib/rpmchecksig.c lib/rpmdb.c lib/rpminstall.c @@ -54,7 +54,6 @@ lib/scriptlet.c lib/signature.c lib/stringbuf.c lib/transaction.c -lib/uninstall.c lib/verify.c rpmio/base64.c rpmio/digest.c diff --git a/po/rpm.pot b/po/rpm.pot index 25024ed..ec772b7 100644 --- a/po/rpm.pot +++ b/po/rpm.pot @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2001-02-10 09:07-0500\n" +"POT-Creation-Date: 2001-02-10 11:46-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -14,1072 +14,1072 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" -#: build.c:26 +#: build.c:25 #, c-format msgid "cannot open rpm database in %s\n" msgstr "" -#: build.c:36 +#: build.c:35 msgid "failed build dependencies:\n" msgstr "" -#: build.c:65 +#: build.c:64 #, c-format msgid "Unable to open spec file %s: %s\n" msgstr "" -#: build.c:132 build.c:144 +#: build.c:131 build.c:143 #, c-format msgid "Failed to open tar pipe: %m\n" msgstr "" #. Give up -#: build.c:151 +#: build.c:150 #, c-format msgid "Failed to read spec file from %s\n" msgstr "" -#: build.c:179 +#: build.c:178 #, c-format msgid "Failed to rename %s to %s: %m\n" msgstr "" -#: build.c:218 +#: build.c:217 #, c-format msgid "failed to stat %s: %m\n" msgstr "" -#: build.c:223 +#: build.c:222 #, c-format msgid "File %s is not a regular file.\n" msgstr "" -#: build.c:232 +#: build.c:231 #, c-format msgid "File %s does not appear to be a specfile.\n" msgstr "" #. parse up the build operators -#: build.c:289 +#: build.c:288 #, c-format msgid "Building target platforms: %s\n" msgstr "" -#: build.c:304 +#: build.c:303 #, c-format msgid "Building for target %s\n" msgstr "" -#: rpm.c:201 rpmqv.c:357 +#: rpm.c:200 rpmqv.c:356 #, c-format msgid "rpm: %s\n" msgstr "" -#: rpm.c:212 rpmqv.c:362 +#: rpm.c:211 rpmqv.c:361 #, c-format msgid "RPM version %s\n" msgstr "" -#: rpm.c:216 rpmqv.c:366 +#: rpm.c:215 rpmqv.c:365 msgid "Copyright (C) 1998-2000 - Red Hat, Inc." msgstr "" -#: rpm.c:217 rpmqv.c:367 +#: rpm.c:216 rpmqv.c:366 msgid "This program may be freely redistributed under the terms of the GNU GPL" msgstr "" -#: rpm.c:225 +#: rpm.c:224 msgid "Usage: rpm {--help}" msgstr "" -#: rpm.c:226 +#: rpm.c:225 msgid " rpm {--version}" msgstr "" -#: rpm.c:227 +#: rpm.c:226 msgid " rpm {--initdb} [--dbpath ]" msgstr "" -#: rpm.c:228 +#: rpm.c:227 msgid "" " rpm {--install -i} [-v] [--hash -h] [--percent] [--force] [--test]" msgstr "" -#: rpm.c:229 +#: rpm.c:228 msgid " [--replacepkgs] [--replacefiles] [--root ]" msgstr "" -#: rpm.c:230 +#: rpm.c:229 msgid " [--excludedocs] [--includedocs] [--noscripts]" msgstr "" -#: rpm.c:231 +#: rpm.c:230 msgid "" " [--rcfile ] [--ignorearch] [--dbpath ]" msgstr "" -#: rpm.c:232 +#: rpm.c:231 msgid "" " [--prefix ] [--ignoreos] [--nodeps] [--allfiles]" msgstr "" -#: rpm.c:233 rpm.c:242 rpm.c:252 +#: rpm.c:232 rpm.c:241 rpm.c:251 msgid " [--ftpproxy ] [--ftpport ]" msgstr "" -#: rpm.c:234 rpm.c:253 +#: rpm.c:233 rpm.c:252 msgid " [--httpproxy ] [--httpport ]" msgstr "" -#: rpm.c:235 +#: rpm.c:234 msgid "" " [--justdb] [--noorder] [--relocate oldpath=newpath]" msgstr "" -#: rpm.c:236 +#: rpm.c:235 msgid "" " [--badreloc] [--notriggers] [--excludepath ]" msgstr "" -#: rpm.c:237 +#: rpm.c:236 msgid " [--ignoresize] file1.rpm ... fileN.rpm" msgstr "" -#: rpm.c:238 +#: rpm.c:237 msgid "" " rpm {--upgrade -U} [-v] [--hash -h] [--percent] [--force] [--test]" msgstr "" -#: rpm.c:239 +#: rpm.c:238 msgid " [--oldpackage] [--root ] [--noscripts]" msgstr "" -#: rpm.c:240 +#: rpm.c:239 msgid "" " [--excludedocs] [--includedocs] [--rcfile ]" msgstr "" -#: rpm.c:241 +#: rpm.c:240 msgid "" " [--ignorearch] [--dbpath ] [--prefix ] " msgstr "" -#: rpm.c:243 +#: rpm.c:242 msgid " [--httpproxy ] [--httpport ] " msgstr "" -#: rpm.c:244 +#: rpm.c:243 msgid " [--ignoreos] [--nodeps] [--allfiles] [--justdb]" msgstr "" -#: rpm.c:245 +#: rpm.c:244 msgid " [--noorder] [--relocate oldpath=newpath]" msgstr "" -#: rpm.c:246 +#: rpm.c:245 msgid "" " [--badreloc] [--excludepath ] [--ignoresize]" msgstr "" -#: rpm.c:247 +#: rpm.c:246 msgid " file1.rpm ... fileN.rpm" msgstr "" -#: rpm.c:248 +#: rpm.c:247 msgid " rpm {--query -q} [-afpg] [-i] [-l] [-s] [-d] [-c] [-v] [-R]" msgstr "" -#: rpm.c:249 +#: rpm.c:248 msgid " [--scripts] [--root ] [--rcfile ]" msgstr "" -#: rpm.c:250 +#: rpm.c:249 msgid " [--whatprovides] [--whatrequires] [--requires]" msgstr "" -#: rpm.c:251 +#: rpm.c:250 msgid " [--triggeredby]" msgstr "" -#: rpm.c:254 +#: rpm.c:253 msgid " [--provides] [--triggers] [--dump]" msgstr "" -#: rpm.c:255 +#: rpm.c:254 msgid " [--changelog] [--dbpath ] [targets]" msgstr "" -#: rpm.c:256 +#: rpm.c:255 msgid " rpm {--verify -V -y} [-afpg] [--root ] [--rcfile ]" msgstr "" -#: rpm.c:257 +#: rpm.c:256 msgid "" " [--dbpath ] [--nodeps] [--nofiles] [--noscripts]" msgstr "" -#: rpm.c:258 +#: rpm.c:257 msgid " [--nomd5] [targets]" msgstr "" -#: rpm.c:259 +#: rpm.c:258 msgid " rpm {--setperms} [-afpg] [target]" msgstr "" -#: rpm.c:260 +#: rpm.c:259 msgid " rpm {--setugids} [-afpg] [target]" msgstr "" -#: rpm.c:261 +#: rpm.c:260 msgid " rpm {--freshen -F} file1.rpm ... fileN.rpm" msgstr "" -#: rpm.c:262 +#: rpm.c:261 msgid " rpm {--erase -e} [--root ] [--noscripts] [--rcfile ]" msgstr "" -#: rpm.c:263 +#: rpm.c:262 msgid " [--dbpath ] [--nodeps] [--allmatches]" msgstr "" -#: rpm.c:264 +#: rpm.c:263 msgid " [--justdb] [--notriggers] package1 ... packageN" msgstr "" -#: rpm.c:265 +#: rpm.c:264 msgid " rpm {--resign} [--rcfile ] package1 package2 ... packageN" msgstr "" -#: rpm.c:266 +#: rpm.c:265 msgid " rpm {--addsign} [--rcfile ] package1 package2 ... packageN" msgstr "" -#: rpm.c:267 +#: rpm.c:266 msgid "" " rpm {--checksig -K} [--nopgp] [--nogpg] [--nomd5] [--rcfile ]" msgstr "" -#: rpm.c:268 +#: rpm.c:267 msgid " package1 ... packageN" msgstr "" -#: rpm.c:269 +#: rpm.c:268 msgid " rpm {--rebuilddb} [--rcfile ] [--dbpath ]" msgstr "" -#: rpm.c:270 +#: rpm.c:269 msgid " rpm {--querytags}" msgstr "" -#: rpm.c:304 rpmqv.c:442 +#: rpm.c:303 rpmqv.c:441 msgid "Usage:" msgstr "" -#: rpm.c:306 rpmqv.c:444 +#: rpm.c:305 rpmqv.c:443 msgid "print this message" msgstr "" -#: rpm.c:308 rpmqv.c:129 rpmqv.c:446 +#: rpm.c:307 rpmqv.c:128 rpmqv.c:445 msgid "print the version of rpm being used" msgstr "" -#: rpm.c:311 +#: rpm.c:310 msgid " All modes support the following arguments:" msgstr "" -#: rpm.c:312 +#: rpm.c:311 msgid " --define ' '" msgstr "" -#: rpm.c:313 rpmqv.c:136 rpmqv.c:451 +#: rpm.c:312 rpmqv.c:135 rpmqv.c:450 msgid "define macro with value " msgstr "" -#: rpm.c:314 +#: rpm.c:313 msgid " --eval '+' " msgstr "" -#: rpm.c:315 +#: rpm.c:314 msgid "print the expansion of macro to stdout" msgstr "" -#: rpm.c:316 +#: rpm.c:315 msgid " --pipe " msgstr "" -#: rpm.c:317 rpmqv.c:142 rpmqv.c:455 +#: rpm.c:316 rpmqv.c:141 rpmqv.c:454 msgid "send stdout to " msgstr "" -#: rpm.c:318 +#: rpm.c:317 msgid " --rcfile " msgstr "" -#: rpm.c:319 +#: rpm.c:318 msgid "use instead of /etc/rpmrc and $HOME/.rpmrc" msgstr "" -#: rpm.c:321 rpmqv.c:160 rpmqv.c:459 +#: rpm.c:320 rpmqv.c:159 rpmqv.c:458 msgid "display final rpmrc and macro configuration" msgstr "" -#: rpm.c:323 rpmqv.c:467 +#: rpm.c:322 rpmqv.c:466 msgid "be a little more verbose" msgstr "" -#: rpm.c:325 rpmqv.c:469 +#: rpm.c:324 rpmqv.c:468 msgid "be incredibly verbose (for debugging)" msgstr "" -#: rpm.c:328 +#: rpm.c:327 msgid " Install, upgrade and query (with -p) allow URL's to be used in place" msgstr "" -#: rpm.c:329 +#: rpm.c:328 msgid " of file names as well as the following options:" msgstr "" -#: rpm.c:330 +#: rpm.c:329 msgid " --ftpproxy " msgstr "" -#: rpm.c:331 rpmqv.c:476 +#: rpm.c:330 rpmqv.c:475 msgid "hostname or IP of ftp proxy" msgstr "" -#: rpm.c:332 +#: rpm.c:331 msgid " --ftpport " msgstr "" -#: rpm.c:333 rpmqv.c:478 +#: rpm.c:332 rpmqv.c:477 msgid "port number of ftp server (or proxy)" msgstr "" -#: rpm.c:334 +#: rpm.c:333 msgid " --httpproxy " msgstr "" -#: rpm.c:335 rpmqv.c:480 +#: rpm.c:334 rpmqv.c:479 msgid "hostname or IP of http proxy" msgstr "" -#: rpm.c:336 +#: rpm.c:335 msgid " --httpport " msgstr "" -#: rpm.c:337 rpmqv.c:482 +#: rpm.c:336 rpmqv.c:481 msgid "port number of http server (or proxy)" msgstr "" -#: rpm.c:341 rpmqv.c:502 +#: rpm.c:340 rpmqv.c:501 msgid "query mode" msgstr "" -#: rpm.c:342 rpm.c:388 rpm.c:413 rpm.c:465 rpm.c:539 +#: rpm.c:341 rpm.c:387 rpm.c:412 rpm.c:464 rpm.c:538 msgid " --dbpath " msgstr "" -#: rpm.c:343 rpm.c:389 rpm.c:414 rpm.c:466 rpm.c:540 rpmqv.c:462 +#: rpm.c:342 rpm.c:388 rpm.c:413 rpm.c:465 rpm.c:539 rpmqv.c:461 msgid "use as the directory for the database" msgstr "" -#: rpm.c:344 +#: rpm.c:343 msgid " --queryformat " msgstr "" -#: rpm.c:345 rpmqv.c:504 +#: rpm.c:344 rpmqv.c:503 msgid "use as the header format (implies --info)" msgstr "" -#: rpm.c:346 rpm.c:390 rpm.c:448 rpm.c:477 +#: rpm.c:345 rpm.c:389 rpm.c:447 rpm.c:476 msgid " --root " msgstr "" -#: rpm.c:347 rpm.c:391 rpm.c:449 rpm.c:478 rpm.c:542 rpmqv.c:145 rpmqv.c:464 +#: rpm.c:346 rpm.c:390 rpm.c:448 rpm.c:477 rpm.c:541 rpmqv.c:144 rpmqv.c:463 msgid "use as the top level directory" msgstr "" -#: rpm.c:348 +#: rpm.c:347 msgid " Package specification options:" msgstr "" -#: rpm.c:350 +#: rpm.c:349 msgid "query all packages" msgstr "" -#: rpm.c:351 +#: rpm.c:350 msgid " -f + " msgstr "" -#: rpm.c:352 +#: rpm.c:351 msgid "query package owning " msgstr "" -#: rpm.c:353 +#: rpm.c:352 msgid " -p + " msgstr "" -#: rpm.c:354 +#: rpm.c:353 msgid "query (uninstalled) package " msgstr "" -#: rpm.c:355 +#: rpm.c:354 msgid " --triggeredby " msgstr "" -#: rpm.c:356 +#: rpm.c:355 msgid "query packages triggered by " msgstr "" -#: rpm.c:357 +#: rpm.c:356 msgid " --whatprovides " msgstr "" -#: rpm.c:358 +#: rpm.c:357 msgid "query packages which provide capability" msgstr "" -#: rpm.c:359 +#: rpm.c:358 msgid " --whatrequires " msgstr "" -#: rpm.c:360 +#: rpm.c:359 msgid "query packages which require capability" msgstr "" -#: rpm.c:361 +#: rpm.c:360 msgid " Information selection options:" msgstr "" -#: rpm.c:363 rpmqv.c:508 +#: rpm.c:362 rpmqv.c:507 msgid "display package information" msgstr "" -#: rpm.c:365 rpmqv.c:510 +#: rpm.c:364 rpmqv.c:509 msgid "display the package's change log" msgstr "" -#: rpm.c:367 rpmqv.c:512 +#: rpm.c:366 rpmqv.c:511 msgid "display package file list" msgstr "" -#: rpm.c:369 rpmqv.c:514 +#: rpm.c:368 rpmqv.c:513 msgid "show file states (implies -l)" msgstr "" -#: rpm.c:371 rpmqv.c:516 +#: rpm.c:370 rpmqv.c:515 msgid "list only documentation files (implies -l)" msgstr "" -#: rpm.c:373 rpmqv.c:518 +#: rpm.c:372 rpmqv.c:517 msgid "list only configuration files (implies -l)" msgstr "" -#: rpm.c:375 rpmqv.c:520 +#: rpm.c:374 rpmqv.c:519 msgid "" "show all verifiable information for each file (must be used with -l, -c, or " "-d)" msgstr "" -#: rpm.c:377 +#: rpm.c:376 msgid "list capabilities package provides" msgstr "" -#: rpm.c:379 +#: rpm.c:378 msgid "list package dependencies" msgstr "" -#: rpm.c:381 +#: rpm.c:380 msgid "print the various [un]install scripts" msgstr "" -#: rpm.c:383 +#: rpm.c:382 msgid "show the trigger scripts contained in the package" msgstr "" -#: rpm.c:387 rpmqv.c:531 +#: rpm.c:386 rpmqv.c:530 msgid "" "verify a package installation using the same same package specification " "options as -q" msgstr "" -#: lib/poptBT.c:183 lib/verify.c:56 rpm.c:393 rpm.c:435 rpm.c:470 rpmqv.c:263 -#: rpmqv.c:533 rpmqv.c:581 rpmqv.c:615 +#: lib/poptBT.c:183 lib/verify.c:54 rpm.c:392 rpm.c:434 rpm.c:469 rpmqv.c:262 +#: rpmqv.c:532 rpmqv.c:580 rpmqv.c:614 msgid "do not verify package dependencies" msgstr "" -#: lib/verify.c:62 rpm.c:395 rpmqv.c:209 rpmqv.c:537 +#: lib/verify.c:60 rpm.c:394 rpmqv.c:208 rpmqv.c:536 msgid "do not verify file md5 checksums" msgstr "" -#: rpm.c:397 rpmqv.c:535 +#: rpm.c:396 rpmqv.c:534 msgid "do not verify file attributes" msgstr "" -#: rpm.c:399 rpmqv.c:542 +#: rpm.c:398 rpmqv.c:541 msgid "list the tags that can be used in a query format" msgstr "" -#: rpm.c:402 +#: rpm.c:401 msgid " --install " msgstr "" -#: rpm.c:403 +#: rpm.c:402 msgid " -i " msgstr "" -#: rpm.c:404 rpmqv.c:259 rpmqv.c:556 +#: rpm.c:403 rpmqv.c:258 rpmqv.c:555 msgid "install package" msgstr "" -#: rpm.c:405 +#: rpm.c:404 msgid " --excludepath " msgstr "" -#: rpm.c:406 +#: rpm.c:405 msgid "skip files in path " msgstr "" -#: rpm.c:407 +#: rpm.c:406 msgid " --relocate =" msgstr "" -#: rpm.c:408 rpmqv.c:593 +#: rpm.c:407 rpmqv.c:592 msgid "relocate files from to " msgstr "" -#: rpm.c:410 rpmqv.c:231 rpmqv.c:561 +#: rpm.c:409 rpmqv.c:230 rpmqv.c:560 msgid "relocate files in non-relocateable package" msgstr "" -#: rpm.c:411 +#: rpm.c:410 msgid " --prefix " msgstr "" -#: rpm.c:412 rpmqv.c:277 rpmqv.c:591 +#: rpm.c:411 rpmqv.c:276 rpmqv.c:590 msgid "relocate the package to , if relocatable" msgstr "" -#: rpm.c:416 rpmqv.c:237 rpmqv.c:563 +#: rpm.c:415 rpmqv.c:236 rpmqv.c:562 msgid "do not install documentation" msgstr "" -#: rpm.c:418 rpmqv.c:242 rpmqv.c:567 +#: rpm.c:417 rpmqv.c:241 rpmqv.c:566 msgid "short hand for --replacepkgs --replacefiles" msgstr "" -#: rpm.c:420 rpmqv.c:248 rpmqv.c:569 +#: rpm.c:419 rpmqv.c:247 rpmqv.c:568 msgid "print hash marks as package installs (good with -v)" msgstr "" -#: rpm.c:422 rpmqv.c:225 rpmqv.c:558 +#: rpm.c:421 rpmqv.c:224 rpmqv.c:557 msgid "install all files, even configurations which might otherwise be skipped" msgstr "" -#: rpm.c:425 rpmqv.c:250 rpmqv.c:571 +#: rpm.c:424 rpmqv.c:249 rpmqv.c:570 msgid "don't verify package architecture" msgstr "" -#: rpm.c:427 rpmqv.c:255 rpmqv.c:573 +#: rpm.c:426 rpmqv.c:254 rpmqv.c:572 msgid "don't check disk space before installing" msgstr "" -#: rpm.c:429 rpmqv.c:252 rpmqv.c:575 +#: rpm.c:428 rpmqv.c:251 rpmqv.c:574 msgid "don't verify package operating system" msgstr "" -#: rpm.c:431 rpmqv.c:257 rpmqv.c:577 +#: rpm.c:430 rpmqv.c:256 rpmqv.c:576 msgid "install documentation" msgstr "" -#: rpm.c:433 rpm.c:468 rpmqv.c:261 rpmqv.c:579 rpmqv.c:613 +#: rpm.c:432 rpm.c:467 rpmqv.c:260 rpmqv.c:578 rpmqv.c:612 msgid "update the database, but do not modify the filesystem" msgstr "" -#: rpm.c:437 rpm.c:472 rpmqv.c:265 rpmqv.c:583 rpmqv.c:617 +#: rpm.c:436 rpm.c:471 rpmqv.c:264 rpmqv.c:582 rpmqv.c:616 msgid "do not reorder package installation to satisfy dependencies" msgstr "" -#: rpm.c:439 +#: rpm.c:438 msgid "don't execute any installation scripts" msgstr "" -#: rpm.c:441 rpm.c:476 rpmqv.c:621 +#: rpm.c:440 rpm.c:475 rpmqv.c:620 msgid "don't execute any scripts triggered by this package" msgstr "" -#: rpm.c:443 rpmqv.c:275 rpmqv.c:589 +#: rpm.c:442 rpmqv.c:274 rpmqv.c:588 msgid "print percentages as package installs" msgstr "" -#: rpm.c:445 rpmqv.c:286 rpmqv.c:595 +#: rpm.c:444 rpmqv.c:285 rpmqv.c:594 msgid "install even if the package replaces installed files" msgstr "" -#: rpm.c:447 rpmqv.c:288 rpmqv.c:597 +#: rpm.c:446 rpmqv.c:287 rpmqv.c:596 msgid "reinstall if the package is already present" msgstr "" -#: rpm.c:451 rpmqv.c:290 rpmqv.c:599 +#: rpm.c:450 rpmqv.c:289 rpmqv.c:598 msgid "don't install, but tell if it would work or not" msgstr "" -#: rpm.c:454 +#: rpm.c:453 msgid " --upgrade " msgstr "" -#: rpm.c:455 +#: rpm.c:454 msgid " -U " msgstr "" -#: rpm.c:456 rpmqv.c:603 +#: rpm.c:455 rpmqv.c:602 msgid "upgrade package (same options as --install, plus)" msgstr "" -#: rpm.c:458 rpmqv.c:272 rpmqv.c:605 +#: rpm.c:457 rpmqv.c:271 rpmqv.c:604 msgid "" "upgrade to an old version of the package (--force on upgrades does this " "automatically)" msgstr "" -#: rpm.c:460 +#: rpm.c:459 msgid " --erase " msgstr "" -#: rpm.c:462 rpmqv.c:235 rpmqv.c:609 +#: rpm.c:461 rpmqv.c:234 rpmqv.c:608 msgid "erase (uninstall) package" msgstr "" -#: rpm.c:464 rpmqv.c:228 rpmqv.c:611 +#: rpm.c:463 rpmqv.c:227 rpmqv.c:610 msgid "" "remove all packages which match (normally an error is generated if " " specified multiple packages)" msgstr "" -#: rpm.c:474 rpmqv.c:619 +#: rpm.c:473 rpmqv.c:618 msgid "do not execute any package specific scripts" msgstr "" -#: rpm.c:480 +#: rpm.c:479 msgid " -b " msgstr "" -#: rpm.c:481 +#: rpm.c:480 msgid " -t " msgstr "" -#: rpm.c:482 +#: rpm.c:481 msgid "build package, where is one of:" msgstr "" -#: rpm.c:484 +#: rpm.c:483 msgid "prep (unpack sources and apply patches)" msgstr "" -#: rpm.c:486 +#: rpm.c:485 #, c-format msgid "list check (do some cursory checks on %files)" msgstr "" -#: rpm.c:488 +#: rpm.c:487 msgid "compile (prep and compile)" msgstr "" -#: rpm.c:490 +#: rpm.c:489 msgid "install (prep, compile, install)" msgstr "" -#: rpm.c:492 +#: rpm.c:491 msgid "binary package (prep, compile, install, package)" msgstr "" -#: rpm.c:494 +#: rpm.c:493 msgid "bin/src package (prep, compile, install, package)" msgstr "" -#: lib/poptBT.c:194 rpm.c:496 +#: lib/poptBT.c:194 rpm.c:495 msgid "skip straight to specified stage (only for c,i)" msgstr "" -#: lib/poptBT.c:173 rpm.c:498 +#: lib/poptBT.c:173 rpm.c:497 msgid "remove build tree when done" msgstr "" -#: lib/poptBT.c:190 rpm.c:500 +#: lib/poptBT.c:190 rpm.c:499 msgid "remove sources when done" msgstr "" -#: rpm.c:502 +#: rpm.c:501 msgid "remove spec file when done" msgstr "" -#: lib/poptBT.c:196 rpm.c:504 rpmqv.c:201 +#: lib/poptBT.c:196 rpm.c:503 rpmqv.c:200 msgid "generate PGP/GPG signature" msgstr "" -#: rpm.c:505 +#: rpm.c:504 msgid " --buildroot " msgstr "" -#: rpm.c:506 +#: rpm.c:505 msgid "use as the build root" msgstr "" -#: rpm.c:507 +#: rpm.c:506 msgid " --target=+" msgstr "" -#: rpm.c:508 +#: rpm.c:507 msgid "build the packages for the build targets platform1...platformN." msgstr "" -#: rpm.c:510 +#: rpm.c:509 msgid "do not execute any stages" msgstr "" -#: rpm.c:511 +#: rpm.c:510 msgid " --timecheck " msgstr "" -#: rpm.c:512 +#: rpm.c:511 msgid "set the time check to seconds (0 disables)" msgstr "" -#: rpm.c:514 +#: rpm.c:513 msgid " --rebuild " msgstr "" -#: rpm.c:515 +#: rpm.c:514 msgid "" "install source package, build binary package and remove spec file, sources, " "patches, and icons." msgstr "" -#: rpm.c:516 +#: rpm.c:515 msgid " --recompile " msgstr "" -#: rpm.c:517 +#: rpm.c:516 msgid "like --rebuild, but don't build any package" msgstr "" -#: rpm.c:520 +#: rpm.c:519 msgid " --resign + " msgstr "" -#: rpm.c:521 rpmqv.c:199 rpmqv.c:627 +#: rpm.c:520 rpmqv.c:198 rpmqv.c:626 msgid "sign a package (discard current signature)" msgstr "" -#: rpm.c:522 +#: rpm.c:521 msgid " --addsign + " msgstr "" -#: rpm.c:523 rpmqv.c:197 rpmqv.c:629 +#: rpm.c:522 rpmqv.c:196 rpmqv.c:628 msgid "add a signature to a package" msgstr "" -#: rpm.c:524 +#: rpm.c:523 msgid " --checksig +" msgstr "" -#: rpm.c:525 +#: rpm.c:524 msgid " -K + " msgstr "" -#: rpm.c:526 rpmqv.c:203 rpmqv.c:633 +#: rpm.c:525 rpmqv.c:202 rpmqv.c:632 msgid "verify package signature" msgstr "" -#: rpm.c:528 rpmqv.c:205 rpmqv.c:635 +#: rpm.c:527 rpmqv.c:204 rpmqv.c:634 msgid "skip any PGP signatures" msgstr "" -#: rpm.c:530 rpmqv.c:207 rpmqv.c:637 +#: rpm.c:529 rpmqv.c:206 rpmqv.c:636 msgid "skip any GPG signatures" msgstr "" -#: rpm.c:532 rpmqv.c:639 +#: rpm.c:531 rpmqv.c:638 msgid "skip any MD5 signatures" msgstr "" -#: rpm.c:536 +#: rpm.c:535 msgid "make sure a valid database exists" msgstr "" -#: rpm.c:538 +#: rpm.c:537 msgid "rebuild database from existing database" msgstr "" -#: rpm.c:546 rpmqv.c:544 +#: rpm.c:545 rpmqv.c:543 msgid "" "set the file permissions to those in the package database using the same " "package specification options as -q" msgstr "" -#: rpm.c:549 rpmqv.c:547 +#: rpm.c:548 rpmqv.c:546 msgid "" "set the file owner and group to those in the package database using the same " "package specification options as -q" msgstr "" -#: rpm.c:689 rpm.c:695 rpm.c:704 rpm.c:726 rpm.c:732 rpm.c:739 rpm.c:747 -#: rpm.c:755 rpm.c:776 rpm.c:839 rpmqv.c:832 rpmqv.c:838 rpmqv.c:845 -#: rpmqv.c:851 rpmqv.c:885 rpmqv.c:893 rpmqv.c:899 rpmqv.c:907 rpmqv.c:974 +#: rpm.c:688 rpm.c:694 rpm.c:703 rpm.c:725 rpm.c:731 rpm.c:738 rpm.c:746 +#: rpm.c:754 rpm.c:775 rpm.c:838 rpmqv.c:831 rpmqv.c:837 rpmqv.c:844 +#: rpmqv.c:850 rpmqv.c:884 rpmqv.c:892 rpmqv.c:898 rpmqv.c:906 rpmqv.c:973 msgid "only one major mode may be specified" msgstr "" -#: rpm.c:697 +#: rpm.c:696 msgid "-u and --uninstall are deprecated and no longer work.\n" msgstr "" -#: rpm.c:699 +#: rpm.c:698 msgid "Use -e or --erase instead.\n" msgstr "" -#: rpm.c:782 rpmqv.c:869 +#: rpm.c:781 rpmqv.c:868 msgid "relocations must begin with a /" msgstr "" -#: rpm.c:784 rpmqv.c:871 +#: rpm.c:783 rpmqv.c:870 msgid "relocations must contain a =" msgstr "" -#: rpm.c:787 rpmqv.c:874 +#: rpm.c:786 rpmqv.c:873 msgid "relocations must have a / following the =" msgstr "" -#: rpm.c:796 rpmqv.c:858 +#: rpm.c:795 rpmqv.c:857 msgid "exclude paths must begin with a /" msgstr "" -#: rpm.c:805 rpmqv.c:928 +#: rpm.c:804 rpmqv.c:927 msgid "The --rcfile option has been eliminated.\n" msgstr "" -#: rpm.c:806 +#: rpm.c:805 msgid "Use --macros with a colon separated list of macro files to read.\n" msgstr "" -#: rpm.c:811 rpmqv.c:934 +#: rpm.c:810 rpmqv.c:933 #, c-format msgid "Internal error in argument processing (%d) :-(\n" msgstr "" -#: rpm.c:846 rpmqv.c:989 +#: rpm.c:845 rpmqv.c:988 msgid "one type of query/verify may be performed at a time" msgstr "" -#: rpm.c:851 rpmqv.c:993 +#: rpm.c:850 rpmqv.c:992 msgid "unexpected query flags" msgstr "" -#: rpm.c:854 rpmqv.c:996 +#: rpm.c:853 rpmqv.c:995 msgid "unexpected query format" msgstr "" -#: rpm.c:857 rpmqv.c:999 +#: rpm.c:856 rpmqv.c:998 msgid "unexpected query source" msgstr "" -#: rpm.c:860 rpmqv.c:1009 +#: rpm.c:859 rpmqv.c:1008 msgid "only installation, upgrading, rmsource and rmspec may be forced" msgstr "" -#: rpm.c:863 rpmqv.c:1014 +#: rpm.c:862 rpmqv.c:1013 msgid "files may only be relocated during package installation" msgstr "" -#: rpm.c:866 rpmqv.c:1017 +#: rpm.c:865 rpmqv.c:1016 msgid "only one of --prefix or --relocate may be used" msgstr "" -#: rpm.c:869 rpmqv.c:1020 +#: rpm.c:868 rpmqv.c:1019 msgid "" "--relocate and --excludepath may only be used when installing new packages" msgstr "" -#: rpm.c:872 rpmqv.c:1023 +#: rpm.c:871 rpmqv.c:1022 msgid "--prefix may only be used when installing new packages" msgstr "" -#: rpm.c:875 rpmqv.c:1026 +#: rpm.c:874 rpmqv.c:1025 msgid "arguments to --prefix must begin with a /" msgstr "" -#: rpm.c:878 rpmqv.c:1029 +#: rpm.c:877 rpmqv.c:1028 msgid "--hash (-h) may only be specified during package installation" msgstr "" -#: rpm.c:882 rpmqv.c:1033 +#: rpm.c:881 rpmqv.c:1032 msgid "--percent may only be specified during package installation" msgstr "" -#: rpm.c:886 rpmqv.c:1038 +#: rpm.c:885 rpmqv.c:1037 msgid "--replacefiles may only be specified during package installation" msgstr "" -#: rpm.c:890 rpmqv.c:1042 +#: rpm.c:889 rpmqv.c:1041 msgid "--replacepkgs may only be specified during package installation" msgstr "" -#: rpm.c:894 rpmqv.c:1046 +#: rpm.c:893 rpmqv.c:1045 msgid "--excludedocs may only be specified during package installation" msgstr "" -#: rpm.c:898 rpmqv.c:1050 +#: rpm.c:897 rpmqv.c:1049 msgid "--includedocs may only be specified during package installation" msgstr "" -#: rpm.c:902 rpmqv.c:1054 +#: rpm.c:901 rpmqv.c:1053 msgid "only one of --excludedocs and --includedocs may be specified" msgstr "" -#: rpm.c:906 rpmqv.c:1058 +#: rpm.c:905 rpmqv.c:1057 msgid "--ignorearch may only be specified during package installation" msgstr "" -#: rpm.c:910 rpmqv.c:1062 +#: rpm.c:909 rpmqv.c:1061 msgid "--ignoreos may only be specified during package installation" msgstr "" -#: rpm.c:914 rpmqv.c:1067 +#: rpm.c:913 rpmqv.c:1066 msgid "--ignoresize may only be specified during package installation" msgstr "" -#: rpm.c:918 rpmqv.c:1071 +#: rpm.c:917 rpmqv.c:1070 msgid "--allmatches may only be specified during package erasure" msgstr "" -#: rpm.c:922 rpmqv.c:1075 +#: rpm.c:921 rpmqv.c:1074 msgid "--allfiles may only be specified during package installation" msgstr "" -#: rpm.c:926 rpmqv.c:1080 +#: rpm.c:925 rpmqv.c:1079 msgid "--justdb may only be specified during package installation and erasure" msgstr "" -#: rpm.c:931 +#: rpm.c:930 msgid "" "--noscripts may only be specified during package installation, erasure, and " "verification" msgstr "" -#: rpm.c:935 +#: rpm.c:934 msgid "" "--notriggers may only be specified during package installation, erasure, and " "verification" msgstr "" -#: rpm.c:939 rpmqv.c:1091 +#: rpm.c:938 rpmqv.c:1090 msgid "" "--nodeps may only be specified during package building, rebuilding, " "recompilation, installation,erasure, and verification" msgstr "" -#: rpm.c:944 rpmqv.c:1096 +#: rpm.c:943 rpmqv.c:1095 msgid "" "--test may only be specified during package installation, erasure, and " "building" msgstr "" -#: rpm.c:948 rpmqv.c:1101 +#: rpm.c:947 rpmqv.c:1100 msgid "" "--root (-r) may only be specified during installation, erasure, querying, " "and database rebuilds" msgstr "" -#: rpm.c:960 rpmqv.c:1113 +#: rpm.c:959 rpmqv.c:1112 msgid "arguments to --root (-r) must begin with a /" msgstr "" -#: rpm.c:966 +#: rpm.c:965 msgid "--oldpackage may only be used during upgrades" msgstr "" -#: rpm.c:969 rpmqv.c:1120 +#: rpm.c:968 rpmqv.c:1119 msgid "--nopgp may only be used during signature checking" msgstr "" -#: rpm.c:972 rpmqv.c:1123 +#: rpm.c:971 rpmqv.c:1122 msgid "--nogpg may only be used during signature checking" msgstr "" -#: rpm.c:975 rpmqv.c:1128 +#: rpm.c:974 rpmqv.c:1127 msgid "" "--nomd5 may only be used during signature checking and package verification" msgstr "" -#: rpm.c:986 rpmqv.c:1144 +#: rpm.c:985 rpmqv.c:1143 msgid "no files to sign\n" msgstr "" -#: rpm.c:991 rpmqv.c:1149 +#: rpm.c:990 rpmqv.c:1148 #, c-format msgid "cannot access file %s\n" msgstr "" -#: rpm.c:1006 rpmqv.c:1165 +#: rpm.c:1005 rpmqv.c:1164 msgid "pgp not found: " msgstr "" -#: rpm.c:1010 rpmqv.c:1169 +#: rpm.c:1009 rpmqv.c:1168 msgid "Enter pass phrase: " msgstr "" -#: rpm.c:1012 rpmqv.c:1171 +#: rpm.c:1011 rpmqv.c:1170 msgid "Pass phrase check failed\n" msgstr "" -#: rpm.c:1015 rpmqv.c:1174 +#: rpm.c:1014 rpmqv.c:1173 msgid "Pass phrase is good.\n" msgstr "" -#: rpm.c:1020 rpmqv.c:1179 +#: rpm.c:1019 rpmqv.c:1178 msgid "Invalid %%_signature spec in macro file.\n" msgstr "" -#: rpm.c:1026 rpmqv.c:1185 +#: rpm.c:1025 rpmqv.c:1184 msgid "--sign may only be used during package building" msgstr "" -#: rpm.c:1041 rpmqv.c:1201 +#: rpm.c:1040 rpmqv.c:1200 msgid "exec failed\n" msgstr "" -#: rpm.c:1060 rpmqv.c:1445 +#: rpm.c:1059 rpmqv.c:1444 msgid "unexpected arguments to --querytags " msgstr "" -#: rpm.c:1071 rpmqv.c:1467 +#: rpm.c:1070 rpmqv.c:1466 msgid "no packages given for signature check" msgstr "" -#: rpm.c:1082 rpmqv.c:1478 +#: rpm.c:1081 rpmqv.c:1477 msgid "no packages given for signing" msgstr "" -#: rpm.c:1098 rpmqv.c:1341 +#: rpm.c:1097 rpmqv.c:1340 msgid "no packages given for uninstall" msgstr "" -#: rpm.c:1162 rpmqv.c:1370 +#: rpm.c:1161 rpmqv.c:1369 msgid "no packages given for install" msgstr "" -#: rpm.c:1186 rpmqv.c:1411 +#: rpm.c:1185 rpmqv.c:1410 msgid "extra arguments given for query of all packages" msgstr "" -#: rpm.c:1191 rpmqv.c:1416 +#: rpm.c:1190 rpmqv.c:1415 msgid "no arguments given for query" msgstr "" -#: rpm.c:1208 rpmqv.c:1433 +#: rpm.c:1207 rpmqv.c:1432 msgid "extra arguments given for verify of all packages" msgstr "" -#: rpm.c:1212 rpmqv.c:1437 +#: rpm.c:1211 rpmqv.c:1436 msgid "no arguments given for verify" msgstr "" @@ -1101,374 +1101,374 @@ msgstr "" msgid "cannot re-open payload: %s\n" msgstr "" -#: rpmqv.c:132 +#: rpmqv.c:131 msgid "provide less detailed output" msgstr "" -#: rpmqv.c:134 +#: rpmqv.c:133 msgid "provide more detailed output" msgstr "" -#: rpmqv.c:137 +#: rpmqv.c:136 msgid "' '" msgstr "" -#: rpmqv.c:139 +#: rpmqv.c:138 msgid "print macro expansion of +" msgstr "" -#: rpmqv.c:140 +#: rpmqv.c:139 msgid "+" msgstr "" -#: rpmqv.c:143 +#: rpmqv.c:142 msgid "" msgstr "" -#: rpmqv.c:146 rpmqv.c:278 +#: rpmqv.c:145 rpmqv.c:277 msgid "" msgstr "" -#: rpmqv.c:148 +#: rpmqv.c:147 msgid "read instead of default macro file(s)" msgstr "" -#: rpmqv.c:149 rpmqv.c:153 rpmqv.c:157 +#: rpmqv.c:148 rpmqv.c:152 rpmqv.c:156 msgid "" msgstr "" -#: rpmqv.c:152 rpmqv.c:156 +#: rpmqv.c:151 rpmqv.c:155 msgid "read instead of default rpmrc file(s)" msgstr "" -#: rpmqv.c:165 +#: rpmqv.c:164 msgid "disable use of libio(3) API" msgstr "" -#: rpmqv.c:168 +#: rpmqv.c:167 msgid "debug protocol data stream" msgstr "" -#: rpmqv.c:170 +#: rpmqv.c:169 msgid "debug rpmio I/O" msgstr "" -#: rpmqv.c:172 +#: rpmqv.c:171 msgid "debug URL cache handling" msgstr "" -#: rpmqv.c:180 +#: rpmqv.c:179 msgid "initialize database" msgstr "" -#: rpmqv.c:182 +#: rpmqv.c:181 msgid "rebuild database inverted lists from installed package headers" msgstr "" -#: rpmqv.c:185 +#: rpmqv.c:184 msgid "generate headers compatible with (legacy) rpm[23] packaging" msgstr "" -#: lib/poptBT.c:175 rpmqv.c:188 +#: lib/poptBT.c:175 rpmqv.c:187 msgid "generate headers compatible with rpm4 packaging" msgstr "" -#: rpmqv.c:233 +#: rpmqv.c:232 msgid "save erased package files by renaming into sub-directory" msgstr "" -#: rpmqv.c:235 +#: rpmqv.c:234 msgid "+" msgstr "" -#: rpmqv.c:239 rpmqv.c:565 +#: rpmqv.c:238 rpmqv.c:564 msgid "skip files with leading component " msgstr "" -#: rpmqv.c:240 +#: rpmqv.c:239 msgid "" msgstr "" -#: rpmqv.c:245 +#: rpmqv.c:244 msgid "upgrade package(s) if already installed" msgstr "" -#: rpmqv.c:246 rpmqv.c:259 rpmqv.c:293 +#: rpmqv.c:245 rpmqv.c:258 rpmqv.c:292 msgid "+" msgstr "" -#: rpmqv.c:268 rpmqv.c:539 +#: rpmqv.c:267 rpmqv.c:538 msgid "do not execute scripts (if any)" msgstr "" -#: rpmqv.c:270 rpmqv.c:587 +#: rpmqv.c:269 rpmqv.c:586 msgid "don't execute any scriptlets triggered by this package" msgstr "" -#: rpmqv.c:280 +#: rpmqv.c:279 msgid "relocate files from path to " msgstr "" -#: rpmqv.c:281 +#: rpmqv.c:280 msgid "=" msgstr "" -#: rpmqv.c:283 +#: rpmqv.c:282 msgid "save erased package files by repackaging" msgstr "" -#: rpmqv.c:292 +#: rpmqv.c:291 msgid "upgrade package(s)" msgstr "" -#: rpmqv.c:312 +#: rpmqv.c:311 msgid "Query options (with -q or --query):" msgstr "" -#: rpmqv.c:315 +#: rpmqv.c:314 msgid "Verify options (with -V or --verify):" msgstr "" -#: rpmqv.c:321 +#: rpmqv.c:320 msgid "Signature options:" msgstr "" -#: rpmqv.c:327 +#: rpmqv.c:326 msgid "Database options:" msgstr "" -#: rpmqv.c:333 +#: rpmqv.c:332 msgid "Build options with [ | | ]:" msgstr "" -#: rpmqv.c:339 +#: rpmqv.c:338 msgid "Install/Upgrade/Erase options:" msgstr "" -#: rpmqv.c:344 +#: rpmqv.c:343 msgid "Common options for all rpm modes:" msgstr "" -#: rpmqv.c:378 +#: rpmqv.c:377 #, c-format msgid "Usage: %s {--help}\n" msgstr "" -#: rpmqv.c:449 +#: rpmqv.c:448 msgid " All modes support the following options:" msgstr "" -#: rpmqv.c:450 +#: rpmqv.c:449 msgid " --define ' '" msgstr "" -#: rpmqv.c:452 +#: rpmqv.c:451 msgid " --eval '+' " msgstr "" -#: rpmqv.c:453 +#: rpmqv.c:452 msgid "print the expansion of macro to stdout" msgstr "" -#: rpmqv.c:454 +#: rpmqv.c:453 msgid " --pipe " msgstr "" -#: rpmqv.c:456 +#: rpmqv.c:455 msgid " --rcfile " msgstr "" -#: rpmqv.c:457 +#: rpmqv.c:456 msgid "use instead of default list of macro files" msgstr "" -#: rpmqv.c:461 +#: rpmqv.c:460 msgid " --dbpath " msgstr "" -#: rpmqv.c:463 +#: rpmqv.c:462 msgid " --root " msgstr "" -#: rpmqv.c:473 +#: rpmqv.c:472 msgid "" " Install, upgrade and query (with -p) modes allow URL's to be used in place" msgstr "" -#: rpmqv.c:474 +#: rpmqv.c:473 msgid " of file names as well as the following options:" msgstr "" -#: rpmqv.c:475 +#: rpmqv.c:474 msgid " --ftpproxy " msgstr "" -#: rpmqv.c:477 +#: rpmqv.c:476 msgid " --ftpport " msgstr "" -#: rpmqv.c:479 +#: rpmqv.c:478 msgid " --httpproxy " msgstr "" -#: rpmqv.c:481 +#: rpmqv.c:480 msgid " --httpport " msgstr "" -#: rpmqv.c:487 +#: rpmqv.c:486 msgid " Package specification options:" msgstr "" -#: lib/poptQV.c:68 rpmqv.c:489 +#: lib/poptQV.c:68 rpmqv.c:488 msgid "query/verify all packages" msgstr "" -#: rpmqv.c:490 +#: rpmqv.c:489 msgid " -f + " msgstr "" -#: rpmqv.c:491 +#: rpmqv.c:490 msgid "query/verify package owning " msgstr "" -#: rpmqv.c:492 +#: rpmqv.c:491 msgid " -p + " msgstr "" -#: rpmqv.c:493 +#: rpmqv.c:492 msgid "query/verify (uninstalled) package " msgstr "" -#: rpmqv.c:494 +#: rpmqv.c:493 msgid " --triggeredby " msgstr "" -#: rpmqv.c:495 +#: rpmqv.c:494 msgid "query/verify packages triggered by " msgstr "" -#: rpmqv.c:496 +#: rpmqv.c:495 msgid " --whatprovides " msgstr "" -#: rpmqv.c:497 +#: rpmqv.c:496 msgid "query/verify packages which provide capability" msgstr "" -#: rpmqv.c:498 +#: rpmqv.c:497 msgid " --whatrequires " msgstr "" -#: rpmqv.c:499 +#: rpmqv.c:498 msgid "query/verify packages which require capability" msgstr "" -#: rpmqv.c:503 +#: rpmqv.c:502 msgid " --queryformat " msgstr "" -#: rpmqv.c:506 +#: rpmqv.c:505 msgid " Information selection options:" msgstr "" -#: rpmqv.c:522 +#: rpmqv.c:521 msgid "list capabilities provided by package" msgstr "" -#: rpmqv.c:524 +#: rpmqv.c:523 msgid "list capabilities required by package" msgstr "" -#: rpmqv.c:526 +#: rpmqv.c:525 msgid "print the various [un]install scriptlets" msgstr "" -#: rpmqv.c:528 +#: rpmqv.c:527 msgid "show the trigger scriptlets contained in the package" msgstr "" -#: rpmqv.c:554 +#: rpmqv.c:553 msgid " --install " msgstr "" -#: rpmqv.c:555 +#: rpmqv.c:554 msgid " -i " msgstr "" -#: rpmqv.c:564 +#: rpmqv.c:563 msgid " --excludepath " msgstr "" -#: rpmqv.c:585 +#: rpmqv.c:584 msgid "don't execute any installation scriptlets" msgstr "" -#: rpmqv.c:590 +#: rpmqv.c:589 msgid " --prefix " msgstr "" -#: rpmqv.c:592 +#: rpmqv.c:591 msgid " --relocate =" msgstr "" -#: rpmqv.c:601 +#: rpmqv.c:600 msgid " --upgrade " msgstr "" -#: rpmqv.c:602 +#: rpmqv.c:601 msgid " -U " msgstr "" -#: rpmqv.c:607 +#: rpmqv.c:606 msgid " --erase " msgstr "" -#: rpmqv.c:626 +#: rpmqv.c:625 msgid " --resign + " msgstr "" -#: rpmqv.c:628 +#: rpmqv.c:627 msgid " --addsign + " msgstr "" -#: rpmqv.c:631 +#: rpmqv.c:630 msgid " --checksig +" msgstr "" -#: rpmqv.c:632 +#: rpmqv.c:631 msgid " -K + " msgstr "" -#: rpmqv.c:645 +#: rpmqv.c:644 msgid "initalize database (unnecessary, legacy use)" msgstr "" -#: rpmqv.c:647 +#: rpmqv.c:646 msgid "rebuild database indices from existing database headers" msgstr "" -#: rpmqv.c:929 +#: rpmqv.c:928 msgid "Use \"--macros \" instead.\n" msgstr "" -#: rpmqv.c:1003 +#: rpmqv.c:1002 msgid "--dbpath given for operation that does not use a database" msgstr "" -#: rpmqv.c:1087 +#: rpmqv.c:1086 msgid "" "--notriggers may only be specified during package installation and erasure" msgstr "" -#: rpmqv.c:1241 +#: rpmqv.c:1240 msgid "no packages files given for rebuild" msgstr "" -#: rpmqv.c:1310 +#: rpmqv.c:1309 msgid "no spec files given for build" msgstr "" -#: rpmqv.c:1312 +#: rpmqv.c:1311 msgid "no tar files given for build" msgstr "" @@ -2185,79 +2185,40 @@ msgstr "" msgid "line %d: Bad %s number: %s\n" msgstr "" -#: lib/cpio.c:284 -msgid "========= Directories not explictly included in package:\n" -msgstr "" - -#: lib/cpio.c:286 -#, c-format -msgid "%9d %s\n" -msgstr "" - -#: lib/cpio.c:1397 -#, c-format -msgid "%s directory created with perms %04o.\n" -msgstr "" - -#: lib/cpio.c:1499 lib/cpio.c:1615 -#, c-format -msgid "%s saved as %s\n" -msgstr "" - -#: lib/cpio.c:1640 -#, c-format -msgid "%s rmdir of %s failed: Directory not empty\n" -msgstr "" - -#: lib/cpio.c:1645 -#, c-format -msgid "%s rmdir of %s failed: %s\n" -msgstr "" - -#: lib/cpio.c:1654 -#, c-format -msgid "%s unlink of %s failed: %s\n" -msgstr "" - -#: lib/cpio.c:1671 -#, c-format -msgid "%s created as %s\n" -msgstr "" - -#: lib/cpio.c:2072 +#: lib/cpio.c:195 #, c-format msgid "(error 0x%x)" msgstr "" -#: lib/cpio.c:2075 +#: lib/cpio.c:198 msgid "Bad magic" msgstr "" -#: lib/cpio.c:2076 +#: lib/cpio.c:199 msgid "Bad/unreadable header" msgstr "" -#: lib/cpio.c:2097 +#: lib/cpio.c:220 msgid "Header size too big" msgstr "" -#: lib/cpio.c:2098 +#: lib/cpio.c:221 msgid "Unknown file type" msgstr "" -#: lib/cpio.c:2099 +#: lib/cpio.c:222 msgid "Missing hard link" msgstr "" -#: lib/cpio.c:2100 +#: lib/cpio.c:223 msgid "MD5 sum mismatch" msgstr "" -#: lib/cpio.c:2101 +#: lib/cpio.c:224 msgid "Internal error" msgstr "" -#: lib/cpio.c:2110 +#: lib/cpio.c:233 msgid " failed - " msgstr "" @@ -2531,12 +2492,51 @@ msgstr "" msgid "file %s is on an unknown device\n" msgstr "" +#: lib/fsm.c:214 +msgid "========= Directories not explictly included in package:\n" +msgstr "" + +#: lib/fsm.c:216 +#, c-format +msgid "%9d %s\n" +msgstr "" + +#: lib/fsm.c:1177 +#, c-format +msgid "%s directory created with perms %04o.\n" +msgstr "" + +#: lib/fsm.c:1279 lib/fsm.c:1395 +#, c-format +msgid "%s saved as %s\n" +msgstr "" + +#: lib/fsm.c:1420 +#, c-format +msgid "%s rmdir of %s failed: Directory not empty\n" +msgstr "" + +#: lib/fsm.c:1425 +#, c-format +msgid "%s rmdir of %s failed: %s\n" +msgstr "" + +#: lib/fsm.c:1434 +#, c-format +msgid "%s unlink of %s failed: %s\n" +msgstr "" + +#: lib/fsm.c:1451 +#, c-format +msgid "%s created as %s\n" +msgstr "" + #. This should not be allowed #: lib/header.c:172 msgid "dataLength() RPM_STRING_TYPE count must be 1.\n" msgstr "" -#: lib/header.c:207 lib/header.c:1036 lib/install.c:236 +#: lib/header.c:207 lib/header.c:1036 lib/psm.c:500 #, c-format msgid "Data type %d not supported\n" msgstr "" @@ -2621,66 +2621,6 @@ msgstr "" msgid "(unknown type)" msgstr "" -#: lib/install.c:80 -#, c-format -msgid "user %s does not exist - using root\n" -msgstr "" - -#: lib/install.c:88 -#, c-format -msgid "group %s does not exist - using root\n" -msgstr "" - -#. -#. * This would probably be a good place to check if disk space -#. * was used up - if so, we should return a different error. -#. -#. XXX FIXME: Fclose with libio destroys errno -#: lib/install.c:461 -#, c-format -msgid "unpacking of archive failed%s%s: %s\n" -msgstr "" - -#: lib/install.c:462 -msgid " on file " -msgstr "" - -#: lib/install.c:503 -#, c-format -msgid "cannot create %s %s\n" -msgstr "" - -#: lib/install.c:509 -#, c-format -msgid "cannot write to %s\n" -msgstr "" - -#: lib/install.c:530 -msgid "installing a source package\n" -msgstr "" - -#: lib/install.c:582 -msgid "source package contains no .spec file\n" -msgstr "" - -#: lib/install.c:662 -msgid "source package expected, binary found\n" -msgstr "" - -#: lib/install.c:733 lib/uninstall.c:26 -#, c-format -msgid "%s: %s-%s-%s has %d files, test = %d\n" -msgstr "" - -#: lib/install.c:797 lib/install.c:879 lib/uninstall.c:69 lib/uninstall.c:91 -#, c-format -msgid "%s: running %s script(s) (if any)\n" -msgstr "" - -#: lib/install.c:804 -msgid "skipping %s-%s-%s install, %%pre scriptlet failed rc %d\n" -msgstr "" - #: lib/misc.c:328 lib/misc.c:333 lib/misc.c:339 #, c-format msgid "error creating temporary file %s\n" @@ -2964,6 +2904,66 @@ msgstr "" msgid "unknown error %d encountered while manipulating package %s" msgstr "" +#: lib/psm.c:344 +#, c-format +msgid "user %s does not exist - using root\n" +msgstr "" + +#: lib/psm.c:352 +#, c-format +msgid "group %s does not exist - using root\n" +msgstr "" + +#. +#. * This would probably be a good place to check if disk space +#. * was used up - if so, we should return a different error. +#. +#. XXX FIXME: Fclose with libio destroys errno +#: lib/psm.c:725 +#, c-format +msgid "unpacking of archive failed%s%s: %s\n" +msgstr "" + +#: lib/psm.c:726 +msgid " on file " +msgstr "" + +#: lib/psm.c:767 +#, c-format +msgid "cannot create %s %s\n" +msgstr "" + +#: lib/psm.c:773 +#, c-format +msgid "cannot write to %s\n" +msgstr "" + +#: lib/psm.c:794 +msgid "installing a source package\n" +msgstr "" + +#: lib/psm.c:846 +msgid "source package contains no .spec file\n" +msgstr "" + +#: lib/psm.c:926 +msgid "source package expected, binary found\n" +msgstr "" + +#: lib/psm.c:997 lib/psm.c:1188 +#, c-format +msgid "%s: %s-%s-%s has %d files, test = %d\n" +msgstr "" + +#: lib/psm.c:1061 lib/psm.c:1143 lib/psm.c:1231 lib/psm.c:1253 +#, c-format +msgid "%s: running %s script(s) (if any)\n" +msgstr "" + +#: lib/psm.c:1068 +msgid "skipping %s-%s-%s install, %%pre scriptlet failed rc %d\n" +msgstr "" + #: lib/query.c:151 #, c-format msgid "incorrect format: %s\n" @@ -3709,28 +3709,28 @@ msgstr "" msgid "%s skipped due to missingok flag\n" msgstr "" -#: lib/verify.c:59 +#: lib/verify.c:57 msgid "don't verify files in package" msgstr "" -#: lib/verify.c:65 +#: lib/verify.c:63 msgid "do not execute %verifyscript (if any)" msgstr "" -#: lib/verify.c:241 +#: lib/verify.c:239 msgid "package lacks both user name and id lists (this should never happen)\n" msgstr "" -#: lib/verify.c:259 +#: lib/verify.c:257 msgid "package lacks both group name and id lists (this should never happen)\n" msgstr "" -#: lib/verify.c:321 +#: lib/verify.c:319 #, c-format msgid "missing %s" msgstr "" -#: lib/verify.c:402 +#: lib/verify.c:400 #, c-format msgid "Unsatisfied dependencies for %s-%s-%s: " msgstr "" diff --git a/rpm.c b/rpm.c index c8dc031..235f8b0 100755 --- a/rpm.c +++ b/rpm.c @@ -4,7 +4,6 @@ #include #include "build.h" -#include "install.h" #include "signature.h" #include "debug.h" diff --git a/rpmqv.c b/rpmqv.c index cb7927b..384e552 100755 --- a/rpmqv.c +++ b/rpmqv.c @@ -25,7 +25,6 @@ static int initdb = 0; #endif #ifdef IAM_RPMEIU -#include "install.h" #define GETOPT_INSTALL 1014 #define GETOPT_RELOCATE 1016 #define GETOPT_EXCLUDEPATH 1019 -- 2.7.4