svn commit: r201267 - stable/8/lib/libstand

John Baldwin jhb at FreeBSD.org
Wed Dec 30 17:53:07 UTC 2009


Author: jhb
Date: Wed Dec 30 17:53:07 2009
New Revision: 201267
URL: http://svn.freebsd.org/changeset/base/201267

Log:
  MFC 200919:
  Fix a bug in gzipfs that prevented lseek() from working and add lseek()
  support to bzip2fs.  This fixes problems with loading compressed amd64
  kernel modules containing debug symbols.

Modified:
  stable/8/lib/libstand/bzipfs.c
  stable/8/lib/libstand/gzipfs.c
Directory Properties:
  stable/8/lib/libstand/   (props changed)

Modified: stable/8/lib/libstand/bzipfs.c
==============================================================================
--- stable/8/lib/libstand/bzipfs.c	Wed Dec 30 17:45:35 2009	(r201266)
+++ stable/8/lib/libstand/bzipfs.c	Wed Dec 30 17:53:07 2009	(r201267)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 #ifndef REGRESSION
 #include "stand.h"
 #else
+#include <stdlib.h>
 #include <sys/errno.h>
 #include <sys/fcntl.h>
 #include <sys/types.h>
@@ -42,7 +43,7 @@ struct open_file {
 };
 #define F_READ          0x0001  /* file opened for reading */
 #define EOFFSET (ELAST+8)       /* relative seek not supported */
-static inline u_int min(u_int a, u_int b) { return (a < b ? a : b); }
+static inline u_int min(u_int a, u_int b) { return(a < b ? a : b); }
 #define panic(x, y) abort()
 #endif
 
@@ -174,6 +175,8 @@ bzf_open(const char *fname, struct open_
 
     /* Construct new name */
     bzfname = malloc(strlen(fname) + 5);
+    if (bzfname == NULL)
+	return(ENOMEM);
     sprintf(bzfname, "%s.bz2", fname);
 
     /* Try to open the compressed datafile */
@@ -195,13 +198,14 @@ bzf_open(const char *fname, struct open_
 
     /* Allocate a bz_file structure, populate it */
     bzf = malloc(sizeof(struct bz_file));
+    if (bzf == NULL)
+	return(ENOMEM);
     bzero(bzf, sizeof(struct bz_file));
     bzf->bzf_rawfd = rawfd;
 
-    /* Verify that the file is bzipped (XXX why do this afterwards?) */
+    /* Verify that the file is bzipped */
     if (check_header(bzf)) {
 	close(bzf->bzf_rawfd);
-	BZ2_bzDecompressEnd(&(bzf->bzf_bzstream));
 	free(bzf);
 	return(EFTYPE);
     }
@@ -247,7 +251,7 @@ bzf_read(struct open_file *f, void *buf,
 	if (bzf->bzf_bzstream.avail_in == 0) {		/* oops, unexpected EOF */
 	    printf("bzf_read: unexpected EOF\n");
 	    if (bzf->bzf_bzstream.avail_out == size)
-		return (EIO);
+		return(EIO);
 	    break;
 	}
 
@@ -266,6 +270,50 @@ bzf_read(struct open_file *f, void *buf,
     return(0);
 }
 
+static int
+bzf_rewind(struct open_file *f)
+{
+    struct bz_file	*bzf = (struct bz_file *)f->f_fsdata;
+    struct bz_file	*bzf_tmp;
+
+    /*
+     * Since bzip2 does not have an equivalent inflateReset function a crude
+     * one needs to be provided.  The functions all called in such a way that
+     * at any time an error occurs a role back can be done (effectively making
+     * this rewind 'atomic', either the reset occurs successfully or not at all,
+     * with no 'undefined' state happening).
+     */
+
+    /* Allocate a bz_file structure, populate it */
+    bzf_tmp = malloc(sizeof(struct bz_file));
+    if (bzf_tmp == NULL)
+	return(-1);
+    bzero(bzf_tmp, sizeof(struct bz_file));
+    bzf_tmp->bzf_rawfd = bzf->bzf_rawfd;
+
+    /* Initialise the inflation engine */
+    if (BZ2_bzDecompressInit(&(bzf_tmp->bzf_bzstream), 0, 1) != BZ_OK) {
+	free(bzf_tmp);
+	return(-1);
+    }
+
+    /* Seek back to the beginning of the file */
+    if (lseek(bzf->bzf_rawfd, 0, SEEK_SET) == -1) {
+	BZ2_bzDecompressEnd(&(bzf_tmp->bzf_bzstream));
+	free(bzf_tmp);
+	return(-1);
+    }
+
+    /* Free old bz_file data */
+    BZ2_bzDecompressEnd(&(bzf->bzf_bzstream));
+    free(bzf);
+
+    /* Use the new bz_file data */
+    f->f_fsdata = bzf_tmp;
+
+    return(0);
+}
+
 static off_t
 bzf_seek(struct open_file *f, off_t offset, int where)
 {
@@ -284,14 +332,17 @@ bzf_seek(struct open_file *f, off_t offs
 	target = -1;
     default:
 	errno = EINVAL;
-	return (-1);
+	return(-1);
     }
 
     /* Can we get there from here? */
-    if (target < bzf->bzf_bzstream.total_out_lo32) {
+    if (target < bzf->bzf_bzstream.total_out_lo32 && bzf_rewind(f) != 0) {
 	errno = EOFFSET;
 	return -1;
-    } 
+    }
+
+    /* if bzf_rewind was called then bzf has changed */
+    bzf = (struct bz_file *)f->f_fsdata;
 
     /* skip forwards if required */
     while (target > bzf->bzf_bzstream.total_out_lo32) {
@@ -301,7 +352,7 @@ bzf_seek(struct open_file *f, off_t offs
 	    return(-1);
     }
     /* This is where we are (be honest if we overshot) */
-    return (bzf->bzf_bzstream.total_out_lo32);
+    return(bzf->bzf_bzstream.total_out_lo32);
 }
 
 static int

Modified: stable/8/lib/libstand/gzipfs.c
==============================================================================
--- stable/8/lib/libstand/gzipfs.c	Wed Dec 30 17:45:35 2009	(r201266)
+++ stable/8/lib/libstand/gzipfs.c	Wed Dec 30 17:53:07 2009	(r201267)
@@ -212,10 +212,9 @@ zf_open(const char *fname, struct open_f
     bzero(zf, sizeof(struct z_file));
     zf->zf_rawfd = rawfd;
 
-    /* Verify that the file is gzipped (XXX why do this afterwards?) */
+    /* Verify that the file is gzipped */
     if (check_header(zf)) {
 	close(zf->zf_rawfd);
-	inflateEnd(&(zf->zf_zstream));
 	free(zf);
 	return(EFTYPE);
     }
@@ -261,7 +260,7 @@ zf_read(struct open_file *f, void *buf, 
 	if (zf->zf_zstream.avail_in == 0) {		/* oops, unexpected EOF */
 	    printf("zf_read: unexpected EOF\n");
 	    if (zf->zf_zstream.avail_out == size)
-		return (EIO);
+		return(EIO);
 	    break;
 	}
 
@@ -286,12 +285,13 @@ zf_rewind(struct open_file *f)
     struct z_file	*zf = (struct z_file *)f->f_fsdata;
 
     if (lseek(zf->zf_rawfd, zf->zf_dataoffset, SEEK_SET) == -1)
-	return -1;
+	return(-1);
     zf->zf_zstream.avail_in = 0;
     zf->zf_zstream.next_in = NULL;
+    zf->zf_endseen = 0;
     (void)inflateReset(&zf->zf_zstream);
 
-    return 0;
+    return(0);
 }
 
 static off_t
@@ -312,12 +312,12 @@ zf_seek(struct open_file *f, off_t offse
 	target = -1;
     default:
 	errno = EINVAL;
-	return (-1);
+	return(-1);
     }
 
     /* rewind if required */
     if (target < zf->zf_zstream.total_out && zf_rewind(f) != 0)
-	return -1;
+	return(-1);
 
     /* skip forwards if required */
     while (target > zf->zf_zstream.total_out) {
@@ -327,7 +327,7 @@ zf_seek(struct open_file *f, off_t offse
 	    return(-1);
     }
     /* This is where we are (be honest if we overshot) */
-    return (zf->zf_zstream.total_out);
+    return(zf->zf_zstream.total_out);
 }
 
 


More information about the svn-src-all mailing list