Reduce memory consuption when handling the -T option.

The commit cdb27293 made the -T option more flexible, but
incurred a very considerable memory overhead by storing
all file names in the argument array.  In case of very
big file lists this caused tar to run out of memory.  This
was reported by Christian Wetzel <wetzel@phoenix-pacs.de>
on March 14, 2013
(http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00018.html).

On the other hand, Michal Žeidl discovered that tar misfunctioned
when given empty file lists or lists with the trailing newline
misssing in the last entry.  This was reported by Pavel Raiskup
on July 23
(http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00009.html and
msg00010.html).

This change fixes both issues.

* src/common.h (name_add_file,request_stdin): New prototype.
(more_options): New prototype.
* src/names.c (NELT_FILE): New entry type.
(name_elt) <file>: New union member.
(name_add_file): New function.
(read_name_from_file): New function, a rewrite of
the same function from tar.c
(read_next_name,copy_name): New static functions.
(name_next_elt): Handle NELT_FILE entries.
* src/tar.c (request_stdin): Make extern.
(read_name_from_file,add_file_id)
(update_argv): Removed.
(parse_opt): Change handling of the -T option.
(more_options): New function.

* tests/T-null.at: Rewrite test.
* tests/T-zfile.at: New file.
* tests/T-nonl.at: New file.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.

* THANKS: Update.
This commit is contained in:
Sergey Poznyakoff
2013-08-04 18:22:02 +03:00
parent 8a834dfa10
commit 26538c9bfc
10 changed files with 367 additions and 227 deletions
+2
View File
@@ -44,6 +44,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
TESTSUITE_AT = \
T-empty.at\
T-null.at\
T-zfile.at\
T-nonl.at\
testsuite.at\
append.at\
append01.at\
+5 -6
View File
@@ -23,8 +23,8 @@
# Reported by: Karl Berry <karl@freefriends.org>
# References: <200610301353.k9UDr1O30680@f7.net>
AT_SETUP([files-from: empty entries])
AT_KEYWORDS([files-from empty])
AT_SETUP([empty entries])
AT_KEYWORDS([files-from empty-line])
AT_DATA([file-list],
[jeden
@@ -34,17 +34,16 @@ trzy
])
AT_TAR_CHECK([
AT_SORT_PREREQ
genfile --file jeden
genfile --file dwa
genfile --file trzy
tar cfvT archive ../file-list | sort
tar cfvT archive ../file-list
],
[0],
[dwa
jeden
[jeden
dwa
trzy
],
[],[],[],[ustar]) # Testing one format is enough
+62
View File
@@ -0,0 +1,62 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar 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 of the License, or
# (at your option) any later version.
#
# GNU tar 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, see <http://www.gnu.org/licenses/>.
# Tar malfunctioned when given a file list with the last line not ending
# in a newline.
#
# Reported by: Michal Žejdl <zejdl@suas.cz>
# References: <http://lists.gnu.org/archive/html/bug-tar/2013-07/msg00009.html>
AT_SETUP([entries with missing newlines])
AT_KEYWORDS([files-from nonewline nonl T-nonl])
AT_TAR_CHECK([
genfile --length=0 --file empty
AS_ECHO_N(c) > 1.nonl
echo d > 2.nonl
AS_ECHO_N(e) >> 2.nonl
touch a b c d e
AT_DATA([filelist],[a
b
])
tar cf archive -T empty -T 1.nonl -T 2.nonl -T filelist
tar tf archive
echo ==
tar cf archive -T 2.nonl -T empty -T filelist -T 1.nonl
tar tf archive
],
[0],
[c
d
e
a
b
==
d
e
a
b
c
],
[],[],[],[ustar])
AT_CLEANUP
+11 -13
View File
@@ -18,30 +18,28 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([files-from: 0-separated file without -0])
AT_SETUP([0-separated file without -0])
AT_KEYWORDS([files-from null T-null])
AT_DATA([expout],[jeden\ndwa
trzy
])
AT_TAR_CHECK([
AT_SORT_PREREQ
echo dwa > temp
echo jeden > temp
echo dwa >> temp
echo trzy >> temp
cat temp | tr '\n' '\0' > temp1
echo jeden > file-list
cat temp1 >> file-list
cat temp | tr '\n' '\0' > file-list
genfile -f "jeden
dwa" || AT_SKIP_TEST
genfile -f jeden
genfile -f dwa
genfile -f trzy
tar cfTv archive file-list | sort
tar cfTv archive file-list
],
[0],
[expout],
[jeden
dwa
trzy
],
[tar: file-list: file name read contains nul character
],[],[],[ustar]) # Testing one format is enough
+47
View File
@@ -0,0 +1,47 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2013 Free Software Foundation, Inc.
#
# This file is part of GNU tar.
#
# GNU tar 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 of the License, or
# (at your option) any later version.
#
# GNU tar 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, see <http://www.gnu.org/licenses/>.
AT_SETUP([empty file])
AT_KEYWORDS([files-from empty-file])
AT_TAR_CHECK([
genfile --length=0 --file empty
genfile --file a
genfile --file b
AT_DATA([valid],[a
b
])
tar cf archive -T empty -T valid
tar tf archive
echo "=="
tar cf archive -T valid -T empty
tar tf archive
],
[0],
[a
b
==
a
b
],
[],[],[],[ustar]) # Testing one format is enough
AT_CLEANUP
+2
View File
@@ -199,6 +199,8 @@ m4_include([opcomp06.at])
AT_BANNER([The -T option])
m4_include([T-empty.at])
m4_include([T-null.at])
m4_include([T-zfile.at])
m4_include([T-nonl.at])
AT_BANNER([Various options])
m4_include([indexfile.at])