Bladeren bron

Fix bug in sparse file listing

List posix archives containing sparse files >8GB correctly and do not fail.
This fixes also bug in format of listing for sparse files >8GB - now the
real size is printed instead of the effective one (this is not strictly
posix format related).

* src/list.c: Remove redundant assignment.
* src/tar.h: Add new 'real_size' and 'real_size_set' fields in
  tar_stat_info struct.
* src/xheader.c: Correctly handle (especially sparse) file sizes directly in
  xheader_decode().
Pavel Raiskup 12 jaren geleden
bovenliggende
commit
ec94fbdf45
3 gewijzigde bestanden met toevoegingen van 18 en 2 verwijderingen
  1. 0 1
      src/list.c
  2. 4 0
      src/tar.h
  3. 14 1
      src/xheader.c

+ 0 - 1
src/list.c

@@ -689,7 +689,6 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
 	}
     }
 
-  stat_info->archive_file_size = stat_info->stat.st_size;
   xheader_decode (stat_info);
 
   if (sparse_member_p (stat_info))

+ 4 - 0
src/tar.h

@@ -327,6 +327,10 @@ struct tar_stat_info
   size_t sparse_map_size;   /* Size of the sparse map */
   struct sp_array *sparse_map;
 
+  off_t real_size;          /* The real size of sparse file */
+  int   real_size_set;      /* True when GNU.sparse.realsize is set in
+			       archived file */
+
   size_t xattr_map_size;   /* Size of the xattr map */
   struct xattr_array *xattr_map;
 

+ 14 - 1
src/xheader.c

@@ -755,6 +755,16 @@ xheader_decode (struct tar_stat_info *st)
 	continue;
     }
   run_override_list (keyword_override_list, st);
+
+  /* The archived (effective) file size is always set directly in tar header
+     field, possibly overridden by "size" extended header - in both cases,
+     result is now decoded in st->stat.st_size */
+  st->archive_file_size = st->stat.st_size;
+
+  /* The real file size (given by stat()) may be redefined for sparse
+     files in "GNU.sparse.realsize" extended header */
+  if (st->real_size_set)
+    st->stat.st_size = st->real_size;
 }
 
 static void
@@ -1360,7 +1370,10 @@ sparse_size_decoder (struct tar_stat_info *st,
 {
   uintmax_t u;
   if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
-    st->stat.st_size = u;
+    {
+      st->real_size_set = 1;
+      st->real_size = u;
+    }
 }
 
 static void