...and here's a fix (not including the test).

On Mon, Sep 16, 2019 at 3:22 PM enh <[email protected]> wrote:
>
> here's the same test rebased on top of my previous test, which was
> committed in the meantime...
>
>
> On Sun, Sep 15, 2019 at 11:01 AM enh <[email protected]> wrote:
> >
> > (you beat me getting back to this...)
> >
> > On Sun, Sep 15, 2019 at 12:18 AM Rob Landley <[email protected]> wrote:
> > >
> > > On 9/13/19 8:17 PM, Rob Landley wrote:
> > > > I think what we need to do is add up the segments. (Which is what I 
> > > > thought it
> > > > _was_ doing, but my head cold has turned into dizzy+headache and I has 
> > > > a tired.)
> > > >
> > > > I can fix this when I feel better if you don't get to it.
> > >
> > > I pushed a patch. It only calls truncate() when it hits a zero length 
> > > segment
> > > (and only when lseek() didn't fail, so writing to a nonseekable output 
> > > shouldn't
> > > gratuitously fail at the truncate)
> >
> > (yeah, i hadn't thought about anything other than regular files.)
> >
> > >, and it uses the last offset+length as a
> > > sparse file as the display length.
> > >
> > > I think that fixes it?
> >
> > it fixes extraction, yes. i can confirm that i get the same results
> > for the motivating tar files with GNU and toybox tar now.
> >
> > but if you try the attached patch which adds a test for a sparse file
> > with a hole at the end, it passes with TEST_HOST=1 but fails otherwise
> > because i don't think we're adding the final entry?
> >
> > > Rob
From 66659273d846d8cc71712e974fb70ce63d8ba5e0 Mon Sep 17 00:00:00 2001
From: Elliott Hughes <[email protected]>
Date: Mon, 16 Sep 2019 15:55:57 -0700
Subject: [PATCH] tar: fix creation of tar files containing sparse files with
 holes at the end.

This fixes the new test.

Also fix the leak of TT.sparse for each new sparse file (twice, one each
for both addition and extraction).
---
 toys/posix/tar.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/toys/posix/tar.c b/toys/posix/tar.c
index c4bdc4b6..71f3c6d3 100644
--- a/toys/posix/tar.c
+++ b/toys/posix/tar.c
@@ -294,6 +294,8 @@ static int add_to_tar(struct dirtree *node)
       strncpy(hdr.gname, TT.group ? TT.group : gr->gr_name, sizeof(hdr.gname));
   }
 
+  free(TT.sparse);
+  TT.sparse = 0;
   TT.sparselen = 0;
   if (hdr.type == '0') {
     // Before we write the header, make sure we can read the file
@@ -304,28 +306,34 @@ static int add_to_tar(struct dirtree *node)
     }
     if (FLAG(S)) {
       long long lo, ld = 0, len = 0;
+      int i = 0;
 
       // Enumerate the extents
       while ((lo = lseek(fd, ld, SEEK_HOLE)) != -1) {
-        if (!(TT.sparselen&511))
-          TT.sparse = xrealloc(TT.sparse, (TT.sparselen+514)*sizeof(long long));
+        if (TT.sparselen < i+4)
+          TT.sparse = xrealloc(TT.sparse,(TT.sparselen+=512)*sizeof(long long));
         if (ld != lo) {
-          TT.sparse[TT.sparselen++] = ld;
-          len += TT.sparse[TT.sparselen++] = lo-ld;
+          TT.sparse[i++] = ld;
+          len += TT.sparse[i++] = lo-ld;
         }
         if (lo == st->st_size) {
-          if (TT.sparselen<=2) TT.sparselen = 0;
+          if (i<=2) i = 0;
           else {
             // Gratuitous extra entry for compatibility with other versions
-            TT.sparse[TT.sparselen++] = lo;
-            TT.sparse[TT.sparselen++] = 0;
+            TT.sparse[i++] = lo;
+            TT.sparse[i++] = 0;
           }
           break;
         }
-        if ((ld = lseek(fd, lo, SEEK_DATA)) < lo) ld = st->st_size;
+        // A hole at the end is represented by a zero-length run of data.
+        if ((ld = lseek(fd, lo, SEEK_DATA)) == -1) {
+          len += TT.sparse[i++] = st->st_size;
+          TT.sparse[i++] = 0;
+        }
       }
 
       // If there were extents, change type to S record
+      TT.sparselen = i;
       if (TT.sparselen) {
         hdr.type = 'S';
         lnk = (char *)&hdr;
@@ -620,6 +628,8 @@ static void unpack_tar(char *first)
 
       // Load 4 pairs of offset/len from S block, plus 21 pairs from each
       // continuation block, list says where to seek/write sparse file contents
+      free(TT.sparse);
+      TT.sparse = 0;
       TT.sparselen = 0;
       s = 386+(char *)&tar;
       *sparse = i = 0;
-- 
2.23.0.237.gc6a4ce50a0-goog

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to