This change likely needs some context ... I need an I/O state machine to handle I/O from archive, and archives of archives etc. So I've cloned lib/fsm.[ch] and renamed to rpmio/iosm.[ch]. I've also created copies of cpio.[ch] and tar.[ch]. What remains to be done is to uncouple the I/O state machine from higher level RPM objects like rpmts, rpmte, and rpmfi. Most of the messy construction details will not affect mainline rpm code paths. 73 de Jeff On Mar 2, 2008, at 5:40 PM, Jeff Johnson wrote: > RPM Package Manager, CVS Repository > http://rpm5.org/cvs/ > > ______________________________________________________________________ > ______ > > Server: rpm5.org Name: Jeff Johnson > Root: /v/rpm/cvs Email: jbj@rpm5.org > Module: rpm Date: 02-Mar-2008 > 23:40:09 > Branch: HEAD Handle: 2008030222400701 > > Added files: > rpm/rpmio cpio.c cpio.h iosm.c iosm.h tar.c tar.h > Modified files: > rpm CHANGES > rpm/lib cpio.c cpio.h fsm.c fsm.h rpmfi.c tar.c > tar.h > rpm/perl RPM_Dependencies.xs RPM_Spec.xs > rpm/rpmio Makefile.am tdeb.c > > Log: > - jbj: perl: fix: include rpmio.h before rpmlib.h (for rpmRC > returns). > - jbj: start creating I/O State Machine(IOSM) in rpmio/iosm.c. > > Summary: > Revision Changes Path > 1.2218 +2 -0 rpm/CHANGES > 2.141 +6 -4 rpm/lib/cpio.c > 2.68 +9 -9 rpm/lib/cpio.h > 2.152 +2 -2 rpm/lib/fsm.c > 2.38 +5 -5 rpm/lib/fsm.h > 2.114 +1 -1 rpm/lib/rpmfi.c > 1.10 +15 -9 rpm/lib/tar.c > 1.3 +9 -9 rpm/lib/tar.h > 1.7 +1 -0 rpm/perl/RPM_Dependencies.xs > 1.11 +1 -1 rpm/perl/RPM_Spec.xs > 1.143 +4 -4 rpm/rpmio/Makefile.am > 1.1 +279 -0 rpm/rpmio/cpio.c > 1.1 +149 -0 rpm/rpmio/cpio.h > 1.1 +2653 -0 rpm/rpmio/iosm.c > 1.1 +362 -0 rpm/rpmio/iosm.h > 1.1 +468 -0 rpm/rpmio/tar.c > 1.1 +85 -0 rpm/rpmio/tar.h > 1.3 +11 -11 rpm/rpmio/tdeb.c > > ______________________________________________________________________ > ______ > > patch -p0 <<'@@ .' > Index: rpm/CHANGES > > ====================================================================== > ====== > $ cvs diff -u -r1.2217 -r1.2218 CHANGES > --- rpm/CHANGES 2 Mar 2008 07:17:34 -0000 1.2217 > +++ rpm/CHANGES 2 Mar 2008 22:40:07 -0000 1.2218 > @@ -1,4 +1,6 @@ > 5.0.0 -> 5.1a1: > + - jbj: perl: fix: include rpmio.h before rpmlib.h (for rpmRC > returns). > + - jbj: start creating I/O State Machine(IOSM) in rpmio/iosm.c. > - jbj: verify.c: use rpmProblemGetAltNEVR() to make > rpmProblem opaque. > - jbj: fsm: use rpmfi iterators in several loops. > - jbj: rpmfi: add rpmfiSetHeader() so verify.c doesn't need > _RPMFI_INTERNAL. > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/cpio.c > > ====================================================================== > ====== > $ cvs diff -u -r2.140 -r2.141 cpio.c > --- rpm/lib/cpio.c 2 Mar 2008 07:06:01 -0000 2.140 > +++ rpm/lib/cpio.c 2 Mar 2008 22:40:07 -0000 2.141 > @@ -56,8 +56,9 @@ > sprintf(space, "%8.8lx", (unsigned long) (val)); \ > memcpy(phys, space, 8) > > -int cpioTrailerWrite(FSM_t fsm) > +int cpioTrailerWrite(void * _fsm) > { > + FSM_t fsm = _fsm; > struct cpioCrcPhysicalHeader * hdr = > (struct cpioCrcPhysicalHeader *)fsm->rdbuf; > int rc; > @@ -82,8 +83,9 @@ > return rc; > } > > -int cpioHeaderWrite(FSM_t fsm, struct stat * st) > +int cpioHeaderWrite(void * _fsm, struct stat * st) > { > + FSM_t fsm = _fsm; > struct cpioCrcPhysicalHeader * hdr = (struct > cpioCrcPhysicalHeader *)fsm->rdbuf; > char field[64]; > size_t len; > @@ -133,9 +135,9 @@ > return rc; > } > > -int cpioHeaderRead(FSM_t fsm, struct stat * st) > - /*@modifies fsm, *st @*/ > +int cpioHeaderRead(void * _fsm, struct stat * st) > { > + FSM_t fsm = _fsm; > struct cpioCrcPhysicalHeader hdr; > int nameSize; > char * end; > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/cpio.h > > ====================================================================== > ====== > $ cvs diff -u -r2.67 -r2.68 cpio.h > --- rpm/lib/cpio.h 17 Feb 2008 02:52:11 -0000 2.67 > +++ rpm/lib/cpio.h 2 Mar 2008 22:40:07 -0000 2.68 > @@ -106,32 +106,32 @@ > > /** > * Write cpio trailer. > - * @retval fsm file path and stat info > + * @retval _fsm file path and stat info > * @return 0 on success > */ > -int cpioTrailerWrite(FSM_t fsm) > +int cpioTrailerWrite(void * _fsm) > /*@globals h_errno, fileSystem, internalState @*/ > - /*@modifies fsm, fileSystem, internalState @*/; > + /*@modifies _fsm, fileSystem, internalState @*/; > > /** > * Write cpio header. > - * @retval fsm file path and stat info > + * @retval _fsm file path and stat info > * @param st > * @return 0 on success > */ > -int cpioHeaderWrite(FSM_t fsm, struct stat * st) > +int cpioHeaderWrite(void * _fsm, struct stat * st) > /*@globals h_errno, fileSystem, internalState @*/ > - /*@modifies fsm, fileSystem, internalState @*/; > + /*@modifies _fsm, fileSystem, internalState @*/; > > /** > * Read cpio header. > - * @retval fsm file path and stat info > + * @retval _fsm file path and stat info > * @retval st > * @return 0 on success > */ > -int cpioHeaderRead(FSM_t fsm, struct stat * st) > +int cpioHeaderRead(void * _fsm, struct stat * st) > /*@globals h_errno, fileSystem, internalState @*/ > - /*@modifies fsm, *st, fileSystem, internalState @*/; > + /*@modifies _fsm, *st, fileSystem, internalState @*/; > > /** \ingroup payload > * Return formatted error message on payload handling failure. > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/fsm.c > > ====================================================================== > ====== > $ cvs diff -u -r2.151 -r2.152 fsm.c > --- rpm/lib/fsm.c 2 Mar 2008 20:57:24 -0000 2.151 > +++ rpm/lib/fsm.c 2 Mar 2008 22:40:08 -0000 2.152 > @@ -591,8 +591,8 @@ > const void * _ts, const void * _fi, FD_t cfd, > unsigned int * archiveSize, const char ** failedFile) > { > - const rpmts ts = _ts; > - const rpmfi fi = _fi; > + const rpmts ts = (const rpmts) _ts; > + const rpmfi fi = (const rpmfi) _fi; > size_t pos = 0; > int rc, ec = 0; > > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/fsm.h > > ====================================================================== > ====== > $ cvs diff -u -r2.37 -r2.38 fsm.h > --- rpm/lib/fsm.h 2 Mar 2008 20:57:24 -0000 2.37 > +++ rpm/lib/fsm.h 2 Mar 2008 22:40:08 -0000 2.38 > @@ -219,11 +219,11 @@ > struct stat osb; /*!< Original file stat(2) info. */ > > unsigned blksize; /*!< Archive block size. */ > - int (*headerRead) (FSM_t fsm, struct stat *st) > - /*@modifies fsm, st @*/; > - int (*headerWrite) (FSM_t fsm, struct stat *st) > - /*@modifies fsm, st @*/; > - int (*trailerWrite) (FSM_t fsm) > + int (*headerRead) (void * _fsm, struct stat *st) > + /*@modifies _fsm, st @*/; > + int (*headerWrite) (void * _fsm, struct stat *st) > + /*@modifies _fsm, st @*/; > + int (*trailerWrite) (void * _fsm) > /*@modifies fsm @*/; > > char * lmtab; /*!< ar(1) long member name table. */ > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/rpmfi.c > > ====================================================================== > ====== > $ cvs diff -u -r2.113 -r2.114 rpmfi.c > --- rpm/lib/rpmfi.c 2 Mar 2008 20:57:25 -0000 2.113 > +++ rpm/lib/rpmfi.c 2 Mar 2008 22:40:08 -0000 2.114 > @@ -1267,7 +1267,7 @@ > > rpmfi rpmfiNew(const void * _ts, Header h, rpmTag tagN, int flags) > { > - const rpmts ts = _ts; > + const rpmts ts = (const rpmts) _ts; > int scareMem = (flags & 0x1); > HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); > rpmte p; > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/tar.c > > ====================================================================== > ====== > $ cvs diff -u -r1.9 -r1.10 tar.c > --- rpm/lib/tar.c 2 Mar 2008 07:06:01 -0000 1.9 > +++ rpm/lib/tar.c 2 Mar 2008 22:40:08 -0000 1.10 > @@ -54,15 +54,16 @@ > > /** > * Read long file/link name from tar archive. > - * @param fsm file state machine > + * @param _fsm file state machine > * @param len no. bytes of name > * @retval *fnp long file/link name > * @return 0 on success > */ > -static int tarHeaderReadName(FSM_t fsm, int len, /*@out@*/ const > char ** fnp) > +static int tarHeaderReadName(void * _fsm, int len, /*@out@*/ > const char ** fnp) > /*@globals h_errno, fileSystem, internalState @*/ > /*@modifies fsm, *fnp, fileSystem, internalState @*/ > { > + FSM_t fsm = _fsm; > char * t; > int nb; > int rc = 0; > @@ -89,9 +90,10 @@ > return rc; > } > > -int tarHeaderRead(FSM_t fsm, struct stat * st) > +int tarHeaderRead(void * _fsm, struct stat * st) > /*@modifies fsm, *st @*/ > { > + FSM_t fsm = _fsm; > tarHeader hdr = (tarHeader) fsm->wrbuf; > char * t; > int nb; > @@ -257,14 +259,15 @@ > > /** > * Write long file/link name into tar archive. > - * @param fsm file state machine > + * @param _fsm file state machine > * @param path long file/link name > * @return 0 on success > */ > -static int tarHeaderWriteName(FSM_t fsm, const char * path) > +static int tarHeaderWriteName(void * _fsm, const char * path) > /*@globals h_errno, fileSystem, internalState @*/ > /*@modifies fsm, fileSystem, internalState @*/ > { > + FSM_t fsm = _fsm; > const char * s = path; > int nb = strlen(s); > int rc = 0; > @@ -295,15 +298,16 @@ > > /** > * Write tar header block with checksum into tar archive. > - * @param fsm file state machine > + * @param _fsm file state machine > * @param st file info > * @param hdr tar header block > * @return 0 on success > */ > -static int tarHeaderWriteBlock(FSM_t fsm, struct stat * st, > tarHeader hdr) > +static int tarHeaderWriteBlock(void * _fsm, struct stat * st, > tarHeader hdr) > /*@globals h_errno, fileSystem, internalState @*/ > /*@modifies fsm, hdr, fileSystem, internalState @*/ > { > + FSM_t fsm = _fsm; > int rc; > > if (_tar_debug) > @@ -339,8 +343,9 @@ > return rc; > } > > -int tarHeaderWrite(FSM_t fsm, struct stat * st) > +int tarHeaderWrite(void * _fsm, struct stat * st) > { > + FSM_t fsm = _fsm; > /*@observer@*/ > static const char * llname = "././@LongLink"; > tarHeader hdr = (tarHeader) fsm->rdbuf; > @@ -445,8 +450,9 @@ > return rc; > } > > -int tarTrailerWrite(FSM_t fsm) > +int tarTrailerWrite(void * _fsm) > { > + FSM_t fsm = _fsm; > int rc = 0; > > if (_tar_debug) > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/tar.h > > ====================================================================== > ====== > $ cvs diff -u -r1.2 -r1.3 tar.h > --- rpm/lib/tar.h 25 May 2007 18:34:13 -0000 1.2 > +++ rpm/lib/tar.h 2 Mar 2008 22:40:08 -0000 1.3 > @@ -51,32 +51,32 @@ > > /** > * Write cpio trailer to payload. > - * @retval fsm file path and stat info > + * @retval _fsm file path and stat info > * @return 0 on success > */ > -int tarTrailerWrite(FSM_t fsm) > +int tarTrailerWrite(void * _fsm) > /*@globals h_errno, fileSystem, internalState @*/ > - /*@modifies fsm, fileSystem, internalState @*/; > + /*@modifies _fsm, fileSystem, internalState @*/; > > /** > * Write tar header to payload. > - * @retval fsm file path and stat info > + * @retval _fsm file path and stat info > * @param st > * @return 0 on success > */ > -int tarHeaderWrite(FSM_t fsm, struct stat * st) > +int tarHeaderWrite(void * _fsm, struct stat * st) > /*@globals h_errno, fileSystem, internalState @*/ > - /*@modifies fsm, fileSystem, internalState @*/; > + /*@modifies _fsm, fileSystem, internalState @*/; > > /** > * Read tar header from payload. > - * @retval fsm file path and stat info > + * @retval _fsm file path and stat info > * @retval st > * @return 0 on success > */ > -int tarHeaderRead(FSM_t fsm, struct stat * st) > +int tarHeaderRead(void * _fsm, struct stat * st) > /*@globals h_errno, fileSystem, internalState @*/ > - /*@modifies fsm, *st, fileSystem, internalState @*/; > + /*@modifies _fsm, *st, fileSystem, internalState @*/; > > #ifdef __cplusplus > } > @@ . > patch -p0 <<'@@ .' > Index: rpm/perl/RPM_Dependencies.xs > > ====================================================================== > ====== > $ cvs diff -u -r1.6 -r1.7 RPM_Dependencies.xs > --- rpm/perl/RPM_Dependencies.xs 19 Nov 2007 18:57:58 -0000 1.6 > +++ rpm/perl/RPM_Dependencies.xs 2 Mar 2008 22:40:08 -0000 1.7 > @@ -6,6 +6,7 @@ > #undef Mkdir > #undef Stat > > +#include "rpmio.h" > #include "rpmcb.h" /* XXX fnpyKey */ > > #define _RPMEVR_INTERNAL > @@ . > patch -p0 <<'@@ .' > Index: rpm/perl/RPM_Spec.xs > > ====================================================================== > ====== > $ cvs diff -u -r1.10 -r1.11 RPM_Spec.xs > --- rpm/perl/RPM_Spec.xs 2 Dec 2007 01:01:24 -0000 1.10 > +++ rpm/perl/RPM_Spec.xs 2 Mar 2008 22:40:08 -0000 1.11 > @@ -6,8 +6,8 @@ > #undef Mkdir > #undef Stat > > -#include "rpmlib.h" > #include "rpmio.h" > +#include "rpmlib.h" > #include "rpmcli.h" > #include "stringbuf.h" > #include "rpmmacro.h" > @@ . > patch -p0 <<'@@ .' > Index: rpm/rpmio/Makefile.am > > ====================================================================== > ====== > $ cvs diff -u -r1.142 -r1.143 Makefile.am > --- rpm/rpmio/Makefile.am 29 Feb 2008 23:59:43 -0000 1.142 > +++ rpm/rpmio/Makefile.am 2 Mar 2008 22:40:08 -0000 1.143 > @@ -4,7 +4,7 @@ > > LINT = splint > > -EXTRA_DIST = tdeb.c tdir.c tfts.c tget.c tglob.c thkp.c thtml.c > tinv.c tkey.c tmire.c tput.c trpmio.c tsw.c ttar.c lookup3.c tpw.c > librpmio.vers testit.sh rpmgrep.1 > +EXTRA_DIST = cpio.c iosm.c tar.c tdeb.c tdir.c tfts.c tget.c > tglob.c thkp.c thtml.c tinv.c tkey.c tmire.c tput.c trpmio.c tsw.c > ttar.c lookup3.c tpw.c librpmio.vers testit.sh rpmgrep.1 > > EXTRA_PROGRAMS = tdeb tdir tfts tget tglob thkp thtml tinv tkey > tmacro tmagic tmire tput tpw trpmio tsw ttar dumpasn1 lookup3 > > @@ -48,8 +48,8 @@ > rpmnss.h rpmpgp.h rpmsq.h rpmssl.h rpmsw.h rpmurl.h rpmxar.h \ > stringbuf.h ugid.h rpmuuid.h > noinst_HEADERS = \ > - md2.h md4.h poptIO.h rmd128.h rmd160.h rmd256.h rmd320.h > sha224.h \ > - salsa10.h salsa20.h tiger.h \ > + cpio.h iosm.h md2.h md4.h poptIO.h rmd128.h rmd160.h rmd256.h > rmd320.h sha224.h \ > + salsa10.h salsa20.h tar.h tiger.h \ > LzmaDecode.h rpmhook.h rpmio_internal.h rpmlua.h > > usrlibdir = $(libdir) > @@ -154,7 +154,7 @@ > rpmdigest_SOURCES = rpmdigest.c > rpmdigest_LDADD = $(RPMIO_LDADD) > > -tdeb_SOURCES = tdeb.c > +tdeb_SOURCES = tdeb.c iosm.c cpio.c tar.c > tdeb_LDFLAGS = $(RPM_LDADD) > > tdir_SOURCES = tdir.c > @@ . > patch -p0 <<'@@ .' > Index: rpm/rpmio/cpio.c > > ====================================================================== > ====== > $ cvs diff -u -r0 -r1.1 cpio.c > --- /dev/null 2008-03-02 23:33:00 +0100 > +++ cpio.c 2008-03-02 23:40:09 +0100 > @@ -0,0 +1,279 @@ > +/** \ingroup payload > + * \file lib/cpio.c > + * Handle cpio payloads within rpm packages. > + * > + * \warning FIXME: We don't translate between cpio and system > mode bits! These > + * should both be the same, but really odd things are going to > happen if > + * that's not true! > + */ > + > +#include "system.h" > + > +#include <rpmio.h> > +#include <rpmlib.h> > + > +#include "fsm.h" > + > +#include "debug.h" > + > +/*@access FSM_t @*/ > + > +/*@unchecked@*/ > +int _cpio_debug = 0; > + > +/** > + * Convert string to unsigned integer (with buffer size check). > + * @param str input string > + * @retval endptr address of 1st character not processed > + * @param base numerical conversion base > + * @param num max no. of bytes to read > + * @return converted integer > + */ > +static int strntoul(const char *str, /*@out@*/char **endptr, int > base, size_t num) > + /*@modifies *endptr @*/ > + /*@requires maxSet(endptr) >= 0 @*/ > +{ > + char * buf, * end; > + unsigned long ret; > + > + buf = alloca(num + 1); > + strncpy(buf, str, num); > + buf[num] = '\0'; > + > + ret = strtoul(buf, &end, base); > + if (*end != '\0') > + *endptr = ((char *)str) + (end - buf); /* XXX discards const */ > + else > + *endptr = ((char *)str) + strlen(buf); > + > + return ret; > +} > + > +#define GET_NUM_FIELD(phys, log) \ > + log = strntoul(phys, &end, 16, sizeof(phys)); \ > + if ( (end - phys) != sizeof(phys) ) return CPIOERR_BAD_HEADER; > +#define SET_NUM_FIELD(phys, val, space) \ > + sprintf(space, "%8.8lx", (unsigned long) (val)); \ > + memcpy(phys, space, 8) > + > +int cpioTrailerWrite(void * _fsm) > +{ > + FSM_t fsm = _fsm; > + struct cpioCrcPhysicalHeader * hdr = > + (struct cpioCrcPhysicalHeader *)fsm->rdbuf; > + int rc; > + > + memset(hdr, '0', PHYS_HDR_SIZE); > + memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic)); > + memcpy(hdr->nlink, "00000001", 8); > + memcpy(hdr->namesize, "0000000b", 8); > + memcpy(fsm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, sizeof > (CPIO_TRAILER)); > + > + /* XXX DWRITE uses rdnb for I/O length. */ > + fsm->rdnb = PHYS_HDR_SIZE + sizeof(CPIO_TRAILER); > + rc = fsmNext(fsm, FSM_DWRITE); > + > + /* > + * GNU cpio pads to 512 bytes here, but we don't. This may > matter for > + * tape device(s) and/or concatenated cpio archives. <shrug> > + */ > + if (!rc) > + rc = fsmNext(fsm, FSM_PAD); > + > + return rc; > +} > + > +int cpioHeaderWrite(void * _fsm, struct stat * st) > +{ > + FSM_t fsm = _fsm; > + struct cpioCrcPhysicalHeader * hdr = (struct > cpioCrcPhysicalHeader *)fsm->rdbuf; > + char field[64]; > + size_t len; > + dev_t dev; > + int rc = 0; > + > +if (_cpio_debug) > +fprintf(stderr, " cpioHeaderWrite(%p, %p)\n", fsm, st); > + > + memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic)); > + SET_NUM_FIELD(hdr->inode, st->st_ino, field); > + SET_NUM_FIELD(hdr->mode, st->st_mode, field); > + SET_NUM_FIELD(hdr->uid, st->st_uid, field); > + SET_NUM_FIELD(hdr->gid, st->st_gid, field); > + SET_NUM_FIELD(hdr->nlink, st->st_nlink, field); > + SET_NUM_FIELD(hdr->mtime, st->st_mtime, field); > + SET_NUM_FIELD(hdr->filesize, st->st_size, field); > + > + dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr- > >devMajor, dev, field); > + dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr- > >devMinor, dev, field); > + dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr- > >rdevMajor, dev, field); > + dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr- > >rdevMinor, dev, field); > + > + len = strlen(fsm->path) + 1; SET_NUM_FIELD(hdr->namesize, > len, field); > + memcpy(hdr->checksum, "00000000", 8); > + memcpy(fsm->rdbuf + PHYS_HDR_SIZE, fsm->path, len); > + > + /* XXX DWRITE uses rdnb for I/O length. */ > + fsm->rdnb = PHYS_HDR_SIZE + len; > + rc = fsmNext(fsm, FSM_DWRITE); > + if (!rc && fsm->rdnb != fsm->wrnb) > + rc = CPIOERR_WRITE_FAILED; > + if (!rc) > + rc = fsmNext(fsm, FSM_PAD); > + > + if (!rc && S_ISLNK(st->st_mode)) { > +assert(fsm->lpath != NULL); > + fsm->rdnb = strlen(fsm->lpath); > + memcpy(fsm->rdbuf, fsm->lpath, fsm->rdnb); > + rc = fsmNext(fsm, FSM_DWRITE); > + if (!rc && fsm->rdnb != fsm->wrnb) > + rc = CPIOERR_WRITE_FAILED; > + if (!rc) > + rc = fsmNext(fsm, FSM_PAD); > + } > + > + return rc; > +} > + > +int cpioHeaderRead(void * _fsm, struct stat * st) > +{ > + FSM_t fsm = _fsm; > + struct cpioCrcPhysicalHeader hdr; > + int nameSize; > + char * end; > + int major, minor; > + int rc = 0; > + > +if (_cpio_debug) > +fprintf(stderr, " cpioHeaderRead(%p, %p)\n", fsm, st); > + > + fsm->wrlen = PHYS_HDR_SIZE; > + rc = fsmNext(fsm, FSM_DREAD); > + if (!rc && fsm->rdnb != fsm->wrlen) > + rc = CPIOERR_READ_FAILED; > + if (rc) return rc; > + memcpy(&hdr, fsm->wrbuf, fsm->rdnb); > + > + if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof > (CPIO_CRC_MAGIC)-1) && > + strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1)) > + return CPIOERR_BAD_MAGIC; > + > + GET_NUM_FIELD(hdr.inode, st->st_ino); > + GET_NUM_FIELD(hdr.mode, st->st_mode); > + GET_NUM_FIELD(hdr.uid, st->st_uid); > + GET_NUM_FIELD(hdr.gid, st->st_gid); > + GET_NUM_FIELD(hdr.nlink, st->st_nlink); > + GET_NUM_FIELD(hdr.mtime, st->st_mtime); > + GET_NUM_FIELD(hdr.filesize, st->st_size); > + > + GET_NUM_FIELD(hdr.devMajor, major); > + GET_NUM_FIELD(hdr.devMinor, minor); > + /*@-shiftimplementation@*/ > + st->st_dev = Makedev(major, minor); > + /*@=shiftimplementation@*/ > + > + GET_NUM_FIELD(hdr.rdevMajor, major); > + GET_NUM_FIELD(hdr.rdevMinor, minor); > + /*@-shiftimplementation@*/ > + st->st_rdev = Makedev(major, minor); > + /*@=shiftimplementation@*/ > + > + GET_NUM_FIELD(hdr.namesize, nameSize); > + if (nameSize >= fsm->wrsize) > + return CPIOERR_BAD_HEADER; > + > + { char * t = xmalloc(nameSize + 1); > + fsm->wrlen = nameSize; > + rc = fsmNext(fsm, FSM_DREAD); > + if (!rc && fsm->rdnb != fsm->wrlen) > + rc = CPIOERR_BAD_HEADER; > + if (rc) { > + t = _free(t); > + fsm->path = NULL; > + return rc; > + } > + memcpy(t, fsm->wrbuf, fsm->rdnb); > + t[nameSize] = '\0'; > + fsm->path = t; > + } > + > + if (S_ISLNK(st->st_mode)) { > + rc = fsmNext(fsm, FSM_POS); > + if (rc) return rc; > + fsm->wrlen = st->st_size; > + rc = fsmNext(fsm, FSM_DREAD); > + if (!rc && fsm->rdnb != fsm->wrlen) > + rc = CPIOERR_READ_FAILED; > + if (rc) return rc; > + fsm->wrbuf[st->st_size] = '\0'; > + fsm->lpath = xstrdup(fsm->wrbuf); > + } > + > +if (_cpio_debug) > +fprintf(stderr, "\t %06o%3d (%4d,%4d)%10d %s\n\t-> %s\n", > + (unsigned)st->st_mode, (int)st->st_nlink, > + (int)st->st_uid, (int)st->st_gid, (int)st->st_size, > + (fsm->path ? fsm->path : ""), (fsm->lpath ? fsm- > >lpath : "")); > + > + return rc; > +} > + > +char * cpioStrerror(int rc) > +{ > + char msg[256]; > + char *s; > + int l, myerrno = errno; > + > + strcpy(msg, "cpio: "); > + switch (rc) { > + default: > + s = msg + strlen(msg); > + sprintf(s, _("(error 0x%x)"), (unsigned)rc); > + s = NULL; > + break; > + case CPIOERR_BAD_MAGIC: s = _("Bad magic"); break; > + case CPIOERR_BAD_HEADER: s = _("Bad/unreadable header"); break; > + > + case CPIOERR_OPEN_FAILED: s = "open"; break; > + case CPIOERR_CHMOD_FAILED: s = "chmod"; break; > + case CPIOERR_CHOWN_FAILED: s = "chown"; break; > + case CPIOERR_WRITE_FAILED: s = "write"; break; > + case CPIOERR_UTIME_FAILED: s = "utime"; break; > + case CPIOERR_UNLINK_FAILED: s = "unlink"; break; > + case CPIOERR_RENAME_FAILED: s = "rename"; break; > + case CPIOERR_SYMLINK_FAILED: s = "symlink"; break; > + case CPIOERR_STAT_FAILED: s = "stat"; break; > + case CPIOERR_LSTAT_FAILED: s = "lstat"; break; > + case CPIOERR_MKDIR_FAILED: s = "mkdir"; break; > + case CPIOERR_RMDIR_FAILED: s = "rmdir"; break; > + case CPIOERR_MKNOD_FAILED: s = "mknod"; break; > + case CPIOERR_MKFIFO_FAILED: s = "mkfifo"; break; > + case CPIOERR_LINK_FAILED: s = "link"; break; > + case CPIOERR_READLINK_FAILED: s = "readlink"; break; > + case CPIOERR_READ_FAILED: s = "read"; break; > + case CPIOERR_COPY_FAILED: s = "copy"; break; > + case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon"; break; > + > + case CPIOERR_HDR_SIZE: s = _("Header size too big"); break; > + case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); > break; > + case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link > (s)"); break; > + case CPIOERR_DIGEST_MISMATCH: s = _("File digest mismatch"); > break; > + case CPIOERR_INTERNAL: s = _("Internal error"); break; > + case CPIOERR_UNMAPPED_FILE: s = _("Archive file not in > header"); break; > + case CPIOERR_ENOENT: s = strerror(ENOENT); break; > + case CPIOERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break; > + } > + > + l = sizeof(msg) - strlen(msg) - 1; > + if (s != NULL) { > + if (l > 0) strncat(msg, s, l); > + l -= strlen(s); > + } > + if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) { > + s = _(" failed - "); > + if (l > 0) strncat(msg, s, l); > + l -= strlen(s); > + if (l > 0) strncat(msg, strerror(myerrno), l); > + } > + return xstrdup(msg); > +} > @@ . > patch -p0 <<'@@ .' > Index: rpm/rpmio/cpio.h > > ====================================================================== > ====== > $ cvs diff -u -r0 -r1.1 cpio.h > --- /dev/null 2008-03-02 23:33:00 +0100 > +++ cpio.h 2008-03-02 23:40:09 +0100 > @@ -0,0 +1,149 @@ > +#ifndef H_CPIO > +#define H_CPIO > + > +/** \ingroup payload > + * \file lib/cpio.h > + * Structures used to handle cpio payloads within rpm packages. > + * > + * @warning Rpm's cpio implementation may be different than > standard cpio. > + * The implementation is pretty close, but it has some > behaviors which are > + * more to RPM's liking. I tried to document the differing > behavior in cpio.c, > + * but I may have missed some (ewt). > + * > + */ > + > +/** \ingroup payload > + * @note CPIO_CHECK_ERRNO bit is set only if errno is valid. > + */ > +#define CPIOERR_CHECK_ERRNO 0x00008000 > + > +/** \ingroup payload > + */ > +enum cpioErrorReturns { > + CPIOERR_BAD_MAGIC = (2 ), > + CPIOERR_BAD_HEADER = (3 ), > + CPIOERR_OPEN_FAILED = (4 | CPIOERR_CHECK_ERRNO), > + CPIOERR_CHMOD_FAILED = (5 | CPIOERR_CHECK_ERRNO), > + CPIOERR_CHOWN_FAILED = (6 | CPIOERR_CHECK_ERRNO), > + CPIOERR_WRITE_FAILED = (7 | CPIOERR_CHECK_ERRNO), > + CPIOERR_UTIME_FAILED = (8 | CPIOERR_CHECK_ERRNO), > + CPIOERR_UNLINK_FAILED = (9 | CPIOERR_CHECK_ERRNO), > + > + CPIOERR_RENAME_FAILED = (10 | CPIOERR_CHECK_ERRNO), > + CPIOERR_SYMLINK_FAILED = (11 | CPIOERR_CHECK_ERRNO), > + CPIOERR_STAT_FAILED = (12 | CPIOERR_CHECK_ERRNO), > + CPIOERR_LSTAT_FAILED = (13 | CPIOERR_CHECK_ERRNO), > + CPIOERR_MKDIR_FAILED = (14 | CPIOERR_CHECK_ERRNO), > + CPIOERR_RMDIR_FAILED = (15 | CPIOERR_CHECK_ERRNO), > + CPIOERR_MKNOD_FAILED = (16 | CPIOERR_CHECK_ERRNO), > + CPIOERR_MKFIFO_FAILED = (17 | CPIOERR_CHECK_ERRNO), > + CPIOERR_LINK_FAILED = (18 | CPIOERR_CHECK_ERRNO), > + CPIOERR_READLINK_FAILED = (19 | CPIOERR_CHECK_ERRNO), > + CPIOERR_READ_FAILED = (20 | CPIOERR_CHECK_ERRNO), > + CPIOERR_COPY_FAILED = (21 | CPIOERR_CHECK_ERRNO), > + CPIOERR_LSETFCON_FAILED = (22 | CPIOERR_CHECK_ERRNO), > + CPIOERR_HDR_SIZE = (23 ), > + CPIOERR_HDR_TRAILER = (24 ), > + CPIOERR_UNKNOWN_FILETYPE= (25 ), > + CPIOERR_MISSING_HARDLINK= (26 ), > + CPIOERR_DIGEST_MISMATCH = (27 ), > + CPIOERR_INTERNAL = (28 ), > + CPIOERR_UNMAPPED_FILE = (29 ), > + CPIOERR_ENOENT = (30 ), > + CPIOERR_ENOTEMPTY = (31 ) > +}; > + > +/** \ingroup payload > + */ > +typedef enum cpioMapFlags_e { > + CPIO_MAP_PATH = (1 << 0), > + CPIO_MAP_MODE = (1 << 1), > + CPIO_MAP_UID = (1 << 2), > + CPIO_MAP_GID = (1 << 3), > + CPIO_FOLLOW_SYMLINKS= (1 << 4), /*!< only for building. */ > + CPIO_MAP_ABSOLUTE = (1 << 5), > + CPIO_MAP_ADDDOT = (1 << 6), > + CPIO_ALL_HARDLINKS = (1 << 7), /*!< fail if hardlinks are > missing. */ > + CPIO_MAP_TYPE = (1 << 8), /*!< only for building. */ > + CPIO_SBIT_CHECK = (1 << 9), > + CPIO_PAYLOAD_LIST = (1 << 10), > + CPIO_PAYLOAD_EXTRACT= (1 << 11), > + CPIO_PAYLOAD_CREATE = (1 << 12) > +} cpioMapFlags; > + > +#define CPIO_NEWC_MAGIC "070701" > +#define CPIO_CRC_MAGIC "070702" > +#define CPIO_TRAILER "TRAILER!!!" > + > +/** \ingroup payload > + * Cpio archive header information. > + */ > +struct cpioCrcPhysicalHeader { > + char magic[6]; > + char inode[8]; > + char mode[8]; > + char uid[8]; > + char gid[8]; > + char nlink[8]; > + char mtime[8]; > + char filesize[8]; > + char devMajor[8]; > + char devMinor[8]; > + char rdevMajor[8]; > + char rdevMinor[8]; > + char namesize[8]; > + char checksum[8]; /* ignored !! */ > +}; > + > +#define PHYS_HDR_SIZE 110 /* Don't depend on sizeof(struct) */ > + > +/*@unchecked@*/ > +extern int _cpio_debug; > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** > + * Write cpio trailer. > + * @retval _fsm file path and stat info > + * @return 0 on success > + */ > +int cpioTrailerWrite(void * _fsm) > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies _fsm, fileSystem, internalState @*/; > + > +/** > + * Write cpio header. > + * @retval _fsm file path and stat info > + * @param st > + * @return 0 on success > + */ > +int cpioHeaderWrite(void * _fsm, struct stat * st) > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies _fsm, fileSystem, internalState @*/; > + > +/** > + * Read cpio header. > + * @retval _fsm file path and stat info > + * @retval st > + * @return 0 on success > + */ > +int cpioHeaderRead(void * _fsm, struct stat * st) > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies _fsm, *st, fileSystem, internalState @*/; > + > +/** \ingroup payload > + * Return formatted error message on payload handling failure. > + * @param rc error code > + * @return (malloc'd) formatted error string > + */ > +/*@only@*/ > +char * cpioStrerror(int rc) > + /*@*/; > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* H_CPIO */ > @@ . > patch -p0 <<'@@ .' > Index: rpm/rpmio/iosm.c > > ====================================================================== > ====== > $ cvs diff -u -r0 -r1.1 iosm.c > --- /dev/null 2008-03-02 23:33:00 +0100 > +++ iosm.c 2008-03-02 23:40:09 +0100 > @@ -0,0 +1,2653 @@ > +/** \ingroup payload > + * \file lib/iosm.c > + * File state machine to handle a payload from a package. > + */ > + > +#include "system.h" > + > +#include <rpmio_internal.h> /* XXX urlPath, fdGetCpioPos */ > +#include <rpmcb.h> /* XXX fnpyKey */ > +#include <rpmtag.h> > +#include <rpmlib.h> > + > +#define _RPMFI_INTERNAL > +#define _RPMIOSM_INTERNAL > +#include "iosm.h" > +#define iosmUNSAFE XiosmStage > + > +#include "cpio.h" > +#include "tar.h" > +#include "ar.h" > + > +#include "rpmte.h" > +#include "rpmts.h" > +#include "rpmsq.h" > + > +#include "ugid.h" /* XXX unameToUid() and gnameToGid() */ > + > +#include "debug.h" > + > +/*@access FD_t @*/ /* XXX void ptr args */ > +/*@access IOSMI_t @*/ > +/*@access IOSM_t @*/ > + > +/*@access rpmfi @*/ > + > +#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) > + > +#define _IOSM_DEBUG 0 > +/*@unchecked@*/ > +int _iosm_debug = _IOSM_DEBUG; > + > +/*@-exportheadervar@*/ > +/*@unchecked@*/ > +int _iosm_threads = 0; > +/*@=exportheadervar@*/ > + > +/* XXX Failure to remove is not (yet) cause for failure. */ > +/*@-exportlocal -exportheadervar@*/ > +/*@unchecked@*/ > +int strict_erasures = 0; > +/*@=exportlocal =exportheadervar@*/ > + > +void * iosmGetTs(const IOSM_t iosm) { > + const IOSMI_t iter = iosm->iter; > + /*@-compdef -refcounttrans -retexpose -usereleased @*/ > + return (iter ? iter->ts : NULL); > + /*@=compdef =refcounttrans =retexpose =usereleased @*/ > +} > + > +void * iosmGetFi(const IOSM_t iosm) > +{ > + const IOSMI_t iter = iosm->iter; > + /*@-compdef -refcounttrans -retexpose -usereleased @*/ > + return (iter ? iter->fi : NULL); > + /*@=compdef =refcounttrans =retexpose =usereleased @*/ > +} > + > +#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 iosm 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 * iosmFsPath(/*@special@*/ /*@null@*/ const IOSM_t iosm, > + /*@null@*/ const struct stat * st, > + /*@null@*/ const char * subdir, > + /*@null@*/ const char * suffix) > + /*@uses iosm->dirName, iosm->baseName */ > + /*@*/ > +{ > + const char * s = NULL; > + > + if (iosm) { > + char * t; > + int nb; > + nb = strlen(iosm->dirName) + > + (st && !S_ISDIR(st->st_mode) ? (subdir ? strlen(subdir) : > 0) : 0) + > + (st && !S_ISDIR(st->st_mode) ? (suffix ? strlen(suffix) : > 0) : 0) + > + strlen(iosm->baseName) + 1; > + s = t = xmalloc(nb); > + t = stpcpy(t, iosm->dirName); > + if (st && !S_ISDIR(st->st_mode)) > + if (subdir) t = stpcpy(t, subdir); > + t = stpcpy(t, iosm->baseName); > + if (st && !S_ISDIR(st->st_mode)) > + if (suffix) t = stpcpy(t, suffix); > + } > + return s; > +} > + > +/** \ingroup payload > + * Destroy file info iterator. > + * @param p file info iterator > + * @retval NULL always > + */ > +static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ > void * p) > + /*@globals fileSystem @*/ > + /*@modifies fileSystem @*/ > +{ > + IOSMI_t iter = p; > + if (iter) { > +/*@-internalglobs@*/ /* XXX rpmswExit() */ > + iter->ts = rpmtsFree(iter->ts); > +/*@=internalglobs@*/ > + iter->fi = rpmfiUnlink(iter->fi, "mapIterator"); > + } > + return _free(p); > +} > + > +/** \ingroup payload > + * Create file info iterator. > + * @param ts transaction set > + * @param fi transaction element file info > + * @return file info iterator > + */ > +static void * > +mapInitIterator(rpmts ts, rpmfi fi) > + /*@modifies ts, fi @*/ > +{ > + IOSMI_t iter = NULL; > + > + iter = xcalloc(1, sizeof(*iter)); > + iter->ts = rpmtsLink(ts, "mapIterator"); > + iter->fi = rpmfiLink(fi, "mapIterator"); > + iter->reverse = (rpmteType(fi->te) == TR_REMOVED && fi- > >action != FA_COPYOUT); > + iter->i = (iter->reverse ? (fi->fc - 1) : 0); > + iter->isave = iter->i; > + return iter; > +} > + > +/** \ingroup payload > + * Return next index into file info. > + * @param a file info iterator > + * @return next index, -1 on termination > + */ > +static int mapNextIterator(/*@null@*/ void * a) > + /*@*/ > +{ > + IOSMI_t iter = a; > + int i = -1; > + > + if (iter) { > + const rpmfi fi = iter->fi; > + if (iter->reverse) { > + if (iter->i >= 0) i = iter->i--; > + } else { > + if (iter->i < fi->fc) i = iter->i++; > + } > + iter->isave = i; > + } > + return i; > +} > + > +/** \ingroup payload > + */ > +static int cpioStrCmp(const void * a, const void * b) > + /*@*/ > +{ > + const char * aurl = *(const char **)a; > + const char * burl = *(const char **)b; > + const char * afn = NULL; > + const char * bfn = NULL; > + > + (void) urlPath(aurl, &afn); > + (void) urlPath(burl, &bfn); > + > +#ifdef VERY_OLD_BUGGY_RPM_PACKAGES > + /* XXX Some rpm-2.4 packages from 1997 have basename only in > payloads. */ > + if (strchr(afn, '/') == NULL) > + bfn = strrchr(bfn, '/') + 1; > +#endif > + > + /* 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 to '/'. */ > + if (afn[0] == '/') afn += 1; > + if (bfn[0] == '/') bfn += 1; > + > + return strcmp(afn, bfn); > +} > + > +/** \ingroup payload > + * Locate archive path in file info. > + * @param iter file info iterator > + * @param iosmPath archive path > + * @return index into file info, -1 if archive path was not found > + */ > +static int mapFind(/*@null@*/ IOSMI_t iter, const char * iosmPath) > + /*@modifies iter @*/ > +{ > + int ix = -1; > + > + if (iter) { > + const rpmfi fi = iter->fi; > + int fc = rpmfiFC(fi); > + if (fi && fc > 0 && fi->apath && iosmPath && *iosmPath) { > + const char ** p = NULL; > + > + if (fi->apath != NULL) > + p = bsearch(&iosmPath, fi->apath, fc, sizeof(iosmPath), > + cpioStrCmp); > + if (p) { > + iter->i = p - fi->apath; > + ix = mapNextIterator(iter); > + } > + } > + } > + return ix; > +} > + > +/** \ingroup payload > + * Directory name iterator. > + */ > +typedef struct dnli_s { > + rpmfi fi; > +/*@only@*/ /*@null@*/ > + char * active; > + int reverse; > + int isave; > + int i; > +} * DNLI_t; > + > +/** \ingroup payload > + * Destroy directory name iterator. > + * @param a directory name iterator > + * @retval NULL always > + */ > +static /*@null@*/ void * dnlFreeIterator(/*@only@*//*@null@*/ > const void * a) > + /*@modifies a @*/ > +{ > + if (a) { > + DNLI_t dnli = (void *)a; > + if (dnli->active) free(dnli->active); > + } > + return _free(a); > +} > + > +/** \ingroup payload > + */ > +static inline int dnlCount(/*@null@*/ const DNLI_t dnli) > + /*@*/ > +{ > + return (dnli ? dnli->fi->dc : 0); > +} > + > +/** \ingroup payload > + */ > +static inline int dnlIndex(/*@null@*/ const DNLI_t dnli) > + /*@*/ > +{ > + return (dnli ? dnli->isave : -1); > +} > + > +/** \ingroup payload > + * Create directory name iterator. > + * @param iosm file state machine data > + * @param reverse traverse directory names in reverse order? > + * @return directory name iterator > + */ > +/*@-usereleased@*/ > +static /*@only@*/ /*@null@*/ > +void * dnlInitIterator(/*@special@*/ const IOSM_t iosm, > + int reverse) > + /*@uses iosm->iter @*/ > + /*@*/ > +{ > + rpmfi fi = iosmGetFi(iosm); > + const char * dnl; > + 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. */ > + if ((fi = rpmfiInit(fi, 0)) != NULL) > + while ((i = rpmfiNext(fi)) >= 0) { > + if (!XFA_SKIPPING(fi->actions[i])) dnli->active[fi- > >dil[i]] = 1; > + } > + > + /* Exclude parent directories that are explicitly included. */ > + if ((fi = rpmfiInit(fi, 0)) != NULL) > + while ((i = rpmfiNext(fi)) >= 0) { > + int dil; > + size_t 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++) { > + size_t jlen; > + > + if (!dnli->active[j] || j == dil) > + /*@innercontinue@*/ continue; > + (void) urlPath(fi->dnl[j], &dnl); > + jlen = strlen(dnl); > + if (jlen != (dnlen+bnlen+1)) > + /*@innercontinue@*/ continue; > + if (strncmp(dnl, fi->dnl[dil], dnlen)) > + /*@innercontinue@*/ continue; > + if (strncmp(dnl+dnlen, fi->bnl[i], bnlen)) > + /*@innercontinue@*/ continue; > + if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') > + /*@innercontinue@*/ continue; > + /* This directory is included in the package. */ > + dnli->active[j] = 0; > + /*@innerbreak@*/ 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; > + rpmlog(RPMLOG_DEBUG, > + D_("========== Directories not explicitly included in package: > \n")); > + } > + (void) urlPath(fi->dnl[i], &dnl); > + rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, dnl); > + } > + if (j) > + rpmlog(RPMLOG_DEBUG, "==========\n"); > + } > + } > + return dnli; > +} > +/*@=usereleased@*/ > + > +/** \ingroup payload > + * Return next directory name (from file info). > + * @param dnli directory name iterator > + * @return next directory name > + */ > +static /*@observer@*/ /*@null@*/ > +const char * dnlNextIterator(/*@null@*/ DNLI_t dnli) > + /*@modifies dnli @*/ > +{ > + const char * dn = NULL; > + > + if (dnli) { > + rpmfi fi = dnli->fi; > + int i = -1; > + > + if (dnli->active) > + 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; > +} > + > +#if defined(HAVE_PTHREAD_H) > +static void * iosmThread(void * arg) > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies arg, fileSystem, internalState @*/ > +{ > + IOSM_t iosm = arg; > +/*@-unqualifiedtrans@*/ > + return ((void *) ((long)XiosmStage(iosm, iosm->nstage))); > +/*@=unqualifiedtrans@*/ > +} > +#endif > + > +int iosmNext(IOSM_t iosm, iosmStage nstage) > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + iosm->nstage = nstage; > +#if defined(HAVE_PTHREAD_H) > + if (_iosm_threads) > + return rpmsqJoin( rpmsqThread(iosmThread, iosm) ); > +#endif > + return XiosmStage(iosm, iosm->nstage); > +} > + > +/** \ingroup payload > + * Save hard link in chain. > + * @param iosm file state machine data > + * @return Is chain only partially filled? > + */ > +static int saveHardLink(/*@special@*/ /*@partial@*/ IOSM_t iosm) > + /*@uses iosm->links, iosm->ix, iosm->sb, iosm->goal, iosm- > >nsuffix @*/ > + /*@defines iosm->li @*/ > + /*@releases iosm->path @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + struct stat * st = &iosm->sb; > + int rc = 0; > + int ix = -1; > + int j; > + > + /* Find hard link set. */ > + for (iosm->li = iosm->links; iosm->li; iosm->li = iosm->li- > >next) { > + if (iosm->li->sb.st_ino == st->st_ino && iosm->li->sb.st_dev == > st->st_dev) > + break; > + } > + > + /* New hard link encountered, add new link to set. */ > + if (iosm->li == NULL) { > + iosm->li = xcalloc(1, sizeof(*iosm->li)); > + iosm->li->next = NULL; > + iosm->li->sb = *st; /* structure assignment */ > + iosm->li->nlink = st->st_nlink; > + iosm->li->linkIndex = iosm->ix; > + iosm->li->createdPath = -1; > + > + iosm->li->filex = xcalloc(st->st_nlink, sizeof(iosm->li->filex > [0])); > + memset(iosm->li->filex, -1, (st->st_nlink * sizeof(iosm->li- > >filex[0]))); > + iosm->li->nsuffix = xcalloc(st->st_nlink, sizeof(*iosm->li- > >nsuffix)); > + > + if (iosm->goal == IOSM_PKGBUILD) > + iosm->li->linksLeft = st->st_nlink; > + if (iosm->goal == IOSM_PKGINSTALL) > + iosm->li->linksLeft = 0; > + > + /*@-kepttrans@*/ > + iosm->li->next = iosm->links; > + /*@=kepttrans@*/ > + iosm->links = iosm->li; > + } > + > + if (iosm->goal == IOSM_PKGBUILD) --iosm->li->linksLeft; > + iosm->li->filex[iosm->li->linksLeft] = iosm->ix; > + /*@-observertrans -dependenttrans@*/ > + iosm->li->nsuffix[iosm->li->linksLeft] = iosm->nsuffix; > + /*@=observertrans =dependenttrans@*/ > + if (iosm->goal == IOSM_PKGINSTALL) iosm->li->linksLeft++; > + > + if (iosm->goal == IOSM_PKGBUILD) > + return (iosm->li->linksLeft > 0); > + > + if (iosm->goal != IOSM_PKGINSTALL) > + return 0; > + > + if (!(st->st_size || iosm->li->linksLeft == st->st_nlink)) > + return 1; > + > + /* Here come the bits, time to choose a non-skipped file > name. */ > + { rpmfi fi = iosmGetFi(iosm); > + > + for (j = iosm->li->linksLeft - 1; j >= 0; j--) { > + ix = iosm->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. */ > + iosm->li->linkIndex = j; > + iosm->path = _free(iosm->path); > + iosm->ix = ix; > + rc = iosmNext(iosm, IOSM_MAP); > + return rc; > +} > + > +/** \ingroup payload > + * Destroy set of hard links. > + * @param li set of hard links > + * @return NULL always > + */ > +static /*@null@*/ void * freeHardLink(/*@only@*/ /*@null@*/ > struct hardLink_s * li) > + /*@modifies li @*/ > +{ > + if (li) { > + li->nsuffix = _free(li->nsuffix); /* XXX elements are shared */ > + li->filex = _free(li->filex); > + } > + return _free(li); > +} > + > +IOSM_t newIOSM(void) > +{ > + IOSM_t iosm = xcalloc(1, sizeof(*iosm)); > + return iosm; > +} > + > +IOSM_t freeIOSM(IOSM_t iosm) > +{ > + if (iosm) { > + iosm->path = _free(iosm->path); > + while ((iosm->li = iosm->links) != NULL) { > + iosm->links = iosm->li->next; > + iosm->li->next = NULL; > + iosm->li = freeHardLink(iosm->li); > + } > + iosm->dnlx = _free(iosm->dnlx); > + iosm->ldn = _free(iosm->ldn); > + iosm->iter = mapFreeIterator(iosm->iter); > + } > + return _free(iosm); > +} > + > +static int arSetup(IOSM_t iosm, rpmfi fi) > + /*@modifies iosm @*/ > +{ > + const char * path; > + char * t; > + size_t lmtablen = 0; > + size_t nb; > + > + /* Calculate size of ar(1) long member table. */ > + if ((fi = rpmfiInit(fi, 0)) != NULL) > + while (rpmfiNext(fi) >= 0) { > +#ifdef NOTYET > + if (fi->apath) { > + const char * apath = NULL; > + (void) urlPath(fi->apath[ix], &apath); > + path = apath + fi->striplen; > + } else > +#endif > + path = rpmfiBN(fi); > + if ((nb = strlen(path)) < 15) > + continue; > + lmtablen += nb + 1; /* trailing \n */ > + } > + > + /* Anything to do? */ > + if (lmtablen == 0) > + return 0; > + > + /* Create and load ar(1) long member table. */ > + iosm->lmtab = t = xmalloc(lmtablen + 1); /* trailing \0 */ > + iosm->lmtablen = lmtablen; > + iosm->lmtaboff = 0; > + if ((fi = rpmfiInit(fi, 0)) != NULL) > + while (rpmfiNext(fi) >= 0) { > +#ifdef NOTYET > + if (fi->apath) { > + const char * apath = NULL; > + (void) urlPath(fi->apath[ix], &apath); > + path = apath + fi->striplen; > + } else > +#endif > + path = rpmfiBN(fi); > + if ((nb = strlen(path)) < 15) > + continue; > + t = stpcpy(t, path); > + *t++ = '\n'; > + } > + *t = '\0'; > + > + return 0; > +} > + > +int iosmSetup(IOSM_t iosm, iosmStage goal, const char * afmt, > + const void * _ts, const void * _fi, FD_t cfd, > + unsigned int * archiveSize, const char ** failedFile) > +{ > + const rpmts ts = (const rpmts) _ts; > + const rpmfi fi = (const rpmfi) _fi; > + size_t pos = 0; > + int rc, ec = 0; > + > +/*@+voidabstract -nullpass@*/ > +if (_iosm_debug < 0) > +fprintf(stderr, "--> iosmSetup(%p, 0x%x, \"%s\", %p, %p, %p, %p, > %p)\n", iosm, goal, afmt, (void *)ts, fi, cfd, archiveSize, > failedFile); > +/*@=voidabstract =nullpass@*/ > + > + if (iosm->headerRead == NULL) { > + if (afmt != NULL && (!strcmp(afmt, "tar") || !strcmp(afmt, > "ustar"))) { > +if (_iosm_debug < 0) > +fprintf(stderr, "\ttar vectors set\n"); > + iosm->headerRead = &tarHeaderRead; > + iosm->headerWrite = &tarHeaderWrite; > + iosm->trailerWrite = &tarTrailerWrite; > + iosm->blksize = TAR_BLOCK_SIZE; > + } else > + if (afmt != NULL && !strcmp(afmt, "ar")) { > +if (_iosm_debug < 0) > +fprintf(stderr, "\tar vectors set\n"); > + _fsmNext = &iosmNext; > + iosm->headerRead = &arHeaderRead; > + iosm->headerWrite = &arHeaderWrite; > + iosm->trailerWrite = &arTrailerWrite; > + iosm->blksize = 2; > + (void) arSetup(iosm, fi); > + } else > + { > +if (_iosm_debug < 0) > +fprintf(stderr, "\tcpio vectors set\n"); > + iosm->headerRead = &cpioHeaderRead; > + iosm->headerWrite = &cpioHeaderWrite; > + iosm->trailerWrite = &cpioTrailerWrite; > + iosm->blksize = 4; > + } > + } > + > + iosm->goal = goal; > + if (cfd != NULL) { > + iosm->cfd = fdLink(cfd, "persist (iosm)"); > + pos = fdGetCpioPos(iosm->cfd); > + fdSetCpioPos(iosm->cfd, 0); > + } > + iosm->iter = mapInitIterator(ts, fi); > + > + if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == > IOSM_PKGBUILD) { > + void * ptr; > + fi->archivePos = 0; > + ptr = rpmtsNotify(ts, fi->te, > + RPMCALLBACK_INST_START, fi->archivePos, fi->archiveSize); > + } > + > + /*@-assignexpose@*/ > + iosm->archiveSize = archiveSize; > + if (iosm->archiveSize) > + *iosm->archiveSize = 0; > + iosm->failedFile = failedFile; > + if (iosm->failedFile) > + *iosm->failedFile = NULL; > + /*@=assignexpose@*/ > + > + memset(iosm->sufbuf, 0, sizeof(iosm->sufbuf)); > + if (iosm->goal == IOSM_PKGINSTALL) { > + if (ts && rpmtsGetTid(ts) != -1) > + sprintf(iosm->sufbuf, ";%08x", (unsigned)rpmtsGetTid(ts)); > + } > + > + ec = iosm->rc = 0; > + rc = iosmUNSAFE(iosm, IOSM_CREATE); > + if (rc && !ec) ec = rc; > + > + rc = iosmUNSAFE(iosm, iosm->goal); > + if (rc && !ec) ec = rc; > + > + if (iosm->archiveSize && ec == 0) > + *iosm->archiveSize = (fdGetCpioPos(iosm->cfd) - pos); > + > +/*@-nullstate@*/ /* FIX: *iosm->failedFile may be NULL */ > + return ec; > +/*@=nullstate@*/ > +} > + > +int iosmTeardown(IOSM_t iosm) > +{ > + int rc = iosm->rc; > + > +if (_iosm_debug < 0) > +fprintf(stderr, "--> iosmTeardown(%p)\n", iosm); > + if (!rc) > + rc = iosmUNSAFE(iosm, IOSM_DESTROY); > + > + iosm->lmtab = _free(iosm->lmtab); > + iosm->iter = mapFreeIterator(iosm->iter); > + if (iosm->cfd != NULL) { > + iosm->cfd = fdFree(iosm->cfd, "persist (iosm)"); > + iosm->cfd = NULL; > + } > + iosm->failedFile = NULL; > + return rc; > +} > + > +static int iosmMapFContext(IOSM_t iosm) > + /*@modifies iosm @*/ > +{ > + rpmts ts = iosmGetTs(iosm); > + rpmfi fi = iosmGetFi(iosm); > + > + /* > + * Find file security context (if not disabled). > + */ > + iosm->fcontext = NULL; > + if (ts != NULL && rpmtsSELinuxEnabled(ts) == 1 && > + !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) > + { > + security_context_t scon = NULL; > + > +/*@-moduncon@*/ > + if (matchpathcon(iosm->path, iosm->sb.st_mode, &scon) == 0 && > scon != NULL) > + iosm->fcontext = scon; > + else { > + int i = iosm->ix; > + > + /* Get file security context from package. */ > + if (fi && i >= 0 && i < fi->fc) > + iosm->fcontext = (fi->fcontexts ? fi->fcontexts[i] : NULL); > + } > +/*@=moduncon@*/ > + } > + return 0; > +} > + > +int iosmMapPath(IOSM_t iosm) > +{ > + rpmfi fi = iosmGetFi(iosm); /* XXX const except for fstates */ > + int rc = 0; > + int i; > + > + iosm->osuffix = NULL; > + iosm->nsuffix = NULL; > + iosm->astriplen = 0; > + iosm->action = FA_UNKNOWN; > + iosm->mapFlags = fi->mapflags; > + > + i = iosm->ix; > + if (fi && i >= 0 && i < fi->fc) { > + > + iosm->astriplen = fi->astriplen; > + iosm->action = (fi->actions ? fi->actions[i] : fi->action); > + iosm->fflags = (fi->fflags ? fi->fflags[i] : fi->flags); > + iosm->mapFlags = (fi->fmapflags ? fi->fmapflags[i] : fi- > >mapflags); > + > + /* src rpms have simple base name in payload. */ > + iosm->dirName = fi->dnl[fi->dil[i]]; > + iosm->baseName = fi->bnl[i]; > + > + switch (iosm->action) { > + case FA_SKIP: > + break; > + case FA_UNKNOWN: > + break; > + > + case FA_COPYOUT: > + break; > + case FA_COPYIN: > + case FA_CREATE: > +assert(rpmteType(fi->te) == TR_ADDED); > + break; > + > + case FA_SKIPNSTATE: > + if (fi->fstates && rpmteType(fi->te) == TR_ADDED) > + fi->fstates[i] = RPMFILE_STATE_NOTINSTALLED; > + break; > + > + case FA_SKIPNETSHARED: > + if (fi->fstates && rpmteType(fi->te) == TR_ADDED) > + fi->fstates[i] = RPMFILE_STATE_NETSHARED; > + break; > + > + case FA_SKIPCOLOR: > + if (fi->fstates && rpmteType(fi->te) == TR_ADDED) > + fi->fstates[i] = RPMFILE_STATE_WRONGCOLOR; > + break; > + > + case FA_BACKUP: > + if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost > file. */ > + switch (rpmteType(fi->te)) { > + case TR_ADDED: > + iosm->osuffix = SUFFIX_RPMORIG; > + /*@innerbreak@*/ break; > + case TR_REMOVED: > + iosm->osuffix = SUFFIX_RPMSAVE; > + /*@innerbreak@*/ break; > + } > + break; > + > + case FA_ALTNAME: > +assert(rpmteType(fi->te) == TR_ADDED); > + if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost > file. */ > + iosm->nsuffix = SUFFIX_RPMNEW; > + break; > + > + case FA_SAVE: > +assert(rpmteType(fi->te) == TR_ADDED); > + if (!(iosm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost > file. */ > + iosm->osuffix = SUFFIX_RPMSAVE; > + break; > + case FA_ERASE: > +#if 0 /* XXX is this a genhdlist fix? */ > + assert(rpmteType(fi->te) == TR_REMOVED); > +#endif > + /* > + * XXX TODO: %ghost probably shouldn't be removed, but that > changes > + * legacy rpm behavior. > + */ > + break; > + default: > + break; > + } > + > + if ((iosm->mapFlags & CPIO_MAP_PATH) || iosm->nsuffix) { > + const struct stat * st = &iosm->sb; > + iosm->path = _free(iosm->path); > + iosm->path = iosmFsPath(iosm, st, iosm->subdir, > + (iosm->suffix ? iosm->suffix : iosm->nsuffix)); > + } > + } > + return rc; > +} > + > +int iosmMapAttrs(IOSM_t iosm) > +{ > + struct stat * st = &iosm->sb; > + rpmfi fi = iosmGetFi(iosm); > + int i = iosm->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); > + dev_t finalRdev = (fi->frdevs ? fi->frdevs[i] : 0); > + uint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0); > + uid_t uid = fi->uid; > + gid_t gid = fi->gid; > + > +#if defined(RPM_VENDOR_OPENPKG) /* no-owner-group-on-srpm- > install */ > + /* Make sure OpenPKG RPM does not try to set file owner/group > on files during > + installation of _source_ RPMs. Instead, let it use the current > + run-time owner/group, because most of the time the owner/ > group in > + the source RPM (which is the owner/group of the files as > staying on > + the package author system) is not existing on the target > system, of > + course. */ > +#endif > + if (fi->fuser && unameToUid(fi->fuser[i], &uid)) { > +#if defined(RPM_VENDOR_OPENPKG) /* no-owner-group-on-srpm- > install */ > + if (headerIsEntry(fi->h, RPMTAG_SOURCERPM) != 0) { > +#endif > + if (iosm->goal == IOSM_PKGINSTALL) > + rpmlog(RPMLOG_WARNING, > + _("user %s does not exist - using root\n"), fi->fuser[i]); > + uid = 0; > + finalMode &= ~S_ISUID; /* turn off suid bit */ > +#if defined(RPM_VENDOR_OPENPKG) /* no-owner-group-on-srpm- > install */ > + } > +#endif > + } > + > + if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) { > +#if defined(RPM_VENDOR_OPENPKG) /* no-owner-group-on-srpm- > install */ > + if (headerIsEntry(fi->h, RPMTAG_SOURCERPM) != 0) { > +#endif > + if (iosm->goal == IOSM_PKGINSTALL) > + rpmlog(RPMLOG_WARNING, > + _("group %s does not exist - using root\n"), fi->fgroup[i]); > + gid = 0; > + finalMode &= ~S_ISGID; /* turn off sgid bit */ > +#if defined(RPM_VENDOR_OPENPKG) /* no-owner-group-on-srpm- > install */ > + } > +#endif > + } > + > + if (iosm->mapFlags & CPIO_MAP_MODE) > + st->st_mode = (st->st_mode & S_IFMT) | (finalMode & ~S_IFMT); > + if (iosm->mapFlags & CPIO_MAP_TYPE) { > + st->st_mode = (st->st_mode & ~S_IFMT) | (finalMode & S_IFMT); > + if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) > + && st->st_nlink == 0) > + st->st_nlink = 1; > + st->st_rdev = finalRdev; > + st->st_mtime = finalMtime; > + } > + if (iosm->mapFlags & CPIO_MAP_UID) > + st->st_uid = uid; > + if (iosm->mapFlags & CPIO_MAP_GID) > + st->st_gid = gid; > + > + { rpmts ts = iosmGetTs(iosm); > + > + /* > + * Set file digest (if not disabled). > + */ > + if (ts != NULL && !(rpmtsFlags(ts) & > RPMTRANS_FLAG_NOFDIGESTS)) { > + iosm->fdigestalgo = fi->digestalgo; > + iosm->fdigest = (fi->fdigests ? fi->fdigests[i] : NULL); > + iosm->digestlen = fi->digestlen; > + iosm->digest = (fi->digests ? (fi->digests + (iosm->digestlen > * i)) : NULL); > + } else { > + iosm->fdigestalgo = 0; > + iosm->fdigest = NULL; > + iosm->digestlen = 0; > + iosm->digest = NULL; > + } > + } > + > + } > + return 0; > +} > + > +/** \ingroup payload > + * Create file from payload stream. > + * @param iosm file state machine data > + * @return 0 on success > + */ > +/*@-compdef@*/ > +static int extractRegular(/*@special@*/ IOSM_t iosm) > + /*@uses iosm->fdigest, iosm->digest, iosm->sb, iosm->wfd @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + const struct stat * st = &iosm->sb; > + int left = st->st_size; > + int rc = 0; > + int xx; > + > + rc = iosmNext(iosm, IOSM_WOPEN); > + if (rc) > + goto exit; > + > + if (st->st_size > 0 && (iosm->fdigest != NULL || iosm- > >digest != NULL)) > + fdInitDigest(iosm->wfd, iosm->fdigestalgo, 0); > + > + while (left) { > + > + iosm->wrlen = (left > iosm->wrsize ? iosm->wrsize : left); > + rc = iosmNext(iosm, IOSM_DREAD); > + if (rc) > + goto exit; > + > + rc = iosmNext(iosm, IOSM_WRITE); > + if (rc) > + goto exit; > + > + left -= iosm->wrnb; > + > + /* Notify iff progress, completion is done elsewhere */ > + if (!rc && left) > + (void) iosmNext(iosm, IOSM_NOTIFY); > + } > + > + xx = fsync(Fileno(iosm->wfd)); > + > + if (st->st_size > 0 && (iosm->fdigest || iosm->digest)) { > + void * digest = NULL; > + int asAscii = (iosm->digest == NULL ? 1 : 0); > + > + (void) Fflush(iosm->wfd); > + fdFiniDigest(iosm->wfd, iosm->fdigestalgo, &digest, NULL, > asAscii); > + > + if (digest == NULL) { > + rc = CPIOERR_DIGEST_MISMATCH; > + goto exit; > + } > + > + if (iosm->digest != NULL) { > + if (memcmp(digest, iosm->digest, iosm->digestlen)) > + rc = CPIOERR_DIGEST_MISMATCH; > + } else { > + if (strcmp(digest, iosm->fdigest)) > + rc = CPIOERR_DIGEST_MISMATCH; > + } > + digest = _free(digest); > + } > + > +exit: > + (void) iosmNext(iosm, IOSM_WCLOSE); > + return rc; > +} > +/*@=compdef@*/ > + > +/** \ingroup payload > + * Write next item to payload stream. > + * @param iosm file state machine data > + * @param writeData should data be written? > + * @return 0 on success > + */ > +/*@-compdef -compmempass@*/ > +static int writeFile(/*@special@*/ /*@partial@*/ IOSM_t iosm, > int writeData) > + /*@uses iosm->path, iosm->opath, iosm->sb, iosm->osb, iosm->cfd > @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + const char * path = iosm->path; > + const char * opath = iosm->opath; > + struct stat * st = &iosm->sb; > + struct stat * ost = &iosm->osb; > + size_t left; > + int xx; > + 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 iosm->rdbuf, len in iosm->rdnb. */ > + rc = iosmUNSAFE(iosm, IOSM_READLINK); > + if (rc) goto exit; > + st->st_size = iosm->rdnb; > + iosm->lpath = xstrdup(iosm->rdbuf); /* XXX save readlink > return. */ > + } > + > + if (iosm->mapFlags & CPIO_MAP_ABSOLUTE) { > + int nb = strlen(iosm->dirName) + strlen(iosm->baseName) + sizeof > ("."); > + char * t = alloca(nb); > + *t = '\0'; > + iosm->path = t; > + if (iosm->mapFlags & CPIO_MAP_ADDDOT) > + *t++ = '.'; > + t = stpcpy( stpcpy(t, iosm->dirName), iosm->baseName); > + } else if (iosm->mapFlags & CPIO_MAP_PATH) { > + rpmfi fi = iosmGetFi(iosm); > + if (fi->apath) { > + const char * apath = NULL; > + (void) urlPath(fi->apath[iosm->ix], &apath); > + iosm->path = apath + fi->striplen; > + } else > + iosm->path = fi->bnl[iosm->ix]; > + } > + > + rc = iosmNext(iosm, IOSM_HWRITE); > + iosm->path = path; > + if (rc) goto exit; > + > + if (writeData && S_ISREG(st->st_mode)) { > +#if defined(HAVE_MMAP) > + char * rdbuf = NULL; > + void * mapped = (void *)-1; > + size_t nmapped = 0; > + /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_DONTNEED > better. */ > + int use_mmap = (st->st_size <= 0x07ffffff); > +#endif > + > + rc = iosmNext(iosm, IOSM_ROPEN); > + if (rc) goto exit; > + > + /* XXX unbuffered mmap generates *lots* of fdio debugging */ > +#if defined(HAVE_MMAP) > + if (use_mmap) { > + mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, > Fileno(iosm->rfd), 0); > + if (mapped != (void *)-1) { > + rdbuf = iosm->rdbuf; > + iosm->rdbuf = (char *) mapped; > + iosm->rdlen = nmapped = st->st_size; > +#if defined(HAVE_MADVISE) && defined(MADV_DONTNEED) > + xx = madvise(mapped, nmapped, MADV_DONTNEED); > +#endif > + } > + } > +#endif > + > + left = st->st_size; > + > + while (left) { > +#if defined(HAVE_MMAP) > + if (mapped != (void *)-1) { > + iosm->rdnb = nmapped; > + } else > +#endif > + { > + iosm->rdlen = (left > iosm->rdsize ? iosm->rdsize : left), > + rc = iosmNext(iosm, IOSM_READ); > + if (rc) goto exit; > + } > + > + /* XXX DWRITE uses rdnb for I/O length. */ > + rc = iosmNext(iosm, IOSM_DWRITE); > + if (rc) goto exit; > + > + left -= iosm->wrnb; > + } > + > +#if defined(HAVE_MMAP) > + if (mapped != (void *)-1) { > + xx = msync(mapped, nmapped, MS_ASYNC); > +#if defined(HAVE_MADVISE) && defined(MADV_DONTNEED) > + xx = madvise(mapped, nmapped, MADV_DONTNEED); > +#endif > +/*@-noeffect@*/ > + xx = munmap(mapped, nmapped); > +/*@=noeffect@*/ > + iosm->rdbuf = rdbuf; > + } else > +#endif > + xx = fsync(Fileno(iosm->rfd)); > + > + } > + > + rc = iosmNext(iosm, IOSM_PAD); > + if (rc) goto exit; > + > + rc = 0; > + > +exit: > + if (iosm->rfd != NULL) > + (void) iosmNext(iosm, IOSM_RCLOSE); > +/*@-dependenttrans@*/ > + iosm->opath = opath; > + iosm->path = path; > +/*@=dependenttrans@*/ > + return rc; > +} > +/*@=compdef =compmempass@*/ > + > +/** \ingroup payload > + * Write set of linked files to payload stream. > + * @param iosm file state machine data > + * @return 0 on success > + */ > +static int writeLinkedFile(/*@special@*/ /*@partial@*/ IOSM_t iosm) > + /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->li, iosm- > >failedFile @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + const char * path = iosm->path; > + const char * lpath = iosm->lpath; > + const char * nsuffix = iosm->nsuffix; > + int iterIndex = iosm->ix; > + int ec = 0; > + int rc; > + int i; > + const char * linkpath = NULL; > + int firstfile = 1; > + > + iosm->path = NULL; > + iosm->lpath = NULL; > + iosm->nsuffix = NULL; > + iosm->ix = -1; > + > + for (i = iosm->li->nlink - 1; i >= 0; i--) { > + > + if (iosm->li->filex[i] < 0) continue; > + > + iosm->ix = iosm->li->filex[i]; > +/*@-compdef@*/ > + rc = iosmNext(iosm, IOSM_MAP); > +/*@=compdef@*/ > + > + /* XXX tar and cpio have to do things differently. */ > + if (iosm->headerWrite == tarHeaderWrite) { > + if (firstfile) { > + const char * apath = NULL; > + char *t; > + (void) urlPath(iosm->path, &apath); > + /* Remove the buildroot prefix. */ > + t = xmalloc(sizeof(".") + strlen(apath + iosm->astriplen)); > + (void) stpcpy( stpcpy(t, "."), apath + iosm->astriplen); > + linkpath = t; > + firstfile = 0; > + } else > + iosm->lpath = linkpath; > + > + /* Write data after first link for tar. */ > + rc = writeFile(iosm, (iosm->lpath == NULL)); > + } else { > + /* Write data after last link for cpio. */ > + rc = writeFile(iosm, (i == 0)); > + } > + if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) { > + ec = rc; > + *iosm->failedFile = xstrdup(iosm->path); > + } > + > + iosm->path = _free(iosm->path); > + iosm->li->filex[i] = -1; > + } > + > +/*@-dependenttrans@*/ > + linkpath = _free(linkpath); > +/*@=dependenttrans@*/ > + iosm->ix = iterIndex; > + iosm->nsuffix = nsuffix; > + iosm->lpath = lpath; > + iosm->path = path; > + return ec; > +} > + > +/** \ingroup payload > + * Create pending hard links to existing file. > + * @param iosm file state machine data > + * @return 0 on success > + */ > +/*@-compdef@*/ > +static int iosmMakeLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm) > + /*@uses iosm->path, iosm->opath, iosm->nsuffix, iosm->ix, iosm- > >li @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + const char * path = iosm->path; > + const char * opath = iosm->opath; > + const char * nsuffix = iosm->nsuffix; > + int iterIndex = iosm->ix; > + int ec = 0; > + int rc; > + int i; > + > + iosm->path = NULL; > + iosm->opath = NULL; > + iosm->nsuffix = NULL; > + iosm->ix = -1; > + > + iosm->ix = iosm->li->filex[iosm->li->createdPath]; > + rc = iosmNext(iosm, IOSM_MAP); > + iosm->opath = iosm->path; > + iosm->path = NULL; > + for (i = 0; i < iosm->li->nlink; i++) { > + if (iosm->li->filex[i] < 0) continue; > + if (iosm->li->createdPath == i) continue; > + > + iosm->ix = iosm->li->filex[i]; > + iosm->path = _free(iosm->path); > + rc = iosmNext(iosm, IOSM_MAP); > + if (XFA_SKIPPING(iosm->action)) continue; > + > + rc = iosmUNSAFE(iosm, IOSM_VERIFY); > + if (!rc) continue; > + if (!(rc == CPIOERR_ENOENT)) break; > + > + /* XXX link(iosm->opath, iosm->path) */ > + rc = iosmNext(iosm, IOSM_LINK); > + if (iosm->failedFile && rc != 0 && *iosm->failedFile == NULL) { > + ec = rc; > + *iosm->failedFile = xstrdup(iosm->path); > + } > + > + iosm->li->linksLeft--; > + } > + iosm->path = _free(iosm->path); > + iosm->opath = _free(iosm->opath); > + > + iosm->ix = iterIndex; > + iosm->nsuffix = nsuffix; > + iosm->path = path; > + iosm->opath = opath; > + return ec; > +} > +/*@=compdef@*/ > + > +/** \ingroup payload > + * Commit hard linked file set atomically. > + * @param iosm file state machine data > + * @return 0 on success > + */ > +/*@-compdef@*/ > +static int iosmCommitLinks(/*@special@*/ /*@partial@*/ IOSM_t iosm) > + /*@uses iosm->path, iosm->nsuffix, iosm->ix, iosm->sb, > + iosm->li, iosm->links @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + const char * path = iosm->path; > + const char * nsuffix = iosm->nsuffix; > + int iterIndex = iosm->ix; > + struct stat * st = &iosm->sb; > + int rc = 0; > + int i; > + > + iosm->path = NULL; > + iosm->nsuffix = NULL; > + iosm->ix = -1; > + > + for (iosm->li = iosm->links; iosm->li; iosm->li = iosm->li- > >next) { > + if (iosm->li->sb.st_ino == st->st_ino && iosm->li->sb.st_dev == > st->st_dev) > + break; > + } > + > + for (i = 0; i < iosm->li->nlink; i++) { > + if (iosm->li->filex[i] < 0) continue; > + iosm->ix = iosm->li->filex[i]; > + rc = iosmNext(iosm, IOSM_MAP); > + if (!XFA_SKIPPING(iosm->action)) > + rc = iosmNext(iosm, IOSM_COMMIT); > + iosm->path = _free(iosm->path); > + iosm->li->filex[i] = -1; > + } > + > + iosm->ix = iterIndex; > + iosm->nsuffix = nsuffix; > + iosm->path = path; > + return rc; > +} > +/*@=compdef@*/ > + > +/** > + * Remove (if created) directories not explicitly included in > package. > + * @param iosm file state machine data > + * @return 0 on success > + */ > +static int iosmRmdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm) > + /*@uses iosm->path, iosm->dnlx, iosm->ldn, iosm->rdbuf, iosm- > >iter @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + const char * path = iosm->path; > + void * dnli = dnlInitIterator(iosm, 1); > + char * dn = iosm->rdbuf; > + int dc = dnlCount(dnli); > + int rc = 0; > + > + iosm->path = NULL; > + dn[0] = '\0'; > + /*@-observertrans -dependenttrans@*/ > + if (iosm->ldn != NULL && iosm->dnlx != NULL) > + while ((iosm->path = dnlNextIterator(dnli)) != NULL) { > + size_t dnlen = strlen(iosm->path); > + char * te; > + > + dc = dnlIndex(dnli); > + if (iosm->dnlx[dc] < 1 || iosm->dnlx[dc] >= dnlen) > + continue; > + > + /* Copy to avoid const on iosm->path. */ > + te = stpcpy(dn, iosm->path) - 1; > + iosm->path = dn; > + > + /* Remove generated directories. */ > + /*@-usereleased@*/ /* LCL: te used after release? */ > + do { > + if (*te == '/') { > + *te = '\0'; > +/*@-compdef@*/ > + rc = iosmNext(iosm, IOSM_RMDIR); > +/*@=compdef@*/ > + *te = '/'; > + } > + if (rc) > + /*@innerbreak@*/ break; > + te--; > + } while ((te - iosm->path) > iosm->dnlx[dc]); > + /*@=usereleased@*/ > + } > + dnli = dnlFreeIterator(dnli); > + /*@=observertrans =dependenttrans@*/ > + > + iosm->path = path; > + return rc; > +} > + > +/** > + * Create (if necessary) directories not explicitly included in > package. > + * @param iosm file state machine data > + * @return 0 on success > + */ > +static int iosmMkdirs(/*@special@*/ /*@partial@*/ IOSM_t iosm) > + /*@uses iosm->path, iosm->sb, iosm->osb, iosm->rdbuf, iosm->iter, > + iosm->ldn, iosm->ldnlen, iosm->ldnalloc @*/ > + /*@defines iosm->dnlx, iosm->ldn @*/ > + /*@globals h_errno, fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + struct stat * st = &iosm->sb; > + struct stat * ost = &iosm->osb; > + const char * path = iosm->path; > + mode_t st_mode = st->st_mode; > + void * dnli = dnlInitIterator(iosm, 0); > + char * dn = iosm->rdbuf; > + int dc = dnlCount(dnli); > + int rc = 0; > + int i; > +/*@-compdef@*/ > + rpmts ts = iosmGetTs(iosm); > +/*@=compdef@*/ > + rpmsx sx = NULL; > + > + /* XXX Set file contexts on non-packaged dirs iff selinux > enabled. */ > + if (ts != NULL && rpmtsSELinuxEnabled(ts) == 1 && > + !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) > + sx = rpmtsREContext(ts); > + > + iosm->path = NULL; > + > + dn[0] = '\0'; > + iosm->dnlx = (dc ? xcalloc(dc, sizeof(*iosm->dnlx)) : NULL); > + /*@-observertrans -dependenttrans@*/ > + if (iosm->dnlx != NULL) > + while ((iosm->path = dnlNextIterator(dnli)) != NULL) { > + size_t dnlen = strlen(iosm->path); > + char * te; > + > + dc = dnlIndex(dnli); > + if (dc < 0) continue; > + iosm->dnlx[dc] = dnlen; > + if (dnlen <= 1) > + continue; > + > + /*@-compdef -nullpass@*/ /* FIX: iosm->ldn not defined ??? */ > + if (dnlen <= iosm->ldnlen && !strcmp(iosm->path, iosm->ldn)) > + continue; > + /*@=compdef =nullpass@*/ > + > + /* Copy to avoid const on iosm->path. */ > + (void) stpcpy(dn, iosm->path); > + iosm->path = dn; > + > + /* Assume '/' directory exists, "mkdir -p" for others if non- > existent */ > + (void) urlPath(dn, (const char **)&te); > + for (i = 1, te++; *te != '\0'; te++, i++) { > + if (*te != '/') > + /*@innercontinue@*/ continue; > + > + *te = '\0'; > + > + /* Already validated? */ > + /*@-usedef -compdef -nullpass -nullderef@*/ > + if (i < iosm->ldnlen && > + (iosm->ldn[i] == '/' || iosm->ldn[i] == '\0') && > + !strncmp(iosm->path, iosm->ldn, i)) > + { > + *te = '/'; > + /* Move pre-existing path marker forward. */ > + iosm->dnlx[dc] = (te - dn); > + /*@innercontinue@*/ continue; > + } > + /*@=usedef =compdef =nullpass =nullderef@*/ > + > + /* Validate next component of path. */ > + rc = iosmUNSAFE(iosm, IOSM_LSTAT); > + *te = '/'; > + > + /* Directory already exists? */ > + if (rc == 0 && S_ISDIR(ost->st_mode)) { > + /* Move pre-existing path marker forward. */ > + iosm->dnlx[dc] = (te - dn); > + } else if (rc == CPIOERR_ENOENT) { > + rpmfi fi = iosmGetFi(iosm); > + *te = '\0'; > + st->st_mode = S_IFDIR | (fi->dperms & 07777); > + rc = iosmNext(iosm, IOSM_MKDIR); > + if (!rc) { > + /* XXX FIXME? only new dir will have context set. */ > + /* Get file security context from patterns. */ > + if (sx != NULL) { > + iosm->fcontext = rpmsxFContext(sx, iosm->path, st->st_mode); > + rc = iosmNext(iosm, IOSM_LSETFCON); > + } > + if (iosm->fcontext == NULL) > + rpmlog(RPMLOG_DEBUG, > + D_("%s directory created with perms %04o, no context.\n"), > + iosm->path, (unsigned)(st->st_mode & 07777)); > + else > + rpmlog(RPMLOG_DEBUG, > + D_("%s directory created with perms %04o, context %s.\n"), > + iosm->path, (unsigned)(st->st_mode & 07777), > + iosm->fcontext); > + iosm->fcontext = NULL; > + } > + *te = '/'; > + } > + if (rc) > + /*@innerbreak@*/ break; > + } > + if (rc) break; > + > + /* Save last validated path. */ > +/*@-compdef@*/ /* FIX: ldn/path annotations ? */ > + if (iosm->ldnalloc < (dnlen + 1)) { > + iosm->ldnalloc = dnlen + 100; > + iosm->ldn = xrealloc(iosm->ldn, iosm->ldnalloc); > + } > + if (iosm->ldn != NULL) { /* XXX can't happen */ > + strcpy(iosm->ldn, iosm->path); > + iosm->ldnlen = dnlen; > + } > +/*@=compdef@*/ > + } > + dnli = dnlFreeIterator(dnli); > + sx = rpmsxFree(sx); > + /*@=observertrans =dependenttrans@*/ > + > + iosm->path = path; > + st->st_mode = st_mode; /* XXX restore st->st_mode */ > +/*@-compdef@*/ /* FIX: ldn/path annotations ? */ > + return rc; > +/*@=compdef@*/ > +} > + > +#ifdef NOTYET > +/** > + * Check for file on disk. > + * @param iosm file state machine data > + * @return 0 on success > + */ > +static int iosmStat(/*@special@*/ /*@partial@*/ IOSM_t iosm) > + /*@globals fileSystem, internalState @*/ > + /*@modifies iosm, fileSystem, internalState @*/ > +{ > + int rc = 0; > + > + if (iosm->path != NULL) { > + int saveernno = errno; > + rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & CPIO_FOLLOW_SYMLINKS) > + ? IOSM_LSTAT : IOSM_STAT)); > + if (rc == CPIOERR_ENOENT) { > + errno = saveerrno; > + rc = 0; > + iosm->exists = 0; > + } else if (rc == 0) { > + iosm->exists = 1; > + } > + } else { > + /* Skip %ghost files on build. */ > + iosm->exists = 0; > + } > + return rc; > +} > +#endif > + > +#define IS_DEV_LOG(_x) \ > + ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \ > + !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \ > + ((_x)[sizeof("/dev/log")-1] == '\0' || \ > + (_x)[sizeof("/dev/log")-1] == ';')) > + > +/*@-compmempass@*/ > +int XiosmStage(IOSM_t iosm, iosmStage stage) > +{ > +#ifdef UNUSED > + iosmStage prevStage = iosm->stage; > + const char * const prev = iosmStageString(prevStage); > +#endif > + const char * const cur = iosmStageString(stage); > + struct stat * st = &iosm->sb; > + struct stat * ost = &iosm->osb; > + int saveerrno = errno; > + int rc = iosm->rc; > + size_t left; > + int i; > + > +#define _fafilter(_a) \ > + (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == > FA_COPYIN || (_a) == FA_COPYOUT) \ > + ? fileActionString(_a) : "") > + > + if (stage & IOSM_DEAD) { > + /* do nothing */ > + } else if (stage & IOSM_INTERNAL) { > + if (_iosm_debug && !(stage & IOSM_SYSCALL)) > + rpmlog(RPMLOG_DEBUG, " %8s %06o%3d (%4d,%4d)%12lu %s %s\n", > + cur, > + (unsigned)st->st_mode, (int)st->st_nlink, > + (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, > + (iosm->path ? iosm->path : ""), > + _fafilter(iosm->action)); > + } else { > + const char * apath = NULL; > + if (iosm->path) > + (void) urlPath(iosm->path, &apath); > + iosm->stage = stage; > + if (_iosm_debug || !(stage & IOSM_VERBOSE)) > + rpmlog(RPMLOG_DEBUG, "%-8s %06o%3d (%4d,%4d)%12lu %s %s\n", > + cur, > + (unsigned)st->st_mode, (int)st->st_nlink, > + (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size, > + (iosm->path ? apath + iosm->astriplen : ""), > + _fafilter(iosm->action)); > + } > +#undef _fafilter > + > + switch (stage) { > + case IOSM_UNKNOWN: > + break; > + case IOSM_PKGINSTALL: > + while (1) { > + /* Clean iosm, free'ing memory. Read next archive header. */ > + rc = iosmUNSAFE(iosm, IOSM_INIT); > + > + /* Exit on end-of-payload. */ > + if (rc == CPIOERR_HDR_TRAILER) { > + rc = 0; > + /*@loopbreak@*/ break; > + } > + > + /* Exit on error. */ > + if (rc) { > + iosm->postpone = 1; > + (void) iosmNext(iosm, IOSM_UNDO); > + /*@loopbreak@*/ break; > + } > + > + /* Extract file from archive. */ > + rc = iosmNext(iosm, IOSM_PROCESS); > + if (rc) { > + (void) iosmNext(iosm, IOSM_UNDO); > + /*@loopbreak@*/ break; > + } > + > + /* Notify on success. */ > + (void) iosmNext(iosm, IOSM_NOTIFY); > + > + rc = iosmNext(iosm, IOSM_FINI); > + if (rc) { > + /*@loopbreak@*/ break; > + } > + } > + break; > + case IOSM_PKGERASE: > + case IOSM_PKGCOMMIT: > + while (1) { > + /* Clean iosm, free'ing memory. */ > + rc = iosmUNSAFE(iosm, IOSM_INIT); > + > + /* Exit on end-of-payload. */ > + if (rc == CPIOERR_HDR_TRAILER) { > + rc = 0; > + /*@loopbreak@*/ break; > + } > + > + /* Rename/erase next item. */ > + if (iosmNext(iosm, IOSM_FINI)) > + /*@loopbreak@*/ break; > + } > + break; > + case IOSM_PKGBUILD: > + while (1) { > + > + rc = iosmUNSAFE(iosm, IOSM_INIT); > + > + /* Exit on end-of-payload. */ > + if (rc == CPIOERR_HDR_TRAILER) { > + rc = 0; > + /*@loopbreak@*/ break; > + } > + > + /* Exit on error. */ > + if (rc) { > + iosm->postpone = 1; > + (void) iosmNext(iosm, IOSM_UNDO); > + /*@loopbreak@*/ break; > + } > + > + /* Copy file into archive. */ > + rc = iosmNext(iosm, IOSM_PROCESS); > + if (rc) { > + (void) iosmNext(iosm, IOSM_UNDO); > + /*@loopbreak@*/ break; > + } > + > + /* Notify on success. */ > + (void) iosmNext(iosm, IOSM_NOTIFY); > + > + if (iosmNext(iosm, IOSM_FINI)) > + /*@loopbreak@*/ break; > + } > + > + /* Flush partial sets of hard linked files. */ > + if (!(iosm->mapFlags & CPIO_ALL_HARDLINKS)) { > + int nlink, j; > + while ((iosm->li = iosm->links) != NULL) { > + iosm->links = iosm->li->next; > + iosm->li->next = NULL; > + > + /* Re-calculate link count for archive header. */ > + for (j = -1, nlink = 0, i = 0; i < iosm->li->nlink; i++) { > + if (iosm->li->filex[i] < 0) > + /*@innercontinue@*/ continue; > + nlink++; > + if (j == -1) j = i; > + } > + /* XXX force the contents out as well. */ > + if (j != 0) { > + iosm->li->filex[0] = iosm->li->filex[j]; > + iosm->li->filex[j] = -1; > + } > + iosm->li->sb.st_nlink = nlink; > + > + iosm->sb = iosm->li->sb; /* structure assignment */ > + iosm->osb = iosm->sb; /* structure assignment */ > + > + if (!rc) rc = writeLinkedFile(iosm); > + > + iosm->li = freeHardLink(iosm->li); > + } > + } > + > + if (!rc) > + rc = iosmNext(iosm, IOSM_TRAILER); > + > + break; > + case IOSM_CREATE: > + { rpmts ts = iosmGetTs(iosm); > +#define _tsmask (RPMTRANS_FLAG_PKGCOMMIT | RPMTRANS_FLAG_COMMIT) > + iosm->commit = ((ts && (rpmtsFlags(ts) & _tsmask) && > + iosm->goal != IOSM_PKGCOMMIT) ? 0 : 1); > +#undef _tsmask > + } > + iosm->path = _free(iosm->path); > + iosm->lpath = _free(iosm->lpath); > + iosm->opath = _free(iosm->opath); > + iosm->dnlx = _free(iosm->dnlx); > + > + iosm->ldn = _free(iosm->ldn); > + iosm->ldnalloc = iosm->ldnlen = 0; > + > + iosm->rdsize = iosm->wrsize = 0; > + iosm->rdbuf = iosm->rdb = _free(iosm->rdb); > + iosm->wrbuf = iosm->wrb = _free(iosm->wrb); > + if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == > IOSM_PKGBUILD) { > + iosm->rdsize = 8 * BUFSIZ; > + iosm->rdbuf = iosm->rdb = xmalloc(iosm->rdsize); > + iosm->wrsize = 8 * BUFSIZ; > + iosm->wrbuf = iosm->wrb = xmalloc(iosm->wrsize); > + } > + > + iosm->mkdirsdone = 0; > + iosm->ix = -1; > + iosm->links = NULL; > + iosm->li = NULL; > + errno = 0; /* XXX get rid of EBADF */ > + > + /* Detect and create directories not explicitly in package. */ > + if (iosm->goal == IOSM_PKGINSTALL) { > +/*@-compdef@*/ > + rc = iosmNext(iosm, IOSM_MKDIRS); > +/*@=compdef@*/ > + if (!rc) iosm->mkdirsdone = 1; > + } > + > + break; > + case IOSM_INIT: > + iosm->path = _free(iosm->path); > + iosm->lpath = _free(iosm->lpath); > + iosm->postpone = 0; > + iosm->diskchecked = iosm->exists = 0; > + iosm->subdir = NULL; > + iosm->suffix = (iosm->sufbuf[0] != '\0' ? iosm->sufbuf : NULL); > + iosm->action = FA_UNKNOWN; > + iosm->osuffix = NULL; > + iosm->nsuffix = NULL; > + > + if (iosm->goal == IOSM_PKGINSTALL) { > + /* Read next header from payload, checking for end-of- > payload. */ > + rc = iosmUNSAFE(iosm, IOSM_NEXT); > + } > + if (rc) break; > + > + /* Identify mapping index. */ > + iosm->ix = ((iosm->goal == IOSM_PKGINSTALL) > + ? mapFind(iosm->iter, iosm->path) : mapNextIterator(iosm->iter)); > + > +{ rpmfi fi = iosmGetFi(iosm); > +if (!(fi->mapflags & CPIO_PAYLOAD_LIST)) { > + /* Detect end-of-loop and/or mapping error. */ > +if (!(fi->mapflags & CPIO_PAYLOAD_EXTRACT)) { > + if (iosm->ix < 0) { > + if (iosm->goal == IOSM_PKGINSTALL) { > +#if 0 > + rpmlog(RPMLOG_WARNING, > + _("archive file %s was not found in header file list\n"), > + iosm->path); > +#endif > + if (iosm->failedFile && *iosm->failedFile == NULL) > + *iosm->failedFile = xstrdup(iosm->path); > + rc = CPIOERR_UNMAPPED_FILE; > + } else { > + rc = CPIOERR_HDR_TRAILER; > + } > + break; > + } > +} > + > + /* On non-install, mode must be known so that dirs don't get > suffix. */ > + if (iosm->goal != IOSM_PKGINSTALL) { > + rpmfi fi = iosmGetFi(iosm); > + st->st_mode = fi->fmodes[iosm->ix]; > + } > +} > +} > + > + /* Generate file path. */ > + rc = iosmNext(iosm, IOSM_MAP); > + if (rc) break; > + > + /* Perform lstat/stat for disk file. */ > +#ifdef NOTYET > + rc = iosmStat(iosm); > +#else > + if (iosm->path != NULL && > + !(iosm->goal == IOSM_PKGINSTALL && S_ISREG(st->st_mode))) > + { > + rc = iosmUNSAFE(iosm, (!(iosm->mapFlags & > CPIO_FOLLOW_SYMLINKS) > + ? IOSM_LSTAT : IOSM_STAT)); > + if (rc == CPIOERR_ENOENT) { > + errno = saveerrno; > + rc = 0; > + iosm->exists = 0; > + } else if (rc == 0) { > + iosm->exists = 1; > + } > + } else { > + /* Skip %ghost files on build. */ > + iosm->exists = 0; > + } > +#endif > + iosm->diskchecked = 1; > + if (rc) break; > + > + /* On non-install, the disk file stat is what's remapped. */ > + if (iosm->goal != IOSM_PKGINSTALL) > + *st = *ost; /* structure assignment */ > + > + /* Remap file perms, owner, and group. */ > + rc = iosmMapAttrs(iosm); > + if (rc) break; > + > + iosm->postpone = XFA_SKIPPING(iosm->action); > + if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == > IOSM_PKGBUILD) { > + /*@-evalorder@*/ /* FIX: saveHardLink can modify iosm */ > + if (!(S_ISDIR(st->st_mode) || S_ISLNK(st->st_mode)) > + && (st->st_nlink > 1 || iosm->lpath != NULL)) > + iosm->postpone = saveHardLink(iosm); > + /*@=evalorder@*/ > + } > +{ rpmfi fi = iosmGetFi(iosm); > +if (fi->mapflags & CPIO_PAYLOAD_LIST) iosm->postpone = 1; > +} > + break; > + case IOSM_PRE: > + break; > + case IOSM_MAP: > + rc = iosmMapPath(iosm); > + break; > + case IOSM_MKDIRS: > + rc = iosmMkdirs(iosm); > + break; > + case IOSM_RMDIRS: > + if (iosm->dnlx) > + rc = iosmRmdirs(iosm); > + break; > + case IOSM_PROCESS: > + if (iosm->postpone) { > + if (iosm->goal == IOSM_PKGINSTALL) { > + /* XXX Skip over file body, archive headers already done. */ > + if (S_ISREG(st->st_mode)) > + rc = iosmNext(iosm, IOSM_EAT); > + } > + break; > + } > + > + if (iosm->goal == IOSM_PKGBUILD) { > + if (iosm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost > file. */ > + break; > + if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { > + struct hardLink_s * li, * prev; > + > +if (!(iosm->mapFlags & CPIO_ALL_HARDLINKS)) break; > + rc = writeLinkedFile(iosm); > + if (rc) break; /* W2DO? */ > + > + for (li = iosm->links, prev = NULL; li; prev = li, li = li->next) > + if (li == iosm->li) > + /*@loopbreak@*/ break; > + > + if (prev == NULL) > + iosm->links = iosm->li->next; > + else > + prev->next = iosm->li->next; > + iosm->li->next = NULL; > + iosm->li = freeHardLink(iosm->li); > + } else { > + rc = writeFile(iosm, 1); > + } > + break; > + } > + > + if (iosm->goal != IOSM_PKGINSTALL) > + break; > + > + if (S_ISREG(st->st_mode) && iosm->lpath != NULL) { > + const char * opath = iosm->opath; > + char * t = xmalloc(strlen(iosm->lpath+1) + strlen(iosm- > >suffix) + 1); > + (void) stpcpy(t, iosm->lpath+1); > + iosm->opath = t; > + /* XXX link(iosm->opath, iosm->path) */ > + rc = iosmNext(iosm, IOSM_LINK); > + if (iosm->failedFile && rc != 0 && *iosm->failedFile == > NULL) { > + *iosm->failedFile = xstrdup(iosm->path); > + } > + iosm->opath = _free(iosm->opath); > + iosm->opath = opath; > + break; /* XXX so that delayed hard links get skipped. */ > + } > + if (S_ISREG(st->st_mode)) { > + const char * path = iosm->path; > + if (iosm->osuffix) > + iosm->path = iosmFsPath(iosm, st, NULL, NULL); > + rc = iosmUNSAFE(iosm, IOSM_VERIFY); > + > + if (rc == 0 && iosm->osuffix) { > + const char * opath = iosm->opath; > + iosm->opath = iosm->path; > + iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix); > + rc = iosmNext(iosm, IOSM_RENAME); > + if (!rc) > + rpmlog(RPMLOG_WARNING, > + _("%s saved as %s\n"), > + (iosm->opath ? iosm->opath : ""), > + (iosm->path ? iosm->path : "")); > + iosm->path = _free(iosm->path); > + iosm->opath = opath; > + } > + > + /*@-dependenttrans@*/ > + iosm->path = path; > + /*@=dependenttrans@*/ > + if (!(rc == CPIOERR_ENOENT)) return rc; > + rc = extractRegular(iosm); > + } else if (S_ISDIR(st->st_mode)) { > + mode_t st_mode = st->st_mode; > + rc = iosmUNSAFE(iosm, IOSM_VERIFY); > + if (rc == CPIOERR_ENOENT) { > + st->st_mode &= ~07777; /* XXX abuse st->st_mode */ > + st->st_mode |= 00700; > + rc = iosmNext(iosm, IOSM_MKDIR); > + st->st_mode = st_mode; /* XXX restore st->st_mode */ > + } > + } else if (S_ISLNK(st->st_mode)) { > +assert(iosm->lpath != NULL); > + /*@=dependenttrans@*/ > + rc = iosmUNSAFE(iosm, IOSM_VERIFY); > + if (rc == CPIOERR_ENOENT) > + rc = iosmNext(iosm, IOSM_SYMLINK); > + } 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 = iosmUNSAFE(iosm, IOSM_VERIFY); > + if (rc == CPIOERR_ENOENT) { > + st->st_mode = 0000; /* XXX abuse st->st_mode */ > + rc = iosmNext(iosm, IOSM_MKFIFO); > + st->st_mode = st_mode; /* XXX restore st->st_mode */ > + } > + } else if (S_ISCHR(st->st_mode) || > + S_ISBLK(st->st_mode) || > + /*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/) > + { > + rc = iosmUNSAFE(iosm, IOSM_VERIFY); > + if (rc == CPIOERR_ENOENT) > + rc = iosmNext(iosm, IOSM_MKNOD); > + } else { > + /* XXX Repackaged payloads may be missing files. */ > + if (iosm->repackaged) > + break; > + > + /* XXX Special case /dev/log, which shouldn't be packaged > anyways */ > + if (!IS_DEV_LOG(iosm->path)) > + rc = CPIOERR_UNKNOWN_FILETYPE; > + } > + if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { > + iosm->li->createdPath = iosm->li->linkIndex; > + rc = iosmMakeLinks(iosm); > + } > + break; > + case IOSM_POST: > + break; > + case IOSM_MKLINKS: > + rc = iosmMakeLinks(iosm); > + break; > + case IOSM_NOTIFY: /* XXX move from iosm to psm -> tsm */ > + if (iosm->goal == IOSM_PKGINSTALL || iosm->goal == > IOSM_PKGBUILD) { > + rpmts ts = iosmGetTs(iosm); > + rpmfi fi = iosmGetFi(iosm); > + void * ptr; > + uint64_t archivePos = fdGetCpioPos(iosm->cfd); > + if (archivePos > fi->archivePos) { > + fi->archivePos = archivePos; > + ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, > + fi->archivePos, fi->archiveSize); > + } > + } > + break; > + case IOSM_UNDO: > + if (iosm->postpone) > + break; > + if (iosm->goal == IOSM_PKGINSTALL) { > + /* XXX only erase if temp fn w suffix is in use */ > + if (iosm->sufbuf[0] != '\0') > + (void) iosmNext(iosm, > + (S_ISDIR(st->st_mode) ? IOSM_RMDIR : IOSM_UNLINK)); > + > +#ifdef NOTYET /* XXX remove only dirs just created, not all. */ > + if (iosm->dnlx) > + (void) iosmNext(iosm, IOSM_RMDIRS); > +#endif > + errno = saveerrno; > + } > + if (iosm->failedFile && *iosm->failedFile == NULL) > + *iosm->failedFile = xstrdup(iosm->path); > + break; > + case IOSM_FINI: > + if (!iosm->postpone && iosm->commit) { > + if (iosm->goal == IOSM_PKGINSTALL) > + rc = ((!S_ISDIR(st->st_mode) && st->st_nlink > 1) > + ? iosmCommitLinks(iosm) : iosmNext(iosm, IOSM_COMMIT)); > + if (iosm->goal == IOSM_PKGCOMMIT) > + rc = iosmNext(iosm, IOSM_COMMIT); > + if (iosm->goal == IOSM_PKGERASE) > + rc = iosmNext(iosm, IOSM_COMMIT); > + } > + iosm->path = _free(iosm->path); > + iosm->lpath = _free(iosm->lpath); > + iosm->opath = _free(iosm->opath); > + memset(st, 0, sizeof(*st)); > + memset(ost, 0, sizeof(*ost)); > + break; > + case IOSM_COMMIT: > + /* Rename pre-existing modified or unmanaged file. */ > + if (iosm->osuffix && iosm->diskchecked && > + (iosm->exists || (iosm->goal == IOSM_PKGINSTALL && S_ISREG(st- > >st_mode)))) > + { > + const char * opath = iosm->opath; > + const char * path = iosm->path; > + iosm->opath = iosmFsPath(iosm, st, NULL, NULL); > + iosm->path = iosmFsPath(iosm, st, NULL, iosm->osuffix); > + rc = iosmNext(iosm, IOSM_RENAME); > + if (!rc) { > + rpmlog(RPMLOG_WARNING, _("%s saved as %s\n"), > + (iosm->opath ? iosm->opath : ""), > + (iosm->path ? iosm->path : "")); > + } > + iosm->path = _free(iosm->path); > + iosm->path = path; > + iosm->opath = _free(iosm->opath); > + iosm->opath = opath; > + } > + > + /* Remove erased files. */ > + if (iosm->goal == IOSM_PKGERASE) { > + if (iosm->action == FA_ERASE) { > + rpmfi fi = iosmGetFi(iosm); > + if (S_ISDIR(st->st_mode)) { > + rc = iosmNext(iosm, IOSM_RMDIR); > + if (!rc) break; > + switch (rc) { > + case CPIOERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel > hack */ > + case CPIOERR_ENOTEMPTY: > + /* XXX make sure that build side permits %missingok on > directories. */ > + if (iosm->fflags & RPMFILE_MISSINGOK) > + /*@innerbreak@*/ break; > + > + /* XXX common error message. */ > + rpmlog( > + (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), > + _("%s rmdir of %s failed: Directory not empty\n"), > + rpmfiTypeString(fi), iosm->path); > + /*@innerbreak@*/ break; > + default: > + rpmlog( > + (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), > + _("%s rmdir of %s failed: %s\n"), > + rpmfiTypeString(fi), iosm->path, strerror(errno)); > + /*@innerbreak@*/ break; > + } > + } else { > + rc = iosmNext(iosm, IOSM_UNLINK); > + if (!rc) break; > + switch (rc) { > + case CPIOERR_ENOENT: > + if (iosm->fflags & RPMFILE_MISSINGOK) > + /*@innerbreak@*/ break; > + /*@fallthrough@*/ > + default: > + rpmlog( > + (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), > + _(" %s: unlink of %s failed: %s\n"), > + rpmfiTypeString(fi), iosm->path, strerror(errno)); > + /*@innerbreak@*/ break; > + } > + } > + } > + /* XXX Failure to remove is not (yet) cause for failure. */ > + if (!strict_erasures) rc = 0; > + break; > + } > + > + /* XXX Special case /dev/log, which shouldn't be packaged > anyways */ > +{ rpmfi fi = iosmGetFi(iosm); > +if (!(fi->mapflags & CPIO_PAYLOAD_EXTRACT)) { > + if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(iosm->path)) { > + /* Rename temporary to final file name. */ > + if (!S_ISDIR(st->st_mode) && > + (iosm->subdir || iosm->suffix || iosm->nsuffix)) > + { > + iosm->opath = iosm->path; > + iosm->path = iosmFsPath(iosm, st, NULL, iosm->nsuffix); > + rc = iosmNext(iosm, IOSM_RENAME); > + if (rc) > + (void) Unlink(iosm->opath); > + else if (iosm->nsuffix) { > + const char * opath = iosmFsPath(iosm, st, NULL, NULL); > + rpmlog(RPMLOG_WARNING, _("%s created as %s\n"), > + (opath ? opath : ""), > + (iosm->path ? iosm->path : "")); > + opath = _free(opath); > + } > + iosm->opath = _free(iosm->opath); > + } > + /* > + * Set file security context (if not disabled). > + */ > + if (!rc && !getuid()) { > + rc = iosmMapFContext(iosm); > + if (!rc) > + rc = iosmNext(iosm, IOSM_LSETFCON); > + iosm->fcontext = NULL; > + } > + if (S_ISLNK(st->st_mode)) { > + if (!rc && !getuid()) > + rc = iosmNext(iosm, IOSM_LCHOWN); > + } else { > + if (!rc && !getuid()) > + rc = iosmNext(iosm, IOSM_CHOWN); > + if (!rc) > + rc = iosmNext(iosm, IOSM_CHMOD); > + if (!rc) { > + time_t mtime = st->st_mtime; > + rpmfi fi = iosmGetFi(iosm); > + if (fi->fmtimes) > + st->st_mtime = fi->fmtimes[iosm->ix]; > + rc = iosmNext(iosm, IOSM_UTIME); > + st->st_mtime = mtime; > + } > + } > + } > +} > +} > + > + /* Notify on success. */ > + if (!rc) rc = iosmNext(iosm, IOSM_NOTIFY); > + else if (iosm->failedFile && *iosm->failedFile == NULL) { > + *iosm->failedFile = iosm->path; > + iosm->path = NULL; > + } > + break; > + case IOSM_DESTROY: > + iosm->path = _free(iosm->path); > + > + /* Check for hard links missing from payload. */ > + while ((iosm->li = iosm->links) != NULL) { > + iosm->links = iosm->li->next; > + iosm->li->next = NULL; > + if (iosm->goal == IOSM_PKGINSTALL && > + iosm->commit && iosm->li->linksLeft) > + { > + for (i = 0 ; i < iosm->li->linksLeft; i++) { > + if (iosm->li->filex[i] < 0) > + /*@innercontinue@*/ continue; > + rc = CPIOERR_MISSING_HARDLINK; > + if (iosm->failedFile && *iosm->failedFile == NULL) { > + iosm->ix = iosm->li->filex[i]; > + if (!iosmNext(iosm, IOSM_MAP)) { > + *iosm->failedFile = iosm->path; > + iosm->path = NULL; > + } > + } > + /*@loopbreak@*/ break; > + } > + } > + if (iosm->goal == IOSM_PKGBUILD && > + (iosm->mapFlags & CPIO_ALL_HARDLINKS)) > + { > + rc = CPIOERR_MISSING_HARDLINK; > + } > + iosm->li = freeHardLink(iosm->li); > + } > + iosm->ldn = _free(iosm->ldn); > + iosm->ldnalloc = iosm->ldnlen = 0; > + iosm->rdbuf = iosm->rdb = _free(iosm->rdb); > + iosm->wrbuf = iosm->wrb = _free(iosm->wrb); > + break; > + case IOSM_VERIFY: > + if (iosm->diskchecked && !iosm->exists) { > + rc = CPIOERR_ENOENT; > + break; > + } > + if (S_ISREG(st->st_mode)) { > + char * path = alloca(strlen(iosm->path) + sizeof("- > RPMDELETE")); > + (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE"); > + /* > + * XXX HP-UX (and other os'es) don't permit unlink on busy > + * XXX files. > + */ > + iosm->opath = iosm->path; > + iosm->path = path; > + rc = iosmNext(iosm, IOSM_RENAME); > + if (!rc) > + (void) iosmNext(iosm, IOSM_UNLINK); > + else > + rc = CPIOERR_UNLINK_FAILED; > + iosm->path = iosm->opath; > + iosm->opath = NULL; > + return (rc ? rc : CPIOERR_ENOENT); /* 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 = iosmUNSAFE(iosm, IOSM_STAT); > + if (rc == CPIOERR_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 iosm->rdbuf, len in iosm->rdnb. */ > + rc = iosmUNSAFE(iosm, IOSM_READLINK); > + errno = saveerrno; > + if (rc) break; > + if (!strcmp(iosm->lpath, iosm->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 (iosm->stage == IOSM_PROCESS) rc = iosmNext(iosm, IOSM_UNLINK); > + if (rc == 0) rc = CPIOERR_ENOENT; > + return (rc ? rc : CPIOERR_ENOENT); /* XXX HACK */ > + /*@notreached@*/ break; > + > + case IOSM_UNLINK: > + /* XXX Remove setuid/setgid bits on possibly hard linked files. */ > + if (iosm->mapFlags & CPIO_SBIT_CHECK) { > + struct stat stb; > + if (Lstat(iosm->path, &stb) == 0 && S_ISREG(stb.st_mode) && > (stb.st_mode & 06000) != 0) { > + /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */ > + (void)Chmod(iosm->path, stb.st_mode & 0777); > + } > + } > + rc = Unlink(iosm->path); > + if (_iosm_debug && (stage & IOSM_SYSCALL)) > + rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur, > + iosm->path, (rc < 0 ? strerror(errno) : "")); > + if (rc < 0) > + rc = (errno == ENOENT ? CPIOERR_ENOENT : > CPIOERR_UNLINK_FAILED); > + break; > + case IOSM_RENAME: > + /* XXX Remove setuid/setgid bits on possibly hard linked files. */ > + if (iosm->mapFlags & CPIO_SBIT_CHECK) { > + struct stat stb; > + if (Lstat(iosm->path, &stb) == 0 && S_ISREG(stb.st_mode) && > (stb.st_mode & 06000) != 0) { > + /* XXX rc = iosmNext(iosm, IOSM_CHMOD); instead */ > + (void)Chmod(iosm->path, stb.st_mode & 0777); > + } > + } > + rc = Rename(iosm->opath, iosm->path); > + /* XXX Repackaged payloads may be missing files. */ > + if (iosm->repackaged) > + rc = 0; > +#if defined(ETXTBSY) > + if (rc && errno == ETXTBSY) { > + char * path = alloca(strlen(iosm->path) + sizeof("- > RPMDELETE")); > + (void) stpcpy( stpcpy(path, iosm->path), "-RPMDELETE"); > + /* > + * XXX HP-UX (and other os'es) don't permit rename to busy > + * XXX files. > + */ > + rc = Rename(iosm->path, path); > + if (!rc) rc = Rename(iosm->opath, iosm->path); > + } > +#endif > + if (_iosm_debug && (stage & IOSM_SYSCALL)) > + rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur, > + iosm->opath, iosm->path, (rc < 0 ? strerror(errno) : "")); > + if (rc < 0) rc = CPIOERR_RENAME_FAILED; > + break; > + case IOSM_MKDIR: > + rc = Mkdir(iosm->path, (st->st_mode & 07777)); > + if (_iosm_debug && (stage & IOSM_SYSCALL)) > + rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", cur, > + iosm->path, (unsigned)(st->st_mode & 07777), > + (rc < 0 ? strerror(errno) : "")); > + if (rc < 0) rc = CPIOERR_MKDIR_FAILED; > + break; > + case IOSM_RMDIR: > + rc = Rmdir(iosm->path); > + if (_iosm_debug && (stage & IOSM_SYSCALL)) > + rpmlog(RPMLOG_DEBUG, " %8s (%s) %s\n", cur, > + iosm->path, (rc < 0 ? strerror(errno) : "")); > + if (rc < 0) > + switch (errno) { > + case ENOENT: rc = CPIOERR_ENOENT; / > *@switchbreak@*/ break; > + case ENOTEMPTY: rc = CPIOERR_ENOTEMPTY; / > *@switchbreak@*/ break; > + default: rc = CPIOERR_RMDIR_FAILED; / > *@switchbreak@*/ break; > + } > + break; > + case IOSM_LSETFCON: > + { const char * iosmpath = NULL; > + if (iosm->fcontext == NULL || *iosm->fcontext == '\0' > + || !strcmp(iosm->fcontext, "<<none>>")) > + break; > + (void) urlPath(iosm->path, &iosmpath); /* XXX iosm->path */ > + rc = lsetfilecon(iosmpath, (security_context_t)iosm->fcontext); > + if (_iosm_debug && (stage & IOSM_SYSCALL)) > + rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", cur, > + iosm->path, iosm->fcontext, > + (rc < 0 ? strerror(errno) : "")); > + if (rc < 0) rc = (errno == EOPNOTSUPP ? 0 : > CPIOERR_LSETFCON_FAILED); > + } break; >