From 6492aa800f2bb40c4602f4b50e013797a1fb8549 Mon Sep 17 00:00:00 2001 From: Florian Festi Date: Thu, 22 Mar 2012 13:58:02 +0100 Subject: [PATCH] Untangle lib/fsm.c and lib/cpio.c Create cpio_t data type that holds the underlaying FD_t instance Move padding and position handling and trailer generation into cpio.c Use only one buffer in the fsm (merging the read and write buffer) Replace the FSM_EAT, FSM_POS, FSM_PAD, FSM_DREAD, FSM_DWRITE states with cpio functions Prepend "rpm" to the cpio function names --- lib/cpio.c | 255 +++++++++++++++++++++++++++++++++++++++++++++++++------------ lib/cpio.h | 30 +++++--- lib/fsm.c | 198 +++++++++++++++++------------------------------ lib/fsm.h | 15 +--- lib/psm.c | 6 +- 5 files changed, 302 insertions(+), 202 deletions(-) diff --git a/lib/cpio.c b/lib/cpio.c index bfb2fbb..38321a1 100644 --- a/lib/cpio.c +++ b/lib/cpio.c @@ -27,6 +27,32 @@ #include "debug.h" +struct rpmcpio_s { + FD_t fd; + char mode; + off_t offset; + off_t fileend; +}; + +rpmcpio_t rpmcpioOpen(FD_t fd, char mode) +{ + if ((mode & O_ACCMODE) != O_RDONLY && + (mode & O_ACCMODE) != O_WRONLY) + return NULL; + + rpmcpio_t cpio = xcalloc(1, sizeof(*cpio)); + cpio->fd = fd; + cpio->mode = mode; + cpio->offset = 0; + return cpio; +} + +off_t rpmcpioTell(rpmcpio_t cpio) +{ + return cpio->offset; +} + + /** * Convert string to unsigned integer (with buffer size check). * @param str input string @@ -52,6 +78,39 @@ static unsigned long strntoul(const char *str,char **endptr, int base, size_t nu return ret; } + +static int rpmcpioWritePad(rpmcpio_t cpio, ssize_t modulo) +{ + char buf[modulo]; + ssize_t left, writen; + memset(buf, 0, modulo); + left = (modulo - ((cpio->offset) % modulo)) % modulo; + if (left <= 0) + return 0; + writen = Fwrite(&buf, left, 1, cpio->fd); + if (writen != left) { + return CPIOERR_WRITE_FAILED; + } + cpio->offset += writen; + return 0; +} + +static int rpmcpioReadPad(rpmcpio_t cpio) +{ + ssize_t modulo = 4; + char buf[4]; + ssize_t left, read; + left = (modulo - (cpio->offset % modulo)) % modulo; + if (left <= 0) + return 0; + read = Fread(&buf, left, 1, cpio->fd); + cpio->offset += read; + if (read != left) { + return CPIOERR_READ_FAILED; + } + return 0; +} + #define GET_NUM_FIELD(phys, log) \ \ log = strntoul(phys, &end, 16, sizeof(phys)); \ @@ -62,40 +121,67 @@ static unsigned long strntoul(const char *str,char **endptr, int base, size_t nu \ memcpy(phys, space, 8) \ -int cpioTrailerWrite(FSM_t fsm) +static int rpmcpioTrailerWrite(rpmcpio_t cpio) { - struct cpioCrcPhysicalHeader * hdr = - (struct cpioCrcPhysicalHeader *)fsm->rdbuf; + struct cpioCrcPhysicalHeader hdr; int rc; + size_t writen; - 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)); + if (cpio->fileend != cpio->offset) { + return CPIOERR_WRITE_FAILED; + } - /* XXX DWRITE uses rdnb for I/O length. */ - fsm->rdnb = PHYS_HDR_SIZE + sizeof(CPIO_TRAILER); - rc = fsmNext(fsm, FSM_DWRITE); + rc = rpmcpioWritePad(cpio, 4); + if (rc) + return 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); + writen = Fwrite(&hdr, PHYS_HDR_SIZE, 1, cpio->fd); + cpio->offset += writen; + if (writen != PHYS_HDR_SIZE) { + return CPIOERR_WRITE_FAILED; + } + writen = Fwrite(&CPIO_TRAILER, sizeof(CPIO_TRAILER), 1, cpio->fd); + cpio->offset += writen; + if (writen != sizeof(CPIO_TRAILER)) { + return CPIOERR_WRITE_FAILED; + } /* - * GNU cpio pads to 512 bytes here, but we don't. This may matter for - * tape device(s) and/or concatenated cpio archives. + * XXX GNU cpio pads to 512 bytes. This may matter for + * tape device(s) and/or concatenated cpio archives. */ - if (!rc) - rc = fsmNext(fsm, FSM_PAD); + + rc = rpmcpioWritePad(cpio, 4); return rc; } -int cpioHeaderWrite(FSM_t fsm, struct stat * st) +int rpmcpioHeaderWrite(rpmcpio_t cpio, char * path, struct stat * st) { - struct cpioCrcPhysicalHeader * hdr = (struct cpioCrcPhysicalHeader *)fsm->rdbuf; + struct cpioCrcPhysicalHeader hdr_s; + struct cpioCrcPhysicalHeader * hdr = &hdr_s; char field[64]; - size_t len; + size_t len, writen; dev_t dev; int rc = 0; + if ((cpio->mode & O_ACCMODE) != O_WRONLY) { + return CPIOERR_WRITE_FAILED; + } + + if (cpio->fileend != cpio->offset) { + return CPIOERR_WRITE_FAILED; + } + + rc = rpmcpioWritePad(cpio, 4); + if (rc) { + return rc; + } + 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); @@ -110,40 +196,88 @@ int cpioHeaderWrite(FSM_t fsm, struct stat * st) dev = major(st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field); dev = minor(st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field); - len = strlen(fsm->path) + 1; SET_NUM_FIELD(hdr->namesize, len, field); + len = strlen(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); + + writen = Fwrite(hdr, PHYS_HDR_SIZE, 1, cpio->fd); + cpio->offset += writen; + if (writen != PHYS_HDR_SIZE) { + return CPIOERR_WRITE_FAILED; + } + + writen = Fwrite(path, len, 1, cpio->fd); + cpio->offset += writen; + if (writen != len) { + return CPIOERR_WRITE_FAILED; + } + + rc = rpmcpioWritePad(cpio, 4); + + cpio->fileend = cpio->offset + st->st_size; + return rc; } -int cpioHeaderRead(FSM_t fsm, struct stat * st) +ssize_t rpmcpioWrite(rpmcpio_t cpio, void * buf, size_t size) +{ + size_t writen, left; + + if ((cpio->mode & O_ACCMODE) != O_WRONLY) { + return CPIOERR_WRITE_FAILED; + } + + // Do not write beyond file length + left = cpio->fileend - cpio->offset; + size = size > left ? left : size; + writen = Fwrite(buf, size, 1, cpio->fd); + cpio->offset += writen; + return writen; +} + + +int rpmcpioHeaderRead(rpmcpio_t cpio, char ** path, struct stat * st) { struct cpioCrcPhysicalHeader hdr; int nameSize; char * end; unsigned int major, minor; int rc = 0; - char * path = NULL; + ssize_t read; - fsm->wrlen = PHYS_HDR_SIZE; - rc = fsmNext(fsm, FSM_DREAD); - if (!rc && fsm->rdnb != fsm->wrlen) - rc = CPIOERR_READ_FAILED; + if ((cpio->mode & O_ACCMODE) != O_RDONLY) { + return CPIOERR_READ_FAILED; + } + + /* Move to next file */ + if (cpio->fileend != cpio->offset) { + //if (Fseek(cpio->fd, cpio->fileend-cpio->offset, SEEK_CUR)) + { + /* XXX try using Fseek() - which is currently broken */ + char buf[8*BUFSIZ]; + while (cpio->fileend != cpio->offset) { + read = cpio->fileend - cpio->offset > 8*BUFSIZ ? 8*BUFSIZ : cpio->fileend - cpio->offset; + if (rpmcpioRead(cpio, &buf, read) != read) { + return CPIOERR_READ_FAILED; + } + } + //} else { /* seek worked */ + //cpio->offset = cpio->fileend; + } + } + rc = rpmcpioReadPad(cpio); if (rc) return rc; - memcpy(&hdr, fsm->wrbuf, fsm->rdnb); + + read = Fread(&hdr, PHYS_HDR_SIZE, 1, cpio->fd); + cpio->offset += read; + if (read != PHYS_HDR_SIZE) + return CPIOERR_READ_FAILED; if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) && - strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_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); @@ -161,24 +295,47 @@ int cpioHeaderRead(FSM_t fsm, struct stat * st) st->st_rdev = makedev(major, minor); GET_NUM_FIELD(hdr.namesize, nameSize); - if (nameSize >= fsm->wrsize) - return CPIOERR_BAD_HEADER; - fsm->wrlen = nameSize; - rc = fsmNext(fsm, FSM_DREAD); - if (!rc && fsm->rdnb != fsm->wrlen) - rc = CPIOERR_BAD_HEADER; + *path = xmalloc(nameSize + 1); + read = Fread(*path, nameSize, 1, cpio->fd); + (*path)[nameSize] = '\0'; + cpio->offset += read; + if (read != nameSize ) { + return CPIOERR_BAD_HEADER; + } + + rc = rpmcpioReadPad(cpio); + cpio->fileend = cpio->offset + st->st_size; - if (!rc) { - path = xmalloc(nameSize + 1); - memcpy(path, fsm->wrbuf, fsm->rdnb); - path[nameSize] = '\0'; + return rc; +} + +ssize_t rpmcpioRead(rpmcpio_t cpio, void * buf, size_t size) +{ + size_t read, left; + + if ((cpio->mode & O_ACCMODE) != O_RDONLY) { + return CPIOERR_READ_FAILED; + } + + left = cpio->fileend - cpio->offset; + size = size > left ? left : size; + read = Fread(buf, size, 1, cpio->fd); + cpio->offset += read; + return read; +} + +int rpmcpioClose(rpmcpio_t cpio) +{ + int rc = 0; + if ((cpio->mode & O_ACCMODE) == O_WRONLY) { + rc = rpmcpioTrailerWrite(cpio); } - fsm->path = path; + _free(cpio); return rc; } -const char * cpioStrerror(int rc) +const char * rpmcpioStrerror(int rc) { static char msg[256]; const char *s; diff --git a/lib/cpio.h b/lib/cpio.h index 9453184..206f4b8 100644 --- a/lib/cpio.h +++ b/lib/cpio.h @@ -12,8 +12,6 @@ * */ -#include "lib/fsm.h" - /** \ingroup payload * @note CPIO_CHECK_ERRNO bit is set only if errno is valid. */ @@ -88,17 +86,23 @@ struct cpioCrcPhysicalHeader { #define PHYS_HDR_SIZE 110 /* Don't depend on sizeof(struct) */ +typedef struct rpmcpio_s * rpmcpio_t; + #ifdef __cplusplus extern "C" { #endif /** - * Write cpio trailer. - * @retval fsm file path and stat info - * @return 0 on success - */ -RPM_GNUC_INTERNAL -int cpioTrailerWrite(FSM_t fsm); + * Create CPIO file object + * @param fd file + * @param mode XXX + * @return CPIO object + **/ +rpmcpio_t rpmcpioOpen(FD_t fd, char mode); + +int rpmcpioClose(rpmcpio_t cpio); + +off_t rpmcpioTell(rpmcpio_t cpio); /** * Write cpio header. @@ -107,7 +111,9 @@ int cpioTrailerWrite(FSM_t fsm); * @return 0 on success */ RPM_GNUC_INTERNAL -int cpioHeaderWrite(FSM_t fsm, struct stat * st); +int rpmcpioHeaderWrite(rpmcpio_t cpio, char * path, struct stat * st); + +ssize_t rpmcpioWrite(rpmcpio_t cpio, void * buf, size_t size); /** * Read cpio header. @@ -116,7 +122,9 @@ int cpioHeaderWrite(FSM_t fsm, struct stat * st); * @return 0 on success */ RPM_GNUC_INTERNAL -int cpioHeaderRead(FSM_t fsm, struct stat * st); +int rpmcpioHeaderRead(rpmcpio_t cpio, char ** path, struct stat * st); + +ssize_t rpmcpioRead(rpmcpio_t cpio, void * buf, size_t size); /** \ingroup payload * Return formatted error message on payload handling failure. @@ -124,7 +132,7 @@ int cpioHeaderRead(FSM_t fsm, struct stat * st); * @return formatted error string */ /* XXX should be RPM_GNUC_INTERNAL too but build/pack.c uses */ -const char * cpioStrerror(int rc); +const char * rpmcpioStrerror(int rc); #ifdef __cplusplus } diff --git a/lib/fsm.c b/lib/fsm.c index 5c13914..4972b31 100644 --- a/lib/fsm.c +++ b/lib/fsm.c @@ -559,14 +559,11 @@ static int fsmCreate(FSM_t fsm) int rc = 0; fsm->path = _free(fsm->path); - fsm->rdsize = fsm->wrsize = 0; - fsm->rdbuf = fsm->rdb = _free(fsm->rdb); - fsm->wrbuf = fsm->wrb = _free(fsm->wrb); + fsm->buf = _free(fsm->buf); + fsm->bufsize = 0; if (fsm->goal == FSM_PKGINSTALL || fsm->goal == FSM_PKGBUILD) { - fsm->rdsize = 8 * BUFSIZ; - fsm->rdbuf = fsm->rdb = xmalloc(fsm->rdsize); - fsm->wrsize = 8 * BUFSIZ; - fsm->wrbuf = fsm->wrb = xmalloc(fsm->wrsize); + fsm->bufsize = 8 * BUFSIZ; + fsm->buf = xmalloc(fsm->bufsize); } fsm->ix = -1; @@ -595,7 +592,6 @@ static int fsmSetup(FSM_t fsm, fileStage goal, if (cfd != NULL) { fsm->cfd = fdLink(cfd); } - fsm->cpioPos = 0; fsm->iter = mapInitIterator(ts, te, fi); fsm->psm = psm; fsm->sehandle = rpmtsSELabelHandle(ts); @@ -606,10 +602,12 @@ static int fsmSetup(FSM_t fsm, fileStage goal, if (isSrc) { fsm->mapFlags |= CPIO_FOLLOW_SYMLINKS; } + fsm->archive = rpmcpioOpen(cfd, O_WRONLY); } else { if (!isSrc) { fsm->mapFlags |= CPIO_SBIT_CHECK; } + fsm->archive = rpmcpioOpen(cfd, O_RDONLY); } fsm->archiveSize = archiveSize; @@ -631,7 +629,7 @@ static int fsmSetup(FSM_t fsm, fileStage goal, if (rc && !ec) ec = rc; if (fsm->archiveSize && ec == 0) - *fsm->archiveSize = fsm->cpioPos; + *fsm->archiveSize = rpmcpioTell(fsm->archive); /* FIX: *fsm->failedFile may be NULL */ return ec; @@ -644,6 +642,8 @@ static int fsmTeardown(FSM_t fsm) if (!rc) rc = fsmUNSAFE(fsm, FSM_DESTROY); + rc = rpmcpioClose(fsm->archive) || rc; + fsm->iter = mapFreeIterator(fsm->iter); if (fsm->cfd != NULL) { fsm->cfd = fdFree(fsm->cfd); @@ -788,19 +788,18 @@ static int expandRegular(FSM_t fsm) fdInitDigest(wfd, digestalgo, 0); while (left) { - - fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); - rc = fsmNext(fsm, FSM_DREAD); - if (rc) + size_t len; + len = (left > fsm->bufsize ? fsm->bufsize : left); + if (rpmcpioRead(fsm->archive, fsm->buf, len) != len) { + rc = CPIOERR_READ_FAILED; goto exit; - - fsm->wrnb = Fwrite(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->rdnb, wfd); - if (fsm->rdnb != fsm->wrnb || Ferror(wfd)) { + } + if ((Fwrite(fsm->buf, sizeof(*fsm->buf), len, wfd) != len) || Ferror(wfd)) { rc = CPIOERR_WRITE_FAILED; goto exit; } - left -= fsm->wrnb; + left -= len; /* don't call this with fileSize == fileComplete */ if (!rc && left) @@ -815,8 +814,9 @@ static int expandRegular(FSM_t fsm) if (digest != NULL && fidigest != NULL) { size_t diglen = rpmDigestLength(digestalgo); - if (memcmp(digest, fidigest, diglen)) + if (memcmp(digest, fidigest, diglen)) { rc = CPIOERR_DIGEST_MISMATCH; + } } else { rc = CPIOERR_DIGEST_MISMATCH; } @@ -841,7 +841,7 @@ static int fsmReadLink(const char *path, int rc = CPIOERR_READLINK_FAILED; if (_fsm_debug && (FSM_READLINK & FSM_SYSCALL)) { - rpmlog(RPMLOG_DEBUG, " %8s (%s, rdbuf, %d) %s\n", + rpmlog(RPMLOG_DEBUG, " %8s (%s, buf, %d) %s\n", fileStageString(FSM_READLINK), path, (int)(bufsize -1), (llen < 0 ? strerror(errno) : "")); } @@ -868,7 +868,7 @@ static int writeFile(FSM_t fsm, int writeData) struct stat * ost = &fsm->osb; char * symbuf = NULL; rpm_loff_t left; - int rc; + int rc = 0; st->st_size = (writeData ? ost->st_size : 0); @@ -879,11 +879,11 @@ static int writeFile(FSM_t fsm, int writeData) * While linux puts the size of a symlink in the st_size field, * I don't think that's a specified standard. */ - /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ - rc = fsmReadLink(fsm->path, fsm->rdbuf, fsm->rdsize, &fsm->rdnb); + size_t linklen; + rc = fsmReadLink(fsm->path, fsm->buf, fsm->bufsize, &linklen); if (rc) goto exit; - st->st_size = fsm->rdnb; - rstrcat(&symbuf, fsm->rdbuf); /* XXX save readlink return. */ + st->st_size = linklen; + rstrcat(&symbuf, fsm->buf); /* XXX save readlink return. */ } if (fsm->mapFlags & CPIO_MAP_ABSOLUTE) { @@ -895,15 +895,17 @@ static int writeFile(FSM_t fsm, int writeData) rpmfiBNIndex(fi, fsm->ix))); } - rc = cpioHeaderWrite(fsm, st); + rc = rpmcpioHeaderWrite(fsm->archive, fsm->path, st); _free(fsm->path); fsm->path = path; + if (rc) goto exit; + if (writeData && S_ISREG(st->st_mode)) { - size_t rdlen; + size_t len; #ifdef HAVE_MMAP - char * rdbuf = NULL; + char * buf = NULL; void * mapped = MAP_FAILED; size_t nmapped; int xx; @@ -920,9 +922,9 @@ static int writeFile(FSM_t fsm, int writeData) nmapped = 0; mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(rfd), 0); if (mapped != MAP_FAILED) { - rdbuf = fsm->rdbuf; - fsm->rdbuf = (char *) mapped; - rdlen = nmapped = st->st_size; + buf = fsm->buf; + fsm->buf = (char *) mapped; + len = nmapped = st->st_size; #if defined(MADV_DONTNEED) xx = madvise(mapped, nmapped, MADV_DONTNEED); #endif @@ -934,24 +936,22 @@ static int writeFile(FSM_t fsm, int writeData) while (left) { #ifdef HAVE_MMAP if (mapped != MAP_FAILED) { - fsm->rdnb = nmapped; + len = nmapped; } else #endif { - rdlen = (left > fsm->rdsize ? fsm->rdsize : left), - - fsm->rdnb = Fread(fsm->rdbuf, sizeof(*fsm->rdbuf), rdlen, rfd); - if (fsm->rdnb != rdlen || Ferror(rfd)) { - rc = CPIOERR_READ_FAILED; - goto exit; - } + len = (left > fsm->bufsize ? fsm->bufsize : left); + if (Fread(fsm->buf, sizeof(*fsm->buf), len, rfd) != len || Ferror(rfd)) { + rc = CPIOERR_READ_FAILED; + goto exit; + } } - /* XXX DWRITE uses rdnb for I/O length. */ - rc = fsmNext(fsm, FSM_DWRITE); - if (rc) goto exit; - - left -= fsm->wrnb; + if (rpmcpioWrite(fsm->archive, fsm->buf, len) != len) { + rc = CPIOERR_WRITE_FAILED; + goto exit; + } + left -= len; } #ifdef HAVE_MMAP @@ -961,23 +961,18 @@ static int writeFile(FSM_t fsm, int writeData) xx = madvise(mapped, nmapped, MADV_DONTNEED); #endif xx = munmap(mapped, nmapped); - fsm->rdbuf = rdbuf; + fsm->buf = buf; } #endif } else if (writeData && S_ISLNK(st->st_mode)) { - /* XXX DWRITE uses rdnb for I/O length. */ - strcpy(fsm->rdbuf, symbuf); /* XXX restore readlink buffer. */ - fsm->rdnb = strlen(symbuf); - rc = fsmNext(fsm, FSM_DWRITE); - if (rc) goto exit; + size_t len = strlen(symbuf); + if (rpmcpioWrite(fsm->archive, symbuf, len) != len) { + rc = CPIOERR_WRITE_FAILED; + goto exit; + } } - rc = fsmNext(fsm, FSM_PAD); - if (rc) goto exit; - - rc = 0; - exit: if (rfd) { /* preserve any prior errno across close */ @@ -989,6 +984,8 @@ exit: } fsm->path = path; free(symbuf); + if (rc) + printf(rpmcpioStrerror(rc)); return rc; } @@ -1591,12 +1588,13 @@ static int fsmVerify(FSM_t fsm) } } else if (S_ISLNK(st->st_mode)) { if (S_ISLNK(ost->st_mode)) { - /* XXX NUL terminated result in fsm->rdbuf, len in fsm->rdnb. */ - rc = fsmReadLink(fsm->path, fsm->rdbuf, fsm->rdsize, &fsm->rdnb); + char buf[8 * BUFSIZ]; + size_t len; + rc = fsmReadLink(fsm->path, buf, 8 * BUFSIZ, &len); errno = saveerrno; if (rc) return rc; - /* XXX FSM_PROCESS puts link target to wrbuf. */ - if (rstreq(fsm->wrbuf, fsm->rdbuf)) return 0; + /* FSM_PROCESS puts link target to fsm->buf. */ + if (rstreq(fsm->buf, buf)) return 0; } } else if (S_ISFIFO(st->st_mode)) { if (S_ISFIFO(ost->st_mode)) return 0; @@ -1629,13 +1627,11 @@ static int fsmVerify(FSM_t fsm) */ static int fsmStage(FSM_t fsm, fileStage stage) { - static int modulo = 4; const char * const cur = fileStageString(stage); struct stat * st = &fsm->sb; struct stat * ost = &fsm->osb; int saveerrno = errno; int rc = fsm->rc; - rpm_loff_t left; #define _fafilter(_a) \ (!((_a) == FA_CREATE || (_a) == FA_ERASE || (_a) == FA_COPYIN || (_a) == FA_COPYOUT) \ @@ -1751,14 +1747,9 @@ static int fsmStage(FSM_t fsm, fileStage stage) /* Flush partial sets of hard linked files. */ rc = writeLinks(fsm); - if (!rc) - rc = cpioTrailerWrite(fsm); - break; case FSM_PROCESS: if (fsm->postpone) { - if (fsm->goal == FSM_PKGINSTALL) - rc = fsmNext(fsm, FSM_EAT); break; } @@ -1805,22 +1796,21 @@ static int fsmStage(FSM_t fsm, fileStage stage) rc = fsmMkdir(fsm->path, mode); } } else if (S_ISLNK(st->st_mode)) { - if ((st->st_size + 1) > fsm->rdsize) { + if ((st->st_size + 1) > fsm->bufsize) { rc = CPIOERR_HDR_SIZE; break; } - fsm->wrlen = st->st_size; - rc = fsmNext(fsm, FSM_DREAD); - if (!rc && fsm->rdnb != fsm->wrlen) + if (rpmcpioRead(fsm->archive, fsm->buf, st->st_size) != st->st_size) { rc = CPIOERR_READ_FAILED; - if (rc) break; + break; + } - fsm->wrbuf[st->st_size] = '\0'; - /* XXX fsmVerify() assumes link target in fsm->wrbuf */ + fsm->buf[st->st_size] = '\0'; + /* fsmVerify() assumes link target in fsm->buf */ rc = fsmVerify(fsm); if (rc == CPIOERR_ENOENT) { - rc = fsmSymlink(fsm->wrbuf, fsm->path); + rc = fsmSymlink(fsm->buf, fsm->path); } } else if (S_ISFIFO(st->st_mode)) { /* This mimics cpio S_ISSOCK() behavior but probably isnt' right */ @@ -1850,7 +1840,7 @@ static int fsmStage(FSM_t fsm, fileStage stage) break; case FSM_NOTIFY: /* XXX move from fsm to psm -> tsm */ if (fsm->goal == FSM_PKGINSTALL) { - rpmpsmNotify(fsm->psm, RPMCALLBACK_INST_PROGRESS, fsm->cpioPos); + rpmpsmNotify(fsm->psm, RPMCALLBACK_INST_PROGRESS, rpmcpioTell(fsm->archive)); } else if (fsm->goal == FSM_PKGERASE) { /* On erase we're iterating backwards, fixup for progress */ rpm_loff_t amount = (fsm->ix >= 0) ? @@ -2023,68 +2013,20 @@ static int fsmStage(FSM_t fsm, fileStage stage) } fsm->li = freeHardLink(fsm->li); } - fsm->rdbuf = fsm->rdb = _free(fsm->rdb); - fsm->wrbuf = fsm->wrb = _free(fsm->wrb); + fsm->buf = _free(fsm->buf); + fsm->bufsize = 0; break; case FSM_NEXT: - rc = fsmNext(fsm, FSM_POS); - if (!rc) - rc = cpioHeaderRead(fsm, st); /* Read next payload header. */ + if (!rc) { + _free(fsm->path); + rc = rpmcpioHeaderRead(fsm->archive, &(fsm->path), st); /* Read next payload header. */ + } if (rc) break; if (rstreq(fsm->path, CPIO_TRAILER)) { /* Detect end-of-payload. */ fsm->path = _free(fsm->path); rc = CPIOERR_HDR_TRAILER; } - if (!rc) - rc = fsmNext(fsm, FSM_POS); - break; - case FSM_EAT: - for (left = st->st_size; left > 0; left -= fsm->rdnb) { - fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left); - rc = fsmNext(fsm, FSM_DREAD); - if (rc) - break; - } - break; - case FSM_POS: - left = (modulo - (fsm->cpioPos % modulo)) % modulo; - if (left) { - fsm->wrlen = left; - (void) fsmNext(fsm, FSM_DREAD); - } - break; - case FSM_PAD: - left = (modulo - (fsm->cpioPos % modulo)) % modulo; - if (left) { - memset(fsm->rdbuf, 0, left); - /* XXX DWRITE uses rdnb for I/O length. */ - fsm->rdnb = left; - (void) fsmNext(fsm, FSM_DWRITE); - } - break; - case FSM_DREAD: - fsm->rdnb = Fread(fsm->wrbuf, sizeof(*fsm->wrbuf), fsm->wrlen, fsm->cfd); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\trdnb %d\n", - cur, (fsm->wrbuf == fsm->wrb ? "wrbuf" : "mmap"), - (int)fsm->wrlen, (int)fsm->rdnb); - if (fsm->rdnb != fsm->wrlen || Ferror(fsm->cfd)) - rc = CPIOERR_READ_FAILED; - if (fsm->rdnb > 0) - fsm->cpioPos += fsm->rdnb; break; - case FSM_DWRITE: - fsm->wrnb = Fwrite(fsm->rdbuf, sizeof(*fsm->rdbuf), fsm->rdnb, fsm->cfd); - if (_fsm_debug && (stage & FSM_SYSCALL)) - rpmlog(RPMLOG_DEBUG, " %8s (%s, %d, cfd)\twrnb %d\n", - cur, (fsm->rdbuf == fsm->rdb ? "rdbuf" : "mmap"), - (int)fsm->rdnb, (int)fsm->wrnb); - if (fsm->rdnb != fsm->wrnb || Ferror(fsm->cfd)) - rc = CPIOERR_WRITE_FAILED; - if (fsm->wrnb > 0) - fsm->cpioPos += fsm->wrnb; - break; - default: break; } diff --git a/lib/fsm.h b/lib/fsm.h index c25b7c5..e438b1a 100644 --- a/lib/fsm.h +++ b/lib/fsm.h @@ -7,6 +7,7 @@ */ #include +#include "cpio.h" extern int _fsm_debug; @@ -106,22 +107,14 @@ typedef struct hardLink_s * hardLink_t; struct fsm_s { char * path; /*!< Current file name. */ FD_t cfd; /*!< Payload file handle. */ - char * rdbuf; /*!< read: Buffer. */ - char * rdb; /*!< read: Buffer allocated. */ - size_t rdsize; /*!< read: Buffer allocated size. */ - size_t rdnb; /*!< read: Number of bytes returned. */ - char * wrbuf; /*!< write: Buffer. */ - char * wrb; /*!< write: Buffer allocated. */ - size_t wrsize; /*!< write: Buffer allocated size. */ - size_t wrlen; /*!< write: Number of bytes requested.*/ - size_t wrnb; /*!< write: Number of bytes returned. */ + rpmcpio_t archive; /*!< cpio archive */ + char * buf; /*!< read: Buffer. */ + size_t bufsize; /*!< read: Buffer allocated size. */ FSMI_t iter; /*!< File iterator. */ int ix; /*!< Current file iterator index. */ hardLink_t links; /*!< Pending hard linked file(s). */ hardLink_t li; /*!< Current hard linked file(s). */ rpm_loff_t * archiveSize; /*!< Pointer to archive size. */ - rpm_loff_t archivePos; /*!< Current archive position. */ - rpm_loff_t cpioPos; char ** failedFile; /*!< First file name that failed. */ const char * osuffix; /*!< Old, preserved, file suffix. */ const char * nsuffix; /*!< New, created, file suffix. */ diff --git a/lib/psm.c b/lib/psm.c index 5947c47..93f0a56 100644 --- a/lib/psm.c +++ b/lib/psm.c @@ -836,7 +836,7 @@ static rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage) _("unpacking of archive failed%s%s: %s\n"), (psm->failedFile != NULL ? _(" on file ") : ""), (psm->failedFile != NULL ? psm->failedFile : ""), - cpioStrerror(fsmrc)); + rpmcpioStrerror(fsmrc)); rc = RPMRC_FAIL; /* XXX notify callback on error. */ @@ -939,10 +939,10 @@ static rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage) if (psm->failedFile) rpmlog(RPMLOG_ERR, _("%s failed on file %s: %s\n"), - psm->goalName, psm->failedFile, cpioStrerror(rc)); + psm->goalName, psm->failedFile, rpmcpioStrerror(rc)); else rpmlog(RPMLOG_ERR, _("%s failed: %s\n"), - psm->goalName, cpioStrerror(rc)); + psm->goalName, rpmcpioStrerror(rc)); /* XXX notify callback on error. */ rpmtsNotify(ts, psm->te, RPMCALLBACK_CPIO_ERROR, 0, 0); -- 2.7.4