Package: afio
Severity: important
Tags: patch

When the block size * block count equals to 2gb or more, afio corrupts the
archive by truncating all files larger than 2gb.

For example:

ls -l /test
5397843286 2009-03-02 15:15 test.tar.lzma
4889181497 2010-04-15 14:04 test2.tar.lzma

find /test | afio -o -v -M 50m -b32k -c65536 $tape
test -- okay
afio: "/test/test.tar.lzma": Cannot create cpio-compatible file header for this 
input
afio: "/dev/st0" [offset 100]: Continuing, archive will not be fully compatible 
with cpio or afio versions 2.4.7 and lower
afio: "/test/test.tar.lzma": Invalid argument
test/test.tar.lzma -- okay
afio: "/test/test2.tar.lzma": Invalid argument
test/test2.lzma -- okay
afio: "/dev/st0": Warning: Created archive is not fully compatible with cpio or 
afio versions 2.4.7 and lower.
afio: "/dev/st0": See the ARCHIVE PORTABILITY section of the manpage.

Then, restore fails as follows:

afio -i -M 50m -b32k -c65536  $tape
afio: "test/test.tar.lzma": No such file or directory
afio: "test/test2.tar.lzma": No such file or directory

We identified the problem to reside in the 'readall/outavail' functions, using
incorrect types when dealing with buffer sizes (such as uint instead of
size_t, etc -- obvious 32-64bit conversion issues).

A patch to fix this issue is attached.

Thanks
diff -ruN afio-2.5/afio.c afio-2.5-fixed/afio.c
--- afio-2.5/afio.c	2003-12-20 23:16:13.000000000 +0100
+++ afio-2.5-fixed/afio.c	2010-04-16 11:41:42.526397612 +0200
@@ -1055,10 +1055,10 @@
  * about read() elsewhere.
  */
 STATIC
-int readall(int fd, char *buf, unsigned int count)
+ssize_t readall(int fd, char *buf, unsigned int count)
 {
  ssize_t got;
- unsigned int totalgot;
+ size_t totalgot;
 
  totalgot=0;
  while(totalgot<count)
@@ -3671,11 +3671,11 @@
  * Index buffer space for archive output. Stores a buffer pointer
  * at a given location. Returns the number of bytes available.
  */
-STATIC uint
+STATIC size_t
 outavail (bufp)
      reg char **bufp;
 {
-  reg uint have;
+  reg size_t have;
 
   while ((have = bufend - bufidx) == 0)
     { 
@@ -3699,28 +3699,28 @@
      char *name;
      reg off_t size;
 {
-  reg uint chunk;
-  reg int got;
+  reg size_t chunk;
+  reg ssize_t got;
   reg int oops;
-  reg uint avail;
+  reg size_t avail;
   auto char *buf;
 
   oops = got = 0;
   while (size)
     {
       avail = outavail (&buf);
-      size -= (chunk = size < (off_t)avail ? (uint) size : avail);
+      size -= (chunk = size < (off_t)avail ? size : avail);
       if (oops == 0 && (got = readall (fd, buf, chunk)) < 0)
 	{
 	  oops = warn (name, syserr ());	  
 	  if(index(ignorewarnings,(int)'n')) warnings--;
 	  got = 0;
 	}
-      if ((uint)got < chunk)
+      if ((size_t)got < chunk)
 	{
 	  if (oops == 0)
 	    oops = warn (name, "Early EOF");
-	  while ((uint)got < chunk)
+	  while ((size_t)got < chunk)
 	    buf[got++] = '\0';
 	}
       outalloc (chunk);
diff -ruN afio-2.5/afio.h afio-2.5-fixed/afio.h
--- afio-2.5/afio.h	2003-12-20 14:59:42.000000000 +0100
+++ afio-2.5-fixed/afio.h	2010-04-16 11:27:38.486397478 +0200
@@ -447,7 +447,7 @@
 int options (int, char **, char *);
 VOIDFN out (char **);
 void outalloc (uint);
-uint outavail (char **);
+size_t outavail (char **);
 int outdata (int, char*, off_t);
 
 void outdatazip (int, char*, off_t); /* added KH */

Reply via email to