332 Commits

Author SHA1 Message Date
Sergey Poznyakoff
fb782b023f Updated 2004-12-20 13:59:15 +00:00
Sergey Poznyakoff
8d44c6b51e Added to the repository 2004-12-20 13:56:41 +00:00
Sergey Poznyakoff
c575787495 Removed 2004-12-20 13:56:31 +00:00
Sergey Poznyakoff
71850c6ab3 Document quicktest.sh 2004-12-20 13:55:37 +00:00
Sergey Poznyakoff
fa87656256 Distribute star/quicktest.sh 2004-12-20 13:55:22 +00:00
Sergey Poznyakoff
7c3510b40d (update_po): Give -r to wget. Always remove index.html
Ignore alloca-opt module (it duplicates alloca)
2004-12-20 13:55:06 +00:00
Sergey Poznyakoff
5f1e6a6a3b Raised version number to 1.15 2004-12-20 13:54:01 +00:00
Sergey Poznyakoff
aa600ee769 Updated 2004-12-18 20:14:34 +00:00
Sergey Poznyakoff
bf2b8556e8 Updated 2004-12-18 20:09:55 +00:00
Sergey Poznyakoff
8263cc7bc0 Added delete05.at 2004-12-18 20:08:56 +00:00
Sergey Poznyakoff
6af2e16b9b Fixed typo in AT_SETUP 2004-12-18 20:08:11 +00:00
Sergey Poznyakoff
664ec232d4 Test deletion of non-existing members 2004-12-18 20:07:59 +00:00
Sergey Poznyakoff
90b1e24487 (decode_options): Ignore --seek if used with --delete.
Delete.c is based on the assumption that the archive is being
actually read, not lseeked.
2004-12-18 20:07:04 +00:00
Sergey Poznyakoff
94f7d4e7c1 Document auto-detection of compressed archive formats. 2004-12-18 20:06:39 +00:00
Sergey Poznyakoff
6323ff0880 Updated 2004-12-18 20:06:18 +00:00
Sergey Poznyakoff
7b29b10847 Updated 2004-12-17 16:12:01 +00:00
Sergey Poznyakoff
e6a67c2eb5 (delete_archive_members): Bugfix: when
attempting to delete an unexisting member, the last
blocking_factor blocks were zeroed.
2004-12-17 16:10:36 +00:00
Paul Eggert
2e7378e819 * TODO: Mention sub-second resolution, lutimes, lchmod. 2004-12-14 19:07:44 +00:00
Paul Eggert
849ec50941 Mention sub-second resolution, lutimes, lchmod. 2004-12-14 19:07:20 +00:00
Paul Eggert
889b8a1046 Remove unnecessary entries from lib/.cvsignore and m4/.cvsignore. 2004-11-28 06:41:15 +00:00
Paul Eggert
2f034ae71b Remove pathmax.h, xstrdup.c. 2004-11-28 06:40:35 +00:00
Paul Eggert
bf8852627a Remove malloc.m4, pathmax.m4, realloc.m4. 2004-11-28 06:40:03 +00:00
Paul Eggert
73b52b1b9b Adjust to recent gnulib changes. 2004-11-28 06:32:01 +00:00
Sergey Poznyakoff
c69d2f6539 Updated 2004-11-26 19:12:09 +00:00
Sergey Poznyakoff
412fbeb90d Updated 2004-11-26 19:10:20 +00:00
Sergey Poznyakoff
322114744f (tar_checksum): New function 2004-11-26 19:09:48 +00:00
Sergey Poznyakoff
b5db978830 (tar_checksum): New function 2004-11-26 19:09:26 +00:00
Sergey Poznyakoff
4674867a23 (hit_eof): Changed type to boolean
(read_full_records,reading_from_pipe): New variables
(check_compressed_archive,open_compressed_archive): New functions
(open_archive): Autodetect compressed archives and act accodingly.
Set reading_from_pipe. This fixes contraversial set of changes
introduced 2004-05-11,2004-03-22.
2004-11-26 19:08:58 +00:00
Sergey Poznyakoff
d5f1626556 Updated 2004-11-26 19:08:25 +00:00
Sergey Poznyakoff
c8b0fd28c2 Concatenate multivolume archives 2004-11-26 19:08:14 +00:00
Sergey Poznyakoff
dcdbe18968 Raised version number to 1.14.91 2004-11-26 19:07:42 +00:00
Sergey Poznyakoff
6c941e0826 Updated 2004-11-26 15:55:32 +00:00
Sergey Poznyakoff
ff989f4b84 Updated 2004-11-16 11:03:05 +00:00
Sergey Poznyakoff
b2a65edf5c Fixed -o semantics. Thanks Jean Delvare <khali@linux-fr.org> 2004-11-16 11:02:45 +00:00
Sergey Poznyakoff
d305c258bf Updated 2004-10-25 15:59:44 +00:00
Sergey Poznyakoff
8ff11f27c1 Use locale_charset() from gnulib 2004-10-25 15:57:48 +00:00
Sergey Poznyakoff
5dee0c1348 (options): Use OPTION_NO_TRANS 2004-10-25 15:57:29 +00:00
Sergey Poznyakoff
b55daca933 (decode_header): Set uname/gname to NULL if their header counterparts are empty 2004-10-25 15:56:57 +00:00
Sergey Poznyakoff
f218c29b13 (LDADD): Add LIBICONV 2004-10-25 15:56:37 +00:00
Sergey Poznyakoff
1625cc5f67 Initialize SUFFIXES and CLEANFILES since the makefile snippet from localcharset uses '+=' on them. 2004-10-25 15:56:20 +00:00
Sergey Poznyakoff
c0f0d25271 Add localcharset 2004-10-25 15:55:59 +00:00
Sergey Poznyakoff
2ab1422c04 Minor fix 2004-10-25 15:55:27 +00:00
Sergey Poznyakoff
53a80edafc Updated 2004-10-25 15:55:11 +00:00
Sergey Poznyakoff
75284507b3 Updated 2004-10-04 09:33:11 +00:00
Sergey Poznyakoff
9b712b0fc8 Added Bryan Ford 2004-10-04 09:32:22 +00:00
Sergey Poznyakoff
d47a177d3d Added argp-help.c 2004-10-04 09:30:17 +00:00
Sergey Poznyakoff
2c7d98238b (.text): Fixed rule 2004-10-04 09:29:25 +00:00
Sergey Poznyakoff
9e2233007c Updated 2004-10-04 09:27:53 +00:00
Sergey Poznyakoff
06742ec624 New function check_cache_directory(),
called from dump_dir0() if exclude_caches_option is set,
to check for a cache directory tag and exclude the directory
if such a tag is found.
2004-10-04 09:27:13 +00:00
Sergey Poznyakoff
5b56886a72 New variable exclude_caches_option. 2004-10-04 09:26:42 +00:00
Sergey Poznyakoff
5db60955f5 New option --exclude-caches, to exclude
cache directories automatically on archive creation.
Cache directories are directories containing a
standardized tag file, as specified at:
	http://www.brynosaurus.com/cachedir/spec.html
2004-10-04 09:26:25 +00:00
Sergey Poznyakoff
52030539f7 Updated 2004-09-16 13:42:32 +00:00
Sergey Poznyakoff
e370518b43 Minor fix 2004-09-16 13:42:22 +00:00
Sergey Poznyakoff
3cb52ac16a Updated 2004-09-12 12:51:37 +00:00
Sergey Poznyakoff
75bf036edc Normalized use of remove_any_file(). 2004-09-12 12:50:31 +00:00
Sergey Poznyakoff
6cf99ce8ae (parse_opt): Emit warning if -l option is used.
(show_default_settings): REMOTE_SHELL may be undefined
2004-09-12 12:50:06 +00:00
Sergey Poznyakoff
ae3238495d Comment WANT_DIRECTORY_REMOVE_OPTION 2004-09-12 12:49:41 +00:00
Sergey Poznyakoff
33491a8d7c Added 'rtapelib.o: localedir.h' dependency 2004-09-12 12:48:54 +00:00
Sergey Poznyakoff
5fd2daf959 Updated 2004-09-07 18:53:08 +00:00
Sergey Poznyakoff
37ac08b3fe Updated 2004-09-07 18:52:03 +00:00
Sergey Poznyakoff
35cae74c4c Rewritten testsuite in autotest 2004-09-07 18:48:13 +00:00
Sergey Poznyakoff
a1c8c7bd47 Updated 2004-09-07 18:43:26 +00:00
Sergey Poznyakoff
71c05b230c Rewritten for autotest 2004-09-07 18:43:17 +00:00
Sergey Poznyakoff
cf2fa13bc5 (argp_program_version): Modified. 2004-09-07 18:43:05 +00:00
Sergey Poznyakoff
7d6865480e Updated for autotest 2004-09-07 18:42:47 +00:00
Sergey Poznyakoff
cadabfc4c7 Updated 2004-09-07 13:27:39 +00:00
Sergey Poznyakoff
6b401f904a Use genfile instead of mksparse 2004-09-07 13:27:22 +00:00
Sergey Poznyakoff
f3f06e8a71 Removed mksparse 2004-09-07 13:27:14 +00:00
Sergey Poznyakoff
8fed513af1 Integrated into (paxutils) genfile.c 2004-09-07 13:27:05 +00:00
Sergey Poznyakoff
00478f4bd3 Integrated into paxutils. 2004-09-07 13:26:41 +00:00
Sergey Poznyakoff
4ad940344a Install genfile.c from paxutils 2004-09-07 13:26:03 +00:00
Sergey Poznyakoff
b5d9942a35 Updated 2004-09-06 14:30:57 +00:00
Sergey Poznyakoff
c0b641f055 Updated 2004-09-06 14:30:21 +00:00
Sergey Poznyakoff
7347b4f5d5 Started merging with cpio into paxutils. 2004-09-06 14:28:55 +00:00
Sergey Poznyakoff
e3bd2a63a6 Updated 2004-09-03 09:22:20 +00:00
Sergey Poznyakoff
430b139592 Do not depend on any particular ordering of output. 2004-09-03 09:19:32 +00:00
Sergey Poznyakoff
06bb349ca9 Updated 2004-09-02 13:54:24 +00:00
Sergey Poznyakoff
2e419759d1 (usage): Minor fix 2004-09-02 13:53:30 +00:00
Sergey Poznyakoff
da3f3e0b3b Install rmt into rmtdir 2004-09-02 13:53:18 +00:00
Sergey Poznyakoff
a0404319e2 ew option --with-rmt. New configuration variable DEFAULT_RMT_DIR. Removed DEFAULT_RMT_COMMAND. 2004-09-02 13:53:03 +00:00
Sergey Poznyakoff
a2a6547e2d Document the use of -C option in file lists. Document --seek option. 2004-09-02 13:52:40 +00:00
Sergey Poznyakoff
5e30076bfd Updated 2004-09-01 15:10:04 +00:00
Sergey Poznyakoff
7c7da5f79f use genfile instead of dd 2004-09-01 15:09:33 +00:00
Sergey Poznyakoff
d1f3689d96 Raised version number to 1.14.90 2004-09-01 15:08:14 +00:00
Sergey Poznyakoff
ac830291f1 Updated 2004-09-01 15:06:09 +00:00
Sergey Poznyakoff
44283eb6ca Added listed02.sh 2004-09-01 15:06:00 +00:00
Sergey Poznyakoff
4ad0f97e2c New test 2004-09-01 15:05:50 +00:00
Sergey Poznyakoff
d14f101217 (register_individual_file,is_individual_file): New functions. 2004-09-01 15:05:28 +00:00
Sergey Poznyakoff
19335cdfb4 (dump_file0): Fix bug introduced 2004-02-21. 2004-09-01 15:05:09 +00:00
Sergey Poznyakoff
4e4e8c57fd (is_individual_file): New prototype 2004-09-01 15:04:46 +00:00
Sergey Poznyakoff
df6161b9fe Updated 2004-08-31 11:57:09 +00:00
Sergey Poznyakoff
33da1b2f64 Updated 2004-08-31 11:51:58 +00:00
Sergey Poznyakoff
28efbf6944 (unquote_string): Unquote '\a' and '\v'. Reported by Helmut Waitzmann <helmut.waitzmann@web.de> 2004-08-31 11:49:28 +00:00
Sergey Poznyakoff
678a4411ea (main): Call set_start_time() 2004-08-31 11:49:03 +00:00
Sergey Poznyakoff
001e5cf813 Fixed initialization of stat_info->is_sparse 2004-08-31 11:48:51 +00:00
Sergey Poznyakoff
fc264a87a8 (set_start_time, removed_prefixes_p): New prototypes. 2004-08-31 11:48:23 +00:00
Sergey Poznyakoff
68bd7ac50a When computing write rate do not take
into account the time needed to verify the archive(s).
The bug reported by John L. Males <jlmales@yahoo.com>
(set_start_time,compute_duration): New functions.
(print_total_written): Use the result of compute_duration().
(close_archive): Call compute_duration.
2004-08-31 11:48:05 +00:00
Sergey Poznyakoff
3f4f5a4bf4 (removed_prefixes_p): New function 2004-08-31 11:47:02 +00:00
Sergey Poznyakoff
e563240b95 (verify_volume): Call set_next_block_after
if read_header returns HEADER_FAILURE
Destroy and reinitialize content of current_stat_info and
extended_header after each iteration.
Issue a warning if the archive created contains some members
whose file names were stripped off their leading prefixes.
This is a temporary fix of the issue reported by Bdale Garbee
<bdale@gag.com> (Refs: Debian bug 230064, Message-Id
<87n07kyzhi.fsf@rover.gag.com>, Sun, 15 Feb 2004 11:22:17 -0700)
2004-08-31 11:45:55 +00:00
Sergey Poznyakoff
6522c25b8d (sparse_add_map): Fixed improper initializations
of sparse_map_size. We assume that whatever number it contains
describes adequately the current size of sparse_map. The only
number we need to reset is sparse_map_avail.
2004-08-31 11:45:16 +00:00
Sergey Poznyakoff
0ec47c16a9 Updated 2004-08-30 15:18:09 +00:00
Sergey Poznyakoff
b1f2c77860 Fix copy-n-paste errors in the license 2004-08-30 15:16:00 +00:00
Sergey Poznyakoff
607c1bf3b4 Updated 2004-08-19 13:13:37 +00:00
Sergey Poznyakoff
74b3e8ab49 Updated 2004-08-19 13:10:01 +00:00
Sergey Poznyakoff
8771e7c560 Renamed LIBPATH to LIBDIR.
New option -a (--all). Do not start restore unless
-a or patterns are given.
(restore_fs,restore_files): Fixed use of --listed option.
2004-08-19 13:09:37 +00:00
Sergey Poznyakoff
1992ef9496 (test_root): Append / to ROOT_FS unless it already ends in it. 2004-08-19 13:09:16 +00:00
Sergey Poznyakoff
73030de19f Renamed LIBPATH to LIBDIR.
Use ROOT_FS with -C option. Do not send mail
if ADMINISTRATOR is set to NONE.
2004-08-19 13:08:43 +00:00
Sergey Poznyakoff
a5f5e75388 Updated 2004-08-17 16:06:05 +00:00
Sergey Poznyakoff
bd599facc8 Fixed typo 2004-08-17 16:05:03 +00:00
Paul Eggert
7f27104062 In bootstrap, set LC_ALL=C and save some more gnulib m4 files. 2004-08-12 20:24:51 +00:00
Paul Eggert
e24d4efed0 Set LC_ALL=C so that file names sort consistently.
Prefer the gnulib copies of gettext.m4, glibc21.m4,
lib-ld.m4, lib-prefix.m4, po.m4 too.
2004-08-12 20:24:13 +00:00
Paul Eggert
a418ef678e Merge argp, getopt, xalloc changes from gnulib. 2004-08-12 18:37:09 +00:00
Paul Eggert
83acd3c604 Remove; gnulib now works unpatched. 2004-08-12 18:35:24 +00:00
Paul Eggert
303132dcdc Adjust to changes to gnulib xalloc module.
(extr_init): Remove assignment to xalloc_fail_func; no longer needed.
(xalloc_die): New function.
2004-08-12 18:34:40 +00:00
Paul Eggert
3848b93af6 Add fnmatch.h, getopt_.h, sysexit.h, xalloc-die.c. 2004-08-12 18:34:18 +00:00
Paul Eggert
93becc4f52 (_getopt_long_only_r): Remove check.
gl_ARGP now does this for us.
2004-08-12 18:33:13 +00:00
Paul Eggert
03092879ac (gnulib_modules): Add xalloc-die. 2004-08-12 18:32:54 +00:00
Sergey Poznyakoff
38f39174f2 Updated 2004-08-10 11:24:25 +00:00
Sergey Poznyakoff
1c0a13aade Added multiv03.sh 2004-08-10 11:17:58 +00:00
Sergey Poznyakoff
2d041189aa (flush_write): Limit filenames
of the members that straddle multivolume archive
boundary to 100 characters.
2004-08-10 11:17:16 +00:00
Sergey Poznyakoff
f6c0aee290 Updated 2004-08-09 11:26:16 +00:00
Sergey Poznyakoff
54e4a0df65 Rearranged leading comments. Added explicit references to original report messages wherever available. 2004-08-09 11:25:15 +00:00
Sergey Poznyakoff
34ff480be9 Added extrac05.sh 2004-08-09 11:24:31 +00:00
Sergey Poznyakoff
260acce7a3 (read_and): Call decode_header before calling skip_member()
(skip_member): Use is_sparse field to determine if the
member is a sparse file.
2004-08-09 11:24:06 +00:00
Sergey Poznyakoff
5a8a98cffe Updated 2004-08-08 14:22:00 +00:00
Sergey Poznyakoff
320298c663 Added link01.sh 2004-08-08 14:21:38 +00:00
Sergey Poznyakoff
4f3e70b0f9 New file 2004-08-08 14:21:07 +00:00
Sergey Poznyakoff
c50565d965 Improved compatibility with 1.13.25 2004-08-08 14:20:17 +00:00
Sergey Poznyakoff
df2c78e32b Extended --update-po option to take an optional argument specifying the po file to update. 2004-08-08 14:19:49 +00:00
Paul Eggert
56389381fc Remove patches/argp.diff; no longer needed. 2004-08-07 06:50:56 +00:00
Paul Eggert
45a6a18d85 Merge from gnulib; mostly FILESYSTEM_PREFIX_LEN -> FILE_SYSTEM_PREFIX_LEN. 2004-08-07 06:37:30 +00:00
Paul Eggert
68ff77508c (purge_directory): Fix format buffer typos in warning strings. 2004-08-07 06:33:59 +00:00
Paul Eggert
43ca8709c0 (parse_opt): FILESYSTEM_PREFIX_LEN -> FILE_SYSTEM_PREFIX_LEN 2004-08-07 06:33:34 +00:00
Paul Eggert
c4e054673b (excluded_name, safer_name_suffix, stripped_prefix_len):
FILESYSTEM_PREFIX_LEN -> FILE_SYSTEM_PREFIX_LEN.
2004-08-07 06:33:07 +00:00
Paul Eggert
df6200e97e (must_be_dot_or_slash): FILESYSTEM_PREFIX_LEN -> FILE_SYSTEM_PREFIX_LEN. 2004-08-07 06:32:41 +00:00
Paul Eggert
9ae5a981fc Include <getcwd.h>.
(extract_archive): Rewrite with new macro IS_ABSOLUTE_FILE_NAME.
(make_directories):
FILESYSTEM_PREFIX_LEN -> FILE_SYSTEM_PREFIX_LEN.
2004-08-07 06:32:12 +00:00
Paul Eggert
7287be445e Remove addext.c, malloc.c, realloc.c. 2004-08-07 06:31:20 +00:00
Paul Eggert
cafa07d966 Don't use valloc; it's buggy on some GNU/Linux systems, and it returns
storage that can't be freed on older BSD systems.
2004-08-03 04:46:37 +00:00
Paul Eggert
9038410bb7 (valloc): Remove. 2004-08-03 04:45:57 +00:00
Paul Eggert
f3da0c26b8 (quote_n, quote): Remove these redundant functions.
(ptr_align): New function, from coreutils/src/system.h.
(page_aligned_alloc): New function.
2004-08-03 04:45:05 +00:00
Paul Eggert
82eff37f6f (page_aligned_alloc): New decl. 2004-08-03 04:44:39 +00:00
Paul Eggert
6869d0f6b3 (diff_init): Don't use valloc; on older or buggy hosts, you can't
free the result.  Use page_aligned_alloc instead.
2004-08-03 04:44:13 +00:00
Paul Eggert
81460a0349 (record_buffer): New var.
(open_archive): Don't use valloc; on older or buggy hosts, you can't
free the result.  Use page_aligned_alloc instead.
Record the pointer to be freed into record_buffer.
(close_archive): Free record_buffer.
2004-08-03 04:43:38 +00:00
Paul Eggert
ae29dcca87 Add getpagesize.m4. 2004-08-03 04:42:53 +00:00
Paul Eggert
ac7c2b7116 Add getpagesize.h. 2004-08-03 04:42:35 +00:00
Paul Eggert
08cba4e4e5 (valloc): Remove check; valloc no longer used. 2004-08-03 04:42:18 +00:00
Paul Eggert
d81b5d6f1e (gnulib_modules): Add getpagesize. 2004-08-03 04:41:48 +00:00
Paul Eggert
55ec665a41 Add fchown-stub.c 2004-07-10 06:51:38 +00:00
Paul Eggert
4ab8cff6b3 * lib/.cvsignore: Add fchown-stub.c. 2004-07-10 06:51:17 +00:00
Paul Eggert
e4afe72b7a src/extract.c (extract_archive): Do not report an error
when hard-linking X to X when X exists.
2004-07-10 06:14:51 +00:00
Paul Eggert
0a3a9744f7 (extract_archive): Do not report an error
when hard-linking X to X when X exists.
2004-07-10 06:13:28 +00:00
Sergey Poznyakoff
ad548198f3 Added Martin Simmons 2004-06-29 10:17:38 +00:00
Sergey Poznyakoff
4f732c1595 Updated 2004-06-29 10:13:14 +00:00
Sergey Poznyakoff
f94cf6216b (gnu_restore): Renamed to purge_directory().
Do not attempt to purge the directory if it is on a different
device and one_file_system_option is set.
2004-06-29 10:11:46 +00:00
Sergey Poznyakoff
44391cb932 (extr_init): Save the device number
of the root device.
(extract_archive): Renamed gnu_restore() to purge_directory().
2004-06-29 10:11:13 +00:00
Sergey Poznyakoff
af15956c4d (root_device): New global.
(gnu_restore): Renamed to purge_directory().
2004-06-29 10:10:26 +00:00
Sergey Poznyakoff
402b50d4d2 Updated 2004-06-29 10:09:52 +00:00
Sergey Poznyakoff
240a4ed90a Updated 2004-06-25 10:33:06 +00:00
Sergey Poznyakoff
6938706958 The actual default for exclude patterns is --no-anchored. Thanks "Felix Natter" <felix.natter@ldc.de> for noticing. 2004-06-25 10:32:44 +00:00
Sergey Poznyakoff
cd2c8d4fbb The actual default for exclude patterns is --no-anchored. Fixed. 2004-06-25 10:32:27 +00:00
Sergey Poznyakoff
421043b6b1 Updated 2004-06-22 09:30:57 +00:00
Sergey Poznyakoff
24aa94e5cf Fixed docstring for --checkpoint option. 2004-06-22 09:30:32 +00:00
Sergey Poznyakoff
8160c0dae9 Fixed several inconsistencies. 2004-06-22 09:30:01 +00:00
Sergey Poznyakoff
53614b3dff Updated 2004-05-19 14:30:21 +00:00
Sergey Poznyakoff
23c2244ddf Updated 2004-05-19 14:28:20 +00:00
Sergey Poznyakoff
ebdf1bc7a6 Determine type of the archive before appending to it. 2004-05-19 14:27:41 +00:00
Sergey Poznyakoff
ba08e339a6 (struct fmttab): Accept 'pax' as alias
for 'posix'
(options): New option -n (--seek).
2004-05-19 14:27:22 +00:00
Sergey Poznyakoff
951b0370df (skip_file): Use seek_archive() if possible. 2004-05-19 14:26:25 +00:00
Sergey Poznyakoff
167f5ba2bc (seek_archive): New function
(seekable_archive): New global.
2004-05-19 14:25:55 +00:00
Sergey Poznyakoff
488430f739 (seek_archive): New function 2004-05-19 14:25:27 +00:00
Sergey Poznyakoff
80c29e6315 Fix typo 2004-05-19 10:59:25 +00:00
Sergey Poznyakoff
432b157a28 Updated 2004-05-19 10:58:04 +00:00
Sergey Poznyakoff
b121917368 (safer_name_suffix): Fixed bug intraduced 2004-05-11. 2004-05-19 10:57:25 +00:00
Sergey Poznyakoff
fa8cb1895c Updated 2004-05-19 10:35:23 +00:00
Sergey Poznyakoff
64759986a9 Document -H option 2004-05-19 10:34:09 +00:00
Sergey Poznyakoff
d4d6c23008 New option -H (short alias to --format) 2004-05-19 10:33:26 +00:00
Sergey Poznyakoff
325a45f0f1 New option --update-po 2004-05-19 10:32:52 +00:00
Sergey Poznyakoff
f41e484f23 Updated 2004-05-16 20:57:53 +00:00
Sergey Poznyakoff
141d267691 Minor formatting fix 2004-05-16 20:56:05 +00:00
Sergey Poznyakoff
3331593d8d Updated 2004-05-16 20:55:18 +00:00
Sergey Poznyakoff
3344bf9380 Minor fix 2004-05-16 20:51:21 +00:00
Sergey Poznyakoff
463d99453f Fix improper use of 'path' word 2004-05-16 20:50:55 +00:00
Sergey Poznyakoff
d2d5d64cb4 Minor fix. 2004-05-16 20:49:53 +00:00
Sergey Poznyakoff
32ebe16224 Updated 2004-05-16 20:48:14 +00:00
Sergey Poznyakoff
a447fd3714 Use argp for command line parsing. 2004-05-16 20:47:47 +00:00
Sergey Poznyakoff
792965270b Check for _getopt_long_only_r and force using included version of getopt if the function is not available. 2004-05-16 20:47:07 +00:00
Sergey Poznyakoff
916019e417 Added to the repository 2004-05-16 20:46:30 +00:00
Sergey Poznyakoff
3ee93d341e Apply patches from 'patches' subdirectory 2004-05-16 20:46:02 +00:00
Sergey Poznyakoff
dd4cef1699 Added to the repository 2004-05-16 09:04:16 +00:00
Sergey Poznyakoff
8286de0946 Updated. 2004-05-13 08:25:51 +00:00
Sergey Poznyakoff
a65779d558 Renamed strip_path_option to strip_components_option 2004-05-13 08:24:32 +00:00
Sergey Poznyakoff
e1a4fea80d Raised version number to 1.14.1 2004-05-13 08:23:47 +00:00
Sergey Poznyakoff
5608be67f7 Renamed --strip-path to --strip-components
Changed improper use of _() to ngettext().
2004-05-13 08:22:28 +00:00
Sergey Poznyakoff
0a79415a97 Updated 2004-05-11 14:25:18 +00:00
Sergey Poznyakoff
f730b47314 Minor correction 2004-05-11 14:24:50 +00:00
Sergey Poznyakoff
48c24ac711 (decode_options): Fixed typo in the comment. 2004-05-11 14:24:23 +00:00
Sergey Poznyakoff
3e8f210904 (open_archive): Removed assignment to read_full_records_option. 2004-05-11 14:23:25 +00:00
Sergey Poznyakoff
ee56bd0d0b (sys_child_open_for_uncompress): Do not
set read_full_records_option: the compressed archive is
likely not to contain integer number of records. Should
the user wish to use reblocking, he may always give tar
-B option. This is a minor improvement over the change
dated 2004-03-22.
2004-05-11 14:17:28 +00:00
Sergey Poznyakoff
ecb338ad8e (safer_name_suffix): (safer_name_suffix): Use "%s"
as the format argument, rather than a possibly-translated variable
string. Patch provided by Jim Meyering  <jim@meyering.net>
2004-05-11 14:12:39 +00:00
Sergey Poznyakoff
ce486a8fd7 Updated 2004-05-11 13:15:18 +00:00
Sergey Poznyakoff
abba83af27 New file 2004-05-11 13:12:56 +00:00
Sergey Poznyakoff
823f96841c Rewritten. Added rules for generating documentation for the project's website. 2004-05-11 13:10:45 +00:00
Sergey Poznyakoff
95256b3c07 Updated 2004-05-11 09:25:59 +00:00
Sergey Poznyakoff
a7109edd94 Added copyleft statement 2004-05-11 09:25:30 +00:00
Sergey Poznyakoff
0500b1ba3e Raised version number to 1.14 2004-05-11 09:25:15 +00:00
Sergey Poznyakoff
e8fa866d3a Updated 2004-05-10 13:50:42 +00:00
Sergey Poznyakoff
3e0962674f Quote TAR_ARCHIVE_FORMATS 2004-05-10 13:48:57 +00:00
Sergey Poznyakoff
3295d54e21 (compare): Fixed argument quoting under eval 2004-05-10 13:48:23 +00:00
Sergey Poznyakoff
be8899e6aa Fixed prerequisite headers for sys/buf.h (needed on FreeBSD) 2004-05-10 13:47:52 +00:00
Sergey Poznyakoff
b5aff8401f Updated 2004-05-10 11:48:07 +00:00
Sergey Poznyakoff
933d42174f Updated 2004-05-10 11:46:56 +00:00
Sergey Poznyakoff
33715a50a3 New option --rmt-command.
(decode_options): Handle --rmt-command. Initialize
rmt_command_option to DEFAULT_RMT_COMMAND.
2004-05-10 11:42:23 +00:00
Sergey Poznyakoff
3be53a3c2f Use rmt_command_option instead of hardcoded "/etc/rmt". 2004-05-10 11:41:43 +00:00
Sergey Poznyakoff
4c004cff39 (read_and): Print block number before
issuing 'Skipping to next header' diagnostics, if
requested by block_number_option.
2004-05-10 11:41:23 +00:00
Sergey Poznyakoff
1c623b11f6 (rmt_command_option): New variable. 2004-05-10 11:40:55 +00:00
Sergey Poznyakoff
898dc536c6 (localedir.h rule): Generate correct DEFAULT_RMT_COMMAND variable. 2004-05-10 11:39:51 +00:00
Sergey Poznyakoff
2b708cb119 Fixed --version output. 2004-05-10 11:38:54 +00:00
Sergey Poznyakoff
c6096f64c5 Fixed --version output.
Fixed initialization of the listing files and printing
the time of the last previous level dump.
2004-05-10 11:38:16 +00:00
Sergey Poznyakoff
b9c6ebab26 Install the scripts only if requested by the configure. 2004-05-10 11:37:54 +00:00
Sergey Poznyakoff
bc07e8cce4 Call gl_AC_TYPE_INTMAX_T. Document
DEFAULT_.* variables. Use DEFAULT_RMT_COMMAND to set
the pathname of the rmt utility.
New option --enable-backup-scripts.
2004-05-10 11:37:31 +00:00
Sergey Poznyakoff
289687bd1c Updated 2004-05-10 11:36:40 +00:00
Sergey Poznyakoff
ee3b833d37 Updated 2004-05-10 08:04:37 +00:00
Sergey Poznyakoff
ad63cd4904 Updated 2004-05-08 22:25:22 +00:00
Sergey Poznyakoff
d58eaa815d Minor fix 2004-05-08 22:22:24 +00:00
Sergey Poznyakoff
f71b35b3f6 Removed 2004-05-08 22:19:40 +00:00
Sergey Poznyakoff
10eef2def8 Updated 2004-05-08 22:18:38 +00:00
Sergey Poznyakoff
07727fe74a Updated 2004-05-08 22:16:17 +00:00
Sergey Poznyakoff
ef87ce7d10 New file 2004-05-08 22:14:52 +00:00
Sergey Poznyakoff
22fae29fb7 New file. Source for backup.sh 2004-05-08 22:14:05 +00:00
Sergey Poznyakoff
981980ac31 Removed 2004-05-08 22:12:18 +00:00
Sergey Poznyakoff
6246fffacd Updated 2004-05-08 22:11:21 +00:00
Sergey Poznyakoff
e128aa980c Updated 2004-05-07 15:04:44 +00:00
Sergey Poznyakoff
21002fe811 Updated 2004-05-07 15:04:10 +00:00
Sergey Poznyakoff
13ac1dcc0f Updated 2004-05-07 15:01:31 +00:00
Sergey Poznyakoff
1695e161be Added copyleft header 2004-05-07 14:59:19 +00:00
Sergey Poznyakoff
66cc5df1c6 Added copyleft header 2004-05-07 14:54:29 +00:00
Sergey Poznyakoff
fc22e70a00 Updated 2004-05-07 14:49:35 +00:00
Sergey Poznyakoff
43d020e35c test if -C works when used with --same-order 2004-05-07 14:48:59 +00:00
Sergey Poznyakoff
6c1654791d (name_gather): Bugfix: Honor single -C with --same-order 2004-05-07 14:46:37 +00:00
Sergey Poznyakoff
4cca5e5887 Updated 2004-05-06 09:26:58 +00:00
Sergey Poznyakoff
24af03768f Updated 2004-05-06 09:16:53 +00:00
Sergey Poznyakoff
d2d8f9ab55 Updated 2004-05-06 09:16:06 +00:00
Sergey Poznyakoff
31e36b1e93 Updated for new directory contents. 2004-05-06 09:15:35 +00:00
Sergey Poznyakoff
6c4dc180dd Added to the repository 2004-05-06 09:14:51 +00:00
Sergey Poznyakoff
0273b1ae09 Removed 2004-05-06 09:14:29 +00:00
Sergey Poznyakoff
640effdebd Check whether date accepts +format argument (for backup scripts). 2004-05-06 09:11:32 +00:00
Sergey Poznyakoff
d21a12cf62 Oops, sorry. Mistakingly added... 2004-05-05 20:49:07 +00:00
Sergey Poznyakoff
6d9cdefe83 Added to the repository 2004-05-05 20:45:36 +00:00
Sergey Poznyakoff
19d51157a5 Updated 2004-05-05 11:56:23 +00:00
Sergey Poznyakoff
4e2d5f2ee8 --utc implies -vv 2004-05-05 11:56:04 +00:00
Sergey Poznyakoff
de5ec134a1 Udated 2004-05-05 11:55:18 +00:00
Sergey Poznyakoff
45399a7e81 Updated 2004-04-28 07:44:41 +00:00
Sergey Poznyakoff
e662d0f367 Make sure ICONV_CONST is defined. AM_ICONV does not define it if it fails to find iconv.h. 2004-04-28 07:44:19 +00:00
Sergey Poznyakoff
b7336abee0 Updated 2004-04-26 13:49:10 +00:00
Sergey Poznyakoff
dca678e62f Updated 2004-04-26 13:48:50 +00:00
Sergey Poznyakoff
39e95d7eee Synchronized with the recent changes. 2004-04-26 13:44:19 +00:00
Sergey Poznyakoff
4b6f666105 Include stpcpy.h 2004-04-26 13:43:20 +00:00
Sergey Poznyakoff
a963130dd7 Updated 2004-04-26 13:42:24 +00:00
Sergey Poznyakoff
6f7d0eb14d Updated 2004-04-26 13:41:27 +00:00
Sergey Poznyakoff
8ad16912cf Generate Makefile.am from Makefile.tmpl 2004-04-26 13:40:50 +00:00
Sergey Poznyakoff
e17093af78 Invoke tar_GNULIB to configure gnulib stuff. 2004-04-26 13:38:41 +00:00
Sergey Poznyakoff
c5997e92f0 Use gnulib-tool to generate lib/Makefile.am and parts of configure.ac 2004-04-26 13:38:14 +00:00
Sergey Poznyakoff
7be4d61e92 Updated 2004-04-26 09:24:27 +00:00
Sergey Poznyakoff
af244aeef3 Produce an error, not warning, if the filename is too long. 2004-04-26 09:19:07 +00:00
Sergey Poznyakoff
005449337c Updated 2004-04-20 11:07:33 +00:00
Sergey Poznyakoff
a6d294236b Fixed typo 2004-04-20 11:07:04 +00:00
Sergey Poznyakoff
f5461e304c Bugfix by Jrgen Weigert 2004-04-20 11:06:35 +00:00
Sergey Poznyakoff
3087f4c1c9 Fixed test for iconv_t 2004-04-20 11:06:08 +00:00
Paul Eggert
1b0a1ba7ed Merge getdate documentation changes from coreutils. 2004-04-05 05:46:08 +00:00
Paul Eggert
2bda83b48d Merge recent gnulib changes, and remove some lint. 2004-04-05 02:29:18 +00:00
Sergey Poznyakoff
41d042c05f Updated 2004-04-04 13:33:54 +00:00
Sergey Poznyakoff
b826791a01 Added mksparse 2004-04-04 13:32:11 +00:00
Sergey Poznyakoff
2a384c4a84 Protect inclusion of <sys/time.h>
by ifdef.
Declare time() if HAVE_DECL_TIME is 0
2004-04-04 13:31:26 +00:00
Sergey Poznyakoff
f9dc020f90 Raised version number to 1.13.94 2004-04-04 13:30:42 +00:00
Sergey Poznyakoff
466e40abe5 Updated 2004-04-04 13:30:14 +00:00
Sergey Poznyakoff
f131340d6d Updated 2004-04-04 10:12:56 +00:00
Sergey Poznyakoff
7e2a46c522 Added missing call to 'after' 2004-04-04 10:12:08 +00:00
Sergey Poznyakoff
6dd96965de Updated 2004-04-04 09:53:18 +00:00
Sergey Poznyakoff
1bcc35dda0 Updated 2004-04-04 09:50:42 +00:00
Sergey Poznyakoff
2b861845e9 Updated 2004-04-04 09:48:45 +00:00
Sergey Poznyakoff
6cab217353 Added Mads Martin Joergensen 2004-04-04 09:47:35 +00:00
Sergey Poznyakoff
a5bafe7962 (usage): Prototype moved to common.h 2004-04-04 09:47:08 +00:00
Sergey Poznyakoff
096bf74fcf include <fnmatch.h>
(size_decoder): Assign to both st->archive_file_size and
st->stat.st_size.
(st->stat.st_size): Assign to st->stat.st_size
(sparse_numbytes_decoder): Removed unused variable
2004-04-04 09:43:09 +00:00
Sergey Poznyakoff
a55ec0a319 (utf8_convert): Changed prototype
(get_input_charset): Removed unused variable
2004-04-04 09:42:27 +00:00
Sergey Poznyakoff
61f44c9361 (usage): Prototype moved to common.h 2004-04-04 09:41:16 +00:00
Sergey Poznyakoff
55a96565b5 Include <sys/time.h> and <utime.h> when available 2004-04-04 09:33:41 +00:00
Sergey Poznyakoff
15a607fc11 (struct tar_sparse_optab.sparse_member_p)
(struct tar_sparse_optab.fixup_header): New member
(tar_sparse_member_p): New function.
(tar_sparse_init): Return true if decode_header is not provided
(tar_sparse_fixup_header)
(sparse_member_p,sparse_fixup_header)
(sparse_skip_file)
(oldgnu_sparse_member_p,oldgnu_fixup_header,star_sparse_member_p)
(star_fixup_header, pax_sparse_member_p): New function
(pax_decode_header): Remove
2004-04-04 09:33:25 +00:00
Sergey Poznyakoff
1329cfe9f8 include "common.h" 2004-04-04 09:32:33 +00:00
Sergey Poznyakoff
3ff03c0c5e (decode_header): Use sparse_fixup_header to correct
the st_size value.
(print_header): Do not rely on GNUTYPE_SPARSE type.
Use st->stat.st_size to print real file size.
(skip_member): Assign stat_info.file_name to save_name. This fixes
bug reported by Mads Martin Joergensen <mmj@suse.de>
Use sparse_skip_file() to skip sparse members.
2004-04-04 09:31:44 +00:00
Sergey Poznyakoff
3030a247b1 (extract_archive): Use sparse_member_p instead of GNUTYPE_SPARSE. 2004-04-04 09:26:11 +00:00
Sergey Poznyakoff
22c2e2ab8a Removed unused variables 2004-04-04 09:25:48 +00:00
Sergey Poznyakoff
be48ff0699 (diff_archive): Use is_sparse member instead of GNUTYPE_SPARSE. 2004-04-04 09:25:30 +00:00
Sergey Poznyakoff
a1d15e7c89 Added missing prototypes 2004-04-04 09:25:01 +00:00
Sergey Poznyakoff
ad2c53d626 Added new tests 2004-04-04 09:24:44 +00:00
Sergey Poznyakoff
8c0cb259bf Updated 2004-03-26 19:43:51 +00:00
Sergey Poznyakoff
472f860074 Add longv7.sh 2004-03-26 19:40:27 +00:00
Sergey Poznyakoff
d8981440bb (write_long_name): Do not allow more than
NAME_FIELD_SIZE-1 characters in a file name for V7 format
archives.
2004-03-26 19:39:40 +00:00
Sergey Poznyakoff
7f2e3cf63a Updated 2004-03-22 12:01:46 +00:00
Sergey Poznyakoff
f7dbd14d57 Updated to match the recent changes 2004-03-22 12:00:12 +00:00
Sergey Poznyakoff
106a24176e (open_archive): Clear read_full_records_option
if reading from a pipe.
(short_read): Display warning about the deduced record size
if version > 1
2004-03-22 11:59:35 +00:00
Sergey Poznyakoff
c83fcab116 Updated 2004-03-22 09:18:36 +00:00
Sergey Poznyakoff
4cb8697f60 Use genfile instead of dd 2004-03-22 09:17:48 +00:00
Sergey Poznyakoff
6bd7b64c78 (to_decimal): New function.
(xheader_format_name): Use to_decimal() instead of snprintf.
2004-03-22 09:17:18 +00:00
Sergey Poznyakoff
e5882c8220 (start_header): Check for GNU_FORMAT if incremental_option is set. 2004-03-22 09:16:49 +00:00
Sergey Poznyakoff
72e3da5dc7 Added gl_FUNC_STRTOULL 2004-03-22 09:15:56 +00:00
Sergey Poznyakoff
7b0b6c4e7a Updated 2004-03-12 10:39:27 +00:00
Sergey Poznyakoff
683390b02d (read_and): Stop processing the archive after
encountering a single zero record. Many old archives contain
arbitrary garbage after it.
The warning is issued anyway.
2004-03-12 10:38:46 +00:00
Sergey Poznyakoff
e189bd8eca Updated 2004-03-02 09:36:20 +00:00
Sergey Poznyakoff
5282ef9709 (utf8_convert): Indentation fix. 2004-03-02 09:35:13 +00:00
Sergey Poznyakoff
b38e4b4520 Added Leland Lucius 2004-03-02 09:34:44 +00:00
Sergey Poznyakoff
9f14fd52de (rmt_lseek__,rmt_ioctl__): Bugfix. The
conversion buffer was not null terminated. Fix provided
by Leland Lucius <llucius@tiny.net>
2004-03-02 09:34:06 +00:00
Sergey Poznyakoff
2345d02c63 Updated 2004-02-29 10:21:17 +00:00
Sergey Poznyakoff
6f219c485e Updated 2004-02-29 10:18:05 +00:00
Sergey Poznyakoff
a06ed48867 Added multi-fail.sh 2004-02-29 10:17:18 +00:00
Sergey Poznyakoff
d6929326e7 New test. 2004-02-29 10:16:33 +00:00
Sergey Poznyakoff
7fb546943e (sys_child_open_for_uncompress): Minor stylistic fix. 2004-02-29 10:16:02 +00:00
Sergey Poznyakoff
37400fa94e (flush_read): Bugfix: the condition at line 714 included
|| (status > 0 && !read_full_records_option)

which is grossly wrong, since even if new_volume() below succeeds,
the subsequent call to rmtread will overwrite the chunk of data
already read in the buffer and thus spoil everything.
2004-02-29 10:15:45 +00:00
Sergey Poznyakoff
8c1b242931 Updated 2004-02-29 00:15:05 +00:00
Sergey Poznyakoff
176557a004 New file 2004-02-29 00:09:31 +00:00
Sergey Poznyakoff
427f8d6185 Accomodate for the new testsuite logic 2004-02-29 00:07:00 +00:00
Sergey Poznyakoff
d584c1ed0f Rewritten 2004-02-29 00:06:36 +00:00
Sergey Poznyakoff
a8d1b579d7 Added new tests 2004-02-29 00:06:16 +00:00
Sergey Poznyakoff
5a9174376b New options: --utc and keep-newer-files 2004-02-29 00:06:03 +00:00
Sergey Poznyakoff
cedd9d6e81 (tartime): Print UTC if --utc was given. 2004-02-29 00:05:31 +00:00
Sergey Poznyakoff
29584d69fd Handle --keep-newer-files option 2004-02-29 00:05:12 +00:00
Sergey Poznyakoff
236deef28e (utc_option): new global
(enum old_files.KEEP_NEWER_FILES): New element
2004-02-29 00:04:50 +00:00
Sergey Poznyakoff
ca84e28ee5 Removed spurious AC_CHECK_LIB(iconv) 2004-02-29 00:04:21 +00:00
Sergey Poznyakoff
81bf1687f8 Updated 2004-02-29 00:04:03 +00:00
Paul Eggert
7afd75ed24 Append period to dircategory entry. 2004-02-26 18:02:50 +00:00
Sergey Poznyakoff
3dbc6a6645 Updated 2004-02-24 15:28:27 +00:00
Sergey Poznyakoff
d8b790047f (decode_header): Call xheader_decode before the assignment to current_stat_info.archive_file_size. 2004-02-24 15:27:54 +00:00
Paul Eggert
fb9a7d180f Invoke AM_ICONV, to define ICONV_CONST if needed. 2004-02-23 22:31:20 +00:00
121 changed files with 8602 additions and 6671 deletions

View File

@@ -18,4 +18,7 @@ stamp-h1
*.shar.gz
gnulib
gnulib/*
gnulib/*/*
gnulib/*/*
rmt
rmt/*
rmt/*/*

1096
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -20,4 +20,5 @@
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = ChangeLog.1 PORTS
SUBDIRS = doc lib src scripts po tests
SUBDIRS = doc lib rmt src scripts po tests

123
NEWS
View File

@@ -5,8 +5,69 @@ See the end for copying conditions.
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.15 - Sergey Poznyakoff, 2004-12-20
version 1.13.93
* Compressed archives are recognised automatically, it is no longer
necessary to specify -Z, -z, or -j options to read them. Thus, you can
now run `tar tf archive.tar.gz'.
* When restoring incremental dumps, --one-file-system option
prevents directory hierarchies residing on different devices
from being purged.
With the previous versions of tar it was dangerous to create
incremental dumps with --one-file-system option, since they
would recursively remove mount points when restoring from the
back up. This change fixes the bug.
* Renamed --strip-path to --strip-components for consistency with
the GNU convention.
* Skipping archive members is sped up if the archive media supports
seeks.
* Restore script starts restoring only if it is given --all (-a) option,
or some patterns. This is to prevent accidental restores.
* `tar --verify' prints a warning if during archive creation some of
the file names had their prefixes stripped off.
* New option --exclude-caches instructs tar to exclude cache directories
automatically on archive creation. Cache directories are those
containing a standardized tag file, as specified at:
http://www.brynosaurus.com/cachedir/spec.html
* New configure option --with-rmt allows to specify full path name to
the `rmt' utility. This supercedes DEFAULT_RMT_COMMAND variable
introduced in version 1.14
* New configure variable DEFAULT_RMT_DIR allows to specify the directory
where to install `rmt' utility. This is necessary since modifying
--libexecdir as was suggested for version 1.14 produced a side effect: it
also modified installation prefix for backup scripts (if
--enable-backup-scripts was given).
* Bugfixes:
** Fixed flow in recognizing files to be included in incremental dumps.
** Correctly recognize sparse archive members when used with -T option.
** GNU multivolume headers cannot store filenames longer than 100 characters.
Do not allow multivolume archives to begin with such filenames.
** If a member with link count > 2 was stored in the archive twice,
previous versions of tar were not able to extract it, since they
were trying to link the file to itself, which always failed and
lead to removing the already extracted copy. Preserve the first
extracted copy in such cases.
** Restore script was passing improper argument to tar --listed option (which
didn't affect the functionality, but was logically incorrect).
** Fixed verification of created archives.
** Fixed unquoting of file names containing backslash escapes (previous
versions failed to recognize \a and \v).
** When attempting to delete a non-existing member from the archive, previous
versions of tar used to overwrite last archive block with zeroes.
version 1.14 - Sergey Poznyakoff, 2004-05-11
* Added support for POSIX.1-2001 and ustar archive formats.
* New option --format allows to select the output archive format
@@ -45,8 +106,26 @@ version 1.13.93
-o option.
* --incremental and --listed-incremental options work correctly on
individual files, as well as on directories.
individual files, as well as on directories.
* New scripts: backup (replaces old level-0 and level-1) and restore.
The scripts are compiled and installed if --enable-backup-scripts
option is given to configure.
* By default tar searches "rmt" utility in "$prefix/libexec/rmt",
which is consistent with the location where the version of "rmt"
included in the package is installed. Previous versions of tar
used "/etc/rmt". To install "rmt" to its traditional location,
run configure with option --libexecdir=/etc. Otherwise, if you
already have rmt installed and wish to use it, instead of the
shipped in version, set the variable DEFAULT_RMT_COMMAND to
the full path name of the utility, e.g. ./configure
DEFAULT_RMT_COMMAND=/etc/rmt.
Notice also that the full path name of the "rmt" utility to
use can be set at runtime, by giving option --rmt-command to
tar.
* Removed obsolete command line options:
** --absolute-paths superseded by --absolute-names
** --block-compress is not needed any longer
@@ -59,32 +138,38 @@ individual files, as well as on directories.
* New message translations fi (Finnish), gl (Galician), hr (Croatian),
hu (Hungarian), ms (Malaysian), nb (Norwegian), ro (Romanian), sk
(Slovak), zh_CN (Chinese simplified), zh_TW (Chinese traditional).
The code 'no' for Norwegian has been withdrawn; use 'nb' instead.
The code 'no' for Norwegian (Bokm<6B>l) has been withdrawn; use 'nb' instead.
* Bug fixes.
version 1.13.25 - Paul Eggert, 2001-09-26
* Bug fixes.
version 1.13.24 - Paul Eggert, 2001-09-22
* New option --overwrite-dir.
* Fixes for buffer overrun, porting, and copyright notice problems.
* The message translations for Korean are available again.
version 1.13.23 - Paul Eggert, 2001-09-13
* Bug, porting, and copyright notice fixes.
version 1.13.22 - Paul Eggert, 2001-08-29
* Bug fixes.
version 1.13.21 - Paul Eggert, 2001-08-28
* Porting and copyright notice fixes.
version 1.13.20 - Paul Eggert, 2001-08-27
* Some bugs were fixed:
@@ -111,6 +196,7 @@ version 1.13.20 - Paul Eggert, 2001-08-27
The translation for Korean has been withdrawn due to encoding errors.
It will be reissued once those are fixed.
version 1.13.19 - Paul Eggert, 2001-01-13
* The -I option has been withdrawn, as it was buggy and confusing.
@@ -119,6 +205,7 @@ version 1.13.19 - Paul Eggert, 2001-01-13
* With an option like -N DATE, if DATE starts with "/" or ".", it is taken
to be a file name; the last-modified time of that file is used as the date.
version 1.13.18 - Paul Eggert, 2000-10-29
* Some security problems have been fixed. `tar -x' now modifies only
@@ -149,11 +236,13 @@ version 1.13.18 - Paul Eggert, 2000-10-29
* `tar --delete -f -' now works again.
version 1.13.17 - Paul Eggert, 2000-01-07.
* `tar --delete -f -' is no longer allowed; it was too buggy.
* Diagnostic messages have been made more regular and consistent.
version 1.13.16 - Paul Eggert, 1999-12-13.
* By default, tar now refuses to overwrite an existing file when
@@ -197,17 +286,20 @@ version 1.13.16 - Paul Eggert, 1999-12-13.
* tar now ignores socket files when creating an archive.
Previously tar archived sockets as fifos, which caused problems.
version 1.13.15 - Paul Eggert, 1999-12-03.
* If a file's ctime changes when being archived, report an error.
Previously tar looked at mtime, which missed some errors.
version 1.13.14 - Paul Eggert, 1999-11-07.
* New translations ja, pt_BR.
* New options --help and --version for rmt.
* Ignore Solaris door files when creating an archive.
version 1.13.13 - Paul Eggert, 1999-10-11.
* Invalid headers in tar files now elicit errors, not just warnings.
@@ -215,6 +307,7 @@ version 1.13.13 - Paul Eggert, 1999-10-11.
* If you specify an invalid date, `tar' now substitutes (time_t) -1.
* `configure --with-dmalloc' is no longer available.
version 1.13.12 - Paul Eggert, 1999-09-24.
* `tar' now supports hard links to symbolic links.
@@ -245,7 +338,7 @@ version 1.13.12 - Paul Eggert, 1999-09-24.
* Some diagnostics have been reworded for consistency.
version 1.13.11 - Paul Eggert, 1999-08-23.
* The short name of the --bzip option has been changed to -I,
@@ -265,14 +358,14 @@ version 1.13.11 - Paul Eggert, 1999-08-23.
numeric UTC offsets like `-0500' instead of abbreviations like
`EST', as abbreviations are not standardized and are ambiguous.
version 1.13.10 - Paul Eggert, 1999-08-20.
* `tar' now uses signed base-64 when outputting header values that are
out of the range of the standard unsigned base-8 format. [This
change was superseded in 1.13.12, described above.]
version 1.13.9 - Paul Eggert, 1999-08-18.
* `tar' now writes two zero blocks at end-of-archive instead of just one.
@@ -284,14 +377,14 @@ version 1.13.9 - Paul Eggert, 1999-08-18.
* `tar' now reads buggy tar files that have a null byte at the start of a
numeric header field.
version 1.13.8 - Paul Eggert, 1999-08-16.
* For compatibility with traditional `tar', intermediate directories
created automatically by root are no longer given the uid and gid of
the original file or directory.
version 1.13.7 - Paul Eggert, 1999-08-14.
* --listed-incremental and --newer are now incompatible options.
@@ -301,7 +394,7 @@ version 1.13.7 - Paul Eggert, 1999-08-14.
* --diff without --absolute-names no longer falls back on absolute names.
version 1.13.6 - Paul Eggert, 1999-08-11.
* An --exclude pattern containing / now excludes a file only if it matches an
@@ -328,30 +421,30 @@ version 1.13.6 - Paul Eggert, 1999-08-11.
* New option -y or --bzip2 for bzip2 compression, by popular request.
version 1.13.5 - Paul Eggert, 1999-07-20.
* Do the delayed updates of file metadata even after a fatal error.
version 1.13.4 - Paul Eggert, 1999-07-20.
* Do not chmod unless we are root or the -p option was given;
this matches historical practice.
version 1.13.3 - Paul Eggert, 1999-07-16.
* A path name is excluded if any of its file name components matches an
excluded pattern, even if the path name was specified on the command line.
Also see 1.13.6 for later changes in this area.
version 1.13.2 - Paul Eggert, 1999-07-14.
* Bug reporting address changed to <bug-tar@gnu.org>.
version 1.13.1 - Paul Eggert, 1999-07-12.
* Bug fixes only.

128
PORTS
View File

@@ -1,48 +1,60 @@
* Ports of GNU tar and other micro-tars -*- outline -*-
Ports of GNU tar and other tars
See the end of file for copying conditions.
Please write tar-bugs@gnu.ai.mit.edu if you are aware of various ports
of GNU tar to non-Unix systems not listed here, or for corrections.
* Introduction
Most entries in this file are out of date, unfortunately. Such
entries are marked with an `X'. Run grep '^\*\*[^X]' PORTS to
extract valid entries.
Please write bug-tar@gnu.org if you are aware of various ports of GNU tar
to non-GNU and non-Unix systems not listed here, or for corrections.
Please provide the goal system, a complete and stable URL, the maintainer
name and address, the tar version used as a base, and your comments.
.* Amiga
* GNU/Linux and Unix
. + ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/GNUtar-1.11.8.lha
** Star is a tape archiver similar to tar.
<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/star.html>
* Amiga
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/GNUtar-1.11.8.lha
maintained by Enrico Forestieri <enrico@com.unipr.it>
Based on tar 1.11.8.
. + ftp://ftp.ninemoons.com/pub/ade/current/amiga-bin/tar-1.11.8-bin.lha
**X ftp://ftp.ninemoons.com/pub/ade/current/amiga-bin/tar-1.11.8-bin.lha
maintained by the ADE group <fnf@fishpond.ninemoons.com>
Based on tar 1.11.8, needs ixemul.library.
. + ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/gnutar.lha
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/gnutar.lha
maintained by <mscheler@wuarchive.wustl.edu>
.* DEC alpha (NT)
* DEC alpha (NT)
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
maintained by Drew Bliss & Geoff Voelker
.* DEC VAX (VMS)
* DEC VAX (VMS)
. + http://www.lp.se/free/vmstar/
**X http://www.lp.se/free/vmstar/
maintained by Richard Levitte <levitte@lp.se>
This is not GNU tar, but a separate implementation.
. + maintained by William Bader <william@nscs.fast.net>
** maintained by William Bader <william@nscs.fast.net>
For V4.7. Based on an old PDtar. Requires compatible shared libraries
to run V5 or V6 executables.
.* IBM/PC (DV/X)
* IBM/PC (DV/X)
. + ftp://qdeck.com/ (?)
**X ftp://qdeck.com/ (?)
maintained by David Ronis <ronis@gibbs.chem.mcgill.ca>
For Desqview/X. Everything works besides compression. Copy of hacked
sources available, some of DV/X's programmer's library also needed.
.* IBM/PC (MSDOS)
* IBM/PC (MSDOS)
. + http://www.simtel.net/simtel.net/
**X http://www.simtel.net/simtel.net/
http://www.leo.org/pub/comp/platforms/pc/gnuish (Germany)
ftp://ftp.simtel.net/simtelnet/gnu
ftp://ftp.leo.org/pub/comp/platforms/pc/gnuish
@@ -50,82 +62,112 @@
You get many GNU tools, not only `tar'. The GNUish project is described
in `gnuish_t.htm'.
. + The DJGPP development tools also include some `tar' utilities.
** The DJGPP development tools also include some `tar' utilities.
. + ftp://ftp.mcs.com/mcsnet.users/les/dos-gnutar/
**X ftp://ftp.mcs.com/mcsnet.users/les/dos-gnutar/
maintained by Leslie Mikesell <les@mcs.net>
Based on tar 1.11.2. Support for SCSI (via ASPI) and network (rsh over
packet driver). No support for win95 long file names.
. + ftp://ftp.wu-wien.ac.at:pub/src/PCmisc/aspi-tar/*
**X ftp://ftp.wu-wien.ac.at/pub/src/PCmisc/aspi-tar/*
maintained by Christoph Splittgerber <chris@orion.sdata.de>
Based on tar 1.10. Support for SCSI (via ASPI).
. + ftp://wuarchive (?)
**X ftp://wuarchive (?)
Several DOS version based on PDtar. John Gilmore <gnu@toad.com> says
he has copies of several vintages saved.
. + ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.exe
**X ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.exe
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.taz
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.zip
. + ftp://ftp.cdrom.com/.4/os2/archiver/tar.zip
**X ftp://ftp.cdrom.com/.4/os2/archiver/tar.zip
Based on PDtar.
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
maintained by Drew Bliss & Geoff Voelker
GNU tar for NT (intel and Alpha platforms).
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
. + http://people.darmstadt.netsurf.de/tst/tar.htm
**X http://people.darmstadt.netsurf.de/tst/tar.htm
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
This is not a `tar' port, but an index of them.
.* IBM/PC (OS/2)
* IBM/PC (OS/2)
. + http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtar254.zip
**X http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtar254.zip
http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtak254.zip
maintained by Andreas Kaiser <Andreas.Kaiser@stuttgart.netsurf.de>
Version 2.54. Based on tar 1.10. The second archive contains SCSI
drivers (DAT streamers notably) and rmt-type programs.
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
* IBM/PC (Win32: Windows 95, NT 3.5 or NT 4.0)
.* IBM/PC (Win32: Windows 95, NT 3.5 or NT 4.0)
. + ftp://ftp.cygnus.com:~ftp/pub/sac/win32/usersrc/*
**X ftp://ftp.cygnus.com:~ftp/pub/sac/win32/usersrc/*
maintained by Cygnus
GNU-Win32 B17.1 distribution. Download all files, `cat' them together,
and `untar' the result. You get many GNU tools, not only `tar'.
Based on tar 1.11.2.
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
maintained by Drew Bliss & Geoff Voelker
GNU tar for NT (intel and Alpha platforms).
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
.* IBM/PC (Windows 3.1)
* IBM/PC (Windows 3.1)
. + ftp://ftp.mcs.com/mcsnet.users/les/win-gnutar/
**X ftp://ftp.mcs.com/mcsnet.users/les/win-gnutar/
maintained by Leslie Mikesell <les@mcs.net>
Support for network (rsh over winsock). No support for win95 long
file names.
. + ftp://ftp.gamesdomain.ru/.1/os/windows/programr/tar.zip
**X ftp://ftp.gamesdomain.ru/.1/os/windows/programr/tar.zip
Based on GNU tar 1.11.2.
.* Macintosh
* Macintosh
. + There is a tar in Stuffit Expander which is available many places and
comes with MacOS. It creates some spurious files but works on average.
** Paulo Abreu (paulotex at yahoo dot com) did a
limited port of GNU tar to Darwin, with support for resource forks
and finder info, but this no longer seems to be available.
. + There is an excellent GNU tar bundled in Tenon MachTen, but it does not
seem to be available separately.
** There is a tar in Stuffit Expander which is available many places and
comes with MacOS. It creates some spurious files but works on average.
** There is an excellent GNU tar bundled in Tenon MachTen, but it does not
seem to be available separately.
* Copyright notice
Copyright (C) 1999, 2001, 2003, 2004 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)
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; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Local Variables:
mode: outline
paragraph-separate: "[ ]*$"
version-control: never
End:

37
README
View File

@@ -46,6 +46,36 @@ in the environment before configuring (the behavior of `-[0-7]' or
`-[0-7]lmh' options in `tar' are then derived automatically). Similarly,
`DEFAULT_BLOCKING' can be preset to something else than 20.
** Selecting full pathname of the "rmt" binary.
Previous versions of tar always looked for "rmt" binary in the
directory "/etc/rmt". However, the "rmt" program included
in the distribution was installed under "$prefix/libexec/rmt".
To fix this discrepancy, tar now looks for "$prefix/libexec/rmt".
If you do not want this behavior, specify full path name of
"rmt" binary using DEFAULT_RMT_DIR variable, e.g.:
./configure DEFAULT_RMT_DIR=/etc
If you already have a copy of "rmt" installed and wish to use it
instead of the version supplied with the distribution, use --with-rmt
option:
./configure --with-rmt=/etc/rmt
This will also disable building the included version of rmt.
** Installing backup scripts.
This version of tar is shipped with the shell scripts for producing
incremental backups (dumps) and restoring filesystems from them.
The name of the backup script is "backup". The name of the
restore script is "restore". They are installed in "$prefix/sbin"
directory.
Use option --enable-backup-scripts to compile and install these
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.
@@ -169,9 +199,10 @@ and new `tar' features.
* What's next?
In the future we will try to release tar-1.14 as soon as possible and
start merging with paxutils afterwards. We'll also try to rewrite
some parts of the documentation after paxutils has been merged.
GNU tar will be merged into GNU paxutils: a project containing
several utilities related to creating and handling archives in
various formats. The project will include tar, cpio and pax
utilities.
* Bug reporting.

View File

@@ -24,25 +24,33 @@ Before building the package, run "bootstrap". It obtains various
additional files from the CVS repository and the Translation Project
site and prepares the source directory for building.
When run without arguments, bootstrap will try to obtain gnulib files
from CVS repository on savannah using anonymous SSH access. Then, it
will fetch the po files from tar page at Translation Project, and,
finally, it will start autoconfiguration process. Simply running
it without arguments should do in most cases. Several options
allow to control the behavior of bootstrap:
When run without arguments, bootstrap will try to obtain gnulib and
paxutils files from their corresponding CVS repositories on Savannah
using anonymous SSH access. Then, it will fetch the po files from tar
page at Translation Project, and, finally, it will start autoconfiguration
process. Simply running it without arguments should do in most cases.
Several options allow to control the behavior of bootstrap:
--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.
--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.
--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.
Notice also that when using CVS authentication method "ext", bootstrap

27
THANKS
View File

@@ -4,7 +4,7 @@ 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
Jay Fenlason and Joy Kendall, and was maintained in turn by Fran<EFBFBD>§ois
Pinard and Paul Eggert.
Many people further contributed to GNU tar by reporting problems,
@@ -62,6 +62,7 @@ Bob Mende Pie mende@piecomputer.rutgers.edu
Bradley A. Smith basmith@prometheus.chem.umn.edu
Brendan Kehoe brendan@cygnus.com
Brett Gaines gaines@saifr00.ateng.az.honeywell.com
Bryan Ford baford@mit.edu
Brian Perkins bperkins@netspace.org
Brian R. Smith brian@cygnus.com
Bruce Evans bde@runx.oz.au
@@ -164,7 +165,7 @@ Ezra Peisach epeisach@mit.edu
Fabio d'Alessi cars@civ.bio.unipd.it
Frank Koenen koenfr@lidp.com
Franz-Werner Gergen gergen@edvulx.mpi-stuttgart.mpg.de
François Pinard pinard@iro.umontreal.ca
Fran<EFBFBD>§ois Pinard pinard@iro.umontreal.ca
Fritz Elfert fritz@fsun.triltsch.de
George Chyu gschyu@ccgate.dp.beckman.com
Gerben Wierda gerben@rna.indiv.nluug.nl
@@ -178,12 +179,13 @@ Greg Chung gchung@caip.rutgers.edu
Greg Hudson ghudson@mit.edu
Greg Maples greg@clari.net
Greg McGary gkm@cstone.net
Göran Uddeborg gvran@uddeborg.pp.se
G<EFBFBD>ran Uddeborg gvran@uddeborg.pp.se
Hans Guerth 100664.3101@compuserve.com
Harald König koenig@tat.physik.uni-tuebingen.de
Harald K<EFBFBD>nig koenig@tat.physik.uni-tuebingen.de
Harald Milz hm@seneca.ix.de
Heiko Schinke mdqac@biochemtech.uni-halle.de
Heiko Schlichting heiko@fu-berlin.de
Helmut Waitzmann Helmut.Waitzmann@web.de
Henrik Bakman hb@csd.uu.se
Hernan Prieto Schmidt hernan@pea.usp.br
Hiroyuki Bessho bsh@grotto.iijnet.or.jp
@@ -237,6 +239,7 @@ John David Anglin dave@hiauly1.hia.nrc.ca
John Gilmore gnu@toad.com
John J. Szetela johns@angelo.amd.com
John L. Chmielewski jlc@attmail.com
John L. Males jlmales@yahoo.com
John Oleynick juo@klinzhai.rutgers.edu
John R. Vanderpool fish@daacdev1.stx.com
John Rouillard rouilj@cs.umb.edu
@@ -251,11 +254,12 @@ Joy Kendall jak8@world.std.com
Judy Ricker jricker@gdstech.grumman.com
Juha Sarlin juha@tds.kth.se
Jurgen Botz jbotz@orixa.mtholyoke.edu
Jürgen Lüters jlueters@t-online.de
Jürgen Reiss reiss@psychologie.uni-wuerzburg.de
J<EFBFBD>¼rgen L<EFBFBD>¼ters jlueters@t-online.de
J<EFBFBD>¼rgen Reiss reiss@psychologie.uni-wuerzburg.de
Jyh-Shyang Wang erik@vsp.ee.nctu.edu.tw
Jörg Weule weule@cs.uni-duesseldorf.de
Jörgen Hägg Jorgen.Hagg@axis.se
J<EFBFBD>rg Weule weule@cs.uni-duesseldorf.de
J<EFBFBD>rgen H<EFBFBD>¤gg Jorgen.Hagg@axis.se
J<EFBFBD>¶rgen Weigert jw@suse.de
Kai Petzke wpp@marie.physik.tu-berlin.de
Kai Schlichting kai@computel.com
Karl Berry karl@cs.umb.edu
@@ -279,10 +283,12 @@ Larry Creech lcreech@lonestar.rcclub.org
Larry Schwimmer rosebud@cyclone.stanford.edu
Laurent Caillat-Vallet caillat@noe.lyon.cemagref.fr
Laurent Sainte-Marthe smarthe@genethon.fr
Leland Lucius llucius@tiny.net
Les Mikesell les@mcs.com
Loren J. Rittle rittle@comm.mot.com
Loïc Prylli Loic.Prylli@lip.ens-lyon.fr
Lo<EFBFBD>¯c Prylli Loic.Prylli@lip.ens-lyon.fr
Luke Mewburn lukem@connect.com.au
Mads Martin Joergensen mmj@suse.de
Machael Stone mstone@cs.loyola.edu
Manfred Weichel Manfred.Weichel@mch.sni.de
Manuel Munier Manuel.Munier@loria.fr
@@ -299,6 +305,7 @@ Markus Kuhn mskuhn@cip.informatik.uni-erlangen.de
Martin Bellenberg sunsoft@ifm.uni-hamburg.de
Martin Goik goik@HDM-Stuttgart.de
Martin Mares mj@k332.feld.cvut.cz
Martin Simmons ZYHYLCRMZPRP@spammotel.com
Marty Leisner leisner@eso.mc.xerox.com
Massimo Dal Zotto dz@cs.unitn.it
Mats Lofkvist d87-mal@nada.kth.se
@@ -443,7 +450,7 @@ Tarang Kumar Patel mombasa@ptolemy.arc.nasa.gov
Ted Rule Ted_Rule@flextech.co.uk
The King elvis@gnu.org
Thomas Bushnell n/BSG thomas@gnu.org
Thomas König Thomas.Koenig@ciw.uni-karlsruhe.de
Thomas K<EFBFBD>nig Thomas.Koenig@ciw.uni-karlsruhe.de
Thomas Krebs krebs@faps.uni-erlangen.de
Thomas M. Browder Jr. browder@use1.eglin.af.mil
Thomas Priesner priesner@flo.sh.bosch.de

23
TODO
View File

@@ -2,8 +2,16 @@ Suggestions for improving GNU tar.
* Incorporate fixes from major distributions, e.g., Debian GNU/Linux.
* Add support for restoring file time stamps to sub-second resolution,
if the file system supports this.
* Add support for restoring the attributes of symbolic links, for
OSes like FreeBSD that have the lutimes and lchmod functions.
* --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 (--sparse, --incremental, --label and
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.
@@ -16,9 +24,10 @@ so that the GNU extensions (--sparse, --incremental, --label and
UNIX98 tar warns if all links cannot be resolved.
(GNU tar --check-links option)
Perhaps we could announce a phase-in period where "l" changes in semantics.
In the meanwhile we could make the "l" semantics to be determined by the
value of POSIXLY_CORRECT variable.
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.
@@ -30,7 +39,7 @@ so that the GNU extensions (--sparse, --incremental, --label and
It would be useful to be able to use '--remove-files' with '--diff',
to remove all files that compare successfully, when verifying a backup.
* Add tests for testing the added functonality.
* Add tests for the new functonality.
* Consider this:
@@ -47,10 +56,10 @@ so that the GNU extensions (--sparse, --incremental, --label and
(http://mail.gnu.org/archive/html/bug-gnu-utils/2002-05/msg00022.html)
* Copyright notice
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU tar.

191
bootstrap
View File

@@ -2,7 +2,7 @@
# Bootstrap 'tar' from CVS.
# Copyright (C) 2003 Free Software Foundation, Inc.
# Copyright (C) 2003, 2004 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
@@ -19,15 +19,25 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Written by Paul Eggert.
# Written by Paul Eggert and Sergey Poznyakoff.
# URL of our text domain page in Translation Project
TP_URL="http://www2.iro.umontreal.ca/~gnutra/po/maint/tar/"
# Ensure file names are sorted consistently across platforms;
# e.g., m4/ulonglong_gl.m4 should follow m4/ulonglong.m4.
LC_ALL=C
export LC_ALL
usage() {
cat <<EOF
usage: $0 [--gnulib-srcdir=DIR][--cvs-auth=AUTH-METHOD][--cvs-user=USERNAME][--no-po]
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
@@ -40,15 +50,35 @@ usage() {
--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.
Running without arguments will suffice in most cases. It is equivalent
to
to
./bootstrap --cvs-auth=ext --cvs-user=anoncvs
EOF
}
update_po() {
if [ $# = 1 ]; then
case $1 in
*.po) POFILE=$1;;
*) POFILE=${1}.po;;
esac
echo "$0: getting translation for $1..."
wget -r -C 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 -C off $TP_URL &&
rm -f index.html index.html.[0-9]*
ls *.po | sed 's/\.po$//' >LINGUAS
) || exit
fi
}
# Parse options.
DOWNLOAD_PO=yes
@@ -60,18 +90,33 @@ do
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=\(.*\)'`;;
--cvs-user=*)
CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
--no-po)
DOWNLOAD_PO=no;;
--update-po=*)
DOWNLOAD_PO=`expr "$option" : '--update-po=\(.*\)'`;;
--update-po)
DOWNLOAD_PO=only;;
*)
echo >&2 "$0: $option: unknown option"
exit 1;;
esac
done
case $DOWNLOAD_PO in
only) update_po
exit 0
;;
no|yes) ;;
*) update_po $DOWNLOAD_PO
exit 0
esac
echo "$0: Bootstrapping CVS tar..."
build_cvs_prefix() {
@@ -84,36 +129,44 @@ build_cvs_prefix() {
CVS_RSH=ssh
export CVS_RSH
fi
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--}" in
-) build_cvs_prefix ext anoncvs
;;
pserver) build_cvs_prefix $CVS_AUTH ${CVS_USER:-anoncvs}
;;
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
if [ "${CVS_AUTH--}" = "pserver" ]; then
cvs -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/$1 login || exit
fi
cvs -q -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/$1 co $1 || exit
trap 0
fi
}
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
-)
if [ ! -d gnulib ]; then
echo "$0: getting gnulib files..."
trap exit 1 2 13 15
trap 'rm -fr gnulib; exit 1' 0
case "${CVS_AUTH--}" in
-) build_cvs_prefix ext anoncvs;;
pserver) build_cvs_prefix $CVS_AUTH ${CVS_USER:-anoncvs};;
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
if [ "${CVS_AUTH--}" = "pserver" ]; then
cvs -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/gnulib login || exit
fi
cvs -q -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/gnulib co gnulib || exit
trap 0
fi
GNULIB_SRCDIR=gnulib
-) checkout gnulib
GNULIB_SRCDIR=gnulib
esac
<$GNULIB_SRCDIR/gnulib-tool || exit
@@ -121,6 +174,7 @@ esac
gnulib_modules='
alloca
argmatch
argp
backupfile
dirname
error
@@ -132,10 +186,13 @@ full-write
getdate
getline
getopt
getpagesize
gettext
gettime
hash
human
lchown
localcharset
memset
modechange
obstack
@@ -149,9 +206,11 @@ stdbool
stpcpy
strtol
strtoul
timespec
unlocked-io
utime
xalloc
xalloc-die
xgetcwd
xstrtoumax
'
@@ -159,11 +218,13 @@ xstrtoumax
previous_gnulib_modules=
while [ "$gnulib_modules" != "$previous_gnulib_modules" ]; do
previous_gnulib_modules=$gnulib_modules
# In gnulib `alloca-opt' duplicates `alloca', so make sure not
# to use it.
gnulib_modules=`
(echo "$gnulib_modules"
for gnulib_module in $gnulib_modules; do
$GNULIB_SRCDIR/gnulib-tool --extract-dependencies $gnulib_module
done) | sort -u
done) | sed 's/alloca-opt/alloca/' | sort -u
`
done
@@ -181,14 +242,17 @@ for gnulib_file in $gnulib_files; do
case $gnulib_file in
m4/codeset.m4) continue;;
m4/glibc21.m4) continue;;
m4/intdiv0.m4) continue;;
m4/inttypes_h.m4) continue;;
m4/inttypes.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 &&
@@ -196,16 +260,59 @@ for gnulib_file in $gnulib_files; do
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"
(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 paxutils files
case ${PAXUTILS_SRCDIR--} in
-) checkout paxutils
PAXUTILS_SRCDIR=paxutils
esac
# copy_files srcdir dstdir
copy_files() {
for file in `cat $1/DISTFILES`
do
case $file in
"#*") continue;;
esac
echo "$0: Copying file $1/$file"
cp -p $1/$file $2/`expr $file : '.*/\(.*\)'`
done
}
copy_files ${PAXUTILS_SRCDIR}/m4 m4
if [ -d rmt ]; then
:
else
mkdir rmt
fi
copy_files ${PAXUTILS_SRCDIR}/rmt rmt
copy_files ${PAXUTILS_SRCDIR}/lib lib
copy_files ${PAXUTILS_SRCDIR}/tests tests
# Get translations.
if test "$DOWNLOAD_PO" = "yes"; then
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 -C off $TP_URL &&
ls *.po | sed 's/\.po$//' >LINGUAS
) || exit
update_po
fi
# Reconfigure, getting other files.

View File

@@ -18,7 +18,7 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
AC_INIT([GNU tar], [1.13.93], [bug-tar@gnu.org])
AC_INIT([GNU tar], [1.15], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_HEADERS([config.h:config.hin])
@@ -29,40 +29,26 @@ gl_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_EXEEXT
AC_PROG_RANLIB
AC_PROG_YACC
AC_SYS_LARGEFILE
AC_ISC_POSIX
AC_C_INLINE
AC_CHECK_HEADERS(fcntl.h linux/fd.h memory.h net/errno.h \
sgtty.h string.h \
sys/buf.h sys/device.h sys/gentape.h \
sys/param.h sys/device.h sys/gentape.h \
sys/inet.h sys/io/trioctl.h \
sys/mtio.h sys/tprintf.h sys/tape.h \
sys/mtio.h sys/time.h sys/tprintf.h sys/tape.h \
unistd.h)
AC_CHECK_HEADERS([sys/buf.h], [], [],
[#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif])
AC_HEADER_SYS_WAIT
AM_STDBOOL_H
if test $ac_cv_header_sys_mtio_h = yes; then
AC_CACHE_CHECK(for remote tape header files, tar_cv_header_rmt,
[AC_TRY_CPP([
#if HAVE_SGTTY_H
# include <sgtty.h>
#endif
#include <sys/socket.h>],
tar_cv_header_rmt=yes, tar_cv_header_rmt=no)])
test $tar_cv_header_rmt = yes && RMT='rmt$(EXEEXT)'
AC_SUBST(RMT)
fi
AC_CACHE_CHECK(which ioctl field to test for reversed bytes,
tar_cv_header_mtio_check_field,
[AC_EGREP_HEADER(mt_model, sys/mtio.h,
tar_cv_header_mtio_check_field=mt_model,
tar_cv_header_mtio_check_field=mt_type)])
AC_DEFINE_UNQUOTED(MTIO_CHECK_FIELD, $tar_cv_header_mtio_check_field,
[Define to mt_model (v.g., for DG/UX), else to mt_type.])
AC_HEADER_DIRENT
AC_HEADER_MAJOR
AC_HEADER_STAT
@@ -95,61 +81,18 @@ 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
AM_FUNC_GETLINE
gl_BACKUPFILE
gl_DIRNAME
gl_ERROR
gl_EXCLUDE
gl_FILEBLOCKS
gl_FUNC_ALLOCA
gl_FUNC_FNMATCH_GNU
gl_FUNC_MEMSET
gl_FUNC_MKTIME
gl_FUNC_RMDIR
gl_FUNC_STRTOL
gl_FUNC_STRTOUL
gl_FUNC_STRTOIMAX
gl_FUNC_STRTOUMAX
gl_GETDATE
gl_GETOPT
gl_HASH
gl_HUMAN
gl_MODECHANGE
gl_OBSTACK
gl_PATHMAX
gl_QUOTE
gl_QUOTEARG
gl_SAFE_READ
gl_SAFE_WRITE
gl_SAVE_CWD
gl_SAVEDIR
gl_STRCASE
gl_TIME_R
gl_XALLOC
gl_XGETCWD
gl_XSTRTOL
gl_FUNC_STPCPY
jm_FUNC_FTRUNCATE
jm_FUNC_GLIBC_UNLOCKED_IO
jm_FUNC_CHOWN
jm_FUNC_LCHOWN
jm_FUNC_MALLOC
jm_FUNC_REALLOC
jm_FUNC_UTIME
jm_XSTRTOUMAX
AC_CHECK_MEMBERS([struct stat.st_spare1, struct stat.st_atim.tv_nsec, struct stat.st_atimespec.tv_nsec, struct stat.st_atimensec], , ,
[
#include <sys/types.h>
#include <sys/stat.h>])
# Save and restore LIBS so e.g., -lrt, isn't added to it. Otherwise, *all*
# programs in the package would end up linked with that potentially-shared
# library, inducing unnecessary run-time overhead.
@@ -169,7 +112,7 @@ LIBS=$tar_save_LIBS
AC_CHECK_FUNCS(fsync lstat mkfifo readlink strerror symlink setlocale utimes)
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
AC_CHECK_DECLS([valloc])
AC_CHECK_DECLS([time],,, [#include <time.h>])
# Set LIB_SETSOCKOPT to -lnsl -lsocket if necessary.
tar_save_LIBS=$LIBS
@@ -216,6 +159,9 @@ fi
AC_MSG_CHECKING(for default archive format)
AC_ARG_VAR([DEFAULT_ARCHIVE_FORMAT],
[Set the default archive format. Allowed values are: V7, OLDGNU, USTAR, POSIX, GNU. Default is GNU])
if test -z "$DEFAULT_ARCHIVE_FORMAT"; then
DEFAULT_ARCHIVE_FORMAT="GNU"
fi
@@ -229,6 +175,8 @@ AC_MSG_RESULT($DEFAULT_ARCHIVE_FORMAT)
AC_MSG_CHECKING(for default archive)
AC_ARG_VAR([DEFAULT_ARCHIVE],
[Set the name of the default archive (default: -)])
if test -z "$DEFAULT_ARCHIVE"; then
DEFAULT_ARCHIVE=-
else
@@ -262,24 +210,54 @@ AC_DEFINE_UNQUOTED(DEFAULT_ARCHIVE, "$DEFAULT_ARCHIVE",
[Define to a string giving the full name of the default archive file.])
AC_MSG_RESULT($DEFAULT_ARCHIVE)
AC_ARG_VAR([DEFAULT_BLOCKING],
[Define default blocking factor (default: 20)])
AC_MSG_CHECKING(for default blocking)
DEFAULT_BLOCKING=${DEFAULT_BLOCKING-20}
AC_DEFINE_UNQUOTED(DEFAULT_BLOCKING, $DEFAULT_BLOCKING,
[Define to a number giving the default blocking size for archives.])
AC_MSG_RESULT($DEFAULT_BLOCKING)
PU_RMT
# Iconv
AM_ICONV
AC_CHECK_HEADERS(iconv.h)
AC_CHECK_TYPE(iconv_t,:,
AC_DEFINE(iconv_t, int,
[Conversion descriptor type]),
[
#ifdef HAVE_ICONV_H
# include <iconv.h>
#endif
])
# Gettext.
AM_GNU_GETTEXT([external], [need-ngettext])
AM_GNU_GETTEXT_VERSION(0.12.1)
# Iconv
AC_CHECK_HEADERS(iconv.h,
[AC_CHECK_TYPE(iconv_t,:,
AC_DEFINE(iconv_t, int,
[Conversion descriptor type]),
[#include <iconv.h>])])
# Initialize the test suite.
AC_CONFIG_TESTDIR(tests)
AC_CONFIG_FILES([tests/Makefile tests/atlocal]) # FIXME: tests/preset?
AM_MISSING_PROG([AUTOM4TE], [autom4te])
AC_CHECK_LIB(iconv, iconv)
AC_SUBST(BACKUP_LIBEXEC_SCRIPTS)
AC_SUBST(BACKUP_SBIN_SCRIPTS)
AC_ARG_ENABLE(backup-scripts,
AC_HELP_STRING([--enable-backup-scripts],
[Create and install backup and restore scripts]),
[case $enableval in
yes) BACKUP_LIBEXEC_SCRIPTS='$(BACKUP_LIBEXEC_SCRIPTS_LIST)'
BACKUP_SBIN_SCRIPTS='$(BACKUP_SBIN_SCRIPTS_LIST)'
;;
esac])
AC_SUBST(BACKUP_SED_COND)
if date +%Y-%m-%d 2>/dev/null >&2; then
BACKUP_SED_COND='/^\#ELSE_DATE_FORMAT_OK/,/^\#ENDIF_DATE_FORMAT_OK/d;/^\#IF_DATE_FORMAT_OK/d'
else
BACKUP_SED_COND='/^\#IF_DATE_FORMAT_OK/,/^\#ELSE_DATE_FORMAT_OK/d;/^\#ENDIF_DATE_FORMAT_OK/d'
fi
AC_OUTPUT([Makefile\
@@ -287,6 +265,5 @@ AC_OUTPUT([Makefile\
lib/Makefile\
po/Makefile.in\
scripts/Makefile\
src/Makefile\
tests/Makefile\
tests/preset])
rmt/Makefile\
src/Makefile])

87
directory Normal file
View File

@@ -0,0 +1,87 @@
%%comments:
Copyright (C) 2004 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts. A copy of the license is included in the file COPYING.
%%name: tar
%%short-description: Creates tar archives
%%full-description:
GNU tar is an archiver that creates and handles file archives in various
formats. You can use tar to create file archives, to extract files from
previously created archives, store additional files, or update or list
files which were already stored.
The program saves many files together into a single tape or disk
archive, and can restore individual files from the archive. It
includes multivolume support, the ability to archive sparse files,
automatic archive compression/decompression, remote archives and
special features that allow 'tar' to be used for incremental and full
backups.
The supported archive formats are: V7 tar, GNU, ustar and POSIX (also
known as pax interchange format). GNU tar is also able to read and
extract 'star' archives.
Tar can direct its output to available devices, files, or other
programs (using pipes); tar can even access remote devices or files
(as archives).
%%category: system, backup
%%license: GPL
%%maintainer: Sergey Poznyakoff <gray@Mirddin.farlep.net>,
Jeff Bailey <jbailey@nisa.net>,
Paul Eggert <eggert@CS.UCLA.EDU>
%%updated: 20 Dec 2004
%%keywords: archive, backup, tar, pax
%%interface: Command line
%%programs: tar, rmt
%%GNU: yes
%%web-page: http://www.gnu.org/software/tar
%%doc: English user reference included
%%doc: English user manual in Texinfo, Dvi, Postscript, HTML, Plaintext is available from http://www.gnu.org/software/tar/manual/tar.html
%%developers:
John Gilmore,
Thomas Bushnell,
Paul Eggert <eggert@twinsun.com>,
Sergey Poznyakoff <gray@Mirddin.farlep.net>
%%contributors: Jay Fenlason,
Joy Kendall,
Francois Pinard <pinard@iro.umontreal.ca>
%%source-tarball: ftp://ftp.gnu.org/pub/gnu/tar/tar-1.15.tar.gz
%%source-info: http://savannah.gnu.org/projects/tar
%%repository:
:pserver:anoncvs@subversions.gnu.org:/cvsroot/tar login,
:pserver:anoncvs@subversions.gnu.org:/cvsroot/tar co tar,
http://savannah.gnu.org/cvs/?group=tar,
http://savannah.gnu.org/cgi-bin/viewcvs/tar/tar,
%%source-language: C
%%related-programs: GNU cpio
%%version: 1.15 (stable) released on 20 Dec 2004
%%bug-list: bug-tar@gnu.org bug-tar@gnu.org http://mail.gnu.org/mailman/listinfo/bug-tar
%%entry-written-by: Sergey Poznyakoff <gray@gnu.org>

View File

@@ -26,3 +26,9 @@ tar.ex
tar.ats
tar.exs
tar.kws
tmp-tar.*
tmp2-tar.*
html_mono
html_node
html_chapter
*.stamp

View File

@@ -18,10 +18,10 @@
## Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
info_TEXINFOS = tar.texi
tar_TEXINFOS = fdl.texi freemanuals.texi getdate.texi header.texi
EXTRA_DIST = convtexi.pl
EXTRA_DIST = convtexi.pl fdl.texi freemanuals.texi getdate.texi header.texi
CLEANFILES = tmp-*
CLEANFILES = tmp-* tmp2-* index.html
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
# Just call `make dvi RENDITION=PROOF' if you want PROOF rendition.
@@ -31,7 +31,7 @@ $(srcdir)/tar.info: tar.texi fdl.texi freemanuals.texi getdate.texi \
$(srcdir)/header.texi version.texi
$(MAKEINFO) --no-split -D$(RENDITION) -I$(srcdir) tar.texi -o $@
tar.dvi: tar.texi getdate.texi $(srcdir)/header.texi version.texi
tmp-tar.texi: tar.texi getdate.texi $(srcdir)/header.texi version.texi
$(MAKEINFO) -D$(RENDITION) -Etmp-tar.tmp -otmp-tar.info \
-I$(srcdir) tar.texi
rm -f tmp-tar.sed tmp-tar.info*
@@ -41,6 +41,8 @@ tar.dvi: tar.texi getdate.texi $(srcdir)/header.texi version.texi
|| echo >>tmp-tar.sed '/^@smallbook/d'
sed -f tmp-tar.sed tmp-tar.tmp > tmp-tar.texi
rm -f tmp-tar.sed tmp-tar.tmp
tar.dvi: tmp-tar.texi
TEXINPUTS=$(top_srcdir)/config:$$TEXINPUTS \
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
$(TEXI2DVI) tmp-tar.texi
@@ -49,3 +51,152 @@ tar.dvi: tar.texi getdate.texi $(srcdir)/header.texi version.texi
$(srcdir)/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' >$@
##
PROJECT=$(PACKAGE_TARNAME)
BASE_URL="http://www.gnu.org/software/$(PROJECT)/manual/"
TEXI2HTML=${SHELL} `cd $(top_srcdir); pwd`/config/missing --run texi2html
INFO=${SHELL} `cd $(top_srcdir); pwd`/config/missing --run info
DVIPDF=${SHELL} `cd $(top_srcdir); pwd`/config/missing --run dvipdf
clean-local:
rm -rf $(WEBDOC) $(WEB_HTML_STAMPS)
html: html_mono.stamp html_node.stamp html_chapter.stamp
tmp2-$(PROJECT).texi: Makefile tmp-$(PROJECT).texi
echo '/@copying/,/@end copying/{H;x;s/@copying//;s/@end copying//;x;}' > tmp2.sed
echo '/@insertcopying/{x;h;}' >> tmp2.sed
echo 's/\(.\)@ifset/\1\' >> tmp2.sed
echo '@ifset/' >> tmp2.sed
sed -f tmp2.sed tmp-$(PROJECT).texi > tmp2-$(PROJECT).texi
rm -f tmp2.sed
html_node.stamp: tmp2-$(PROJECT).texi
texi2html="$(TEXI2HTML)";\
if ! test -d html_node; then mkdir html_node; fi; \
cd html_node; \
$$texi2html -menu -split_node -prefix $(PROJECT) ../tmp2-$(PROJECT).texi; \
cd ..; \
touch html_node.stamp
html_chapter.stamp: tmp2-$(PROJECT).texi
texi2html="$(TEXI2HTML)";\
if ! test -d html_chapter; then mkdir html_chapter; fi; \
cd html_chapter; \
$$texi2html -menu -split_chapter -prefix $(PROJECT) ../tmp2-$(PROJECT).texi; \
cd ..; \
touch html_chapter.stamp
html_mono.stamp: tmp2-$(PROJECT).texi
texi2html="$(TEXI2HTML)";\
if ! test -d html_mono; then mkdir html_mono; fi; \
cd html_mono; \
$$texi2html -menu -monolithic -prefix $(PROJECT) ../tmp2-$(PROJECT).texi; \
cd ..; \
touch html_mono.stamp
ps: $(PROJECT).ps
$(PROJECT).ps: $(PROJECT).dvi
$(DVIPS) -o$(PROJECT).ps $(PROJECT).dvi
# Override the default rule. The texinfo <= 4.5 is unable to cope with
# tar docs.
$(PROJECT).pdf: $(PROJECT).dvi
$(DVIPDF) $(PROJECT).dvi
text: $(PROJECT).text
$(PROJECT).text: Makefile $(PROJECT).info
$(INFO) --node=Top --subnodes --out $(PROJECT).text -f ./$(PROJECT).info
$(PROJECT).info.tar.gz: Makefile
rm -f $(PROJECT).info.tar.gz
tar cf $(PROJECT).info.tar $(PROJECT).info*
gzip -f $(PROJECT).info.tar
$(PROJECT).dvi.gz: Makefile $(PROJECT).dvi
gzip -c $(PROJECT).dvi > $(PROJECT).dvi.gz
$(PROJECT).ps.gz: Makefile $(PROJECT).ps
gzip -c $(PROJECT).ps > $(PROJECT).ps.gz
$(PROJECT).pdf.gz: Makefile $(PROJECT).pdf
gzip -c $(PROJECT).pdf > $(PROJECT).pdf.gz
$(PROJECT).texi.tar.gz: Makefile $(info_TEXINFOS) $(tar_TEXINFOS)
tar cfz $(PROJECT).texi.tar.gz $(info_TEXINFOS) $(tar_TEXINFOS)
WEB_HTML=\
html_mono\
html_node\
html_chapter
WEB_HTML_STAMPS=$(patsubst %,%.stamp,$(WEB_HTML))
WEB_BIN=\
$(PROJECT).info.tar.gz\
$(PROJECT).dvi.gz\
$(PROJECT).pdf.gz\
$(PROJECT).ps.gz\
$(PROJECT).texi.tar.gz\
$(PROJECT).text
WEBDOC=$(WEB_HTML) $(WEB_BIN)
webdocdir: $(WEB_HTML_STAMPS) $(WEB_BIN) index.html
if ! test -d $(WEBDOCDIR); then mkdir $(WEBDOCDIR); fi; \
here=`cd $(srcdir) && pwd`; \
webdocdir=`cd $(WEBDOCDIR) && pwd`; \
for file in $(WEB_HTML) index.html; do \
if test -d $$here/$$file; then \
cp -pr $$here/$$file $$webdocdir/$$file; \
else \
test -f $$webdocdir/$$file \
|| ln $$here/$$file $$webdocdir/$$file 2> /dev/null \
|| cp -p $$here/$$file $$webdocdir/$$file || :; \
fi; \
done; \
if ! test -d $(WEBDOCDIR)/other; then mkdir $(WEBDOCDIR)/other; fi;\
for file in $(WEB_BIN); do \
if test -d $$here/$$file; then \
cp -pr $$here/$$file $$webdocdir/other/$$file; \
else \
test -f $$webdocdir/other/$$file \
|| ln $$here/$$file $$webdocdir/other/$$file 2> /dev/null \
|| cp -p $$here/$$file $$webdocdir/other/$$file || :; \
fi; \
done
index.html: index.html.in $(WEBDOC)
@echo "s^%BASE_URL%^$(BASE_URL)^;" > .webdoc
@echo "s/%DATE%/`date`/;" >> .webdoc
@echo "s/%UPDATED%/`date +'%B, %d'`/;" >> .webdoc
@echo "s/%PACKAGE_NAME%/$(PACKAGE_NAME)/" >> .webdoc
@echo "s/%PACKAGE%/$(PACKAGE)/" >> .webdoc
@echo "s/%VERSION%/$(VERSION)/" >> .webdoc
@for file in `sed -n 's,.*"other/%PACKAGE%\(.*\)".*,$(PACKAGE)\1,pg;s,.*"\(.*\)%PACKAGE%\(.*\)".*,\1$(PACKAGE)\2,pg' index.html.in`; \
do\
ls -sk $$file; \
done |\
$(AWK) -vPACKAGE=$(PACKAGE) \
'BEGIN { len = length(PACKAGE) } \
{ gsub("\\.", "_", $$2); \
if (match($$2,"/")) \
$$2=substr($$2,RSTART+1); \
print "s/%" toupper(substr($$2,len+2)) "_SIZE%/" $$1 "/;" }' >> .webdoc
sed -f .webdoc index.html.in > index.html
rm -f .webdoc
webdocname=$(PACKAGE)-$(VERSION)-doc
WEBDOCDIR=$(webdocname)
webdoc:
$(MAKE) RENDITION=PUBLISH WEBDOCDIR=$(top_builddir)/doc/$(webdocname) webdocdir
cd $(top_builddir)/doc &&\
tar cfz $(webdocname).tar.gz $(webdocname) &&\
rm -r $(webdocname)
## End of webdoc

View File

@@ -1,432 +0,0 @@
@node Date input formats
@chapter Date input formats
@c Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free Software
@c Foundation, Inc.
@c Permission is granted to copy, distribute and/or modify this document
@c under the terms of the GNU Free Documentation License, Version 1.1
@c or any later version published by the Free Software Foundation;
@c with no Invariant Sections, with no
@c Front-Cover Texts, and with no Back-Cover Texts.
@c A copy of the license is included in the section entitled ``GNU
@c Free Documentation License''.
@cindex date input formats
@findex getdate
First, a quote:
@quotation
Our units of temporal measurement, from seconds on up to months, are so
complicated, asymmetrical and disjunctive so as to make coherent mental
reckoning in time all but impossible. Indeed, had some tyrannical god
contrived to enslave our minds to time, to make it all but impossible
for us to escape subjection to sodden routines and unpleasant surprises,
he could hardly have done better than handing down our present system.
It is like a set of trapezoidal building blocks, with no vertical or
horizontal surfaces, like a language in which the simplest thought
demands ornate constructions, useless particles and lengthy
circumlocutions. Unlike the more successful patterns of language and
science, which enable us to face experience boldly or at least
level-headedly, our system of temporal calculation silently and
persistently encourages our terror of time.
@dots{} It is as though architects had to measure length in feet, width
in meters and height in ells; as though basic instruction manuals
demanded a knowledge of five different languages. It is no wonder then
that we often look into our own immediate past or future, last Tuesday
or a week from Sunday, with feelings of helpless confusion. @dots{}
--- Robert Grudin, @cite{Time and the Art of Living}.
@end quotation
This section describes the textual date representations that @sc{gnu}
programs accept. These are the strings you, as a user, can supply as
arguments to the various programs. The C interface (via the
@code{getdate} function) is not described here.
@cindex beginning of time, for @acronym{POSIX}
@cindex epoch, for @acronym{POSIX}
Although the date syntax here can represent any possible time since the
year zero, computer integers often cannot represent such a wide range of
time. On @acronym{POSIX} systems, the clock starts at 1970-01-01 00:00:00
@sc{utc}: @acronym{POSIX} does not require support for times before the
@acronym{POSIX} Epoch and times far in the future. Traditional Unix systems
have 32-bit signed @code{time_t} and can represent times from 1901-12-13
20:45:52 through 2038-01-19 03:14:07 @sc{utc}. Systems with 64-bit
signed @code{time_t} can represent all the times in the known
lifetime of the universe.
@menu
* General date syntax:: Common rules.
* Calendar date items:: 19 Dec 1994.
* Time of day items:: 9:20pm.
* Time zone items:: @sc{est}, @sc{pdt}, @sc{gmt}, ...
* Day of week items:: Monday and others.
* Relative items in date strings:: next tuesday, 2 years ago.
* Pure numbers in date strings:: 19931219, 1440.
* Authors of getdate:: Bellovin, Eggert, Salz, Berets, et al.
@end menu
@node General date syntax
@section General date syntax
@cindex general date syntax
@cindex items in date strings
A @dfn{date} is a string, possibly empty, containing many items
separated by whitespace. The whitespace may be omitted when no
ambiguity arises. The empty string means the beginning of today (i.e.,
midnight). Order of the items is immaterial. A date string may contain
many flavors of items:
@itemize @bullet
@item calendar date items
@item time of the day items
@item time zone items
@item day of the week items
@item relative items
@item pure numbers.
@end itemize
@noindent We describe each of these item types in turn, below.
@cindex numbers, written-out
@cindex ordinal numbers
@findex first @r{in date strings}
@findex next @r{in date strings}
@findex last @r{in date strings}
A few numbers may be written out in words in most contexts. This is
most useful for specifying day of the week items or relative items (see
below). Here is the list: @samp{first} for 1, @samp{next} for 2,
@samp{third} for 3, @samp{fourth} for 4, @samp{fifth} for 5,
@samp{sixth} for 6, @samp{seventh} for 7, @samp{eighth} for 8,
@samp{ninth} for 9, @samp{tenth} for 10, @samp{eleventh} for 11 and
@samp{twelfth} for 12. Also, @samp{last} means exactly @math{-1}.
@cindex months, written-out
When a month is written this way, it is still considered to be written
numerically, instead of being ``spelled in full''; this changes the
allowed strings.
@cindex language, in dates
In the current implementation, only English is supported for words and
abbreviations like @samp{AM}, @samp{DST}, @samp{EST}, @samp{first},
@samp{January}, @samp{Sunday}, @samp{tomorrow}, and @samp{year}.
@cindex language, in dates
@cindex time zone item
The output of @command{date} is not always acceptable as a date string,
not only because of the language problem, but also because there is no
standard meaning for time zone items like @samp{IST}. When using
@command{date} to generate a date string intended to be parsed later,
specify a date format that is independent of language and that does not
use time zone items other than @samp{UTC} and @samp{Z}. Here are some
ways to do this:
@example
$ LC_ALL=C TZ=UTC0 date
Fri Dec 15 19:48:05 UTC 2000
$ TZ=UTC0 date +"%Y-%m-%d %H:%M:%SZ"
2000-12-15 19:48:05Z
$ date --iso-8601=seconds # a GNU extension
2000-12-15T11:48:05-0800
$ date --rfc-822 # a GNU extension
Fri, 15 Dec 2000 11:48:05 -0800
$ date +"%Y-%m-%d %H:%M:%S %z" # %z is a GNU extension.
2000-12-15 11:48:05 -0800
@end example
@cindex case, ignored in dates
@cindex comments, in dates
Alphabetic case is completely ignored in dates. Comments may be introduced
between round parentheses, as long as included parentheses are properly
nested. Hyphens not followed by a digit are currently ignored. Leading
zeros on numbers are ignored.
@node Calendar date items
@section Calendar date items
@cindex calendar date item
A @dfn{calendar date item} specifies a day of the year. It is
specified differently, depending on whether the month is specified
numerically or literally. All these strings specify the same calendar date:
@example
1972-09-24 # @sc{iso} 8601.
72-9-24 # Assume 19xx for 69 through 99,
# 20xx for 00 through 68.
72-09-24 # Leading zeros are ignored.
9/24/72 # Common U.S. writing.
24 September 1972
24 Sept 72 # September has a special abbreviation.
24 Sep 72 # Three-letter abbreviations always allowed.
Sep 24, 1972
24-sep-72
24sep72
@end example
The year can also be omitted. In this case, the last specified year is
used, or the current year if none. For example:
@example
9/24
sep 24
@end example
Here are the rules.
@cindex @sc{iso} 8601 date format
@cindex date format, @sc{iso} 8601
For numeric months, the @sc{iso} 8601 format
@samp{@var{year}-@var{month}-@var{day}} is allowed, where @var{year} is
any positive number, @var{month} is a number between 01 and 12, and
@var{day} is a number between 01 and 31. A leading zero must be present
if a number is less than ten. If @var{year} is 68 or smaller, then 2000
is added to it; otherwise, if @var{year} is less than 100,
then 1900 is added to it. The construct
@samp{@var{month}/@var{day}/@var{year}}, popular in the United States,
is accepted. Also @samp{@var{month}/@var{day}}, omitting the year.
@cindex month names in date strings
@cindex abbreviations for months
Literal months may be spelled out in full: @samp{January},
@samp{February}, @samp{March}, @samp{April}, @samp{May}, @samp{June},
@samp{July}, @samp{August}, @samp{September}, @samp{October},
@samp{November} or @samp{December}. Literal months may be abbreviated
to their first three letters, possibly followed by an abbreviating dot.
It is also permitted to write @samp{Sept} instead of @samp{September}.
When months are written literally, the calendar date may be given as any
of the following:
@example
@var{day} @var{month} @var{year}
@var{day} @var{month}
@var{month} @var{day} @var{year}
@var{day}-@var{month}-@var{year}
@end example
Or, omitting the year:
@example
@var{month} @var{day}
@end example
@node Time of day items
@section Time of day items
@cindex time of day item
A @dfn{time of day item} in date strings specifies the time on a given
day. Here are some examples, all of which represent the same time:
@example
20:02:0
20:02
8:02pm
20:02-0500 # In @sc{est} (U.S. Eastern Standard Time).
@end example
More generally, the time of the day may be given as
@samp{@var{hour}:@var{minute}:@var{second}}, where @var{hour} is
a number between 0 and 23, @var{minute} is a number between 0 and
59, and @var{second} is a number between 0 and 59. Alternatively,
@samp{:@var{second}} can be omitted, in which case it is taken to
be zero.
@findex am @r{in date strings}
@findex pm @r{in date strings}
@findex midnight @r{in date strings}
@findex noon @r{in date strings}
If the time is followed by @samp{am} or @samp{pm} (or @samp{a.m.}
or @samp{p.m.}), @var{hour} is restricted to run from 1 to 12, and
@samp{:@var{minute}} may be omitted (taken to be zero). @samp{am}
indicates the first half of the day, @samp{pm} indicates the second
half of the day. In this notation, 12 is the predecessor of 1:
midnight is @samp{12am} while noon is @samp{12pm}.
(This is the zero-oriented interpretation of @samp{12am} and @samp{12pm},
as opposed to the old tradition derived from Latin
which uses @samp{12m} for noon and @samp{12pm} for midnight.)
@cindex time zone correction
@cindex minutes, time zone correction by
The time may alternatively be followed by a time zone correction,
expressed as @samp{@var{s}@var{hh}@var{mm}}, where @var{s} is @samp{+}
or @samp{-}, @var{hh} is a number of zone hours and @var{mm} is a number
of zone minutes. When a time zone correction is given this way, it
forces interpretation of the time relative to
Coordinated Universal Time (@sc{utc}), overriding any previous
specification for the time zone or the local time zone. The @var{minute}
part of the time of the day may not be elided when a time zone correction
is used. This is the best way to specify a time zone correction by
fractional parts of an hour.
Either @samp{am}/@samp{pm} or a time zone correction may be specified,
but not both.
@node Time zone items
@section Time zone items
@cindex time zone item
A @dfn{time zone item} specifies an international time zone, indicated
by a small set of letters, e.g., @samp{UTC} or @samp{Z}
for Coordinated Universal
Time. Any included periods are ignored. By following a
non-daylight-saving time zone by the string @samp{DST} in a separate
word (that is, separated by some white space), the corresponding
daylight saving time zone may be specified.
Time zone items other than @samp{UTC} and @samp{Z}
are obsolescent and are not recommended, because they
are ambiguous; for example, @samp{EST} has a different meaning in
Australia than in the United States. Instead, it's better to use
unambiguous numeric time zone corrections like @samp{-0500}, as
described in the previous section.
@node Day of week items
@section Day of week items
@cindex day of week item
The explicit mention of a day of the week will forward the date
(only if necessary) to reach that day of the week in the future.
Days of the week may be spelled out in full: @samp{Sunday},
@samp{Monday}, @samp{Tuesday}, @samp{Wednesday}, @samp{Thursday},
@samp{Friday} or @samp{Saturday}. Days may be abbreviated to their
first three letters, optionally followed by a period. The special
abbreviations @samp{Tues} for @samp{Tuesday}, @samp{Wednes} for
@samp{Wednesday} and @samp{Thur} or @samp{Thurs} for @samp{Thursday} are
also allowed.
@findex next @var{day}
@findex last @var{day}
A number may precede a day of the week item to move forward
supplementary weeks. It is best used in expression like @samp{third
monday}. In this context, @samp{last @var{day}} or @samp{next
@var{day}} is also acceptable; they move one week before or after
the day that @var{day} by itself would represent.
A comma following a day of the week item is ignored.
@node Relative items in date strings
@section Relative items in date strings
@cindex relative items in date strings
@cindex displacement of dates
@dfn{Relative items} adjust a date (or the current date if none) forward
or backward. The effects of relative items accumulate. Here are some
examples:
@example
1 year
1 year ago
3 years
2 days
@end example
@findex year @r{in date strings}
@findex month @r{in date strings}
@findex fortnight @r{in date strings}
@findex week @r{in date strings}
@findex day @r{in date strings}
@findex hour @r{in date strings}
@findex minute @r{in date strings}
The unit of time displacement may be selected by the string @samp{year}
or @samp{month} for moving by whole years or months. These are fuzzy
units, as years and months are not all of equal duration. More precise
units are @samp{fortnight} which is worth 14 days, @samp{week} worth 7
days, @samp{day} worth 24 hours, @samp{hour} worth 60 minutes,
@samp{minute} or @samp{min} worth 60 seconds, and @samp{second} or
@samp{sec} worth one second. An @samp{s} suffix on these units is
accepted and ignored.
@findex ago @r{in date strings}
The unit of time may be preceded by a multiplier, given as an optionally
signed number. Unsigned numbers are taken as positively signed. No
number at all implies 1 for a multiplier. Following a relative item by
the string @samp{ago} is equivalent to preceding the unit by a
multiplier with value @math{-1}.
@findex day @r{in date strings}
@findex tomorrow @r{in date strings}
@findex yesterday @r{in date strings}
The string @samp{tomorrow} is worth one day in the future (equivalent
to @samp{day}), the string @samp{yesterday} is worth
one day in the past (equivalent to @samp{day ago}).
@findex now @r{in date strings}
@findex today @r{in date strings}
@findex this @r{in date strings}
The strings @samp{now} or @samp{today} are relative items corresponding
to zero-valued time displacement, these strings come from the fact
a zero-valued time displacement represents the current time when not
otherwise changed by previous items. They may be used to stress other
items, like in @samp{12:00 today}. The string @samp{this} also has
the meaning of a zero-valued time displacement, but is preferred in
date strings like @samp{this thursday}.
When a relative item causes the resulting date to cross a boundary
where the clocks were adjusted, typically for daylight-saving time,
the resulting date and time are adjusted accordingly.
@node Pure numbers in date strings
@section Pure numbers in date strings
@cindex pure numbers in date strings
The precise interpretation of a pure decimal number depends
on the context in the date string.
If the decimal number is of the form @var{yyyy}@var{mm}@var{dd} and no
other calendar date item (@pxref{Calendar date items}) appears before it
in the date string, then @var{yyyy} is read as the year, @var{mm} as the
month number and @var{dd} as the day of the month, for the specified
calendar date.
If the decimal number is of the form @var{hh}@var{mm} and no other time
of day item appears before it in the date string, then @var{hh} is read
as the hour of the day and @var{mm} as the minute of the hour, for the
specified time of the day. @var{mm} can also be omitted.
If both a calendar date and a time of day appear to the left of a number
in the date string, but no relative item, then the number overrides the
year.
@node Authors of getdate
@section Authors of @code{getdate}
@cindex authors of @code{getdate}
@cindex Bellovin, Steven M.
@cindex Salz, Rich
@cindex Berets, Jim
@cindex MacKenzie, David
@cindex Meyering, Jim
@cindex Eggert, Paul
@code{getdate} was originally implemented by Steven M. Bellovin
(@email{smb@@research.att.com}) while at the University of North Carolina
at Chapel Hill. The code was later tweaked by a couple of people on
Usenet, then completely overhauled by Rich $alz (@email{rsalz@@bbn.com})
and Jim Berets (@email{jberets@@bbn.com}) in August, 1990. Various
revisions for the @sc{gnu} system were made by David MacKenzie, Jim Meyering,
Paul Eggert and others.
@cindex Pinard, F.
@cindex Berry, K.
This chapter was originally produced by Fran@,{c}ois Pinard
(@email{pinard@@iro.umontreal.ca}) from the @file{getdate.y} source code,
and then edited by K.@: Berry (@email{kb@@cs.umb.edu}).

79
doc/index.html.in Normal file
View File

@@ -0,0 +1,79 @@
<!-- X-URL: %BASE_URL% -->
<!-- Date: %DATE% -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<TITLE>%PACKAGE_NAME% Reference Manual - Table of Contents - GNU Project - Free Software Foundation (FSF)</TITLE>
<LINK REV="made" HREF="mailto:gray@gnu.org">
<BASE HREF="%BASE_URL%">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=US-ASCII">
<META NAME="keywords" CONTENT="tar rmt">
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#1F00FF" ALINK="#FF0000" VLINK="#9900DD">
<H1>%PACKAGE_NAME% Reference Manual - Table of Contents</H1>
<ADDRESS>Free Software Foundation</ADDRESS>
<ADDRESS>last updated %UPDATED%</ADDRESS>
<P>
<A HREF="/graphics/gnu-head-sm.jpg"><IMG SRC="/graphics/gnu-head-sm.jpg"
ALT=" [image of the Head of a GNU] "
WIDTH="129" HEIGHT="122">&#32;(jpeg 7k)</A>
<A HREF="/graphics/gnu-head.jpg">(jpeg 21k)</A>
<A HREF="/philosophy/gif.html">no gifs due to patent problems</A>
<P>
<P>
<P><HR><P>
<P>
This manual is available in the following formats:
<P>
<UL>
<LI>formatted in <A HREF="html_mono/%PACKAGE%.html">HTML
(%HTML_SIZE%K characters)</A> entirely on one web page.</LI>
<LI> formatted in <a href="html_chapter/%PACKAGE%_toc.html">HTML</a>
with one web page per chapter.</LI>
<LI> formatted in <a href="html_node/%PACKAGE%_toc.html">HTML</a>
with one web page per node.</LI>
<LI>formatted as an
<A HREF="other/%PACKAGE%.info.tar.gz">Info document (%INFO_TAR_GZ_SIZE%K characters
gzipped tar file)</A>.</LI>
<LI>formatted as
<A HREF="other/%PACKAGE%.text">ASCII text (%TEXT_SIZE%K characters)</A>.</LI>
<LI>formatted as
<A HREF="other/%PACKAGE%.dvi.gz">a TeX dvi file (%DVI_GZ_SIZE%K characters
gzipped)</A>.</LI>
<LI>formatted as
<A href="other/%PACKAGE%.ps.gz">a PostScript file (%PS_GZ_SIZE%K characters
gzipped)</A>.</LI>
<LI>formatted as
<A href="other/%PACKAGE%.pdf.gz">a PDF file (%PDF_GZ_SIZE%K characters
gzipped)</A>.</LI>
<LI>the original
<A HREF="other/%PACKAGE%.texi.tar.gz">Texinfo source (%TEXI_TAR_GZ_SIZE%K characters
gzipped tar file)</A></LI>
</UL>
<P>
<HR>
Return to <A HREF="/home.html">GNU's home page</A>.
<P>
Send FSF &amp; GNU inquiries &amp; questions to
<A HREF="mailto:gnu@gnu.org"><EM>gnu@gnu.org</EM></A>.
Other <A HREF="/home.html#ContactInfo">ways to contact</A> the FSF.
<P>
Comments on these web pages to
<A HREF="mailto:webmasters@www.gnu.org"><EM>webmasters@www.gnu.org</EM></A>,
send other questions to
<A HREF="mailto:gnu@gnu.org"><EM>gnu@gnu.org</EM></A>.
<P>
Copyright (C) 1997, 1998 Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111, USA
<P>
Verbatim copying and distribution of this entire article is
permitted in any medium, provided this notice is preserved.<HR>
</BODY>
</HTML>
<!--
Local Variables:
mode: html
end:
-->

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,33 @@
.deps
Makefile
Makefile.am
Makefile.in
addext.c
alloca.c
alloca.h
alloca_.h
allocsa.c
allocsa.h
allocsa.valgrind
argmatch.c
argmatch.h
argp-ba.c
argp-eexst.c
argp-fmtstream.c
argp-fmtstream.h
argp-fs-xinl.c
argp-help.c
argp-namefrob.h
argp-parse.c
argp-pv.c
argp-pvh.c
argp-xinl.c
argp.h
backupfile.c
backupfile.h
basename.c
charset.alias
chown.c
config.charset
dirname.c
dirname.h
error.c
@@ -20,13 +37,17 @@ exclude.h
exit.h
exitfail.c
exitfail.h
fchown-stub.c
fileblocks.c
fnmatch.c
fnmatch.h
fnmatch_.h
fnmatch_loop.c
ftruncate.c
full-write.c
full-write.h
getcwd.c
getcwd.h
getdate.c
getdate.h
getdate.y
@@ -37,27 +58,40 @@ getndelim2.h
getopt.c
getopt.h
getopt1.c
getopt_.h
getopt_int.h
getpagesize.h
gettext.h
gettime.c
gettimeofday.c
hash.c
hash.h
human.c
human.h
lchown.c
lchown.h
malloc.c
localcharset.c
localcharset.h
localedir.h
mempcpy.c
mempcpy.h
memset.c
mktime.c
modechange.c
modechange.h
obstack.c
obstack.h
pathmax.h
quote.c
quote.h
quotearg.c
quotearg.h
realloc.c
ref-add.sed
ref-add.sin
ref-del.sed
ref-del.sin
rmdir.c
rmt.h
rtapelib.c
safe-read.c
safe-read.h
safe-write.c
@@ -66,29 +100,43 @@ save-cwd.c
save-cwd.h
savedir.c
savedir.h
setenv.c
setenv.h
stat-macros.h
stdbool.h
stdbool_.h
stpcpy.c
stpcpy.h
strcase.h
strcasecmp.c
strchrnul.c
strchrnul.h
stripslash.c
strncasecmp.c
strndup.c
strndup.h
strnlen.c
strtoimax.c
strtol.c
strtoll.c
strtoul.c
strtoull.c
strtoumax.c
stpcpy.c
stpcpy.h
sysexit.h
sysexit_.h
sysexits.h
system.h
time_r.c
time_r.h
timespec.h
unlocked-io.h
unsetenv.c
utime.c
xalloc-die.c
xalloc.h
xgetcwd.c
xgetcwd.h
xmalloc.c
xstrdup.c
xstrtol.c
xstrtol.h
xstrtoul.c

View File

@@ -1,170 +0,0 @@
# Makefile for GNU tar library.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
noinst_LIBRARIES = libtar.a
libtar_a_SOURCES = prepargs.c prepargs.h
libtar_a_LIBADD = $(LIBOBJS) $(ALLOCA)
libtar_a_DEPENDENCIES = $(libtar_a_LIBADD)
BUILT_SOURCES =
EXTRA_DIST =
MAINTAINERCLEANFILES =
MOSTLYCLEANFILES =
lib_OBJECTS = $(libtar_a_OBJECTS)
# gnulib modules
# alloca
BUILT_SOURCES += $(ALLOCA_H)
EXTRA_DIST += alloca_.h
# We need the following in order to create an <alloca.h> when the system
# doesn't have one that works with the given compiler.
all-local $(lib_OBJECTS): $(ALLOCA_H)
alloca.h: alloca_.h
cp $(srcdir)/alloca_.h $@-t
mv $@-t $@
MOSTLYCLEANFILES += alloca.h alloca.h-t
# argmatch
libtar_a_SOURCES += argmatch.h argmatch.c
# backupfile
libtar_a_SOURCES += backupfile.h backupfile.c addext.c
# dirname
libtar_a_SOURCES += dirname.h dirname.c basename.c stripslash.c
# exclude
libtar_a_SOURCES += exclude.h exclude.c
# exitfail
libtar_a_SOURCES += exitfail.h exitfail.c
# exit
libtar_a_SOURCES += exit.h
# fnmatch
BUILT_SOURCES += $(FNMATCH_H)
EXTRA_DIST += fnmatch_.h fnmatch_loop.c
# stpcpy
EXTRA_DIST += stpcpy.c stpcpy.h
# We need the following in order to create an <fnmatch.h> when the system
# doesn't have one that supports the required API.
all-local $(lib_OBJECTS): $(FNMATCH_H)
fnmatch.h: fnmatch_.h
cp $(srcdir)/fnmatch_.h $@-t
mv $@-t $@
MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t
# full-write
libtar_a_SOURCES += full-write.h full-write.c
# getdate
libtar_a_SOURCES += getdate.h getdate.y
BUILT_SOURCES += getdate.c
MAINTAINERCLEANFILES += getdate.c
#
# 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
# getline
libtar_a_SOURCES += getline.h
EXTRA_DIST += getndelim2.h getndelim2.c
# getopt
libtar_a_SOURCES += getopt.h getopt.c getopt1.c
# gettext
libtar_a_SOURCES += gettext.h
# hash
libtar_a_SOURCES += hash.h hash.c
# human
libtar_a_SOURCES += human.h human.c
# lchown
libtar_a_SOURCES += lchown.h
# modechange
libtar_a_SOURCES += modechange.h modechange.c
# pathmax
libtar_a_SOURCES += pathmax.h
# time_r
EXTRA_DIST += time_r.h
# quote
libtar_a_SOURCES += quote.h quote.c
# quotearg
libtar_a_SOURCES += quotearg.h quotearg.c
# safe-read
libtar_a_SOURCES += safe-read.h safe-read.c
# safe-write
libtar_a_SOURCES += safe-write.h safe-write.c
# save-cwd
libtar_a_SOURCES += save-cwd.h save-cwd.c
# savedir
libtar_a_SOURCES += savedir.h savedir.c
# stdbool
BUILT_SOURCES += $(STDBOOL_H)
EXTRA_DIST += stdbool_.h
# strcase
EXTRA_DIST += strcase.h
# We need the following in order to create an <stdbool.h> when the system
# doesn't have one that works.
all-local $(lib_OBJECTS): $(STDBOOL_H)
stdbool.h: stdbool_.h
sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h > $@-t
mv $@-t $@
MOSTLYCLEANFILES += stdbool.h stdbool.h-t
# unlocked-io
libtar_a_SOURCES += unlocked-io.h
# xalloc
libtar_a_SOURCES += xalloc.h xmalloc.c xstrdup.c
# xgetcwd
libtar_a_SOURCES += xgetcwd.h xgetcwd.c
# xstrtol
libtar_a_SOURCES += xstrtol.h xstrtol.c xstrtoul.c
# xstrtoumax
libtar_a_SOURCES += xstrtoumax.c

56
lib/Makefile.tmpl Normal file
View File

@@ -0,0 +1,56 @@
# Makefile for GNU tar library.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004
# 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., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
noinst_LIBRARIES = libtar.a
noinst_HEADERS = system.h localedir.h rmt.h
libtar_a_SOURCES = prepargs.c prepargs.h rtapelib.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 's,^.*/,,;$(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,13 +1,18 @@
*_gl.m4
Makefile
Makefile.in
alloca.m4
allocsa.m4
argp.m4
backupfile.m4
bison.m4
chown.m4
clock_time.m4
codeset.m4
d-ino.m4
dirname.m4
dos.m4
eealloc.m4
error.m4
exclude.m4
exitfail.m4
@@ -15,13 +20,18 @@ extensions.m4
fileblocks.m4
fnmatch.m4
ftruncate.m4
getcwd-path-max.m4
getcwd.m4
getdate.m4
getline.m4
getndelim2.m4
getopt.m4
getpagesize.m4
gettext.m4
gettime.m4
gettimeofday.m4
glibc21.m4
gnulib.m4
hash.m4
human.m4
iconv.m4
@@ -37,45 +47,52 @@ lcmessage.m4
lib-ld.m4
lib-link.m4
lib-prefix.m4
localcharset.m4
longdouble.m4
longlong.m4
malloc.m4
mbrtowc.m4
mbstate_t.m4
mempcpy.m4
memset.m4
mktime.m4
modechange.m4
nls.m4
obstack.m4
onceonly.m4
pathmax.m4
po.m4
printf-posix.m4
progtest.m4
quote.m4
quotearg.m4
realloc.m4
restrict.m4
rmdir.m4
rmt.m4
safe-read.m4
safe-write.m4
save-cwd.m4
savedir.m4
setenv.m4
signed.m4
size_max.m4
ssize_t.m4
st_mtim.m4
stdbool.m4
stdint_h.m4
stpcpy.m4
strcase.m4
strchrnul.m4
strerror_r.m4
strndup.m4
strnlen.m4
strtoimax.m4
strtol.m4
strtoll.m4
strtoul.m4
strtoull.m4
strtoumax.m4
stpcpy.m4
sysexits.m4
time_r.m4
timespec.m4
tm_gmtoff.m4
uintmax_t.m4
ulonglong.m4

View File

@@ -24,6 +24,9 @@ lib/getopt.c
lib/human.c
lib/quotearg.c
lib/xmalloc.c
lib/rtapelib.c
lib/argp-help.c
rmt/rmt.c
# Package source files
src/buffer.c
@@ -37,8 +40,6 @@ src/list.c
src/mangle.c
src/misc.c
src/names.c
src/rmt.c
src/rtapelib.c
src/tar.c
src/update.c
src/xheader.c

View File

@@ -1,2 +1,6 @@
Makefile.in
Makefile
backup.sh
backup
restore
dump-remind

View File

@@ -1,6 +1,4 @@
# Makefile for GNU tar scripts.
# Copyright (C) 1994, 2003 Free Software Foundation, Inc.
# Copyright (C) 2004 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
@@ -13,7 +11,39 @@
## 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
EXTRA_DIST = WARNING backup-specs dump-remind level-0 level-1 weekly.new
BACKUP_LIBEXEC_SCRIPTS_LIST=backup.sh dump-remind
BACKUP_SBIN_SCRIPTS_LIST=backup restore
libexec_SCRIPTS=@BACKUP_LIBEXEC_SCRIPTS@
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=backup.sh dump-remind
sbin_SCRIPTS=@BACKUP_SBIN_SCRIPTS@
EXTRA_SCRIPTS=tarcat
EXTRA_DIST=\
backup.sh.in\
backup.in\
restore.in\
dump-remind.in\
backup-specs
CLEANFILES=backup.sh backup restore dump-remind
SED_CMD="s,\@libexecdir\@,$(libexecdir),;\
s,\@sysconfdir\@,$(sysconfdir),;\
s,\@PACKAGE\@,$(PACKAGE),;\
s,\@VERSION\@,$(VERSION),;\
s,\@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),;\
s,\@DATE_FORMAT_OK\@,$(DATE_FORMAT_OK),;@BACKUP_SED_COND@"
backup.sh: $(srcdir)/backup.sh.in
sed $(SED_CMD) $? > $@
backup: $(srcdir)/backup.in
sed $(SED_CMD) $? > $@
restore: $(srcdir)/restore.in
sed $(SED_CMD) $? > $@
dump-remind: $(srcdir)/dump-remind.in
sed $(SED_CMD) $? > $@

View File

@@ -1,3 +0,0 @@
GNU tar scripts have not been updated in a long while. make will
not not install them. Please consider the contents of this directory
are provided as indicative for the time being.

View File

@@ -1,34 +1,68 @@
# site-specific parameters for file system backup.
# This is a sample configuration file for GNU tar backup script.
# See end of file for copying conditions
# User name of administrator of backups.
ADMINISTRATOR=backup-reports
# User name or email address of the administrator of backups. A report
# will be sent to this address when the backup terminates
ADMINISTRATOR="root@localhost"
# Hour at which backups are normally done.
# This should be a number from 0 to 23.
BACKUP_HOUR=1
# (Optional) Path to tar binary.
TAR=/bin/tar
# Location of GNU tar. This must be the same for all hosts.
TAR=/usr/local/gnubin/tar
# (Optional) Path to rsh binary or its equivalent. You may wish to
# set it to ssh as shown in the example below, to improve security.
# In this case you will have to use public key authentication.
RSH=/usr/local/bin/ssh
# (Optional) Path to rsh binary on remote mashines. This will be
# passed via --rsh-command option to the remote invocation of
# tar
RSH_COMMAND=/usr/local/bin/ssh
# Name of temporary file to hold volume numbers. This needs to be accessible
# by all the machines which have filesystems to be dumped.
VOLNO_FILE=/root/volume
# Device to use for dumping. It should be on the host
# on which the dump scripts are run.
TAPE_FILE=/dev/nrsmt0
# Command to obtain status of tape drive, including error count.
# On some tape drives there may not be such a command;
# then simply use `TAPE_STATUS=false'.
#
# Might also consider
# TAPE_STATUS="mt -f ${TAPE_FILE} status"
# if `mts' is missing, though this alternative is rather verbose.
TAPE_STATUS="mts -t ${TAPE_FILE}"
TAPE_FILE=/dev/rmt0
# Blocking factor to use for writing the dump.
BLOCKING=124
# Name of temporary file to hold volume numbers. This needs to be accessible
# by all the machines which have filesystems to be dumped.
VOLNO_FILE=/home/gd2/dump/volnofile
# List of file systems to be dumped. If prefixed with a HOST:
# the filesystem is accessed on the given HOST, unless it
# coincides with the local machine name.
# If a file system starts with a slash, it is handled as a local
# one.
BACKUP_DIRS='remote1:/etc remote1:/var/spool/crontab'
# Alternatively, you may leave this variable unassigned, and
# keep the list of filesystems to be dumped in file
# $SYSCONFDIR/backup/dirs, one filesystem per line. Empty
# lines and shell comments are allowed in this file. The location
# of this file may be overridden using DIRLIST variable, e.g.:
# DIRLIST=/etc/my-backup/dirlist
# List of individual files to be dumped.
# These should be accesible from the machine on which the dump is run.
BACKUP_FILES=''
# This list may also be kept in file $SYSCONFDIR/backup/files, the
# format of which is the same as described above. The location of
# this file may be overridden by setting FILELIST variable:
# FILELIST=/etc/my-backup/filelist
# Name of 'exclude file list'. It is searched under $SYSCONFDIR/tar-backup
# on remote machines
XLIST=exclude_files
# Default directory for storing incremental listings on remote
# machines is $SYSCONFDIR/tar-backup. It can be overridden using
# REMOTEBACKUPDIR variable
# Default directory for storing backup logs is $SYSCONFDIR/backup/log.
# It can also be overridden via LOGPATH variable.
# Time to sleep between dumps of any two successive filesystems
SLEEP_TIME=15
# Script to be run when it's time to insert a new tape in for the next
# volume. Administrators may want to tailor this script for their site.
@@ -36,37 +70,6 @@ VOLNO_FILE=/home/gd2/dump/volnofile
# probably defined in the manual.
#DUMP_REMIND_SCRIPT='rsh apple-gunkies /home/gd2/dump/dump-remind'
# List of file systems to be dumped.
# Actually, any directory may be used, but if it has subdirectories on
# other file systems, they are not included.
# The host name specifies which host to run tar on.
# It should normally be the host that actually has the file system.
# If GNU tar is not installed on that machine, then you can specify some
# other host which can access the file system through NFS.
# Although these are arranged one per line, that is not mandatory.
# It does not work to use # for comments within the string.
BACKUP_DIRS='
albert:/fs/fsf
sugar-bombs:/fs/gd
albert:/fs/gd2
churchy:/fs/gd3
nutrimat:/fs/gp
nutrimat:/fs/gp2
albert:/fs/mailer
placebo:/archive
nutrimat:/fs/dist
albert:/
albert:/usr
nutrimat:/
placebo:/
ernst:/usr1
'
# List of individual files to be dumped.
# These should be accesible from the machine on which the dump is run.
BACKUP_FILES=''
# Message to display on the terminal while waiting for dump time. Usually
# this will just be some literal text, preferably something more
# entertaining than this. The awk script here saves some redundant
@@ -78,5 +81,20 @@ SLEEP_MESSAGE="`awk '
\"D O N O T T O U C H T H I S T E R M I N A L !!!!!\"
}' /dev/null`"
# Copyright (C) 2004 Free Software Foundation, Inc.
# eof
## 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., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.

255
scripts/backup.in Normal file
View File

@@ -0,0 +1,255 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright 2004, Free Software Foundation
#
# 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 1, 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Load library routines
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
. ${LIBDIR-@libexecdir@}/backup.sh
DUMP_LEVEL=0
TIME=
NOW=`now`
usage() {
cat - <<EOF
usage: $PROGNAME [OPTIONS] [WHEN]
Options are:
-l, --level=LEVEL Do backup level LEVEL (default $DUMP_LEVEL).
-f, --force Force backup even if today's log file already
exists.
-v, --verbose[=LEVEL] Set verbosity level. Default 100.
-t, --time=TIME Wait till TIME, then do backup.
Informational options:
-h, --help Display this help message.
-L, --license Display program license.
-V, --version Display program version.
Optional argument WHEN is for backward compatibility only. It has been
superseded by --time option.
TIME argument can be one of:
now -- do backup immediately.
HH -- do backup at HH hours.
HH:MM -- do backup at HH:MM.
Send bug reports to @PACKAGE_BUGREPORT@.
EOF
}
# For compatibility with previous versions, deduce the backup level
# from the command name
case "$PROGNAME" in
level-[0-9]) DUMP_LEVEL=`expr $PROGNAME : 'level-\([0-9][0-9]*\)'`;;
esac
for opt
do
if [ -z "$prev" ]; then
option=$opt
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
else
option="${prev}=$opt"
prev=""
optarg=$opt
fi
case $option in
--l=*|--le=*|--lev=*|--leve=*|--level=*)
DUMP_LEVEL=$optarg
;;
-l|--l|--le|--lev|--leve|--level)
prev=$option
;;
--verb=*|--verbo=*|--verbos=*|--verbose=*)
VERBOSE=$optarg
;;
-v|--verb|--verbo|--verbos|--verbose)
VERBOSE=100
;;
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
--t=*|--ti=*|--tim=*|--time=*)
TIME=$optarg
;;
-t) prev=--t;;
-t*) TIME=`expr $option : "-t\(.*\)"`;;
--t|--ti|--tim|--time)
prev=$option
;;
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "backup (@PACKAGE@ @VERSION@)"
exit 0;;
-L|--li|--lic|--lice|--licen|--licens|--license)
license
exit;;
-h|--h|--he|--hel|--help)
usage
exit;;
-f|--f|--fo|--for|--forc|--force)
FORCE=yes
;;
*) if [ "x$TIME" != "x" ]; then
bailout "Extra argument. Try $PROGNAME --help for more info."
else
TIME=$option
fi;;
esac
done
if [ "x$TIME" = x ]; then
bailout "No backup time specified. Try $PROGNAME --help for more info."
exit 1
fi
init_backup
# Maybe sleep until around specified or default hour.
wait_time $TIME
if [ $DUMP_LEVEL -ne 0 ]; then
PREV_LEVEL=`expr $DUMP_LEVEL - 1`
PREV_DATE=`ls -t ${LOGPATH}/log-*-level-$PREV_LEVEL|
head -1|
sed "s,${LOGPATH}/log-\(.*\)-level.*,\1,"`
if [ "x$PREV_DATE" = x ]; then
bailout "Can't determine date of the previous backup"
fi
message 0 "Backup from $PREV_DATE to $NOW"
fi
# start doing things
# Make sure the log file did not already exist. Create it.
if [ "x$FORCE" = "xyes" ]; then
rm ${LOGFILE}
fi
if [ -f "${LOGFILE}" ] ; then
bailout "Log file ${LOGFILE} already exists."
else
touch "${LOGFILE}"
fi
message 1 "Ready for backup."
message 10 "TAR invocation: $TAR_PART1"
message 20 "Variables:"
message 20 "BACKUP_DIRS=$BACKUP_DIRS"
message 20 "BACKUP_FILES=$BACKUP_FILES"
# The buch of commands below is run in a subshell for which all output is
# piped through `tee' to the logfile. Doing this, instead of having
# multiple pipelines all over the place, is cleaner and allows access to
# the exit value from various commands more easily.
(
message 1 "preparing tapes"
$MT_BEGIN "${TAPE_FILE}"
rm -f "${VOLNO_FILE}"
message 1 "processing backup directories"
set - ${BACKUP_DIRS}
while [ $# -ne 0 ] ; do
date="`date`"
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
remotehost="`expr \"${1}\" : '\([^/][^/]*\):.*'`"
if [ -z "$remotehost" ]; then
remotehost=$localhost
fi
echo "Backing up ${1} at ${date}"
message 10 "fs=$fs"
message 10 "fsname=$fsname"
message 10 "remotehost=$remotehost"
if [ $DUMP_LEVEL -eq 0 ]; then
make_level_log ${remotehost}
else
echo "Last `prev_level` dump on this filesystem was on $PREV_DATE"
remote_run "${remotehost}" cp "`level_log_name ${fsname} $PREV_LEVEL`" "`level_log_name temp`"
fi
${DUMP_BEGIN-:} $DUMP_LEVEL $remotehost $fs $fsname
backup_host ${remotehost} \
"--listed=`level_log_name temp`" \
"--label='`print_level` backup of ${fs} on ${remotehost} at ${NOW}'" \
-C ${ROOT_FS}${fs} .
# `rsh' doesn't exit with the exit status of the remote command. What
# stupid lossage. TODO: think of a reliable workaround.
if [ $? -ne 0 ] ; then
echo "Backup of ${1} failed." 1>&2
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
flush_level_log ${remotehost} ${fsname}
fi
${MT_STATUS}
${DUMP_END-:} $DUMP_LEVEL $remotehost $fs $fsname
echo "sleeping ${SLEEP_TIME} seconds"
sleep ${SLEEP_TIME}
shift
done
# Dump any individual files requested.
if [ "x${BACKUP_FILES}" != "x" ] ; then
message 1 "processing individual files"
date="`date`"
if [ $DUMP_LEVEL -eq 0 ]; then
make_level_log $localhost
else
echo "Last `prev_level` dump on this filesystem was on $PREV_DATE"
remote_run "${localhost}" cp "`level_log_name MISC $PREV_LEVEL`" "`level_log_name temp`"
fi
echo "Backing up miscellaneous files at ${date}"
${DUMP_BEGIN-:} $DUMP_LEVEL $localhost MISC MISC
backup_host $localhost \
"--listed=`level_log_name temp`"\
"--label='`print_level` backup of miscellaneous files at ${NOW}'" \
${BACKUP_FILES}
if [ $? -ne 0 ] ; then
echo "Backup of miscellaneous files failed."
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
flush_level_log $localhost MISC
fi
${MT_STATUS}
${DUMP_END-:} $DUMP_LEVEL $localhost MISC MISC
else
echo "No miscellaneous files specified"
fi
message 1 "final cleanup"
$MT_REWIND "${TAPE_FILE}"
$MT_OFFLINE "${TAPE_FILE}"
echo "."
) 2>&1 | tee -a "${LOGFILE}"
if test "${ADMINISTRATOR}" != NONE; then
echo "Sending the dump log to ${ADMINISTRATOR}"
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
fi
# EOF

346
scripts/backup.sh.in Normal file
View File

@@ -0,0 +1,346 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright 2004, Free Software Foundation
#
# 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 1, 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
PROGNAME=`basename $0`
CONFIGPATH="$SYSCONFDIR/backup"
REMOTEBACKUPDIR="$SYSCONFDIR/tar-backup"
CONFIGFILE=${CONFIGPATH}/backup-specs
DIRLIST=${CONFIGPATH}/dirs
FILELIST=${CONFIGPATH}/files
LOGPATH=${CONFIGPATH}/log
# Default functions for running various magnetic tape commands
mt_begin() {
mt -f "$1" retension
}
mt_rewind() {
mt -f "$1" rewind
}
mt_offline() {
mt -f "$1" offl
}
mt_status() {
mt -f "$1" status
}
# The main configuration file may override any of these variables
MT_BEGIN=mt_begin
MT_REWIND=mt_rewind
MT_OFFLINE=mt_offl
MT_STATUS=mt_status
# Insure `mail' is in PATH.
PATH="/usr/ucb:${PATH}"
export PATH
# Put startdate in the subject line of mailed report, since if it happens
# to run longer than 24 hours (as may be the case if someone forgets to put
# in the next volume of the tape in adequate time), the backup date won't
# appear too misleading.
startdate="`date`"
here="`pwd`"
# Save local hostname
localhost="`hostname | sed -e 's/\..*//' | tr A-Z a-z`"
# Produce a diagnostic output
message() {
if [ "$VERBOSE" != "" ]; then
if [ $VERBOSE -ge $1 ]; then
shift
echo "$@" >&2
fi
fi
}
# Bail out and exit.
bailout() {
echo "$PROGNAME: $*" >&2
exit 1
}
# Return current date
now() {
#IF_DATE_FORMAT_OK
date +%Y-%m-%d
#ELSE_DATE_FORMAT_OK
LC_ALL=C date | \
sed 's/[^ ]* *\([^ ]*\) *\([^ ]*\).* \([^ ]*\)$/\3-\1-\2/
/-[0-9]$/s/\([0-9]\)$/0\1/
/Jan/{s/Jan/01/p;q;}
/Feb/{s/Feb/02/p;q;}
/Mar/{s/Mar/03/p;q;}
/Apr/{s/Apr/04/p;q;}
/May/{s/May/05/p;q;}
/Jun/{s/Jun/06/p;q;}
/Jul/{s/Jul/07/p;q;}
/Aug/{s/Aug/08/p;q;}
/Sep/{s/Sep/09/p;q;}
/Oct/{s/Oct/10/p;q;}
/Nov/{s/Nov/11/p;q;}
/Dec/{s/Dec/12/p;q;}'
#ENDIF_DATE_FORMAT_OK
}
# Bail out if we don't have root privileges.
test_root() {
if [ ! -w ${ROOT_FS-/} ]; then
bailout "The backup must be run as root or else some files will fail to be dumped."
fi
case "${ROOT_FS}" in
*/) ;;
*) ROOT_FS="${ROOT_FS}/"
esac
}
advice() {
echo "Directory $1 is not found." >&2
cat >&2 <<EOF
The following directories and files are needed for the backup to function:
1. Directory with configuration files and file lists:
$CONFIGPATH
2. Directory for backup log files
$LOGPATH
3. Main configuration file
$CONFIGFILE
Please, create these and invoke the script again.
EOF
}
init_common() {
# Check if the necessary directories exist
if [ ! -d $CONFIGPATH ]; then
advice $CONFIGPATH
exit 1
fi
if [ ! -d $LOGPATH ]; then
if mkdir $LOGPATH; then
:
else
advice $LOGPATH
exit 1
fi
fi
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
if [ ! -r $CONFIGFILE ]; then
echo "$PROGNAME: cannot read $CONFIGFILE. Stop." >&2
exit 1
fi
. $CONFIGFILE
# Environment sanity check
test_root
if [ x"${ADMINISTRATOR}" = x ]; then
bailout "ADMINISTRATOR not defined"
fi
[ x"$TAR" = x ] && TAR=tar
[ x"$SLEEP_TIME" = x ] && SLEEP_TIME=60
if [ x$VOLNO_FILE = x ]; then
bailout "VOLNO_FILE not specified"
fi
if [ -r $DIRLIST ]; then
BACKUP_DIRS="$BACKUP_DIRS `cat $DIRLIST`"
fi
if [ -r $FILELIST ]; then
BACKUP_FILES="$BACKUP_FILES `cat $FILELIST`"
fi
if [ \( x"$BACKUP_DIRS" = x \) -a \( x"$BACKUP_FILES" = x \) ]; then
bailout "Neither BACKUP_DIRS nor BACKUP_FILES specified"
fi
if [ "$RSH" = "" ]; then
RSH=rsh
fi
POSIXLY_CORRECT=1
export POSIXLY_CORRECT
}
init_backup() {
init_common
TAR_PART1="${TAR} -c --format=gnu --multi-volume --one-file-system --sparse --volno-file=${VOLNO_FILE}"
if [ "x$XLIST" != x ]; then
TAR_PART1="${TAR_PART1} \`test -r $REMOTEBACKUPDIR/$XLIST && echo \"--exclude-from $REMOTEBACKUPDIR/$XLIST\"\`"
fi
if [ "$RSH_COMMAND" != "" ]; then
TAR_PART1="${TAR_PART1} --rsh-command=$RSH_COMMAND"
fi
if [ x$BLOCKING != x ]; then
TAR_PART1="${TAR_PART1} --blocking=${BLOCKING}"
fi
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
fi
# Set logfile name
# Logfile name should be in the form ``log-1993-03-18-level-0''
# They go in the directory `@sysconfdir@/log'.
# i.e. year-month-date. This format is useful for sorting by name, since
# logfiles are intentionally kept online for future reference.
LOGFILE="${LOGPATH}/log-`now`-level-${DUMP_LEVEL}"
}
init_restore() {
init_common
# FIXME: Replace --list with --extract
TAR_PART1="${TAR} --extract --multi-volume"
if [ "$RSH_COMMAND" != "" ]; then
TAR_PART1="${TAR_PART1} --rsh-command=$RSH_COMMAND"
fi
if [ x$BLOCKING != x ]; then
TAR_PART1="${TAR_PART1} --blocking=${BLOCKING}"
fi
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
fi
LOGFILE="${LOGPATH}/restore-`now`"
}
wait_time() {
if [ "${1}" != "now" ]; then
if [ "${1}x" != "x" ]; then
spec="${1}"
else
spec="${BACKUP_HOUR}"
fi
pausetime="`date | awk -v spec=\"${spec}\" '
BEGIN {
split(spec, time, ":")
}
{
split($4, now, ":")
diff = 3600 * (time[1] - now[1]) + 60 * (time[2] - now[2]);
if (diff < 0)
diff += 3600 * 24
print diff
}'`"
clear
echo "${SLEEP_MESSAGE}"
sleep "${pausetime}"
fi
}
level_log_name() {
echo "$REMOTEBACKUPDIR/${1}.level-${2-$DUMP_LEVEL}"
}
# Prepare a temporary level logfile
# usage: make_level_log HOSTNAME
make_level_log() {
if [ "z${localhost}" != "z$1" ] ; then
$RSH "$1" mkdir $REMOTEBACKUPDIR > /dev/null 2>&1
$RSH "$1" rm -f `level_log_name temp`
else
mkdir $REMOTEBACKUPDIR > /dev/null 2>&1
rm -f `level_log_name temp`
fi
}
# Rename temporary log
# usage: flush_level_log HOSTNAME FSNAME
flush_level_log() {
message 10 "RENAME: `level_log_name temp` --> `level_log_name $2`"
if [ "z${localhost}" != "z$1" ] ; then
$RSH "$1" mv -f `level_log_name temp` "`level_log_name $2`"
else
mv -f `level_log_name temp` "`level_log_name $2`"
fi
}
# Return the timestamp of the last backup.
# usage: get_dump_time LEVEL
get_dump_time() {
ls -r ${LOGPATH}/log-*-level-$1 \
| head -1 \
| sed "s,.*log-\(.*\)-level-$1,\1,"
}
# Do actual backup on a host
# usage: backup_host HOSTNAME [TAR_ARGUMENTS]
backup_host() {
message 10 "ARGS: $@"
rhost=$1
shift
if [ "z${localhost}" != "z$rhost" ] ; then
$RSH "$rhost" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" $@
else
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
CMD="exec ${TAR_PART1} -f \"${TAPE_FILE}\" $@"
message 10 "CMD: $CMD"
sh -c "$CMD"
message 10 "RC: $?"
fi
}
print_level() {
if [ ${1-$DUMP_LEVEL} -eq 0 ]; then
echo "Full"
else
echo "Level ${1-$DUMP_LEVEL}"
fi
}
prev_level() {
print_level `expr $DUMP_LEVEL - 1` | tr A-Z a-z
}
remote_run() {
rhost=$1
shift
message 10 "REMOTE $rhost: $@"
if [ "x$rhost" != "x${localhost}" ] ; then
$RSH "${rhost}" "$@"
else
$*
fi
}
license() {
cat - <<EOF
This program is part of GNU tar
Copyright 2004, Free Software Foundation
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 1, 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., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
EOF
}

9
scripts/dump-remind → scripts/dump-remind.in Executable file → Normal file
View File

@@ -13,11 +13,12 @@
PATH="/usr/lib:/usr/local/gnubin:${PATH}"
export PATH
# Get definition of TAPE_FILE, VOLNO_FILE, and so on.
. /home/gd2/dump/backup-specs
# Load library routines
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
. ${LIBPATH-@libexecdir@}/backup.sh
mt -f "${TAPE_FILE}" rewind
mt -f "${TAPE_FILE}" offl
MT_REWIND
MT_OFFLINE
volno="`cat \"${VOLNO_FILE}\" 2> /dev/null`"
if [ $? -ne 0 ]; then

View File

@@ -1,200 +0,0 @@
#!/bin/sh
#
# Run this script as root on the machine that has the tape drive, to make a
# full (level-0) dump.
#
# If you give `now' as an argument, the dump is done immediately.
# Otherwise, it waits until 1am, or until the hour given as argument.
# Specify the hour as a number from 0 to 23.
#
# You must edit the file `backup-specs' to set the parameters for your site.
# Useful for backup-specs, in case things have to be done slightly
# differently for different dump levels.
DUMP_LEVEL=0
# Insure `mail' is in PATH.
PATH="/usr/ucb:${PATH}"
export PATH
# This is not the most reliable test in the world. The following might be
# more predictable:
#
# whoami="`whoami`"
# euid="`sed -ne '/^'\"${whoami}\"':/{s/^[^:]*:[^:]*://;s/:.*//p;q;}' /etc/passwd`"
# if [ "${euid}" != 0 ]; then ...
#
if [ ! -w / ]; then
echo "The backup must be run as root or else some files will fail to be dumped."
exit 1
fi
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
. ./backup-specs
# Maybe sleep until around specified or default hour.
if [ "${1}" != "now" ]; then
if [ "${1}x" != "x" ]; then
spec="${1}"
else
spec="${BACKUP_HOUR}"
fi
pausetime="`date | awk '
{
hr = substr($4, 1, 2);
mn = substr($4, 4, 2);
if((hr + 0) < (spec + 0))
print 3600 * (spec - hr) - 60 * mn;
else
print 3600 * (spec + (24 - hr)) - 60 * mn;
}' spec=\"${spec}\"`"
clear
echo "${SLEEP_MESSAGE}"
sleep "${pausetime}"
fi
# start doing things
# Put startdate in the subject line of mailed report, since if it happens
# to run longer than 24 hours (as may be the case if someone forgets to put
# in the next volume of the tape in adequate time), the backup date won't
# appear too misleading.
startdate="`date`"
here="`pwd`"
# Logfile name should be in the form ``log-1993-03-18-level-0''
# They go in the subdirectory `log' of the current directory.
# i.e. year-month-date. This format is useful for sorting by name, since
# logfiles are intentionally kept online for future reference.
LOGFILE="log/log-`date | sed -ne '
s/[^ ]* *\([^ ]*\) *\([^ ]*\).* \([^ ]*\)$/\3-\1-\2/
/-[0-9]$/s/\([0-9]\)$/0\1/
/Jan/{s/Jan/01/p;q;}
/Feb/{s/Feb/02/p;q;}
/Mar/{s/Mar/03/p;q;}
/Apr/{s/Apr/04/p;q;}
/May/{s/May/05/p;q;}
/Jun/{s/Jun/06/p;q;}
/Jul/{s/Jul/07/p;q;}
/Aug/{s/Aug/08/p;q;}
/Sep/{s/Sep/09/p;q;}
/Oct/{s/Oct/10/p;q;}
/Nov/{s/Nov/11/p;q;}
/Dec/{s/Dec/12/p;q;}'`-level-${DUMP_LEVEL}"
localhost="`hostname | sed -e 's/\..*//'`"
TAR_PART1="${TAR} -c --multi-volume --one-file-system --blocking=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
fi
# Make sure the log file did not already exist. Create it.
if [ -f "${LOGFILE}" ] ; then
echo "Log file ${LOGFILE} already exists." 1>&2
exit 1
else
touch "${LOGFILE}"
fi
# Most everything below here is run in a subshell for which all output is
# piped through `tee' to the logfile. Doing this, instead of having
# multiple pipelines all over the place, is cleaner and allows access to
# the exit value from various commands more easily.
(
# Caveat: Some version of `mt' require `-t', not `-f'.
mt -f "${TAPE_FILE}" rewind
rm -f "${VOLNO_FILE}"
set - ${BACKUP_DIRS}
while [ $# -ne 0 ] ; do
date="`date`"
remotehost="`echo \"${1}\" | sed -e 's/:.*$//'`"
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
# This filename must be absolute; it is opened on the machine that runs tar.
TAR_PART2="--listed=/etc/tar-backup/temp.level-0"
TAR_PART3="--label='Full backup of ${fs} on ${remotehost} at ${date}' -C ${fs} ."
echo "Backing up ${1} at ${date}"
# Actually back things up.
if [ "z${localhost}" != "z${remotehost}" ] ; then
rsh "${remotehost}" mkdir /etc/tar-backup > /dev/null 2>&1
rsh "${remotehost}" rm -f /etc/tar-backup/temp.level-0
rsh "${remotehost}" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" ${TAR_PART2} ${TAR_PART3}
else
mkdir /etc/tar-backup > /dev/null 2>&1
rm -f /etc/tar-backup/temp.level-0
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3}"
fi
# `rsh' doesn't exit with the exit status of the remote command. What
# stupid lossage. TODO: think of a reliable workaround.
if [ $? -ne 0 ] ; then
echo "Backup of ${1} failed." 1>&2
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
if [ "z${localhost}" != "z${remotehost}" ] ; then
rsh "${remotehost}" mv -f /etc/tar-backup/temp.level-0 "/etc/tar-backup/${fsname}.level-0"
else
mv -f /etc/tar-backup/temp.level-0 "/etc/tar-backup/${fsname}.level-0"
fi
fi
${TAPE_STATUS}
sleep 60
shift
done
# Dump any individual files requested.
if [ "x${BACKUP_FILES}" != "x" ] ; then
date="`date`"
TAR_PART2="--listed=/etc/tar-backup/temp.level-0"
TAR_PART3="--label='Full backup of miscellaneous files at ${date}'"
mkdir /etc/tar-backup > /dev/null 2>&1
rm -f /etc/tar-backup/temp.level-0
echo "Backing up miscellaneous files at ${date}"
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3} ${BACKUP_FILES}"
# `rsh' doesn't exit with the exit status of the remote command. What
# lossage. TODO: think of a reliable workaround.
if [ $? -ne 0 ] ; then
echo "Backup of miscellaneous files failed."
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
mv -f /etc/tar-backup/temp.level-0 /etc/tar-backup/misc.level-0
fi
${TAPE_STATUS}
else
echo "No miscellaneous files specified"
fi
# Caveat: some versions of `mt' use `-t' instead of `-f'.
mt -f "${TAPE_FILE}" rewind
mt -f "${TAPE_FILE}" offl
) 2>&1 | tee -a "${LOGFILE}"
echo "Sending the dump log to ${ADMINISTRATOR}"
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
# eof

View File

@@ -1,203 +0,0 @@
#!/bin/sh
#
# Run this script as root on the machine that has the tape drive, to make a
# level-1 dump containing all files changed since the last full dump.
#
# If you give `now' as an argument, the dump is done immediately.
# Otherwise, it waits until 1am.
#
# You must edit the file `backup-specs' to set the parameters for your site.
# Useful for backup-specs, in case things have to be done slightly
# differently for different dump levels.
DUMP_LEVEL=1
# Insure `mail' is in PATH.
PATH="/usr/ucb:${PATH}"
export PATH
# This is not the most reliable test in the world. The following might be
# more predictable:
#
# whoami="`whoami`"
# euid="`sed -ne '/^'\"${whoami}\"':/{s/^[^:]*:[^:]*://;s/:.*//p;q;}' /etc/passwd`"
# if [ "${euid}" != 0 ]; then ...
#
if [ ! -w / ]; then
echo "The backup must be run as root or else some files will fail to be dumped."
exit 1
fi
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
. ./backup-specs
# Maybe sleep until around specified or default hour.
if [ "z${1}" != "znow" ]; then
if [ "${1}x" != "x" ]; then
spec="${1}"
else
spec="${BACKUP_HOUR}"
fi
pausetime="`date | awk '
{
hr = substr($4, 1, 2);
mn = substr($4, 4, 2);
if((hr + 0) < (spec + 0))
print 3600 * (spec - hr) - 60 * mn;
else
print 3600 * (spec + (24 - hr)) - 60 * mn;
}' spec=\"${spec}\"`"
clear
echo "${SLEEP_MESSAGE}"
sleep "${pausetime}"
fi
# start doing things
# Put startdate in the subject line of mailed report, since if it happens
# to run longer than 24 hours (as may be the case if someone forgets to put
# in the next volume of the tape in adequate time), the backup date won't
# appear too misleading.
startdate="`date`"
here="`pwd`"
# Logfile name should be in the form ``log-1993-03-18-level-1''
# They go in the subdirectory `log' of the current directory.
# i.e. year-month-date. This format is useful for sorting by name, since
# logfiles are intentionally kept online for future reference.
LOGFILE="log/log-`date | sed -ne '
s/[^ ]* *\([^ ]*\) *\([^ ]*\).* \([^ ]*\)$/\3-\1-\2/
/-[0-9]$/s/\([0-9]\)$/0\1/
/Jan/{s/Jan/01/p;q;}
/Feb/{s/Feb/02/p;q;}
/Mar/{s/Mar/03/p;q;}
/Apr/{s/Apr/04/p;q;}
/May/{s/May/05/p;q;}
/Jun/{s/Jun/06/p;q;}
/Jul/{s/Jul/07/p;q;}
/Aug/{s/Aug/08/p;q;}
/Sep/{s/Sep/09/p;q;}
/Oct/{s/Oct/10/p;q;}
/Nov/{s/Nov/11/p;q;}
/Dec/{s/Dec/12/p;q;}'`-level-${DUMP_LEVEL}"
localhost="`hostname | sed -e 's/\..*//'`"
TAR_PART1="${TAR} -c --multi-volume --one-file-system --blocking=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
fi
# Make sure the log file did not already exist. Create it.
if [ -f "${LOGFILE}" ] ; then
echo "Log file ${LOGFILE} already exists." 1>&2
exit 1
else
touch "${LOGFILE}"
fi
# Most everything below here is run in a subshell for which all output is
# piped through `tee' to the logfile. Doing this, instead of having
# multiple pipelines all over the place, is cleaner and allows access to
# the exit value from various commands more easily.
(
# Caveat: Some version of `mt' require `-t', not `-f'.
mt -f "${TAPE_FILE}" rewind
rm -f "${VOLNO_FILE}"
set - ${BACKUP_DIRS}
while [ $# -ne 0 ] ; do
date="`date`"
remotehost="`echo \"${1}\" | sed -e 's/:.*$//'`"
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
# This filename must be absolute; it is opened on the machine that runs tar.
TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
TAR_PART3="--label='level 1 backup of ${fs} on ${remotehost} at ${date}' -C ${fs} ."
echo "Backing up ${1} at ${date}"
echo "Last full dump on this filesystem:"
if [ "z${remotehost}" != "z${localhost}" ] ; then
rsh "${remotehost}" "ls -l /etc/tar-backup/${fsname}.level-0; \
cp /etc/tar-backup/${fsname}.level-0 /etc/tar-backup/temp.level-1"
else
ls -l "/etc/tar-backup/${fsname}.level-0"
cp "/etc/tar-backup/${fsname}.level-0" /etc/tar-backup/temp.level-1
fi
# Actually back things up.
if [ "z${remotehost}" != "z${localhost}" ] ; then
rsh "${remotehost}" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" ${TAR_PART2} ${TAR_PART3}
else
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3}"
fi
# `rsh' doesn't exit with the exit status of the remote command. What
# stupid lossage. TODO: think of a reliable workaround.
if [ $? -ne 0 ] ; then
echo "Backup of ${1} failed."
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
if [ "z${localhost}" != "z${remotehost}" ] ; then
rsh "${remotehost}" mv -f /etc/tar-backup/temp.level-1 "/etc/tar-backup/${fsname}.level-1"
else
mv -f /etc/tar-backup/temp.level-1 "/etc/tar-backup/${fsname}.level-1"
fi
fi
${TAPE_STATUS}
sleep 60
shift
done
# Dump any individual files requested.
if [ "x${BACKUP_FILES}" != "x" ] ; then
date="`date`"
TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
TAR_PART3="--label='Incremental backup of miscellaneous files at ${date}'"
echo "Backing up miscellaneous files at ${date}"
echo "Last full dump of these files:"
ls -l /etc/tar-backup/misc.level-0
rm -f /etc/tar-backup/temp.level-1
cp /etc/tar-backup/misc.level-0 /etc/tar-backup/temp.level-1
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3} ${BACKUP_FILES}"
if [ $? -ne 0 ] ; then
echo "Backup of miscellaneous files failed." 1>&2
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/misc.level-1
fi
${TAPE_STATUS}
else
echo "No miscellaneous files specified"
fi
# Caveat: some versions of `mt' use `-t' instead of `-f'.
mt -f "${TAPE_FILE}" rewind
mt -f "${TAPE_FILE}" offl
) 2>&1 | tee -a "${LOGFILE}"
echo "Sending the dump log to ${ADMINISTRATOR}"
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
# eof

236
scripts/restore.in Normal file
View File

@@ -0,0 +1,236 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright 2004, Free Software Foundation
#
# 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 1, 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Load library routines
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
. ${LIBDIR-@libexecdir@}/backup.sh
usage() {
cat - <<EOF
usage: $PROGNAME [OPTIONS] [PATTERN [PATTERN...]]
Options are:
-a, --all Restore all filesystems.
-l, --level=LEVEL Start restoring from the given backup LEVEL
(default $DUMP_LEVEL).
-v, --verbose[=LEVEL] Set verbosity level. Default 100.
Informational options:
-h, --help Display this help message.
-L, --license Display program license.
-V, --version Display program version.
Send bug reports to @PACKAGE_BUGREPORT@.
EOF
}
unset PATTERN
DUMP_LEVEL=0
CMDLINE="$0 $@"
for opt
do
if [ -z "$prev" ]; then
option=$opt
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
else
option="${prev}=$opt"
prev=""
optarg=$opt
fi
case $option in
-a|--a|--al|--all)
RESTORE_ALL=1
;;
--l=*|--le=*|--lev=*|--leve=*|--level=*)
DUMP_LEVEL=$optarg
;;
-l|--l|--le|--lev|--leve|--level)
prev=$option
;;
--verb=*|--verbo=*|--verbos=*|--verbose=*)
VERBOSE=$optarg
;;
-v|--verb|--verbo|--verbos|--verbose)
VERBOSE=100
;;
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "restore (@PACKAGE@ @VERSION@)"
exit 0;;
-L|--li|--lic|--lice|--licen|--licens|--license)
license
exit;;
-h|--h|--he|--hel|--help)
usage
exit;;
-*) bailout "Unknown option $opt. Try $PROGNAME --help for more info.";;
*) if [ -z "$PATTERN" ]; then
PATTERN=$opt
else
PATTERN="$PATTERN|$opt"
fi
;;
esac
done
if [ -z "$RESTORE_ALL" ]; then
if [ -z "$PATTERN" ]; then
usage
exit;
fi
fi
init_restore
cat > $LOGFILE <<EOF
This file contains any messages produced by $PROGNAME.
It was created by GNU $PROGNAME, from @PACKAGE@ (@VERSION@).
Invocation command line was
\$ $CMDLINE
EOF
restore_fs()
{
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
remotehost="`expr \"${1}\" : '\([^/][^/]*\):.*'`"
if [ -z "$remotehost" ]; then
remotehost=$localhost
fi
message 10 "fs=$fs"
message 10 "fsname=$fsname"
message 10 "remotehost=$remotehost"
LOGPAT="`level_log_name ${fsname} '[0-9]'`"
PREFIX="`level_log_name ${fsname} ''`"
message 10 LOGPAT=$LOGPAT
message 10 PREFIX=$PREFIX
LEVELS=`remote_run "${remotehost}" ls $LOGPAT |
sed "s,$PREFIX,," | sort -n`
message 10 "LEVELS=$LEVELS"
echo "Starting restore of ${1} at level $DUMP_LEVEL."
for level in $LEVELS
do
if [ $level -lt $DUMP_LEVEL ]; then
message 10 "Skipping level $level"
continue;
fi
message 10 "Restoring level $level"
DATE=`get_dump_time $level`
FILE="`level_log_name ${fsname} ${level}`"
message 10 "FILE=$FILE"
LABEL="`print_level $level` backup of ${fs} on ${remotehost} at ${DATE}"
${RESTORE_BEGIN-:} $level $remotehost $fs $fsname
backup_host ${remotehost} \
"--listed=\"$FILE\"" \
"--label=\"$LABEL\"" \
-C ${ROOT_FS-/}$fs
${RESTORE_END-:} $level $remotehost $fs $fsname
done
}
restore_files()
{
LOGPAT="`level_log_name MISC '[0-9]'`"
PREFIX="`level_log_name MISC ''`"
message 10 LOGPAT=$LOGPAT
message 10 PREFIX=$PREFIX
LEVELS=`remote_run "${localhost}" ls $LOGPAT | sed "s,$PREFIX,," | sort -n`
message 10 "LEVELS=$LEVELS"
echo "Starting restore of miscellaneous files at level $DUMP_LEVEL."
for level in $LEVELS
do
if [ $level -lt $DUMP_LEVEL ]; then
message 10 "Skipping level $level"
continue;
fi
message 10 "Restoring level $level"
DATE=`get_dump_time $level`
FILE="`level_log_name MISC ${level}`"
message 10 "FILE=$FILE"
LABEL="`print_level $level` backup of miscellaneous files at ${DATE}"
${RESTORE_BEGIN-:} $level $localhost MISC MISC
backup_host ${localhost} \
"--listed=\"$FILE\"" \
"--label=\"$LABEL\"" \
-C ${ROOT_FS-/} $@
${RESTORE_END-:} $level $localhost MISC MISC
done
}
# Operation Overwiew:
#
# 1. Determine the time of the last backup
# 2. Create list of incremental listings to process
# 3. For each filesystem:
# 3.1. Start at the requested dump level (default 0) and proceed up to
# the last available level:
# 3.1.1 Deduce the volume label
# 3.1.2. Invoke [rsh] tar --listed=FILE --label=LABEL [opts] -xf $TAPE_FILE
# 4. End
(message 1 "Preparing for restore"
message 1 "processing backup directories"
for dir in ${BACKUP_DIRS}
do
message 1 "Processing $dir"
case $dir in
${PATTERN-*}) restore_fs $dir;;
esac
done
if [ "x${BACKUP_FILES}" != "x" ] ; then
message 1 "processing miscellaneous files"
if [ -z "$PATTERN" ]; then
restore_files
else
RESTORE_FILES=""
for file in ${BACKUP_FILES}
do
rel_file=`expr $file : '/\(.*\)'`
case $file in
$PATTERN) if [ -z "$RESTORE_FILES" ]; then
RESTORE_FILES="$rel_file"
else
RESTORE_FILES="$RESTORE_FILES $rel_file"
fi;;
esac
done
[ -z "$RESTORE_FILES" ] || restore_files $RESTORE_FILES
fi
fi) 2>&1 | tee -a "${LOGFILE}"
# EOF

11
scripts/tarcat Executable file
View File

@@ -0,0 +1,11 @@
#! /bin/sh
# Usage: tarcat volume1 volume2 ...
# concatenates a GNU tar multi-volume archive into a single tar archive.
# Author: Bruno Haible <bruno@clisp.org>
cat "$1"
shift
for f
do
dd skip=1 if="$f"
done

View File

@@ -1,42 +0,0 @@
#!/bin/sh
# start doing things
TOBACKUP="albert:/"
HOST=`hostname | sed 's/\..*//'`
TAPEFILE=/dev/rfd0a
LOGFILE=tar-out
BLOCKING=20
TAR_PART1="/usr/local/bin/tar clbfVM $BLOCKING"
rm -f $LOGFILE
mt -f $TAPEFILE rewind
host=`echo $TOBACKUP | sed 's/:.*$//'`;
fs=`echo $TOBACKUP | sed 's/^.*://'`;
date=`date`;
fsname=`echo $TOBACKUP | sed 's/\//:/g'`
TAR_PART2="'Weekly backup of $fs on $host at $date' -C $fs ."
echo Backing up $TOBACKUP at $date | tee -a $LOGFILE
# Actually back things up.
if [ $HOST != $host ] ; then
rsh $host $TAR_PART1 $HOST:$TAPEFILE $TAR_PART2
else
sh -c "exec $TAR_PART1 $TAPEFILE $TAR_PART2"
fi
if [ $? -ne 0 ] ; then
echo Backup of $TOBACKUP failed. | tee -a $LOGFILE
echo mts at time of failure | tee -a $LOGFILE
mts -t $TAPEFILE | tee -a $LOGFILE
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
echo $date > $fsname.lasttar
fi
sleep 60;
mt -f $TAPEFILE rewind
mt -f $TAPEFILE offl

View File

@@ -3,4 +3,5 @@ Makefile
localedir.h
rmt
tar
.deps
.deps
.gdbinit

View File

@@ -19,11 +19,8 @@
## 02111-1307, USA.
bin_PROGRAMS = tar
libexec_PROGRAMS = @RMT@
EXTRA_PROGRAMS = rmt
noinst_HEADERS = arith.h common.h rmt.h system.h tar.h
rmt_SOURCES = rmt.c
noinst_HEADERS = arith.h common.h tar.h
tar_SOURCES = \
buffer.c\
compare.c\
@@ -36,22 +33,16 @@ tar_SOURCES = \
mangle.c\
misc.c\
names.c\
rtapelib.c\
sparse.c\
system.c\
tar.c\
update.c\
utf8.c
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/lib -I../lib
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
DISTCLEANFILES = localedir.h
localedir.h : Makefile
echo '#define LOCALEDIR "$(localedir)"' >$@
rmt.o tar.o : localedir.h
tar.o: ../lib/localedir.h
LDADD = ../lib/libtar.a $(LIBINTL)
LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
rmt_LDADD = $(LDADD) $(LIB_SETSOCKOPT)
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)

View File

@@ -19,7 +19,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include <signal.h>
@@ -28,7 +28,7 @@
#include <quotearg.h>
#include "common.h"
#include "rmt.h"
#include <rmt.h>
/* Number of retries before giving up on read. */
#define READ_ERROR_MAX 10
@@ -40,6 +40,7 @@
static tarlong prev_written; /* bytes written on previous volumes */
static tarlong bytes_written; /* bytes written on this volume */
static void *record_buffer; /* allocated memory */
/* FIXME: The following variables should ideally be static to this
module. However, this cannot be done yet. The cleanup continues! */
@@ -66,16 +67,19 @@ static pid_t child_pid;
static int read_error_count;
/* Have we hit EOF yet? */
static int hit_eof;
static bool hit_eof;
/* Checkpointing counter */
static int checkpoint;
static bool read_full_records = false;
static bool reading_from_pipe = false;
/* We're reading, but we just read the last block and it's time to update.
Declared in update.c
As least EXTERN like this one as possible. (?? --gray)
FIXME: Either eliminate it or move it to common.h.
FIXME: Either eliminate it or move it to common.h.
*/
extern bool time_to_start_writing;
@@ -109,11 +113,139 @@ static off_t real_s_sizeleft;
/* Functions. */
void
clear_read_error_count ()
clear_read_error_count (void)
{
read_error_count = 0;
}
/* Time-related functions */
double duration;
void
set_start_time ()
{
#if HAVE_CLOCK_GETTIME
if (clock_gettime (CLOCK_REALTIME, &start_timespec) != 0)
#endif
start_time = time (0);
}
void
compute_duration ()
{
#if HAVE_CLOCK_GETTIME
struct timespec now;
if (clock_gettime (CLOCK_REALTIME, &now) == 0)
duration += ((now.tv_sec - start_timespec.tv_sec)
+ (now.tv_nsec - start_timespec.tv_nsec) / 1e9);
else
#endif
duration += time (NULL) - start_time;
set_start_time ();
}
/* Compression detection */
enum compress_type {
ct_none,
ct_compress,
ct_gzip,
ct_bzip2
};
struct zip_magic
{
enum compress_type type;
unsigned char *magic;
size_t length;
char *program;
char *option;
};
static struct zip_magic magic[] = {
{ ct_none, },
{ ct_compress, "\037\235", 2, "compress", "-Z" },
{ ct_gzip, "\037\213", 2, "gzip", "-z" },
{ ct_bzip2, "BZh", 3, "bzip2", "-j" },
};
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
#define compress_option(t) magic[t].option
#define compress_program(t) magic[t].program
/* Check if the file FD is a compressed archive. FD is guaranteed to
represent a local file */
enum compress_type
check_compressed_archive (int fd)
{
struct zip_magic *p;
size_t status;
union block buf;
status = read (fd, &buf, sizeof buf);
if (status != sizeof buf)
{
archive_read_error ();
FATAL_ERROR ((0, 0, _("Quitting now.")));
}
lseek (fd, 0, SEEK_SET); /* This will fail if fd==0, but that does not
matter, since we do not handle compressed
stdin anyway */
if (tar_checksum (&buf) == HEADER_SUCCESS)
/* Probably a valid header */
return ct_none;
for (p = magic + 1; p < magic + NMAGIC; p++)
if (memcmp (buf.buffer, p->magic, p->length) == 0)
return p->type;
return ct_none;
}
/* Open an archive named archive_name_array[0]. Detect if it is
a compressed archive of known type and use corresponding decompression
program if so */
int
open_compressed_archive ()
{
enum compress_type type;
int fd = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
MODE_RW, rsh_command_option);
if (fd == -1 || _isrmt (fd))
return fd;
type = check_compressed_archive (fd);
if (type == ct_none)
{
if (rmtlseek (fd, (off_t) 0, SEEK_CUR) != 0)
{
/* Archive may be not seekable. Reopen it. */
rmtclose (fd);
fd = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
MODE_RW, rsh_command_option);
}
return fd;
}
/* FD is not needed any more */
rmtclose (fd);
/* Open compressed archive */
use_compress_program_option = compress_program (type);
child_pid = sys_child_open_for_uncompress ();
read_full_records = reading_from_pipe = true;
return archive;
}
void
print_total_written (void)
{
@@ -121,25 +253,16 @@ print_total_written (void)
char bytes[sizeof (tarlong) * CHAR_BIT];
char abbr[LONGEST_HUMAN_READABLE + 1];
char rate[LONGEST_HUMAN_READABLE + 1];
double seconds;
int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
#if HAVE_CLOCK_GETTIME
struct timespec now;
if (clock_gettime (CLOCK_REALTIME, &now) == 0)
seconds = ((now.tv_sec - start_timespec.tv_sec)
+ (now.tv_nsec - start_timespec.tv_nsec) / 1e9);
else
#endif
seconds = time (0) - start_time;
sprintf (bytes, TARLONG_FORMAT, written);
/* 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 < seconds && written / seconds < (uintmax_t) -1
? human_readable (written / seconds, rate, human_opts, 1, 1)
(0 < duration && written / duration < (uintmax_t) -1
? human_readable (written / duration, rate, human_opts, 1, 1)
: "?"));
}
@@ -156,7 +279,7 @@ reset_eof (void)
{
if (hit_eof)
{
hit_eof = 0;
hit_eof = false;
current_block = record_start;
record_end = record_start + blocking_factor;
access_mode = ACCESS_WRITE;
@@ -176,7 +299,7 @@ find_next_block (void)
flush_archive ();
if (current_block == record_end)
{
hit_eof = 1;
hit_eof = true;
return 0;
}
}
@@ -270,29 +393,28 @@ open_archive (enum access_mode wanted_access)
save_name = 0;
real_s_name = 0;
record_start =
page_aligned_alloc (&record_buffer,
(record_size
+ (multi_volume_option ? 2 * BLOCKSIZE : 0)));
if (multi_volume_option)
{
record_start = valloc (record_size + (2 * BLOCKSIZE));
if (record_start)
record_start += 2;
}
else
record_start = valloc (record_size);
if (!record_start)
FATAL_ERROR ((0, 0, _("Cannot allocate memory for blocking factor %d"),
blocking_factor));
record_start += 2;
current_block = record_start;
record_end = record_start + blocking_factor;
/* When updating the archive, we start with reading. */
access_mode = wanted_access == ACCESS_UPDATE ? ACCESS_READ : wanted_access;
read_full_records = read_full_records_option;
reading_from_pipe = false;
if (use_compress_program_option)
{
switch (wanted_access)
{
case ACCESS_READ:
child_pid = sys_child_open_for_uncompress ();
read_full_records = reading_from_pipe = true;
break;
case ACCESS_WRITE:
@@ -310,14 +432,24 @@ open_archive (enum access_mode wanted_access)
}
else if (strcmp (archive_name_array[0], "-") == 0)
{
read_full_records_option = 1; /* could be a pipe, be safe */
read_full_records = true; /* could be a pipe, be safe */
if (verify_option)
FATAL_ERROR ((0, 0, _("Cannot verify stdin/stdout archive")));
switch (wanted_access)
{
case ACCESS_READ:
archive = STDIN_FILENO;
{
enum compress_type type;
archive = STDIN_FILENO;
type = check_compressed_archive (archive);
if (type != ct_none)
FATAL_ERROR ((0, 0,
_("Archive is compressed. Use %s option"),
compress_option (type)));
}
break;
case ACCESS_WRITE:
@@ -339,8 +471,7 @@ open_archive (enum access_mode wanted_access)
switch (wanted_access)
{
case ACCESS_READ:
archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
MODE_RW, rsh_command_option);
archive = open_compressed_archive ();
break;
case ACCESS_WRITE:
@@ -408,8 +539,10 @@ open_archive (enum access_mode wanted_access)
else
strcpy (record_start->header.name, volume_label_option);
assign_string (&current_stat_info.file_name, record_start->header.name);
current_stat_info.had_trailing_slash = strip_trailing_slashes (current_stat_info.file_name);
assign_string (&current_stat_info.file_name,
record_start->header.name);
current_stat_info.had_trailing_slash =
strip_trailing_slashes (current_stat_info.file_name);
record_start->header.typeflag = GNUTYPE_VOLHDR;
TIME_TO_CHARS (start_time, record_start->header.mtime);
@@ -512,17 +645,24 @@ flush_write (void)
if (volume_label_option)
record_start++;
if (strlen (real_s_name) > NAME_FIELD_SIZE)
FATAL_ERROR ((0, 0,
_("%s: file name too long to be stored in a GNU multivolume header"),
quotearg_colon (real_s_name)));
memset (record_start, 0, BLOCKSIZE);
/* FIXME: Michael P Urban writes: [a long name file] is being written
when a new volume rolls around [...] Looks like the wrong value is
being preserved in real_s_name, though. */
strcpy (record_start->header.name, real_s_name);
strncpy (record_start->header.name, real_s_name, NAME_FIELD_SIZE);
record_start->header.typeflag = GNUTYPE_MULTIVOL;
OFF_TO_CHARS (real_s_sizeleft, record_start->header.size);
OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
record_start->oldgnu_header.offset);
tmp = verbose_option;
verbose_option = 0;
finish_header (&current_stat_info, record_start, -1);
@@ -597,7 +737,7 @@ archive_read_error (void)
}
static void
short_read (ssize_t status)
short_read (size_t status)
{
size_t left; /* bytes left */
char *more; /* pointer to next byte to read */
@@ -606,26 +746,29 @@ short_read (ssize_t status)
left = record_size - status;
while (left % BLOCKSIZE != 0
|| (left && status && read_full_records_option))
|| (left && status && read_full_records))
{
if (status)
while ((status = rmtread (archive, more, left)) < 0)
while ((status = rmtread (archive, more, left)) == SAFE_READ_ERROR)
archive_read_error ();
if (status == 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
WARN((0, 0, _("Read %s bytes from %s"),
STRINGIFY_BIGINT (record_size - left, buf),
*archive_name_cursor));
if (!reading_from_pipe)
{
char buf[UINTMAX_STRSIZE_BOUND];
WARN((0, 0, _("Read %s bytes from %s"),
STRINGIFY_BIGINT (record_size - left, buf),
*archive_name_cursor));
}
break;
}
if (! read_full_records_option)
if (! read_full_records)
{
unsigned long rest = record_size - left;
FATAL_ERROR ((0, 0,
ngettext ("Unaligned block (%lu byte) in archive",
"Unaligned block (%lu bytes) in archive",
@@ -642,8 +785,8 @@ short_read (ssize_t status)
/* FIXME: for size=0, multi-volume support. On the first record, warn
about the problem. */
if (!read_full_records_option && verbose_option
&& record_start_block == 0 && status > 0)
if (!read_full_records && verbose_option > 1
&& record_start_block == 0 && status != 0)
{
unsigned long rsize = (record_size - left) / BLOCKSIZE;
WARN ((0, 0,
@@ -661,7 +804,7 @@ short_read (ssize_t status)
void
flush_read (void)
{
ssize_t status; /* result from system call */
size_t status; /* result from system call */
if (checkpoint_option && !(++checkpoint % 10))
WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
@@ -703,9 +846,14 @@ flush_read (void)
return;
}
/* The condition below used to include
|| (status > 0 && !read_full_records)
This is incorrect since even if new_volume() succeeds, the
subsequent call to rmtread will overwrite the chunk of data
already read in the buffer, so the processing will fail */
if ((status == 0
|| (status < 0 && errno == ENOSPC)
|| (status > 0 && !read_full_records_option))
|| (status == SAFE_READ_ERROR && errno == ENOSPC))
&& multi_volume_option)
{
union block *cursor;
@@ -726,12 +874,12 @@ flush_read (void)
break;
}
while ((status =
rmtread (archive, record_start->buffer, record_size)) < 0)
while ((status = rmtread (archive, record_start->buffer, record_size))
== SAFE_READ_ERROR)
archive_read_error ();
if (status != record_size)
short_read (status);
short_read (status);
cursor = record_start;
@@ -760,7 +908,7 @@ flush_read (void)
{
uintmax_t s1, s2;
if (cursor->header.typeflag != GNUTYPE_MULTIVOL
|| strcmp (cursor->header.name, real_s_name))
|| strncmp (cursor->header.name, real_s_name, NAME_FIELD_SIZE))
{
WARN ((0, 0, _("%s is not continued on this volume"),
quote (real_s_name)));
@@ -799,7 +947,7 @@ flush_read (void)
records_read++;
return;
}
else if (status < 0)
else if (status == SAFE_READ_ERROR)
{
archive_read_error ();
goto error_loop; /* try again */
@@ -881,6 +1029,42 @@ backspace_output (void)
}
}
off_t
seek_archive (off_t size)
{
off_t start = current_block_ordinal ();
off_t offset;
off_t nrec, nblk;
off_t skipped = (blocking_factor - (current_block - record_start));
size -= skipped * BLOCKSIZE;
if (size < record_size)
return 0;
/* FIXME: flush? */
/* Compute number of records to skip */
nrec = size / record_size;
offset = rmtlseek (archive, nrec * record_size, SEEK_CUR);
if (offset < 0)
return offset;
if (offset % record_size)
FATAL_ERROR ((0, 0, _("rmtlseek not stopped at a record boundary")));
/* Convert to number of records */
offset /= BLOCKSIZE;
/* Compute number of skipped blocks */
nblk = offset - start;
/* Update buffering info */
records_read += nblk / blocking_factor;
record_start_block = offset - blocking_factor;
current_block = record_end;
return nblk;
}
/* Close the archive file. */
void
close_archive (void)
@@ -889,21 +1073,22 @@ close_archive (void)
flush_archive ();
sys_drain_input_pipe ();
if (verify_option)
compute_duration ();
if (verify_option)
verify_volume ();
if (rmtclose (archive) != 0)
close_warn (*archive_name_cursor);
sys_wait_for_child (child_pid);
tar_stat_destroy (&current_stat_info);
if (save_name)
free (save_name);
if (real_s_name)
free (real_s_name);
free (multi_volume_option ? record_start - 2 : record_start);
free (record_buffer);
}
/* Called to initialize the global volume number. */
@@ -949,7 +1134,7 @@ closeout_volume_number (void)
Return nonzero on success.
*/
static bool
new_volume (enum access_mode access)
new_volume (enum access_mode mode)
{
static FILE *read_file;
static int looped;
@@ -1071,14 +1256,14 @@ new_volume (enum access_mode access)
if (strcmp (archive_name_cursor[0], "-") == 0)
{
read_full_records_option = true;
read_full_records = true;
archive = STDIN_FILENO;
}
else if (verify_option)
archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,
rsh_command_option);
else
switch (access)
switch (mode)
{
case ACCESS_READ:
archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW,
@@ -1101,7 +1286,7 @@ new_volume (enum access_mode access)
if (archive < 0)
{
open_warn (*archive_name_cursor);
if (!verify_option && access == ACCESS_WRITE && backup_option)
if (!verify_option && mode == ACCESS_WRITE && backup_option)
undo_last_backup ();
goto tryagain;
}

View File

@@ -1,7 +1,7 @@
/* Common declarations for the tar program.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003 Free Software Foundation, Inc.
2003, 2004 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
@@ -38,11 +38,6 @@
/* Some various global definitions. */
/* Name of file to use for interacting with user. */
#if MSDOS
# define TTY_NAME "con"
#else
# define TTY_NAME "/dev/tty"
#endif
/* GLOBAL is defined to empty in tar.c only, and left alone in other *.c
modules. Here, we merely set it to "extern" if it is not already set.
@@ -85,6 +80,7 @@ GLOBAL int exit_status;
#include <modechange.h>
#include <quote.h>
#include <safe-read.h>
#include <timespec.h>
/* Log base 2 of common values. */
#define LG_8 3
@@ -128,6 +124,9 @@ GLOBAL size_t record_size;
GLOBAL bool absolute_names_option;
/* Display file times in UTC */
GLOBAL bool utc_option;
/* This variable tells how to interpret newer_mtime_option, below. If zero,
files get archived if their mtime is not less than newer_mtime_option.
If nonzero, files get archived if *either* their ctime or mtime is not less
@@ -156,11 +155,12 @@ 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;
/* Specified file containing names to work on. */
GLOBAL const char *files_from_option;
GLOBAL bool force_local_option;
/* Specified value to be put into tar file in place of stat () results, or
just -1 if such an override should not take place. */
GLOBAL gid_t group_option;
@@ -181,11 +181,12 @@ GLOBAL uintmax_t occurrence_option;
enum old_files
{
DEFAULT_OLD_FILES, /* default */
DEFAULT_OLD_FILES, /* default */
NO_OVERWRITE_DIR_OLD_FILES, /* --no-overwrite-dir */
OVERWRITE_OLD_FILES, /* --overwrite */
UNLINK_FIRST_OLD_FILES, /* --unlink-first */
KEEP_OLD_FILES /* --keep-old-files */
OVERWRITE_OLD_FILES, /* --overwrite */
UNLINK_FIRST_OLD_FILES, /* --unlink-first */
KEEP_OLD_FILES, /* --keep-old-files */
KEEP_NEWER_FILES /* --keep-newer-files */
};
GLOBAL enum old_files old_files_option;
@@ -197,13 +198,23 @@ GLOBAL struct mode_change *mode_option;
GLOBAL bool multi_volume_option;
/* The same variable hold the time, whether mtime or ctime. Just fake a
/* The same variable holds the time, whether mtime or ctime. Just fake a
non-existing option, for making the code clearer, elsewhere. */
#define newer_ctime_option newer_mtime_option
/* Specified threshold date and time. Files having an older time stamp
do not get archived (also see after_date_option above). */
GLOBAL time_t newer_mtime_option;
GLOBAL struct timespec newer_mtime_option;
/* Return true if newer_mtime_option is initialized. */
#define NEWER_OPTION_INITIALIZED(opt) (0 <= (opt).tv_nsec)
/* Return true if the struct stat ST's M time is less than
newer_mtime_option. */
#define OLDER_STAT_TIME(st, m) \
((st).st_##m##time < newer_mtime_option.tv_sec \
|| ((st).st_##m##time == newer_mtime_option.tv_sec \
&& TIMESPEC_NS ((st).st_##m##tim) < newer_mtime_option.tv_nsec))
/* Zero if there is no recursion, otherwise FNM_LEADING_DIR. */
GLOBAL int recursion_option;
@@ -222,6 +233,9 @@ GLOBAL bool read_full_records_option;
GLOBAL bool remove_files_option;
/* Specified rmt command. */
GLOBAL const char *rmt_command_option;
/* Specified remote shell command. */
GLOBAL const char *rsh_command_option;
@@ -233,9 +247,9 @@ GLOBAL int same_owner_option;
/* If positive, preserve permissions when extracting. */
GLOBAL int same_permissions_option;
/* When set, strip the given number of path elements from the file name
/* When set, strip the given number of file name components from the file name
before extracting */
GLOBAL size_t strip_path_elements;
GLOBAL size_t strip_name_components;
GLOBAL bool show_omitted_dirs_option;
@@ -313,6 +327,10 @@ struct name
GLOBAL dev_t ar_dev;
GLOBAL ino_t ar_ino;
GLOBAL bool seekable_archive;
GLOBAL dev_t root_device;
/* Declarations for each module. */
@@ -352,6 +370,8 @@ void clear_read_error_count (void);
void xclose (int fd);
void archive_write_error (ssize_t) __attribute__ ((noreturn));
void archive_read_error (void);
off_t seek_archive (off_t size);
void set_start_time (void);
/* Module create.c. */
@@ -363,7 +383,7 @@ enum dump_status
dump_status_not_implemented
};
bool file_dumpable_p (struct tar_stat_info *stat);
bool file_dumpable_p (struct tar_stat_info *);
void create_archive (void);
void pad_archive (off_t size_left);
void dump_file (char *, int, dev_t);
@@ -422,7 +442,7 @@ void delete_archive_members (void);
char *get_directory_contents (char *, dev_t);
void read_directory_file (void);
void write_directory_file (void);
void gnu_restore (char const *);
void purge_directory (char const *);
/* Module list.c. */
@@ -481,6 +501,7 @@ 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);
enum read_header tar_checksum (union block *header);
void skip_file (off_t);
void skip_member (void);
@@ -500,7 +521,15 @@ enum remove_option
{
ORDINARY_REMOVE_OPTION,
RECURSIVE_REMOVE_OPTION,
WANT_DIRECTORY_REMOVE_OPTION
/* FIXME: The following value is never used. It seems to be intended
as a placeholder for a hypothetical option that should instruct tar
to recursively remove subdirectories in purge_directory(),
as opposed to the functionality of --recursive-unlink
(RECURSIVE_REMOVE_OPTION value), which removes them in
prepare_to_extract() phase. However, with the addition of more
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);
@@ -531,7 +560,7 @@ void open_diag (char const *name);
void read_error (char const *);
void read_error_details (char const *, off_t, size_t);
void read_fatal (char const *) __attribute__ ((noreturn));
void read_fatal_details (char const *, off_t, size_t);
void read_fatal_details (char const *, off_t, size_t) __attribute__ ((noreturn));
void read_warn_details (char const *, off_t, size_t);
void read_diag_details (char const *name, off_t offset, size_t size);
void readlink_error (char const *);
@@ -555,7 +584,7 @@ void unlink_error (char const *);
void utime_error (char const *);
void waitpid_error (char const *);
void write_error (char const *);
void write_error_details (char const *, ssize_t, size_t);
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)
__attribute__ ((noreturn));
@@ -563,18 +592,20 @@ void write_fatal_details (char const *, ssize_t, size_t)
pid_t xfork (void);
void xpipe (int[2]);
void *page_aligned_alloc (void **, size_t);
/* Module names.c. */
extern struct name *gnu_list_name;
void gid_to_gname (gid_t, char **gname);
int gname_to_gid (char *gname, gid_t *);
int gname_to_gid (char const *, gid_t *);
void uid_to_uname (uid_t, char **uname);
int uname_to_uid (char *uname, uid_t *);
int uname_to_uid (char const *, uid_t *);
void init_names (void);
void name_add (const char *);
void name_init (int, char *const *);
void name_init (void);
void name_term (void);
char *name_next (int);
void name_close (void);
@@ -595,9 +626,12 @@ bool excluded_name (char const *);
void add_avoided_name (char const *);
bool is_avoided_name (char const *);
bool is_individual_file (char const *);
bool contains_dot_dot (char const *);
bool removed_prefixes_p (void);
#define ISFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
(c)->found_count == occurrence_option)
#define WASFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
@@ -605,11 +639,14 @@ bool contains_dot_dot (char const *);
/* Module tar.c. */
void usage (int);
int confirm (const char *, const char *);
void request_stdin (const char *);
void tar_stat_init (struct tar_stat_info *st);
void tar_stat_destroy (struct tar_stat_info *st);
void usage (int) __attribute__ ((noreturn));
/* Module update.c. */
@@ -620,16 +657,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 *);
void xheader_read (union block *, size_t);
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 *);
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);
/* Module system.c */
void sys_stat_nanoseconds (struct tar_stat_info *stat);
void sys_stat_nanoseconds (struct tar_stat_info *);
void sys_detect_dev_null_output (void);
void sys_save_archive_dev_ino (void);
void sys_drain_input_pipe (void);
@@ -640,17 +683,23 @@ bool sys_compare_gid (struct stat *a, struct stat *b);
bool sys_file_is_archive (struct tar_stat_info *p);
bool sys_compare_links (struct stat *link_data, struct stat *stat_data);
int sys_truncate (int fd);
void sys_reset_uid_gid (void);
pid_t sys_child_open_for_compress (void);
pid_t sys_child_open_for_uncompress (void);
ssize_t sys_write_archive_buffer (void);
size_t sys_write_archive_buffer (void);
bool sys_get_archive_stat (void);
/* 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 *stat);
enum dump_status sparse_dump_file (int fd, struct tar_stat_info *stat);
enum dump_status sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size);
bool sparse_diff_file (int fd, struct tar_stat_info *stat);
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 *);
/* Module utf8.c */
bool string_ascii_p (const char *str);
bool utf8_convert (bool to_utf, char const *input, char **output);

View File

@@ -1,7 +1,7 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003 Free Software Foundation, Inc.
2003, 2004 Free Software Foundation, Inc.
Written by John Gilmore, on 1987-04-30.
@@ -19,7 +19,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#if HAVE_UTIME_H
# include <utime.h>
@@ -38,7 +38,7 @@ struct utimbuf
#include <quotearg.h>
#include "common.h"
#include "rmt.h"
#include <rmt.h>
#include <stdarg.h>
/* Nonzero if we are verifying at the moment. */
@@ -54,15 +54,15 @@ static char *diff_buffer;
void
diff_init (void)
{
diff_buffer = valloc (record_size);
if (!diff_buffer)
xalloc_die ();
void *ptr;
diff_buffer = page_aligned_alloc (&ptr, record_size);
}
/* 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, const char *fmt, ...)
report_difference (struct tar_stat_info *st __attribute__ ((unused)),
const char *fmt, ...)
{
if (fmt)
{
@@ -74,35 +74,34 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
va_end (ap);
fprintf (stdlis, "\n");
}
if (exit_status == TAREXIT_SUCCESS)
exit_status = TAREXIT_DIFFERS;
}
/* Take a buffer returned by read_and_process and do nothing with it. */
static int
process_noop (size_t size, char *data)
process_noop (size_t size __attribute__ ((unused)),
char *data __attribute__ ((unused)))
{
/* Yes, I know. SIZE and DATA are unused in this function. Some
compilers may even report it. That's OK, just relax! */
return 1;
}
static int
process_rawdata (size_t bytes, char *buffer)
{
ssize_t status = safe_read (diff_handle, diff_buffer, bytes);
size_t status = safe_read (diff_handle, diff_buffer, bytes);
if (status != bytes)
{
if (status < 0)
if (status == SAFE_READ_ERROR)
{
read_error (current_stat_info.file_name);
report_difference (&current_stat_info, NULL);
}
else
{
report_difference (&current_stat_info,
report_difference (&current_stat_info,
ngettext ("Could only read %lu of %lu byte",
"Could only read %lu of %lu bytes",
bytes),
@@ -279,7 +278,7 @@ diff_archive (void)
/* Need to treat sparse files completely differently here. */
if (current_header->header.typeflag == GNUTYPE_SPARSE)
if (current_stat_info.is_sparse)
sparse_diff_file (diff_handle, &current_stat_info);
else
{
@@ -308,19 +307,20 @@ diff_archive (void)
case LNKTYPE:
{
struct stat link_data, stat_data;
struct stat file_data;
struct stat link_data;
if (!get_stat_data (current_stat_info.file_name, &stat_data))
if (!get_stat_data (current_stat_info.file_name, &file_data))
break;
if (!get_stat_data (current_stat_info.link_name, &link_data))
break;
if (!sys_compare_links (&stat_data, &link_data))
if (!sys_compare_links (&file_data, &link_data))
report_difference (&current_stat_info,
_("Not linked to %s"),
quote (current_stat_info.link_name));
}
break;
#ifdef HAVE_READLINK
case SYMTYPE:
{
@@ -494,6 +494,14 @@ diff_archive (void)
void
verify_volume (void)
{
if (removed_prefixes_p ())
{
WARN((0, 0,
_("Archive contains file names with leading prefixes removed.")));
WARN((0, 0,
_("Verification may fail to locate original files.")));
}
if (!diff_buffer)
diff_init ();
@@ -555,6 +563,7 @@ verify_volume (void)
do
{
counter++;
set_next_block_after (current_header);
status = read_header (false);
}
while (status == HEADER_FAILURE);
@@ -568,6 +577,8 @@ verify_volume (void)
break;
diff_archive ();
tar_stat_destroy (&current_stat_info);
xheader_destroy (&extended_header);
}
access_mode = ACCESS_WRITE;

View File

@@ -19,7 +19,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#if HAVE_UTIME_H
# include <utime.h>
@@ -337,11 +337,11 @@ string_to_chars (char *str, char *p, size_t s)
b) current archive is /dev/null */
bool
file_dumpable_p (struct tar_stat_info *stat)
file_dumpable_p (struct tar_stat_info *st)
{
return !(dev_null_output
|| (stat->archive_file_size == 0
&& (stat->stat.st_mode & MODE_R) == MODE_R));
|| (st->archive_file_size == 0
&& (st->stat.st_mode & MODE_R) == MODE_R));
}
@@ -376,7 +376,7 @@ start_private_header (const char *name, size_t size)
{
time_t t;
union block *header = find_next_block ();
memset (header->buffer, 0, sizeof (union block));
tar_copy_str (header->header.name, name, NAME_FIELD_SIZE);
@@ -397,7 +397,7 @@ start_private_header (const char *name, size_t size)
/* Create a new header and store there at most NAME_FIELD_SIZE bytes of
the file name */
static union block *
static union block *
write_short_name (struct tar_stat_info *st)
{
union block *header = find_next_block ();
@@ -406,6 +406,11 @@ write_short_name (struct tar_stat_info *st)
return header;
}
#define FILL(field,byte) do { \
memset(field, byte, sizeof(field)-1); \
(field)[sizeof(field)-1] = 0; \
} while (0)
/* Write a GNUTYPE_LONGLINK or GNUTYPE_LONGNAME block. */
static void
write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
@@ -413,8 +418,22 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
size_t size = strlen (p) + 1;
size_t bufsize;
union block *header;
char *tmpname;
header = start_private_header ("././@LongLink", size);
FILL(header->header.mtime, '0');
FILL(header->header.mode, '0');
FILL(header->header.uid, '0');
FILL(header->header.gid, '0');
FILL(header->header.devmajor, 0);
FILL(header->header.devminor, 0);
uid_to_uname (0, &tmpname);
UNAME_TO_CHARS (tmpname, header->header.uname);
free (tmpname);
gid_to_gname (0, &tmpname);
GNAME_TO_CHARS (tmpname, header->header.gname);
free (tmpname);
strcpy (header->header.magic, OLDGNU_MAGIC);
header->header.typeflag = type;
finish_header (st, header, -1);
@@ -459,18 +478,18 @@ write_ustar_long_name (const char *name)
if (length > PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)
{
WARN ((0, 0, _("%s: file name is too long (max %d); not dumped"),
quotearg_colon (name),
PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1));
ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"),
quotearg_colon (name),
PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1));
return NULL;
}
i = split_long_name (name, length);
if (i == 0 || length - i - 1 > NAME_FIELD_SIZE)
{
WARN ((0, 0,
_("%s: file name is too long (cannot be split); not dumped"),
quotearg_colon (name)));
ERROR ((0, 0,
_("%s: file name is too long (cannot be split); not dumped"),
quotearg_colon (name)));
return NULL;
}
@@ -478,7 +497,7 @@ write_ustar_long_name (const char *name)
memset (header->buffer, 0, sizeof (header->buffer));
memcpy (header->header.prefix, name, i);
memcpy (header->header.name, name + i + 1, length - i - 1);
return header;
}
@@ -495,11 +514,11 @@ write_long_link (struct tar_stat_info *st)
case V7_FORMAT: /* old V7 tar format */
case USTAR_FORMAT:
case STAR_FORMAT:
WARN ((0, 0,
_("%s: link name is too long; not dumped"),
quotearg_colon (st->link_name)));
break;
ERROR ((0, 0,
_("%s: link name is too long; not dumped"),
quotearg_colon (st->link_name)));
break;
case OLDGNU_FORMAT:
case GNU_FORMAT:
write_gnu_long_link (st, st->link_name, GNUTYPE_LONGLINK);
@@ -519,11 +538,20 @@ write_long_name (struct tar_stat_info *st)
xheader_store ("path", st, NULL);
break;
case V7_FORMAT:
case V7_FORMAT:
if (strlen (st->file_name) > NAME_FIELD_SIZE-1)
{
ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"),
quotearg_colon (st->file_name),
NAME_FIELD_SIZE - 1));
return NULL;
}
break;
case USTAR_FORMAT:
case STAR_FORMAT:
return write_ustar_long_name (st->file_name);
case OLDGNU_FORMAT:
case GNU_FORMAT:
write_gnu_long_link (st, st->file_name, GNUTYPE_LONGNAME);
@@ -534,17 +562,16 @@ write_long_name (struct tar_stat_info *st)
}
return write_short_name (st);
}
static union block *
write_extended (struct tar_stat_info *st, union block *old_header)
{
union block *header, hp;
size_t size;
char *p;
if (extended_header.buffer || extended_header.stk == NULL)
return old_header;
return old_header;
xheader_finish (&extended_header);
memcpy (hp.buffer, old_header, sizeof (hp));
p = xheader_xhdr_name (st);
@@ -555,7 +582,7 @@ write_extended (struct tar_stat_info *st, union block *old_header)
return header;
}
static union block *
static union block *
write_header_name (struct tar_stat_info *st)
{
if (archive_format == POSIX_FORMAT && !string_ascii_p (st->file_name))
@@ -626,7 +653,7 @@ start_header (struct tar_stat_info *st)
xheader_store ("uid", st, NULL);
else
UID_TO_CHARS (st->stat.st_uid, header->header.uid);
if (st->stat.st_gid > MAXOCTAL7 && archive_format == POSIX_FORMAT)
xheader_store ("gid", st, NULL);
else
@@ -656,19 +683,19 @@ start_header (struct tar_stat_info *st)
else
MAJOR_TO_CHARS (st->devminor, header->header.devminor);
}
else
else if (archive_format != GNU_FORMAT && archive_format != OLDGNU_FORMAT)
{
MAJOR_TO_CHARS (0, header->header.devmajor);
MINOR_TO_CHARS (0, header->header.devminor);
}
if (archive_format == POSIX_FORMAT)
{
xheader_store ("atime", st, NULL);
xheader_store ("ctime", st, NULL);
}
else if (incremental_option)
if (archive_format == OLDGNU_FORMAT)
if (archive_format == OLDGNU_FORMAT || archive_format == GNU_FORMAT)
{
TIME_TO_CHARS (st->stat.st_atime, header->oldgnu_header.atime);
TIME_TO_CHARS (st->stat.st_ctime, header->oldgnu_header.ctime);
@@ -705,7 +732,7 @@ start_header (struct tar_stat_info *st)
{
uid_to_uname (st->stat.st_uid, &st->uname);
gid_to_gname (st->stat.st_gid, &st->gname);
if (archive_format == POSIX_FORMAT
&& (strlen (st->uname) > UNAME_FIELD_SIZE
|| !string_ascii_p (st->uname)))
@@ -762,10 +789,6 @@ void
finish_header (struct tar_stat_info *st,
union block *header, off_t block_ordinal)
{
size_t i;
int sum;
char *p;
/* Note: It is important to do this before the call to write_extended(),
so that the actual ustar header is printed */
if (verbose_option
@@ -798,40 +821,40 @@ pad_archive (off_t size_left)
set_next_block_after (blk);
size_left -= BLOCKSIZE;
}
}
}
static enum dump_status
dump_regular_file (int fd, struct tar_stat_info *stat)
dump_regular_file (int fd, struct tar_stat_info *st)
{
off_t size_left = stat->stat.st_size;
off_t size_left = st->stat.st_size;
off_t block_ordinal;
union block *blk;
block_ordinal = current_block_ordinal ();
blk = start_header (stat);
blk = start_header (st);
if (!blk)
return dump_status_fail;
/* Mark contiguous files, if we support them. */
if (archive_format != V7_FORMAT && S_ISCTG (stat->stat.st_mode))
if (archive_format != V7_FORMAT && S_ISCTG (st->stat.st_mode))
blk->header.typeflag = CONTTYPE;
finish_header (stat, blk, block_ordinal);
finish_header (st, blk, block_ordinal);
while (size_left > 0)
{
size_t bufsize, count;
if (multi_volume_option)
{
assign_string (&save_name, stat->file_name);
assign_string (&save_name, st->file_name);
save_sizeleft = size_left;
save_totsize = stat->stat.st_size;
save_totsize = st->stat.st_size;
}
blk = find_next_block ();
bufsize = available_space_after (blk);
if (size_left < bufsize)
{
/* Last read -- zero out area beyond. */
@@ -840,12 +863,12 @@ dump_regular_file (int fd, struct tar_stat_info *stat)
if (count)
memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
}
count = (fd < 0) ? bufsize : safe_read (fd, blk->buffer, bufsize);
if (count < 0)
if (count == SAFE_READ_ERROR)
{
read_diag_details (stat->orig_file_name,
stat->stat.st_size - size_left, bufsize);
read_diag_details (st->orig_file_name,
st->stat.st_size - size_left, bufsize);
pad_archive (size_left);
return dump_status_short;
}
@@ -861,7 +884,7 @@ dump_regular_file (int fd, struct tar_stat_info *stat)
ngettext ("%s: File shrank by %s byte; padding with zeros",
"%s: File shrank by %s bytes; padding with zeros",
size_left),
quotearg_colon (stat->orig_file_name),
quotearg_colon (st->orig_file_name),
STRINGIFY_BIGINT (size_left, buf)));
if (! ignore_failed_read_option)
exit_status = TAREXIT_FAILURE;
@@ -872,7 +895,7 @@ dump_regular_file (int fd, struct tar_stat_info *stat)
return dump_status_ok;
}
void
static void
dump_regular_finish (int fd, struct tar_stat_info *st, time_t original_ctime)
{
if (fd >= 0)
@@ -899,22 +922,63 @@ dump_regular_finish (int fd, struct tar_stat_info *st, time_t original_ctime)
}
}
void
dump_dir0 (char *directory,
struct tar_stat_info *stat, int top_level, dev_t parent_device)
/* 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)
{
dev_t our_device = stat->stat.st_dev;
if (!is_avoided_name (stat->orig_file_name))
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;
if (!is_avoided_name (st->orig_file_name))
{
union block *blk = NULL;
off_t block_ordinal = current_block_ordinal ();
stat->stat.st_size = 0; /* force 0 size on dir */
st->stat.st_size = 0; /* force 0 size on dir */
blk = start_header (stat);
blk = start_header (st);
if (!blk)
return;
if (incremental_option)
blk->header.typeflag = GNUTYPE_DUMPDIR;
else /* if (standard_option) */
@@ -923,7 +987,7 @@ dump_dir0 (char *directory,
/* If we're gnudumping, we aren't done yet so don't close it. */
if (!incremental_option)
finish_header (stat, blk, block_ordinal);
finish_header (st, blk, block_ordinal);
else if (gnu_list_name->dir_contents)
{
off_t size_left;
@@ -931,8 +995,8 @@ dump_dir0 (char *directory,
size_t bufsize;
ssize_t count;
const char *buffer, *p_buffer;
off_t block_ordinal = current_block_ordinal ();
block_ordinal = current_block_ordinal ();
buffer = gnu_list_name->dir_contents; /* FOO */
totsize = 0;
if (buffer)
@@ -944,14 +1008,14 @@ dump_dir0 (char *directory,
}
totsize++;
OFF_TO_CHARS (totsize, blk->header.size);
finish_header (stat, blk, block_ordinal);
finish_header (st, blk, block_ordinal);
p_buffer = buffer;
size_left = totsize;
while (size_left > 0)
{
if (multi_volume_option)
{
assign_string (&save_name, stat->orig_file_name);
assign_string (&save_name, st->orig_file_name);
save_sizeleft = size_left;
save_totsize = totsize;
}
@@ -980,25 +1044,35 @@ dump_dir0 (char *directory,
if (one_file_system_option
&& !top_level
&& parent_device != stat->stat.st_dev)
&& parent_device != st->stat.st_dev)
{
if (verbose_option)
WARN ((0, 0,
_("%s: file is on a different filesystem; not dumped"),
quotearg_colon (stat->orig_file_name)));
quotearg_colon (st->orig_file_name)));
return;
}
if (exclude_caches_option
&& check_cache_directory(st->orig_file_name))
{
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 = strdup (stat->orig_file_name);
char *name_buf = strdup (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)
{
@@ -1011,7 +1085,7 @@ dump_dir0 (char *directory,
if (!excluded_name (name_buf))
dump_file (name_buf, 0, our_device);
}
free (name_buf);
}
}
@@ -1029,22 +1103,22 @@ ensure_slash (char **pstr)
(*pstr)[len] = '\0';
}
bool
dump_dir (struct tar_stat_info *stat, int top_level, dev_t parent_device)
static bool
dump_dir (struct tar_stat_info *st, int top_level, dev_t parent_device)
{
char *directory;
directory = savedir (stat->orig_file_name);
directory = savedir (st->orig_file_name);
if (!directory)
{
savedir_diag (stat->orig_file_name);
savedir_diag (st->orig_file_name);
return false;
}
ensure_slash (&stat->orig_file_name);
ensure_slash (&stat->file_name);
ensure_slash (&st->orig_file_name);
ensure_slash (&st->file_name);
dump_dir0 (directory, stat, top_level, parent_device);
dump_dir0 (directory, st, top_level, parent_device);
free (directory);
return true;
@@ -1060,7 +1134,7 @@ create_archive (void)
open_archive (ACCESS_WRITE);
xheader_write_global ();
if (incremental_option)
{
size_t buffer_size = 1000;
@@ -1127,8 +1201,9 @@ create_archive (void)
static unsigned
hash_link (void const *entry, unsigned n_buckets)
{
struct link const *link = entry;
return (uintmax_t) (link->dev ^ link->ino) % n_buckets;
struct link const *l = entry;
uintmax_t num = l->dev ^ l->ino;
return num % n_buckets;
}
/* Compare two links for equality. */
@@ -1160,41 +1235,41 @@ static Hash_table *link_table;
/* Try to dump stat as a hard link to another file in the archive. If
succeeded returns true */
static bool
dump_hard_link (struct tar_stat_info *stat)
dump_hard_link (struct tar_stat_info *st)
{
if (link_table && stat->stat.st_nlink > 1)
if (link_table && st->stat.st_nlink > 1)
{
struct link lp;
struct link *dup;
struct link *duplicate;
off_t block_ordinal;
union block *blk;
lp.ino = stat->stat.st_ino;
lp.dev = stat->stat.st_dev;
if ((dup = hash_lookup (link_table, &lp)))
lp.ino = st->stat.st_ino;
lp.dev = st->stat.st_dev;
if ((duplicate = hash_lookup (link_table, &lp)))
{
/* We found a link. */
char const *link_name = safer_name_suffix (dup->name, true);
char const *link_name = safer_name_suffix (duplicate->name, true);
duplicate->nlink--;
dup->nlink--;
block_ordinal = current_block_ordinal ();
assign_string (&stat->link_name, link_name);
assign_string (&st->link_name, link_name);
if (NAME_FIELD_SIZE < strlen (link_name))
write_long_link (stat);
stat->stat.st_size = 0;
blk = start_header (stat);
write_long_link (st);
st->stat.st_size = 0;
blk = start_header (st);
if (!blk)
return true;
tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
blk->header.typeflag = LNKTYPE;
finish_header (stat, blk, block_ordinal);
finish_header (st, blk, block_ordinal);
if (remove_files_option && unlink (stat->orig_file_name) != 0)
unlink_error (stat->orig_file_name);
if (remove_files_option && unlink (st->orig_file_name) != 0)
unlink_error (st->orig_file_name);
return true;
}
@@ -1203,25 +1278,25 @@ dump_hard_link (struct tar_stat_info *stat)
}
static void
file_count_links (struct tar_stat_info *stat)
file_count_links (struct tar_stat_info *st)
{
if (stat->stat.st_nlink > 1)
if (st->stat.st_nlink > 1)
{
struct link *dup;
struct link *duplicate;
struct link *lp = xmalloc (offsetof (struct link, name)
+ strlen (stat->orig_file_name) + 1);
lp->ino = stat->stat.st_ino;
lp->dev = stat->stat.st_dev;
lp->nlink = stat->stat.st_nlink;
strcpy (lp->name, stat->orig_file_name);
+ strlen (st->orig_file_name) + 1);
lp->ino = st->stat.st_ino;
lp->dev = st->stat.st_dev;
lp->nlink = st->stat.st_nlink;
strcpy (lp->name, st->orig_file_name);
if (! ((link_table
|| (link_table = hash_initialize (0, 0, hash_link,
compare_links, 0)))
&& (dup = hash_insert (link_table, lp))))
&& (duplicate = hash_insert (link_table, lp))))
xalloc_die ();
if (dup != lp)
if (duplicate != lp)
abort ();
lp->nlink--;
}
@@ -1230,7 +1305,7 @@ file_count_links (struct tar_stat_info *stat)
/* For each dumped file, check if all its links were dumped. Emit
warnings if it is not so. */
void
check_links ()
check_links (void)
{
struct link *lp;
@@ -1257,8 +1332,8 @@ check_links ()
/* FIXME: One should make sure that for *every* path leading to setting
exit_status to failure, a clear diagnostic has been issued. */
void
dump_file0 (struct tar_stat_info *stat, char *p,
static void
dump_file0 (struct tar_stat_info *st, char *p,
int top_level, dev_t parent_device)
{
union block *header;
@@ -1266,26 +1341,26 @@ dump_file0 (struct tar_stat_info *stat, char *p,
time_t original_ctime;
struct utimbuf restore_times;
off_t block_ordinal = -1;
if (interactive_option && !confirm ("add", p))
return;
assign_string (&stat->orig_file_name, p);
assign_string (&stat->file_name, safer_name_suffix (p, false));
assign_string (&st->orig_file_name, p);
assign_string (&st->file_name, safer_name_suffix (p, false));
if (deref_stat (dereference_option, p, &stat->stat) != 0)
if (deref_stat (dereference_option, p, &st->stat) != 0)
{
stat_diag (p);
return;
}
stat->archive_file_size = stat->stat.st_size;
sys_stat_nanoseconds(stat);
original_ctime = stat->stat.st_ctime;
restore_times.actime = stat->stat.st_atime;
restore_times.modtime = stat->stat.st_mtime;
st->archive_file_size = st->stat.st_size;
sys_stat_nanoseconds (st);
original_ctime = st->stat.st_ctime;
restore_times.actime = st->stat.st_atime;
restore_times.modtime = st->stat.st_mtime;
#ifdef S_ISHIDDEN
if (S_ISHIDDEN (stat->stat.st_mode))
if (S_ISHIDDEN (st->stat.st_mode))
{
char *new = (char *) alloca (strlen (p) + 2);
if (new)
@@ -1298,30 +1373,33 @@ dump_file0 (struct tar_stat_info *stat, char *p,
#endif
/* See if we want only new files, and check if this one is too old to
put in the archive. */
put in the archive.
if (!S_ISDIR (stat->stat.st_mode)
&& stat->stat.st_mtime < newer_mtime_option
&& (!after_date_option || stat->stat.st_ctime < newer_ctime_option))
This check is omitted if incremental_option is set *and* the
requested file is not explicitely listed in the command line. */
if (!(incremental_option && !is_individual_file (p))
&& !S_ISDIR (st->stat.st_mode)
&& OLDER_STAT_TIME (st->stat, m)
&& (!after_date_option || OLDER_STAT_TIME (st->stat, c)))
{
if (0 < top_level) /* equivalent to !incremental_option */
if (!incremental_option)
WARN ((0, 0, _("%s: file is unchanged; not dumped"),
quotearg_colon (p)));
/* FIXME: recheck this return. */
return;
}
/* See if we are trying to dump the archive. */
if (sys_file_is_archive (stat))
if (sys_file_is_archive (st))
{
WARN ((0, 0, _("%s: file is the archive; not dumped"),
quotearg_colon (p)));
return;
}
if (S_ISDIR (stat->stat.st_mode))
if (S_ISDIR (st->stat.st_mode))
{
dump_dir (stat, top_level, parent_device);
dump_dir (st, top_level, parent_device);
if (atime_preserve_option)
utime (p, &restore_times);
return;
@@ -1331,49 +1409,49 @@ dump_file0 (struct tar_stat_info *stat, char *p,
else
{
/* Check for multiple links. */
if (dump_hard_link (stat))
if (dump_hard_link (st))
return;
/* This is not a link to a previously dumped file, so dump it. */
if (S_ISREG (stat->stat.st_mode)
|| S_ISCTG (stat->stat.st_mode))
if (S_ISREG (st->stat.st_mode)
|| S_ISCTG (st->stat.st_mode))
{
int fd;
enum dump_status status;
if (file_dumpable_p (stat))
if (file_dumpable_p (st))
{
fd = open (stat->orig_file_name,
fd = open (st->orig_file_name,
O_RDONLY | O_BINARY);
if (fd < 0)
{
if (!top_level && errno == ENOENT)
WARN ((0, 0, _("%s: File removed before we read it"),
quotearg_colon (stat->orig_file_name)));
quotearg_colon (st->orig_file_name)));
else
open_diag (stat->orig_file_name);
open_diag (st->orig_file_name);
return;
}
}
else
fd = -1;
if (sparse_option && sparse_file_p (stat))
if (sparse_option && sparse_file_p (st))
{
status = sparse_dump_file (fd, stat);
status = sparse_dump_file (fd, st);
if (status == dump_status_not_implemented)
status = dump_regular_file (fd, stat);
status = dump_regular_file (fd, st);
}
else
status = dump_regular_file (fd, stat);
status = dump_regular_file (fd, st);
switch (status)
{
case dump_status_ok:
if (multi_volume_option)
assign_string (&save_name, 0);
dump_regular_finish (fd, stat, original_ctime);
dump_regular_finish (fd, st, original_ctime);
break;
case dump_status_short:
@@ -1381,7 +1459,7 @@ dump_file0 (struct tar_stat_info *stat, char *p,
assign_string (&save_name, 0);
close (fd);
break;
case dump_status_fail:
close (fd);
return;
@@ -1391,17 +1469,17 @@ dump_file0 (struct tar_stat_info *stat, char *p,
}
if (atime_preserve_option)
utime (stat->orig_file_name, &restore_times);
file_count_links (stat);
utime (st->orig_file_name, &restore_times);
file_count_links (st);
return;
}
#ifdef HAVE_READLINK
else if (S_ISLNK (stat->stat.st_mode))
else if (S_ISLNK (st->stat.st_mode))
{
char *buffer;
int size;
size_t linklen = stat->stat.st_size;
if (linklen != stat->stat.st_size || linklen + 1 == 0)
size_t linklen = st->stat.st_size;
if (linklen != st->stat.st_size || linklen + 1 == 0)
xalloc_die ();
buffer = (char *) alloca (linklen + 1);
size = readlink (p, buffer, linklen + 1);
@@ -1411,18 +1489,18 @@ dump_file0 (struct tar_stat_info *stat, char *p,
return;
}
buffer[size] = '\0';
assign_string (&stat->link_name, buffer);
assign_string (&st->link_name, buffer);
if (size > NAME_FIELD_SIZE)
write_long_link (stat);
write_long_link (st);
block_ordinal = current_block_ordinal ();
stat->stat.st_size = 0; /* force 0 size on symlink */
header = start_header (stat);
st->stat.st_size = 0; /* force 0 size on symlink */
header = start_header (st);
if (!header)
return;
tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE);
header->header.typeflag = SYMTYPE;
finish_header (stat, header, block_ordinal);
finish_header (st, header, block_ordinal);
/* nothing more to do to it */
if (remove_files_option)
@@ -1430,22 +1508,22 @@ dump_file0 (struct tar_stat_info *stat, char *p,
if (unlink (p) == -1)
unlink_error (p);
}
file_count_links (stat);
file_count_links (st);
return;
}
#endif
else if (S_ISCHR (stat->stat.st_mode))
else if (S_ISCHR (st->stat.st_mode))
type = CHRTYPE;
else if (S_ISBLK (stat->stat.st_mode))
else if (S_ISBLK (st->stat.st_mode))
type = BLKTYPE;
else if (S_ISFIFO (stat->stat.st_mode))
else if (S_ISFIFO (st->stat.st_mode))
type = FIFOTYPE;
else if (S_ISSOCK (stat->stat.st_mode))
else if (S_ISSOCK (st->stat.st_mode))
{
WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
return;
}
else if (S_ISDOOR (stat->stat.st_mode))
else if (S_ISDOOR (st->stat.st_mode))
{
WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
return;
@@ -1464,21 +1542,21 @@ dump_file0 (struct tar_stat_info *stat, char *p,
}
block_ordinal = current_block_ordinal ();
stat->stat.st_size = 0; /* force 0 size */
header = start_header (stat);
st->stat.st_size = 0; /* force 0 size */
header = start_header (st);
if (!header)
return;
header->header.typeflag = type;
if (type != FIFOTYPE)
{
MAJOR_TO_CHARS (major (stat->stat.st_rdev),
MAJOR_TO_CHARS (major (st->stat.st_rdev),
header->header.devmajor);
MINOR_TO_CHARS (minor (stat->stat.st_rdev),
MINOR_TO_CHARS (minor (st->stat.st_rdev),
header->header.devminor);
}
finish_header (stat, header, block_ordinal);
finish_header (st, header, block_ordinal);
if (remove_files_option)
{
if (unlink (p) == -1)
@@ -1489,8 +1567,8 @@ dump_file0 (struct tar_stat_info *stat, char *p,
void
dump_file (char *p, int top_level, dev_t parent_device)
{
struct tar_stat_info stat;
tar_stat_init (&stat);
dump_file0 (&stat, p, top_level, parent_device);
tar_stat_destroy (&stat);
struct tar_stat_info st;
tar_stat_init (&st);
dump_file0 (&st, p, top_level, parent_device);
tar_stat_destroy (&st);
}

View File

@@ -17,10 +17,10 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include "common.h"
#include "rmt.h"
#include <rmt.h>
static union block *new_record;
static int new_blocks;
@@ -359,33 +359,32 @@ delete_archive_members (void)
write_record (1);
}
}
}
if (logical_status == HEADER_END_OF_FILE)
{
/* Write the end of tape. FIXME: we can't use write_eot here,
as it gets confused when the input is at end of file. */
int total_zero_blocks = 0;
do
if (logical_status == HEADER_END_OF_FILE)
{
int zero_blocks = blocking_factor - new_blocks;
memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
total_zero_blocks += zero_blocks;
write_record (total_zero_blocks < 2);
/* Write the end of tape. FIXME: we can't use write_eot here,
as it gets confused when the input is at end of file. */
int total_zero_blocks = 0;
do
{
int zero_blocks = blocking_factor - new_blocks;
memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
total_zero_blocks += zero_blocks;
write_record (total_zero_blocks < 2);
}
while (total_zero_blocks < 2);
}
while (total_zero_blocks < 2);
}
if (! acting_as_filter && ! _isrmt (archive))
{
if (sys_truncate (archive))
truncate_warn (archive_name_array[0]);
}
}
free (new_record);
if (! acting_as_filter && ! _isrmt (archive))
{
if (sys_truncate (archive))
truncate_warn (archive_name_array[0]);
}
close_archive ();
names_notfound ();
}

View File

@@ -1,7 +1,7 @@
/* Extract files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
2001, 2003 Free Software Foundation, Inc.
2001, 2003, 2004 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-11-19.
@@ -19,9 +19,10 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include <quotearg.h>
#include <errno.h>
#include <xgetcwd.h>
#if HAVE_UTIME_H
# include <utime.h>
@@ -113,8 +114,20 @@ extr_init (void)
we_are_root = geteuid () == 0;
same_permissions_option += we_are_root;
same_owner_option += we_are_root;
xalloc_fail_func = extract_finish;
/* Save 'root device' to avoid purging mount points.
FIXME: Should the same be done after handling -C option ? */
if (one_file_system_option)
{
struct stat st;
char *dir = xgetcwd ();
if (deref_stat (true, dir, &st))
stat_diag (dir);
else
root_device = st.st_dev;
}
/* Option -p clears the kernel umask, so it does not affect proper
restoration of file permissions. New intermediate directories will
comply with umask at start of program. */
@@ -315,11 +328,11 @@ delay_set_stat (char const *file_name, struct stat const *stat_info,
}
/* Update the delayed_set_stat info for an intermediate directory
created on the path to DIR_NAME. The intermediate directory turned
created within the file name of DIR. The intermediate directory turned
out to be the same as this directory, e.g. due to ".." or symbolic
links. *DIR_STAT_INFO is the status of the directory. */
static void
repair_delayed_set_stat (char const *dir_name,
repair_delayed_set_stat (char const *dir,
struct stat const *dir_stat_info)
{
struct delayed_set_stat *data;
@@ -344,7 +357,7 @@ repair_delayed_set_stat (char const *dir_name,
}
ERROR ((0, 0, _("%s: Unexpected inconsistency when making directory"),
quotearg_colon (dir_name)));
quotearg_colon (dir)));
}
/* After a file/link/symlink/directory creation has failed, see if
@@ -354,14 +367,14 @@ repair_delayed_set_stat (char const *dir_name,
static int
make_directories (char *file_name)
{
char *cursor0 = file_name + FILESYSTEM_PREFIX_LEN (file_name);
char *cursor; /* points into path */
char *cursor0 = file_name + FILE_SYSTEM_PREFIX_LEN (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))
@@ -372,7 +385,7 @@ make_directories (char *file_name)
if (cursor == cursor0 || ISSLASH (cursor[-1]))
continue;
/* Avoid mkdir where last part of path is "." or "..". */
/* Avoid mkdir where last part of file name is "." or "..". */
if (cursor[-1] == '.'
&& (cursor == cursor0 + 1 || ISSLASH (cursor[-2])
@@ -380,7 +393,7 @@ make_directories (char *file_name)
&& (cursor == cursor0 + 2 || ISSLASH (cursor[-3])))))
continue;
*cursor = '\0'; /* truncate the path there */
*cursor = '\0'; /* truncate the name there */
mode = MODE_RWX & ~ newdir_umask;
invert_permissions = we_are_root ? 0 : MODE_WXUSR & ~ mode;
status = mkdir (file_name, mode ^ invert_permissions);
@@ -419,21 +432,56 @@ make_directories (char *file_name)
return did_something; /* tell them to retry if we made one */
}
static bool
file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
{
struct stat st;
if (stat (file_name, &st))
{
stat_warn (file_name);
return true; /* Be on the safe side */
}
if (!S_ISDIR (st.st_mode)
&& st.st_mtime >= tar_stat->stat.st_mtime)
{
return true;
}
return false;
}
/* Prepare to extract a file.
Return zero if extraction should not proceed. */
static int
prepare_to_extract (char const *file_name, bool directory)
prepare_to_extract (char const *file_name)
{
if (to_stdout_option)
return 0;
if (old_files_option == UNLINK_FIRST_OLD_FILES
&& !remove_any_file (file_name, recursive_unlink_option)
&& errno && errno != ENOENT)
switch (old_files_option)
{
unlink_error (file_name);
return 0;
case UNLINK_FIRST_OLD_FILES:
if (!remove_any_file (file_name,
recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
: ORDINARY_REMOVE_OPTION)
&& errno && errno != ENOENT)
{
unlink_error (file_name);
return 0;
}
break;
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, &current_stat_info))
{
WARN ((0, 0, _("Current `%s' is newer"), file_name));
return 0;
}
break;
default:
break;
}
return 1;
@@ -446,6 +494,8 @@ prepare_to_extract (char const *file_name, bool directory)
static int
maybe_recoverable (char *file_name, int *interdir_made)
{
int e = errno;
if (*interdir_made)
return 0;
@@ -456,17 +506,28 @@ maybe_recoverable (char *file_name, int *interdir_made)
switch (old_files_option)
{
default:
case KEEP_OLD_FILES:
return 0;
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, &current_stat_info))
{
errno = e;
return 0;
}
/* FALL THROUGH */
case DEFAULT_OLD_FILES:
case NO_OVERWRITE_DIR_OLD_FILES:
case OVERWRITE_OLD_FILES:
{
int r = remove_any_file (file_name, 0);
int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION);
errno = EEXIST;
return r;
}
case UNLINK_FIRST_OLD_FILES:
break;
}
case ENOENT:
@@ -553,7 +614,6 @@ extract_archive (void)
int openflag;
mode_t mode;
off_t size;
off_t file_size;
int interdir_made = 0;
char typeflag;
char *file_name;
@@ -573,9 +633,9 @@ extract_archive (void)
print_header (&current_stat_info, -1);
file_name = safer_name_suffix (current_stat_info.file_name, false);
if (strip_path_elements)
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name, strip_path_elements);
size_t prefix_len = stripped_prefix_len (file_name, strip_name_components);
if (prefix_len == (size_t) -1)
{
skip_member ();
@@ -583,7 +643,7 @@ extract_archive (void)
}
file_name += prefix_len;
}
apply_nonancestor_delayed_set_stat (file_name, 0);
/* Take a safety backup of a previously existing file. */
@@ -600,12 +660,10 @@ extract_archive (void)
/* Extract the archive entry according to its type. */
typeflag = current_header->header.typeflag;
/*KLUDGE */
if (current_format == POSIX_FORMAT
&& current_stat_info.archive_file_size != current_stat_info.stat.st_size)
typeflag = GNUTYPE_SPARSE;
/* KLUDGE */
typeflag = sparse_member_p (&current_stat_info) ?
GNUTYPE_SPARSE : current_header->header.typeflag;
switch (typeflag)
{
case GNUTYPE_SPARSE:
@@ -636,7 +694,7 @@ extract_archive (void)
goto extract_file;
}
if (! prepare_to_extract (file_name, 0))
if (! prepare_to_extract (file_name))
{
skip_member ();
if (backup_option)
@@ -681,7 +739,7 @@ extract_archive (void)
}
extract_file:
if (typeflag == GNUTYPE_SPARSE)
if (current_stat_info.is_sparse)
{
sparse_extract_file (fd, &current_stat_info, &size);
}
@@ -751,12 +809,11 @@ extract_archive (void)
case SYMTYPE:
#ifdef HAVE_SYMLINK
if (! prepare_to_extract (file_name, 0))
if (! prepare_to_extract (file_name))
break;
if (absolute_names_option
|| ! (ISSLASH (current_stat_info.link_name
[FILESYSTEM_PREFIX_LEN (current_stat_info.link_name)])
|| ! (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
|| contains_dot_dot (current_stat_info.link_name)))
{
while (status = symlink (current_stat_info.link_name, file_name),
@@ -835,7 +892,7 @@ extract_archive (void)
status = 0;
}
}
if (status != 0 && backup_option)
undo_last_backup ();
break;
@@ -856,7 +913,7 @@ extract_archive (void)
#endif
case LNKTYPE:
if (! prepare_to_extract (file_name, 0))
if (! prepare_to_extract (file_name))
break;
again_link:
@@ -869,17 +926,18 @@ extract_archive (void)
/* MSDOS does not implement links. However, djgpp's link() actually
copies the file. */
status = link (link_name, file_name);
e = errno;
if (status == 0)
{
struct delayed_symlink *ds = delayed_symlink_head;
if (ds && stat (link_name, &st1) == 0)
if (ds && lstat (link_name, &st1) == 0)
for (; ds; ds = ds->next)
if (ds->dev == st1.st_dev
&& ds->ino == st1.st_ino
&& ds->mtime == st1.st_mtime)
{
struct string_list *p =
struct string_list *p =
xmalloc (offsetof (struct string_list, string)
+ strlen (file_name) + 1);
strcpy (p->string, file_name);
@@ -889,17 +947,20 @@ extract_archive (void)
}
break;
}
if ((e == EEXIST && strcmp (link_name, file_name) == 0)
|| (lstat (link_name, &st1) == 0
&& lstat (file_name, &st2) == 0
&& st1.st_dev == st2.st_dev
&& st1.st_ino == st2.st_ino))
break;
errno = e;
if (maybe_recoverable (file_name, &interdir_made))
goto again_link;
if (incremental_option && errno == EEXIST)
break;
e = errno;
if (stat (link_name, &st1) == 0
&& stat (file_name, &st2) == 0
&& st1.st_dev == st2.st_dev
&& st1.st_ino == st2.st_ino)
break;
link_error (link_name, file_name);
if (backup_option)
@@ -920,7 +981,7 @@ extract_archive (void)
#if S_IFCHR || S_IFBLK
make_node:
if (! prepare_to_extract (file_name, 0))
if (! prepare_to_extract (file_name))
break;
status = mknod (file_name, current_stat_info.stat.st_mode,
@@ -941,7 +1002,7 @@ extract_archive (void)
#if HAVE_MKFIFO || defined mkfifo
case FIFOTYPE:
if (! prepare_to_extract (file_name, 0))
if (! prepare_to_extract (file_name))
break;
while (status = mkfifo (file_name, current_stat_info.stat.st_mode),
@@ -969,7 +1030,7 @@ extract_archive (void)
/* Read the entry and delete files that aren't listed in the
archive. */
gnu_restore (file_name);
purge_directory (file_name);
}
else if (typeflag == GNUTYPE_DUMPDIR)
skip_member ();
@@ -978,7 +1039,7 @@ extract_archive (void)
| (we_are_root ? 0 : MODE_WXUSR))
& MODE_RWX);
status = prepare_to_extract (file_name, 1);
status = prepare_to_extract (file_name);
if (status == 0)
break;
if (status < 0)
@@ -1010,7 +1071,7 @@ extract_archive (void)
}
errno = EEXIST;
}
if (maybe_recoverable (file_name, &interdir_made))
goto again_dir;
@@ -1150,3 +1211,10 @@ fatal_exit (void)
error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
abort ();
}
void
xalloc_die (void)
{
error (0, 0, "%s", _("memory exhausted"));
fatal_exit ();
}

View File

@@ -17,7 +17,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include <getline.h>
#include <hash.h>
#include <quotearg.h>
@@ -39,7 +39,7 @@ struct directory
enum children children;
bool nfs;
bool found;
char name[1]; /* path name of directory */
char name[1]; /* file name of directory */
};
static Hash_table *directory_table;
@@ -95,7 +95,7 @@ note_directory (char const *name, dev_t dev, ino_t ino, bool nfs, bool found)
return directory;
}
/* Return a directory entry for a given path NAME, or zero if none found. */
/* Return a directory entry for a given file NAME, or zero if none found. */
static struct directory *
find_directory (char *name)
{
@@ -117,11 +117,11 @@ compare_dirents (const void *first, const void *second)
(*(char *const *) second) + 1);
}
/* Recursively scan the given PATH. */
/* Recursively scan the given directory. */
static void
scan_path (struct obstack *stk, char *path, dev_t device)
scan_directory (struct obstack *stk, char *dir_name, dev_t device)
{
char *dirp = savedir (path); /* for scanning directory */
char *dirp = savedir (dir_name); /* for scanning directory */
char const *entry; /* directory entry being scanned */
size_t entrylen; /* length of directory entry */
char *name_buffer; /* directory, `/', and directory member */
@@ -132,20 +132,20 @@ scan_path (struct obstack *stk, char *path, dev_t device)
if (! dirp)
{
savedir_error (path);
savedir_error (dir_name);
}
errno = 0;
name_buffer_size = strlen (path) + NAME_FIELD_SIZE;
name_buffer_size = strlen (dir_name) + NAME_FIELD_SIZE;
name_buffer = xmalloc (name_buffer_size + 2);
strcpy (name_buffer, path);
if (! ISSLASH (path[strlen (path) - 1]))
strcpy (name_buffer, dir_name);
if (! ISSLASH (dir_name[strlen (dir_name) - 1]))
strcat (name_buffer, "/");
name_length = strlen (name_buffer);
directory = find_directory (path);
directory = find_directory (dir_name);
children = directory ? directory->children : CHANGED_CHILDREN;
if (dirp && children != NO_CHILDREN)
for (entry = dirp;
(entrylen = strlen (entry)) != 0;
@@ -159,23 +159,23 @@ scan_path (struct obstack *stk, char *path, dev_t device)
name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
}
strcpy (name_buffer + name_length, entry);
if (excluded_name (name_buffer))
obstack_1grow (stk, 'N');
else
{
struct stat stat_data;
if (deref_stat (dereference_option, name_buffer, &stat_data))
{
stat_diag (name_buffer);
continue;
}
if (S_ISDIR (stat_data.st_mode))
{
bool nfs = NFS_FILE_STAT (stat_data);
if ((directory = find_directory (name_buffer)) != NULL)
{
/* With NFS, the same file can have two different devices
@@ -184,7 +184,7 @@ scan_path (struct obstack *stk, char *path, dev_t device)
To avoid spurious incremental redumping of
directories, consider all NFS devices as equal,
relying on the i-node to establish differences. */
if (! (((directory->nfs & nfs)
|| directory->device_number == stat_data.st_dev)
&& directory->inode_number == stat_data.st_ino))
@@ -209,13 +209,13 @@ scan_path (struct obstack *stk, char *path, dev_t device)
stat_data.st_ino, nfs, 1);
directory->children =
((listed_incremental_option
|| newer_mtime_option <= stat_data.st_mtime
|| (after_date_option &&
newer_ctime_option <= stat_data.st_ctime))
|| OLDER_STAT_TIME (stat_data, m)
|| (after_date_option
&& OLDER_STAT_TIME (stat_data, c)))
? ALL_CHILDREN
: CHANGED_CHILDREN);
}
if (one_file_system_option && device != stat_data.st_dev)
directory->children = NO_CHILDREN;
else if (children == ALL_CHILDREN)
@@ -239,19 +239,18 @@ scan_path (struct obstack *stk, char *path, dev_t device)
else
if (children == CHANGED_CHILDREN
&& stat_data.st_mtime < newer_mtime_option
&& (!after_date_option
|| stat_data.st_ctime < newer_ctime_option))
&& OLDER_STAT_TIME (stat_data, m)
&& (!after_date_option || OLDER_STAT_TIME (stat_data, c)))
obstack_1grow (stk, 'N');
else
obstack_1grow (stk, 'Y');
}
obstack_grow (stk, entry, entrylen + 1);
}
obstack_grow (stk, "\000\000", 2);
free (name_buffer);
if (dirp)
free (dirp);
@@ -267,16 +266,16 @@ sort_obstack (struct obstack *stk)
char *buffer;
char **array;
char **array_cursor;
counter = 0;
for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
counter++;
if (!counter)
return NULL;
array = obstack_alloc (stk, sizeof (char *) * (counter + 1));
array_cursor = array;
for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
*array_cursor++ = cursor;
@@ -290,7 +289,7 @@ sort_obstack (struct obstack *stk)
for (array_cursor = array; *array_cursor; array_cursor++)
{
char *string = *array_cursor;
while ((*cursor++ = *string++))
continue;
}
@@ -299,13 +298,13 @@ sort_obstack (struct obstack *stk)
}
char *
get_directory_contents (char *path, dev_t device)
get_directory_contents (char *dir_name, dev_t device)
{
struct obstack stk;
char *buffer;
obstack_init (&stk);
scan_path (&stk, path, device);
scan_directory (&stk, dir_name, device);
buffer = sort_obstack (&stk);
obstack_free (&stk, NULL);
return buffer;
@@ -357,7 +356,10 @@ read_directory_file (void)
ERROR ((0, 0, "%s:1: %s", quotearg_colon (listed_incremental_option),
_("Time stamp out of range")));
else
newer_mtime_option = t;
{
newer_mtime_option.tv_sec = t;
newer_mtime_option.tv_nsec = 0;
}
while (0 < (n = getline (&buf, &bufsize, fp)))
{
@@ -458,10 +460,9 @@ write_directory_file (void)
/* Restoration of incremental dumps. */
/* Examine the directories under directory_name and delete any
files that were not there at the time of the back-up.
FIXME: The function name is obviously a misnomer */
files that were not there at the time of the back-up. */
void
gnu_restore (char const *directory_name)
purge_directory (char const *directory_name)
{
char *archive_dir;
char *current_dir;
@@ -514,13 +515,30 @@ gnu_restore (char const *directory_name)
}
if (*arc == '\0')
{
struct stat st;
char *p = new_name (directory_name, cur);
if (deref_stat (true, p, &st))
{
stat_diag (p);
WARN((0, 0, _("%s: Not purging directory: unable to stat"),
quotearg_colon (p)));
continue;
}
else if (one_file_system_option && st.st_dev != root_device)
{
WARN((0, 0,
_("%s: directory is on a different device: not purging"),
quotearg_colon (p)));
continue;
}
if (! interactive_option || confirm ("delete", p))
{
if (verbose_option)
fprintf (stdlis, _("%s: Deleting %s\n"),
program_name, quote (p));
if (! remove_any_file (p, 1))
if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION))
{
int e = errno;
ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));

View File

@@ -1,7 +1,7 @@
/* 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 Free Software Foundation, Inc.
2001, 2003, 2004 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-26.
@@ -22,7 +22,7 @@
/* Define to non-zero for forcing old ctime format instead of ISO format. */
#undef USE_OLD_CTIME
#include "system.h"
#include <system.h>
#include <quotearg.h>
#include "common.h"
@@ -78,7 +78,7 @@ 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)
{
@@ -92,12 +92,17 @@ read_and (void (*do_something) (void))
Ensure incoming names are null terminated. */
if (! name_match (current_stat_info.file_name)
|| (newer_mtime_option != TYPE_MINIMUM (time_t)
|| (NEWER_OPTION_INITIALIZED (newer_mtime_option)
/* FIXME: We get mtime now, and again later; this causes
duplicate diagnostics if header.mtime is bogus. */
&& ((current_stat_info.stat.st_mtime
= TIME_FROM_HEADER (current_header->header.mtime))
< newer_mtime_option))
= TIME_FROM_HEADER (current_header->header.mtime)),
#ifdef ST_MTIM_NSEC
/* FIXME: Grab fractional time stamps from
extended header. */
current_stat_info.stat.st_mtim.ST_MTIM_NSEC = 0,
#endif
OLDER_STAT_TIME (current_stat_info.stat, m)))
|| excluded_name (current_stat_info.file_name))
{
switch (current_header->header.typeflag)
@@ -113,6 +118,8 @@ read_and (void (*do_something) (void))
quotearg_colon (current_stat_info.file_name)));
/* Fall through. */
default:
decode_header (current_header,
&current_stat_info, &current_format, 0);
skip_member ();
continue;
}
@@ -140,6 +147,7 @@ read_and (void (*do_something) (void))
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
break;
}
status = prev_status;
continue;
@@ -165,6 +173,15 @@ read_and (void (*do_something) (void))
case HEADER_ZERO_BLOCK:
case HEADER_SUCCESS:
if (block_number_option)
{
char buf[UINTMAX_STRSIZE_BOUND];
off_t block_ordinal = current_block_ordinal ();
block_ordinal -= recent_long_name_blocks;
block_ordinal -= recent_long_link_blocks;
fprintf (stdlis, _("block %s: "),
STRINGIFY_BIGINT (block_ordinal, buf));
}
ERROR ((0, 0, _("Skipping to next header")));
break;
@@ -249,6 +266,61 @@ list_archive (void)
assign_string (&save_name, 0);
}
/* Check header checksum */
/* The standard BSD tar sources create the checksum by adding up the
bytes in the header as type char. I think the type char was unsigned
on the PDP-11, but it's signed on the Next and Sun. It looks like the
sources to BSD tar were never changed to compute the checksum
correctly, so both the Sun and Next add the bytes of the header as
signed chars. This doesn't cause a problem until you get a file with
a name containing characters with the high bit set. So tar_checksum
computes two checksums -- signed and unsigned. */
enum read_header
tar_checksum (union block *header)
{
size_t i;
int unsigned_sum = 0; /* the POSIX one :-) */
int signed_sum = 0; /* the Sun one :-( */
int recorded_sum;
uintmax_t parsed_sum;
char *p;
p = header->buffer;
for (i = sizeof *header; i-- != 0;)
{
unsigned_sum += (unsigned char) *p;
signed_sum += (signed char) (*p++);
}
if (unsigned_sum == 0)
return HEADER_ZERO_BLOCK;
/* Adjust checksum to count the "chksum" field as blanks. */
for (i = sizeof header->header.chksum; i-- != 0;)
{
unsigned_sum -= (unsigned char) header->header.chksum[i];
signed_sum -= (signed char) (header->header.chksum[i]);
}
unsigned_sum += ' ' * sizeof header->header.chksum;
signed_sum += ' ' * sizeof header->header.chksum;
parsed_sum = from_header (header->header.chksum,
sizeof header->header.chksum, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (int));
if (parsed_sum == (uintmax_t) -1)
return HEADER_FAILURE;
recorded_sum = parsed_sum;
if (unsigned_sum != recorded_sum && signed_sum != recorded_sum)
return HEADER_FAILURE;
return HEADER_SUCCESS;
}
/* 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.
@@ -262,23 +334,9 @@ list_archive (void)
You must always set_next_block_after(current_header) to skip past
the header which this routine reads. */
/* The standard BSD tar sources create the checksum by adding up the
bytes in the header as type char. I think the type char was unsigned
on the PDP-11, but it's signed on the Next and Sun. It looks like the
sources to BSD tar were never changed to compute the checksum
correctly, so both the Sun and Next add the bytes of the header as
signed chars. This doesn't cause a problem until you get a file with
a name containing characters with the high bit set. So read_header
computes two checksums -- signed and unsigned. */
enum read_header
read_header (bool raw_extended_headers)
{
size_t i;
int unsigned_sum; /* the POSIX one :-) */
int signed_sum; /* the Sun one :-( */
int recorded_sum;
uintmax_t parsed_sum;
char *p;
union block *header;
union block *header_copy;
@@ -292,44 +350,15 @@ read_header (bool raw_extended_headers)
while (1)
{
enum read_header status;
header = find_next_block ();
current_header = header;
if (!header)
return HEADER_END_OF_FILE;
unsigned_sum = 0;
signed_sum = 0;
p = header->buffer;
for (i = sizeof *header; i-- != 0;)
{
unsigned_sum += (unsigned char) *p;
signed_sum += (signed char) (*p++);
}
if (unsigned_sum == 0)
return HEADER_ZERO_BLOCK;
/* Adjust checksum to count the "chksum" field as blanks. */
for (i = sizeof header->header.chksum; i-- != 0;)
{
unsigned_sum -= (unsigned char) header->header.chksum[i];
signed_sum -= (signed char) (header->header.chksum[i]);
}
unsigned_sum += ' ' * sizeof header->header.chksum;
signed_sum += ' ' * sizeof header->header.chksum;
parsed_sum = from_header (header->header.chksum,
sizeof header->header.chksum, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (int));
if (parsed_sum == (uintmax_t) -1)
return HEADER_FAILURE;
recorded_sum = parsed_sum;
if (unsigned_sum != recorded_sum && signed_sum != recorded_sum)
return HEADER_FAILURE;
if ((status = tar_checksum (header)) != HEADER_SUCCESS)
return status;
/* Good block. Decode file size and return. */
@@ -355,7 +384,7 @@ read_header (bool raw_extended_headers)
xalloc_die ();
header_copy = xmalloc (size + 1);
if (header->header.typeflag == GNUTYPE_LONGNAME)
{
if (next_long_name)
@@ -370,7 +399,7 @@ read_header (bool raw_extended_headers)
next_long_link = header_copy;
next_long_link_blocks = size / BLOCKSIZE;
}
set_next_block_after (header);
*header_copy = *header;
bp = header_copy->buffer + BLOCKSIZE;
@@ -386,7 +415,7 @@ read_header (bool raw_extended_headers)
written = available_space_after (data_block);
if (written > size)
written = size;
memcpy (bp, data_block->buffer, written);
bp += written;
set_next_block_after ((union block *)
@@ -402,7 +431,7 @@ read_header (bool raw_extended_headers)
xheader_read (header, OFF_FROM_HEADER (header->header.size));
xheader_decode_global ();
}
/* Loop! */
}
@@ -515,11 +544,13 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode);
stat_info->stat.st_mtime = TIME_FROM_HEADER (header->header.mtime);
assign_string (&stat_info->uname, header->header.uname);
assign_string (&stat_info->gname, header->header.gname);
assign_string (&stat_info->uname,
header->header.uname[0] ? header->header.uname : NULL);
assign_string (&stat_info->gname,
header->header.gname[0] ? header->header.gname : NULL);
stat_info->devmajor = MAJOR_FROM_HEADER (header->header.devmajor);
stat_info->devminor = MINOR_FROM_HEADER (header->header.devminor);
stat_info->stat.st_atime = start_time;
stat_info->stat.st_ctime = start_time;
@@ -558,12 +589,13 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|| !gname_to_gid (header->header.gname, &stat_info->stat.st_gid))
stat_info->stat.st_gid = GID_FROM_HEADER (header->header.gid);
}
switch (header->header.typeflag)
{
case BLKTYPE:
case CHRTYPE:
stat_info->stat.st_rdev = makedev (stat_info->devmajor, stat_info->devminor);
stat_info->stat.st_rdev = makedev (stat_info->devmajor,
stat_info->devminor);
break;
default:
@@ -571,8 +603,16 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
}
}
current_stat_info.archive_file_size = current_stat_info.stat.st_size;
stat_info->archive_file_size = stat_info->stat.st_size;
xheader_decode (stat_info);
if (sparse_member_p (stat_info))
{
sparse_fixup_header (stat_info);
stat_info->is_sparse = true;
}
else
stat_info->is_sparse = false;
}
/* Convert buffer at WHERE0 of size DIGS from external format to
@@ -899,7 +939,7 @@ tartime (time_t t)
#else
/* Use ISO 8610 format. See:
http://www.cl.cam.ac.uk/~mgk25/iso-time.html */
struct tm *tm = localtime (&t);
struct tm *tm = utc_option ? gmtime (&t) : localtime (&t);
if (tm)
{
sprintf (buffer, "%04ld-%02d-%02d %02d:%02d:%02d",
@@ -953,7 +993,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
char modes[11];
char const *time_stamp;
char *temp_name = st->orig_file_name ? st->orig_file_name : st->file_name;
/* These hold formatted ints. */
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
char *user, *group;
@@ -1100,16 +1140,10 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
strcat (size,
STRINGIFY_BIGINT (minor (st->stat.st_rdev), uintbuf));
break;
case GNUTYPE_SPARSE:
strcpy (size,
STRINGIFY_BIGINT
(UINTMAX_FROM_HEADER (current_header
->oldgnu_header.realsize),
uintbuf));
break;
default:
/* st->stat.st_size keeps stored file size */
strcpy (size, STRINGIFY_BIGINT (st->archive_file_size, uintbuf));
strcpy (size, STRINGIFY_BIGINT (st->stat.st_size, uintbuf));
break;
}
@@ -1186,7 +1220,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Print a similar line when we make a directory automatically. */
void
print_for_mkdir (char *pathname, int length, mode_t mode)
print_for_mkdir (char *dirname, int length, mode_t mode)
{
char modes[11];
@@ -1205,7 +1239,7 @@ print_for_mkdir (char *pathname, int length, mode_t mode)
}
fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
_("Creating directory:"), length, quotearg (pathname));
_("Creating directory:"), length, quotearg (dirname));
}
}
@@ -1221,6 +1255,19 @@ skip_file (off_t size)
save_sizeleft = size;
}
if (seekable_archive)
{
off_t nblk = seek_archive (size);
if (nblk >= 0)
{
size -= nblk * BLOCKSIZE;
if (multi_volume_option) /* Argh.. */
save_sizeleft -= nblk * BLOCKSIZE;
}
else
seekable_archive = false;
}
while (size > 0)
{
x = find_next_block ();
@@ -1234,27 +1281,18 @@ skip_file (off_t size)
}
}
/* Skip the current member in the archive. */
/* Skip the current member in the archive.
NOTE: Current header must be decoded before calling this function. */
void
skip_member (void)
{
char save_typeflag = current_header->header.typeflag;
set_next_block_after (current_header);
assign_string (&save_name, current_stat_info.file_name);
if (current_format == OLDGNU_FORMAT
&& current_header->oldgnu_header.isextended)
{
union block *exhdr;
do
{
exhdr = find_next_block ();
if (!exhdr)
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
set_next_block_after (exhdr);
}
while (exhdr->sparse_header.isextended);
}
if (save_typeflag != DIRTYPE)
if (current_stat_info.is_sparse)
sparse_skip_file (&current_stat_info);
else if (save_typeflag != DIRTYPE)
skip_file (current_stat_info.stat.st_size);
}

View File

@@ -15,7 +15,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include "common.h"
#include <quotearg.h>

View File

@@ -1,7 +1,7 @@
/* Miscellaneous functions, not really specific to GNU tar.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
2003 Free Software Foundation, Inc.
2003, 2004 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
@@ -17,8 +17,8 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rmt.h"
#include <system.h>
#include <rmt.h>
#include "common.h"
#include <quotearg.h>
#include <save-cwd.h>
@@ -123,13 +123,13 @@ unquote_string (char *string)
source++;
break;
case 'n':
*destination++ = '\n';
case 'a':
*destination++ = '\a';
source++;
break;
case 't':
*destination++ = '\t';
case 'b':
*destination++ = '\b';
source++;
break;
@@ -138,8 +138,8 @@ unquote_string (char *string)
source++;
break;
case 'b':
*destination++ = '\b';
case 'n':
*destination++ = '\n';
source++;
break;
@@ -148,6 +148,16 @@ unquote_string (char *string)
source++;
break;
case 't':
*destination++ = '\t';
source++;
break;
case 'v':
*destination++ = '\v';
source++;
break;
case '?':
*destination++ = 0177;
source++;
@@ -203,32 +213,33 @@ unquote_string (char *string)
static char *before_backup_name;
static char *after_backup_name;
/* Return 1 if PATH is obviously "." or "/". */
/* Return 1 if FILE_NAME is obviously "." or "/". */
static bool
must_be_dot_or_slash (char const *path)
must_be_dot_or_slash (char const *file_name)
{
path += FILESYSTEM_PREFIX_LEN (path);
file_name += FILE_SYSTEM_PREFIX_LEN (file_name);
if (ISSLASH (path[0]))
if (ISSLASH (file_name[0]))
{
for (;;)
if (ISSLASH (path[1]))
path++;
else if (path[1] == '.' && ISSLASH (path[2 + (path[2] == '.')]))
path += 2 + (path[2] == '.');
if (ISSLASH (file_name[1]))
file_name++;
else if (file_name[1] == '.'
&& ISSLASH (file_name[2 + (file_name[2] == '.')]))
file_name += 2 + (file_name[2] == '.');
else
return ! path[1];
return ! file_name[1];
}
else
{
while (path[0] == '.' && ISSLASH (path[1]))
while (file_name[0] == '.' && ISSLASH (file_name[1]))
{
path += 2;
while (ISSLASH (*path))
path++;
file_name += 2;
while (ISSLASH (*file_name))
file_name++;
}
return ! path[0] || (path[0] == '.' && ! path[1]);
return ! file_name[0] || (file_name[0] == '.' && ! file_name[1]);
}
}
@@ -236,32 +247,32 @@ must_be_dot_or_slash (char const *path)
Report an error with errno set to zero for obvious cases of this;
otherwise call rmdir. */
static int
safer_rmdir (const char *path)
safer_rmdir (const char *file_name)
{
if (must_be_dot_or_slash (path))
if (must_be_dot_or_slash (file_name))
{
errno = 0;
return -1;
}
return rmdir (path);
return rmdir (file_name);
}
/* Remove PATH, returning 1 on success. If PATH is a directory, then
if OPTION is RECURSIVE_REMOVE_OPTION is set remove PATH
recursively; otherwise, remove it only if it is empty. If PATH is
/* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory,
then if OPTION is RECURSIVE_REMOVE_OPTION is set remove FILE_NAME
recursively; otherwise, remove it only if it is empty. If FILE_NAME is
a directory that cannot be removed (e.g., because it is nonempty)
and if OPTION is WANT_DIRECTORY_REMOVE_OPTION, then return -1.
Return 0 on error, with errno set; if PATH is obviously the working
Return 0 on error, with errno set; if FILE_NAME is obviously the working
directory return zero with errno set to zero. */
int
remove_any_file (const char *path, enum remove_option option)
remove_any_file (const char *file_name, enum remove_option option)
{
/* Try unlink first if we are not root, as this saves us a system
call in the common case where we're removing a non-directory. */
if (! we_are_root)
{
if (unlink (path) == 0)
if (unlink (file_name) == 0)
return 1;
/* POSIX 1003.1-2001 requires EPERM when attempting to unlink a
@@ -271,13 +282,13 @@ remove_any_file (const char *path, enum remove_option option)
return 0;
}
if (safer_rmdir (path) == 0)
if (safer_rmdir (file_name) == 0)
return 1;
switch (errno)
{
case ENOTDIR:
return we_are_root && unlink (path) == 0;
return we_are_root && unlink (file_name) == 0;
case 0:
case EEXIST:
@@ -294,7 +305,7 @@ remove_any_file (const char *path, enum remove_option option)
case RECURSIVE_REMOVE_OPTION:
{
char *directory = savedir (path);
char *directory = savedir (file_name);
char const *entry;
size_t entrylen;
@@ -305,10 +316,11 @@ remove_any_file (const char *path, enum remove_option option)
(entrylen = strlen (entry)) != 0;
entry += entrylen + 1)
{
char *path_buffer = new_name (path, entry);
int r = remove_any_file (path_buffer, 1);
char *file_name_buffer = new_name (file_name, entry);
int r = remove_any_file (file_name_buffer,
RECURSIVE_REMOVE_OPTION);
int e = errno;
free (path_buffer);
free (file_name_buffer);
if (! r)
{
@@ -319,7 +331,7 @@ remove_any_file (const char *path, enum remove_option option)
}
free (directory);
return safer_rmdir (path) == 0;
return safer_rmdir (file_name) == 0;
}
}
break;
@@ -328,37 +340,39 @@ remove_any_file (const char *path, enum remove_option option)
return 0;
}
/* Check if PATH already exists and make a backup of it right now.
/* Check if FILE_NAME already exists and make a backup of it right now.
Return success (nonzero) only if the backup is either unneeded, or
successful. For now, directories are considered to never need
backup. If ARCHIVE is nonzero, this is the archive and so, we do
not have to backup block or character devices, nor remote entities. */
backup. If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and
so, we do not have to backup block or character devices, nor remote
entities. */
bool
maybe_backup_file (const char *path, int archive)
maybe_backup_file (const char *file_name, int this_is_the_archive)
{
struct stat file_stat;
/* Check if we really need to backup the file. */
if (archive && _remdev (path))
if (this_is_the_archive && _remdev (file_name))
return true;
if (stat (path, &file_stat))
if (stat (file_name, &file_stat))
{
if (errno == ENOENT)
return true;
stat_error (path);
stat_error (file_name);
return false;
}
if (S_ISDIR (file_stat.st_mode))
return true;
if (archive && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
if (this_is_the_archive
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
return true;
assign_string (&before_backup_name, path);
assign_string (&before_backup_name, file_name);
/* A run situation may exist between Emacs or other GNU programs trying to
make a backup for the same file simultaneously. If theoretically
@@ -366,7 +380,7 @@ maybe_backup_file (const char *path, int archive)
convention, GNU-wide, for all programs doing backups. */
assign_string (&after_backup_name, 0);
after_backup_name = find_backup_file_name (path, backup_type);
after_backup_name = find_backup_file_name (file_name, backup_type);
if (! after_backup_name)
xalloc_die ();
@@ -586,12 +600,6 @@ close_error (char const *name)
call_arg_error ("close", name);
}
void
close_fatal (char const *name)
{
call_arg_fatal ("close", name);
}
void
close_warn (char const *name)
{
@@ -875,16 +883,16 @@ write_error (char const *name)
}
void
write_error_details (char const *name, ssize_t status, size_t size)
write_error_details (char const *name, size_t status, size_t size)
{
if (status < 0)
if (status == 0)
write_error (name);
else
ERROR ((0, 0,
ngettext ("%s: Wrote only %lu of %lu byte",
"%s: Wrote only %lu of %lu bytes",
record_size),
name, (unsigned long) status, (unsigned long) record_size));
size),
name, (unsigned long int) status, (unsigned long int) size));
}
void
@@ -919,18 +927,29 @@ xpipe (int fd[2])
call_arg_fatal ("pipe", _("interprocess channel"));
}
/* Return an unambiguous printable representation, allocated in slot N,
for NAME, suitable for diagnostics. */
char const *
quote_n (int n, char const *name)
/* Return PTR, aligned upward to the next multiple of ALIGNMENT.
ALIGNMENT must be nonzero. The caller must arrange for ((char *)
PTR) through ((char *) PTR + ALIGNMENT - 1) to be addressable
locations. */
static inline void *
ptr_align (void *ptr, size_t alignment)
{
return quotearg_n_style (n, locale_quoting_style, name);
char *p0 = ptr;
char *p1 = p0 + alignment - 1;
return p1 - (size_t) p1 % alignment;
}
/* Return an unambiguous printable representation of NAME, suitable
for diagnostics. */
char const *
quote (char const *name)
/* Return the address of a page-aligned buffer of at least SIZE bytes.
The caller should free *PTR when done with the buffer. */
void *
page_aligned_alloc (void **ptr, size_t size)
{
return quote_n (0, name);
size_t alignment = getpagesize ();
size_t size1 = size + alignment;
if (size1 < size)
xalloc_die ();
*ptr = xmalloc (size1);
return ptr_align (*ptr, alignment);
}

View File

@@ -1,7 +1,7 @@
/* Various processing of names.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
2003 Free Software Foundation, Inc.
2003, 2004 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
@@ -17,7 +17,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include <fnmatch.h>
#include <hash.h>
@@ -56,6 +56,8 @@ static char *cached_no_such_gname;
static uid_t cached_no_such_uid;
static gid_t cached_no_such_gid;
static void register_individual_file (char const *name);
/* Given UID, find the corresponding UNAME. */
void
uid_to_uname (uid_t uid, char **uname)
@@ -118,7 +120,7 @@ gid_to_gname (gid_t gid, char **gname)
/* Given UNAME, set the corresponding UID and return 1, or else, return 0. */
int
uname_to_uid (char *uname, uid_t *uidp)
uname_to_uid (char const *uname, uid_t *uidp)
{
struct passwd *passwd;
@@ -148,7 +150,7 @@ uname_to_uid (char *uname, uid_t *uidp)
/* Given GNAME, set the corresponding GID and return 1, or else, return 0. */
int
gname_to_gid (char *gname, gid_t *gidp)
gname_to_gid (char const *gname, gid_t *gidp)
{
struct group *group;
@@ -227,7 +229,7 @@ is_pattern (const char *string)
/* Set up to gather file names for tar. They can either come from a
file or were saved from decoding arguments. */
void
name_init (int argc, char *const *argv)
name_init (void)
{
name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
name_buffer_length = NAME_FIELD_SIZE;
@@ -358,6 +360,8 @@ name_next (int change_dirs)
else
{
unquote_string (name_buffer);
if (incremental_option)
register_individual_file (name_buffer);
return name_buffer;
}
}
@@ -443,6 +447,8 @@ name_gather (void)
namelist = buffer;
nametail = &namelist->next;
}
else if (change_dir)
addname (0, change_dir);
}
else
{
@@ -513,10 +519,10 @@ addname (char const *string, int change_dir)
return name;
}
/* Find a match for PATH (whose string length is LENGTH) in the name
/* Find a match for FILE_NAME (whose string length is LENGTH) in the name
list. */
static struct name *
namelist_match (char const *path, size_t length)
namelist_match (char const *file_name, size_t length)
{
struct name *p;
@@ -524,27 +530,27 @@ namelist_match (char const *path, size_t length)
{
/* If first chars don't match, quick skip. */
if (p->firstch && p->name[0] != path[0])
if (p->firstch && p->name[0] != file_name[0])
continue;
if (p->regexp
? fnmatch (p->name, path, recursion_option) == 0
? fnmatch (p->name, file_name, recursion_option) == 0
: (p->length <= length
&& (path[p->length] == '\0'
|| (ISSLASH (path[p->length]) && recursion_option))
&& memcmp (path, p->name, p->length) == 0))
&& (file_name[p->length] == '\0'
|| (ISSLASH (file_name[p->length]) && recursion_option))
&& memcmp (file_name, p->name, p->length) == 0))
return p;
}
return 0;
}
/* Return true if and only if name PATH (from an archive) matches any
/* Return true if and only if name FILE_NAME (from an archive) matches any
name from the namelist. */
int
name_match (const char *path)
name_match (const char *file_name)
{
size_t length = strlen (path);
size_t length = strlen (file_name);
while (1)
{
@@ -561,10 +567,10 @@ name_match (const char *path)
return ! files_from_option;
}
cursor = namelist_match (path, length);
cursor = namelist_match (file_name, length);
if (cursor)
{
if (!(ISSLASH (path[cursor->length]) && recursion_option)
if (!(ISSLASH (file_name[cursor->length]) && recursion_option)
|| cursor->found_count == 0)
cursor->found_count++; /* remember it matched */
if (starting_file_option)
@@ -639,7 +645,7 @@ names_notfound (void)
ERROR ((0, 0, _("%s: Required occurrence not found in archive"),
quotearg_colon (cursor->name)));
}
/* Don't bother freeing the name list; we're about to exit. */
namelist = 0;
nametail = &namelist;
@@ -748,8 +754,8 @@ compare_names (struct name const *n1, struct name const *n2)
static void
add_hierarchy_to_namelist (struct name *name, dev_t device)
{
char *path = name->name;
char *buffer = get_directory_contents (path, device);
char *file_name = name->name;
char *buffer = get_directory_contents (file_name, device);
if (! buffer)
name->dir_contents = "\0\0\0\0";
@@ -759,18 +765,18 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
size_t allocated_length = (name_length >= NAME_FIELD_SIZE
? name_length + NAME_FIELD_SIZE
: NAME_FIELD_SIZE);
char *name_buffer = xmalloc (allocated_length + 1);
char *namebuf = xmalloc (allocated_length + 1);
/* FIXME: + 2 above? */
char *string;
size_t string_length;
int change_dir = name->change_dir;
name->dir_contents = buffer;
strcpy (name_buffer, path);
if (! ISSLASH (name_buffer[name_length - 1]))
strcpy (namebuf, file_name);
if (! ISSLASH (namebuf[name_length - 1]))
{
name_buffer[name_length++] = '/';
name_buffer[name_length] = '\0';
namebuf[name_length++] = '/';
namebuf[name_length] = '\0';
}
for (string = buffer; *string; string += string_length + 1)
@@ -788,15 +794,15 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
}
while (allocated_length <= name_length + string_length);
name_buffer = xrealloc (name_buffer, allocated_length + 1);
namebuf = xrealloc (namebuf, allocated_length + 1);
}
strcpy (name_buffer + name_length, string + 1);
add_hierarchy_to_namelist (addname (name_buffer, change_dir),
strcpy (namebuf + name_length, string + 1);
add_hierarchy_to_namelist (addname (namebuf, change_dir),
device);
}
}
free (name_buffer);
free (namebuf);
}
}
@@ -857,13 +863,13 @@ collect_and_sort_names (void)
will have to do that if it wants to. Oh, and if the namelist is
empty, it returns null, unlike name_match, which returns TRUE. */
struct name *
name_scan (const char *path)
name_scan (const char *file_name)
{
size_t length = strlen (path);
size_t length = strlen (file_name);
while (1)
{
struct name *cursor = namelist_match (path, length);
struct name *cursor = namelist_match (file_name, length);
if (cursor)
return cursor;
@@ -914,18 +920,18 @@ blank_name_list (void)
name->found_count = 0;
}
/* Yield a newly allocated file name consisting of PATH concatenated to
NAME, with an intervening slash if PATH does not already end in one. */
/* 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. */
char *
new_name (const char *path, const char *name)
new_name (const char *file_name, const char *name)
{
size_t pathlen = strlen (path);
size_t file_name_len = strlen (file_name);
size_t namesize = strlen (name) + 1;
int slash = pathlen && ! ISSLASH (path[pathlen - 1]);
char *buffer = xmalloc (pathlen + slash + namesize);
memcpy (buffer, path, pathlen);
buffer[pathlen] = '/';
memcpy (buffer + pathlen + slash, name, namesize);
int slash = file_name_len && ! ISSLASH (file_name[file_name_len - 1]);
char *buffer = xmalloc (file_name_len + slash + namesize);
memcpy (buffer, file_name, file_name_len);
buffer[file_name_len] = '/';
memcpy (buffer + file_name_len + slash, name, namesize);
return buffer;
}
@@ -933,7 +939,7 @@ new_name (const char *path, const char *name)
bool
excluded_name (char const *name)
{
return excluded_filename (excluded, name + FILESYSTEM_PREFIX_LEN (name));
return excluded_filename (excluded, name + FILE_SYSTEM_PREFIX_LEN (name));
}
/* Hash tables of strings. */
@@ -999,7 +1005,44 @@ is_avoided_name (char const *name)
{
return hash_string_lookup (avoided_name_table, name);
}
static Hash_table *individual_file_table;
static void
register_individual_file (char const *name)
{
struct stat st;
if (deref_stat (dereference_option, name, &st) != 0)
return; /* Will be complained about later */
if (S_ISDIR (st.st_mode))
return;
hash_string_insert (&individual_file_table, name);
}
bool
is_individual_file (char const *name)
{
return hash_string_lookup (individual_file_table, name);
}
static Hash_table *prefix_table[2];
/* Return true if file names of some members in the archive were stripped off
their leading components. We could have used
return prefix_table[0] || prefix_table[1]
but the following seems to be safer: */
bool
removed_prefixes_p (void)
{
return (prefix_table[0] && hash_get_n_entries (prefix_table[0]) != 0)
|| (prefix_table[1] && hash_get_n_entries (prefix_table[1]) != 0);
}
/* Return a safer suffix of FILE_NAME, or "." if it has no safer
suffix. Check for fully specified file names and other atrocities.
Warn the user if we do not return NAME. If LINK_TARGET is 1,
@@ -1014,16 +1057,16 @@ safer_name_suffix (char const *file_name, bool link_target)
p = file_name;
else
{
/* Skip file system prefixes, leading pathnames that contain
/* Skip file system prefixes, leading file name components that contain
"..", and leading slashes. */
size_t prefix_len = FILESYSTEM_PREFIX_LEN (file_name);
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);
for (p = file_name + prefix_len; *p; )
{
if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
prefix_len = p + 2 - file_name;
do
{
char c = *p++;
@@ -1039,7 +1082,6 @@ safer_name_suffix (char const *file_name, bool link_target)
if (prefix_len)
{
static Hash_table *prefix_table[2];
char *prefix = alloca (prefix_len + 1);
memcpy (prefix, file_name, prefix_len);
prefix[prefix_len] = '\0';
@@ -1065,9 +1107,9 @@ safer_name_suffix (char const *file_name, bool link_target)
N_("Substituting `.' for empty member name"),
N_("Substituting `.' for empty hard link target")
};
WARN ((0, 0, _(diagnostic[link_target])));
WARN ((0, 0, "%s", _(diagnostic[link_target])));
}
p = ".";
}
@@ -1075,13 +1117,13 @@ safer_name_suffix (char const *file_name, bool link_target)
}
/* Return the size of the prefix of FILE_NAME that is removed after
stripping NUM leading path name components. NUM must be
stripping NUM leading file name components. NUM must be
positive. */
size_t
stripped_prefix_len (char const *file_name, size_t num)
{
char const *p = file_name + FILESYSTEM_PREFIX_LEN (file_name);
char const *p = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
while (ISSLASH (*p))
p++;
while (*p)
@@ -1099,11 +1141,11 @@ stripped_prefix_len (char const *file_name, size_t num)
return -1;
}
/* Return nonzero if NAME contains ".." as a path name component. */
/* Return nonzero if NAME contains ".." as a file name component. */
bool
contains_dot_dot (char const *name)
{
char const *p = name + FILESYSTEM_PREFIX_LEN (name);
char const *p = name + FILE_SYSTEM_PREFIX_LEN (name);
for (;; p++)
{

575
src/rmt.c
View File

@@ -1,575 +0,0 @@
/* Remote connection server.
Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Copyright (C) 1983 Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms are permitted provided
that the above copyright notice and this paragraph are duplicated in all
such forms and that any documentation, advertising materials, and other
materials related to such distribution and use acknowledge that the
software was developed by the University of California, Berkeley. The
name of the University may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include "system.h"
#include <localedir.h>
#include <safe-read.h>
#include <full-write.h>
#include <getopt.h>
#include <sys/socket.h>
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif
/* Maximum size of a string from the requesting program. */
#define STRING_SIZE 64
/* Name of executing program. */
const char *program_name;
/* File descriptor of the tape device, or negative if none open. */
static int tape = -1;
/* Buffer containing transferred data, and its allocated size. */
static char *record_buffer;
static size_t allocated_size;
/* Buffer for constructing the reply. */
static char reply_buffer[BUFSIZ];
/* Debugging tools. */
static FILE *debug_file;
#define DEBUG(File) \
if (debug_file) fprintf(debug_file, File)
#define DEBUG1(File, Arg) \
if (debug_file) fprintf(debug_file, File, Arg)
#define DEBUG2(File, Arg1, Arg2) \
if (debug_file) fprintf(debug_file, File, Arg1, Arg2)
/* Return an error string, given an error number. */
#if HAVE_STRERROR
# ifndef strerror
char *strerror ();
# endif
#else
static char *
private_strerror (int errnum)
{
extern char *sys_errlist[];
extern int sys_nerr;
if (errnum > 0 && errnum <= sys_nerr)
return _(sys_errlist[errnum]);
return _("Unknown system error");
}
# define strerror private_strerror
#endif
static void
report_error_message (const char *string)
{
DEBUG1 ("rmtd: E 0 (%s)\n", string);
sprintf (reply_buffer, "E0\n%s\n", string);
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
}
static void
report_numbered_error (int num)
{
DEBUG2 ("rmtd: E %d (%s)\n", num, strerror (num));
sprintf (reply_buffer, "E%d\n%s\n", num, strerror (num));
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
}
static void
get_string (char *string)
{
int counter;
for (counter = 0; counter < STRING_SIZE; counter++)
{
if (safe_read (STDIN_FILENO, string + counter, 1) != 1)
exit (EXIT_SUCCESS);
if (string[counter] == '\n')
break;
}
string[counter] = '\0';
}
static void
prepare_input_buffer (int fd, size_t size)
{
if (size <= allocated_size)
return;
if (record_buffer)
free (record_buffer);
record_buffer = malloc (size);
if (! record_buffer)
{
DEBUG (_("rmtd: Cannot allocate buffer space\n"));
report_error_message (N_("Cannot allocate buffer space"));
exit (EXIT_FAILURE); /* exit status used to be 4 */
}
allocated_size = size;
#ifdef SO_RCVBUF
if (0 <= fd)
{
int isize = size < INT_MAX ? size : INT_MAX;
while (setsockopt (fd, SOL_SOCKET, SO_RCVBUF,
(char *) &isize, sizeof isize)
&& 1024 < isize)
isize >>= 1;
}
#endif
}
/* Decode OFLAG_STRING, which represents the 2nd argument to `open'.
OFLAG_STRING should contain an optional integer, followed by an optional
symbolic representation of an open flag using only '|' to separate its
components (e.g. "O_WRONLY|O_CREAT|O_TRUNC"). Prefer the symbolic
representation if available, falling back on the numeric
representation, or to zero if both formats are absent.
This function should be the inverse of encode_oflag. The numeric
representation is not portable from one host to another, but it is
for backward compatibility with old-fashioned clients that do not
emit symbolic open flags. */
static int
decode_oflag (char const *oflag_string)
{
char *oflag_num_end;
int numeric_oflag = strtol (oflag_string, &oflag_num_end, 10);
int symbolic_oflag = 0;
oflag_string = oflag_num_end;
while (ISSPACE ((unsigned char) *oflag_string))
oflag_string++;
do
{
struct name_value_pair { char const *name; int value; };
static struct name_value_pair const table[] =
{
#ifdef O_APPEND
{"APPEND", O_APPEND},
#endif
{"CREAT", O_CREAT},
#ifdef O_DSYNC
{"DSYNC", O_DSYNC},
#endif
{"EXCL", O_EXCL},
#ifdef O_LARGEFILE
{"LARGEFILE", O_LARGEFILE}, /* LFS extension for opening large files */
#endif
#ifdef O_NOCTTY
{"NOCTTY", O_NOCTTY},
#endif
#ifdef O_NONBLOCK
{"NONBLOCK", O_NONBLOCK},
#endif
{"RDONLY", O_RDONLY},
{"RDWR", O_RDWR},
#ifdef O_RSYNC
{"RSYNC", O_RSYNC},
#endif
#ifdef O_SYNC
{"SYNC", O_SYNC},
#endif
{"TRUNC", O_TRUNC},
{"WRONLY", O_WRONLY}
};
struct name_value_pair const *t;
size_t s;
if (*oflag_string++ != 'O' || *oflag_string++ != '_')
return numeric_oflag;
for (t = table;
(strncmp (oflag_string, t->name, s = strlen (t->name)) != 0
|| (oflag_string[s]
&& strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789",
oflag_string[s])));
t++)
if (t == table + sizeof table / sizeof *table - 1)
return numeric_oflag;
symbolic_oflag |= t->value;
oflag_string += s;
}
while (*oflag_string++ == '|');
return symbolic_oflag;
}
static struct option const long_opts[] =
{
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
static void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
printf (_("\
Usage: %s [OPTION]\n\
Manipulate a tape drive, accepting commands from a remote process.\n\
\n\
--version Output version info.\n\
--help Output this help.\n"),
program_name);
printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
}
exit (status);
}
int
main (int argc, char *const *argv)
{
char command;
ssize_t status;
/* FIXME: Localization is meaningless, unless --help and --version are
locally used. Localization would be best accomplished by the calling
tar, on messages found within error packets. */
program_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
switch (getopt_long (argc, argv, "", long_opts, NULL))
{
default:
usage (EXIT_FAILURE);
case 'h':
usage (EXIT_SUCCESS);
case 'v':
{
printf ("rmt (%s) %s\n%s\n", PACKAGE_NAME, PACKAGE_VERSION,
"Copyright (C) 2003 Free Software Foundation, Inc.");
puts (_("\
This program comes with NO WARRANTY, to the extent permitted by law.\n\
You may redistribute it under the terms of the GNU General Public License;\n\
see the file named COPYING for details."));
}
return EXIT_SUCCESS;
case -1:
break;
}
if (optind < argc)
{
if (optind != argc - 1)
usage (EXIT_FAILURE);
debug_file = fopen (argv[optind], "w");
if (debug_file == 0)
{
report_numbered_error (errno);
return EXIT_FAILURE;
}
setbuf (debug_file, 0);
}
top:
errno = 0;
status = 0;
if (safe_read (STDIN_FILENO, &command, 1) != 1)
return EXIT_SUCCESS;
switch (command)
{
/* FIXME: Maybe 'H' and 'V' for --help and --version output? */
case 'O':
{
char device_string[STRING_SIZE];
char oflag_string[STRING_SIZE];
get_string (device_string);
get_string (oflag_string);
DEBUG2 ("rmtd: O %s %s\n", device_string, oflag_string);
if (tape >= 0)
close (tape);
tape = open (device_string, decode_oflag (oflag_string), MODE_RW);
if (tape < 0)
goto ioerror;
goto respond;
}
case 'C':
{
char device_string[STRING_SIZE];
get_string (device_string); /* discard */
DEBUG ("rmtd: C\n");
if (close (tape) < 0)
goto ioerror;
tape = -1;
goto respond;
}
case 'L':
{
char count_string[STRING_SIZE];
char position_string[STRING_SIZE];
off_t count = 0;
int negative;
int whence;
char *p;
get_string (count_string);
get_string (position_string);
DEBUG2 ("rmtd: L %s %s\n", count_string, position_string);
/* Parse count_string, taking care to check for overflow.
We can't use standard functions,
since off_t might be longer than long. */
for (p = count_string; *p == ' ' || *p == '\t'; p++)
continue;
negative = *p == '-';
p += negative || *p == '+';
for (;;)
{
int digit = *p++ - '0';
if (9 < (unsigned) digit)
break;
else
{
off_t c10 = 10 * count;
off_t nc = negative ? c10 - digit : c10 + digit;
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
{
report_error_message (N_("Seek offset out of range"));
return EXIT_FAILURE;
}
count = nc;
}
}
switch (atoi (position_string))
{
case 0: whence = SEEK_SET; break;
case 1: whence = SEEK_CUR; break;
case 2: whence = SEEK_END; break;
default:
report_error_message (N_("Seek direction out of range"));
return EXIT_FAILURE;
}
count = lseek (tape, count, whence);
if (count < 0)
goto ioerror;
/* Convert count back to string for reply.
We can't use sprintf, since off_t might be longer than long. */
p = count_string + sizeof count_string;
*--p = '\0';
do
*--p = '0' + (int) (count % 10);
while ((count /= 10) != 0);
DEBUG1 ("rmtd: A %s\n", p);
sprintf (reply_buffer, "A%s\n", p);
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
goto top;
}
case 'W':
{
char count_string[STRING_SIZE];
size_t size;
size_t counter;
get_string (count_string);
size = atol (count_string);
DEBUG1 ("rmtd: W %s\n", count_string);
prepare_input_buffer (STDIN_FILENO, size);
for (counter = 0; counter < size; counter += status)
{
status = safe_read (STDIN_FILENO, &record_buffer[counter],
size - counter);
if (status <= 0)
{
DEBUG (_("rmtd: Premature eof\n"));
report_error_message (N_("Premature end of file"));
return EXIT_FAILURE; /* exit status used to be 2 */
}
}
status = full_write (tape, record_buffer, size);
if (status < 0)
goto ioerror;
goto respond;
}
case 'R':
{
char count_string[STRING_SIZE];
size_t size;
get_string (count_string);
DEBUG1 ("rmtd: R %s\n", count_string);
size = atol (count_string);
prepare_input_buffer (-1, size);
status = safe_read (tape, record_buffer, size);
if (status < 0)
goto ioerror;
sprintf (reply_buffer, "A%ld\n", (long) status);
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
full_write (STDOUT_FILENO, record_buffer, status);
goto top;
}
case 'I':
{
char operation_string[STRING_SIZE];
char count_string[STRING_SIZE];
get_string (operation_string);
get_string (count_string);
DEBUG2 ("rmtd: I %s %s\n", operation_string, count_string);
#ifdef MTIOCTOP
{
struct mtop mtop;
const char *p;
off_t count = 0;
int negative;
/* Parse count_string, taking care to check for overflow.
We can't use standard functions,
since off_t might be longer than long. */
for (p = count_string; *p == ' ' || *p == '\t'; p++)
continue;
negative = *p == '-';
p += negative || *p == '+';
for (;;)
{
int digit = *p++ - '0';
if (9 < (unsigned) digit)
break;
else
{
off_t c10 = 10 * count;
off_t nc = negative ? c10 - digit : c10 + digit;
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
{
report_error_message (N_("Seek offset out of range"));
return EXIT_FAILURE;
}
count = nc;
}
}
mtop.mt_count = count;
if (mtop.mt_count != count)
{
report_error_message (N_("Seek offset out of range"));
return EXIT_FAILURE;
}
mtop.mt_op = atoi (operation_string);
if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
goto ioerror;
}
#endif
goto respond;
}
case 'S': /* status */
{
DEBUG ("rmtd: S\n");
#ifdef MTIOCGET
{
struct mtget operation;
if (ioctl (tape, MTIOCGET, (char *) &operation) < 0)
goto ioerror;
status = sizeof operation;
sprintf (reply_buffer, "A%ld\n", (long) status);
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
full_write (STDOUT_FILENO, (char *) &operation, sizeof operation);
}
#endif
goto top;
}
default:
DEBUG1 (_("rmtd: Garbage command %c\n"), command);
report_error_message (N_("Garbage command"));
return EXIT_FAILURE; /* exit status used to be 3 */
}
respond:
DEBUG1 ("rmtd: A %ld\n", (long) status);
sprintf (reply_buffer, "A%ld\n", (long) status);
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
goto top;
ioerror:
report_numbered_error (errno);
goto top;
}

View File

@@ -1,95 +0,0 @@
/* Definitions for communicating with a remote tape drive.
Copyright (C) 1988, 1992, 1996, 1997, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern char *rmt_path__;
int rmt_open__ (const char *, int, int, const char *);
int rmt_close__ (int);
ssize_t rmt_read__ (int, char *, size_t);
ssize_t rmt_write__ (int, char *, size_t);
off_t rmt_lseek__ (int, off_t, int);
int rmt_ioctl__ (int, int, char *);
/* A filename is remote if it contains a colon not preceded by a slash,
to take care of `/:/' which is a shorthand for `/.../<CELL-NAME>/fs'
on machines running OSF's Distributing Computing Environment (DCE) and
Distributed File System (DFS). However, when --force-local, a
filename is never remote. */
#define _remdev(Path) \
(!force_local_option && (rmt_path__ = strchr (Path, ':')) \
&& rmt_path__ > (Path) && ! memchr (Path, rmt_path__ - (Path), '/'))
#define _isrmt(Fd) \
((Fd) >= __REM_BIAS)
#define __REM_BIAS (1 << 30)
#ifndef O_CREAT
# define O_CREAT 01000
#endif
#define rmtopen(Path, Oflag, Mode, Command) \
(_remdev (Path) ? rmt_open__ (Path, Oflag, __REM_BIAS, Command) \
: open (Path, Oflag, Mode))
#define rmtaccess(Path, Amode) \
(_remdev (Path) ? 0 : access (Path, Amode))
#define rmtstat(Path, Buffer) \
(_remdev (Path) ? (errno = EOPNOTSUPP), -1 : stat (Path, Buffer))
#define rmtcreat(Path, Mode, Command) \
(_remdev (Path) \
? rmt_open__ (Path, 1 | O_CREAT, __REM_BIAS, Command) \
: creat (Path, Mode))
#define rmtlstat(Path, Buffer) \
(_remdev (Path) ? (errno = EOPNOTSUPP), -1 : lstat (Path, Buffer))
#define rmtread(Fd, Buffer, Length) \
(_isrmt (Fd) ? rmt_read__ (Fd - __REM_BIAS, Buffer, Length) \
: safe_read (Fd, Buffer, Length))
#define rmtwrite(Fd, Buffer, Length) \
(_isrmt (Fd) ? rmt_write__ (Fd - __REM_BIAS, Buffer, Length) \
: full_write (Fd, Buffer, Length))
#define rmtlseek(Fd, Offset, Where) \
(_isrmt (Fd) ? rmt_lseek__ (Fd - __REM_BIAS, Offset, Where) \
: lseek (Fd, Offset, Where))
#define rmtclose(Fd) \
(_isrmt (Fd) ? rmt_close__ (Fd - __REM_BIAS) : close (Fd))
#define rmtioctl(Fd, Request, Argument) \
(_isrmt (Fd) ? rmt_ioctl__ (Fd - __REM_BIAS, Request, Argument) \
: ioctl (Fd, Request, Argument))
#define rmtdup(Fd) \
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : dup (Fd))
#define rmtfstat(Fd, Buffer) \
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : fstat (Fd, Buffer))
#define rmtfcntl(Fd, Command, Argument) \
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : fcntl (Fd, Command, Argument))
#define rmtisatty(Fd) \
(_isrmt (Fd) ? 0 : isatty (Fd))

View File

@@ -1,715 +0,0 @@
/* Functions for communicating with a remote tape drive.
Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* The man page rmt(8) for /etc/rmt documents the remote mag tape protocol
which rdump and rrestore use. Unfortunately, the man page is *WRONG*.
The author of the routines I'm including originally wrote his code just
based on the man page, and it didn't work, so he went to the rdump source
to figure out why. The only thing he had to change was to check for the
'F' return code in addition to the 'E', and to separate the various
arguments with \n instead of a space. I personally don't think that this
is much of a problem, but I wanted to point it out. -- Arnold Robbins
Originally written by Jeff Lee, modified some by Arnold Robbins. Redone
as a library that can replace open, read, write, etc., by Fred Fish, with
some additional work by Arnold Robbins. Modified to make all rmt* calls
into macros for speed by Jay Fenlason. Use -DWITH_REXEC for rexec
code, courtesy of Dan Kegel. */
#include "system.h"
#include <safe-read.h>
#include <full-write.h>
/* Try hard to get EOPNOTSUPP defined. 486/ISC has it in net/errno.h,
3B2/SVR3 has it in sys/inet.h. Otherwise, like on MSDOS, use EINVAL. */
#ifndef EOPNOTSUPP
# if HAVE_NET_ERRNO_H
# include <net/errno.h>
# endif
# if HAVE_SYS_INET_H
# include <sys/inet.h>
# endif
# ifndef EOPNOTSUPP
# define EOPNOTSUPP EINVAL
# endif
#endif
#include <signal.h>
#if HAVE_NETDB_H
# include <netdb.h>
#endif
#include "rmt.h"
/* Exit status if exec errors. */
#define EXIT_ON_EXEC_ERROR 128
/* FIXME: Size of buffers for reading and writing commands to rmt. */
#define COMMAND_BUFFER_SIZE 64
#ifndef RETSIGTYPE
# define RETSIGTYPE void
#endif
/* FIXME: Maximum number of simultaneous remote tape connections. */
#define MAXUNIT 4
#define PREAD 0 /* read file descriptor from pipe() */
#define PWRITE 1 /* write file descriptor from pipe() */
/* Return the parent's read side of remote tape connection Fd. */
#define READ_SIDE(Fd) (from_remote[Fd][PREAD])
/* Return the parent's write side of remote tape connection Fd. */
#define WRITE_SIDE(Fd) (to_remote[Fd][PWRITE])
/* The pipes for receiving data from remote tape drives. */
static int from_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
/* The pipes for sending data to remote tape drives. */
static int to_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
/* Temporary variable used by macros in rmt.h. */
char *rmt_path__;
/* Close remote tape connection HANDLE, and reset errno to ERRNO_VALUE. */
static void
_rmt_shutdown (int handle, int errno_value)
{
close (READ_SIDE (handle));
close (WRITE_SIDE (handle));
READ_SIDE (handle) = -1;
WRITE_SIDE (handle) = -1;
errno = errno_value;
}
/* Attempt to perform the remote tape command specified in BUFFER on
remote tape connection HANDLE. Return 0 if successful, -1 on
error. */
static int
do_command (int handle, const char *buffer)
{
/* Save the current pipe handler and try to make the request. */
size_t length = strlen (buffer);
RETSIGTYPE (*pipe_handler) () = signal (SIGPIPE, SIG_IGN);
ssize_t written = full_write (WRITE_SIDE (handle), buffer, length);
signal (SIGPIPE, pipe_handler);
if (written == length)
return 0;
/* Something went wrong. Close down and go home. */
_rmt_shutdown (handle, EIO);
return -1;
}
static char *
get_status_string (int handle, char *command_buffer)
{
char *cursor;
int counter;
/* Read the reply command line. */
for (counter = 0, cursor = command_buffer;
counter < COMMAND_BUFFER_SIZE;
counter++, cursor++)
{
if (safe_read (READ_SIDE (handle), cursor, 1) != 1)
{
_rmt_shutdown (handle, EIO);
return 0;
}
if (*cursor == '\n')
{
*cursor = '\0';
break;
}
}
if (counter == COMMAND_BUFFER_SIZE)
{
_rmt_shutdown (handle, EIO);
return 0;
}
/* Check the return status. */
for (cursor = command_buffer; *cursor; cursor++)
if (*cursor != ' ')
break;
if (*cursor == 'E' || *cursor == 'F')
{
errno = atoi (cursor + 1);
/* Skip the error message line. */
/* FIXME: there is better to do than merely ignoring error messages
coming from the remote end. Translate them, too... */
{
char character;
while (safe_read (READ_SIDE (handle), &character, 1) == 1)
if (character == '\n')
break;
}
if (*cursor == 'F')
_rmt_shutdown (handle, errno);
return 0;
}
/* Check for mis-synced pipes. */
if (*cursor != 'A')
{
_rmt_shutdown (handle, EIO);
return 0;
}
/* Got an `A' (success) response. */
return cursor + 1;
}
/* Read and return the status from remote tape connection HANDLE. If
an error occurred, return -1 and set errno. */
static long
get_status (int handle)
{
char command_buffer[COMMAND_BUFFER_SIZE];
const char *status = get_status_string (handle, command_buffer);
return status ? atol (status) : -1L;
}
static off_t
get_status_off (int handle)
{
char command_buffer[COMMAND_BUFFER_SIZE];
const char *status = get_status_string (handle, command_buffer);
if (! status)
return -1;
else
{
/* Parse status, taking care to check for overflow.
We can't use standard functions,
since off_t might be longer than long. */
off_t count = 0;
int negative;
for (; *status == ' ' || *status == '\t'; status++)
continue;
negative = *status == '-';
status += negative || *status == '+';
for (;;)
{
int digit = *status++ - '0';
if (9 < (unsigned) digit)
break;
else
{
off_t c10 = 10 * count;
off_t nc = negative ? c10 - digit : c10 + digit;
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
return -1;
count = nc;
}
}
return count;
}
}
#if WITH_REXEC
/* Execute /etc/rmt as user USER on remote system HOST using rexec.
Return a file descriptor of a bidirectional socket for stdin and
stdout. If USER is zero, use the current username.
By default, this code is not used, since it requires that the user
have a .netrc file in his/her home directory, or that the
application designer be willing to have rexec prompt for login and
password info. This may be unacceptable, and .rhosts files for use
with rsh are much more common on BSD systems. */
static int
_rmt_rexec (char *host, char *user)
{
int saved_stdin = dup (STDIN_FILENO);
int saved_stdout = dup (STDOUT_FILENO);
struct servent *rexecserv;
int result;
/* When using cpio -o < filename, stdin is no longer the tty. But the
rexec subroutine reads the login and the passwd on stdin, to allow
remote execution of the command. So, reopen stdin and stdout on
/dev/tty before the rexec and give them back their original value
after. */
if (! freopen ("/dev/tty", "r", stdin))
freopen ("/dev/null", "r", stdin);
if (! freopen ("/dev/tty", "w", stdout))
freopen ("/dev/null", "w", stdout);
if (rexecserv = getservbyname ("exec", "tcp"), !rexecserv)
error (EXIT_ON_EXEC_ERROR, 0, _("exec/tcp: Service not available"));
result = rexec (&host, rexecserv->s_port, user, 0, "/etc/rmt", 0);
if (fclose (stdin) == EOF)
error (0, errno, _("stdin"));
fdopen (saved_stdin, "r");
if (fclose (stdout) == EOF)
error (0, errno, _("stdout"));
fdopen (saved_stdout, "w");
return result;
}
#endif /* WITH_REXEC */
/* Place into BUF a string representing OFLAG, which must be suitable
as argument 2 of `open'. BUF must be large enough to hold the
result. This function should generate a string that decode_oflag
can parse. */
static void
encode_oflag (char *buf, int oflag)
{
sprintf (buf, "%d ", oflag);
switch (oflag & O_ACCMODE)
{
case O_RDONLY: strcat (buf, "O_RDONLY"); break;
case O_RDWR: strcat (buf, "O_RDWR"); break;
case O_WRONLY: strcat (buf, "O_WRONLY"); break;
default: abort ();
}
#ifdef O_APPEND
if (oflag & O_APPEND) strcat (buf, "|O_APPEND");
#endif
if (oflag & O_CREAT) strcat (buf, "|O_CREAT");
#ifdef O_DSYNC
if (oflag & O_DSYNC) strcat (buf, "|O_DSYNC");
#endif
if (oflag & O_EXCL) strcat (buf, "|O_EXCL");
#ifdef O_LARGEFILE
if (oflag & O_LARGEFILE) strcat (buf, "|O_LARGEFILE");
#endif
#ifdef O_NOCTTY
if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
#endif
#ifdef O_NONBLOCK
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
#endif
#ifdef O_RSYNC
if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
#endif
#ifdef O_SYNC
if (oflag & O_SYNC) strcat (buf, "|O_SYNC");
#endif
if (oflag & O_TRUNC) strcat (buf, "|O_TRUNC");
}
/* Open a file (a magnetic tape device?) on the system specified in
PATH, as the given user. PATH has the form `[USER@]HOST:FILE'.
OPEN_MODE is O_RDONLY, O_WRONLY, etc. If successful, return the
remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On
error, return -1. */
int
rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
{
int remote_pipe_number; /* pseudo, biased file descriptor */
char *path_copy ; /* copy of path string */
char *remote_host; /* remote host name */
char *remote_file; /* remote file name (often a device) */
char *remote_user; /* remote user name */
/* Find an unused pair of file descriptors. */
for (remote_pipe_number = 0;
remote_pipe_number < MAXUNIT;
remote_pipe_number++)
if (READ_SIDE (remote_pipe_number) == -1
&& WRITE_SIDE (remote_pipe_number) == -1)
break;
if (remote_pipe_number == MAXUNIT)
{
errno = EMFILE;
return -1;
}
/* Pull apart the system and device, and optional user. */
{
char *cursor;
path_copy = xstrdup (path);
remote_host = path_copy;
remote_user = 0;
remote_file = 0;
for (cursor = path_copy; *cursor; cursor++)
switch (*cursor)
{
default:
break;
case '\n':
/* Do not allow newlines in the path, since the protocol
uses newline delimiters. */
free (path_copy);
errno = ENOENT;
return -1;
case '@':
if (!remote_user)
{
remote_user = remote_host;
*cursor = '\0';
remote_host = cursor + 1;
}
break;
case ':':
if (!remote_file)
{
*cursor = '\0';
remote_file = cursor + 1;
}
break;
}
}
/* FIXME: Should somewhat validate the decoding, here. */
if (remote_user && *remote_user == '\0')
remote_user = 0;
#if WITH_REXEC
/* Execute the remote command using rexec. */
READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
if (READ_SIDE (remote_pipe_number) < 0)
{
int e = errno;
free (path_copy);
errno = e;
return -1;
}
WRITE_SIDE (remote_pipe_number) = READ_SIDE (remote_pipe_number);
#else /* not WITH_REXEC */
{
const char *remote_shell_basename;
pid_t status;
/* Identify the remote command to be executed. */
if (!remote_shell)
{
#ifdef REMOTE_SHELL
remote_shell = REMOTE_SHELL;
#else
free (path_copy);
errno = EIO;
return -1;
#endif
}
remote_shell_basename = base_name (remote_shell);
/* Set up the pipes for the `rsh' command, and fork. */
if (pipe (to_remote[remote_pipe_number]) == -1
|| pipe (from_remote[remote_pipe_number]) == -1)
{
int e = errno;
free (path_copy);
errno = e;
return -1;
}
status = fork ();
if (status == -1)
{
int e = errno;
free (path_copy);
errno = e;
return -1;
}
if (status == 0)
{
/* Child. */
close (STDIN_FILENO);
dup (to_remote[remote_pipe_number][PREAD]);
close (to_remote[remote_pipe_number][PREAD]);
close (to_remote[remote_pipe_number][PWRITE]);
close (STDOUT_FILENO);
dup (from_remote[remote_pipe_number][PWRITE]);
close (from_remote[remote_pipe_number][PREAD]);
close (from_remote[remote_pipe_number][PWRITE]);
sys_reset_uid_gid ();
if (remote_user)
execl (remote_shell, remote_shell_basename, remote_host,
"-l", remote_user, "/etc/rmt", (char *) 0);
else
execl (remote_shell, remote_shell_basename, remote_host,
"/etc/rmt", (char *) 0);
/* Bad problems if we get here. */
/* In a previous version, _exit was used here instead of exit. */
error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell"));
}
/* Parent. */
close (from_remote[remote_pipe_number][PWRITE]);
close (to_remote[remote_pipe_number][PREAD]);
}
#endif /* not WITH_REXEC */
/* Attempt to open the tape device. */
{
size_t remote_file_len = strlen (remote_file);
char *command_buffer = xmalloc (remote_file_len + 1000);
sprintf (command_buffer, "O%s\n", remote_file);
encode_oflag (command_buffer + remote_file_len + 2, open_mode);
strcat (command_buffer, "\n");
if (do_command (remote_pipe_number, command_buffer) == -1
|| get_status (remote_pipe_number) == -1)
{
int e = errno;
free (command_buffer);
free (path_copy);
_rmt_shutdown (remote_pipe_number, e);
return -1;
}
free (command_buffer);
}
free (path_copy);
return remote_pipe_number + bias;
}
/* Close remote tape connection HANDLE and shut down. Return 0 if
successful, -1 on error. */
int
rmt_close__ (int handle)
{
int status;
if (do_command (handle, "C\n") == -1)
return -1;
status = get_status (handle);
_rmt_shutdown (handle, errno);
return status;
}
/* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE.
Return the number of bytes read on success, -1 on error. */
ssize_t
rmt_read__ (int handle, char *buffer, size_t length)
{
char command_buffer[COMMAND_BUFFER_SIZE];
ssize_t status, rlen;
size_t counter;
sprintf (command_buffer, "R%lu\n", (unsigned long) length);
if (do_command (handle, command_buffer) == -1
|| (status = get_status (handle)) == -1)
return -1;
for (counter = 0; counter < status; counter += rlen, buffer += rlen)
{
rlen = safe_read (READ_SIDE (handle), buffer, status - counter);
if (rlen <= 0)
{
_rmt_shutdown (handle, EIO);
return -1;
}
}
return status;
}
/* Write LENGTH bytes from BUFFER to remote tape connection HANDLE.
Return the number of bytes written on success, -1 on error. */
ssize_t
rmt_write__ (int handle, char *buffer, size_t length)
{
char command_buffer[COMMAND_BUFFER_SIZE];
RETSIGTYPE (*pipe_handler) ();
size_t written;
sprintf (command_buffer, "W%lu\n", (unsigned long) length);
if (do_command (handle, command_buffer) == -1)
return -1;
pipe_handler = signal (SIGPIPE, SIG_IGN);
written = full_write (WRITE_SIDE (handle), buffer, length);
signal (SIGPIPE, pipe_handler);
if (written == length)
return get_status (handle);
/* Write error. */
_rmt_shutdown (handle, EIO);
return -1;
}
/* Perform an imitation lseek operation on remote tape connection
HANDLE. Return the new file offset if successful, -1 if on error. */
off_t
rmt_lseek__ (int handle, off_t offset, int whence)
{
char command_buffer[COMMAND_BUFFER_SIZE];
char operand_buffer[UINTMAX_STRSIZE_BOUND];
uintmax_t u = offset < 0 ? - (uintmax_t) offset : (uintmax_t) offset;
char *p = operand_buffer + sizeof operand_buffer;
do
*--p = '0' + (int) (u % 10);
while ((u /= 10) != 0);
if (offset < 0)
*--p = '-';
switch (whence)
{
case SEEK_SET: whence = 0; break;
case SEEK_CUR: whence = 1; break;
case SEEK_END: whence = 2; break;
default: abort ();
}
sprintf (command_buffer, "L%s\n%d\n", p, whence);
if (do_command (handle, command_buffer) == -1)
return -1;
return get_status_off (handle);
}
/* Perform a raw tape operation on remote tape connection HANDLE.
Return the results of the ioctl, or -1 on error. */
int
rmt_ioctl__ (int handle, int operation, char *argument)
{
switch (operation)
{
default:
errno = EOPNOTSUPP;
return -1;
#ifdef MTIOCTOP
case MTIOCTOP:
{
char command_buffer[COMMAND_BUFFER_SIZE];
char operand_buffer[UINTMAX_STRSIZE_BOUND];
uintmax_t u = (((struct mtop *) argument)->mt_count < 0
? - (uintmax_t) ((struct mtop *) argument)->mt_count
: (uintmax_t) ((struct mtop *) argument)->mt_count);
char *p = operand_buffer + sizeof operand_buffer;
do
*--p = '0' + (int) (u % 10);
while ((u /= 10) != 0);
if (((struct mtop *) argument)->mt_count < 0)
*--p = '-';
/* MTIOCTOP is the easy one. Nothing is transferred in binary. */
sprintf (command_buffer, "I%d\n%s\n",
((struct mtop *) argument)->mt_op, p);
if (do_command (handle, command_buffer) == -1)
return -1;
return get_status (handle);
}
#endif /* MTIOCTOP */
#ifdef MTIOCGET
case MTIOCGET:
{
ssize_t status;
ssize_t counter;
/* Grab the status and read it directly into the structure. This
assumes that the status buffer is not padded and that 2 shorts
fit in a long without any word alignment problems; i.e., the
whole struct is contiguous. NOTE - this is probably NOT a good
assumption. */
if (do_command (handle, "S") == -1
|| (status = get_status (handle), status == -1))
return -1;
for (; status > 0; status -= counter, argument += counter)
{
counter = safe_read (READ_SIDE (handle), argument, status);
if (counter <= 0)
{
_rmt_shutdown (handle, EIO);
return -1;
}
}
/* Check for byte position. mt_type (or mt_model) is a small integer
field (normally) so we will check its magnitude. If it is larger
than 256, we will assume that the bytes are swapped and go through
and reverse all the bytes. */
if (((struct mtget *) argument)->MTIO_CHECK_FIELD < 256)
return 0;
for (counter = 0; counter < status; counter += 2)
{
char copy = argument[counter];
argument[counter] = argument[counter + 1];
argument[counter + 1] = copy;
}
return 0;
}
#endif /* MTIOCGET */
}
}

View File

@@ -1,6 +1,6 @@
/* Functions for dealing with sparse files
/* Functions for dealing with sparse files
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2004 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
@@ -16,7 +16,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include <quotearg.h>
#include "common.h"
@@ -33,12 +33,14 @@ struct tar_sparse_optab
{
bool (*init) (struct tar_sparse_file *);
bool (*done) (struct tar_sparse_file *);
bool (*sparse_member_p) (struct tar_sparse_file *);
bool (*dump_header) (struct tar_sparse_file *);
bool (*fixup_header) (struct tar_sparse_file *);
bool (*decode_header) (struct tar_sparse_file *);
bool (*scan_block) (struct tar_sparse_file *, enum sparse_scan_state,
void *);
bool (*dump_region) (struct tar_sparse_file *, size_t index);
bool (*extract_region) (struct tar_sparse_file *, size_t index);
bool (*dump_region) (struct tar_sparse_file *, size_t);
bool (*extract_region) (struct tar_sparse_file *, size_t);
};
struct tar_sparse_file
@@ -52,6 +54,14 @@ struct tar_sparse_file
reqiure */
};
static bool
tar_sparse_member_p (struct tar_sparse_file *file)
{
if (file->optab->sparse_member_p)
return file->optab->sparse_member_p (file);
return false;
}
static bool
tar_sparse_init (struct tar_sparse_file *file)
{
@@ -79,18 +89,18 @@ tar_sparse_scan (struct tar_sparse_file *file, enum sparse_scan_state state,
}
static bool
tar_sparse_dump_region (struct tar_sparse_file *file, size_t index)
tar_sparse_dump_region (struct tar_sparse_file *file, size_t i)
{
if (file->optab->dump_region)
return file->optab->dump_region (file, index);
return file->optab->dump_region (file, i);
return false;
}
static bool
tar_sparse_extract_region (struct tar_sparse_file *file, size_t index)
tar_sparse_extract_region (struct tar_sparse_file *file, size_t i)
{
if (file->optab->extract_region)
return file->optab->extract_region (file, index);
return file->optab->extract_region (file, i);
return false;
}
@@ -107,7 +117,15 @@ tar_sparse_decode_header (struct tar_sparse_file *file)
{
if (file->optab->decode_header)
return file->optab->decode_header (file);
return false;
return true;
}
static bool
tar_sparse_fixup_header (struct tar_sparse_file *file)
{
if (file->optab->fixup_header)
return file->optab->fixup_header (file);
return true;
}
@@ -171,13 +189,14 @@ sparse_scan_file (struct tar_sparse_file *file)
return false;
clear_block (buffer);
file->stat_info->sparse_map_size = 0;
file->stat_info->sparse_map_avail = 0;
file->stat_info->archive_file_size = 0;
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
while ((count = safe_read (file->fd, buffer, sizeof buffer)) > 0)
while ((count = safe_read (file->fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
{
/* Analize the block */
if (zero_block_p (buffer, count))
@@ -199,11 +218,11 @@ sparse_scan_file (struct tar_sparse_file *file)
if (!tar_sparse_scan (file, scan_block, buffer))
return false;
}
offset += count;
clear_block (buffer);
}
if (sp.numbytes == 0)
sp.offset = offset;
@@ -237,7 +256,7 @@ sparse_select_optab (struct tar_sparse_file *file)
case STAR_FORMAT:
file->optab = &star_optab;
break;
default:
return false;
}
@@ -245,28 +264,28 @@ sparse_select_optab (struct tar_sparse_file *file)
}
static bool
sparse_dump_region (struct tar_sparse_file *file, size_t index)
sparse_dump_region (struct tar_sparse_file *file, size_t i)
{
union block *blk;
off_t bytes_left = file->stat_info->sparse_map[index].numbytes;
if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
off_t bytes_left = file->stat_info->sparse_map[i].numbytes;
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
SEEK_SET))
return false;
while (bytes_left > 0)
{
size_t bufsize = (bytes_left > BLOCKSIZE) ? BLOCKSIZE : bytes_left;
off_t bytes_read;
size_t bytes_read;
blk = find_next_block ();
memset (blk->buffer, 0, BLOCKSIZE);
bytes_read = safe_read (file->fd, blk->buffer, bufsize);
if (bytes_read < 0)
if (bytes_read == SAFE_READ_ERROR)
{
read_diag_details (file->stat_info->orig_file_name,
file->stat_info->sparse_map[index].offset
+ file->stat_info->sparse_map[index].numbytes
file->stat_info->sparse_map[i].offset
+ file->stat_info->sparse_map[i].numbytes
- bytes_left,
bufsize);
return false;
@@ -281,15 +300,15 @@ sparse_dump_region (struct tar_sparse_file *file, size_t index)
}
static bool
sparse_extract_region (struct tar_sparse_file *file, size_t index)
sparse_extract_region (struct tar_sparse_file *file, size_t i)
{
size_t write_size;
if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
SEEK_SET))
return false;
write_size = file->stat_info->sparse_map[index].numbytes;
write_size = file->stat_info->sparse_map[i].numbytes;
if (write_size == 0)
{
@@ -325,12 +344,12 @@ sparse_extract_region (struct tar_sparse_file *file, size_t index)
/* Interface functions */
enum dump_status
sparse_dump_file (int fd, struct tar_stat_info *stat)
sparse_dump_file (int fd, struct tar_stat_info *st)
{
bool rc;
struct tar_sparse_file file;
file.stat_info = stat;
file.stat_info = st;
file.fd = fd;
if (!sparse_select_optab (&file)
@@ -357,21 +376,43 @@ sparse_dump_file (int fd, struct tar_stat_info *stat)
/* Returns true if the file represented by stat is a sparse one */
bool
sparse_file_p (struct tar_stat_info *stat)
sparse_file_p (struct tar_stat_info *st)
{
return (ST_NBLOCKS (stat->stat)
< (stat->stat.st_size / ST_NBLOCKSIZE
+ (stat->stat.st_size % ST_NBLOCKSIZE != 0)));
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)
{
struct tar_sparse_file file;
if (!sparse_select_optab (&file))
return false;
file.stat_info = st;
return tar_sparse_member_p (&file);
}
bool
sparse_fixup_header (struct tar_stat_info *st)
{
struct tar_sparse_file file;
if (!sparse_select_optab (&file))
return false;
file.stat_info = st;
return tar_sparse_fixup_header (&file);
}
enum dump_status
sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size)
sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
{
bool rc = true;
struct tar_sparse_file file;
size_t i;
file.stat_info = stat;
file.stat_info = st;
file.fd = fd;
if (!sparse_select_optab (&file)
@@ -385,25 +426,43 @@ sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size)
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
}
enum dump_status
sparse_skip_file (struct tar_stat_info *st)
{
bool rc = true;
struct tar_sparse_file file;
file.stat_info = st;
file.fd = -1;
if (!sparse_select_optab (&file)
|| !tar_sparse_init (&file))
return dump_status_not_implemented;
rc = tar_sparse_decode_header (&file);
skip_file (file.stat_info->archive_file_size);
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
}
static char diff_buffer[BLOCKSIZE];
static bool
check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
{
if (!lseek_or_error (file, beg, SEEK_SET))
return false;
while (beg < end)
{
size_t bytes_read;
size_t rdsize = end - beg;
if (rdsize > BLOCKSIZE)
rdsize = BLOCKSIZE;
clear_block (diff_buffer);
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
if (bytes_read < 0)
if (bytes_read == SAFE_READ_ERROR)
{
read_diag_details (file->stat_info->orig_file_name,
beg,
@@ -423,19 +482,19 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
}
static bool
check_data_region (struct tar_sparse_file *file, size_t index)
check_data_region (struct tar_sparse_file *file, size_t i)
{
size_t size_left;
if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
SEEK_SET))
return false;
size_left = file->stat_info->sparse_map[index].numbytes;
size_left = file->stat_info->sparse_map[i].numbytes;
while (size_left > 0)
{
size_t bytes_read;
size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
union block *blk = find_next_block ();
if (!blk)
{
@@ -444,11 +503,11 @@ check_data_region (struct tar_sparse_file *file, size_t index)
}
set_next_block_after (blk);
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
if (bytes_read < 0)
if (bytes_read == SAFE_READ_ERROR)
{
read_diag_details (file->stat_info->orig_file_name,
file->stat_info->sparse_map[index].offset
+ file->stat_info->sparse_map[index].numbytes
file->stat_info->sparse_map[i].offset
+ file->stat_info->sparse_map[i].numbytes
- size_left,
rdsize);
return false;
@@ -465,14 +524,14 @@ check_data_region (struct tar_sparse_file *file, size_t index)
}
bool
sparse_diff_file (int fd, struct tar_stat_info *stat)
sparse_diff_file (int fd, struct tar_stat_info *st)
{
bool rc = true;
struct tar_sparse_file file;
size_t i;
off_t offset = 0;
file.stat_info = stat;
file.stat_info = st;
file.fd = fd;
if (!sparse_select_optab (&file)
@@ -496,14 +555,14 @@ sparse_diff_file (int fd, struct tar_stat_info *stat)
return rc;
}
/* Old GNU Format. The sparse file information is stored in the
oldgnu_header in the following manner:
The header is marked with type 'S'. Its `size' field contains
the cumulative size of all non-empty blocks of the file. The
actual file size is stored in `realsize' member of oldgnu_header.
The map of the file is stored in a list of `struct sparse'.
Each struct contains offset to the block of data and its
size (both as octal numbers). The first file header contains
@@ -522,8 +581,14 @@ enum oldgnu_add_status
add_fail
};
static bool
oldgnu_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
{
return current_header->header.typeflag == GNUTYPE_SPARSE;
}
/* Add a sparse item to the sparse file and its obstack */
static enum oldgnu_add_status
static enum oldgnu_add_status
oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
{
struct sp_array sp;
@@ -541,8 +606,18 @@ oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
return add_ok;
}
/* Convert old GNU format sparse data to internal representation
FIXME: Clubbers current_header! */
static bool
oldgnu_fixup_header (struct tar_sparse_file *file)
{
/* NOTE! st_size was initialized from the header
which actually contains archived size. The following fixes it */
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
file->stat_info->stat.st_size =
OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
return true;
}
/* Convert old GNU format sparse data to internal representation */
static bool
oldgnu_get_sparse_info (struct tar_sparse_file *file)
{
@@ -550,14 +625,8 @@ oldgnu_get_sparse_info (struct tar_sparse_file *file)
union block *h = current_header;
int ext_p;
static enum oldgnu_add_status rc;
/* FIXME: note this! st_size was initialized from the header
which actually contains archived size. The following fixes it */
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
file->stat_info->stat.st_size =
OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
file->stat_info->sparse_map_size = 0;
file->stat_info->sparse_map_avail = 0;
for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
{
rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
@@ -608,7 +677,7 @@ oldgnu_dump_header (struct tar_sparse_file *file)
off_t block_ordinal = current_block_ordinal ();
union block *blk;
size_t i;
blk = start_header (file->stat_info);
blk->header.typeflag = GNUTYPE_SPARSE;
if (file->stat_info->sparse_map_avail > SPARSES_IN_OLDGNU_HEADER)
@@ -625,7 +694,7 @@ oldgnu_dump_header (struct tar_sparse_file *file)
SPARSES_IN_OLDGNU_HEADER);
blk->oldgnu_header.isextended = i < file->stat_info->sparse_map_avail;
finish_header (file->stat_info, blk, block_ordinal);
while (i < file->stat_info->sparse_map_avail)
{
blk = find_next_block ();
@@ -645,7 +714,9 @@ oldgnu_dump_header (struct tar_sparse_file *file)
static struct tar_sparse_optab oldgnu_optab = {
NULL, /* No init function */
NULL, /* No done function */
oldgnu_sparse_member_p,
oldgnu_dump_header,
oldgnu_fixup_header,
oldgnu_get_sparse_info,
NULL, /* No scan_block function */
sparse_dump_region,
@@ -655,8 +726,24 @@ static struct tar_sparse_optab oldgnu_optab = {
/* Star */
/* Convert STAR format sparse data to internal representation
FIXME: Clubbers current_header! */
static bool
star_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
{
return current_header->header.typeflag == GNUTYPE_SPARSE;
}
static bool
star_fixup_header (struct tar_sparse_file *file)
{
/* NOTE! st_size was initialized from the header
which actually contains archived size. The following fixes it */
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
file->stat_info->stat.st_size =
OFF_FROM_HEADER (current_header->star_in_header.realsize);
return true;
}
/* Convert STAR format sparse data to internal representation */
static bool
star_get_sparse_info (struct tar_sparse_file *file)
{
@@ -664,14 +751,8 @@ star_get_sparse_info (struct tar_sparse_file *file)
union block *h = current_header;
int ext_p;
static enum oldgnu_add_status rc;
/* FIXME: note this! st_size was initialized from the header
which actually contains archived size. The following fixes it */
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
file->stat_info->stat.st_size =
OFF_FROM_HEADER (current_header->star_in_header.realsize);
file->stat_info->sparse_map_size = 0;
file->stat_info->sparse_map_avail = 0;
if (h->star_in_header.prefix[0] == '\0'
&& h->star_in_header.sp[0].offset[10] != '\0')
@@ -714,10 +795,12 @@ star_get_sparse_info (struct tar_sparse_file *file)
static struct tar_sparse_optab star_optab = {
NULL, /* No init function */
NULL, /* No done function */
star_sparse_member_p,
NULL,
star_fixup_header,
star_get_sparse_info,
NULL, /* No scan_block function */
NULL, /* No dump region function */
NULL, /* No dump region function */
sparse_extract_region,
};
@@ -733,6 +816,12 @@ static struct tar_sparse_optab star_optab = {
end repeat
*/
static bool
pax_sparse_member_p (struct tar_sparse_file *file)
{
return file->stat_info->archive_file_size != file->stat_info->stat.st_size;
}
static bool
pax_dump_header (struct tar_sparse_file *file)
{
@@ -748,7 +837,7 @@ pax_dump_header (struct tar_sparse_file *file)
xheader_store ("GNU.sparse.offset", file->stat_info, &i);
xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
}
blk = start_header (file->stat_info);
/* Store the effective (shrunken) file size */
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
@@ -756,21 +845,13 @@ pax_dump_header (struct tar_sparse_file *file)
return true;
}
static bool
pax_decode_header (struct tar_sparse_file *file)
{
/* Restore actual size */
size_t s = file->stat_info->archive_file_size;
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
file->stat_info->stat.st_size = s;
return true;
}
static struct tar_sparse_optab pax_optab = {
NULL, /* No init function */
NULL, /* No done function */
pax_sparse_member_p,
pax_dump_header,
pax_decode_header,
NULL, /* No decode_header function */
NULL, /* No fixup_header function */
NULL, /* No scan_block function */
sparse_dump_region,
sparse_extract_region,

View File

@@ -1,6 +1,6 @@
/* System-dependent calls for tar.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2004 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
@@ -16,53 +16,40 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include "common.h"
#include "rmt.h"
#include <rmt.h>
#include <signal.h>
void
sys_stat_nanoseconds(struct tar_stat_info *stat)
sys_stat_nanoseconds (struct tar_stat_info *st)
{
#if defined(HAVE_STRUCT_STAT_ST_SPARE1)
stat->atime_nsec = stat->stat.st_spare1 * 1000;
stat->mtime_nsec = stat->stat.st_spare2 * 1000;
stat->ctime_nsec = stat->stat.st_spare3 * 1000;
st->atime_nsec = st->stat.st_spare1 * 1000;
st->mtime_nsec = st->stat.st_spare2 * 1000;
st->ctime_nsec = st->stat.st_spare3 * 1000;
#elif defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
stat->atime_nsec = stat->stat.st_atim.tv_nsec;
stat->mtime_nsec = stat->stat.st_mtim.tv_nsec;
stat->ctime_nsec = stat->stat.st_ctim.tv_nsec;
st->atime_nsec = st->stat.st_atim.tv_nsec;
st->mtime_nsec = st->stat.st_mtim.tv_nsec;
st->ctime_nsec = st->stat.st_ctim.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
stat->atime_nsec = stat->stat.st_atimespec.tv_nsec;
stat->mtime_nsec = stat->stat.st_mtimespec.tv_nsec;
stat->ctime_nsec = stat->stat.st_ctimespec.tv_nsec;
st->atime_nsec = st->stat.st_atimespec.tv_nsec;
st->mtime_nsec = st->stat.st_mtimespec.tv_nsec;
st->ctime_nsec = st->stat.st_ctimespec.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
stat->atime_nsec = stat->stat.st_atimensec;
stat->mtime_nsec = stat->stat.st_mtimensec;
stat->ctime_nsec = stat->stat.st_ctimensec;
st->atime_nsec = st->stat.st_atimensec;
st->mtime_nsec = st->stat.st_mtimensec;
st->ctime_nsec = st->stat.st_ctimensec;
#else
stat->atime_nsec = stat->mtime_nsec = stat->ctime_nsec = 0;
#endif
}
int
sys_utimes(char *file_name, struct timeval tvp[3])
{
#ifdef HAVE_UTIMES
return utimes (file_name, tvp);
#else
struct utimbuf utimbuf;
utimbuf.actime = tvp[0].tv_sec;
utimbuf.modtime = tvp[1].tv_sec;
return utime (file_name, &utimbuf);
st->atime_nsec = st->mtime_nsec = st->ctime_nsec = 0;
#endif
}
#if MSDOS
bool
sys_get_archive_stat ()
sys_get_archive_stat (void)
{
return 0;
}
@@ -74,12 +61,12 @@ sys_file_is_archive (struct tar_stat_info *p)
}
void
sys_save_archive_dev_ino ()
sys_save_archive_dev_ino (void)
{
}
void
sys_detect_dev_null_output ()
sys_detect_dev_null_output (void)
{
static char const dev_null[] = "nul";
@@ -88,7 +75,7 @@ sys_detect_dev_null_output ()
}
void
sys_drain_input_pipe ()
sys_drain_input_pipe (void)
{
}
@@ -98,7 +85,7 @@ sys_wait_for_child (pid_t child_pid)
}
void
sys_spawn_shell ()
sys_spawn_shell (void)
{
spawnl (P_WAIT, getenv ("COMSPEC"), "-", 0);
}
@@ -131,26 +118,10 @@ sys_truncate (int fd)
return write (fd, "", 0);
}
void
sys_reset_uid_gid ()
{
}
ssize_t
size_t
sys_write_archive_buffer (void)
{
ssize_t status;
ssize_t written = 0;
while (0 <= (status = full_write (archive, record_start->buffer + written,
record_size - written)))
{
written += status;
if (written == record_size)
break;
}
return written ? written : status;
return full_write (archive, record_start->buffer, record_size);
}
/* Set ARCHIVE for writing, then compressing an archive. */
@@ -174,11 +145,11 @@ extern union block *record_start; /* FIXME */
static struct stat archive_stat; /* stat block for archive file */
bool
sys_get_archive_stat ()
sys_get_archive_stat (void)
{
return fstat (archive, &archive_stat) == 0;
}
bool
sys_file_is_archive (struct tar_stat_info *p)
{
@@ -187,7 +158,7 @@ sys_file_is_archive (struct tar_stat_info *p)
/* Save archive file inode and device numbers */
void
sys_save_archive_dev_ino ()
sys_save_archive_dev_ino (void)
{
if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
{
@@ -200,7 +171,7 @@ sys_save_archive_dev_ino ()
/* Detect if outputting to "/dev/null". */
void
sys_detect_dev_null_output ()
sys_detect_dev_null_output (void)
{
static char const dev_null[] = "/dev/null";
struct stat dev_null_stat;
@@ -219,12 +190,15 @@ sys_detect_dev_null_output ()
work to do, we might have to revise this area in such time. */
void
sys_drain_input_pipe ()
sys_drain_input_pipe (void)
{
size_t r;
if (access_mode == ACCESS_READ
&& ! _isrmt (archive)
&& (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
while (rmtread (archive, record_start->buffer, record_size) > 0)
while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
&& r != SAFE_READ_ERROR)
continue;
}
@@ -252,7 +226,7 @@ sys_wait_for_child (pid_t child_pid)
}
void
sys_spawn_shell ()
sys_spawn_shell (void)
{
pid_t child;
const char *shell = getenv ("SHELL");
@@ -302,13 +276,6 @@ sys_truncate (int fd)
return pos < 0 ? -1 : ftruncate (fd, pos);
}
void
sys_reset_uid_gid ()
{
setuid (getuid ());
setgid (getgid ());
}
/* Return nonzero if NAME is the name of a regular file, or if the file
does not exist (so it would be created as a regular file). */
static int
@@ -322,24 +289,10 @@ is_regular_file (const char *name)
return errno == ENOENT;
}
ssize_t
size_t
sys_write_archive_buffer (void)
{
ssize_t status;
ssize_t written = 0;
while (0 <= (status = rmtwrite (archive, record_start->buffer + written,
record_size - written)))
{
written += status;
if (written == record_size
|| _isrmt (archive)
|| ! (S_ISFIFO (archive_stat.st_mode)
|| S_ISSOCK (archive_stat.st_mode)))
break;
}
return written ? written : status;
return rmtwrite (archive, record_start->buffer, record_size);
}
#define PREAD 0 /* read file descriptor from pipe() */
@@ -471,7 +424,7 @@ sys_child_open_for_compress (void)
while (1)
{
ssize_t status = 0;
size_t status = 0;
char *cursor;
size_t length;
@@ -484,13 +437,12 @@ sys_child_open_for_compress (void)
size_t size = record_size - length;
status = safe_read (STDIN_FILENO, cursor, size);
if (status <= 0)
if (status == SAFE_READ_ERROR)
read_fatal (use_compress_program_option);
if (status == 0)
break;
}
if (status < 0)
read_fatal (use_compress_program_option);
/* Copy the record. */
if (status == 0)
@@ -553,7 +505,6 @@ sys_child_open_for_uncompress (void)
{
/* The parent tar is still here! Just clean up. */
read_full_records_option = 1;
archive = parent_pipe[PREAD];
xclose (parent_pipe[PWRITE]);
return child_pid;
@@ -628,13 +579,13 @@ sys_child_open_for_uncompress (void)
char *cursor;
size_t maximum;
size_t count;
ssize_t status;
size_t status;
clear_read_error_count ();
error_loop:
status = rmtread (archive, record_start->buffer, record_size);
if (status < 0)
if (status == SAFE_READ_ERROR)
{
archive_read_error ();
goto error_loop;

View File

@@ -1,513 +0,0 @@
/* System dependent definitions for GNU tar.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <alloca.h>
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
# define __attribute__(Spec) /* empty */
# endif
#endif
#include <sys/types.h>
#include <ctype.h>
/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
as an argument to <ctype.h> macros like `isspace'. */
#if STDC_HEADERS
# define IN_CTYPE_DOMAIN(c) 1
#else
# define IN_CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177)
#endif
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
#define ISODIGIT(c) ((unsigned) (c) - '0' <= 7)
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
/* Declare string and memory handling routines. Take care that an ANSI
string.h and pre-ANSI memory.h might conflict, and that memory.h and
strings.h conflict on some systems. */
#if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
# if !STDC_HEADERS && HAVE_MEMORY_H
# include <memory.h>
# endif
#else
# include <strings.h>
# ifndef strchr
# define strchr index
# endif
# ifndef strrchr
# define strrchr rindex
# endif
# ifndef memcpy
# define memcpy(d, s, n) bcopy ((char const *) (s), (char *) (d), n)
# endif
# ifndef memcmp
# define memcmp(a, b, n) bcmp ((char const *) (a), (char const *) (b), n)
# endif
#endif
/* Declare errno. */
#include <errno.h>
#ifndef errno
extern int errno;
#endif
/* Declare open parameters. */
#if HAVE_FCNTL_H
# include <fcntl.h>
#else
# include <sys/file.h>
#endif
/* Pick only one of the next three: */
#ifndef O_RDONLY
# define O_RDONLY 0 /* only allow read */
#endif
#ifndef O_WRONLY
# define O_WRONLY 1 /* only allow write */
#endif
#ifndef O_RDWR
# define O_RDWR 2 /* both are allowed */
#endif
#ifndef O_ACCMODE
# define O_ACCMODE (O_RDONLY | O_RDWR | O_WRONLY)
#endif
/* The rest can be OR-ed in to the above: */
#ifndef O_CREAT
# define O_CREAT 8 /* create file if needed */
#endif
#ifndef O_EXCL
# define O_EXCL 16 /* file cannot already exist */
#endif
#ifndef O_TRUNC
# define O_TRUNC 32 /* truncate file on open */
#endif
/* MS-DOG forever, with my love! */
#ifndef O_BINARY
# define O_BINARY 0
#endif
/* Declare file status routines and bits. */
#include <sys/stat.h>
#if !HAVE_LSTAT && !defined lstat
# define lstat stat
#endif
#if STX_HIDDEN && !_LARGE_FILES /* AIX */
# ifdef stat
# undef stat
# endif
# define stat(path, buf) statx (path, buf, STATSIZE, STX_HIDDEN)
# ifdef lstat
# undef lstat
# endif
# define lstat(path, buf) statx (path, buf, STATSIZE, STX_HIDDEN | STX_LINK)
#endif
#if STAT_MACROS_BROKEN
# undef S_ISBLK
# undef S_ISCHR
# undef S_ISCTG
# undef S_ISDIR
# undef S_ISFIFO
# undef S_ISLNK
# undef S_ISREG
# undef S_ISSOCK
#endif
/* On MSDOS, there are missing things from <sys/stat.h>. */
#if MSDOS
# define S_ISUID 0
# define S_ISGID 0
# define S_ISVTX 0
#endif
#ifndef S_ISDIR
# define S_ISDIR(Mode) (((Mode) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISREG
# define S_ISREG(Mode) (((Mode) & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISBLK
# ifdef S_IFBLK
# define S_ISBLK(Mode) (((Mode) & S_IFMT) == S_IFBLK)
# else
# define S_ISBLK(Mode) 0
# endif
#endif
#ifndef S_ISCHR
# ifdef S_IFCHR
# define S_ISCHR(Mode) (((Mode) & S_IFMT) == S_IFCHR)
# else
# define S_ISCHR(Mode) 0
# endif
#endif
#ifndef S_ISCTG
# ifdef S_IFCTG
# define S_ISCTG(Mode) (((Mode) & S_IFMT) == S_IFCTG)
# else
# define S_ISCTG(Mode) 0
# endif
#endif
#ifndef S_ISDOOR
# define S_ISDOOR(Mode) 0
#endif
#ifndef S_ISFIFO
# ifdef S_IFIFO
# define S_ISFIFO(Mode) (((Mode) & S_IFMT) == S_IFIFO)
# else
# define S_ISFIFO(Mode) 0
# endif
#endif
#ifndef S_ISLNK
# ifdef S_IFLNK
# define S_ISLNK(Mode) (((Mode) & S_IFMT) == S_IFLNK)
# else
# define S_ISLNK(Mode) 0
# endif
#endif
#ifndef S_ISSOCK
# ifdef S_IFSOCK
# define S_ISSOCK(Mode) (((Mode) & S_IFMT) == S_IFSOCK)
# else
# define S_ISSOCK(Mode) 0
# endif
#endif
#if !HAVE_MKFIFO && !defined mkfifo && defined S_IFIFO
# define mkfifo(Path, Mode) (mknod (Path, (Mode) | S_IFIFO, 0))
#endif
#ifndef S_ISUID
# define S_ISUID 0004000
#endif
#ifndef S_ISGID
# define S_ISGID 0002000
#endif
#ifndef S_ISVTX
# define S_ISVTX 0001000
#endif
#ifndef S_IRUSR
# define S_IRUSR 0000400
#endif
#ifndef S_IWUSR
# define S_IWUSR 0000200
#endif
#ifndef S_IXUSR
# define S_IXUSR 0000100
#endif
#ifndef S_IRGRP
# define S_IRGRP 0000040
#endif
#ifndef S_IWGRP
# define S_IWGRP 0000020
#endif
#ifndef S_IXGRP
# define S_IXGRP 0000010
#endif
#ifndef S_IROTH
# define S_IROTH 0000004
#endif
#ifndef S_IWOTH
# define S_IWOTH 0000002
#endif
#ifndef S_IXOTH
# define S_IXOTH 0000001
#endif
#define MODE_WXUSR (S_IWUSR | S_IXUSR)
#define MODE_R (S_IRUSR | S_IRGRP | S_IROTH)
#define MODE_RW (S_IWUSR | S_IWGRP | S_IWOTH | MODE_R)
#define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
#ifndef SEEK_CUR
# define SEEK_CUR 1
#endif
#ifndef SEEK_END
# define SEEK_END 2
#endif
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
/* Declare make device, major and minor. Since major is a function on
SVR4, we have to resort to GOT_MAJOR instead of just testing if
major is #define'd. */
#if MAJOR_IN_MKDEV
# include <sys/mkdev.h>
# define GOT_MAJOR
#endif
#if MAJOR_IN_SYSMACROS
# include <sys/sysmacros.h>
# define GOT_MAJOR
#endif
/* Some <sys/types.h> defines the macros. */
#ifdef major
# define GOT_MAJOR
#endif
#ifndef GOT_MAJOR
# if MSDOS
# define major(Device) (Device)
# define minor(Device) (Device)
# define makedev(Major, Minor) (((Major) << 8) | (Minor))
# define GOT_MAJOR
# endif
#endif
/* For HP-UX before HP-UX 8, major/minor are not in <sys/sysmacros.h>. */
#ifndef GOT_MAJOR
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
# include <sys/mknod.h>
# define GOT_MAJOR
# endif
#endif
#ifndef GOT_MAJOR
# define major(Device) (((Device) >> 8) & 0xff)
# define minor(Device) ((Device) & 0xff)
# define makedev(Major, Minor) (((Major) << 8) | (Minor))
#endif
#undef GOT_MAJOR
/* Declare wait status. */
#if HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifndef WEXITSTATUS
# define WEXITSTATUS(s) (((s) >> 8) & 0xff)
#endif
#ifndef WIFSIGNALED
# define WIFSIGNALED(s) (((s) & 0xffff) - 1 < (unsigned) 0xff)
#endif
#ifndef WTERMSIG
# define WTERMSIG(s) ((s) & 0x7f)
#endif
/* FIXME: It is wrong to use BLOCKSIZE for buffers when the logical block
size is greater than 512 bytes; so ST_BLKSIZE code below, in preparation
for some cleanup in this area, later. */
/* Extract or fake data from a `struct stat'. ST_BLKSIZE gives the
optimal I/O blocksize for the file, in bytes. Some systems, like
Sequents, return st_blksize of 0 on pipes. */
#define DEFAULT_ST_BLKSIZE 512
#if !HAVE_ST_BLKSIZE
# define ST_BLKSIZE(Statbuf) DEFAULT_ST_BLKSIZE
#else
# define ST_BLKSIZE(Statbuf) \
((Statbuf).st_blksize > 0 ? (Statbuf).st_blksize : DEFAULT_ST_BLKSIZE)
#endif
/* Extract or fake data from a `struct stat'. ST_NBLOCKS gives the
number of ST_NBLOCKSIZE-byte blocks in the file (including indirect blocks).
HP-UX counts st_blocks in 1024-byte units,
this loses when mixing HP-UX and BSD filesystems with NFS. AIX PS/2
counts st_blocks in 4K units. */
#if !HAVE_ST_BLOCKS
# if defined(_POSIX_SOURCE) || !defined(BSIZE)
# define ST_NBLOCKS(Statbuf) ((Statbuf).st_size / ST_NBLOCKSIZE + ((Statbuf).st_size % ST_NBLOCKSIZE != 0))
# else
off_t st_blocks ();
# define ST_NBLOCKS(Statbuf) (st_blocks ((Statbuf).st_size))
# endif
#else
# define ST_NBLOCKS(Statbuf) ((Statbuf).st_blocks)
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
# define ST_NBLOCKSIZE 1024
# else
# if defined(_AIX) && defined(_I386)
# define ST_NBLOCKSIZE (4 * 1024)
# endif
# endif
#endif
#ifndef ST_NBLOCKSIZE
#define ST_NBLOCKSIZE 512
#endif
/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses
<sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires
<sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It
seems that the rest use <sys/mtio.h>, which itself requires other files,
depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
#if HAVE_SYS_GENTAPE_H
# include <sys/gentape.h>
#else
# if HAVE_SYS_TAPE_H
# if HAVE_SYS_DEVICE_H
# include <sys/device.h>
# endif
# if HAVE_SYS_BUF_H
# include <sys/buf.h>
# endif
# if HAVE_SYS_TPRINTF_H
# include <sys/tprintf.h>
# endif
# include <sys/tape.h>
# else
# if HAVE_SYS_MTIO_H
# include <sys/ioctl.h>
# if HAVE_SGTTY_H
# include <sgtty.h>
# endif
# if HAVE_SYS_IO_TRIOCTL_H
# include <sys/io/trioctl.h>
# endif
# include <sys/mtio.h>
# endif
# endif
#endif
/* Declare standard functions. */
#if STDC_HEADERS
# include <stdlib.h>
#else
void *malloc ();
char *getenv ();
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#if !defined _POSIX_VERSION && MSDOS
# include <io.h>
#endif
#if WITH_DMALLOC
# undef HAVE_DECL_VALLOC
# define DMALLOC_FUNC_CHECK
# include <dmalloc.h>
#endif
#include <limits.h>
#ifndef MB_LEN_MAX
# define MB_LEN_MAX 1
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
/* These macros work even on ones'-complement hosts (!).
The extra casts work around common compiler bugs. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
#define TYPE_MINIMUM(t) (TYPE_SIGNED (t) \
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
: (t) 0)
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
/* Bound on length of the string representing an integer value of type t.
Subtract one for the sign bit if t is signed;
302 / 1000 is log10 (2) rounded up;
add one for integer division truncation;
add one more for a minus sign if t is signed. */
#define INT_STRLEN_BOUND(t) \
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
+ 1 + TYPE_SIGNED (t))
#define UINTMAX_STRSIZE_BOUND (INT_STRLEN_BOUND (uintmax_t) + 1)
/* Prototypes for external functions. */
#if HAVE_LOCALE_H
# include <locale.h>
#endif
#if !HAVE_SETLOCALE
# define setlocale(Category, Locale) /* empty */
#endif
#include <time.h>
#ifndef time
time_t time ();
#endif
/* Library modules. */
#include <dirname.h>
#include <error.h>
#include <savedir.h>
#include <unlocked-io.h>
#include <xalloc.h>
#include <gettext.h>
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
#if ! defined valloc && ! HAVE_DECL_VALLOC
# define valloc(Size) malloc (Size)
#endif
#if MSDOS
# include <process.h>
# define SET_BINARY_MODE(arc) setmode(arc, O_BINARY)
# define ERRNO_IS_EACCES errno == EACCES
# define mkdir(file, mode) (mkdir) (file)
#else
# include <pwd.h>
# include <grp.h>
# define SET_BINARY_MODE(arc)
# define ERRNO_IS_EACCES 0
#endif
#if XENIX
# include <sys/inode.h>
#endif

2093
src/tar.c

File diff suppressed because it is too large Load Diff

View File

@@ -288,6 +288,8 @@ struct tar_stat_info
off_t archive_file_size; /* Size of file as stored in the archive.
Equals stat.st_size for non-sparse files */
bool is_sparse; /* Is the file sparse */
size_t sparse_map_avail; /* Index to the first unused element in
sparse_map array. Zero if the file is
not sparse */

View File

@@ -1,7 +1,7 @@
/* Update a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003
Free Software Foundation, Inc.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
2004 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
@@ -22,7 +22,7 @@
of the archive. No attempt is made to record the reads from the args; if
they're on raw tape or something like that, it'll probably lose... */
#include "system.h"
#include <system.h>
#include <quotearg.h>
#include "common.h"
@@ -33,7 +33,7 @@ extern union block *current_block;
/* We've hit the end of the old stuff, and its time to start writing new
stuff to the tape. This involves seeking back one record and
re-writing the current record (which has been changed).
FIXME: Either eliminate it or move it to common.h.
FIXME: Either eliminate it or move it to common.h.
*/
bool time_to_start_writing;
@@ -42,22 +42,22 @@ bool time_to_start_writing;
first part of the record. */
char *output_start;
/* Catenate file PATH to the archive without creating a header for it.
/* Catenate file FILE_NAME to the archive without creating a header for it.
It had better be a tar file or the archive is screwed. */
static void
append_file (char *path)
append_file (char *file_name)
{
int handle = open (path, O_RDONLY | O_BINARY);
int handle = open (file_name, O_RDONLY | O_BINARY);
struct stat stat_data;
if (handle < 0)
{
open_error (path);
open_error (file_name);
return;
}
if (fstat (handle, &stat_data) != 0)
stat_error (path);
stat_error (file_name);
else
{
off_t bytes_left = stat_data.st_size;
@@ -66,7 +66,7 @@ append_file (char *path)
{
union block *start = find_next_block ();
size_t buffer_size = available_space_after (start);
ssize_t status;
size_t status;
char buf[UINTMAX_STRSIZE_BOUND];
if (bytes_left < buffer_size)
@@ -78,15 +78,15 @@ append_file (char *path)
}
status = safe_read (handle, start->buffer, buffer_size);
if (status < 0)
read_fatal_details (path, stat_data.st_size - bytes_left,
if (status == SAFE_READ_ERROR)
read_fatal_details (file_name, stat_data.st_size - bytes_left,
buffer_size);
if (status == 0)
FATAL_ERROR ((0, 0,
ngettext ("%s: File shrank by %s byte",
"%s: File shrank by %s bytes",
bytes_left),
quotearg_colon (path),
quotearg_colon (file_name),
STRINGIFY_BIGINT (bytes_left, buf)));
bytes_left -= status;
@@ -96,7 +96,7 @@ append_file (char *path)
}
if (close (handle) != 0)
close_error (path);
close_error (file_name);
}
/* Implement the 'r' (add files to end of archive), and 'u' (add files
@@ -106,12 +106,12 @@ void
update_archive (void)
{
enum read_header previous_status = HEADER_STILL_UNREAD;
int found_end = 0;
bool found_end = false;
name_gather ();
open_archive (ACCESS_UPDATE);
xheader_write_global ();
while (!found_end)
{
enum read_header status = read_header (false);
@@ -126,30 +126,33 @@ update_archive (void)
{
struct name *name;
decode_header (current_header, &current_stat_info,
&current_format, 0);
archive_format = current_format;
if (subcommand_option == UPDATE_SUBCOMMAND
&& (name = name_scan (current_stat_info.file_name)) != NULL)
{
struct stat s;
enum archive_format unused;
decode_header (current_header, &current_stat_info, &unused, 0);
chdir_do (name->change_dir);
if (deref_stat (dereference_option,
current_stat_info.file_name, &s) == 0
&& s.st_mtime <= current_stat_info.stat.st_mtime)
add_avoided_name (current_stat_info.file_name);
}
skip_member ();
break;
}
case HEADER_ZERO_BLOCK:
current_block = current_header;
found_end = 1;
found_end = true;
break;
case HEADER_END_OF_FILE:
found_end = 1;
found_end = true;
break;
case HEADER_FAILURE:
@@ -175,6 +178,8 @@ update_archive (void)
break;
}
tar_stat_destroy (&current_stat_info);
xheader_destroy (&extended_header);
previous_status = status;
}
@@ -183,18 +188,18 @@ update_archive (void)
output_start = current_block->buffer;
{
char *path;
char *file_name;
while ((path = name_from_list ()) != NULL)
while ((file_name = name_from_list ()) != NULL)
{
if (excluded_name (path))
if (excluded_name (file_name))
continue;
if (interactive_option && !confirm ("add", path))
if (interactive_option && !confirm ("add", file_name))
continue;
if (subcommand_option == CAT_SUBCOMMAND)
append_file (path);
append_file (file_name);
else
dump_file (path, 1, (dev_t) 0);
dump_file (file_name, 1, (dev_t) 0);
}
}

View File

@@ -16,283 +16,30 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include <quotearg.h>
#include <localcharset.h>
#include "common.h"
#ifdef HAVE_ICONV_H
# include <iconv.h>
#endif
struct langtab
{
char *lang; /* Language code */
char *terr; /* Territory code */
char *charset; /* Corresponding charset */
};
#ifndef ICONV_CONST
# define ICONV_CONST
#endif
/* The list of language codes defined in ISO 639 with the corresponding
default character sets.
#ifndef HAVE_ICONV
NOTES:
# undef iconv_open
# define iconv_open(tocode, fromcode) ((iconv_t) -1)
1) The list must be ordered by:
a) lang field in ascending order
b) terr field in descending order.
NULL fields are considered less than non-null ones.
2) Many entries have NULL charset fields. Please help fill them!
3) The "default" character set for a given language is a matter
of preference. Possibly the table should contain a *list* of
possible character sets.
4) LC_ALL "modifier" field is not taken into account */
# undef iconv
# define iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft) ((size_t) 0)
static struct langtab langtab[] = {
{ "C", NULL, "ASCII"},
{ "POSIX", NULL, "ASCII" },
{ "aa", NULL, NULL}, /* Afar */
{ "ab", NULL, NULL}, /* Abkhazian */
{ "ae", NULL, NULL}, /* Avestan */
{ "af", NULL, "iso-8859-1"}, /* Afrikaans */
{ "am", NULL, "UTF-8"}, /* Amharic */
{ "ar", NULL, "iso-8859-6"}, /* Arabic */
{ "as", NULL, NULL}, /* Assamese */
{ "ay", NULL, "iso-8859-1"}, /* Aymara */
{ "az", NULL, NULL}, /* Azerbaijani */
{ "ba", NULL, NULL}, /* Bashkir */
{ "be", NULL, "UTF-8"}, /* Byelorussian; Belarusian */
{ "bg", NULL, "iso-8859-5"}, /* Bulgarian */
{ "bh", NULL, NULL}, /* Bihari */
{ "bi", NULL, NULL}, /* Bislama */
{ "bn", NULL, NULL}, /* Bengali; Bangla */
{ "bo", NULL, NULL}, /* Tibetan */
{ "br", NULL, "iso-8859-1"}, /* Breton: 1,5,8,9 */
{ "bs", NULL, NULL}, /* Bosnian */
{ "ca", NULL, "iso-8859-1"}, /* Catalan: 1,5,8,9 */
{ "ce", NULL, NULL}, /* Chechen */
{ "ch", NULL, NULL}, /* Chamorro */
{ "co", NULL, "iso-8859-1"}, /* Corsican */
{ "cs", NULL, "iso-8859-2"}, /* Czech */
{ "cu", NULL, NULL }, /* Church Slavic */
{ "cv", NULL, NULL}, /* Chuvash */
{ "cy", NULL, "iso-8859-1"}, /* Welsh */
{ "da", NULL, "iso-8859-1"}, /* Danish: 4-9 */
{ "de", NULL, "iso-8859-1"}, /* German */
{ "dz", NULL, NULL }, /* Dzongkha; Bhutani */
{ "el", NULL, "iso-8859-7"}, /* Greek */
{ "en", NULL, "iso-8859-1"}, /* English */
{ "eo", NULL, "iso-8859-3"}, /* Esperanto */
{ "es", NULL, "iso-8859-1"}, /* Spanish */
{ "et", NULL, "iso-8859-15"}, /* Estonian: 6,7,9 */
{ "eu", NULL, "iso-8859-1"}, /* Basque: 5,8,9 */
{ "fa", NULL, "UTF-8"}, /* Persian */
{ "fi", NULL, "iso-8859-15"}, /* Finnish */
{ "fj", NULL, NULL }, /* Fijian; Fiji */
{ "fo", NULL, "iso-8859-1"}, /* Faroese: 6,9 */
{ "fr", NULL, "iso-8859-1"}, /* French */
{ "fy", NULL, "iso-8859-1"}, /* Frisian */
{ "ga", NULL, "iso-8859-14"}, /* Irish */
{ "gd", NULL, "iso-8859-14" }, /* Scots; Gaelic */
{ "gl", NULL, NULL }, /* Gallegan; Galician */
{ "gn", NULL, NULL}, /* Guarani */
{ "gu", NULL, NULL}, /* Gujarati */
{ "gv", NULL, "iso-8859-14"}, /* Manx */
{ "ha", NULL, NULL }, /* Hausa (?) */
{ "he", NULL, "iso-8859-8" }, /* Hebrew */
{ "hi", NULL, NULL}, /* Hindi */
{ "ho", NULL, NULL}, /* Hiri Motu */
{ "hr", NULL, "iso-8859-2"}, /* Croatian: 10 */
{ "hu", NULL, "iso-8859-2"}, /* Hungarian */
{ "hy", NULL, NULL}, /* Armenian */
{ "hz", NULL, NULL}, /* Herero */
{ "id", NULL, "iso-8859-1"}, /* Indonesian (formerly in) */
{ "ia", NULL, NULL}, /* Interlingua */
{ "ie", NULL, NULL}, /* Interlingue */
{ "ik", NULL, NULL}, /* Inupiak */
{ "io", NULL, NULL}, /* Ido */
{ "is", NULL, "iso-8859-1"}, /* Icelandic */
{ "it", NULL, "iso-8859-1"}, /* Italian */
{ "iu", NULL, NULL}, /* Inuktitut */
{ "ja", NULL, "EUC-JP"}, /* Japanese */
{ "jv", NULL, NULL}, /* Javanese */
{ "ka", NULL, NULL}, /* Georgian */
{ "ki", NULL, NULL}, /* Kikuyu */
{ "kj", NULL, NULL}, /* Kuanyama */
{ "kk", NULL, NULL}, /* Kazakh */
{ "kl", NULL, "iso-8859-1"}, /* Kalaallisut; Greenlandic */
{ "km", NULL, NULL}, /* Khmer; Cambodian */
{ "kn", NULL, NULL}, /* Kannada */
{ "ko", NULL, "EUC-KR"}, /* Korean */
{ "ks", NULL, NULL}, /* Kashmiri */
{ "ku", NULL, NULL}, /* Kurdish */
{ "kv", NULL, NULL}, /* Komi */
{ "kw", NULL, "iso-8859-14"}, /* Cornish: 1,5,8 */
{ "ky", NULL, NULL}, /* Kirghiz */
{ "la", NULL, "iso-8859-1"}, /* Latin */
{ "lb", NULL, "iso-8859-1"}, /* Letzeburgesch */
{ "ln", NULL, NULL}, /* Lingala */
{ "lo", NULL, NULL}, /* Lao; Laotian */
{ "lt", NULL, "iso-8859-4"}, /* Lithuanian */
{ "lv", NULL, "iso-8859-4"}, /* Latvian; Lettish */
{ "mg", NULL, NULL}, /* Malagasy */
{ "mh", NULL, NULL}, /* Marshall */
{ "mi", NULL, NULL}, /* Maori */
{ "mk", NULL, NULL}, /* Macedonian */
{ "ml", NULL, NULL}, /* Malayalam */
{ "mn", NULL, NULL}, /* Mongolian */
{ "mo", NULL, "iso-8859-2"}, /* Moldavian */
{ "mr", NULL, NULL}, /* Marathi */
{ "ms", NULL, NULL}, /* Malay */
{ "mt", NULL, "iso-8859-3"}, /* Maltese */
{ "my", NULL, NULL}, /* Burmese */
{ "na", NULL, NULL}, /* Nauru */
{ "nb", NULL, "iso-8859-1"}, /* Norwegian Bokm<6B>l; Bokm@aa{}l */
{ "nd", NULL, NULL}, /* Ndebele, North */
{ "ne", NULL, NULL}, /* Nepali */
{ "ng", NULL, NULL}, /* Ndonga */
{ "nl", NULL, "iso-8859-1"}, /* Dutch: 5,9 */
{ "nn", NULL, "iso-8859-1"}, /* Norwegian Nynorsk */
{ "no", NULL, "iso-8859-1"}, /* Norwegian */
{ "nr", NULL, NULL}, /* Ndebele, South */
{ "nv", NULL, NULL}, /* Navajo */
{ "ny", NULL, NULL}, /* Chichewa; Nyanja */
{ "oc", NULL, NULL}, /* Occitan; Proven<65>al; Proven@,{c}al */
{ "om", NULL, NULL}, /* (Afan) Oromo */
{ "or", NULL, NULL}, /* Oriya */
{ "os", NULL, NULL}, /* Ossetian; Ossetic */
{ "pa", NULL, NULL}, /* Panjabi; Punjabi */
{ "pi", NULL, NULL}, /* Pali */
{ "pl", NULL, "iso-8859-2"}, /* Polish */
{ "ps", NULL, NULL}, /* Pashto, Pushto */
{ "pt", NULL, "iso-8859-1"}, /* Portuguese */
{ "qu", NULL, "iso-8859-1"}, /* Quechua */
{ "rm", NULL, "iso-8859-1"}, /* Rhaeto-Romance */
{ "rn", NULL, NULL }, /* Rundi; Kirundi */
{ "ro", NULL, "iso-8859-2"}, /* Romanian */
{ "ru", NULL, "koi8-r"}, /* Russian */
{ "rw", NULL, NULL}, /* Kinyarwanda */
{ "sa", NULL, NULL}, /* Sanskrit */
{ "sc", NULL, "iso-8859-1"}, /* Sardinian */
{ "sd", NULL, NULL}, /* Sindhi */
{ "se", NULL, "iso-8859-10"}, /* Northern Sami */
{ "sg", NULL, NULL}, /* Sango; Sangro */
{ "si", NULL, NULL}, /* Sinhalese */
{ "sk", NULL, "iso-8859-2"}, /* Slovak */
{ "sl", NULL, "iso-8859-1"}, /* Slovenian */
{ "sm", NULL, NULL}, /* Samoan */
{ "sn", NULL, NULL}, /* Shona */
{ "so", NULL, NULL}, /* Somali */
{ "sq", NULL, "iso-8859-1"}, /* Albanian: 2,5,8,9,10 */
{ "sr", NULL, "iso-8859-2"}, /* Serbian */
{ "ss", NULL, NULL}, /* Swati; Siswati */
{ "st", NULL, NULL}, /* Sesotho; Sotho, Southern */
{ "su", NULL, NULL}, /* Sundanese */
{ "sv", NULL, "iso-8859-1"}, /* Swedish */
{ "sw", NULL, NULL}, /* Swahili */
{ "ta", NULL, NULL}, /* Tamil */
{ "te", NULL, NULL}, /* Telugu */
{ "tg", NULL, NULL}, /* Tajik */
{ "th", NULL, "iso-8859-11"}, /* Thai */
{ "ti", NULL, NULL}, /* Tigrinya */
{ "tk", NULL, NULL}, /* Turkmen */
{ "tl", NULL, "iso-8859-1"}, /* Tagalog */
{ "tn", NULL, NULL}, /* Tswana; Setswana */
{ "to", NULL, NULL}, /* Tonga (?) */
{ "tr", NULL, "iso-8859-9"}, /* Turkish */
{ "ts", NULL, NULL}, /* Tsonga */
{ "tt", NULL, NULL}, /* Tatar */
{ "tw", NULL, NULL}, /* Twi */
{ "ty", NULL, NULL}, /* Tahitian */
{ "ug", NULL, NULL}, /* Uighur */
{ "uk", NULL, "koi8-u"}, /* Ukrainian */
{ "ur", NULL, NULL}, /* Urdu */
{ "uz", NULL, NULL}, /* Uzbek */
{ "vi", NULL, NULL}, /* Vietnamese */
{ "vo", NULL, NULL}, /* Volap<61>k; Volap@"{u}k; Volapuk */
{ "wa", NULL, "iso-8859-1"}, /* Walloon */
{ "wo", NULL, NULL}, /* Wolof */
{ "xh", NULL, NULL}, /* Xhosa */
{ "yi", NULL, "iso-8859-8"}, /* Yiddish (formerly ji) */
{ "yo", NULL, NULL}, /* Yoruba */
{ "za", NULL, NULL}, /* Zhuang */
{ "zh", "TW", "big5"}, /* Chinese */
{ "zh", NULL, "gb2312"}, /* Chinese */
{ "zu", NULL, NULL}, /* Zulu */
{ NULL }
};
# undef iconv_close
# define iconv_close(cd) 0
/* Given the language and (optionally) territory code, return the
default character set for that language. See notes above. */
const char *
charset_lookup (char *lang, char *terr)
{
static struct langtab *p;
if (!lang)
return NULL;
for (p = langtab; p->lang; p++)
if (strcasecmp (p->lang, lang) == 0
&& (terr == NULL
|| p->terr == NULL
|| !strcasecmp (p->terr, terr) == 0))
return p->charset;
return NULL;
}
static const char *
get_input_charset ()
{
const char *charset = NULL;
char *tmp;
int rc;
/* Try to deduce the charset from LC_ALL or LANG variables */
tmp = getenv ("LC_ALL");
if (!tmp)
tmp = getenv ("LANG");
if (tmp)
{
char *lang;
char *terr;
lang = strtok (tmp, "_");
terr = strtok (NULL, ".");
charset = strtok (NULL, "@");
if (!charset)
charset = charset_lookup (lang, terr);
}
if (!charset)
charset = "iso-8859-1";
return charset;
}
#ifndef HAVE_LIBICONV
iconv_t
iconv_open (const char *tocode, const char *fromcode)
{
return (iconv_t)(-1);
}
size_t
iconv (iconv_t cd, ICONV_CONST char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
return 0;
}
int
iconv_close (iconv_t cd)
{
return 0;
}
#endif /* !HAVE_LIBICONV */
#endif
@@ -305,22 +52,22 @@ utf8_init (bool to_utf)
if (conv_desc[(int) to_utf] == (iconv_t) -1)
{
if (to_utf)
conv_desc[(int) to_utf] = iconv_open ("UTF-8", get_input_charset ());
conv_desc[(int) to_utf] = iconv_open ("UTF-8", locale_charset ());
else
conv_desc[(int) to_utf] = iconv_open (get_input_charset (), "UTF-8");
conv_desc[(int) to_utf] = iconv_open (locale_charset (), "UTF-8");
}
return conv_desc[(int) to_utf];
}
bool
utf8_convert(bool to_utf, char *input, char **output)
utf8_convert (bool to_utf, char const *input, char **output)
{
const char *ib;
char ICONV_CONST *ib;
char *ob;
size_t inlen;
size_t outlen;
size_t rc;
iconv_t cd = utf8_init(to_utf);
iconv_t cd = utf8_init (to_utf);
if (cd == 0)
{
@@ -333,7 +80,7 @@ utf8_convert(bool to_utf, char *input, char **output)
inlen = strlen (input) + 1;
outlen = inlen * MB_LEN_MAX + 1;
ob = *output = xmalloc (outlen);
ib = input;
ib = (char ICONV_CONST *) input;
rc = iconv (cd, &ib, &inlen, &ob, &outlen);
*ob = 0;
return rc != -1;

View File

@@ -16,10 +16,12 @@
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include <system.h>
#include <fnmatch.h>
#include <hash.h>
#include <quotearg.h>
#include <stpcpy.h>
#include <xstrtol.h>
#include "common.h"
@@ -28,13 +30,16 @@
#define obstack_chunk_free free
#include <obstack.h>
bool xheader_protected_pattern_p (const char *pattern);
bool xheader_protected_keyword_p (const char *keyword);
#include <fnmatch.h>
static bool xheader_protected_pattern_p (char const *pattern);
static bool xheader_protected_keyword_p (char const *keyword);
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 ();
static void extended_header_init (void);
/* Number of global headers written so far. */
static size_t global_header_count;
@@ -78,7 +83,7 @@ static char *exthdr_name;
/* Template for the name field of a 'g' type header */
static char *globexthdr_name;
bool
static bool
xheader_keyword_deleted_p (const char *kw)
{
struct keyword_list *kp;
@@ -89,7 +94,7 @@ xheader_keyword_deleted_p (const char *kw)
return false;
}
bool
static bool
xheader_keyword_override_p (const char *keyword)
{
struct keyword_list *kp;
@@ -100,7 +105,7 @@ xheader_keyword_override_p (const char *keyword)
return false;
}
void
static void
xheader_list_append (struct keyword_list **root, char const *kw,
char const *value)
{
@@ -111,7 +116,7 @@ xheader_list_append (struct keyword_list **root, char const *kw,
*root = kp;
}
void
static void
xheader_list_destroy (struct keyword_list **root)
{
if (root)
@@ -128,15 +133,14 @@ xheader_list_destroy (struct keyword_list **root)
*root = NULL;
}
}
void
static void
xheader_set_single_keyword (char *kw)
{
USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw));
}
void
static void
xheader_set_keyword_equal (char *kw, char *eq)
{
bool global = true;
@@ -155,7 +159,7 @@ xheader_set_keyword_equal (char *kw, char *eq)
for (p = eq + 1; *p && isspace (*p); p++)
;
if (strcmp (kw, "delete") == 0)
{
if (xheader_protected_pattern_p (p))
@@ -191,15 +195,35 @@ xheader_set_option (char *string)
}
}
static void
to_decimal (uintmax_t value, char *where, size_t size)
{
size_t i = 0, j;
where[i++] = 0;
do
{
where[i++] = '0' + value % 10;
value /= 10;
}
while (i < size && value);
for (j = 0, i--; j < i; j++, i--)
{
char c = where[j];
where[j] = where[i];
where[i] = c;
}
}
/*
string Includes: Replaced By:
%d The directory name of the file,
equivalent to the result of the
dirname utility on the translated
pathname.
file name.
%f The filename of the file, equivalent
to the result of the basename
utility on the translated pathname.
utility on the translated file name.
%p The process ID of the pax process.
%% A '%' character. */
@@ -210,11 +234,11 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
size_t len = strlen (fmt);
char *q;
const char *p;
char *dirname = NULL;
char *basename = NULL;
char *dir = NULL;
char *base = NULL;
char pidbuf[64];
char nbuf[64];
for (p = fmt; *p && (p = strchr (p, '%')); )
{
switch (p[1])
@@ -226,38 +250,35 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
case 'd':
if (st)
{
dirname = safer_name_suffix (dir_name (st->orig_file_name),
false);
len += strlen (dirname) - 1;
dir = safer_name_suffix (dir_name (st->orig_file_name), false);
len += strlen (dir) - 1;
}
break;
case 'f':
if (st)
{
basename = base_name (st->orig_file_name);
len += strlen (basename) - 1;
base = base_name (st->orig_file_name);
len += strlen (base) - 1;
}
break;
case 'p':
snprintf (pidbuf, sizeof pidbuf, "%lu",
(unsigned long) getpid ());
to_decimal (getpid (), pidbuf, sizeof pidbuf);
len += strlen (pidbuf) - 1;
break;
case 'n':
if (allow_n)
{
snprintf (nbuf, sizeof nbuf, "%lu",
(unsigned long) global_header_count + 1);
to_decimal (global_header_count + 1, pidbuf, sizeof pidbuf);
len += strlen (nbuf) - 1;
}
break;
}
p++;
}
buf = xmalloc (len + 1);
for (q = buf, p = fmt; *p; )
{
@@ -269,19 +290,19 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
*q++ = *p++;
p++;
break;
case 'd':
if (dirname)
q = stpcpy (q, dirname);
if (dir)
q = stpcpy (q, dir);
p += 2;
break;
case 'f':
if (basename)
q = stpcpy (q, basename);
if (base)
q = stpcpy (q, base);
p += 2;
break;
case 'p':
q = stpcpy (q, pidbuf);
p += 2;
@@ -294,7 +315,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
p += 2;
}
/* else fall through */
default:
*q++ = *p++;
if (*p)
@@ -323,7 +344,7 @@ xheader_xhdr_name (struct tar_stat_info *st)
#define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
char *
xheader_ghdr_name ()
xheader_ghdr_name (void)
{
if (!globexthdr_name)
{
@@ -346,7 +367,7 @@ xheader_write (char type, char *name, struct xheader *xhdr)
union block *header;
size_t size;
char *p;
size = xhdr->size;
header = start_private_header (name, size);
header->header.typeflag = type;
@@ -354,11 +375,11 @@ xheader_write (char type, char *name, struct xheader *xhdr)
simple_finish_header (header);
p = xhdr->buffer;
do
{
size_t len;
header = find_next_block ();
len = BLOCKSIZE;
if (len > size)
@@ -372,17 +393,17 @@ xheader_write (char type, char *name, struct xheader *xhdr)
}
while (size > 0);
xheader_destroy (xhdr);
}
}
void
xheader_write_global ()
xheader_write_global (void)
{
char *name;
struct keyword_list *kp;
if (!keyword_global_override_list)
return;
extended_header_init ();
for (kp = keyword_global_override_list; kp; kp = kp->next)
code_string (kp->value, kp->pattern, &extended_header);
@@ -424,7 +445,7 @@ locate_handler (char const *keyword)
return NULL;
}
bool
static bool
xheader_protected_pattern_p (const char *pattern)
{
struct xhdr_tab const *p;
@@ -435,7 +456,7 @@ xheader_protected_pattern_p (const char *pattern)
return false;
}
bool
static bool
xheader_protected_keyword_p (const char *keyword)
{
struct xhdr_tab const *p;
@@ -514,7 +535,7 @@ decx (void *data, char const *keyword, char const *value)
if (xheader_keyword_deleted_p (keyword)
|| xheader_keyword_override_p (keyword))
return;
t = locate_handler (keyword);
if (t)
t->decoder (st, value);
@@ -525,12 +546,12 @@ 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)
{
char *p = extended_header.buffer + BLOCKSIZE;
char *endp = &extended_header.buffer[extended_header.size-1];
while (p < endp)
if (!decode_record (&p, decx, st))
break;
@@ -546,7 +567,7 @@ decg (void *data, char const *keyword, char const *value)
}
void
xheader_decode_global ()
xheader_decode_global (void)
{
if (extended_header.size)
{
@@ -561,7 +582,7 @@ xheader_decode_global ()
}
static void
extended_header_init ()
extended_header_init (void)
{
if (!extended_header.stk)
{
@@ -574,8 +595,7 @@ void
xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
{
struct xhdr_tab const *t;
char *value;
if (extended_header.buffer)
return;
t = locate_handler (keyword);
@@ -606,7 +626,7 @@ xheader_read (union block *p, size_t size)
if (len > BLOCKSIZE)
len = BLOCKSIZE;
memcpy (&extended_header.buffer[j], p->buffer, len);
set_next_block_after (p);
@@ -764,19 +784,22 @@ code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
}
static void
dummy_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
char const *keyword __attribute__ ((unused)),
struct xheader *xhdr __attribute__ ((unused)),
void *data __attribute__ ((unused)))
{
}
static void
dummy_decoder (struct tar_stat_info *st, char const *arg)
dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
char const *arg __attribute__ ((unused)))
{
}
static void
atime_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_time (st->stat.st_atime, st->atime_nsec, keyword, xhdr);
}
@@ -789,7 +812,7 @@ atime_decoder (struct tar_stat_info *st, char const *arg)
static void
gid_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_num (st->stat.st_gid, keyword, xhdr);
}
@@ -804,7 +827,7 @@ gid_decoder (struct tar_stat_info *st, char const *arg)
static void
gname_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_string (st->gname, keyword, xhdr);
}
@@ -817,7 +840,7 @@ gname_decoder (struct tar_stat_info *st, char const *arg)
static void
linkpath_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_string (st->link_name, keyword, xhdr);
}
@@ -830,7 +853,7 @@ linkpath_decoder (struct tar_stat_info *st, char const *arg)
static void
ctime_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_time (st->stat.st_ctime, st->ctime_nsec, keyword, xhdr);
}
@@ -843,7 +866,7 @@ ctime_decoder (struct tar_stat_info *st, char const *arg)
static void
mtime_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_time (st->stat.st_mtime, st->mtime_nsec, keyword, xhdr);
}
@@ -856,7 +879,7 @@ mtime_decoder (struct tar_stat_info *st, char const *arg)
static void
path_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_string (st->file_name, keyword, xhdr);
}
@@ -871,7 +894,7 @@ path_decoder (struct tar_stat_info *st, char const *arg)
static void
size_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_num (st->stat.st_size, keyword, xhdr);
}
@@ -881,12 +904,12 @@ size_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
st->stat.st_size = u;
st->archive_file_size = st->stat.st_size = u;
}
static void
uid_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_num (st->stat.st_uid, keyword, xhdr);
}
@@ -901,7 +924,7 @@ uid_decoder (struct tar_stat_info *st, char const *arg)
static void
uname_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr, void *data __attribute__ ((unused)))
{
code_string (st->uname, keyword, xhdr);
}
@@ -924,12 +947,13 @@ sparse_size_decoder (struct tar_stat_info *st, char const *arg)
{
uintmax_t u;
if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
st->archive_file_size = u;
st->stat.st_size = u;
}
static void
sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
struct xheader *xhdr, void *data)
struct xheader *xhdr,
void *data __attribute__ ((unused)))
{
code_num (st->sparse_map_avail, keyword, xhdr);
}
@@ -978,7 +1002,7 @@ sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg)
{
if (st->sparse_map_avail == st->sparse_map_size)
{
size_t newsize = st->sparse_map_size *= 2;
st->sparse_map_size *= 2;
st->sparse_map = xrealloc (st->sparse_map,
st->sparse_map_size
* sizeof st->sparse_map[0]);
@@ -988,18 +1012,18 @@ sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg)
}
struct xhdr_tab const xhdr_tab[] = {
{ "atime", atime_coder, atime_decoder },
{ "comment", dummy_coder, dummy_decoder },
{ "charset", dummy_coder, dummy_decoder },
{ "ctime", ctime_coder, ctime_decoder },
{ "gid", gid_coder, gid_decoder },
{ "gname", gname_coder, gname_decoder },
{ "linkpath", linkpath_coder, linkpath_decoder},
{ "mtime", mtime_coder, mtime_decoder },
{ "path", path_coder, path_decoder },
{ "size", size_coder, size_decoder },
{ "uid", uid_coder, uid_decoder },
{ "uname", uname_coder, uname_decoder },
{ "atime", atime_coder, atime_decoder, false },
{ "comment", dummy_coder, dummy_decoder, false },
{ "charset", dummy_coder, dummy_decoder, false },
{ "ctime", ctime_coder, ctime_decoder, false },
{ "gid", gid_coder, gid_decoder, false },
{ "gname", gname_coder, gname_decoder, false },
{ "linkpath", linkpath_coder, linkpath_decoder, false },
{ "mtime", mtime_coder, mtime_decoder, false },
{ "path", path_coder, path_decoder, false },
{ "size", size_coder, size_decoder, false },
{ "uid", uid_coder, uid_decoder, false },
{ "uname", uname_coder, uname_decoder, false },
/* Sparse file handling */
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
@@ -1015,12 +1039,12 @@ struct xhdr_tab const xhdr_tab[] = {
/* The next directory entry actually contains the names of files
that were in the directory at the time the dump was made.
Supersedes GNUTYPE_DUMPDIR header type. */
{ "GNU.dump.name", dump_name_coder, dump_name_decoder },
{ "GNU.dump.status", dump_status_coder, dump_status_decoder },
{ "GNU.dump.name", dump_name_coder, dump_name_decoder, false },
{ "GNU.dump.status", dump_status_coder, dump_status_decoder, false },
/* Keeps the tape/volume header. May be present only in the global headers.
Equivalent to GNUTYPE_VOLHDR. */
{ "GNU.volume.header", volume_header_coder, volume_header_decoder },
{ "GNU.volume.header", volume_header_coder, volume_header_decoder, false },
/* These may be present in a first global header of the archive.
They provide the same functionality as GNUTYPE_MULTIVOL header.
@@ -1028,9 +1052,9 @@ struct xhdr_tab const xhdr_tab[] = {
otherwise kept in the size field of a multivolume header. The
GNU.volume.offset keeps the offset of the start of this volume,
otherwise kept in oldgnu_header.offset. */
{ "GNU.volume.size", volume_size_coder, volume_size_decoder },
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder },
{ "GNU.volume.size", volume_size_coder, volume_size_decoder, false },
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, false },
#endif
{ NULL, NULL, NULL }
{ NULL, NULL, NULL, false }
};

View File

@@ -1,8 +1,11 @@
Makefile.in
Makefile
preset
.deps
genfile
tmp-*
directory
archive
atconfig
atlocal
testsuite
genfile.c
testsuite.dir
testsuite.log
package.m4

View File

@@ -1,9 +1,10 @@
# Makefile for GNU tar regression tests.
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003 Free Software
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004 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
@@ -20,26 +21,100 @@
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
check_PROGRAMS = genfile mksparse
BUILT_SOURCES = preset
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 star/README star/quicktest.sh
DISTCLEANFILES = atconfig $(check_SCRIPTS)
MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
TESTS = version.sh \
append.sh delete01.sh delete02.sh delete03.sh delete04.sh \
extrac01.sh extrac02.sh extrac03.sh extrac04.sh \
gzip.sh incremen.sh ignfail.sh listed01.sh \
multiv01.sh old.sh options.sh volume.sh \
recurse.sh
## ------------ ##
## package.m4. ##
## ------------ ##
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
{ \
echo '# Signature of the current package.'; \
echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \
echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \
echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \
echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \
echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \
} >$(srcdir)/package.m4
#
## ------------ ##
## Test suite. ##
## ------------ ##
TESTSUITE_AT = \
testsuite.at\
delete01.at\
delete02.at\
delete03.at\
delete04.at\
delete05.at\
extrac01.at\
extrac02.at\
extrac03.at\
extrac04.at\
extrac05.at\
gzip.at\
incremental.at\
ignfail.at\
link01.at\
listed01.at\
listed02.at\
longv7.at\
multiv01.at\
multiv02.at\
multiv03.at\
old.at\
options.at\
recurse.at\
same-order01.at\
same-order02.at\
sparse01.at\
volume.at\
version.at\
star/gtarfail.at\
star/gtarfail2.at\
star/multi-fail.at\
star/ustar-big-2g.at\
star/ustar-big-8g.at\
star/pax-big-10g.at
TESTSUITE = $(srcdir)/testsuite
AUTOTEST = $(AUTOM4TE) --language=autotest
$(TESTSUITE): package.m4 $(TESTSUITE_AT)
$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
mv $@.tmp $@
atconfig: $(top_builddir)/config.status
cd $(top_builddir) && ./config.status tests/$@
clean-local:
$(SHELL) $(TESTSUITE) --clean
check-local: atconfig atlocal $(TESTSUITE)
$(SHELL) $(TESTSUITE)
#check_SCRIPTS = tar
# Run the test suite on the *installed* tree.
installcheck-local:
$(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
## ------------ ##
## genfile ##
## ------------ ##
check_PROGRAMS = genfile
genfile_SOURCES = genfile.c
mksparse_SOURCES = mksparse.c
EXTRA_DIST = after before preset.in $(TESTS)
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/lib -I../lib -I$(top_srcdir)/src
LDADD = ../lib/libtar.a $(LIBINTL)
mostlyclean:
rm -rf tmp-*
$(TESTS): genfile mksparse

View File

@@ -1,9 +0,0 @@
#! /bin/sh
# Do common operations after a particular test.
cd ..
exec 1> /dev/null
exec 2> /dev/null
echo $echo_n "$out$echo_c" | cmp -s - tmp-$$/stdout || exit 1
echo $echo_n "$err$echo_c" | cmp -s - tmp-$$/stderr || exit 1
rm -rf tmp-$$

48
tests/delete03.sh → tests/append.at Executable file → Normal file
View File

@@ -1,46 +1,34 @@
#! /bin/sh
# Deleting members with long file names.
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
. ./preset
. $srcdir/before
prereq gnu oldgnu posix
AT_SETUP([append])
AT_KEYWORDS([append])
set -e
prefix=This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_file_names_that_run_into_a_limit_of_the_posix_tar_formatXX
rm -f $prefix*
for i in 1 2 3 4 5 6 7 8 9
do touch $prefix$i
done
tar -cf archive ./$prefix*
tar --delete -f archive ./${prefix}5
tar -tf archive
AT_TAR_CHECK([touch file1
touch file2
tar cf archive file1
tar rf archive file2
tar tf archive],
[0],
[file1
file2
])
out="\
./${prefix}1
./${prefix}2
./${prefix}3
./${prefix}4
./${prefix}6
./${prefix}7
./${prefix}8
./${prefix}9
"
. $srcdir/after
AT_CLEANUP

View File

@@ -1,19 +0,0 @@
#! /bin/sh
# Append was just not working.
. ./preset
. $srcdir/before
set -e
touch file1
touch file2
tar cf archive file1
tar rf archive file2
tar tf archive
out="\
file1
file2
"
. $srcdir/after

6
tests/atlocal.in Normal file
View File

@@ -0,0 +1,6 @@
# @configure_input@ -*- shell-script -*-
# Configurable variable values for tar test suite.
# Copyright (C) 2004 Free Software Foundation, Inc.
PATH=@abs_builddir@:@abs_top_builddir@/src:$top_srcdir:$srcdir:$PATH

View File

@@ -1,38 +0,0 @@
#! /bin/sh
# Do common operations before a particular test.
mkdir tmp-$$
cd tmp-$$
case $srcdir in
/*|~*) ;;
*) srcdir=../$srcdir ;;
esac
out=
err=
echo $0 > checking
exec 1> stdout
exec 2> stderr
PATH=..:../../src:$PATH
prereq() {
if test $# -ne 0; then
case $TAR_OPTIONS in
--format=*) FMTOPT=$TAR_OPTIONS;;
*) FMTOPT=`tar --show-defaults`;;
esac
FORMAT=
for option
do
case $FMTOPT in
--format=$option*) FORMAT=$option
break;;
esac
done
test -z "$FORMAT" && exit 77
fi
}

36
tests/delete01.at Normal file
View File

@@ -0,0 +1,36 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Deleting a member after a big one was destroying the archive.
AT_SETUP([deleting a member after a big one])
AT_KEYWORDS([delete01])
AT_TAR_CHECK([
genfile -l 50000 > file1
genfile -l 1024 > file2
tar cf archive file1 file2
tar f archive --delete file2
tar tf archive],
[0],
[file1
])
AT_CLEANUP

View File

@@ -1,18 +0,0 @@
#! /bin/sh
# Deleting a member after a big one was destroying the archive.
. ./preset
. $srcdir/before
set -e
genfile -l 50000 > file1
genfile -l 1024 > file2
tar cf archive file1 file2
tar f archive --delete file2
tar tf archive
out="\
file1
"
. $srcdir/after

44
tests/delete02.at Normal file
View File

@@ -0,0 +1,44 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Deleting a member with the archive from stdin was not working correctly.
AT_SETUP([deleting a member from stdin archive])
AT_KEYWORDS([delete02])
AT_TAR_CHECK([
genfile -l 3073 -p zeros > 1
cp 1 2
cp 2 3
tar cf archive 1 2 3
tar tf archive
cat archive | tar f - --delete 2 > archive2
echo separator
tar tf archive2],
[0],
[1
2
3
separator
1
3
])
AT_CLEANUP

View File

@@ -1,26 +0,0 @@
#! /bin/sh
# Deleting a member with the archive from stdin was not working correctly.
. ./preset
. $srcdir/before
set -e
genfile -l 3073 -p zeros > 1
cp 1 2
cp 2 3
tar cf archive 1 2 3
tar tf archive
cat archive | tar f - --delete 2 > archive2
echo -----
tar tf archive
out="\
1
2
3
-----
1
3
"
. $srcdir/after

48
tests/delete03.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) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
AT_SETUP([deleting members with long names])
AT_KEYWORDS([delete03])
m4_define([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_file_names_that_run_into_a_limit_of_the_posix_tar_formatXX])
AT_TAR_CHECK([
prefix=PREFIX
rm -f $prefix*
for i in 1 2 3 4 5 6 7 8 9
do touch $prefix$i
done
tar -cf archive ./$prefix* &&
tar --delete -f archive ./${prefix}5 &&
tar -tf archive
],
[0],
[./PREFIX[]1
./PREFIX[]2
./PREFIX[]3
./PREFIX[]4
./PREFIX[]6
./PREFIX[]7
./PREFIX[]8
./PREFIX[]9
],[],[],[],[gnu, oldgnu, posix])
AT_CLEANUP

53
tests/delete04.at Normal file
View File

@@ -0,0 +1,53 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Deleting a large last member was destroying earlier members.
AT_SETUP([deleting a large last member])
AT_KEYWORDS([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
tar cf archive file1 file2 file3 file4 file5 file6 file7 file8 file9 file10
tar f archive --delete file10
tar tf archive
],
[0],
[file1
file2
file3
file4
file5
file6
file7
file8
file9
])
AT_CLEANUP

View File

@@ -1,34 +0,0 @@
#! /bin/sh
# Deleting a large last member was destroying earlier members.
. ./preset
. $srcdir/before
set -e
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
tar cf archive file1 file2 file3 file4 file5 file6 file7 file8 file9 file10
tar f archive --delete file10
tar tf archive
out="\
file1
file2
file3
file4
file5
file6
file7
file8
file9
"
. $srcdir/after

48
tests/delete05.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) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# When attempted to delete a non-existing member, tar used to destroy
# last blocking_factor blocks.
# References:
# <Pine.LNX.4.10.10412160956460.30933-100000@electra.znyx.com>
# http://lists.gnu.org/archive/html/bug-tar/2004-12/msg00016.html
AT_SETUP([deleting non-existing member])
AT_KEYWORDS([delete05])
AT_TAR_CHECK([
genfile -l 1024 > en
genfile -l 1024 > to
tar cf archive en to
# Make sure we don't use bogus blocking factor.
# GNU tar up to and including 1.14.91 produced an empty archive this way:
tar --file archive --blocking-factor=20 --delete tre
tar tf archive
],
[0],
[en
to
],
[tar: tre: Not found in archive
tar: Error exit delayed from previous errors
])
AT_CLEANUP

33
tests/extrac01.at Normal file
View File

@@ -0,0 +1,33 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# There was a diagnostic when directory already exists.
AT_SETUP([extract01])
AT_KEYWORDS([extract01])
AT_TAR_CHECK([
mkdir directory
touch directory/file
tar cf archive directory || exit 1
tar xf archive || exit 1
])
AT_CLEANUP

View File

@@ -1,13 +0,0 @@
#! /bin/sh
# There was a diagnostic when directory already exists.
. ./preset
. $srcdir/before
set -e
mkdir directory
touch directory/file
tar cf archive directory || exit 1
tar xf archive || exit 1
. $srcdir/after

37
tests/extrac02.at Normal file
View File

@@ -0,0 +1,37 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Could not extract symlinks over an existing file.
AT_SETUP([extracting symlinks over an existing file])
AT_KEYWORDS([extract02])
# FIXME: Skip if symlinks are not supported on the system
AT_TAR_CHECK([
touch file
ln -s file link 2> /dev/null || ln file link
tar cf archive link
rm link
touch link
tar xf archive
])
AT_CLEANUP

View File

@@ -1,15 +0,0 @@
#! /bin/sh
# Could not extract symlinks over an existing file.
. ./preset
. $srcdir/before
set -e
touch file
ln -s file link 2> /dev/null || ln file link
tar cf archive link
rm link
touch link
tar xf archive
. $srcdir/after

37
tests/extrac03.at Normal file
View File

@@ -0,0 +1,37 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Paths going up and down were inducing extraction loops.
AT_SETUP([extraction loops])
AT_KEYWORDS([extract03])
AT_TAR_CHECK([
mkdir directory
tar -cPvf archive directory/../directory
echo separator
tar -xPvf archive],
[0],
[directory/../directory/
separator
directory/../directory/
])
AT_CLEANUP

View File

@@ -1,19 +0,0 @@
#! /bin/sh
# Paths going up and down were inducing extraction loops.
. ./preset
. $srcdir/before
set -e
mkdir directory
tar cfv archive directory/../directory
echo -----
tar xfv archive
out="\
directory/../directory/
-----
directory/../directory/
"
. $srcdir/after

46
tests/extrac04.at Normal file
View File

@@ -0,0 +1,46 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Check for fnmatch problems in glibc 2.1.95.
AT_SETUP([extract + fnmatch])
AT_KEYWORDS([extract04])
AT_TAR_CHECK([
touch file1
mkdir directory
mkdir directory/subdirectory
touch directory/file1
touch directory/file2
touch directory/subdirectory/file1
touch directory/subdirectory/file2
tar -cf archive ./file1 directory
tar -tf archive \
--exclude='./*1' \
--exclude='d*/*1' \
--exclude='d*/s*/*2' | sort
],
[0],
[directory/
directory/file2
directory/subdirectory/
])
AT_CLEANUP

View File

@@ -1,27 +0,0 @@
#! /bin/sh
# Check for fnmatch problems in glibc 2.1.95.
. ./preset
. $srcdir/before
set -e
touch file1
mkdir directory
mkdir directory/subdirectory
touch directory/file1
touch directory/file2
touch directory/subdirectory/file1
touch directory/subdirectory/file2
tar -cf archive ./file1 directory
tar -tf archive \
--exclude='./*1' \
--exclude='d*/*1' \
--exclude='d*/s*/*2' | sort
out="\
directory/
directory/file2
directory/subdirectory/
"
. $srcdir/after

61
tests/extrac05.at Normal file
View File

@@ -0,0 +1,61 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Problem: when extracting selected members from a PAX archive,
# tar 1.14 incorrectly deemed all members to be sparse and
# therefore was not able to properly skip them.
#
# Reported by: Luca Fibbi <fibbi@lamma.rete.toscana.it>
#
# References: <3.0.6.32.20040809113727.00a30e50@localhost>
# http://lists.gnu.org/archive/html/bug-tar/2004-08/msg00008.html
AT_SETUP([extracting selected members from pax])
AT_KEYWORDS([extract05])
AT_DATA([list],
[jeden
cztery
])
AT_TAR_CHECK([
genfile --length 118 > jeden
genfile --length 223 > dwa
genfile --length 517 > trzy
genfile --sparse --file sparsefile 0 ABCD 1M EFGH 2000K IJKL
genfile --length 110 > cztery
tar cf archive jeden dwa trzy cztery || exit 1
mkdir dir
cd dir
tar xvfT ../archive ../../list || exit 1
cd ..
],
[0],
[jeden
cztery
],
[],[],[],
[posix])
AT_CLEANUP

View File

@@ -1,170 +0,0 @@
/* Generate a file containing some preset patterns.
Copyright (C) 1995, 1996, 1997, 2001, 2003 Free Software
Foundation, Inc.
François Pinard <pinard@iro.umontreal.ca>, 1995.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "system.h"
#include <argmatch.h>
#include <getopt.h>
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif
enum pattern
{
DEFAULT_PATTERN,
ZEROS_PATTERN
};
/* The name this program was run with. */
const char *program_name;
/* If nonzero, display usage information and exit. */
static int show_help = 0;
/* If nonzero, print the version on standard output and exit. */
static int show_version = 0;
/* Length of file to generate. */
static int file_length = 0;
/* Pattern to generate. */
static enum pattern pattern = DEFAULT_PATTERN;
/* Explain how to use the program, then get out. */
void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
printf (_("Generate data files for GNU tar test suite.\n"));
printf (_("\
\n\
Usage: %s [OPTION]...\n"), program_name);
fputs (_("\
If a long option shows an argument as mandatory, then it is mandatory\n\
for the equivalent short option also.\n\
\n\
-l, --file-length=LENGTH LENGTH of generated file\n\
-p, --pattern=PATTERN PATTERN is `default' or `zeros'\n\
--help display this help and exit\n\
--version output version information and exit\n"),
stdout);
}
exit (status);
}
/* Main program. Decode ARGC arguments passed through the ARGV array
of strings, then launch execution. */
/* Long options equivalences. */
static const struct option long_options[] =
{
{"help", no_argument, &show_help, 1},
{"length", required_argument, NULL, 'l'},
{"pattern", required_argument, NULL, 'p'},
{"version", no_argument, &show_version, 1},
{0, 0, 0, 0},
};
static char const * const pattern_args[] = { "default", "zeros", 0 };
static enum pattern const pattern_types[] = {DEFAULT_PATTERN, ZEROS_PATTERN};
int
main (int argc, char *const *argv)
{
int option_char; /* option character */
int counter; /* general purpose counter */
/* Decode command options. */
program_name = argv[0];
setlocale (LC_ALL, "");
while (option_char = getopt_long (argc, argv, "l:p:", long_options, NULL),
option_char != EOF)
switch (option_char)
{
default:
usage (EXIT_FAILURE);
case '\0':
break;
case 'l':
file_length = atoi (optarg);
break;
case 'p':
pattern = XARGMATCH ("--pattern", optarg,
pattern_args, pattern_types);
break;
}
/* Process trivial options. */
if (show_version)
{
printf ("genfile (GNU %s) %s\n", PACKAGE, VERSION);
printf (_("Copyright (C) %d Free Software Foundation, Inc.\n"), 2003);
puts (_("\
This program comes with NO WARRANTY, to the extent permitted by law.\n\
You may redistribute it under the terms of the GNU General Public License;\n\
see the file named COPYING for details."));
/* Note to translator: Please translate "F. Pinard" to "François
Pinard" if "ç" (c-with-cedilla) is available in the
translation's character set and encoding. */
puts (_("Written by F. Pinard."));
exit (EXIT_SUCCESS);
}
if (show_help)
usage (EXIT_SUCCESS);
if (optind < argc)
usage (EXIT_FAILURE);
/* Generate file. */
switch (pattern)
{
case DEFAULT_PATTERN:
for (counter = 0; counter < file_length; counter++)
putchar (counter & 255);
break;
case ZEROS_PATTERN:
for (counter = 0; counter < file_length; counter++)
putchar (0);
break;
}
exit (0);
}

41
tests/gzip.at Normal file
View File

@@ -0,0 +1,41 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# tar should detect that its gzip child failed.
AT_SETUP([gzip])
AT_KEYWORDS([gzip])
unset TAR_OPTIONS
AT_CHECK([
tar xfvz /dev/null
test $? = 2 || exit 1
],
[0],
[],
[
gzip: stdin: unexpected end of file
tar: Child returned status 1
tar: Error exit delayed from previous errors
],
[],[])
AT_CLEANUP

View File

@@ -1,17 +0,0 @@
#! /bin/sh
# tar should detect that its gzip child failed.
. ./preset
. $srcdir/before
tar xfvz /dev/null
test $? = 2 || exit 1
err="\
gzip: stdin: unexpected end of file
tar: Child returned status 1
tar: Error exit delayed from previous errors
"
. $srcdir/after

79
tests/ignfail.at Normal file
View File

@@ -0,0 +1,79 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Unreadable directories yielded error despite --ignore-failed-read.
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
echo 1>&2 -----
chmod 000 file
tar cf archive file
status=$?
chmod 600 file
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 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
fi
],
[0],
[],
[
-----
tar: file: Cannot open: Permission denied
tar: Error exit delayed from previous errors
-----
tar: file: Warning: Cannot open: Permission denied
-----
tar: directory: Cannot savedir: Permission denied
tar: Error exit delayed from previous errors
-----
tar: directory: Warning: Cannot savedir: Permission denied
])
AT_CLEANUP

View File

@@ -1,63 +0,0 @@
#! /bin/sh
# Unreadable directories yielded error despite --ignore-failed-read.
. ./preset
. $srcdir/before
> check-uid
set - x`ls -l check-uid`
if test $3 = root; then
# The test is meaningless for super-user.
rm check-uid
else
touch file
mkdir directory
touch directory/file
echo 1>&2 -----
chmod 000 file
tar cf archive file
status=$?
chmod 600 file
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 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 || exit 1
err="\
-----
tar: Cannot add file file: Permission denied
tar: Error exit delayed from previous errors
-----
tar: Cannot add file file: Permission denied
-----
tar: Cannot add directory directory: Permission denied
tar: Error exit delayed from previous errors
-----
tar: Cannot add directory directory: Permission denied
"
fi
. $srcdir/after

View File

@@ -1,40 +0,0 @@
#! /bin/sh
# A directory older than the listed entry was skipped completely.
. ./preset
. $srcdir/before
prereq gnu oldgnu
set -e
mkdir structure
echo x >structure/file
# On Nextstep (and perhaps other 4.3BSD systems),
# a newly created file's ctime isn't updated
# until the next sync or stat operation on the file.
ls -l structure/file >/dev/null
# If the time of an initial backup and the creation time of a file contained
# in that backup are the same, the file will be backed up again when an
# incremental backup is done, because the incremental backup backs up
# files created `on or after' the initial backup time. Without the sleep
# command, behaviour of tar becomes variable, depending whether the system
# clock ticked over to the next second between creating the file and
# backing it up.
sleep 1
tar cf archive --listed=list structure
tar cfv archive --listed=list structure
echo -----
sleep 1
echo y >structure/file
tar cfv archive --listed=list structure
out="\
structure/
-----
structure/
structure/file
"
. $srcdir/after

60
tests/incremental.at Normal file
View File

@@ -0,0 +1,60 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# A directory older than the listed entry was skipped completely.
AT_SETUP([incremental])
AT_KEYWORDS([incremental])
AT_TAR_CHECK([
mkdir structure
echo x >structure/file
# On Nextstep (and perhaps other 4.3BSD systems),
# a newly created file's ctime isn't updated
# until the next sync or stat operation on the file.
ls -l structure/file >/dev/null
# If the time of an initial backup and the creation time of a file contained
# in that backup are the same, the file will be backed up again when an
# incremental backup is done, because the incremental backup backs up
# files created `on or after' the initial backup time. Without the sleep
# command, behaviour of tar becomes variable, depending whether the system
# clock ticked over to the next second between creating the file and
# backing it up.
sleep 1
tar cf archive --listed=list structure
tar cfv archive --listed=list structure
echo separator
sleep 1
echo y >structure/file
tar cfv archive --listed=list structure
],
[0],
[
structure/
separator
structure/
structure/file
],
[],[],[],[gnu,oldgnu])
AT_CLEANUP

55
tests/link01.at Normal file
View File

@@ -0,0 +1,55 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Problem: If a member with link count > 2 was stored in the archive twice,
# previous versions of tar were not able to extract it, since they
# were trying to link the file to itself, which always failed and
# lead to removing the already extracted copy. This script tests
# the workaround by Paul Eggert that leaves the extracted copy
# untouched.
#
# Reported by: Toby Peterson <toby@apple.com>
#
# References: <2330D503-D20A-11D8-A0CF-00039391EECE@apple.com>
# http://lists.gnu.org/archive/html/bug-tar/2004-07/msg00009.html
AT_SETUP([link count gt 2])
AT_KEYWORDS([link01])
AT_TAR_CHECK([
mkdir directory
mkdir directory/test1
mkdir directory/test2
echo TEST > directory/test1/test.txt
ln directory/test1/test.txt directory/test2/test.txt
tar cf archive directory/test1/test.txt directory/test1/test.txt
rm -r directory
tar xf archive
ls directory/test1
],
[0],
[test.txt
])
AT_CLEANUP

46
tests/listed01.sh → tests/listed01.at Executable file → Normal file
View File

@@ -1,32 +1,34 @@
#! /bin/sh
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Check if listed-incremental backups work for individual files.
# Script proposed by Andreas Schuldei <andreas@schuldei.org>
# This file is part of GNU tar testsuite.
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
. ./preset
. $srcdir/before
prereq gnu oldgnu
# Check if listed-incremental backups work for individual files.
# Script proposed by Andreas Schuldei <andreas@schuldei.org>
# References: <20040215014223.GA9699@lukas.schuldei.com>
# http://lists.gnu.org/archive/html/bug-tar/2004-02/msg00011.html
AT_SETUP([--listed for individual files])
AT_KEYWORDS([listed01])
AT_TAR_CHECK([
mkdir directory
dd if=/dev/zero of=directory/file1 bs=1024 count=10 2>/dev/null
genfile --length 10240 --pattern zeros > directory/file1
# Let the things settle
sleep 1
@@ -35,23 +37,25 @@ tar --create \
--listed-incremental=listing \
directory/file*
tar tf archive.1
tar tf archive.1 || exit 1
dd if=/dev/zero of=directory/file2 bs=1024 count=20 2>/dev/null
genfile --length 10240 --pattern zeros > directory/file2
echo "separator"
tar --create \
--file=archive.2 \
--listed-incremental=listing \
directory/file*
directory/file* || exit 1
tar tf archive.2
out="\
directory/file1
tar tf archive.2 || exit 1
],
[0],
[directory/file1
separator
directory/file2
"
],
[],[],[],[gnu, oldgnu])
AT_CLEANUP
. $srcdir/after

150
tests/listed02.at Normal file
View File

@@ -0,0 +1,150 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Check if listed-incremental backups work for files moved from one directory
# to another.
# Based on a script by Martin Simmons <ZYHYLCRMZPRP@spammotel.com>
# References:
# <20040626230315.163AA1D148@cpc5-cmbg1-6-0-cust208.cmbg.cable.ntl.com>
# http://lists.gnu.org/archive/html/bug-tar/2004-06/msg00028.html
AT_SETUP([working --listed])
AT_KEYWORDS([listed02])
AT_TAR_CHECK([
mkdir directory
echo Create directories
mkdir tart
sleep 1
mkdir tart/c0
sleep 1
mkdir tart/c1
sleep 1
for file in tart/a1 tart/b1 tart/c0/cq1 tart/c0/cq2 tart/c1/ca1 tart/c1/ca2
do
echo File $file > $file
sleep 1
done
sleep 1
echo Creating main archive
tar -c -v --listed-incremental=tart.incr1 -f archive.1 tart || exit 1
sleep 1
echo Modifying filesystem
rm tart/a1
mv tart/b1 tart/b2
mv tart/c1 tart/c2
touch tart/c2/ca3
echo Directory contents
find tart|sort
sleep 1
echo Creating incremental archive
cp -p tart.incr1 tart.incr2
tar -c -v --listed-incremental=tart.incr2 -f archive.2 tart || exit 1
sleep 1
rm -rf tart/*
echo Extracting main archive
tar -x -v --listed-incremental=tart.incr1 -f archive.1 || exit 1
echo Extracting incremental archive
# This command should produce three messages about deletion
# of the existing files, that may appear in any order. Piping
# to sort makes sure we don't depend on any particular ordering.
tar -x -v --listed-incremental=tart.incr2 -f archive.2 | sort
echo Final files:
find tart|sort
],
[0],
[Create directories
Creating main archive
tart/
tart/c0/
tart/c1/
tart/a1
tart/b1
tart/c0/cq1
tart/c0/cq2
tart/c1/ca1
tart/c1/ca2
Modifying filesystem
Directory contents
tart
tart/b2
tart/c0
tart/c0/cq1
tart/c0/cq2
tart/c2
tart/c2/ca1
tart/c2/ca2
tart/c2/ca3
Creating incremental archive
tart/
tart/c0/
tart/c2/
tart/b2
tart/c2/ca1
tart/c2/ca2
tart/c2/ca3
Extracting main archive
tart/
tart/c0/
tart/c1/
tart/a1
tart/b1
tart/c0/cq1
tart/c0/cq2
tart/c1/ca1
tart/c1/ca2
Extracting incremental archive
tar: Deleting `tart/a1'
tar: Deleting `tart/b1'
tar: Deleting `tart/c1'
tart/
tart/b2
tart/c0/
tart/c2/
tart/c2/ca1
tart/c2/ca2
tart/c2/ca3
Final files:
tart
tart/b2
tart/c0
tart/c0/cq1
tart/c0/cq2
tart/c2
tart/c2/ca1
tart/c2/ca2
tart/c2/ca3
],
[tar: tart/c0: Directory is new
tar: tart/c1: Directory is new
tar: tart/c2: Directory is new
],
[],[],[gnu, oldgnu])
AT_CLEANUP

48
tests/longv7.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) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Old format (V7) archives should not accept file names longer than
# 99 characters
AT_SETUP([V7 and long names])
AT_KEYWORDS([longv7])
m4_define([DIR],[this_is_a_very_long_name_for_a_directory_which_causes_problems])
m4_define([FILE],[this_is_a_very_long_file_name_which_raises_issues.c])
AT_TAR_CHECK([
mkdir DIR
touch DIR/FILE
tar cf archive DIR
echo separator
tar tf archive
],
[0],
[separator
DIR/
],
[tar: DIR/FILE: file name is too long (max 99); not dumped
tar: Error exit delayed from previous errors
],
[],[],[v7])
AT_CLEANUP

View File

@@ -1,159 +0,0 @@
/* This file is part of GNU tar test suite
Copyright (C) 2004 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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <string.h>
char *progname;
char *buffer;
size_t buffer_size;
void
die (char *fmt, ...)
{
va_list ap;
fprintf (stderr, "%s: ", progname);
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fprintf (stderr, "\n");
}
void
mkhole (int fd, off_t displ)
{
if (displ = lseek (fd, displ, SEEK_CUR) == -1)
{
perror ("lseek");
exit (1);
}
ftruncate (fd, lseek (fd, 0, SEEK_CUR));
}
void
mksparse (int fd, off_t displ, char *marks)
{
int i;
for (; *marks; marks++)
{
memset (buffer, *marks, buffer_size);
if (write(fd, buffer, buffer_size) != buffer_size)
{
perror ("write");
exit (1);
}
if (lseek (fd, displ, SEEK_CUR) == -1)
{
perror ("lseek");
exit (1);
}
}
}
void
usage ()
{
printf ("Usage: mksparse filename blocksize disp letters [disp letters...] [disp]\n");
exit (1);
}
int
xlat_suffix (off_t *vp, char *p)
{
if (p[1])
return 1;
switch (p[0])
{
case 'g':
case 'G':
*vp *= 1024;
case 'm':
case 'M':
*vp *= 1024;
case 'k':
case 'K':
*vp *= 1024;
break;
default:
return 1;
}
return 0;
}
int
main (int argc, char **argv)
{
int i;
int fd;
char *p;
off_t n;
progname = strrchr (argv[0], '/');
if (progname)
progname++;
else
progname = argv[0];
if (argc < 4)
usage ();
fd = open (argv[1], O_CREAT|O_TRUNC|O_RDWR, 0644);
if (fd < 0)
die ("cannot open %s", argv[1]);
n = strtoul (argv[2], &p, 0);
if (n <= 0 || (*p && xlat_suffix (&n, p)))
die ("Invalid buffer size: %s", argv[2]);
buffer_size = n;
buffer = malloc (buffer_size);
if (!buffer)
die ("Not enough memory");
for (i = 3; i < argc; i += 2)
{
off_t displ;
displ = strtoul (argv[i], &p, 0);
if (displ < 0 || (*p && xlat_suffix (&displ, p)))
die ("Invalid displacement: %s", argv[i]);
if (i == argc-1)
{
mkhole (fd, displ);
break;
}
else
mksparse (fd, displ, argv[i+1]);
}
close(fd);
return 0;
}

59
tests/multiv01.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) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Test multivolume dumps from pipes.
AT_SETUP([multivolume dumps from pipes])
AT_KEYWORDS([multiv01])
# Fixme: should be configurable
# TRUSS=truss -o /tmp/tr
# TRUSS=strace
AT_TAR_CHECK([
genfile --length 7168 > file1
for block in " 1" " 2" " 3" " 4" " 5" " 6" " 7" " 8" \
" 9" "10" "11" "12" "13" "14" "15" "16" ; do \
echo "file2 block ${block} bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla"
for count in 2 3 4 5 6 7 8 ; do
echo "bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla"
done
done >file2
tar -c --multi-volume --tape-length=10 \
--listed-incremental=t.snar \
-f t1-pipe.tar -f t2-pipe.tar ./file1 ./file2 || exit 1
mkdir extract-dir-pipe
dd bs=4096 count=10 if=t2-pipe.tar 2>/dev/null |
PATH=$PATH ${TRUSS} tar -f t1-pipe.tar -f - \
-C extract-dir-pipe -x --multi-volume \
--tape-length=10 --read-full-records || exit 1
cmp file1 extract-dir-pipe/file1
cmp file2 extract-dir-pipe/file2
],
[0],
[],[],[],[],[gnu, oldgnu])
AT_CLEANUP

View File

@@ -1,39 +0,0 @@
#! /bin/sh
# Test multivolume dumps from pipes.
. ./preset
. $srcdir/before
prereq gnu oldgnu
# Fixme: should be configurable
# TRUSS=truss -o /tmp/tr
# TRUSS=strace
set -e
dd if=/dev/zero bs=1024 count=7 2>/dev/null >file1
for block in " 1" " 2" " 3" " 4" " 5" " 6" " 7" " 8" \
" 9" "10" "11" "12" "13" "14" "15" "16" ; do \
echo "file2 block ${block} bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla"
for count in 2 3 4 5 6 7 8 ; do
echo "bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla!bla"
done
done >file2
tar -c --multi-volume --tape-length=10 \
--listed-incremental=t.snar \
-f t1-pipe.tar -f t2-pipe.tar ./file1 ./file2
mkdir extract-dir-pipe
dd bs=4096 count=10 if=t2-pipe.tar 2>/dev/null |
PATH=$PATH ${TRUSS} tar -f t1-pipe.tar -f - \
-C extract-dir-pipe -x --multi-volume \
--tape-length=10 --read-full-records
cmp file1 extract-dir-pipe/file1
cmp file2 extract-dir-pipe/file2
out="\
"
. $srcdir/after

47
tests/multiv02.at Normal file
View File

@@ -0,0 +1,47 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Previous versions of tar were not able to skip a member straddling
# the multivolume archive boundary. Reported by Mads Martin Joergensen
# <mmj@suse.de>
#
# References: <20040402144254.GC4409@suse.de>
# http://lists.gnu.org/archive/html/bug-tar/2004-04/msg00002.html
AT_SETUP([skipping a straddling member])
AT_KEYWORDS([multiv02])
AT_TAR_CHECK([
genfile --length 10240 > en
genfile --length 20000 > to
genfile --length 20000 > tre
genfile --length 10240 > fire
tar -c -f A.tar -f B.tar -f C.tar -M -L 30 en to tre fire || exit 1
echo separator
tar -v -x -f A.tar -f B.tar -f C.tar -M en || exit 1
],
[0],
[separator
en
],
[],[],[],[gnu, oldgnu])
AT_CLEANUP

61
tests/multiv03.at Normal file
View File

@@ -0,0 +1,61 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Problem: GNU multivolume archives are not able to continue on members
# with filenames longer than 100 characters. Versions of tar <= 1.14
# were not checking filename lengths and produced malformed multivolume
# headers.
# References: <20040809214854.GB32706@suse.de>
# http://lists.gnu.org/archive/html/bug-tar/2004-08/msg00012.html
AT_SETUP([MV archive & long filenames])
AT_KEYWORDS([multiv03])
AT_TAR_CHECK([
AFILE=`awk 'BEGIN { for (i = 0; i < 100; i++) printf "a"; exit; }'`
BFILE=`awk 'BEGIN { for (i = 0; i < 101; i++) printf "b"; exit; }'`
cat > ../experr <<EOF
tar: $BFILE: file name too long to be stored in a GNU multivolume header
tar: Error is not recoverable: exiting now
EOF
cat > ../expout <<EOF
$AFILE
separator
EOF
genfile --length 15360 > $AFILE
tar -M -L 10 -c -f arch.1 -f arch.2 $AFILE || exit 1
tar -tM -f arch.1 -f arch.2 || exit 1
echo separator
genfile --length 15360 > $BFILE
tar -M -L 10 -c -f arch.1 -f arch.2 $BFILE
],
[2],
[expout],
[experr],
[],[],[gnu, oldgnu])
AT_CLEANUP

37
tests/old.at Normal file
View File

@@ -0,0 +1,37 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# An old archive was not receiving directories.
AT_SETUP([old archives])
AT_KEYWORDS([old])
unset TAR_OPTIONS
AT_CHECK([
mkdir directory
tar cfvo archive directory || exit 1
tar tf archive
],
[0],
[directory/
directory/
])
AT_CLEANUP

View File

@@ -1,17 +0,0 @@
#! /bin/sh
# An old archive was not receiving directories.
. ./preset
. $srcdir/before
set -e
mkdir directory
tar cfvo archive directory
tar tf archive
out="\
directory/
directory/
"
. $srcdir/after

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