diff --git a/lib/fsm.c b/lib/fsm.c index 1ebf20f3f..c7a341ce6 100644 --- a/lib/fsm.c +++ b/lib/fsm.c @@ -1193,7 +1193,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, FD_t cfd, rpmpsm psm, char ** failedFile) { rpmfs fs = rpmteGetFileStates(te); - rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD); + rpmfi fi = rpmfiNewArchiveReader(cfd, files); FSM_t fsm = fsmNew(FSM_PKGINSTALL, fs, fi, failedFile); struct stat * st = &fsm->sb; int saveerrno = errno; @@ -1204,8 +1204,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, FD_t cfd, int numHardlinks; char * found = xcalloc(fc, sizeof(*found)); - rc = rpmfiAttachArchive(fi, cfd, O_RDONLY); - if (!rpmteIsSource(te)) fsm->mapFlags |= CPIO_SBIT_CHECK; @@ -1223,16 +1221,15 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, FD_t cfd, fsmReset(fsm); /* Read next payload header. */ - rc = rpmfiArchiveNext(fi); + rc = rpmfiNext(fi); - /* Detect and exit on end-of-payload. */ - if (rc == CPIOERR_HDR_TRAILER) { - rc = 0; + if (rc < 0) { + if (rc == CPIOERR_HDR_TRAILER) + rc = 0; break; } - found[rpmfiFX(fi)] = 1; - if (rc) break; + found[rpmfiFX(fi)] = 1; rc = fsmInit(fsm); /* Sets fsm->postpone for skipped files */ diff --git a/lib/rpmfi.c b/lib/rpmfi.c index e92f6d8ec..5fe2baacd 100644 --- a/lib/rpmfi.c +++ b/lib/rpmfi.c @@ -1434,6 +1434,8 @@ err: return NULL; } +static int iterReadArchiveNext(rpmfi fi); + static rpmfi initIter(rpmfiles files, int itype, int link) { rpmfi fi = NULL; @@ -1447,6 +1449,9 @@ static rpmfi initIter(rpmfiles files, int itype, int link) fi->i = rpmfilesFC(fi->files); fi->next = iterBack; break; + case RPMFI_ITER_READ_ARCHIVE: + fi->next = iterReadArchiveNext; + break; case RPMFI_ITER_FWD: default: fi->i = -1; @@ -1629,6 +1634,21 @@ int rpmfiAttachArchive(rpmfi fi, FD_t fd, char mode) return (fi->archive == NULL); } +rpmfi rpmfiNewArchiveReader(FD_t fd, rpmfiles files) +{ + rpmcpio_t archive = rpmcpioOpen(fd, O_RDONLY); + rpmfi fi = NULL; + if (archive) { + fi = rpmfilesIter(files, RPMFI_ITER_READ_ARCHIVE); + } + if (fi) { + fi->archive = archive; + } else { + rpmcpioFree(archive); + } + return fi; +} + int rpmfiArchiveClose(rpmfi fi) { if (fi == NULL) @@ -1742,7 +1762,7 @@ int rpmfiArchiveWriteFile(rpmfi fi, FD_t fd) return rc; } -int rpmfiArchiveNext(rpmfi fi) +static int iterReadArchiveNext(rpmfi fi) { int rc; int fx = -1; @@ -1766,10 +1786,7 @@ int rpmfiArchiveNext(rpmfi fi) fx = rpmfiFindOFN(fi, path); } free(path); - rpmfiSetFX(fi, fx); } else { - rpmfiSetFX(fi, fx); - uint32_t numlinks; const int * links; rpm_loff_t fsize = 0; @@ -1791,7 +1808,7 @@ int rpmfiArchiveNext(rpmfi fi) if (fx < 0) { return CPIOERR_UNMAPPED_FILE; } - return 0; + return fx; } size_t rpmfiArchiveRead(rpmfi fi, void * buf, size_t size) diff --git a/lib/rpmfi_internal.h b/lib/rpmfi_internal.h index e22561798..c4fbff358 100644 --- a/lib/rpmfi_internal.h +++ b/lib/rpmfi_internal.h @@ -12,6 +12,7 @@ typedef enum rpmFileIter_e { RPMFI_ITER_FWD = 0, RPMFI_ITER_BACK = 1, + RPMFI_ITER_READ_ARCHIVE = 2, } rpmFileIter; #ifdef __cplusplus @@ -196,6 +197,18 @@ int rpmfilesDigestAlgo(rpmfiles fi); rpm_color_t rpmfilesColor(rpmfiles files); +/** \ingroup payload + * Get new file iterator for looping over the archive content. + * Returned rpmfi visites files in the order they are read from the payload. + * Content of the regular files can be retrieved with rpmfiArchiveRead() or + * rpmfiArchiveReadToFile() when they are visited with rpmfiNext(). + * rpmfiSetFX() is not supported for this type of iterator. + * @param fd file + * @param fi file info + * @return new rpmfi + */ +rpmfi rpmfiNewArchiveReader(FD_t fd, rpmfiles files); + /** \ingroup payload * Add payload archive to the file info * @param fi file info @@ -243,15 +256,6 @@ size_t rpmfiArchiveWrite(rpmfi fi, const void * buf, size_t size); */ int rpmfiArchiveWriteFile(rpmfi fi, FD_t fd); -/** \ingroup payload - * Read next archive header from archive and move fi to the - * file found in the archive. Sets rpmfiFX! - * @param fi file info - * @return > 0 on error - */ -int rpmfiArchiveNext(rpmfi fi); - - /** \ingroup payload * Read content from current file in archive * @param fi file info