532 Commits

Author SHA1 Message Date
Sergey Poznyakoff
b94eed6d03 Version 1.20.
* configure.ac: Raise version number to 1.20
* src/compare.c (diff_dumpdir): const.
* src/common.h (dumpdir_t,dumpdir_iter_t): New data types.
(dumpdir_create0,dumpdir_create,dumpdir_free,dumpdir_locate)
(dumpdir_first,dumpdir_next): New functions.
* src/incremen.c (dumpdir_create0,dumpdir_create,dumpdir_free)
(dumpdir_first,dumpdir_next): New functions.
(dumpdir_locate): Rewrite using binary search.
(struct directory): Change members char *contents, *icontents to
struct dumpdir *dump, *idump. All references updated.
(note_directory): Last arg is const.
* src/names.c (add_hierarchy_to_namelist): buffer is const.
* tests/incr03.at, tests/incr04.at, tests/rename02.at,
tests/rename03.at: Insert calls to sleep between creation of files
and adding them to the archive.
2008-05-05 21:30:57 +00:00
Sergey Poznyakoff
192860abb8 Update 2008-03-31 08:03:00 +00:00
Sergey Poznyakoff
c2d2e806a1 (dump_file0): Count links only for actually dumped files 2008-03-31 08:02:53 +00:00
Sergey Poznyakoff
2a89f7a0a8 * NEWS: Document --no-check-device and --check-device.
* doc/rendition.texi: Change the way FIXME-*refs are handled in
!PROOF.
* doc/intern.texi, doc/tar.texi: Update.
* doc/untabify.el: New file.
* doc/Makefile.am (EXTRA_DIST): Add untabify.el
(untabify, final, check-format, check-refs, check-fixmes)
(check-unrevised, all-check-docs, check-docs): New rules.
2008-03-27 10:11:05 +00:00
Sergey Poznyakoff
71d2a66f42 * src/common.h (check_device_option): New global.
* src/incremen.c (procdir): Use boolean and instead of bitwise
one. Patch by Jean-Louis Martineau.
Compare device numbers only if check_device_option is set.
* src/tar.c: New command line options --no-check-device and
--check-device. Proposed by Jean-Louis Martineau.
(parse_opt): Hanlde new options.
(decode_options): Initialize check_device_option to true.
2008-03-27 08:56:26 +00:00
Sergey Poznyakoff
e496c1b529 * bootstrap: Use rsync to get translations.
* doc/tar.texi: Minor change.
* lib/.cvsignore: Update
* po/.cvsignore: Update
* src/system.c: Remove include setenv.h.
* tests/atlocal.in (STAR_DATA_URL): Update.
* tests/star/README: Update URL.
2008-03-06 08:17:33 +00:00
Sergey Poznyakoff
6667fa7fb8 Update 2008-02-09 10:36:40 +00:00
Sergey Poznyakoff
a16ad3112e Fix a typo 2008-02-09 10:35:55 +00:00
Sergey Poznyakoff
7efe3850f6 * NEWS: Update.
* configure.ac: Version 1.19.90
* po/POTFILES.in: Add missing files.
* src/compare.c (verify_volume): Honor --ignore-zeros.
Proposed by Jan-Benedict Glaw.
* tests/shortfile.at (AT_KEYWORDS): Add shortfile0.
2008-02-08 14:12:22 +00:00
Sergey Poznyakoff
d0694ee604 Update the description 2008-02-08 10:32:15 +00:00
Sergey Poznyakoff
37f0faf1c0 (dump_file0): Apply transform_name to symlink targets. 2008-02-07 15:46:41 +00:00
Sergey Poznyakoff
b893aee6d2 Update 2008-02-07 15:46:28 +00:00
Sergey Poznyakoff
f60d655908 Update 2008-02-04 10:39:05 +00:00
Sergey Poznyakoff
549481a0a7 Update 2008-02-04 10:38:27 +00:00
Sergey Poznyakoff
e08afc2002 Document changes to the --transform option. 2008-02-04 10:38:18 +00:00
Sergey Poznyakoff
338591a486 Support multiple --transform options. Support semicolon-separated lists of replace expressions. 2008-02-04 10:35:20 +00:00
Paul Eggert
c0e0d06e69 * doc/tar.texi: Update Back-Cover text to reflect new GNU wording.
2007-12-17  Paul Eggert  <eggert@cs.ucla.edu>

Exit with nonzero status if a close fails on an archive.
Problem (and initial trivial fix)
* src/buffer.c (close_archive, new_volume): close_error, not close_warn.
2008-01-31 00:50:12 +00:00
Sergey Poznyakoff
6e85425618 Update 2007-12-05 09:48:37 +00:00
Sergey Poznyakoff
336519aa4f Add shortupd.at. 2007-12-05 09:45:35 +00:00
Sergey Poznyakoff
5f4d99491d (check_compressed_archive): Do not bail out if the
file is too short, set boolean flag, passed as an argument
instead.  This fixes a bug introduced on 2007-08-24. See also
tests/shortupd.at.
2007-12-05 09:45:22 +00:00
Paul Eggert
48d83be336 Don't read from name[-1].
* src/incremen.c (make_directory): Handle namelen == 0, since
find_directory_meta calls make_directory ("").
2007-11-13 07:01:26 +00:00
Sergey Poznyakoff
60d351cc5a Update 2007-11-07 08:48:39 +00:00
Sergey Poznyakoff
e33be3d0a1 Add fseeko and snprintf. 2007-11-07 08:48:28 +00:00
Sergey Poznyakoff
32562b9412 (checkout): Use URL of the gnulib CVS mirror. 2007-11-07 08:48:19 +00:00
Sergey Poznyakoff
dfd87ba1d0 (magic): Fix lzma option 2007-10-31 13:10:55 +00:00
Sergey Poznyakoff
5d4a682a55 Update 2007-10-31 12:57:04 +00:00
Sergey Poznyakoff
8e3a2a520d (sys_exec_info_script,sys_exec_checkpoint_script): pass the current blocking factor in TAR_BLOCKING_FACTOR environment variable. 2007-10-31 12:56:46 +00:00
Sergey Poznyakoff
745832a280 New actions: bell and ttyout 2007-10-31 12:56:27 +00:00
Sergey Poznyakoff
458efab23b Minor fix 2007-10-30 14:58:52 +00:00
Sergey Poznyakoff
23dcaa117f Update 2007-10-30 14:09:20 +00:00
Sergey Poznyakoff
5099ddf6cc Document --hard-dereference and --checkpoint-action options. Improve documentation of --check-links. 2007-10-30 14:09:04 +00:00
Sergey Poznyakoff
8476145508 Use texi2html and the CVS version of gendocs.sh to create HTML versions of the manual 2007-10-30 14:08:41 +00:00
Sergey Poznyakoff
362492fe70 Use texi2html and the CVS version of gendocs.sh to create HTML versions of the manual 2007-10-30 14:08:21 +00:00
Sergey Poznyakoff
7111008659 Update 2007-10-29 16:57:32 +00:00
Sergey Poznyakoff
ec4741d732 (parse_opt): New options --hard-dereference, --checkpoint-action.
(decode_options): Call checkpoint_finish_compile.
2007-10-29 16:56:56 +00:00
Sergey Poznyakoff
bed7de0271 (sys_exec_checkpoint_script): New function.
(sys_exec_info_script): Restore SIGPIPE handler.
2007-10-29 16:56:33 +00:00
Sergey Poznyakoff
eaaadcfd36 (file_count_links): do nothing if hard_dereference_option is set. 2007-10-29 16:56:13 +00:00
Sergey Poznyakoff
a8830fbb86 (enum checkpoint_style): Remove.
(checkpoint_style): Remove.
(DEFAULT_CHECKPOINT): New define.
(hard_dereference_option): New variable.
(sys_exec_checkpoint_script): New declaration.
2007-10-29 16:55:58 +00:00
Sergey Poznyakoff
848659f1c6 (checkpoint, do_checkpoint): Remove.
(_flush_write, simple_flush_read, _gnu_flush_read): Use
checkpoint_run.
2007-10-29 16:55:37 +00:00
Sergey Poznyakoff
17cbd4862c checkpoint handling 2007-10-29 16:55:16 +00:00
Sergey Poznyakoff
64ded9e702 (tar_SOURCES): add checkpoint.c 2007-10-29 16:54:51 +00:00
Sergey Poznyakoff
ccd0a527e4 Version 1.19.1 2007-10-29 16:54:38 +00:00
Sergey Poznyakoff
3f869877a4 Version 1.19.1 2007-10-29 16:53:28 +00:00
Sergey Poznyakoff
8c528937a9 Update 2007-10-29 16:53:20 +00:00
Sergey Poznyakoff
460f4ec146 Update 2007-10-29 08:53:58 +00:00
Sergey Poznyakoff
eb59c14a1f (sys_exec_info_script): Initialize buf. Problem reported by Bengt-Arne Fjellner. 2007-10-29 08:51:46 +00:00
Paul Eggert
3c4f4ca423 Avoid compiler warnings.
* src/list.c (read_header_primitive): Define two locals, to
avoid incorrect "may be used uninitialized" warnings.
* src/incremen.c (procdir): Remove decl of unused local, "len".

expired.
SCALAR(0x830b08c)
2007-10-18 21:36:38 +00:00
Sergey Poznyakoff
506b4db5d0 Update 2007-10-18 07:59:48 +00:00
Sergey Poznyakoff
5bfb6c5f9d (gzip): Remove compression patent warning. According to Brett Smith, the patent is expired. 2007-10-18 07:59:39 +00:00
Sergey Poznyakoff
3725b5606f Update 2007-10-17 09:12:54 +00:00
Sergey Poznyakoff
d1a7eebc30 Update 2007-10-17 09:12:03 +00:00
Sergey Poznyakoff
dfe280dcca Add Lasse Collin and Jean-Pierre Demailly. 2007-10-17 09:11:50 +00:00
Sergey Poznyakoff
620a136e74 New options --auto-compress (-a) and --lzma 2007-10-17 09:11:34 +00:00
Sergey Poznyakoff
3fb5d67b28 (set_comression_program_by_suffix): New prototype. 2007-10-17 09:11:23 +00:00
Sergey Poznyakoff
c30a794679 (magic): Add an entry for new lzma format. Proposed by Lasse Collin 2007-10-17 09:11:08 +00:00
Sergey Poznyakoff
00bb0d8f5c Add suffix.c 2007-10-17 09:10:46 +00:00
Sergey Poznyakoff
af3e05b6af New file. Determine compression algorithm by archive file name suffix. Suggested by Jean-Pierre Demailly. 2007-10-17 09:10:34 +00:00
Paul Eggert
6060d613d1 * src/utf8.c (string_ascii_p): Recode to avoid bogus GCC 4.2.1
warning about "comparison is always true due to limited range of
data type" when char is unsigned.
2007-10-13 05:49:18 +00:00
Paul Eggert
3f12066739 Adjust to recent gnulib changes.
* configure.ac: Dont' check for strerror, since gnulib now does this.
* .cvsignore: Add m4, tar-[0-9]*.
* lib/.cvsignore: Adjust to various gnulib file name changes.
Add .deps, rmt-command.h.

SCALAR(0x830b0dc)
directories.

SCALAR(0x831ad2c)
2007-10-11 22:04:44 +00:00
Sergey Poznyakoff
3b74fbfc3b Update 2007-10-10 11:04:25 +00:00
Sergey Poznyakoff
14d39a2c14 Update 2007-10-10 11:03:42 +00:00
Sergey Poznyakoff
7b57922073 Version 1.19 2007-10-10 11:03:14 +00:00
Sergey Poznyakoff
05c6da4c62 Update 2007-10-05 11:21:40 +00:00
Sergey Poznyakoff
4ece30109d (dump_regular_file): Fix file padding in case of truncation to zero size. 2007-10-05 11:20:27 +00:00
Sergey Poznyakoff
55f1eadbf2 Update 2007-10-04 07:16:52 +00:00
Sergey Poznyakoff
9b22262fc6 Use AT_DATA for sample output. 2007-10-04 07:16:39 +00:00
Sergey Poznyakoff
2de140fa95 Update 2007-10-03 20:18:47 +00:00
Sergey Poznyakoff
6f6864df13 (try_purge_directory): Ensure that arguments to T and R are safe. 2007-10-03 20:18:32 +00:00
Sergey Poznyakoff
519a7c0c75 Update 2007-09-29 00:48:08 +00:00
Sergey Poznyakoff
1ef212d0fb (obstack_code_rename): Apply safer_name_suffix to name arguments before storing them in T and R records. Reported by Nicholas Cole. 2007-09-29 00:47:59 +00:00
Sergey Poznyakoff
333780b227 Update 2007-09-27 09:16:38 +00:00
Sergey Poznyakoff
2c56ca0e7f Raise version number to 1.18.90 2007-09-27 09:16:24 +00:00
Sergey Poznyakoff
63f8de655b Update 2007-09-27 08:05:38 +00:00
Sergey Poznyakoff
2743e1ba5b Document version 2 2007-09-27 08:05:31 +00:00
Sergey Poznyakoff
40ece6bf4d Update 2007-09-26 22:08:51 +00:00
Sergey Poznyakoff
63e835f5c0 New option --exclude-vcs
(exclude_vcs_files): New function
2007-09-26 22:08:36 +00:00
Sergey Poznyakoff
efe6609cd9 (struct directory): New member tagfile
(make_directory): Initialize tagfile to NULL
(procdir): New argument: entry
Hanlde exclusion tags.
(makedumpdir): Take into account directory->tagfile.
(scan_directory): Hanlde exclusion tags.
2007-09-26 22:08:13 +00:00
Sergey Poznyakoff
b0d5935cb0 (exclusion_tag_warning, check_exclusion_tags): Remove static qualifier.
(check_exclusion_tags): account for dirname without terminating
slash.
(dump_dir0): exclusion_tag_all is handled elsewhere.
2007-09-26 22:07:44 +00:00
Sergey Poznyakoff
a1b1b7cc8a (exclusion_tag_warning, check_exclusion_tags): New prototypes 2007-09-26 22:06:43 +00:00
Sergey Poznyakoff
8940247418 Update 2007-09-26 22:06:24 +00:00
Paul Eggert
0dacafbbb0 * AUTHORS: Remove unnecessary information. Just list the
principal authors.
* THANKS: Remove info duplicated from AUTHORS.

SCALAR(0x82892dc)


SCALAR(0x8279918)

SCALAR(0x8289444)


stripping and name suffix normalization.
2007-09-14 21:00:37 +00:00
Sergey Poznyakoff
e3e50c987b Minor rewording 2007-09-08 08:49:35 +00:00
Sergey Poznyakoff
923f0cda43 Update 2007-08-26 09:02:09 +00:00
Sergey Poznyakoff
c485b7984d (apply_nonancestor_delayed_set_stat): Rename st->sb to avoid shadowing another local. 2007-08-26 09:01:38 +00:00
Sergey Poznyakoff
d769b724f4 (diff_dumpdir): Rename stat->stat_data to avoid shadowing the syscall. 2007-08-26 09:01:08 +00:00
Sergey Poznyakoff
a0eb52da3f (check_exclusion_tags): Remove declaration of unused local, "ret". 2007-08-26 08:59:28 +00:00
Sergey Poznyakoff
87ac3207fb Don't include <getline.h>. No longer needed. 2007-08-26 08:59:08 +00:00
Sergey Poznyakoff
c634f2c6f1 Raise version number to 1.18.1 2007-08-24 12:23:19 +00:00
Sergey Poznyakoff
5416153391 Update 2007-08-24 12:08:58 +00:00
Sergey Poznyakoff
5bb69a88d8 Add shortfile.at 2007-08-24 12:08:47 +00:00
Sergey Poznyakoff
0a848ff669 New test case for the today's change in src/buffer.c (1.111) 2007-08-24 12:08:35 +00:00
Sergey Poznyakoff
7c0b81cbb9 (check_compressed_archive): Detect files smaller than 512 bytes. 2007-08-24 12:07:32 +00:00
Sergey Poznyakoff
862770bf91 Update 2007-08-19 09:17:32 +00:00
Sergey Poznyakoff
89d682d0b9 Gnulib initialization destroyed paxutils m4 files.
Initialize paxutils structure after that of gnulib.
2007-08-19 09:17:21 +00:00
Sergey Poznyakoff
764174dc1d Update 2007-08-12 08:25:35 +00:00
Sergey Poznyakoff
5ab30f709a (symlink_to_gnulib): Make sure the target directory exists and create it if it does not. 2007-08-12 08:25:27 +00:00
Sergey Poznyakoff
e2b8c8fa9f (contains_dot_dot): Fix double-dot recognition in case of duplicate /. Patch by Dmitry V. Levin. 2007-08-12 08:25:00 +00:00
Sergey Poznyakoff
42250f5010 Update 2007-08-12 07:15:11 +00:00
Sergey Poznyakoff
62571aa7c3 Fix a typo 2007-08-12 07:14:29 +00:00
Sergey Poznyakoff
32f7047037 Update 2007-06-29 20:23:05 +00:00
Sergey Poznyakoff
a69be0adce Add to the repository 2007-06-29 20:22:48 +00:00
Sergey Poznyakoff
1fb35e7374 Final update for GPLv3 2007-06-29 20:20:02 +00:00
Sergey Poznyakoff
7e69b14775 Update 2007-06-28 17:01:18 +00:00
Sergey Poznyakoff
625c45d304 Update for the change of the TP URL 2007-06-28 17:00:35 +00:00
Sergey Poznyakoff
3fe0f0d7f8 Update 2007-06-27 14:06:55 +00:00
Sergey Poznyakoff
c3d4fee823 Restore after an accidental remove 2007-06-27 13:46:15 +00:00
Sergey Poznyakoff
a0fb51e136 Relicense under GPLv3 2007-06-27 13:30:12 +00:00
Sergey Poznyakoff
ac8690fc4e Update copyright year 2007-06-21 08:52:22 +00:00
Sergey Poznyakoff
395df04927 Update 2007-06-21 08:51:15 +00:00
Sergey Poznyakoff
89a91c7b44 Skip test if genfile is unable to create the file 2007-06-21 08:51:03 +00:00
Sergey Poznyakoff
5635a428ab (AT_TAR_MKHIER): Skip test if genfile is unable to create the file 2007-06-21 08:50:09 +00:00
Sergey Poznyakoff
8b5f10a6c4 Resolve testsuite failures 40-42 on cygwin. 2007-06-21 07:12:09 +00:00
Sergey Poznyakoff
6e98015774 Update 2007-06-16 12:10:24 +00:00
Sergey Poznyakoff
bd13e18a63 Add back write permissions on dir 2007-06-16 12:10:14 +00:00
Sergey Poznyakoff
01cf5c5315 New file 2007-06-16 12:09:59 +00:00
Sergey Poznyakoff
0dd814fac2 (Fixing Snapshot Files): New appendix 2007-06-16 12:09:50 +00:00
Sergey Poznyakoff
b27b516b68 (tar_TEXINFOS): Add tar-snapshot-edit.texi 2007-06-16 12:09:34 +00:00
Sergey Poznyakoff
c7f69c265b Update 2007-06-09 17:07:54 +00:00
Sergey Poznyakoff
bc00f45420 Sort the output 2007-06-09 17:07:46 +00:00
Paul Eggert
57304e8b0a Fix typo: occurence -> occurrence. 2007-06-08 18:49:19 +00:00
Sergey Poznyakoff
d3f04456e8 Raise version number to 1.17 2007-06-08 09:34:18 +00:00
Sergey Poznyakoff
d78083e82c Update 2007-06-08 08:27:40 +00:00
Sergey Poznyakoff
c8d4ceccc1 (Operation Summary): Restore alphabetical order of the options. 2007-06-08 08:27:32 +00:00
Sergey Poznyakoff
6287d3045f Update 2007-06-08 08:15:41 +00:00
Sergey Poznyakoff
9d3142805b s/(ASCII|ID|BSD)/@acronym{&}/;s/"[^"]+"/``&''/
Use `path' only when it refers to search paths, use
`file name' otherwise.
Fix various errors (based on patch by Benno Schulenberg)
2007-06-08 08:14:12 +00:00
Sergey Poznyakoff
05eddc1a58 Update testsuite 2007-06-01 21:57:30 +00:00
Sergey Poznyakoff
78bfbb5661 Update 2007-06-01 21:24:41 +00:00
Sergey Poznyakoff
fe576585e6 (decode_xform): Exempt symbolic links from component
stripping and name suffix normalization.
2007-06-01 21:24:30 +00:00
Sergey Poznyakoff
080a6b2ac5 Update calls to transform_member_name 2007-06-01 21:24:08 +00:00
Sergey Poznyakoff
f236f33643 (xform_type): New data type
(transform_member_name): Last argument is of xform_type type
All callers updated
2007-06-01 21:23:53 +00:00
Sergey Poznyakoff
a4ffcfb875 Update 2007-05-30 19:15:32 +00:00
Sergey Poznyakoff
967fcb9318 (decx): Unknown pax keywords produce a warning,not error. 2007-05-30 19:15:17 +00:00
Paul Eggert
12b3a5d5b1 * src/misc.c (set_file_atime): Use gl_futimens, not futimens,
due to gnulib change.

SCALAR(0x828a248)

SCALAR(0x828a404)
2007-05-29 16:48:23 +00:00
Sergey Poznyakoff
eeb610da48 Update 2007-05-19 17:04:34 +00:00
Sergey Poznyakoff
749e20e6fa Update 2007-05-19 17:03:59 +00:00
Sergey Poznyakoff
56f6556f94 (tarball_prereq): Discard eventual md5sum output. 2007-05-19 17:03:44 +00:00
Sergey Poznyakoff
43c5343194 Minor fix 2007-05-19 17:03:35 +00:00
Sergey Poznyakoff
250db35f17 Global extended_header removed, use new xheader calls instead. 2007-05-19 17:03:28 +00:00
Sergey Poznyakoff
6f929b2c89 (buffer_write_global_xheader): New function
Update to use new xheader calls.
2007-05-19 17:03:01 +00:00
Sergey Poznyakoff
64cddf2fbc (xheader_init): New function
(xheader_decode_global,xheader_store,xheader_read)
(xheader_write_global,xheader_write,xheader_string_begin)
(xheader_string_add,xheader_string_end): Take xhdr as first
argument.
2007-05-19 17:02:46 +00:00
Sergey Poznyakoff
ccdbafb276 (struct xheader): New definition
(struct tar_stat_info): New member xhdr (extended header).
2007-05-19 17:02:29 +00:00
Sergey Poznyakoff
bd222d606a (buffer_write_global_xheader): New function
(struct xheader): Move definition to tar.h
(extended_header): Remove global
(xheader_init): New function
(xheader_decode_global,xheader_store,xheader_read)
(xheader_write_global,xheader_write,xheader_string_begin)
(xheader_string_add,xheader_string_end): Take xhdr as first
argument.
2007-05-19 17:02:13 +00:00
Sergey Poznyakoff
94fb06f5db Fix typos 2007-05-18 09:14:54 +00:00
Sergey Poznyakoff
74d217db74 Update 2007-05-18 08:22:33 +00:00
Sergey Poznyakoff
17ef61b2fd (dump_file0): Original ctime cannot be used as a directory change indicator if --remove-files is given. 2007-05-18 08:22:21 +00:00
Paul Eggert
f32828d577 Adjust to latest Gnulib.
* lib/.cvsignore: Add dirfd.c, dirfd.h, float+.h, mbscasecmp.c,
stdio.h, stdio_.h, stdlib.h, stdlib_.h, time.h, time_.h, unistd.h.
Remove exit.h, getcwd.h, mempcpy.h, memrchr.h, mkdtemp.h, stpcpy.h,
strcase.h, strchrnul.h, strdup.h, strndup.h, strnlen.h, time_r.h,
vsnprintf.h.
* m4/.cvsignore: Remove localedir.h.  Sort.
2007-04-13 00:51:07 +00:00
Sergey Poznyakoff
e67e085421 Update 2007-04-03 21:52:52 +00:00
Sergey Poznyakoff
ca856c2585 (main): Don't call closeopen. 2007-04-03 21:52:42 +00:00
Sergey Poznyakoff
18641602c1 Don't include <sys/time.h>, <sys/resource.h>; no longer needed. 2007-04-03 21:52:20 +00:00
Sergey Poznyakoff
8bdbc08a89 (closeopen): Remove decl. 2007-04-03 21:52:01 +00:00
Sergey Poznyakoff
a5d5cc599f Update 2007-04-03 21:38:40 +00:00
Sergey Poznyakoff
761895d43c Update 2007-04-03 21:38:14 +00:00
Sergey Poznyakoff
5d4f057e31 (sys_exec_info_script): Store the inter-communication fd in the environment variable TAR_FD 2007-04-03 21:38:00 +00:00
Sergey Poznyakoff
7c0ba663c8 Update 2007-04-03 12:31:24 +00:00
Sergey Poznyakoff
51118be241 Expect a warning on stderr 2007-04-03 12:30:43 +00:00
Sergey Poznyakoff
69f5d77383 Update 2007-04-03 12:18:53 +00:00
Sergey Poznyakoff
d989864712 (main): Move closeopen after decode_options to allow shell process substitution to work. 2007-04-03 12:18:40 +00:00
Sergey Poznyakoff
983d328ff2 Restore accidentally deleted lines 2007-03-30 19:28:22 +00:00
Sergey Poznyakoff
586c684815 (transform_name_fp): Change signature. All callers updated. 2007-03-30 19:20:52 +00:00
Sergey Poznyakoff
bbf7dec45e Fix indentation 2007-03-30 19:19:56 +00:00
Sergey Poznyakoff
40f79286ab Update 2007-03-30 19:18:46 +00:00
Sergey Poznyakoff
ebc522d521 (all_names_found): Remove check for matching_flags. 2007-03-30 19:18:35 +00:00
Sergey Poznyakoff
ad85f632c6 (transform_member_name): New function
(decode_header): Use transform_member_name
2007-03-30 19:18:24 +00:00
Sergey Poznyakoff
062b37115f (extract_link, extract_symlink): Use
transform_member_name instead of safer_name_suffix so that
--transform and --strip-components affect links as well.
2007-03-30 19:18:10 +00:00
Sergey Poznyakoff
6261c58ae8 (transform_name_fp): Change signature
(transform_member_name): New function
2007-03-30 19:17:44 +00:00
Sergey Poznyakoff
427bda01a3 Update 2007-03-30 08:50:21 +00:00
Sergey Poznyakoff
1d26fff0f3 Do not include mkdtemp.h 2007-03-30 08:50:08 +00:00
Sergey Poznyakoff
bb6b92e37d (slurp): Remove any occurrences of $bt from the generated gnulib.mk 2007-03-30 08:49:56 +00:00
Sergey Poznyakoff
8ca4064a8c Update 2007-03-30 08:49:38 +00:00
Paul Eggert
5c890a6003 Adjust to recent gnulib changes.
* lib/.cvsignore: Add fchownat.c, rmt-command.h, strerror.c, string.h,
string_.h, sys, sys_time_.h, unistd_.h, wchar_.h, wctype_.h.
Remove localedir.h, size_max.h, xsize.h.
* src/xheader.c: Don't include stpcpy.h; no longer needed, now that
gnulib string.h defines stpcpy on all platforms.
2007-01-26 23:02:40 +00:00
Sergey Poznyakoff
3705fd6452 Update 2007-01-23 10:26:40 +00:00
Sergey Poznyakoff
bde442ba15 Add exclude.at 2007-01-23 10:26:30 +00:00
Sergey Poznyakoff
c9a8f1bc33 New test case 2007-01-23 10:26:20 +00:00
Sergey Poznyakoff
66e9b9cd6c New options --exclude-caches-all, --exclude-caches-under, --exclude-tag-all, --exclude-tag-under 2007-01-23 10:25:21 +00:00
Sergey Poznyakoff
b9588c4722 (struct exclude_tag): rename to exclusion_tag
(check_exclusion_tags): New function
(cachedir_file_p): New function (from check_cache_directory)
(dump_dir0,dump_file0): Use check_exclusion_tags
2007-01-23 10:25:06 +00:00
Sergey Poznyakoff
9a41b3b3db (exclude_caches_option): Remove
(enum exclusion_tag_type): New data type
(add_exclude_tag): Rename to add_exclusion_tag
(cachedir_file_p): New prototype
2007-01-23 10:24:43 +00:00
Sergey Poznyakoff
990e7d4437 Document --exclude-caches* and --exclude-tag* options. 2007-01-23 10:24:19 +00:00
Sergey Poznyakoff
173d3229e3 Update 2007-01-19 15:43:13 +00:00
Sergey Poznyakoff
2d261da8f9 Version 1.16.2 2007-01-19 15:42:43 +00:00
Sergey Poznyakoff
99527fa17b (sparse_skip_file,pax_dump_header_1)
(pax_decode_header): Keep track of the number of bytes written.
2007-01-19 15:42:26 +00:00
Sergey Poznyakoff
868ee74028 (expand_sparse): use ftruncate to handle the trailing hole 2007-01-19 15:41:55 +00:00
Sergey Poznyakoff
8c90bf0414 Fix typos 2007-01-19 15:41:39 +00:00
Sergey Poznyakoff
892cdea8a1 Require strerror 2007-01-19 15:41:32 +00:00
Sergey Poznyakoff
00763876f1 Update 2007-01-04 20:06:33 +00:00
Sergey Poznyakoff
1a1cfaafa6 (list_dumpdir): Minor fixes. 2007-01-04 20:05:32 +00:00
Sergey Poznyakoff
445d95be07 (diff_dumpdir): Compare directory contents using
dumpdir_cmp.  Do not free dumpdir_buffer, it will leave the
incremental directory table in the inconsistent state and trigger
full dump.
(read_and_process): Process dumpdirs no matter what the archive
format.
2007-01-04 20:05:05 +00:00
Sergey Poznyakoff
6fe55234c9 Update 2007-01-04 16:16:00 +00:00
Sergey Poznyakoff
e24d8574a8 (read_and_process): Fix type of "size" 2007-01-04 16:15:10 +00:00
Sergey Poznyakoff
4da5205ed6 Update 2006-12-13 08:22:18 +00:00
Sergey Poznyakoff
8241687465 Skip the test if genfile is not able to create the filename with an embedded newline. 2006-12-13 08:22:04 +00:00
Paul Eggert
8e3f3adf98 Port to Forte Developer 7 C 5.4 and C99.
* src/common.h (add_exclude_tag): Add decl; C99 requires this
and Forte warns about it.
* src/incremen.c: Include <mkdtemp.h> for mkdtemp prototype,
for same reason.
* src/misc.c (get_max_open_files): Rewrite to avoid code that
Forte C complains about as being unreachable.
* src/xheader.c (mtime_code): Rewrite to avoid Forte error
reported by Trond Hasle Amundsen.

* src/incremen.c (compare_dirnames): Rewrite to avoid casts.
* src/utf8.c (string_ascii_p): Likewise.
* src/xheader.c (mtime_coder, volume_size_coder, volume_offset_coder):
Likewise.

SCALAR(0x8283218)
2006-12-12 23:56:24 +00:00
Sergey Poznyakoff
e5ef01710a Fix wording 2006-12-08 16:59:56 +00:00
Sergey Poznyakoff
e70e63612a Update 2006-12-08 16:45:34 +00:00
Sergey Poznyakoff
28b26242c7 Add paxutils files to dot_ignore. 2006-12-08 16:45:09 +00:00
Sergey Poznyakoff
6b279a6f8c Update 2006-12-08 13:40:15 +00:00
Sergey Poznyakoff
079f2d6807 Raise version number to 1.16.1 2006-12-08 13:40:07 +00:00
Sergey Poznyakoff
b09417ca8d (slurp): Create .(cvs|git)ignore if not present 2006-12-08 13:39:58 +00:00
Sergey Poznyakoff
b15e3f1bbd Remove autogenerated files 2006-12-08 12:42:32 +00:00
Sergey Poznyakoff
1616b1d1b4 Update 2006-12-07 14:35:13 +00:00
Sergey Poznyakoff
f23bc997fd Update 2006-12-07 14:34:48 +00:00
Sergey Poznyakoff
8ec119a27f Update 2006-12-07 14:34:28 +00:00
Sergey Poznyakoff
e35d05b1d2 Use genfile instead of dd, because on some systems /dev/zero is not available. 2006-12-07 14:34:15 +00:00
Sergey Poznyakoff
cdb77dcd7b (extract_file): Call skip_member if open fails.
Patch proposed by Jan-Benedict Glaw <jbglaw@lug-owl.de>
2006-12-07 14:33:54 +00:00
Sergey Poznyakoff
9bf87b195e (dump_dir0): Move checks for exclude tags to
dump_file0.
(dump_dir): Move calls to ensure_slash to dump_file0
2006-12-07 14:33:42 +00:00
Sergey Poznyakoff
643e3f2441 Update documentation of --exclude-tag 2006-12-07 14:33:30 +00:00
Sergey Poznyakoff
6e75833cb7 (distclean-local): Fixed 2006-12-07 14:33:17 +00:00
Paul Eggert
908d78d208 * NEWS: Fix some race conditions with tar -x --same-owner.
* src/extract.c (ARCHIVED_PERMSTATS): Add a comment saying that
S_IRWXG | S_IRWXO might be masked out.
(set_mode): Set the mode if some bits were masked out originally.
(set_stat): Don't chmod before chown, as that might temporarily
grant permissions that we don't want to grant.  The chmod was
there only to work around broken hosts, so add a comment advising
users not to use those broken hosts instead.
(repair_delayed_set_stat, extract_dir):
Remember to mask out current umask before inverting permissions.
(extract_dir): If the owner might change, or if the mode has
special bits, create the directory 700 at first, but restore it later.
(open_output_file): New arg mode; all uses changed.
(extract_file, extract_node, extract_fifo): If the owner might
change, omit group and other bits at first, but restore them after
changing the owner.
2006-12-04 21:35:56 +00:00
Paul Eggert
192f55e2a0 * doc/tar.texi (Long Options): Remove doubled word. 2006-12-04 09:33:31 +00:00
Sergey Poznyakoff
9d99fd13cd Update 2006-11-30 09:54:07 +00:00
Sergey Poznyakoff
07902e9f9a (xheader_read): Remove unused variable 2006-11-30 09:53:20 +00:00
Sergey Poznyakoff
0c94a109b9 Update 2006-11-30 09:42:59 +00:00
Sergey Poznyakoff
27094c4fc3 Implement --update-po and .bootstrap 2006-11-30 09:42:12 +00:00
Sergey Poznyakoff
5aca761e1b Remove src/mangle.c 2006-11-30 09:41:50 +00:00
Sergey Poznyakoff
cc82db7f2d (exclude): Document --exclude-tag 2006-11-30 09:41:42 +00:00
Sergey Poznyakoff
137ebf41fd (dump_dir0): Implement --exclude-tag option 2006-11-30 09:40:47 +00:00
Paul Eggert
49ea4c5057 * NEWS: Remove support for mangled names.
* doc/tar.texi (verbose tutorial): Likewise.
* src/Makefile.am (tar_SOURCES): Remove mangle.c.
* src/common.h (extract_mangle): Remove decl.
* src/extract.c (extract_mangle_wrapper): Remove.
(prepare_to_extract): Remove support for mangled names.
* src/list.c (read_and, print_header): Likewise.
* src/mangle.c: Remove.
* src/tar.h (GNUTYPE_NAMES): Remove.
2006-11-30 06:39:29 +00:00
Paul Eggert
409bddf38c * lib/.cvsignore: Add fstatat.c, gnulib.mk, openat-proc.c, same-inode.h, stat_.h,
tempname.c, tempname.h, uinttostr.c.
2006-11-30 06:27:24 +00:00
Paul Eggert
c930802f31 Port to latest gnulib. There were a lot of changes, so the
simplest way to get this up and running was to switch to coreutils
bootstrap procedure.  I noticed one feature missing after this
merge: the ability to update a single .po file.  I can add that
later if need be.
* README-cvs, bootstrap.conf: New files.
* lib/.cvsignore: Remove Makefile.am, printf-parse.c, vasnprintf.c.
* lib/printf-parse.c, lib/vasnprintf.c: New files, from coreutils,
to override gnulib, so that we don't need xsize.h.
* bootstrap: Replace with coreutils bootstrap, except add support
for paxutils.
* configure.ac (gl_USE_SYSTEM_EXTENSIONS): Remove, as gl_EARLY now
does this.
(gl_EARLY, gl_INIT): Add.
(tar_GNULIB): Remove.
* gnulib.modules: Add configmake.
* lib/Makefile.tmpl: Remove, replacing with....
* lib/Makefile.am: New file.
* src/Makefile.am (tar.o): Remove dependency: Automake does this
for us.
* src/tar.c: Include <configmake.h> and <rmt-command.h>, not
<localedir.h>.
2006-11-30 00:14:10 +00:00
Paul Eggert
ca14885884 Remove trailing white space. 2006-11-29 18:28:45 +00:00
Paul Eggert
01d6188297 Remove trailing white space. 2006-11-29 18:16:27 +00:00
Paul Eggert
759c5208c5 Remove trailing white space. 2006-11-29 18:11:34 +00:00
Sergey Poznyakoff
8457e06b99 Do not depend on command timing. 2006-11-13 10:42:19 +00:00
Sergey Poznyakoff
8719c4f680 Update 2006-11-13 10:41:47 +00:00
Sergey Poznyakoff
574022ab78 Do not use 'k' modifier in dd options. 2006-11-13 10:41:34 +00:00
Sergey Poznyakoff
304d8b9f0c (start_header): Pass mtime as a call-specific data to xheader_store. 2006-11-13 10:39:51 +00:00
Sergey Poznyakoff
6712656eb2 (mtime_coder): Treat non-null data as a pointer to struct timespec, overriding st->mtime 2006-11-13 10:39:15 +00:00
Sergey Poznyakoff
415d9c9e15 Update copyright year 2006-11-01 00:30:45 +00:00
Sergey Poznyakoff
1a8141ab8a Update 2006-11-01 00:24:44 +00:00
Sergey Poznyakoff
023c766600 Do not assume tar's default archive is stdout 2006-11-01 00:24:19 +00:00
Sergey Poznyakoff
fdb46aa2e2 Add more keywords 2006-11-01 00:24:09 +00:00
Sergey Poznyakoff
2504e7d3ae Add new test cases. 2006-11-01 00:23:52 +00:00
Sergey Poznyakoff
b0765e257c (enum read_file_list_state.file_list_skip): New value
(read_name_from_file): Skip zero-length entries
2006-11-01 00:23:24 +00:00
Sergey Poznyakoff
73d4c40a87 Update 2006-10-31 20:19:30 +00:00
Sergey Poznyakoff
7aed52718f Call last_component instead of base_name. The latter returns a malloced string since 2006-03-11. 2006-10-31 20:18:50 +00:00
Sergey Poznyakoff
f572ca0cfb Update 2006-10-21 16:48:08 +00:00
Sergey Poznyakoff
29236a68fa (distclean-local): New rule 2006-10-21 16:47:56 +00:00
Sergey Poznyakoff
a4b1564d4a Version 1.16 2006-10-21 16:47:42 +00:00
Sergey Poznyakoff
94d0385a57 Update 2006-10-17 08:14:06 +00:00
Sergey Poznyakoff
603c1d60a6 Fix help output formatting. Thanks Benno Schulenberg. 2006-10-17 08:13:43 +00:00
Sergey Poznyakoff
29e9004b69 Update 2006-10-16 07:51:40 +00:00
Sergey Poznyakoff
8da152d2b3 Update 2006-10-16 07:49:00 +00:00
Sergey Poznyakoff
00746182f3 (dist-hook): Create a cpio archive. 2006-10-16 07:48:51 +00:00
Sergey Poznyakoff
6c8815909d Update 2006-10-14 21:13:28 +00:00
Sergey Poznyakoff
fde336b21a (AT_KEYWORDS): Keyword `filechange'
Test tar exit status.
2006-10-14 21:12:42 +00:00
Sergey Poznyakoff
394b12d950 New test grow.at 2006-10-14 21:12:04 +00:00
Sergey Poznyakoff
372638ae7a Do not attempt to close stderr after call to close_stdout. 2006-10-14 21:11:43 +00:00
Sergey Poznyakoff
c455373e5b (dump_regular_file,dump_file0): Set exit_status to
TAREXIT_DIFFERS if the file being dumped was truncated or
otherwise changed.
2006-10-14 21:11:27 +00:00
Sergey Poznyakoff
f2541c66cd (Synopsis): Document tar exit codes. 2006-10-14 21:11:03 +00:00
Sergey Poznyakoff
7e6d54d0c0 Update 2006-10-14 10:48:14 +00:00
Sergey Poznyakoff
876e554157 (AT_KEYWORDS): Add stdout keyword 2006-10-14 10:46:24 +00:00
Sergey Poznyakoff
1118d24fd3 New test verbose.at 2006-10-14 10:46:13 +00:00
Sergey Poznyakoff
dc6f7ebf20 (_open_archive): Make sure stdlis is set to stderr
when we are writing archive to stdout (unless --index-file is
used). Bug introduced on 2006-07-06.
2006-10-14 10:45:44 +00:00
Sergey Poznyakoff
1102eeef1f Update 2006-10-02 15:45:08 +00:00
Sergey Poznyakoff
e8a4c35a73 Add new testcase: multiv05.at: 2006-10-02 15:44:52 +00:00
Sergey Poznyakoff
e359fad641 (xheader_string_end): Fix diagnostic message. 2006-10-02 15:44:20 +00:00
Sergey Poznyakoff
f5504a3bae (new_volume): Initialize current_block 2006-10-02 15:44:09 +00:00
Sergey Poznyakoff
341be8f405 Add Joerg Weilbier 2006-10-02 15:43:59 +00:00
Sergey Poznyakoff
4f2a22f306 Update 2006-09-27 09:03:23 +00:00
Sergey Poznyakoff
a76ab340dd (doc0, doc1, initialize_argp_doc): Removed. Rely on the new argp method instead 2006-09-27 09:03:13 +00:00
Sergey Poznyakoff
3ad3ca8734 Minor fix 2006-09-27 09:03:02 +00:00
Sergey Poznyakoff
82b2829e10 Use ${package} instead of hardcoding package name 2006-09-27 09:02:45 +00:00
Sergey Poznyakoff
f852428d5f Update 2006-09-12 09:59:08 +00:00
Sergey Poznyakoff
86e91a5bfc Fix typo 2006-09-12 09:56:39 +00:00
Paul Eggert
ec5743a628 * tests/testsuite.at (AT_TAR_MKHIER): Use install-sh -d
rather than the no-longer-included mkinstalldirs.
2006-09-08 23:29:43 +00:00
Paul Eggert
bf7f4fdc1e Add at-func.c, configmake.h, fchmodat.c,
fcntl.h, fcntl_.h, inttypes_.h, lstat.c, lstat.h.
2006-09-08 23:27:45 +00:00
Sergey Poznyakoff
98b9522499 Update 2006-09-08 16:47:15 +00:00
Sergey Poznyakoff
6398dbe1a5 List texinfo among build prerequisites for the CVS version. 2006-09-08 16:47:01 +00:00
Sergey Poznyakoff
37724f5e20 (try_purge_directory): Initialize struct st. Fix condition for selecting candidates for removal. 2006-09-08 16:45:41 +00:00
Sergey Poznyakoff
c8c351684c (intl_files_to_remove): Do not remove m4/inttypes-h.m4 and m4/inttypes-pri.m4 2006-09-08 15:17:56 +00:00
Paul Eggert
01b6fb98bf * bootstrap: Set XGETTEXT_OPTIONS to flag our printf-format functions,
so that translators are warned about strings that are formats but
don't look like formats.  This might help prevent core dumps.
* configure.ac (AM_GNU_GETTEXT): Upgrade to need-formatstring-macros.
Suggested by Eric Blake to avoid problems like
<http://lists.gnu.org/archive/html/bug-coreutils/2006-07/msg00087.html>.
(AM_GNU_GETTEXT_VERSION): Upgrade from 0.12.1 to 0.15.  The gettext
manual says we should use the version number normally expected of
maintainers, neither more nor less.
2006-08-11 21:39:36 +00:00
Paul Eggert
f1309bffbf * bootstrap (get_translations):
Don't exclude ky.po; it is working again.
2006-08-11 07:44:21 +00:00
Paul Eggert
c732eb584e * bootstrap: Don't exclude ja.po; it is working again.
Don't remove all old .po files if we're merely updating one.
* po/.cvsignore: Add Makevars.
2006-08-09 18:30:16 +00:00
Paul Eggert
0680ad4d42 * src/tar.c: Work around limitation imposed by gettext 0.15
by concatenating strings with "\v" after translation.
(doc): Remove, splitting into:
(doc0, doc1): New constants.
(argp): Don't use doc; just initialize to NULL.
(initialize_argp_doc): New function.
(decode_options): Use it.
2006-08-08 05:28:32 +00:00
Paul Eggert
1942370acd Fix typo: remove po/tar.html. 2006-08-07 22:58:12 +00:00
Paul Eggert
94de7c4c77 * bootstrap: Redo po file retrieval to match Bison's method,
since the translation project changed its index format.
Don't use --assume-autoconf; it's now replaced
by looking in configure.ac.
(m4/codeset.m4, m4/intdiv.m4, m4/inttypes-pri.m4, m4/isc-posix.m4):
(m4/lcmessage.m4, m4/onceonly_2_57.m4, m4/gettext.m4, m4/glibc21.m4):
(m4/inttypes_h.m4, m4/lib-ld.m4, m4/lib-prefix.m4, m4/po.m4):
(m4/stdint_h.m4, m4/uintmax_t.m4, m4/ulonglong.m4):
Don't rename to ..._gl.m4, as this is no longer needed.
(m4/geteext.m4): Patch to remove the need for intl/*.
Use autopoint manually, then remove the intl files,
then undo changes to gnulib files that autoreconf made,
and then run aclocal/autoconf/autoheader/automake.
This makes our bootstrap procedure closer to Bison's.
(po/Makevars): Generate automatically.
* configure.ac (AC_PREREQ): Update from 2.59 to 2.60.
(gl_AC_TYPE_INTMAX_T, jm_AC_TYPE_UINTMAX_T): Remove.
* gnulib.modules: Add inttypes, stdint.
* lib/.cvsignore: Add close-stream.c, close-stream.h,
stdint.h, stdint_.h.
* po/Makefile: Remove; now automatically generated.
2006-08-07 22:57:25 +00:00
Paul Eggert
05805868f2 (read_incr_db_01): Check input strings more
carefully.  Do not pass arbitrary char values to isspace, as
this has undefined behavior.  Likewise for assigning arbitrary
uintmax_t values to other types.
(read_negative_num, read_unsigned_num, read_timespec):
New functions, to check input values a bit more carefuly.
(read_num): Use read_unsigned_num.  New arg MAX_VAL;
all callers changed.
(read_incr_db_2): Use these new functions.
Use a consistent diagnostic for unexpected EOF.
(read_directory_file): Do not assign arbitrary uintmax_t value
to int.
(read_timespec, write_directory_file_entry, write_directory_file):
Handle negative time_t values correctly.  We don't bother to do
this with pre-2 formats, since presumably the time stamps were
output incorrectly.
2006-08-07 21:29:27 +00:00
Paul Eggert
57aa98047e gettext 0.15 rejects this. 2006-08-07 21:12:21 +00:00
Sergey Poznyakoff
7573967406 Update 2006-07-24 09:14:18 +00:00
Sergey Poznyakoff
ab8711413c Add append02.at 2006-07-24 09:14:00 +00:00
Sergey Poznyakoff
9fd9a0913d New test case 2006-07-24 09:13:44 +00:00
Sergey Poznyakoff
f4e4adea80 (to_chars_subst): Update comment regarding OLDGNU
vs. GNU format differences.
(mode_to_chars): Treat OLDGNU_FORMAT same as GNU_FORMAT. Fixes bug
reported by TAMUKI Shoichi <tamuki@linet.gr.jp>, which caused
equivalent `tar cf ...' and `tar rf ...' commands to produce
different archives.
2006-07-24 09:13:21 +00:00
Sergey Poznyakoff
7110641821 (decode_options): Do not require -L with -M -Hpax.
It could be needed in future, but currently it is not.
2006-07-24 09:12:55 +00:00
Paul Eggert
fce454b5ca * bootstrap: Adjust to today's change to gnulib-tool by invoking
it with --assume-autoconf='latest-stable'.
2006-07-20 16:57:31 +00:00
Paul Eggert
8ad985ea6c Adjust to recent gnulib changes.
* lib/.cvsignore: Remove atexit.c, exit.c, getndelim2.c, getndelim2.h,
pathmax.h, paxconvert.c, paxerror.h, xstrdup.c.
Add inttypes.h, mktime.c, wcwidth.h, xstrndup.c, xstrndup.h.
* src/create.c (start_header): Adjust to API change to mode_adjust.
2006-07-17 05:47:26 +00:00
Sergey Poznyakoff
37edfd9e8f Update 2006-07-09 11:26:46 +00:00
Sergey Poznyakoff
016f7c87a7 Update 2006-07-09 11:26:16 +00:00
Sergey Poznyakoff
52b8bea074 Add Ralf Wildenhues 2006-07-09 11:25:47 +00:00
Sergey Poznyakoff
5addfdcb03 Fix some typos 2006-07-09 11:25:18 +00:00
Sergey Poznyakoff
e707b47aba Fix entry ordering 2006-07-06 20:10:37 +00:00
Sergey Poznyakoff
76dc519f9f Update 2006-07-06 20:08:53 +00:00
Sergey Poznyakoff
2a00376816 (TESTSUITE_AT): Add indexfile.at 2006-07-06 20:08:20 +00:00
Sergey Poznyakoff
9766528b07 Include indexfile.at 2006-07-06 20:08:09 +00:00
Sergey Poznyakoff
f26a90783b New test case 2006-07-06 20:08:01 +00:00
Sergey Poznyakoff
36fe16aaf5 (decode_options): Initialize stdlis 2006-07-06 20:07:37 +00:00
Sergey Poznyakoff
89f1667fdb (_open_archive): Remove stdlis initialization 2006-07-06 20:05:30 +00:00
Sergey Poznyakoff
f2d65dda39 Update 2006-07-05 06:46:53 +00:00
Sergey Poznyakoff
8370746251 (FIXME): Do not use deprecated @quote-args.
Do not use @allow-recursion. In its current form the macro is not
recursive.
2006-07-05 06:46:32 +00:00
Sergey Poznyakoff
2614af6d3c (manual): Fix TEXINPUTS 2006-07-05 06:46:11 +00:00
Sergey Poznyakoff
614def3113 Update 2006-07-04 21:53:40 +00:00
Sergey Poznyakoff
b6365e9b03 Update 2006-07-04 21:52:53 +00:00
Sergey Poznyakoff
bf789e3642 Update --directory description 2006-07-04 21:52:34 +00:00
Sergey Poznyakoff
1421ee630d (main): Call closeopen 2006-07-04 21:52:14 +00:00
Sergey Poznyakoff
9869d0ae17 (chdir_arg): Use x2nrealloc to reallocate wd.
(get_max_open_files,closeopen): New functions
(chdir_do): Do not use save_cwd if it was already used more than
max_open_files-4 times to avoid running off the file
descriptors.
2006-07-04 21:52:05 +00:00
Sergey Poznyakoff
edc0b12c5e (closeopen): New function 2006-07-04 21:51:42 +00:00
Sergey Poznyakoff
808cafa454 (AC_CHECK_FUNCS): Check for getdtablesize 2006-07-04 21:51:33 +00:00
Sergey Poznyakoff
d1dedae402 (update_po): Fix single translation update 2006-07-03 16:46:14 +00:00
Sergey Poznyakoff
de754902da Update 2006-06-27 13:39:20 +00:00
Sergey Poznyakoff
bc7f4ad027 Update 2006-06-26 14:42:35 +00:00
Sergey Poznyakoff
55abc110f5 Add cross-references 2006-06-26 14:42:18 +00:00
Sergey Poznyakoff
4d753fced1 Minor fixes 2006-06-26 12:48:25 +00:00
Sergey Poznyakoff
85a4e0fdeb Do not depend on getopt.h 2006-06-26 11:18:54 +00:00
Sergey Poznyakoff
583415c2c1 Update 2006-06-26 08:09:18 +00:00
Sergey Poznyakoff
6488588c5f Update 2006-06-26 08:08:47 +00:00
Sergey Poznyakoff
ac40b1e6f6 Update 2006-06-25 12:46:43 +00:00
Sergey Poznyakoff
4bf5f6dca4 --sparse-version turns on --sparse 2006-06-25 12:46:12 +00:00
Sergey Poznyakoff
ecaff7cbba Use ST_IS_SPARSE instead of sparse_file_p (update paxutils first) 2006-06-25 12:45:57 +00:00
Sergey Poznyakoff
ea9e2d8d8e (sparse_file_p): Remove 2006-06-25 12:45:16 +00:00
Sergey Poznyakoff
39e5d9182c (Other Tars): New node describing how to extract
GNU-specific member formats using third-party tars.
2006-06-25 12:45:03 +00:00
Sergey Poznyakoff
c7aa519f09 (tar_TEXINFOS): Sorted 2006-06-25 12:44:15 +00:00
Sergey Poznyakoff
bf5ba3dbef A sample utility to expand sparse files
extracted by third-party tars. It is not meant to be installed nor
to be included in the distribution. It is here, so that it can be
obtained either from CVS or from the tar web site.
2006-06-25 12:44:04 +00:00
Sergey Poznyakoff
ea368b6d1b Update 2006-06-24 16:50:11 +00:00
Sergey Poznyakoff
d0201294c0 (xhdr_tab.decoder): pass keyword as a second
argument. All callers changed.
(decode_record): Check for numeric overflow
(xheader_string_end): Return boolean value. Check for possible
numeric overflow
2006-06-24 16:49:33 +00:00
Sergey Poznyakoff
c5b15c4ac1 (segm_count): Change type to size_t 2006-06-24 16:49:05 +00:00
Sergey Poznyakoff
4b3dd17c00 (pax_dump_header_0): Return false if
xheader_string_end fails (for 0.1 formats).
(pax_dump_header): Return meaningful value
2006-06-24 16:48:45 +00:00
Sergey Poznyakoff
d339cc38af Remove not used variables 2006-06-24 16:48:24 +00:00
Sergey Poznyakoff
796a69787e (extract_volhdr): Add missing return 2006-06-24 16:48:08 +00:00
Sergey Poznyakoff
4c54e234c1 (name_init): New prototype.
(xheader_string_end): Return bool.
2006-06-24 16:47:57 +00:00
Sergey Poznyakoff
c027e03924 (print_total_stats): Add default case 2006-06-24 16:47:29 +00:00
Sergey Poznyakoff
6d615f12d4 Update 2006-06-23 15:24:53 +00:00
Sergey Poznyakoff
8f970d2c1e Include sparsemvp.at, spmvp00.at, spmvp01.at, spmvp10.at 2006-06-23 15:24:43 +00:00
Sergey Poznyakoff
d04af8f714 Rewritten as an include file.
(TAR_MVP_TEST): New macro
2006-06-23 15:24:10 +00:00
Sergey Poznyakoff
e2ecb82711 Explicitely give `-f -' to the tar invocation 2006-06-23 15:23:47 +00:00
Sergey Poznyakoff
8e2e731733 Add spmvp00.at, spmpv01.at, spmpv10.at 2006-06-23 15:23:16 +00:00
Sergey Poznyakoff
19a63e523d Implement new keywords: GNU.sparse.name, GNU.sparse.major, GNU.sparse.minor, GNU.sparse.realsize 2006-06-23 15:22:50 +00:00
Sergey Poznyakoff
5679d3020e (struct tar_stat_info.sparse_major,sparse_minor): New members 2006-06-23 15:22:31 +00:00
Sergey Poznyakoff
1001c1b326 New option --sparse-version 2006-06-23 15:22:12 +00:00
Sergey Poznyakoff
090d1d36ae Implement sparse format versioning. Implement new
version (1.0) of PAX sparse format.
(pax_sparse_member_p): Fix condition
(pax_dump_header): A dispatcher function
(pax_dump_header_0,pax_dump_header_1): New functions.
(pax_optab): Update
(oldgnu_dump_header): Minor fix: make sure
sparse_header.isextended is set before calling
set_next_block_after
2006-06-23 15:21:48 +00:00
Sergey Poznyakoff
2e1f904f2c (tar_sparse_major,tar_sparse_minor): New globals. 2006-06-23 15:20:06 +00:00
Sergey Poznyakoff
6a0b5421b9 Update master menu 2006-06-23 15:19:47 +00:00
Sergey Poznyakoff
9c764b14a9 (Sparse Formats): New node 2006-06-23 15:19:27 +00:00
Sergey Poznyakoff
ae67839879 (tar_TEXINFOS): Add sparse.texi 2006-06-23 15:19:08 +00:00
Sergey Poznyakoff
9588a106a7 New files 2006-06-23 15:18:18 +00:00
Sergey Poznyakoff
b3627f3f07 Update 2006-06-21 10:44:29 +00:00
Sergey Poznyakoff
ca7df3fe6b Raise version number to 1.15.92 2006-06-21 10:44:16 +00:00
Sergey Poznyakoff
ab19642053 Implement new option, --mtime, allowing to set
modification times for all archive members during creation.
(struct tar_args): textual_date_option replaced with a linked list
textual_date. All references updated.
(get_date_or_file,report_textual_dates): New functions.
2006-06-21 10:40:39 +00:00
Sergey Poznyakoff
a71b154289 (start_header): Override mtime if requested 2006-06-21 10:40:10 +00:00
Sergey Poznyakoff
ceaef10443 (set_mtime_option,mtime_option): New globals 2006-06-21 10:39:58 +00:00
Sergey Poznyakoff
5da6733724 (Overriding File Metadata): New node
Document --mtime option.
2006-06-21 10:39:52 +00:00
Sergey Poznyakoff
8d6c177ecb update 2006-06-20 15:15:11 +00:00
Sergey Poznyakoff
1ecd6672e1 (GNU.sparse.name): New variable for storing sparse file name. 2006-06-20 15:14:59 +00:00
Sergey Poznyakoff
ca2f855c90 (pax_dump_header): Store original sparse file name
in GNU.sparse.name variable. The name field in the ustar header
now contains generated name (%d/GNUSparseFile.%p/%f), so that
non-pax-aware tars won't extract the file under the original
filename.
2006-06-20 15:14:47 +00:00
Sergey Poznyakoff
693134a4e7 (name_next_elt): Call register_individual_file
(namelist_match): Remove third argument
(name_match): Change return type to bool
(name_scan): Remove second argument
2006-06-20 15:14:19 +00:00
Sergey Poznyakoff
90cec95580 (maybe_backup_file): Second argument is bool 2006-06-20 15:14:00 +00:00
Sergey Poznyakoff
b6fcb4ba8f (procdir): Use is_individual_file to check for
files explicitely specified in the command line. Fixes bug
reported by Dat Head on 19 Jun 2006 (descending into mountpoints
with --one-file-system in use)
2006-06-20 15:13:49 +00:00
Sergey Poznyakoff
6d1e9ab67e Remove second argument from calls to name_scan 2006-06-20 15:13:30 +00:00
Sergey Poznyakoff
300210aa15 (struct name.explicit): Remove
Use variable names in all declarations
(name_scan): Remove second argument
2006-06-20 15:13:20 +00:00
Sergey Poznyakoff
532b2dd31f Fix typo in a comment 2006-06-16 07:19:34 +00:00
Sergey Poznyakoff
3358f5fcc3 Update 2006-06-13 19:34:20 +00:00
Sergey Poznyakoff
51e3f3f1ca Update 2006-06-13 14:59:43 +00:00
Sergey Poznyakoff
caf6b29f1e (Using Multiple Tapes,Multi-Volume Archives): Rewritten 2006-06-13 14:59:32 +00:00
Sergey Poznyakoff
12ae9f6912 Update 2006-06-13 13:35:46 +00:00
Sergey Poznyakoff
64041696c9 (xopindex,opsummary): New macros 2006-06-13 13:35:34 +00:00
Sergey Poznyakoff
8ee09b9939 Define op as codeindex. Use xopindex and opsummary to
populate it
Consequently prefer @dfn{long options} over @dfn{mnemonic
options}.
Document --unquote, --no-unquote
(Short Option Summary): Build a table of cross-references to the
corresponding long options.
2006-06-13 13:35:14 +00:00
Sergey Poznyakoff
72f60f9e5f (FIXME) [!PROOF_FOOTNOTED]: Enclose in a cartouche 2006-06-13 13:34:32 +00:00
Sergey Poznyakoff
378818cb3e (check-options): Expand macros before grepping in $(info_TEXINFOS) 2006-06-13 13:34:14 +00:00
Sergey Poznyakoff
c980a06329 Update 2006-06-12 22:51:32 +00:00
Sergey Poznyakoff
4c7a2b10b8 Implement --overwrite-dir option (long ago documented) 2006-06-12 22:50:29 +00:00
Sergey Poznyakoff
8f3ed604b9 Update 2006-06-12 22:50:17 +00:00
Sergey Poznyakoff
b886724818 (check-options): New goal 2006-06-12 22:49:37 +00:00
Sergey Poznyakoff
f143fa5d64 Update 2006-06-12 13:21:28 +00:00
Sergey Poznyakoff
1e3568d947 (options, parse_opt): Allow for optional argument to
the --totals option, which specifies a signal upon delivery of which
the statistics must be output.
(main): Call print_total_stats if total_option is set.
2006-06-12 13:20:10 +00:00
Sergey Poznyakoff
b229a86dd7 (check_time): Use volume_start_time when checking
for the timestamp plausability.
2006-06-12 13:19:43 +00:00
Sergey Poznyakoff
05b250d4a4 (records_skipped): Remove static qualifier, the
variable is used by print_total_stats in buffer.c
2006-06-12 13:19:16 +00:00
Sergey Poznyakoff
42d180b24e (volume_start_time,last_stat_time): New globals
(print_total_written): Replaced with:
(print_total_stats): New function
2006-06-12 13:18:59 +00:00
Sergey Poznyakoff
8c10111c66 (total_blocks_deleted): New variable
(set_start_time): Set volume_start_time and last_stat_time as well
(set_volume_start_time): New function
(compute_duration): Do not call set_start_time, update
last_stat_time instead. Use it in calculation instead of
start_time, which is now set only once, upon startup.
(print_total_written): Removed.
(print_total_stats): New function for printing byte/speed statistics.
(_open_archive): Detect attempts to update compressed archives.
(_gnu_flush_write): Always update prev_written.
(open_archive): Call set_volume_start_time.
2006-06-12 13:18:26 +00:00
Sergey Poznyakoff
15a55db341 Update 2006-06-12 13:17:54 +00:00
Sergey Poznyakoff
e721e74259 Document better the --totals option. 2006-06-12 13:17:42 +00:00
Sergey Poznyakoff
1bea3b4b25 Update 2006-06-11 20:07:20 +00:00
Sergey Poznyakoff
4ef056729e (xheader_set_single_keyword): Fix typo.
(decode_time): Avoid using gotos.
2006-06-11 20:06:46 +00:00
Sergey Poznyakoff
37986cdff9 Update 2006-06-11 15:05:52 +00:00
Sergey Poznyakoff
5fe07ac97d Update master menu 2006-06-11 15:05:22 +00:00
Sergey Poznyakoff
a35935e973 (master-menu): New goal 2006-06-11 15:04:39 +00:00
Sergey Poznyakoff
e832cab432 New file 2006-06-11 15:04:17 +00:00
Sergey Poznyakoff
578f46309f Update 2006-06-10 09:55:20 +00:00
Sergey Poznyakoff
4396675861 Remove leftover include 2006-06-10 09:54:02 +00:00
Sergey Poznyakoff
a3dd97d9be Update 2006-06-09 13:55:36 +00:00
Sergey Poznyakoff
13adf3f762 Update 2006-06-09 13:50:20 +00:00
Sergey Poznyakoff
f1b1e9a476 Fix indentation, introduce end-of-format marker for texify.sed 2006-06-09 13:50:04 +00:00
Sergey Poznyakoff
fc4502c17e Update 2006-06-09 13:49:51 +00:00
Sergey Poznyakoff
0abf3a5ac9 Fix typo 2006-06-09 13:49:39 +00:00
Sergey Poznyakoff
19b36aaf60 Auxiliary script to convert ../src/tar.h to header.texi 2006-06-09 13:48:28 +00:00
Sergey Poznyakoff
9b44f8efed *** empty log message *** 2006-06-09 13:46:53 +00:00
Sergey Poznyakoff
97bfe578ed New file 2006-06-09 13:46:34 +00:00
Sergey Poznyakoff
fb88325f56 (tar_TEXINFOS): Add intern.texi
(EXTRA_DIST): Remove convtexi.pl, add texify.sed
2006-06-09 13:46:11 +00:00
Sergey Poznyakoff
a1b2406646 Update 2006-06-08 22:36:30 +00:00
Sergey Poznyakoff
5e14ef32c0 Minor fixes. 2006-06-08 22:35:52 +00:00
Sergey Poznyakoff
f9bd340c1b --checkpoint takes an optional argument specifying
number of records between two successive checkpoints (proposed
by Jason Armistead on 2004-06-22).Optional dot starting the
argument means "print dots instead of textual checkpoints".
(tar_help): New function
2006-06-08 22:35:39 +00:00
Sergey Poznyakoff
46defea70e (checkpoint_option): Change type to unsigned
(checkpoint_style): New variable.
2006-06-08 22:34:56 +00:00
Sergey Poznyakoff
5daab19c27 Implement more flexible checkpoint style 2006-06-08 22:34:38 +00:00
Sergey Poznyakoff
7214086d3d Update 2006-06-08 22:34:16 +00:00
Sergey Poznyakoff
93560dd669 Add Jason Armistead 2006-06-08 22:33:33 +00:00
Sergey Poznyakoff
c1f55f1c37 Update 2006-06-08 14:43:23 +00:00
Sergey Poznyakoff
2d2e1d411e (dumpdir_locate,obstack_code_rename,purge_directory): Re-implement renaming. Introduce
X control code.
(make_tmp_dir_name): Remove
2006-06-08 14:43:05 +00:00
Sergey Poznyakoff
5591fa407a Document dumpdir format 2006-06-08 14:42:20 +00:00
Sergey Poznyakoff
e2dbba2f07 (tar_TEXINFOS): Add dumpdir.texi 2006-06-08 14:42:07 +00:00
Sergey Poznyakoff
018de58373 New file 2006-06-08 14:41:56 +00:00
Sergey Poznyakoff
17111bef8f Add mkdtemp 2006-06-08 14:41:15 +00:00
Sergey Poznyakoff
3a9f2ea587 Update 2006-06-08 09:51:06 +00:00
Sergey Poznyakoff
02c7b862a3 (add_char_segment): Fix length assignement 2006-06-08 09:50:56 +00:00
Sergey Poznyakoff
9154c0c43b Update 2006-06-08 09:43:44 +00:00
Sergey Poznyakoff
5108a3dc41 Update 2006-06-08 09:34:03 +00:00
Sergey Poznyakoff
c52e5fc4e8 Update 2006-06-08 09:28:18 +00:00
Sergey Poznyakoff
0fc3177ed2 Update 2006-06-08 09:27:38 +00:00
Sergey Poznyakoff
6be1349236 (set_transform_expr,_transform_name_to_obstack): Implement NUMBER flag. 2006-06-08 09:27:25 +00:00
Sergey Poznyakoff
a2625311c8 Update 2006-06-07 14:57:57 +00:00
Sergey Poznyakoff
6e2760f7d7 Update 2006-06-07 14:57:29 +00:00
Sergey Poznyakoff
8b2f4ad670 (_transform_name_to_obstack,set_transform_expr): Implement case conversion operations (GNU extension). 2006-06-07 14:57:10 +00:00
Sergey Poznyakoff
d4c0836ec2 Update 2006-06-06 21:36:17 +00:00
Sergey Poznyakoff
40afe4d362 Update 2006-06-06 21:35:22 +00:00
Sergey Poznyakoff
435edb824e (transform_name_fp): Run fun even if _transform_name_to_obstack returns false. 2006-06-06 21:33:25 +00:00
Sergey Poznyakoff
9d2e8df195 Update 2006-06-06 21:30:26 +00:00
Sergey Poznyakoff
aa7476a68e Update 2006-06-03 20:53:17 +00:00
Sergey Poznyakoff
16c48ef8d0 Update 2006-06-02 15:07:00 +00:00
Sergey Poznyakoff
0da8aac59f Use genfile --files-from 2006-06-02 15:06:29 +00:00
Sergey Poznyakoff
bb6f707781 Fix typo in the comment 2006-06-02 15:06:19 +00:00
Sergey Poznyakoff
7cb01d37bb Add incr04.at 2006-06-02 15:06:10 +00:00
Sergey Poznyakoff
d79bbe0fd1 (set_transform_expr): New function 2006-06-02 15:05:52 +00:00
Sergey Poznyakoff
f984c43b82 Update 2006-06-02 15:05:36 +00:00
Sergey Poznyakoff
d75890c1b8 (options): Minor rewording 2006-06-02 10:54:05 +00:00
Sergey Poznyakoff
b3b4347821 Update 2006-06-02 10:42:25 +00:00
Sergey Poznyakoff
39080c7628 Update 2006-06-02 08:08:10 +00:00
Sergey Poznyakoff
c58063c17a New option --transform
New option --show-transformed-names generalizes
--show-stored-names. The latter is retained as an alias.
2006-06-02 08:06:46 +00:00
Sergey Poznyakoff
ae7bd36423 (print_header): Update displayable name selection. 2006-06-02 08:05:04 +00:00
Sergey Poznyakoff
973b611290 (extract_archive): safer_name_suffix and stripped_prefix_len are now called by decode_header 2006-06-02 08:04:37 +00:00
Sergey Poznyakoff
29fb7356df (dump_file0): Transform file name 2006-06-02 08:03:53 +00:00
Sergey Poznyakoff
bbee515590 (transform_name, transform_name_fp): New functions
(show_stored_names_option): Renamed to
show_transformed_names_option. All uses changed
2006-06-02 08:03:08 +00:00
Sergey Poznyakoff
c8aa01c80c New file 2006-06-02 08:02:24 +00:00
Sergey Poznyakoff
43ba23114f (tar_SOURCES): New module transform.c 2006-06-02 08:01:44 +00:00
Sergey Poznyakoff
7bfcbd6a27 Update 2006-06-02 08:01:33 +00:00
Sergey Poznyakoff
c5fd5f9e8d Update 2006-05-31 12:45:44 +00:00
Sergey Poznyakoff
a23a95b4a0 (make_directory): Fix initialization of struct directory. 2006-05-31 12:45:14 +00:00
Sergey Poznyakoff
19498c9172 Initialize AM_CPPFLAGS 2006-05-25 19:29:03 +00:00
Sergey Poznyakoff
edff149522 Update 2006-05-25 14:13:07 +00:00
Sergey Poznyakoff
f20e08dd45 (parse_opt): Add comment before --preserve case. 2006-05-25 14:12:51 +00:00
Sergey Poznyakoff
e6d15fc7af Updated 2006-05-25 14:12:35 +00:00
Sergey Poznyakoff
c96ba08e06 Update 2006-05-25 11:02:50 +00:00
Sergey Poznyakoff
6f89b1fce5 Document use of wildcards 2006-05-25 11:02:09 +00:00
Sergey Poznyakoff
93f8f6780a Update 2006-05-25 07:05:58 +00:00
Sergey Poznyakoff
75f37f4cef Make AT_SETUP more readable. 2006-05-25 07:05:41 +00:00
Sergey Poznyakoff
3947e63c25 (options): Move globbing-related options into a
separate group. Set -l as an alias to --check-links, as required
by UNIX98
(struct tar_args): New fields
wildcards,matching_flags,include_anchored
(MAKE_EXCL_OPTIONS,MAKE_INCL_OPTIONS): New macros
(parse_opt): Use x2nrealloc to grow archive_name_array.
Use MAKE_EXCL_OPTIONS,MAKE_INCL_OPTIONS to create appropriate
fnmatch options, and name_add_name,name_add_dir to handle member
name and -C arguments.
(decode_options): Likewise
(main): Remove call to init_names.
2006-05-25 07:05:28 +00:00
Sergey Poznyakoff
8b471d55ff Rewritten handling of member names in the command
line. Tar no longer attempts to guess globbing patterns, instead
it relies on --wildcard option.
(init_names): Removed.
(struct name_elt): New structure.
(name_array): Change type to struct name_elt. All references updated
(name_add_name,name_add_dir): New functions
(name_next_elt): New function
(name_next): Rewritten using name_next_elt.
(namelist_match): Rewritten pattern matching using
exclude_fnmatch.
(names_notfound): Warn if globbing patterns were used without
--wildcards option
2006-05-25 07:04:53 +00:00
Sergey Poznyakoff
c2c2df6c93 (dump_file,dump_file0): First argument is const char*. All callers updated. 2006-05-25 07:04:15 +00:00
Sergey Poznyakoff
cf857388c1 (struct name): Refactured
(warn_regex_usage): New variable.
(dump_file): First argument is const char*.
(name_init,name_add): Removed
(name_add_name,name_add_dir): New functions
(name_next): Return const char*.
2006-05-25 07:03:57 +00:00
Sergey Poznyakoff
9dfad74683 (AM_INIT_AUTOMAKE): Use tar-ustar option. Raise version requirement to 1.9 2006-05-25 07:03:30 +00:00
Sergey Poznyakoff
57267f7ed9 Update 2006-05-25 07:02:59 +00:00
Sergey Poznyakoff
476abe556b Update 2006-05-23 07:10:55 +00:00
Sergey Poznyakoff
fe72c79ad8 (change_tape_menu): Fix typo (uninitialized variable) introduced yesterday. 2006-05-23 07:10:34 +00:00
Sergey Poznyakoff
8fea578b22 Update 2006-05-22 10:02:32 +00:00
Sergey Poznyakoff
a46704b1bf (change_tape_menu): Break the loop after obtaining new archive name. Check for empty input line 2006-05-22 10:02:23 +00:00
Sergey Poznyakoff
6f8cbc5ca8 Use @var{file_name} instead of @var{file name} 2006-05-22 10:01:34 +00:00
Sergey Poznyakoff
c03131aba9 Update 2006-05-15 09:52:29 +00:00
Sergey Poznyakoff
c9195c75be (AT_TAR_CHECK): Declare expected failure if $XFAILFILE exists. 2006-05-15 09:52:16 +00:00
Sergey Poznyakoff
5632d195f5 Create $XFAILFILE on failure 2006-05-15 09:52:03 +00:00
Sergey Poznyakoff
ef90e05363 (XFAILFILE): New variable 2006-05-15 09:51:53 +00:00
Sergey Poznyakoff
939d63b92d Update 2006-05-13 14:03:46 +00:00
Sergey Poznyakoff
0ff13351f0 Update 2006-05-13 14:01:26 +00:00
Sergey Poznyakoff
c57418b462 New file 2006-05-13 14:01:13 +00:00
Sergey Poznyakoff
3c7dd57a17 Update 2006-05-13 13:58:59 +00:00
Sergey Poznyakoff
0b3fe146dd Update 2006-05-13 12:16:09 +00:00
Sergey Poznyakoff
90088ff00d Update 2006-05-13 12:02:58 +00:00
Sergey Poznyakoff
a183d6f7f5 Update 2006-05-13 12:00:06 +00:00
Sergey Poznyakoff
4883aab47d (AT_STAR_PREREQ): Provide md5 sum. 2006-05-13 11:59:51 +00:00
Sergey Poznyakoff
30873dbd97 Add keywords. 2006-05-13 11:59:36 +00:00
Sergey Poznyakoff
74849d8119 (AT_TARBALL_PREREQ): New defun
(AT_STAR_PREREQ): Rewrite using tarball_prereq
Include chtype.at and volsize.at
2006-05-13 11:59:08 +00:00
Sergey Poznyakoff
3962eb6a3e (TEST_DATA_URL,STAR_DATA_URL)
(STAR_TESTSCRIPTS): Provide default values.
(tarball_prereq): New function
2006-05-13 11:58:41 +00:00
Sergey Poznyakoff
c99076e925 (TESTSUITE_AT): Add chtype.at, volsize.at
(check-full): New target
2006-05-13 11:58:16 +00:00
Sergey Poznyakoff
6315d1700b (read_header_primitive): New function
(read_header): Front end for read_header_primitive
2006-05-13 11:57:52 +00:00
Sergey Poznyakoff
520104f5f8 (extract_volhdr): New function
(prepare_to_extract): Use extract_volhdr as extractor for volume
names.
2006-05-13 11:57:36 +00:00
Sergey Poznyakoff
34e5f66589 (read_header_primitive): New function 2006-05-13 11:57:20 +00:00
Sergey Poznyakoff
d2b3114a3b (read_header0): Use read_header_primitive to avoid clubbering current_tar_info. All callers updated. 2006-05-13 11:57:06 +00:00
Sergey Poznyakoff
2b27e8de1f Update 2006-05-13 11:56:51 +00:00
Sergey Poznyakoff
a85cfd69e3 (find_directory_meta): Bugfix 2006-05-13 08:38:12 +00:00
Sergey Poznyakoff
4b951034f3 Update 2006-05-08 12:48:27 +00:00
Sergey Poznyakoff
1524831224 Call AT_SORT_PREREQ. Remove fd 2 redirection after sort invocations 2006-05-08 12:46:41 +00:00
Sergey Poznyakoff
ee6f14194d Call AT_UNPRIVILEGED_PREREQ 2006-05-08 12:46:16 +00:00
Sergey Poznyakoff
ac7f4e853d (AT_SORT_PREREQ, AT_UNPRIVILEGED_PREREQ): New defines 2006-05-08 12:46:01 +00:00
Sergey Poznyakoff
47dd75e87b Update 2006-05-08 12:12:45 +00:00
Sergey Poznyakoff
6054b5e9d5 (AT_KEYWORDS): Add missing incremental kw 2006-05-08 12:12:09 +00:00
Sergey Poznyakoff
edd6df370d Update for the new behavior 2006-05-08 12:11:53 +00:00
Sergey Poznyakoff
fd89d5a3cd Add incr03.at,rename01.at,rename02.at,rename03.at 2006-05-08 12:11:43 +00:00
Sergey Poznyakoff
71f2e412ae New testcase 2006-05-08 12:11:26 +00:00
Sergey Poznyakoff
67877f7de2 (collect_and_sort_names): Update dir_contents of the first non-fake name entry when in listed incremental mode. 2006-05-08 12:10:36 +00:00
Sergey Poznyakoff
c9e7465642 (struct directory.contents, flags): New members
(nfs,found,new): Remove. Replaced by appropriate bitmask values in
`flags' field. All uses updated.
(directory_meta_table): New table.
(hash_directory): Rename to hash_directory_name
(compare_directories): Rename to compare_directory_names
(hash_directory_meta,compare_directory_meta,find_directory_meta):
New functions
(compare_dirents): Removed
(note_directory): Get 7th argument: directory contents.
All callers updated
(dumpdir_locate,makedumpdir): New functions
(scan_directory): Rewritten. Use makedumpdir to create a sorted
dumpdir array. This makes the obstack argument unnecessary. Besides,
ALL_CHILDREN flag is set only for new directories.
(procdir): Change return type to struct directory. Return
immediately if the directory was already initialized. Discover
directory renames using directory_meta_table.
(append_incremental_renames): New function.
(read_directory_file, write_directory_file): Use new snapshot file
format.
2006-05-08 12:10:14 +00:00
Sergey Poznyakoff
a0b4431f26 (rename_directory): New function 2006-05-08 12:09:46 +00:00
Sergey Poznyakoff
192ac7136a (rename_directory,append_incremental_renames): New functions. 2006-05-08 12:09:35 +00:00
Sergey Poznyakoff
c2775aedf1 Raise version number to 1.15.91 2006-05-08 12:09:15 +00:00
Sergey Poznyakoff
f1fe157dfe Update 2006-05-08 12:09:07 +00:00
Sergey Poznyakoff
dd197c5ccb Update 2006-05-02 19:16:23 +00:00
Sergey Poznyakoff
c576ac1354 Always use genfile --file, this enables extra error checking. 2006-05-02 19:16:12 +00:00
Sergey Poznyakoff
53d1279719 Attempt to extract a member with truncated file name from the archive. 2006-05-02 19:15:50 +00:00
Sergey Poznyakoff
729b91adb1 (try_new_volume): Attempt to continue if the name is apparently truncated in a GNU format volume. 2006-05-02 19:15:35 +00:00
Sergey Poznyakoff
dc7c0f1309 Update 2006-05-02 16:33:10 +00:00
Sergey Poznyakoff
783e58b394 (_open_archive): Remove unnecessary argument to check_compressed_archive. 2006-05-02 16:32:40 +00:00
Sergey Poznyakoff
c0e5268e75 Update 2006-04-25 17:27:03 +00:00
Sergey Poznyakoff
1518cef987 (@copying): Remove the reference to not existing invariant section. 2006-04-25 17:26:30 +00:00
Sergey Poznyakoff
8dd9a2105e Skip the test if the file system does not support sparse files. 2006-04-25 17:23:35 +00:00
Sergey Poznyakoff
9ec31e3438 Update 2006-04-11 12:02:27 +00:00
Sergey Poznyakoff
d4a41d5311 New testcase 2006-04-11 12:01:28 +00:00
Sergey Poznyakoff
a46e6aa4dc Include extrac06.at 2006-04-11 12:01:02 +00:00
Sergey Poznyakoff
b4d40436fd (TESTSUITE_AT): Add extrac06.at 2006-04-11 12:00:37 +00:00
Sergey Poznyakoff
f97d80335a (directory.new): New member
(note_directory,find_directory: Use make_directory to create
struct directory entries
(procdir): Avoid duplicating  directories in the incremental
backup map.
2006-04-11 12:00:23 +00:00
Sergey Poznyakoff
90b061cf55 Minor changes 2006-04-11 11:59:54 +00:00
Sergey Poznyakoff
8300c820d5 (extract_dir): Fix toggling existing directory
permissions. Use parts of patch provided by Ian Jackson
<iwj@ubuntu.com>.
2006-04-11 11:59:40 +00:00
Paul Eggert
e0b3fc61e1 * tests/atlocal.in (PATH): Add build-aux from the source tree,
not the build tree.
2006-03-19 04:04:54 +00:00
Sergey Poznyakoff
533854fd45 Update 2006-03-13 09:46:52 +00:00
Sergey Poznyakoff
e99d4f83df Add Benno Schulenberg 2006-03-13 09:44:15 +00:00
Sergey Poznyakoff
b8d5835375 Sort the two lines of stderr from the
first `tar -v --listed-incremental'.  They would come out
reversed and provoke a test failure on a tmpfs
file system.
2006-03-13 09:43:37 +00:00
Sergey Poznyakoff
61dd37ec86 (options): Consistently begin help messages with a lowercase letter. 2006-03-13 09:42:55 +00:00
Sergey Poznyakoff
48d20d8f9e Minor fixes. 2006-03-13 09:42:22 +00:00
Sergey Poznyakoff
adbbde5d4f Update 2006-03-11 22:42:46 +00:00
Sergey Poznyakoff
208389f3ad (AM_CPPFLAGS): Define LOCALEDIR 2006-03-11 22:42:07 +00:00
Paul Eggert
db0f0804f5 Remove unistd_.h from lib/.cvsignore. 2006-03-08 02:00:47 +00:00
Paul Eggert
18486cf8d7 * src/buffer.c (record_buffer_aligned): New var.
(init_buffer): Use it to ensure that the buffer is aligned.
This doesn't result in any measurable performance improvement
on my host (Debian GNU/Linux 3.1 stable, with default block size),
but I assume it does help on some hosts.
2006-03-08 00:55:56 +00:00
Paul Eggert
6c1020d386 * lib/.cvsignore: Add unistd_.h. Sort. 2006-03-08 00:23:34 +00:00
Sergey Poznyakoff
38c0884898 Update 2006-03-04 09:58:26 +00:00
Sergey Poznyakoff
7bcb876c5a Use -f - to read from stdin. 2006-03-04 09:57:44 +00:00
Sergey Poznyakoff
dfd5ec2519 Update 2006-02-21 07:10:52 +00:00
Sergey Poznyakoff
e81556858b Fix typo: --to-command instead of --to-program 2006-02-21 07:09:39 +00:00
Paul Eggert
92554b7c94 * tests/multiv04.at (split directory members in a MV archive):
Don't use %X in an awk printf format; this doesn't work with
Solaris 10 /usr/bin/awk.  Use %x instead.
2006-02-21 05:55:28 +00:00
Sergey Poznyakoff
631de61428 Fix copyright years 2006-02-20 10:01:47 +00:00
Sergey Poznyakoff
8bfefd8854 Uniformly start all test titles with a lower case letter 2006-02-20 10:00:48 +00:00
Sergey Poznyakoff
f7a29307e2 Update 2006-02-20 09:45:23 +00:00
150 changed files with 15234 additions and 4650 deletions

View File

@@ -3,7 +3,6 @@
*.tar
.bootstrap
ABOUT-NLS
COPYING
INSTALL
Makefile
Makefile.in
@@ -13,5 +12,7 @@ build-aux
config.*
configure
gnulib
m4
rmt
stamp-h1
tar-[0-9]*

41
AUTHORS
View File

@@ -1,34 +1,15 @@
Authors of GNU tar.
The following contributions warranted legal paper exchanges with the
Free Software Foundation. Also see files ChangeLog and THANKS.
Public domain tar was written by John Gilmore, with contributions from
Henry Spencer, Fred Fish, Ian Darwin, Geoff Collyer, Stan Barber, Guy
Harris, Dave Brower, Richard Todd, Michael Rendell, Stu Heiss, and
Rich Salz.
TAR Sergey Poznyakoff 2003-10
Assigns his past and future changes.
The FSF version, named GNU tar, was derived from public domain tar by
Jay Fenlason and Joy Kendall. Amy Gorin and Melissa Weisshaus
contributed to the manual. GNU tar has been maintained in turn by
Thomas Bushnell BSG, François Pinard, Paul Eggert, and Sergey
Poznyakoff.
TAR Paul Eggert 2000-10
Assigns his past and future changes.
TAR Jay Fenlason
Assigns his changes.
TAR Richard E Salz 1993-03-11
Disclaims changes to getdate.y.
TAR MANUAL (?) Amy Gorin (US 1963) 1995-01-10
Assigns the Tar Manual.
TAR Francois Pinard Canada 1949 1996-02-01
Assigns past and future changes.
TAR Melissa Weisshaus US 1966 1997-04-09
Assigns changes to the manual and future changes.
melissa@gnu.ai.mit.edu
TAR Thomas Michael Innis Bushnell US 1967 1997-04-09
Assigns changes.
thomas@gnu.ai.mit.edu
TAR Thomas Michael Innis Bushnell US 1967 1997-04-09
Assigns changes to manual.
thomas@gnu.ai.mit.edu
Many others have contributed to GNU tar; please see the files THANKS
and ChangeLog.

676
COPYING Normal file
View File

@@ -0,0 +1,676 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 of the License, 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, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

1416
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
# Main Makefile for GNU tar.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2007 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 2, or (at your option)
## 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,
@@ -22,3 +22,10 @@ ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = ChangeLog.1 PORTS
SUBDIRS = doc lib rmt src scripts po tests
dist-hook:
-rm -f $(distdir).cpio
find $(distdir) | cpio -Hcrc -o | \
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
distclean-local:
-rm -f $(distdir).cpio.gz

294
NEWS
View File

@@ -1,11 +1,267 @@
GNU tar NEWS - User visible changes.
GNU tar NEWS - User visible changes. 2008-03-27
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.19.90 (CVS)
* New option --auto-compress (-a)
With --create, selects compression algorithm basing on the suffix
of the archive file name.
* New option --lzma
Selects LZMA compression algorithm
* New option --hard-dereference
During archive creation, dereferences hard links and stores the files
they refer to, instead of creating usual hard link members (type '1').
* New option --checkpoint-action
This action allows to specify an action to be executed upon hitting a
checkpoint. Recognized actions are: dot, echo (the default),
echo=string, ttyout=string, exec=cmdline, and sleep=value. Any number
of `--checkpoint-action' options can be specified, the actions will be
executed in order of their appearance in the command line. See
chapter 3.8 "Checkpoints" for a complete description.
* New options --no-check-device, --check-device.
The `--no-check-device' option disables comparing device numbers during
preparatory stage of an incremental dump. This allows to avoid
creating full dumps if the device numbers change (e.g. when using an
LVM snapshot).
The `--check-device' option enables comparing device numbers. This is
the default. This option is provided to undo the effect of the previous
`--no-check-device' option, e.g. if it was set in TAR_OPTIONS
environment variable.
* The --transform option.
Any number of `--transform' options can be given in the command line.
The specified transformations will be applied in turn.
The argument to `--transform' option can be a list of replace
expressions, separated by a semicolon (as in `sed').
Filename transformations are applied to symbolic link targets
during both creation and extraction. Tar 1.19 used them only
during extraction.
For a detailed description, see chapter 6.7 "Modifying File and Member
Names".
* Info (end-of-volume) scripts
The value of the blocking factor is made available to info and
checkpoint scripts via environment variable TAR_BLOCKING_FACTOR.
* Bugfixes.
** Fix bug introduced in version 1.19: tar refused to update non-existing
archives.
version 1.19 - Sergey Poznyakoff, 2007-10-10
* New option --exclude-vcs
Excludes directories and files, created by several widely used version
control systems, e.g. "CVS/", ".svn/", etc.
* --exclude-tag and --exclude-cache options
The following options now work with incremental archives as well:
--exclude-caches
--exclude-caches-all
--exclude-tag
--exclude-tag-all
--exclude-tag-under
* Fix handling of renamed files in listed incremental archives.
Previous versions always stored absolute file names in rename
records, even if -P was not used. This is fixed: rename records
contain file names processed in accordance with the command line
settings.
* Fix --version output.
* Recognition of broken archives.
When supplied an archive smaller than 512 bytes in reading mode (-x,
-t), the previous version of tar silently ignored it, exiting with
code 0. It is fixed. Tar now issues the following diagnostic message:
'This does not look like a tar archive', and exits with code 2.
* Fix double-dot recognition in archive member names in case of duplicate '/.'.
* Fix file padding in case of truncation of the input file to zero size.
version 1.18 - Sergey Poznyakoff, 2007-06-29
* Licensed under the GPLv3
* Fixed several bugs in the testsuite
version 1.17 - Sergey Poznyakoff, 2007-06-08
* Fix archivation of sparse files in posix mode. Previous versions padded
sparse members with spurious zero blocks.
* Fix operation of --verify --listed-incremental. Version 1.16.1 produced
a full dump when both options were given.
* Fix --occurrence. In previous versions it continued scanning the archive
even though all requested members has already been extracted.
* Scope of --transform and --strip-components options.
In addition to affecting regular archive members, the --transform
option affects hard and soft link targets and the --strip-components
option affects hard link targets as well.
* End-of-volume script can send the new volume name to tar by writing
it to the file descriptor stored in the environment variable `TAR_FD'.
version 1.16.1 - Sergey Poznyakoff, 2006-12-09
* New option --exclude-tag allows to specify "exclusion tag files", i.e.
files whose presence in a directory means that the directory should not
be archived.
* The --exclude-cache option excludes directories that contain the
CACHEDIR.TAG file from being archived. Previous versions excluded
directory contents only, while the directories themselves were
still added to the archive.
* Support for reading ustar type 'N' header logical records has been removed.
This GNU extension was generated only by very old versions of GNU 'tar'.
Unfortunately its implementation had security holes; see
<http://archives.neohapsis.com/archives/fulldisclosure/2006-11/0344.html>.
We don't expect that any tar archives in practical use have type 'N'
records, but if you have one and you trust its contents, you can
decode it with GNU tar 1.16 or earlier.
* Race conditions have been fixed that in some cases briefly allowed
files extracted by 'tar -x --same-owner' (or plain 'tar -x', when
running as root) to be accessed by users that they shouldn't have been.
version 1.16 - Sergey Poznyakoff, 2006-10-21
* After creating an archive, tar exits with code 1 if some files were
changed while being read. Previous versions exited with code 2 (fatal
error), and only if some files were truncated while being archived.
* New option --mtime allows to set modification times for all archive
members during creation.
* Bug fixes
** Avoid running off file descriptors when using multiple -C options.
** tar --index-file=FILE --file=- sent the archive to FILE, and
the listing to stderr.
version 1.15.91 - Sergey Poznyakoff, 2006-06-16
* Incompatible changes
** Globbing
Previous versions of GNU tar assumed shell-style globbing when
extracting from or listing an archive. For example:
tar xf foo.tar '*.c'
would extract all files whose names end in '.c'. This behavior
was not documented and was incompatible with traditional tar
implementations. Therefore, starting from this version, GNU tar
no longer uses globbing by default. For example, the above invocation
is now interpreted as a request to extract from the archive the file
named '*.c'.
To treat member names as globbing patterns, use --wildcards option.
If you wish tar to mimic the behavior of versions up to 1.15.90,
add --wildcards to the value of the environment variable TAR_OPTIONS.
The exact way in which tar interprets member names is controlled by the
following command line options:
--wildcards use wildcards
--anchored patterns match file name start
--ignore-case ignore case
--wildcards-match-slash wildcards match `/'
Each of these options has a '--no-' counterpart that disables its
effect (e.g. --no-wildcards).
These options affect both the interpretation of member names from
command line and that of the exclusion patterns (given with --exclude
and --exclude-from options). The defaults are:
1. For member names: --no-wildcards --anchored
2. For exclusion patterns: --wildcards --no-anchored --wildcards-match-slash
The options can appear multiple times in the command line, thereby
changing the way command line arguments are interpreted. For example,
to use case-insensitive matching in exclude patterns and to revert to
case-sensitive matching for the rest of command line, one could write:
tar xf foo.tar --ignore-case --exclude-from=FILE --no-ignore-case file.name
** Short option -l is now an alias of --check-links option, which complies
with UNIX98. This ends the transition period started with version 1.14.
* New features
** New option --transform allows to transform file names before storing them
in the archive or member names before extracting. The option takes a
sed replace expression as its argument. For example,
tar cf foo.tar --transform 's,^,prefix/,'
will add 'prefix/' to all file names stored in foo.tar.
** --strip-components option works when deleting and comparing. In previous
versions it worked only with --extract.
** New option --show-transformed-names enables display of transformed file
or archive. It generalizes --show-stored-names option, introduced in
1.15.90. In particular, when creating an archive in verbose mode, it lists
member names as stored in the archive, i.e., with any eventual prefixes
removed and file name transformations applied. The option is useful,
for example, while comparing `tar cv' and `tar tv' outputs.
** New incremental snapshot file format keeps information about file names
as well as that about directories.
** The --checkpoint option takes an optional argument specifying the number
of records between the two successive checkpoints. Optional dot
starting the argument intructs tar to print dots instead of textual
checkpoints.
** The --totals option can be used with any tar operation (previous versions
understood it only with --create). If an argument to this option is
given, it specifies the signal upon delivery of which the statistics
is to be printed. Both forms of this option (with and without
argument) can be given to in a single invocation of tar.
* Bug fixes
** Detect attempts to update compressed archives.
version 1.15.90 - Sergey Poznyakoff, 2006-02-19
* New features
* Any number of -T (--files-from) options may be used in the command line.
** Any number of -T (--files-from) options may be used in the command line.
The file specified with -T may include any valid `tar' options,
including another -T option.
Compatibility note: older versions of tar would only recognize -C
@@ -13,14 +269,14 @@ as an option name within the file list file. Now any file whose name
starts with - is handled as an option. To insert file names starting with
dash, use the --add-file option.
* List files containing null-separated file names are detected and processed
** List files containing null-separated file names are detected and processed
automatically. It is no longer necessary to give the --null option.
* New option --no-unquote disables the unquoting of input file names.
** New option --no-unquote disables the unquoting of input file names.
This is useful for processing output from `find dir -print0'.
An orthogonal option --unquote is provided as well.
* New option --test-label tests the archive volume label.
** New option --test-label tests the archive volume label.
If an argument is specified, the label is compared against its value.
Tar exits with code 0 if the two strings match, and with code 2 if
they do not.
@@ -28,28 +284,28 @@ they do not.
If no argument is given, the --verbose option is implied. In this case,
tar prints the label name if present and exits with code 0.
* New option --show-stored-names. When creating an archive in verbose mode,
** New option --show-stored-names. When creating an archive in verbose mode,
it lists member names as stored in the archive, i.e., with any eventual
prefixes removed. The option is useful, for example, while comparing
`tar cv' and `tar tv' outputs.
* New option --to-command pipes the contents of archive members to the
** New option --to-command pipes the contents of archive members to the
specified command.
* New option --atime-preserve=system, which uses the O_NOATIME feature
** New option --atime-preserve=system, which uses the O_NOATIME feature
of recent Linux kernels to avoid some problems when preserving file
access times.
* New option --delay-directory-restore delays restoring modification times
** New option --delay-directory-restore delays restoring modification times
and permissions of extracted directories until the end of extraction.
This is necessary for restoring from archives with unusual member
ordering (in particular, those created with --no-recursion option).
This option is implied when restoring from incremental archives.
* New option --restrict prohibits use of some potentially harmful tar
** New option --restrict prohibits use of some potentially harmful tar
options. Currently it disables '!' escape in multi-volume name menu.
* New options --quoting-style and --quote-chars control the way tar
** New options --quoting-style and --quote-chars control the way tar
quotes member names on output. The --quoting-style takes an argument
specifying the quoting style to use (literal, shell, shell-always,
c, escape, locale, clocale). The argument to --quote-chars is a string
@@ -57,17 +313,17 @@ specifying characters to quote, even if the selected quoting style
would not quote them otherwise. The option --no-quote-chars is
provided to disable quoting certain characters.
* The end-of-volume script (introduced with --info-script option) can
** The end-of-volume script (introduced with --info-script option) can
get current archive name from the environment variable TAR_ARCHIVE and
the volume number from the variable TAR_VOLUME. It can alter the
archive name by writing new name to the file descriptor 3.
* Better support for full-resolution time stamps. Tar cannot restore
** Better support for full-resolution time stamps. Tar cannot restore
time stamps to full nanosecond resolution, though, until the kernel
guys get their act together and give us a system call to set file time
stamps to nanosecond resolution.
* The -v option now prints time stamps only to 1-minute resolution,
** The -v option now prints time stamps only to 1-minute resolution,
not full resolution, to avoid using up too many output columns.
Nanosecond resolution is now supported, but that would be too much.
@@ -81,7 +337,7 @@ Consequently, the file pointer was set off and the next member
was not processed correctly.
** Previous version created invalid archives when files shrink
during reading.
** Compare mode (tar d) hanged when trying to compare file contents.
** Compare mode (tar d) hung when trying to compare file contents.
** Previous versions in certain cases failed to restore directory
modification times.
** When creating an archive, do not attempt to store files whose
@@ -738,13 +994,13 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
2004, 2005, 2006 Free Software Foundation, Inc.
2004, 2005, 2006, 2007, 2008 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 2, or (at your option)
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU tar is distributed in the hope that it will be useful,
@@ -760,4 +1016,8 @@ Boston, MA 02110-1301, USA.
Local variables:
mode: outline
paragraph-separate: "[ ]*$"
eval: (add-hook 'write-file-hooks 'time-stamp)
time-stamp-start: "changes. "
time-stamp-format: "%:y-%02m-%02d"
time-stamp-end: "\n"
end:

6
PORTS
View File

@@ -145,13 +145,13 @@ See the end of file for copying conditions.
* Copyright notice
Copyright (C) 1999, 2001, 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2003, 2004, 2007 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 2, or (at your option)
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU tar is distributed in the hope that it will be useful,
@@ -170,4 +170,4 @@ mode: outline
paragraph-separate: "[ ]*$"
version-control: never
End:

6
README
View File

@@ -78,7 +78,7 @@ scripts.
** `--disable-largefile' omits support for large files, even if the
operating system supports large files. Typically, large files are
those larger on 2 GB on a 32-bit host.
those larger than 2 GB on a 32-bit host.
* Installation hints
@@ -223,13 +223,13 @@ and share your findings by writing to <bug-tar@gnu.org>.
* Copying
Copyright (C) 1990, 1991, 1992, 1994, 1997, 1998, 1999, 2000,
2001, 2003, 2004 Free Software Foundation, Inc.
2001, 2003, 2004, 2007 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 2, or (at your option)
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU tar is distributed in the hope that it will be useful,

View File

@@ -14,6 +14,7 @@ that you have the latest stable version.
- Gettext <http://www.gnu.org/software/gettext/>
- Gzip <http://www.gnu.org/software/gzip/>
- M4 <http://www.gnu.org/software/m4/>
- Texinfo <http://www.gnu.org/software/texinfo>
- Wget <http://www.gnu.org/software/wget/>
As of this writing, the latest stable version of Gzip is 1.2.4 but we
@@ -61,13 +62,13 @@ some other value.
Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 2001, 2003, 2004, 2005, 2007 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 2, or (at your option)
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU tar is distributed in the hope that it will be useful,

70
README-cvs Normal file
View File

@@ -0,0 +1,70 @@
-*- outline -*-
These notes intend to help people working on the CVS version of
this package.
* Requirements
Only the sources are installed in the CVS repository (to ease the
maintenance, merges etc.), therefore you will have to get the latest
stable versions of the maintainer tools we depend upon, including:
- Automake <http://www.gnu.org/software/automake/>
- Autoconf <http://www.gnu.org/software/autoconf/>
- Bison <http://www.gnu.org/software/bison/>
- Gettext <http://www.gnu.org/software/gettext/>
- Gzip <http://www.gnu.org/software/gzip/>
- Tar <http://www.gnu.org/software/tar/>
- Wget <http://www.gnu.org/software/wget/>
As of this writing, the latest stable version of Gzip is 1.2.4 but we
suggest using test version 1.3.5 (or later, if one becomes available).
Valgrind <http://valgrind.org/> is also highly recommended, if
Valgrind supports your architecture.
Only building the initial full source tree will be a bit painful,
later, a plain `cvs update -P && make' should be sufficient.
* First CVS checkout
Obviously, if you are reading these notes, you did manage to check out
this package from CVS. The next step is to get other files needed to
build, which are extracted from other source packages:
$ ./bootstrap
And there you are! Just
$ ./configure
$ make
$ make check
At this point, there should be no difference between your local copy,
and the CVS master copy:
$ cvs diff
should output no difference.
Enjoy!
-----
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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.

20
THANKS
View File

@@ -1,11 +1,6 @@
GNU tar THANKS file
Public domain tar was written by John Gilmore, with contributions
from Henry Spencer, Fred Fish, Ian Darwin, Geoff Collyer, Stan Barber,
Guy Harris, Dave Brower, Richard Todd, Michael Rendell, Stu Heiss and
Rich $alz. The FSF version, named GNU tar, was derived from PDTAR by
Jay Fenlason and Joy Kendall, and was maintained in turn by François
Pinard, Paul Eggert and Sergey Poznyakoff.
Please see the AUTHORS file for the list of principal authors.
Many people further contributed to GNU tar by reporting problems,
suggesting various improvements or submitting actual code. Here is a
@@ -53,6 +48,7 @@ Bela Lubkin filbo@armory.com
Ben A. Mesander ben@piglet.cr.usgs.gov
Benedikt Stockebrand benedikt@devnull.ruhr.de
Bennett Todd bet@mordor.com
Benno Schulenberg benno@nietvergeten.nl
Benny Holmgren benny@hgs.se
Bernard Chen bern@cs.ucla.edu
Bernard Derval derval@iro.umontreal.ca
@@ -219,11 +215,14 @@ Jan Djarv jan.djarv@mbox200.swipnet.se
Janice Burton r06a165@bcc25.kodak.com
Janne Snabb snabb@niksula.hut.fi
Jason R. Mastaler jason@webmaster.net
Jason Armistead Jason.Armistead@otis.com
Jay Fenlason hack@gnu.org
Jean-Louis Martineau martineau@zmanda.com
Jean-Michel Soenen soenen@lectra.fr
Jean-Ph. Martin-Flatin syj@ecmwf.int
Jean-loup Gailly jloup@chorus.fr
Jean-Loup Gailly jloup@chorus.fr
Jeff Moskow jeff@rtr.com
Jean-Ph. Martin-Flatin syj@ecmwf.int
Jean-Pierre Demailly Jean-Pierre.Demailly@ujf-grenoble.fr
Jeff Prothero jsp@betz.biostr.washington.edu
Jeff Siegel js@hornet.att.com
Jeff Sorensen sorenj@alumni.rpi.edu
@@ -267,6 +266,7 @@ Jurgen Botz jbotz@orixa.mtholyoke.edu
Jyh-Shyang Wang erik@vsp.ee.nctu.edu.tw
Jörg Schilling schilling@fokus.fraunhofer.de
Jörg Weule weule@cs.uni-duesseldorf.de
Jörg Weilbier gnu@weilbier.net
Jörgen Hågg Jorgen.Hagg@axis.se
Jörgen Weigert jw@suse.de
Jürgen Lüters jlueters@t-online.de
@@ -292,6 +292,7 @@ Konno Hiroharu konno@pac.co.jp
Kurt Jaeger pi@lf.net
Larry Creech lcreech@lonestar.rcclub.org
Larry Schwimmer rosebud@cyclone.stanford.edu
Lasse Collin lasse.collin@tukaani.org
Laurent Caillat-Vallet caillat@noe.lyon.cemagref.fr
Laurent Sainte-Marthe smarthe@genethon.fr
Leland Lucius llucius@tiny.net
@@ -389,6 +390,7 @@ Pierce Cantrell cantrell@ee.tamu.edu
R. Kent Dybvig dyb@cadence.bloomington.in.us
R. Scott Butler butler@prism.es.dupont.com
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
Ralf Wildenhues Ralf.Wildenhues@gmx.de
Ralf S. Engelschall rse@engelschall.com
Ralf Suckow suckow@contrib.de
Ralph Corderoy ralph@inputplus.co.uk
@@ -462,6 +464,7 @@ Sylvain Rougier un@grolier.fr
Tarang Kumar Patel mombasa@ptolemy.arc.nasa.gov
Ted Rule Ted_Rule@flextech.co.uk
The King elvis@gnu.org
Thomas metaf4@users.askja.de
Thomas Bushnell n/BSG thomas@gnu.org
Thomas Krebs krebs@faps.uni-erlangen.de
Thomas König Thomas.Koenig@ciw.uni-karlsruhe.de
@@ -508,6 +511,7 @@ William Kucharski kucharsk@netcom.com
Wojciech Polak polak@gnu.org
Wolfgang Rupprecht wolfgang@wsrcc.com
Wolfram Gloger Wolfram.Gloger@dent.med.uni-muenchen.de
Wolfram Kleff bugreport@wkleff.intergenia.de
Wolfram Wagner ww@mpi-sb.mpg.de
Włodzimierz Jan Martin wjm@pg.gda.pl
Yasushi Suzudo SGR00413@niftyserve.or.jp

22
TODO
View File

@@ -1,5 +1,7 @@
Suggestions for improving GNU tar.
* <45BEC0DB.8040903@unix-beratung.de>
* Incorporate fixes from major distributions, e.g., Debian GNU/Linux.
* Add support for restoring file time stamps to sub-second resolution,
@@ -10,25 +12,9 @@ Suggestions for improving GNU tar.
* --append should bail out if the two archives are of different types.
* Add support for GNU private keywords in POSIX 1003.1-2001 headers,
so that the GNU extensions (--incremental, --label and
--multi-volume) may be used with POSIX archives.
* Add support for a 'pax' command that conforms to POSIX 1003.1-2001.
This would unify paxutils with tar.
* Remove command-line incompatibilities between GNU tar and UNIX tar
as specified by UNIX98. The main problem is:
l GNU tar doesn't cross filesystem boundaries.
UNIX98 tar warns if all links cannot be resolved.
(GNU tar --check-links option)
Currently tar prints a warning when this option is used. Sometime
in the future its semantics will be changed to that of --check-links.
In the meanwhile we should announce a phase-in period where "l"
changes in semantics.
* Interoperate better with Joerg Schilling's star implementation.
* Add an option to remove files that compare successfully.
@@ -59,13 +45,13 @@ so that the GNU extensions (--incremental, --label and
* Copyright notice
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2007 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 2, or (at your option)
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU tar is distributed in the hope that it will be useful,

732
bootstrap
View File

@@ -1,12 +1,12 @@
#! /bin/sh
# Bootstrap 'tar' from CVS.
# Bootstrap this package from CVS.
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
# Copyright (C) 2003, 2004, 2005, 2006, 2007 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 2, or (at your option)
# 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,
@@ -21,174 +21,298 @@
# Written by Paul Eggert and Sergey Poznyakoff.
# URL of our text domain page in Translation Project
TP_URL="http://www.iro.umontreal.ca/translation/maint/tar/"
nl='
'
# Ensure file names are sorted consistently across platforms;
# e.g., m4/ulonglong_gl.m4 should follow m4/ulonglong.m4.
# Ensure file names are sorted consistently across platforms.
# Also, ensure diagnostics are in English, e.g., "wget --help" below.
LC_ALL=C
export LC_ALL
usage() {
cat <<EOF
usage: $0 [--gnulib-srcdir=DIR][--paxutils-srcdir=DIR][--cvs-auth=AUTH-METHOD][--cvs-user=USERNAME][--no-po]
Options are:
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
sources reside. Use this if you already
have paxutils sources on your machine, and
do not want to waste your bandwidth dowloading
them again.
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
do not want to waste your bandwidth dowloading
them again.
--cvs-auth=METHOD Set the CVS access method used for downloading
gnulib files. METHOD is one of the keywords
accepted by cvs -d option (see info cvs
repository).
--cvs-user=USERNAME Set the CVS username to be used when accessing
the gnulib repository.
--no-po Do not download po files.
--update-po[=LANG] Update po file(s) and exit.
echo >&2 "\
Usage: $0 [OPTION]...
Bootstrap this package from the checked-out sources.
If the file \`.bootstrap' exists in the current working directory, its
contents is read, comments and empty lines removed, shell variables expanded
and the result is prepended to the command line options.
Options:
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
sources reside. Use this if you already
have paxutils sources on your machine, and
do not want to waste your bandwidth dowloading
them again.
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
sources reside. Use this if you already
have gnulib sources on your machine, and
do not want to waste your bandwidth dowloading
them again.
--copy Copy files instead of creating symbolic links.
--force Attempt to bootstrap even if the sources seem
not to have been checked out.
--skip-po Do not download po files.
--update-po Update po files and exit.
--cvs-user=USERNAME Set the CVS username to be used when accessing
the paxutils repository.
Running without arguments will suffice in most cases. It is equivalent
to
If the file bootstrap.conf exists in the current working directory, its
contents are read as shell variables to configure the bootstrap.
./bootstrap --cvs-auth=pserver
Local defaults can be provided by placing the file \`.bootstrap' in the
current working directory. The file is read after bootstrap.conf, comments
and empty lines are removed, shell variables expanded and the result is
prepended to the command line options.
EOF
Running without arguments will suffice in most cases.
"
}
update_po() {
if [ $# = 1 ]; then
checkout() {
if [ ! -d $1 ]; then
echo "$0: getting $1 files..."
case $1 in
*.po) POFILE=$1;;
*) POFILE=${1}.po;;
paxutils)
case ${CVS_AUTH-pserver} in
pserver)
CVS_PREFIX=':pserver:anonymous@';;
ssh)
CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
*)
echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
exit 1;;
esac
case $CVS_RSH in
'') CVS_RSH=ssh; export CVS_RSH;;
esac
CVSURL=${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1"
;;
gnulib)
CVSURL=:pserver:anonymous@pserver.git.sv.gnu.org:/gnulib.git
;;
esac
echo "$0: getting translation for $1..."
wget -r --cache=off $TP_URL/$POFILE
else
echo "$0: getting translations into po..."
(cd po &&
rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'` &&
wget -nv -nd -r -l 1 -A .po --cache off $TP_URL &&
rm -f index.html index.html.[0-9]*
ls *.po | sed 's/\.po$//' >LINGUAS
) || exit
trap "cleanup $1" 1 2 13 15
cvs -z3 -q -d $CVSURL co $1 || cleanup $1
trap - 1 2 13 15
fi
}
# Read configuration file
cleanup() {
status=$?
rm -fr $1
exit $status
}
# Configuration.
# List of gnulib modules needed.
gnulib_modules=
# Any gnulib files needed that are not in modules.
gnulib_files=
# The command to download all .po files for a specified domain into
# a specified directory. Fill in the first %s is the domain name, and
# the second with the destination directory. Use rsync's -L and -r
# options because the latest/%s directory and the .po files within are
# all symlinks.
po_download_command_format=\
"rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
extract_package_name='
/^AC_INIT(/{
/.*,.*,.*,/{
s///
s/[][]//g
p
q
}
s/AC_INIT(\[*//
s/]*,.*//
s/^GNU //
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
s/[^A-Za-z0-9_]/-/g
p
}
'
package=`sed -n "$extract_package_name" configure.ac` || exit
# Extra files from gnulib, which override files from other sources.
gnulib_extra_files='
build-aux/announce-gen
build-aux/install-sh
build-aux/missing
build-aux/mdate-sh
build-aux/texinfo.tex
build-aux/depcomp
build-aux/config.guess
build-aux/config.sub
doc/INSTALL
'
# Other locale categories that need message catalogs.
EXTRA_LOCALE_CATEGORIES=
# Additional xgettext options to use. Use "\\\newline" to break lines.
XGETTEXT_OPTIONS='\\\
--flag=_:1:pass-c-format\\\
--flag=N_:1:pass-c-format\\\
--flag=error:3:c-format --flag=error_at_line:5:c-format\\\
'
# Files we don't want to import.
excluded_files=
# File that should exist in the top directory of a checked out hierarchy,
# but not in a distribution tarball.
CVS_only_file=README-cvs
# Whether to use copies instead of symlinks.
copy=false
# Override the default configuration, if necessary.
test -r bootstrap.conf && . ./bootstrap.conf
# Read local configuration file
if [ -r .bootstrap ]; then
echo "$0: Reading configuration file .bootstrap"
eval set -- "`sed 's/#.*$//;/^$/d' .bootstrap | tr '\n' ' '` $*"
fi
# Translate configuration into internal form.
# Parse options.
DOWNLOAD_PO=yes
for option
do
case $option in
--help)
usage
exit;;
--gnulib-srcdir=*)
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
--paxutils-srcdir=*)
PAXUTILS_SRCDIR=`expr "$option" : '--paxutils-srcdir=\(.*\)'`;;
--cvs-auth=*)
CVS_AUTH=`expr "$option" : '--cvs-auth=\(.*\)'`;;
--gnulib-srcdir=*)
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
--cvs-user=*)
CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
--no-po)
DOWNLOAD_PO=no;;
--skip-po | --no-po) # --no-po is for compatibility with 'tar' tradition.
DOWNLOAD_PO=skip;;
--update-po=*)
DOWNLOAD_PO=`expr "$option" : '--update-po=\(.*\)'`;;
--update-po)
DOWNLOAD_PO=only;;
--force)
CVS_only_file=;;
--copy)
copy=true;;
*)
echo >&2 "$0: $option: unknown option"
exit 1;;
esac
done
if test -n "$CVS_only_file" && test ! -r "$CVS_only_file"; then
echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
exit 1
fi
echo "$0: Bootstrapping CVS $package..."
# Get translations.
download_po_files() {
subdir=$1
domain=$2
echo "$0: getting translations into $subdir for $domain..."
cmd=`printf "$po_download_command_format" "$domain" "$subdir"`
eval "$cmd"
}
# Download .po files to $po_dir/.reference and copy only the new
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
update_po_files() {
# Directory containing primary .po files.
# Overwrite them only when we're sure a .po file is new.
po_dir=$1
domain=$2
# Download *.po files into this dir.
# Usually contains *.s1 checksum files.
ref_po_dir="$po_dir/.reference"
test -d $ref_po_dir || mkdir $ref_po_dir || return
download_po_files $ref_po_dir $domain \
&& ls "$ref_po_dir"/*.po 2>/dev/null |
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
test "$langs" = '*' && langs=x
for po in `cd $ref_po_dir && echo *.po|sed 's/\.po//g'`; do
case $po in x) continue;; esac
new_po="$ref_po_dir/$po.po"
cksum_file="$ref_po_dir/$po.s1"
if ! test -f "$cksum_file" ||
! test -f "$po_dir/$po.po" ||
! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
echo "updated $po_dir/$po.po..."
cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
fi
done
}
case $DOWNLOAD_PO in
only) update_po
exit 0
;;
no|yes) ;;
*) update_po $DOWNLOAD_PO
exit 0
'skip')
;;
'')
if test -d po; then
update_po_files po $package || exit
fi
;;
'only')
if test -d po; then
update_po_files po $package || exit
fi
exit
;;
esac
echo "$0: Bootstrapping CVS tar..."
# Get paxutils files.
build_cvs_prefix() {
CVS_PREFIX=:${1}:
if [ "${2}" != - ]; then
CVS_PREFIX=${CVS_PREFIX}${2}@
fi
if [ "$1" = "ext" ]; then
if [ -z "${CVS_RSH}" ]; then
CVS_RSH=ssh
export CVS_RSH
fi
fi
}
# checkout package
checkout() {
if [ ! -d $1 ]; then
echo "$0: getting $1 files..."
trap exit 1 2 13 15
trap 'rm -fr $1; exit 1' 0
case "${CVS_AUTH-pserver}" in
pserver) build_cvs_prefix pserver ${CVS_USER:-anonymous}
;;
gserver|server)
build_cvs_prefix $CVS_AUTH ${CVS_USER--}
;;
ext) build_cvs_prefix $CVS_AUTH ${CVS_USER--}
;;
*) echo "$0: Unknown CVS access method" >&2
exit 1;;
esac
cvs -q -d ${CVS_PREFIX}cvs.sv.gnu.org:/cvsroot/$1 co $1 || exit
trap - 0
fi
}
gnulib_modules=
newline='
'
get_modules() {
new_gnulib_modules=`sed '/^[ ]*#/d; /^[ ]*$/d' $*`
case $gnulib_modules,$new_gnulib_modules in
?*,?*) new_gnulib_modules=$newline$new_gnulib_modules;;
esac
gnulib_modules=$gnulib_modules$new_gnulib_modules
}
# Get paxutils files
case ${PAXUTILS_SRCDIR--} in
-) checkout paxutils
PAXUTILS_SRCDIR=paxutils
esac
if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
get_modules $PAXUTILS_SRCDIR/gnulib.modules
gnulib_modules=`
(echo "$gnulib_modules"; grep '^[^#]' $PAXUTILS_SRCDIR/gnulib.modules) |
sort -u
`
fi
ignore_file_list=
cleanup_ifl() {
test -n "$ignore_file_list" && rm -f $ignore_file_list
}
trap 'cleanup_ifl' 1 2 3 15
# ignorefile DIR FILE
# add FILE to the temporary ignorelist in the directory DIR
ignorefile() {
file=$1/.ignore.$$
echo "$2" >> $file
if `echo $ignore_list | grep -qv $file`; then
ignore_file_list="$ignore_file_list
$file"
fi
}
# copy_files srcdir dstdir
copy_files() {
for file in `cat $1/DISTFILES`
@@ -205,16 +329,258 @@ copy_files() {
fi
echo "$0: Copying file $1/$file to $2/$dst"
cp -p $1/$file $2/$dst
ignorefile $2 $dst
done
}
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
-)
checkout gnulib
GNULIB_SRCDIR=gnulib
esac
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
<$gnulib_tool || exit
ensure_dir_exists()
{
d=`dirname $dst`
test -d "$d" || mkdir -p -- "$d"
}
symlink_to_gnulib()
{
src=$GNULIB_SRCDIR/$1
dst=${2-$1}
test -f "$src" && {
if $copy; then
{
test ! -h "$dst" || {
echo "$0: rm -f $dst" &&
rm -f "$dst"
}
} &&
test -f "$dst" &&
cmp -s "$src" "$dst" || {
echo "$0: cp -fp $src $dst" &&
ensure_dir_exists $dst &&
cp -fp "$src" "$dst"
}
else
test -h "$dst" &&
src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
test "$src_i" = "$dst_i" || {
dot_dots=
case $src in
/*) ;;
*)
case /$dst/ in
*//* | */../* | */./* | /*/*/*/*/*/)
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
exit 1;;
/*/*/*/*/) dot_dots=../../../;;
/*/*/*/) dot_dots=../../;;
/*/*/) dot_dots=../;;
esac;;
esac
echo "$0: ln -fs $dot_dots$src $dst" &&
ensure_dir_exists $dst &&
ln -fs "$dot_dots$src" "$dst"
}
fi
}
}
cp_mark_as_generated()
{
cp_src=$1
cp_dst=$2
if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
symlink_to_gnulib "$cp_dst"
else
case $cp_dst in
*.[ch]) c1='/* '; c2=' */';;
*.texi) c1='@c '; c2= ;;
*.m4|*/Make*|Make*) c1='# ' ; c2= ;;
*) c1= ; c2= ;;
esac
if test -z "$c1"; then
cmp -s "$cp_src" "$cp_dst" || {
echo "$0: cp -f $cp_src $cp_dst" &&
cp -f "$cp_src" "$cp_dst"
}
else
# Copy the file first to get proper permissions if it
# doesn't already exist. Then overwrite the copy.
cp "$cp_src" "$cp_dst-t" &&
(
echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
cat "$cp_src"
) > $cp_dst-t &&
if cmp -s "$cp_dst-t" "$cp_dst"; then
rm -f "$cp_dst-t"
else
echo "$0: cp $cp_src $cp_dst # with edits" &&
mv -f "$cp_dst-t" "$cp_dst"
fi
fi
fi
}
version_controlled_file() {
dir=$1
file=$2
found=no
if test -d CVS; then
grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
grep '^/[^/]*/[0-9]' > /dev/null && found=yes
elif test -d .git; then
git-rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
else
echo "$0: no version control for $dir/$file?" >&2
fi
test $found = yes
}
slurp() {
for dir in . `(cd $1 && find * -type d -print)`; do
copied=
sep=
for file in `ls $1/$dir`; do
test -d $1/$dir/$file && continue
for excluded_file in $excluded_files; do
test "$dir/$file" = "$excluded_file" && continue 2
done
if test $file = Makefile.am; then
copied=$copied${sep}gnulib.mk; sep=$nl
remove_intl='/^[^#].*\/intl/s/^/#/;'"s,/$bt,,g"
sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/gnulib.mk || {
echo "$0: Copying $1/$dir/$file to $dir/gnulib.mk ..." &&
rm -f $dir/gnulib.mk &&
sed "$remove_intl" $1/$dir/$file >$dir/gnulib.mk
}
elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
version_controlled_file $dir $file; then
echo "$0: $dir/$file overrides $1/$dir/$file"
else
copied=$copied$sep$file; sep=$nl
if test $file = gettext.m4; then
echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
rm -f $dir/$file
sed '
/^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
AC_DEFUN([AM_INTL_SUBDIR], [
/^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
$a\
AC_DEFUN([gl_LOCK_EARLY], [])
' $1/$dir/$file >$dir/$file
else
cp_mark_as_generated $1/$dir/$file $dir/$file
fi
fi || exit
done
if test -n "$copied"; then
copied="Makefile
Makefile.in
$copied"
if test -d CVS; then
dot_ig=.cvsignore
else
dor_ig=.gitignore
fi
ig=$dir/$dot_ig
if [ -f $dir/.ignore.$$ ]; then
tfile=$dir/.ignore.$$
else
tfile=
fi
if test -f $ig; then
echo "$copied" | sort -u - $ig | cmp -s - $ig ||
echo "$copied" | sort -u - $ig $tfile -o $ig
else
copied="$dot_ig
$copied"
if [ "$dir" = "po" ]; then
copied="LINGUAS
Makevars
POTFILES
*.mo
*.gmo
*.po
remove-potcdate.sed
stamp-po
$package.pot
$copied"
fi
echo "$copied" | sort -u - $tfile -o $ig
fi || exit
fi
done
}
# Create boot temporary directories to import from gnulib and gettext.
bt='.#bootmp'
bt2=${bt}2
rm -fr $bt $bt2 &&
mkdir $bt $bt2 || exit
# Import from gnulib.
test -d build-aux || {
echo "$0: mkdir build-aux ..." &&
mkdir build-aux
} || exit
gnulib_tool_options="\
--import\
--no-changelog\
--aux-dir $bt/build-aux\
--doc-base $bt/doc\
--lib lib$package\
--m4-base $bt/m4/\
--source-base $bt/lib/\
--tests-base $bt/tests\
--local-dir gl\
"
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
$gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
slurp $bt || exit
for file in $gnulib_files; do
symlink_to_gnulib $file || exit
done
# Import from gettext.
echo "$0: (cd $bt2; autopoint) ..."
cp configure.ac $bt2 &&
(cd $bt2 && autopoint && rm configure.ac) &&
slurp $bt2 $bt || exit
rm -fr $bt $bt2 || exit
# Import from paxutils
copy_files ${PAXUTILS_SRCDIR}/m4 m4
echo "$0: Creating m4/paxutils.m4"
(echo "# This file is generated automatically. Please, do not edit."
echo "#"
echo "AC_DEFUN([tar_PAXUTILS],["
echo "AC_DEFUN([${package}_PAXUTILS],["
cat ${PAXUTILS_SRCDIR}/m4/DISTFILES | sed '/^#/d;s/\(.*\)\.m4/pu_\1/' | tr a-z A-Z
echo "])") > ./m4/paxutils.m4
ignorefile m4 paxutils.m4
if [ -d rmt ]; then
:
@@ -229,89 +595,59 @@ done
copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
-) checkout gnulib
GNULIB_SRCDIR=gnulib
esac
<$GNULIB_SRCDIR/gnulib-tool || exit
get_modules gnulib.modules
gnulib_modules=`echo "$gnulib_modules" | sort -u`
previous_gnulib_modules=
while [ "$gnulib_modules" != "$previous_gnulib_modules" ]; do
previous_gnulib_modules=$gnulib_modules
gnulib_modules=`
(echo "$gnulib_modules"
for gnulib_module in $gnulib_modules; do
$GNULIB_SRCDIR/gnulib-tool --extract-dependencies $gnulib_module
done) | sort -u
`
done
gnulib_files=`
(for gnulib_module in $gnulib_modules; do
$GNULIB_SRCDIR/gnulib-tool --extract-filelist $gnulib_module
done) | sort -u
`
gnulib_dirs=`echo "$gnulib_files" | sed 's,/[^/]*$,,' | sort -u`
mkdir -p $gnulib_dirs || exit
for gnulib_file in $gnulib_files; do
dest=$gnulib_file
case $gnulib_file in
m4/codeset.m4) continue;;
m4/intdiv0.m4) continue;;
m4/inttypes-pri.m4) continue;;
m4/isc-posix.m4) continue;;
m4/lcmessage.m4) continue;;
m4/onceonly_2_57.m4) dest=m4/onceonly.m4;;
# These will be overwritten by autopoint, which still uses
# old jm_.* macro names, so we have to keep both copies.
m4/gettext.m4 | m4/glibc21.m4 | m4/inttypes_h.m4 | m4/lib-ld.m4 | \
m4/lib-prefix.m4 | m4/po.m4 | m4/stdint_h.m4 | m4/uintmax_t.m4 | \
m4/ulonglong.m4)
dest=`expr $gnulib_file : '\(.*\).m4'`_gl.m4;;
esac
rm -f $dest &&
echo "$0: Copying file $GNULIB_SRCDIR/$gnulib_file" &&
cp -p $GNULIB_SRCDIR/$gnulib_file $dest || exit
done
echo "$0: Creating m4/gnulib.m4"
(echo "# This file is generated automatically. Please, do not edit."
echo "#"
echo "AC_DEFUN([tar_GNULIB],["
for gnulib_module in $gnulib_modules; do
echo "# $gnulib_module"
$GNULIB_SRCDIR/gnulib-tool --extract-autoconf-snippet $gnulib_module
done | sed '/AM_GNU_GETTEXT/d'
echo "])") > ./m4/gnulib.m4
echo "$0: Creating lib/Makefile.am"
(echo "# This file is generated automatically. Do not edit!"
cat lib/Makefile.tmpl
for gnulib_module in $gnulib_modules; do
echo "# $gnulib_module"
$GNULIB_SRCDIR/gnulib-tool --extract-automake-snippet $gnulib_module
done | sed 's/lib_SOURCES/libtar_a_SOURCES/g' ) > lib/Makefile.am
# Get translations.
if test "$DOWNLOAD_PO" = "yes"; then
update_po
fi
# Reconfigure, getting other files.
echo "$0: autoreconf --verbose --install --force ..."
autoreconf --verbose --install --force || exit 1
for command in \
'aclocal --force -I m4' \
'autoconf --force' \
'autoheader --force' \
'automake --add-missing --copy --force-missing';
do
echo "$0: $command ..."
$command || exit
done
# Get some extra files from gnulib, overriding existing files.
for file in $gnulib_extra_files; do
case $file in
*/INSTALL) dst=INSTALL;;
*) dst=$file;;
esac
symlink_to_gnulib $file $dst || exit
done
# Create gettext configuration.
echo "$0: Creating po/Makevars from po/Makevars.template ..."
rm -f po/Makevars
sed '
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
}
' po/Makevars.template >po/Makevars
if test -d runtime-po; then
# Similarly for runtime-po/Makevars, but not quite the same.
rm -f runtime-po/Makevars
sed '
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
/^subdir *=.*/s/=.*/= runtime-po/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
}
' <po/Makevars.template >runtime-po/Makevars
# Copy identical files from po to runtime-po.
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
fi
cleanup_ifl
echo "$0: done. Now you can run './configure'."

59
bootstrap.conf Normal file
View File

@@ -0,0 +1,59 @@
# Bootstrap configuration.
# Copyright (C) 2006, 2007 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.
# We don't need these modules, even though gnulib-tool mistakenly
# includes them because of gettext dependencies.
avoided_gnulib_modules='
--avoid=lock
--avoid=size_max
'
# gnulib modules used by this package.
gnulib_modules="$avoided_gnulib_modules
`grep '^[^#]' gnulib.modules`
"
# Additional xgettext options to use. Use "\\\newline" to break lines.
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
--flag=_:1:pass-c-format\\\
--flag=N_:1:pass-c-format\\\
--flag=error:3:c-format --flag=error_at_line:5:c-format\\\
--flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format\\\
--flag=argp_error:2:c-format\\\
--flag=__argp_error:2:c-format\\\
--flag=argp_failure:4:c-format\\\
--flag=__argp_failure:4:c-format\\\
--flag=argp_fmtstream_printf:2:c-format\\\
--flag=__argp_fmtstream_printf:2:c-format\\\
'
# Gettext supplies these files, but we don't need them since
# we don't have an intl subdirectory.
excluded_files='
m4/glibc2.m4
m4/intdiv0.m4
m4/lcmessage.m4
m4/lock.m4
m4/printf-posix.m4
m4/size_max.m4
m4/uintmax_t.m4
m4/ulonglong.m4
m4/visibility.m4
'

View File

@@ -1,11 +1,11 @@
# Configure template for GNU tar.
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
# 2002, 2003, 2004, 2005, 2006, 2007, 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 2, or (at your option)
# 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,
@@ -18,18 +18,19 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
AC_INIT([GNU tar], [1.15.90], [bug-tar@gnu.org])
AC_INIT([GNU tar], [1.20], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h:config.hin])
AC_PREREQ([2.59])
AM_INIT_AUTOMAKE([1.8 gnits dist-bzip2 dist-shar std-options])
AC_PREREQ([2.60])
AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
gl_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_EXEEXT
AC_PROG_RANLIB
AC_PROG_YACC
gl_EARLY
AC_SYS_LARGEFILE
AC_ISC_POSIX
AC_C_INLINE
@@ -80,15 +81,13 @@ AC_CHECK_TYPE(dev_t, unsigned)
AC_CHECK_TYPE(ino_t, unsigned)
gt_TYPE_SSIZE_T
gl_AC_TYPE_INTMAX_T
jm_AC_TYPE_UINTMAX_T
# gnulib modules
tar_GNULIB
gl_INIT
# paxutils modules
tar_PAXUTILS
AC_CHECK_FUNCS(fsync lstat mkfifo readlink strerror symlink setlocale utimes)
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink symlink setlocale utimes)
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
AC_CHECK_DECLS([time],,, [#include <time.h>])
@@ -214,8 +213,8 @@ AC_CHECK_TYPE(iconv_t,:,
])
# Gettext.
AM_GNU_GETTEXT([external], [need-ngettext])
AM_GNU_GETTEXT_VERSION(0.12.1)
AM_GNU_GETTEXT([external], [need-formatstring-macros])
AM_GNU_GETTEXT_VERSION([0.16])
# Initialize the test suite.
AC_CONFIG_TESTDIR(tests)
@@ -240,7 +239,6 @@ else
BACKUP_SED_COND='/^\#IF_DATE_FORMAT_OK/,/^\#ELSE_DATE_FORMAT_OK/d;/^\#ENDIF_DATE_FORMAT_OK/d'
fi
AC_OUTPUT([Makefile\
doc/Makefile\
lib/Makefile\

View File

@@ -24,6 +24,9 @@ tar.kw
tar.kws
tar.ky
tar.log
tar.op
tar.ops
tar.pdf
tar.pg
tar.pgs
tar.ps
@@ -31,6 +34,4 @@ tar.toc
tar.tp
tar.vr
tar.vrs
tmp-tar.*
tmp2-tar.*
version.texi

View File

@@ -1,11 +1,11 @@
# Makefile for GNU tar documentation.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
# Software Foundation, Inc.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
# 2007 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 2, or (at your option)
## 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,
@@ -19,16 +19,19 @@
info_TEXINFOS = tar.texi
tar_TEXINFOS = \
dumpdir.texi\
tar-snapshot-edit.texi\
fdl.texi\
freemanuals.texi\
genfile.texi\
getdate.texi\
header.texi\
intern.texi\
rendition.texi\
snapshot.texi\
sparse.texi\
value.texi
EXTRA_DIST = convtexi.pl gendocs_template
DISTCLEANFILES=*.info*
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
@@ -37,8 +40,91 @@ RENDITION = DISTRIB
MAKEINFOFLAGS=-D$(RENDITION)
header.texi: $(top_srcdir)/src/tar.h
sed -n '/Archive Format/,/End of Format/p' $(top_srcdir)/src/tar.h \
| expand | sed 's/\([{}]\)/@\1/g' >$@
sed -f $(srcdir)/texify.sed $(top_srcdir)/src/tar.h \
| expand >$@
master-menu: $(tar_TEXINFOS)
emacs -batch -l mastermenu.el -f make-master-menu $(info_TEXINFOS)
untabify:
emacs -batch -l untabify.el $(info_TEXINFOS) $(tar_TEXINFOS)
final: untabify master-menu
# Checking
check-format:
@if test -n "`cat $(info_TEXINFOS) $(tar_TEXINFOS) | tr -d -c '\t'`"; then \
echo "Sources contain tabs; run make untabify"; \
false; \
fi
check-options:
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
$(top_builddir)/src/tar --usage | \
sed -n 's/^\[--\([^]\=\[]*\).*/\1/p' | sort | uniq > opts.$$$$;\
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
$(info_TEXINFOS) | \
sed -n '/^@macro/,/^@end macro/d;s/@opindex *\([^@,]*\).*/\1/p' \
| sort | uniq > docs.$$$$;\
(echo 'Not documented options:';\
join -v1 opts.$$$$ docs.$$$$;\
echo 'Non-existing options:';\
join -v2 opts.$$$$ docs.$$$$) > report.$$$$;\
rm opts.$$$$ docs.$$$$;\
if [ -n "`sed '1,2d' report.$$$$`" ]; then \
cat report.$$$$;\
rm report.$$$$;\
exit 1;\
fi;\
rm report.$$$$
check-refs:
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
do \
sed -e = $$file | \
sed -n 'N;/@FIXME-.*ref/{s/\(^[0-9][0-9]*\).*@FIXME-.*ref{\([^}]*\).*/'$$file':\1: \2/gp}'; \
done > $@-t; \
if [ -s $@-t ]; then \
echo "Unresolved cross-references:"; \
cat $@-t;\
rm $@-t; \
else \
rm -f $@-t; \
fi
check-fixmes:
@for file in $(info_TEXINFOS); \
do \
sed -e = $$file | \
sed -n 'N;/@FIXME{/{s/\(^[0-9][0-9]*\).*@FIXME{\([^}]*\).*/'$$file':\1: \2/gp}'; \
done > $@-t; \
if [ -s $@-t ]; then \
echo "Unresolved FIXMEs:"; \
cat $@-t; \
rm $@-t; \
false; \
else \
rm -f $@-t; \
fi
check-unrevised:
@grep -Hn @UNREVISED $(info_TEXINFOS) > $@-t; \
if [ -s $@-t ]; then \
echo "Unrevised nodes:"; \
cat $@-t; \
rm $@-t; \
false;\
else \
rm $@-t; \
fi
all-check-docs: check-format check-options check-refs check-fixmes check-unrevised
check-docs:
$(MAKE) -k all-check-docs
#
clean-local:
rm -rf manual
@@ -51,8 +137,8 @@ TEXI2DVI=texi2dvi -t '@set $(RENDITION)' -E
# Usual value is:
# /usr/share/texmf/pdftex/plain/misc:/usr/share/texmf/pdftex/config
manual:
TEXINPUTS=$(srcdir):$(top_srcdir)/config:$(TEXINPUTS) \
TEXINPUTS=$(srcdir):$(top_srcdir)/build-tex:$(TEXINPUTS) \
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
$(GENDOCS) tar 'GNU tar manual'
$(GENDOCS) --texi2html tar 'GNU tar manual'

View File

@@ -1,134 +0,0 @@
#!/usr/local/bin/perl -- # -*-Perl-*-
eval "exec /usr/local/bin/perl -S $0 $*"
if 0;
# Copy a Texinfo file, replacing @value's, @FIXME's and other gooddies.
# Copyright (C) 1996, 2001 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 2, 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.
# François Pinard <pinard@iro.umontreal.ca>, 1996.
$_ = <>;
while ($_)
{
if (/^\@c()$/ || /^\@c (.*)/ || /^\@(include .*)/)
{
if ($topseen)
{
print "\@format\n";
print "\@strong{\@\@c} $1\n";
$_ = <>;
while (/\@c (.*)/)
{
print "\@strong{\@\@c} $1\n";
$_ = <>;
}
print "\@end format\n";
}
else
{
$delay .= "\@format\n";
$delay .= "\@strong{\@\@c} $1\n";
$_ = <>;
while (/\@c (.*)/)
{
$delay .= "\@strong{\@\@c} $1\n";
$_ = <>;
}
$delay .= "\@end format\n";
}
}
elsif (/^\@chapter /)
{
print;
# print $delay;
$delay = '';
$topseen = 1;
$_ = <>;
}
elsif (/^\@macro /)
{
$_ = <> while ($_ && ! /^\@end macro/);
$_ = <>;
}
elsif (/^\@set ([^ ]+) (.*)/)
{
$set{$1} = $2;
$_ = <>;
}
elsif (/^\@UNREVISED/)
{
print "\@quotation\n";
print "\@emph{(This message will disappear, once this node is revised.)}\n";
print "\@end quotation\n";
$_ = <>;
}
else
{
while (/\@value{([^\}]*)}/)
{
if (defined $set{$1})
{
$_ = "$`$set{$1}$'";
}
else
{
$_ = "$`\@strong{<UNDEFINED>}$1\@strong{</UNDEFINED>}$'";
}
}
while (/\@FIXME-?([a-z]*)\{/)
{
$tag = $1 eq '' ? 'fixme' : $1;
$tag =~ y/a-z/A-Z/;
print "$`\@strong{<$tag>}";
$_ = $';
$level = 1;
while ($level > 0)
{
if (/([{}])/)
{
if ($1 eq '{')
{
$level++;
print "$`\{";
$_ = $';
}
elsif ($level > 1)
{
$level--;
print "$`\}";
$_ = $';
}
else
{
$level = 0;
print "$`\@strong{</$tag>}";
$_ = $';
}
}
else
{
print;
$_ = <>;
}
}
}
print;
$_ = <>;
}
}
exit 0;

132
doc/dumpdir.texi Normal file
View File

@@ -0,0 +1,132 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006, 2007 Free Software Foundation, Inc.
@c Written by Sergey Poznyakoff
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
Incremental archives keep information about contents of each
dumped directory in special data blocks called @dfn{dumpdirs}.
Dumpdir is a sequence of entries of the following form:
@smallexample
@var{C} @var{filename} \0
@end smallexample
@noindent
where @var{C} is one of the @dfn{control codes} described below,
@var{filename} is the name of the file @var{C} operates upon, and
@samp{\0} represents a nul character (ASCII 0). The white space
characters were added for readability, real dumpdirs do not contain
them.
Each dumpdir ends with a single nul character.
The following table describes control codes and their meanings:
@table @samp
@item Y
@var{filename} is contained in the archive.
@item N
@var{filename} was present in the directory at the time the archive
was made, yet it was not dumped to the archive, because it had not
changed since the last backup.
@item D
@var{filename} is a directory.
@item R
This code requests renaming of the @var{filename} to the name
specified with the @samp{T} command, that immediately follows it.
@item T
Specify target file name for @samp{R} command (see below).
@item X
Specify @dfn{temporary directory} name for a rename operation (see below).
@end table
Codes @samp{Y}, @samp{N} and @samp{D} require @var{filename} argument
to be a relative file name to the directory this dumpdir describes,
whereas codes @samp{R}, @samp{T} and @samp{X} require their argument
to be an absolute file name.
The three codes @samp{R}, @samp{T} and @samp{X} specify a
@dfn{renaming operation}. In the simplest case it is:
@smallexample
R@file{source}\0T@file{dest}\0
@end smallexample
@noindent
which means ``rename file @file{source} to file @file{dest}''.
However, there are cases that require using a @dfn{temporary
directory}. For example, consider the following scenario:
@enumerate 1
@item
Previous run dumped a directory @file{foo} which contained the
following three directories:
@smallexample
a
b
c
@end smallexample
@item
They were renamed @emph{cyclically}, so that:
@example
@file{a} became @file{b}
@file{b} became @file{c}
@file{c} became @file{a}
@end example
@item
New incremental dump was made.
@end enumerate
This case cannot be handled by three successive renames, since
renaming @file{a} to @file{b} will destroy the existing directory.
To correctly process it, @GNUTAR{} needs a temporary directory, so
it creates the following dumpdir (newlines have been added for
readability):
@smallexample
@group
Xfoo\0
Rfoo/a\0T\0
Rfoo/b\0Tfoo/c\0
Rfoo/c\0Tfoo/a\0
R\0Tfoo/a\0
@end group
@end smallexample
The first command, @samp{Xfoo\0}, instructs the extractor to create a
temporary directory in the directory @file{foo}. Second command,
@samp{Rfoo/aT\0}, says ``rename file @file{foo/a} to the temporary
directory that has just been created'' (empty file name after a
command means use temporary directory). Third and fourth commands
work as usual, and, finally, the last command, @samp{R\0Tfoo/a\0}
tells tar to rename the temporary directory to @file{foo/a}.
The exact placement of a dumpdir in the archive depends on the
archive format (@pxref{Formats}):
@itemize
@item PAX archives
In PAX archives, dumpdir is stored in the extended header of the
corresponding directory, in variable @code{GNU.dumpdir}.
@item GNU and old GNU archives
These formats implement special header type @samp{D}, which is similar
to ustar header @samp{5} (directory), except that it precedes a data
block containing the dumpdir.
@end itemize
@c End of dumpdir.texi

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- $Id: gendocs_template,v 1.2 2005/05/15 03:59:09 eggert Exp $ -->
<!-- $Id: gendocs_template,v 1.5 2007/10/30 14:58:52 gray Exp $ -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
@@ -30,24 +30,41 @@
alt=" [image of the head of a GNU] "
width="129" height="122" />
</a>
<a href="/philosophy/gif.html">(no gifs due to patent problems)</a>
</p>
<hr />
The manual for %%PACKAGE%% is available in the following formats:</p>
<p>The manual for %%PACKAGE%% is available in the following formats:</p>
<ul>
<li><a href="%%PACKAGE%%.html">HTML
(%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li>
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
<li><a href="html_node/index.html">HTML</a> - with one web page per
node.</li>
%%IF HTML_SECTION%%
<li><a href="html_section/index.html">HTML</a> - with one web page per
section.</li>
%%ENDIF HTML_SECTION%%
%%IF HTML_CHAPTER%%
<li><a href="html_chapter/index.html">HTML</a> - with one web page per
chapter.</li>
%%ENDIF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
one web page.</li>
<li><a href="%%PACKAGE%%_html_node.tar.gz">HTML compressed
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per node.</li>
<li><a href="%%PACKAGE%%-info.tar.gz">Info document
%%IF HTML_SECTION%%
<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
(%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per section.</li>
%%ENDIF HTML_SECTION%%
%%IF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
(%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
with one web page per chapter.</li>
%%ENDIF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.info.tar.gz">Info document
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
<li><a href="%%PACKAGE%%.txt">ASCII text
(%%ASCII_SIZE%%K characters)</a>.</li>
@@ -99,7 +116,7 @@ permitted in any medium, provided this notice is preserved.
<p>
Updated:
<!-- timestamp start -->
$Date: 2005/05/15 03:59:09 $ $Author: eggert $
$Date: 2007/10/30 14:58:52 $ $Author: gray $
<!-- timestamp end -->
</p>
</div>

333
doc/intern.texi Normal file
View File

@@ -0,0 +1,333 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@menu
* Standard:: Basic Tar Format
* Extensions:: @acronym{GNU} Extensions to the Archive Format
* Sparse Formats:: Storing Sparse Files
* Snapshot Files::
* Dumpdir::
@end menu
@node Standard
@unnumberedsec Basic Tar Format
@UNREVISED
While an archive may contain many files, the archive itself is a
single ordinary file. Like any other file, an archive file can be
written to a storage device such as a tape or disk, sent through a
pipe or over a network, saved on the active file system, or even
stored in another archive. An archive file is not easy to read or
manipulate without using the @command{tar} utility or Tar mode in
@acronym{GNU} Emacs.
Physically, an archive consists of a series of file entries terminated
by an end-of-archive entry, which consists of two 512 blocks of zero
bytes. A file
entry usually describes one of the files in the archive (an
@dfn{archive member}), and consists of a file header and the contents
of the file. File headers contain file names and statistics, checksum
information which @command{tar} uses to detect file corruption, and
information about file types.
Archives are permitted to have more than one member with the same
member name. One way this situation can occur is if more than one
version of a file has been stored in the archive. For information
about adding new versions of a file to an archive, see @ref{update}.
In addition to entries describing archive members, an archive may
contain entries which @command{tar} itself uses to store information.
@xref{label}, for an example of such an archive entry.
A @command{tar} archive file contains a series of blocks. Each block
contains @code{BLOCKSIZE} bytes. Although this format may be thought
of as being on magnetic tape, other media are often used.
Each file archived is represented by a header block which describes
the file, followed by zero or more blocks which give the contents
of the file. At the end of the archive file there are two 512-byte blocks
filled with binary zeros as an end-of-file marker. A reasonable system
should write such end-of-file marker at the end of an archive, but
must not assume that such a block exists when reading an archive. In
particular @GNUTAR{} always issues a warning if it does not encounter it.
The blocks may be @dfn{blocked} for physical I/O operations.
Each record of @var{n} blocks (where @var{n} is set by the
@option{--blocking-factor=@var{512-size}} (@option{-b @var{512-size}}) option to @command{tar}) is written with a single
@w{@samp{write ()}} operation. On magnetic tapes, the result of
such a write is a single record. When writing an archive,
the last record of blocks should be written at the full size, with
blocks after the zero block containing all zeros. When reading
an archive, a reasonable system should properly handle an archive
whose last record is shorter than the rest, or which contains garbage
records after a zero block.
The header block is defined in C as follows. In the @GNUTAR{}
distribution, this is part of file @file{src/tar.h}:
@smallexample
@include header.texi
@end smallexample
All characters in header blocks are represented by using 8-bit
characters in the local variant of ASCII. Each field within the
structure is contiguous; that is, there is no padding used within
the structure. Each character on the archive medium is stored
contiguously.
Bytes representing the contents of files (after the header block
of each file) are not translated in any way and are not constrained
to represent characters in any character set. The @command{tar} format
does not distinguish text files from binary files, and no translation
of file contents is performed.
The @code{name}, @code{linkname}, @code{magic}, @code{uname}, and
@code{gname} are null-terminated character strings. All other fields
are zero-filled octal numbers in ASCII. Each numeric field of width
@var{w} contains @var{w} minus 1 digits, and a null.
The @code{name} field is the file name of the file, with directory names
(if any) preceding the file name, separated by slashes.
@FIXME{how big a name before field overflows?}
The @code{mode} field provides nine bits specifying file permissions
and three bits to specify the Set @acronym{UID}, Set @acronym{GID}, and Save Text
(@dfn{sticky}) modes. Values for these bits are defined above.
When special permissions are required to create a file with a given
mode, and the user restoring files from the archive does not hold such
permissions, the mode bit(s) specifying those special permissions
are ignored. Modes which are not supported by the operating system
restoring files from the archive will be ignored. Unsupported modes
should be faked up when creating or updating an archive; e.g., the
group permission could be copied from the @emph{other} permission.
The @code{uid} and @code{gid} fields are the numeric user and group
@acronym{ID} of the file owners, respectively. If the operating system does
not support numeric user or group @acronym{ID}s, these fields should
be ignored.
The @code{size} field is the size of the file in bytes; linked files
are archived with this field specified as zero.
The @code{mtime} field is the data modification time of the file at
the time it was archived. It is the ASCII representation of the octal
value of the last time the file's contents were modified, represented
as an integer number of
seconds since January 1, 1970, 00:00 Coordinated Universal Time.
The @code{chksum} field is the ASCII representation of the octal value
of the simple sum of all bytes in the header block. Each 8-bit
byte in the header is added to an unsigned integer, initialized to
zero, the precision of which shall be no less than seventeen bits.
When calculating the checksum, the @code{chksum} field is treated as
if it were all blanks.
The @code{typeflag} field specifies the type of file archived. If a
particular implementation does not recognize or permit the specified
type, the file will be extracted as if it were a regular file. As this
action occurs, @command{tar} issues a warning to the standard error.
The @code{atime} and @code{ctime} fields are used in making incremental
backups; they store, respectively, the particular file's access and
status change times.
The @code{offset} is used by the @option{--multi-volume} (@option{-M}) option, when
making a multi-volume archive. The offset is number of bytes into
the file that we need to restart at to continue the file on the next
tape, i.e., where we store the location that a continued file is
continued at.
The following fields were added to deal with sparse files. A file
is @dfn{sparse} if it takes in unallocated blocks which end up being
represented as zeros, i.e., no useful data. A test to see if a file
is sparse is to look at the number blocks allocated for it versus the
number of characters in the file; if there are fewer blocks allocated
for the file than would normally be allocated for a file of that
size, then the file is sparse. This is the method @command{tar} uses to
detect a sparse file, and once such a file is detected, it is treated
differently from non-sparse files.
Sparse files are often @code{dbm} files, or other database-type files
which have data at some points and emptiness in the greater part of
the file. Such files can appear to be very large when an @samp{ls
-l} is done on them, when in truth, there may be a very small amount
of important data contained in the file. It is thus undesirable
to have @command{tar} think that it must back up this entire file, as
great quantities of room are wasted on empty blocks, which can lead
to running out of room on a tape far earlier than is necessary.
Thus, sparse files are dealt with so that these empty blocks are
not written to the tape. Instead, what is written to the tape is a
description, of sorts, of the sparse file: where the holes are, how
big the holes are, and how much data is found at the end of the hole.
This way, the file takes up potentially far less room on the tape,
and when the file is extracted later on, it will look exactly the way
it looked beforehand. The following is a description of the fields
used to handle a sparse file:
The @code{sp} is an array of @code{struct sparse}. Each @code{struct
sparse} contains two 12-character strings which represent an offset
into the file and a number of bytes to be written at that offset.
The offset is absolute, and not relative to the offset in preceding
array element.
The header can hold four of these @code{struct sparse} at the moment;
if more are needed, they are not stored in the header.
The @code{isextended} flag is set when an @code{extended_header}
is needed to deal with a file. Note that this means that this flag
can only be set when dealing with a sparse file, and it is only set
in the event that the description of the file will not fit in the
allotted room for sparse structures in the header. In other words,
an extended_header is needed.
The @code{extended_header} structure is used for sparse files which
need more sparse structures than can fit in the header. The header can
fit 4 such structures; if more are needed, the flag @code{isextended}
gets set and the next block is an @code{extended_header}.
Each @code{extended_header} structure contains an array of 21
sparse structures, along with a similar @code{isextended} flag
that the header had. There can be an indeterminate number of such
@code{extended_header}s to describe a sparse file.
@table @asis
@item @code{REGTYPE}
@itemx @code{AREGTYPE}
These flags represent a regular file. In order to be compatible
with older versions of @command{tar}, a @code{typeflag} value of
@code{AREGTYPE} should be silently recognized as a regular file.
New archives should be created using @code{REGTYPE}. Also, for
backward compatibility, @command{tar} treats a regular file whose name
ends with a slash as a directory.
@item @code{LNKTYPE}
This flag represents a file linked to another file, of any type,
previously archived. Such files are identified in Unix by each
file having the same device and inode number. The linked-to name is
specified in the @code{linkname} field with a trailing null.
@item @code{SYMTYPE}
This represents a symbolic link to another file. The linked-to name
is specified in the @code{linkname} field with a trailing null.
@item @code{CHRTYPE}
@itemx @code{BLKTYPE}
These represent character special files and block special files
respectively. In this case the @code{devmajor} and @code{devminor}
fields will contain the major and minor device numbers respectively.
Operating systems may map the device specifications to their own
local specification, or may ignore the entry.
@item @code{DIRTYPE}
This flag specifies a directory or sub-directory. The directory
name in the @code{name} field should end with a slash. On systems where
disk allocation is performed on a directory basis, the @code{size} field
will contain the maximum number of bytes (which may be rounded to
the nearest disk block allocation unit) which the directory may
hold. A @code{size} field of zero indicates no such limiting. Systems
which do not support limiting in this manner should ignore the
@code{size} field.
@item @code{FIFOTYPE}
This specifies a FIFO special file. Note that the archiving of a
FIFO file archives the existence of this file and not its contents.
@item @code{CONTTYPE}
This specifies a contiguous file, which is the same as a normal
file except that, in operating systems which support it, all its
space is allocated contiguously on the disk. Operating systems
which do not allow contiguous allocation should silently treat this
type as a normal file.
@item @code{A} @dots{} @code{Z}
These are reserved for custom implementations. Some of these are
used in the @acronym{GNU} modified format, as described below.
@end table
Other values are reserved for specification in future revisions of
the P1003 standard, and should not be used by any @command{tar} program.
The @code{magic} field indicates that this archive was output in
the P1003 archive format. If this field contains @code{TMAGIC},
the @code{uname} and @code{gname} fields will contain the ASCII
representation of the owner and group of the file respectively.
If found, the user and group @acronym{ID}s are used rather than the values in
the @code{uid} and @code{gid} fields.
For references, see ISO/IEC 9945-1:1990 or IEEE Std 1003.1-1990, pages
169-173 (section 10.1) for @cite{Archive/Interchange File Format}; and
IEEE Std 1003.2-1992, pages 380-388 (section 4.48) and pages 936-940
(section E.4.48) for @cite{pax - Portable archive interchange}.
@node Extensions
@unnumberedsec @acronym{GNU} Extensions to the Archive Format
@UNREVISED
The @acronym{GNU} format uses additional file types to describe new types of
files in an archive. These are listed below.
@table @code
@item GNUTYPE_DUMPDIR
@itemx 'D'
This represents a directory and a list of files created by the
@option{--incremental} (@option{-G}) option. The @code{size} field gives the total
size of the associated list of files. Each file name is preceded by
either a @samp{Y} (the file should be in this archive) or an @samp{N}.
(The file is a directory, or is not stored in the archive.) Each file
name is terminated by a null. There is an additional null after the
last file name.
@item GNUTYPE_MULTIVOL
@itemx 'M'
This represents a file continued from another volume of a multi-volume
archive created with the @option{--multi-volume} (@option{-M}) option. The original
type of the file is not given here. The @code{size} field gives the
maximum size of this piece of the file (assuming the volume does
not end before the file is written out). The @code{offset} field
gives the offset from the beginning of the file where this part of
the file begins. Thus @code{size} plus @code{offset} should equal
the original size of the file.
@item GNUTYPE_SPARSE
@itemx 'S'
This flag indicates that we are dealing with a sparse file. Note
that archiving a sparse file requires special operations to find
holes in the file, which mark the positions of these holes, along
with the number of bytes of data to be found after the hole.
@item GNUTYPE_VOLHDR
@itemx 'V'
This file type is used to mark the volume header that was given with
the @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) option when the archive was created. The @code{name}
field contains the @code{name} given after the @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) option.
The @code{size} field is zero. Only the first file in each volume
of an archive should have this type.
@end table
You may have trouble reading a @acronym{GNU} format archive on a
non-@acronym{GNU} system if the options @option{--incremental} (@option{-G}),
@option{--multi-volume} (@option{-M}), @option{--sparse} (@option{-S}), or @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) were
used when writing the archive. In general, if @command{tar} does not
use the @acronym{GNU}-added fields of the header, other versions of
@command{tar} should be able to read the archive. Otherwise, the
@command{tar} program will give an error, the most likely one being a
checksum error.
@node Sparse Formats
@unnumberedsec Storing Sparse Files
@include sparse.texi
@node Snapshot Files
@unnumberedsec Format of the Incremental Snapshot Files
@include snapshot.texi
@node Dumpdir
@unnumberedsec Dumpdir
@include dumpdir.texi

91
doc/mastermenu.el Normal file
View File

@@ -0,0 +1,91 @@
;;; mastermenu.el --- Redefinition of texinfo-master-menu-list
;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
;; Author: Sergey Poznyakoff
;; Maintainer: bug-tar@gnu.org
;; Keywords: maint, tex, docs
;; This file is part of GNU tar documentation suite
;; 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.
;;; Commentary:
;; This file redefines texinfo-master-menu-list so that it takes into
;; account included files.
;; Known bugs: @menu without previous sectioning command will inherit
;; documentation string from the previous menu. However, since such a
;; menu is illegal in a texinfo file, we can live with it.
(require 'texinfo)
(require 'texnfo-upd)
(defun texinfo-master-menu-list-recursive (title)
"Auxiliary function used by `texinfo-master-menu-list'."
(save-excursion
(let (master-menu-list)
(while (re-search-forward "\\(^@menu\\|^@include\\)" nil t)
(cond
((string= (match-string 0) "@include")
(skip-chars-forward " \t")
(let ((included-name (let ((start (point)))
(end-of-line)
(skip-chars-backward " \t")
(buffer-substring start (point)))))
(end-of-line)
(let ((prev-title (texinfo-copy-menu-title)))
(save-excursion
(set-buffer (find-file-noselect included-name))
(setq master-menu-list
(append (texinfo-master-menu-list-recursive prev-title)
master-menu-list))))))
(t
(setq master-menu-list
(cons (list
(texinfo-copy-menu)
(let ((menu-title (texinfo-copy-menu-title)))
(if (string= menu-title "")
title
menu-title)))
master-menu-list)))))
master-menu-list)))
(defun texinfo-master-menu-list ()
"Return a list of menu entries and header lines for the master menu,
recursing into included files.
Start with the menu for chapters and indices and then find each
following menu and the title of the node preceding that menu.
The master menu list has this form:
\(\(\(... \"entry-1-2\" \"entry-1\"\) \"title-1\"\)
\(\(... \"entry-2-2\" \"entry-2-1\"\) \"title-2\"\)
...\)
However, there does not need to be a title field."
(reverse (texinfo-master-menu-list-recursive "")))
(defun make-master-menu ()
"Create master menu in the first Emacs argument."
(find-file (car command-line-args-left))
(texinfo-master-menu nil)
(save-buffer))
;;; mastermenu.el ends here

View File

@@ -1,9 +1,9 @@
@c This is part of GNU tar manual.
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
@c 2003, 2004 Free Software Foundation, Inc.
@c 2003, 2004, 2006 Free Software Foundation, Inc.
@c See file tar.texi for copying conditions.
@c This file contains support for 'renditions' by Fra@,{c}ois Pinard
@c This file contains support for 'renditions' by Fran@,{c}ois Pinard
@c I extended it by adding a FIXME_FOOTNOTE variable, which controls
@c whether FIXME information should be placed in footnotes or
@c inlined. --gray
@@ -55,39 +55,45 @@
@c Output various FIXME information only in PROOF rendition.
@macro FIXME{string}
@allow-recursion
@quote-arg
@ifset PROOF
@ifset PROOF_FOOTNOTED
@footnote{@strong{FIXME:} \string\}
@end ifset
@ifclear PROOF_FOOTNOTED
@cartouche
@strong{<FIXME>} \string\ @strong{</>}
@end cartouche
@end ifclear
@end ifset
@end macro
@macro FIXME-ref{string}
@quote-arg
@ifset PROOF
@strong{<REF>} \string\ @strong{</>}
@end ifset
@ifclear PROOF
@cite{\string\}
@end ifclear
@end macro
@macro FIXME-pxref{string}
@quote-arg
@ifset PROOF
@strong{<PXREF>} \string\ @strong{</>}
See @strong{<PXREF>} \string\ @strong{</>}
@end ifset
@ifclear PROOF
See @cite{\string\}
@end ifclear
@end macro
@macro FIXME-xref{string}
@quote-arg
@ifset PROOF
@strong{<XREF>} \string\ @strong{</>}
See @strong{<XREF>} \string\ @strong{</>}
@end ifset
@ifclear PROOF
See @cite{\string\}
@end ifclear
@end macro
@c End of rendition.texi

View File

@@ -1,35 +1,63 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2005 Free Software Foundation, Inc.
@c Copyright (C) 2005, 2007 Free Software Foundation, Inc.
@c Written by Sergey Poznyakoff
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
A @dfn{snapshot file} (or @dfn{directory file}) is created during
incremental backups (@pxref{Incremental Dumps}). It
contains the status of the filesystem at the time of the dump and is
contains the status of the file system at the time of the dump and is
used to determine which files were modified since the last backup.
@GNUTAR{} version @value{VERSION} supports two snapshot file
@GNUTAR{} version @value{VERSION} supports three snapshot file
formats. The first format, called @dfn{format 0}, is the one used by
@GNUTAR{} versions up to 1.15.1. The second format, called @dfn{format
1} is an extended version of this format, that contains more metadata
and allows for further extensions.
and allows for further extensions. It was used by version
1.15.1. Starting from version 1.16 and up to @value{VERSION}, the
@dfn{format 2} is used.
@GNUTAR{} is able to read all three formats, but will create
snapshots only in format 2.
This appendix describes all three formats in detail.
@enumerate 0
@cindex format 0, snapshot file
@cindex snapshot file, format 0
@item
@samp{Format 0} snapshot file begins with a line containing a
decimal number that represents the UNIX timestamp of the beginning of
the last archivation. This line is followed by directory metadata
descriptions, one per line. Each description has the following format:
decimal number that represents a @acronym{UNIX} timestamp of the
beginning of the last archivation. This line is followed by directory
metadata descriptions, one per line. Each description has the
following format:
@smallexample
[@var{nfs}]@var{dev} @var{inode} @var{name}
@var{nfs}@var{dev} @var{inode} @var{name}
@end smallexample
@noindent
where optional @var{nfs} is a single plus character (@samp{+}) if this
directory is located on an NFS-mounted partition, @var{dev} and
@var{inode} are the device and inode numbers of the directory, and
@var{name} is the directory name.
where:
@table @var
@item nfs
A single plus character (@samp{+}), if this directory is located on
an @acronym{NFS}-mounted partition, or a single space otherwise;
@item dev
Device number of the directory;
@item inode
I-node number of the directory;
@item name
Name of the directory. Any special characters (white-space,
backslashes, etc.) are quoted.
@end table
@cindex format 1, snapshot file
@cindex snapshot file, format 1
@item
@samp{Format 1} snapshot file begins with a line specifying the
format of the file. This line has the following structure:
@@ -38,28 +66,75 @@ format of the file. This line has the following structure:
@end smallexample
@noindent
where @var{tar-version} is the version of @GNUTAR{} implementation
that created this snapshot, and @var{incr-format-version} is the
version number of the snapshot format (in this case @samp{1}).
where @var{tar-version} is the version number of @GNUTAR{}
implementation that created this snapshot, and
@var{incr-format-version} is the version number of the snapshot format
(in this case @samp{1}).
The following line contains two decimal numbers, representing the
Next line contains two decimal numbers, representing the
time of the last backup. First number is the number of seconds, the
second one is the number of nanoseconds, since the beginning of the
epoch.
Following lines contain directory metadate, one line per
directory. The line format is:
Lines that follow contain directory metadata, one line per
directory. Each line is formatted as follows:
@smallexample
[@var{nfs}]@var{mtime-sec} @var{mtime-nsec} @var{dev} @var{inode} @var{name}
@end smallexample
@noindent
where @var{mtime-sec} and @var{mtime-nsec} represent the last
where @var{mtime-sec} and @var{mtime-nsec} represent last
modification time of this directory with nanosecond precision;
@var{nfs}, @var{dev}, @var{inode} and @var{name} have the same meaning
as with @samp{format 0}.
@cindex format 2, snapshot file
@cindex snapshot file, format 2
@item
@FIXME{}
A snapshot file begins with a format identifier, as described for
version 1, e.g.:
@smallexample
GNU tar-@value{VERSION}-2
@end smallexample
This line is followed by newline. Rest of file consists of
records, separated by null (@acronym{ASCII} 0)
characters. Thus, in contrast to the previous formats, format 2
snapshot is a binary file.
First two records are decimal numbers, representing the
time of the last backup. First number is the number of seconds, the
second one is the number of nanoseconds, since the beginning of the
epoch. These are followed by arbitrary number of directory records.
Each @dfn{directory record} contains a set of metadata describing a
particular directory. Parts of a directory record are delimited with
@acronym{ASCII} 0 characters. The following table describes each
part. The @dfn{Number} type in this table stands for a decimal number
in @acronym{ASCII} notation.
@multitable @columnfractions 0.2 0.2 0.6
@headitem Field @tab Type @tab Description
@item nfs @tab Character @tab @samp{1} if the directory is located on
an @acronym{NFS}-mounted partition, or @samp{0} otherwise;
@item mtime-sec @tab Number @tab Modification time, seconds;
@item mtime-nano @tab Number @tab Modification time, nanoseconds;
@item dev-no @tab Number @tab Device number;
@item i-no @tab Number @tab I-node number;
@item name @tab String @tab Directory name; In contrast to the
previous versions it is not quoted.
@item contents @tab Dumpdir @tab Contents of the directory;
@xref{Dumpdir}, for a description of its format.
@item
@end multitable
Dumpdirs stored in snapshot files contain only records of types
@samp{Y}, @samp{N} and @samp{D}.
@end enumerate
@c End of snapshot.texi

235
doc/sparse.texi Normal file
View File

@@ -0,0 +1,235 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2006 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@cindex sparse formats
@cindex sparse versions
The notion of sparse file, and the ways of handling it from the point
of view of @GNUTAR{} user have been described in detail in
@ref{sparse}. This chapter describes the internal format @GNUTAR{}
uses to store such files.
The support for sparse files in @GNUTAR{} has a long history. The
earliest version featuring this support that I was able to find was 1.09,
released in November, 1990. The format introduced back then is called
@dfn{old GNU} sparse format and in spite of the fact that its design
contained many flaws, it was the only format @GNUTAR{} supported
until version 1.14 (May, 2004), which introduced initial support for
sparse archives in @acronym{PAX} archives (@pxref{posix}). This
format was not free from design flows, either and it was subsequently
improved in versions 1.15.2 (November, 2005) and 1.15.92 (June,
2006).
In addition to GNU sparse format, @GNUTAR{} is able to read and
extract sparse files archived by @command{star}.
The following subsections describe each format in detail.
@menu
* Old GNU Format::
* PAX 0:: PAX Format, Versions 0.0 and 0.1
* PAX 1:: PAX Format, Version 1.0
@end menu
@node Old GNU Format
@appendixsubsec Old GNU Format
@cindex sparse formats, Old GNU
@cindex Old GNU sparse format
The format introduced some time around 1990 (v. 1.09). It was
designed on top of standard @code{ustar} headers in such an
unfortunate way that some of its fields overwrote fields required by
POSIX.
An old GNU sparse header is designated by type @samp{S}
(@code{GNUTYPE_SPARSE}) and has the following layout:
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
@item 0 @tab 345 @tab @tab N/A @tab Not used.
@item 345 @tab 12 @tab atime @tab Number @tab @code{atime} of the file.
@item 357 @tab 12 @tab ctime @tab Number @tab @code{ctime} of the file .
@item 369 @tab 12 @tab offset @tab Number @tab For
multivolume archives: the offset of the start of this volume.
@item 381 @tab 4 @tab @tab N/A @tab Not used.
@item 385 @tab 1 @tab @tab N/A @tab Not used.
@item 386 @tab 96 @tab sp @tab @code{sparse_header} @tab (4 entries) File map.
@item 482 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
extension sparse header follows, @code{0} otherwise.
@item 483 @tab 12 @tab realsize @tab Number @tab Real size of the file.
@end multitable
Each of @code{sparse_header} object at offset 386 describes a single
data chunk. It has the following structure:
@multitable @columnfractions 0.10 0.10 0.20 0.60
@headitem Offset @tab Size @tab Data type @tab Contents
@item 0 @tab 12 @tab Number @tab Offset of the
beginning of the chunk.
@item 12 @tab 12 @tab Number @tab Size of the chunk.
@end multitable
If the member contains more than four chunks, the @code{isextended}
field of the header has the value @code{1} and the main header is
followed by one or more @dfn{extension headers}. Each such header has
the following structure:
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
@item 0 @tab 21 @tab sp @tab @code{sparse_header} @tab
(21 entires) File map.
@item 504 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
extension sparse header follows, or @code{0} otherwise.
@end multitable
A header with @code{isextended=0} ends the map.
@node PAX 0
@appendixsubsec PAX Format, Versions 0.0 and 0.1
@cindex sparse formats, v.0.0
There are two formats available in this branch. The version @code{0.0}
is the initial version of sparse format used by @command{tar}
versions 1.14--1.15.1. The sparse file map is kept in extended
(@code{x}) PAX header variables:
@table @code
@vrindex GNU.sparse.size, extended header variable
@item GNU.sparse.size
Real size of the stored file
@item GNU.sparse.numblocks
@vrindex GNU.sparse.numblocks, extended header variable
Number of blocks in the sparse map
@item GNU.sparse.offset
@vrindex GNU.sparse.offset, extended header variable
Offset of the data block
@item GNU.sparse.numbytes
@vrindex GNU.sparse.numbytes, extended header variable
Size of the data block
@end table
The latter two variables repeat for each data block, so the overall
structure is like this:
@smallexample
@group
GNU.sparse.size=@var{size}
GNU.sparse.numblocks=@var{numblocks}
repeat @var{numblocks} times
GNU.sparse.offset=@var{offset}
GNU.sparse.numbytes=@var{numbytes}
end repeat
@end group
@end smallexample
This format presented the following two problems:
@enumerate 1
@item
Whereas the POSIX specification allows a variable to appear multiple
times in a header, it requires that only the last occurrence be
meaningful. Thus, multiple occurrences of @code{GNU.sparse.offset} and
@code{GNU.sparse.numbytes} are conflicting with the POSIX specs.
@item
Attempting to extract such archives using a third-party @command{tar}s
results in extraction of sparse files in @emph{compressed form}. If
the @command{tar} implementation in question does not support POSIX
format, it will also extract a file containing extension header
attributes. This file can be used to expand the file to its original
state. However, posix-aware @command{tar}s will usually ignore the
unknown variables, which makes restoring the file more
difficult. @xref{extracting sparse v.0.x, Extraction of sparse
members in v.0.0 format}, for the detailed description of how to
restore such members using non-GNU @command{tar}s.
@end enumerate
@cindex sparse formats, v.0.1
@GNUTAR{} 1.15.2 introduced sparse format version @code{0.1}, which
attempted to solve these problems. As its predecessor, this format
stores sparse map in the extended POSIX header. It retains
@code{GNU.sparse.size} and @code{GNU.sparse.numblocks} variables, but
instead of @code{GNU.sparse.offset}/@code{GNU.sparse.numbytes} pairs
it uses a single variable:
@table @code
@item GNU.sparse.map
@vrindex GNU.sparse.map, extended header variable
Map of non-null data chunks. It is a string consisting of
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
@end table
To address the 2nd problem, the @code{name} field in @code{ustar}
is replaced with a special name, constructed using the following pattern:
@smallexample
%d/GNUSparseFile.%p/%f
@end smallexample
@vrindex GNU.sparse.name, extended header variable
The real name of the sparse file is stored in the variable
@code{GNU.sparse.name}. Thus, those @command{tar} implementations
that are not aware of GNU extensions will at least extract the files
into separate directories, giving the user a possibility to expand it
afterwards. @xref{extracting sparse v.0.x, Extraction of sparse
members in v.0.1 format}, for the detailed description of how to
restore such members using non-GNU @command{tar}s.
The resulting @code{GNU.sparse.map} string can be @emph{very} long.
Although POSIX does not impose any limit on the length of a @code{x}
header variable, this possibly can confuse some tars.
@node PAX 1
@appendixsubsec PAX Format, Version 1.0
@cindex sparse formats, v.1.0
The version @code{1.0} of sparse format was introduced with @GNUTAR{}
1.15.92. Its main objective was to make the resulting file
extractable with little effort even by non-posix aware @command{tar}
implementations. Starting from this version, the extended header
preceding a sparse member always contains the following variables that
identify the format being used:
@table @code
@item GNU.sparse.major
@vrindex GNU.sparse.major, extended header variable
Major version
@item GNU.sparse.minor
@vrindex GNU.sparse.minor, extended header variable
Minor version
@end table
The @code{name} field in @code{ustar} header contains a special name,
constructed using the following pattern:
@smallexample
%d/GNUSparseFile.%p/%f
@end smallexample
@vrindex GNU.sparse.name, extended header variable, in v.1.0
@vrindex GNU.sparse.realsize, extended header variable
The real name of the sparse file is stored in the variable
@code{GNU.sparse.name}. The real size of the file is stored in the
variable @code{GNU.sparse.realsize}.
The sparse map itself is stored in the file data block, preceding the actual
file data. It consists of a series of octal numbers of arbitrary length, delimited
by newlines. The map is padded with nulls to the nearest block boundary.
The first number gives the number of entries in the map. Following are map entries,
each one consisting of two numbers giving the offset and size of the
data block it describes.
The format is designed in such a way that non-posix aware tars and tars not
supporting @code{GNU.sparse.*} keywords will extract each sparse file
in its condensed form with the file map prepended and will place it
into a separate directory. Then, using a simple program it would be
possible to expand the file to its original form even without @GNUTAR{}.
@xref{Sparse Recovery}, for the detailed information on how to extract
sparse members without @GNUTAR{}.

View File

@@ -0,0 +1,58 @@
@c This is part of the paxutils manual.
@c Copyright (C) 2007 Free Software Foundation, Inc.
@c This file is distributed under GFDL 1.1 or any later version
@c published by the Free Software Foundation.
@cindex Device numbers, changing
@cindex snapshot files, editing
@cindex snapshot files, fixing device numbers
Sometimes device numbers can change after upgrading your kernel
version or recofiguring the harvare. Reportedly this is the case with
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
cases this change is unnoticed by the users. However, it influences
@command{tar} incremental backups: the device number is stored in tar
snapshot files (@pxref{Snapshot Files}) and is used to determine whether
the file has changed since the last backup. If the device numbers
change for some reason, the next backup you run will be a full backup.
@pindex tar-snapshot-edit
To minimize the impact in these cases, GNU @command{tar} comes with
the @command{tar-snapshot-edit} utility for inspecting and updating
device numbers in snapshot files. The utility, written by
Dustin J.@: Mitchell, is available from
@uref{http://www.gnu.org/@/software/@/tar/@/utils/@/tar-snapshot-edit.html,
@GNUTAR{} home page}.
To obtain the device numbers used in the snapshot file, run
@smallexample
$ @kbd{tar-snapshot-edit @var{snapfile}}
@end smallexample
@noindent
where @var{snapfile} is the name of the snapshot file (you can supply as many
files as you wish in a single command line ).
To update all occurrences of the given device number in the file, use
@option{-r} option. It takes a single argument of the form
@samp{@var{olddev}-@var{newdev}}, where @var{olddev} is the device number
used in the snapshot file, and @var{newdev} is the corresponding new device
number. Both numbers may be specified in hex (e.g., @samp{0xfe01}),
decimal (e.g., @samp{65025}), or as a major:minor number pair (e.g.,
@samp{254:1}). To change several device numbers at once, specify them
in a single comma-separated list, as in
@option{-r 0x3060-0x4500,0x307-0x4600}.
Before updating the snapshot file, it is a good idea to create a backup
copy of it. This is accomplished by @samp{-b} option. The name of the
backup file is obtained by appending @samp{~} to the original file name.
An example session:
@smallexample
$ @kbd{tar-snapshot-edit /var/backup/snap.a}
file version 2
/tmp/snap: Device 0x0306 occurs 634 times.
$ @kbd{tar-snapshot-edit -b -r 0x0306-0x4500 /var/backup/snap.a}
file version 2
@end smallexample

File diff suppressed because it is too large Load Diff

26
doc/texify.sed Normal file
View File

@@ -0,0 +1,26 @@
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
#
# 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, 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 GNU tar; if not, write to the Free Software
# Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1{s,/\*,@comment ,
b
}
2,/.*\*\//{s,\*/,,;s/^/@comment/
b
}
/\/* END \*\//,$d
s/\([{}]\)/@\1/g
s,/\*,&@r{,
s,\*/,}&,

13
doc/untabify.el Normal file
View File

@@ -0,0 +1,13 @@
;;;; Untabify the sources.
;;;; Usage: emacs -batch -l untabify.el [file ...]
(defun global-untabify (buflist)
(mapcar
(lambda (bufname)
(set-buffer (find-file bufname))
(untabify (point-min) (point-max))
(save-buffer)
(kill-buffer (current-buffer)))
buflist))
(global-untabify command-line-args-left)

View File

@@ -1,9 +1,22 @@
@c This is part of GNU tar manual.
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
@c 2003, 2004, 2005 Free Software Foundation, Inc.
@c 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@c See file tar.texi for copying conditions.
@macro GNUTAR
@acronym{GNU} @command{tar}
@end macro
@macro xopindex{option,text}
@opindex \option\@r{, \text\}
@end macro
@macro opsummary{option}
@ifclear ANCHOR--\option\
@set ANCHOR--\option\ 1
@anchor{--\option\}
@end ifclear
@xopindex{\option\, summary}
@end macro

View File

@@ -6,12 +6,14 @@ argmatch
argp
backupfile
closeout
configmake
dirname
error
exclude
exitfail
fileblocks
fnmatch-gnu
fseeko
ftruncate
full-write
getdate
@@ -22,9 +24,11 @@ gettext
gettime
hash
human
inttypes
lchown
localcharset
memset
mkdtemp
modechange
obstack
quote
@@ -35,10 +39,13 @@ safe-read
save-cwd
savedir
setenv
snprintf
stat-time
stdbool
stdint
stpcpy
strdup
strerror
strtol
strtoul
timespec

View File

@@ -1,17 +1,10 @@
.cvsignore
.deps
__fpending.c
__fpending.h
closeout.c
closeout.h
Makefile
Makefile.am
Makefile.in
alloca.c
alloca.h
alloca_.h
allocsa.c
allocsa.h
allocsa.valgrind
alloca.in.h
argmatch.c
argmatch.h
argp-ba.c
@@ -28,55 +21,78 @@ argp-pvh.c
argp-xinl.c
argp.h
asnprintf.c
at-func.c
backupfile.c
backupfile.h
basename.c
canonicalize-lgpl.c
canonicalize.h
charset.alias
chdir-long.c
chdir-long.h
chown.c
close-stream.c
close-stream.h
closeout.c
closeout.h
config.charset
configmake.h
creat-safer.c
dirent.h
dirent.in.h
dirfd.c
dirfd.h
dirname.c
dirname.h
dup-safer.c
dup2.c
error.c
error.h
exclude.c
exclude.h
exit.h
exitfail.c
exitfail.h
fchdir.c
fchmodat.c
fchown-stub.c
fchownat.c
fcntl--.h
fcntl-safer.h
fcntl.h
fcntl.in.h
fd-safer.c
fileblocks.c
float+.h
float.h
float.in.h
fnmatch.c
fnmatch.h
fnmatch_.h
fnmatch.in.h
fnmatch_loop.c
fpending.c
fpending.h
fseeko.c
fstatat.c
ftruncate.c
full-write.c
full-write.h
getcwd.c
getcwd.h
getdate.c
getdate.h
getdate.y
getdelim.c
getdelim.h
getline.c
getline.h
getopt.c
getopt.h
getopt.in.h
getopt1.c
getopt_.h
getopt_int.h
getpagesize.c
getpagesize.h
gettext.h
gettime.c
gettimeofday.c
gnulib.mk
hash.c
hash.h
human.c
@@ -85,23 +101,28 @@ imaxtostr.c
intprops.h
inttostr.c
inttostr.h
inttypes.h
inttypes.in.h
lchown.c
lchown.h
localcharset.c
localcharset.h
localedir.h
lseek.c
lstat.c
lstat.h
malloc.c
malloca.c
malloca.h
malloca.valgrind
mbchar.c
mbchar.h
mbscasecmp.c
mbuiter.h
memchr.c
mempcpy.c
mempcpy.h
memrchr.c
memrchr.h
memset.c
minmax.h
mkdirat.c
mkdtemp.c
mktime.c
modechange.c
modechange.h
@@ -111,8 +132,10 @@ offtostr.c
open-safer.c
openat-die.c
openat-priv.h
openat-proc.c
openat.c
openat.h
pathmax.h
paxerror.c
paxexit.c
paxlib.h
@@ -126,6 +149,8 @@ quote.c
quote.h
quotearg.c
quotearg.h
readlink.c
realloc.c
ref-add.sed
ref-add.sin
ref-del.sed
@@ -137,6 +162,7 @@ regex_internal.c
regex_internal.h
regexec.c
rmdir.c
rmt-command.h
rmt.h
rpmatch.c
rtapelib.c
@@ -144,31 +170,38 @@ safe-read.c
safe-read.h
safe-write.c
safe-write.h
same-inode.h
save-cwd.c
save-cwd.h
savedir.c
savedir.h
setenv.c
setenv.h
size_max.h
sleep.c
snprintf.c
stat-macros.h
stat-time.h
stdbool.h
stdbool_.h
stdbool.in.h
stdint.h
stdint.in.h
stdio.h
stdio.in.h
stdlib.h
stdlib.in.h
stpcpy.c
stpcpy.h
strcase.h
strcasecmp.c
strchrnul.c
strchrnul.h
strdup.c
strdup.h
streq.h
strerror.c
string.h
string.in.h
strings.in.h
stripslash.c
strncasecmp.c
strndup.c
strndup.h
strnlen.c
strnlen.h
strnlen1.c
strnlen1.h
strtoimax.c
@@ -177,15 +210,30 @@ strtoll.c
strtoul.c
strtoull.c
strtoumax.c
sysexit_.h
sys
sys_stat.h
sys_stat.in.h
sys_time.h
sys_time.in.h
sysexits.h
sysexits.in.h
system-ioctl.h
system.h
tempname.c
tempname.h
time.h
time.in.h
time_r.c
time_r.h
timespec.h
uinttostr.c
umaxtostr.c
unistd--.h
unistd-safer.h
unistd.h
unistd.in.h
unitypes.h
uniwidth
uniwidth.h
unlinkdir.c
unlinkdir.h
unlocked-io.h
@@ -200,13 +248,20 @@ version-etc-fsf.c
version-etc.c
version-etc.h
vsnprintf.c
vsnprintf.h
wchar.h
wchar.in.h
wctype.h
wctype.in.h
wcwidth.c
xalloc-die.c
xalloc.h
xgetcwd.c
xgetcwd.h
xmalloc.c
xsize.h
xstrndup.c
xstrndup.h
xstrtol-error.c
xstrtol.c
xstrtol.h
xstrtoul.c

41
lib/Makefile.am Normal file
View File

@@ -0,0 +1,41 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
# 2005, 2006, 2007 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 of the License, 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 St, Fifth Floor, Boston, MA 02110-1301 USA
include gnulib.mk
rmt-command.h : Makefile
rm -f $@-t $@
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
echo "#endif" >> $@-t
mv $@-t $@
BUILT_SOURCES += rmt-command.h
CLEANFILES += rmt-command.h rmt-command.h-t
noinst_HEADERS += system.h system-ioctl.h rmt.h paxlib.h stdopen.h
libtar_a_SOURCES += \
paxerror.c paxexit.c paxlib.h paxnames.c \
prepargs.c prepargs.h \
rtapelib.c \
rmt.h \
stdopen.c stdopen.h \
system.h system-ioctl.h
libtar_a_LIBADD += $(LIBOBJS)
libtar_a_DEPENDENCIES += $(LIBOBJS)

View File

@@ -1,55 +0,0 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
# 2005, 2006 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 2, 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.
noinst_LIBRARIES = libtar.a
noinst_HEADERS = system.h system-ioctl.h localedir.h rmt.h paxlib.h stdopen.h
libtar_a_SOURCES = prepargs.c prepargs.h rtapelib.c paxerror.c paxexit.c paxnames.c stdopen.c
localedir = $(datadir)/locale
DISTCLEANFILES = localedir.h
localedir.h : Makefile
echo '#define LOCALEDIR "$(localedir)"' >$@
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@
echo "#endif" >> $@
rtapelib.o: localedir.h
libtar_a_LIBADD = $(LIBOBJS) $(ALLOCA)
libtar_a_DEPENDENCIES = $(libtar_a_LIBADD)
BUILT_SOURCES =
EXTRA_DIST = Makefile.tmpl
MAINTAINERCLEANFILES =
MOSTLYCLEANFILES =
lib_OBJECTS = $(libtar_a_OBJECTS)
# Special rule for getdate
#
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
$(srcdir)/getdate.c: getdate.y
cd $(srcdir) && \
$(YACC) $(YFLAGS) getdate.y && \
mv -f y.tab.c getdate.c
SUFFIXES = .o .c .h
CLEANFILES =
# gnulib modules

View File

@@ -1,9 +1,9 @@
/* Parse arguments from a string and prepend them to an argv.
Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
Copyright 1999, 2000, 2001, 2007 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 2, or (at your option)
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,

View File

@@ -1,10 +1,10 @@
/* stdopen.c - ensure that the three standard file descriptors are in use
Copyright (C) 2005 Free Software Foundation, Inc.
Copyright (C) 2005, 2007 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 2, or (at your option)
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,

View File

@@ -1,9 +1,9 @@
/* Emulate waitpid on systems that just have wait.
Copyright 1994, 1995, 1998, 1999 Free Software Foundation, Inc.
Copyright 1994, 1995, 1998, 1999, 2007 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 2, or (at your option)
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,

View File

@@ -1,3 +0,0 @@
Makefile
Makefile.in
*.m4

View File

@@ -1,20 +0,0 @@
index.html
*.po
LINGUAS
Makefile.in.in
Makevars.template
Rules-quot
boldquot.sed
en@boldquot.header
en@quot.header
insert-header.sin
quot.sed
remove-potcdate.sin
Makefile.in
POTFILES
Makefile
tar.pot
remove-potcdate.sed
*.gmo
*.mo
stamp-po

View File

@@ -1,41 +0,0 @@
# Makefile variables for PO directory in any package using GNU gettext.
# Usually the message domain is the same as the package name.
DOMAIN = $(PACKAGE)
# These two variables depend on the location of this directory.
subdir = po
top_builddir = ..
# These options get passed to xgettext.
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
# This is the copyright holder that gets inserted into the header of the
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
# package. (Note that the msgstr strings, extracted from the package's
# sources, belong to the copyright holder of the package.) Translators are
# expected to transfer the copyright for their translations to this person
# or entity, or to disclaim their copyright. The empty string stands for
# the public domain; in this case the translators are expected to disclaim
# their copyright.
COPYRIGHT_HOLDER = Free Software Foundation, Inc.
# This is the email address or URL to which the translators shall report
# bugs in the untranslated strings:
# - Strings which are not entire sentences, see the maintainer guidelines
# in the GNU gettext documentation, section 'Preparing Strings'.
# - Strings which use unclear terms or require additional context to be
# understood.
# - Strings which make invalid assumptions about notation of date, time or
# money.
# - Pluralisation problems.
# - Incorrect English spelling.
# - Incorrect formatting.
# It can be your email address, or a mailing list address where translators
# can write to without being subscribed, or the URL of a web page through
# which the translators can contact you.
MSGID_BUGS_ADDRESS = bug-tar@gnu.org
# This is the list of locale categories, beyond LC_MESSAGES, for which the
# message catalogs shall be used. It is usually empty.
EXTRA_LOCALE_CATEGORIES =

View File

@@ -1,11 +1,11 @@
# List of files which contain translatable strings.
# Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005 Free Software
# Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005, 2007 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 2, or (at your option)
# 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,
@@ -22,10 +22,13 @@
lib/argmatch.c
lib/argp-help.c
lib/argp-parse.c
lib/closeout.c
lib/error.c
lib/getopt.c
lib/obstack.c
lib/human.c
lib/obstack.c
lib/openat-die.c
lib/paxerror.c
lib/paxexit.c
lib/paxnames.c
@@ -34,6 +37,8 @@ lib/rpmatch.c
lib/rtapelib.c
lib/xalloc-die.c
lib/xmalloc.c
lib/version-etc.c
lib/xalloc-die.c
rmt/rmt.c
@@ -46,12 +51,12 @@ src/delete.c
src/extract.c
src/incremen.c
src/list.c
src/mangle.c
src/misc.c
src/names.c
src/tar.c
src/update.c
src/xheader.c
src/checkpoint.c
# Testsuite
tests/genfile.c

View File

@@ -1,8 +1,8 @@
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
## 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,

View File

@@ -82,11 +82,11 @@ SLEEP_MESSAGE="`awk '
}' /dev/null`"
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2007 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 2, or (at your option)
## 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,

328
scripts/tar-snapshot-edit Executable file
View File

@@ -0,0 +1,328 @@
#! /usr/bin/perl -w
# Display and edit the 'dev' field in tar's snapshots
# Copyright (C) 2007 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.
#
# Author: Dustin J. Mitchell <dustin@zmanda.com>
#
# This script is capable of replacing values in the 'dev' field of an
# incremental backup 'snapshot' file. This is useful when the device
# used to store files in a tar archive changes, without the files
# themselves changing. This may happen when, for example, a device
# driver changes major or minor numbers.
use Getopt::Std;
## reading
sub read_incr_db ($) {
my $filename = shift;
open(my $file, "<$filename") || die "Could not open '$filename' for reading";
my $header_str = <$file>;
my $file_version;
if ($header_str =~ /^GNU tar-[^-]*-([0-9]+)\n$/) {
$file_version = $1+0;
} else {
$file_version = 0;
}
print "file version $file_version\n";
if ($file_version == 0) {
return read_incr_db_0($file, $header_str);
} elsif ($file_version == 1) {
return read_incr_db_1($file);
} elsif ($file_version == 2) {
return read_incr_db_2($file);
} else {
die "Unrecognized snapshot version in header '$header_str'";
}
}
sub read_incr_db_0 ($$) {
my $file = shift;
my $header_str = shift;
my $hdr_timestamp_sec = $header_str;
chop $hdr_timestamp_sec;
my $hdr_timestamp_nsec = ''; # not present in file format 0
my @dirs;
while (<$file>) {
/^([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
push @dirs, { dev=>$1,
ino=>$2,
name=>$3 };
}
close($file);
# file version, timestamp, timestamp, dir list
return [ 0, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
}
sub read_incr_db_1 ($) {
my $file = shift;
my $timestamp = <$file>; # "sec nsec"
my ($hdr_timestamp_sec, $hdr_timestamp_nsec) = ($timestamp =~ /([0-9]*) ([0-9]*)/);
my @dirs;
while (<$file>) {
/^([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
push @dirs, { timestamp_sec=>$1,
timestamp_nsec=>$2,
dev=>$3,
ino=>$4,
name=>$5 };
}
close($file);
# file version, timestamp, timestamp, dir list
return [ 1, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
}
sub read_incr_db_2 ($) {
my $file = shift;
$/="\0"; # $INPUT_RECORD_SEPARATOR
my $hdr_timestamp_sec = <$file>;
chop $hdr_timestamp_sec;
my $hdr_timestamp_nsec = <$file>;
chop $hdr_timestamp_nsec;
my @dirs;
while (1) {
last if eof($file);
my $nfs = <$file>;
my $timestamp_sec = <$file>;
my $timestamp_nsec = <$file>;
my $dev = <$file>;
my $ino = <$file>;
my $name = <$file>;
# get rid of trailing NULs
chop $nfs;
chop $timestamp_sec;
chop $timestamp_nsec;
chop $dev;
chop $ino;
chop $name;
my @dirents;
while (my $dirent = <$file>) {
chop $dirent;
push @dirents, $dirent;
last if ($dirent eq "");
}
die "missing terminator" unless (<$file> eq "\0");
push @dirs, { nfs=>$nfs,
timestamp_sec=>$timestamp_sec,
timestamp_nsec=>$timestamp_nsec,
dev=>$dev,
ino=>$ino,
name=>$name,
dirents=>\@dirents };
}
close($file);
$/ = "\n"; # reset to normal
# file version, timestamp, timestamp, dir list
return [ 2, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
}
## display
sub show_device_counts ($$) {
my $info = shift;
my $filename = shift;
my %devices;
foreach my $dir (@{${@$info}[3]}) {
my $dev = ${%$dir}{'dev'};
$devices{$dev}++;
}
foreach $dev (sort keys %devices) {
printf "$filename: Device 0x%04x occurs $devices{$dev} times.\n", $dev;
}
}
## editing
sub replace_device_number ($@) {
my $info = shift(@_);
my @repl = @_;
foreach my $dir (@{${@$info}[3]}) {
foreach $x (@repl) {
if (${%$dir}{'dev'} eq $$x[0]) {
${%$dir}{'dev'} = $$x[1];
last;
}
}
}
}
## writing
sub write_incr_db ($$) {
my $info = shift;
my $filename = shift;
my $file_version = $$info[0];
open($file, ">$filename") || die "Could not open '$filename' for writing";
if ($file_version == 0) {
write_incr_db_0($info, $file);
} elsif ($file_version == 1) {
write_incr_db_1($info, $file);
} elsif ($file_version == 2) {
write_incr_db_2($info, $file);
} else {
die "Unknown file version $file_version.";
}
close($file);
}
sub write_incr_db_0 ($$) {
my $info = shift;
my $file = shift;
my $timestamp_sec = $info->[1];
print $file "$timestamp_sec\n";
foreach my $dir (@{${@$info}[3]}) {
print $file "${%$dir}{'dev'} ";
print $file "${%$dir}{'ino'} ";
print $file "${%$dir}{'name'}\n";
}
}
sub write_incr_db_1 ($$) {
my $info = shift;
my $file = shift;
print $file "GNU tar-1.15-1\n";
my $timestamp_sec = $info->[1];
my $timestamp_nsec = $info->[2];
print $file "$timestamp_sec $timestamp_nsec\n";
foreach my $dir (@{${@$info}[3]}) {
print $file "${%$dir}{'timestamp_sec'} ";
print $file "${%$dir}{'timestamp_nsec'} ";
print $file "${%$dir}{'dev'} ";
print $file "${%$dir}{'ino'} ";
print $file "${%$dir}{'name'}\n";
}
}
sub write_incr_db_2 ($$) {
my $info = shift;
my $file = shift;
print $file "GNU tar-1.16-2\n";
my $timestamp_sec = $info->[1];
my $timestamp_nsec = $info->[2];
print $file $timestamp_sec . "\0";
print $file $timestamp_nsec . "\0";
foreach my $dir (@{${@$info}[3]}) {
print $file ${%$dir}{'nfs'} . "\0";
print $file ${%$dir}{'timestamp_sec'} . "\0";
print $file ${%$dir}{'timestamp_nsec'} . "\0";
print $file ${%$dir}{'dev'} . "\0";
print $file ${%$dir}{'ino'} . "\0";
print $file ${%$dir}{'name'} . "\0";
foreach my $dirent (@{${%$dir}{'dirents'}}) {
print $file $dirent . "\0";
}
print $file "\0";
}
}
## main
sub main {
our ($opt_b, $opt_r, $opt_h);
getopts('br:h');
HELP_MESSAGE() if ($opt_h || $#ARGV == -1 || ($opt_b && !$opt_r));
my @repl;
if ($opt_r) {
foreach my $spec (split(/,/, $opt_r)) {
($spec =~ /^([^-]+)-([^-]+)/) || die "Invalid replacement specification '$opt_r'";
push @repl, [interpret_dev($1), interpret_dev($2)];
}
}
foreach my $snapfile (@ARGV) {
my $info = read_incr_db($snapfile);
if ($opt_r ) {
if ($opt_b) {
rename($snapfile, $snapfile . "~") || die "Could not rename '$snapfile' to backup";
}
replace_device_number($info, @repl);
write_incr_db($info, $snapfile);
} else {
show_device_counts($info, $snapfile);
}
}
}
sub HELP_MESSAGE {
print "Usage: tar-snapshot-edit.pl [-r 'DEV1-DEV2[,DEV3-DEV4...]' [-b]] SNAPFILE [SNAPFILE [..]]\n";
print "\n";
print " Without -r, summarize the 'device' values in each SNAPFILE.\n";
print "\n";
print " With -r, replace occurrences of DEV1 with DEV2 in each SNAPFILE.\n";
print " DEV1 and DEV2 may be specified in hex (e.g., 0xfe01), decimal (e.g.,\n";
print " 65025), or MAJ:MIN (e.g., 254:1). To replace multiple occurrences,\n";
print " separate them with commas. If -b is also specified, backup\n";
print " files (ending with '~') will be created.\n";
exit 1;
}
sub interpret_dev ($) {
my $dev = shift;
if ($dev =~ /^([0-9]+):([0-9]+)$/) {
return $1 * 256 + $2;
} elsif ($dev =~ /^0x[0-9a-fA-F]+$/) {
return oct $dev;
} elsif ($dev =~ /^[0-9]+$/) {
return $dev+0;
} else {
die "Invalid device specification '$dev'";
}
}
main

473
scripts/xsparse.c Normal file
View File

@@ -0,0 +1,473 @@
/* xsparse - expands compressed sparse file images extracted from GNU tar
archives.
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
Written by Sergey Poznyakoff
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. */
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
/* Bound on length of the string representing an off_t.
See INT_STRLEN_BOUND in intprops.h for explanation */
#define OFF_T_STRLEN_BOUND ((sizeof (off_t) * CHAR_BIT) * 146 / 485 + 1)
#define OFF_T_STRSIZE_BOUND (OFF_T_STRLEN_BOUND+1)
#define BLOCKSIZE 512
struct sp_array
{
off_t offset;
size_t numbytes;
};
char *progname;
int verbose;
void
die (int code, char *fmt, ...)
{
va_list ap;
fprintf (stderr, "%s: ", progname);
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fprintf (stderr, "\n");
exit (code);
}
void *
emalloc (size_t size)
{
char *p = malloc (size);
if (!p)
die (1, "not enough memory");
return p;
}
off_t
string_to_off (char *p, char **endp)
{
off_t v = 0;
for (; *p; p++)
{
int digit = *p - '0';
off_t x = v * 10;
if (9 < (unsigned) digit)
{
if (endp)
{
*endp = p;
break;
}
die (1, "number parse error near %s", p);
}
else if (x / 10 != v)
die (1, "number out of allowed range, near %s", p);
v = x + digit;
if (v < 0)
die (1, "negative number");
}
if (endp)
*endp = p;
return v;
}
size_t
string_to_size (char *p, char **endp)
{
off_t v = string_to_off (p, endp);
size_t ret = v;
if (ret != v)
die (1, "number too big");
return ret;
}
size_t sparse_map_size;
struct sp_array *sparse_map;
void
get_line (char *s, int size, FILE *stream)
{
char *p = fgets (s, size, stream);
size_t len;
if (!p)
die (1, "unexpected end of file");
len = strlen (p);
if (s[len - 1] != '\n')
die (1, "buffer overflow");
s[len - 1] = 0;
}
int
get_var (FILE *fp, char **name, char **value)
{
static char *buffer;
static size_t bufsize = OFF_T_STRSIZE_BOUND;
char *p, *q;
buffer = emalloc (bufsize);
do
{
size_t len, s;
if (!fgets (buffer, bufsize, fp))
return 0;
len = strlen (buffer);
if (len == 0)
return 0;
s = string_to_size (buffer, &p);
if (*p != ' ')
die (1, "malformed header: expected space but found %s", p);
if (buffer[len-1] != '\n')
{
if (bufsize < s + 1)
{
bufsize = s + 1;
buffer = realloc (buffer, bufsize);
if (!buffer)
die (1, "not enough memory");
}
if (!fgets (buffer + len, s - len + 1, fp))
die (1, "unexpected end of file or read error");
}
p++;
}
while (memcmp (p, "GNU.sparse.", 11));
p += 11;
q = strchr (p, '=');
if (!q)
die (1, "malformed header: expected `=' not found");
*q++ = 0;
q[strlen (q) - 1] = 0;
*name = p;
*value = q;
return 1;
}
char *outname;
off_t outsize;
unsigned version_major;
unsigned version_minor;
void
read_xheader (char *name)
{
char *kw, *val;
FILE *fp = fopen (name, "r");
char *expect = NULL;
size_t i = 0;
if (verbose)
printf ("Reading extended header file\n");
while (get_var (fp, &kw, &val))
{
if (verbose)
printf ("Found variable GNU.sparse.%s = %s\n", kw, val);
if (expect && strcmp (kw, expect))
die (1, "bad keyword sequence: expected `%s' but found `%s'",
expect, kw);
expect = NULL;
if (strcmp (kw, "name") == 0)
{
outname = emalloc (strlen (val) + 1);
strcpy (outname, val);
}
else if (strcmp (kw, "major") == 0)
{
version_major = string_to_size (val, NULL);
}
else if (strcmp (kw, "minor") == 0)
{
version_minor = string_to_size (val, NULL);
}
else if (strcmp (kw, "realsize") == 0
|| strcmp (kw, "size") == 0)
{
outsize = string_to_off (val, NULL);
}
else if (strcmp (kw, "numblocks") == 0)
{
sparse_map_size = string_to_size (val, NULL);
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
}
else if (strcmp (kw, "offset") == 0)
{
sparse_map[i].offset = string_to_off (val, NULL);
expect = "numbytes";
}
else if (strcmp (kw, "numbytes") == 0)
{
sparse_map[i++].numbytes = string_to_size (val, NULL);
}
else if (strcmp (kw, "map") == 0)
{
for (i = 0; i < sparse_map_size; i++)
{
sparse_map[i].offset = string_to_off (val, &val);
if (*val != ',')
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
*val);
sparse_map[i].numbytes = string_to_size (val+1, &val);
if (*val != ',')
{
if (!(*val == 0 && i == sparse_map_size-1))
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
*val);
}
else
val++;
}
if (*val)
die (1, "bad GNU.sparse.map: garbage at the end");
}
}
if (expect)
die (1, "bad keyword sequence: expected `%s' not found", expect);
if (version_major == 0 && sparse_map_size == 0)
die (1, "size of the sparse map unknown");
if (i != sparse_map_size)
die (1, "not all sparse entries supplied");
fclose (fp);
}
void
read_map (FILE *ifp)
{
size_t i;
char nbuf[OFF_T_STRSIZE_BOUND];
if (verbose)
printf ("Reading v.1.0 sparse map\n");
get_line (nbuf, sizeof nbuf, ifp);
sparse_map_size = string_to_size (nbuf, NULL);
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
for (i = 0; i < sparse_map_size; i++)
{
get_line (nbuf, sizeof nbuf, ifp);
sparse_map[i].offset = string_to_off (nbuf, NULL);
get_line (nbuf, sizeof nbuf, ifp);
sparse_map[i].numbytes = string_to_size (nbuf, NULL);
}
fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
SEEK_SET);
}
void
expand_sparse (FILE *sfp, int ofd)
{
size_t i;
size_t maxbytes = 0;
char *buffer;
for (i = 0; i < sparse_map_size; i++)
if (maxbytes < sparse_map[i].numbytes)
maxbytes = sparse_map[i].numbytes;
for (buffer = malloc (maxbytes); !buffer; maxbytes /= 2)
if (maxbytes == 0)
die (1, "not enough memory");
for (i = 0; i < sparse_map_size; i++)
{
size_t size = sparse_map[i].numbytes;
if (size == 0)
ftruncate (ofd, sparse_map[i].offset);
else
{
lseek (ofd, sparse_map[i].offset, SEEK_SET);
while (size)
{
size_t rdsize = (size < maxbytes) ? size : maxbytes;
if (rdsize != fread (buffer, 1, rdsize, sfp))
die (1, "read error (%d)", errno);
if (rdsize != write (ofd, buffer, rdsize))
die (1, "write error (%d)", errno);
size -= rdsize;
}
}
}
free (buffer);
}
void
usage (int code)
{
printf ("Usage: %s [OPTIONS] infile [outfile]\n", progname);
printf ("%s: expand sparse files extracted from GNU archives\n",
progname);
printf ("\nOPTIONS are:\n\n");
printf (" -h Display this help list\n");
printf (" -n Dry run: do nothing, print what would have been done\n");
printf (" -v Increase verbosity level\n");
printf (" -x FILE Parse extended header FILE\n\n");
exit (code);
}
void
guess_outname (char *name)
{
char *p;
char *s;
if (name[0] == '.' && name[1] == '/')
name += 2;
p = name + strlen (name) - 1;
s = NULL;
for (; p > name && *p != '/'; p--)
;
if (*p == '/')
s = p + 1;
if (p != name)
{
for (p--; p > name && *p != '/'; p--)
;
}
if (*p != '/')
{
if (s)
outname = s;
else
{
outname = emalloc (4 + strlen (name));
strcpy (outname, "../");
strcpy (outname + 3, name);
}
}
else
{
size_t len = p - name + 1;
outname = emalloc (len + strlen (s) + 1);
memcpy (outname, name, len);
strcpy (outname + len, s);
}
}
int
main (int argc, char **argv)
{
int c;
int dry_run = 0;
char *xheader_file = NULL;
char *inname;
FILE *ifp;
struct stat st;
int ofd;
progname = argv[0];
while ((c = getopt (argc, argv, "hnvx:")) != EOF)
{
switch (c)
{
case 'h':
usage (0);
break;
case 'x':
xheader_file = optarg;
break;
case 'n':
dry_run = 1;
case 'v':
verbose++;
break;
default:
exit (1);
}
}
argc -= optind;
argv += optind;
if (argc == 0 || argc > 2)
usage (1);
if (xheader_file)
read_xheader (xheader_file);
inname = argv[0];
if (argv[1])
outname = argv[1];
if (stat (inname, &st))
die (1, "cannot stat %s (%d)", inname, errno);
ifp = fopen (inname, "r");
if (ifp == NULL)
die (1, "cannot open file %s (%d)", inname, errno);
if (!xheader_file || version_major == 1)
read_map (ifp);
if (!outname)
guess_outname (inname);
ofd = open (outname, O_RDWR|O_CREAT|O_TRUNC, st.st_mode);
if (ofd == -1)
die (1, "cannot open file %s (%d)", outname, errno);
if (verbose)
printf ("Expanding file `%s' to `%s'\n", inname, outname);
if (dry_run)
{
printf ("Finished dry run\n");
return 0;
}
expand_sparse (ifp, ofd);
fclose (ifp);
close (ofd);
if (verbose)
printf ("Done\n");
if (outsize)
{
if (stat (outname, &st))
die (1, "cannot stat output file %s (%d)", outname, errno);
if (st.st_size != outsize)
die (1, "expanded file has wrong size");
}
return 0;
}

View File

@@ -1,7 +1,6 @@
Makefile.in
Makefile
localedir.h
rmt
tar
.deps
.gdbinit
Makefile
Makefile.in
rmt
tar

View File

@@ -1,11 +1,11 @@
# Makefile for GNU tar sources.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
# Software Foundation, Inc.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
# 2007 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 2, or (at your option)
## 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,
@@ -23,6 +23,7 @@ bin_PROGRAMS = tar
noinst_HEADERS = arith.h common.h tar.h
tar_SOURCES = \
buffer.c\
checkpoint.c\
compare.c\
create.c\
delete.c\
@@ -30,18 +31,17 @@ tar_SOURCES = \
xheader.c\
incremen.c\
list.c\
mangle.c\
misc.c\
names.c\
sparse.c\
suffix.c\
system.c\
tar.c\
transform.c\
update.c\
utf8.c
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
tar.o: ../lib/localedir.h
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)

View File

@@ -1,9 +1,9 @@
/* Long integers, for GNU tar.
Copyright 1999 Free Software Foundation, Inc.
Copyright 1999, 2007 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 2, or (at your option)
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,

View File

@@ -1,13 +1,13 @@
/* Buffer management for tar.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
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 2, or (at your option) any later
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
@@ -26,7 +26,6 @@
#include <closeout.h>
#include <fnmatch.h>
#include <getline.h>
#include <human.h>
#include <quotearg.h>
@@ -44,6 +43,7 @@
static tarlong prev_written; /* bytes written on previous volumes */
static tarlong bytes_written; /* bytes written on this volume */
static void *record_buffer[2]; /* allocated memory */
union block *record_buffer_aligned[2];
static int record_index;
/* FIXME: The following variables should ideally be static to this
@@ -55,6 +55,8 @@ union block *current_block; /* current block of archive */
enum access_mode access_mode; /* how do we handle the archive */
off_t records_read; /* number of records read from this archive */
off_t records_written; /* likewise, for records written */
extern off_t records_skipped; /* number of records skipped at the start
of the archive, defined in delete.c */
static off_t record_start_block; /* block ordinal at record_start */
@@ -72,9 +74,6 @@ static int read_error_count;
/* Have we hit EOF yet? */
static bool hit_eof;
/* Checkpointing counter */
static int checkpoint;
static bool read_full_records = false;
/* We're reading, but we just read the last block and it's time to update.
@@ -118,6 +117,15 @@ static off_t save_totsize; /* total size of file we are writing, only
static off_t save_sizeleft; /* where we are in the file we are writing,
only valid if save_name is nonzero */
static struct tar_stat_info dummy;
void
buffer_write_global_xheader ()
{
xheader_write_global (&dummy.xhdr);
}
void
mv_begin (struct tar_stat_info *st)
{
@@ -165,6 +173,15 @@ void
set_start_time ()
{
gettime (&start_time);
volume_start_time = start_time;
last_stat_time = start_time;
}
void
set_volume_start_time ()
{
gettime (&volume_start_time);
last_stat_time = volume_start_time;
}
void
@@ -172,9 +189,9 @@ compute_duration ()
{
struct timespec now;
gettime (&now);
duration += ((now.tv_sec - start_time.tv_sec)
+ (now.tv_nsec - start_time.tv_nsec) / 1e9);
set_start_time ();
duration += ((now.tv_sec - last_stat_time.tv_sec)
+ (now.tv_nsec - last_stat_time.tv_nsec) / 1e9);
gettime (&last_stat_time);
}
@@ -184,7 +201,8 @@ enum compress_type {
ct_none,
ct_compress,
ct_gzip,
ct_bzip2
ct_bzip2,
ct_lzma
};
struct zip_magic
@@ -201,6 +219,7 @@ static struct zip_magic const magic[] = {
{ ct_compress, 2, "\037\235", "compress", "-Z" },
{ ct_gzip, 2, "\037\213", "gzip", "-z" },
{ ct_bzip2, 3, "BZh", "bzip2", "-j" },
{ ct_lzma, 6, "\xFFLZMA", "lzma", "--lzma" }, /* FIXME: ???? */
};
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
@@ -210,18 +229,22 @@ static struct zip_magic const magic[] = {
/* Check if the file ARCHIVE is a compressed archive. */
enum compress_type
check_compressed_archive ()
check_compressed_archive (bool *pshort)
{
struct zip_magic const *p;
bool sfr;
bool temp;
if (!pshort)
pshort = &temp;
/* Prepare global data needed for find_next_block: */
record_end = record_start; /* set up for 1st record = # 0 */
sfr = read_full_records;
read_full_records = true; /* Suppress fatal error on reading a partial
record */
find_next_block ();
*pshort = find_next_block () == 0;
/* Restore global values */
read_full_records = sfr;
@@ -249,11 +272,16 @@ open_compressed_archive ()
if (!multi_volume_option)
{
enum compress_type type = check_compressed_archive ();
bool shortfile;
enum compress_type type = check_compressed_archive (&shortfile);
if (type == ct_none)
return archive;
{
if (shortfile)
ERROR ((0, 0, _("This does not look like a tar archive")));
return archive;
}
/* FD is not needed any more */
rmtclose (archive);
@@ -273,26 +301,65 @@ open_compressed_archive ()
}
void
print_total_written (void)
static void
print_stats (FILE *fp, const char *text, tarlong numbytes)
{
tarlong written = prev_written + bytes_written;
char bytes[sizeof (tarlong) * CHAR_BIT];
char abbr[LONGEST_HUMAN_READABLE + 1];
char rate[LONGEST_HUMAN_READABLE + 1];
int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
sprintf (bytes, TARLONG_FORMAT, written);
sprintf (bytes, TARLONG_FORMAT, numbytes);
/* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
fprintf (stderr, _("Total bytes written: %s (%s, %s/s)\n"), bytes,
human_readable (written, abbr, human_opts, 1, 1),
(0 < duration && written / duration < (uintmax_t) -1
? human_readable (written / duration, rate, human_opts, 1, 1)
fprintf (fp, "%s: %s (%s, %s/s)\n",
text, bytes,
human_readable (numbytes, abbr, human_opts, 1, 1),
(0 < duration && numbytes / duration < (uintmax_t) -1
? human_readable (numbytes / duration, rate, human_opts, 1, 1)
: "?"));
}
void
print_total_stats ()
{
switch (subcommand_option)
{
case CREATE_SUBCOMMAND:
case CAT_SUBCOMMAND:
case UPDATE_SUBCOMMAND:
case APPEND_SUBCOMMAND:
/* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
print_stats (stderr, _("Total bytes written"),
prev_written + bytes_written);
break;
case DELETE_SUBCOMMAND:
{
char buf[UINTMAX_STRSIZE_BOUND];
print_stats (stderr, _("Total bytes read"),
records_read * record_size);
print_stats (stderr, _("Total bytes written"),
prev_written + bytes_written);
fprintf (stderr, _("Total bytes deleted: %s\n"),
STRINGIFY_BIGINT ((records_read - records_skipped)
* record_size
- (prev_written + bytes_written), buf));
}
break;
case EXTRACT_SUBCOMMAND:
case LIST_SUBCOMMAND:
case DIFF_SUBCOMMAND:
print_stats (stderr, _("Total bytes read"),
records_read * record_size);
break;
default:
abort ();
}
}
/* Compute and return the block ordinal at current_block. */
off_t
current_block_ordinal (void)
@@ -369,10 +436,11 @@ xclose (int fd)
static void
init_buffer ()
{
if (!record_buffer[record_index])
page_aligned_alloc (&record_buffer[record_index], record_size);
if (! record_buffer_aligned[record_index])
record_buffer_aligned[record_index] =
page_aligned_alloc (&record_buffer[record_index], record_size);
record_start = record_buffer[record_index];
record_start = record_buffer_aligned[record_index];
current_block = record_start;
record_end = record_start + blocking_factor;
}
@@ -384,16 +452,6 @@ _open_archive (enum access_mode wanted_access)
{
int backed_up_flag = 0;
if (index_file_name)
{
stdlis = freopen (index_file_name, "w", stdout);
if (! stdlis)
open_error (index_file_name);
close_stdout_set_file_name (index_file_name);
}
else
stdlis = to_stdout_option ? stderr : stdout;
if (record_size == 0)
FATAL_ERROR ((0, 0, _("Invalid value for record_size")));
@@ -433,7 +491,8 @@ _open_archive (enum access_mode wanted_access)
break;
}
if (wanted_access == ACCESS_WRITE
if (!index_file_name
&& wanted_access == ACCESS_WRITE
&& strcmp (archive_name_array[0], "-") == 0)
stdlis = stderr;
}
@@ -447,27 +506,33 @@ _open_archive (enum access_mode wanted_access)
{
case ACCESS_READ:
{
bool shortfile;
enum compress_type type;
archive = STDIN_FILENO;
type = check_compressed_archive (archive);
type = check_compressed_archive (&shortfile);
if (type != ct_none)
FATAL_ERROR ((0, 0,
_("Archive is compressed. Use %s option"),
compress_option (type)));
if (shortfile)
ERROR ((0, 0, _("This does not look like a tar archive")));
}
break;
case ACCESS_WRITE:
archive = STDOUT_FILENO;
stdlis = stderr;
if (!index_file_name)
stdlis = stderr;
break;
case ACCESS_UPDATE:
archive = STDIN_FILENO;
stdlis = stderr;
write_archive_to_stdout = true;
record_end = record_start; /* set up for 1st record = # 0 */
if (!index_file_name)
stdlis = stderr;
break;
}
}
@@ -492,8 +557,13 @@ _open_archive (enum access_mode wanted_access)
break;
case ACCESS_UPDATE:
archive = rmtopen (archive_name_array[0], O_RDWR | O_CREAT | O_BINARY,
archive = rmtopen (archive_name_array[0],
O_RDWR | O_CREAT | O_BINARY,
MODE_RW, rsh_command_option);
if (check_compressed_archive (NULL) != ct_none)
FATAL_ERROR ((0, 0,
_("Cannot update compressed archives")));
break;
}
@@ -514,14 +584,11 @@ _open_archive (enum access_mode wanted_access)
switch (wanted_access)
{
case ACCESS_UPDATE:
records_written = 0;
record_end = record_start; /* set up for 1st record = # 0 */
case ACCESS_READ:
find_next_block (); /* read it in, check for EOF */
break;
case ACCESS_UPDATE:
case ACCESS_WRITE:
records_written = 0;
break;
@@ -534,13 +601,7 @@ _flush_write (void)
{
ssize_t status;
if (checkpoint_option && !(++checkpoint % 10))
/* TRANSLATORS: This is a ``checkpoint of write operation'',
*not* ``Writing a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
*not* ``Escribiendo un punto de comprobaci@'on'' */
WARN ((0, 0, _("Write checkpoint %d"), checkpoint));
checkpoint_run (true);
if (tape_length_option && tape_length_option <= bytes_written)
{
errno = ENOSPC;
@@ -550,7 +611,7 @@ _flush_write (void)
status = record_size;
else
status = sys_write_archive_buffer ();
return status;
}
@@ -565,7 +626,7 @@ archive_write_error (ssize_t status)
if (totals_option)
{
int e = errno;
print_total_written ();
print_total_stats ();
errno = e;
}
@@ -644,39 +705,6 @@ short_read (size_t status)
records_read++;
}
/* Perform a read to flush the buffer. */
size_t
_flush_read (void)
{
size_t status; /* result from system call */
if (checkpoint_option && !(++checkpoint % 10))
/* TRANSLATORS: This is a ``checkpoint of read operation'',
*not* ``Reading a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
*not* ``Leyendo un punto de comprobaci@'on'' */
WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
/* Clear the count of errors. This only applies to a single call to
flush_read. */
read_error_count = 0; /* clear error count */
if (write_archive_to_stdout && record_start_block != 0)
{
archive = STDOUT_FILENO;
status = sys_write_archive_buffer ();
archive = STDIN_FILENO;
if (status != record_size)
archive_write_error (status);
}
status = rmtread (archive, record_start->buffer, record_size);
if (status == record_size)
records_read++;
return status;
}
/* Flush the current buffer to/from the archive. */
void
flush_archive (void)
@@ -805,7 +833,7 @@ close_archive (void)
verify_volume ();
if (rmtclose (archive) != 0)
close_warn (*archive_name_cursor);
close_error (*archive_name_cursor);
sys_wait_for_child (child_pid);
@@ -872,8 +900,9 @@ change_tape_menu (FILE *read_file)
{
char *input_buffer = NULL;
size_t size = 0;
while (1)
bool stop = false;
while (!stop)
{
fputc ('\007', stderr);
fprintf (stderr,
@@ -903,7 +932,7 @@ change_tape_menu (FILE *read_file)
case '?':
{
fprintf (stderr, _("\
n [name] Give a new file name for the next (and subsequent) volume(s)\n\
n name Give a new file name for the next (and subsequent) volume(s)\n\
q Abort tar\n\
y or newline Continue operation\n"));
if (!restrict_option)
@@ -940,8 +969,15 @@ change_tape_menu (FILE *read_file)
;
*cursor = '\0';
/* FIXME: the following allocation is never reclaimed. */
*archive_name_cursor = xstrdup (name);
if (name[0])
{
/* FIXME: the following allocation is never reclaimed. */
*archive_name_cursor = xstrdup (name);
stop = true;
}
else
fprintf (stderr, "%s",
_("File name not specified. Try again.\n"));
}
break;
@@ -982,9 +1018,10 @@ new_volume (enum access_mode mode)
assign_string (&volume_label, NULL);
assign_string (&continued_file_name, NULL);
continued_file_size = continued_file_offset = 0;
current_block = record_start;
if (rmtclose (archive) != 0)
close_warn (*archive_name_cursor);
close_error (*archive_name_cursor);
archive_name_cursor++;
if (archive_name_cursor == archive_name_array + archive_names)
@@ -1055,10 +1092,12 @@ new_volume (enum access_mode mode)
}
static bool
read_header0 ()
read_header0 (struct tar_stat_info *info)
{
enum read_header rc = read_header (false);
enum read_header rc;
tar_stat_init (info);
rc = read_header_primitive (false, info);
if (rc == HEADER_SUCCESS)
{
set_next_block_after (current_header);
@@ -1073,22 +1112,24 @@ try_new_volume ()
{
size_t status;
union block *header;
enum access_mode acc;
switch (subcommand_option)
{
case APPEND_SUBCOMMAND:
case CAT_SUBCOMMAND:
case UPDATE_SUBCOMMAND:
if (!new_volume (ACCESS_UPDATE))
return true;
acc = ACCESS_UPDATE;
break;
default:
if (!new_volume (ACCESS_READ))
return true;
acc = ACCESS_READ;
break;
}
if (!new_volume (acc))
return true;
while ((status = rmtread (archive, record_start->buffer, record_size))
== SAFE_READ_ERROR)
archive_read_error ();
@@ -1099,14 +1140,13 @@ try_new_volume ()
header = find_next_block ();
if (!header)
return false;
switch (header->header.typeflag)
{
case XGLTYPE:
{
struct tar_stat_info dummy;
if (!read_header0 ())
if (!read_header0 (&dummy))
return false;
tar_stat_init (&dummy);
xheader_decode (&dummy); /* decodes values from the global header */
tar_stat_destroy (&dummy);
if (!real_s_name)
@@ -1120,8 +1160,9 @@ try_new_volume ()
}
case GNUTYPE_VOLHDR:
if (!read_header0 ())
if (!read_header0 (&dummy))
return false;
tar_stat_destroy (&dummy);
assign_string (&volume_label, current_header->header.name);
set_next_block_after (header);
header = find_next_block ();
@@ -1130,8 +1171,9 @@ try_new_volume ()
/* FALL THROUGH */
case GNUTYPE_MULTIVOL:
if (!read_header0 ())
if (!read_header0 (&dummy))
return false;
tar_stat_destroy (&dummy);
assign_string (&continued_file_name, current_header->header.name);
continued_file_size =
UINTMAX_FROM_HEADER (current_header->header.size);
@@ -1149,9 +1191,19 @@ try_new_volume ()
if (!continued_file_name
|| strcmp (continued_file_name, real_s_name))
{
WARN ((0, 0, _("%s is not continued on this volume"),
quote (real_s_name)));
return false;
if ((archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
&& strlen (real_s_name) >= NAME_FIELD_SIZE
&& strncmp (continued_file_name, real_s_name,
NAME_FIELD_SIZE) == 0)
WARN ((0, 0,
_("%s is possibly continued on this volume: header contains truncated name"),
quote (real_s_name)));
else
{
WARN ((0, 0, _("%s is not continued on this volume"),
quote (real_s_name)));
return false;
}
}
s = continued_file_size + continued_file_offset;
@@ -1231,7 +1283,7 @@ static void
_write_volume_label (const char *str)
{
if (archive_format == POSIX_FORMAT)
xheader_store ("GNU.volume.label", NULL, str);
xheader_store ("GNU.volume.label", &dummy, str);
else
{
union block *label = find_next_block ();
@@ -1348,9 +1400,9 @@ add_multi_volume_header (void)
if (archive_format == POSIX_FORMAT)
{
off_t d = real_s_totsize - real_s_sizeleft;
xheader_store ("GNU.volume.filename", NULL, real_s_name);
xheader_store ("GNU.volume.size", NULL, &real_s_sizeleft);
xheader_store ("GNU.volume.offset", NULL, &d);
xheader_store ("GNU.volume.filename", &dummy, real_s_name);
xheader_store ("GNU.volume.size", &dummy, &real_s_sizeleft);
xheader_store ("GNU.volume.offset", &dummy, &d);
}
else
gnu_add_multi_volume_header ();
@@ -1388,13 +1440,8 @@ simple_flush_read (void)
{
size_t status; /* result from system call */
if (checkpoint_option && !(++checkpoint % 10))
/* TRANSLATORS: This is a ``checkpoint of read operation'',
*not* ``Reading a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
*not* ``Leyendo un punto de comprobaci@'on'' */
WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
checkpoint_run (false);
/* Clear the count of errors. This only applies to a single call to
flush_read. */
@@ -1452,13 +1499,8 @@ _gnu_flush_read (void)
{
size_t status; /* result from system call */
if (checkpoint_option && !(++checkpoint % 10))
/* TRANSLATORS: This is a ``checkpoint of read operation'',
*not* ``Reading a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
*not* ``Leyendo un punto de comprobaci@'on'' */
WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
checkpoint_run (false);
/* Clear the count of errors. This only applies to a single call to
flush_read. */
@@ -1547,11 +1589,10 @@ _gnu_flush_write (size_t buffer_level)
if (!new_volume (ACCESS_WRITE))
return;
xheader_destroy (&extended_header);
tar_stat_destroy (&dummy);
increase_volume_number ();
if (totals_option)
prev_written += bytes_written;
prev_written += bytes_written;
bytes_written = 0;
copy_ptr = record_start->buffer + status;
@@ -1566,7 +1607,9 @@ _gnu_flush_write (size_t buffer_level)
if (real_s_name)
add_multi_volume_header ();
write_extended (true, NULL, find_next_block ());
write_extended (true, &dummy, find_next_block ());
tar_stat_destroy (&dummy);
if (real_s_name)
add_chunk_header ();
header = find_next_block ();
@@ -1629,4 +1672,5 @@ open_archive (enum access_mode wanted_access)
default:
break;
}
set_volume_start_time ();
}

270
src/checkpoint.c Normal file
View File

@@ -0,0 +1,270 @@
/* Checkpoint management for tar.
Copyright (C) 2007 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, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include "common.h"
enum checkpoint_opcode
{
cop_dot,
cop_bell,
cop_echo,
cop_ttyout,
cop_sleep,
cop_exec
};
struct checkpoint_action
{
struct checkpoint_action *next;
enum checkpoint_opcode opcode;
union
{
time_t time;
char *command;
} v;
};
/* Checkpointing counter */
static unsigned checkpoint;
/* List of checkpoint actions */
static struct checkpoint_action *checkpoint_action, *checkpoint_action_tail;
static struct checkpoint_action *
alloc_action (enum checkpoint_opcode opcode)
{
struct checkpoint_action *p = xzalloc (sizeof *p);
if (checkpoint_action_tail)
checkpoint_action_tail->next = p;
else
checkpoint_action = p;
checkpoint_action_tail = p;
p->opcode = opcode;
return p;
}
static char *
copy_string_unquote (const char *str)
{
char *output = xstrdup (str);
size_t len = strlen (output);
if ((*output == '"' || *output == '\'')
&& output[len-1] == *output)
{
memmove (output, output+1, len-2);
output[len-2] = 0;
}
unquote_string (output);
return output;
}
void
checkpoint_compile_action (const char *str)
{
struct checkpoint_action *act;
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
alloc_action (cop_dot);
if (strcmp (str, "bell") == 0)
alloc_action (cop_bell);
else if (strcmp (str, "echo") == 0)
alloc_action (cop_echo);
else if (strncmp (str, "echo=", 5) == 0)
{
act = alloc_action (cop_echo);
act->v.command = copy_string_unquote (str + 5);
}
else if (strncmp (str, "exec=", 5) == 0)
{
act = alloc_action (cop_exec);
act->v.command = copy_string_unquote (str + 5);
}
else if (strncmp (str, "ttyout=", 7) == 0)
{
act = alloc_action (cop_ttyout);
act->v.command = copy_string_unquote (str + 7);
}
else if (strncmp (str, "sleep=", 6) == 0)
{
char *p;
time_t n = strtoul (str+6, &p, 10);
if (*p)
FATAL_ERROR ((0, 0, _("%s: not a valid timeout"), str));
act = alloc_action (cop_sleep);
act->v.time = n;
}
else
FATAL_ERROR ((0, 0, _("%s: unknown checkpoint action"), str));
}
void
checkpoint_finish_compile ()
{
if (checkpoint_option)
{
if (!checkpoint_action)
/* Provide a historical default */
checkpoint_compile_action ("echo");
}
else if (checkpoint_action)
/* Otherwise, set default checkpoint rate */
checkpoint_option = DEFAULT_CHECKPOINT;
}
char *
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
{
const char *opstr = do_write ? gettext ("write") : gettext ("read");
size_t opstrlen = strlen (opstr);
char uintbuf[UINTMAX_STRSIZE_BOUND];
char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
size_t cpslen = strlen (cps);
const char *ip;
char *op;
char *output;
size_t outlen = strlen (input); /* Initial guess */
/* Fix the initial length guess */
for (ip = input; (ip = strchr (ip, '%')) != NULL; )
{
switch (ip[1])
{
case 'u':
outlen += cpslen - 2;
break;
case 's':
outlen += opstrlen - 2;
}
ip++;
}
output = xmalloc (outlen + 1);
for (ip = input, op = output; *ip; )
{
if (*ip == '%')
{
switch (*++ip)
{
case 'u':
op = stpcpy (op, cps);
break;
case 's':
op = stpcpy (op, opstr);
break;
default:
*op++ = '%';
*op++ = *ip;
break;
}
ip++;
}
else
*op++ = *ip++;
}
*op = 0;
return output;
}
static void
run_checkpoint_actions (bool do_write)
{
struct checkpoint_action *p;
FILE *tty = NULL;
for (p = checkpoint_action; p; p = p->next)
{
switch (p->opcode)
{
case cop_dot:
fputc ('.', stdlis);
fflush (stdlis);
break;
case cop_bell:
if (!tty)
tty = fopen ("/dev/tty", "w");
if (tty)
{
fputc ('\a', tty);
fflush (tty);
}
break;
case cop_echo:
{
char *tmp;
const char *str = p->v.command;
if (!str)
{
if (do_write)
/* TRANSLATORS: This is a ``checkpoint of write operation'',
*not* ``Writing a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
*not* ``Escribiendo un punto de comprobaci@'on'' */
str = gettext ("Write checkpoint %u");
else
/* TRANSLATORS: This is a ``checkpoint of read operation'',
*not* ``Reading a checkpoint''.
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
*not* ``Leyendo un punto de comprobaci@'on'' */
str = gettext ("Read checkpoint %u");
}
tmp = expand_checkpoint_string (str, do_write, checkpoint);
WARN ((0, 0, "%s", tmp));
free (tmp);
}
break;
case cop_ttyout:
if (!tty)
tty = fopen ("/dev/tty", "w");
if (tty)
{
char *tmp = expand_checkpoint_string (p->v.command, do_write,
checkpoint);
fprintf (tty, "%s", tmp);
fflush (tty);
free (tmp);
}
break;
case cop_sleep:
sleep (p->v.time);
break;
case cop_exec:
sys_exec_checkpoint_script (p->v.command,
archive_name_cursor[0],
checkpoint);
break;
}
}
if (tty)
fclose (tty);
}
void
checkpoint_run (bool do_write)
{
if (checkpoint_option && !(++checkpoint % checkpoint_option))
run_checkpoint_actions (do_write);
}

View File

@@ -1,11 +1,11 @@
/* Common declarations for the tar program.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007, 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 2, or (at your option) any later
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
@@ -129,12 +129,14 @@ GLOBAL enum backup_type backup_type;
GLOBAL bool block_number_option;
GLOBAL bool checkpoint_option;
GLOBAL unsigned checkpoint_option;
#define DEFAULT_CHECKPOINT 10
/* Specified name of compression program, or "gzip" as implied by -z. */
GLOBAL const char *use_compress_program_option;
GLOBAL bool dereference_option;
GLOBAL bool hard_dereference_option;
/* Print a message if not all links are dumped */
GLOBAL int check_links_option;
@@ -142,8 +144,18 @@ GLOBAL int check_links_option;
/* Patterns that match file names to be excluded. */
GLOBAL struct exclude *excluded;
/* Exclude directories containing a cache directory tag. */
GLOBAL bool exclude_caches_option;
enum exclusion_tag_type
{
exclusion_tag_none,
/* Exclude the directory contents, but preserve the directory
itself and the exclusion tag file */
exclusion_tag_contents,
/* Exclude everything below the directory, preserving the directory
itself */
exclusion_tag_under,
/* Exclude entire directory */
exclusion_tag_all,
};
/* Specified value to be put into tar file in place of stat () results, or
just -1 if such an override should not take place. */
@@ -176,6 +188,8 @@ GLOBAL enum old_files old_files_option;
/* Specified file name for incremental list. */
GLOBAL const char *listed_incremental_option;
/* Check device numbers when doing incremental dumps. */
GLOBAL bool check_device_option;
/* Specified mode change string. */
GLOBAL struct mode_change *mode_option;
@@ -189,6 +203,11 @@ GLOBAL bool multi_volume_option;
do not get archived (also see after_date_option above). */
GLOBAL struct timespec newer_mtime_option;
/* If true, override actual mtime (see below) */
GLOBAL bool set_mtime_option;
/* Value to be put in mtime header field instead of the actual mtime */
GLOBAL struct timespec mtime_option;
/* Return true if newer_mtime_option is initialized. */
#define NEWER_OPTION_INITIALIZED(opt) (0 <= (opt).tv_nsec)
@@ -239,6 +258,8 @@ GLOBAL size_t strip_name_components;
GLOBAL bool show_omitted_dirs_option;
GLOBAL bool sparse_option;
GLOBAL unsigned tar_sparse_major;
GLOBAL unsigned tar_sparse_minor;
GLOBAL bool starting_file_option;
@@ -281,16 +302,20 @@ GLOBAL int archive;
/* Nonzero when outputting to /dev/null. */
GLOBAL bool dev_null_output;
/* Timestamp for when we started execution. */
GLOBAL struct timespec start_time;
/* Timestamps: */
GLOBAL struct timespec start_time; /* when we started execution */
GLOBAL struct timespec volume_start_time; /* when the current volume was
opened*/
GLOBAL struct timespec last_stat_time; /* when the statistics was last
computed */
GLOBAL struct tar_stat_info current_stat_info;
/* List of tape drive names, number of such tape drives, allocated number,
and current cursor in list. */
GLOBAL const char **archive_name_array;
GLOBAL int archive_names;
GLOBAL int allocated_archive_names;
GLOBAL size_t archive_names;
GLOBAL size_t allocated_archive_names;
GLOBAL const char **archive_name_cursor;
/* Output index file name. */
@@ -299,16 +324,15 @@ GLOBAL char const *index_file_name;
/* Structure for keeping track of filenames and lists thereof. */
struct name
{
struct name *next;
size_t length; /* cached strlen(name) */
struct name *next; /* Link to the next element */
int change_dir; /* Number of the directory to change to.
Set with the -C option. */
uintmax_t found_count; /* number of times a matching file has
been found */
int explicit; /* was explicitely given in the command line */
char firstch; /* first char is literally matched */
char regexp; /* this name is a regexp, not literal */
int change_dir; /* set with the -C option */
int matching_flags; /* this name is a regexp, not literal */
char const *dir_contents; /* for incremental_option */
char fake; /* dummy entry */
size_t length; /* cached strlen(name) */
char name[1];
};
@@ -325,9 +349,10 @@ GLOBAL bool unquote_option;
GLOBAL bool test_label_option; /* Test archive volume label and exit */
/* When creating archive in verbose mode, list member names as stored in the
archive */
GLOBAL bool show_stored_names_option;
/* Show file or archive names after transformation.
In particular, when creating archive in verbose mode, list member names
as stored in the archive */
GLOBAL bool show_transformed_names_option;
/* Delay setting modification times and permissions of extracted directories
until the end of extraction. This variable helps correctly restore directory
@@ -335,6 +360,9 @@ GLOBAL bool show_stored_names_option;
set for incremental archives. */
GLOBAL bool delay_directory_restore_option;
/* Warn about implicit use of the wildcards in command line arguments.
(Default for tar prior to 1.15.91, but changed afterwards */
GLOBAL bool warn_regex_usage;
/* Declarations for each module. */
@@ -358,22 +386,23 @@ extern char *continued_file_name;
extern uintmax_t continued_file_size;
extern uintmax_t continued_file_offset;
size_t available_space_after (union block *);
size_t available_space_after (union block *pointer);
off_t current_block_ordinal (void);
void close_archive (void);
void closeout_volume_number (void);
void compute_duration (void);
union block *find_next_block (void);
void flush_read (void);
void flush_write (void);
void flush_archive (void);
void init_volume_number (void);
void open_archive (enum access_mode);
void print_total_written (void);
void open_archive (enum access_mode mode);
void print_total_stats (void);
void reset_eof (void);
void set_next_block_after (union block *);
void set_next_block_after (union block *block);
void clear_read_error_count (void);
void xclose (int fd);
void archive_write_error (ssize_t) __attribute__ ((noreturn));
void archive_write_error (ssize_t status) __attribute__ ((noreturn));
void archive_read_error (void);
off_t seek_archive (off_t size);
void set_start_time (void);
@@ -383,6 +412,7 @@ void mv_end (void);
void mv_total_size (off_t size);
void mv_size_left (off_t size);
void buffer_write_global_xheader (void);
/* Module create.c. */
@@ -394,19 +424,28 @@ enum dump_status
dump_status_not_implemented
};
bool file_dumpable_p (struct tar_stat_info *);
void add_exclusion_tag (const char *name, enum exclusion_tag_type type,
bool (*)(const char*));
bool cachedir_file_p (const char *name);
bool file_dumpable_p (struct tar_stat_info *st);
void create_archive (void);
void pad_archive (off_t size_left);
void dump_file (char *, int, dev_t);
void dump_file (const char *st, int top_level, dev_t parent_device);
union block *start_header (struct tar_stat_info *st);
void finish_header (struct tar_stat_info *, union block *, off_t);
void finish_header (struct tar_stat_info *st, union block *header,
off_t block_ordinal);
void simple_finish_header (union block *header);
union block * write_extended (bool global, struct tar_stat_info *st,
union block *old_header);
union block *start_private_header (const char *name, size_t size);
void write_eot (void);
void check_links (void);
void exclusion_tag_warning (const char *dirname, const char *tagname,
const char *message);
enum exclusion_tag_type check_exclusion_tags (char *dirname,
const char **tag_file_name);
#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
#define MAJOR_TO_CHARS(val, where) major_to_chars (val, where, sizeof (where))
#define MINOR_TO_CHARS(val, where) minor_to_chars (val, where, sizeof (where))
@@ -419,16 +458,16 @@ void check_links (void);
#define UNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
#define GNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
bool gid_to_chars (gid_t, char *, size_t);
bool major_to_chars (major_t, char *, size_t);
bool minor_to_chars (minor_t, char *, size_t);
bool mode_to_chars (mode_t, char *, size_t);
bool off_to_chars (off_t, char *, size_t);
bool size_to_chars (size_t, char *, size_t);
bool time_to_chars (time_t, char *, size_t);
bool uid_to_chars (uid_t, char *, size_t);
bool uintmax_to_chars (uintmax_t, char *, size_t);
void string_to_chars (char const *, char *, size_t);
bool gid_to_chars (gid_t gid, char *buf, size_t size);
bool major_to_chars (major_t m, char *buf, size_t size);
bool minor_to_chars (minor_t m, char *buf, size_t size);
bool mode_to_chars (mode_t m, char *buf, size_t size);
bool off_to_chars (off_t off, char *buf, size_t size);
bool size_to_chars (size_t v, char *buf, size_t size);
bool time_to_chars (time_t t, char *buf, size_t size);
bool uid_to_chars (uid_t uid, char *buf, size_t size);
bool uintmax_to_chars (uintmax_t v, char *buf, size_t size);
void string_to_chars (char const *s, char *buf, size_t size);
/* Module diffarch.c. */
@@ -443,17 +482,29 @@ void verify_volume (void);
void extr_init (void);
void extract_archive (void);
void extract_finish (void);
bool rename_directory (char *src, char *dst);
/* Module delete.c. */
void delete_archive_members (void);
/* Module incremen.c. */
typedef struct dumpdir *dumpdir_t;
typedef struct dumpdir_iter *dumpdir_iter_t;
char *get_directory_contents (char *, dev_t);
dumpdir_t dumpdir_create0 (const char *contents, const char *cmask);
dumpdir_t dumpdir_create (const char *contents);
void dumpdir_free (dumpdir_t);
char *dumpdir_locate (dumpdir_t dump, const char *name);
char *dumpdir_next (dumpdir_iter_t itr);
char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
const char *get_directory_contents (char *dir_name, dev_t device);
const char *append_incremental_renames (const char *dump);
void read_directory_file (void);
void write_directory_file (void);
void purge_directory (char const *);
void purge_directory (char const *directory_name);
void list_dumpdir (char *buffer, size_t size);
void update_parent_directory (const char *name);
@@ -472,22 +523,14 @@ enum read_header
HEADER_FAILURE /* ill-formed header, or bad checksum */
};
struct xheader
{
struct obstack *stk;
size_t size;
char *buffer;
};
GLOBAL struct xheader extended_header;
extern union block *current_header;
extern enum archive_format current_format;
extern size_t recent_long_name_blocks;
extern size_t recent_long_link_blocks;
void decode_header (union block *, struct tar_stat_info *,
enum archive_format *, int);
char const *tartime (struct timespec, bool);
void decode_header (union block *header, struct tar_stat_info *stat_info,
enum archive_format *format_pointer, int do_user_group);
char const *tartime (struct timespec t, bool full_time);
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
@@ -499,43 +542,39 @@ char const *tartime (struct timespec, bool);
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
#define UINTMAX_FROM_HEADER(where) uintmax_from_header (where, sizeof (where))
gid_t gid_from_header (const char *, size_t);
major_t major_from_header (const char *, size_t);
minor_t minor_from_header (const char *, size_t);
mode_t mode_from_header (const char *, size_t);
off_t off_from_header (const char *, size_t);
size_t size_from_header (const char *, size_t);
time_t time_from_header (const char *, size_t);
uid_t uid_from_header (const char *, size_t);
uintmax_t uintmax_from_header (const char *, size_t);
gid_t gid_from_header (const char *buf, size_t size);
major_t major_from_header (const char *buf, size_t size);
minor_t minor_from_header (const char *buf, size_t size);
mode_t mode_from_header (const char *buf, size_t size);
off_t off_from_header (const char *buf, size_t size);
size_t size_from_header (const char *buf, size_t size);
time_t time_from_header (const char *buf, size_t size);
uid_t uid_from_header (const char *buf, size_t size);
uintmax_t uintmax_from_header (const char * buf, size_t size);
void list_archive (void);
void print_for_mkdir (char *, int, mode_t);
void print_header (struct tar_stat_info *, off_t);
void read_and (void (*) (void));
enum read_header read_header (bool);
void print_for_mkdir (char *dirname, int length, mode_t mode);
void print_header (struct tar_stat_info *st, off_t block_ordinal);
void read_and (void (*do_something) (void));
enum read_header read_header_primitive (bool raw_extended_headers,
struct tar_stat_info *info);
enum read_header read_header (bool raw_extended_headers);
enum read_header tar_checksum (union block *header, bool silent);
void skip_file (off_t);
void skip_file (off_t size);
void skip_member (void);
/* Module mangle.c. */
void extract_mangle (void);
/* Module misc.c. */
void assign_string (char **, const char *);
char *quote_copy_string (const char *);
int unquote_string (char *);
void assign_string (char **dest, const char *src);
char *quote_copy_string (const char *str);
int unquote_string (char *str);
void code_ns_fraction (int, char *);
char const *code_timespec (struct timespec, char *);
void code_ns_fraction (int ns, char *p);
char const *code_timespec (struct timespec ts, char *sbuf);
enum { BILLION = 1000000000, LOG10_BILLION = 9 };
enum { TIMESPEC_STRSIZE_BOUND =
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
size_t dot_dot_prefix_len (char const *);
enum remove_option
{
ORDINARY_REMOVE_OPTION,
@@ -550,31 +589,31 @@ enum remove_option
meta-info to the incremental dumps, this should become unnecessary */
WANT_DIRECTORY_REMOVE_OPTION
};
int remove_any_file (const char *, enum remove_option);
bool maybe_backup_file (const char *, int);
int remove_any_file (const char *file_name, enum remove_option option);
bool maybe_backup_file (const char *file_name, bool this_is_the_archive);
void undo_last_backup (void);
int deref_stat (bool, char const *, struct stat *);
int deref_stat (bool deref, char const *name, struct stat *buf);
int chdir_arg (char const *);
void chdir_do (int);
int chdir_arg (char const *dir);
void chdir_do (int dir);
void close_diag (char const *name);
void open_diag (char const *name);
void read_diag_details (char const *name, off_t offset, size_t size);
void readlink_diag (char const *name);
void savedir_diag (char const *name);
void seek_diag_details (char const *, off_t);
void seek_diag_details (char const *name, off_t offset);
void stat_diag (char const *name);
void write_error_details (char const *, size_t, size_t);
void write_fatal (char const *) __attribute__ ((noreturn));
void write_fatal_details (char const *, ssize_t, size_t)
void write_error_details (char const *name, size_t status, size_t size);
void write_fatal (char const *name) __attribute__ ((noreturn));
void write_fatal_details (char const *name, ssize_t status, size_t size)
__attribute__ ((noreturn));
pid_t xfork (void);
void xpipe (int[2]);
void xpipe (int fd[2]);
void *page_aligned_alloc (void **, size_t);
void *page_aligned_alloc (void **ptr, size_t size);
int set_file_atime (int fd, char const *file,
struct timespec const timespec[2]);
@@ -582,35 +621,35 @@ int set_file_atime (int fd, char const *file,
extern struct name *gnu_list_name;
void gid_to_gname (gid_t, char **gname);
int gname_to_gid (char const *, gid_t *);
void uid_to_uname (uid_t, char **uname);
int uname_to_uid (char const *, uid_t *);
void gid_to_gname (gid_t gid, char **gname);
int gname_to_gid (char const *gname, gid_t *pgid);
void uid_to_uname (uid_t uid, char **uname);
int uname_to_uid (char const *uname, uid_t *puid);
void init_names (void);
void name_add (const char *);
void name_init (void);
void name_add_name (const char *name, int matching_flags);
void name_add_dir (const char *name);
void name_term (void);
char *name_next (int);
const char *name_next (int change_dirs);
void name_gather (void);
struct name *addname (char const *, int);
int name_match (const char *);
struct name *addname (char const *string, int change_dir);
bool name_match (const char *name);
void names_notfound (void);
void collect_and_sort_names (void);
struct name *name_scan (const char *, bool);
struct name *name_scan (const char *name);
char *name_from_list (void);
void blank_name_list (void);
char *new_name (const char *, const char *);
char *new_name (const char *dir_name, const char *name);
size_t stripped_prefix_len (char const *file_name, size_t num);
bool all_names_found (struct tar_stat_info *);
bool all_names_found (struct tar_stat_info *st);
bool excluded_name (char const *);
bool excluded_name (char const *name);
void add_avoided_name (char const *);
bool is_avoided_name (char const *);
bool is_individual_file (char const *);
void add_avoided_name (char const *name);
bool is_avoided_name (char const *name);
bool is_individual_file (char const *name);
bool contains_dot_dot (char const *);
bool contains_dot_dot (char const *name);
#define ISFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
(c)->found_count == occurrence_option)
@@ -621,8 +660,8 @@ bool contains_dot_dot (char const *);
void usage (int);
int confirm (const char *, const char *);
void request_stdin (const char *);
int confirm (const char *message_action, const char *name);
void request_stdin (const char *option);
void tar_stat_init (struct tar_stat_info *st);
void tar_stat_destroy (struct tar_stat_info *st);
@@ -639,22 +678,22 @@ void update_archive (void);
/* Module xheader.c. */
void xheader_decode (struct tar_stat_info *);
void xheader_decode_global (void);
void xheader_store (char const *, struct tar_stat_info const *, void const *);
void xheader_read (union block *, size_t);
void xheader_init (struct xheader *xhdr);
void xheader_decode (struct tar_stat_info *stat);
void xheader_decode_global (struct xheader *xhdr);
void xheader_store (char const *keyword, struct tar_stat_info *st,
void const *data);
void xheader_read (struct xheader *xhdr, union block *header, size_t size);
void xheader_write (char type, char *name, struct xheader *xhdr);
void xheader_write_global (void);
void xheader_finish (struct xheader *);
void xheader_destroy (struct xheader *);
void xheader_write_global (struct xheader *xhdr);
void xheader_finish (struct xheader *hdr);
void xheader_destroy (struct xheader *hdr);
char *xheader_xhdr_name (struct tar_stat_info *st);
char *xheader_ghdr_name (void);
void xheader_write (char, char *, struct xheader *);
void xheader_write_global (void);
void xheader_set_option (char *string);
void xheader_string_begin (void);
void xheader_string_add (char const *s);
void xheader_string_end (char const *keyword);
void xheader_string_begin (struct xheader *xhdr);
void xheader_string_add (struct xheader *xhdr, char const *s);
bool xheader_string_end (struct xheader *xhdr, char const *keyword);
bool xheader_keyword_deleted_p (const char *kw);
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
size_t n);
@@ -678,19 +717,43 @@ bool sys_get_archive_stat (void);
int sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st);
void sys_wait_command (void);
int sys_exec_info_script (const char **archive_name, int volume_number);
void sys_exec_checkpoint_script (const char *script_name,
const char *archive_name,
int checkpoint_number);
/* Module compare.c */
void report_difference (struct tar_stat_info *st, const char *message, ...);
/* Module sparse.c */
bool sparse_file_p (struct tar_stat_info *);
bool sparse_member_p (struct tar_stat_info *);
bool sparse_fixup_header (struct tar_stat_info *);
enum dump_status sparse_dump_file (int, struct tar_stat_info *);
enum dump_status sparse_extract_file (int, struct tar_stat_info *, off_t *);
enum dump_status sparse_skip_file (struct tar_stat_info *);
bool sparse_diff_file (int, struct tar_stat_info *);
bool sparse_member_p (struct tar_stat_info *st);
bool sparse_fixup_header (struct tar_stat_info *st);
enum dump_status sparse_dump_file (int, struct tar_stat_info *st);
enum dump_status sparse_extract_file (int fd, struct tar_stat_info *st,
off_t *size);
enum dump_status sparse_skip_file (struct tar_stat_info *st);
bool sparse_diff_file (int, struct tar_stat_info *st);
/* Module utf8.c */
bool string_ascii_p (const char *str);
bool utf8_convert (bool to_utf, char const *input, char **output);
/* Module transform.c */
typedef enum
{
xform_regfile,
xform_link,
xform_symlink
} xform_type;
void set_transform_expr (const char *expr);
bool transform_name (char **pinput);
bool transform_member_name (char **pinput, xform_type type);
bool transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *);
/* Module suffix.c */
void set_comression_program_by_suffix (const char *name, const char *defprog);
/* Module checkpoint.c */
void checkpoint_compile_action (const char *str);
void checkpoint_finish_compile (void);
void checkpoint_run (bool do_write);

View File

@@ -1,13 +1,13 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by John Gilmore, on 1987-04-30.
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 2, or (at your option) any later
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
@@ -53,14 +53,13 @@ diff_init (void)
/* Sigh about something that differs by writing a MESSAGE to stdlis,
given MESSAGE is nonzero. Also set the exit status if not already. */
void
report_difference (struct tar_stat_info *st __attribute__ ((unused)),
const char *fmt, ...)
report_difference (struct tar_stat_info *st, const char *fmt, ...)
{
if (fmt)
{
va_list ap;
fprintf (stdlis, "%s: ", quotearg_colon (current_stat_info.file_name));
fprintf (stdlis, "%s: ", quotearg_colon (st->file_name));
va_start (ap, fmt);
vfprintf (stdlis, fmt, ap);
va_end (ap);
@@ -111,27 +110,10 @@ process_rawdata (size_t bytes, char *buffer)
return 1;
}
/* Directory contents, only for GNUTYPE_DUMPDIR. */
static char *dumpdir_cursor;
static int
process_dumpdir (size_t bytes, char *buffer)
{
if (memcmp (buffer, dumpdir_cursor, bytes))
{
report_difference (&current_stat_info, _("Contents differ"));
return 0;
}
dumpdir_cursor += bytes;
return 1;
}
/* Some other routine wants SIZE bytes in the archive. For each chunk
of the archive, call PROCESSOR with the size of the chunk, and the
address of the chunk it can work with. The PROCESSOR should return
nonzero for success. It it return error once, continue skipping
nonzero for success. Once it returns error, continue skipping
without calling PROCESSOR anymore. */
static void
@@ -139,7 +121,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
{
union block *data_block;
size_t data_size;
size_t size = st->stat.st_size;
off_t size = st->stat.st_size;
mv_begin (st);
while (size)
@@ -346,14 +328,49 @@ diff_special (void)
report_difference (&current_stat_info, _("Mode differs"));
}
static int
dumpdir_cmp (const char *a, const char *b)
{
size_t len;
while (*a)
switch (*a)
{
case 'Y':
case 'N':
if (!strchr ("YN", *b))
return 1;
if (strcmp(a + 1, b + 1))
return 1;
len = strlen (a) + 1;
a += len;
b += len;
break;
case 'D':
if (strcmp(a, b))
return 1;
len = strlen (a) + 1;
a += len;
b += len;
break;
case 'R':
case 'T':
case 'X':
return *b;
}
return *b;
}
static void
diff_dumpdir (void)
{
char *dumpdir_buffer;
const char *dumpdir_buffer;
dev_t dev = 0;
struct stat stat;
struct stat stat_data;
if (deref_stat (true, current_stat_info.file_name, &stat))
if (deref_stat (true, current_stat_info.file_name, &stat_data))
{
if (errno == ENOENT)
stat_warn (current_stat_info.file_name);
@@ -361,15 +378,14 @@ diff_dumpdir (void)
stat_error (current_stat_info.file_name);
}
else
dev = stat.st_dev;
dev = stat_data.st_dev;
dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev);
if (dumpdir_buffer)
{
dumpdir_cursor = dumpdir_buffer;
read_and_process (&current_stat_info, process_dumpdir);
free (dumpdir_buffer);
if (dumpdir_cmp (current_stat_info.dumpdir, dumpdir_buffer))
report_difference (&current_stat_info, _("Contents differ"));
}
else
read_and_process (&current_stat_info, process_noop);
@@ -485,10 +501,9 @@ diff_archive (void)
break;
case GNUTYPE_DUMPDIR:
diff_dumpdir ();
/* Fall through. */
case DIRTYPE:
if (is_dumpdir (&current_stat_info))
diff_dumpdir ();
diff_dir ();
break;
@@ -582,12 +597,25 @@ verify_volume (void)
"VERIFY FAILURE: %d invalid headers detected",
counter), counter));
}
if (status == HEADER_ZERO_BLOCK || status == HEADER_END_OF_FILE)
if (status == HEADER_END_OF_FILE)
break;
if (status == HEADER_ZERO_BLOCK)
{
set_next_block_after (current_header);
if (!ignore_zeros_option)
{
char buf[UINTMAX_STRSIZE_BOUND];
status = read_header (false);
if (status == HEADER_ZERO_BLOCK)
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
}
}
diff_archive ();
tar_stat_destroy (&current_stat_info);
xheader_destroy (&extended_header);
}
access_mode = ACCESS_WRITE;

View File

@@ -1,13 +1,13 @@
/* Create a tar archive.
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
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 2, or (at your option) any later
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
@@ -33,6 +33,111 @@ struct link
size_t nlink;
char name[1];
};
struct exclusion_tag
{
const char *name;
size_t length;
enum exclusion_tag_type type;
bool (*predicate) (const char *name);
struct exclusion_tag *next;
};
static struct exclusion_tag *exclusion_tags;
void
add_exclusion_tag (const char *name, enum exclusion_tag_type type,
bool (*predicate) (const char *name))
{
struct exclusion_tag *tag = xmalloc (sizeof tag[0]);
tag->next = exclusion_tags;
tag->name = name;
tag->type = type;
tag->predicate = predicate;
tag->length = strlen (name);
exclusion_tags = tag;
}
void
exclusion_tag_warning (const char *dirname, const char *tagname,
const char *message)
{
if (verbose_option)
WARN ((0, 0,
_("%s: contains a cache directory tag %s; %s"),
quotearg_colon (dirname),
quotearg_n (1, tagname),
message));
}
enum exclusion_tag_type
check_exclusion_tags (char *dirname, const char **tag_file_name)
{
static char *tagname;
static size_t tagsize;
struct exclusion_tag *tag;
size_t dlen = strlen (dirname);
int addslash = dirname[dlen-1] != '/';
char *nptr = NULL;
for (tag = exclusion_tags; tag; tag = tag->next)
{
size_t size = dlen + addslash + tag->length + 1;
if (size > tagsize)
{
tagsize = size;
tagname = xrealloc (tagname, tagsize);
}
if (!nptr)
{
strcpy (tagname, dirname);
nptr = tagname + dlen;
if (addslash)
*nptr++ = '/';
}
strcpy (nptr, tag->name);
if (access (tagname, F_OK) == 0
&& (!tag->predicate || tag->predicate (tagname)))
{
if (tag_file_name)
*tag_file_name = tag->name;
return tag->type;
}
}
return exclusion_tag_none;
}
/* Exclusion predicate to test if the named file (usually "CACHEDIR.TAG")
contains a valid header, as described at:
http://www.brynosaurus.com/cachedir
Applications can write this file into directories they create
for use as caches containing purely regenerable, non-precious data,
allowing us to avoid archiving them if --exclude-caches is specified. */
#define CACHEDIR_SIGNATURE "Signature: 8a477f597d28d172789f06886806bc55"
#define CACHEDIR_SIGNATURE_SIZE (sizeof CACHEDIR_SIGNATURE - 1)
bool
cachedir_file_p (const char *name)
{
bool tag_present = false;
int fd = open (name, O_RDONLY);
if (fd >= 0)
{
static char tagbuf[CACHEDIR_SIGNATURE_SIZE];
if (read (fd, tagbuf, CACHEDIR_SIGNATURE_SIZE)
== CACHEDIR_SIGNATURE_SIZE
&& memcmp (tagbuf, CACHEDIR_SIGNATURE, CACHEDIR_SIGNATURE_SIZE) == 0)
tag_present = true;
close (fd);
}
return tag_present;
}
/* The maximum uintmax_t value that can be represented with DIGITS digits,
assuming that each digit is BITS_PER_DIGIT wide. */
@@ -128,7 +233,7 @@ to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
char const *minval_string;
char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
char const *value_string;
if (gnu_format)
{
uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
@@ -138,7 +243,7 @@ to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
}
else
minval_string = "0";
if (negative)
{
char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
@@ -147,13 +252,18 @@ to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
}
else
value_string = STRINGIFY_BIGINT (value, valbuf);
if (substitute)
{
int negsub;
uintmax_t sub = substitute (&negsub) & maxval;
/* FIXME: This is the only place where GNU_FORMAT differs from
OLDGNU_FORMAT. Apart from this they are completely identical. */
/* NOTE: This is one of the few places where GNU_FORMAT differs from
OLDGNU_FORMAT. The actual differences are:
1. In OLDGNU_FORMAT all strings in a tar header end in \0
2. Incremental archives use oldgnu_header.
Apart from this they are completely identical. */
uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
char subbuf[UINTMAX_STRSIZE_BOUND + 1];
char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
@@ -236,7 +346,7 @@ to_chars (int negative, uintmax_t value, size_t valsize,
}
else
substitute = NULL; /* No substitution for formats, other than GNU */
return to_chars_subst (negative, gnu_format, value, valsize, substitute,
where, size, type);
}
@@ -291,7 +401,8 @@ mode_to_chars (mode_t v, char *p, size_t s)
&& S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
&& archive_format != POSIX_FORMAT
&& archive_format != USTAR_FORMAT
&& archive_format != GNU_FORMAT)
&& archive_format != GNU_FORMAT
&& archive_format != OLDGNU_FORMAT)
{
negative = v < 0;
u = v;
@@ -380,7 +491,7 @@ bool
file_dumpable_p (struct tar_stat_info *st)
{
if (dev_null_output)
return totals_option && sparse_option && sparse_file_p (st);
return totals_option && sparse_option && ST_IS_SPARSE (st->stat);
return !(st->archive_file_size == 0
&& (st->stat.st_mode & MODE_R) == MODE_R);
}
@@ -602,10 +713,10 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
char *p;
int type;
if (extended_header.buffer || extended_header.stk == NULL)
if (st->xhdr.buffer || st->xhdr.stk == NULL)
return old_header;
xheader_finish (&extended_header);
xheader_finish (&st->xhdr);
memcpy (hp.buffer, old_header, sizeof (hp));
if (global)
{
@@ -617,7 +728,7 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
type = XHDTYPE;
p = xheader_xhdr_name (st);
}
xheader_write (type, p, &extended_header);
xheader_write (type, p, &st->xhdr);
free (p);
header = find_next_block ();
memcpy (header, &hp.buffer, sizeof (hp.buffer));
@@ -663,7 +774,8 @@ start_header (struct tar_stat_info *st)
if (mode_option)
st->stat.st_mode =
((st->stat.st_mode & ~MODE_ALL)
| mode_adjust (st->stat.st_mode, mode_option, initial_umask));
| mode_adjust (st->stat.st_mode, S_ISDIR (st->stat.st_mode) != 0,
initial_umask, mode_option, NULL));
/* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
for a few tars and came up with the following interoperability
@@ -730,12 +842,12 @@ start_header (struct tar_stat_info *st)
}
{
struct timespec mtime = st->mtime;
struct timespec mtime = set_mtime_option ? mtime_option : st->mtime;
if (archive_format == POSIX_FORMAT)
{
if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec
|| mtime.tv_nsec != 0)
xheader_store ("mtime", st, NULL);
xheader_store ("mtime", st, &mtime);
if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec)
mtime.tv_sec = 0;
}
@@ -954,8 +1066,7 @@ dump_regular_file (int fd, struct tar_stat_info *st)
return dump_status_short;
}
size_left -= count;
if (count)
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
if (count != bufsize)
{
@@ -967,62 +1078,23 @@ dump_regular_file (int fd, struct tar_stat_info *st)
size_left),
quotearg_colon (st->orig_file_name),
STRINGIFY_BIGINT (size_left, buf)));
if (! ignore_failed_read_option)
exit_status = TAREXIT_FAILURE;
pad_archive (size_left - (bufsize-count));
if (! ignore_failed_read_option)
exit_status = TAREXIT_DIFFERS;
pad_archive (size_left - (bufsize - count));
return dump_status_short;
}
}
return dump_status_ok;
}
/* Look in directory DIRNAME for a cache directory tag file
with the magic name "CACHEDIR.TAG" and a standard header,
as described at:
http://www.brynosaurus.com/cachedir
Applications can write this file into directories they create
for use as caches containing purely regenerable, non-precious data,
allowing us to avoid archiving them if --exclude-caches is specified. */
#define CACHEDIR_SIGNATURE "Signature: 8a477f597d28d172789f06886806bc55"
#define CACHEDIR_SIGNATURE_SIZE (sizeof CACHEDIR_SIGNATURE - 1)
static bool
check_cache_directory (char *dirname)
{
static char tagname[] = "CACHEDIR.TAG";
char *tagpath;
int fd;
int tag_present = false;
tagpath = xmalloc (strlen (dirname) + strlen (tagname) + 1);
strcpy (tagpath, dirname);
strcat (tagpath, tagname);
fd = open (tagpath, O_RDONLY);
if (fd >= 0)
{
static char tagbuf[CACHEDIR_SIGNATURE_SIZE];
if (read (fd, tagbuf, CACHEDIR_SIGNATURE_SIZE)
== CACHEDIR_SIGNATURE_SIZE
&& memcmp (tagbuf, CACHEDIR_SIGNATURE, CACHEDIR_SIGNATURE_SIZE) == 0)
tag_present = true;
close (fd);
}
free (tagpath);
return tag_present;
}
static void
dump_dir0 (char *directory,
struct tar_stat_info *st, int top_level, dev_t parent_device)
{
dev_t our_device = st->stat.st_dev;
const char *tag_file_name;
if (!is_avoided_name (st->orig_file_name))
{
union block *blk = NULL;
@@ -1104,44 +1176,63 @@ dump_dir0 (char *directory,
WARN ((0, 0,
_("%s: file is on a different filesystem; not dumped"),
quotearg_colon (st->orig_file_name)));
return;
}
if (exclude_caches_option
&& check_cache_directory(st->orig_file_name))
else
{
if (verbose_option)
WARN ((0, 0,
_("%s: contains a cache directory tag; not dumped"),
quotearg_colon (st->orig_file_name)));
return;
}
{
char const *entry;
size_t entry_len;
char *name_buf = xstrdup (st->orig_file_name);
size_t name_size = strlen (name_buf);
size_t name_len = name_size;
/* Now output all the files in the directory. */
/* FIXME: Should speed this up by cd-ing into the dir. */
for (entry = directory; (entry_len = strlen (entry)) != 0;
entry += entry_len + 1)
{
if (name_size < name_len + entry_len)
char *name_buf;
size_t name_size;
switch (check_exclusion_tags (st->orig_file_name, &tag_file_name))
{
case exclusion_tag_all:
/* Handled in dump_file0 */
break;
case exclusion_tag_none:
{
name_size = name_len + entry_len;
name_buf = xrealloc (name_buf, name_size + 1);
}
strcpy (name_buf + name_len, entry);
if (!excluded_name (name_buf))
dump_file (name_buf, 0, our_device);
}
char const *entry;
size_t entry_len;
size_t name_len;
free (name_buf);
}
name_buf = xstrdup (st->orig_file_name);
name_size = name_len = strlen (name_buf);
/* Now output all the files in the directory. */
/* FIXME: Should speed this up by cd-ing into the dir. */
for (entry = directory; (entry_len = strlen (entry)) != 0;
entry += entry_len + 1)
{
if (name_size < name_len + entry_len)
{
name_size = name_len + entry_len;
name_buf = xrealloc (name_buf, name_size + 1);
}
strcpy (name_buf + name_len, entry);
if (!excluded_name (name_buf))
dump_file (name_buf, 0, our_device);
}
free (name_buf);
}
break;
case exclusion_tag_contents:
exclusion_tag_warning (st->orig_file_name, tag_file_name,
_("contents not dumped"));
name_size = strlen (st->orig_file_name) + strlen (tag_file_name) + 1;
name_buf = xmalloc (name_size);
strcpy (name_buf, st->orig_file_name);
strcat (name_buf, tag_file_name);
dump_file (name_buf, 0, our_device);
free (name_buf);
break;
case exclusion_tag_under:
exclusion_tag_warning (st->orig_file_name, tag_file_name,
_("contents not dumped"));
break;
}
}
}
/* Ensure exactly one trailing slash. */
@@ -1167,9 +1258,6 @@ dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
return false;
}
ensure_slash (&st->orig_file_name);
ensure_slash (&st->file_name);
dump_dir0 (directory, st, top_level, parent_device);
free (directory);
@@ -1182,10 +1270,10 @@ dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
void
create_archive (void)
{
char *p;
const char *p;
open_archive (ACCESS_WRITE);
xheader_write_global ();
buffer_write_global_xheader ();
if (incremental_option)
{
@@ -1334,6 +1422,8 @@ dump_hard_link (struct tar_stat_info *st)
static void
file_count_links (struct tar_stat_info *st)
{
if (hard_dereference_option)
return;
if (st->stat.st_nlink > 1)
{
struct link *duplicate;
@@ -1387,11 +1477,12 @@ check_links (void)
exit_status to failure, a clear diagnostic has been issued. */
static void
dump_file0 (struct tar_stat_info *st, char const *p,
dump_file0 (struct tar_stat_info *st, const char *p,
int top_level, dev_t parent_device)
{
union block *header;
char type;
off_t original_size;
struct timespec original_ctime;
struct timespec restore_times[2];
off_t block_ordinal = -1;
@@ -1404,12 +1495,14 @@ dump_file0 (struct tar_stat_info *st, char const *p,
assign_string (&st->file_name,
safer_name_suffix (p, false, absolute_names_option));
transform_name (&st->file_name);
if (deref_stat (dereference_option, p, &st->stat) != 0)
{
stat_diag (p);
return;
}
st->archive_file_size = st->stat.st_size;
st->archive_file_size = original_size = st->stat.st_size;
st->atime = restore_times[0] = get_stat_atime (&st->stat);
st->mtime = restore_times[1] = get_stat_mtime (&st->stat);
st->ctime = original_ctime = get_stat_ctime (&st->stat);
@@ -1487,6 +1580,18 @@ dump_file0 (struct tar_stat_info *st, char const *p,
if (is_dir)
{
const char *tag_file_name;
ensure_slash (&st->orig_file_name);
ensure_slash (&st->file_name);
if (check_exclusion_tags (st->orig_file_name, &tag_file_name)
== exclusion_tag_all)
{
exclusion_tag_warning (st->orig_file_name, tag_file_name,
_("directory not dumped"));
return;
}
ok = dump_dir (fd, st, top_level, parent_device);
/* dump_dir consumes FD if successful. */
@@ -1497,7 +1602,7 @@ dump_file0 (struct tar_stat_info *st, char const *p,
{
enum dump_status status;
if (fd != -1 && sparse_option && sparse_file_p (st))
if (fd != -1 && sparse_option && ST_IS_SPARSE (st->stat))
{
status = sparse_dump_file (fd, st);
if (status == dump_status_not_implemented)
@@ -1511,6 +1616,7 @@ dump_file0 (struct tar_stat_info *st, char const *p,
case dump_status_ok:
case dump_status_short:
mv_end ();
file_count_links (st);
break;
case dump_status_fail:
@@ -1520,8 +1626,6 @@ dump_file0 (struct tar_stat_info *st, char const *p,
abort ();
}
file_count_links (st);
ok = status == dump_status_ok;
}
@@ -1546,9 +1650,17 @@ dump_file0 (struct tar_stat_info *st, char const *p,
if (ok)
{
if (timespec_cmp (get_stat_ctime (&final_stat), original_ctime) != 0)
WARN ((0, 0, _("%s: file changed as we read it"),
quotearg_colon (p)));
if ((timespec_cmp (get_stat_ctime (&final_stat), original_ctime) != 0
/* Original ctime will change if the file is a directory and
--remove-files is given */
&& !(remove_files_option && is_dir))
|| original_size < final_stat.st_size)
{
WARN ((0, 0, _("%s: file changed as we read it"),
quotearg_colon (p)));
if (exit_status == TAREXIT_SUCCESS)
exit_status = TAREXIT_DIFFERS;
}
else if (atime_preserve_option == replace_atime_preserve
&& set_file_atime (fd, p, restore_times) != 0)
utime_error (p);
@@ -1593,6 +1705,7 @@ dump_file0 (struct tar_stat_info *st, char const *p,
}
buffer[size] = '\0';
assign_string (&st->link_name, buffer);
transform_name (&st->link_name);
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
write_long_link (st);
@@ -1601,7 +1714,7 @@ dump_file0 (struct tar_stat_info *st, char const *p,
header = start_header (st);
if (!header)
return;
tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE);
tar_copy_str (header->header.linkname, st->link_name, NAME_FIELD_SIZE);
header->header.typeflag = SYMTYPE;
finish_header (st, header, block_ordinal);
/* nothing more to do to it */
@@ -1667,7 +1780,7 @@ dump_file0 (struct tar_stat_info *st, char const *p,
}
void
dump_file (char *p, int top_level, dev_t parent_device)
dump_file (const char *p, int top_level, dev_t parent_device)
{
struct tar_stat_info st;
tar_stat_init (&st);

View File

@@ -5,7 +5,7 @@
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 2, or (at your option) any later
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
@@ -39,7 +39,7 @@ extern off_t records_written;
/* The number of records skipped at the start of the archive, when
passing over members that are not deleted. */
static off_t records_skipped;
off_t records_skipped;
/* Move archive descriptor by COUNT records worth. If COUNT is
positive we move forward, else we move negative. If it's a tape,
@@ -174,7 +174,7 @@ delete_archive_members (void)
abort ();
case HEADER_SUCCESS:
if ((name = name_scan (current_stat_info.file_name, false)) == NULL)
if ((name = name_scan (current_stat_info.file_name)) == NULL)
{
skip_member ();
break;
@@ -285,7 +285,7 @@ delete_archive_members (void)
/* Found another header. */
if ((name = name_scan (current_stat_info.file_name, false)) != NULL)
if ((name = name_scan (current_stat_info.file_name)) != NULL)
{
name->found_count++;
if (ISFOUND(name))
@@ -294,7 +294,7 @@ delete_archive_members (void)
set_next_block_after (current_header);
blocks_to_skip = (current_stat_info.stat.st_size
+ BLOCKSIZE - 1) / BLOCKSIZE;
while (record_end - current_block <= blocks_to_skip)
{
blocks_to_skip -= (record_end - current_block);
@@ -307,10 +307,10 @@ delete_archive_members (void)
}
/* Copy header. */
if (extended_header.size)
if (current_stat_info.xhdr.size)
{
write_recent_bytes (extended_header.buffer,
extended_header.size);
write_recent_bytes (current_stat_info.xhdr.buffer,
current_stat_info.xhdr.size);
}
else
{

View File

@@ -1,13 +1,13 @@
/* Extract files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-11-19.
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 2, or (at your option) any later
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
@@ -37,7 +37,8 @@ enum permstatus
/* This file may have existed already; its permissions are unknown. */
UNKNOWN_PERMSTATUS,
/* This file was created using the permissions from the archive. */
/* This file was created using the permissions from the archive,
except with S_IRWXG | S_IRWXO masked out if 0 < same_owner_option. */
ARCHIVED_PERMSTATUS,
/* This is an intermediate directory; the archive did not specify
@@ -149,12 +150,15 @@ set_mode (char const *file_name,
{
mode = stat_info->st_mode;
/* If we created the file and it has a usual mode, then its mode
is normally set correctly already. But on many hosts, some
/* If we created the file and it has a mode that we set already
with O_CREAT, then its mode is often set correctly already.
But if we are changing ownership, the mode's group and and
other permission bits were omitted originally, so it's less
likely that the mode is OK now. Also, on many hosts, some
directories inherit the setgid bits from their parents, so we
we must set directories' modes explicitly. */
if (permstatus == ARCHIVED_PERMSTATUS
&& ! (mode & ~ MODE_RWX)
if ((permstatus == ARCHIVED_PERMSTATUS
&& ! (mode & ~ (0 < same_owner_option ? S_IRWXU : MODE_RWX)))
&& typeflag != DIRTYPE
&& typeflag != GNUTYPE_DUMPDIR)
return;
@@ -193,7 +197,7 @@ check_time (char const *file_name, struct timespec t)
if (t.tv_sec <= 0)
WARN ((0, 0, _("%s: implausibly old time stamp %s"),
file_name, tartime (t, true)));
else if (timespec_cmp (start_time, t) < 0)
else if (timespec_cmp (volume_start_time, t) < 0)
{
struct timespec now;
gettime (&now);
@@ -217,7 +221,7 @@ check_time (char const *file_name, struct timespec t)
/* Restore stat attributes (owner, group, mode and times) for
FILE_NAME, using information given in *ST.
If CUR_INFO is nonzero, *CUR_INFO is the
file's currernt status.
file's current status.
If not restoring permissions, invert the
INVERT_PERMISSIONS bits from the file's current permissions.
PERMSTATUS specifies the status of the file's permissions.
@@ -265,11 +269,11 @@ set_stat (char const *file_name,
}
/* Some systems allow non-root users to give files away. Once this
done, it is not possible anymore to change file permissions, so we
have to set permissions prior to possibly giving files away. */
set_mode (file_name, &st->stat, cur_info,
invert_permissions, permstatus, typeflag);
done, it is not possible anymore to change file permissions.
However, setting file permissions now would be incorrect, since
they would apply to the wrong user, and there would be a race
condition. So, don't use systems that allow non-root users to
give files away. */
}
if (0 < same_owner_option && permstatus != INTERDIR_PERMSTATUS)
@@ -278,29 +282,36 @@ set_stat (char const *file_name,
the symbolic link itself. In this case, a mere chown would change
the attributes of the file the symbolic link is pointing to, and
should be avoided. */
int chown_result = 1;
if (typeflag == SYMTYPE)
{
#if HAVE_LCHOWN
if (lchown (file_name, st->stat.st_uid, st->stat.st_gid) < 0)
chown_error_details (file_name,
st->stat.st_uid, st->stat.st_gid);
chown_result = lchown (file_name, st->stat.st_uid, st->stat.st_gid);
#endif
}
else
{
if (chown (file_name, st->stat.st_uid, st->stat.st_gid) < 0)
chown_error_details (file_name,
st->stat.st_uid, st->stat.st_gid);
/* On a few systems, and in particular, those allowing to give files
away, changing the owner or group destroys the suid or sgid bits.
So let's attempt setting these bits once more. */
if (st->stat.st_mode & (S_ISUID | S_ISGID | S_ISVTX))
set_mode (file_name, &st->stat, 0,
invert_permissions, permstatus, typeflag);
chown_result = chown (file_name, st->stat.st_uid, st->stat.st_gid);
}
if (chown_result == 0)
{
/* Changing the owner can flip st_mode bits in some cases, so
ignore cur_info if it might be obsolete now. */
if (cur_info
&& cur_info->st_mode & S_IXUGO
&& cur_info->st_mode & (S_ISUID | S_ISGID))
cur_info = NULL;
}
else if (chown_result < 0)
chown_error_details (file_name,
st->stat.st_uid, st->stat.st_gid);
}
if (typeflag != SYMTYPE)
set_mode (file_name, &st->stat, cur_info,
invert_permissions, permstatus, typeflag);
}
/* Remember to restore stat attributes (owner, group, mode and times)
@@ -374,7 +385,8 @@ repair_delayed_set_stat (char const *dir,
data->atime = current_stat_info.atime;
data->mtime = current_stat_info.mtime;
data->invert_permissions =
(MODE_RWX & (current_stat_info.stat.st_mode ^ st.st_mode));
((current_stat_info.stat.st_mode ^ st.st_mode)
& MODE_RWX & ~ current_umask);
data->permstatus = ARCHIVED_PERMSTATUS;
return;
}
@@ -392,13 +404,12 @@ static int
make_directories (char *file_name)
{
char *cursor0 = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
char *cursor; /* points into the file name */
char *cursor; /* points into the file name */
int did_something = 0; /* did we do anything yet? */
int mode;
int invert_permissions;
int status;
for (cursor = cursor0; *cursor; cursor++)
{
if (! ISSLASH (*cursor))
@@ -428,7 +439,7 @@ make_directories (char *file_name)
invert_permissions is zero, because
repair_delayed_set_stat may need to update the struct. */
delay_set_stat (file_name,
&current_stat_info /* ignored */,
&current_stat_info,
invert_permissions, INTERDIR_PERMSTATUS);
print_for_mkdir (file_name, cursor - file_name, mode);
@@ -582,13 +593,13 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
if (! skip_this_one)
{
struct tar_stat_info st;
st.stat.st_mode = data->mode;
st.stat.st_uid = data->uid;
st.stat.st_gid = data->gid;
st.atime = data->atime;
st.mtime = data->mtime;
set_stat (data->file_name, &st, cur_info,
struct tar_stat_info sb;
sb.stat.st_mode = data->mode;
sb.stat.st_uid = data->uid;
sb.stat.st_gid = data->gid;
sb.atime = data->atime;
sb.mtime = data->mtime;
set_stat (data->file_name, &sb, cur_info,
data->invert_permissions, data->permstatus, DIRTYPE);
}
@@ -627,8 +638,9 @@ extract_dir (char *file_name, int typeflag)
else if (typeflag == GNUTYPE_DUMPDIR)
skip_member ();
mode = (current_stat_info.stat.st_mode |
(we_are_root ? 0 : MODE_WXUSR)) & MODE_RWX;
mode = current_stat_info.stat.st_mode | (we_are_root ? 0 : MODE_WXUSR);
if (0 < same_owner_option || current_stat_info.stat.st_mode & ~ MODE_RWX)
mode &= S_IRWXU;
while ((status = mkdir (file_name, mode)))
{
@@ -647,7 +659,7 @@ extract_dir (char *file_name, int typeflag)
}
if (S_ISDIR (st.st_mode))
{
mode = st.st_mode & ~ current_umask;
mode = st.st_mode;
break;
}
}
@@ -668,25 +680,29 @@ extract_dir (char *file_name, int typeflag)
if (status == 0
|| old_files_option == DEFAULT_OLD_FILES
|| old_files_option == OVERWRITE_OLD_FILES)
delay_set_stat (file_name, &current_stat_info,
MODE_RWX & (mode ^ current_stat_info.stat.st_mode),
(status == 0
? ARCHIVED_PERMSTATUS
: UNKNOWN_PERMSTATUS));
{
if (status == 0)
delay_set_stat (file_name, &current_stat_info,
((mode ^ current_stat_info.stat.st_mode)
& MODE_RWX & ~ current_umask),
ARCHIVED_PERMSTATUS);
else /* For an already existing directory, invert_perms must be 0 */
delay_set_stat (file_name, &current_stat_info,
0,
UNKNOWN_PERMSTATUS);
}
return status;
}
static int
open_output_file (char *file_name, int typeflag)
open_output_file (char *file_name, int typeflag, mode_t mode)
{
int fd;
int openflag = (O_WRONLY | O_BINARY | O_CREAT
| (old_files_option == OVERWRITE_OLD_FILES
? O_TRUNC
: O_EXCL));
mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
#if O_CTG
/* Contiguous files (on the Masscomp) have to specify the size in
@@ -725,6 +741,9 @@ extract_file (char *file_name, int typeflag)
size_t count;
size_t written;
int interdir_made = 0;
mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
mode_t invert_permissions =
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
/* FIXME: deal with protection issues. */
@@ -742,11 +761,12 @@ extract_file (char *file_name, int typeflag)
else
{
do
fd = open_output_file (file_name, typeflag);
fd = open_output_file (file_name, typeflag, mode ^ invert_permissions);
while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
if (fd < 0)
{
skip_member ();
open_error (file_name);
return 1;
}
@@ -807,7 +827,7 @@ extract_file (char *file_name, int typeflag)
if (to_command_option)
sys_wait_command ();
else
set_stat (file_name, &current_stat_info, NULL, 0,
set_stat (file_name, &current_stat_info, NULL, invert_permissions,
(old_files_option == OVERWRITE_OLD_FILES ?
UNKNOWN_PERMSTATUS : ARCHIVED_PERMSTATUS),
typeflag);
@@ -868,7 +888,7 @@ create_placeholder_file (char *file_name, bool is_symlink, int *interdir_made)
if (h && ! h->after_links
&& strncmp (file_name, h->file_name, h->file_name_len) == 0
&& ISSLASH (file_name[h->file_name_len])
&& (base_name (file_name) == file_name + h->file_name_len + 1))
&& (last_component (file_name) == file_name + h->file_name_len + 1))
{
do
{
@@ -894,10 +914,12 @@ create_placeholder_file (char *file_name, bool is_symlink, int *interdir_made)
static int
extract_link (char *file_name, int typeflag)
{
char const *link_name = safer_name_suffix (current_stat_info.link_name,
true, absolute_names_option);
int interdir_made = 0;
char const *link_name;
transform_member_name (&current_stat_info.link_name, xform_link);
link_name = current_stat_info.link_name;
if (! absolute_names_option && contains_dot_dot (link_name))
return create_placeholder_file (file_name, false, &interdir_made);
@@ -952,6 +974,8 @@ extract_symlink (char *file_name, int typeflag)
int status;
int interdir_made = 0;
transform_member_name (&current_stat_info.link_name, xform_symlink);
if (! absolute_names_option
&& (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
|| contains_dot_dot (current_stat_info.link_name)))
@@ -985,16 +1009,19 @@ extract_node (char *file_name, int typeflag)
{
int status;
int interdir_made = 0;
mode_t mode = current_stat_info.stat.st_mode & ~ current_umask;
mode_t invert_permissions =
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
do
status = mknod (file_name, current_stat_info.stat.st_mode,
status = mknod (file_name, mode ^ invert_permissions,
current_stat_info.stat.st_rdev);
while (status && maybe_recoverable (file_name, &interdir_made));
if (status != 0)
mknod_error (file_name);
else
set_stat (file_name, &current_stat_info, NULL, 0,
set_stat (file_name, &current_stat_info, NULL, invert_permissions,
ARCHIVED_PERMSTATUS, typeflag);
return status;
}
@@ -1006,13 +1033,16 @@ extract_fifo (char *file_name, int typeflag)
{
int status;
int interdir_made = 0;
mode_t mode = current_stat_info.stat.st_mode & ~ current_umask;
mode_t invert_permissions =
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
while ((status = mkfifo (file_name, current_stat_info.stat.st_mode)))
while ((status = mkfifo (file_name, mode)) != 0)
if (!maybe_recoverable (file_name, &interdir_made))
break;
if (status == 0)
set_stat (file_name, &current_stat_info, NULL, 0,
set_stat (file_name, &current_stat_info, NULL, invert_permissions,
ARCHIVED_PERMSTATUS, typeflag);
else
mkfifo_error (file_name);
@@ -1021,13 +1051,14 @@ extract_fifo (char *file_name, int typeflag)
#endif
static int
extract_mangle_wrapper (char *file_name, int typeflag)
extract_volhdr (char *file_name, int typeflag)
{
extract_mangle ();
if (verbose_option)
fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
skip_member ();
return 0;
}
static int
extract_failure (char *file_name, int typeflag)
{
@@ -1107,13 +1138,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
break;
case GNUTYPE_VOLHDR:
if (verbose_option)
fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
*fun = NULL;
break;
case GNUTYPE_NAMES:
*fun = extract_mangle_wrapper;
*fun = extract_volhdr;
break;
case GNUTYPE_MULTIVOL:
@@ -1174,51 +1199,36 @@ void
extract_archive (void)
{
char typeflag;
char *file_name;
tar_extractor_t fun;
set_next_block_after (current_header);
decode_header (current_header, &current_stat_info, &current_format, 1);
if (interactive_option && !confirm ("extract", current_stat_info.file_name))
if (!current_stat_info.file_name[0]
|| (interactive_option
&& !confirm ("extract", current_stat_info.file_name)))
{
skip_member ();
return;
}
/* Print the block from current_header and current_stat. */
if (verbose_option)
print_header (&current_stat_info, -1);
file_name = safer_name_suffix (current_stat_info.file_name,
false, absolute_names_option);
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name,
strip_name_components);
if (prefix_len == (size_t) -1)
{
skip_member ();
return;
}
file_name += prefix_len;
}
/* Restore stats for all non-ancestor directories, unless
it is an incremental archive.
(see NOTICE in the comment to delay_set_stat above) */
if (!delay_directory_restore_option)
apply_nonancestor_delayed_set_stat (file_name, 0);
apply_nonancestor_delayed_set_stat (current_stat_info.file_name, 0);
/* Take a safety backup of a previously existing file. */
if (backup_option)
if (!maybe_backup_file (file_name, 0))
if (!maybe_backup_file (current_stat_info.file_name, 0))
{
int e = errno;
ERROR ((0, e, _("%s: Was unable to backup this file"),
quotearg_colon (file_name)));
quotearg_colon (current_stat_info.file_name)));
skip_member ();
return;
}
@@ -1228,9 +1238,10 @@ extract_archive (void)
typeflag = sparse_member_p (&current_stat_info) ?
GNUTYPE_SPARSE : current_header->header.typeflag;
if (prepare_to_extract (file_name, typeflag, &fun))
if (prepare_to_extract (current_stat_info.file_name, typeflag, &fun))
{
if (fun && (*fun) (file_name, typeflag) && backup_option)
if (fun && (*fun) (current_stat_info.file_name, typeflag)
&& backup_option)
undo_last_backup ();
}
else
@@ -1319,6 +1330,39 @@ extract_finish (void)
apply_nonancestor_delayed_set_stat ("", 1);
}
bool
rename_directory (char *src, char *dst)
{
if (rename (src, dst))
{
int e = errno;
switch (e)
{
case ENOENT:
if (make_directories (dst))
{
if (rename (src, dst) == 0)
return true;
e = errno;
}
break;
case EXDEV:
/* FIXME: Fall back to recursive copying */
default:
break;
}
ERROR ((0, e, _("Cannot rename %s to %s"),
quote_n (0, src),
quote_n (1, dst)));
return false;
}
return true;
}
void
fatal_exit (void)
{

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
/* List a tar archive, with support routines for reading a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-26.
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 2, or (at your option) any later
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
@@ -76,7 +76,6 @@ read_and (void (*do_something) (void))
{
prev_status = status;
tar_stat_destroy (&current_stat_info);
xheader_destroy (&extended_header);
status = read_header (false);
switch (status)
@@ -107,7 +106,6 @@ read_and (void (*do_something) (void))
{
case GNUTYPE_VOLHDR:
case GNUTYPE_MULTIVOL:
case GNUTYPE_NAMES:
break;
case DIRTYPE:
@@ -281,8 +279,8 @@ tar_checksum (union block *header, bool silent)
}
/* Read a block that's supposed to be a header block. Return its
address in "current_header", and if it is good, the file's size in
current_stat_info.stat.st_size.
address in "current_header", and if it is good, the file's size
and names (file name, link name) in *info.
Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
block full of zeros (EOF marker).
@@ -294,7 +292,7 @@ tar_checksum (union block *header, bool silent)
the header which this routine reads. */
enum read_header
read_header (bool raw_extended_headers)
read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
{
union block *header;
union block *header_copy;
@@ -303,8 +301,8 @@ read_header (bool raw_extended_headers)
size_t size, written;
union block *next_long_name = 0;
union block *next_long_link = 0;
size_t next_long_name_blocks;
size_t next_long_link_blocks;
size_t next_long_name_blocks = 0;
size_t next_long_link_blocks = 0;
while (1)
{
@@ -321,9 +319,9 @@ read_header (bool raw_extended_headers)
/* Good block. Decode file size and return. */
if (header->header.typeflag == LNKTYPE)
current_stat_info.stat.st_size = 0; /* links 0 size on tape */
info->stat.st_size = 0; /* links 0 size on tape */
else
current_stat_info.stat.st_size = OFF_FROM_HEADER (header->header.size);
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
if (header->header.typeflag == GNUTYPE_LONGNAME
|| header->header.typeflag == GNUTYPE_LONGLINK
@@ -336,14 +334,13 @@ read_header (bool raw_extended_headers)
else if (header->header.typeflag == GNUTYPE_LONGNAME
|| header->header.typeflag == GNUTYPE_LONGLINK)
{
size_t name_size = current_stat_info.stat.st_size;
size_t name_size = info->stat.st_size;
size_t n = name_size % BLOCKSIZE;
size = name_size + BLOCKSIZE;
if (n)
size += BLOCKSIZE - n;
if (name_size != current_stat_info.stat.st_size
|| size < name_size)
if (name_size != info->stat.st_size || size < name_size)
xalloc_die ();
header_copy = xmalloc (size + 1);
@@ -389,12 +386,16 @@ read_header (bool raw_extended_headers)
}
else if (header->header.typeflag == XHDTYPE
|| header->header.typeflag == SOLARIS_XHDTYPE)
xheader_read (header, OFF_FROM_HEADER (header->header.size));
xheader_read (&info->xhdr, header,
OFF_FROM_HEADER (header->header.size));
else if (header->header.typeflag == XGLTYPE)
{
xheader_read (header, OFF_FROM_HEADER (header->header.size));
xheader_decode_global ();
xheader_destroy (&extended_header);
struct xheader xhdr;
memset (&xhdr, 0, sizeof xhdr);
xheader_read (&xhdr, header,
OFF_FROM_HEADER (header->header.size));
xheader_decode_global (&xhdr);
xheader_destroy (&xhdr);
}
/* Loop! */
@@ -434,9 +435,9 @@ read_header (bool raw_extended_headers)
recent_long_name = 0;
recent_long_name_blocks = 0;
}
assign_string (&current_stat_info.orig_file_name, name);
assign_string (&current_stat_info.file_name, name);
current_stat_info.had_trailing_slash = strip_trailing_slashes (current_stat_info.file_name);
assign_string (&info->orig_file_name, name);
assign_string (&info->file_name, name);
info->had_trailing_slash = strip_trailing_slashes (info->file_name);
if (recent_long_link)
free (recent_long_link);
@@ -455,13 +456,60 @@ read_header (bool raw_extended_headers)
recent_long_link = 0;
recent_long_link_blocks = 0;
}
assign_string (&current_stat_info.link_name, name);
assign_string (&info->link_name, name);
return HEADER_SUCCESS;
}
}
}
enum read_header
read_header (bool raw_extended_headers)
{
return read_header_primitive (raw_extended_headers, &current_stat_info);
}
static char *
decode_xform (char *file_name, void *data)
{
xform_type type = *(xform_type*)data;
switch (type)
{
case xform_symlink:
/* FIXME: It is not quite clear how and to which extent are the symbolic
links subject to filename transformation. In the absence of another
solution, symbolic links are exempt from component stripping and
name suffix normalization, but subject to filename transformation
proper. */
return file_name;
case xform_link:
file_name = safer_name_suffix (file_name, true, absolute_names_option);
break;
case xform_regfile:
file_name = safer_name_suffix (file_name, false, absolute_names_option);
break;
}
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name,
strip_name_components);
if (prefix_len == (size_t) -1)
prefix_len = strlen (file_name);
file_name += prefix_len;
}
return file_name;
}
bool
transform_member_name (char **pinput, xform_type type)
{
return transform_name_fp (pinput, decode_xform, &type);
}
#define ISOCTAL(c) ((c)>='0'&&(c)<='7')
/* Decode things from a file HEADER block into STAT_INFO, also setting
@@ -491,7 +539,7 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
&& ISOCTAL (header->star_header.ctime[0])
&& header->star_header.ctime[11] == ' ')
format = STAR_FORMAT;
else if (extended_header.size)
else if (stat_info->xhdr.size)
format = POSIX_FORMAT;
else
format = USTAR_FORMAT;
@@ -579,6 +627,8 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|| stat_info->dumpdir)
stat_info->is_dumpdir = true;
}
transform_member_name (&stat_info->file_name, xform_regfile);
}
/* Convert buffer at WHERE0 of size DIGS from external format to
@@ -975,7 +1025,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
char modes[11];
char const *time_stamp;
int time_stamp_len;
char *temp_name = st->orig_file_name ? st->orig_file_name : st->file_name;
char *temp_name;
/* These hold formatted ints. */
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
@@ -989,21 +1039,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
if (test_label_option && current_header->header.typeflag != GNUTYPE_VOLHDR)
return;
if (show_stored_names_option)
{
switch (subcommand_option)
{
case CAT_SUBCOMMAND:
case UPDATE_SUBCOMMAND:
case APPEND_SUBCOMMAND:
case CREATE_SUBCOMMAND:
temp_name = st->file_name ? st->file_name : st->orig_file_name;
break;
default:
temp_name = st->orig_file_name ? st->orig_file_name : st->file_name;
}
}
if (show_transformed_names_option)
temp_name = st->file_name ? st->file_name : st->orig_file_name;
else
temp_name = st->orig_file_name ? st->orig_file_name : st->file_name;
@@ -1038,10 +1075,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
modes[0] = 'M';
break;
case GNUTYPE_NAMES:
modes[0] = 'N';
break;
case GNUTYPE_LONGNAME:
case GNUTYPE_LONGLINK:
modes[0] = 'L';
@@ -1225,10 +1258,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
uintbuf));
fprintf (stdlis, _("--Continued at byte %s--\n"), size);
break;
case GNUTYPE_NAMES:
fprintf (stdlis, _("--Mangled file names--\n"));
break;
}
}
fflush (stdlis);

View File

@@ -1,121 +0,0 @@
/* Encode long filenames for GNU tar.
Copyright 1988, 92, 94, 96, 97, 99, 2000 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 2, 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. */
#include <system.h>
#include "common.h"
#include <quotearg.h>
struct mangled
{
struct mangled *next;
int type;
char mangled[NAME_FIELD_SIZE];
char *linked_to;
char normal[1];
};
/* Extract a GNUTYPE_NAMES record contents. It seems that such are
not produced anymore by GNU tar, but we leave the reading code
around nevertheless, for salvaging old tapes. */
void
extract_mangle (void)
{
off_t size = current_stat_info.stat.st_size;
char *buffer = xmalloc ((size_t) (size + 1));
char *copy = buffer;
char *cursor = buffer;
if (size != (size_t) size || size == (size_t) -1)
xalloc_die ();
buffer[size] = '\0';
while (size > 0)
{
union block *block = find_next_block ();
size_t available;
if (!block)
{
ERROR ((0, 0, _("Unexpected EOF in mangled names")));
return;
}
available = available_space_after (block);
if (available > size)
available = size;
memcpy (copy, block->buffer, available);
copy += available;
size -= available;
set_next_block_after ((union block *) (block->buffer + available - 1));
}
while (*cursor)
{
char *next_cursor;
char *name;
char *name_end;
next_cursor = strchr (cursor, '\n');
*next_cursor++ = '\0';
if (!strncmp (cursor, "Rename ", 7))
{
name = cursor + 7;
name_end = strchr (name, ' ');
while (strncmp (name_end, " to ", 4))
{
name_end++;
name_end = strchr (name_end, ' ');
}
*name_end = '\0';
if (next_cursor[-2] == '/')
next_cursor[-2] = '\0';
unquote_string (name_end + 4);
if (rename (name, name_end + 4))
ERROR ((0, errno, _("%s: Cannot rename to %s"),
quotearg_colon (name), quote_n (1, name_end + 4)));
else if (verbose_option)
WARN ((0, 0, _("Renamed %s to %s"), name, name_end + 4));
}
#ifdef HAVE_SYMLINK
else if (!strncmp (cursor, "Symlink ", 8))
{
name = cursor + 8;
name_end = strchr (name, ' ');
while (strncmp (name_end, " to ", 4))
{
name_end++;
name_end = strchr (name_end, ' ');
}
*name_end = '\0';
unquote_string (name);
unquote_string (name_end + 4);
if (symlink (name, name_end + 4)
&& (unlink (name_end + 4) || symlink (name, name_end + 4)))
ERROR ((0, errno, _("%s: Cannot symlink to %s"),
quotearg_colon (name), quote_n (1, name_end + 4)));
else if (verbose_option)
WARN ((0, 0, _("Symlinked %s to %s"), name, name_end + 4));
}
#endif
else
ERROR ((0, 0, _("Unknown demangling command %s"), cursor));
cursor = next_cursor;
}
}

View File

@@ -1,11 +1,11 @@
/* Miscellaneous functions, not really specific to GNU tar.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007 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 2, or (at your option) any later
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
@@ -22,6 +22,7 @@
#include "common.h"
#include <quotearg.h>
#include <save-cwd.h>
#include <xgetcwd.h>
#include <unlinkdir.h>
#include <utimens.h>
@@ -412,7 +413,7 @@ remove_any_file (const char *file_name, enum remove_option option)
so, we do not have to backup block or character devices, nor remote
entities. */
bool
maybe_backup_file (const char *file_name, int this_is_the_archive)
maybe_backup_file (const char *file_name, bool this_is_the_archive)
{
struct stat file_stat;
@@ -515,7 +516,7 @@ set_file_atime (int fd, char const *file, struct timespec const timespec[2])
}
#endif
return futimens (fd, file, timespec);
return gl_futimens (fd, file, timespec);
}
/* A description of a working directory. */
@@ -542,8 +543,14 @@ chdir_arg (char const *dir)
{
if (wds == wd_alloc)
{
wd_alloc = 2 * (wd_alloc + 1);
wd = xrealloc (wd, sizeof *wd * wd_alloc);
if (wd_alloc == 0)
{
wd_alloc = 2;
wd = xmalloc (sizeof *wd * wd_alloc);
}
else
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
if (! wds)
{
wd[wds].name = ".";
@@ -582,9 +589,30 @@ chdir_do (int i)
if (! prev->saved)
{
int err = 0;
prev->saved = 1;
if (save_cwd (&prev->saved_cwd) != 0)
FATAL_ERROR ((0, 0, _("Cannot save working directory")));
err = errno;
else if (0 <= prev->saved_cwd.desc)
{
/* Make sure we still have at least one descriptor available. */
int fd1 = prev->saved_cwd.desc;
int fd2 = dup (fd1);
if (0 <= fd2)
close (fd2);
else if (errno == EMFILE)
{
/* Force restore_cwd to use chdir_long. */
close (fd1);
prev->saved_cwd.desc = -1;
prev->saved_cwd.name = xgetcwd ();
}
else
err = errno;
}
if (err)
FATAL_ERROR ((0, err, _("Cannot save working directory")));
}
if (curr->saved)

View File

@@ -1,11 +1,11 @@
/* Various processing of names.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007 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 2, or (at your option) any later
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
@@ -183,49 +183,90 @@ gname_to_gid (char const *gname, gid_t *gidp)
static struct name *namelist; /* first name in list, if any */
static struct name **nametail = &namelist; /* end of name list */
static const char **name_array; /* store an array of names */
static int allocated_names; /* how big is the array? */
static int names; /* how many entries does it have? */
static int name_index; /* how many of the entries have we scanned? */
/* Initialize structures. */
void
init_names (void)
/* File name arguments are processed in two stages: first a
name_array (see below) is filled, then the names from it
are moved into the namelist.
This awkward process is needed only to implement --same-order option,
which is meant to help process large archives on machines with
limited memory. With this option on, namelist contains at most one
entry, which diminishes the memory consumption.
However, I very much doubt if we still need this -- Sergey */
/* A name_array element contains entries of three types: */
#define NELT_NAME 0 /* File name */
#define NELT_CHDIR 1 /* Change directory request */
#define NELT_FMASK 2 /* Change fnmatch options request */
struct name_elt /* A name_array element. */
{
allocated_names = 10;
name_array = xmalloc (sizeof (const char *) * allocated_names);
names = 0;
}
char type; /* Element type, see NELT_* constants above */
union
{
const char *name; /* File or directory name */
int matching_flags;/* fnmatch options if type == NELT_FMASK */
} v;
};
/* Add NAME at end of name_array, reallocating it as necessary. */
void
name_add (const char *name)
static struct name_elt *name_array; /* store an array of names */
static size_t allocated_names; /* how big is the array? */
static size_t names; /* how many entries does it have? */
static size_t name_index; /* how many of the entries have we scanned? */
/* Check the size of name_array, reallocating it as necessary. */
static void
check_name_alloc ()
{
if (names == allocated_names)
{
allocated_names *= 2;
name_array =
xrealloc (name_array, sizeof (const char *) * allocated_names);
if (allocated_names == 0)
allocated_names = 10; /* Set initial allocation */
name_array = x2nrealloc (name_array, &allocated_names,
sizeof (name_array[0]));
}
name_array[names++] = name;
}
/* Add to name_array the file NAME with fnmatch options MATCHING_FLAGS */
void
name_add_name (const char *name, int matching_flags)
{
static int prev_flags = 0; /* FIXME: Or EXCLUDE_ANCHORED? */
struct name_elt *ep;
check_name_alloc ();
ep = &name_array[names++];
if (prev_flags != matching_flags)
{
ep->type = NELT_FMASK;
ep->v.matching_flags = matching_flags;
prev_flags = matching_flags;
check_name_alloc ();
ep = &name_array[names++];
}
ep->type = NELT_NAME;
ep->v.name = name;
}
/* Add to name_array a chdir request for the directory NAME */
void
name_add_dir (const char *name)
{
struct name_elt *ep;
check_name_alloc ();
ep = &name_array[names++];
ep->type = NELT_CHDIR;
ep->v.name = name;
}
/* Names from external name file. */
static char *name_buffer; /* buffer to hold the current file name */
static size_t name_buffer_length; /* allocated length of name_buffer */
/* FIXME: I should better check more closely. It seems at first glance that
is_pattern is only used when reading a file, and ignored for all
command line arguments. */
static inline int
is_pattern (const char *string)
{
return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
}
/* Set up to gather file names for tar. They can either come from a
file or were saved from decoding arguments. */
void
@@ -242,27 +283,40 @@ name_term (void)
free (name_array);
}
/* Get the next name from ARGV or the file of names. Result is in
static int matching_flags; /* exclude_fnmatch options */
/* Get the next NELT_NAME element from name_array. Result is in
static storage and can't be relied upon across two calls.
If CHANGE_DIRS is true, treat a filename of the form "-C" as
meaning that the next filename is the name of a directory to change
to. If filename_terminator is NUL, CHANGE_DIRS is effectively
always false. */
char *
name_next (int change_dirs)
If CHANGE_DIRS is true, treat any entries of type NELT_CHDIR as
the request to change to the given directory. If filename_terminator
is NUL, CHANGE_DIRS is effectively always false.
Entries of type NELT_FMASK cause updates of the matching_flags
value. */
struct name_elt *
name_next_elt (int change_dirs)
{
static struct name_elt entry;
const char *source;
char *cursor;
int chdir_flag = 0;
if (filename_terminator == '\0')
change_dirs = 0;
while (name_index != names)
{
struct name_elt *ep;
size_t source_len;
source = name_array[name_index++];
ep = &name_array[name_index++];
if (ep->type == NELT_FMASK)
{
matching_flags = ep->v.matching_flags;
continue;
}
source = ep->v.name;
source_len = strlen (source);
if (name_buffer_length < source_len)
{
@@ -285,25 +339,31 @@ name_next (int change_dirs)
while (cursor > name_buffer && ISSLASH (*cursor))
*cursor-- = '\0';
if (chdir_flag)
if (change_dirs && ep->type == NELT_CHDIR)
{
if (chdir (name_buffer) < 0)
chdir_fatal (name_buffer);
chdir_flag = 0;
}
else if (change_dirs && strcmp (name_buffer, "-C") == 0)
chdir_flag = 1;
else
{
if (unquote_option)
unquote_string (name_buffer);
if (incremental_option)
register_individual_file (name_buffer);
return name_buffer;
entry.type = ep->type;
entry.v.name = name_buffer;
return &entry;
}
}
return 0;
return NULL;
}
const char *
name_next (int change_dirs)
{
struct name_elt *nelt = name_next_elt (change_dirs);
return nelt ? nelt->v.name : NULL;
}
/* Gather names in a list for scanning. Could hash them later if we
@@ -323,7 +383,7 @@ name_gather (void)
static struct name *buffer;
static size_t allocated_size;
char const *name;
struct name_elt *ep;
if (same_order_option)
{
@@ -336,19 +396,15 @@ name_gather (void)
/* FIXME: This memset is overkill, and ugly... */
memset (buffer, 0, allocated_size);
}
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
change_dir = chdir_arg (xstrdup (ep->v.name));
while ((name = name_next (0)) && strcmp (name, "-C") == 0)
{
char const *dir = name_next (0);
if (! dir)
FATAL_ERROR ((0, 0, _("Missing file name after -C")));
change_dir = chdir_arg (xstrdup (dir));
}
if (name)
if (ep)
{
size_t needed_size;
buffer->length = strlen (name);
buffer->length = strlen (ep->v.name);
needed_size = offsetof (struct name, name) + buffer->length + 1;
if (allocated_size < needed_size)
{
@@ -363,10 +419,11 @@ name_gather (void)
buffer = xrealloc (buffer, allocated_size);
}
buffer->change_dir = change_dir;
strcpy (buffer->name, name);
strcpy (buffer->name, ep->v.name);
buffer->next = 0;
buffer->found_count = 0;
buffer->matching_flags = matching_flags;
namelist = buffer;
nametail = &namelist->next;
}
@@ -381,15 +438,11 @@ name_gather (void)
for (;;)
{
int change_dir0 = change_dir;
while ((name = name_next (0)) && strcmp (name, "-C") == 0)
{
char const *dir = name_next (0);
if (! dir)
FATAL_ERROR ((0, 0, _("Missing file name after -C")));
change_dir = chdir_arg (xstrdup (dir));
}
if (name)
addname (name, change_dir);
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
change_dir = chdir_arg (xstrdup (ep->v.name));
if (ep)
addname (ep->v.name, change_dir);
else
{
if (change_dir != change_dir0)
@@ -408,35 +461,16 @@ addname (char const *string, int change_dir)
struct name *name = xmalloc (offsetof (struct name, name) + length + 1);
if (string)
{
name->fake = 0;
strcpy (name->name, string);
}
strcpy (name->name, string);
else
{
name->fake = 1;
name->name[0] = 0;
/* FIXME: This initialization (and the byte of memory that it
initializes) is probably not needed, but we are currently in
bug-fix mode so we'll leave it in for now. */
name->name[0] = 0;
}
name->next = 0;
name->next = NULL;
name->length = length;
name->found_count = 0;
name->regexp = 0; /* assume not a regular expression */
name->firstch = 1; /* assume first char is literal */
name->matching_flags = matching_flags;
name->change_dir = change_dir;
name->dir_contents = 0;
name->explicit = 1;
if (string && is_pattern (string))
{
name->regexp = 1;
if (string[0] == '*' || string[0] == '[' || string[0] == '?')
name->firstch = 0;
}
name->dir_contents = NULL;
*nametail = name;
nametail = &name->next;
@@ -446,34 +480,23 @@ addname (char const *string, int change_dir)
/* Find a match for FILE_NAME (whose string length is LENGTH) in the name
list. */
static struct name *
namelist_match (char const *file_name, size_t length, bool exact)
namelist_match (char const *file_name, size_t length)
{
struct name *p;
for (p = namelist; p; p = p->next)
{
/* If first chars don't match, quick skip. */
if (p->firstch && p->name[0] != file_name[0])
continue;
if (p->regexp
? fnmatch (p->name, file_name, recursion_option) == 0
: exact ? (p->length == length
&& memcmp (file_name, p->name, length) == 0)
: (p->length <= length
&& (file_name[p->length] == '\0'
|| (ISSLASH (file_name[p->length]) && recursion_option))
&& memcmp (file_name, p->name, p->length) == 0))
if (p->name[0]
&& exclude_fnmatch (p->name, file_name, p->matching_flags))
return p;
}
return 0;
return NULL;
}
/* Return true if and only if name FILE_NAME (from an archive) matches any
name from the namelist. */
int
bool
name_match (const char *file_name)
{
size_t length = strlen (file_name);
@@ -483,17 +506,17 @@ name_match (const char *file_name)
struct name *cursor = namelist;
if (!cursor)
return 1;
if (cursor->fake)
return true;
if (cursor->name[0] == 0)
{
chdir_do (cursor->change_dir);
namelist = 0;
nametail = &namelist;
return 1;
return true;
}
cursor = namelist_match (file_name, length, false);
cursor = namelist_match (file_name, length);
if (cursor)
{
if (!(ISSLASH (file_name[cursor->length]) && recursion_option)
@@ -520,10 +543,10 @@ name_match (const char *file_name)
{
name_gather (); /* read one more */
if (namelist->found_count)
return 0;
return false;
}
else
return 0;
return false;
}
}
@@ -549,14 +572,38 @@ all_names_found (struct tar_stat_info *p)
len = strlen (p->file_name);
for (cursor = namelist; cursor; cursor = cursor->next)
{
if (cursor->regexp
|| (!WASFOUND(cursor) && !cursor->fake)
if ((cursor->name[0] && !WASFOUND (cursor))
|| (len >= cursor->length && ISSLASH (p->file_name[cursor->length])))
return false;
}
return true;
}
static inline int
is_pattern (const char *string)
{
return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
}
static void
regex_usage_warning (const char *name)
{
static int warned_once = 0;
if (warn_regex_usage && is_pattern (name))
{
warned_once = 1;
WARN ((0, 0,
/* TRANSLATORS: The following three msgids form a single sentence.
*/
_("Pattern matching characters used in file names. Please,")));
WARN ((0, 0,
_("use --wildcards to enable pattern matching, or --no-wildcards to")));
WARN ((0, 0,
_("suppress this warning.")));
}
}
/* Print the names of things in the namelist that were not matched. */
void
names_notfound (void)
@@ -564,14 +611,15 @@ names_notfound (void)
struct name const *cursor;
for (cursor = namelist; cursor; cursor = cursor->next)
if (!WASFOUND(cursor) && !cursor->fake)
if (!WASFOUND (cursor) && cursor->name[0])
{
regex_usage_warning (cursor->name);
if (cursor->found_count == 0)
ERROR ((0, 0, _("%s: Not found in archive"),
quotearg_colon (cursor->name)));
else
ERROR ((0, 0, _("%s: Required occurrence not found in archive"),
quotearg_colon (cursor->name)));
quotearg_colon (cursor->name)));
}
/* Don't bother freeing the name list; we're about to exit. */
@@ -580,11 +628,14 @@ names_notfound (void)
if (same_order_option)
{
char *name;
const char *name;
while ((name = name_next (1)) != NULL)
ERROR ((0, 0, _("%s: Not found in archive"),
quotearg_colon (name)));
{
regex_usage_warning (name);
ERROR ((0, 0, _("%s: Not found in archive"),
quotearg_colon (name)));
}
}
}
@@ -683,7 +734,7 @@ static void
add_hierarchy_to_namelist (struct name *name, dev_t device)
{
char *file_name = name->name;
char *buffer = get_directory_contents (file_name, device);
const char *buffer = get_directory_contents (file_name, device);
if (! buffer)
name->dir_contents = "\0\0\0\0";
@@ -695,7 +746,7 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
: NAME_FIELD_SIZE);
char *namebuf = xmalloc (allocated_length + 1);
/* FIXME: + 2 above? */
char *string;
const char *string;
size_t string_length;
int change_dir = name->change_dir;
@@ -728,7 +779,6 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
}
strcpy (namebuf + name_length, string + 1);
np = addname (namebuf, change_dir);
np->explicit = 0;
add_hierarchy_to_namelist (np, device);
}
}
@@ -762,10 +812,12 @@ collect_and_sort_names (void)
next_name = name->next;
if (name->found_count || name->dir_contents)
continue;
if (name->regexp) /* FIXME: just skip regexps for now */
if (name->matching_flags & EXCLUDE_WILDCARDS)
/* NOTE: EXCLUDE_ANCHORED is not relevant here */
/* FIXME: just skip regexps for now */
continue;
chdir_do (name->change_dir);
if (name->fake)
if (name->name[0] == 0)
continue;
if (deref_stat (dereference_option, name->name, &statbuf) != 0)
@@ -787,24 +839,29 @@ collect_and_sort_names (void)
for (name = namelist; name; name = name->next)
name->found_count = 0;
if (listed_incremental_option)
{
for (name = namelist; name && name->name[0] == 0; name++)
;
if (name)
name->dir_contents = append_incremental_renames (name->dir_contents);
}
}
/* This is like name_match, except that
1. It returns a pointer to the name it matched, and doesn't set FOUND
in structure. The caller will have to do that if it wants to.
2. If the namelist is empty, it returns null, unlike name_match, which
returns TRUE.
3. The second argument (EXACT) controls matching algorithm. If it
is TRUE, the exact matching is used. However, regular expressions are
always matched as such, no matter what the value of EXACT is. */
returns TRUE. */
struct name *
name_scan (const char *file_name, bool exact)
name_scan (const char *file_name)
{
size_t length = strlen (file_name);
while (1)
{
struct name *cursor = namelist_match (file_name, length, exact);
struct name *cursor = namelist_match (file_name, length);
if (cursor)
return cursor;
@@ -834,7 +891,8 @@ name_from_list (void)
{
if (!gnu_list_name)
gnu_list_name = namelist;
while (gnu_list_name && (gnu_list_name->found_count || gnu_list_name->fake))
while (gnu_list_name
&& (gnu_list_name->found_count || gnu_list_name->name[0] == 0))
gnu_list_name = gnu_list_name->next;
if (gnu_list_name)
{
@@ -856,7 +914,7 @@ blank_name_list (void)
}
/* Yield a newly allocated file name consisting of FILE_NAME concatenated to
NAME, with an intervening slash if FILE_NAME does not already end in one. */
NAME, with an intervening slash if FILE_NAME does not already end in one. */
char *
new_name (const char *file_name, const char *name)
{
@@ -954,11 +1012,10 @@ contains_dot_dot (char const *name)
if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
return 1;
do
while (! ISSLASH (*p))
{
if (! *p++)
return 0;
}
while (! ISSLASH (*p));
}
}

View File

@@ -1,10 +1,10 @@
/* Functions for dealing with sparse files
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2007 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 2, or (at your option) any later
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
@@ -409,15 +409,6 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
}
/* Returns true if the file represented by stat is a sparse one */
bool
sparse_file_p (struct tar_stat_info *st)
{
return (ST_NBLOCKS (st->stat)
< (st->stat.st_size / ST_NBLOCKSIZE
+ (st->stat.st_size % ST_NBLOCKSIZE != 0)));
}
bool
sparse_member_p (struct tar_stat_info *st)
{
@@ -475,7 +466,7 @@ sparse_skip_file (struct tar_stat_info *st)
file.fd = -1;
rc = tar_sparse_decode_header (&file);
skip_file (file.stat_info->archive_file_size);
skip_file (file.stat_info->archive_file_size - file.dumped_size);
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
}
@@ -740,11 +731,9 @@ oldgnu_dump_header (struct tar_sparse_file *file)
oldgnu_store_sparse_info (file, &i,
blk->sparse_header.sp,
SPARSES_IN_SPARSE_HEADER);
set_next_block_after (blk);
if (i < file->stat_info->sparse_map_avail)
blk->sparse_header.isextended = 1;
else
break;
set_next_block_after (blk);
}
return true;
}
@@ -843,16 +832,15 @@ static struct tar_sparse_optab const star_optab = {
};
/* GNU PAX sparse file format. The sparse file map is stored in
x header:
/* GNU PAX sparse file format. There are several versions:
* 0.0
The initial version of sparse format used by tar 1.14-1.15.1.
The sparse file map is stored in x header:
GNU.sparse.size Real size of the stored file
GNU.sparse.numblocks Number of blocks in the sparse map
GNU.sparse.map Map of non-null data chunks. A string consisting
of comma-separated values "offset,size[,offset,size]..."
Tar versions 1.14-1.15.1 instead of the latter used:
repeat numblocks time
GNU.sparse.offset Offset of the next data block
GNU.sparse.numbytes Size of the next data block
@@ -860,44 +848,89 @@ static struct tar_sparse_optab const star_optab = {
This has been reported as conflicting with the POSIX specs. The reason is
that offsets and sizes of non-zero data blocks were stored in multiple
instances of GNU.sparse.offset/GNU.sparse.numbytes variables. However,
instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
POSIX requires the latest occurrence of the variable to override all
previous occurrences.
To avoid this incompatibility new keyword GNU.sparse.map was introduced
in tar 1.15.2. Some people might still need the 1.14 way of handling
sparse files for the compatibility reasons: it can be achieved by
specifying `--pax-option delete=GNU.sparse.map' in the command line.
To avoid this incompatibility two following versions were introduced.
See FIXME-1.14-1.15.1-1.20, below.
* 0.1
Used by tar 1.15.2 -- 1.15.91 (alpha releases).
The sparse file map is stored in
x header:
GNU.sparse.size Real size of the stored file
GNU.sparse.numblocks Number of blocks in the sparse map
GNU.sparse.map Map of non-null data chunks. A string consisting
of comma-separated values "offset,size[,offset,size]..."
The resulting GNU.sparse.map string can be *very* long. While POSIX does not
impose any limit on the length of a x header variable, this can confuse some
tars.
* 1.0
Starting from this version, the exact sparse format version is specified
explicitely in the header using the following variables:
GNU.sparse.major Major version
GNU.sparse.minor Minor version
X header keeps the following variables:
GNU.sparse.name Real file name of the sparse file
GNU.sparse.realsize Real size of the stored file (corresponds to the old
GNU.sparse.size variable)
The name field of the ustar header is constructed using the pattern
"%d/GNUSparseFile.%p/%f".
The sparse map itself is stored in the file data block, preceding the actual
file data. It consists of a series of octal numbers of arbitrary length,
delimited by newlines. The map is padded with nulls to the nearest block
boundary.
The first number gives the number of entries in the map. Following are map
entries, each one consisting of two numbers giving the offset and size of
the data block it describes.
The format is designed in such a way that non-posix aware tars and tars not
supporting GNU.sparse.* keywords will extract each sparse file in its
condensed form with the file map attached and will place it into a separate
directory. Then, using a simple program it would be possible to expand the
file to its original form even without GNU tar.
Bu default, v.1.0 archives are created. To use other formats,
--sparse-version option is provided. Additionally, v.0.0 can be obtained
by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
--pax-option delete=GNU.sparse.map
*/
static bool
pax_sparse_member_p (struct tar_sparse_file *file)
{
return file->stat_info->sparse_map_avail > 0;
return file->stat_info->sparse_map_avail > 0
|| file->stat_info->sparse_major > 0;
}
static bool
pax_dump_header (struct tar_sparse_file *file)
pax_dump_header_0 (struct tar_sparse_file *file)
{
off_t block_ordinal = current_block_ordinal ();
union block *blk;
size_t i;
char nbuf[UINTMAX_STRSIZE_BOUND];
struct sp_array *map = file->stat_info->sparse_map;
char *save_file_name = NULL;
/* Store the real file size */
xheader_store ("GNU.sparse.size", file->stat_info, NULL);
xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
/* FIXME-1.14-1.15.1-1.20: See the comment above.
Starting with 1.17 this should display a warning about POSIX-incompatible
keywords being generated. In 1.20, the true branch of the if block below
will be removed and GNU.sparse.map will be marked in xhdr_tab as
protected. */
if (xheader_keyword_deleted_p ("GNU.sparse.map"))
if (xheader_keyword_deleted_p ("GNU.sparse.map")
|| tar_sparse_minor == 0)
{
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
{
@@ -907,21 +940,225 @@ pax_dump_header (struct tar_sparse_file *file)
}
else
{
xheader_string_begin ();
xheader_store ("GNU.sparse.name", file->stat_info, NULL);
save_file_name = file->stat_info->file_name;
file->stat_info->file_name = xheader_format_name (file->stat_info,
"%d/GNUSparseFile.%p/%f", 0);
xheader_string_begin (&file->stat_info->xhdr);
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
{
if (i)
xheader_string_add (",");
xheader_string_add (umaxtostr (map[i].offset, nbuf));
xheader_string_add (",");
xheader_string_add (umaxtostr (map[i].numbytes, nbuf));
xheader_string_add (&file->stat_info->xhdr, ",");
xheader_string_add (&file->stat_info->xhdr,
umaxtostr (map[i].offset, nbuf));
xheader_string_add (&file->stat_info->xhdr, ",");
xheader_string_add (&file->stat_info->xhdr,
umaxtostr (map[i].numbytes, nbuf));
}
if (!xheader_string_end (&file->stat_info->xhdr,
"GNU.sparse.map"))
{
free (file->stat_info->file_name);
file->stat_info->file_name = save_file_name;
return false;
}
xheader_string_end ("GNU.sparse.map");
}
blk = start_header (file->stat_info);
/* Store the effective (shrunken) file size */
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
finish_header (file->stat_info, blk, block_ordinal);
if (save_file_name)
{
free (file->stat_info->file_name);
file->stat_info->file_name = save_file_name;
}
return true;
}
static bool
pax_dump_header_1 (struct tar_sparse_file *file)
{
off_t block_ordinal = current_block_ordinal ();
union block *blk;
char *p, *q;
size_t i;
char nbuf[UINTMAX_STRSIZE_BOUND];
off_t size = 0;
struct sp_array *map = file->stat_info->sparse_map;
char *save_file_name = file->stat_info->file_name;
#define COPY_STRING(b,dst,src) do \
{ \
char *endp = b->buffer + BLOCKSIZE; \
char *srcp = src; \
while (*srcp) \
{ \
if (dst == endp) \
{ \
set_next_block_after (b); \
b = find_next_block (); \
dst = b->buffer; \
endp = b->buffer + BLOCKSIZE; \
} \
*dst++ = *srcp++; \
} \
} while (0)
/* Compute stored file size */
p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
size += strlen (p) + 1;
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
{
p = umaxtostr (map[i].offset, nbuf);
size += strlen (p) + 1;
p = umaxtostr (map[i].numbytes, nbuf);
size += strlen (p) + 1;
}
size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
file->stat_info->archive_file_size += size * BLOCKSIZE;
file->dumped_size += size * BLOCKSIZE;
/* Store sparse file identification */
xheader_store ("GNU.sparse.major", file->stat_info, NULL);
xheader_store ("GNU.sparse.minor", file->stat_info, NULL);
xheader_store ("GNU.sparse.name", file->stat_info, NULL);
xheader_store ("GNU.sparse.realsize", file->stat_info, NULL);
file->stat_info->file_name = xheader_format_name (file->stat_info,
"%d/GNUSparseFile.%p/%f", 0);
blk = start_header (file->stat_info);
/* Store the effective (shrunken) file size */
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
finish_header (file->stat_info, blk, block_ordinal);
free (file->stat_info->file_name);
file->stat_info->file_name = save_file_name;
blk = find_next_block ();
q = blk->buffer;
p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
COPY_STRING (blk, q, p);
COPY_STRING (blk, q, "\n");
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
{
p = umaxtostr (map[i].offset, nbuf);
COPY_STRING (blk, q, p);
COPY_STRING (blk, q, "\n");
p = umaxtostr (map[i].numbytes, nbuf);
COPY_STRING (blk, q, p);
COPY_STRING (blk, q, "\n");
}
memset (q, 0, BLOCKSIZE - (q - blk->buffer));
set_next_block_after (blk);
return true;
}
static bool
pax_dump_header (struct tar_sparse_file *file)
{
file->stat_info->sparse_major = tar_sparse_major;
file->stat_info->sparse_minor = tar_sparse_minor;
return (file->stat_info->sparse_major == 0) ?
pax_dump_header_0 (file) : pax_dump_header_1 (file);
}
static bool
decode_num (uintmax_t *num, char const *arg, uintmax_t maxval)
{
uintmax_t u;
char *arg_lim;
if (!ISDIGIT (*arg))
return false;
u = strtoumax (arg, &arg_lim, 10);
if (! (u <= maxval && errno != ERANGE) || *arg_lim)
return false;
*num = u;
return true;
}
static bool
pax_decode_header (struct tar_sparse_file *file)
{
if (file->stat_info->sparse_major > 0)
{
uintmax_t u;
char nbuf[UINTMAX_STRSIZE_BOUND];
union block *blk;
char *p;
size_t i;
#define COPY_BUF(b,buf,src) do \
{ \
char *endp = b->buffer + BLOCKSIZE; \
char *dst = buf; \
do \
{ \
if (dst == buf + UINTMAX_STRSIZE_BOUND -1) \
{ \
ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \
file->stat_info->orig_file_name)); \
return false; \
} \
if (src == endp) \
{ \
set_next_block_after (b); \
file->dumped_size += BLOCKSIZE; \
b = find_next_block (); \
src = b->buffer; \
endp = b->buffer + BLOCKSIZE; \
} \
*dst = *src++; \
} \
while (*dst++ != '\n'); \
dst[-1] = 0; \
} while (0)
set_next_block_after (current_header);
file->dumped_size += BLOCKSIZE;
blk = find_next_block ();
p = blk->buffer;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
file->stat_info->sparse_map_size = u;
file->stat_info->sparse_map = xcalloc (file->stat_info->sparse_map_size,
sizeof (*file->stat_info->sparse_map));
file->stat_info->sparse_map_avail = 0;
for (i = 0; i < file->stat_info->sparse_map_size; i++)
{
struct sp_array sp;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
sp.offset = u;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
sp.numbytes = u;
sparse_add_map (file->stat_info, &sp);
}
set_next_block_after (blk);
}
return true;
}
@@ -930,8 +1167,8 @@ static struct tar_sparse_optab const pax_optab = {
NULL, /* No done function */
pax_sparse_member_p,
pax_dump_header,
NULL, /* No decode_header function */
NULL, /* No fixup_header function */
NULL,
pax_decode_header,
NULL, /* No scan_block function */
sparse_dump_region,
sparse_extract_region,

78
src/suffix.c Normal file
View File

@@ -0,0 +1,78 @@
/* This file is part of GNU tar.
Copyright (C) 2007 Free Software Foundation, Inc.
Written by Sergey Poznyakoff.
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, 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 GNU tar. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include "common.h"
struct compression_suffix
{
const char *suffix;
size_t length;
const char *program;
};
struct compression_suffix compression_suffixes[] = {
#define S(s,p) #s, sizeof (#s) - 1, #p
{ S(gz, gzip) },
{ S(tgz, gzip) },
{ S(taz, gzip) },
{ S(Z, compress) },
{ S(taZ, compress) },
{ S(bz2, bzip2) },
{ S(tbz, bzip2) },
{ S(tbz2, bzip2) },
{ S(tz2, bzip2) },
{ S(lzma, lzma) },
{ S(tlz, lzma) },
#undef S
};
int nsuffixes = sizeof (compression_suffixes) /
sizeof (compression_suffixes[0]);
static const char *
find_compression_program (const char *name, const char *defprog)
{
char *suf = strrchr (name, '.');
if (suf)
{
int i;
size_t len;
suf++;
len = strlen (suf);
for (i = 0; i < nsuffixes; i++)
{
if (compression_suffixes[i].length == len
&& memcmp (compression_suffixes[i].suffix, suf, len) == 0)
return compression_suffixes[i].program;
}
}
return defprog;
}
void
set_comression_program_by_suffix (const char *name, const char *defprog)
{
const char *program = find_compression_program (name, defprog);
if (program)
use_compress_program_option = program;
}

View File

@@ -1,10 +1,10 @@
/* System-dependent calls for tar.
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2007 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 2, or (at your option) any later
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
@@ -17,8 +17,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <system.h>
#include <getline.h>
#include <setenv.h>
#include "common.h"
#include <rmt.h>
@@ -697,7 +695,7 @@ stat_to_env (char *name, char type, struct tar_stat_info *st)
}
}
static pid_t pid;
static pid_t global_pid;
static RETSIGTYPE (*pipe_handler) (int sig);
int
@@ -708,9 +706,9 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
xpipe (p);
pipe_handler = signal (SIGPIPE, SIG_IGN);
pid = xfork ();
global_pid = xfork ();
if (pid != 0)
if (global_pid != 0)
{
xclose (p[PREAD]);
return p[PWRITE];
@@ -737,14 +735,14 @@ sys_wait_command (void)
{
int status;
if (pid < 0)
if (global_pid < 0)
return;
signal (SIGPIPE, pipe_handler);
while (waitpid (pid, &status, 0) == -1)
while (waitpid (global_pid, &status, 0) == -1)
if (errno != EINTR)
{
pid = -1;
global_pid = -1;
waitpid_error (to_command_option);
return;
}
@@ -753,18 +751,18 @@ sys_wait_command (void)
{
if (!ignore_command_error_option && WEXITSTATUS (status))
ERROR ((0, 0, _("%lu: Child returned status %d"),
(unsigned long) pid, WEXITSTATUS (status)));
(unsigned long) global_pid, WEXITSTATUS (status)));
}
else if (WIFSIGNALED (status))
{
WARN ((0, 0, _("%lu: Child terminated on signal %d"),
(unsigned long) pid, WTERMSIG (status)));
(unsigned long) global_pid, WTERMSIG (status)));
}
else
ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
(unsigned long) pid));
(unsigned long) global_pid));
pid = -1;
global_pid = -1;
}
int
@@ -774,9 +772,10 @@ sys_exec_info_script (const char **archive_name, int volume_number)
char *argv[4];
char uintbuf[UINTMAX_STRSIZE_BOUND];
int p[2];
static RETSIGTYPE (*saved_handler) (int sig);
xpipe (p);
pipe_handler = signal (SIGPIPE, SIG_IGN);
saved_handler = signal (SIGPIPE, SIG_IGN);
pid = xfork ();
@@ -786,7 +785,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
int rc;
int status;
char *buf;
char *buf = NULL;
size_t size = 0;
FILE *fp;
@@ -801,10 +800,13 @@ sys_exec_info_script (const char **archive_name, int volume_number)
while (waitpid (pid, &status, 0) == -1)
if (errno != EINTR)
{
signal (SIGPIPE, saved_handler);
waitpid_error (info_script_option);
return -1;
}
signal (SIGPIPE, saved_handler);
if (WIFEXITED (status))
{
if (WEXITSTATUS (status) == 0 && rc > 0)
@@ -822,13 +824,15 @@ sys_exec_info_script (const char **archive_name, int volume_number)
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
setenv ("TAR_ARCHIVE", *archive_name, 1);
setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
setenv ("TAR_BLOCKING_FACTOR",
STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
setenv ("TAR_FORMAT",
archive_format_string (current_format == DEFAULT_FORMAT ?
archive_format : current_format), 1);
setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
xclose (p[PREAD]);
xdup2 (p[PWRITE], 3);
argv[0] = "/bin/sh";
argv[1] = "-c";
@@ -840,5 +844,51 @@ sys_exec_info_script (const char **archive_name, int volume_number)
exec_fatal (info_script_option);
}
void
sys_exec_checkpoint_script (const char *script_name,
const char *archive_name,
int checkpoint_number)
{
pid_t pid;
char *argv[4];
char uintbuf[UINTMAX_STRSIZE_BOUND];
pid = xfork ();
if (pid != 0)
{
/* Master */
int status;
while (waitpid (pid, &status, 0) == -1)
if (errno != EINTR)
{
waitpid_error (script_name);
break;
}
return;
}
/* Child */
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
setenv ("TAR_ARCHIVE", archive_name, 1);
setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1);
setenv ("TAR_BLOCKING_FACTOR",
STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
setenv ("TAR_FORMAT",
archive_format_string (current_format == DEFAULT_FORMAT ?
archive_format : current_format), 1);
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = (char*) script_name;
argv[3] = NULL;
execv (argv[0], argv);
exec_fatal (script_name);
}
#endif /* not MSDOS */

885
src/tar.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
/* GNU tar Archive Format description.
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
2000, 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
2000, 2001, 2003, 2004, 2005, 2006, 2007 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 2, or (at your option) any later
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
@@ -165,6 +165,7 @@ struct oldgnu_header
'A' Solaris Access Control List
'E' Solaris Extended Attribute File
'I' Inode only, as in 'star'
'N' Obsolete GNU tar, for file names that do not fit into the main header.
'X' POSIX 1003.1-2001 eXtended (VU version) */
/* This is a dir entry that contains the names of files that were in the
@@ -180,9 +181,6 @@ struct oldgnu_header
/* This is the continuation of a file that began on another volume. */
#define GNUTYPE_MULTIVOL 'M'
/* For storing filenames that do not fit into the main header. */
#define GNUTYPE_NAMES 'N'
/* This is for sparse files. */
#define GNUTYPE_SPARSE 'S'
@@ -192,8 +190,7 @@ struct oldgnu_header
/* Solaris extended header */
#define SOLARIS_XHDTYPE 'X'
/* Jörg Schilling star header */
/* J@"org Schilling star header */
struct star_header
{ /* byte offset */
@@ -221,7 +218,8 @@ struct star_header
#define SPARSES_IN_STAR_HEADER 4
#define SPARSES_IN_STAR_EXT_HEADER 21
struct star_in_header {
struct star_in_header
{
char fill[345]; /* 0 Everything that is before t_prefix */
char prefix[1]; /* 345 t_name prefix */
char fill2; /* 346 */
@@ -236,11 +234,13 @@ struct star_in_header {
char xmagic[4]; /* 508 "tar" */
};
struct star_ext_header {
struct star_ext_header
{
struct sparse sp[SPARSES_IN_STAR_EXT_HEADER];
char isextended;
};
/* END */
/* tar Header Block, overall structure. */
@@ -263,10 +263,18 @@ enum archive_format
/* Information about a sparse file. */
struct sp_array
{
off_t offset;
size_t numbytes;
};
{
off_t offset;
size_t numbytes;
};
struct xheader
{
struct obstack *stk;
size_t size;
char *buffer;
uintmax_t string_length;
};
struct tar_stat_info
{
@@ -293,12 +301,17 @@ struct tar_stat_info
bool is_sparse; /* Is the file sparse */
/* For sparse files: */
unsigned sparse_major;
unsigned sparse_minor;
size_t sparse_map_avail; /* Index to the first unused element in
sparse_map array. Zero if the file is
not sparse */
size_t sparse_map_size; /* Size of the sparse map */
struct sp_array *sparse_map;
/* Extended headers */
struct xheader xhdr;
/* For dumpdirs */
bool is_dumpdir; /* Is the member a dumpdir? */
bool skipped; /* The member contents is already read
@@ -316,5 +329,3 @@ union block
struct star_in_header star_in_header;
struct star_ext_header star_ext_header;
};
/* End of Format description. */

567
src/transform.c Normal file
View File

@@ -0,0 +1,567 @@
/* This file is part of GNU tar.
Copyright (C) 2006, 2007, 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. */
#include <system.h>
#include <regex.h>
#include "common.h"
enum transform_type
{
transform_first,
transform_global
};
enum replace_segm_type
{
segm_literal, /* Literal segment */
segm_backref, /* Back-reference segment */
segm_case_ctl /* Case control segment (GNU extension) */
};
enum case_ctl_type
{
ctl_stop, /* Stop case conversion */
ctl_upcase_next,/* Turn the next character to uppercase */
ctl_locase_next,/* Turn the next character to lowercase */
ctl_upcase, /* Turn the replacement to uppercase until ctl_stop */
ctl_locase /* Turn the replacement to lowercase until ctl_stop */
};
struct replace_segm
{
struct replace_segm *next;
enum replace_segm_type type;
union
{
struct
{
char *ptr;
size_t size;
} literal; /* type == segm_literal */
size_t ref; /* type == segm_backref */
enum case_ctl_type ctl; /* type == segm_case_ctl */
} v;
};
struct transform
{
struct transform *next;
enum transform_type transform_type;
unsigned match_number;
regex_t regex;
/* Compiled replacement expression */
struct replace_segm *repl_head, *repl_tail;
size_t segm_count; /* Number of elements in the above list */
};
static struct transform *transform_head, *transform_tail;
static struct transform *
new_transform ()
{
struct transform *p = xzalloc (sizeof *p);
if (transform_tail)
transform_tail->next = p;
else
transform_head = p;
transform_tail = p;
return p;
}
static struct replace_segm *
add_segment (struct transform *tf)
{
struct replace_segm *segm = xmalloc (sizeof *segm);
segm->next = NULL;
if (tf->repl_tail)
tf->repl_tail->next = segm;
else
tf->repl_head = segm;
tf->repl_tail = segm;
tf->segm_count++;
return segm;
}
static void
add_literal_segment (struct transform *tf, char *str, char *end)
{
size_t len = end - str;
if (len)
{
struct replace_segm *segm = add_segment (tf);
segm->type = segm_literal;
segm->v.literal.ptr = xmalloc (len + 1);
memcpy (segm->v.literal.ptr, str, len);
segm->v.literal.ptr[len] = 0;
segm->v.literal.size = len;
}
}
static void
add_char_segment (struct transform *tf, int chr)
{
struct replace_segm *segm = add_segment (tf);
segm->type = segm_literal;
segm->v.literal.ptr = xmalloc (2);
segm->v.literal.ptr[0] = chr;
segm->v.literal.ptr[1] = 0;
segm->v.literal.size = 1;
}
static void
add_backref_segment (struct transform *tf, size_t ref)
{
struct replace_segm *segm = add_segment (tf);
segm->type = segm_backref;
segm->v.ref = ref;
}
static void
add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl)
{
struct replace_segm *segm = add_segment (tf);
segm->type = segm_case_ctl;
segm->v.ctl = ctl;
}
static const char *
parse_transform_expr (const char *expr)
{
int delim;
int i, j, rc;
char *str, *beg, *cur;
const char *p;
int cflags = 0;
struct transform *tf = new_transform ();
if (expr[0] != 's')
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
delim = expr[1];
/* Scan regular expression */
for (i = 2; expr[i] && expr[i] != delim; i++)
if (expr[i] == '\\' && expr[i+1])
i++;
if (expr[i] != delim)
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
/* Scan replacement expression */
for (j = i + 1; expr[j] && expr[j] != delim; j++)
if (expr[j] == '\\' && expr[j+1])
j++;
if (expr[j] != delim)
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
/* Check flags */
tf->transform_type = transform_first;
for (p = expr + j + 1; *p && *p != ';'; p++)
switch (*p)
{
case 'g':
tf->transform_type = transform_global;
break;
case 'i':
cflags |= REG_ICASE;
break;
case 'x':
cflags |= REG_EXTENDED;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
tf->match_number = strtoul (p, (char**) &p, 0);
p--;
break;
default:
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression: %c"),
*p));
}
if (*p == ';')
p++;
/* Extract and compile regex */
str = xmalloc (i - 1);
memcpy (str, expr + 2, i - 2);
str[i - 2] = 0;
rc = regcomp (&tf->regex, str, cflags);
if (rc)
{
char errbuf[512];
regerror (rc, &tf->regex, errbuf, sizeof (errbuf));
USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf));
}
if (str[0] == '^' || str[strlen (str) - 1] == '$')
tf->transform_type = transform_first;
free (str);
/* Extract and compile replacement expr */
i++;
str = xmalloc (j - i + 1);
memcpy (str, expr + i, j - i);
str[j - i] = 0;
for (cur = beg = str; *cur;)
{
if (*cur == '\\')
{
size_t n;
add_literal_segment (tf, beg, cur);
switch (*++cur)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = strtoul (cur, &cur, 10);
if (n > tf->regex.re_nsub)
USAGE_ERROR ((0, 0, _("Invalid transform replacement: back reference out of range")));
add_backref_segment (tf, n);
break;
case '\\':
add_char_segment (tf, '\\');
cur++;
break;
case 'a':
add_char_segment (tf, '\a');
cur++;
break;
case 'b':
add_char_segment (tf, '\b');
cur++;
break;
case 'f':
add_char_segment (tf, '\f');
cur++;
break;
case 'n':
add_char_segment (tf, '\n');
cur++;
break;
case 'r':
add_char_segment (tf, '\r');
cur++;
break;
case 't':
add_char_segment (tf, '\t');
cur++;
break;
case 'v':
add_char_segment (tf, '\v');
cur++;
break;
case '&':
add_char_segment (tf, '&');
cur++;
break;
case 'L':
/* Turn the replacement to lowercase until a `\U' or `\E'
is found, */
add_case_ctl_segment (tf, ctl_locase);
cur++;
break;
case 'l':
/* Turn the next character to lowercase, */
add_case_ctl_segment (tf, ctl_locase_next);
cur++;
break;
case 'U':
/* Turn the replacement to uppercase until a `\L' or `\E'
is found, */
add_case_ctl_segment (tf, ctl_upcase);
cur++;
break;
case 'u':
/* Turn the next character to uppercase, */
add_case_ctl_segment (tf, ctl_upcase_next);
cur++;
break;
case 'E':
/* Stop case conversion started by `\L' or `\U'. */
add_case_ctl_segment (tf, ctl_stop);
cur++;
break;
default:
/* Try to be nice */
{
char buf[2];
buf[0] = '\\';
buf[1] = *cur;
add_literal_segment (tf, buf, buf + 2);
}
cur++;
break;
}
beg = cur;
}
else if (*cur == '&')
{
add_literal_segment (tf, beg, cur);
add_backref_segment (tf, 0);
beg = ++cur;
}
else
cur++;
}
add_literal_segment (tf, beg, cur);
return p;
}
void
set_transform_expr (const char *expr)
{
while (*expr)
expr = parse_transform_expr (expr);
}
/* Run case conversion specified by CASE_CTL on array PTR of SIZE
characters. Returns pointer to statically allocated storage. */
static char *
run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
{
static char *case_ctl_buffer;
static size_t case_ctl_bufsize;
char *p;
if (case_ctl_bufsize < size)
{
case_ctl_bufsize = size;
case_ctl_buffer = xrealloc (case_ctl_buffer, case_ctl_bufsize);
}
memcpy (case_ctl_buffer, ptr, size);
switch (case_ctl)
{
case ctl_upcase_next:
case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
break;
case ctl_locase_next:
case_ctl_buffer[0] = tolower (case_ctl_buffer[0]);
break;
case ctl_upcase:
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
*p = toupper (*p);
break;
case ctl_locase:
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
*p = tolower (*p);
break;
case ctl_stop:
break;
}
return case_ctl_buffer;
}
static struct obstack stk;
static bool stk_init;
void
_single_transform_name_to_obstack (struct transform *tf, char *input)
{
regmatch_t *rmp;
int rc;
size_t nmatches = 0;
enum case_ctl_type case_ctl = ctl_stop, /* Current case conversion op */
save_ctl = ctl_stop; /* Saved case_ctl for \u and \l */
/* Reset case conversion after a single-char operation */
#define CASE_CTL_RESET() if (case_ctl == ctl_upcase_next \
|| case_ctl == ctl_locase_next) \
{ \
case_ctl = save_ctl; \
save_ctl = ctl_stop; \
}
rmp = xmalloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
while (*input)
{
size_t disp;
char *ptr;
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
if (rc == 0)
{
struct replace_segm *segm;
disp = rmp[0].rm_eo;
if (rmp[0].rm_so)
obstack_grow (&stk, input, rmp[0].rm_so);
nmatches++;
if (tf->match_number && nmatches < tf->match_number)
{
obstack_grow (&stk, input, disp);
input += disp;
continue;
}
for (segm = tf->repl_head; segm; segm = segm->next)
{
switch (segm->type)
{
case segm_literal: /* Literal segment */
if (case_ctl == ctl_stop)
ptr = segm->v.literal.ptr;
else
{
ptr = run_case_conv (case_ctl,
segm->v.literal.ptr,
segm->v.literal.size);
CASE_CTL_RESET();
}
obstack_grow (&stk, ptr, segm->v.literal.size);
break;
case segm_backref: /* Back-reference segment */
if (rmp[segm->v.ref].rm_so != -1
&& rmp[segm->v.ref].rm_eo != -1)
{
size_t size = rmp[segm->v.ref].rm_eo
- rmp[segm->v.ref].rm_so;
ptr = input + rmp[segm->v.ref].rm_so;
if (case_ctl != ctl_stop)
{
ptr = run_case_conv (case_ctl, ptr, size);
CASE_CTL_RESET();
}
obstack_grow (&stk, ptr, size);
}
break;
case segm_case_ctl:
switch (segm->v.ctl)
{
case ctl_upcase_next:
case ctl_locase_next:
switch (save_ctl)
{
case ctl_stop:
case ctl_upcase:
case ctl_locase:
save_ctl = case_ctl;
default:
break;
}
/*FALL THROUGH*/
case ctl_upcase:
case ctl_locase:
case ctl_stop:
case_ctl = segm->v.ctl;
}
}
}
}
else
{
disp = strlen (input);
obstack_grow (&stk, input, disp);
}
input += disp;
if (tf->transform_type == transform_first)
{
obstack_grow (&stk, input, strlen (input));
break;
}
}
obstack_1grow (&stk, 0);
free (rmp);
}
bool
_transform_name_to_obstack (char *input, char **output)
{
struct transform *tf;
if (!stk_init)
{
obstack_init (&stk);
stk_init = true;
}
for (tf = transform_head; tf; tf = tf->next)
{
_single_transform_name_to_obstack (tf, input);
input = obstack_finish (&stk);
}
*output = input;
return transform_head != NULL;
}
bool
transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *dat)
{
char *str;
bool ret = _transform_name_to_obstack (*pinput, &str);
if (ret)
{
assign_string (pinput, fun ? fun (str, dat) : str);
obstack_free (&stk, str);
}
else if (fun)
{
*pinput = NULL;
assign_string (pinput, fun (str, dat));
free (str);
ret = true;
}
return ret;
}
bool
transform_name (char **pinput)
{
return transform_name_fp (pinput, NULL, NULL);
}

View File

@@ -1,11 +1,11 @@
/* Update a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
2004, 2005 Free Software Foundation, Inc.
2004, 2005, 2007 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 2, or (at your option) any later
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
@@ -110,7 +110,7 @@ update_archive (void)
name_gather ();
open_archive (ACCESS_UPDATE);
xheader_write_global ();
buffer_write_global_xheader ();
while (!found_end)
{
@@ -131,7 +131,7 @@ update_archive (void)
archive_format = current_format;
if (subcommand_option == UPDATE_SUBCOMMAND
&& (name = name_scan (current_stat_info.file_name, false)) != NULL)
&& (name = name_scan (current_stat_info.file_name)) != NULL)
{
struct stat s;
@@ -181,7 +181,6 @@ update_archive (void)
}
tar_stat_destroy (&current_stat_info);
xheader_destroy (&extended_header);
previous_status = status;
}

View File

@@ -1,10 +1,10 @@
/* Charset handling for GNU tar.
Copyright (C) 2004 Free Software Foundation, Inc.
Copyright (C) 2004, 2006, 2007 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 2, or (at your option) any later
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
@@ -28,7 +28,7 @@
# define ICONV_CONST
#endif
#ifndef HAVE_ICONV
#ifndef HAVE_ICONV
# undef iconv_open
# define iconv_open(tocode, fromcode) ((iconv_t) -1)
@@ -39,7 +39,7 @@
# undef iconv_close
# define iconv_close(cd) 0
#endif
#endif
@@ -88,11 +88,10 @@ utf8_convert (bool to_utf, char const *input, char **output)
bool
string_ascii_p (const char *str)
string_ascii_p (char const *p)
{
const unsigned char *p = (const unsigned char *)str;
for (; *p; p++)
if (*p > 127)
if (*p & ~0x7f)
return false;
return true;
}

View File

@@ -1,10 +1,10 @@
/* POSIX extended headers for tar.
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2007 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 2, or (at your option) any later
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
@@ -22,7 +22,6 @@
#include <hash.h>
#include <inttostr.h>
#include <quotearg.h>
#include <stpcpy.h>
#include "common.h"
@@ -35,7 +34,6 @@ static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
/* Used by xheader_finish() */
static void code_string (char const *string, char const *keyword,
struct xheader *xhdr);
static void extended_header_init (void);
/* Number of global headers written so far. */
static size_t global_header_count;
@@ -157,7 +155,7 @@ xheader_list_destroy (struct keyword_list **root)
static void
xheader_set_single_keyword (char *kw)
{
USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw));
USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet implemented"), kw));
}
static void
@@ -225,7 +223,7 @@ xheader_set_option (char *string)
to the result of the basename
utility on the translated file name.
%p The process ID of the pax process.
%n The value of the 3rd argument.
%n The value of the 3rd argument.
%% A '%' character. */
char *
@@ -264,7 +262,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
case 'f':
if (st)
{
base = base_name (st->orig_file_name);
base = last_component (st->orig_file_name);
len += strlen (base) - 2;
}
break;
@@ -331,7 +329,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
}
free (dirp);
/* Do not allow it to end in a slash */
while (q > buf && ISSLASH (q[-1]))
q--;
@@ -405,7 +403,7 @@ xheader_write (char type, char *name, struct xheader *xhdr)
}
void
xheader_write_global (void)
xheader_write_global (struct xheader *xhdr)
{
char *name;
struct keyword_list *kp;
@@ -413,12 +411,11 @@ xheader_write_global (void)
if (!keyword_global_override_list)
return;
extended_header_init ();
xheader_init (xhdr);
for (kp = keyword_global_override_list; kp; kp = kp->next)
code_string (kp->value, kp->pattern, &extended_header);
xheader_finish (&extended_header);
xheader_write (XGLTYPE, name = xheader_ghdr_name (),
&extended_header);
code_string (kp->value, kp->pattern, xhdr);
xheader_finish (xhdr);
xheader_write (XGLTYPE, name = xheader_ghdr_name (), xhdr);
free (name);
}
@@ -430,7 +427,7 @@ struct xhdr_tab
char const *keyword;
void (*coder) (struct tar_stat_info const *, char const *,
struct xheader *, void const *data);
void (*decoder) (struct tar_stat_info *, char const *, size_t);
void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
bool protect;
};
@@ -478,17 +475,19 @@ xheader_protected_keyword_p (const char *keyword)
/* Decode a single extended header record, advancing *PTR to the next record.
Return true on success, false otherwise. */
static bool
decode_record (char **ptr,
decode_record (struct xheader *xhdr,
char **ptr,
void (*handler) (void *, char const *, char const *, size_t),
void *data)
{
char *start = *ptr;
char *p = start;
unsigned long int len;
uintmax_t u;
size_t len;
char *len_lim;
char const *keyword;
char *nextp;
size_t len_max = extended_header.buffer + extended_header.size - start;
size_t len_max = xhdr->buffer + xhdr->size - start;
while (*p == ' ' || *p == '\t')
p++;
@@ -501,7 +500,12 @@ decode_record (char **ptr,
}
errno = 0;
len = strtoul (p, &len_lim, 10);
len = u = strtoumax (p, &len_lim, 10);
if (len != u || errno == ERANGE)
{
ERROR ((0, 0, _("Extended header length is out of allowed range")));
return false;
}
if (len_max < len)
{
@@ -551,7 +555,7 @@ run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
{
struct xhdr_tab const *t = locate_handler (kp->pattern);
if (t)
t->decoder (st, kp->value, strlen (kp->value));
t->decoder (st, t->keyword, kp->value, strlen (kp->value));
}
}
@@ -567,10 +571,10 @@ decx (void *data, char const *keyword, char const *value, size_t size)
t = locate_handler (keyword);
if (t)
t->decoder (st, value, size);
t->decoder (st, keyword, value, size);
else
ERROR((0, 0, _("Ignoring unknown extended header keyword `%s'"),
keyword));
WARN((0, 0, _("Ignoring unknown extended header keyword `%s'"),
keyword));
}
void
@@ -579,10 +583,10 @@ xheader_decode (struct tar_stat_info *st)
run_override_list (keyword_global_override_list, st);
run_override_list (global_header_override_list, st);
if (extended_header.size)
if (st->xhdr.size)
{
char *p = extended_header.buffer + BLOCKSIZE;
while (decode_record (&p, decx, st))
char *p = st->xhdr.buffer + BLOCKSIZE;
while (decode_record (&st->xhdr, &p, decx, st))
continue;
}
run_override_list (keyword_override_list, st);
@@ -597,35 +601,35 @@ decg (void *data, char const *keyword, char const *value,
}
void
xheader_decode_global (void)
xheader_decode_global (struct xheader *xhdr)
{
if (extended_header.size)
if (xhdr->size)
{
char *p = extended_header.buffer + BLOCKSIZE;
char *p = xhdr->buffer + BLOCKSIZE;
xheader_list_destroy (&global_header_override_list);
while (decode_record (&p, decg, &global_header_override_list))
while (decode_record (xhdr, &p, decg, &global_header_override_list))
continue;
}
}
static void
extended_header_init (void)
void
xheader_init (struct xheader *xhdr)
{
if (!extended_header.stk)
if (!xhdr->stk)
{
extended_header.stk = xmalloc (sizeof *extended_header.stk);
obstack_init (extended_header.stk);
xhdr->stk = xmalloc (sizeof *xhdr->stk);
obstack_init (xhdr->stk);
}
}
void
xheader_store (char const *keyword, struct tar_stat_info const *st,
xheader_store (char const *keyword, struct tar_stat_info *st,
void const *data)
{
struct xhdr_tab const *t;
if (extended_header.buffer)
if (st->xhdr.buffer)
return;
t = locate_handler (keyword);
if (!t || !t->coder)
@@ -633,22 +637,20 @@ xheader_store (char const *keyword, struct tar_stat_info const *st,
if (xheader_keyword_deleted_p (keyword)
|| xheader_keyword_override_p (keyword))
return;
extended_header_init ();
t->coder (st, keyword, &extended_header, data);
xheader_init (&st->xhdr);
t->coder (st, keyword, &st->xhdr, data);
}
void
xheader_read (union block *p, size_t size)
xheader_read (struct xheader *xhdr, union block *p, size_t size)
{
size_t j = 0;
size_t nblocks;
free (extended_header.buffer);
xheader_init (xhdr);
size += BLOCKSIZE;
extended_header.size = size;
nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE;
extended_header.buffer = xmalloc (size + 1);
extended_header.buffer[size] = '\0';
xhdr->size = size;
xhdr->buffer = xmalloc (size + 1);
xhdr->buffer[size] = '\0';
do
{
@@ -657,7 +659,7 @@ xheader_read (union block *p, size_t size)
if (len > BLOCKSIZE)
len = BLOCKSIZE;
memcpy (&extended_header.buffer[j], p->buffer, len);
memcpy (&xhdr->buffer[j], p->buffer, len);
set_next_block_after (p);
p = find_next_block ();
@@ -728,39 +730,39 @@ xheader_destroy (struct xheader *xhdr)
/* Buildable strings */
static uintmax_t string_length;
void
xheader_string_begin ()
xheader_string_begin (struct xheader *xhdr)
{
string_length = 0;
xhdr->string_length = 0;
}
void
xheader_string_add (char const *s)
xheader_string_add (struct xheader *xhdr, char const *s)
{
if (extended_header.buffer)
if (xhdr->buffer)
return;
extended_header_init ();
string_length += strlen (s);
x_obstack_grow (&extended_header, s, strlen (s));
xheader_init (xhdr);
xhdr->string_length += strlen (s);
x_obstack_grow (xhdr, s, strlen (s));
}
void
xheader_string_end (char const *keyword)
bool
xheader_string_end (struct xheader *xhdr, char const *keyword)
{
size_t len;
size_t p;
size_t n = 0;
uintmax_t len;
uintmax_t p;
uintmax_t n = 0;
size_t size;
char nbuf[UINTMAX_STRSIZE_BOUND];
char const *np;
char *cp;
if (extended_header.buffer)
return;
extended_header_init ();
if (xhdr->buffer)
return false;
xheader_init (xhdr);
len = strlen (keyword) + string_length + 3; /* ' ' + '=' + '\n' */
len = strlen (keyword) + xhdr->string_length + 3; /* ' ' + '=' + '\n' */
do
{
@@ -771,14 +773,24 @@ xheader_string_end (char const *keyword)
while (n != p);
p = strlen (keyword) + n + 2;
x_obstack_blank (&extended_header, p);
x_obstack_1grow (&extended_header, '\n');
cp = obstack_next_free (extended_header.stk) - string_length - p - 1;
memmove (cp + p, cp, string_length);
size = p;
if (size != p)
{
ERROR ((0, 0,
_("Generated keyword/value pair is too long (keyword=%s, length=%s)"),
keyword, nbuf));
obstack_free (xhdr->stk, obstack_finish (xhdr->stk));
return false;
}
x_obstack_blank (xhdr, p);
x_obstack_1grow (xhdr, '\n');
cp = obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1;
memmove (cp + p, cp, xhdr->string_length);
cp = stpcpy (cp, np);
*cp++ = ' ';
cp = stpcpy (cp, keyword);
*cp++ = '=';
return true;
}
@@ -836,8 +848,15 @@ code_time (struct timespec t, char const *keyword, struct xheader *xhdr)
xheader_print (xhdr, keyword, code_timespec (t, buf));
}
static bool
decode_time (struct timespec *ts, char const *arg, char const *keyword)
enum decode_time_status
{
decode_time_success,
decode_time_range,
decode_time_bad_header
};
static enum decode_time_status
_decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
time_t s;
unsigned long int ns = 0;
@@ -853,21 +872,21 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
intmax_t i = strtoimax (arg, &arg_lim, 10);
if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
goto out_of_range;
return decode_time_range;
s = i;
}
else
{
uintmax_t i = strtoumax (arg, &arg_lim, 10);
if (TYPE_MAXIMUM (time_t) < i)
goto out_of_range;
return decode_time_range;
s = i;
}
p = arg_lim;
if (errno == ERANGE)
goto out_of_range;
return decode_time_range;
if (*p == '.')
{
@@ -895,7 +914,7 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
if (ns != 0)
{
if (s == TYPE_MINIMUM (time_t))
goto out_of_range;
return decode_time_range;
s--;
ns = BILLION - ns;
}
@@ -906,20 +925,34 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
ts->tv_sec = s;
ts->tv_nsec = ns;
return true;
return decode_time_success;
}
}
ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
keyword, arg));
return false;
out_of_range:
out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
TYPE_MAXIMUM (time_t));
return false;
return decode_time_bad_header;
}
static bool
decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
switch (_decode_time (ts, arg, keyword))
{
case decode_time_success:
return true;
case decode_time_bad_header:
ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
keyword, arg));
return false;
case decode_time_range:
out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
TYPE_MAXIMUM (time_t));
return false;
}
return true;
}
static void
code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
{
@@ -962,6 +995,7 @@ dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
static void
dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
char const *keyword __attribute__ ((unused)),
char const *arg __attribute__ ((unused)),
size_t size __attribute__((unused)))
{
@@ -975,11 +1009,13 @@ atime_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
atime_decoder (struct tar_stat_info *st, char const *arg,
atime_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
struct timespec ts;
if (decode_time (&ts, arg, "atime"))
if (decode_time (&ts, arg, keyword))
st->atime = ts;
}
@@ -991,11 +1027,13 @@ gid_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
gid_decoder (struct tar_stat_info *st, char const *arg,
gid_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), "gid"))
if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), keyword))
st->stat.st_gid = u;
}
@@ -1007,7 +1045,9 @@ gname_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
gname_decoder (struct tar_stat_info *st, char const *arg,
gname_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
decode_string (&st->gname, arg);
@@ -1021,7 +1061,9 @@ linkpath_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
linkpath_decoder (struct tar_stat_info *st, char const *arg,
linkpath_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
decode_string (&st->link_name, arg);
@@ -1035,27 +1077,32 @@ ctime_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
ctime_decoder (struct tar_stat_info *st, char const *arg,
ctime_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
struct timespec ts;
if (decode_time (&ts, arg, "ctime"))
if (decode_time (&ts, arg, keyword))
st->ctime = ts;
}
static void
mtime_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data __attribute__ ((unused)))
struct xheader *xhdr, void const *data)
{
code_time (st->mtime, keyword, xhdr);
struct timespec const *mtime = data;
code_time (mtime ? *mtime : st->mtime, keyword, xhdr);
}
static void
mtime_decoder (struct tar_stat_info *st, char const *arg,
mtime_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
struct timespec ts;
if (decode_time (&ts, arg, "mtime"))
if (decode_time (&ts, arg, keyword))
st->mtime = ts;
}
@@ -1067,7 +1114,9 @@ path_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
path_decoder (struct tar_stat_info *st, char const *arg,
path_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
decode_string (&st->orig_file_name, arg);
@@ -1083,11 +1132,13 @@ size_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
size_decoder (struct tar_stat_info *st, char const *arg,
size_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "size"))
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
st->stat.st_size = u;
}
@@ -1099,11 +1150,13 @@ uid_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
uid_decoder (struct tar_stat_info *st, char const *arg,
uid_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), "uid"))
if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), keyword))
st->stat.st_uid = u;
}
@@ -1115,7 +1168,9 @@ uname_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
uname_decoder (struct tar_stat_info *st, char const *arg,
uname_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
decode_string (&st->uname, arg);
@@ -1129,11 +1184,13 @@ sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
sparse_size_decoder (struct tar_stat_info *st, char const *arg,
sparse_size_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "GNU.sparse.size"))
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
st->stat.st_size = u;
}
@@ -1146,11 +1203,13 @@ sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg,
sparse_numblocks_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, SIZE_MAX, "GNU.sparse.numblocks"))
if (decode_num (&u, arg, SIZE_MAX, keyword))
{
st->sparse_map_size = u;
st->sparse_map = xcalloc (u, sizeof st->sparse_map[0]);
@@ -1167,11 +1226,13 @@ sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
sparse_offset_decoder (struct tar_stat_info *st, char const *arg,
sparse_offset_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "GNU.sparse.offset"))
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
{
if (st->sparse_map_avail < st->sparse_map_size)
st->sparse_map[st->sparse_map_avail].offset = u;
@@ -1190,26 +1251,29 @@ sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg,
sparse_numbytes_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, SIZE_MAX, "GNU.sparse.numbytes"))
if (decode_num (&u, arg, SIZE_MAX, keyword))
{
if (st->sparse_map_avail < st->sparse_map_size)
st->sparse_map[st->sparse_map_avail++].numbytes = u;
else
ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
"GNU.sparse.numbytes", arg));
keyword, arg));
}
}
static void
sparse_map_decoder (struct tar_stat_info *st, char const *arg,
sparse_map_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size __attribute__((unused)))
{
int offset = 1;
static char *keyword = "GNU.sparse.map";
st->sparse_map_avail = 0;
while (1)
@@ -1283,7 +1347,9 @@ dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
dumpdir_decoder (struct tar_stat_info *st, char const *arg,
dumpdir_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size)
{
st->dumpdir = xmalloc (size);
@@ -1298,7 +1364,10 @@ volume_label_coder (struct tar_stat_info const *st, char const *keyword,
}
static void
volume_label_decoder (struct tar_stat_info *st, char const *arg, size_t size)
volume_label_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
decode_string (&volume_label, arg);
}
@@ -1307,15 +1376,17 @@ static void
volume_size_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
off_t v = *(off_t*)data;
code_num (v, keyword, xhdr);
off_t const *v = data;
code_num (*v, keyword, xhdr);
}
static void
volume_size_decoder (struct tar_stat_info *st, char const *arg, size_t size)
volume_size_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg, size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.size"))
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
continued_file_size = u;
}
@@ -1324,25 +1395,64 @@ static void
volume_offset_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
off_t v = *(off_t*)data;
code_num (v, keyword, xhdr);
off_t const *v = data;
code_num (*v, keyword, xhdr);
}
static void
volume_offset_decoder (struct tar_stat_info *st, char const *arg, size_t size)
volume_offset_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg, size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.offset"))
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
continued_file_offset = u;
}
static void
volume_filename_decoder (struct tar_stat_info *st, char const *arg,
size_t size)
volume_filename_decoder (struct tar_stat_info *st,
char const *keyword __attribute__((unused)),
char const *arg,
size_t size __attribute__((unused)))
{
decode_string (&continued_file_name, arg);
}
static void
sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
code_num (st->sparse_major, keyword, xhdr);
}
static void
sparse_major_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
st->sparse_major = u;
}
static void
sparse_minor_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void const *data)
{
code_num (st->sparse_minor, keyword, xhdr);
}
static void
sparse_minor_decoder (struct tar_stat_info *st,
char const *keyword,
char const *arg,
size_t size)
{
uintmax_t u;
if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
st->sparse_minor = u;
}
struct xhdr_tab const xhdr_tab[] = {
{ "atime", atime_coder, atime_decoder, false },
@@ -1359,10 +1469,20 @@ struct xhdr_tab const xhdr_tab[] = {
{ "uname", uname_coder, uname_decoder, false },
/* Sparse file handling */
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
{ "GNU.sparse.name", path_coder, path_decoder,
true },
{ "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
true },
{ "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
true },
{ "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
true },
{ "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
true },
/* tar 1.14 - 1.15.1 keywords. Multiplse instances of these appeared in 'x'
/* tar 1.14 - 1.15.90 keywords. */
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
/* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
headers, and each of them was meaningful. It confilcted with POSIX specs,
which requires that "when extended header records conflict, the last one
given in the header shall take precedence." */
@@ -1370,7 +1490,7 @@ struct xhdr_tab const xhdr_tab[] = {
true },
{ "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
true },
/* tar >=1.16 keyword, introduced to remove the above-mentioned conflict. */
/* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
{ "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
sparse_map_decoder, false },

View File

@@ -1,13 +1,17 @@
Makefile.in
Makefile
argcv.h
argcv.c
*.bz2
*.gz
*.tar
*.gtar
.deps
genfile
Makefile
Makefile.in
argcv.c
argcv.h
atconfig
atlocal
testsuite
genfile
genfile.c
package.m4
testsuite
testsuite.dir
testsuite.log
package.m4

View File

@@ -1,14 +1,14 @@
# Makefile for GNU tar regression tests.
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005 Free Software
# Foundation, Inc.
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
# 2006, 2007 Free Software Foundation, Inc.
# François Pinard <pinard@iro.umontreal.ca>, 1988.
# Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
## 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 2, or (at your option)
## 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,
@@ -46,24 +46,35 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
## ------------ ##
TESTSUITE_AT = \
T-empty.at\
T-null.at\
testsuite.at\
append.at\
append01.at\
append02.at\
chtype.at\
comprec.at\
delete01.at\
delete02.at\
delete03.at\
delete04.at\
delete05.at\
exclude.at\
extrac01.at\
extrac02.at\
extrac03.at\
extrac04.at\
extrac05.at\
extrac06.at\
extrac07.at\
gzip.at\
grow.at\
incremental.at\
incr01.at\
incr02.at\
incr03.at\
incr04.at\
indexfile.at\
ignfail.at\
link01.at\
listed01.at\
@@ -77,22 +88,33 @@ TESTSUITE_AT = \
multiv02.at\
multiv03.at\
multiv04.at\
multiv05.at\
old.at\
options.at\
options02.at\
pipe.at\
recurse.at\
rename01.at\
rename02.at\
rename03.at\
same-order01.at\
same-order02.at\
shortfile.at\
shortupd.at\
shortrec.at\
sparse01.at\
sparse02.at\
sparse03.at\
sparsemv.at\
sparsemvp.at\
spmvp00.at\
spmvp01.at\
spmvp10.at\
truncate.at\
update.at\
volsize.at\
volume.at\
verbose.at\
version.at\
star/gtarfail.at\
star/gtarfail2.at\
@@ -117,6 +139,9 @@ clean-local:
check-local: atconfig atlocal $(TESTSUITE)
$(SHELL) $(TESTSUITE)
check-full:
FULL_TEST=1 $(MAKE) check
#check_SCRIPTS = tar
# Run the test suite on the *installed* tree.
@@ -134,5 +159,5 @@ genfile_SOURCES = genfile.c argcv.c argcv.h
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/lib -I../lib -I$(top_srcdir)/src
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
LDADD = ../lib/libtar.a $(LIBINTL) $(LIB_CLOCK_GETTIME)

52
tests/T-empty.at Normal file
View File

@@ -0,0 +1,52 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# Tar 1.16 coredumped if a filelist file contained empty (zero-length)
# entries
# Reported by: Karl Berry <karl@freefriends.org>
# References: <200610301353.k9UDr1O30680@f7.net>
AT_SETUP([files-from: empty entries])
AT_KEYWORDS([files-from empty])
AT_DATA([file-list],
[jeden
dwa
trzy
])
AT_TAR_CHECK([
AT_SORT_PREREQ
genfile --file jeden
genfile --file dwa
genfile --file trzy
tar cfvT archive ../file-list | sort
],
[0],
[dwa
jeden
trzy
],
[],[],[],[ustar]) # Testing one format is enough
AT_CLEANUP

48
tests/T-null.at Normal file
View File

@@ -0,0 +1,48 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
AT_SETUP([files-from: 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 trzy >> temp
cat temp | tr '\n' '\0' > temp1
echo jeden > file-list
cat temp1 >> file-list
genfile -f "jeden
dwa" || AT_SKIP_TEST
genfile -f trzy
tar cfTv archive file-list | sort
],
[0],
[expout],
[tar: file-list: file name read contains nul character
],[],[],[ustar]) # Testing one format is enough
AT_CLEANUP

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -19,7 +19,7 @@
# 02110-1301, USA.
AT_SETUP([append])
AT_KEYWORDS([append])
AT_KEYWORDS([append append00])
AT_TAR_CHECK([touch file1
touch file2

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2005 Free Software Foundation, Inc.
# Copyright (C) 2005, 2006, 2007 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 2, or (at your option)
# 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,
@@ -26,8 +26,8 @@
# <7231C15EAC2F164CA6DC326D97493C8B36C25D@exchange35.fed.cclrc.ac.uk>
# http://lists.gnu.org/archive/html/bug-tar/2005-02/msg00032.html
AT_SETUP([append01])
AT_KEYWORDS([appending files with long names])
AT_SETUP([appending files with long names])
AT_KEYWORDS([append append01])
m4_define([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_appending_long_file_names_that_run_into_a_limit_of_the_ustar_tarX])

75
tests/append02.at Normal file
View File

@@ -0,0 +1,75 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# Using tar 1.15.x the following equivalent command sets:
#
# 1. tar cf archive file1 file2
# and
# 2. tar cfT archive /dev/null
# tar rf archive file1
# tar rt archive file2
#
# produced different archives (GNU format is assumed). Namely, in the
# second case the mode field of all members, except the first, was truncated
# to lower 3 octets (& 0777).
#
# References:
# <200607210526.AA03440@tamuki.linet.gr.jp>
# http://lists.gnu.org/archive/html/bug-tar/2006-07/msg00029.html
# The test case below verifies that the equivalent create and append commands
# produce binary equivalent archives for all formats.
AT_SETUP([append vs. create])
AT_KEYWORDS([append append02 append-gnu])
AT_TAR_CHECK([
genfile --file file1
genfile --file file2
# Make sure file timestamps in the archive will not differ
MTIME="--mtime=@0"
# For PAX archives, we need to make sure extended header names are
# reproducible and that their contents won't change with time
if test $[]TEST_TAR_FORMAT = posix; then
TAR_OPTIONS="$TAR_OPTIONS --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=mtime,delete=atime,delete=ctime"
fi
echo Creating archive.1
tar $MTIME -cf archive.1 file1 file2
echo Creating archive.2
tar $MTIME -cf archive.2 -T /dev/null
tar $MTIME -rf archive.2 file1
tar $MTIME -rf archive.2 file2
echo Comparing archives
cmp archive.1 archive.2
],
[0],
[Creating archive.1
Creating archive.2
Comparing archives
])
AT_CLEANUP
# End of append02.at

View File

@@ -1,7 +1,33 @@
# @configure_input@ -*- shell-script -*-
# Configurable variable values for tar test suite.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
PATH=@abs_builddir@:@abs_top_builddir@/src:@abs_top_builddir@/build-aux:$top_srcdir:$srcdir:$PATH
PATH=@abs_builddir@:@abs_top_builddir@/src:@abs_top_srcdir@/build-aux:$top_srcdir:$srcdir:$PATH
XFAILFILE=$abs_builddir/.badversion
trap "test -r $XFAILFILE && cat $XFAILFILE; exit $?" 1 2 13 15
TEST_DATA_URL=ftp://download.gnu.org.ua/pub/tests/tar
if test -z "$TEST_DATA_DIR"; then
TEST_DATA_DIR=$abs_builddir
fi
STAR_DATA_URL=ftp://ftp.berlios.de/pub/star/testscripts
if test -z "$STAR_TESTSCRIPTS"; then
STAR_TESTSCRIPTS=$TEST_DATA_DIR
fi
# tarball_prereq file sum dir url
tarball_prereq() {
if test -d "$3"; then
if test -r $3/$1; then
:
elif test -n "$FULL_TEST"; then
wget -q --directory-prefix=$3 $4/$1
fi
fi
echo "$2 $3/$1" | md5sum --status --check - >/dev/null 2>&1
}

73
tests/chtype.at Normal file
View File

@@ -0,0 +1,73 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# Description: Incremental restore malfunctions if an archive member
# changes type before restoration, e.g. from directory to file or vice
# versa.
# Reported by: Wolfram Kleff <bugreport@wkleff.intergenia.de>
# References: <200605101232.25031.bugreport@wkleff.intergenia.de>
AT_SETUP([changed file types in incrementals])
AT_KEYWORDS([incremental chtype])
AT_TAR_CHECK([
AT_SORT_PREREQ
AT_TAR_MKHIER([directory/b/c],[x])
mkdir directory/a
genfile --file directory/a/a
echo First backup
tar --create --file=archive.1 --listed-incremental=db.1 directory
sleep 2
# Remove directory b and create a file with this name.
# Previous versions were not able to restore over this file.
rm -r directory/b
genfile --file directory/b
genfile --file directory/a/b
echo Second backup
tar --create --file=archive.2 --listed-incremental=db.2 directory
# Delete a
rm -r directory
echo Restore archive.1
tar -xf archive.1 --listed-incremental=/dev/null
echo Restore archive.2
tar -xf archive.2 --listed-incremental=/dev/null
find directory | sort
],
[0],
[First backup
Second backup
Restore archive.1
Restore archive.2
directory
directory/a
directory/a/a
directory/a/b
directory/b
],[],[],[],[gnu, oldgnu, posix])
AT_CLEANUP
# End of chtype.at

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -24,7 +24,7 @@ AT_KEYWORDS([comprec])
AT_TAR_CHECK([
AT_GZIP_PREREQ
genfile --length 10240 > file1
genfile --length 10240 --file file1
echo "separator"
tar cfz archive file1
echo "separator"
@@ -38,4 +38,4 @@ separator
file1
])
AT_CLEANUP
AT_CLEANUP

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -24,8 +24,8 @@ AT_SETUP([deleting a member after a big one])
AT_KEYWORDS([delete delete01])
AT_TAR_CHECK([
genfile -l 50000 > file1
genfile -l 1024 > file2
genfile -l 50000 --file file1
genfile -l 1024 --file file2
tar cf archive file1 file2
tar f archive --delete file2
tar tf archive],

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2005, 2007 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 2, or (at your option)
# 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,
@@ -24,7 +24,7 @@ AT_SETUP([deleting a member from stdin archive])
AT_KEYWORDS([delete delete02])
AT_TAR_CHECK([
genfile -l 3073 -p zeros > 1
genfile -l 3073 -p zeros --file 1
cp 1 2
cp 2 3
tar cf archive 1 2 3

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2007 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 2, or (at your option)
# 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,

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -24,16 +24,16 @@ AT_SETUP([deleting a large last member])
AT_KEYWORDS([delete delete04])
AT_TAR_CHECK([
genfile -l 3 >file1
genfile -l 5 >file2
genfile -l 3 >file3
genfile -l 6 >file4
genfile -l 24 >file5
genfile -l 13 >file6
genfile -l 1385 >file7
genfile -l 30 >file8
genfile -l 10 >file9
genfile -l 256000 >file10
genfile -l 3 -f file1
genfile -l 5 -f file2
genfile -l 3 -f file3
genfile -l 6 -f file4
genfile -l 24 -f file5
genfile -l 13 -f file6
genfile -l 1385 -f file7
genfile -l 30 -f file8
genfile -l 10 -f file9
genfile -l 256000 -f file10
tar cf archive file1 file2 file3 file4 file5 file6 file7 file8 file9 file10
tar f archive --delete file10
tar tf archive

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -28,8 +28,8 @@ AT_SETUP([deleting non-existing member])
AT_KEYWORDS([delete delete05])
AT_TAR_CHECK([
genfile -l 1024 > en
genfile -l 1024 > to
genfile -l 1024 -f en
genfile -l 1024 -f to
tar cf archive en to
# Make sure we don't use bogus blocking factor.

163
tests/exclude.at Normal file
View File

@@ -0,0 +1,163 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2007 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.
# Test the functioning of --exclude-caches and --exclude-tag option families
AT_SETUP([exclude])
AT_KEYWORDS([exclude])
AT_TAR_CHECK([
AT_SORT_PREREQ
mkdir dir
echo blues > dir/blues
echo jazz > dir/jazz
mkdir dir/folk
echo tagfile > dir/folk/tagfile
echo sanjuan > dir/folk/sanjuan
mkdir dir/rock
echo "Signature: 8a477f597d28d172789f06886806bc55" > dir/rock/CACHEDIR.TAG
echo "test" > dir/rock/file
for option in exclude-caches exclude-caches-under exclude-caches-all
do
echo OPTION $option
tar -cf archive.tar --$option -v dir 2>err | sort
cat err
echo ARCHIVE
tar tf archive.tar | sort
done
for option in exclude-tag exclude-tag-under exclude-tag-all
do
echo OPTION $option
tar -cf archive.tar --${option}=tagfile -v dir 2>err | sort
cat err
echo ARCHIVE
tar tf archive.tar | sort
done
],
[0],
[OPTION exclude-caches
dir/
dir/blues
dir/folk/
dir/folk/sanjuan
dir/folk/tagfile
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
tar: dir/rock/: contains a cache directory tag CACHEDIR.TAG; contents not dumped
ARCHIVE
dir/
dir/blues
dir/folk/
dir/folk/sanjuan
dir/folk/tagfile
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
OPTION exclude-caches-under
dir/
dir/blues
dir/folk/
dir/folk/sanjuan
dir/folk/tagfile
dir/jazz
dir/rock/
tar: dir/rock/: contains a cache directory tag CACHEDIR.TAG; contents not dumped
ARCHIVE
dir/
dir/blues
dir/folk/
dir/folk/sanjuan
dir/folk/tagfile
dir/jazz
dir/rock/
OPTION exclude-caches-all
dir/
dir/blues
dir/folk/
dir/folk/sanjuan
dir/folk/tagfile
dir/jazz
tar: dir/rock/: contains a cache directory tag CACHEDIR.TAG; directory not dumped
ARCHIVE
dir/
dir/blues
dir/folk/
dir/folk/sanjuan
dir/folk/tagfile
dir/jazz
OPTION exclude-tag
dir/
dir/blues
dir/folk/
dir/folk/tagfile
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
dir/rock/file
tar: dir/folk/: contains a cache directory tag tagfile; contents not dumped
ARCHIVE
dir/
dir/blues
dir/folk/
dir/folk/tagfile
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
dir/rock/file
OPTION exclude-tag-under
dir/
dir/blues
dir/folk/
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
dir/rock/file
tar: dir/folk/: contains a cache directory tag tagfile; contents not dumped
ARCHIVE
dir/
dir/blues
dir/folk/
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
dir/rock/file
OPTION exclude-tag-all
dir/
dir/blues
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
dir/rock/file
tar: dir/folk/: contains a cache directory tag tagfile; directory not dumped
ARCHIVE
dir/
dir/blues
dir/jazz
dir/rock/
dir/rock/CACHEDIR.TAG
dir/rock/file
],
[],[],[],[ustar])
AT_CLEANUP

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -20,7 +20,7 @@
# There was a diagnostic when directory already exists.
AT_SETUP([extract01])
AT_SETUP([extract over an existing directory])
AT_KEYWORDS([extract extract01])
AT_TAR_CHECK([

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -21,7 +21,7 @@
# Could not extract symlinks over an existing file.
AT_SETUP([extracting symlinks over an existing file])
AT_KEYWORDS([extract extract02])
AT_KEYWORDS([extract extract02 symlink])
# FIXME: Skip if symlinks are not supported on the system

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2007 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 2, or (at your option)
# 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,

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -21,9 +21,10 @@
# Check for fnmatch problems in glibc 2.1.95.
AT_SETUP([extract + fnmatch])
AT_KEYWORDS([extract extract04])
AT_KEYWORDS([extract extract04 fnmatch])
AT_TAR_CHECK([
AT_SORT_PREREQ
touch file1
mkdir directory
mkdir directory/subdirectory
@@ -35,7 +36,7 @@ tar -cf archive ./file1 directory
tar -tf archive \
--exclude='./*1' \
--exclude='d*/*1' \
--exclude='d*/s*/*2' | sort 2>/dev/null
--exclude='d*/s*/*2' | sort
],
[0],
[directory/

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -36,11 +36,11 @@ cztery
])
AT_TAR_CHECK([
genfile --length 118 > jeden
genfile --length 223 > dwa
genfile --length 517 > trzy
genfile --length 118 --file jeden
genfile --length 223 --file dwa
genfile --length 517 --file trzy
genfile --sparse --file sparsefile 0 ABCD 1M EFGH 2000K IJKL
genfile --length 110 > cztery
genfile --length 110 --file cztery
tar cf archive jeden dwa trzy cztery || exit 1

72
tests/extrac06.at Normal file
View File

@@ -0,0 +1,72 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# The bug occurs when extracting from a tarfile a directory when the directory
# already exists and the version in the tarfile has more permissive
# permissions than your umask. In this case, the permissions of the
# existing directory will toggle between the version which complies with
# your umask (which would be correct, without -p) and the version from the
# tarfile.
#
# Reported by: Ian Jackson <iwj@ubuntu.com>
#
# References: <17461.519.640947.664400@davenant.relativity.greenend.org.uk>
#
AT_SETUP([mode of extracted directories])
AT_KEYWORDS([extract extract06 directory mode])
AT_TAR_CHECK([
# Force umask
umask 022
# Make sure user's umask is honored, even if we are superuser
TAR_OPTIONS="$TAR_OPTIONS --no-same-permissions"
# Create a directory
mkdir directory
chmod 777 directory
genfile --stat=mode:777 directory
# Archive it
tar cf arc directory
# Change its permissions ...
chmod 755 directory
genfile --stat=mode:777 directory
# ... and attempt to restore it twice
tar xf arc directory
genfile --stat=mode:777 directory
tar xf arc directory
genfile --stat=mode:777 directory
# After both restores, the directory mode should be 755
],
[0],
[777
755
755
755
])
AT_CLEANUP

59
tests/extrac07.at Normal file
View File

@@ -0,0 +1,59 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# Tar 1.16 failed to extract archives that have symlinks
# in read-only directories.
#
# Reported-by: Eelco Dolstra <eelco@cs.uu.nl>
# References: <45475D78.8050708@cs.uu.nl>
AT_SETUP([extracting symlinks to a read-only dir])
AT_KEYWORDS([extract extract07 read-only symlink])
AT_TAR_CHECK([
echo Prepare the directory
mkdir dir
genfile -f foo
cd dir
ln -s ../foo .
cd ..
chmod -w dir
echo Create the archive
tar cf archive dir || exit 1
chmod +w dir
echo Extract
mkdir out
tar -C out -xvf archive
],
[0],
[Prepare the directory
Create the archive
Extract
dir/
dir/foo
],
[],[],[ustar]) # Testing one format is enough
AT_CLEANUP

40
tests/grow.at Normal file
View File

@@ -0,0 +1,40 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# Tar should exit with error code 1 (file differs) if any files have
# changed during archiving.
AT_SETUP([grow])
AT_KEYWORDS([grow filechange])
AT_TAR_CHECK([
genfile --file foo --length 50000k
genfile --file baz
genfile --run 'tar -vcf bar foo baz' --checkpoint 10 --length 1024 \
--append foo
],
[1],
[foo
baz
],
[tar: foo: file changed as we read it
])
AT_CLEANUP

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2007 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 2, or (at your option)
# 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,

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2006, 2007 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 2, or (at your option)
# 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,
@@ -24,42 +24,40 @@ AT_SETUP([ignfail])
AT_KEYWORDS([ignfail])
AT_TAR_CHECK([
if test -w / ; then
# The test is meaningless for super-user.
AT_SKIP_TEST
else
touch file
mkdir directory
touch directory/file
# The test is meaningless for super-user.
AT_UNPRIVILEGED_PREREQ
echo 1>&2 -----
chmod 000 file
tar cf archive file
status=$?
chmod 600 file
test $status = 2 || exit 1
touch file
mkdir directory
touch directory/file
echo 1>&2 -----
chmod 000 file
tar cf archive --ignore-failed-read file || exit 1
status=$?
chmod 600 file
test $status = 0 || exit 1
echo 1>&2 -----
chmod 000 file
tar cf archive file
status=$?
chmod 600 file
test $status = 2 || exit 1
echo 1>&2 -----
chmod 000 directory
tar cf archive directory
status=$?
chmod 700 directory
test $status = 2 || exit 1
echo 1>&2 -----
chmod 000 file
tar cf archive --ignore-failed-read file || exit 1
status=$?
chmod 600 file
test $status = 0 || exit 1
echo 1>&2 -----
chmod 000 directory
tar cf archive --ignore-failed-read directory || exit 1
status=$?
chmod 700 directory
test $status = 0
fi
echo 1>&2 -----
chmod 000 directory
tar cf archive directory
status=$?
chmod 700 directory
test $status = 2 || exit 1
echo 1>&2 -----
chmod 000 directory
tar cf archive --ignore-failed-read directory || exit 1
status=$?
chmod 700 directory
test $status = 0
],
[0],
[],

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2005 Free Software Foundation, Inc.
# Copyright (C) 2005, 2007 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 2, or (at your option)
# 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,

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2005 Free Software Foundation, Inc.
# Copyright (C) 2005, 2007 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 2, or (at your option)
# 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,

80
tests/incr03.at Normal file
View File

@@ -0,0 +1,80 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# Description:
# Previous versions checked only mtime/ctime of directories during
# incremental backups. As a result, it sufficed to rename a single file
# to get full dump of the directory where it resided. Since v.1.15.91
# tar checks directory contents as well, so in this case only the renamed
# file is dumped.
AT_SETUP([renamed files in incrementals])
AT_KEYWORDS([incremental incr03 rename])
AT_TAR_CHECK([
AT_SORT_PREREQ
mkdir directory
genfile --file=directory/x
genfile --file=directory/y
sleep 1
tar -cf archive.1 -g db directory
mv directory/x directory/z
tar -cf archive.2 -g db directory
mv directory orig
echo Listing of archive.1
tar -tf archive.1 | sort
echo Listing of archive.2
tar -tf archive.2 | sort
echo Directory after first restore
tar -xf archive.1 -g db
find directory | sort
echo Directory after second restore
tar -xf archive.2 -g db
find directory | sort
],
[0],
[Listing of archive.1
directory/
directory/x
directory/y
Listing of archive.2
directory/
directory/z
Directory after first restore
directory
directory/x
directory/y
Directory after second restore
directory
directory/y
directory/z
],[],[],[],[gnu, oldgnu, posix])
AT_CLEANUP
# End of incr03.at

65
tests/incr04.at Normal file
View File

@@ -0,0 +1,65 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 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.
# Description: Rewritten incremental backup support (2006-05-08)
# missed initialization of all struct directory members in make_directory,
# which lead to random core dumps.
# Reported by Sergey Myasnikov <tigra@sw.ru>. This testcase uses original
# script provided by him.
# References: <1148669592.5127.81.camel@tigra.sw.ru>
# http://lists.gnu.org/archive/html/bug-tar/2006-05/msg00038.html
AT_SETUP([proper icontents initialization])
AT_KEYWORDS([incremental incr04 icontents])
m4_define([NAME_PREFIX],[a/b/one_31_chars_long_file_name_])
AT_TAR_CHECK([
AT_TAR_MKHIER(a/b)
awk 'BEGIN {
for (i=1;i<=142;i++)
printf("NAME_PREFIX[%03d]\n", i);
}' < /dev/null | genfile --files-from -
sleep 1
echo "Initial dump"
tar cvf a0.tar -g a.sna a
mv a/b a/c
echo "Incremental dump"
tar cvf a1.tar -g a.sna a
],
[0],
[Initial dump
a/
a/b/
m4_for(I,1,142,1,[NAME_PREFIX[]m4_if(m4_len(I),1,00,m4_len(I),2,0)I
])dnl
Incremental dump
a/
a/c/
],
[tar: a/b: Directory is new
tar: a/c: Directory has been renamed from `a/b'
],[],[],[gnu, oldgnu, posix])
AT_CLEANUP
# End of incr04.at

View File

@@ -1,11 +1,11 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2007 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 2, or (at your option)
# 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,

Some files were not shown because too many files have changed in this diff Show More