Untangle lib/fsm.c and lib/cpio.c
authorFlorian Festi <ffesti@redhat.com>
Thu, 22 Mar 2012 12:58:02 +0000 (13:58 +0100)
committerFlorian Festi <ffesti@redhat.com>
Tue, 27 Mar 2012 12:12:42 +0000 (14:12 +0200)
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
lib/cpio.h
lib/fsm.c
lib/fsm.h
lib/psm.c

index bfb2fbb..38321a1 100644 (file)
 #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. <shrug>
+     * 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;
index 9453184..206f4b8 100644 (file)
@@ -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
 }
index 5c13914..4972b31 100644 (file)
--- 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;
     }
index c25b7c5..e438b1a 100644 (file)
--- a/lib/fsm.h
+++ b/lib/fsm.h
@@ -7,6 +7,7 @@
  */
 
 #include <rpm/rpmfi.h>
+#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. */
index 5947c47..93f0a56 100644 (file)
--- 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);