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 */