Hi guys,

When using -M option for creating multi volume archives, tar can produces bad archives (archives which tar cannot extracted again).

Whether archive is bad or good depends on behavior of used files systems. Using file systems which always happen to write entire tar record (10240 bytes) or nothing if they are out of space will produce correct archives. Example of such file systems are Linux's ext2 or Solaris's ZFS. On the other hand Solaris's UFS or VFAT on Linux are file systems which will very likely produce bad archives (write call typically succeed only partly when it's running out of space).

Example from Linux box (using VFAT):

[EMAIL PROTECTED]:~# mount | grep /mnt
/dev/loop1 on /mnt type vfat (rw)
[EMAIL PROTECTED]:~# df -h | grep /mnt
/dev/loop1            8.8M  8.8M     0 100% /mnt
[EMAIL PROTECTED]:~# tar -c -M -f /mnt/test.tar /usr/sbin/*
tar: Removing leading `/' from member names
Prepare volume #2 for `/mnt/test.tar' and hit return: n /test.tar.2
Prepare volume #2 for `/test.tar.2' and hit return:
[EMAIL PROTECTED]:~# tar -t -M -f /mnt/test.tar
usr/sbin/accept
usr/sbin/accessdb
[..]
Prepare volume #2 for `/mnt/test.tar' and hit return: n /test.tar.2
Prepare volume #2 for `/test.tar.2' and hit return:
tar: This volume is out of sequence
Prepare volume #2 for `/test.tar.2' and hit return:

---

Please mention message "This volume is out of sequence". It seems that tar will store entire tar record which was only partly written at the end of volume again at beginning of next volume.

This seems to be pretty much algorithm bug somewhere in tar. And it's also regression which appeared somewhere between tar version 1.13 and 1.14 (or at least version 1.13 can extract these archives).

Also it seems to be for years known issue:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=142052

While I don't know right solution for this I have created patch which will ensure that tar will always succeed in writing entire tar record. Patch is again version 1.17 and it can be applied to to latest version 1.20 as well. It basically truncates archive if write succeeds only partly.

Any idea where is exact problem? Where should we look? Better solution?

Thanks,

Petr

--- tar-1.17/src/system.c.orig	2007-04-03 23:39:45.000000000 +0200
+++ tar-1.17/src/system.c	2008-06-25 13:32:00.000000000 +0200
@@ -270,7 +270,25 @@
 size_t
 sys_write_archive_buffer (void)
 {
-  return rmtwrite (archive, record_start->buffer, record_size);
+  off_t length;
+  size_t ret = rmtwrite (archive, record_start->buffer, record_size);
+
+  if (!multi_volume_option || ret == record_size)
+    return ret;
+
+/*
+ * GNU tar seems to be creating bad multi volume archives when tar record
+ * is  split (write() doesn't write all data it was requested). This was
+ * tested to happen on UFS and it doesn't seem to happen on ZFS (or on Linux).
+ *
+ * Therefore this workaround will allow do writes only of whole requested data.
+ *
+ * Ideally GNU tar should create correct archive which can also extract.
+*/
+  length = lseek(archive, 0, SEEK_CUR);
+  ftruncate(archive, length - ret);
+  lseek(archive, 0, SEEK_END);
+  return 0;
 }
 
 #define	PREAD 0			/* read file descriptor from pipe() */

Reply via email to