Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Sep 2006 01:52:44 GMT
From:      Yoshihiro Ota <ota@j.email.ne.jp>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/103500: mkuzip enhancement to accept size of input file
Message-ID:  <200609230152.k8N1qihu002363@www.freebsd.org>
Resent-Message-ID: <200609230200.k8N20dM3057371@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         103500
>Category:       misc
>Synopsis:       mkuzip enhancement to accept size of input file
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Sep 23 02:00:38 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Yoshihiro Ota
>Release:        6.[01]-RELEASE, 6.2-PRERELEASE
>Organization:
>Environment:
FreeBSD xxx.yyy.com 6.2-PRERELEASE FreeBSD 6.2-PRERELEASE #23: Wed Sep 20 00:16:08 EST 2006     root@xxx.yyy.com:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
mkuzip cannot compress devices because stat.2 does not return the size of devices.  The patch attached allows mkuzip to prcocess non-stat.2 sizeable files such as device.

mkuzip takes new -S size option as expected size of the input file.  If EOF reaches before the size, the new mkuzip creates one empty block and all remaining block pointers points to the empty block.  If size is too small, it exists with error.
>How-To-Repeat:
mkuzip -o /var/tmp/tmp.uzip /dev/ad0s1a
>Fix:
--- src.org/usr.bin/mkuzip/mkuzip.c     Sat Apr 15 17:10:12 2006
+++ src/usr.bin/mkuzip/mkuzip.c Tue Apr 18 06:14:53 2006
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <inttypes.h>
 
 #define CLSTSIZE       16384
 #define DEFAULT_SUFX   ".uzip"
@@ -33,6 +34,7 @@
     "m=geom_uzip\n(kldstat -m $m 2>&-||kldload $m)>&-&&"
     "mount_cd9660 /dev/`mdconfig -af $0`.uzip $1\nexit $?\n";
  
+static uint32_t get_size(char *);
 static char *readblock(int, char *, u_int32_t);
 static void usage(void);
 static void *safe_malloc(size_t);
@@ -43,12 +45,16 @@
 int main(int argc, char **argv)
 {
        char *iname, *oname, *obuf, *ibuf;
+       char *p;
        uint64_t *toc;
-       int fdr, fdw, i, opt, verbose, tmp;
+       int fdr, fdw, opt, verbose, tmp;
        struct iovec iov[2];
-       struct stat sb;
        uLongf destlen;
        uint64_t offset;
+       off_t i;
+       off_t *inputsz; /* we try file size first; otherwise user supplied */
+       off_t filesz; /* file size */
+       off_t usersz; /* user supplied size */
        struct cloop_header {
                char magic[CLOOP_MAGIC_LEN];    /* cloop magic */
                uint32_t blksz;                 /* block size */
@@ -61,7 +67,7 @@
        oname = NULL;
        verbose = 0;

-       while((opt = getopt(argc, argv, "o:s:v")) != -1) {
+       while((opt = getopt(argc, argv, "o:s:S:v")) != -1) {
                switch(opt) {
                case 'o':
                        oname = optarg;
@@ -86,6 +92,27 @@
                        hdr.blksz = tmp;
                        break;

+               case 'S':
+                       usersz = (off_t)strtoumax(optarg, &p, 0);
+                       if(p == NULL || *p == '\0')
+                               break;
+                       switch(*p)
+                       {
+                               case 't': case 'T':
+                                       usersz <<= 10;
+                               case 'g': case 'G':
+                                       usersz <<= 10;
+                               case 'm': case 'M':
+                                       usersz <<= 10;
+                               case 'k': case 'K':
+                                       usersz <<= 10;
+                               case 'b': case 'B':
+                                       break;
+                               default:
+                                       err(1, "Unknown suffix on -S argument");
+                       }
+                       break;
+
                case 'v':
                        verbose = 1;
                        break;
@@ -122,12 +149,21 @@
        signal(SIGXFSZ, exit);
        atexit(cleanup);

-       if (stat(iname, &sb) != 0) {
-               err(1, "%s", iname);
+
+       filesz = get_size(iname);
+       if(filesz > 0)
+               inputsz = &filesz;
+       else
+               inputsz = &usersz;
+
+       if(*inputsz < 0) {
+               err(1, "input file size is not avaiable;\n"
+                       "try -S input_size option with large enough size");
                /* Not reached */
        }
-       hdr.nblocks = sb.st_size / hdr.blksz;
-       if ((sb.st_size % hdr.blksz) != 0) {
+
+       hdr.nblocks = *inputsz / hdr.blksz;
+       if ((*inputsz % hdr.blksz) != 0) {
                if (verbose != 0)
                        fprintf(stderr, "file size is not multiple "
                        "of %d, padding data\n", hdr.blksz);
@@ -160,21 +196,23 @@

        if (verbose != 0)
                fprintf(stderr, "data size %ju bytes, number of clusters "
-                   "%u, index length %zu bytes\n", sb.st_size,
+                   "%u, index length %zu bytes\n", *inputsz,
                    hdr.nblocks, iov[1].iov_len);

-       for(i = 0; i == 0 || ibuf != NULL; i++) {
-               ibuf = readblock(fdr, ibuf, hdr.blksz);
-               if (ibuf != NULL) {
-                       destlen = compressBound(hdr.blksz);
-                       if (compress2(obuf, &destlen, ibuf, hdr.blksz,
-                           Z_BEST_COMPRESSION) != Z_OK) {
-                               errx(1, "can't compress data: compress2() "
-                                   "failed");
+       for(i = 0; i <= hdr.nblocks; i++) {
+               p = readblock(fdr, ibuf, hdr.blksz);
+
+               /* compress 0'ed data even if no data is read */
+               destlen = compressBound(hdr.blksz);
+               if (compress2(obuf, &destlen, ibuf, hdr.blksz,
+                       Z_BEST_COMPRESSION) != Z_OK) {
+                               errx(1, "can't compress data: compress2() failed
");
                                /* Not reached */
-                       }
+               }
+
+               if (p != NULL) {
                        if (verbose != 0)
-                               fprintf(stderr, "cluster #%d, in %u bytes, "
+                               fprintf(stderr, "cluster #%ju, in %u bytes, "
                                    "out %lu bytes\n", i, hdr.blksz, destlen);
                } else {
                        destlen = DEV_BSIZE - (offset % DEV_BSIZE);
@@ -189,14 +227,27 @@
                        /* Not reached */
                }
                toc[i] = htobe64(offset);
+               if(p == NULL) {
+                       /* -S size was too large; the rest points to zero filled
 block */
+                       for(; i <= hdr.nblocks; i++)
+                               toc[i] = htobe64(offset);
+                       break;
+               }
                offset += destlen;
        }
+       if(p != NULL && i > hdr.nblocks) { /* check if we can read more */
+               if(readblock(fdr, ibuf, hdr.blksz) != NULL) {
+                       /* file has grown or -S was too smal */
+                       err(1, "uziped file was not large enought");
+                       /* Not reached */
+               }
+       }
        close(fdr);

        if (verbose != 0)
                fprintf(stderr, "compressed data to %ju bytes, saved %lld "
-                   "bytes, %.2f%% decrease.\n", offset, (long long)(sb.st_size
- offset),
-                   100.0 * (long long)(sb.st_size - offset) / (float)sb.st_size
);
+                   "bytes, %.2f%% decrease.\n", offset, (long long)(*inputsz -
offset),
+                   100.0 * (long long)(*inputsz - offset) / (float)*inputsz);

        /* Convert to big endian */
        hdr.blksz = htonl(hdr.blksz);
@@ -213,6 +264,20 @@
        exit(0);
 }

+static uint32_t
+get_size(char *filename)
+{
+       struct stat sb;
+       if (stat(filename, &sb) != 0) {
+               err(1, "%s", filename);
+               /* Not reached */
+       }
+       if(sb.st_size > 0) /* we got the actual size */
+               return sb.st_size;
+
+       return 0;
+}
+
 static char *
 readblock(int fd, char *ibuf, u_int32_t clstsize)
 {
@@ -234,7 +299,9 @@
 usage(void)
 {

-       fprintf(stderr, "usage: mkuzip [-v] [-o outfile] [-s cluster_size] infil
e\n");
+       fprintf(stderr,
+               "usage: mkuzip [-v] [-o outfile] "
+               "[-s cluster_size] [-S input_size] infile\n");
        exit(1);
 }


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609230152.k8N1qihu002363>