]> Dogcows Code - chaz/tar/blobdiff - scripts/xsparse.c
Upgrade tar-snapshot-edit script.
[chaz/tar] / scripts / xsparse.c
index 87fad1a9dd82ef6fdcf4c78d21989c8618be8d89..14d5658c18a34541152a960e289e15c4490f36ba 100644 (file)
@@ -1,13 +1,13 @@
 /* xsparse - expands compressed sparse file images extracted from GNU tar
    archives.
 
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc.
 
    Written by Sergey Poznyakoff
-   
+
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include <stdlib.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -38,7 +40,7 @@
 struct sp_array
 {
   off_t offset;
-  size_t numbytes;
+  off_t numbytes;
 };
 
 char *progname;
@@ -128,12 +130,12 @@ get_var (FILE *fp, char **name, char **value)
   static char *buffer;
   static size_t bufsize = OFF_T_STRSIZE_BOUND;
   char *p, *q;
-  
+
   buffer = emalloc (bufsize);
   do
     {
       size_t len, s;
-      
+
       if (!fgets (buffer, bufsize, fp))
        return 0;
       len = strlen (buffer);
@@ -185,12 +187,12 @@ read_xheader (char *name)
 
   if (verbose)
     printf ("Reading extended header file\n");
-  
+
   while (get_var (fp, &kw, &val))
     {
       if (verbose)
        printf ("Found variable GNU.sparse.%s = %s\n", kw, val);
-      
+
       if (expect && strcmp (kw, expect))
        die (1, "bad keyword sequence: expected `%s' but found `%s'",
             expect, kw);
@@ -225,7 +227,7 @@ read_xheader (char *name)
        }
       else if (strcmp (kw, "numbytes") == 0)
        {
-         sparse_map[i++].numbytes = string_to_size (val, NULL);
+         sparse_map[i++].numbytes = string_to_off (val, NULL);
        }
       else if (strcmp (kw, "map") == 0)
        {
@@ -235,7 +237,7 @@ read_xheader (char *name)
              if (*val != ',')
                die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
                     *val);
-             sparse_map[i].numbytes = string_to_size (val+1, &val);
+             sparse_map[i].numbytes = string_to_off (val+1, &val);
              if (*val != ',')
                {
                  if (!(*val == 0 && i == sparse_map_size-1))
@@ -266,7 +268,7 @@ read_map (FILE *ifp)
 
   if (verbose)
     printf ("Reading v.1.0 sparse map\n");
-  
+
   get_line (nbuf, sizeof nbuf, ifp);
   sparse_map_size = string_to_size (nbuf, NULL);
   sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
@@ -276,41 +278,49 @@ read_map (FILE *ifp)
       get_line (nbuf, sizeof nbuf, ifp);
       sparse_map[i].offset = string_to_off (nbuf, NULL);
       get_line (nbuf, sizeof nbuf, ifp);
-      sparse_map[i].numbytes = string_to_size (nbuf, NULL);
+      sparse_map[i].numbytes = string_to_off (nbuf, NULL);
     }
 
-  fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
-        SEEK_SET);
-}  
+  fseeko (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
+         SEEK_SET);
+}
 
 void
 expand_sparse (FILE *sfp, int ofd)
 {
   size_t i;
-  size_t maxbytes = 0;
+  off_t max_numbytes = 0;
+  size_t maxbytes;
   char *buffer;
 
   for (i = 0; i < sparse_map_size; i++)
-    if (maxbytes < sparse_map[i].numbytes)
-      maxbytes = sparse_map[i].numbytes;
-  
+    if (max_numbytes < sparse_map[i].numbytes)
+      max_numbytes = sparse_map[i].numbytes;
+
+  maxbytes = max_numbytes < SIZE_MAX ? max_numbytes : SIZE_MAX;
+
   for (buffer = malloc (maxbytes); !buffer; maxbytes /= 2)
     if (maxbytes == 0)
       die (1, "not enough memory");
-  
+
   for (i = 0; i < sparse_map_size; i++)
     {
-      size_t size = sparse_map[i].numbytes;
+      off_t size = sparse_map[i].numbytes;
 
-      lseek (ofd, sparse_map[i].offset, SEEK_SET);
-      while (size)
+      if (size == 0)
+       ftruncate (ofd, sparse_map[i].offset);
+      else
        {
-         size_t rdsize = (size < maxbytes) ? size : maxbytes;
-         if (rdsize != fread (buffer, 1, rdsize, sfp))
-           die (1, "read error (%d)", errno);
-         if (rdsize != write (ofd, buffer, rdsize))
-           die (1, "write error (%d)", errno);
-         size -= rdsize;
+         lseek (ofd, sparse_map[i].offset, SEEK_SET);
+         while (size)
+           {
+             size_t rdsize = (size < maxbytes) ? size : maxbytes;
+             if (rdsize != fread (buffer, 1, rdsize, sfp))
+               die (1, "read error (%d)", errno);
+             if (rdsize != write (ofd, buffer, rdsize))
+               die (1, "write error (%d)", errno);
+             size -= rdsize;
+           }
        }
     }
   free (buffer);
@@ -336,13 +346,13 @@ guess_outname (char *name)
 {
   char *p;
   char *s;
-  
+
   if (name[0] == '.' && name[1] == '/')
     name += 2;
 
   p = name + strlen (name) - 1;
   s = NULL;
-      
+
   for (; p > name && *p != '/'; p--)
     ;
   if (*p == '/')
@@ -352,7 +362,7 @@ guess_outname (char *name)
       for (p--; p > name && *p != '/'; p--)
        ;
     }
-  
+
   if (*p != '/')
     {
       if (s)
@@ -383,7 +393,7 @@ main (int argc, char **argv)
   FILE *ifp;
   struct stat st;
   int ofd;
-  
+
   progname = argv[0];
   while ((c = getopt (argc, argv, "hnvx:")) != EOF)
     {
@@ -402,7 +412,7 @@ main (int argc, char **argv)
        case 'v':
          verbose++;
          break;
-         
+
        default:
          exit (1);
        }
@@ -423,17 +433,17 @@ main (int argc, char **argv)
 
   if (stat (inname, &st))
     die (1, "cannot stat %s (%d)", inname, errno);
-  
+
   ifp = fopen (inname, "r");
   if (ifp == NULL)
     die (1, "cannot open file %s (%d)", inname, errno);
-  
+
   if (!xheader_file || version_major == 1)
     read_map (ifp);
 
   if (!outname)
     guess_outname (inname);
-  
+
   ofd = open (outname, O_RDWR|O_CREAT|O_TRUNC, st.st_mode);
   if (ofd == -1)
     die (1, "cannot open file %s (%d)", outname, errno);
@@ -446,7 +456,7 @@ main (int argc, char **argv)
       printf ("Finished dry run\n");
       return 0;
     }
-  
+
   expand_sparse (ifp, ofd);
 
   fclose (ifp);
@@ -454,7 +464,7 @@ main (int argc, char **argv)
 
   if (verbose)
     printf ("Done\n");
-  
+
   if (outsize)
     {
       if (stat (outname, &st))
@@ -462,7 +472,6 @@ main (int argc, char **argv)
       if (st.st_size != outsize)
        die (1, "expanded file has wrong size");
     }
-  
+
   return 0;
 }
-
This page took 0.025724 seconds and 4 git commands to generate.