Fix multivolume archive creation when volume length=record size.

* src/tar.c (decode_options): Do not allow volume length less
than record size.
* src/buffer.c (_gnu_flush_write): Compensate for the effect
of eventual flush_archive occurring in the middle of buffer
move.
Increment records_written only if _flush_write was able to write
something.
* tests/multiv06.at: New testcase.
* tests/Makefile.am, test/testsuite.at: Add tests/multiv06.at
This commit is contained in:
Sergey Poznyakoff
2008-07-24 18:16:08 +00:00
parent c9a7297a8a
commit 3af9cc0f15
7 changed files with 92 additions and 4 deletions

View File

@@ -1,3 +1,16 @@
2008-07-24 Sergey Poznyakoff <gray@gnu.org.ua>
* src/tar.c (decode_options): Do not allow volume length less
than record size.
* src/buffer.c (_gnu_flush_write): Compensate for the effect
of eventual flush_archive occurring in the middle of buffer
move.
Increment records_written only if _flush_write was able to write
something.
* tests/multiv06.at: New testcase.
* tests/Makefile.am, test/testsuite.at: Add tests/multiv06.at
2008-06-26 Sergey Poznyakoff <gray@gnu.org.ua>
* configure.ac, NEWS: Version 1.20.90

View File

@@ -1,7 +1,7 @@
/* Buffer management for tar.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
@@ -1599,13 +1599,15 @@ _gnu_flush_write (size_t buffer_level)
char *copy_ptr;
size_t copy_size;
size_t bufsize;
tarlong wrt;
status = _flush_write ();
if (status != record_size && !multi_volume_option)
archive_write_error (status);
else
{
records_written++;
if (status)
records_written++;
bytes_written += status;
}
@@ -1654,6 +1656,7 @@ _gnu_flush_write (size_t buffer_level)
if (real_s_name)
add_chunk_header ();
wrt = bytes_written;
header = find_next_block ();
bufsize = available_space_after (header);
while (bufsize < copy_size)
@@ -1668,6 +1671,16 @@ _gnu_flush_write (size_t buffer_level)
memcpy (header->buffer, copy_ptr, copy_size);
memset (header->buffer + copy_size, 0, bufsize - copy_size);
set_next_block_after (header + (copy_size - 1) / BLOCKSIZE);
if (multi_volume_option && wrt < bytes_written)
{
/* The value of bytes_written has changed while moving data;
that means that flush_archive was executed at least once in
between, and, as a consequence, copy_size bytes were not written
to disk. We need to update sizeleft variables to compensate for
that. */
save_sizeleft += copy_size;
multi_volume_sync ();
}
find_next_block ();
}

View File

@@ -1041,7 +1041,7 @@ dump_regular_file (int fd, struct tar_stat_info *st)
while (size_left > 0)
{
size_t bufsize, count;
mv_size_left (size_left);
blk = find_next_block ();

View File

@@ -2324,6 +2324,9 @@ decode_options (int argc, char **argv)
else if (utc_option)
verbose_option = 2;
if (tape_length_option && tape_length_option < record_size)
USAGE_ERROR ((0, 0, _("Volume length cannot be less than record size")));
/* Forbid using -c with no input files whatsoever. Check that `-f -',
explicit or implied, is used correctly. */

View File

@@ -89,6 +89,7 @@ TESTSUITE_AT = \
multiv03.at\
multiv04.at\
multiv05.at\
multiv06.at\
old.at\
options.at\
options02.at\

57
tests/multiv06.at Normal file
View File

@@ -0,0 +1,57 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2008 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# When volume size equals record size, swapping buffers in
# new_volume triggers a call to flush_archive. The size left variables
# must be corrected after that, which was not done in versions <= 1.20.
# Reported by: Marek Kielar <mkielar@go2.pl>
# References: <1907cbb6.79e32b49.48887f09.fd55@o2.pl>
AT_SETUP([Multivolumes with L=record_size])
AT_KEYWORDS([multivolume multiv multiv06])
m4_define([echo2],[
echo $*
echo >&2 $*
])
AT_TAR_CHECK([
exec <&-
echo2("Creating file")
genfile --length 20139 --file file
echo2("Creating archive")
tar -c -M -L10 -b20 -farc.1 -farc.2 -farc.3 file
echo2("Testing archive")
tar -t -M -farc.1 -farc.2 -farc.3],
[0],
[Creating file
Creating archive
Testing archive
file
],
[Creating file
Creating archive
Testing archive
],
[],[],
[gnu, pax])
AT_CLEANUP

View File

@@ -155,6 +155,7 @@ m4_include([multiv02.at])
m4_include([multiv03.at])
m4_include([multiv04.at])
m4_include([multiv05.at])
m4_include([multiv06.at])
m4_include([old.at])