]> git.draconx.ca Git - liblbx.git/commitdiff
Fix lbx_extract's seeking to maintain a correct offset even on errors.
authorNick Bowler <draconx@gmail.com>
Sun, 23 Dec 2007 04:11:26 +0000 (23:11 -0500)
committerNick Bowler <draconx@gmail.com>
Sun, 23 Dec 2007 04:11:26 +0000 (23:11 -0500)
src/lbx.c
src/lbxtool.c

index 3eac7080faadf6a13093754515160165e51ecbd8..597d0433e313a5898bac2e407f989a53d0339bbb 100644 (file)
--- a/src/lbx.c
+++ b/src/lbx.c
@@ -106,26 +106,40 @@ int lbx_stat(struct lbx_state *lbx, size_t index, struct lbx_statbuf *buf)
        return 0;
 }
 
-/*
- * Read and discard len bytes from the file.  On success, returns 0.  On
- * failure, returns -1 and sets lbx_errno.
- */
-static int skipdata(FILE *f, size_t len)
+/* Advance to the beginning of the index'th file by either fseek or reading. */
+static int _lbx_fseek(struct lbx_state *lbx, size_t base)
 {
-       unsigned char buf[1024];
-       
-       while (len) {
-               if (fread(buf, MIN(sizeof buf, len), 1, f) != 1) {
-                       if (feof(f)) {
-                               lbx_errno = LBX_EEOF;
-                       } else {
-                               lbx_errno = -errno;
+       static unsigned char oblivion[1024];
+       long dist;
+
+       if (lbx->foff < base) {
+               dist = base - lbx->foff;
+       } else if (lbx->foff > base) {
+               dist = -(long)(lbx->foff - base);
+       } else {
+               return 0;
+       }
+
+       if (fseek(lbx->f, dist, SEEK_CUR) == 0) {
+               lbx->foff += dist;
+       } else if (lbx->foff < base) {
+               while (dist) {
+                       size_t rc, amt = MIN(sizeof oblivion, dist);
+                       rc = fread(oblivion, 1, amt, lbx->f);
+                       lbx->foff += rc;
+                       dist -= rc;
+                       if (rc < amt) {
+                               if (feof(lbx->f))
+                                       lbx_errno = LBX_EEOF;
+                               else
+                                       lbx_errno = -errno;
+                               return -1;
                        }
-                       return -1;
                }
-               len -= MIN(sizeof buf, len);
+       } else {
+               lbx_errno = -errno;
+               return -1;
        }
-
        return 0;
 }
 
@@ -142,23 +156,9 @@ size_t lbx_extract(struct lbx_state *lbx, size_t index, FILE *of)
        base = lbx->offsets[index];
        len  = lbx->offsets[index+1] - lbx->offsets[index];
 
-       /* Seek to the beginning of the file. */
-       if (lbx->foff != base) {
-               int seekrc;
-               long dist = (lbx->foff < base) ?  (base - lbx->foff)
-                                              : -(lbx->foff - base);
-
-               seekrc = fseek(lbx->f, dist, SEEK_CUR);
-               if (seekrc == -1 && lbx->foff < base) {
-                       if (skipdata(lbx->f, dist) == -1) {
-                               /* lbx_errno set by skipdata */
-                               return 0;
-                       }
-               } else if (seekrc == -1) {
-                       lbx_errno = -errno;
-                       return 0;
-               }
-               lbx->foff += dist; /* FIXME: failed skipdata breaks this. */
+       if (_lbx_fseek(lbx, base) == -1) {
+               /* lbx_errno set by _lbx_fseek(). */
+               return 0;
        }
 
        /* Copy file data */
index a220cea67d858fd881939a3396f9ad0683cacd37..5435d5f423e7c928814c36104211ed7eb6c3f4f3 100644 (file)
@@ -81,6 +81,7 @@ int extract(FILE *f, const char *name, int verbose) {
                if (verbose) printf("extracting %s...\n", stat.name);
                rc = lbx_extract(lbx, i, of);
                if (rc < stat.size) {
+                       if (rc == 0) remove(stat.name);
                        errmsg("error extracting %s: %s.\n",
                               stat.name, lbx_strerror());
                        break;