144 Commits

Author SHA1 Message Date
Sergey Poznyakoff
ecd700fbfb Version 1.25
* configure.ac: Version 1.25
* NEWS: Describe the changes.
2010-11-07 16:04:48 +02:00
Sergey Poznyakoff
f1fed3996a Run alternative decompression programs if the principal one is not available.
Some compression programs are able to handle various compression formats
(e.g. `gzip' can decompress files created by `compress', `xz' is able
to handle lzma, etc.)  Tar tries to use such programs for decompression
if the principal decompressor cannot be started.

* src/buffer.c (compress_type): Swap ct_none and ct_tar.
(archive_compression_type): New static variable.
(zip_magic): Remove program and option fields.
(zip_program): New structure and static.
(compress_program): Remove macro.
(find_zip_program): New static function.
(first_decompress_program,next_decompress_program): New functions.
(open_compressed_archive): Set archive_compression_type instead of
use_compress_program_option.
* src/common.h (first_decompress_program)
(next_decompress_program): New functions.
(WARN_DECOMPRESS_PROGRAM): New flag.
(WARN_VERBOSE_WARNINGS): Include WARN_DECOMPRESS_PROGRAM.
* src/warning.c (warning_args): Add "decompress-program".
(warning_types): Add WARN_DECOMPRESS_PROGRAM.
* src/system.c (run_decompress_program): New function.
(sys_child_open_for_uncompress): Use run_decompress_program
instead of calling execlp directly.
2010-11-05 10:09:51 +02:00
Paul Eggert
b32edff5aa tests: fix some issues with signals, timestamps, "test" typo
* tests/extrac17.at: Add --warning=no-timestamp, to avoid
bogus warning due to NFS clock skew.
* tests/remfiles01.at: Discard diagnostics that some shells
generate about broken pipes.
* tests/sigpipe.at: Likewise.
* tests/remfiles01.at: Fix typo: "test $EC" was written where
"test $EC -ne 0" was intended.
2010-11-02 01:05:16 -07:00
Sergey Poznyakoff
3913675640 Fix extraction of device nodes.
* src/extract.c (extract_node): Do not mask out node type.
The bug was introduced in commit ea964cce.
2010-11-01 15:05:25 +02:00
Paul Eggert
b8feb2b142 tar: don't cross struct member boundaries with OLDGNU_MAGIC
* src/create.c (write_gnu_long_link, start_header): Access
header->buffer + offsetof (struct posix_header, magic), instead of
header->header.magic, when reading or writing the OLDGNU_MAGIC
pattern.  The code violates the C standard without this change,
and GCC warns about this if fortify checking is enabled.  It's not
a bug on traditional (i.e., non-debugging) platforms, but it does
violate the C standard so it should be fixed.  Problem originally
reported by John Emil Karlson in
<http://lists.gnu.org/archive/html/bug-tar/2010-04/msg00023.html>.
* src/list.c (decode_header): Likewise.
2010-10-27 22:31:16 -07:00
Paul Eggert
3fe59ed5ef tests: port to sh variants that squirrel away file descriptors
OpenBSD /bin/sh, and some other sh variants, squirrel away file
descriptors before closing them.  For example, for "cat 3<&-" they
first dup file descriptor 3 to a fd that is 10 or greater, then
close 3 (because if "cat" had been a builtin command like ":" then
they would have wanted to avoid the fork and restore the fd after
":" finished); and they treat ordinary (forking) commands the same
as builtin commands.  This approach fails after "ulimit -n 10".
Work around this deficiency by closing the file descriptors before
invoking ulimit.  Problem reported by Christian Weisgerber in
<http://lists.gnu.org/archive/html/bug-tar/2010-10/msg00041.html>;
solution suggested by Jilles Tjoelker in
<http://article.gmane.org/gmane.comp.shells.dash/415>.

* tests/extrac11.at (scarce file descriptors): Close file
descriptors before invoking ulimit -n.
2010-10-27 20:25:56 -07:00
Sergey Poznyakoff
5af29cb944 Transform file names when updating and appendig to archives.
This complements 28e91b48.

* src/common.h (transform_stat_info): New prototype.
* src/list.c (transform_stat_info): Remove static qualifier.
* src/update.c (update_archive): Call transform_stat_info.
* tests/Makefile.am (TESTSUITE_AT): Add append03.at
* tests/testsuite.at: Include append03.at
2010-10-27 14:07:46 +03:00
Paul Eggert
7dd57ebdfa tests: port to Solaris diff
* tests/extrac13.at: Don't assume that "diff -c" outputs nothing
when there are no differences.  This is not true on Solaris,
where it outputs "No differences encounted".
2010-10-26 18:13:03 -07:00
Paul Eggert
e23d123b93 tar: fix -x --overwrite bug (no --dereference, ! O_NOFOLLOW)
This bug was discovered on Solaris 8.  On older hosts lacking
O_NOFOLLOW, tar -x --overwrite (without --dereference) follows
symbolic links, causing the "extract over symlinks" test to fail.

* src/extract.c (open_output_file): If O_NOFOLLOW is needed but
does not work, check for a symlink separately.
2010-10-26 17:58:53 -07:00
Paul Eggert
6398c7a79c tar: don't use "((" in shell scripts
* tests/extrac11.at: Replace "((" with "( (" in shell scripts, as
"((" is not portable to the Korn shell, and POSIX 1003.1-2008 says
that "((" is not portable.
2010-10-26 15:04:56 -07:00
Sergey Poznyakoff
28e91b48f6 Make sure name matching occurs before name transformation.
The commit 9c194c99 altered that order.

* src/list.c (transform_stat_info): New function.  Split off from
decode_header.
(read_and): Call transform_stat_info right before do_something,
and after deciding if we should proceed with this member name,
so that name matching occurs before name transformation.

* tests/extrac17.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add extrac17.at
* tests/testsuite.at: Include extrac17.at.
2010-10-26 22:29:02 +03:00
Paul Eggert
3c0bedd494 tar: don't assume stdin is open when testing fd limits
* tests/extrac11.at: Redirect stdin from /dev/null, in case
the parent 'make' is running with stdin closed.
2010-10-26 11:33:38 -07:00
Sergey Poznyakoff
c520964e84 Further fixes in bootstrap.
* bootstrap: Restore the default for gnulib_path
(symlink_to_dir): Re-apply 67cad07.
2010-10-26 16:48:40 +03:00
Paul Eggert
acb77ac5bd tar: fix bug with -C and extracting directories
Problem reported by Denis Excoffier in
<http://lists.gnu.org/archive/html/bug-tar/2010-10/msg00034.html>.

* src/extract.c (extract_dir): Use mkdirat, not mkdir.
* tests/extrac16.at: New file, to test for this bug.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.

This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist.  Run make ChangeLog if you wish to create it earlier.
2010-10-25 20:21:06 -07:00
Sergey Poznyakoff
983113b140 Version 1.24
* configure.ac, NEWS: Version 1.24
* bootstrap: Restore tar-specific code lost during last
sync from gnulib (241b72ffad).
* src/misc.c (chdir_do): Remove unused automatic variable.
2010-10-25 00:35:50 +03:00
Paul Eggert
9447e799ab tar: use more-accurate diagnostic when intermediate mkdir fails
Without this change, if tar tried to extract a file A/B/C, noticed
that A/B didn't exist, attempted to mkdir A/B, and the mkdir
failed, it did not diagnose the mkdir failure, but simply reported
the failure to open A/B/C.  This sometimes led to confusion
because it wasn't clear what tar was trying to do, in particular
that tar tried to mkdir A/B.  With this patch, tar issues two
diagnostics in this case: one for A/B and the other for A/B/C.
Problem reported by Hauke Laging in
<http://lists.gnu.org/archive/html/bug-tar/2010-10/msg00020.html>.
* gnulib.modules: Remove faccessat.
* src/extract.c (make_directories): New arg INTERDIR_MADE.
Diagnose mkdir failure.  Return 0 on success, nonzero on failure,
as opposed to nonzero iff some directory was created.  All callers
changed.  Simplify the code when mkdir fails, by checking whether
the desired file exists unless errno==EEXIST: this is more robust.
* tests/extrac15.at: New test, to check this.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
2010-10-15 22:26:43 -07:00
Paul Eggert
502abd93bd tests: port to NFS file servers with clock skew
Several of the tests assumed that a newly created file cannot
have a time stamp dated in the future.  This assumption is not
true when files are served by a remote host whose clock is
slightly in advance of ours.  Fix the problems that I observed
when running "make check" a couple of times on such a server.

* tests/backup01.at: Use --warning=no-timestamp to suppress
clock-skew warnings.
* tests/chtype.at, tests/comprec.at, tests/exclude06.at:
* tests/extrac01.at, tests/extrac03.at, tests/extrac05.at:
* tests/extrac06.at, tests/extrac08.at, tests/extrac13.at:
* tests/extrac14.at, tests/incr01.at, tests/incr03.at, tests/link01.at:
* tests/multiv01.at, tests/multiv02.at, tests/multiv03.at:
* tests/pipe.at, tests/rename02.at, tests/rename03.at:
* tests/rename05.at, tests/same-order01.at, tests/same-order02.at:
* tests/sparse01.at:
Likewise.
2010-10-15 21:53:37 -07:00
Paul Eggert
241b72ffad gnulib: sync from latest gnulib, notably bootstrap and parse-datetime
* bootstrap: Sync from gnulib.
* doc/.gitignore: Rename getdate.texi to parse-datetime.texi.
* doc/Makefile.am (tar_TEXINFOS): Likewise.
* doc/tar.texi (Top): Adjust to renaming of getdate to parse-datetime.
* gnulib.modules: Likewise.  Also, remove ftruncate (now obsolete).
And add inttostr (we missed this dependency).
* src/tar.c: Include parse-datetime.h, not getdate.h.  All calls
to get_date replaced with parse_datetime.
2010-10-11 16:25:32 -07:00
Paul Eggert
c5c196310e tar: -x -C symlink fix
* src/misc.c (chdir_do): Don't use O_NOFOLLOW when opening the
argument to -C.  This is for consistency with "tar -c -C FOO", and
matches the new documentation.
* tests/extrac14.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
2010-09-24 13:13:47 -07:00
Paul Eggert
14efeb9f95 tar: --dereference consistency
This closes another race condition, that occurs when overwriting a
symlink with a regular file.
* NEWS (--dereference consistency): New section.
* doc/tar.texi (Option Summary): Describe new --deference behavior.
(dereference): Likewise.  Remove discussion that I didn't follow,
even before --dereference was changed.
* src/common.h (deref_stat, set_file_atime): Adjust signatures.
* src/compare.c (diff_file, diff_multivol): Respect open_read_flags
instead of rolling our own flags.  This implements the new behavior
for --dereference.
(diff_file, diff_dumpdir): Likewise, for fstatat_flags.
* src/create.c: Adjust to set_file_atime signature change.
* src/extract.c (mark_after_links, file_newer_p, extract_dir):
Likewise.
* src/incremen.c (try_purge_directory): Likewise.
* src/misc.c (maybe_backup_file): Likewise.
* src/extract.c (file_newer_p): New arg STP.  All callers changed.
(maybe_recoverable): New arg REGULAR.  All callers changed.
Handle the case of overwriting a symlink with a regular file,
when --overwrite is specified but --dereference is not.
(open_output_file): Add O_CLOEXEC, O_NOCTTY, O_NONBLOCK for
consistency with file creation.  Add O_NOFOLLOW if
overwriting_old_files && ! dereference_option.
* src/incremen.c (update_parent_directory): Use fstat, not fstatat;
there's less to go wrong.
* src/misc.c (deref_stat): Remove DEREF arg.  All callers changed.
Instead, use fstatat_flags.
(set_file_atime): Remove ATFLAG arg.  All callers changed.
Instead, use fstatat_flags.
* src/names.c, src/update.c: Adjust to deref_stat signature change.
* src/tar.c (get_date_or_file): Use stat, not deref_stat, as this
is not a file to be archived.
* tests/Makefile.am (TESTSUITE_AT): Add extrac13.at.
* tests/extrac13.at: New file.
* tests/testsuite.at: Include it.
2010-09-23 19:41:47 -07:00
Paul Eggert
efe26f98ec tar: do not crash with --listed-incremental
Problem reported by Frantisek Hanzlik in
<https://bugzilla.redhat.com/635318> via Kamil Dudka in
<http://lists.gnu.org/archive/html/bug-tar/2010-09/msg00066.html>.
I don't understand this code either, but Sergey can take a look at
this patch, and perhaps install a better one, when he has the time.
* src/incremen.c (append_incremental_renames): Don't actually append
anything to DIR if DIR is null.
2010-09-20 11:35:04 -07:00
Paul Eggert
4bde4f39d0 tar: prefer openat-style functions
This change replaces traditional functions like 'open' with the
POSIX.1-2008 functions like 'openat'.  Mostly this is an internal
refactoring change, in preparation for further changes to close
some races.
* gnulib.modules: Add faccessat, linkat, mkfifoat, renameat, symlinkat.
Remove save-cwd.
* src/Makefile.am (tar_LDADD): Add $(LIB_EACCESS).
* tests/Makefile.am (LDADD): Likewise.
* src/common.h (chdir_fd): New extern var.
* src/compare.c (diff_file, diff_multivol): Use openat instead of open.
* src/create.c (create_archive, restore_parent_fd): Likewise.
* src/extract.c (create_placeholder_file): Likewise.
* src/names.c (collect_and_sort_names): Likewise.
* src/update.c (append_file): Likewise.
* src/compare.c (diff_symlink): Use readlinkat instead of readlink.
* src/compare.c (diff_file): Use chdir_fd instead of AT_FDCWD.
* src/create.c (subfile_open, dump_file0): Likewise.
* src/extract.c (fd_chmod, fd_chown, fd_stat, set_stat):
(repair_delayed_set_stat, apply_nonancestor_delayed_set_stat):
Likewise.
* src/extract.c (mark_after_links, file_newer_p, extract_dir):
(extract_link, apply_delayed_links):
Use fstatat rather than stat or lstat.
* src/misc.c (maybe_backup_file, deref_stat): Likewise.
* src/extract.c (make_directories): Use mkdirat rather than mkdir.
Use faccessat rather than access.  This fixes a minor permissions
bug when tar is running setuid (who would want to do that?!).
(open_output_file): Use openat rather than open.
In the process, this removes support for Masscomp's O_CTG files,
which aren't compatible with openat's signature.  Masscomp!  Wow!
That's a blast from the past.  As far as I know, that operating
system hasn't been supported for more than 20 years.
(extract_link, apply_delayed_links):
Use linkat rather than link.
(extract_symlink, apply_delayed_links):
Use symlinkat rather than symlink.
(extract_node): Use mknodat rather than mknod.
(extract_fifo): Use mkfifoat rather than mkfifo.
(apply_delayed_links): Use unlinkat rather than unlink or rmdir.
* src/misc.c (safer_rmdir, remove_any_file): Likewise.
* src/unlink.c (flush_deferred_unlinks): Likewise.
* src/extract.c (rename_directory): Use renameat rather than rename.
* src/misc.c (maybe_backup_file, undo_last_backup): Likewise.
* src/misc.c: Don't include <save-cwd.h>; no longer needed now
that we're using openat etc.
(struct wd): Add member fd.  Remove members err and fd.  All uses
changed.
(CHDIR_CACHE_SIZE): New constant.
(wdcache, wdcache_count, chdir_fd): New vars.
(chdir_do): Use openat rather than save_cwd.  Keep the cache up
to date.  This code won't scale well, but is good enough for now.
* src/update.c (update_archive): Use openat + fdopendir +
streamsavedir rather than savedir.

This file is a placeholder. It will be replaced with the actual ChangeLog
by make dist.  Run make ChangeLog if you wish to create it earlier.
2010-09-18 23:42:54 -07:00
Paul Eggert
fc5e44c99c tar: add utimens.h includes
* src/extract.c: Include <utimens.h>, needed for fdutimens prototype.
* src/misc.c: Likewise.
2010-09-18 00:40:16 -07:00
Paul Eggert
098ad10c71 tar: switch to gnulib fdutimensat module
* gnulib.modules: Add fdutimensat.
* src/common.h (fd_utimensat): Remove decl.
* src/extract.c (set_stat): Call fdutimensat, not fd_utimensat.
* src/misc.c (set_file_atime): Likewise.
(fd_utimensat): Remove.
2010-09-17 14:24:04 -07:00
Paul Eggert
6e08ab7694 tar: extract permissions for . last
* src/common.h (must_be_dot_or_slash): New decl.
* src/extract.c (mark_after_links): New function, taking code
that used to be in create_placeholder_file.
(create_placeholder_file): Use it.
(delay_set_stat): Always delay setting status for . and /.
* src/misc.c (must_be_dot_or_slash): Now extern.
* tests/extrac12.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Likewise.
2010-09-17 12:28:25 -07:00
Paul Eggert
cecb7ac8e6 tar: don't check for getdtablesize; use AC_CHECK_FUNCS_ONCE
* configure.ac: Don't check for getdtablesize; no longer needed.
Use AC_CHECK_FUNCS_ONCE rather than AC_CHECK_FUNCS, for efficiency.
2010-09-17 10:48:03 -07:00
Paul Eggert
ea964cce81 tar: extract symlink attributes, close some symlink-related races
* NEWS: Describe symlink-extraction improvements.
* src/extract.c (enum permstatus): Remove.
(fchmod, fchown): Define dummy replacement macros if the system
does not supply them.
(implemented): New function.
(struct delayed_set_stat): Remove members invert_permissions,
permstatus.  They were too confusing, and tried to do too much
in too-little space.  Instead, add members current_mode,
current_mode_mask, interdir, atflag.  All users changed.
(struct delayed_link): Add members mode, atime, mtime, to support
platforms such as BSD where symlinks have these attributes.
All users changed.
(fd_chmod): Renamed from fdchmod.  New argument atflag.  Check for
operation not supported at run-time, not at configure-time.  Put
fd argument first.  All callers changed.
(fd_chown): Likewise, renaming from fdchown.
(fd_stat): Likewise, renaming from fdstat.
(set_mode): Remove args stat_info, cur_info, invert_permissions,
permstatus.  Add args mode, mode_mask, current_mode, current_mode_mask,
atflag.  All callers changed.  Close some races.  Use an easier-to
understand method for computing permissions.  Work around POSIX
incompatibility in Linux fchmodat.  Support extraction of symlink
modes, if the OS allows it.
(set_stat): Remove args cur_info, invert_permissions, permstatus.
Add args current_mode, current_mode_mask, interdir, atflag.
All callers changed.  Close some races.  Support extraction of
attributes on symlinks, if the OS allows it.
(delay_set_stat): Remove args invert_permissions, permstatus.
Add args current_mode, current_mode_mask, mode, atflag.
The ST arg can be null now, indicating that it's an intermediate
directory.  All callers changed.
(repair_delayed_set_stat, apply_nonancestor_delayed_set_stat):
Close some races.
(extract_dir): Also be paranoid if only --same-permissions, due
to semantics of setgid and setuid directories on some hosts.
This closes a race on those hosts.  Simplify calculation of
delay_set_stat arguments; the old code was truly strange and
probably wrong in some border cases.
(extract_dir, extract_file, extract_node, extract_fifo): Don't rely on
unspecified behavior in mode arg of open, mknod, etc.  Instead,
mask out those bits when creating the file, and add them later via
fchmod or chmodat.
(open_output_file): file_name is now const.  Add arg current_mode,
current_mode_mask.  All callers changed.  When overwriting old files,
refuse to overwrite something that is not a regular file, since
we're extracting a regular file.
(extract_file): Remove the FIXME comment.  Whatever the protection
issues were, they should be fixed now.  As a result of all the other
API changes, we now use fchmod etc. rather than chmod etc., closing
some races.
(create_placeholder_file, apply_delayed_links): Record desired
mode and times for symlinks, for OSes that support that.
2010-09-17 10:44:13 -07:00
Paul Eggert
e3fdb78d4b tar: tar -x without --incremental no longer sets atime again
* src/extract.c (set_stat): Use UTIME_OMIT rather than UTIME_NOW.
The UTIME_NOW was there only to emulate the previous behavior of
using the current time, and the previous behavior was there only
because before we started assuming POSIX.1-2008 there was no
portable way to get the effect of UTIME_NOW.
2010-09-16 11:02:26 -07:00
Paul Eggert
d945888643 tar: another --atime-preserve race fix
* src/common.h (set_file_atime): Add parentfd arg.
* src/compare.c (diff_file): Use it.
* src/create.c (dump_file0): Likewise.  This closes yet another
race condition with symbolic links.
* src/misc.c (set_file_atime): Add parentfd arg.
2010-09-16 10:47:07 -07:00
Paul Eggert
ecbcb7b6d7 tar: --atime-preserve fixes for races etc.
This patch fixes a race condition in the --atime-preserve=replace
option, which might cause tar to improperly follow a symbolic link.

It also drops the use of the _FIOSATIME ioctl of Solaris 2.x
and later, which loses resolution on time stamps.  Modern Solaris
systems support full-resolution time stamps in the kernel, and
it's not worth the hassle of testing this call, useful only in
no-longer-supported Solaris variants.

Also, it undoes a change I recently introduced to the --compare
option, which caused it to not follow symbolic links unless the
--dereference option was also used.  Quite possibly this change is
a good idea, but the old behavior was documented and the change
should not have been installed casually.

* configure.ac: Don't check for stropts.h and sys/filio.h.
* gnulib.modules: Add futimens, utimensat.  Remove futimens.
* src/common.h (fd_utimensat): New decl.
* src/compare.c (diff_file, diff_multivol):
Don't use open_read_flags: those are for --create only.
* src/create.c (dump_file0): Adjust to set_file_atime changes.
Pass fstatat_flags to set_file_atime, so that symbolic links are
not followed inadvertantly.
* src/extract.c: Don't include utimens.h.
(set_stat): Use fd_utimensat ant UTIME_NOW rather than fdutimens.
* src/misc.c: Don't include utimens.h, stropts.h, sys/filio.h.
(fd_utimensat): New function.
(set_file_atime): Use it.  New arg atflag, controlling symlink
handling.  All callers changed.
2010-09-16 10:17:04 -07:00
Paul Eggert
59146768ef * configure.ac: tar: close some race conditions when extracting
* configure.ac: Check for fchmod and fchown.  Don't check for utimes.
* src/extract.c (fdchmod, fdchown, fdstat): New functions.
(set_mode, set_stat): New arg FD.  All callers changed.
This avoids some race conditions between closing a regular file
and setting its metadata, and it's a bit faster.
2010-09-14 13:34:25 -07:00
Paul Eggert
0fb3020da0 tar: don't worry about fdopendir closing its argument
* NEWS: Don't mention dirfd; no longer needed.
* gnulib.modules: Remove dirfd.
* src/create.c (get_directory_entries): Remove the code dealing
with dirfd failures, as the new fdopendir replacement doesn't
close its argument so we don't need to call dirfd.  See
<http://lists.gnu.org/archive/html/bug-gnulib/2010-09/msg00208.html>
and gnulib commit 970c9038e4cca46e1b037ae0a6d574dfae6a7327.
2010-09-13 13:13:08 -07:00
Paul Eggert
d7db30d0e8 * NEWS: Fix wording typo in previous change.
Reported by Jim Meyering.
2010-09-13 00:22:53 -07:00
Paul Eggert
8da503cad6 tar: live within system-supplied limits on file descriptors
* NEWS: Note the change.  Mention dirfd and fdopendir.
* gnulib.modules: Add dirfd and fdopendir.  The code was already
using fdopendir; dirfd is a new need.
* src/common.h (open_searchdir_flags, get_directory_entries):
(subfile_open, restore_parent_fd, tar_stat_close): New decls.
(check_exclusion_tags): Adjust signature to match code change.
* src/create.c (IMPOSTOR_ERRNO): New constant.
(check_exclusion_tags): First arg is now a struct tar_stat_info
const *, not an fd.  All callers changed.
(dump_regular_file, dump_file0): A zero fd represents an unused
slot, so play it safe if the fd member is zero here.  A negative
fd represents the negation of an errno value, so play it safe and
do not assign -1 to fd merely because an open fails.
(open_failure_recover, get_directory_entries, restore_parent_fd):
(subfile_open): New functions.  These help to recover from file
descriptor exhaustion.
(dump_dir, dump_file0): Use them.
(dump_file0): Use tar_stat_close instead of rolling our own close.
* src/incremen.c (scan_directory): Use get_directory_entries,
subfile_open, etc., to recover from file descriptor exhaustion.
* src/names.c (add_hierarchy_to_namelist): Likewise.
(collect_and_sort_names): A negative fd represents the negation
of an errno value, so play it safe and do not assign -1 to fd.
* src/tar.c (decode_options): Set open_searchdir_flags.
Add O_CLOEXEC to all the open flags.
(tar_stat_close): New function, which knows how to deal with
new convention for directory streams and file descriptors.
Diagnose 'close' failures.
(tar_stat_destroy): Use it.
* src/tar.h (struct tar_stat_info): New member dirstream.
fd now has the negative of an errno value, not merely -1, if
the file could not be opened, so that failures to reopen directories
are better-diagnosed later.
* tests/Makefile.am (TESTSUITE_AT): Add extrac11.at.
* tests/testsuite.at: Likewise.
* tests/extrac11.at: New file.
2010-09-12 14:27:13 -07:00
Paul Eggert
c743301494 tar: improve documentation of reliability and security issues
* doc/tar.texi (Reliability and security, Reliability):
(Permissions problems, Data corruption and repair, Race conditions):
(Security, Privacy, Integrity, Live untrusted data):
(Security rules of thumb): New nodes.
2010-09-08 13:40:27 -07:00
Paul Eggert
de328a580a tar: more reliable directory traversal when creating archives
* NEWS: Document this.
* gnulib.modules: Add openat, readlinkat.
* src/common.h (open_read_flags, fstatat_flags): New global variables.
(cachedir_file_p, dump_file, check_exclusion_tags, scan_directory):
Adjust to new signatures, described below.
(name_fill_directory): Remove.
* src/compare.c (diff_file, diff_multivol): Use open_read_flags.
* src/create.c (struct exclusion_tag): Exclusion predicates now take
a file descriptor, not a file name.
(add_exclusion_tag): Likewise.  All uses changed.
(cachedir_file_p): Likewise.
(check_exclusion_tags): The directory is now a file descriptor,
not a file name.  All uses changed.  Use openat for better traversal.
(file_dumpable_p): Arg is now a struct stat, not a struct
tar_stat_info.  All uses changed.  Check the arg's file types too.
(dump_dir0, dump_dir, dump_file0, dump_file): Omit top_level and
parent_device args, since st->parent tells us that now.  All uses
changed.
(dump_dir): Likewise.  Also, omit fd arg for similar reasons.
Apply fdsavedir to a dup of the file descriptor, since we need a
file descriptor for openat etc. as well, and fdsavedir (perhaps
unwisely) consumes its file descriptor when successful.
Do not consume st->fd when successful; this simplifies the caller.
(create_archive): Allocate a file descriptor when retraversing
a directory, during incremental dumps.
(dump_file0): Use fstatat, openat, and readlinkat for better traversal.
When opening a file, use the result of fstat on the file descriptor
rather than the fstatat on the directory entry, to avoid some race
conditions.  No need to reopen the directory since we now no longer
close it.  Change "did we open the file?" test from 0 <= fd to
0 < fd since fd == 0 now represents uninitialized.
(dump_file): Now accepts struct tar_stat_info describing parent,
not parent_device.  Also, accept basename and fullname of entry.
All uses changed.
* src/incremen.c (update_parent_directory): Accept struct
tar_stat_info for parent, not name.  All callers changed.
Use fstatat for safer directory traversal.
(procdir): Accept struct tar_stat_info, not struct stat and
dev_t, for info about directory.  All callers changed.
(scan_directory): Accept struct tar_stat_info, not name,
device, and cmdline, for info about directory.  All callers
changed.  Do not consume the file descriptor, since caller
might need it.  Use fstatat and openat for safer directory
traversal; also, use fstat after opening to double-check.
(name_fill_directory): Remove.
* src/names.c (add_hierarchy_to_namelist): Accept struct
tar_stat_info instead of device and cmdline.  All callers changed.
When descending into a subdirectory, use openat and fstat for
safer directory traversal.
(collect_and_sort_names): Use open and fstat for safer directory
traversal.  Set up struct tar_stat_info for callee's new API.
* src/tar.c (decode_options): Initialize open_read_flags
and fstatat_flags.
(tar_stat_destroy): Close st->fd if it is positive (not zero!).
* src/tar.h (struct tar_stat_info): New members parent, fd.
* src/update.c (update_archive): Adjust to dump_file's API change.
* tests/filerem02.at: Ignore stderr since its contents now depend
on the file system implementation.
2010-09-06 13:39:21 -07:00
Paul Eggert
bad4b0006c tar: remove lint discovered by Sun C compiler
* src/common.h (WARN_ALL): Don't mask with 0xffffffff; on a 32-bit
host, 0xffffffff is of type 'unsigned int', which makes WARN_ALL
an unsigned int value that is too large to fit into an int, and
the C standard says that this has undefined behavior.  The mask is
not needed, so omit it.
2010-09-04 23:53:23 -07:00
Paul Eggert
e985feb292 tar: restore macros that are used in some cases
* src/tar.c (LOW_DENSITY_NUM, MID_DENSITY_NUM, HIGH_DENSITY_NUM):
Restore these macros, undoing the previous change to this file.
The macros are used after all, in some cases.  Sorry about that.
2010-09-04 00:09:30 -07:00
Paul Eggert
fbc54fa337 tar: remove unused macros
* src/create.c (UINTMAX_TO_CHARS): Remove; no longer used.
* src/tar.c (LOW_DENSITY_NUM, MID_DENSITY_NUM, HIGH_DENSITY_NUM):
Likewise.
* src/incremen.c (DIR_IS_NEW): Comment out; not used.
Mark this with a FIXME, since it looks like it should be used.
2010-09-02 20:46:25 -07:00
Sergey Poznyakoff
45a574151a Fix --remove-files in update/append mode.
* src/update.c (update_archive): Call finish_deferred_unlinks when
done.
2010-08-27 15:36:24 +03:00
Paul Eggert
0adf4027f5 tar: avoid assumptions about root access and chmod -w in test cases
* tests/extrac07.at, tests/extrac09.at, tests/listed03.at: Use
AT_UNPRIVILEGED_PREREQ, since this test requires non-root
privileges.
* tests/extrac07.at: Don't use "chmod -w", as POSIX says it's not
portable to start a chmod permissions-list with "-" as it may be
confused with an option.  Use "chmod a-w" instead.
2010-08-26 10:23:06 -07:00
Paul Eggert
fce1c1c8cb tar: fix bug with -C and delayed setting of metadata
* src/common.h (chdir_current): New decl.
* src/extract.c (struct delayed_set_stat, struct delayed_link):
New member change_dir.
(delay_set_stat, create_placeholder_file): Set it.
(apply_nonancestor_delayed_set_stat, apply_delayed_links): Use it.
(extract_link): Check that the links are all relative to the same
directory.
(extract_archive): Restore the current directory after
apply_nonancestor_delayed_set_stat has possibly changed it.
* src/misc.c (chdir_current): New external var; this used to
be the private static variable 'previous' inside chdir_dir.
All uses changed.
* tests/Makefile.am (TESTSUITE_AT): New test extrac10.at.
* tests/extrac10.at: New file.
* tests/testsuite.at: Include it.
2010-08-25 17:09:59 -07:00
Sergey Poznyakoff
372ac37d01 Don't apply file transformations to volume names.
* src/list.c (decode_header): Don't apply file transformations to volume names.
* tests/xform01.at: New testcase.
* tests/xform-h.at (xform): Rename macro to xformtest. Use pushdef/popdef.
* tests/Makefile.am, tests/testsuite.at: Add xform01.at
2010-08-25 10:54:45 +03:00
Paul Eggert
a9895fd20c tar: optimize -c --sparse when file is entirely sparse
* src/sparse.c (sparse_scan_file): If the file is entirely sparse,
that is, if ST_NBLOCKS is zero, don't bother scanning for nonzero
blocks.  Idea by Kit Westneat, communicated by Bernd Schubert in
<http://lists.gnu.org/archive/html/bug-tar/2010-08/msg00038.html>.
Also, omit unnecessary lseek at start of file.
2010-08-24 17:29:06 -07:00
Paul Eggert
a59c819beb tar: don't assume size of a sparse file chunk fits in size_t
* src/tar.h (struct sp_array): Change numbytes from size_t to off_t.
All uses changed.
* scripts/xsparse.c (struct sp_array): Likewise.
Include <stdint.h>, for SIZE_MAX.
(expand_sparse): Don't try to allocate a buffer bigger than
SIZE_MAX bytes.
* src/common.h (SIZE_TO_CHARS, size_to_chars, SIZE_FROM_HEADER):
(size_from_header): Remove decls.
* src/create.c (size_to_chars): Remove.
* src/list.c (size_from_header): Remove.
* src/sparse.c (sparse_extract_region, check_data_region):
(oldgnu_add_sparse, oldgnu_store_sparse_info, pax_decode_header):
Don't assume chunk sizes fit in size_t.
(oldgnu_add_sparse): Check for off_t overflow.
* src/xheader.c (sparse_numbytes_decoder, sparse_map_decoder):
Likewise.
2010-08-24 16:50:49 -07:00
Paul Eggert
57b11473b0 tar: use ctime, not mtime, when checking placeholders
* src/extract.c (struct delayed_link): Rename member mtime to ctime.
All uses changed to use ctime rather than mtime.
2010-08-24 15:44:25 -07:00
Paul Eggert
fbcadc9592 tar: add comment to link04.at test
* tests/link04.at: Add explanatory comment at head.
2010-08-24 08:18:37 -07:00
Paul Eggert
3b219f943e tar: fix 1.23 Solaris regression related to PRIV_SYS_LINKDIR
The idea was suggested by Petr Sumbera in the thread starting here:
http://lists.gnu.org/archive/html/bug-tar/2010-08/msg00000.html
* src/extract.c (set_mode): Save the errno of the chmod that
failed, for the benefit of chmod_error_details.  Do not bother
retrying chmod unless the mode suggests setuid is the issue.
(extract_archive): Remove redundant call to priv_set_remove_linkdir.
* src/system.c: Include priv-set.h.
(sys_spawn_shell, sys_child_open_for_compress):
(sys_child_open_for_uncompress, sys_exec_command):
(sys_exec_info_script, sys_exec_checkpoint_script):
Invoke priv_set_restore_linkdir before execv or execlp, so that
the subprocess has the same privileges that tar originally did.
2010-08-24 00:07:50 -07:00
Paul Eggert
37ddfb0b7e tar: handle files that occur multiple times but have link count 1
This patch was inspired by the following patch that addressed a
similar problem in GNU coreutils du:
http://git.savannah.gnu.org/gitweb/?p=coreutils.git;h=efe53cc72b599979ea292754ecfe8abf7c839d22
* src/common.h (name_count): New decl.
* src/create.c (trivial_link_count): New static var.
(create_archive): Initialize it.
(dump_hard_link, file_count_links): Use it, so that files with
link count 1 are handled correctly when they are found multiple times.
* src/names.c (allocated_entries): Renamed from allocated_names,
since the identifier's name was misleading.  All uses changed.
(entries): Renamed from names.  All uses changed.
(scanned): Renamed from name_index.  All uses changed.
(name_count): New var.
(name_add_name): Increment it.
* tests/link04.at: New file.
* tests/testsuite.at: Add it.
* tests/Makefile.am (TESTSUITE_AT): Likewise.
2010-08-23 19:13:12 -07:00
Paul Eggert
09f039050e tar: use nlink_t for link counts
* src/create.c (struct link): nlink is now of type nlink_t, not size_t.
2010-08-23 13:49:49 -07:00
Paul Eggert
34795cedb7 tar: don't export names that aren't used elsewhere
* src/common.h (file_dumpable_p, gid_to_chars, major_to_chars):
(minor_to_chars, mode_to_chars, uid_to_chars, uintmax_to_chars):
(string_to_chars, dumpdir_creat0, dumpdir_create, dumpdir_free):
(dumpdir_locate, dumpdir_next, dumpdir_first, gid_from_header):
(major_from_header, minor_from_header, mode_from_header):
(time_from_header, uid_from_header, quote_copy_string, request_stdin):
(xheader_init, transform_header_name):
Remove declarations; these are no longer exported from their modules.
(GID_TO_CHARS, MAJOR_TO_CHARS, MINOR_TO_CHARS, MODE_TO_CHARS):
(UID_TO_CHARS, UINTMAX_TO_CHARS, UNAME_TO_CHARS, GNAME_TO_CHARS):
Move to src/create.c, since no other module uses these.
(GID_FROM_HEADER, MAJOR_FROM_HEADER, MINOR_FROM_HEADER):
(MODE_FROM_HEADER, TIME_FROM_HEADER, UID_FROM_HEADER):
Move to src/extract.c, since no other module uses these.
(dumpdir_t, dumpdir_iter_t): Remove; no longer used.
* src/create.c (gid_to_chars, major_to_chars, minor_to_chars):
(mode_to_chars, uid_to_chars, uintmax_to_chars, string_to_chars):
(file_dumpable_p): Now static.
* src/incremen.c (dumpdir_create0, dumpdir_create, dumpdir_free):
(dumpdir_locate, dumpdir_next, dumpdir_first): Now static.
(scan_directory, write_directory_file_entry):
Use struct dumpdir_iter * rather than dumpdir_iter_t.
* src/list.c (gid_from_header, major_from_header, minor_from_header):
(mode_from_header, time_from_header, uid_from_header):
(transform_member_name): Now static.
* src/misc.c (quote_copy_string): #if 0 out, as it's not used
anywhere.
* src/system.c (wait_for_grandchild): Now static.
* src/tar.c (request_stdin): Now static.
* src/xheader.c (xheader_init): Now static.
2010-08-23 13:27:36 -07:00
Paul Eggert
9764a6b1d3 tar: fix misspelled identifier "set_comression_program_by_suffix"
* src/suffix.c (set_compression_program_by_suffix): Renamed from
set_comression_program_by_suffix.
* src/buffer.c, src/common.h, src/tar.c: All uses changed.
2010-08-23 11:37:19 -07:00
Paul Eggert
a1a15e3202 tar: change interdir_made from int to bool
* src/extract.c (maybe_recoverable, create_placeholder_file):
Change interdir_made from int * to bool *, since the flag has just
two values 0 and 1.  All uses changed.  This does not affect tar's
behavior.
2010-08-20 01:09:17 -07:00
Paul Eggert
0ab5e64ac0 tar: remove trailing white space from source files
* ChangeLog.1, ChangeLog.CVS, Makefile.am, NEWS, README:
* README-hacking, directory, doc/Makefile.am, doc/dumpdir.texi:
* doc/gendocs_template, doc/intern.texi, doc/mastermenu.el:
* doc/snapshot.texi, doc/sparse.texi, doc/tar-snapshot-edit.texi:
* doc/value.texi, lib/Makefile.am, scripts/backup-specs:
* scripts/dump-remind.in, scripts/tar-snapshot-edit, scripts/tarcat:
* scripts/xsparse.c, src/arith.h, src/buffer.c, src/compare.c:
* src/create.c, src/delete.c, src/exit.c, src/suffix.c, src/tar.c:
* src/tar.h, src/update.c, src/warning.c, src/xheader.c:
* tests/append01.at, tests/append02.at, tests/atlocal.in:
* tests/delete03.at, tests/exclude.at, tests/exclude06.at:
* tests/extrac04.at, tests/extrac05.at, tests/extrac06.at:
* tests/extrac07.at, tests/filerem01.at, tests/filerem02.at:
* tests/incr01.at, tests/incr02.at, tests/incr03.at, tests/incr06.at:
* tests/label02.at, tests/label03.at, tests/label04.at:
* tests/label05.at, tests/link02.at, tests/link03.at:
* tests/listed01.at, tests/listed02.at, tests/long01.at:
* tests/longv7.at, tests/multiv01.at, tests/multiv02.at:
* tests/multiv03.at, tests/multiv05.at, tests/multiv06.at:
* tests/multiv07.at, tests/multiv08.at, tests/options.at:
* tests/options02.at, tests/remfiles03.at, tests/rename01.at:
* tests/rename02.at, tests/rename03.at, tests/rename04.at:
* tests/rename05.at, tests/same-order01.at, tests/same-order02.at:
* tests/shortfile.at, tests/shortupd.at, tests/sparse01.at:
* tests/sparse02.at, tests/sparsemv.at, tests/sparsemvp.at:
* tests/star/README, tests/star/gtarfail2.at:
* tests/star/multi-fail.at:
* tests/star/pax-big-10g.at, tests/star/quicktest.sh:
* tests/star/ustar-big-2g.at, tests/star/ustar-big-8g.at:
* tests/update01.at, tests/update02.at, tests/volsize.at:
* tests/volume.at:
Remove trailing spaces and tabs from lines, and remove
trailing empty lines from files.  This makes it a bit easier
to share code among coreutils and other projects that do this.
2010-08-19 15:50:07 -07:00
Paul Eggert
0a694a16e5 tar: update licenses to latest versions from www.gnu.org
* COPYING: Update to latest version; this is just minor formatting.
* doc/fdl.texi: Update from GFDL 1.2 to 1.3.
* doc/tar.texi: Adjust to new format of fdl.texi.  Omit trailing
white space.
2010-08-19 04:15:42 -07:00
Paul Eggert
b3b15f7cbc * src/misc.c (struct wd): Fix comment to match code. 2010-07-18 12:34:13 -07:00
Paul R. Eggert
8c662c9f29 tar: no need to report getcwd error if never using the result
* src/misc.c (struct wd): Rename 'saved' to 'err', with new semantics.
(chdir_arg, chdir_do): Adjust to new semantics.  Do not report an
error merely because save_cwd fails; report an error only if
save_cwd's result is needed later.
* tests/extrac09.at: New file, to test for bug that was fixed.
* tests/testsuite.at: Include it.
* tests/Makefile.am (TESTSUITE_AT): Add it.
2010-07-18 12:20:47 -07:00
Paul R. Eggert
427b3b8c79 tar: go back to absolutifying filenames in normalize_filename for now
* src/misc.c (normalize_filename): For now, go back to making
filenames absolute, even though this causes 'tar' to fail when
getcwd fails.  However, do not attempt to resolve ".." as this
does not work with symlinks.  Also, do the right thing with
leading file system prefixes and on hosts where // != /.
2010-07-17 15:47:46 -07:00
Sergey Poznyakoff
c1b30c268f Allow for size suffixes in -L and --record-size options.
* src/tar.c (TAR_SIZE_SUFFIXES): New define.
(parse_opt): Allow for size suffixes in arguments to
-L and --record-size options.
* NEWS, doc/tar.texi: Update.
2010-07-17 11:38:08 +03:00
Paul R. Eggert
cc40c57a37 tar: don't crash if getcwd fails
* src/extract.c: Don't include xgetcwd.h.
(extract_dir): stat "." rather than statting getcwd's output.
* src/misc.c (normalize_filename_x): Rewrite so as not to resolve
/../, which can't be done reliably in the presence of symlinks.
Don't reject valid names such as ".".
(normalize_filename): Don't make it absolute; that way, we don't
have to invoke xgetcwd which might fail.  Don't bother to realloc
at the end, since that uses time and now saves little space.
(chdir_do): Don't crash if xgetcwd fails.
* tests/Makefile.am (TESTSUITE_AT): Add listed03.at.
* tests/listed03.at: New file.
* tests/testsuite.at: Include listed03.at.
2010-07-15 11:25:15 -07:00
Sergey Poznyakoff
ab6dd4948d Keep a detailed map of archive members stored in the record buffer.
A separate map (bufmap) provides information for creating
multi-volume continuation headers.

* src/buffer.c (bufmap): New struct.
(bufmap_head, bufmap_tail, inhibit_map): New variables.
(mv_begin_write): New function.
(mv_begin): Rename to mv_begin_read. Rewrite using mv_begin_write.
All callers changed.
(mv_total_size): Remove.
(bufmap_locate, bufmap_free, bufmap_reset): New functions.
(_flush_write): Update bufmap.
(close_archive): Free bufmap.
(add_chunk_header): Take a bufmap argument.
(gnu_add_multi_volume_header): Likewise.
(add_multi_volume_header): Likewise.
(_gnu_flush_write): Rewrite using bufmap.
(real_s_name, real_s_totsize)
(real_s_sizeleft)
(save_name, save_totsize, save_sizeleft): Removed. All
uses updated.
(mv_size_left): Update bufmap_head.
(mv_end): Rewrite.
(multi_volume_sync): Remove.

* src/common.h (mv_begin_write): New prototype.
(mv_begin): Rename to mv_begin_read.
* src/create.c: Use mv_begin_write instead of mv_begin.
Remove calls to mv_size_left and mv_end.
* src/sparse.c: Likewise.

* tests/multiv07.at: Close stdin.
* tests/spmvp00.at: Update AT_KEYWORDS.
* tests/spmvp10.at: Likewise.

* tests/multiv08.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add multiv08.at.
2010-07-11 22:57:17 +03:00
Sergey Poznyakoff
b4bcb97e38 Version 1.23.90
* NEWS, configure.ac: Version 1.23.90
* doc/tar.texi: Document the use of lbzip2.
2010-07-11 19:36:43 +03:00
Sergey Poznyakoff
9c194c9942 Fix exclusion of long file names when extracting from pax format archives.
* src/list.c (read_and): Call decode_header before attempting
name_match.
(list_archive): Remove call to decode_header.

* src/compare.c (diff_archive): Remove call to decode_header.
* src/extract.c (extract_archive): Likewise.

* test/exclude06.at: New test case.
* tests/testsuite.at: Include exclude06.at.
* tests/Makefile.am (TESTSUITE_AT): Add exclude06.at.
2010-06-28 16:56:54 +03:00
Sergey Poznyakoff
80a6ef7d94 Minor fix.
* src/buffer.c (magic): Split the character constant to help
cc recognize character boundaries (7 is a valid hex character).
2010-06-28 00:04:49 +03:00
Sergey Poznyakoff
9b31db388e Minor fix.
* src/buffer.c (magic): Fix xz magic.
2010-06-27 23:47:20 +03:00
Paul Eggert
f6edb92580 Remove some lint, found by gcc -W etc.
* src/common.h (label_notfound): New decl.
* src/buffer.c (set_volume_start_time, compress_type):
(guess_seekable_archive, open_compressed_archive, init_buffer):
(_flush_write, archive_is-dev, increase_volume_number):
(change_tape_menu, try_new_volume, add_chunk_header):
(multi_volume_sync):
Declare as 'static' if it's not exported.
Use function prototype (void) rather than old-style ().
* src/checkpoint.c (expand_checkpoint_string): Likewise.
* src/incremen.c (dirlist_replace_prefix, makedumpdir, read_incr_db_2):
Likewise.
* src/list.c (print_volume_label): Likewise.
* src/misc.c (normalize_filename_x): Likewise.
* src/names.c (make_name, free_name, check_name_alloc, name_next_elt):
Likewise.
* src/tar.c (tar_list_quoting_style, add_exclude_array):
(set_stat_signal): Likewise.
* src/transform.c (new_transform, _single_transform_name_to_obstack):
(_transform_name_to_obstack): Likewise.
* src/unlink.c (dunlink_alloc): Likewise.

* src/buffer.c (struct zip_magic): Use const when appropriate.
* src/incremen.c (obstack_code_rename, write_directory_file_entry):
Likewise.
* src/sparse.c (COPY_STRING): Likewise.
* src/system.c (dec_to_env, time_to_env, oct_to_env, str_to_env):
(chr_to_env): Likewise.
* src/tar.c (tar_list_quoting_style, set_stat_signal): Likewise.

* src/extract.c (extract_node): Don't return garbage.

* src/names.c: Remove old-style declarations of getgrnam etc.
All modern systems declare these, and it's not worth the hassle
of ignoring the warnings on modern systems for old-style decls.
2010-06-16 13:04:12 -07:00
Sergey Poznyakoff
e21d54e8cd Bugfix.
* src/incremen.c (make_directory): Retain the slash if it is the
only character in a filename.
2010-05-17 20:22:16 +03:00
Sergey Poznyakoff
c79f0d06bc Recode NEWS back to UTF-8 2010-04-02 14:24:58 +03:00
Sergey Poznyakoff
2c97cb7ea2 Fix the gzip.at test case.
* tests/gzip.at: Suppress gzip error output, as it can differ
depending on its version etc. Bug reported by Ludovic Courtès.
2010-04-01 00:03:51 +03:00
Sergey Poznyakoff
fc61c17410 New option --full-time.
* src/common.h (full_time_option): New global.
* src/tar.c (FULL_TIME_OPTION): New constant.
(options): New option --full-time.
(parse_opt): Handle the --full-time option.
* src/list.c (simple_print_header): Pass full_time_option
as the 2nd argument to tartime.
* doc/tar.texi: Update.
* NEWS: Update.
2010-03-28 12:26:37 +03:00
Sergey Poznyakoff
2981fcc5cb Minor fixes in the testsuite.
* tests/extrac07.at: Fix a typo (invalid number
of arguments before format list).
* tests/link02.at: Use `ln' instead of `link'.
* tests/link03.at: Likewise.
2010-03-27 22:46:18 +02:00
Sergey Poznyakoff
40dea1ae7f Fix coredump.
* src/names.c (collect_and_sort_names): Remove
entry from the table before freeing it.
2010-03-27 22:24:19 +02:00
Sergey Poznyakoff
b60e56fdb6 Fix dead loop on extracting existing symlinks with the -k option.
* src/extract.c (create_placeholder_file)
(extract_link, extract_symlink)
(extract_node, extract_fifo): Handle all possible
return values from maybe_recoverable. This complements
8f390db92f. Reported by Ico Doornekamp <bug-tar@zevv.nl>.
* NEWS: Update.
2010-03-27 22:02:28 +02:00
Sergey Poznyakoff
340dbf5aab Fix undesired error exit on receiving SIGPIPE.
* src/tar.c: Do not ignore SIGPIPE.
* tests/sigpipe.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add sigpipe.at
* tests/remfiles01.at: Fix error code expectation.
* NEWS: Update.
2010-03-20 13:20:30 +02:00
Sergey Poznyakoff
c1d3d13493 Fix --remove-files.
Tar --remove-files relied on canonicalize_file_name,
which replaces symlinks in file name components with
the directories they point to. Due to this, tar
effectively ignored existence of symbolic links and
was unable to remove a directory that contained any
(Alexander Kozlov <akozlov@nada.kth.se>, 2010-03-15).

* gnulib.modules: Remove canonicalize.
* src/misc.c (normalize_filename): Rewrite
from scratch. The function operates only on
its input string, it makes no attempt to test
components for existence or to resolve symbolic
links.
* tests/Makefile.am (TESTSUITE_AT): Add remfiles03.at.
* tests/testsuite.at: Likewise.
* tests/remfiles03.at: New test case.
* NEWS: Update.
2010-03-17 11:52:40 +02:00
Sergey Poznyakoff
67b4f3519d Bugfixes.
* src/buffer.c (check_label_pattern): Initialize result.
* tests/remfiles01.at: Skip if run with root privileges.
2010-03-12 09:48:46 +02:00
Sergey Poznyakoff
0ba8bdf5f3 Fix --test-label' and --label -r' behavior.
* doc/tar.texi (Including a Label in the Archive): Revise
the section.
* NEWS: Update

* src/buffer.c (open_archive): Check volume label on
ACCESS_UPDATE as well.
* src/list.c (test_archive_label): Rewrite to match the
documentation.
* src/names.c (regex_usage_warning): Return int.
(names_notfound): Rewrite the conditional.
(label_notfound): New function.

* tests/label03.at: New testcase.
* tests/label04.at: New testcase.
* tests/label05.at: New testcase.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
2010-03-11 17:41:23 +02:00
Sergey Poznyakoff
8d3cc6c3cf Doc fixes.
* doc/tar.texi: Consistently use lowercase `see' within sentences.
More fixes spotted by Denis Excoffier.
* THANKS: Update.
2010-03-11 15:06:18 +02:00
Sergey Poznyakoff
3f4a6d83f0 Shut up a gcc warning message.
* src/tar.c (tar_help_filter): Use a separate const
variable to hold returns from gettext. Reported by
Peter Breitenlohner.
2010-03-11 15:05:57 +02:00
Sergey Poznyakoff
a3f1d933cc Bugfix.
* src/names.c (collect_and_sort_names): Initialize prev_name.
Reported by Dmitry V. Levin.
2010-03-11 12:19:32 +02:00
Sergey Poznyakoff
e8e0b6cb7a Version 1.23
* configure.ac, NEWS: Update version number.
2010-03-10 13:53:15 +02:00
Sergey Poznyakoff
338add8d10 Doc changes.
* NEWS: Update.
* THANKS: Update.
* doc/snapshot.texi, doc/snapshot.texi,
doc/sparse.texi, doc/tar-snapshot-edit.texi,
doc/tar.texi: Spellchecked and proof-read. Thanks
to Denis Excoffier.
* gnulib.modules: Remove utime.
2010-03-10 13:22:49 +02:00
Kamil Dudka
46b07a52f9 Fix possible overflow in code_timespec (tiny change)
* src/misc.c (code_timespec): ignore invalid values of ns
2010-03-08 12:34:58 +02:00
Sergey Poznyakoff
a06b3a29fb Minor fix in the testsuite.
* tests/extrac05.at: Skip test if creating
sparse file fails.
2010-03-08 12:31:59 +02:00
Sergey Poznyakoff
6f02669c7b Fix eventual memory override and fd exhaustion in create.c
Both bugs reported by Kamil Dudka.

* src/create.c (check_exclusion_tags): Do not keep
pointer to a location within tagname: it may change
after xrealloc. Use byte offset instead.
(dump_file0): Close fd before returning without
dumping the directory.
2010-03-08 12:27:23 +02:00
Sergey Poznyakoff
e1e1f87eb4 Minor change.
* doc/tar.texi: Improve some wording.
2010-03-02 18:48:20 +02:00
Antonio Diaz Diaz
bffe1074aa Add Lzip support
* configure.ac: Add TAR_COMPR_PROGRAM(lzip)
* doc/tar.texi: Reflect lzip support.
* src/buffer.c (compress_type) <ct_lzip>: New constant.
(magic): Add magic for lzip.
* src/suffix.c (compression_suffixes): Add lz.
* src/tar.c: New option --lzip.
2010-03-02 18:44:25 +02:00
Sergey Poznyakoff
9a3e8a6f43 Minor fix.
* tests/exclude05.at: Rewrite awk invocation to avoid
overflowing awk's file table on Solaris.
2010-03-02 18:39:40 +02:00
Eric Blake
a0fd0d95e2 Fix large file support.
* scripts/xsparse.c (read_map): Use fseeko.
* src/incremen.c (write_directory_file): Likewise.
2010-03-02 18:08:07 +02:00
Sergey Poznyakoff
3925776b41 Bugfix
* src/buffer.c (seek_archive): Rewrite size computation
to prevent it from reaching negative values. Based on
report by Denis Excoffier <Denis.Excoffier@free.fr>.
2010-03-02 11:20:20 +02:00
Sergey Poznyakoff
762be4f2bd Supply more information to the --to-command script.
* src/system.c (stat_to_env): Pass information about the current
volume in variables TAR_ARCHIVE, TAR_VOLUME, TAR_BLOCKING_FACTOR,
TAR_FORMAT.
* doc/tar.texi: Document new environment variables.
* NEWS: Likewise.
* configure.ac: Version number 1.22.91.
2010-02-25 10:41:18 +02:00
Sergey Poznyakoff
b7899bb121 Minor change.
* src/names.c (regex_usage_warning): Fix warning message.
2010-02-17 16:48:34 +02:00
Sergey Poznyakoff
6e196273a4 Update THANKS 2010-02-05 18:41:15 +02:00
Ondřej Vašík
bdb9de4b1e Bugfix (tiny change)
* src/xheader.c (xheader_read): Remove unnecessary call
to xheader_init.
2010-02-05 18:39:53 +02:00
Sergey Poznyakoff
c4acbdaa97 Enable silent build mode.
* configure.ac: Require automake 1.11, autoconf 2.63. Enable silent rules.
* NEWS: Update.
* lib/Makefile.am (rmt-command.h): Silent the rule.
2010-01-26 13:42:48 +02:00
Sergey Poznyakoff
c3fa22fc80 Read POSIX multivolume archives split at the header boundary.
* src/common.h (read_header_mode): New enum.
(read_header): Change type of the 3rd argument.
* src/list.c (read_header): Change type of the 3rd argument.
All callers updated.
* src/buffer.c (try_new_volume): Allow for volumes split at the
extended/ustar header boundary. This is against POSIX specs, but
we must be able to read such archives anyway.

* tests/multiv07.at: New test case.
* tests/Makefile.am: Add multiv07.at
* tests/testsuite.at: Likewise.

* src/compare.c: Update calls to read_header.
* src/delete.c: Likewise.
* src/update.c: Likewise.
2010-01-25 17:03:28 +02:00
Sergey Poznyakoff
706bd01915 Minor change.
* NEWS: Update.
* doc/tar.texi: Update.
* src/create.c (finish_header): Minor change.
2010-01-24 22:45:57 +02:00
Rob Vermaas
0057cd6803 Bugfix (tiny change).
* src/tar.c (format_default_settings)[REMOTE_SHELL]: Fix
misplaced comma.
2010-01-24 22:24:49 +02:00
Sergey Poznyakoff
45cf3a7426 Minor fix.
* src/incremen.c (read_incr_db_01)
(read_directory_file): Initialize bufsize to 0.
Suggested by noordsij@cs.helsinki.fi.
2010-01-24 18:09:31 +02:00
Sergey Poznyakoff
28f2669b15 Improve handling of --test-label.
* src/list.c (print_volume_label): New function.
(print_header): Call print_volume_label.
(test_archive_label): New function.
* src/buffer.c (VOLUME_LABEL_APPEND): Remove.
(VOLUME_TEXT, VOLUME_TEXT_LEN): New macros
(drop_volume_label_suffix): New function.
(check_label_pattern): Use drop_volume_label_suffix.
* src/common.h (subcommand): New constant TEST_LABEL_SUBCOMMAND.
(test_label_option): Remove.
(drop_volume_label_suffix): New proto.
(test_archive_label): New proto.
* src/names.c (all_names_found): Remove test for test_label_option.
* src/tar.c (subcommand_string): Handle TEST_LABEL_SUBCOMMAND.
(set_subcommand_option): Improve diagnostics.
(parse_opt): Set subcommand if --test-label is given.
(main): Handle TEST_LABEL_SUBCOMMAND.
2010-01-24 16:58:04 +02:00
Sergey Poznyakoff
166b7c7d02 Fix listing of volume labels (in particular in PAX archives).
* src/buffer.c (match_volume_label): Call set_volume_label.
(check_label_pattern): Get label string
as argument.
(match_volume_label): Handle volume labels stored in
global PAX headers.
* src/common.c (print_header,read_header): Change signature.
(read_header_primitive): Remove prototype.
* src/list.c (recent_global_header): New static.
(list_archive): Always print volume labels.
(read_header_primitive): Remove.
(read_header): Change the signature (all callers updated)
Save the recent global header.
(volume_label_printed): New static.
(simple_print_header): New function (ex-print_header).
(print_header): Change the signature (all callers updated).
For POSIX formats, print first volume header (if set).
* src/xheader.c (xheader_write_global): Write the data
accumulated in xhdr->stk even if keyword_global_override_list
is empty.
(xheader_read): On unexpected EOF, report error instead of
coredumping.
(XHDR_PROTECTED, XHDR_GLOBAL): New defines.
(struct xhdr_tab): Remove `protected' with `flags'. All uses updated.
(decg): If XHDR_GLOBAL bit is set, call the keyword's decode
method instead of adding it to `kwl'.

* src/compare.c: Update calls to read_header.
* src/create.c: Likewise.
* src/delete.c: Likewise.
* src/update.c: Likewise.
* src/extract.c: Likewise.
(extract_volhdr): Do not print "Reading <label>" statement, because
it is inconsistent: it is not printed if the volume begins with a
member continued from the previous volume.

* tests/label01.at: New testcase.
* tests/label02.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add new testcases.
2010-01-24 15:52:22 +02:00
Sergey Poznyakoff
cd91cd3c62 Fix prefix length calculation in ustar mode.
* src/create.c (split_long_name): Fix prefix length
calculation.
(write_ustar_long_name): Improve ustar mode compatibility
with the Sun version.
2010-01-22 17:52:42 +02:00
Sergey Poznyakoff
cac45fffc5 Rewrite update algorithm.
* src/common.h (namebuf_t): New typedef.
(namebuf_create, namebuf_free)
(namebuf_name): New prototypes.
(remname): New prototype.
* src/misc.c (struct namebuf): New structure.
(namebuf_create, namebuf_free)
(namebuf_name): New functions.
* src/create.c (dup_dir0): Remove is_avoided_name
checks. This is taken care of in update_archive.
* src/incremen.c (scan_directory): Use namebuf
to produce full file names.
* src/names.c (nametail): Remove extra level of
indirection. All uses updated.
(avoided_name_table, add_avoided_name)
(is_avoided_name): Remove.
* src/update.c (update_archive): Change algorithm.
Instead of adding unmodified files to the avoided_name
table, create namelist so that it contains only
modified files.

* tests/Makefile.am: Add update01.at, update02.at
* tests/testsuite.at: Likewise.
* tests/update.at (AT_KEYWORDS): Add update00.
2009-10-14 23:26:52 +03:00
Sergey Poznyakoff
0c6c288b53 Minor changes.
* src/tar.c (main): Ignore SIGPIPE.
* src/system.c (sys_child_open_for_compress)
(sys_child_open_for_uncompress): Reset SIGPIPE
in child to default.
* tests/remfiles01.at: Avoid race conditions.
* tests/remfiles02.at: Likewise.
2009-10-14 17:55:15 +03:00
Sergey Poznyakoff
87240ee7c4 Bugfix.
* src/buffer.c (_open_archive): Call guess_seekable_archive
only if the call to open_compressed_archive succeeded.
2009-10-14 17:51:19 +03:00
Sergey Poznyakoff
84a55f12e5 Improve previous changes.
* acinclude.m4: Fix typos.
* gnulib.modules: Add xvasprintf.
* src/common.h: Include xvasprintf.h.
* src/tar.c (options): Remove docstrings for --gzip, --bzip2,
--compress, --lzop, --lzma and --xz.
(tar_help_filter): Generate these using actual values of
*_PROGRAM constants.
(format_default_settings): Use xasprintf.
(parse_opt): Use *_PROGRAM defines instead of hardcoded
program names.
2009-10-10 19:49:38 +03:00
Sergey Poznyakoff
a7e9b6a17b Allow installers to specify alternative program names for compression programs.
This adds --with-gzip, --with-bzip2 etc. switches to the configure, so that
one can do, e.g. ./configure --with-bzip2=lbzip2 and have lbzip2 executed
whenever user calls `tar --bzip2'.

* acinclude.m4: New file.
* configure.ac: Add TAR_COMPR_PROGRAM invocations for
the supported compressors.
* src/buffer.c (magic): Use *_COMPRESSOR defines instead
of hardcoded program names.
* src/suffix.c (compression_suffixes): Likewise.
2009-10-10 17:30:53 +03:00
Sergey Poznyakoff
f0ceef8596 Minor fix.
* src/buffer.c (magic): Fix `xz' entry: add the name of the program.
* src/suffix.c (compression_suffixes, nsuffixes): Mark as static.
2009-10-09 11:49:26 +03:00
Sergey Poznyakoff
63e092548a Provide a way to explicitly set mtime for extended header ustar blocks.
* src/tar.c (struct textual_date): ts is a copy of the structure,
not a pointer to it. Date is a copy as well, hence the `const' is
taken away.
(get_date_or_file): Return 0/1 depending on success/failure.
Copy timestamp to the `ts' member. Store a copy of the string
in `date'.
(report_textual_dates): Report only if verbose_option is set,
but always free the list.
(expand_pax_option): New function.
(parse_opt): Preprocess the argument to xheader_set_option with
expand_pax_option.
(decode_options): Call report_textual_dates unconditionally.
* src/xheader.c (exthdr_mtime_option, exthdr_mtime)
(globexthdr_mtime_option, globexthdr_mtime): New statics.
(xheader_set_keyword_equal): handle exthdr.mtime and globexthdr.mtime.
(xheader_write): Override `t' argument if a corresponding
exthdr.mtime or globexthdr.mtime option is set.
* NEWS: Update
* doc/tar.texi: Document the changes.
2009-10-07 21:08:29 +03:00
Sergey Poznyakoff
7cb84c25ee Use file's mtime as mtime for its extended header.
This makes two pax archives binary equivalent if they
have the same contents and care is taken to make extended
headers otherwise reproducible, e.g. by using:

  --pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0

Proposed by Michael D. Adams <mdmkolbe@gmail.com>.

* src/common.h (start_private_header): Take time_t as 3rd param.
(xheader_write): Likewise.
* src/create.c (start_private_header): Take time_t as 3rd param.
All callers updated.
(write_extended): Use file's mtime as mtime for its extended header,
Use current time stamp as mtime for global headers.
(xheader_write): Take time_t as 3rd param.
2009-10-07 18:40:07 +03:00
Sergey Poznyakoff
4dfcd6c054 Fix bugs in handling the --remove-files option.
Make sure the files are deleted only if they were succesfully stored
to the archive.

* src/exit.c: New file.
* src/unlink.c: New file.
* src/Makefile.am (tar_SOURCES): Add exit.c and unlink.c.
* src/common.h: Include progname.h
(program_name): Remove global.
(records_written): New extern.
(queue_deferred_unlink, finish_deferred_unlinks): New prototypes.
(fatal_exit_hook): New extern.
* src/create.c (create_archive): Call finish_deferred_unlinks.
(dump_hard_link, dump_file0): Don't actually unlink the file,
queue it to deferred_unlinks instead.
* src/delete.c (records_written): Remove extern: declared in
common.h.
* src/extract.c (extract_archive): Set fatal_exit_hook.
(fatal_exit, xalloc_die): Move to exit.c
* src/system.c (sys_wait_for_child): Exit immediately
if the child dies or exits with a non-zero status.
(sys_child_open_for_compress)
(sys_child_open_for_uncompress): Use set_program_name,
instead of setting program_name directly.
* src/tar.c (main): Use set_program_name,
instead of setting program_name directly.

* tests/Makefile.am (TESTSUITE_AT): Add remfiles01.at
and remfiles02.at.
* tests/testsuite.at: Likewise.
* tests/gzip.at: Reflect the above changes.
2009-10-07 16:42:06 +03:00
Sergey Poznyakoff
2947023d27 Fix bug in OLDGNU format creation.
See tests/append02.at for a detailed description

* src/common.h (MODE_FROM_HEADER): Take additional argument.
(mode_from_header): Likewise.
* src/create.c (mode_to_chars): Store all mode bits if
using OLDGNU_FORMAT. This reverses f4e4adea80.
* src/list.c (decode_header): Use header mode field
to discern between GNU and OLDGNU formats.
(mode_from_header): Store unrecognized mode bits (from 10th up)
in the location pointed to by the third parameter.
* tests/append02.at: Update documentation and references.
2009-10-04 23:38:34 +03:00
Sergey Poznyakoff
92773d860f Restore extra help output.
* src/tar.c (tar_list_quoting_styles): Change first argument to
struct obstack.
(format_default_settings): New function.
(show_default_settings)
(show_default_settings_fs): Removed.
(tar_help): Removed.
(tar_help_filter): New function.
(argp): Set help_filter.
(parse_opt): Fix error message.
2009-09-16 11:52:34 +03:00
Sergey Poznyakoff
dccb3806a6 Improve command line option handling.
* gnulib.modules: Add argp-version-etc and progname,
use getopt-gnu instead of getopt.
* src/tar.c (HANG_OPTION, USAGE_OPTION)
(VERSION_OPTION): Remove.
(options): Remove corresponding options. Let argp
handle them.
(parse_opt): Likewise.
(_argp_hang): Removed.
(tar_authors): New variable.
(decode_options): Call argp_version_setup.
Do not use ARGP_NO_HELP flag in the call to argp_parse.
2009-09-08 11:08:49 +03:00
Sergey Poznyakoff
0d8e324912 Avoid overwriting exit_status with a value indicating less important condition.
* src/tar.c (set_exit_status): New function.
* src/common.h (set_exit_status): New prototype.
* src/compare.c: Use set_exit_status instead of
exit_status assignments.
* src/create.c: Likewise.
* src/misc.c: Likewise.

* src/system.c (wait_for_grandchild): Use auto variable
instead of the global exit_status.
* src/incremen.c (scan_directory): Use file_removed_diag
instead of stat_diag.
2009-09-08 11:04:48 +03:00
Sergey Poznyakoff
cef4d5e838 Automatic detection of seekable archives.
* src/buffer.c (guess_seekable_archive): New function.
(_open_archive): Call guess_seekable_archive for archives
open for reading.
(new_volume): Likewise.
* src/common.h (seek_option): New global.
* src/tar.c (options): New option --no-seek.
(parse_opt): --seek and --no-seek set seek_option,
not seekable_archive.
(decode_options): Initialize seek_option to -1.

* NEWS: Update.
* doc/tar.texi: Update.
2009-09-08 10:27:57 +03:00
Sergey Poznyakoff
ba954ea1e1 Fix testcases.
* tests/extrac08.at: Ensure a predictable umask value.
* tests/xform-h.at (xform): do not depend on file name
ordering.
2009-08-27 20:12:14 +03:00
Sergey Poznyakoff
006c1efbe8 Fix interaction between --listed-incremental and -C
* src/incremen.c (read_directory_file): Execute eventual -C dir
after opening the snapshot file.
(collect_and_sort_names): Remove call to chdir_do
* tests/incr05.at, tests/incr06.at: Use relative file names for
snapshot files.
2009-08-13 16:45:49 +03:00
Sergey Poznyakoff
aeffa4f266 Update for new exclude module from gnulib. Add testcases by Phil Proudman.
* src/names.c (is_pattern): Remove.
(regex_usage_warning): Use fnmatch_pattern_has_wildcards instead of
is_pattern.
* src/tar.c: New option --exclude-backups.
(vcs_file_table, backup_file_table): New globals.
(add_exclude_array): New function.
* tests/exclude01.at, tests/exclude02.at,
tests/exclude03.at, tests/exclude04.at,
tests/exclude05.at: New testcases. Supplied by Phil Proudman.
* tests/Makefile.am (TESTSUITE_AT): Add new tests.
* tests/testsuite.at: Add new tests.
* THANKS: Update.
2009-08-12 19:25:29 +03:00
Sergey Poznyakoff
829b3feb26 Remove src/version.c (reappeared after migration to Git) 2009-08-10 01:03:31 +03:00
Sergey Poznyakoff
88347995b2 Minor fixes.
* src/misc.c (file_removed_diag): Set exit code to TAREXIT_DIFFERS.
2009-08-09 11:20:52 +03:00
Sergey Poznyakoff
acd833fb98 Minor fixes 2009-08-08 22:33:16 +03:00
Sergey Poznyakoff
51aee274e8 Fix handling of files removed during incremental dumps.
Changes to src/create.c and src/incremen.c are partially
based on patch from Alexander Peslyak <solar at openwall.com>.

The new testcases require paxutils commit f653a2b or later.

* src/common.h (struct name): New member `cmdline'.
(dump_file): Change type of the 2nd argument to bool.
(file_removed_diag, dir_removed_diag): New prototypes.
(addname): New argument `cmdline'.
(name_from_list): Change return value.
* src/create.c (dump_dir0, dump_dir): top_level is bool.
(create_archive): Update calls to name_from_list.
Take advantage of the name->cmdline to set top_level argument
during incremental backups.
(dump_file0): top_level is bool.
Do not bail out if a no-top-level file disappears during incremental
backup, use file_removed_diag instead.
(dump_filed): top_level is bool.
* src/incremen.c (update_parent_directory): Silently ignore
ENOENT.  It should have already been reported elsewhere.
(scan_directory): Use dir_removed_diag to report missing directories.
* src/misc.c (file_removed_diag, dir_removed_diag): New functions.
* src/names.c (name_gather): Set ->cmdname.
(addname): Likewise. All uses updated.
(name_from_list): Return struct name const *. All uses updated.

* tests/filerem01.at: New testcase.
* tests/filerem02.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add filerem01.at, filerem02.at
* tests/grow.at, test/truncate.at: Use new syntax for genfile --run.

* NEWS: Update.
* doc/tar.texi: Minor fix.
2009-08-08 19:53:54 +03:00
Sergey Poznyakoff
2b1bffbad6 Optimize searches for directory structures by keeping a pointer to struct directory in struct name.
* src/common.h (struct name): New member `directory' replaces
dir_contents. Rearrange members.
(rebase_directory): Change signature.
(scan_directory): Change signature.
(name_fill_directory)
(directory_contents, safe_directory_contents): New prototypes.
(append_incremental_renames): Change signature.
(replace_prefix): New proto.
* src/compare.c (diff_dumpdir): Use directory_contents + scan_directory.
* src/create.c
* src/incremen.c (replace_prefix): Move to misc.c
(rebase_directory): Rewrite.
(scan_directory): Return pointer to struct directory.
(directory_contents, safe_directory_contents): New functions.
(get_directory_contents): Remove.
(name_fill_directory): New function.
(append_incremental_renames): Rewrite. This also fixes a memory leak.
* src/names.c (name_gather, addname): Reflect changes in struct name.
(add_hierarchy_to_namelist): Rewrite using name_fill_directory and
directory_contents.
(rebase_child_list): Update call to rebase_directory.
(collect_and_sort_names): Optimize

* src/misc.c (replace_prefix): New function.
* src/names.c (add_hierarchy_to_namelist): Use new get_directory_contents.

* tests/incr05.at: New test case.
* tests/incr06.at: New test case.
* tests/Makefile.am, test/testsuite.at: Add incr05.at and incr06.at.

* doc/Makefile.am (check-options): Improve rule.
* doc/tar.texi, NEWS: Update.
2009-08-08 15:29:19 +03:00
Sergey Poznyakoff
df59690240 Minor fixes.
* src/common.h (rebase_directory): New prototype.
* src/incremen.c (rebase_directory): Use replace_prefix.
* src/names.c (collect_and_sort_names): Abort if
hash_insert fails.
2009-08-07 23:07:01 +03:00
Sergey Poznyakoff
1bcbbcf1ff Improve listed incremental dumps.
The modified algorithm tries to avoid dumping the same
directory twice and ensures the order of the directories
in the resulting archive is the same, whatever their order
on the command line.  It also fixes the operation of
--listed-incremental -C.

* gnulib.modules: Add canonicalize
* src/common.h (incremental_level): New global.
(check_exclusion_tags): first argument is const.
(get_directory_contents): Add third argument.
(zap_slashes, normalize_filename): New prototypes.
(chdir_count): New prototype.
(WARN_VERBOSE_WARNINGS): New define.
(WARN_ALL): Exclude WARN_VERBOSE_WARNINGS.
* src/compare.c (diff_dumpdir): Update the call to get_directory_contents.
* src/create.c (check_exclusion_tags): First argument is const.
Use ISSLASH and DIRECTORY_SEPARATOR instead of referring to '/'.

* src/incremen.c (struct directory): New member `caname'.
(hash_directory_name): Rename to hash_directory_canonical_name. Operate
on the canonical name.
(compare_directory_names): Rename to compare_directory_canonical_names.
Operate on the canonical name.
(make_directory): Take two arguments.
(free_directory): Free caname.
(attach_directory): Create caname.
(find_directory): Use caname for lookups.
(PD_VERBOSE): Remove.
(PD_FORCE_INIT): New define.
(procdir): First argument is const.
Reinitialize directory if PD_FORCE_INIT bit is set.
Do not use PD_VERBOSE or verbose_option for issuing warnings.
Rely on WARNOPT instead.
Always set *entry.
(scan_directory): Take three arguments. The third one is a boolean
which is true if the directory is explicitly mentioned on the command
line.
(get_directory_contents): Remove.  Use scan_directory instead.
All callers updated.
(read_directory_file): Truncate the file if --level=0 is given.
* src/misc.c: Include canonicalize.h
(zap_slashes, normalize_filename): New functions.
(chdir_count): New function.
* src/names.c (add_hierarchy_to_namelist): Take three arguments, as
get_directory_contents and scan_directory.
(collect_and_sort_names): Allow at most one -C, before file name
arguments.
Read directory file after eventual changing to another directory.
Avoid adding the same directory under different pathnames to
the list.
* src/tar.c: New option --level.

* tests/incr03.at, tests/incr04.at, tests/listed01.at,
tests/listed02.at, tests/rename01.at, tests/rename02.at,
tests/rename03.at: Update for new tar behavior.
* tests/multiv01.at: Do not use --listed-incremental.
2009-08-07 14:52:55 +03:00
Sergey Poznyakoff
ac5288c1ac Forgotten to push src/warning.c 2009-08-05 22:18:33 +03:00
Sergey Poznyakoff
67a1a0eac5 Implement the --warning option.
* src/warning.c: New file.
* src/Makefile.am: Add warning.c
* src/common.h: Provide definitions for warning classes.
(warning_option): New global.
(WARNOPT): New define.
(set_warning_option): New prototype.
* src/tar.c: New option `--warning'.
* src/compare.c: When applicable WARNOPT instead of WARN.
* src/create.c: Likewise.
* src/extract.c: Likewise.
* src/incremen.c: Likewise.
* src/list.c: Likewise.

* NEWS, doc/tar.texi: Update.
2009-08-05 13:52:38 +03:00
Carl Worth
471c0f76cd Fix descriptions of some options (tiny change) 2009-08-05 10:42:42 +03:00
Sergey Poznyakoff
755c246588 Fix backup handling and restoring file modes of existing directories
* NEWS, THANKS: Update
* src/extract.c (extract_dir): reset status to 0 if the
directory already exists.
* src/misc.c (maybe_backup_file): Assign before_backup_name
and clear after_backup_name before checking if we really need
to backup the file.
* tests/backup01.at: New testcase.
* tests/extrac08.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add extrac08.at and
backup01.at
2009-08-05 10:38:50 +03:00
Sergey Poznyakoff
5944f452b0 Fix hard links recognition with -c --remove-files
* src/create.c (dump_hard_link): Always look up in the link table
if remove_files_option is set. Patch suggested by Theodore Ts'o
<tytso@mit.edu>.
(check_links): Remove extra newline from the warning message.
* tests/link02.at, tests/link03.at: New testcases.
* tests/Makefile.am (TESTSUITE_AT): Add link02.at and link03.at
* tests/testsuite.at: Include link02.at and link03.at
2009-07-30 23:49:32 +03:00
Sergey Poznyakoff
f74cab3a93 Fix handling of hard link targets by -c --transform
* src/create.c (file_count_links): Transform link target
before the look up.
* tests/xform-h.at: New test case.
* tests/Makefile.am (TESTSUITE_AT): Add xform-h.at.
* tests/testsuite.at: Add xform-h.at
2009-07-30 11:43:16 +03:00
Sergey Poznyakoff
01c4475b17 Minor fix.
* src/extract.c (file_newer_p): Do not report error on ENOENT
2009-06-23 16:52:33 +03:00
Sergey Poznyakoff
b7d206cb1e Remove rebox.el (reappeared after migration to Git) 2009-06-19 15:49:17 +03:00
Sergey Poznyakoff
c30c4ffb9f Remove files that were removed in CVS, but reappeared after migration to Git 2009-06-18 14:24:50 +03:00
David Bartley
b216fed634 Fix Solaris bug where chmod fails if we don't have PRIV_SYS_LINKDIR
* gnulib.modules: Add priv-set.
* src/extract.c (set_mode, extract_archive): Restore
PRIV_SYS_LINKDIR on chmod failure.
* src/tar.c (main): Drop PRIV_SYS_LINKDIR on startup.
2009-06-18 13:57:10 +03:00
Sergey Poznyakoff
0d6720288b Ensure default behavior for SIGPIPE
* src/tar.c (main): Install default handler for SIGPIPE.
Proposed by Bastian Blank.
2009-06-18 13:05:48 +03:00
Eric Blake
da760e3faa Follow autoconf recommendation for TESTSUITEFLAGS.
* tests/Makefile.am (check-local, installcheck-local): Honor
TESTSUITEFLAGS.
2009-06-18 12:30:04 +03:00
Sergey Poznyakoff
af30244849 Fix handling of sub-subprocess returns.
* src/system.c (wait_for_grandchild): New function.
(sys_child_open_for_compress)
(sys_child_open_for_uncompress): Use wait_for_grandchild
to manage grandchild return.
2009-06-18 12:22:47 +03:00
Sergey Poznyakoff
be34933b63 Report record size only if the archive refers to a device.
* Makefile.am (INCLUDES): Add ../lib, for rmt-command.h
* src/buffer.c (short_read): Report the actual record size
only if the archive descriptor refers to a device.
* tests/pipe.at, tests/shortrec.at,
tests/sparsemvp.at: Reflect the above change.
* NEWS, configure.ac: Version 1.22.90
2009-05-25 10:18:59 +03:00
Sergey Poznyakoff
8f390db92f Do not issue errors on existing files when given the -k option
* Makefile.am (dist-hook): Fix rule.
* src/extract.c (maybe_recoverable): Return three-state value.
(extract_dir): Skip extraction if maybe_recoverable indicates so.
(extract_file): Likewise.
2009-05-14 11:28:41 +03:00
Eric Blake
705fab49eb Avoid undefined behavior
* src/xheader.c (xheader_set_keyword_equal): Pass correct type to
ctype macros.
* src/transform.c (run_case_conv): Likewise.
2009-05-12 12:12:15 +03:00
Sergey Poznyakoff
f14558de94 Remove src/Makefile.in 2009-05-12 12:11:17 +03:00
Sergey Poznyakoff
67cad0792b Bugfixes.
* bootstrap (symlink_to_dir): Fix symlink calculation.
* doc/tar.texi: Minor fixes by Victor Villa and Stepan Kasal.
2009-03-12 16:15:06 +02:00
178 changed files with 8489 additions and 10133 deletions

8
.gitignore vendored
View File

@@ -11,21 +11,21 @@
ABOUT-NLS
ChangeLog
INSTALL
Make.rules
Makefile
Makefile.in
Make.rules
aclocal.m4
autom4te.cache
build-aux
build-aux/
config.h
config.h.in
config.log
config.status
configure
gnu
gnulib
libtool
m4
paxutils
stamp-h1
build-aux/
gnu

18
COPYING
View File

@@ -1,12 +1,11 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
@@ -69,7 +68,7 @@ patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
TERMS AND CONDITIONS
0. Definitions.
@@ -77,7 +76,7 @@ modification follow.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
@@ -510,7 +509,7 @@ actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
@@ -619,9 +618,9 @@ an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -673,4 +672,3 @@ may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -1,4 +1,4 @@
Currently there is just one ChangeLog file for tar, but
Currently there is just one ChangeLog file for tar, but
there used to be separate ChangeLog files for each subdirectory.
This file records what used to be in those separate files.

View File

@@ -5,7 +5,7 @@
2009-03-04 Sergey Poznyakoff <gray@gnu.org.ua>
Add xz support.
* src/buffer.c, src/suffix.c: Add support for xz compression.
* src/tar.c: New option --xz, for compression/decompression using xz.
Re-assign -J as a short equivalent of --xz.
@@ -34,8 +34,8 @@
2008-11-25 Sergey Poznyakoff <gray@gnu.org.ua>
Do not try to drain the input pipe before closing the
archive.
archive.
* src/buffer.c (close_archive): Remove call to
sys_drain_input_pipe. Pass hit_eof as the second
argument to sys_wait_for_child.
@@ -63,7 +63,7 @@
* src/extract.c (extract_link, extract_symlink): Remove calls to
transform_member_name. It is done in read_header.
* src/list.c (decode_xform): Reflect change in data type of 2nd
argument.
argument.
(transform_member_name): 2nd arg is int.
(decode_header): Transform file name and link target names.
* src/tar.c: Remove --transform-symlinks.
@@ -73,7 +73,7 @@
set global flags using `flags=' syntax.
(_transform_name_to_obstack, transform_name_fp)
(transform_name): Take an additional argument, specifying scope
flags.
flags.
2008-10-19 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -86,7 +86,7 @@
* tests/sparsemvp.at: Likewise.
* tests/volsize.at: Likewise.
* NEWS: Update.
2008-10-16 Sergey Poznyakoff <gray@gnu.org.ua>
* src/common.h (transform_symlinks_option): New global.
@@ -99,11 +99,11 @@
* doc/tar.texi: Document --transform-symlinks
* NEWS: Update.
* THANKS: Update.
* src/names.c (name_gather): Use xzalloc.
* src/buffer.c (short_read): Move record size detection before
the loop.
2008-10-07 Sergey Poznyakoff <gray@gnu.org.ua>
* src/tar.c (options): Add --lzop option.
@@ -111,7 +111,7 @@
2008-10-05 Xavier Hienne <xavier.hienne@free.fr> (tiny change)
* src/checkpoint.c (checkpoint_compile_action): Add missing
`else'.
`else'.
2008-09-24 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -157,7 +157,7 @@
* tests/atlocal.in (decho): New function.
* tests/multiv06.at: Use decho instead of echo2.
* tests/incremental.at: Raise wait interval to 2 seconds.
2008-07-24 Sergey Poznyakoff <gray@gnu.org.ua>
* src/tar.c (decode_options): Do not allow volume length less
@@ -193,21 +193,21 @@
tests/longv7.at, tests/lustar01.at, tests/lustar02.at,
tests/shortfile.at: Update to match new diagnostic wording
(see 2008-05-06).
* NEWS: Update.
2008-06-14 Sergey Poznyakoff <gray@gnu.org.ua>
* doc/tar.texi (exclude): Document support for new VCS.
* THANKS: Update.
* NEWS: Update.
* NEWS: Update.
* tests/multiv05.at: Fix typos.
* tests/volsize.at: Remove a TZ dependency.
2008-06-14 Dan Drake <dan@dandrake.org> (tiny change)
* src/tar.c (exclude_vcs_files): Support for Bazaar, Mercurial and
Darcs.
Darcs.
2008-05-06 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -231,23 +231,23 @@
* tests/incr03.at, tests/incr04.at, tests/rename02.at,
tests/rename03.at: Insert calls to sleep between creation of files
and adding them to the archive.
2008-03-31 Sergey Poznyakoff <gray@gnu.org.ua>
* src/create.c (dump_file0): Count links only for actually dumped
files.
files.
2008-03-27 Sergey Poznyakoff <gray@gnu.org.ua>
* NEWS: Document --no-check-device and --check-device.
* doc/rendition.texi: Change the way FIXME-*refs are handled in
!PROOF.
!PROOF.
* doc/intern.texi, doc/tar.texi: Update.
* doc/untabify.el: New file.
* doc/Makefile.am (EXTRA_DIST): Add untabify.el
(untabify, final, check-format, check-refs, check-fixmes)
(check-unrevised, all-check-docs, check-docs): New rules.
* src/common.h (check_device_option): New global.
* src/incremen.c (procdir): Use boolean and instead of bitwise
one. Patch by Jean-Louis Martineau.
@@ -256,7 +256,7 @@
--check-device. Proposed by Jean-Louis Martineau.
(parse_opt): Hanlde new options.
(decode_options): Initialize check_device_option to true.
* THANKS: Update
2008-03-06 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -267,7 +267,7 @@
* po/.cvsignore: Update
* src/system.c: Remove include setenv.h.
* tests/atlocal.in (STAR_DATA_URL): Update.
* tests/star/README: Update URL.
* tests/star/README: Update URL.
2008-02-09 Sergey Poznyakoff <gray@gnu.org.ua>
@@ -303,7 +303,7 @@
Exit with nonzero status if a close fails on an archive.
Problem (and initial trivial fix)
* src/buffer.c (close_archive, new_volume): close_error, not
close_warn.
close_warn.
2007-12-05 Sergey Poznyakoff <gray@gnu.org.ua>

View File

@@ -22,8 +22,8 @@ ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = ChangeLog.1 Make.rules
SUBDIRS = doc gnu lib rmt src scripts po tests
dist-hook:
$(MAKE) changelog_dir=$(distdir) make-ChangeLog
dist-hook:
$(MAKE) changelog_dir=$(distdir) ChangeLog
-rm -f $(distdir).cpio
find $(distdir) | cpio -Hcrc -o | \
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
@@ -36,5 +36,3 @@ include Make.rules
gen_start_date = 2009-03-06
prev_change_log = ChangeLog.CVS
changelog_dir = .

256
NEWS
View File

@@ -1,19 +1,247 @@
GNU tar NEWS - User visible changes. 2009-03-05
GNU tar NEWS - User visible changes. 2010-11-07
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.25 - Sergey Poznyakoff, 2010-11-07
* Fix extraction of empty directories with the -C option in effect.
* Fix extraction of device nodes.
* Make sure name matching occurs before eventual name transformation.
Tar 1.24 changed the ordering of name matching and name transformation
so that the former saw already transformed file names. This made it
impossible to match file names in certain cases. It is fixed now.
* Fix the behavior of tar -x --overwrite on hosts lacking O_NOFOLLOW.
* Improve the testsuite.
* Alternative decompression programs.
If extraction from a compressed archive fails because the corresponding
compression program is not installed and the following two conditions
are met, tar retries extraction using an alternative decompressor:
1. Another compression program supported by tar is able to handle this
compression format.
2. The compression program was not explicitly requested in the command
line by the use of such options as -z, -j, etc.
For example, if `compress' is not available, tar will try `gzip'.
version 1.24 - Sergey Poznyakoff, 2010-10-24
* The --full-time option.
New command line option `--full-time' instructs tar to output file
time stamps to the full resolution.
* Bugfixes.
** More reliable directory traversal when creating archives
Tar now checks for inconsistencies caused when a file system is
modified while tar is creating an archive. In the new approach, tar
maintains a cache of file descriptors to directories, so it uses more
file descriptors than before, but it adjusts to system limits on
the number of file descriptors. Tar also takes more care when
a file system is modified while tar is extracting from an archive.
The new checks are implemented via the openat and related calls
standardized by POSIX.1-2008. On an older system where these calls do
not exist or do not return useful results, tar emulates the calls at
some cost in efficiency and reliability.
** Symbolic link attributes
When extracting symbolic links, tar now restores attributes such as
last-modified time and link permissions, if the operating system
supports this. For example, recent versions of the Linux kernel
support setting times on symlinks, and some BSD kernels also support
symlink permissions.
** --dereference consistency
The --dereference (-h) option now applies to files that are copied
into or out of archives, independently of other options. For example,
if F is a symbolic link and archive.tar contains a regular-file member
also named F, "tar --overwrite -x -f archive.tar F" now overwrites F
itself, rather than the file that F points to. (To overwrite the file
that F points to, add the --dereference (-h) option.) Formerly,
--dereference was intended to apply only when using the -c option, but
the implementation was not consistent.
Also, the --dereference option no longer affects accesses to other
files, such as archives and time stamp files. Symbolic links to these
files are always followed. Previously, the links were usually but not
always followed.
** Spurious error diagnostics on broken pipe.
When receiving SIGPIPE, tar would exit with error status and
"write error" diagnostics. In particular, this occurred if
invoked as in the example below:
tar tf archive.tar | head -n 1
** --remove-files
`Tar --remove-files' failed to remove a directory which contained
symlinks to another files within that directory.
** --test-label behavior
In case of a mismatch, `tar --test-label LABEL' exits with code 1,
not 2 as it did in previous versions.
The `--verbose' option used with `--test-label' provides additional
diagnostics.
Several volume labels may be specified in a command line, e.g.:
tar --test-label -f archive 'My volume' 'New volume' 'Test volume'
In this case, tar exits with code 0 if any one of the arguments
matches the actual volume label.
** --label used with --update
The `--label' option can be used with `--update' to prevent accidental
update of an archive:
tar -rf archive --label 'My volume' .
This did not work in previous versions, in spite of what the docs said.
** --record-size and --tape-length (-L) options
Usual size suffixes are allowed for these options. For example,
-L10k stands for a 10 kilobyte tape length.
** Fix dead loop on extracting existing symlinks with the -k option.
version 1.23 - Sergey Poznyakoff, 2010-03-10
* Record size autodetection
When listing or extracting archives, the actual record size is
reported only if the archive is read from a device (as opposed
to regular files and pipes).
* Seekable archives
When a read-only operation (e.g. --list or --extract) is requested
on a regular file, tar attemtps to speed up accesses by using lseek.
* New command line option `--warning'
The `--warning' command line option allows to suppress or enable
particular warning messages during `tar' run. It takes a single
argument (a `keyword'), identifying the class of warning messages
to affect. If the argument is prefixed with `no-', such warning
messages are suppressed. For example,
tar --warning=no-alone-zero-block -x -f archive
suppresses the output of `A lone zero block' diagnostics, which is
normally issued if `archive' ends with a single block of zeros.
See Tar Manual, section 3.9 "Controlling Warning Messages", for a
detailed discussion.
* New command line option `--level'
The `--level=N' option sets the incremental dump level N. It
is valid when used in conjunction with the -c and --listed-incremental
options. So far the only meaningful value for N is 0. The
`--level=0' option forces creating the level 0 dump, by truncating
the snapshot file if it exists.
* Files removed during incremental dumps
If a file or directory is removed while incremental dump is
in progress, tar exact actions depend on whether this file
was explicitly listed in the command line, or was found
during file system scan.
If the file was explicitly listed in the command line, tar
issues error message and exits with the code 2, meaning
fatal error.
Otherwise, if the file was found during the file system scan,
tar issues a warning, saying "File removed before we read it",
and sets exit code to 1, which means "some files differ".
If the --warning=no-file-removed option is given, no warning
is issued and exit code remains 0.
* Modification times of PAX extended headers.
Modification times in ustar header blocks of extended headers
are set to mtimes of the corresponding archive members. This
can be overridden by the
--pax-opion='exthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a `Time reference' (see below).
Modification times in ustar header blocks of global extended
headers are set to the time when tar was invoked.
This can be overridden by the
--pax-opion='globexthdr.mtime=STRING'
command line option. The STRING is either number of seconds since
the Epoch or a `Time reference' (see below).
* Time references in --pax-option argument.
Any value from the --pax-option argument that is enclosed in a pair
of curly braces represents a time reference. The string between the
braces is understood either as a textual time representation, as described in
chapter 7, "Date input formats", of the Tar manual, or as a name of
an existing file, starting with `/' or `.'. In the latter
case, it is replaced with the modification time of that file.
* Environment of --to-command script.
The environment passed to the --to-command script is extended with
the following variables:
TAR_VERSION GNU tar version number
TAR_ARCHIVE The name of the archive
TAR_VOLUME Ordinal number of the volume
TAR_FORMAT Format of the archive
TAR_BLOCKING_FACTOR Current blocking factor
* Bugfixes
** Fix handling of hard link targets by -c --transform.
** Fix hard links recognition with -c --remove-files.
** Fix restoring files from backup (debian bug #508199).
** Correctly restore modes and permissions on existing directories.
** The --remove-files option removes files only if they were
succesfully stored in the archive.
** Fix storing and listing of the volume labels in POSIX format.
** Improve algorithm for splitting long file names (ustar
format).
** Fix possible memory overflow in the rmt client code (CVE-2010-0624).
version 1.22 - Sergey Poznyakoff, 2009-03-05
* Support for xz compression
Tar uses xz for compression if one of the following conditions is met:
Tar uses xz for compression if one of the following conditions is met:
1. The option --xz or -J (see below) is used.
2. The xz binary is set as compressor using --use-compress-program option.
3. The file name of the archive being created ends in `.xz' and
auto-compress option (-a) is used.
Xz is used for decompression if one of the following conditions is met:
Xz is used for decompression if one of the following conditions is met:
1. The option --xz or -J is used.
2. The xz binary is set as compressor using --use-compress-program option.
@@ -66,7 +294,7 @@ control type of archive members affected by them. The flags are:
- s
Apply transformation to symbolic link targets.
- h
- h
Apply transformation to hard link targets.
Corresponding upper-case letters negate the meaning, so that
@@ -88,10 +316,10 @@ can be changed using `flags=' statement before the expressions, e.g.:
** The --null option disabled handling of tar options in list files. This
is fixed.
** Fixed record size autodetection. If detected record size differs from
the expected value (either default, or set on the command line), tar
always prints a warning if verbosity level is set to 1 or greater,
i.e. if either -t or -v option is given.
** Fixed record size autodetection. If the detected record size differs from
the expected value (either default one, or the one set from the
command line), tar always prints a warning if verbosity level is set
to 1 or greater, i.e. if either -t or -v option is given.
@@ -145,7 +373,7 @@ during both creation and extraction. Tar 1.19 used them only
during extraction.
For a detailed description, see chapter 6.7 "Modifying File and Member
Names".
Names".
* Info (end-of-volume) scripts
@@ -172,8 +400,8 @@ control systems, e.g. "CVS/", ".svn/", etc.
The following options now work with incremental archives as well:
--exclude-caches
--exclude-caches-all
--exclude-caches
--exclude-caches-all
--exclude-tag
--exclude-tag-all
--exclude-tag-under
@@ -184,14 +412,14 @@ Previous versions always stored absolute file names in rename
records, even if -P was not used. This is fixed: rename records
contain file names processed in accordance with the command line
settings.
* Fix --version output.
* Recognition of broken archives.
When supplied an archive smaller than 512 bytes in reading mode (-x,
-t), the previous version of tar silently ignored it, exiting with
code 0. It is fixed. Tar now issues the following diagnostic message:
code 0. It is fixed. Tar now issues the following diagnostic message:
'This does not look like a tar archive', and exits with code 2.
* Fix double-dot recognition in archive member names in case of duplicate '/.'.
@@ -1091,7 +1319,7 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GNU tar.

7
README
View File

@@ -180,19 +180,19 @@ the `lchown' call will be used if available, but that's all.
GNU `tar' is able to create archive in the following formats:
*** The format of UNIX version 7
*** POSIX.1-1988 format, also known as "ustar format"
*** POSIX.1-1988 format, also known as "ustar format"
*** POSIX.1-2001 format, also known as "pax format"
*** Old GNU format (described below)
In addition to those, GNU `tar' is also able to read archives
produced by `star' archiver.
produced by `star' archiver.
A so called `Old GNU' format is based on an early draft of the
POSIX 1003.1 `ustar' standard which is different from the final
standard. It defines its extensions (such as incremental backups
and handling of the long file names) in a way incompatible with
any existing tar archive format, therefore the use of old GNU
format is strongly discouraged.
format is strongly discouraged.
Please read the file NEWS for more information about POSIX compliance
and new `tar' features.
@@ -248,4 +248,3 @@ mode: outline
paragraph-separate: "[ ]*$"
version-control: never
End:

View File

@@ -6,20 +6,20 @@ this package.
You need the following packages to build the Git version of GNU
tar. We do not make any efforts to accommodate older versions of
these packages, so please make sure that you have the latest stable
version.
version.
- Automake <http://www.gnu.org/software/automake/>
- Autoconf <http://www.gnu.org/software/autoconf/>
- M4 <http://www.gnu.org/software/m4/>
- Texinfo <http://www.gnu.org/software/texinfo>
- Gnulib <http://www.gnu.org/software/gnulib>
- Gnulib <http://www.gnu.org/software/gnulib>
- Git <http://git.or.cz>
* Bootstrapping
Obviously, if you are reading these notes, you did manage to clone
tar from Git. The next step is to get other files needed to build,
which are extracted from other source packages:
which are extracted from other source packages:
1. Change to the source tree directory
@@ -27,7 +27,7 @@ which are extracted from other source packages:
2. Run
./bootstrap
./bootstrap
Once done, proceed as described in the file README (section
INSTALLATION).
@@ -43,7 +43,7 @@ contents:
Replace `$HOME/gnulib' with the actual directory where the Gnulib
sources reside.
For more information about `bootstrap', run `bootstrap --help'.
@@ -67,5 +67,3 @@ mode: outline
paragraph-separate: "[ ^L]*$"
version-control: never
End:

4
THANKS
View File

@@ -70,6 +70,7 @@ Burkhard Plache plache@krusty.optimax.ns.ca
Calvin Cliff cliff@trifid.astro.ucla.edu
Cameron Elliott cam@mvbms.mvbms.com
Carl Streeter streeter@cae.wisc.edu
Carl Worth cworth@cworth.org
Carsten Heyl heyl@nads.de
Catrin Urbanneck cur@gppc.de
Cesar Romani romani@ifm.uni-hamburg.de
@@ -132,6 +133,7 @@ David Steiner dsteiner@ispa.uni-osnabrueck.de
David Taylor taylor@think.com
Dean Gaudet dgaudet@watdragon.uwaterloo.ca
Demizu Noritoshi nori-d@is.aist-nara.ac.jp
Denis Excoffier denis.excoffier@free.fr
Denis Fortin fortin@acm.org
Dennis Pixton dennis@math.binghamton.edu
Dick Streefland dicks@tasking.nl
@@ -367,6 +369,7 @@ Olaf Schlueter olaf@toppoint.de
Olaf Wucknitz owucknitz@hs.uni-hamburg.de
Oliver Trepte oliver@fysik4.kth.se
Olivier Roussel roussel@lifl.fr
Ondřej Vašík ovasik@redhat.com
Oswald P. Backus IV backus@lks.csi.com
Pascal Meheut pascal@cnam.cnam.fr
Patrick Fulconis fulco@sig.uvsq.fr
@@ -388,6 +391,7 @@ Peter Fox fox@gec-mi-at.co.uk
Peter Kutschera peter@zditr1.arcs.ac.at
Peter Seebach seebs@taniemarie.solon.com
Phil Hands phil@hands.com
Phil Proudman phil@proudman51.freeserve.co.uk
Philippe Defert defert@cern.ch
Piercarlo Grandi piercarl@sabi.demon.co.uk
Pierce Cantrell cantrell@ee.tamu.edu

26
acinclude.m4 Normal file
View File

@@ -0,0 +1,26 @@
dnl Special Autoconf macros for GNU Tar -*- autoconf -*-
dnl Copyright (C) 2009 Free Software Foundation, Inc.
dnl
dnl GNU tar is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 3, or (at your option)
dnl any later version.
dnl
dnl GNU tar is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License along
dnl with GNU tar. If not, see <http://www.gnu.org/licenses/>.
AC_DEFUN([TAR_COMPR_PROGRAM],[
m4_pushdef([tar_compr_define],translit($1,[a-z+-],[A-ZX_])[_PROGRAM])
m4_pushdef([tar_compr_var],[tar_cv_compressor_]translit($1,[+-],[x_]))
AC_ARG_WITH($1,
AC_HELP_STRING([--with-]$1[=PROG],
[use PROG as ]$1[ compressor program]),
[tar_compr_var=${withval}],
[tar_compr_var=m4_if($2,,$1,$2)])
AC_DEFINE_UNQUOTED(tar_compr_define, "$tar_compr_var",
[Define to the program name of ]$1[ compressor program])])

508
bootstrap
View File

@@ -1,8 +1,10 @@
#! /bin/sh
# Print a version string.
scriptversion=2010-10-24.18; # UTC
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2008, 2009 Free Software Foundation, Inc.
# Copyright (C) 2003-2010 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
@@ -17,7 +19,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Written by Paul Eggert and Sergey Poznyakoff.
# Originally written by Paul Eggert. The canonical version of this
# script is maintained as build-aux/bootstrap in gnulib, however, to
# be useful to your project, you should place a copy of it under
# version control in the top-level directory of your project. The
# intent is that all customization can be done with a bootstrap.conf
# file also maintained in your version control; gnulib comes with a
# template build-aux/bootstrap.conf to get you started.
# Please report bugs or propose patches to bug-gnulib@gnu.org.
nl='
'
@@ -34,7 +44,7 @@ bt_regex=`echo "$bt"| sed 's/\./[.]/g'`
bt2=${bt}2
usage() {
echo >&2 "\
cat <<EOF
Usage: $0 [OPTION]...
Bootstrap this package from the checked-out sources.
@@ -48,7 +58,7 @@ Options:
sources reside. Use this if you already
have gnulib sources on your machine, and
do not want to waste your bandwidth downloading
them again.
them again. Defaults to \$GNULIB_SRCDIR.
--copy Copy files instead of creating symbolic links.
--force Attempt to bootstrap even if the sources seem
not to have been checked out.
@@ -57,8 +67,11 @@ Options:
If the file $0.conf exists in the same directory as this script, its
contents are read as shell variables to configure the bootstrap.
For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR
are honored.
Running without arguments will suffice in most cases.
"
EOF
}
# Configuration.
@@ -72,13 +85,22 @@ gnulib_modules=
# Any gnulib files needed that are not in modules.
gnulib_files=
# A function to be called to edit gnulib.mk right after it's created.
# Override it via your own definition in bootstrap.conf.
gnulib_mk_hook() { :; }
# A function to be called after everything else in this script.
# Override it via your own definition in bootstrap.conf.
bootstrap_epilogue() { :; }
# The command to download all .po files for a specified domain into
# a specified directory. Fill in the first %s is the domain name, and
# the second with the destination directory. Use rsync's -L and -r
# options because the latest/%s directory and the .po files within are
# all symlinks.
po_download_command_format=\
"rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
"rsync --delete --exclude '*.s1' -Lrtvz \
'translationproject.org::tp/latest/%s/' '%s'"
extract_package_name='
/^AC_INIT(/{
@@ -108,14 +130,14 @@ tests_base=tests
# Extra files from gnulib, which override files from other sources.
gnulib_extra_files="
$build_aux/install-sh
$build_aux/missing
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
$build_aux/config.guess
$build_aux/config.sub
doc/INSTALL
$build_aux/install-sh
$build_aux/missing
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
$build_aux/config.guess
$build_aux/config.sub
doc/INSTALL
"
# Additional gnulib-tool options to use. Use "\newline" to break lines.
@@ -131,7 +153,8 @@ XGETTEXT_OPTIONS='\\\
--flag=error:3:c-format --flag=error_at_line:5:c-format\\\
'
# Package bug report address for gettext files
# Package bug report address and copyright holder for gettext files
COPYRIGHT_HOLDER='Free Software Foundation, Inc.'
MSGID_BUGS_ADDRESS=bug-$package@gnu.org
# Files we don't want to import.
@@ -150,6 +173,44 @@ copy=false
# on which version control system (if any) is used in the source directory.
vc_ignore=auto
# find_tool ENVVAR NAMES...
# -------------------------
# Search for a required program. Use the value of ENVVAR, if set,
# otherwise find the first of the NAMES that can be run (i.e.,
# supports --version). If found, set ENVVAR to the program name,
# die otherwise.
find_tool ()
{
find_tool_envvar=$1
shift
find_tool_names=$@
eval "find_tool_res=\$$find_tool_envvar"
if test x"$find_tool_res" = x; then
for i
do
if ($i --version </dev/null) >/dev/null 2>&1; then
find_tool_res=$i
break
fi
done
else
find_tool_error_prefix="\$$find_tool_envvar: "
fi
if test x"$find_tool_res" = x; then
echo >&2 "$0: one of these is required: $find_tool_names"
exit 1
fi
($find_tool_res --version </dev/null) >/dev/null 2>&1 || {
echo >&2 "$0: ${find_tool_error_prefix}cannot run $find_tool_res --version"
exit 1
}
eval "$find_tool_envvar=\$find_tool_res"
eval "export $find_tool_envvar"
}
# Find sha1sum, named gsha1sum on MacPorts, and shasum on MacOS 10.6.
find_tool SHA1SUM sha1sum gsha1sum shasum
# Override the default configuration, if necessary.
# Make sure that bootstrap.conf is sourced from the current directory
# if we were invoked as "sh bootstrap".
@@ -202,7 +263,7 @@ insert_sorted_if_absent() {
file=$1
str=$2
test -f $file || touch $file
echo "$str" | sort -u - $file | cmp -s - $file \
echo "$str" | sort -u - $file | cmp - $file > /dev/null \
|| echo "$str" | sort -u - $file -o $file \
|| exit 1
}
@@ -229,6 +290,128 @@ if test ! -d $build_aux; then
done
fi
# Note this deviates from the version comparison in automake
# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
# but this should suffice as we won't be specifying old
# version formats or redundant trailing .0 in bootstrap.conf.
# If we did want full compatibility then we should probably
# use m4_version_compare from autoconf.
sort_ver() { # sort -V is not generally available
ver1="$1"
ver2="$2"
# split on '.' and compare each component
i=1
while : ; do
p1=$(echo "$ver1" | cut -d. -f$i)
p2=$(echo "$ver2" | cut -d. -f$i)
if [ ! "$p1" ]; then
echo "$1 $2"
break
elif [ ! "$p2" ]; then
echo "$2 $1"
break
elif [ ! "$p1" = "$p2" ]; then
if [ "$p1" -gt "$p2" ] 2>/dev/null; then # numeric comparison
echo "$2 $1"
elif [ "$p2" -gt "$p1" ] 2>/dev/null; then # numeric comparison
echo "$1 $2"
else # numeric, then lexicographic comparison
lp=$(printf "$p1\n$p2\n" | LANG=C sort -n | tail -n1)
if [ "$lp" = "$p2" ]; then
echo "$1 $2"
else
echo "$2 $1"
fi
fi
break
fi
i=$(($i+1))
done
}
get_version() {
app=$1
$app --version >/dev/null 2>&1 || return 1
$app --version 2>&1 |
sed -n '# extract version within line
s/.*[v ]\{1,\}\([0-9]\{1,\}\.[.a-z0-9-]*\).*/\1/
t done
# extract version at start of line
s/^\([0-9]\{1,\}\.[.a-z0-9-]*\).*/\1/
t done
d
:done
#the following essentially does s/5.005/5.5/
s/\.0*\([1-9]\)/.\1/g
p
q'
}
check_versions() {
ret=0
while read app req_ver; do
# We only need libtoolize from the libtool package.
if test "$app" = libtool; then
app=libtoolize
fi
# Honor $APP variables ($TAR, $AUTOCONF, etc.)
appvar=`echo $app | tr '[a-z]-' '[A-Z]_'`
test "$appvar" = TAR && appvar=AMTAR
eval "app=\${$appvar-$app}"
inst_ver=$(get_version $app)
if [ ! "$inst_ver" ]; then
echo "Error: '$app' not found" >&2
ret=1
elif [ ! "$req_ver" = "-" ]; then
latest_ver=$(sort_ver $req_ver $inst_ver | cut -d' ' -f2)
if [ ! "$latest_ver" = "$inst_ver" ]; then
echo "Error: '$app' version == $inst_ver is too old" >&2
echo " '$app' version >= $req_ver is required" >&2
ret=1
fi
fi
done
return $ret
}
print_versions() {
echo "Program Min_version"
echo "----------------------"
printf %s "$buildreq"
echo "----------------------"
# can't depend on column -t
}
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
# but that's not portable enough (e.g., for Solaris).
grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \
&& use_libtool=1
grep '^[ ]*LT_INIT' configure.ac >/dev/null \
&& use_libtool=1
if test $use_libtool = 1; then
find_tool LIBTOOLIZE glibtoolize libtoolize
fi
if ! printf "$buildreq" | check_versions; then
echo >&2
if test -f README-prereq; then
echo "See README-prereq for how to get the prerequisite programs" >&2
else
echo "Please install the prerequisite programs" >&2
fi
exit 1
fi
echo "$0: Bootstrapping from checked-out $package sources..."
# See if we can use gnulib's git-merge-changelog merge driver.
@@ -245,13 +428,13 @@ if test -d .git && (git --version) >/dev/null 2>/dev/null ; then
fi
cleanup() {
status=$?
rm -fr $1
exit $status
status=$?
rm -fr $1
exit $status
}
git_modules_config () {
GIT_CONFIG_LOCAL=.gitmodules git config "$@"
cleanup_gnulib() {
cleanup "$gnulib_path"
}
# Get paxutils files.
@@ -276,6 +459,12 @@ if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
`
fi
git_modules_config () {
test -f .gitmodules && git config --file .gitmodules "$@"
}
gnulib_path=`git_modules_config submodule.gnulib.path`
: ${gnulib_path:=gnulib}
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
@@ -285,30 +474,44 @@ case ${GNULIB_SRCDIR--} in
git submodule init || exit $?
git submodule update || exit $?
elif [ ! -d gnulib ]; then
elif [ ! -d "$gnulib_path" ]; then
echo "$0: getting gnulib files..."
trap cleanup_gnulib 1 2 13 15
git clone --help|grep depth > /dev/null && shallow='--depth 2' || shallow=
git clone $shallow git://git.sv.gnu.org/gnulib ||
"cleanup $1"
shallow=
git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2'
git clone $shallow git://git.sv.gnu.org/gnulib "$gnulib_path" ||
cleanup_gnulib
trap - 1 2 13 15
fi
GNULIB_SRCDIR=gnulib
GNULIB_SRCDIR=$gnulib_path
;;
*)
# Redirect the gnulib submodule to the directory on the command line
# if possible.
# Use GNULIB_SRCDIR as a reference.
if test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then
git submodule init
GNULIB_SRCDIR=`cd $GNULIB_SRCDIR && pwd`
git config --replace-all submodule.gnulib.url $GNULIB_SRCDIR
git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
git submodule update || exit $?
GNULIB_SRCDIR=gnulib
if git submodule -h|grep -- --reference > /dev/null; then
# Prefer the one-liner available in git 1.6.4 or newer.
git submodule update --init --reference "$GNULIB_SRCDIR" \
"$gnulib_path" || exit $?
else
# This fallback allows at least git 1.5.5.
if test -f "$gnulib_path"/gnulib-tool; then
# Since file already exists, assume submodule init already complete.
git submodule update || exit $?
else
# Older git can't clone into an empty directory.
rmdir "$gnulib_path" 2>/dev/null
git clone --reference "$GNULIB_SRCDIR" \
"$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
&& git submodule init && git submodule update \
|| exit $?
fi
fi
GNULIB_SRCDIR=$gnulib_path
fi
;;
esac
@@ -326,22 +529,24 @@ download_po_files() {
eval "$cmd"
}
# Download .po files to $po_dir/.reference and copy only the new
# Mirror .po files to $po_dir/.reference and copy only the new
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
# Note po files that exist locally only are left in $po_dir but will
# not be included in LINGUAS and hence will not be distributed.
update_po_files() {
# Directory containing primary .po files.
# Overwrite them only when we're sure a .po file is new.
po_dir=$1
domain=$2
# Download *.po files into this dir.
# Mirror *.po files into this dir.
# Usually contains *.s1 checksum files.
ref_po_dir="$po_dir/.reference"
test -d $ref_po_dir || mkdir $ref_po_dir || return
download_po_files $ref_po_dir $domain \
&& ls "$ref_po_dir"/*.po 2>/dev/null |
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS" || return
langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
test "$langs" = '*' && langs=x
@@ -350,10 +555,12 @@ update_po_files() {
new_po="$ref_po_dir/$po.po"
cksum_file="$ref_po_dir/$po.s1"
if ! test -f "$cksum_file" ||
! test -f "$po_dir/$po.po" ||
! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
! test -f "$po_dir/$po.po" ||
! $SHA1SUM -c --status "$cksum_file" \
< "$new_po" > /dev/null; then
echo "updated $po_dir/$po.po..."
cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
cp "$new_po" "$po_dir/$po.po" \
&& $SHA1SUM < "$new_po" > "$cksum_file"
fi
done
}
@@ -387,45 +594,46 @@ symlink_to_dir()
# FIXME: for now, this does only one level
parent=`dirname "$dst_dir"`
for dot_ig in x $vc_ignore; do
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'`
test $dot_ig = x && continue
ig=$parent/$dot_ig
insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'`
done
fi
if $copy; then
{
test ! -h "$dst" || {
echo "$0: rm -f $dst" &&
rm -f "$dst"
}
test ! -h "$dst" || {
echo "$0: rm -f $dst" &&
rm -f "$dst"
}
} &&
test -f "$dst" &&
cmp -s "$src" "$dst" || {
echo "$0: cp -fp $src $dst" &&
cp -fp "$src" "$dst"
echo "$0: cp -fp $src $dst" &&
cp -fp "$src" "$dst"
}
else
test -h "$dst" &&
src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
test "$src_i" = "$dst_i" || {
dot_dots=
case $src in
/*) ;;
*)
case /$dst/ in
*//* | */../* | */./* | /*/*/*/*/*/)
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
exit 1;;
/*/*/*/*/) dot_dots=../../../;;
/*/*/*/) dot_dots=../../;;
/*/*/) dot_dots=../;;
esac;;
esac
dot_dots=
case $src in
/*) ;;
*)
case /$dst/ in
/./*) ;;
*//* | */../* | */./* | /*/*/*/*/*/)
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
exit 1;;
/*/*/*/*/) dot_dots=../../../;;
/*/*/*/) dot_dots=../../;;
/*/*/) dot_dots=../;;
esac;;
esac
echo "$0: ln -fs $dot_dots$src $dst" &&
ln -fs "$dot_dots$src" "$dst"
echo "$0: ln -fs $dot_dots$src $dst" &&
ln -fs "$dot_dots$src" "$dst"
}
fi
}
@@ -455,28 +663,28 @@ cp_mark_as_generated()
if test -z "$c1"; then
cmp -s "$cp_src" "$cp_dst" || {
# Copy the file first to get proper permissions if it
# doesn't already exist. Then overwrite the copy.
echo "$0: cp -f $cp_src $cp_dst" &&
rm -f "$cp_dst" &&
cp "$cp_src" "$cp_dst-t" &&
sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst-t" &&
mv -f "$cp_dst-t" "$cp_dst"
# Copy the file first to get proper permissions if it
# doesn't already exist. Then overwrite the copy.
echo "$0: cp -f $cp_src $cp_dst" &&
rm -f "$cp_dst" &&
cp "$cp_src" "$cp_dst-t" &&
sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst-t" &&
mv -f "$cp_dst-t" "$cp_dst"
}
else
# Copy the file first to get proper permissions if it
# doesn't already exist. Then overwrite the copy.
cp "$cp_src" "$cp_dst-t" &&
(
echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
sed "s!$bt_regex/!!g" "$cp_src"
echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
sed "s!$bt_regex/!!g" "$cp_src"
) > $cp_dst-t &&
if cmp -s "$cp_dst-t" "$cp_dst"; then
rm -f "$cp_dst-t"
rm -f "$cp_dst-t"
else
echo "$0: cp $cp_src $cp_dst # with edits" &&
mv -f "$cp_dst-t" "$cp_dst"
echo "$0: cp $cp_src $cp_dst # with edits" &&
mv -f "$cp_dst-t" "$cp_dst"
fi
fi
fi
@@ -488,7 +696,7 @@ version_controlled_file() {
found=no
if test -d CVS; then
grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
grep '^/[^/]*/[0-9]' > /dev/null && found=yes
grep '^/[^/]*/[0-9]' > /dev/null && found=yes
elif test -d .git; then
git rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
elif test -d .svn; then
@@ -506,39 +714,42 @@ slurp() {
for file in `ls -a $1/$dir`; do
case $file in
.|..) continue;;
.*) continue;; # FIXME: should all file names starting with "." be ignored?
# FIXME: should all file names starting with "." be ignored?
.*) continue;;
esac
test -d $1/$dir/$file && continue
for excluded_file in $excluded_files; do
test "$dir/$file" = "$excluded_file" && continue 2
test "$dir/$file" = "$excluded_file" && continue 2
done
if test $file = Makefile.am; then
if test $file = Makefile.am && test "X$gnulib_mk" != XMakefile.am; then
copied=$copied${sep}$gnulib_mk; sep=$nl
remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/$gnulib_mk || {
echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
rm -f $dir/$gnulib_mk &&
sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk
}
remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
sed "$remove_intl" $1/$dir/$file |
cmp - $dir/$gnulib_mk > /dev/null || {
echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
rm -f $dir/$gnulib_mk &&
sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk &&
gnulib_mk_hook $dir/$gnulib_mk
}
elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
version_controlled_file $dir $file; then
echo "$0: $dir/$file overrides $1/$dir/$file"
version_controlled_file $dir $file; then
echo "$0: $dir/$file overrides $1/$dir/$file"
else
copied=$copied$sep$file; sep=$nl
if test $file = gettext.m4; then
echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
rm -f $dir/$file
sed '
/^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
AC_DEFUN([AM_INTL_SUBDIR], [
/^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
$a\
AC_DEFUN([gl_LOCK_EARLY], [])
' $1/$dir/$file >$dir/$file
else
cp_mark_as_generated $1/$dir/$file $dir/$file
fi
copied=$copied$sep$file; sep=$nl
if test $file = gettext.m4; then
echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
rm -f $dir/$file
sed '
/^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
AC_DEFUN([AM_INTL_SUBDIR], [])
/^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
$a\
AC_DEFUN([gl_LOCK_EARLY], [])
' $1/$dir/$file >$dir/$file
else
cp_mark_as_generated $1/$dir/$file $dir/$file
fi
fi || exit
done
@@ -546,18 +757,25 @@ slurp() {
test $dot_ig = x && continue
ig=$dir/$dot_ig
if test -n "$copied"; then
insert_sorted_if_absent $ig "$copied"
# If an ignored file name ends with .in.h, then also add
# the name with just ".h". Many gnulib headers are generated,
# e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc.
# Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed
f=`echo "$copied"|sed 's/\.in\.h$/.h/;s/\.sin$/.sed/;s/\.y$/.c/;s/\.gperf$/.h/'`
insert_sorted_if_absent $ig "$f"
insert_sorted_if_absent $ig "$copied"
# If an ignored file name ends with .in.h, then also add
# the name with just ".h". Many gnulib headers are generated,
# e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc.
# Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed
f=`echo "$copied" |
sed '
s/\.in\.h$/.h/
s/\.sin$/.sed/
s/\.y$/.c/
s/\.gperf$/.h/
'
`
insert_sorted_if_absent $ig "$f"
# For files like sys_stat.in.h and sys_time.in.h, record as
# ignorable the directory we might eventually create: sys/.
f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'`
insert_sorted_if_absent $ig "$f"
# For files like sys_stat.in.h and sys_time.in.h, record as
# ignorable the directory we might eventually create: sys/.
f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'`
insert_sorted_if_absent $ig "$f"
fi
done
done
@@ -582,6 +800,12 @@ gnulib_tool_options="\
--local-dir $local_gl_dir\
$gnulib_tool_option_extras\
"
if test $use_libtool = 1; then
case "$gnulib_tool_options " in
*' --libtool '*) ;;
*) gnulib_tool_options="$gnulib_tool_options --libtool" ;;
esac
fi
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
$gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
slurp $bt || exit
@@ -597,9 +821,9 @@ grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
with_gettext=no
if test $with_gettext = yes; then
echo "$0: (cd $bt2; autopoint) ..."
echo "$0: (cd $bt2; ${AUTOPOINT-autopoint}) ..."
cp configure.ac $bt2 &&
(cd $bt2 && autopoint && rm configure.ac) &&
(cd $bt2 && ${AUTOPOINT-autopoint} && rm configure.ac) &&
slurp $bt2 $bt || exit
fi
rm -fr $bt $bt2 || exit
@@ -616,6 +840,8 @@ find "$m4_base" "$source_base" \
-depth \( -name '*.m4' -o -name '*.[ch]' \) \
-type l -xtype l -delete > /dev/null 2>&1
# Reconfigure, getting other files.
# copy_files srcdir dstdir
copy_files() {
for file in `cat $1/DISTFILES`
@@ -660,27 +886,22 @@ done
copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
# Reconfigure, getting other files.
# Skip autoheader if it's not needed.
grep -E '^[ ]*AC_CONFIG_HEADERS?\>' configure.ac >/dev/null ||
AUTOHEADER=true
for command in \
libtool \
'aclocal --force -I m4' \
'autoconf --force' \
'autoheader --force' \
'automake --add-missing --copy --force-missing';
"${ACLOCAL-aclocal} --force -I m4 $ACLOCAL_FLAGS" \
"${AUTOCONF-autoconf} --force" \
"${AUTOHEADER-autoheader} --force" \
"${AUTOMAKE-automake} --add-missing --copy --force-missing"
do
if test "$command" = libtool; then
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
# but that's not portable enough (e.g., for Solaris).
grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \
&& use_libtool=1
grep '^[ ]*LT_INIT' configure.ac >/dev/null \
&& use_libtool=1
test $use_libtool = 0 \
&& continue
command='libtoolize -c -f'
command="${LIBTOOLIZE-libtoolize} -c -f"
fi
echo "$0: $command ..."
$command || exit
@@ -703,13 +924,14 @@ if test $with_gettext = yes; then
rm -f po/Makevars
sed '
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= '"$MSGID_BUGS_ADDRESS"'/
/^COPYRIGHT_HOLDER *=/s/=.*/= '"$COPYRIGHT_HOLDER"'/
/^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$MSGID_BUGS_ADDRESS"'|
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
}
' po/Makevars.template >po/Makevars
' po/Makevars.template >po/Makevars || exit 1
if test -d runtime-po; then
# Similarly for runtime-po/Makevars, but not quite the same.
@@ -719,15 +941,25 @@ if test $with_gettext = yes; then
/^subdir *=.*/s/=.*/= runtime-po/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
}
' <po/Makevars.template >runtime-po/Makevars
' po/Makevars.template >runtime-po/Makevars || exit 1
# Copy identical files from po to runtime-po.
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
fi
fi
bootstrap_epilogue
echo "$0: done. Now you can run './configure'."
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -1,7 +1,8 @@
# Configure template for GNU tar. -*- autoconf -*-
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
@@ -18,12 +19,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
AC_INIT([GNU tar], [1.22], [bug-tar@gnu.org])
AC_INIT([GNU tar], [1.25], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_PREREQ([2.60])
AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
AC_PREREQ([2.63])
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-xz dist-shar std-options silent-rules])
# Enable silent rules by default:
AM_SILENT_RULES([yes])
AC_PROG_CC
AC_EXEEXT
@@ -36,8 +40,8 @@ AC_ISC_POSIX
AC_C_INLINE
AC_CHECK_HEADERS_ONCE(fcntl.h linux/fd.h memory.h net/errno.h \
sgtty.h string.h stropts.h \
sys/param.h sys/device.h sys/filio.h sys/gentape.h \
sgtty.h string.h \
sys/param.h sys/device.h sys/gentape.h \
sys/inet.h sys/io/trioctl.h \
sys/mtio.h sys/time.h sys/tprintf.h sys/tape.h \
unistd.h locale.h)
@@ -86,7 +90,7 @@ gl_INIT
# paxutils modules
tar_PAXUTILS
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink symlink setlocale utimes)
AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink])
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
AC_CHECK_DECLS([time],,, [#include <time.h>])
@@ -121,6 +125,14 @@ else
[Define to the full path of your rsh, if any.])
fi
TAR_COMPR_PROGRAM(compress)
TAR_COMPR_PROGRAM(gzip)
TAR_COMPR_PROGRAM(bzip2)
TAR_COMPR_PROGRAM(lzip)
TAR_COMPR_PROGRAM(lzma)
TAR_COMPR_PROGRAM(lzop)
TAR_COMPR_PROGRAM(xz)
AC_MSG_CHECKING(for default archive format)
AC_ARG_VAR([DEFAULT_ARCHIVE_FORMAT],

View File

@@ -65,7 +65,7 @@ programs (using pipes); tar can even access remote devices or files
%%contributors: Jay Fenlason,
Joy Kendall,
Francois Pinard <pinard@iro.umontreal.ca>
%%source-tarball: ftp://ftp.gnu.org/pub/gnu/tar/tar-1.15.1.tar.gz
%%source-info: http://savannah.gnu.org/projects/tar
@@ -84,4 +84,3 @@ programs (using pipes); tar can even access remote devices or files
%%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>

6
doc/.gitignore vendored
View File

@@ -1,5 +1,7 @@
getdate.texi
genfile.texi
header.texi
manual
parse-datetime.texi
stamp-vti
tar.aux
tar.cp
@@ -22,5 +24,3 @@ tar.toc
tar.tp
tar.vr
version.texi
genfile.texi
header.texi

View File

@@ -24,9 +24,9 @@ tar_TEXINFOS = \
fdl.texi\
freemanuals.texi\
genfile.texi\
getdate.texi\
header.texi\
intern.texi\
parse-datetime.texi\
rendition.texi\
snapshot.texi\
sparse.texi\
@@ -59,25 +59,28 @@ check-format:
fi
check-options:
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
$(top_builddir)/src/tar --usage | \
sed -n 's/^\[--\([^]\=\[]*\).*/\1/p' | sort | uniq > opts.$$$$;\
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
$(info_TEXINFOS) | \
sed -n '/^@macro/,/^@end macro/d;s/@opindex *\([^@,]*\).*/\1/p' \
| sort | uniq > docs.$$$$;\
(echo 'Not documented options:';\
join -v1 opts.$$$$ docs.$$$$;\
echo 'Non-existing options:';\
join -v2 opts.$$$$ docs.$$$$) > report.$$$$;\
rm opts.$$$$ docs.$$$$;\
if [ -n "`sed '1,2d' report.$$$$`" ]; then \
cat report.$$$$;\
rm report.$$$$;\
exit 1;\
fi;\
rm report.$$$$
status=0;\
join -v1 opts.$$$$ docs.$$$$ > report.$$$$;\
if test -s report.$$$$; then \
echo 'Not documented options:'; \
cat report.$$$$; \
status=1; \
fi; \
join -v2 opts.$$$$ docs.$$$$ > report.$$$$;\
if test -s report.$$$$; then \
echo 'Non-existing options:';\
cat report.$$$$; \
status=1; \
fi; \
rm opts.$$$$ docs.$$$$ report.$$$$;\
test $$status -ne 0 && exit $$status
check-refs:
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
@@ -121,7 +124,7 @@ check-unrevised:
all-check-docs: check-format check-options check-refs check-fixmes check-unrevised
check-docs:
check-docs:
$(MAKE) -k all-check-docs
#
@@ -141,4 +144,3 @@ manual:
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
$(GENDOCS) --texi2html tar 'GNU tar manual'

View File

@@ -16,7 +16,7 @@ dumped directory in special data blocks called @dfn{dumpdirs}.
@noindent
where @var{C} is one of the @dfn{control codes} described below,
@var{filename} is the name of the file @var{C} operates upon, and
@samp{\0} represents a nul character (ASCII 0). The white space
@samp{\0} represents a nul character (ASCII 0). The white space
characters were added for readability, real dumpdirs do not contain
them.
@@ -68,7 +68,7 @@ directory}. For example, consider the following scenario:
@enumerate 1
@item
Previous run dumped a directory @file{foo} which contained the
following three directories:
following three directories:
@smallexample
a
@@ -93,7 +93,7 @@ New incremental dump was made.
renaming @file{a} to @file{b} will destroy the existing directory.
To correctly process it, @GNUTAR{} needs a temporary directory, so
it creates the following dumpdir (newlines have been added for
readability):
readability):
@smallexample
@group
@@ -114,7 +114,7 @@ work as usual, and, finally, the last command, @samp{R\0Tfoo/a\0}
tells tar to rename the temporary directory to @file{foo/a}.
The exact placement of a dumpdir in the archive depends on the
archive format (@pxref{Formats}):
archive format (@pxref{Formats}):
@itemize
@item PAX archives

View File

@@ -1,13 +1,12 @@
@c The GNU Free Documentation License.
@center Version 1.3, 3 November 2008
@node GNU Free Documentation License
@appendixsec GNU Free Documentation License
@cindex FDL, GNU Free Documentation License
@center Version 1.2, November 2002
@c This file is intended to be included within another document,
@c hence no sectioning command or @node.
@display
Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
@uref{http://fsf.org/}
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -93,16 +92,16 @@ An image format is not Transparent if used for any substantial amount
of text. A copy that is not ``Transparent'' is called ``Opaque''.
Examples of suitable formats for Transparent copies include plain
@sc{ascii} without markup, Texinfo input format, La@TeX{} input
format, @acronym{SGML} or @acronym{XML} using a publicly available
@acronym{DTD}, and standard-conforming simple @acronym{HTML},
PostScript or @acronym{PDF} designed for human modification. Examples
of transparent image formats include @acronym{PNG}, @acronym{XCF} and
@acronym{JPG}. Opaque formats include proprietary formats that can be
read and edited only by proprietary word processors, @acronym{SGML} or
@acronym{XML} for which the @acronym{DTD} and/or processing tools are
not generally available, and the machine-generated @acronym{HTML},
PostScript or @acronym{PDF} produced by some word processors for
ASCII without markup, Texinfo input format, La@TeX{} input
format, SGML or XML using a publicly available
DTD, and standard-conforming simple HTML,
PostScript or PDF designed for human modification. Examples
of transparent image formats include PNG, XCF and
JPG. Opaque formats include proprietary formats that can be
read and edited only by proprietary word processors, SGML or
XML for which the DTD and/or processing tools are
not generally available, and the machine-generated HTML,
PostScript or PDF produced by some word processors for
output purposes only.
The ``Title Page'' means, for a printed book, the title page itself,
@@ -112,6 +111,9 @@ formats which do not have any title page as such, ``Title Page'' means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
The ``publisher'' means any person or entity that distributes copies
of the Document to the public.
A section ``Entitled XYZ'' means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
@@ -380,13 +382,30 @@ title.
@item
TERMINATION
You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License. Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
You may not copy, modify, sublicense, or distribute the Document
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, or distribute it is void, and
will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license
from a particular copyright holder is reinstated (a) provisionally,
unless and until the copyright holder explicitly and finally
terminates your license, and (b) permanently, if the copyright holder
fails to notify you of the violation by some reasonable means prior to
60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, receipt of a copy of some or all of the same material does
not give you any rights to use it.
@item
FUTURE REVISIONS OF THIS LICENSE
@@ -404,11 +423,46 @@ following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.
as a draft) by the Free Software Foundation. If the Document
specifies that a proxy can decide which future versions of this
License can be used, that proxy's public statement of acceptance of a
version permanently authorizes you to choose that version for the
Document.
@item
RELICENSING
``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any
World Wide Web server that publishes copyrightable works and also
provides prominent facilities for anybody to edit those works. A
public wiki that anybody can edit is an example of such a server. A
``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the
site means any set of copyrightable works thus published on the MMC
site.
``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0
license published by Creative Commons Corporation, a not-for-profit
corporation with a principal place of business in San Francisco,
California, as well as future copyleft versions of that license
published by that same organization.
``Incorporate'' means to publish or republish a Document, in whole or
in part, as part of another Document.
An MMC is ``eligible for relicensing'' if it is licensed under this
License, and if all works that were first published under this License
somewhere other than this MMC, and subsequently incorporated in whole
or in part into the MMC, (1) had no cover texts or invariant sections,
and (2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site
under CC-BY-SA on the same site at any time before August 1, 2009,
provided the MMC is eligible for relicensing.
@end enumerate
@page
@appendixsubsec ADDENDUM: How to use this License for your documents
@heading ADDENDUM: How to use this License for your documents
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
@@ -418,7 +472,7 @@ license notices just after the title page:
@group
Copyright (C) @var{year} @var{your name}.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license is included in the section entitled ``GNU
@@ -427,7 +481,7 @@ license notices just after the title page:
@end smallexample
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the ``with...Texts.'' line with this:
replace the ``with@dots{}Texts.'' line with this:
@smallexample
@group

View File

@@ -36,7 +36,7 @@
<p>The manual for %%PACKAGE%% is available in the following formats:</p>
<ul>
<li><a href="%%PACKAGE%%.html">HTML
<li><a href="%%PACKAGE%%.html">HTML
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
<li><a href="html_node/index.html">HTML</a> - with one web page per
node.</li>
@@ -49,7 +49,7 @@
chapter.</li>
%%ENDIF HTML_CHAPTER%%
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
one web page.</li>
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
@@ -96,9 +96,9 @@ Return to the <a href="/home.html">GNU Project home page</a>.
</p>
<p>
Please send FSF &amp; GNU inquiries to
Please send FSF &amp; GNU inquiries to
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
the FSF.
<br />
Please send broken links and other corrections (or suggestions) to

View File

@@ -107,10 +107,10 @@ group permission could be copied from the @emph{other} permission.
The @code{uid} and @code{gid} fields are the numeric user and group
@acronym{ID} of the file owners, respectively. If the operating system does
not support numeric user or group @acronym{ID}s, these fields should
be ignored.
be ignored.
The @code{size} field is the size of the file in bytes; linked files
are archived with this field specified as zero.
are archived with this field specified as zero.
The @code{mtime} field is the data modification time of the file at
the time it was archived. It is the ASCII representation of the octal
@@ -330,4 +330,3 @@ checksum error.
@node Dumpdir
@unnumberedsec Dumpdir
@include dumpdir.texi

View File

@@ -27,11 +27,11 @@
;; This file redefines texinfo-master-menu-list so that it takes into
;; account included files.
;; Known bugs: @menu without previous sectioning command will inherit
;; Known bugs: @menu without previous sectioning command will inherit
;; documentation string from the previous menu. However, since such a
;; menu is illegal in a texinfo file, we can live with it.
(require 'texinfo)
(require 'texinfo)
(require 'texnfo-upd)
(defun texinfo-master-menu-list-recursive (title)

View File

@@ -23,14 +23,14 @@ snapshots only in format 2.
This appendix describes all three formats in detail.
@enumerate 0
@cindex format 0, snapshot file
@cindex format 0, snapshot file
@cindex snapshot file, format 0
@item
@item
@samp{Format 0} snapshot file begins with a line containing a
decimal number that represents a @acronym{UNIX} timestamp of the
beginning of the last archivation. This line is followed by directory
metadata descriptions, one per line. Each description has the
following format:
following format:
@smallexample
@var{nfs}@var{dev} @var{inode} @var{name}
@@ -55,9 +55,9 @@ Name of the directory. Any special characters (white-space,
backslashes, etc.) are quoted.
@end table
@cindex format 1, snapshot file
@cindex format 1, snapshot file
@cindex snapshot file, format 1
@item
@item
@samp{Format 1} snapshot file begins with a line specifying the
format of the file. This line has the following structure:
@@ -69,7 +69,7 @@ format of the file. This line has the following structure:
where @var{tar-version} is the version number of @GNUTAR{}
implementation that created this snapshot, and
@var{incr-format-version} is the version number of the snapshot format
(in this case @samp{1}).
(in this case @samp{1}).
Next line contains two decimal numbers, representing the
time of the last backup. First number is the number of seconds, the
@@ -89,11 +89,11 @@ modification time of this directory with nanosecond precision;
@var{nfs}, @var{dev}, @var{inode} and @var{name} have the same meaning
as with @samp{format 0}.
@cindex format 2, snapshot file
@cindex format 2, snapshot file
@cindex snapshot file, format 2
@item
@FIXME{}
A snapshot file begins with a format identifier, as described for
@item
@samp{Format 2} snapshot file begins with a format identifier, as described for
version 1, e.g.:
@smallexample
@@ -109,7 +109,7 @@ snapshot is a binary file.
time of the last backup. First number is the number of seconds, the
second one is the number of nanoseconds, since the beginning of the
epoch. These are followed by arbitrary number of directory records.
Each @dfn{directory record} contains a set of metadata describing a
particular directory. Parts of a directory record are delimited with
@acronym{ASCII} 0 characters. The following table describes each
@@ -124,11 +124,11 @@ an @acronym{NFS}-mounted partition, or @samp{0} otherwise;
@item mtime-nano @tab Number @tab Modification time, nanoseconds;
@item dev-no @tab Number @tab Device number;
@item i-no @tab Number @tab I-node number;
@item name @tab String @tab Directory name; In contrast to the
previous versions it is not quoted.
@item name @tab String @tab Directory name; in contrast to the
previous versions it is not quoted;
@item contents @tab Dumpdir @tab Contents of the directory;
@xref{Dumpdir}, for a description of its format.
@item
@item
@end multitable
Dumpdirs stored in snapshot files contain only records of types
@@ -137,5 +137,3 @@ previous versions it is not quoted.
@end enumerate
@c End of snapshot.texi

View File

@@ -14,12 +14,12 @@ The support for sparse files in @GNUTAR{} has a long history. The
earliest version featuring this support that I was able to find was 1.09,
released in November, 1990. The format introduced back then is called
@dfn{old GNU} sparse format and in spite of the fact that its design
contained many flaws, it was the only format @GNUTAR{} supported
contained many flaws, it was the only format @GNUTAR{} supported
until version 1.14 (May, 2004), which introduced initial support for
sparse archives in @acronym{PAX} archives (@pxref{posix}). This
format was not free from design flows, either and it was subsequently
format was not free from design flaws, either and it was subsequently
improved in versions 1.15.2 (November, 2005) and 1.15.92 (June,
2006).
2006).
In addition to GNU sparse format, @GNUTAR{} is able to read and
extract sparse files archived by @command{star}.
@@ -37,7 +37,7 @@ The following subsections describe each format in detail.
@cindex sparse formats, Old GNU
@cindex Old GNU sparse format
The format introduced some time around 1990 (v. 1.09). It was
The format introduced in November 1990 (v. 1.09) was
designed on top of standard @code{ustar} headers in such an
unfortunate way that some of its fields overwrote fields required by
POSIX.
@@ -61,7 +61,7 @@ extension sparse header follows, @code{0} otherwise.
@end multitable
Each of @code{sparse_header} object at offset 386 describes a single
data chunk. It has the following structure:
data chunk. It has the following structure:
@multitable @columnfractions 0.10 0.10 0.20 0.60
@headitem Offset @tab Size @tab Data type @tab Contents
@@ -78,7 +78,7 @@ the following structure:
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
@item 0 @tab 21 @tab sp @tab @code{sparse_header} @tab
(21 entires) File map.
(21 entries) File map.
@item 504 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
extension sparse header follows, or @code{0} otherwise.
@end multitable
@@ -97,19 +97,19 @@ versions 1.14--1.15.1. The sparse file map is kept in extended
@table @code
@vrindex GNU.sparse.size, extended header variable
@item GNU.sparse.size
Real size of the stored file
Real size of the stored file;
@item GNU.sparse.numblocks
@vrindex GNU.sparse.numblocks, extended header variable
Number of blocks in the sparse map
Number of blocks in the sparse map;
@item GNU.sparse.offset
@vrindex GNU.sparse.offset, extended header variable
Offset of the data block
Offset of the data block;
@item GNU.sparse.numbytes
@vrindex GNU.sparse.numbytes, extended header variable
Size of the data block
Size of the data block.
@end table
The latter two variables repeat for each data block, so the overall
@@ -117,11 +117,11 @@ structure is like this:
@smallexample
@group
GNU.sparse.size=@var{size}
GNU.sparse.numblocks=@var{numblocks}
GNU.sparse.size=@var{size}
GNU.sparse.numblocks=@var{numblocks}
repeat @var{numblocks} times
GNU.sparse.offset=@var{offset}
GNU.sparse.numbytes=@var{numbytes}
GNU.sparse.offset=@var{offset}
GNU.sparse.numbytes=@var{numbytes}
end repeat
@end group
@end smallexample
@@ -136,8 +136,8 @@ meaningful. Thus, multiple occurrences of @code{GNU.sparse.offset} and
@code{GNU.sparse.numbytes} are conflicting with the POSIX specs.
@item
Attempting to extract such archives using a third-party @command{tar}s
results in extraction of sparse files in @emph{compressed form}. If
Attempting to extract such archives using a third-party's @command{tar}
results in extraction of sparse files in @emph{condensed form}. If
the @command{tar} implementation in question does not support POSIX
format, it will also extract a file containing extension header
attributes. This file can be used to expand the file to its original
@@ -160,7 +160,7 @@ it uses a single variable:
@item GNU.sparse.map
@vrindex GNU.sparse.map, extended header variable
Map of non-null data chunks. It is a string consisting of
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
@end table
To address the 2nd problem, the @code{name} field in @code{ustar}
@@ -181,7 +181,7 @@ restore such members using non-GNU @command{tar}s.
The resulting @code{GNU.sparse.map} string can be @emph{very} long.
Although POSIX does not impose any limit on the length of a @code{x}
header variable, this possibly can confuse some tars.
header variable, this possibly can confuse some @command{tar}s.
@node PAX 1
@appendixsubsec PAX Format, Version 1.0
@@ -218,18 +218,17 @@ The real name of the sparse file is stored in the variable
variable @code{GNU.sparse.realsize}.
The sparse map itself is stored in the file data block, preceding the actual
file data. It consists of a series of octal numbers of arbitrary length, delimited
file data. It consists of a series of octal numbers of arbitrary length, delimited
by newlines. The map is padded with nulls to the nearest block boundary.
The first number gives the number of entries in the map. Following are map entries,
each one consisting of two numbers giving the offset and size of the
data block it describes.
The format is designed in such a way that non-posix aware tars and tars not
The format is designed in such a way that non-posix aware @command{tar}s and @command{tar}s not
supporting @code{GNU.sparse.*} keywords will extract each sparse file
in its condensed form with the file map prepended and will place it
into a separate directory. Then, using a simple program it would be
possible to expand the file to its original form even without @GNUTAR{}.
@xref{Sparse Recovery}, for the detailed information on how to extract
sparse members without @GNUTAR{}.

View File

@@ -7,7 +7,7 @@
@cindex snapshot files, editing
@cindex snapshot files, fixing device numbers
Sometimes device numbers can change after upgrading your kernel
version or recofiguring the harvare. Reportedly this is the case with
version or reconfiguring the hardware. Reportedly this is the case with
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
cases this change is unnoticed by the users. However, it influences
@command{tar} incremental backups: the device number is stored in tar
@@ -21,9 +21,9 @@ the @command{tar-snapshot-edit} utility for inspecting and updating
device numbers in snapshot files. The utility, written by
Dustin J.@: Mitchell, is available from
@uref{http://www.gnu.org/@/software/@/tar/@/utils/@/tar-snapshot-edit.html,
@GNUTAR{} home page}.
@GNUTAR{} home page}.
To obtain the device numbers used in the snapshot file, run
To obtain the device numbers used in the snapshot file, run
@smallexample
$ @kbd{tar-snapshot-edit @var{snapfile}}
@@ -31,7 +31,7 @@ $ @kbd{tar-snapshot-edit @var{snapfile}}
@noindent
where @var{snapfile} is the name of the snapshot file (you can supply as many
files as you wish in a single command line ).
files as you wish in a single command line).
To update all occurrences of the given device number in the file, use
@option{-r} option. It takes a single argument of the form
@@ -55,4 +55,3 @@ file version 2
$ @kbd{tar-snapshot-edit -b -r 0x0306-0x4500 /var/backup/snap.a}
file version 2
@end smallexample

File diff suppressed because it is too large Load Diff

View File

@@ -18,5 +18,3 @@
@end ifclear
@xopindex{\option\, summary}
@end macro

View File

@@ -4,6 +4,7 @@
alloca
argmatch
argp
argp-version-etc
backupfile
closeout
configmake
@@ -11,31 +12,40 @@ dirname
error
exclude
exitfail
fdopendir
fdutimensat
fileblocks
fnmatch-gnu
fseeko
ftruncate
full-write
getdate
futimens
getline
getopt
getopt-gnu
getpagesize
gettext
gettime
gitlog-to-changelog
hash
human
inttostr
inttypes
lchown
linkat
localcharset
mkdtemp
mkfifoat
modechange
obstack
openat
parse-datetime
priv-set
progname
quote
quotearg
readlinkat
renameat
rpmatch
safe-read
save-cwd
savedir
setenv
snprintf
@@ -47,13 +57,14 @@ strdup-posix
strerror
strtol
strtoul
symlinkat
timespec
unlinkdir
unlocked-io
utime
utimens
utimensat
version-etc-fsf
xalloc
xalloc-die
xgetcwd
xstrtoumax
xvasprintf

View File

@@ -1,7 +1,7 @@
# Makefile for GNU tar library. -*- Makefile -*-
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
# 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
# 2005, 2006, 2007, 2009, 2010 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,14 +19,14 @@
noinst_LIBRARIES=libtar.a
rmt-command.h : Makefile
rm -f $@-t $@
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
echo "#endif" >> $@-t
mv $@-t $@
$(AM_V_GEN)rm -f $@-t $@
$(AM_V_at)echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
$(AM_V_at)echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
$(AM_V_at)echo "#endif" >> $@-t
$(AM_V_at)mv $@-t $@
BUILT_SOURCES = rmt-command.h
CLEANFILES = rmt-command.h rmt-command.h-t
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h
libtar_a_SOURCES = \
@@ -36,4 +36,3 @@ libtar_a_SOURCES = \
rmt.h \
stdopen.c stdopen.h \
system.h system-ioctl.h

View File

@@ -1,445 +0,0 @@
/* modechange.c -- file mode manipulation
Copyright (C) 1989, 1990, 1997, 1998, 1999 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. */
/* Written by David MacKenzie <djm@ai.mit.edu> */
/* The ASCII mode string is compiled into a linked list of `struct
modechange', which can then be applied to each file to be changed.
We do this instead of re-parsing the ASCII string for each file
because the compiled form requires less computation to use; when
changing the mode of many files, this probably results in a
performance gain. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "modechange.h"
#include <sys/stat.h>
#include "xstrtol.h"
#if STDC_HEADERS
# include <stdlib.h>
#else
char *malloc ();
#endif
#ifndef NULL
# define NULL 0
#endif
#if STAT_MACROS_BROKEN
# undef S_ISDIR
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISUID
# define S_ISUID 04000
#endif
#ifndef S_ISGID
# define S_ISGID 04000
#endif
#ifndef S_ISVTX
# define S_ISVTX 01000
#endif
#ifndef S_IRUSR
# define S_IRUSR 0400
#endif
#ifndef S_IWUSR
# define S_IWUSR 0200
#endif
#ifndef S_IXUSR
# define S_IXUSR 0100
#endif
#ifndef S_IRGRP
# define S_IRGRP 0040
#endif
#ifndef S_IWGRP
# define S_IWGRP 0020
#endif
#ifndef S_IXGRP
# define S_IXGRP 0010
#endif
#ifndef S_IROTH
# define S_IROTH 0004
#endif
#ifndef S_IWOTH
# define S_IWOTH 0002
#endif
#ifndef S_IXOTH
# define S_IXOTH 0001
#endif
#ifndef S_IRWXU
# define S_IRWXU 0700
#endif
#ifndef S_IRWXG
# define S_IRWXG 0070
#endif
#ifndef S_IRWXO
# define S_IRWXO 0007
#endif
/* All the mode bits that can be affected by chmod. */
#define CHMOD_MODE_BITS \
(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
/* Return newly allocated memory to hold one element of type TYPE. */
#define talloc(type) ((type *) malloc (sizeof (type)))
/* Create a mode_change entry with the specified `=ddd'-style
mode change operation, where NEW_MODE is `ddd'. Return the
new entry, or NULL upon failure. */
static struct mode_change *
make_node_op_equals (mode_t new_mode)
{
struct mode_change *p;
p = talloc (struct mode_change);
if (p == NULL)
return p;
p->next = NULL;
p->op = '=';
p->flags = 0;
p->value = new_mode;
p->affected = CHMOD_MODE_BITS; /* Affect all permissions. */
return p;
}
/* Append entry E to the end of the link list with the specified
HEAD and TAIL. */
static void
mode_append_entry (struct mode_change **head,
struct mode_change **tail,
struct mode_change *e)
{
if (*head == NULL)
*head = *tail = e;
else
{
(*tail)->next = e;
*tail = e;
}
}
/* Return a linked list of file mode change operations created from
MODE_STRING, an ASCII string that contains either an octal number
specifying an absolute mode, or symbolic mode change operations with
the form:
[ugoa...][[+-=][rwxXstugo...]...][,...]
MASKED_OPS is a bitmask indicating which symbolic mode operators (=+-)
should not affect bits set in the umask when no users are given.
Operators not selected in MASKED_OPS ignore the umask.
Return MODE_INVALID if `mode_string' does not contain a valid
representation of file mode change operations;
return MODE_MEMORY_EXHAUSTED if there is insufficient memory. */
struct mode_change *
mode_compile (const char *mode_string, unsigned int masked_ops)
{
struct mode_change *head; /* First element of the linked list. */
struct mode_change *tail; /* An element of the linked list. */
uintmax_t mode_value; /* The mode value, if octal. */
char *string_end; /* Pointer to end of parsed value. */
mode_t umask_value; /* The umask value (surprise). */
head = NULL;
#ifdef lint
tail = NULL;
#endif
if (xstrtoumax (mode_string, &string_end, 8, &mode_value, "") == LONGINT_OK)
{
struct mode_change *p;
if (mode_value != (mode_value & CHMOD_MODE_BITS))
return MODE_INVALID;
p = make_node_op_equals ((mode_t) mode_value);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
return head;
}
umask_value = umask (0);
umask (umask_value); /* Restore the old value. */
--mode_string;
/* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */
do
{
/* Which bits in the mode are operated on. */
mode_t affected_bits = 0;
/* `affected_bits' modified by umask. */
mode_t affected_masked;
/* Operators to actually use umask on. */
unsigned ops_to_mask = 0;
int who_specified_p;
affected_bits = 0;
ops_to_mask = 0;
/* Turn on all the bits in `affected_bits' for each group given. */
for (++mode_string;; ++mode_string)
switch (*mode_string)
{
case 'u':
affected_bits |= S_ISUID | S_IRWXU;
break;
case 'g':
affected_bits |= S_ISGID | S_IRWXG;
break;
case 'o':
affected_bits |= S_ISVTX | S_IRWXO;
break;
case 'a':
affected_bits |= CHMOD_MODE_BITS;
break;
default:
goto no_more_affected;
}
no_more_affected:
/* If none specified, affect all bits, except perhaps those
set in the umask. */
if (affected_bits)
who_specified_p = 1;
else
{
who_specified_p = 0;
affected_bits = CHMOD_MODE_BITS;
ops_to_mask = masked_ops;
}
while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-')
{
struct mode_change *change = talloc (struct mode_change);
if (change == NULL)
{
mode_free (head);
return MODE_MEMORY_EXHAUSTED;
}
change->next = NULL;
change->op = *mode_string; /* One of "=+-". */
affected_masked = affected_bits;
/* Per the Single Unix Spec, if `who' is not specified and the
`=' operator is used, then clear all the bits first. */
if (!who_specified_p &&
ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS : 0))
{
struct mode_change *p = make_node_op_equals (0);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
}
if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS
: *mode_string == '+' ? MODE_MASK_PLUS
: MODE_MASK_MINUS))
affected_masked &= ~umask_value;
change->affected = affected_masked;
change->value = 0;
change->flags = 0;
/* Add the element to the tail of the list, so the operations
are performed in the correct order. */
mode_append_entry (&head, &tail, change);
/* Set `value' according to the bits set in `affected_masked'. */
for (++mode_string;; ++mode_string)
switch (*mode_string)
{
case 'r':
change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)
& affected_masked);
break;
case 'w':
change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)
& affected_masked);
break;
case 'X':
change->flags |= MODE_X_IF_ANY_X;
/* Fall through. */
case 'x':
change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)
& affected_masked);
break;
case 's':
/* Set the setuid/gid bits if `u' or `g' is selected. */
change->value |= (S_ISUID | S_ISGID) & affected_masked;
break;
case 't':
/* Set the "save text image" bit if `o' is selected. */
change->value |= S_ISVTX & affected_masked;
break;
case 'u':
/* Set the affected bits to the value of the `u' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXU;
change->flags |= MODE_COPY_EXISTING;
break;
case 'g':
/* Set the affected bits to the value of the `g' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXG;
change->flags |= MODE_COPY_EXISTING;
break;
case 'o':
/* Set the affected bits to the value of the `o' bits
on the same file. */
if (change->value)
goto invalid;
change->value = S_IRWXO;
change->flags |= MODE_COPY_EXISTING;
break;
default:
goto no_more_values;
}
no_more_values:;
}
} while (*mode_string == ',');
if (*mode_string == 0)
return head;
invalid:
mode_free (head);
return MODE_INVALID;
}
/* Return a file mode change operation that sets permissions to match those
of REF_FILE. Return MODE_BAD_REFERENCE if REF_FILE can't be accessed. */
struct mode_change *
mode_create_from_ref (const char *ref_file)
{
struct mode_change *change; /* the only change element */
struct stat ref_stats;
if (stat (ref_file, &ref_stats))
return MODE_BAD_REFERENCE;
change = talloc (struct mode_change);
if (change == NULL)
return MODE_MEMORY_EXHAUSTED;
change->op = '=';
change->flags = 0;
change->affected = CHMOD_MODE_BITS;
change->value = ref_stats.st_mode;
change->next = NULL;
return change;
}
/* Return file mode OLDMODE, adjusted as indicated by the list of change
operations CHANGES. If OLDMODE is a directory, the type `X'
change affects it even if no execute bits were set in OLDMODE.
The returned value has the S_IFMT bits cleared. */
mode_t
mode_adjust (mode_t oldmode, const struct mode_change *changes)
{
mode_t newmode; /* The adjusted mode and one operand. */
mode_t value; /* The other operand. */
newmode = oldmode & CHMOD_MODE_BITS;
for (; changes; changes = changes->next)
{
if (changes->flags & MODE_COPY_EXISTING)
{
/* Isolate in `value' the bits in `newmode' to copy, given in
the mask `changes->value'. */
value = newmode & changes->value;
if (changes->value & S_IRWXU)
/* Copy `u' permissions onto `g' and `o'. */
value |= ((value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
| (value & S_IWUSR ? S_IWGRP | S_IROTH : 0)
| (value & S_IXUSR ? S_IXGRP | S_IXOTH : 0));
else if (changes->value & S_IRWXG)
/* Copy `g' permissions onto `u' and `o'. */
value |= ((value & S_IRGRP ? S_IRUSR | S_IROTH : 0)
| (value & S_IWGRP ? S_IWUSR | S_IROTH : 0)
| (value & S_IXGRP ? S_IXUSR | S_IXOTH : 0));
else
/* Copy `o' permissions onto `u' and `g'. */
value |= ((value & S_IROTH ? S_IRUSR | S_IRGRP : 0)
| (value & S_IWOTH ? S_IWUSR | S_IRGRP : 0)
| (value & S_IXOTH ? S_IXUSR | S_IXGRP : 0));
/* In order to change only `u', `g', or `o' permissions,
or some combination thereof, clear unselected bits.
This can not be done in mode_compile because the value
to which the `changes->affected' mask is applied depends
on the old mode of each file. */
value &= changes->affected;
}
else
{
value = changes->value;
/* If `X', do not affect the execute bits if the file is not a
directory and no execute bits are already set. */
if ((changes->flags & MODE_X_IF_ANY_X)
&& !S_ISDIR (oldmode)
&& (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
/* Clear the execute bits. */
value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);
}
switch (changes->op)
{
case '=':
/* Preserve the previous values in `newmode' of bits that are
not affected by this change operation. */
newmode = (newmode & ~changes->affected) | value;
break;
case '+':
newmode |= value;
break;
case '-':
newmode &= ~value;
break;
}
}
return newmode;
}
/* Free the memory used by the list of file mode change operations
CHANGES. */
void
mode_free (register struct mode_change *changes)
{
register struct mode_change *next;
while (changes)
{
next = changes->next;
free (changes);
changes = next;
}
}

852
rebox.el
View File

@@ -1,852 +0,0 @@
;;; Handling of comment boxes.
;;; Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
;;; Fran<61>ois Pinard <pinard@iro.umontreal.ca>, April 1991.
;;; I first observed rounded corners, as in style 223 boxes, in code from
;;; Warren Tucker <wht@n4hgf.mt-park.ga.us>, a previous shar maintainer.
;;; Refilling paragraphs inside comments, stretching or shrinking the
;;; surrounding box as needed, is a pain to do "by hand". This GNU Emacs
;;; LISP code eases my life on this and I find it fair, giving all sources
;;; for a package, to also give the means for nicely modifying comments.
;;; The function rebox-comment discovers the extent of the boxed comments
;;; near the cursor, possibly refills the text, then adjusts the comment
;;; box style. The function rebox-region does the same, except that it
;;; takes the current region as a boxed comment. Numeric prefixes are
;;; used to add or remove a box, change its style (language, quality or
;;; type), or to prevent refilling of its text. A minus sign alone as
;;; prefix asks for interactive style selection.
;;; For most Emacs language editing modes, refilling does not make sense
;;; outside comments, so you may redefine the M-q command and link it to
;;; this file. For example, I use this in my .emacs file:
;;; (setq c-mode-hook
;;; '(lambda ()
;;; (define-key c-mode-map "\M-q" 'rebox-comment)))
;;; (autoload 'rebox-comment "rebox" nil t)
;;; (autoload 'rebox-region "rebox" nil t)
;;; The cursor should be within a comment before any of these commands,
;;; or else it should be between two comments, in which case the command
;;; applies to the next comment. When the command is given without prefix,
;;; the current comment box style is recognized from the comment itself
;;; as far as possible, and preserved. A prefix may be used to force
;;; a particular box style. A style is made up of three attributes: a
;;; language (the hundreds digit), a quality (the tens digit) and a type
;;; (the units digit). A zero or negative flag value changes the default
;;; box style to its absolute value. Zero digits in default style,
;;; when not overriden in flag, asks for recognition of corresponding
;;; attributes from the current box. `C-u' avoids refilling the text,
;;; using the default box style. `C-u -' defines the style interactively.
;;; Box language is associated with comment delimiters. Values are 100
;;; for none or unknown, 200 for `/*' and `*/' as in plain C, 300 for
;;; '//' as in C++, 400 for `#' as in most scripting languages, 500 for
;;; `;' as in LISP or assembler and 600 for `%' as in TeX or PostScript.
;;; Box quality differs according to language. For unknown languages (100)
;;; or for the C language (200), values are 10 for simple, 20 or 30 for
;;; rounded, and 40 for starred. For all others, box quality indicates
;;; the thickness in characters of the left and right sides of the box:
;;; values are 10, 20, 30 or 40 for 1, 2, 3 or 4 characters wide. C++
;;; quality 10 is always promoted to 20. Roughly said, simple quality
;;; boxes (10) use comment delimiters to left and right of each comment
;;; line, and also for the top or bottom line when applicable. Rounded
;;; quality boxes (20 or 30) try to suggest rounded corners in boxes.
;;; Starred quality boxes (40) mostly use a left margin of asterisks or
;;; X'es, and use them also in box surroundings. Experiment a little to
;;; see what happens.
;;; Box type values are 1 for fully opened boxes for which boxing is done
;;; only for the left and right but not for top or bottom, 2 for half
;;; single lined boxes for which boxing is done on all sides except top,
;;; 3 for fully single lined boxes for which boxing is done on all sides,
;;; 4 for half double lined boxes which is like type 2 but more bold,
;;; or 5 for fully double lined boxes which is like type 3 but more bold.
;;; The special style 221 or 231 is worth a note, because it is fairly
;;; common: the whole C comment stays between a single opening `/*'
;;; and a single closing `*/'. The special style 111 deletes a box.
;;; The initial default style is 023 so, unless overriden, comments are
;;; put in single lined boxes, C comments are of rounded quality.
(defvar rebox-default-style 0 "*Preferred style for box comments.")
;;; Help strings for prompting or error messages.
(defconst REBOX_HELP_FOR_LANGUAGE
"Box language is 100-none, 200-/*, 300-//, 400-#, 500-;, 600-%%")
(defconst REBOX_LANGUAGE_NONE 100)
(defconst REBOX_LANGUAGE_C 200)
(defconst REBOX_LANGUAGE_C++ 300)
(defconst REBOX_LANGUAGE_AWK 400)
(defconst REBOX_LANGUAGE_LISP 500)
(defconst REBOX_LANGUAGE_TEX 600)
(defun rebox-help-string-for-language (language)
(cond ((= language 0) "default language")
((= language REBOX_LANGUAGE_NONE) "no language")
((= language REBOX_LANGUAGE_C) "plain C")
((= language REBOX_LANGUAGE_C++) "C++")
((= language REBOX_LANGUAGE_AWK) "sh/Perl/make")
((= language REBOX_LANGUAGE_LISP) "LISP/assembler")
((= language REBOX_LANGUAGE_TEX) "TeX/PostScript")
(t "<Unknown Language>")))
(defconst REBOX_HELP_FOR_QUALITY
"Box quality/width is 10-simple, 20-rounded, 30-rounded or 40-starred")
(defconst REBOX_QUALITY_SIMPLE_ONE 10)
(defconst REBOX_QUALITY_ROUNDED_TWO 20)
(defconst REBOX_QUALITY_ROUNDED_THREE 30)
(defconst REBOX_QUALITY_STARRED_FOUR 40)
(defun rebox-help-string-for-quality (quality)
(cond ((= quality 0) "default quality")
((= quality REBOX_QUALITY_SIMPLE_ONE) "square or 1-wide")
((= quality REBOX_QUALITY_ROUNDED_TWO) "rounded or 2-wide")
((= quality REBOX_QUALITY_ROUNDED_THREE) "rounded or 3-wide")
((= quality REBOX_QUALITY_STARRED_FOUR) "starred or 4-wide")
(t "<Unknown Quality>")))
(defconst REBOX_HELP_FOR_TYPE
"Box type is 1-open, 2-half-single, 3-single, 4-half-double or 5-double")
(defconst REBOX_TYPE_OPEN 1)
(defconst REBOX_TYPE_HALF_SINGLE 2)
(defconst REBOX_TYPE_SINGLE 3)
(defconst REBOX_TYPE_HALF_DOUBLE 4)
(defconst REBOX_TYPE_DOUBLE 5)
(defun rebox-help-string-for-type (type)
(cond ((= type 0) "default type")
((= type REBOX_TYPE_OPEN) "opened box")
((= type REBOX_TYPE_HALF_SINGLE) "half normal")
((= type REBOX_TYPE_SINGLE) "full normal")
((= type REBOX_TYPE_HALF_DOUBLE) "half bold")
((= type REBOX_TYPE_DOUBLE) "full bold")
(t "<Unknown Type>")))
(defconst REBOX_MAX_LANGUAGE 6)
(defconst REBOX_MAX_QUALITY 4)
(defconst REBOX_MAX_TYPE 5)
;;; Request the style interactively, using the minibuffer.
(defun rebox-ask-for-style ()
(let (key language quality type)
(while (not language)
(message REBOX_HELP_FOR_LANGUAGE)
(setq key (read-char))
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_LANGUAGE)))
(setq language (- key ?0))))
(while (not quality)
(message REBOX_HELP_FOR_QUALITY)
(setq key (read-char))
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_QUALITY)))
(setq quality (- key ?0))))
(while (not type)
(message REBOX_HELP_FOR_TYPE)
(setq key (read-char))
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_TYPE)))
(setq type (- key ?0))))
(+ (* 100 language) (* 10 quality) type)))
;;; Write some TEXT followed by an edited STYLE value into the minibuffer.
(defun rebox-show-style (text style)
(message
(concat text (format " (%03d)" style)
": " (rebox-help-string-for-language (* (/ style 100) 100))
", " (rebox-help-string-for-quality (* (% (/ style 10) 10) 10))
", " (rebox-help-string-for-type (% style 10)))))
;;; Validate FLAG and usually return t if not interrupted by errors.
;;; But if FLAG is zero or negative, then change default box style and
;;; return nil.
(defun rebox-validate-flag (flag)
;; Validate flag.
(if (numberp flag)
(let ((value (if (< flag 0) (- flag) flag)))
(if (> (/ value 100) REBOX_MAX_LANGUAGE)
(error REBOX_HELP_FOR_LANGUAGE))
(if (> (% (/ value 10) 10) REBOX_MAX_QUALITY)
(error REBOX_HELP_FOR_QUALITY))
(if (> (% value 10) REBOX_MAX_TYPE)
(error REBOX_HELP_FOR_TYPE))))
;; Change default box style if requested.
(if (and (numberp flag) (<= flag 0))
(progn
(setq flag (- flag))
(if (not (zerop (/ flag 100)))
(setq rebox-default-style
(+ (* (/ flag 100) 100)
(% rebox-default-style 100))))
(if (not (zerop (% (/ flag 10) 10)))
(setq rebox-default-style
(+ (* (/ rebox-default-style 100) 100)
(* (% (/ flag 10) 10) 10)
(% rebox-default-style 10))))
(if (not (zerop (% flag 10)))
(setq rebox-default-style
(+ (* (/ rebox-default-style 10) 10)
(% flag 10))))
(rebox-show-style "Default style" rebox-default-style)
nil)
t))
;;; Return the minimum value of the left margin of all lines, or -1 if
;;; all lines are empty.
(defun rebox-left-margin ()
(let ((margin -1))
(goto-char (point-min))
(while (not (eobp))
(skip-chars-forward " \t")
(if (not (looking-at "\n"))
(setq margin
(if (< margin 0)
(current-column)
(min margin (current-column)))))
(forward-line 1))
margin))
;;; Return the maximum value of the right margin of all lines. Any
;;; sentence ending a line has a space guaranteed before the margin.
(defun rebox-right-margin ()
(let ((margin 0) period)
(goto-char (point-min))
(while (not (eobp))
(end-of-line)
(if (bobp)
(setq period 0)
(backward-char 1)
(setq period (if (looking-at "[.?!]") 1 0))
(forward-char 1))
(setq margin (max margin (+ (current-column) period)))
(forward-char 1))
margin))
;;; Return a regexp to match the start or end of a comment for some
;;; LANGUAGE, leaving the comment marks themselves available in \1.
;; FIXME: Recognize style 1** boxes.
(defun rebox-regexp-start (language)
(cond ((= language 0) "^[ \t]*\\(/\\*\\|//+\\|#+\\|;+\\|%+\\)")
((= language REBOX_LANGUAGE_NONE) "^\\(\\)")
((= language REBOX_LANGUAGE_C) "^[ \t]*\\(/\\*\\)")
((= language REBOX_LANGUAGE_C++) "^[ \t]*\\(//+\\)")
((= language REBOX_LANGUAGE_AWK) "^[ \t]*\\(#+\\)")
((= language REBOX_LANGUAGE_LISP) "^[ \t]*\\(;+\\)")
((= language REBOX_LANGUAGE_TEX) "^[ \t]*\\(%+\\)")))
(defun rebox-regexp-end (language)
(cond ((= language 0) "\\(\\*/\\|//+\\|#+\\|;+\\|%+\\)[ \t]*$")
((= language REBOX_LANGUAGE_NONE) "\\(\\)$")
((= language REBOX_LANGUAGE_C) "\\(\\*/\\)[ \t]*$")
((= language REBOX_LANGUAGE_C++) "\\(//+\\)[ \t]*$")
((= language REBOX_LANGUAGE_AWK) "\\(#+\\)[ \t]*$")
((= language REBOX_LANGUAGE_LISP) "\\(;+\\)[ \t]*$")
((= language REBOX_LANGUAGE_TEX) "\\(%+\\)[ \t]*$")))
;;; By looking at the text starting at the cursor position, guess the
;;; language in use, and return it.
(defun rebox-guess-language ()
(let ((language REBOX_LANGUAGE_NONE)
(value (* 100 REBOX_MAX_LANGUAGE)))
(while (not (zerop value))
(if (looking-at (rebox-regexp-start value))
(progn
(setq language value)
(setq value 0))
(setq value (- value 100))))
language))
;;; Find the limits of the block of comments following or enclosing
;;; the cursor, or return an error if the cursor is not within such a
;;; block of comments. Extend it as far as possible in both
;;; directions, then narrow the buffer around it.
(defun rebox-find-and-narrow ()
(save-excursion
(let (start end temp language)
;; Find the start of the current or immediately following comment.
(beginning-of-line)
(skip-chars-forward " \t\n")
(beginning-of-line)
(if (not (looking-at (rebox-regexp-start 0)))
(progn
(setq temp (point))
(if (re-search-forward "\\*/" nil t)
(progn
(re-search-backward "/\\*")
(if (> (point) temp)
(error "outside any comment block"))
(setq temp (point))
(beginning-of-line)
(skip-chars-forward " \t")
(if (not (= (point) temp))
(error "text before start of comment"))
(beginning-of-line))
(error "outside any comment block"))))
(setq start (point))
(setq language (rebox-guess-language))
;; - find the end of this comment
(if (= language REBOX_LANGUAGE_C)
(progn
(search-forward "*/")
(if (not (looking-at "[ \t]*$"))
(error "text after end of comment"))))
(end-of-line)
(if (eobp)
(insert "\n")
(forward-char 1))
(setq end (point))
;; - try to extend the comment block backwards
(goto-char start)
(while (and (not (bobp))
(if (= language REBOX_LANGUAGE_C)
(progn
(skip-chars-backward " \t\n")
(if (and (looking-at "[ \t]*\n[ \t]*/\\*")
(> (point) 2))
(progn
(backward-char 2)
(if (looking-at "\\*/")
(progn
(re-search-backward "/\\*")
(setq temp (point))
(beginning-of-line)
(skip-chars-forward " \t")
(if (= (point) temp)
(progn (beginning-of-line) t)))))))
(previous-line 1)
(looking-at (rebox-regexp-start language))))
(setq start (point)))
;; - try to extend the comment block forward
(goto-char end)
(while (looking-at (rebox-regexp-start language))
(if (= language REBOX_LANGUAGE_C)
(progn
(re-search-forward "[ \t]*/\\*")
(re-search-forward "\\*/")
(if (looking-at "[ \t]*$")
(progn
(beginning-of-line)
(forward-line 1)
(setq end (point)))))
(forward-line 1)
(setq end (point))))
;; - narrow to the whole block of comments
(narrow-to-region start end))))
;;; After refilling it if REFILL is not nil, while respecting a left
;;; MARGIN, put the narrowed buffer back into a boxed LANGUAGE comment
;;; box of a given QUALITY and TYPE.
(defun rebox-reconstruct (refill margin language quality type)
(rebox-show-style "Style" (+ language quality type))
(let (right-margin nw nn ne ww ee sw ss se x xx)
;; - decide the elements of the box being produced
(cond ((= language REBOX_LANGUAGE_NONE)
;; - planify a comment for no language in particular
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
;; - planify a simple box
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "| ") (setq ee " |")
(setq sw "+-") (setq ss ?-) (setq se "-+"))
((= type REBOX_TYPE_SINGLE)
(setq nw "+-") (setq nn ?-) (setq ne "-+")
(setq ww "| ") (setq ee " |")
(setq sw "+-") (setq ss ?-) (setq se "-+"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "| ") (setq ee " |")
(setq sw "*=") (setq ss ?=) (setq se "=*"))
((= type REBOX_TYPE_DOUBLE)
(setq nw "*=") (setq nn ?=) (setq ne "=*")
(setq ww "| ") (setq ee " |")
(setq sw "*=") (setq ss ?=) (setq se "=*"))))
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
(= quality REBOX_QUALITY_ROUNDED_THREE))
;; - planify a rounded box
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "| ") (setq ee " |"))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "-'"))
((= type REBOX_TYPE_SINGLE)
(setq nw ".-") (setq nn ?-) (setq ne "-.")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "-'"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/=" ) (setq nn ?=) (setq ne "=\\")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))))
((= quality REBOX_QUALITY_STARRED_FOUR)
;; - planify a starred box
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "| ") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "* ") (setq ee " *")
(setq sw "**") (setq ss ?*) (setq se "**"))
((= type REBOX_TYPE_SINGLE)
(setq nw "**") (setq nn ?*) (setq ne "**")
(setq ww "* ") (setq ee " *")
(setq sw "**") (setq ss ?*) (setq se "**"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "X ") (setq ee " X")
(setq sw "XX") (setq ss ?X) (setq se "XX"))
((= type REBOX_TYPE_DOUBLE)
(setq nw "XX") (setq nn ?X) (setq ne "XX")
(setq ww "X ") (setq ee " X")
(setq sw "XX") (setq ss ?X) (setq se "XX"))))))
((= language REBOX_LANGUAGE_C)
;; - planify a comment for C
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
;; - planify a simple C comment
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "")
(setq ww "/* ") (setq ee " */"))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?-) (setq se " */"))
((= type REBOX_TYPE_SINGLE)
(setq nw "/* ") (setq nn ?-) (setq ne " */")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?-) (setq se " */"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?=) (setq se " */"))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/* ") (setq nn ?=) (setq ne " */")
(setq ww "/* ") (setq ee " */")
(setq sw "/* ") (setq ss ?=) (setq se " */"))))
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
(= quality REBOX_QUALITY_ROUNDED_THREE))
;; - planify a rounded C comment
(cond ((= type REBOX_TYPE_OPEN)
;; ``open rounded'' is a special case
(setq nw "") (setq sw "")
(setq ww " ") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "/*") (setq nn ? ) (setq ne " .")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "*/"))
((= type REBOX_TYPE_SINGLE)
(setq nw "/*") (setq nn ?-) (setq ne "-.")
(setq ww "| ") (setq ee " |")
(setq sw "`-") (setq ss ?-) (setq se "*/"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "/*" ) (setq nn ? ) (setq ne " \\")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/*" ) (setq nn ?=) (setq ne "=\\")
(setq ww "| " ) (setq ee " |" )
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))))
((= quality REBOX_QUALITY_STARRED_FOUR)
;; - planify a starred C comment
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "/* ") (setq nn ? ) (setq ne "")
(setq ww " * ") (setq ee "")
(setq sw " */") (setq ss ? ) (setq se ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq nw "/* ") (setq nn ? ) (setq ne " *")
(setq ww " * ") (setq ee " *")
(setq sw " **") (setq ss ?*) (setq se "**/"))
((= type REBOX_TYPE_SINGLE)
(setq nw "/**") (setq nn ?*) (setq ne "**")
(setq ww " * ") (setq ee " *")
(setq sw " **") (setq ss ?*) (setq se "**/"))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq nw "/* " ) (setq nn ? ) (setq ne " *\\")
(setq ww "|* " ) (setq ee " *|" )
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))
((= type REBOX_TYPE_DOUBLE)
(setq nw "/**" ) (setq nn ?*) (setq ne "**\\")
(setq ww "|* " ) (setq ee " *|" )
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))))))
(t
;; - planify a comment for all other things
(if (and (= language REBOX_LANGUAGE_C++)
(= quality REBOX_QUALITY_SIMPLE_ONE))
(setq quality REBOX_QUALITY_ROUNDED_TWO))
(setq x (cond ((= language REBOX_LANGUAGE_C++) ?/)
((= language REBOX_LANGUAGE_AWK) ?#)
((= language REBOX_LANGUAGE_LISP) ?\;)
((= language REBOX_LANGUAGE_TEX) ?%)))
(setq xx (make-string (/ quality 10) x))
(setq ww (concat xx " "))
(cond ((= type REBOX_TYPE_OPEN)
(setq nw "") (setq sw "") (setq ee ""))
((= type REBOX_TYPE_HALF_SINGLE)
(setq ee (concat " " xx))
(setq nw "")
(setq sw ww) (setq ss ?-) (setq se ee))
((= type REBOX_TYPE_SINGLE)
(setq ee (concat " " xx))
(setq nw ww) (setq nn ?-) (setq ne ee)
(setq sw ww) (setq ss ?-) (setq se ee))
((= type REBOX_TYPE_HALF_DOUBLE)
(setq ee (concat " " xx))
(setq xx (make-string (1+ (/ quality 10)) x))
(setq nw "")
(setq sw xx) (setq ss x) (setq se xx))
((= type REBOX_TYPE_DOUBLE)
(setq ee (concat " " xx))
(setq xx (make-string (1+ (/ quality 10)) x))
(setq nw xx) (setq nn x) (setq ne xx)
(setq sw xx) (setq ss x) (setq se xx)))))
;; - possibly refill, and adjust margins to account for left inserts
(if (not (and flag (listp flag)))
(let ((fill-prefix (make-string margin ? ))
(fill-column (- fill-column (+ (length ww) (length ee)))))
(fill-region (point-min) (point-max))))
(setq right-margin (+ (rebox-right-margin) (length ww)))
;; - construct the box comment, from top to bottom
(goto-char (point-min))
(if (and (= language REBOX_LANGUAGE_C)
(or (= quality REBOX_QUALITY_ROUNDED_TWO)
(= quality REBOX_QUALITY_ROUNDED_THREE))
(= type REBOX_TYPE_OPEN))
(progn
;; - construct an 33 style comment
(skip-chars-forward " " (+ (point) margin))
(insert (make-string (- margin (current-column)) ? )
"/* ")
(end-of-line)
(forward-char 1)
(while (not (eobp))
(skip-chars-forward " " (+ (point) margin))
(insert (make-string (- margin (current-column)) ? )
ww)
(beginning-of-line)
(forward-line 1))
(backward-char 1)
(insert " */"))
;; - construct all other comment styles
;; construct one top line
(if (not (zerop (length nw)))
(progn
(indent-to margin)
(insert nw)
(if (or (not (eq nn ? )) (not (zerop (length ne))))
(insert (make-string (- right-margin (current-column)) nn)
ne))
(insert "\n")))
;; construct one middle line
(while (not (eobp))
(skip-chars-forward " " (+ (point) margin))
(insert (make-string (- margin (current-column)) ? )
ww)
(end-of-line)
(if (not (zerop (length ee)))
(progn
(indent-to right-margin)
(insert ee)))
(beginning-of-line)
(forward-line 1))
;; construct one bottom line
(if (not (zerop (length sw)))
(progn
(indent-to margin)
(insert sw)
(if (or (not (eq ss ? )) (not (zerop (length se))))
(insert (make-string (- right-margin (current-column)) ss)
se "\n")))))))
;;; Add, delete or adjust a comment box in the narrowed buffer.
;;; Various FLAG values are explained at beginning of this file.
(defun rebox-engine (flag)
(let ((undo-list buffer-undo-list)
(marked-point (point-marker))
(language (progn (goto-char (point-min)) (rebox-guess-language)))
(quality 0)
(type 0))
(untabify (point-min) (point-max))
;; Remove all the comment marks, and move all the text rigidly to the
;; left for insuring that the left margin stays at the same place.
;; At the same time, try recognizing the box style, saving its quality
;; in QUALITY and its type in TYPE. (LANGUAGE is already guessed.)
(let ((indent-tabs-mode nil)
(previous-margin (rebox-left-margin))
actual-margin)
;; FIXME: Cleanup style 1** boxes.
;; FIXME: Recognize really all cases of type and quality.
;; - remove all comment marks
(if (= language REBOX_LANGUAGE_NONE)
nil
(goto-char (point-min))
(while (re-search-forward (rebox-regexp-start language) nil t)
(goto-char (match-beginning 1))
(delete-region (point) (match-end 1))
(insert (make-string (- (match-end 1) (point)) ? )))
(goto-char (point-min))
(while (re-search-forward (rebox-regexp-end language) nil t)
(replace-match "" t t)))
(if (= language REBOX_LANGUAGE_C)
(progn
(goto-char (point-min))
(while (re-search-forward "\\*/ */\\*" nil t)
(replace-match " " t t))
(goto-char (point-min))
(while (re-search-forward "^\\( *\\)|\\*\\(.*\\)\\*| *$" nil t)
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_DOUBLE)
(replace-match "\\1 \\2" t))
(goto-char (point-min))
(while (re-search-forward "^\\( *\\)\\*\\(.*\\)\\* *$" nil t)
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_SINGLE)
(replace-match "\\1 \\2" t))
(goto-char (point-min))
(while (re-search-forward "^\\( *\\)|\\(.*\\)| *$" nil t)
(setq quality REBOX_QUALITY_ROUNDED_TWO)
(replace-match "\\1 \\2" t))
(goto-char (point-min))
(if (zerop quality)
(while (re-search-forward "^\\( +\\)\\* " nil t)
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_OPEN)
(replace-match "\\1 " t)))))
;; - remove the first dashed or starred line
(goto-char (point-min))
(if (looking-at "^ *\\(--+\\|\\*\\*+\\)[.\+\\]? *\n")
(progn
(setq type REBOX_TYPE_SINGLE)
(replace-match "" t t))
(if (looking-at "^ *\\(==\\|XX+\\|##+\\|;;+\\)[.\+\\]? *\n")
(progn
(setq type REBOX_TYPE_DOUBLE)
(replace-match "" t t))))
;; - remove the last dashed or starred line
(goto-char (point-max))
(previous-line 1)
(if (looking-at "^ *[`\+\\]?*--+ *\n")
(progn
(if (= type REBOX_TYPE_OPEN)
(setq type REBOX_TYPE_HALF_SINGLE))
(replace-match "" t t))
(if (looking-at "^ *[`\+\\]?*\\(==+\\|##+\\|;;+\\) *\n")
(progn
(if (= type REBOX_TYPE_OPEN)
(setq type REBOX_TYPE_HALF_DOUBLE))
(replace-match "" t t))
(if (looking-at "^ *\\*\\*+[.\+\\]? *\n")
(progn
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_HALF_SINGLE)
(replace-match "" t t))
(if (looking-at "^ *XX+[.\+\\]? *\n")
(progn
(setq quality REBOX_QUALITY_STARRED_FOUR)
(setq type REBOX_TYPE_HALF_DOUBLE)
(replace-match "" t t))))))
;; - remove all spurious whitespace
(goto-char (point-min))
(while (re-search-forward " +$" nil t)
(replace-match "" t t))
(goto-char (point-min))
(if (looking-at "\n+")
(replace-match "" t t))
(goto-char (point-max))
(skip-chars-backward "\n")
(if (looking-at "\n\n+")
(replace-match "\n" t t))
(goto-char (point-min))
(while (re-search-forward "\n\n\n+" nil t)
(replace-match "\n\n" t t))
;; - move the text left is adequate
(setq actual-margin (rebox-left-margin))
(if (not (= previous-margin actual-margin))
(indent-rigidly (point-min) (point-max)
(- previous-margin actual-margin))))
;; Override box style according to FLAG or chosen default style.
;; Else, use either recognized style elements or built-in defaults.
(cond ((and (numberp flag) (not (zerop (/ flag 100))))
(setq language (* (/ flag 100) 100)))
((not (zerop (/ rebox-default-style 100)))
(setq language (* (/ rebox-default-style 100) 100))))
(cond ((and (numberp flag) (not (zerop (% (/ flag 10) 10))))
(setq quality (* (% (/ flag 10) 10) 10)))
((not (zerop (% (/ rebox-default-style 10) 10)))
(setq quality (* (% (/ rebox-default-style 10) 10) 10)))
((zerop quality)
(setq quality REBOX_QUALITY_ROUNDED_TWO)))
(cond ((and (numberp flag) (not (zerop (% flag 10))))
(setq type (% flag 10)))
((not (zerop (% rebox-default-style 10)))
(setq type (% rebox-default-style 10)))
((zerop type)
(setq type 1)))
;; Possibly refill, then reconstruct the comment box.
(let ((indent-tabs-mode nil))
(rebox-reconstruct (not (and flag (listp flag)))
(rebox-left-margin)
language quality type))
;; Retabify to the left only (adapted from tabify.el).
(if indent-tabs-mode
(progn
(goto-char (point-min))
(while (re-search-forward "^[ \t][ \t]+" nil t)
(let ((column (current-column)))
(delete-region (match-beginning 0) (point))
(indent-to column)))))
;; Restore the point position.
(goto-char (marker-position marked-point))
;; Remove all intermediate boundaries from the undo list.
(if (not (eq buffer-undo-list undo-list))
(let ((cursor buffer-undo-list))
(while (not (eq (cdr cursor) undo-list))
(if (car (cdr cursor))
(setq cursor (cdr cursor))
(rplacd cursor (cdr (cdr cursor)))))))))
;;; Set or reset the Taarna team's own way for a C style. You do not
;;; really want to know about this.
(defvar c-mode-taarna-style nil "*Non-nil for Taarna team C-style.")
(defun taarna-mode ()
(interactive)
(if c-mode-taarna-style
(progn
(setq c-mode-taarna-style nil)
(setq c-indent-level 2)
(setq c-continued-statement-offset 2)
(setq c-brace-offset 0)
(setq c-argdecl-indent 5)
(setq c-label-offset -2)
(setq c-tab-always-indent t)
(setq rebox-default-style REBOX_QUALITY_ROUNDED_TWO)
(message "C mode: GNU style"))
(setq c-mode-taarna-style t)
(setq c-indent-level 4)
(setq c-continued-statement-offset 4)
(setq c-brace-offset -4)
(setq c-argdecl-indent 4)
(setq c-label-offset -4)
(setq c-tab-always-indent t)
(setq rebox-default-style
(+ REBOX_QUALITY_SIMPLE_ONE REBOX_TYPE_HALF_SINGLE))
(message "C mode: Taarna style")))
;;; Rebox the current region.
(defun rebox-region (flag)
(interactive "P")
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
(if (rebox-validate-flag flag)
(save-restriction
(narrow-to-region (region-beginning) (region-end))
(rebox-engine flag))))
;;; Rebox the surrounding comment.
(defun rebox-comment (flag)
(interactive "P")
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
(if (rebox-validate-flag flag)
(save-restriction
(rebox-find-and-narrow)
(rebox-engine flag))))

View File

@@ -65,9 +65,9 @@ XLIST=exclude_files
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.
# volume. Administrators may want to tailor this script for their site.
# If this variable isn't set, tar will use some default behavior which is
# probably defined in the manual.
# probably defined in the manual.
#DUMP_REMIND_SCRIPT='rsh apple-gunkies /home/gd2/dump/dump-remind'
# Message to display on the terminal while waiting for dump time. Usually
@@ -75,7 +75,7 @@ SLEEP_TIME=15
# entertaining than this. The awk script here saves some redundant
# repetition, but is not really all that desirable.
SLEEP_MESSAGE="`awk '
BEGIN {
BEGIN {
for (i = 0; i < 30; i++)
print \" \" \
\"D O N O T T O U C H T H I S T E R M I N A L !!!!!\"

View File

@@ -2,14 +2,14 @@
# This file is included in the GNU tar distribution as an example. It is
# not used by default unless the proper line is uncommented in backup-specs.
# System administrators will probably want to customize this and
# backup-specs for their site.
# backup-specs for their site.
#
# This script should be run by tar with --info-script (-F) to inform
# interested parties that a tape for the next volume of the backup needs to
# be put in the tape drive.
# be put in the tape drive.
#
# Include location of `sendmail' and GNU finger.
# Include location of `sendmail' and GNU finger.
PATH="/usr/lib:/usr/local/gnubin:${PATH}"
export PATH
@@ -27,7 +27,7 @@ MT_OFFLINE
#
# Certain users (like `root') aren't real users, and shouldn't be notified.
# Neither should `zippy', `elvis', etc. (on the GNU machines) since they're
# just test accounts.
# just test accounts.
recipients="`
finger .clients 2> /dev/null \
| sed -ne '
@@ -69,8 +69,8 @@ Cc: ${ADMINISTRATOR}
Subject: Backup needs new tape for volume ${TAR_VOLUME}
Reply-To: ${ADMINISTRATOR}
This is an automated report from the backup script running on
`hostname`.
This is an automated report from the backup script running on
`hostname`.
Volume ${TAR_VOLUME} of the backup needs to be put in the tape drive.
Usually whoever prepared the backup leaves labeled tapes on top of the
@@ -92,8 +92,8 @@ Cc: ${ADMINISTRATOR}
Subject: Volume ${TAR_VOLUME} for backup has been added
Reply-To: ${ADMINISTRATOR}
This is an automated report from the backup script running on
`hostname`.
This is an automated report from the backup script running on
`hostname`.
The backup has been continued, so for now no further attention is required.
__EOF__

View File

@@ -211,7 +211,7 @@ sub write_incr_db ($$) {
sub write_incr_db_0 ($$) {
my $info = shift;
my $file = shift;
my $timestamp_sec = $info->[1];
print $file "$timestamp_sec\n";
@@ -226,7 +226,7 @@ sub write_incr_db_0 ($$) {
sub write_incr_db_1 ($$) {
my $info = shift;
my $file = shift;
print $file "GNU tar-1.15-1\n";
my $timestamp_sec = $info->[1];
@@ -246,7 +246,7 @@ sub write_incr_db_1 ($$) {
sub write_incr_db_2 ($$) {
my $info = shift;
my $file = shift;
print $file "GNU tar-1.16-2\n";
my $timestamp_sec = $info->[1];

View File

@@ -35,8 +35,7 @@ do
fi
if [ "$T" = "M" ]; then
SKIP=$(($SKIP + 1))
fi
fi
fi
dd skip=$SKIP if="$f"
dd skip=$SKIP if="$f"
done

View File

@@ -1,10 +1,10 @@
/* xsparse - expands compressed sparse file images extracted from GNU tar
archives.
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc.
Written by Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
@@ -20,8 +20,10 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -38,7 +40,7 @@
struct sp_array
{
off_t offset;
size_t numbytes;
off_t numbytes;
};
char *progname;
@@ -128,12 +130,12 @@ get_var (FILE *fp, char **name, char **value)
static char *buffer;
static size_t bufsize = OFF_T_STRSIZE_BOUND;
char *p, *q;
buffer = emalloc (bufsize);
do
{
size_t len, s;
if (!fgets (buffer, bufsize, fp))
return 0;
len = strlen (buffer);
@@ -185,12 +187,12 @@ read_xheader (char *name)
if (verbose)
printf ("Reading extended header file\n");
while (get_var (fp, &kw, &val))
{
if (verbose)
printf ("Found variable GNU.sparse.%s = %s\n", kw, val);
if (expect && strcmp (kw, expect))
die (1, "bad keyword sequence: expected `%s' but found `%s'",
expect, kw);
@@ -225,7 +227,7 @@ read_xheader (char *name)
}
else if (strcmp (kw, "numbytes") == 0)
{
sparse_map[i++].numbytes = string_to_size (val, NULL);
sparse_map[i++].numbytes = string_to_off (val, NULL);
}
else if (strcmp (kw, "map") == 0)
{
@@ -235,7 +237,7 @@ read_xheader (char *name)
if (*val != ',')
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
*val);
sparse_map[i].numbytes = string_to_size (val+1, &val);
sparse_map[i].numbytes = string_to_off (val+1, &val);
if (*val != ',')
{
if (!(*val == 0 && i == sparse_map_size-1))
@@ -266,7 +268,7 @@ read_map (FILE *ifp)
if (verbose)
printf ("Reading v.1.0 sparse map\n");
get_line (nbuf, sizeof nbuf, ifp);
sparse_map_size = string_to_size (nbuf, NULL);
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
@@ -276,31 +278,34 @@ read_map (FILE *ifp)
get_line (nbuf, sizeof nbuf, ifp);
sparse_map[i].offset = string_to_off (nbuf, NULL);
get_line (nbuf, sizeof nbuf, ifp);
sparse_map[i].numbytes = string_to_size (nbuf, NULL);
sparse_map[i].numbytes = string_to_off (nbuf, NULL);
}
fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
SEEK_SET);
}
fseeko (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
SEEK_SET);
}
void
expand_sparse (FILE *sfp, int ofd)
{
size_t i;
size_t maxbytes = 0;
off_t max_numbytes = 0;
size_t maxbytes;
char *buffer;
for (i = 0; i < sparse_map_size; i++)
if (maxbytes < sparse_map[i].numbytes)
maxbytes = sparse_map[i].numbytes;
if (max_numbytes < sparse_map[i].numbytes)
max_numbytes = sparse_map[i].numbytes;
maxbytes = max_numbytes < SIZE_MAX ? max_numbytes : SIZE_MAX;
for (buffer = malloc (maxbytes); !buffer; maxbytes /= 2)
if (maxbytes == 0)
die (1, "not enough memory");
for (i = 0; i < sparse_map_size; i++)
{
size_t size = sparse_map[i].numbytes;
off_t size = sparse_map[i].numbytes;
if (size == 0)
ftruncate (ofd, sparse_map[i].offset);
@@ -341,13 +346,13 @@ guess_outname (char *name)
{
char *p;
char *s;
if (name[0] == '.' && name[1] == '/')
name += 2;
p = name + strlen (name) - 1;
s = NULL;
for (; p > name && *p != '/'; p--)
;
if (*p == '/')
@@ -357,7 +362,7 @@ guess_outname (char *name)
for (p--; p > name && *p != '/'; p--)
;
}
if (*p != '/')
{
if (s)
@@ -388,7 +393,7 @@ main (int argc, char **argv)
FILE *ifp;
struct stat st;
int ofd;
progname = argv[0];
while ((c = getopt (argc, argv, "hnvx:")) != EOF)
{
@@ -407,7 +412,7 @@ main (int argc, char **argv)
case 'v':
verbose++;
break;
default:
exit (1);
}
@@ -428,17 +433,17 @@ main (int argc, char **argv)
if (stat (inname, &st))
die (1, "cannot stat %s (%d)", inname, errno);
ifp = fopen (inname, "r");
if (ifp == NULL)
die (1, "cannot open file %s (%d)", inname, errno);
if (!xheader_file || version_major == 1)
read_map (ifp);
if (!outname)
guess_outname (inname);
ofd = open (outname, O_RDWR|O_CREAT|O_TRUNC, st.st_mode);
if (ofd == -1)
die (1, "cannot open file %s (%d)", outname, errno);
@@ -451,7 +456,7 @@ main (int argc, char **argv)
printf ("Finished dry run\n");
return 0;
}
expand_sparse (ifp, ofd);
fclose (ifp);
@@ -459,7 +464,7 @@ main (int argc, char **argv)
if (verbose)
printf ("Done\n");
if (outsize)
{
if (stat (outname, &st))
@@ -467,7 +472,6 @@ main (int argc, char **argv)
if (st.st_size != outsize)
die (1, "expanded file has wrong size");
}
return 0;
}

View File

@@ -27,6 +27,7 @@ tar_SOURCES = \
compare.c\
create.c\
delete.c\
exit.c\
extract.c\
xheader.c\
incremen.c\
@@ -38,11 +39,13 @@ tar_SOURCES = \
system.c\
tar.c\
transform.c\
unlink.c\
update.c\
utf8.c
utf8.c\
warning.c
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)

View File

@@ -1,973 +0,0 @@
# Makefile.in generated by automake 1.10.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Makefile for GNU tar sources.
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
# 2007, 2009 Free Software Foundation, Inc.
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = tar$(EXEEXT)
subdir = src
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in ansi2knr.1 ansi2knr.c
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \
$(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/argmatch.m4 \
$(top_srcdir)/m4/argp.m4 $(top_srcdir)/m4/backupfile.m4 \
$(top_srcdir)/m4/bison.m4 $(top_srcdir)/m4/btowc.m4 \
$(top_srcdir)/m4/canonicalize-lgpl.m4 \
$(top_srcdir)/m4/chdir-long.m4 $(top_srcdir)/m4/chown.m4 \
$(top_srcdir)/m4/clock_time.m4 \
$(top_srcdir)/m4/close-stream.m4 $(top_srcdir)/m4/close.m4 \
$(top_srcdir)/m4/closeout.m4 $(top_srcdir)/m4/codeset.m4 \
$(top_srcdir)/m4/d-ino.m4 $(top_srcdir)/m4/dirent_h.m4 \
$(top_srcdir)/m4/dirfd.m4 $(top_srcdir)/m4/dirname.m4 \
$(top_srcdir)/m4/dos.m4 $(top_srcdir)/m4/double-slash-root.m4 \
$(top_srcdir)/m4/dup2.m4 $(top_srcdir)/m4/eealloc.m4 \
$(top_srcdir)/m4/environ.m4 $(top_srcdir)/m4/errno_h.m4 \
$(top_srcdir)/m4/error.m4 $(top_srcdir)/m4/exclude.m4 \
$(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \
$(top_srcdir)/m4/fchdir.m4 $(top_srcdir)/m4/fclose.m4 \
$(top_srcdir)/m4/fcntl-safer.m4 $(top_srcdir)/m4/fcntl_h.m4 \
$(top_srcdir)/m4/fileblocks.m4 $(top_srcdir)/m4/float_h.m4 \
$(top_srcdir)/m4/fnmatch.m4 $(top_srcdir)/m4/fpending.m4 \
$(top_srcdir)/m4/fseeko.m4 $(top_srcdir)/m4/ftruncate.m4 \
$(top_srcdir)/m4/getcwd-abort-bug.m4 \
$(top_srcdir)/m4/getcwd-path-max.m4 $(top_srcdir)/m4/getcwd.m4 \
$(top_srcdir)/m4/getdate.m4 $(top_srcdir)/m4/getdelim.m4 \
$(top_srcdir)/m4/getline.m4 $(top_srcdir)/m4/getopt.m4 \
$(top_srcdir)/m4/getpagesize.m4 $(top_srcdir)/m4/gettext.m4 \
$(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \
$(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/hash.m4 \
$(top_srcdir)/m4/human.m4 $(top_srcdir)/m4/iconv.m4 \
$(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/inline.m4 \
$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax_t.m4 \
$(top_srcdir)/m4/inttostr.m4 $(top_srcdir)/m4/inttypes-pri.m4 \
$(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/inttypes_h.m4 \
$(top_srcdir)/m4/lchown.m4 $(top_srcdir)/m4/lib-ld.m4 \
$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
$(top_srcdir)/m4/localcharset.m4 $(top_srcdir)/m4/locale-fr.m4 \
$(top_srcdir)/m4/locale-ja.m4 $(top_srcdir)/m4/locale-zh.m4 \
$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/lseek.m4 \
$(top_srcdir)/m4/lstat.m4 $(top_srcdir)/m4/malloc.m4 \
$(top_srcdir)/m4/malloca.m4 $(top_srcdir)/m4/mbchar.m4 \
$(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrtowc.m4 \
$(top_srcdir)/m4/mbscasecmp.m4 $(top_srcdir)/m4/mbsinit.m4 \
$(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/mempcpy.m4 \
$(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/mkdtemp.m4 \
$(top_srcdir)/m4/mktime.m4 $(top_srcdir)/m4/modechange.m4 \
$(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/open.m4 $(top_srcdir)/m4/openat.m4 \
$(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/paxutils.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/quote.m4 \
$(top_srcdir)/m4/quotearg.m4 $(top_srcdir)/m4/rawmemchr.m4 \
$(top_srcdir)/m4/readlink.m4 $(top_srcdir)/m4/realloc.m4 \
$(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/rmt.m4 \
$(top_srcdir)/m4/rpmatch.m4 $(top_srcdir)/m4/rtapelib.m4 \
$(top_srcdir)/m4/safe-read.m4 $(top_srcdir)/m4/safe-write.m4 \
$(top_srcdir)/m4/save-cwd.m4 $(top_srcdir)/m4/savedir.m4 \
$(top_srcdir)/m4/setenv.m4 $(top_srcdir)/m4/size_max.m4 \
$(top_srcdir)/m4/sleep.m4 $(top_srcdir)/m4/snprintf.m4 \
$(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \
$(top_srcdir)/m4/stdarg.m4 $(top_srcdir)/m4/stdbool.m4 \
$(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \
$(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \
$(top_srcdir)/m4/stpcpy.m4 $(top_srcdir)/m4/strcase.m4 \
$(top_srcdir)/m4/strchrnul.m4 $(top_srcdir)/m4/strdup.m4 \
$(top_srcdir)/m4/strerror.m4 $(top_srcdir)/m4/string_h.m4 \
$(top_srcdir)/m4/strings_h.m4 $(top_srcdir)/m4/strndup.m4 \
$(top_srcdir)/m4/strnlen.m4 $(top_srcdir)/m4/strtoimax.m4 \
$(top_srcdir)/m4/strtol.m4 $(top_srcdir)/m4/strtoll.m4 \
$(top_srcdir)/m4/strtoul.m4 $(top_srcdir)/m4/strtoull.m4 \
$(top_srcdir)/m4/strtoumax.m4 $(top_srcdir)/m4/sys_stat_h.m4 \
$(top_srcdir)/m4/sys_time_h.m4 $(top_srcdir)/m4/sysexits.m4 \
$(top_srcdir)/m4/system.m4 $(top_srcdir)/m4/tempname.m4 \
$(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \
$(top_srcdir)/m4/timespec.m4 $(top_srcdir)/m4/tm_gmtoff.m4 \
$(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \
$(top_srcdir)/m4/unlinkdir.m4 $(top_srcdir)/m4/unlocked-io.m4 \
$(top_srcdir)/m4/utimbuf.m4 $(top_srcdir)/m4/utime.m4 \
$(top_srcdir)/m4/utimens.m4 $(top_srcdir)/m4/utimes-null.m4 \
$(top_srcdir)/m4/utimes.m4 $(top_srcdir)/m4/vasnprintf.m4 \
$(top_srcdir)/m4/vsnprintf.m4 $(top_srcdir)/m4/wchar.m4 \
$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wcrtomb.m4 \
$(top_srcdir)/m4/wctype.m4 $(top_srcdir)/m4/wcwidth.m4 \
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/write.m4 \
$(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xgetcwd.m4 \
$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/m4/xstrndup.m4 \
$(top_srcdir)/m4/xstrtol.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
am_tar_OBJECTS = buffer.$(OBJEXT) checkpoint.$(OBJEXT) \
compare.$(OBJEXT) create.$(OBJEXT) delete.$(OBJEXT) \
extract.$(OBJEXT) xheader.$(OBJEXT) incremen.$(OBJEXT) \
list.$(OBJEXT) misc.$(OBJEXT) names.$(OBJEXT) sparse.$(OBJEXT) \
suffix.$(OBJEXT) system.$(OBJEXT) tar.$(OBJEXT) \
transform.$(OBJEXT) update.$(OBJEXT) utf8.$(OBJEXT)
tar_OBJECTS = $(am_tar_OBJECTS)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = ../lib/libtar.a ../gnu/libgnu.a \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
tar_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(tar_SOURCES)
DIST_SOURCES = $(tar_SOURCES)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
ALLOCA_H = @ALLOCA_H@
AMTAR = @AMTAR@
APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOM4TE = @AUTOM4TE@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BACKUP_LIBEXEC_SCRIPTS = @BACKUP_LIBEXEC_SCRIPTS@
BACKUP_SBIN_SCRIPTS = @BACKUP_SBIN_SCRIPTS@
BACKUP_SED_COND = @BACKUP_SED_COND@
BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@
BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@
BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@
BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@
BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFAULT_ARCHIVE = @DEFAULT_ARCHIVE@
DEFAULT_ARCHIVE_FORMAT = @DEFAULT_ARCHIVE_FORMAT@
DEFAULT_BLOCKING = @DEFAULT_BLOCKING@
DEFAULT_QUOTING_STYLE = @DEFAULT_QUOTING_STYLE@
DEFAULT_RMT_COMMAND = @DEFAULT_RMT_COMMAND@
DEFAULT_RMT_DIR = @DEFAULT_RMT_DIR@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIRENT_H = @DIRENT_H@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@
EMULTIHOP_VALUE = @EMULTIHOP_VALUE@
ENOLINK_HIDDEN = @ENOLINK_HIDDEN@
ENOLINK_VALUE = @ENOLINK_VALUE@
EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@
EOVERFLOW_VALUE = @EOVERFLOW_VALUE@
ERRNO_H = @ERRNO_H@
EXEEXT = @EXEEXT@
FCNTL_H = @FCNTL_H@
FLOAT_H = @FLOAT_H@
FNMATCH_H = @FNMATCH_H@
GETOPT_H = @GETOPT_H@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
GNULIB_ATOLL = @GNULIB_ATOLL@
GNULIB_BTOWC = @GNULIB_BTOWC@
GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
GNULIB_CHOWN = @GNULIB_CHOWN@
GNULIB_CLOSE = @GNULIB_CLOSE@
GNULIB_DIRFD = @GNULIB_DIRFD@
GNULIB_DPRINTF = @GNULIB_DPRINTF@
GNULIB_DUP2 = @GNULIB_DUP2@
GNULIB_ENVIRON = @GNULIB_ENVIRON@
GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
GNULIB_FCHDIR = @GNULIB_FCHDIR@
GNULIB_FCLOSE = @GNULIB_FCLOSE@
GNULIB_FFLUSH = @GNULIB_FFLUSH@
GNULIB_FOPEN = @GNULIB_FOPEN@
GNULIB_FPRINTF = @GNULIB_FPRINTF@
GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
GNULIB_FPUTC = @GNULIB_FPUTC@
GNULIB_FPUTS = @GNULIB_FPUTS@
GNULIB_FREOPEN = @GNULIB_FREOPEN@
GNULIB_FSEEK = @GNULIB_FSEEK@
GNULIB_FSEEKO = @GNULIB_FSEEKO@
GNULIB_FSYNC = @GNULIB_FSYNC@
GNULIB_FTELL = @GNULIB_FTELL@
GNULIB_FTELLO = @GNULIB_FTELLO@
GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
GNULIB_FWRITE = @GNULIB_FWRITE@
GNULIB_GETCWD = @GNULIB_GETCWD@
GNULIB_GETDELIM = @GNULIB_GETDELIM@
GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@
GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@
GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@
GNULIB_GETLINE = @GNULIB_GETLINE@
GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
GNULIB_IMAXABS = @GNULIB_IMAXABS@
GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
GNULIB_LCHMOD = @GNULIB_LCHMOD@
GNULIB_LCHOWN = @GNULIB_LCHOWN@
GNULIB_LINK = @GNULIB_LINK@
GNULIB_LSEEK = @GNULIB_LSEEK@
GNULIB_LSTAT = @GNULIB_LSTAT@
GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
GNULIB_MBRLEN = @GNULIB_MBRLEN@
GNULIB_MBRTOWC = @GNULIB_MBRTOWC@
GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
GNULIB_MBSCHR = @GNULIB_MBSCHR@
GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
GNULIB_MBSINIT = @GNULIB_MBSINIT@
GNULIB_MBSLEN = @GNULIB_MBSLEN@
GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
GNULIB_MBSNLEN = @GNULIB_MBSNLEN@
GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@
GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@
GNULIB_MBSSEP = @GNULIB_MBSSEP@
GNULIB_MBSSPN = @GNULIB_MBSSPN@
GNULIB_MBSSTR = @GNULIB_MBSSTR@
GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
GNULIB_MEMMEM = @GNULIB_MEMMEM@
GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@
GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@
GNULIB_OPEN = @GNULIB_OPEN@
GNULIB_PERROR = @GNULIB_PERROR@
GNULIB_PRINTF = @GNULIB_PRINTF@
GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
GNULIB_PUTC = @GNULIB_PUTC@
GNULIB_PUTCHAR = @GNULIB_PUTCHAR@
GNULIB_PUTENV = @GNULIB_PUTENV@
GNULIB_PUTS = @GNULIB_PUTS@
GNULIB_RANDOM_R = @GNULIB_RANDOM_R@
GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@
GNULIB_READLINK = @GNULIB_READLINK@
GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
GNULIB_RPMATCH = @GNULIB_RPMATCH@
GNULIB_SCANDIR = @GNULIB_SCANDIR@
GNULIB_SETENV = @GNULIB_SETENV@
GNULIB_SLEEP = @GNULIB_SLEEP@
GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
GNULIB_STPCPY = @GNULIB_STPCPY@
GNULIB_STPNCPY = @GNULIB_STPNCPY@
GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
GNULIB_STRDUP = @GNULIB_STRDUP@
GNULIB_STRERROR = @GNULIB_STRERROR@
GNULIB_STRNDUP = @GNULIB_STRNDUP@
GNULIB_STRNLEN = @GNULIB_STRNLEN@
GNULIB_STRPBRK = @GNULIB_STRPBRK@
GNULIB_STRSEP = @GNULIB_STRSEP@
GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@
GNULIB_STRSTR = @GNULIB_STRSTR@
GNULIB_STRTOD = @GNULIB_STRTOD@
GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@
GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
GNULIB_STRTOLL = @GNULIB_STRTOLL@
GNULIB_STRTOULL = @GNULIB_STRTOULL@
GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@
GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
GNULIB_UNSETENV = @GNULIB_UNSETENV@
GNULIB_VASPRINTF = @GNULIB_VASPRINTF@
GNULIB_VDPRINTF = @GNULIB_VDPRINTF@
GNULIB_VFPRINTF = @GNULIB_VFPRINTF@
GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@
GNULIB_VPRINTF = @GNULIB_VPRINTF@
GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@
GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@
GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@
GNULIB_WCRTOMB = @GNULIB_WCRTOMB@
GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@
GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@
GNULIB_WCTOB = @GNULIB_WCTOB@
GNULIB_WCWIDTH = @GNULIB_WCWIDTH@
GNULIB_WRITE = @GNULIB_WRITE@
GREP = @GREP@
HAVE_ALPHASORT = @HAVE_ALPHASORT@
HAVE_ATOLL = @HAVE_ATOLL@
HAVE_BTOWC = @HAVE_BTOWC@
HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@
HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@
HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@
HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@
HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@
HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@
HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
HAVE_DECL_STRERROR = @HAVE_DECL_STRERROR@
HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@
HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@
HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@
HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@
HAVE_DPRINTF = @HAVE_DPRINTF@
HAVE_DUP2 = @HAVE_DUP2@
HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
HAVE_FSEEKO = @HAVE_FSEEKO@
HAVE_FSYNC = @HAVE_FSYNC@
HAVE_FTELLO = @HAVE_FTELLO@
HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
HAVE_GETDOMAINNAME = @HAVE_GETDOMAINNAME@
HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@
HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@
HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
HAVE_GETUSERSHELL = @HAVE_GETUSERSHELL@
HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
HAVE_ISWCNTRL = @HAVE_ISWCNTRL@
HAVE_LCHMOD = @HAVE_LCHMOD@
HAVE_LINK = @HAVE_LINK@
HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
HAVE_LSTAT = @HAVE_LSTAT@
HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@
HAVE_MBRLEN = @HAVE_MBRLEN@
HAVE_MBRTOWC = @HAVE_MBRTOWC@
HAVE_MBSINIT = @HAVE_MBSINIT@
HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@
HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@
HAVE_MEMPCPY = @HAVE_MEMPCPY@
HAVE_MKDTEMP = @HAVE_MKDTEMP@
HAVE_OS_H = @HAVE_OS_H@
HAVE_RANDOM_H = @HAVE_RANDOM_H@
HAVE_RANDOM_R = @HAVE_RANDOM_R@
HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@
HAVE_READLINK = @HAVE_READLINK@
HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@
HAVE_RPMATCH = @HAVE_RPMATCH@
HAVE_SCANDIR = @HAVE_SCANDIR@
HAVE_SETENV = @HAVE_SETENV@
HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
HAVE_SLEEP = @HAVE_SLEEP@
HAVE_STDINT_H = @HAVE_STDINT_H@
HAVE_STPCPY = @HAVE_STPCPY@
HAVE_STPNCPY = @HAVE_STPNCPY@
HAVE_STRCASECMP = @HAVE_STRCASECMP@
HAVE_STRCASESTR = @HAVE_STRCASESTR@
HAVE_STRCHRNUL = @HAVE_STRCHRNUL@
HAVE_STRNDUP = @HAVE_STRNDUP@
HAVE_STRPBRK = @HAVE_STRPBRK@
HAVE_STRSEP = @HAVE_STRSEP@
HAVE_STRTOD = @HAVE_STRTOD@
HAVE_STRTOLL = @HAVE_STRTOLL@
HAVE_STRTOULL = @HAVE_STRTOULL@
HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@
HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@
HAVE_STRVERSCMP = @HAVE_STRVERSCMP@
HAVE_SYSEXITS_H = @HAVE_SYSEXITS_H@
HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@
HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
HAVE_UNISTD_H = @HAVE_UNISTD_H@
HAVE_UNSETENV = @HAVE_UNSETENV@
HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
HAVE_VASPRINTF = @HAVE_VASPRINTF@
HAVE_VDPRINTF = @HAVE_VDPRINTF@
HAVE_WCHAR_H = @HAVE_WCHAR_H@
HAVE_WCRTOMB = @HAVE_WCRTOMB@
HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@
HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@
HAVE_WCTYPE_H = @HAVE_WCTYPE_H@
HAVE_WINT_T = @HAVE_WINT_T@
HAVE__BOOL = @HAVE__BOOL@
INCLUDE_NEXT = @INCLUDE_NEXT@
INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@
INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
INTTYPES_H = @INTTYPES_H@
LDFLAGS = @LDFLAGS@
LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
LIB_CLOSE = @LIB_CLOSE@
LIB_SETSOCKOPT = @LIB_SETSOCKOPT@
LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@
LOCALE_FR = @LOCALE_FR@
LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
LOCALE_JA = @LOCALE_JA@
LOCALE_ZH_CN = @LOCALE_ZH_CN@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
NEXT_DIRENT_H = @NEXT_DIRENT_H@
NEXT_ERRNO_H = @NEXT_ERRNO_H@
NEXT_FCNTL_H = @NEXT_FCNTL_H@
NEXT_FLOAT_H = @NEXT_FLOAT_H@
NEXT_INTTYPES_H = @NEXT_INTTYPES_H@
NEXT_STDARG_H = @NEXT_STDARG_H@
NEXT_STDINT_H = @NEXT_STDINT_H@
NEXT_STDIO_H = @NEXT_STDIO_H@
NEXT_STDLIB_H = @NEXT_STDLIB_H@
NEXT_STRINGS_H = @NEXT_STRINGS_H@
NEXT_STRING_H = @NEXT_STRING_H@
NEXT_SYSEXITS_H = @NEXT_SYSEXITS_H@
NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@
NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@
NEXT_TIME_H = @NEXT_TIME_H@
NEXT_UNISTD_H = @NEXT_UNISTD_H@
NEXT_WCHAR_H = @NEXT_WCHAR_H@
NEXT_WCTYPE_H = @NEXT_WCTYPE_H@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POSUB = @POSUB@
PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
PRIPTR_PREFIX = @PRIPTR_PREFIX@
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
PU_RMT_PROG = @PU_RMT_PROG@
RANLIB = @RANLIB@
REPLACE_BTOWC = @REPLACE_BTOWC@
REPLACE_CHOWN = @REPLACE_CHOWN@
REPLACE_CLOSE = @REPLACE_CLOSE@
REPLACE_DPRINTF = @REPLACE_DPRINTF@
REPLACE_FCHDIR = @REPLACE_FCHDIR@
REPLACE_FCLOSE = @REPLACE_FCLOSE@
REPLACE_FFLUSH = @REPLACE_FFLUSH@
REPLACE_FOPEN = @REPLACE_FOPEN@
REPLACE_FPRINTF = @REPLACE_FPRINTF@
REPLACE_FREOPEN = @REPLACE_FREOPEN@
REPLACE_FSEEK = @REPLACE_FSEEK@
REPLACE_FSEEKO = @REPLACE_FSEEKO@
REPLACE_FTELL = @REPLACE_FTELL@
REPLACE_FTELLO = @REPLACE_FTELLO@
REPLACE_GETCWD = @REPLACE_GETCWD@
REPLACE_GETLINE = @REPLACE_GETLINE@
REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@
REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@
REPLACE_LCHOWN = @REPLACE_LCHOWN@
REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
REPLACE_LSEEK = @REPLACE_LSEEK@
REPLACE_LSTAT = @REPLACE_LSTAT@
REPLACE_MBRLEN = @REPLACE_MBRLEN@
REPLACE_MBRTOWC = @REPLACE_MBRTOWC@
REPLACE_MBSINIT = @REPLACE_MBSINIT@
REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@
REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@
REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@
REPLACE_MEMMEM = @REPLACE_MEMMEM@
REPLACE_MKDIR = @REPLACE_MKDIR@
REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@
REPLACE_OPEN = @REPLACE_OPEN@
REPLACE_PERROR = @REPLACE_PERROR@
REPLACE_PRINTF = @REPLACE_PRINTF@
REPLACE_PUTENV = @REPLACE_PUTENV@
REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
REPLACE_SPRINTF = @REPLACE_SPRINTF@
REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
REPLACE_STRDUP = @REPLACE_STRDUP@
REPLACE_STRERROR = @REPLACE_STRERROR@
REPLACE_STRPTIME = @REPLACE_STRPTIME@
REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@
REPLACE_STRSTR = @REPLACE_STRSTR@
REPLACE_STRTOD = @REPLACE_STRTOD@
REPLACE_TIMEGM = @REPLACE_TIMEGM@
REPLACE_VASPRINTF = @REPLACE_VASPRINTF@
REPLACE_VDPRINTF = @REPLACE_VDPRINTF@
REPLACE_VFPRINTF = @REPLACE_VFPRINTF@
REPLACE_VPRINTF = @REPLACE_VPRINTF@
REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@
REPLACE_VSPRINTF = @REPLACE_VSPRINTF@
REPLACE_WCRTOMB = @REPLACE_WCRTOMB@
REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@
REPLACE_WCTOB = @REPLACE_WCTOB@
REPLACE_WCWIDTH = @REPLACE_WCWIDTH@
REPLACE_WRITE = @REPLACE_WRITE@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
STDARG_H = @STDARG_H@
STDBOOL_H = @STDBOOL_H@
STDINT_H = @STDINT_H@
STRIP = @STRIP@
SYSEXITS_H = @SYSEXITS_H@
SYS_STAT_H = @SYS_STAT_H@
SYS_TIME_H = @SYS_TIME_H@
SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@
UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
VOID_UNSETENV = @VOID_UNSETENV@
WCHAR_H = @WCHAR_H@
WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@
WCTYPE_H = @WCTYPE_H@
WINT_T_SUFFIX = @WINT_T_SUFFIX@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
gltests_LIBOBJS = @gltests_LIBOBJS@
gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_HEADERS = arith.h common.h tar.h
tar_SOURCES = \
buffer.c\
checkpoint.c\
compare.c\
create.c\
delete.c\
extract.c\
xheader.c\
incremen.c\
list.c\
misc.c\
names.c\
sparse.c\
suffix.c\
system.c\
tar.c\
transform.c\
update.c\
utf8.c
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnits src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
rm -f "$(DESTDIR)$(bindir)/$$f"; \
done
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
installcheck-binPROGRAMS: $(bin_PROGRAMS)
bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
*" $$p "* | *" $(srcdir)/$$p "*) continue;; \
esac; \
f=`echo "$$p" | \
sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
for opt in --help --version; do \
if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \
2>c$${pid}_.err </dev/null \
&& test -n "`cat c$${pid}_.out`" \
&& test -z "`cat c$${pid}_.err`"; then :; \
else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
done; \
done; rm -f c$${pid}_.???; exit $$bad
tar$(EXEEXT): $(tar_OBJECTS) $(tar_DEPENDENCIES)
@rm -f tar$(EXEEXT)
$(LINK) $(tar_OBJECTS) $(tar_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkpoint.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compare.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/create.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sparse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suffix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xheader.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(bindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-exec-am: install-binPROGRAMS
install-html: install-html-am
install-info: install-info-am
install-man:
install-pdf: install-pdf-am
install-ps: install-ps-am
installcheck-am: installcheck-binPROGRAMS
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-binPROGRAMS \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installcheck-binPROGRAMS \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
ps ps-am tags uninstall uninstall-am uninstall-binPROGRAMS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -1,42 +0,0 @@
.\" $Id: ansi2knr.1 $
.TH ANSI2KNR 1 "9 September 1998" \" -*- nroff -*-
.SH NAME
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
.SH SYNOPSIS
\fBansi2knr\fR [\fB--filename\fR \fIfilename\fR] [\fIinput_file\fR [\fIoutput_file\fR]]
.br
.SH DESCRIPTION
\fB--filename\fR provides the file name for the #line directive in the output,
overriding \fIinput_file\fR (if present).
.sp
If no \fIinput_file\fR is supplied, input is read from stdin.
.sp
If no \fIoutput_file\fR is supplied, output goes to stdout.
.sp
There are no error messages.
.sp
\fBansi2knr\fR
recognizes function definitions by seeing a non-keyword identifier at the left
margin, followed by a left parenthesis, with a right parenthesis as the last
character on the line, and with a left brace as the first token on the
following line (ignoring possible intervening comments). It will recognize a
multi-line header provided that no intervening line ends with a left or right
brace or a semicolon. These algorithms ignore whitespace and comments, except
that the function name must be the first thing on the line.
.sp
The following constructs will confuse it:
.br
- Any other construct that starts at the left margin and follows the
above syntax (such as a macro or function call).
.br
- Some macros that tinker with the syntax of the function header.
.sp
The --varargs switch is obsolete, and is recognized only for
backwards compatibility. The present version of
\fBansi2knr\fR
will always attempt to convert a ... argument to va_alist and va_dcl.
.SH AUTHOR
L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
continues to maintain the current version; most of the code in the current
version is his work. ansi2knr also includes contributions by Francois
Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.

View File

@@ -1,720 +0,0 @@
/* Copyright (C) 1989, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved. */
/*$Id: ansi2knr.c $*/
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
/*
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone for the
consequences of using it or for whether it serves any particular purpose or
works at all, unless he says so in writing. Refer to the GNU General Public
License (the "GPL") for full details.
Everyone is granted permission to copy, modify and redistribute ansi2knr,
but only under the conditions described in the GPL. A copy of this license
is supposed to have been given to you along with ansi2knr so you can know
your rights and responsibilities. It should be in a file named COPYLEFT,
or, if there is no file named COPYLEFT, a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies.
We explicitly state here what we believe is already implied by the GPL: if
the ansi2knr program is distributed as a separate set of sources and a
separate executable file which are aggregated on a storage medium together
with another program, this in itself does not bring the other program under
the GPL, nor does the mere fact that such a program or the procedures for
constructing it invoke the ansi2knr executable bring any other part of the
program under the GPL.
*/
/*
* Usage:
ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
* --filename provides the file name for the #line directive in the output,
* overriding input_file (if present).
* If no input_file is supplied, input is read from stdin.
* If no output_file is supplied, output goes to stdout.
* There are no error messages.
*
* ansi2knr recognizes function definitions by seeing a non-keyword
* identifier at the left margin, followed by a left parenthesis, with a
* right parenthesis as the last character on the line, and with a left
* brace as the first token on the following line (ignoring possible
* intervening comments and/or preprocessor directives), except that a line
* consisting of only
* identifier1(identifier2)
* will not be considered a function definition unless identifier2 is
* the word "void", and a line consisting of
* identifier1(identifier2, <<arbitrary>>)
* will not be considered a function definition.
* ansi2knr will recognize a multi-line header provided that no intervening
* line ends with a left or right brace or a semicolon. These algorithms
* ignore whitespace, comments, and preprocessor directives, except that
* the function name must be the first thing on the line. The following
* constructs will confuse it:
* - Any other construct that starts at the left margin and
* follows the above syntax (such as a macro or function call).
* - Some macros that tinker with the syntax of function headers.
*/
/*
* The original and principal author of ansi2knr is L. Peter Deutsch
* <ghost@aladdin.com>. Other authors are noted in the change history
* that follows (in reverse chronological order):
lpd 1999-08-17 added code to allow preprocessor directives
wherever comments are allowed
lpd 1999-04-12 added minor fixes from Pavel Roskin
<pavel_roskin@geocities.com> for clean compilation with
gcc -W -Wall
lpd 1999-03-22 added hack to recognize lines consisting of
identifier1(identifier2, xxx) as *not* being procedures
lpd 1999-02-03 made indentation of preprocessor commands consistent
lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
endless loop; quoted strings within an argument list
confused the parser
lpd 1999-01-24 added a check for write errors on the output,
suggested by Jim Meyering <meyering@ascend.com>
lpd 1998-11-09 added further hack to recognize identifier(void)
as being a procedure
lpd 1998-10-23 added hack to recognize lines consisting of
identifier1(identifier2) as *not* being procedures
lpd 1997-12-08 made input_file optional; only closes input and/or
output file if not stdin or stdout respectively; prints
usage message on stderr rather than stdout; adds
--filename switch (changes suggested by
<ceder@lysator.liu.se>)
lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
compilers that don't understand void, as suggested by
Tom Lane
lpd 1996-01-15 changed to require that the first non-comment token
on the line following a function header be a left brace,
to reduce sensitivity to macros, as suggested by Tom Lane
<tgl@sss.pgh.pa.us>
lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
undefined preprocessor symbols as 0; changed all #ifdefs
for configuration symbols to #ifs
lpd 1995-04-05 changed copyright notice to make it clear that
including ansi2knr in a program does not bring the entire
program under the GPL
lpd 1994-12-18 added conditionals for systems where ctype macros
don't handle 8-bit characters properly, suggested by
Francois Pinard <pinard@iro.umontreal.ca>;
removed --varargs switch (this is now the default)
lpd 1994-10-10 removed CONFIG_BROKETS conditional
lpd 1994-07-16 added some conditionals to help GNU `configure',
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
properly erase prototype args in function parameters,
contributed by Jim Avera <jima@netcom.com>;
correct error in writeblanks (it shouldn't erase EOLs)
lpd 1989-xx-xx original version
*/
/* Most of the conditionals here are to make ansi2knr work with */
/* or without the GNU configure machinery. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#if HAVE_CONFIG_H
/*
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
This will define HAVE_CONFIG_H and so, activate the following lines.
*/
# if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
#else /* not HAVE_CONFIG_H */
/* Otherwise do it the hard way */
# ifdef BSD
# include <strings.h>
# else
# ifdef VMS
extern int strlen(), strncmp();
# else
# include <string.h>
# endif
# endif
#endif /* not HAVE_CONFIG_H */
#if STDC_HEADERS
# include <stdlib.h>
#else
/*
malloc and free should be declared in stdlib.h,
but if you've got a K&R compiler, they probably aren't.
*/
# ifdef MSDOS
# include <malloc.h>
# else
# ifdef VMS
extern char *malloc();
extern void free();
# else
extern char *malloc();
extern int free();
# endif
# endif
#endif
/* Define NULL (for *very* old compilers). */
#ifndef NULL
# define NULL (0)
#endif
/*
* The ctype macros don't always handle 8-bit characters correctly.
* Compensate for this here.
*/
#ifdef isascii
# undef HAVE_ISASCII /* just in case */
# define HAVE_ISASCII 1
#else
#endif
#if STDC_HEADERS || !HAVE_ISASCII
# define is_ascii(c) 1
#else
# define is_ascii(c) isascii(c)
#endif
#define is_space(c) (is_ascii(c) && isspace(c))
#define is_alpha(c) (is_ascii(c) && isalpha(c))
#define is_alnum(c) (is_ascii(c) && isalnum(c))
/* Scanning macros */
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
/* Forward references */
char *ppdirforward();
char *ppdirbackward();
char *skipspace();
char *scanstring();
int writeblanks();
int test1();
int convert1();
/* The main program */
int
main(argc, argv)
int argc;
char *argv[];
{ FILE *in = stdin;
FILE *out = stdout;
char *filename = 0;
char *program_name = argv[0];
char *output_name = 0;
#define bufsize 5000 /* arbitrary size */
char *buf;
char *line;
char *more;
char *usage =
"Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
/*
* In previous versions, ansi2knr recognized a --varargs switch.
* If this switch was supplied, ansi2knr would attempt to convert
* a ... argument to va_alist and va_dcl; if this switch was not
* supplied, ansi2knr would simply drop any such arguments.
* Now, ansi2knr always does this conversion, and we only
* check for this switch for backward compatibility.
*/
int convert_varargs = 1;
int output_error;
while ( argc > 1 && argv[1][0] == '-' ) {
if ( !strcmp(argv[1], "--varargs") ) {
convert_varargs = 1;
argc--;
argv++;
continue;
}
if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
filename = argv[2];
argc -= 2;
argv += 2;
continue;
}
fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
argv[1]);
fprintf(stderr, usage);
exit(1);
}
switch ( argc )
{
default:
fprintf(stderr, usage);
exit(0);
case 3:
output_name = argv[2];
out = fopen(output_name, "w");
if ( out == NULL ) {
fprintf(stderr, "%s: Cannot open output file %s\n",
program_name, output_name);
exit(1);
}
/* falls through */
case 2:
in = fopen(argv[1], "r");
if ( in == NULL ) {
fprintf(stderr, "%s: Cannot open input file %s\n",
program_name, argv[1]);
exit(1);
}
if ( filename == 0 )
filename = argv[1];
/* falls through */
case 1:
break;
}
if ( filename )
fprintf(out, "#line 1 \"%s\"\n", filename);
buf = malloc(bufsize);
if ( buf == NULL )
{
fprintf(stderr, "Unable to allocate read buffer!\n");
exit(1);
}
line = buf;
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
{
test: line += strlen(line);
switch ( test1(buf) )
{
case 2: /* a function header */
convert1(buf, out, 1, convert_varargs);
break;
case 1: /* a function */
/* Check for a { at the start of the next line. */
more = ++line;
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
goto wl;
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
goto wl;
switch ( *skipspace(ppdirforward(more), 1) )
{
case '{':
/* Definitely a function header. */
convert1(buf, out, 0, convert_varargs);
fputs(more, out);
break;
case 0:
/* The next line was blank or a comment: */
/* keep scanning for a non-comment. */
line += strlen(line);
goto f;
default:
/* buf isn't a function header, but */
/* more might be. */
fputs(buf, out);
strcpy(buf, more);
line = buf;
goto test;
}
break;
case -1: /* maybe the start of a function */
if ( line != buf + (bufsize - 1) ) /* overflow check */
continue;
/* falls through */
default: /* not a function */
wl: fputs(buf, out);
break;
}
line = buf;
}
if ( line != buf )
fputs(buf, out);
free(buf);
if ( output_name ) {
output_error = ferror(out);
output_error |= fclose(out);
} else { /* out == stdout */
fflush(out);
output_error = ferror(out);
}
if ( output_error ) {
fprintf(stderr, "%s: error writing to %s\n", program_name,
(output_name ? output_name : "stdout"));
exit(1);
}
if ( in != stdin )
fclose(in);
return 0;
}
/*
* Skip forward or backward over one or more preprocessor directives.
*/
char *
ppdirforward(p)
char *p;
{
for (; *p == '#'; ++p) {
for (; *p != '\r' && *p != '\n'; ++p)
if (*p == 0)
return p;
if (*p == '\r' && p[1] == '\n')
++p;
}
return p;
}
char *
ppdirbackward(p, limit)
char *p;
char *limit;
{
char *np = p;
for (;; p = --np) {
if (*np == '\n' && np[-1] == '\r')
--np;
for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
if (np[-1] == 0)
return np;
if (*np != '#')
return p;
}
}
/*
* Skip over whitespace, comments, and preprocessor directives,
* in either direction.
*/
char *
skipspace(p, dir)
char *p;
int dir; /* 1 for forward, -1 for backward */
{
for ( ; ; ) {
while ( is_space(*p) )
p += dir;
if ( !(*p == '/' && p[dir] == '*') )
break;
p += dir; p += dir;
while ( !(*p == '*' && p[dir] == '/') ) {
if ( *p == 0 )
return p; /* multi-line comment?? */
p += dir;
}
p += dir; p += dir;
}
return p;
}
/* Scan over a quoted string, in either direction. */
char *
scanstring(p, dir)
char *p;
int dir;
{
for (p += dir; ; p += dir)
if (*p == '"' && p[-dir] != '\\')
return p + dir;
}
/*
* Write blanks over part of a string.
* Don't overwrite end-of-line characters.
*/
int
writeblanks(start, end)
char *start;
char *end;
{ char *p;
for ( p = start; p < end; p++ )
if ( *p != '\r' && *p != '\n' )
*p = ' ';
return 0;
}
/*
* Test whether the string in buf is a function definition.
* The string may contain and/or end with a newline.
* Return as follows:
* 0 - definitely not a function definition;
* 1 - definitely a function definition;
* 2 - definitely a function prototype (NOT USED);
* -1 - may be the beginning of a function definition,
* append another line and look again.
* The reason we don't attempt to convert function prototypes is that
* Ghostscript's declaration-generating macros look too much like
* prototypes, and confuse the algorithms.
*/
int
test1(buf)
char *buf;
{ char *p = buf;
char *bend;
char *endfn;
int contin;
if ( !isidfirstchar(*p) )
return 0; /* no name at left margin */
bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
switch ( *bend )
{
case ';': contin = 0 /*2*/; break;
case ')': contin = 1; break;
case '{': return 0; /* not a function */
case '}': return 0; /* not a function */
default: contin = -1;
}
while ( isidchar(*p) )
p++;
endfn = p;
p = skipspace(p, 1);
if ( *p++ != '(' )
return 0; /* not a function */
p = skipspace(p, 1);
if ( *p == ')' )
return 0; /* no parameters */
/* Check that the apparent function name isn't a keyword. */
/* We only need to check for keywords that could be followed */
/* by a left parenthesis (which, unfortunately, is most of them). */
{ static char *words[] =
{ "asm", "auto", "case", "char", "const", "double",
"extern", "float", "for", "if", "int", "long",
"register", "return", "short", "signed", "sizeof",
"static", "switch", "typedef", "unsigned",
"void", "volatile", "while", 0
};
char **key = words;
char *kp;
unsigned len = endfn - buf;
while ( (kp = *key) != 0 )
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
return 0; /* name is a keyword */
key++;
}
}
{
char *id = p;
int len;
/*
* Check for identifier1(identifier2) and not
* identifier1(void), or identifier1(identifier2, xxxx).
*/
while ( isidchar(*p) )
p++;
len = p - id;
p = skipspace(p, 1);
if (*p == ',' ||
(*p == ')' && (len != 4 || strncmp(id, "void", 4)))
)
return 0; /* not a function */
}
/*
* If the last significant character was a ), we need to count
* parentheses, because it might be part of a formal parameter
* that is a procedure.
*/
if (contin > 0) {
int level = 0;
for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
if (level > 0)
contin = -1;
}
return contin;
}
/* Convert a recognized function definition or header to K&R syntax. */
int
convert1(buf, out, header, convert_varargs)
char *buf;
FILE *out;
int header; /* Boolean */
int convert_varargs; /* Boolean */
{ char *endfn;
char *p;
/*
* The breaks table contains pointers to the beginning and end
* of each argument.
*/
char **breaks;
unsigned num_breaks = 2; /* for testing */
char **btop;
char **bp;
char **ap;
char *vararg = 0;
/* Pre-ANSI implementations don't agree on whether strchr */
/* is called strchr or index, so we open-code it here. */
for ( endfn = buf; *(endfn++) != '('; )
;
top: p = endfn;
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
if ( breaks == NULL )
{ /* Couldn't allocate break table, give up */
fprintf(stderr, "Unable to allocate break table!\n");
fputs(buf, out);
return -1;
}
btop = breaks + num_breaks * 2 - 2;
bp = breaks;
/* Parse the argument list */
do
{ int level = 0;
char *lp = NULL;
char *rp = NULL;
char *end = NULL;
if ( bp >= btop )
{ /* Filled up break table. */
/* Allocate a bigger one and start over. */
free((char *)breaks);
num_breaks <<= 1;
goto top;
}
*bp++ = p;
/* Find the end of the argument */
for ( ; end == NULL; p++ )
{ switch(*p)
{
case ',':
if ( !level ) end = p;
break;
case '(':
if ( !level ) lp = p;
level++;
break;
case ')':
if ( --level < 0 ) end = p;
else rp = p;
break;
case '/':
if (p[1] == '*')
p = skipspace(p, 1) - 1;
break;
case '"':
p = scanstring(p, 1) - 1;
break;
default:
;
}
}
/* Erase any embedded prototype parameters. */
if ( lp && rp )
writeblanks(lp + 1, rp);
p--; /* back up over terminator */
/* Find the name being declared. */
/* This is complicated because of procedure and */
/* array modifiers. */
for ( ; ; )
{ p = skipspace(p - 1, -1);
switch ( *p )
{
case ']': /* skip array dimension(s) */
case ')': /* skip procedure args OR name */
{ int level = 1;
while ( level )
switch ( *--p )
{
case ']': case ')':
level++;
break;
case '[': case '(':
level--;
break;
case '/':
if (p > buf && p[-1] == '*')
p = skipspace(p, -1) + 1;
break;
case '"':
p = scanstring(p, -1) + 1;
break;
default: ;
}
}
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
{ /* We found the name being declared */
while ( !isidfirstchar(*p) )
p = skipspace(p, 1) + 1;
goto found;
}
break;
default:
goto found;
}
}
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
{ if ( convert_varargs )
{ *bp++ = "va_alist";
vararg = p-2;
}
else
{ p++;
if ( bp == breaks + 1 ) /* sole argument */
writeblanks(breaks[0], p);
else
writeblanks(bp[-1] - 1, p);
bp--;
}
}
else
{ while ( isidchar(*p) ) p--;
*bp++ = p+1;
}
p = end;
}
while ( *p++ == ',' );
*bp = p;
/* Make a special check for 'void' arglist */
if ( bp == breaks+2 )
{ p = skipspace(breaks[0], 1);
if ( !strncmp(p, "void", 4) )
{ p = skipspace(p+4, 1);
if ( p == breaks[2] - 1 )
{ bp = breaks; /* yup, pretend arglist is empty */
writeblanks(breaks[0], p + 1);
}
}
}
/* Put out the function name and left parenthesis. */
p = buf;
while ( p != endfn ) putc(*p, out), p++;
/* Put out the declaration. */
if ( header )
{ fputs(");", out);
for ( p = breaks[0]; *p; p++ )
if ( *p == '\r' || *p == '\n' )
putc(*p, out);
}
else
{ for ( ap = breaks+1; ap < bp; ap += 2 )
{ p = *ap;
while ( isidchar(*p) )
putc(*p, out), p++;
if ( ap < bp - 1 )
fputs(", ", out);
}
fputs(") ", out);
/* Put out the argument declarations */
for ( ap = breaks+2; ap <= bp; ap += 2 )
(*ap)[-1] = ';';
if ( vararg != 0 )
{ *vararg = 0;
fputs(breaks[0], out); /* any prior args */
fputs("va_dcl", out); /* the final arg */
fputs(bp[0], out);
}
else
fputs(breaks[0], out);
}
free((char *)breaks);
return 0;
}

View File

@@ -1,163 +0,0 @@
/* Arithmetic for numbers greater than a long int, for GNU tar.
Copyright (C) 1996, 1997 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 Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
/* common.h is needed to define FATAL_ERROR. It also includes arith.h. */
#include "common.h"
/* GNU tar needs handling numbers exceeding 32 bits, which is the size of
unsigned long ints for many C compilers. This module should provide
machinery for handling at least BITS_PER_TARLONG bits per number. If
`long long' ints are available and are sufficient for the task, they will
be used preferrably.
Russell Cattelan reports 165 Gb single tapes (digital video D2 tapes on
Ampex drives), so requiring 38 bits for the tape length in bytes. He
also reports breaking the terabyte limit with a single file (using SGI
xFS file system over 37 28GB disk arrays attached to a Power Challenge
XL; check out http://www.lcse.umn.edu/ for a picture), so requiring a
little more than 40 bits for the file size in bytes. The POSIX header
structure allows for 12 octal digits to represent file lengths, that is,
up to 36 bits for the byte size of files.
If `long long' is not supported by the compiler, SIZEOF_LONG_LONG will be
set to zero by configure. In this case, or if `long long' ints does not
have enough bits, then huge numbers are rather represented by an array of
longs, with the least significant super-digit at position 0. For making
multiplication and decimal input/output easy, the base of a super-digit
is an exact exponent of 10, and is such that base*base fits in a long. */
#if SUPERDIGIT
/*-------------------------------.
| Check if ACCUMULATOR is zero. |
`-------------------------------*/
int
zerop_tarlong_helper (unsigned long *accumulator)
{
int counter;
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
if (accumulator[counter])
return 0;
return 1;
}
/*----------------------------------------------.
| Check if FIRST is strictly less than SECOND. |
`----------------------------------------------*/
int
lessp_tarlong_helper (unsigned long *first, unsigned long *second)
{
int counter;
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
if (first[counter] != second[counter])
return first[counter] < second[counter];
return 0;
}
/*----------------------------.
| Reset ACCUMULATOR to zero. |
`----------------------------*/
void
clear_tarlong_helper (unsigned long *accumulator)
{
int counter;
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
accumulator[counter] = 0;
}
/*----------------------------.
| To ACCUMULATOR, add VALUE. |
`----------------------------*/
void
add_to_tarlong_helper (unsigned long *accumulator, int value)
{
int counter;
if (value < 0)
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
if (accumulator[counter] >= -value)
{
accumulator[counter] += value;
return;
}
accumulator[counter] += value + SUPERDIGIT;
value = -1;
}
else
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
if (accumulator[counter] + value < SUPERDIGIT)
{
accumulator[counter] += value;
return;
}
accumulator[counter] += value - SUPERDIGIT;
value = 1;
}
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
}
/*--------------------------------.
| Multiply ACCUMULATOR by VALUE. |
`--------------------------------*/
void
mult_tarlong_helper (unsigned long *accumulator, int value)
{
int carry = 0;
int counter;
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
{
carry += accumulator[counter] * value;
accumulator[counter] = carry % SUPERDIGIT;
carry /= SUPERDIGIT;
}
if (carry)
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
}
/*----------------------------------------------------------.
| Print the decimal representation of ACCUMULATOR on FILE. |
`----------------------------------------------------------*/
void
print_tarlong_helper (unsigned long *accumulator, FILE *file)
{
int counter = LONGS_PER_TARLONG - 1;
while (counter > 0 && accumulator[counter] == 0)
counter--;
fprintf (file, "%uld", accumulator[counter]);
while (counter > 0)
fprintf (file, TARLONG_FORMAT, accumulator[--counter]);
}
#endif /* SUPERDIGIT */

View File

@@ -22,6 +22,6 @@
blocked in 1 kB boundaries. We'll need arbitrary precision
arithmetic anyway once we get into the 2**64 range, so there's no
point doing anything fancy before then. */
#define TARLONG_FORMAT "%.0f"
typedef double tarlong;

File diff suppressed because it is too large Load Diff

View File

@@ -77,7 +77,7 @@ void
checkpoint_compile_action (const char *str)
{
struct checkpoint_action *act;
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
alloc_action (cop_dot);
else if (strcmp (str, "bell") == 0)
@@ -119,14 +119,14 @@ checkpoint_finish_compile ()
{
if (!checkpoint_action)
/* Provide a historical default */
checkpoint_compile_action ("echo");
checkpoint_compile_action ("echo");
}
else if (checkpoint_action)
/* Otherwise, set default checkpoint rate */
checkpoint_option = DEFAULT_CHECKPOINT;
}
char *
static char *
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
{
const char *opstr = do_write ? gettext ("write") : gettext ("read");
@@ -147,7 +147,7 @@ expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
case 'u':
outlen += cpslen - 2;
break;
case 's':
outlen += opstrlen - 2;
}
@@ -164,11 +164,11 @@ expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
case 'u':
op = stpcpy (op, cps);
break;
case 's':
op = stpcpy (op, opstr);
break;
default:
*op++ = '%';
*op++ = *ip;
@@ -188,7 +188,7 @@ run_checkpoint_actions (bool do_write)
{
struct checkpoint_action *p;
FILE *tty = NULL;
for (p = checkpoint_action; p; p = p->next)
{
switch (p->opcode)
@@ -207,7 +207,7 @@ run_checkpoint_actions (bool do_write)
fflush (tty);
}
break;
case cop_echo:
{
char *tmp;
@@ -232,7 +232,7 @@ run_checkpoint_actions (bool do_write)
free (tmp);
}
break;
case cop_ttyout:
if (!tty)
tty = fopen ("/dev/tty", "w");
@@ -245,11 +245,11 @@ run_checkpoint_actions (bool do_write)
free (tmp);
}
break;
case cop_sleep:
sleep (p->v.time);
break;
case cop_exec:
sys_exec_checkpoint_script (p->v.command,
archive_name_cursor[0],
@@ -266,5 +266,4 @@ checkpoint_run (bool do_write)
{
if (checkpoint_option && !(++checkpoint % checkpoint_option))
run_checkpoint_actions (do_write);
}
}

View File

@@ -1,7 +1,8 @@
/* Common declarations for the tar program.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
@@ -60,6 +61,8 @@
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
#include <obstack.h>
#include <progname.h>
#include <xvasprintf.h>
#include <paxlib.h>
@@ -70,9 +73,6 @@
/* Information gleaned from the command line. */
/* Name of this program. */
GLOBAL const char *program_name;
/* Main command option. */
enum subcommand
@@ -85,7 +85,8 @@ enum subcommand
DIFF_SUBCOMMAND, /* -d */
EXTRACT_SUBCOMMAND, /* -x */
LIST_SUBCOMMAND, /* -t */
UPDATE_SUBCOMMAND /* -u */
UPDATE_SUBCOMMAND, /* -u */
TEST_LABEL_SUBCOMMAND, /* --test-label */
};
GLOBAL enum subcommand subcommand_option;
@@ -104,6 +105,8 @@ GLOBAL bool absolute_names_option;
/* Display file times in UTC */
GLOBAL bool utc_option;
/* Output file timestamps to the full resolution */
GLOBAL bool full_time_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.
@@ -185,6 +188,8 @@ GLOBAL enum old_files old_files_option;
/* Specified file name for incremental list. */
GLOBAL const char *listed_incremental_option;
/* Incremental dump level */
GLOBAL int incremental_level;
/* Check device numbers when doing incremental dumps. */
GLOBAL bool check_device_option;
@@ -318,25 +323,46 @@ GLOBAL const char **archive_name_cursor;
/* Output index file name. */
GLOBAL char const *index_file_name;
/* Opaque structure for keeping directory meta-data */
struct directory;
/* Structure for keeping track of filenames and lists thereof. */
struct name
{
struct name *next; /* Link to the next element */
struct name *prev; /* Link to the previous element */
char *name; /* File name or globbing pattern */
size_t length; /* cached strlen (name) */
int matching_flags; /* wildcard flags if name is a pattern */
bool cmdline; /* true if this name was given in the
command line */
int change_dir; /* Number of the directory to change to.
Set with the -C option. */
uintmax_t found_count; /* number of times a matching file has
been found */
int matching_flags; /* this name is a regexp, not literal */
char const *dir_contents; /* for incremental_option */
size_t length; /* cached strlen(name) */
char name[1];
/* The following members are used for incremental dumps only,
if this struct name represents a directory;
see incremen.c */
struct directory *directory;/* directory meta-data and contents */
struct name *parent; /* pointer to the parent hierarchy */
struct name *child; /* pointer to the first child */
struct name *sibling; /* pointer to the next sibling */
char *caname; /* canonical name */
};
/* Obnoxious test to see if dimwit is trying to dump the archive. */
GLOBAL dev_t ar_dev;
GLOBAL ino_t ar_ino;
/* Flags for reading, searching, and fstatatting files. */
GLOBAL int open_read_flags;
GLOBAL int open_searchdir_flags;
GLOBAL int fstatat_flags;
GLOBAL int seek_option;
GLOBAL bool seekable_archive;
GLOBAL dev_t root_device;
@@ -344,8 +370,6 @@ GLOBAL dev_t root_device;
/* Unquote filenames */
GLOBAL bool unquote_option;
GLOBAL bool test_label_option; /* Test archive volume label and exit */
/* Show file or archive names after transformation.
In particular, when creating archive in verbose mode, list member names
as stored in the archive */
@@ -379,9 +403,13 @@ extern enum access_mode access_mode;
extern FILE *stdlis;
extern bool write_archive_to_stdout;
extern char *volume_label;
extern size_t volume_label_count;
extern char *continued_file_name;
extern uintmax_t continued_file_size;
extern uintmax_t continued_file_offset;
extern off_t records_written;
char *drop_volume_label_suffix (const char *label);
size_t available_space_after (union block *pointer);
off_t current_block_ordinal (void);
@@ -404,13 +432,17 @@ void archive_read_error (void);
off_t seek_archive (off_t size);
void set_start_time (void);
void mv_begin (struct tar_stat_info *st);
void mv_begin_write (const char *file_name, off_t totsize, off_t sizeleft);
void mv_begin_read (struct tar_stat_info *st);
void mv_end (void);
void mv_total_size (off_t size);
void mv_size_left (off_t size);
void buffer_write_global_xheader (void);
const char *first_decompress_program (int *pstate);
const char *next_decompress_program (int *pstate);
/* Module create.c. */
enum dump_status
@@ -422,49 +454,35 @@ enum dump_status
};
void add_exclusion_tag (const char *name, enum exclusion_tag_type type,
bool (*)(const char*));
bool cachedir_file_p (const char *name);
bool (*predicate) (int));
bool cachedir_file_p (int fd);
char *get_directory_entries (struct tar_stat_info *st);
bool file_dumpable_p (struct tar_stat_info *st);
void create_archive (void);
void pad_archive (off_t size_left);
void dump_file (const char *st, int top_level, dev_t parent_device);
void dump_file (struct tar_stat_info *parent, char const *name,
char const *fullname);
union block *start_header (struct tar_stat_info *st);
void finish_header (struct tar_stat_info *st, union block *header,
off_t block_ordinal);
void simple_finish_header (union block *header);
union block * write_extended (bool global, struct tar_stat_info *st,
union block *old_header);
union block *start_private_header (const char *name, size_t size);
union block *start_private_header (const char *name, size_t size, time_t t);
void write_eot (void);
void check_links (void);
int subfile_open (struct tar_stat_info const *dir, char const *file, int flags);
void restore_parent_fd (struct tar_stat_info const *st);
void exclusion_tag_warning (const char *dirname, const char *tagname,
const char *message);
enum exclusion_tag_type check_exclusion_tags (char *dirname,
enum exclusion_tag_type check_exclusion_tags (struct tar_stat_info const *st,
const char **tag_file_name);
#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
#define MAJOR_TO_CHARS(val, where) major_to_chars (val, where, sizeof (where))
#define MINOR_TO_CHARS(val, where) minor_to_chars (val, where, sizeof (where))
#define MODE_TO_CHARS(val, where) mode_to_chars (val, where, sizeof (where))
#define OFF_TO_CHARS(val, where) off_to_chars (val, where, sizeof (where))
#define SIZE_TO_CHARS(val, where) size_to_chars (val, where, sizeof (where))
#define TIME_TO_CHARS(val, where) time_to_chars (val, where, sizeof (where))
#define UID_TO_CHARS(val, where) uid_to_chars (val, where, sizeof (where))
#define UINTMAX_TO_CHARS(val, where) uintmax_to_chars (val, where, sizeof (where))
#define UNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
#define GNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
bool gid_to_chars (gid_t gid, char *buf, size_t size);
bool major_to_chars (major_t m, char *buf, size_t size);
bool minor_to_chars (minor_t m, char *buf, size_t size);
bool mode_to_chars (mode_t m, char *buf, size_t size);
#define OFF_TO_CHARS(val, where) off_to_chars (val, where, sizeof (where))
#define TIME_TO_CHARS(val, where) time_to_chars (val, where, sizeof (where))
bool off_to_chars (off_t off, char *buf, size_t size);
bool size_to_chars (size_t v, char *buf, size_t size);
bool time_to_chars (time_t t, char *buf, size_t size);
bool uid_to_chars (uid_t uid, char *buf, size_t size);
bool uintmax_to_chars (uintmax_t v, char *buf, size_t size);
void string_to_chars (char const *s, char *buf, size_t size);
/* Module diffarch.c. */
@@ -486,24 +504,21 @@ bool rename_directory (char *src, char *dst);
void delete_archive_members (void);
/* Module incremen.c. */
typedef struct dumpdir *dumpdir_t;
typedef struct dumpdir_iter *dumpdir_iter_t;
dumpdir_t dumpdir_create0 (const char *contents, const char *cmask);
dumpdir_t dumpdir_create (const char *contents);
void dumpdir_free (dumpdir_t);
char *dumpdir_locate (dumpdir_t dump, const char *name);
char *dumpdir_next (dumpdir_iter_t itr);
char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
struct directory *scan_directory (struct tar_stat_info *st);
const char *directory_contents (struct directory *dir);
const char *safe_directory_contents (struct directory *dir);
void rebase_directory (struct directory *dir,
const char *samp, size_t slen,
const char *repl, size_t rlen);
const char *get_directory_contents (char *dir_name, dev_t device);
const char *append_incremental_renames (const char *dump);
void append_incremental_renames (struct directory *dir);
void read_directory_file (void);
void write_directory_file (void);
void purge_directory (char const *directory_name);
void list_dumpdir (char *buffer, size_t size);
void update_parent_directory (const char *name);
void update_parent_directory (struct tar_stat_info *st);
size_t dumpdir_size (const char *p);
bool is_dumpdir (struct tar_stat_info *stat_info);
@@ -520,6 +535,17 @@ enum read_header
HEADER_FAILURE /* ill-formed header, or bad checksum */
};
/* Operation mode for read_header: */
enum read_header_mode
{
read_header_auto, /* process extended headers automatically */
read_header_x_raw, /* return raw extended headers (return
HEADER_SUCCESS_EXTENDED) */
read_header_x_global /* when POSIX global extended header is read,
decode it and return
HEADER_SUCCESS_EXTENDED */
};
extern union block *current_header;
extern enum archive_format current_format;
extern size_t recent_long_name_blocks;
@@ -527,35 +553,24 @@ extern size_t recent_long_link_blocks;
void decode_header (union block *header, struct tar_stat_info *stat_info,
enum archive_format *format_pointer, int do_user_group);
void transform_stat_info (int typeflag, struct tar_stat_info *stat_info);
char const *tartime (struct timespec t, bool full_time);
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
#define MODE_FROM_HEADER(where) mode_from_header (where, sizeof (where))
#define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
#define SIZE_FROM_HEADER(where) size_from_header (where, sizeof (where))
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
#define UINTMAX_FROM_HEADER(where) uintmax_from_header (where, sizeof (where))
gid_t gid_from_header (const char *buf, size_t size);
major_t major_from_header (const char *buf, size_t size);
minor_t minor_from_header (const char *buf, size_t size);
mode_t mode_from_header (const char *buf, size_t size);
off_t off_from_header (const char *buf, size_t size);
size_t size_from_header (const char *buf, size_t size);
time_t time_from_header (const char *buf, size_t size);
uid_t uid_from_header (const char *buf, size_t size);
uintmax_t uintmax_from_header (const char * buf, size_t size);
uintmax_t uintmax_from_header (const char *buf, size_t size);
void list_archive (void);
void test_archive_label (void);
void print_for_mkdir (char *dirname, int length, mode_t mode);
void print_header (struct tar_stat_info *st, off_t block_ordinal);
void print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal);
void read_and (void (*do_something) (void));
enum read_header read_header_primitive (bool raw_extended_headers,
struct tar_stat_info *info);
enum read_header read_header (bool raw_extended_headers);
enum read_header read_header (union block **return_block,
struct tar_stat_info *info,
enum read_header_mode m);
enum read_header tar_checksum (union block *header, bool silent);
void skip_file (off_t size);
void skip_member (void);
@@ -563,8 +578,16 @@ void skip_member (void);
/* Module misc.c. */
void assign_string (char **dest, const char *src);
char *quote_copy_string (const char *str);
int unquote_string (char *str);
char *zap_slashes (char *name);
char *normalize_filename (const char *name);
void replace_prefix (char **pname, const char *samp, size_t slen,
const char *repl, size_t rlen);
typedef struct namebuf *namebuf_t;
namebuf_t namebuf_create (const char *dir);
void namebuf_free (namebuf_t buf);
char *namebuf_name (namebuf_t buf, const char *name);
void code_ns_fraction (int ns, char *p);
char const *code_timespec (struct timespec ts, char *sbuf);
@@ -572,6 +595,8 @@ enum { BILLION = 1000000000, LOG10_BILLION = 9 };
enum { TIMESPEC_STRSIZE_BOUND =
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
bool must_be_dot_or_slash (char const *);
enum remove_option
{
ORDINARY_REMOVE_OPTION,
@@ -590,10 +615,13 @@ int remove_any_file (const char *file_name, enum remove_option option);
bool maybe_backup_file (const char *file_name, bool this_is_the_archive);
void undo_last_backup (void);
int deref_stat (bool deref, char const *name, struct stat *buf);
int deref_stat (char const *name, struct stat *buf);
extern int chdir_current;
extern int chdir_fd;
int chdir_arg (char const *dir);
void chdir_do (int dir);
int chdir_count (void);
void close_diag (char const *name);
void open_diag (char const *name);
@@ -602,6 +630,10 @@ void readlink_diag (char const *name);
void savedir_diag (char const *name);
void seek_diag_details (char const *name, off_t offset);
void stat_diag (char const *name);
void file_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name));
void dir_removed_diag (char const *name, bool top_level,
void (*diagfn) (char const *name));
void write_error_details (char const *name, size_t status, size_t size);
void write_fatal (char const *name) __attribute__ ((noreturn));
void write_fatal_details (char const *name, ssize_t status, size_t size)
@@ -611,11 +643,12 @@ pid_t xfork (void);
void xpipe (int fd[2]);
void *page_aligned_alloc (void **ptr, size_t size);
int set_file_atime (int fd, char const *file,
struct timespec const timespec[2]);
int set_file_atime (int fd, int parentfd, char const *file,
struct timespec atime);
/* Module names.c. */
extern size_t name_count;
extern struct name *gnu_list_name;
void gid_to_gname (gid_t gid, char **gname);
@@ -629,12 +662,15 @@ void name_add_dir (const char *name);
void name_term (void);
const char *name_next (int change_dirs);
void name_gather (void);
struct name *addname (char const *string, int change_dir);
struct name *addname (char const *string, int change_dir,
bool cmdline, struct name *parent);
void remname (struct name *name);
bool name_match (const char *name);
void names_notfound (void);
void label_notfound (void);
void collect_and_sort_names (void);
struct name *name_scan (const char *name);
char *name_from_list (void);
struct name const *name_from_list (void);
void blank_name_list (void);
char *new_name (const char *dir_name, const char *name);
size_t stripped_prefix_len (char const *file_name, size_t num);
@@ -658,14 +694,15 @@ bool contains_dot_dot (char const *name);
void usage (int);
int confirm (const char *message_action, const char *name);
void request_stdin (const char *option);
void tar_stat_init (struct tar_stat_info *st);
bool tar_stat_close (struct tar_stat_info *st);
void tar_stat_destroy (struct tar_stat_info *st);
void usage (int) __attribute__ ((noreturn));
int tar_timespec_cmp (struct timespec a, struct timespec b);
const char *archive_format_string (enum archive_format fmt);
const char *subcommand_string (enum subcommand c);
void set_exit_status (int val);
/* Module update.c. */
@@ -675,13 +712,12 @@ void update_archive (void);
/* Module xheader.c. */
void xheader_init (struct xheader *xhdr);
void xheader_decode (struct tar_stat_info *stat);
void xheader_decode_global (struct xheader *xhdr);
void xheader_store (char const *keyword, struct tar_stat_info *st,
void const *data);
void xheader_read (struct xheader *xhdr, union block *header, size_t size);
void xheader_write (char type, char *name, struct xheader *xhdr);
void xheader_write (char type, char *name, time_t t, struct xheader *xhdr);
void xheader_write_global (struct xheader *xhdr);
void xheader_finish (struct xheader *hdr);
void xheader_destroy (struct xheader *hdr);
@@ -741,14 +777,60 @@ bool utf8_convert (bool to_utf, char const *input, char **output);
void set_transform_expr (const char *expr);
bool transform_name (char **pinput, int type);
bool transform_member_name (char **pinput, int type);
bool transform_name_fp (char **pinput, int type,
char *(*fun)(char *, void *), void *);
/* Module suffix.c */
void set_comression_program_by_suffix (const char *name, const char *defprog);
void set_compression_program_by_suffix (const char *name, const char *defprog);
/* Module checkpoint.c */
void checkpoint_compile_action (const char *str);
void checkpoint_finish_compile (void);
void checkpoint_run (bool do_write);
/* Module warning.c */
#define WARN_ALONE_ZERO_BLOCK 0x00000001
#define WARN_BAD_DUMPDIR 0x00000002
#define WARN_CACHEDIR 0x00000004
#define WARN_CONTIGUOUS_CAST 0x00000008
#define WARN_FILE_CHANGED 0x00000010
#define WARN_FILE_IGNORED 0x00000020
#define WARN_FILE_REMOVED 0x00000040
#define WARN_FILE_SHRANK 0x00000080
#define WARN_FILE_UNCHANGED 0x00000100
#define WARN_FILENAME_WITH_NULS 0x00000200
#define WARN_IGNORE_ARCHIVE 0x00000400
#define WARN_IGNORE_NEWER 0x00000800
#define WARN_NEW_DIRECTORY 0x00001000
#define WARN_RENAME_DIRECTORY 0x00002000
#define WARN_SYMLINK_CAST 0x00004000
#define WARN_TIMESTAMP 0x00008000
#define WARN_UNKNOWN_CAST 0x00010000
#define WARN_UNKNOWN_KEYWORD 0x00020000
#define WARN_XDEV 0x00040000
#define WARN_DECOMPRESS_PROGRAM 0x00080000
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
in verbose mode */
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
WARN_DECOMPRESS_PROGRAM)
#define WARN_ALL (~WARN_VERBOSE_WARNINGS)
void set_warning_option (const char *arg);
extern int warning_option;
#define WARNOPT(opt,args) \
do \
{ \
if (warning_option & opt) WARN (args); \
} \
while (0)
/* Module unlink.c */
void queue_deferred_unlink (const char *name, bool is_dir);
void finish_deferred_unlinks (void);
/* Module exit.c */
extern void (*fatal_exit_hook) (void);

View File

@@ -1,7 +1,7 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
Written by John Gilmore, on 1987-04-30.
@@ -66,8 +66,7 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
fprintf (stdlis, "\n");
}
if (exit_status == TAREXIT_SUCCESS)
exit_status = TAREXIT_DIFFERS;
set_exit_status (TAREXIT_DIFFERS);
}
/* Take a buffer returned by read_and_process and do nothing with it. */
@@ -123,7 +122,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
size_t data_size;
off_t size = st->stat.st_size;
mv_begin (st);
mv_begin_read (st);
while (size)
{
data_block = find_next_block ();
@@ -152,7 +151,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
static int
get_stat_data (char const *file_name, struct stat *stat_data)
{
int status = deref_stat (dereference_option, file_name, stat_data);
int status = deref_stat (file_name, stat_data);
if (status != 0)
{
@@ -218,12 +217,7 @@ diff_file (void)
}
else
{
int atime_flag =
(atime_preserve_option == system_atime_preserve
? O_NOATIME
: 0);
diff_handle = open (file_name, O_RDONLY | O_BINARY | atime_flag);
diff_handle = openat (chdir_fd, file_name, open_read_flags);
if (diff_handle < 0)
{
@@ -242,10 +236,9 @@ diff_file (void)
if (atime_preserve_option == replace_atime_preserve)
{
struct timespec ts[2];
ts[0] = get_stat_atime (&stat_data);
ts[1] = get_stat_mtime (&stat_data);
if (set_file_atime (diff_handle, file_name, ts) != 0)
struct timespec atime = get_stat_atime (&stat_data);
if (set_file_atime (diff_handle, chdir_fd, file_name, atime)
!= 0)
utime_error (file_name);
}
@@ -278,7 +271,8 @@ diff_symlink (void)
size_t len = strlen (current_stat_info.link_name);
char *linkbuf = alloca (len + 1);
int status = readlink (current_stat_info.file_name, linkbuf, len + 1);
int status = readlinkat (chdir_fd, current_stat_info.file_name,
linkbuf, len + 1);
if (status < 0)
{
@@ -332,7 +326,7 @@ static int
dumpdir_cmp (const char *a, const char *b)
{
size_t len;
while (*a)
switch (*a)
{
@@ -346,7 +340,7 @@ dumpdir_cmp (const char *a, const char *b)
a += len;
b += len;
break;
case 'D':
if (strcmp(a, b))
return 1;
@@ -354,7 +348,7 @@ dumpdir_cmp (const char *a, const char *b)
a += len;
b += len;
break;
case 'R':
case 'T':
case 'X':
@@ -370,7 +364,7 @@ diff_dumpdir (void)
dev_t dev = 0;
struct stat stat_data;
if (deref_stat (true, current_stat_info.file_name, &stat_data))
if (deref_stat (current_stat_info.file_name, &stat_data) != 0)
{
if (errno == ENOENT)
stat_warn (current_stat_info.file_name);
@@ -380,7 +374,7 @@ diff_dumpdir (void)
else
dev = stat_data.st_dev;
dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev);
dumpdir_buffer = directory_contents (scan_directory (&current_stat_info));
if (dumpdir_buffer)
{
@@ -422,7 +416,8 @@ diff_multivol (void)
return;
}
fd = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
fd = openat (chdir_fd, current_stat_info.file_name, open_read_flags);
if (fd < 0)
{
@@ -452,7 +447,6 @@ diff_archive (void)
{
set_next_block_after (current_header);
decode_header (current_header, &current_stat_info, &current_format, 1);
/* Print the block from current_header and current_stat_info. */
@@ -460,7 +454,7 @@ diff_archive (void)
{
if (now_verifying)
fprintf (stdlis, _("Verify "));
print_header (&current_stat_info, -1);
print_header (&current_stat_info, current_header, -1);
}
switch (current_header->header.typeflag)
@@ -578,7 +572,9 @@ verify_volume (void)
flush_read ();
while (1)
{
enum read_header status = read_header (false);
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_auto);
if (status == HEADER_FAILURE)
{
@@ -588,7 +584,8 @@ verify_volume (void)
{
counter++;
set_next_block_after (current_header);
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
}
while (status == HEADER_FAILURE);
@@ -606,14 +603,16 @@ verify_volume (void)
{
char buf[UINTMAX_STRSIZE_BOUND];
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
WARNOPT (WARN_ALONE_ZERO_BLOCK,
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
}
}
diff_archive ();
tar_stat_destroy (&current_stat_info);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* Delete entries from a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
2005, 2006 Free Software Foundation, Inc.
2005, 2006, 2010 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
@@ -35,7 +35,6 @@ extern union block *current_block;
extern union block *recent_long_name;
extern union block *recent_long_link;
extern off_t records_read;
extern off_t records_written;
/* The number of records skipped at the start of the archive, when
passing over members that are not deleted. */
@@ -166,7 +165,9 @@ delete_archive_members (void)
do
{
enum read_header status = read_header (true);
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_x_raw);
switch (status)
{
@@ -261,7 +262,8 @@ delete_archive_members (void)
if (current_block == record_end)
flush_archive ();
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
xheader_decode (&current_stat_info);
@@ -294,7 +296,7 @@ delete_archive_members (void)
set_next_block_after (current_header);
blocks_to_skip = (current_stat_info.stat.st_size
+ BLOCKSIZE - 1) / BLOCKSIZE;
while (record_end - current_block <= blocks_to_skip)
{
blocks_to_skip -= (record_end - current_block);

View File

@@ -1,759 +0,0 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993 Free Software Foundation
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Diff files from a tar archive.
*
* Written 30 April 1987 by John Gilmore, ihnp4!hoptoad!gnu.
*/
#include <stdio.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
#include <sys/types.h>
#ifdef BSD42
#include <sys/file.h>
#else
#ifndef V7
#include <fcntl.h>
#endif
#endif
#ifdef HAVE_SYS_MTIO_H
#include <sys/ioctl.h>
#include <sys/mtio.h>
#endif
#include "tar.h"
#include "port.h"
#include "rmt.h"
#ifndef S_ISLNK
#define lstat stat
#endif
extern void *valloc ();
extern union record *head; /* Points to current tape header */
extern struct stat hstat; /* Stat struct corresponding */
extern int head_standard; /* Tape header is in ANSI format */
void decode_header ();
void diff_sparse_files ();
void fill_in_sparse_array ();
void fl_read ();
long from_oct ();
int do_stat ();
extern void print_header ();
int read_header ();
void saverec ();
void sigh ();
extern void skip_file ();
extern void skip_extended_headers ();
int wantbytes ();
extern FILE *msg_file;
int now_verifying = 0; /* Are we verifying at the moment? */
int diff_fd; /* Descriptor of file we're diffing */
char *diff_buf = 0; /* Pointer to area for reading
file contents into */
char *diff_dir; /* Directory contents for LF_DUMPDIR */
int different = 0;
/*struct sp_array *sparsearray;
int sp_ar_size = 10;*/
/*
* Initialize for a diff operation
*/
void
diff_init ()
{
/*NOSTRICT*/
diff_buf = (char *) valloc ((unsigned) blocksize);
if (!diff_buf)
{
msg ("could not allocate memory for diff buffer of %d bytes",
blocksize);
exit (EX_ARGSBAD);
}
}
/*
* Diff a file against the archive.
*/
void
diff_archive ()
{
register char *data;
int check, namelen;
int err;
long offset;
struct stat filestat;
int compare_chunk ();
int compare_dir ();
int no_op ();
#ifndef __MSDOS__
dev_t dev;
ino_t ino;
#endif
char *get_dir_contents ();
long from_oct ();
errno = EPIPE; /* FIXME, remove perrors */
saverec (&head); /* Make sure it sticks around */
userec (head); /* And go past it in the archive */
decode_header (head, &hstat, &head_standard, 1); /* Snarf fields */
/* Print the record from 'head' and 'hstat' */
if (f_verbose)
{
if (now_verifying)
fprintf (msg_file, "Verify ");
print_header ();
}
switch (head->header.linkflag)
{
default:
msg ("Unknown file type '%c' for %s, diffed as normal file",
head->header.linkflag, current_file_name);
/* FALL THRU */
case LF_OLDNORMAL:
case LF_NORMAL:
case LF_SPARSE:
case LF_CONTIG:
/*
* Appears to be a file.
* See if it's really a directory.
*/
namelen = strlen (current_file_name) - 1;
if (current_file_name[namelen] == '/')
goto really_dir;
if (do_stat (&filestat))
{
if (head->header.isextended)
skip_extended_headers ();
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
if (!S_ISREG (filestat.st_mode))
{
fprintf (msg_file, "%s: not a regular file\n",
current_file_name);
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
filestat.st_mode &= 07777;
if (filestat.st_mode != hstat.st_mode)
sigh ("mode");
if (filestat.st_uid != hstat.st_uid)
sigh ("uid");
if (filestat.st_gid != hstat.st_gid)
sigh ("gid");
if (filestat.st_mtime != hstat.st_mtime)
sigh ("mod time");
if (head->header.linkflag != LF_SPARSE &&
filestat.st_size != hstat.st_size)
{
sigh ("size");
skip_file ((long) hstat.st_size);
goto quit;
}
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
if (diff_fd < 0 && !f_absolute_paths)
{
char tmpbuf[NAMSIZ + 2];
tmpbuf[0] = '/';
strcpy (&tmpbuf[1], current_file_name);
diff_fd = open (tmpbuf, O_NDELAY | O_RDONLY);
}
if (diff_fd < 0)
{
msg_perror ("cannot open %s", current_file_name);
if (head->header.isextended)
skip_extended_headers ();
skip_file ((long) hstat.st_size);
different++;
goto quit;
}
/*
* Need to treat sparse files completely differently here.
*/
if (head->header.linkflag == LF_SPARSE)
diff_sparse_files (hstat.st_size);
else
wantbytes ((long) (hstat.st_size), compare_chunk);
check = close (diff_fd);
if (check < 0)
msg_perror ("Error while closing %s", current_file_name);
quit:
break;
#ifndef __MSDOS__
case LF_LINK:
if (do_stat (&filestat))
break;
dev = filestat.st_dev;
ino = filestat.st_ino;
err = stat (current_link_name, &filestat);
if (err < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file, "%s: does not exist\n", current_file_name);
}
else
{
msg_perror ("cannot stat file %s", current_file_name);
}
different++;
break;
}
if (filestat.st_dev != dev || filestat.st_ino != ino)
{
fprintf (msg_file, "%s not linked to %s\n", current_file_name, current_link_name);
break;
}
break;
#endif
#ifdef S_ISLNK
case LF_SYMLINK:
{
char linkbuf[NAMSIZ + 3];
check = readlink (current_file_name, linkbuf,
(sizeof linkbuf) - 1);
if (check < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file,
"%s: no such file or directory\n",
current_file_name);
}
else
{
msg_perror ("cannot read link %s", current_file_name);
}
different++;
break;
}
linkbuf[check] = '\0'; /* Null-terminate it */
if (strncmp (current_link_name, linkbuf, check) != 0)
{
fprintf (msg_file, "%s: symlink differs\n",
current_link_name);
different++;
}
}
break;
#endif
#ifdef S_IFCHR
case LF_CHR:
hstat.st_mode |= S_IFCHR;
goto check_node;
#endif
#ifdef S_IFBLK
/* If local system doesn't support block devices, use default case */
case LF_BLK:
hstat.st_mode |= S_IFBLK;
goto check_node;
#endif
#ifdef S_ISFIFO
/* If local system doesn't support FIFOs, use default case */
case LF_FIFO:
#ifdef S_IFIFO
hstat.st_mode |= S_IFIFO;
#endif
hstat.st_rdev = 0; /* FIXME, do we need this? */
goto check_node;
#endif
check_node:
/* FIXME, deal with umask */
if (do_stat (&filestat))
break;
if (hstat.st_rdev != filestat.st_rdev)
{
fprintf (msg_file, "%s: device numbers changed\n", current_file_name);
different++;
break;
}
#ifdef S_IFMT
if (hstat.st_mode != filestat.st_mode)
#else /* POSIX lossage */
if ((hstat.st_mode & 07777) != (filestat.st_mode & 07777))
#endif
{
fprintf (msg_file, "%s: mode or device-type changed\n", current_file_name);
different++;
break;
}
break;
case LF_DUMPDIR:
data = diff_dir = get_dir_contents (current_file_name, 0);
if (data)
{
wantbytes ((long) (hstat.st_size), compare_dir);
free (data);
}
else
wantbytes ((long) (hstat.st_size), no_op);
/* FALL THROUGH */
case LF_DIR:
/* Check for trailing / */
namelen = strlen (current_file_name) - 1;
really_dir:
while (namelen && current_file_name[namelen] == '/')
current_file_name[namelen--] = '\0'; /* Zap / */
if (do_stat (&filestat))
break;
if (!S_ISDIR (filestat.st_mode))
{
fprintf (msg_file, "%s is no longer a directory\n", current_file_name);
different++;
break;
}
if ((filestat.st_mode & 07777) != (hstat.st_mode & 07777))
sigh ("mode");
break;
case LF_VOLHDR:
break;
case LF_MULTIVOL:
namelen = strlen (current_file_name) - 1;
if (current_file_name[namelen] == '/')
goto really_dir;
if (do_stat (&filestat))
break;
if (!S_ISREG (filestat.st_mode))
{
fprintf (msg_file, "%s: not a regular file\n",
current_file_name);
skip_file ((long) hstat.st_size);
different++;
break;
}
filestat.st_mode &= 07777;
offset = from_oct (1 + 12, head->header.offset);
if (filestat.st_size != hstat.st_size + offset)
{
sigh ("size");
skip_file ((long) hstat.st_size);
different++;
break;
}
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
if (diff_fd < 0)
{
msg_perror ("cannot open file %s", current_file_name);
skip_file ((long) hstat.st_size);
different++;
break;
}
err = lseek (diff_fd, offset, 0);
if (err != offset)
{
msg_perror ("cannot seek to %ld in file %s", offset, current_file_name);
different++;
break;
}
wantbytes ((long) (hstat.st_size), compare_chunk);
check = close (diff_fd);
if (check < 0)
{
msg_perror ("Error while closing %s", current_file_name);
}
break;
}
/* We don't need to save it any longer. */
saverec ((union record **) 0);/* Unsave it */
}
int
compare_chunk (bytes, buffer)
long bytes;
char *buffer;
{
int err;
err = read (diff_fd, diff_buf, bytes);
if (err != bytes)
{
if (err < 0)
{
msg_perror ("can't read %s", current_file_name);
}
else
{
fprintf (msg_file, "%s: could only read %d of %d bytes\n", current_file_name, err, bytes);
}
different++;
return -1;
}
if (bcmp (buffer, diff_buf, bytes))
{
fprintf (msg_file, "%s: data differs\n", current_file_name);
different++;
return -1;
}
return 0;
}
int
compare_dir (bytes, buffer)
long bytes;
char *buffer;
{
if (bcmp (buffer, diff_dir, bytes))
{
fprintf (msg_file, "%s: data differs\n", current_file_name);
different++;
return -1;
}
diff_dir += bytes;
return 0;
}
/*
* Sigh about something that differs.
*/
void
sigh (what)
char *what;
{
fprintf (msg_file, "%s: %s differs\n",
current_file_name, what);
}
void
verify_volume ()
{
int status;
#ifdef MTIOCTOP
struct mtop t;
int er;
#endif
if (!diff_buf)
diff_init ();
#ifdef MTIOCTOP
t.mt_op = MTBSF;
t.mt_count = 1;
if ((er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
{
if (errno != EIO || (er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
{
#endif
if (rmtlseek (archive, 0L, 0) != 0)
{
/* Lseek failed. Try a different method */
msg_perror ("Couldn't rewind archive file for verify");
return;
}
#ifdef MTIOCTOP
}
}
#endif
ar_reading = 1;
now_verifying = 1;
fl_read ();
for (;;)
{
status = read_header ();
if (status == 0)
{
unsigned n;
n = 0;
do
{
n++;
status = read_header ();
}
while (status == 0);
msg ("VERIFY FAILURE: %d invalid header%s detected!", n, n == 1 ? "" : "s");
}
if (status == 2 || status == EOF)
break;
diff_archive ();
}
ar_reading = 0;
now_verifying = 0;
}
int
do_stat (statp)
struct stat *statp;
{
int err;
err = f_follow_links ? stat (current_file_name, statp) : lstat (current_file_name, statp);
if (err < 0)
{
if (errno == ENOENT)
{
fprintf (msg_file, "%s: does not exist\n", current_file_name);
}
else
msg_perror ("can't stat file %s", current_file_name);
/* skip_file((long)hstat.st_size);
different++;*/
return 1;
}
else
return 0;
}
/*
* JK
* Diff'ing a sparse file with its counterpart on the tar file is a
* bit of a different story than a normal file. First, we must know
* what areas of the file to skip through, i.e., we need to contruct
* a sparsearray, which will hold all the information we need. We must
* compare small amounts of data at a time as we find it.
*/
void
diff_sparse_files (filesize)
int filesize;
{
int sparse_ind = 0;
char *buf;
int buf_size = RECORDSIZE;
union record *datarec;
int err;
long numbytes;
/* int amt_read = 0;*/
int size = filesize;
buf = (char *) ck_malloc (buf_size * sizeof (char));
fill_in_sparse_array ();
while (size > 0)
{
datarec = findrec ();
if (!sparsearray[sparse_ind].numbytes)
break;
/*
* 'numbytes' is nicer to write than
* 'sparsearray[sparse_ind].numbytes' all the time ...
*/
numbytes = sparsearray[sparse_ind].numbytes;
lseek (diff_fd, sparsearray[sparse_ind].offset, 0);
/*
* take care to not run out of room in our buffer
*/
while (buf_size < numbytes)
{
buf = (char *) ck_realloc (buf, buf_size * 2 * sizeof (char));
buf_size *= 2;
}
while (numbytes > RECORDSIZE)
{
if ((err = read (diff_fd, buf, RECORDSIZE)) != RECORDSIZE)
{
if (err < 0)
msg_perror ("can't read %s", current_file_name);
else
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
current_file_name, err, numbytes);
break;
}
if (bcmp (buf, datarec->charptr, RECORDSIZE))
{
different++;
break;
}
numbytes -= err;
size -= err;
userec (datarec);
datarec = findrec ();
}
if ((err = read (diff_fd, buf, numbytes)) != numbytes)
{
if (err < 0)
msg_perror ("can't read %s", current_file_name);
else
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
current_file_name, err, numbytes);
break;
}
if (bcmp (buf, datarec->charptr, numbytes))
{
different++;
break;
}
/* amt_read += numbytes;
if (amt_read >= RECORDSIZE) {
amt_read = 0;
userec(datarec);
datarec = findrec();
}*/
userec (datarec);
sparse_ind++;
size -= numbytes;
}
/*
* if the number of bytes read isn't the
* number of bytes supposedly in the file,
* they're different
*/
/* if (amt_read != filesize)
different++;*/
userec (datarec);
free (sparsearray);
if (different)
fprintf (msg_file, "%s: data differs\n", current_file_name);
}
/*
* JK
* This routine should be used more often than it is ... look into
* that. Anyhow, what it does is translate the sparse information
* on the header, and in any subsequent extended headers, into an
* array of structures with true numbers, as opposed to character
* strings. It simply makes our life much easier, doing so many
* comparisong and such.
*/
void
fill_in_sparse_array ()
{
int ind;
/*
* allocate space for our scratch space; it's initially
* 10 elements long, but can change in this routine if
* necessary
*/
sp_array_size = 10;
sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
/*
* there are at most five of these structures in the header
* itself; read these in first
*/
for (ind = 0; ind < SPARSE_IN_HDR; ind++)
{
if (!head->header.sp[ind].numbytes)
break;
sparsearray[ind].offset =
from_oct (1 + 12, head->header.sp[ind].offset);
sparsearray[ind].numbytes =
from_oct (1 + 12, head->header.sp[ind].numbytes);
}
/*
* if the header's extended, we gotta read in exhdr's till
* we're done
*/
if (head->header.isextended)
{
/* how far into the sparsearray we are 'so far' */
static int so_far_ind = SPARSE_IN_HDR;
union record *exhdr;
for (;;)
{
exhdr = findrec ();
for (ind = 0; ind < SPARSE_EXT_HDR; ind++)
{
if (ind + so_far_ind > sp_array_size - 1)
{
/*
* we just ran out of room in our
* scratch area - realloc it
*/
sparsearray = (struct sp_array *)
ck_realloc (sparsearray,
sp_array_size * 2 * sizeof (struct sp_array));
sp_array_size *= 2;
}
/*
* convert the character strings into longs
*/
sparsearray[ind + so_far_ind].offset =
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].offset);
sparsearray[ind + so_far_ind].numbytes =
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].numbytes);
}
/*
* if this is the last extended header for this
* file, we can stop
*/
if (!exhdr->ext_hdr.isextended)
break;
else
{
so_far_ind += SPARSE_EXT_HDR;
userec (exhdr);
}
}
/* be sure to skip past the last one */
userec (exhdr);
}
}

37
src/exit.c Normal file
View File

@@ -0,0 +1,37 @@
/* This file is part of GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <system.h>
#include "common.h"
void (*fatal_exit_hook) (void);
void
fatal_exit (void)
{
if (fatal_exit_hook)
fatal_exit_hook ();
error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
abort ();
}
void
xalloc_die (void)
{
error (0, 0, "%s", _("memory exhausted"));
fatal_exit ();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,96 +0,0 @@
/* Replacement for getopt() that can be used by tar.
Copyright (C) 1988 Free Software Foundation
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Plug-compatible replacement for getopt() for parsing tar-like
* arguments. If the first argument begins with "-", it uses getopt;
* otherwise, it uses the old rules used by tar, dump, and ps.
*
* Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu)
*/
#include <stdio.h>
#include "getopt.h"
#include "tar.h" /* For msg() declaration if STDC_MSG. */
#include <sys/types.h>
#include "port.h"
int
getoldopt (argc, argv, optstring, long_options, opt_index)
int argc;
char **argv;
char *optstring;
struct option *long_options;
int *opt_index;
{
extern char *optarg; /* Points to next arg */
extern int optind; /* Global argv index */
static char *key; /* Points to next keyletter */
static char use_getopt; /* !=0 if argv[1][0] was '-' */
char c;
char *place;
optarg = NULL;
if (key == NULL)
{ /* First time */
if (argc < 2)
return EOF;
key = argv[1];
if ((*key == '-') || (*key == '+'))
use_getopt++;
else
optind = 2;
}
if (use_getopt)
return getopt_long (argc, argv, optstring,
long_options, opt_index);
c = *key++;
if (c == '\0')
{
key--;
return EOF;
}
place = index (optstring, c);
if (place == NULL || c == ':')
{
msg ("unknown option %c", c);
return ('?');
}
place++;
if (*place == ':')
{
if (optind < argc)
{
optarg = argv[optind];
optind++;
}
else
{
msg ("%c argument missing", c);
return ('?');
}
}
return (c);
}

677
src/gnu.c
View File

@@ -1,677 +0,0 @@
/* GNU dump extensions to tar.
Copyright (C) 1988, 1992, 1993 Free Software Foundation
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
#include <time.h>
time_t time ();
#include "tar.h"
#include "port.h"
#ifndef S_ISLNK
#define lstat stat
#endif
extern time_t new_time;
extern FILE *msg_file;
void addname ();
int check_exclude ();
extern PTR ck_malloc ();
extern PTR ck_realloc ();
int confirm ();
extern PTR init_buffer ();
extern char *get_buffer ();
int is_dot_or_dotdot ();
extern void add_buffer ();
extern void flush_buffer ();
void name_gather ();
int recursively_delete ();
void skip_file ();
char *un_quote_string ();
extern char *new_name ();
static void add_dir_name ();
struct dirname
{
struct dirname *next;
char *name;
char *dir_text;
int dev;
int ino;
int allnew;
};
static struct dirname *dir_list;
static time_t this_time;
void
add_dir (name, dev, ino, text)
char *name;
char *text;
dev_t dev;
ino_t ino;
{
struct dirname *dp;
dp = (struct dirname *) ck_malloc (sizeof (struct dirname));
if (!dp)
abort ();
dp->next = dir_list;
dir_list = dp;
dp->dev = dev;
dp->ino = ino;
dp->name = ck_malloc (strlen (name) + 1);
strcpy (dp->name, name);
dp->dir_text = text;
dp->allnew = 0;
}
void
read_dir_file ()
{
int dev;
int ino;
char *strp;
FILE *fp;
char buf[512];
static char *path = 0;
if (path == 0)
path = ck_malloc (PATH_MAX);
time (&this_time);
if (gnu_dumpfile[0] != '/')
{
#if defined(__MSDOS__) || defined(HAVE_GETCWD) || defined(_POSIX_VERSION)
if (!getcwd (path, PATH_MAX))
{
msg ("Couldn't get current directory.");
exit (EX_SYSTEM);
}
#else
char *getwd ();
if (!getwd (path))
{
msg ("Couldn't get current directory: %s", path);
exit (EX_SYSTEM);
}
#endif
/* If this doesn't fit, we're in serious trouble */
strcat (path, "/");
strcat (path, gnu_dumpfile);
gnu_dumpfile = path;
}
fp = fopen (gnu_dumpfile, "r");
if (fp == 0 && errno != ENOENT)
{
msg_perror ("Can't open %s", gnu_dumpfile);
return;
}
if (!fp)
return;
fgets (buf, sizeof (buf), fp);
if (!f_new_files)
{
f_new_files++;
new_time = atol (buf);
}
while (fgets (buf, sizeof (buf), fp))
{
strp = &buf[strlen (buf)];
if (strp[-1] == '\n')
strp[-1] = '\0';
strp = buf;
dev = atol (strp);
while (isdigit (*strp))
strp++;
ino = atol (strp);
while (isspace (*strp))
strp++;
while (isdigit (*strp))
strp++;
strp++;
add_dir (un_quote_string (strp), dev, ino, (char *) 0);
}
fclose (fp);
}
void
write_dir_file ()
{
FILE *fp;
struct dirname *dp;
char *str;
extern char *quote_copy_string ();
fp = fopen (gnu_dumpfile, "w");
if (fp == 0)
{
msg_perror ("Can't write to %s", gnu_dumpfile);
return;
}
fprintf (fp, "%lu\n", this_time);
for (dp = dir_list; dp; dp = dp->next)
{
if (!dp->dir_text)
continue;
str = quote_copy_string (dp->name);
if (str)
{
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, str);
free (str);
}
else
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, dp->name);
}
fclose (fp);
}
struct dirname *
get_dir (name)
char *name;
{
struct dirname *dp;
for (dp = dir_list; dp; dp = dp->next)
{
if (!strcmp (dp->name, name))
return dp;
}
return 0;
}
/* Collect all the names from argv[] (or whatever), then expand them into
a directory tree, and put all the directories at the beginning. */
void
collect_and_sort_names ()
{
struct name *n, *n_next;
int num_names;
struct stat statbuf;
int name_cmp ();
char *merge_sort ();
name_gather ();
if (gnu_dumpfile)
read_dir_file ();
if (!namelist)
addname (".");
for (n = namelist; n; n = n_next)
{
n_next = n->next;
if (n->found || n->dir_contents)
continue;
if (n->regexp) /* FIXME just skip regexps for now */
continue;
if (n->change_dir)
if (chdir (n->change_dir) < 0)
{
msg_perror ("can't chdir to %s", n->change_dir);
continue;
}
#ifdef AIX
if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK))
#else
if (lstat (n->name, &statbuf) < 0)
#endif /* AIX */
{
msg_perror ("can't stat %s", n->name);
continue;
}
if (S_ISDIR (statbuf.st_mode))
{
n->found++;
add_dir_name (n->name, statbuf.st_dev);
}
}
num_names = 0;
for (n = namelist; n; n = n->next)
num_names++;
namelist = (struct name *) merge_sort ((PTR) namelist, num_names, (char *) (&(namelist->next)) - (char *) namelist, name_cmp);
for (n = namelist; n; n = n->next)
{
n->found = 0;
}
if (gnu_dumpfile)
write_dir_file ();
}
int
name_cmp (n1, n2)
struct name *n1, *n2;
{
if (n1->found)
{
if (n2->found)
return strcmp (n1->name, n2->name);
else
return -1;
}
else if (n2->found)
return 1;
else
return strcmp (n1->name, n2->name);
}
int
dirent_cmp (p1, p2)
const PTR p1;
const PTR p2;
{
char *frst, *scnd;
frst = (*(char **) p1) + 1;
scnd = (*(char **) p2) + 1;
return strcmp (frst, scnd);
}
char *
get_dir_contents (p, device)
char *p;
int device;
{
DIR *dirp;
register struct dirent *d;
char *new_buf;
char *namebuf;
int bufsiz;
int len;
PTR the_buffer;
char *buf;
size_t n_strs;
/* int n_size;*/
char *p_buf;
char **vec, **p_vec;
extern int errno;
errno = 0;
dirp = opendir (p);
bufsiz = strlen (p) + NAMSIZ;
namebuf = ck_malloc (bufsiz + 2);
if (!dirp)
{
if (errno)
msg_perror ("can't open directory %s", p);
else
msg ("error opening directory %s", p);
new_buf = NULL;
}
else
{
struct dirname *dp;
int all_children;
dp = get_dir (p);
all_children = dp ? dp->allnew : 0;
(void) strcpy (namebuf, p);
if (p[strlen (p) - 1] != '/')
(void) strcat (namebuf, "/");
len = strlen (namebuf);
the_buffer = init_buffer ();
while (d = readdir (dirp))
{
struct stat hs;
/* Skip . and .. */
if (is_dot_or_dotdot (d->d_name))
continue;
if (NLENGTH (d) + len >= bufsiz)
{
bufsiz += NAMSIZ;
namebuf = ck_realloc (namebuf, bufsiz + 2);
}
(void) strcpy (namebuf + len, d->d_name);
#ifdef AIX
if (0 != f_follow_links ?
statx (namebuf, &hs, STATSIZE, STX_HIDDEN) :
statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK))
#else
if (0 != f_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs))
#endif
{
msg_perror ("can't stat %s", namebuf);
continue;
}
if ((f_local_filesys && device != hs.st_dev)
|| (f_exclude && check_exclude (namebuf)))
add_buffer (the_buffer, "N", 1);
#ifdef AIX
else if (S_ISHIDDEN (hs.st_mode))
{
add_buffer (the_buffer, "D", 1);
strcat (d->d_name, "A");
d->d_namlen++;
}
#endif /* AIX */
else if (S_ISDIR (hs.st_mode))
{
if (dp = get_dir (namebuf))
{
if (dp->dev != hs.st_dev
|| dp->ino != hs.st_ino)
{
if (f_verbose)
msg ("directory %s has been renamed.", namebuf);
dp->allnew = 1;
dp->dev = hs.st_dev;
dp->ino = hs.st_ino;
}
dp->dir_text = "";
}
else
{
if (f_verbose)
msg ("Directory %s is new", namebuf);
add_dir (namebuf, hs.st_dev, hs.st_ino, "");
dp = get_dir (namebuf);
dp->allnew = 1;
}
if (all_children)
dp->allnew = 1;
add_buffer (the_buffer, "D", 1);
}
else if (!all_children
&& f_new_files
&& new_time > hs.st_mtime
&& (f_new_files > 1
|| new_time > hs.st_ctime))
add_buffer (the_buffer, "N", 1);
else
add_buffer (the_buffer, "Y", 1);
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
}
add_buffer (the_buffer, "\000\000", 2);
closedir (dirp);
/* Well, we've read in the contents of the dir, now sort them */
buf = get_buffer (the_buffer);
if (buf[0] == '\0')
{
flush_buffer (the_buffer);
new_buf = NULL;
}
else
{
n_strs = 0;
for (p_buf = buf; *p_buf;)
{
int tmp;
tmp = strlen (p_buf) + 1;
n_strs++;
p_buf += tmp;
}
vec = (char **) ck_malloc (sizeof (char *) * (n_strs + 1));
for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1)
*p_vec++ = p_buf;
*p_vec = 0;
qsort ((PTR) vec, n_strs, sizeof (char *), dirent_cmp);
new_buf = (char *) ck_malloc (p_buf - buf + 2);
for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++)
{
char *p_tmp;
for (p_tmp = *p_vec; *p_buf++ = *p_tmp++;)
;
}
*p_buf++ = '\0';
free (vec);
flush_buffer (the_buffer);
}
}
free (namebuf);
return new_buf;
}
/* p is a directory. Add all the files in P to the namelist. If any of the
files is a directory, recurse on the subdirectory. . . */
static void
add_dir_name (p, device)
char *p;
int device;
{
char *new_buf;
char *p_buf;
char *namebuf;
int buflen;
register int len;
int sublen;
/* PTR the_buffer;*/
/* char *buf;*/
/* char **vec,**p_vec;*/
/* int n_strs,n_size;*/
struct name *n;
int dirent_cmp ();
new_buf = get_dir_contents (p, device);
for (n = namelist; n; n = n->next)
{
if (!strcmp (n->name, p))
{
n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
break;
}
}
if (new_buf)
{
len = strlen (p);
buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ;
namebuf = ck_malloc (buflen + 1);
(void) strcpy (namebuf, p);
if (namebuf[len - 1] != '/')
{
namebuf[len++] = '/';
namebuf[len] = '\0';
}
for (p_buf = new_buf; *p_buf; p_buf += sublen + 1)
{
sublen = strlen (p_buf);
if (*p_buf == 'D')
{
if (len + sublen >= buflen)
{
buflen += NAMSIZ;
namebuf = ck_realloc (namebuf, buflen + 1);
}
(void) strcpy (namebuf + len, p_buf + 1);
addname (namebuf);
add_dir_name (namebuf, device);
}
}
free (namebuf);
}
}
/* Returns non-zero if p is . or .. This could be a macro for speed. */
int
is_dot_or_dotdot (p)
char *p;
{
return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')));
}
void
gnu_restore (skipcrud)
int skipcrud;
{
char *current_dir;
/* int current_dir_length; */
char *archive_dir;
/* int archive_dir_length; */
PTR the_buffer;
char *p;
DIR *dirp;
struct dirent *d;
char *cur, *arc;
extern struct stat hstat; /* Stat struct corresponding */
long size, copied;
char *from, *to;
extern union record *head;
dirp = opendir (skipcrud + current_file_name);
if (!dirp)
{
/* The directory doesn't exist now. It'll be created.
In any case, we don't have to delete any files out
of it */
skip_file ((long) hstat.st_size);
return;
}
the_buffer = init_buffer ();
while (d = readdir (dirp))
{
if (is_dot_or_dotdot (d->d_name))
continue;
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
}
closedir (dirp);
add_buffer (the_buffer, "", 1);
current_dir = get_buffer (the_buffer);
archive_dir = (char *) ck_malloc (hstat.st_size);
if (archive_dir == 0)
{
msg ("Can't allocate %d bytes for restore", hstat.st_size);
skip_file ((long) hstat.st_size);
return;
}
to = archive_dir;
for (size = hstat.st_size; size > 0; size -= copied)
{
from = findrec ()->charptr;
if (!from)
{
msg ("Unexpected EOF in archive\n");
break;
}
copied = endofrecs ()->charptr - from;
if (copied > size)
copied = size;
bcopy ((PTR) from, (PTR) to, (int) copied);
to += copied;
userec ((union record *) (from + copied - 1));
}
for (cur = current_dir; *cur; cur += strlen (cur) + 1)
{
for (arc = archive_dir; *arc; arc += strlen (arc) + 1)
{
arc++;
if (!strcmp (arc, cur))
break;
}
if (*arc == '\0')
{
p = new_name (skipcrud + current_file_name, cur);
if (f_confirm && !confirm ("delete", p))
{
free (p);
continue;
}
if (f_verbose)
fprintf (msg_file, "%s: deleting %s\n", tar, p);
if (recursively_delete (p))
{
msg ("%s: Error while deleting %s\n", tar, p);
}
free (p);
}
}
flush_buffer (the_buffer);
free (archive_dir);
}
int
recursively_delete (path)
char *path;
{
struct stat sbuf;
DIR *dirp;
struct dirent *dp;
char *path_buf;
/* int path_len; */
if (lstat (path, &sbuf) < 0)
return 1;
if (S_ISDIR (sbuf.st_mode))
{
/* path_len=strlen(path); */
dirp = opendir (path);
if (dirp == 0)
return 1;
while (dp = readdir (dirp))
{
if (is_dot_or_dotdot (dp->d_name))
continue;
path_buf = new_name (path, dp->d_name);
if (recursively_delete (path_buf))
{
free (path_buf);
closedir (dirp);
return 1;
}
free (path_buf);
}
closedir (dirp);
if (rmdir (path) < 0)
return 1;
return 0;
}
if (unlink (path) < 0)
return 1;
return 0;
}

View File

@@ -1,7 +1,7 @@
/* GNU dump extensions to tar.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007, 2008, 2009 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
@@ -43,7 +43,7 @@ enum children
#define DIR_IS_INITED(d) ((d)->flags & DIRF_INIT)
#define DIR_IS_NFS(d) ((d)->flags & DIRF_NFS)
#define DIR_IS_FOUND(d) ((d)->flags & DIRF_FOUND)
#define DIR_IS_NEW(d) ((d)->flags & DIRF_NEW)
/* #define DIR_IS_NEW(d) ((d)->flags & DIRF_NEW) FIXME: not used */
#define DIR_IS_RENAMED(d) ((d)->flags & DIRF_RENAMED)
#define DIR_SET_FLAG(d,f) (d)->flags |= (f)
@@ -73,17 +73,18 @@ struct directory
the original directory structure */
const char *tagfile; /* Tag file, if the directory falls under
exclusion_tag_under */
char *caname; /* canonical name */
char *name; /* file name of directory */
};
struct dumpdir *
static struct dumpdir *
dumpdir_create0 (const char *contents, const char *cmask)
{
struct dumpdir *dump;
size_t i, total, ctsize, len;
char *p;
const char *q;
for (i = 0, total = 0, ctsize = 1, q = contents; *q; total++, q += len)
{
len = strlen (q) + 1;
@@ -107,13 +108,13 @@ dumpdir_create0 (const char *contents, const char *cmask)
return dump;
}
struct dumpdir *
static struct dumpdir *
dumpdir_create (const char *contents)
{
return dumpdir_create0 (contents, "YND");
}
void
static void
dumpdir_free (struct dumpdir *dump)
{
free (dump->elv);
@@ -130,7 +131,7 @@ compare_dirnames (const void *first, const void *second)
/* Locate NAME in the dumpdir array DUMP.
Return pointer to the slot in DUMP->contents, or NULL if not found */
char *
static char *
dumpdir_locate (struct dumpdir *dump, const char *name)
{
char **ptr;
@@ -145,16 +146,16 @@ dumpdir_locate (struct dumpdir *dump, const char *name)
struct dumpdir_iter
{
struct dumpdir *dump; /* Dumpdir being iterated */
int all; /* Iterate over all entries, not only D/N/Y */
int all; /* Iterate over all entries, not only D/N/Y */
size_t next; /* Index of the next element */
};
char *
static char *
dumpdir_next (struct dumpdir_iter *itr)
{
size_t cur = itr->next;
char *ret = NULL;
if (itr->all)
{
ret = itr->dump->contents + cur;
@@ -171,7 +172,7 @@ dumpdir_next (struct dumpdir_iter *itr)
return ret;
}
char *
static char *
dumpdir_first (struct dumpdir *dump, int all, struct dumpdir_iter **pitr)
{
struct dumpdir_iter *itr = xmalloc (sizeof (*itr));
@@ -212,19 +213,19 @@ static Hash_table *directory_meta_table;
/* Calculate the hash of a directory. */
static size_t
hash_directory_name (void const *entry, size_t n_buckets)
hash_directory_canonical_name (void const *entry, size_t n_buckets)
{
struct directory const *directory = entry;
return hash_string (directory->name, n_buckets);
return hash_string (directory->caname, n_buckets);
}
/* Compare two directories for equality of their names. */
static bool
compare_directory_names (void const *entry1, void const *entry2)
compare_directory_canonical_names (void const *entry1, void const *entry2)
{
struct directory const *directory1 = entry1;
struct directory const *directory2 = entry2;
return strcmp (directory1->name, directory2->name) == 0;
return strcmp (directory1->caname, directory2->caname) == 0;
}
static size_t
@@ -245,9 +246,11 @@ compare_directory_meta (void const *entry1, void const *entry2)
&& directory1->inode_number == directory2->inode_number;
}
/* Make a directory entry for given NAME */
/* Make a directory entry for given relative NAME and canonical name CANAME.
The latter is "stolen", i.e. the returned directory contains pointer to
it. */
static struct directory *
make_directory (const char *name)
make_directory (const char *name, char *caname)
{
size_t namelen = strlen (name);
struct directory *directory = xmalloc (sizeof (*directory));
@@ -255,11 +258,12 @@ make_directory (const char *name)
directory->dump = directory->idump = NULL;
directory->orig = NULL;
directory->flags = false;
if (namelen && ISSLASH (name[namelen - 1]))
if (namelen > 1 && ISSLASH (name[namelen - 1]))
namelen--;
directory->name = xmalloc (namelen + 1);
memcpy (directory->name, name, namelen);
directory->name[namelen] = 0;
directory->caname = caname;
directory->tagfile = NULL;
return directory;
}
@@ -267,6 +271,7 @@ make_directory (const char *name)
static void
free_directory (struct directory *dir)
{
free (dir->caname);
free (dir->name);
free (dir);
}
@@ -274,7 +279,8 @@ free_directory (struct directory *dir)
static struct directory *
attach_directory (const char *name)
{
struct directory *dir = make_directory (name);
char *cname = normalize_filename (name);
struct directory *dir = make_directory (name, cname);
if (dirtail)
dirtail->next = dir;
else
@@ -282,27 +288,9 @@ attach_directory (const char *name)
dirtail = dir;
return dir;
}
static void
replace_prefix (char **pname, const char *samp, size_t slen,
const char *repl, size_t rlen)
{
char *name = *pname;
size_t nlen = strlen (name);
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
{
if (rlen > slen)
{
name = xrealloc (name, nlen - slen + rlen + 1);
*pname = name;
}
memmove (name + rlen, name + slen, nlen - slen + 1);
memcpy (name, repl, rlen);
}
}
void
dirlist_replace_prefix (const char *pref, const char *repl)
{
struct directory *dp;
@@ -338,8 +326,8 @@ note_directory (char const *name, struct timespec mtime,
if (! ((directory_table
|| (directory_table = hash_initialize (0, 0,
hash_directory_name,
compare_directory_names, 0)))
hash_directory_canonical_name,
compare_directory_canonical_names, 0)))
&& hash_insert (directory_table, directory)))
xalloc_die ();
@@ -362,13 +350,38 @@ find_directory (const char *name)
return 0;
else
{
struct directory *dir = make_directory (name);
char *caname = normalize_filename (name);
struct directory *dir = make_directory (name, caname);
struct directory *ret = hash_lookup (directory_table, dir);
free_directory (dir);
return ret;
}
}
#if 0
/* Remove directory entry for the given CANAME */
void
remove_directory (const char *caname)
{
struct directory *dir = make_directory (caname, xstrdup (caname));
struct directory *ret = hash_delete (directory_table, dir);
if (ret)
free_directory (ret);
free_directory (dir);
}
#endif
/* If first OLD_PREFIX_LEN bytes of DIR->NAME name match OLD_PREFIX,
replace them with NEW_PREFIX. */
void
rebase_directory (struct directory *dir,
const char *old_prefix, size_t old_prefix_len,
const char *new_prefix, size_t new_prefix_len)
{
replace_prefix (&dir->name, old_prefix, old_prefix_len,
new_prefix, new_prefix_len);
}
/* Return a directory entry for a given combination of device and inode
numbers, or zero if none found. */
static struct directory *
@@ -378,7 +391,7 @@ find_directory_meta (dev_t dev, ino_t ino)
return 0;
else
{
struct directory *dir = make_directory ("");
struct directory *dir = make_directory ("", NULL);
struct directory *ret;
dir->device_number = dev;
dir->inode_number = ino;
@@ -389,41 +402,53 @@ find_directory_meta (dev_t dev, ino_t ino)
}
void
update_parent_directory (const char *name)
update_parent_directory (struct tar_stat_info *parent)
{
struct directory *directory;
char *p;
p = dir_name (name);
directory = find_directory (p);
struct directory *directory = find_directory (parent->orig_file_name);
if (directory)
{
struct stat st;
if (deref_stat (dereference_option, p, &st) != 0)
stat_diag (name);
if (fstat (parent->fd, &st) != 0)
stat_diag (directory->name);
else
directory->mtime = get_stat_mtime (&st);
}
free (p);
}
#define PD_VERBOSE 0x10
#define PD_FORCE_CHILDREN 0x20
#define PD_FORCE_CHILDREN 0x10
#define PD_FORCE_INIT 0x20
#define PD_CHILDREN(f) ((f) & 3)
static struct directory *
procdir (char *name_buffer, struct stat *stat_data,
dev_t device,
procdir (const char *name_buffer, struct tar_stat_info *st,
int flag,
char *entry)
{
struct directory *directory;
struct stat *stat_data = &st->stat;
dev_t device = st->parent ? st->parent->stat.st_dev : 0;
bool nfs = NFS_FILE_STAT (*stat_data);
if ((directory = find_directory (name_buffer)) != NULL)
{
if (DIR_IS_INITED (directory))
return directory;
{
if (flag & PD_FORCE_INIT)
{
assign_string (&directory->name, name_buffer);
}
else
{
*entry = 'N'; /* Avoid duplicating this directory */
return directory;
}
}
if (strcmp (directory->name, name_buffer))
{
*entry = 'N';
return directory;
}
/* With NFS, the same file can have two different devices
if an NFS directory is mounted in multiple locations,
@@ -444,10 +469,11 @@ procdir (char *name_buffer, struct stat *stat_data,
{
if (strcmp (d->name, name_buffer))
{
if (verbose_option)
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0,
_("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
directory->orig = d;
DIR_SET_FLAG (directory, DIRF_RENAMED);
dirlist_replace_prefix (d->name, name_buffer);
@@ -456,9 +482,9 @@ procdir (char *name_buffer, struct stat *stat_data,
}
else
{
if (verbose_option)
WARN ((0, 0, _("%s: Directory has been renamed"),
quotearg_colon (name_buffer)));
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0, _("%s: Directory has been renamed"),
quotearg_colon (name_buffer)));
directory->children = ALL_CHILDREN;
directory->device_number = stat_data->st_dev;
directory->inode_number = stat_data->st_ino;
@@ -488,10 +514,10 @@ procdir (char *name_buffer, struct stat *stat_data,
{
if (strcmp (d->name, name_buffer))
{
if (flag & PD_VERBOSE)
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
WARNOPT (WARN_RENAME_DIRECTORY,
(0, 0, _("%s: Directory has been renamed from %s"),
quotearg_colon (name_buffer),
quote_n (1, d->name)));
directory->orig = d;
DIR_SET_FLAG (directory, DIRF_RENAMED);
dirlist_replace_prefix (d->name, name_buffer);
@@ -501,9 +527,9 @@ procdir (char *name_buffer, struct stat *stat_data,
else
{
DIR_SET_FLAG (directory, DIRF_NEW);
if (flag & PD_VERBOSE)
WARN ((0, 0, _("%s: Directory is new"),
quotearg_colon (name_buffer)));
WARNOPT (WARN_NEW_DIRECTORY,
(0, 0, _("%s: Directory is new"),
quotearg_colon (name_buffer)));
directory->children =
(listed_incremental_option
|| (OLDER_STAT_TIME (*stat_data, m)
@@ -519,6 +545,12 @@ procdir (char *name_buffer, struct stat *stat_data,
if (one_file_system_option && device != stat_data->st_dev
/* ... except if it was explicitely given in the command line */
&& !is_individual_file (name_buffer))
/* FIXME:
WARNOPT (WARN_XDEV,
(0, 0,
_("%s: directory is on a different filesystem; not dumped"),
quotearg_colon (directory->name)));
*/
directory->children = NO_CHILDREN;
else if (flag & PD_FORCE_CHILDREN)
{
@@ -526,14 +558,14 @@ procdir (char *name_buffer, struct stat *stat_data,
if (directory->children == NO_CHILDREN)
*entry = 'N';
}
DIR_SET_FLAG (directory, DIRF_INIT);
if (directory->children != NO_CHILDREN)
{
const char *tag_file_name;
switch (check_exclusion_tags (name_buffer, &tag_file_name))
switch (check_exclusion_tags (st, &tag_file_name))
{
case exclusion_tag_all:
/* This warning can be duplicated by code in dump_file0, but only
@@ -541,8 +573,7 @@ procdir (char *name_buffer, struct stat *stat_data,
an exclusion tag. */
exclusion_tag_warning (name_buffer, tag_file_name,
_("directory not dumped"));
if (entry)
*entry = 'N';
*entry = 'N';
directory->children = NO_CHILDREN;
break;
@@ -551,13 +582,13 @@ procdir (char *name_buffer, struct stat *stat_data,
_("contents not dumped"));
directory->children = NO_CHILDREN;
break;
case exclusion_tag_under:
exclusion_tag_warning (name_buffer, tag_file_name,
_("contents not dumped"));
directory->tagfile = tag_file_name;
break;
case exclusion_tag_none:
break;
}
@@ -577,7 +608,7 @@ procdir (char *name_buffer, struct stat *stat_data,
DIRECTORY->dump is replaced with the created template. Each entry is
prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
void
static void
makedumpdir (struct directory *directory, const char *dir)
{
size_t i,
@@ -643,45 +674,37 @@ makedumpdir (struct directory *directory, const char *dir)
free (array);
}
/* Recursively scan the given directory. */
static const char *
scan_directory (char *dir, dev_t device)
/* Recursively scan the directory identified by ST. */
struct directory *
scan_directory (struct tar_stat_info *st)
{
char *dirp = savedir (dir); /* for scanning directory */
char *name_buffer; /* directory, `/', and directory member */
size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */
size_t name_length; /* used length in name_buffer */
struct stat stat_data;
char const *dir = st->orig_file_name;
char *dirp = get_directory_entries (st);
dev_t device = st->stat.st_dev;
bool cmdline = ! st->parent;
namebuf_t nbuf;
char *tmp;
struct directory *directory;
char ch;
if (! dirp)
savedir_error (dir);
name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
name_buffer = xmalloc (name_buffer_size + 2);
strcpy (name_buffer, dir);
if (! ISSLASH (dir[strlen (dir) - 1]))
strcat (name_buffer, "/");
name_length = strlen (name_buffer);
tmp = xstrdup (dir);
zap_slashes (tmp);
if (deref_stat (dereference_option, name_buffer, &stat_data))
{
stat_diag (name_buffer);
/* FIXME: used to be
children = CHANGED_CHILDREN;
but changed to: */
free (name_buffer);
free (dirp);
return NULL;
}
directory = procdir (tmp, st,
(cmdline ? PD_FORCE_INIT : 0),
&ch);
directory = procdir (name_buffer, &stat_data, device, 0, NULL);
free (tmp);
nbuf = namebuf_create (dir);
if (dirp && directory->children != NO_CHILDREN)
{
char *entry; /* directory entry being scanned */
size_t entrylen; /* length of directory entry */
dumpdir_iter_t itr;
struct dumpdir_iter *itr;
makedumpdir (directory, dirp);
@@ -689,77 +712,105 @@ scan_directory (char *dir, dev_t device)
entry;
entry = dumpdir_next (itr))
{
entrylen = strlen (entry);
if (name_buffer_size <= entrylen - 1 + name_length)
{
do
name_buffer_size += NAME_FIELD_SIZE;
while (name_buffer_size <= entrylen - 1 + name_length);
name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
}
strcpy (name_buffer + name_length, entry + 1);
char *full_name = namebuf_name (nbuf, entry + 1);
if (*entry == 'I') /* Ignored entry */
*entry = 'N';
else if (excluded_name (name_buffer))
else if (excluded_name (full_name))
*entry = 'N';
else
{
if (deref_stat (dereference_option, name_buffer, &stat_data))
int fd = st->fd;
void (*diag) (char const *) = 0;
struct tar_stat_info stsub;
tar_stat_init (&stsub);
if (fd < 0)
{
stat_diag (name_buffer);
*entry = 'N';
continue;
errno = - fd;
diag = open_diag;
}
else if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0)
diag = stat_diag;
else if (S_ISDIR (stsub.stat.st_mode))
{
int subfd = subfile_open (st, entry + 1, open_read_flags);
if (subfd < 0)
diag = open_diag;
else
{
stsub.fd = subfd;
if (fstat (subfd, &stsub.stat) != 0)
diag = stat_diag;
}
}
if (S_ISDIR (stat_data.st_mode))
if (diag)
{
int pd_flag = (verbose_option ? PD_VERBOSE : 0);
file_removed_diag (full_name, false, diag);
*entry = 'N';
}
else if (S_ISDIR (stsub.stat.st_mode))
{
int pd_flag = 0;
if (!recursion_option)
pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
else if (directory->children == ALL_CHILDREN)
pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
*entry = 'D';
procdir (name_buffer, &stat_data, device, pd_flag, entry);
stsub.parent = st;
procdir (full_name, &stsub, pd_flag, entry);
restore_parent_fd (&stsub);
}
else if (one_file_system_option && device != stat_data.st_dev)
else if (one_file_system_option && device != stsub.stat.st_dev)
*entry = 'N';
else if (*entry == 'Y')
/* New entry, skip further checks */;
/* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
else if (OLDER_STAT_TIME (stat_data, m)
else if (OLDER_STAT_TIME (stsub.stat, m)
&& (!after_date_option
|| OLDER_STAT_TIME (stat_data, c)))
|| OLDER_STAT_TIME (stsub.stat, c)))
*entry = 'N';
else
*entry = 'Y';
tar_stat_destroy (&stsub);
}
}
free (itr);
}
free (name_buffer);
namebuf_free (nbuf);
if (dirp)
free (dirp);
return directory->dump ? directory->dump->contents : NULL;
return directory;
}
/* Return pointer to the contents of the directory DIR */
const char *
get_directory_contents (char *dir, dev_t device)
directory_contents (struct directory *dir)
{
return scan_directory (dir, device);
if (!dir)
return NULL;
return dir->dump ? dir->dump->contents : NULL;
}
/* A "safe" version of directory_contents, which never returns NULL. */
const char *
safe_directory_contents (struct directory *dir)
{
const char *ret = directory_contents (dir);
return ret ? ret : "\0\0\0\0";
}
static void
obstack_code_rename (struct obstack *stk, char *from, char *to)
obstack_code_rename (struct obstack *stk, char const *from, char const *to)
{
char *s;
char const *s;
s = from[0] == 0 ? from :
safer_name_suffix (from, false, absolute_names_option);
@@ -815,17 +866,19 @@ store_rename (struct directory *dir, struct obstack *stk)
}
}
const char *
append_incremental_renames (const char *dump)
void
append_incremental_renames (struct directory *dir)
{
struct obstack stk;
size_t size;
struct directory *dp;
const char *dump;
if (dirhead == NULL)
return dump;
return;
obstack_init (&stk);
dump = directory_contents (dir);
if (dump)
{
size = dumpdir_size (dump) - 1;
@@ -837,14 +890,14 @@ append_incremental_renames (const char *dump)
for (dp = dirhead; dp; dp = dp->next)
store_rename (dp, &stk);
if (obstack_object_size (&stk) != size)
/* FIXME: Is this the right thing to do when DIR is null? */
if (dir && obstack_object_size (&stk) != size)
{
obstack_1grow (&stk, 0);
dump = obstack_finish (&stk);
dumpdir_free (dir->dump);
dir->dump = dumpdir_create (obstack_finish (&stk));
}
else
obstack_free (&stk, NULL);
return dump;
obstack_free (&stk, NULL);
}
@@ -869,8 +922,8 @@ read_incr_db_01 (int version, const char *initbuf)
uintmax_t u;
time_t sec;
long int nsec;
char *buf = 0;
size_t bufsize;
char *buf = NULL;
size_t bufsize = 0;
char *ebuf;
long lineno = 1;
@@ -1164,7 +1217,7 @@ read_timespec (FILE *fp, struct timespec *pval)
/* Read incremental snapshot format 2 */
static void
read_incr_db_2 ()
read_incr_db_2 (void)
{
uintmax_t u;
struct obstack stk;
@@ -1229,13 +1282,16 @@ void
read_directory_file (void)
{
int fd;
char *buf = 0;
size_t bufsize;
char *buf = NULL;
size_t bufsize = 0;
int flags = O_RDWR | O_CREAT;
if (incremental_level == 0)
flags |= O_TRUNC;
/* Open the file for both read and write. That way, we can write
it later without having to reopen it, and don't have to worry if
we chdir in the meantime. */
fd = open (listed_incremental_option, O_RDWR | O_CREAT, MODE_RW);
fd = open (listed_incremental_option, flags, MODE_RW);
if (fd < 0)
{
open_error (listed_incremental_option);
@@ -1250,6 +1306,13 @@ read_directory_file (void)
return;
}
/* Consume the first name from the name list and reset the
list afterwards. This is done to change to the new
directory, if the first name is a chdir request (-C dir),
which is necessary to recreate absolute file names. */
name_from_list ();
blank_name_list ();
if (0 < getline (&buf, &bufsize, listed_incremental_stream))
{
char *ebuf;
@@ -1304,7 +1367,7 @@ write_directory_file_entry (void *entry, void *data)
if (DIR_IS_FOUND (directory))
{
char buf[UINTMAX_STRSIZE_BOUND];
char *s;
char const *s;
s = DIR_IS_NFS (directory) ? "1" : "0";
fwrite (s, 2, 1, fp);
@@ -1323,7 +1386,7 @@ write_directory_file_entry (void *entry, void *data)
if (directory->dump)
{
const char *p;
dumpdir_iter_t itr;
struct dumpdir_iter *itr;
for (p = dumpdir_first (directory->dump, 0, &itr);
p;
@@ -1347,7 +1410,7 @@ write_directory_file (void)
if (! fp)
return;
if (fseek (fp, 0L, SEEK_SET) != 0)
if (fseeko (fp, 0L, SEEK_SET) != 0)
seek_error (listed_incremental_option);
if (sys_truncate (fileno (fp)) != 0)
truncate_error (listed_incremental_option);
@@ -1389,7 +1452,7 @@ get_gnu_dumpdir (struct tar_stat_info *stat_info)
to = archive_dir;
set_next_block_after (current_header);
mv_begin (stat_info);
mv_begin_read (stat_info);
for (; size > 0; size -= copied)
{
@@ -1504,7 +1567,8 @@ dumpdir_ok (char *dumpdir)
}
if (has_tempdir)
WARN ((0, 0, _("Malformed dumpdir: 'X' never used")));
WARNOPT (WARN_BAD_DUMPDIR,
(0, 0, _("Malformed dumpdir: 'X' never used")));
return true;
}
@@ -1604,7 +1668,7 @@ try_purge_directory (char const *directory_name)
free (p);
p = new_name (directory_name, cur);
if (deref_stat (false, p, &st))
if (deref_stat (p, &st) != 0)
{
if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed
dirs and check it here? */
@@ -1643,7 +1707,7 @@ try_purge_directory (char const *directory_name)
}
free (p);
dumpdir_free (dump);
free (current_dir);
return true;
}

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, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-26.
@@ -33,7 +33,22 @@ union block *recent_long_name; /* recent long name header and contents */
union block *recent_long_link; /* likewise, for long link */
size_t recent_long_name_blocks; /* number of blocks in recent_long_name */
size_t recent_long_link_blocks; /* likewise, for long link */
union block *recent_global_header; /* Recent global header block */
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
#define MODE_FROM_HEADER(where, hbits) \
mode_from_header (where, sizeof (where), hbits)
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
static gid_t gid_from_header (const char *buf, size_t size);
static major_t major_from_header (const char *buf, size_t size);
static minor_t minor_from_header (const char *buf, size_t size);
static mode_t mode_from_header (const char *buf, size_t size, unsigned *hbits);
static time_t time_from_header (const char *buf, size_t size);
static uid_t uid_from_header (const char *buf, size_t size);
static uintmax_t from_header (const char *, size_t, const char *,
uintmax_t, uintmax_t, bool, bool);
@@ -60,6 +75,66 @@ base64_init (void)
base64_map[(int) base_64_digits[i]] = i;
}
static char *
decode_xform (char *file_name, void *data)
{
int type = *(int*)data;
switch (type)
{
case XFORM_SYMLINK:
/* FIXME: It is not quite clear how and to which extent are the symbolic
links subject to filename transformation. In the absence of another
solution, symbolic links are exempt from component stripping and
name suffix normalization, but subject to filename transformation
proper. */
return file_name;
case XFORM_LINK:
file_name = safer_name_suffix (file_name, true, absolute_names_option);
break;
case XFORM_REGFILE:
file_name = safer_name_suffix (file_name, false, absolute_names_option);
break;
}
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name,
strip_name_components);
if (prefix_len == (size_t) -1)
prefix_len = strlen (file_name);
file_name += prefix_len;
}
return file_name;
}
static bool
transform_member_name (char **pinput, int type)
{
return transform_name_fp (pinput, type, decode_xform, &type);
}
void
transform_stat_info (int typeflag, struct tar_stat_info *stat_info)
{
if (typeflag == GNUTYPE_VOLHDR)
/* Name transformations don't apply to volume headers. */
return;
transform_member_name (&stat_info->file_name, XFORM_REGFILE);
switch (typeflag)
{
case SYMTYPE:
transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
break;
case LNKTYPE:
transform_member_name (&stat_info->link_name, XFORM_LINK);
}
}
/* Main loop for reading an archive. */
void
read_and (void (*do_something) (void))
@@ -77,7 +152,8 @@ read_and (void (*do_something) (void))
prev_status = status;
tar_stat_destroy (&current_stat_info);
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
switch (status)
{
case HEADER_STILL_UNREAD:
@@ -88,7 +164,8 @@ read_and (void (*do_something) (void))
/* Valid header. We should decode next field (mode) first.
Ensure incoming names are null terminated. */
decode_header (current_header, &current_stat_info,
&current_format, 1);
if (! name_match (current_stat_info.file_name)
|| (NEWER_OPTION_INITIALIZED (newer_mtime_option)
/* FIXME: We get mtime now, and again later; this causes
@@ -114,13 +191,12 @@ 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;
}
}
transform_stat_info (current_header->header.typeflag,
&current_stat_info);
(*do_something) ();
continue;
@@ -138,11 +214,13 @@ read_and (void (*do_something) (void))
{
char buf[UINTMAX_STRSIZE_BOUND];
status = read_header (false);
status = read_header (&current_header, &current_stat_info,
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
WARN ((0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
WARNOPT (WARN_ALONE_ZERO_BLOCK,
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
break;
}
status = prev_status;
@@ -204,11 +282,10 @@ void
list_archive (void)
{
off_t block_ordinal = current_block_ordinal ();
/* Print the header block. */
decode_header (current_header, &current_stat_info, &current_format, 0);
/* Print the header block. */
if (verbose_option)
print_header (&current_stat_info, block_ordinal);
print_header (&current_stat_info, current_header, block_ordinal);
if (incremental_option)
{
@@ -279,20 +356,29 @@ tar_checksum (union block *header, bool silent)
}
/* Read a block that's supposed to be a header block. Return its
address in "current_header", and if it is good, the file's size
and names (file name, link name) in *info.
address in *RETURN_BLOCK, and if it is good, the file's size
and names (file name, link name) in *INFO.
Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
block full of zeros (EOF marker).
Return one of enum read_header describing the status of the
operation.
If RAW_EXTENDED_HEADERS is nonzero, do not automagically fold the
GNU long name and link headers into later headers.
The MODE parameter instructs read_header what to do with special
header blocks, i.e.: extended POSIX, GNU long name or long link,
etc.:
You must always set_next_block_after(current_header) to skip past
read_header_auto process them automatically,
read_header_x_raw when a special header is read, return
HEADER_SUCCESS_EXTENDED without actually
processing the header,
read_header_x_global when a POSIX global header is read,
decode it and return HEADER_SUCCESS_EXTENDED.
You must always set_next_block_after(*return_block) to skip past
the header which this routine reads. */
enum read_header
read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
read_header (union block **return_block, struct tar_stat_info *info,
enum read_header_mode mode)
{
union block *header;
union block *header_copy;
@@ -309,7 +395,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
enum read_header status;
header = find_next_block ();
current_header = header;
*return_block = header;
if (!header)
return HEADER_END_OF_FILE;
@@ -329,7 +415,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|| header->header.typeflag == XGLTYPE
|| header->header.typeflag == SOLARIS_XHDTYPE)
{
if (raw_extended_headers)
if (mode == read_header_x_raw)
return HEADER_SUCCESS_EXTENDED;
else if (header->header.typeflag == GNUTYPE_LONGNAME
|| header->header.typeflag == GNUTYPE_LONGLINK)
@@ -391,11 +477,18 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
else if (header->header.typeflag == XGLTYPE)
{
struct xheader xhdr;
if (!recent_global_header)
recent_global_header = xmalloc (sizeof *recent_global_header);
memcpy (recent_global_header, header,
sizeof *recent_global_header);
memset (&xhdr, 0, sizeof xhdr);
xheader_read (&xhdr, header,
OFF_FROM_HEADER (header->header.size));
xheader_decode_global (&xhdr);
xheader_destroy (&xhdr);
if (mode == read_header_x_global)
return HEADER_SUCCESS_EXTENDED;
}
/* Loop! */
@@ -404,7 +497,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
else
{
char const *name;
struct posix_header const *h = &current_header->header;
struct posix_header const *h = &header->header;
char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
if (recent_long_name)
@@ -463,53 +556,6 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
}
}
enum read_header
read_header (bool raw_extended_headers)
{
return read_header_primitive (raw_extended_headers, &current_stat_info);
}
static char *
decode_xform (char *file_name, void *data)
{
int type = *(int*)data;
switch (type)
{
case XFORM_SYMLINK:
/* FIXME: It is not quite clear how and to which extent are the symbolic
links subject to filename transformation. In the absence of another
solution, symbolic links are exempt from component stripping and
name suffix normalization, but subject to filename transformation
proper. */
return file_name;
case XFORM_LINK:
file_name = safer_name_suffix (file_name, true, absolute_names_option);
break;
case XFORM_REGFILE:
file_name = safer_name_suffix (file_name, false, absolute_names_option);
break;
}
if (strip_name_components)
{
size_t prefix_len = stripped_prefix_len (file_name,
strip_name_components);
if (prefix_len == (size_t) -1)
prefix_len = strlen (file_name);
file_name += prefix_len;
}
return file_name;
}
bool
transform_member_name (char **pinput, int type)
{
return transform_name_fp (pinput, type, decode_xform, &type);
}
#define ISOCTAL(c) ((c)>='0'&&(c)<='7')
/* Decode things from a file HEADER block into STAT_INFO, also setting
@@ -530,6 +576,8 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
enum archive_format *format_pointer, int do_user_group)
{
enum archive_format format;
unsigned hbits; /* high bits of the file mode. */
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
if (strcmp (header->header.magic, TMAGIC) == 0)
{
@@ -544,13 +592,15 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
else
format = USTAR_FORMAT;
}
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
format = OLDGNU_FORMAT;
else if (strcmp (header->buffer + offsetof (struct posix_header, magic),
OLDGNU_MAGIC)
== 0)
format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
else
format = V7_FORMAT;
*format_pointer = format;
stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode);
stat_info->stat.st_mode = mode;
stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
stat_info->mtime.tv_nsec = 0;
assign_string (&stat_info->uname,
@@ -627,19 +677,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|| stat_info->dumpdir)
stat_info->is_dumpdir = true;
}
transform_member_name (&stat_info->file_name, XFORM_REGFILE);
switch (header->header.typeflag)
{
case SYMTYPE:
transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
break;
case LNKTYPE:
transform_member_name (&stat_info->link_name, XFORM_LINK);
}
}
/* Convert buffer at WHERE0 of size DIGS from external format to
uintmax_t. DIGS must be positive. If TYPE is nonnull, the data
are of type TYPE. The buffer must represent a value in the range
@@ -667,7 +707,8 @@ from_header (char const *where0, size_t digs, char const *type,
{
if (type && !silent)
ERROR ((0, 0,
/* TRANSLATORS: %s is type of the value (gid_t, uid_t, etc.) */
/* TRANSLATORS: %s is type of the value (gid_t, uid_t,
etc.) */
_("Blanks in header where numeric %s value expected"),
type));
return -1;
@@ -859,7 +900,7 @@ from_header (char const *where0, size_t digs, char const *type,
return -1;
}
gid_t
static gid_t
gid_from_header (const char *p, size_t s)
{
return from_header (p, s, "gid_t",
@@ -868,7 +909,7 @@ gid_from_header (const char *p, size_t s)
false, false);
}
major_t
static major_t
major_from_header (const char *p, size_t s)
{
return from_header (p, s, "major_t",
@@ -876,7 +917,7 @@ major_from_header (const char *p, size_t s)
(uintmax_t) TYPE_MAXIMUM (major_t), false, false);
}
minor_t
static minor_t
minor_from_header (const char *p, size_t s)
{
return from_header (p, s, "minor_t",
@@ -884,25 +925,28 @@ minor_from_header (const char *p, size_t s)
(uintmax_t) TYPE_MAXIMUM (minor_t), false, false);
}
mode_t
mode_from_header (const char *p, size_t s)
/* Convert P to the file mode, as understood by tar.
Store unrecognized mode bits (from 10th up) in HBITS. */
static mode_t
mode_from_header (const char *p, size_t s, unsigned *hbits)
{
/* Do not complain about unrecognized mode bits. */
unsigned u = from_header (p, s, "mode_t",
- (uintmax_t) TYPE_MINIMUM (mode_t),
TYPE_MAXIMUM (uintmax_t), false, false);
return ((u & TSUID ? S_ISUID : 0)
| (u & TSGID ? S_ISGID : 0)
| (u & TSVTX ? S_ISVTX : 0)
| (u & TUREAD ? S_IRUSR : 0)
| (u & TUWRITE ? S_IWUSR : 0)
| (u & TUEXEC ? S_IXUSR : 0)
| (u & TGREAD ? S_IRGRP : 0)
| (u & TGWRITE ? S_IWGRP : 0)
| (u & TGEXEC ? S_IXGRP : 0)
| (u & TOREAD ? S_IROTH : 0)
| (u & TOWRITE ? S_IWOTH : 0)
| (u & TOEXEC ? S_IXOTH : 0));
mode_t mode = ((u & TSUID ? S_ISUID : 0)
| (u & TSGID ? S_ISGID : 0)
| (u & TSVTX ? S_ISVTX : 0)
| (u & TUREAD ? S_IRUSR : 0)
| (u & TUWRITE ? S_IWUSR : 0)
| (u & TUEXEC ? S_IXUSR : 0)
| (u & TGREAD ? S_IRGRP : 0)
| (u & TGWRITE ? S_IWGRP : 0)
| (u & TGEXEC ? S_IXGRP : 0)
| (u & TOREAD ? S_IROTH : 0)
| (u & TOWRITE ? S_IWOTH : 0)
| (u & TOEXEC ? S_IXOTH : 0));
*hbits = mode ^ u;
return mode;
}
off_t
@@ -914,14 +958,7 @@ off_from_header (const char *p, size_t s)
(uintmax_t) TYPE_MAXIMUM (off_t), false, false);
}
size_t
size_from_header (const char *p, size_t s)
{
return from_header (p, s, "size_t", (uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (size_t), false, false);
}
time_t
static time_t
time_from_header (const char *p, size_t s)
{
return from_header (p, s, "time_t",
@@ -929,7 +966,7 @@ time_from_header (const char *p, size_t s)
(uintmax_t) TYPE_MAXIMUM (time_t), false, false);
}
uid_t
static uid_t
uid_from_header (const char *p, size_t s)
{
return from_header (p, s, "uid_t",
@@ -1013,9 +1050,6 @@ tartime (struct timespec t, bool full_time)
they shouldn't. Unix tar is pretty random here anyway. */
/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
HEAD_STANDARD, which must be set up in advance. Not very clean.. */
/* Width of "user/group size", with initial value chosen
heuristically. This grows as needed, though this may cause some
stairstepping in the output. Make it too small and the output will
@@ -1028,8 +1062,11 @@ static int ugswidth = 19;
USGWIDTH, some stairstepping may occur. */
static int datewidth = sizeof "YYYY-MM-DD HH:MM" - 1;
void
print_header (struct tar_stat_info *st, off_t block_ordinal)
static bool volume_label_printed = false;
static void
simple_print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal)
{
char modes[11];
char const *time_stamp;
@@ -1045,9 +1082,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
int pad;
int sizelen;
if (test_label_option && current_header->header.typeflag != GNUTYPE_VOLHDR)
return;
if (show_transformed_names_option)
temp_name = st->file_name ? st->file_name : st->orig_file_name;
else
@@ -1074,9 +1108,10 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* File type and modes. */
modes[0] = '?';
switch (current_header->header.typeflag)
switch (blk->header.typeflag)
{
case GNUTYPE_VOLHDR:
volume_label_printed = true;
modes[0] = 'V';
break;
@@ -1127,7 +1162,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Time stamp. */
time_stamp = tartime (st->mtime, false);
time_stamp = tartime (st->mtime, full_time_option);
time_stamp_len = strlen (time_stamp);
if (datewidth < time_stamp_len)
datewidth = time_stamp_len;
@@ -1144,8 +1179,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Try parsing it as an unsigned integer first, and as a
uid_t if that fails. This method can list positive user
ids that are too large to fit in a uid_t. */
uintmax_t u = from_header (current_header->header.uid,
sizeof current_header->header.uid, 0,
uintmax_t u = from_header (blk->header.uid,
sizeof blk->header.uid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
false, false);
@@ -1154,7 +1189,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
else
{
sprintf (uform, "%ld",
(long) UID_FROM_HEADER (current_header->header.uid));
(long) UID_FROM_HEADER (blk->header.uid));
user = uform;
}
}
@@ -1169,8 +1204,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Try parsing it as an unsigned integer first, and as a
gid_t if that fails. This method can list positive group
ids that are too large to fit in a gid_t. */
uintmax_t g = from_header (current_header->header.gid,
sizeof current_header->header.gid, 0,
uintmax_t g = from_header (blk->header.gid,
sizeof blk->header.gid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
false, false);
@@ -1179,14 +1214,14 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
else
{
sprintf (gform, "%ld",
(long) GID_FROM_HEADER (current_header->header.gid));
(long) GID_FROM_HEADER (blk->header.gid));
group = gform;
}
}
/* Format the file size or major/minor device numbers. */
switch (current_header->header.typeflag)
switch (blk->header.typeflag)
{
case CHRTYPE:
case BLKTYPE:
@@ -1216,7 +1251,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
fprintf (stdlis, " %s", quotearg (temp_name));
switch (current_header->header.typeflag)
switch (blk->header.typeflag)
{
case SYMTYPE:
fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
@@ -1229,7 +1264,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
default:
{
char type_string[2];
type_string[0] = current_header->header.typeflag;
type_string[0] = blk->header.typeflag;
type_string[1] = '\0';
fprintf (stdlis, _(" unknown file type %s\n"),
quote (type_string));
@@ -1263,7 +1298,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
case GNUTYPE_MULTIVOL:
strcpy (size,
STRINGIFY_BIGINT
(UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset),
(UINTMAX_FROM_HEADER (blk->oldgnu_header.offset),
uintbuf));
fprintf (stdlis, _("--Continued at byte %s--\n"), size);
break;
@@ -1272,6 +1307,40 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
fflush (stdlis);
}
static void
print_volume_label (void)
{
struct tar_stat_info vstat;
union block vblk;
enum archive_format dummy;
memset (&vblk, 0, sizeof (vblk));
vblk.header.typeflag = GNUTYPE_VOLHDR;
if (recent_global_header)
memcpy (vblk.header.mtime, recent_global_header->header.mtime,
sizeof vblk.header.mtime);
tar_stat_init (&vstat);
assign_string (&vstat.file_name, ".");
decode_header (&vblk, &vstat, &dummy, 0);
assign_string (&vstat.file_name, volume_label);
simple_print_header (&vstat, &vblk, 0);
tar_stat_destroy (&vstat);
}
void
print_header (struct tar_stat_info *st, union block *blk,
off_t block_ordinal)
{
if (current_format == POSIX_FORMAT && !volume_label_printed && volume_label)
{
print_volume_label ();
volume_label_printed = true;
}
simple_print_header (st, blk, block_ordinal);
}
/* Print a similar line when we make a directory automatically. */
void
print_for_mkdir (char *dirname, int length, mode_t mode)
@@ -1303,7 +1372,7 @@ skip_file (off_t size)
{
union block *x;
/* FIXME: Make sure mv_begin is always called before it */
/* FIXME: Make sure mv_begin_read is always called before it */
if (seekable_archive)
{
@@ -1338,7 +1407,7 @@ skip_member (void)
char save_typeflag = current_header->header.typeflag;
set_next_block_after (current_header);
mv_begin (&current_stat_info);
mv_begin_read (&current_stat_info);
if (current_stat_info.is_sparse)
sparse_skip_file (&current_stat_info);
@@ -1348,3 +1417,34 @@ skip_member (void)
mv_end ();
}
}
void
test_archive_label ()
{
base64_init ();
name_gather ();
open_archive (ACCESS_READ);
if (read_header (&current_header, &current_stat_info, read_header_auto)
== HEADER_SUCCESS)
{
decode_header (current_header,
&current_stat_info, &current_format, 0);
if (current_header->header.typeflag == GNUTYPE_VOLHDR)
assign_string (&volume_label, current_header->header.name);
if (volume_label)
{
if (verbose_option)
print_volume_label ();
if (!name_match (volume_label) && multi_volume_option)
{
char *s = drop_volume_label_suffix (volume_label);
name_match (s);
free (s);
}
}
}
close_archive ();
label_notfound ();
}

View File

@@ -1,57 +0,0 @@
# Makefile for GNU tar on MS-DOS using Turbo C 2.0.
# Copyright (C) 1991 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., 675 Mass Ave, Cambridge, MA 02139, USA.
CC = tcc
RM = rm -f
MODEL = m
DEFS = -DNONAMES -DNO_REMOTE -DNO_MTIO -DSTDC_HEADERS -m$(MODEL) -Dmain=_main
LIBS =
DEF_AR_FILE = tar.out
DEFBLOCKING = 20
CFLAGS = -I. $(DEFS) \
-DDEF_AR_FILE="$(DEF_AR_FILE)" \
-DDEFBLOCKING=$(DEFBLOCKING)
LDFLAGS = -m$(MODEL)
OBJ1 = tar.obj create.obj extract.obj buffer.obj getoldopt.obj update.obj gnu.obj mangle.obj
OBJ2 = version.obj list.obj names.obj diffarch.obj port.obj wildmat.obj getopt.obj
OBJ3 = getopt1.obj regex.obj getdate.obj alloca.obj tcexparg.obj msd_dir.obj
OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
all: tar
tar: testpad.h getdate.c $(OBJS)
$(RM) testpad.obj
$(CC) $(LDFLAGS) -etar *.obj $(LIBS)
.c.obj:
$(CC) -c $(CFLAGS) $<
testpad.h: testpad.exe
testpad
testpad.exe: testpad.c
$(CC) $(LDFLAGS) -etestpad testpad.c $(LIBS)
clean:
$(RM) errs *.obj tar testpad testpad.h
distclean: clean
realclean: clean

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, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007, 2009, 2010 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
@@ -21,16 +21,12 @@
#include <rmt.h>
#include "common.h"
#include <quotearg.h>
#include <save-cwd.h>
#include <xgetcwd.h>
#include <unlinkdir.h>
#include <utimens.h>
#if HAVE_STROPTS_H
# include <stropts.h>
#endif
#if HAVE_SYS_FILIO_H
# include <sys/filio.h>
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
#endif
@@ -46,6 +42,9 @@ assign_string (char **string, const char *value)
*string = value ? xstrdup (value) : 0;
}
#if 0
/* This function is currently unused; perhaps it should be removed? */
/* Allocate a copy of the string quoted as in C, and returns that. If
the string does not have to be quoted, it returns a null pointer.
The allocated copy should normally be freed with free() after the
@@ -58,7 +57,7 @@ assign_string (char **string, const char *value)
when reading directory files. This means that we can't use
quotearg, as quotearg is locale-dependent and is meant for human
consumption. */
char *
static char *
quote_copy_string (const char *string)
{
const char *source = string;
@@ -99,6 +98,7 @@ quote_copy_string (const char *string)
}
return 0;
}
#endif
/* Takes a quoted C string (like those produced by quote_copy_string)
and turns it back into the un-quoted original. This is done in
@@ -214,6 +214,115 @@ unquote_string (char *string)
*destination = '\0';
return result;
}
/* Zap trailing slashes. */
char *
zap_slashes (char *name)
{
char *q;
if (!name || *name == 0)
return name;
q = name + strlen (name) - 1;
while (q > name && ISSLASH (*q))
*q-- = '\0';
return name;
}
/* Normalize FILE_NAME by removing redundant slashes and "."
components, including redundant trailing slashes. Leave ".."
alone, as it may be significant in the presence of symlinks and on
platforms where "/.." != "/". Destructive version: modifies its
argument. */
static void
normalize_filename_x (char *file_name)
{
char *name = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
char *p;
char const *q;
char c;
/* Don't squeeze leading "//" to "/", on hosts where they're distinct. */
name += (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& ISSLASH (*name) && ISSLASH (name[1]) && ! ISSLASH (name[2]));
/* Omit redundant leading "." components. */
for (q = p = name; (*p = *q) == '.' && ISSLASH (q[1]); p += !*q)
for (q += 2; ISSLASH (*q); q++)
continue;
/* Copy components from Q to P, omitting redundant slashes and
internal "." components. */
while ((*p++ = c = *q++) != '\0')
if (ISSLASH (c))
while (ISSLASH (q[*q == '.']))
q += (*q == '.') + 1;
/* Omit redundant trailing "." component and slash. */
if (2 < p - name)
{
p -= p[-2] == '.' && ISSLASH (p[-3]);
p -= 2 < p - name && ISSLASH (p[-2]);
p[-1] = '\0';
}
}
/* Normalize NAME by removing redundant slashes and "." components,
including redundant trailing slashes. Return a normalized
newly-allocated copy. */
char *
normalize_filename (const char *name)
{
char *copy = NULL;
if (IS_RELATIVE_FILE_NAME (name))
{
/* Set COPY to the absolute file name if possible.
FIXME: There should be no need to get the absolute file name.
getcwd is slow, it might fail, and it does not necessarily
return a canonical name even when it succeeds. Perhaps we
can use dev+ino pairs instead of names? */
copy = xgetcwd ();
if (copy)
{
size_t copylen = strlen (copy);
bool need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& copylen == 2 && ISSLASH (copy[1]));
copy = xrealloc (copy, copylen + need_separator + strlen (name) + 1);
copy[copylen] = DIRECTORY_SEPARATOR;
strcpy (copy + copylen + need_separator, name);
}
else
WARN ((0, errno, _("Cannot get working directory")));
}
if (! copy)
copy = xstrdup (name);
normalize_filename_x (copy);
return copy;
}
void
replace_prefix (char **pname, const char *samp, size_t slen,
const char *repl, size_t rlen)
{
char *name = *pname;
size_t nlen = strlen (name);
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
{
if (rlen > slen)
{
name = xrealloc (name, nlen - slen + rlen + 1);
*pname = name;
}
memmove (name + rlen, name + slen, nlen - slen + 1);
memcpy (name, repl, rlen);
}
}
/* Handling numbers. */
@@ -257,6 +366,10 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
char *np;
bool negative = s < 0;
/* ignore invalid values of ns */
if (BILLION <= ns || ns < 0)
ns = 0;
if (negative && ns != 0)
{
s++;
@@ -277,7 +390,7 @@ static char *before_backup_name;
static char *after_backup_name;
/* Return 1 if FILE_NAME is obviously "." or "/". */
static bool
bool
must_be_dot_or_slash (char const *file_name)
{
file_name += FILE_SYSTEM_PREFIX_LEN (file_name);
@@ -318,7 +431,7 @@ safer_rmdir (const char *file_name)
return -1;
}
return rmdir (file_name);
return unlinkat (chdir_fd, file_name, AT_REMOVEDIR);
}
/* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory,
@@ -338,7 +451,7 @@ remove_any_file (const char *file_name, enum remove_option option)
if (try_unlink_first)
{
if (unlink (file_name) == 0)
if (unlinkat (chdir_fd, file_name, 0) == 0)
return 1;
/* POSIX 1003.1-2001 requires EPERM when attempting to unlink a
@@ -354,7 +467,7 @@ remove_any_file (const char *file_name, enum remove_option option)
switch (errno)
{
case ENOTDIR:
return !try_unlink_first && unlink (file_name) == 0;
return !try_unlink_first && unlinkat (chdir_fd, file_name, 0) == 0;
case 0:
case EEXIST:
@@ -417,12 +530,21 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
{
struct stat file_stat;
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
possible, real problems are unlikely. Doing any better would require a
convention, GNU-wide, for all programs doing backups. */
assign_string (&after_backup_name, 0);
/* Check if we really need to backup the file. */
if (this_is_the_archive && _remdev (file_name))
return true;
if (stat (file_name, &file_stat))
if (deref_stat (file_name, &file_stat) != 0)
{
if (errno == ENOENT)
return true;
@@ -438,19 +560,12 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
return true;
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
possible, real problems are unlikely. Doing any better would require a
convention, GNU-wide, for all programs doing backups. */
assign_string (&after_backup_name, 0);
after_backup_name = find_backup_file_name (file_name, backup_type);
if (! after_backup_name)
xalloc_die ();
if (rename (before_backup_name, after_backup_name) == 0)
if (renameat (chdir_fd, before_backup_name, chdir_fd, after_backup_name)
== 0)
{
if (verbose_option)
fprintf (stdlis, _("Renaming %s to %s\n"),
@@ -477,7 +592,8 @@ undo_last_backup (void)
{
if (after_backup_name)
{
if (rename (after_backup_name, before_backup_name) != 0)
if (renameat (chdir_fd, after_backup_name, chdir_fd, before_backup_name)
!= 0)
{
int e = errno;
ERROR ((0, e, _("%s: Cannot rename to %s"),
@@ -492,56 +608,74 @@ undo_last_backup (void)
}
}
/* Depending on DEREF, apply either stat or lstat to (NAME, BUF). */
/* Apply either stat or lstat to (NAME, BUF), depending on the
presence of the --dereference option. NAME is relative to the
most-recent argument to chdir_do. */
int
deref_stat (bool deref, char const *name, struct stat *buf)
deref_stat (char const *name, struct stat *buf)
{
return deref ? stat (name, buf) : lstat (name, buf);
return fstatat (chdir_fd, name, buf, fstatat_flags);
}
/* Set FD's (i.e., FILE's) access time to TIMESPEC[0]. If that's not
possible to do by itself, set its access and data modification
times to TIMESPEC[0] and TIMESPEC[1], respectively. */
/* Set FD's (i.e., assuming the working directory is PARENTFD, FILE's)
access time to ATIME. */
int
set_file_atime (int fd, char const *file, struct timespec const timespec[2])
set_file_atime (int fd, int parentfd, char const *file, struct timespec atime)
{
#ifdef _FIOSATIME
if (0 <= fd)
{
struct timeval timeval;
timeval.tv_sec = timespec[0].tv_sec;
timeval.tv_usec = timespec[0].tv_nsec / 1000;
if (ioctl (fd, _FIOSATIME, &timeval) == 0)
return 0;
}
#endif
return gl_futimens (fd, file, timespec);
struct timespec ts[2];
ts[0] = atime;
ts[1].tv_nsec = UTIME_OMIT;
return fdutimensat (fd, parentfd, file, ts, fstatat_flags);
}
/* A description of a working directory. */
struct wd
{
/* The directory's name. */
char const *name;
int saved;
struct saved_cwd saved_cwd;
/* If nonzero, the file descriptor of the directory, or AT_FDCWD if
the working directory. If zero, the directory needs to be opened
to be used. */
int fd;
};
/* A vector of chdir targets. wd[0] is the initial working directory. */
static struct wd *wd;
/* The number of working directories in the vector. */
static size_t wds;
static size_t wd_count;
/* The allocated size of the vector. */
static size_t wd_alloc;
/* The maximum number of chdir targets with open directories.
Don't make it too large, as many operating systems have a small
limit on the number of open file descriptors. Also, the current
implementation does not scale well. */
enum { CHDIR_CACHE_SIZE = 16 };
/* Indexes into WD of chdir targets with open file descriptors, sorted
most-recently used first. Zero indexes are unused. */
static int wdcache[CHDIR_CACHE_SIZE];
/* Number of nonzero entries in WDCACHE. */
static size_t wdcache_count;
int
chdir_count ()
{
if (wd_count == 0)
return wd_count;
return wd_count - 1;
}
/* DIR is the operand of a -C option; add it to vector of chdir targets,
and return the index of its location. */
int
chdir_arg (char const *dir)
{
if (wds == wd_alloc)
if (wd_count == wd_alloc)
{
if (wd_alloc == 0)
{
@@ -551,11 +685,11 @@ chdir_arg (char const *dir)
else
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
if (! wds)
if (! wd_count)
{
wd[wds].name = ".";
wd[wds].saved = 0;
wds++;
wd[wd_count].name = ".";
wd[wd_count].fd = AT_FDCWD;
wd_count++;
}
}
@@ -567,68 +701,80 @@ chdir_arg (char const *dir)
for (dir += 2; ISSLASH (*dir); dir++)
continue;
if (! dir[dir[0] == '.'])
return wds - 1;
return wd_count - 1;
}
wd[wds].name = dir;
wd[wds].saved = 0;
return wds++;
wd[wd_count].name = dir;
wd[wd_count].fd = 0;
return wd_count++;
}
/* Change to directory I. If I is 0, change to the initial working
directory; otherwise, I must be a value returned by chdir_arg. */
/* Index of current directory. */
int chdir_current;
/* Value suitable for use as the first argument to openat, and in
similar locations for fstatat, etc. This is an open file
descriptor, or AT_FDCWD if the working directory is current. It is
valid until the next invocation of chdir_do. */
int chdir_fd = AT_FDCWD;
/* Change to directory I, in a virtual way. This does not actually
invoke chdir; it merely sets chdir_fd to an int suitable as the
first argument for openat, etc. If I is 0, change to the initial
working directory; otherwise, I must be a value returned by
chdir_arg. */
void
chdir_do (int i)
{
static int previous;
if (previous != i)
if (chdir_current != i)
{
struct wd *prev = &wd[previous];
struct wd *curr = &wd[i];
int fd = curr->fd;
if (! prev->saved)
if (! fd)
{
int err = 0;
prev->saved = 1;
if (save_cwd (&prev->saved_cwd) != 0)
err = errno;
else if (0 <= prev->saved_cwd.desc)
{
/* Make sure we still have at least one descriptor available. */
int fd1 = prev->saved_cwd.desc;
int fd2 = dup (fd1);
if (0 <= fd2)
close (fd2);
else if (errno == EMFILE)
{
/* Force restore_cwd to use chdir_long. */
close (fd1);
prev->saved_cwd.desc = -1;
prev->saved_cwd.name = xgetcwd ();
}
else
err = errno;
}
if (err)
FATAL_ERROR ((0, err, _("Cannot save working directory")));
}
if (curr->saved)
{
if (restore_cwd (&curr->saved_cwd))
FATAL_ERROR ((0, 0, _("Cannot change working directory")));
}
else
{
if (i && ! ISSLASH (curr->name[0]))
if (! IS_ABSOLUTE_FILE_NAME (curr->name))
chdir_do (i - 1);
if (chdir (curr->name) != 0)
chdir_fatal (curr->name);
fd = openat (chdir_fd, curr->name,
open_searchdir_flags & ~ O_NOFOLLOW);
if (fd < 0)
open_fatal (curr->name);
curr->fd = fd;
/* Add I to the cache, tossing out the lowest-ranking entry if the
cache is full. */
if (wdcache_count < CHDIR_CACHE_SIZE)
wdcache[wdcache_count++] = i;
else
{
struct wd *stale = &wd[wdcache[CHDIR_CACHE_SIZE - 1]];
if (close (stale->fd) != 0)
close_diag (stale->name);
stale->fd = 0;
wdcache[CHDIR_CACHE_SIZE - 1] = i;
}
}
previous = i;
if (0 < fd)
{
/* Move the i value to the front of the cache. This is
O(CHDIR_CACHE_SIZE), but the cache is small. */
size_t ci;
int prev = wdcache[0];
for (ci = 1; prev != i; ci++)
{
int curr = wdcache[ci];
wdcache[ci] = prev;
if (curr == i)
break;
prev = curr;
}
wdcache[0] = i;
}
chdir_current = i;
chdir_fd = fd;
}
}
@@ -695,6 +841,36 @@ stat_diag (char const *name)
stat_error (name);
}
void
file_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name))
{
if (!top_level && errno == ENOENT)
{
WARNOPT (WARN_FILE_REMOVED,
(0, 0, _("%s: File removed before we read it"),
quotearg_colon (name)));
set_exit_status (TAREXIT_DIFFERS);
}
else
diagfn (name);
}
void
dir_removed_diag (const char *name, bool top_level,
void (*diagfn) (char const *name))
{
if (!top_level && errno == ENOENT)
{
WARNOPT (WARN_FILE_REMOVED,
(0, 0, _("%s: Directory removed before we read it"),
quotearg_colon (name)));
set_exit_status (TAREXIT_DIFFERS);
}
else
diagfn (name);
}
void
write_fatal_details (char const *name, ssize_t status, size_t size)
{
@@ -746,3 +922,42 @@ page_aligned_alloc (void **ptr, size_t size)
*ptr = xmalloc (size1);
return ptr_align (*ptr, alignment);
}
struct namebuf
{
char *buffer; /* directory, `/', and directory member */
size_t buffer_size; /* allocated size of name_buffer */
size_t dir_length; /* length of directory part in buffer */
};
namebuf_t
namebuf_create (const char *dir)
{
namebuf_t buf = xmalloc (sizeof (*buf));
buf->buffer_size = strlen (dir) + 2;
buf->buffer = xmalloc (buf->buffer_size);
strcpy (buf->buffer, dir);
buf->dir_length = strlen (buf->buffer);
if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
buf->buffer[buf->dir_length++] = DIRECTORY_SEPARATOR;
return buf;
}
void
namebuf_free (namebuf_t buf)
{
free (buf->buffer);
free (buf);
}
char *
namebuf_name (namebuf_t buf, const char *name)
{
size_t len = strlen (name);
while (buf->dir_length + len + 1 >= buf->buffer_size)
buf->buffer = x2realloc (buf->buffer, &buf->buffer_size);
strcpy (buf->buffer + buf->dir_length, name);
return buf->buffer;
}

View File

@@ -1,218 +0,0 @@
/*
* @(#)msd_dir.c 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*/
#include <sys/types.h>
#include <sys/stat.h>
#include "msd_dir.h"
#ifndef __TURBOC__
#include <malloc.h>
#endif
#include <string.h>
#include <dos.h>
#ifndef NULL
# define NULL 0
#endif /* NULL */
#ifndef MAXPATHLEN
# define MAXPATHLEN 255
#endif /* MAXPATHLEN */
/* attribute stuff */
#define A_RONLY 0x01
#define A_HIDDEN 0x02
#define A_SYSTEM 0x04
#define A_LABEL 0x08
#define A_DIR 0x10
#define A_ARCHIVE 0x20
/* dos call values */
#define DOSI_FINDF 0x4e
#define DOSI_FINDN 0x4f
#define DOSI_SDTA 0x1a
#define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
/* #define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM) */
#define ATTRIBUTES (A_RONLY | A_SYSTEM | A_DIR)
/* what find first/next calls look use */
typedef struct {
char d_buf[21];
char d_attribute;
unsigned short d_time;
unsigned short d_date;
long d_size;
char d_name[13];
} Dta_buf;
static char *getdirent();
static void mysetdta();
static void free_dircontents();
static Dta_buf dtabuf;
static Dta_buf *dtapnt = &dtabuf;
static union REGS reg, nreg;
#if defined(M_I86LM)
static struct SREGS sreg;
#endif
DIR *
opendir(name)
char *name;
{
struct stat statb;
DIR *dirp;
char c;
char *s;
struct _dircontents *dp;
char nbuf[MAXPATHLEN + 1];
if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
return (DIR *) NULL;
if (Newisnull(dirp, DIR))
return (DIR *) NULL;
if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
(void) strcat(strcpy(nbuf, name), "\\*.*");
else
(void) strcat(strcpy(nbuf, name), "*.*");
dirp->dd_loc = 0;
mysetdta();
dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
if ((s = getdirent(nbuf)) == (char *) NULL)
return dirp;
do {
if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
{
if (dp)
free((char *) dp);
free_dircontents(dirp->dd_contents);
return (DIR *) NULL;
}
if (dirp->dd_contents)
dirp->dd_cp = dirp->dd_cp->_d_next = dp;
else
dirp->dd_contents = dirp->dd_cp = dp;
(void) strcpy(dp->_d_entry, s);
dp->_d_next = (struct _dircontents *) NULL;
} while ((s = getdirent((char *) NULL)) != (char *) NULL);
dirp->dd_cp = dirp->dd_contents;
return dirp;
}
void
closedir(dirp)
DIR *dirp;
{
free_dircontents(dirp->dd_contents);
free((char *) dirp);
}
struct dirent *
readdir(dirp)
DIR *dirp;
{
static struct dirent dp;
if (dirp->dd_cp == (struct _dircontents *) NULL)
return (struct dirent *) NULL;
dp.d_namlen = dp.d_reclen =
strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
strlwr(dp.d_name); /* JF */
dp.d_ino = 0;
dirp->dd_cp = dirp->dd_cp->_d_next;
dirp->dd_loc++;
return &dp;
}
void
seekdir(dirp, off)
DIR *dirp;
long off;
{
long i = off;
struct _dircontents *dp;
if (off < 0)
return;
for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
;
dirp->dd_loc = off - (i + 1);
dirp->dd_cp = dp;
}
long
telldir(dirp)
DIR *dirp;
{
return dirp->dd_loc;
}
static void
free_dircontents(dp)
struct _dircontents *dp;
{
struct _dircontents *odp;
while (dp) {
if (dp->_d_entry)
free(dp->_d_entry);
dp = (odp = dp)->_d_next;
free((char *) odp);
}
}
static char *
getdirent(dir)
char *dir;
{
if (dir != (char *) NULL) { /* get first entry */
reg.h.ah = DOSI_FINDF;
reg.h.cl = ATTRIBUTES;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dir);
sreg.ds = FP_SEG(dir);
#else
reg.x.dx = (unsigned) dir;
#endif
} else { /* get next entry */
reg.h.ah = DOSI_FINDN;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dtapnt);
sreg.ds = FP_SEG(dtapnt);
#else
reg.x.dx = (unsigned) dtapnt;
#endif
}
#if defined(M_I86LM)
intdosx(&reg, &nreg, &sreg);
#else
intdos(&reg, &nreg);
#endif
if (nreg.x.cflag)
return (char *) NULL;
return dtabuf.d_name;
}
static void
mysetdta()
{
reg.h.ah = DOSI_SDTA;
#if defined(M_I86LM)
reg.x.dx = FP_OFF(dtapnt);
sreg.ds = FP_SEG(dtapnt);
intdosx(&reg, &nreg, &sreg);
#else
reg.x.dx = (int) dtapnt;
intdos(&reg, &nreg);
#endif
}

View File

@@ -1,41 +0,0 @@
/*
* @(#)msd_dir.h 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*/
#define rewinddir(dirp) seekdir(dirp, 0L)
#define MAXNAMLEN 12
#ifdef __TURBOC__
typedef int ino_t;
typedef int dev_t;
#endif
struct direct {
ino_t d_ino; /* a bit of a farce */
int d_reclen; /* more farce */
int d_namlen; /* length of d_name */
char d_name[MAXNAMLEN + 1]; /* garentee null termination */
};
struct _dircontents {
char *_d_entry;
struct _dircontents *_d_next;
};
typedef struct _dirdesc {
int dd_id; /* uniquely identify each open directory */
long dd_loc; /* where we are in directory entry is this */
struct _dircontents *dd_contents; /* pointer to contents of dir */
struct _dircontents *dd_cp; /* pointer to current position */
} DIR;
extern DIR *opendir();
extern struct direct *readdir();
extern void seekdir();
extern long telldir();
extern void closedir();

View File

@@ -1,7 +1,7 @@
/* Various processing of names.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
2003, 2004, 2005, 2006, 2007, 2009 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
@@ -27,15 +27,6 @@
/* User and group names. */
struct group *getgrnam ();
struct passwd *getpwnam ();
#if ! HAVE_DECL_GETPWUID
struct passwd *getpwuid ();
#endif
#if ! HAVE_DECL_GETGRGID
struct group *getgrgid ();
#endif
/* Make sure you link with the proper libraries if you are running the
Yellow Peril (thanks for the good laugh, Ian J.!), or, euh... NIS.
This code should also be modified for non-UNIX systems to do something
@@ -178,13 +169,36 @@ gname_to_gid (char const *gname, gid_t *gidp)
return 1;
}
static struct name *
make_name (const char *file_name)
{
struct name *p = xzalloc (sizeof (*p));
if (!file_name)
file_name = "";
p->name = xstrdup (file_name);
p->length = strlen (p->name);
return p;
}
static void
free_name (struct name *p)
{
if (p)
{
free (p->name);
free (p->caname);
free (p);
}
}
/* Names from the command call. */
static struct name *namelist; /* first name in list, if any */
static struct name **nametail = &namelist; /* end of name list */
static struct name *nametail; /* end of name list */
/* File name arguments are processed in two stages: first a
/* File name arguments are processed in two stages: first a
name_array (see below) is filled, then the names from it
are moved into the namelist.
@@ -192,7 +206,7 @@ static struct name **nametail = &namelist; /* end of name list */
which is meant to help process large archives on machines with
limited memory. With this option on, namelist contains at most one
entry, which diminishes the memory consumption.
However, I very much doubt if we still need this -- Sergey */
/* A name_array element contains entries of three types: */
@@ -207,24 +221,25 @@ struct name_elt /* A name_array element. */
union
{
const char *name; /* File or directory name */
int matching_flags;/* fnmatch options if type == NELT_FMASK */
int matching_flags;/* fnmatch options if type == NELT_FMASK */
} v;
};
static struct name_elt *name_array; /* store an array of names */
static size_t allocated_names; /* how big is the array? */
static size_t names; /* how many entries does it have? */
static size_t name_index; /* how many of the entries have we scanned? */
static size_t allocated_entries; /* how big is the array? */
static size_t entries; /* how many entries does it have? */
static size_t scanned; /* how many of the entries have we scanned? */
size_t name_count; /* how many of the entries are names? */
/* Check the size of name_array, reallocating it as necessary. */
static void
check_name_alloc ()
check_name_alloc (void)
{
if (names == allocated_names)
if (entries == allocated_entries)
{
if (allocated_names == 0)
allocated_names = 10; /* Set initial allocation */
name_array = x2nrealloc (name_array, &allocated_names,
if (allocated_entries == 0)
allocated_entries = 10; /* Set initial allocation */
name_array = x2nrealloc (name_array, &allocated_entries,
sizeof (name_array[0]));
}
}
@@ -237,17 +252,18 @@ name_add_name (const char *name, int matching_flags)
struct name_elt *ep;
check_name_alloc ();
ep = &name_array[names++];
ep = &name_array[entries++];
if (prev_flags != matching_flags)
{
ep->type = NELT_FMASK;
ep->v.matching_flags = matching_flags;
prev_flags = matching_flags;
check_name_alloc ();
ep = &name_array[names++];
ep = &name_array[entries++];
}
ep->type = NELT_NAME;
ep->v.name = name;
name_count++;
}
/* Add to name_array a chdir request for the directory NAME */
@@ -256,10 +272,10 @@ name_add_dir (const char *name)
{
struct name_elt *ep;
check_name_alloc ();
ep = &name_array[names++];
ep = &name_array[entries++];
ep->type = NELT_CHDIR;
ep->v.name = name;
}
}
/* Names from external name file. */
@@ -290,28 +306,28 @@ static int matching_flags; /* exclude_fnmatch options */
If CHANGE_DIRS is true, treat any entries of type NELT_CHDIR as
the request to change to the given directory.
Entries of type NELT_FMASK cause updates of the matching_flags
value. */
struct name_elt *
static struct name_elt *
name_next_elt (int change_dirs)
{
static struct name_elt entry;
const char *source;
char *cursor;
while (name_index != names)
while (scanned != entries)
{
struct name_elt *ep;
size_t source_len;
ep = &name_array[name_index++];
ep = &name_array[scanned++];
if (ep->type == NELT_FMASK)
{
matching_flags = ep->v.matching_flags;
continue;
}
source = ep->v.name;
source_len = strlen (source);
if (name_buffer_length < source_len)
@@ -376,8 +392,7 @@ void
name_gather (void)
{
/* Buffer able to hold a single name. */
static struct name *buffer;
static size_t allocated_size;
static struct name *buffer = NULL;
struct name_elt *ep;
@@ -385,44 +400,25 @@ name_gather (void)
{
static int change_dir;
if (allocated_size == 0)
{
allocated_size = offsetof (struct name, name) + NAME_FIELD_SIZE + 1;
buffer = xzalloc (allocated_size);
}
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
change_dir = chdir_arg (xstrdup (ep->v.name));
if (ep)
{
size_t needed_size;
buffer->length = strlen (ep->v.name);
needed_size = offsetof (struct name, name) + buffer->length + 1;
if (allocated_size < needed_size)
{
do
{
allocated_size *= 2;
if (! allocated_size)
xalloc_die ();
}
while (allocated_size < needed_size);
buffer = xrealloc (buffer, allocated_size);
}
free_name (buffer);
buffer = make_name (ep->v.name);
buffer->change_dir = change_dir;
strcpy (buffer->name, ep->v.name);
buffer->next = 0;
buffer->found_count = 0;
buffer->matching_flags = matching_flags;
namelist = buffer;
nametail = &namelist->next;
buffer->directory = NULL;
buffer->parent = NULL;
buffer->cmdline = true;
namelist = nametail = buffer;
}
else if (change_dir)
addname (0, change_dir);
addname (0, change_dir, false, NULL);
}
else
{
@@ -436,11 +432,11 @@ name_gather (void)
change_dir = chdir_arg (xstrdup (ep->v.name));
if (ep)
addname (ep->v.name, change_dir);
addname (ep->v.name, change_dir, true, NULL);
else
{
if (change_dir != change_dir0)
addname (0, change_dir);
addname (NULL, change_dir, false, NULL);
break;
}
}
@@ -449,25 +445,24 @@ name_gather (void)
/* Add a name to the namelist. */
struct name *
addname (char const *string, int change_dir)
addname (char const *string, int change_dir, bool cmdline, struct name *parent)
{
size_t length = string ? strlen (string) : 0;
struct name *name = xmalloc (offsetof (struct name, name) + length + 1);
if (string)
strcpy (name->name, string);
else
name->name[0] = 0;
struct name *name = make_name (string);
name->prev = nametail;
name->next = NULL;
name->length = length;
name->found_count = 0;
name->matching_flags = matching_flags;
name->change_dir = change_dir;
name->dir_contents = NULL;
name->directory = NULL;
name->parent = parent;
name->cmdline = cmdline;
*nametail = name;
nametail = &name->next;
if (nametail)
nametail->next = name;
else
namelist = name;
nametail = name;
return name;
}
@@ -488,6 +483,22 @@ namelist_match (char const *file_name, size_t length)
return NULL;
}
void
remname (struct name *name)
{
struct name *p;
if ((p = name->prev) != NULL)
p->next = name->next;
else
namelist = name->next;
if ((p = name->next) != NULL)
p->prev = name->prev;
else
nametail = name->prev;
}
/* Return true if and only if name FILE_NAME (from an archive) matches any
name from the namelist. */
bool
@@ -501,12 +512,12 @@ name_match (const char *file_name)
if (!cursor)
return true;
if (cursor->name[0] == 0)
{
chdir_do (cursor->change_dir);
namelist = 0;
nametail = &namelist;
namelist = NULL;
nametail = NULL;
return true;
}
@@ -519,8 +530,8 @@ name_match (const char *file_name)
if (starting_file_option)
{
free (namelist);
namelist = 0;
nametail = &namelist;
namelist = NULL;
nametail = NULL;
}
chdir_do (cursor->change_dir);
@@ -559,8 +570,6 @@ all_names_found (struct tar_stat_info *p)
struct name const *cursor;
size_t len;
if (test_label_option)
return true;
if (!p->file_name || occurrence_option == 0 || p->had_trailing_slash)
return false;
len = strlen (p->file_name);
@@ -573,29 +582,21 @@ all_names_found (struct tar_stat_info *p)
return true;
}
static inline int
is_pattern (const char *string)
{
return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
}
static void
static int
regex_usage_warning (const char *name)
{
static int warned_once = 0;
if (warn_regex_usage && is_pattern (name))
if (warn_regex_usage && fnmatch_pattern_has_wildcards (name, 0))
{
warned_once = 1;
WARN ((0, 0,
/* TRANSLATORS: The following three msgids form a single sentence.
*/
_("Pattern matching characters used in file names. Please,")));
_("Pattern matching characters used in file names")));
WARN ((0, 0,
_("use --wildcards to enable pattern matching, or --no-wildcards to")));
WARN ((0, 0,
_("suppress this warning.")));
_("Use --wildcards to enable pattern matching,"
" or --no-wildcards to suppress this warning")));
}
return warned_once;
}
/* Print the names of things in the namelist that were not matched. */
@@ -608,17 +609,16 @@ names_notfound (void)
if (!WASFOUND (cursor) && cursor->name[0])
{
regex_usage_warning (cursor->name);
if (cursor->found_count == 0)
ERROR ((0, 0, _("%s: Not found in archive"),
quotearg_colon (cursor->name)));
else
ERROR ((0, 0, _("%s: Required occurrence not found in archive"),
quotearg_colon (cursor->name)));
ERROR ((0, 0,
(cursor->found_count == 0) ?
_("%s: Not found in archive") :
_("%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;
namelist = NULL;
nametail = NULL;
if (same_order_option)
{
@@ -632,18 +632,57 @@ names_notfound (void)
}
}
}
void
label_notfound (void)
{
struct name const *cursor;
if (!namelist)
return;
for (cursor = namelist; cursor; cursor = cursor->next)
if (WASFOUND (cursor))
return;
if (verbose_option)
error (0, 0, _("Archive label mismatch"));
set_exit_status (TAREXIT_DIFFERS);
for (cursor = namelist; cursor; cursor = cursor->next)
{
if (regex_usage_warning (cursor->name))
break;
}
/* Don't bother freeing the name list; we're about to exit. */
namelist = NULL;
nametail = NULL;
if (same_order_option)
{
const char *name;
while ((name = name_next (1)) != NULL
&& regex_usage_warning (name) == 0)
;
}
}
/* Sorting name lists. */
/* Sort linked LIST of names, of given LENGTH, using COMPARE to order
names. Return the sorted list. Apart from the type `struct name'
and the definition of SUCCESSOR, this is a generic list-sorting
function, but it's too painful to make it both generic and portable
/* Sort *singly* linked LIST of names, of given LENGTH, using COMPARE
to order names. Return the sorted list. Note that after calling
this function, the `prev' links in list elements are messed up.
Apart from the type `struct name' and the definition of SUCCESSOR,
this is a generic list-sorting function, but it's too painful to
make it both generic and portable
in C. */
static struct name *
merge_sort (struct name *list, int length,
int (*compare) (struct name const*, struct name const*))
merge_sort_sll (struct name *list, int length,
int (*compare) (struct name const*, struct name const*))
{
struct name *first_list;
struct name *second_list;
@@ -681,8 +720,8 @@ merge_sort (struct name *list, int length,
second_list = SUCCESSOR (cursor);
SUCCESSOR (cursor) = 0;
first_list = merge_sort (first_list, first_length, compare);
second_list = merge_sort (second_list, second_length, compare);
first_list = merge_sort_sll (first_list, first_length, compare);
second_list = merge_sort_sll (second_list, second_length, compare);
merge_point = &result;
while (first_list && second_list)
@@ -710,30 +749,51 @@ merge_sort (struct name *list, int length,
#undef SUCCESSOR
}
/* Sort doubly linked LIST of names, of given LENGTH, using COMPARE
to order names. Return the sorted list. */
static struct name *
merge_sort (struct name *list, int length,
int (*compare) (struct name const*, struct name const*))
{
struct name *head, *p, *prev;
head = merge_sort_sll (list, length, compare);
/* Fixup prev pointers */
for (prev = NULL, p = head; p; prev = p, p = p->next)
p->prev = prev;
return head;
}
/* A comparison function for sorting names. Put found names last;
break ties by string comparison. */
static int
compare_names (struct name const *n1, struct name const *n2)
compare_names_found (struct name const *n1, struct name const *n2)
{
int found_diff = WASFOUND(n2) - WASFOUND(n1);
int found_diff = WASFOUND (n2) - WASFOUND (n1);
return found_diff ? found_diff : strcmp (n1->name, n2->name);
}
/* Simple comparison by names. */
static int
compare_names (struct name const *n1, struct name const *n2)
{
return strcmp (n1->name, n2->name);
}
/* Add all the dirs under NAME, which names a directory, to the namelist.
If any of the files is a directory, recurse on the subdirectory.
DEVICE is the device not to leave, if the -l option is specified. */
/* Add all the dirs under ST to the namelist NAME, descending the
directory hierarchy recursively. */
static void
add_hierarchy_to_namelist (struct name *name, dev_t device)
add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name)
{
char *file_name = name->name;
const char *buffer = get_directory_contents (file_name, device);
const char *buffer;
if (! buffer)
name->dir_contents = "\0\0\0\0";
else
name->directory = scan_directory (st);
buffer = directory_contents (name->directory);
if (buffer)
{
struct name *child_head = NULL, *child_tail = NULL;
size_t name_length = name->length;
size_t allocated_length = (name_length >= NAME_FIELD_SIZE
? name_length + NAME_FIELD_SIZE
@@ -744,8 +804,7 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
size_t string_length;
int change_dir = name->change_dir;
name->dir_contents = buffer;
strcpy (namebuf, file_name);
strcpy (namebuf, name->name);
if (! ISSLASH (namebuf[name_length - 1]))
{
namebuf[name_length++] = '/';
@@ -758,6 +817,8 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
if (*string == 'D')
{
struct name *np;
struct tar_stat_info subdir;
int subfd;
if (allocated_length <= name_length + string_length)
{
@@ -772,15 +833,96 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
namebuf = xrealloc (namebuf, allocated_length + 1);
}
strcpy (namebuf + name_length, string + 1);
np = addname (namebuf, change_dir);
add_hierarchy_to_namelist (np, device);
np = addname (namebuf, change_dir, false, name);
if (!child_head)
child_head = np;
else
child_tail->sibling = np;
child_tail = np;
tar_stat_init (&subdir);
subdir.parent = st;
if (st->fd < 0)
{
subfd = -1;
errno = - st->fd;
}
else
subfd = subfile_open (st, string + 1,
open_read_flags | O_DIRECTORY);
if (subfd < 0)
open_diag (namebuf);
else
{
subdir.fd = subfd;
if (fstat (subfd, &subdir.stat) != 0)
stat_diag (namebuf);
else if (! (O_DIRECTORY || S_ISDIR (subdir.stat.st_mode)))
{
errno = ENOTDIR;
open_diag (namebuf);
}
else
{
subdir.orig_file_name = xstrdup (namebuf);
add_hierarchy_to_namelist (&subdir, np);
restore_parent_fd (&subdir);
}
}
tar_stat_destroy (&subdir);
}
}
free (namebuf);
name->child = child_head;
}
}
/* Auxiliary functions for hashed table of struct name's. */
static size_t
name_hash (void const *entry, size_t n_buckets)
{
struct name const *name = entry;
return hash_string (name->caname, n_buckets);
}
/* Compare two directories for equality of their names. */
static bool
name_compare (void const *entry1, void const *entry2)
{
struct name const *name1 = entry1;
struct name const *name2 = entry2;
return strcmp (name1->caname, name2->caname) == 0;
}
/* Rebase `name' member of CHILD and all its siblings to
the new PARENT. */
static void
rebase_child_list (struct name *child, struct name *parent)
{
size_t old_prefix_len = child->parent->length;
size_t new_prefix_len = parent->length;
char *new_prefix = parent->name;
for (; child; child = child->sibling)
{
size_t size = child->length - old_prefix_len + new_prefix_len;
char *newp = xmalloc (size + 1);
strcpy (newp, new_prefix);
strcat (newp, child->name + old_prefix_len);
free (child->name);
child->name = newp;
child->length = size;
rebase_directory (child->directory,
child->parent->name, old_prefix_len,
new_prefix, new_prefix_len);
}
}
/* Collect all the names from argv[] (or whatever), expand them into a
directory tree, and sort them. This gets only subdirectories, not
all files. */
@@ -789,57 +931,138 @@ void
collect_and_sort_names (void)
{
struct name *name;
struct name *next_name;
struct name *next_name, *prev_name = NULL;
int num_names;
struct stat statbuf;
Hash_table *nametab;
name_gather ();
if (listed_incremental_option)
read_directory_file ();
if (!namelist)
addname (".", 0);
addname (".", 0, false, NULL);
for (name = namelist; name; name = next_name)
if (listed_incremental_option)
{
next_name = name->next;
if (name->found_count || name->dir_contents)
switch (chdir_count ())
{
case 0:
break;
case 1:
if (namelist->change_dir == 0)
USAGE_ERROR ((0, 0,
_("Using -C option inside file list is not "
"allowed with --listed-incremental")));
break;
default:
USAGE_ERROR ((0, 0,
_("Only one -C option is allowed with "
"--listed-incremental")));
}
read_directory_file ();
}
num_names = 0;
for (name = namelist; name; name = name->next, num_names++)
{
struct tar_stat_info st;
if (name->found_count || name->directory)
continue;
if (name->matching_flags & EXCLUDE_WILDCARDS)
/* NOTE: EXCLUDE_ANCHORED is not relevant here */
/* FIXME: just skip regexps for now */
continue;
chdir_do (name->change_dir);
if (name->name[0] == 0)
continue;
if (deref_stat (dereference_option, name->name, &statbuf) != 0)
tar_stat_init (&st);
if (deref_stat (name->name, &st.stat) != 0)
{
stat_diag (name->name);
continue;
}
if (S_ISDIR (statbuf.st_mode))
if (S_ISDIR (st.stat.st_mode))
{
name->found_count++;
add_hierarchy_to_namelist (name, statbuf.st_dev);
int dir_fd = openat (chdir_fd, name->name,
open_read_flags | O_DIRECTORY);
if (dir_fd < 0)
open_diag (name->name);
else
{
st.fd = dir_fd;
if (fstat (dir_fd, &st.stat) != 0)
stat_diag (name->name);
else if (O_DIRECTORY || S_ISDIR (st.stat.st_mode))
{
st.orig_file_name = xstrdup (name->name);
name->found_count++;
add_hierarchy_to_namelist (&st, name);
}
}
}
tar_stat_destroy (&st);
}
num_names = 0;
for (name = namelist; name; name = name->next)
num_names++;
namelist = merge_sort (namelist, num_names, compare_names);
for (name = namelist; name; name = name->next)
name->found_count = 0;
num_names = 0;
nametab = hash_initialize (0, 0,
name_hash,
name_compare, NULL);
for (name = namelist; name; name = next_name)
{
next_name = name->next;
name->caname = normalize_filename (name->name);
if (prev_name)
{
struct name *p = hash_lookup (nametab, name);
if (p)
{
/* Keep the one listed in the command line */
if (!name->parent)
{
if (p->child)
rebase_child_list (p->child, name);
hash_delete (nametab, name);
/* FIXME: remove_directory (p->caname); ? */
remname (p);
free_name (p);
num_names--;
}
else
{
if (name->child)
rebase_child_list (name->child, p);
/* FIXME: remove_directory (name->caname); ? */
remname (name);
free_name (name);
continue;
}
}
}
name->found_count = 0;
if (!hash_insert (nametab, name))
xalloc_die ();
prev_name = name;
num_names++;
}
nametail = prev_name;
hash_free (nametab);
namelist = merge_sort (namelist, num_names, compare_names_found);
if (listed_incremental_option)
{
for (name = namelist; name && name->name[0] == 0; name++)
;
if (name)
name->dir_contents = append_incremental_renames (name->dir_contents);
append_incremental_renames (name->directory);
}
}
@@ -880,8 +1103,8 @@ name_scan (const char *file_name)
find and return all the non-found names in the namelist. */
struct name *gnu_list_name;
char *
name_from_list (void)
struct name const *
name_from_list ()
{
if (!gnu_list_name)
gnu_list_name = namelist;
@@ -892,9 +1115,9 @@ name_from_list (void)
{
gnu_list_name->found_count++;
chdir_do (gnu_list_name->change_dir);
return gnu_list_name->name;
return gnu_list_name;
}
return 0;
return NULL;
}
void
@@ -928,24 +1151,6 @@ excluded_name (char const *name)
{
return excluded_file_name (excluded, name + FILE_SYSTEM_PREFIX_LEN (name));
}
/* Names to avoid dumping. */
static Hash_table *avoided_name_table;
/* Remember to not archive NAME. */
void
add_avoided_name (char const *name)
{
hash_string_insert (&avoided_name_table, name);
}
/* Should NAME be avoided when archiving? */
bool
is_avoided_name (char const *name)
{
return hash_string_lookup (avoided_name_table, name);
}
static Hash_table *individual_file_table;
@@ -954,7 +1159,7 @@ register_individual_file (char const *name)
{
struct stat st;
if (deref_stat (dereference_option, name, &st) != 0)
if (deref_stat (name, &st) != 0)
return; /* Will be complained about later */
if (S_ISDIR (st.st_mode))
return;

View File

@@ -1,178 +0,0 @@
/* Defines for Sys V style 3-argument open call.
Copyright (C) 1988, 1994, 1995, 1996 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 Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#if EMUL_OPEN3
/* open3.h -- #defines for the various flags for the Sys V style 3-argument
open() call. On BSD or System 5, the system already has this in an
include file. This file is needed for V7 and MINIX systems for the
benefit of open3() in port.c, a routine that emulates the 3-argument call
using system calls available on V7/MINIX.
Written 1987-06-10 by Richard Todd.
The names have been changed by John Gilmore, 1987-07-31, since Richard
called it "bsdopen", and really this change was introduced in AT&T Unix
systems before BSD picked it up. */
/*-----------------------------------------------------------------------.
| open3 -- routine to emulate the 3-argument open system. |
| |
| open3 (path, flag, mode); |
| |
| Attempts to open the file specified by the given pathname. The |
| following flag bits specify options to the routine. Needless to say, |
| you should only specify one of the first three. Function returns file |
| descriptor if successful, -1 and errno if not. |
`-----------------------------------------------------------------------*/
/* The routine obeys the following mode arguments:
O_RDONLY file open for read only
O_WRONLY file open for write only
O_RDWR file open for both read & write
O_CREAT file is created with specified mode if it needs to be
O_TRUNC if file exists, it is truncated to 0 bytes
O_EXCL used with O_CREAT--routine returns error if file exists */
/* Call that if present in most modern Unix systems. This version attempts
to support all the flag bits except for O_NDELAY and O_APPEND, which are
silently ignored. The emulation is not as efficient as the real thing
(at worst, 4 system calls instead of one), but there's not much I can do
about that. */
/* Array to give arguments to access for various modes FIXME, this table
depends on the specific integer values of O_*, and also contains
integers (args to 'access') that should be #define's. */
static int modes[] =
{
04, /* O_RDONLY */
02, /* O_WRONLY */
06, /* O_RDWR */
06, /* invalid, just cope: O_WRONLY+O_RDWR */
};
/* Shut off the automatic emulation of open(), we'll need it. */
#undef open
int
open3 (char *path, int flags, int mode)
{
int exists = 1;
int call_creat = 0;
/* We actually do the work by calling the open() or creat() system
call, depending on the flags. Call_creat is true if we will use
creat(), false if we will use open(). */
/* See if the file exists and is accessible in the requested mode.
Strictly speaking we shouldn't be using access, since access checks
against real uid, and the open call should check against euid. Most
cases real uid == euid, so it won't matter. FIXME. FIXME, the
construction "flags & 3" and the modes table depends on the specific
integer values of the O_* #define's. Foo! */
if (access (path, modes[flags & 3]) < 0)
{
if (errno == ENOENT)
{
/* The file does not exist. */
exists = 0;
}
else
{
/* Probably permission violation. */
if (flags & O_EXCL)
{
/* Oops, the file exists, we didn't want it. No matter
what the error, claim EEXIST. */
errno = EEXIST; /* FIXME: errno should be read-only */
}
return -1;
}
}
/* If we have the O_CREAT bit set, check for O_EXCL. */
if (flags & O_CREAT)
{
if ((flags & O_EXCL) && exists)
{
/* Oops, the file exists and we didn't want it to. */
errno = EEXIST; /* FIXME: errno should be read-only */
return -1;
}
/* If the file doesn't exist, be sure to call creat() so that it
will be created with the proper mode. */
if (!exists)
call_creat = 1;
}
else
{
/* If O_CREAT isn't set and the file doesn't exist, error. */
if (!exists)
{
errno = ENOENT; /* FIXME: errno should be read-only */
return -1;
}
}
/* If the O_TRUNC flag is set and the file exists, we want to call
creat() anyway, since creat() guarantees that the file will be
truncated and open()-for-writing doesn't. (If the file doesn't
exist, we're calling creat() anyway and the file will be created
with zero length.) */
if ((flags & O_TRUNC) && exists)
call_creat = 1;
/* Actually do the call. */
if (call_creat)
/* Call creat. May have to close and reopen the file if we want
O_RDONLY or O_RDWR access -- creat() only gives O_WRONLY. */
{
int fd = creat (path, mode);
if (fd < 0 || (flags & O_WRONLY))
return fd;
if (close (fd) < 0)
return -1;
/* Fall out to reopen the file we've created. */
}
/* Calling old open, we strip most of the new flags just in case. */
return open (path, flags & (O_RDONLY | O_WRONLY | O_RDWR | O_BINARY));
}
#endif /* EMUL_OPEN3 */

View File

@@ -1,69 +0,0 @@
/* Defines for Sys V style 3-argument open call.
Copyright (C) 1988 Free Software Foundation
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* @(#)open3.h 1.4 87/11/11
*
* open3.h -- #defines for the various flags for the Sys V style 3-argument
* open() call. On BSD or System 5, the system already has this in an
* include file. This file is needed for V7 and MINIX systems for the
* benefit of open3() in port.c, a routine that emulates the 3-argument
* call using system calls available on V7/MINIX.
*
* This file is needed by PD tar even if we aren't using the
* emulator, since the #defines for O_WRONLY, etc. are used in
* a couple of places besides the open() calls, (e.g. in the assignment
* to openflag in extract.c). We just #include this rather than
* #ifdef them out.
*
* Written 6/10/87 by rmtodd@uokmax (Richard Todd).
*
* The names have been changed by John Gilmore, 31 July 1987, since
* Richard called it "bsdopen", and really this change was introduced in
* AT&T Unix systems before BSD picked it up.
*/
/* Only one of the next three should be specified */
#define O_RDONLY 0 /* only allow read */
#define O_WRONLY 1 /* only allow write */
#define O_RDWR 2 /* both are allowed */
/* The rest of these can be OR-ed in to the above. */
/*
* O_NDELAY isn't implemented by the emulator. It's only useful (to tar) on
* systems that have named pipes anyway; it prevents tar's hanging by
* opening a named pipe. We #ifndef it because some systems already have
* it defined.
*/
#ifndef O_NDELAY
#define O_NDELAY 4 /* don't block on opening devices that would
* block on open -- ignored by emulator. */
#endif
#define O_CREAT 8 /* create file if needed */
#define O_EXCL 16 /* file cannot already exist */
#define O_TRUNC 32 /* truncate file on open */
#define O_APPEND 64 /* always write at end of file -- ignored by emul */
#ifdef EMUL_OPEN3
/*
* make emulation transparent to rest of file -- redirect all open() calls
* to our routine
*/
#define open open3
#endif

1256
src/port.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,215 +0,0 @@
/* Portability declarations. Requires sys/types.h.
Copyright (C) 1988, 1992 Free Software Foundation
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#if HAVE_ALLOCA_H
#include <alloca.h>
#else /* not HAVE_ALLOCA_H */
#ifdef _AIX
#pragma alloca
#else /* not _AIX */
char *alloca ();
#endif /* not _AIX */
#endif /* not HAVE_ALLOCA_H */
#endif /* not __GNUC__ */
#include "pathmax.h"
#ifdef _POSIX_VERSION
#include <sys/wait.h>
#else /* !_POSIX_VERSION */
#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
#define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0)
#define WIFEXITED(w) (((w) & 0xff) == 0)
#define WSTOPSIG(w) (((w) >> 8) & 0xff)
#define WTERMSIG(w) ((w) & 0x7f)
#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
#endif /* _POSIX_VERSION */
/* nonstandard */
#ifndef WIFCOREDUMPED
#define WIFCOREDUMPED(w) (((w) & 0x80) != 0)
#endif
#ifdef __MSDOS__
/* missing things from sys/stat.h */
#define S_ISUID 0
#define S_ISGID 0
#define S_ISVTX 0
/* device stuff */
#define makedev(ma, mi) ((ma << 8) | mi)
#define major(dev) (dev)
#define minor(dev) (dev)
typedef long off_t;
#endif /* __MSDOS__ */
#if defined(__STDC__) || defined(__TURBOC__)
#define PTR void *
#else
#define PTR char *
#define const
#endif
/* Since major is a function on SVR4, we can't just use `ifndef major'. */
#ifdef major /* Might be defined in sys/types.h. */
#define HAVE_MAJOR
#endif
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_MKDEV)
#include <sys/mkdev.h>
#define HAVE_MAJOR
#endif
#if !defined(HAVE_MAJOR) && defined(MAJOR_IN_SYSMACROS)
#include <sys/sysmacros.h>
#define HAVE_MAJOR
#endif
#ifndef HAVE_MAJOR
#define major(dev) (((dev) >> 8) & 0xff)
#define minor(dev) ((dev) & 0xff)
#define makedev(maj, min) (((maj) << 8) | (min))
#endif
#undef HAVE_MAJOR
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#if !defined(__MSDOS__) && !defined(STDC_HEADERS)
#include <memory.h>
#endif
#ifdef index
#undef index
#endif
#ifdef rindex
#undef rindex
#endif
#define index strchr
#define rindex strrchr
#define bcopy(s, d, n) memcpy(d, s, n)
#define bzero(s, n) memset(s, 0, n)
#define bcmp memcmp
#else
#include <strings.h>
#endif
#if defined(STDC_HEADERS)
#include <stdlib.h>
#else
char *malloc (), *realloc ();
char *getenv ();
#endif
#ifndef _POSIX_VERSION
#ifdef __MSDOS__
#include <io.h>
#else /* !__MSDOS__ */
off_t lseek ();
#endif /* !__MSDOS__ */
char *getcwd ();
#endif /* !_POSIX_VERSION */
#ifndef NULL
#define NULL 0
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CREAT
#define O_CREAT 0
#endif
#ifndef O_NDELAY
#define O_NDELAY 0
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#include <sys/stat.h>
#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
#define mode_t unsigned short
#endif
#if !defined(S_ISBLK) && defined(S_IFBLK)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
#if !defined(S_ISCHR) && defined(S_IFCHR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISREG) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISFIFO) && defined(S_IFIFO)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
#endif
#if !defined(S_ISLNK) && defined(S_IFLNK)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
#endif
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
#endif
#if !defined(S_ISCTG) && defined(S_IFCTG) /* contiguous file */
#define S_ISCTG(m) (((m) & S_IFMT) == S_IFCTG)
#endif
#if !defined(S_ISVTX)
#define S_ISVTX 0001000
#endif
#ifdef __MSDOS__
#include "msd_dir.h"
#define NLENGTH(direct) ((direct)->d_namlen)
#else /* not __MSDOS__ */
#if defined(DIRENT) || defined(_POSIX_VERSION)
#include <dirent.h>
#define NLENGTH(direct) (strlen((direct)->d_name))
#else /* not (DIRENT or _POSIX_VERSION) */
#define dirent direct
#define NLENGTH(direct) ((direct)->d_namlen)
#ifdef SYSNDIR
#include <sys/ndir.h>
#endif /* SYSNDIR */
#ifdef SYSDIR
#include <sys/dir.h>
#endif /* SYSDIR */
#ifdef NDIR
#include <ndir.h>
#endif /* NDIR */
#endif /* DIRENT or _POSIX_VERSION */
#endif /* not __MSDOS__ */

View File

@@ -1,22 +0,0 @@
/* Read files directly from the fast file system
Copyright (C) 1992 Free Software Foundation
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; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

View File

@@ -1,6 +1,7 @@
/* Functions for dealing with sparse files
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 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
@@ -216,43 +217,45 @@ sparse_scan_file (struct tar_sparse_file *file)
struct tar_stat_info *st = file->stat_info;
int fd = file->fd;
char buffer[BLOCKSIZE];
size_t count;
size_t count = 0;
off_t offset = 0;
struct sp_array sp = {0, 0};
if (!lseek_or_error (file, 0))
return false;
st->archive_file_size = 0;
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
if (ST_NBLOCKS (st->stat) == 0)
offset = st->stat.st_size;
else
{
/* Analyze the block. */
if (zero_block_p (buffer, count))
if (!tar_sparse_scan (file, scan_begin, NULL))
return false;
while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
&& count != SAFE_READ_ERROR)
{
if (sp.numbytes)
/* Analyze the block. */
if (zero_block_p (buffer, count))
{
sparse_add_map (st, &sp);
sp.numbytes = 0;
if (!tar_sparse_scan (file, scan_block, NULL))
if (sp.numbytes)
{
sparse_add_map (st, &sp);
sp.numbytes = 0;
if (!tar_sparse_scan (file, scan_block, NULL))
return false;
}
}
else
{
if (sp.numbytes == 0)
sp.offset = offset;
sp.numbytes += count;
st->archive_file_size += count;
if (!tar_sparse_scan (file, scan_block, buffer))
return false;
}
}
else
{
if (sp.numbytes == 0)
sp.offset = offset;
sp.numbytes += count;
st->archive_file_size += count;
if (!tar_sparse_scan (file, scan_block, buffer))
return false;
}
offset += count;
offset += count;
}
}
if (sp.numbytes == 0)
@@ -324,7 +327,6 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
bytes_left -= bytes_read;
file->dumped_size += bytes_read;
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
set_next_block_after (blk);
}
@@ -334,7 +336,7 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
static bool
sparse_extract_region (struct tar_sparse_file *file, size_t i)
{
size_t write_size;
off_t write_size;
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
return false;
@@ -398,10 +400,11 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
{
size_t i;
mv_begin (file.stat_info);
mv_begin_write (file.stat_info->file_name,
file.stat_info->stat.st_size,
file.stat_info->archive_file_size - file.dumped_size);
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
rc = tar_sparse_dump_region (&file, i);
mv_end ();
}
}
@@ -508,13 +511,13 @@ 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 i)
{
size_t size_left;
off_t size_left;
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
return false;
size_left = file->stat_info->sparse_map[i].numbytes;
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
while (size_left > 0)
{
size_t bytes_read;
@@ -564,9 +567,9 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
file.stat_info = st;
file.fd = fd;
file.seekable = true; /* File *must* be seekable for compare to work */
rc = tar_sparse_decode_header (&file);
mv_begin (st);
mv_begin_read (st);
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
{
rc = check_sparse_region (&file,
@@ -579,7 +582,7 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
if (!rc)
skip_file (file.stat_info->archive_file_size - file.dumped_size);
mv_end ();
tar_sparse_done (&file);
return rc;
}
@@ -625,8 +628,9 @@ oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
if (s->numbytes[0] == '\0')
return add_finish;
sp.offset = OFF_FROM_HEADER (s->offset);
sp.numbytes = SIZE_FROM_HEADER (s->numbytes);
sp.numbytes = OFF_FROM_HEADER (s->numbytes);
if (sp.offset < 0
|| sp.offset + sp.numbytes < 0
|| file->stat_info->stat.st_size < sp.offset + sp.numbytes
|| file->stat_info->archive_file_size < 0)
return add_fail;
@@ -695,8 +699,8 @@ oldgnu_store_sparse_info (struct tar_sparse_file *file, size_t *pindex,
{
OFF_TO_CHARS (file->stat_info->sparse_map[*pindex].offset,
sp->offset);
SIZE_TO_CHARS (file->stat_info->sparse_map[*pindex].numbytes,
sp->numbytes);
OFF_TO_CHARS (file->stat_info->sparse_map[*pindex].numbytes,
sp->numbytes);
}
}
@@ -851,13 +855,13 @@ static struct tar_sparse_optab const star_optab = {
instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
POSIX requires the latest occurrence of the variable to override all
previous occurrences.
To avoid this incompatibility two following versions were introduced.
* 0.1
Used by tar 1.15.2 -- 1.15.91 (alpha releases).
The sparse file map is stored in
x header:
@@ -875,18 +879,18 @@ static struct tar_sparse_optab const star_optab = {
Starting from this version, the exact sparse format version is specified
explicitely in the header using the following variables:
GNU.sparse.major Major version
GNU.sparse.major Major version
GNU.sparse.minor Minor version
X header keeps the following variables:
GNU.sparse.name Real file name of the sparse file
GNU.sparse.realsize Real size of the stored file (corresponds to the old
GNU.sparse.size variable)
The name field of the ustar header is constructed using the pattern
"%d/GNUSparseFile.%p/%f".
The sparse map itself is stored in the file data block, preceding the actual
file data. It consists of a series of octal numbers of arbitrary length,
delimited by newlines. The map is padded with nulls to the nearest block
@@ -924,11 +928,11 @@ pax_dump_header_0 (struct tar_sparse_file *file)
char nbuf[UINTMAX_STRSIZE_BOUND];
struct sp_array *map = file->stat_info->sparse_map;
char *save_file_name = NULL;
/* Store the real file size */
xheader_store ("GNU.sparse.size", file->stat_info, NULL);
xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
if (xheader_keyword_deleted_p ("GNU.sparse.map")
|| tar_sparse_minor == 0)
{
@@ -991,7 +995,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
#define COPY_STRING(b,dst,src) do \
{ \
char *endp = b->buffer + BLOCKSIZE; \
char *srcp = src; \
char const *srcp = src; \
while (*srcp) \
{ \
if (dst == endp) \
@@ -1003,7 +1007,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
} \
*dst++ = *srcp++; \
} \
} while (0)
} while (0)
/* Compute stored file size */
p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
@@ -1018,13 +1022,13 @@ pax_dump_header_1 (struct tar_sparse_file *file)
size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
file->stat_info->archive_file_size += size * BLOCKSIZE;
file->dumped_size += size * BLOCKSIZE;
/* Store sparse file identification */
xheader_store ("GNU.sparse.major", file->stat_info, NULL);
xheader_store ("GNU.sparse.minor", file->stat_info, NULL);
xheader_store ("GNU.sparse.name", file->stat_info, NULL);
xheader_store ("GNU.sparse.realsize", file->stat_info, NULL);
file->stat_info->file_name = xheader_format_name (file->stat_info,
"%d/GNUSparseFile.%p/%f", 0);
@@ -1072,12 +1076,12 @@ decode_num (uintmax_t *num, char const *arg, uintmax_t maxval)
if (!ISDIGIT (*arg))
return false;
u = strtoumax (arg, &arg_lim, 10);
if (! (u <= maxval && errno != ERANGE) || *arg_lim)
return false;
*num = u;
return true;
}
@@ -1117,7 +1121,7 @@ pax_decode_header (struct tar_sparse_file *file)
} \
while (*dst++ != '\n'); \
dst[-1] = 0; \
} while (0)
} while (0)
set_next_block_after (current_header);
file->dumped_size += BLOCKSIZE;
@@ -1126,7 +1130,7 @@ pax_decode_header (struct tar_sparse_file *file)
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
@@ -1137,19 +1141,19 @@ pax_decode_header (struct tar_sparse_file *file)
for (i = 0; i < file->stat_info->sparse_map_size; i++)
{
struct sp_array sp;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
sp.offset = u;
COPY_BUF (blk,nbuf,p);
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
{
ERROR ((0, 0, _("%s: malformed sparse archive member"),
ERROR ((0, 0, _("%s: malformed sparse archive member"),
file->stat_info->orig_file_name));
return false;
}
@@ -1158,7 +1162,7 @@ pax_decode_header (struct tar_sparse_file *file)
}
set_next_block_after (blk);
}
return true;
}
@@ -1168,7 +1172,7 @@ static struct tar_sparse_optab const pax_optab = {
pax_sparse_member_p,
pax_dump_header,
NULL,
pax_decode_header,
pax_decode_header,
NULL, /* No scan_block function */
sparse_dump_region,
sparse_extract_region,

View File

@@ -26,32 +26,35 @@ struct compression_suffix
const char *program;
};
struct compression_suffix compression_suffixes[] = {
#define S(s,p) #s, sizeof (#s) - 1, #p
{ S(gz, gzip) },
{ S(tgz, gzip) },
{ S(taz, gzip) },
{ S(Z, compress) },
{ S(taZ, compress) },
{ S(bz2, bzip2) },
{ S(tbz, bzip2) },
{ S(tbz2, bzip2) },
{ S(tz2, bzip2) },
{ S(lzma, lzma) },
{ S(tlz, lzma) },
{ S(lzo, lzop) },
{ S(xz, xz) },
static struct compression_suffix compression_suffixes[] = {
#define __CAT2__(a,b) a ## b
#define S(s,p) #s, sizeof (#s) - 1, __CAT2__(p,_PROGRAM)
{ S(gz, GZIP) },
{ S(tgz, GZIP) },
{ S(taz, GZIP) },
{ S(Z, COMPRESS) },
{ S(taZ, COMPRESS) },
{ S(bz2, BZIP2) },
{ S(tbz, BZIP2) },
{ S(tbz2, BZIP2) },
{ S(tz2, BZIP2) },
{ S(lz, LZIP) },
{ S(lzma, LZMA) },
{ S(tlz, LZMA) },
{ S(lzo, LZOP) },
{ S(xz, XZ) },
#undef S
#undef __CAT2__
};
int nsuffixes = sizeof (compression_suffixes) /
sizeof (compression_suffixes[0]);
static int nsuffixes = sizeof (compression_suffixes) /
sizeof (compression_suffixes[0]);
static const char *
find_compression_program (const char *name, const char *defprog)
{
char *suf = strrchr (name, '.');
if (suf)
{
int i;
@@ -71,10 +74,9 @@ find_compression_program (const char *name, const char *defprog)
}
void
set_comression_program_by_suffix (const char *name, const char *defprog)
set_compression_program_by_suffix (const char *name, const char *defprog)
{
const char *program = find_compression_program (name, defprog);
if (program)
use_compress_program_option = program;
}

View File

@@ -1,7 +1,7 @@
/* System-dependent calls for tar.
Copyright (C) 2003, 2004, 2005, 2006, 2007,
2008 Free Software Foundation, Inc.
2008, 2010 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
@@ -20,6 +20,7 @@
#include <system.h>
#include "common.h"
#include <priv-set.h>
#include <rmt.h>
#include <signal.h>
@@ -174,11 +175,11 @@ sys_wait_for_child (pid_t child_pid, bool eof)
{
int sig = WTERMSIG (wait_status);
if (!(!eof && sig == SIGPIPE))
ERROR ((0, 0, _("Child died with signal %d"), sig));
FATAL_ERROR ((0, 0, _("Child died with signal %d"), sig));
}
else if (WEXITSTATUS (wait_status) != 0)
ERROR ((0, 0, _("Child returned status %d"),
WEXITSTATUS (wait_status)));
FATAL_ERROR ((0, 0, _("Child returned status %d"),
WEXITSTATUS (wait_status)));
}
}
@@ -192,6 +193,7 @@ sys_spawn_shell (void)
child = xfork ();
if (child == 0)
{
priv_set_restore_linkdir ();
execlp (shell, "-sh", "-i", (char *) 0);
exec_fatal (shell);
}
@@ -283,6 +285,30 @@ xdup2 (int from, int into)
}
}
static void wait_for_grandchild (pid_t pid) __attribute__ ((__noreturn__));
/* Propagate any failure of the grandchild back to the parent. */
static void
wait_for_grandchild (pid_t pid)
{
int wait_status;
int exit_code = 0;
while (waitpid (pid, &wait_status, 0) == -1)
if (errno != EINTR)
{
waitpid_error (use_compress_program_option);
break;
}
if (WIFSIGNALED (wait_status))
raise (WTERMSIG (wait_status));
else if (WEXITSTATUS (wait_status) != 0)
exit_code = WEXITSTATUS (wait_status);
exit (exit_code);
}
/* Set ARCHIVE for writing, then compressing an archive. */
pid_t
sys_child_open_for_compress (void)
@@ -291,7 +317,6 @@ sys_child_open_for_compress (void)
int child_pipe[2];
pid_t grandchild_pid;
pid_t child_pid;
int wait_status;
xpipe (parent_pipe);
child_pid = xfork ();
@@ -307,7 +332,8 @@ sys_child_open_for_compress (void)
/* The new born child tar is here! */
program_name = _("tar (child)");
set_program_name (_("tar (child)"));
signal (SIGPIPE, SIG_DFL);
xdup2 (parent_pipe[PREAD], STDIN_FILENO);
xclose (parent_pipe[PWRITE]);
@@ -338,6 +364,7 @@ sys_child_open_for_compress (void)
}
xdup2 (archive, STDOUT_FILENO);
}
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option, NULL);
exec_fatal (use_compress_program_option);
}
@@ -351,10 +378,11 @@ sys_child_open_for_compress (void)
{
/* The newborn grandchild tar is here! Launch the compressor. */
program_name = _("tar (grandchild)");
set_program_name (_("tar (grandchild)"));
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
xclose (child_pipe[PREAD]);
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option,
(char *) 0);
exec_fatal (use_compress_program_option);
@@ -424,24 +452,30 @@ sys_child_open_for_compress (void)
archive_write_error (status);
}
/* Propagate any failure of the grandchild back to the parent. */
wait_for_grandchild (grandchild_pid);
}
while (waitpid (grandchild_pid, &wait_status, 0) == -1)
if (errno != EINTR)
{
waitpid_error (use_compress_program_option);
break;
}
static void
run_decompress_program (void)
{
int i;
const char *p, *prog = NULL;
if (WIFSIGNALED (wait_status))
for (p = first_decompress_program (&i); p; p = next_decompress_program (&i))
{
kill (child_pid, WTERMSIG (wait_status));
exit_status = TAREXIT_FAILURE;
if (prog)
{
WARNOPT (WARN_DECOMPRESS_PROGRAM,
(0, errno, _("cannot run %s"), prog));
WARNOPT (WARN_DECOMPRESS_PROGRAM,
(0, 0, _("trying %s"), p));
}
prog = p;
execlp (p, p, "-d", NULL);
}
else if (WEXITSTATUS (wait_status) != 0)
exit_status = WEXITSTATUS (wait_status);
exit (exit_status);
if (!prog)
FATAL_ERROR ((0, 0, _("unable to run decompression program")));
exec_fatal (prog);
}
/* Set ARCHIVE for uncompressing, then reading an archive. */
@@ -452,7 +486,6 @@ sys_child_open_for_uncompress (void)
int child_pipe[2];
pid_t grandchild_pid;
pid_t child_pid;
int wait_status;
xpipe (parent_pipe);
child_pid = xfork ();
@@ -468,7 +501,8 @@ sys_child_open_for_uncompress (void)
/* The newborn child tar is here! */
program_name = _("tar (child)");
set_program_name (_("tar (child)"));
signal (SIGPIPE, SIG_DFL);
xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
xclose (parent_pipe[PREAD]);
@@ -489,9 +523,8 @@ sys_child_open_for_uncompress (void)
if (archive < 0)
open_fatal (archive_name_array[0]);
xdup2 (archive, STDIN_FILENO);
execlp (use_compress_program_option, use_compress_program_option,
"-d", (char *) 0);
exec_fatal (use_compress_program_option);
priv_set_restore_linkdir ();
run_decompress_program ();
}
/* We do need a grandchild tar. */
@@ -503,13 +536,12 @@ sys_child_open_for_uncompress (void)
{
/* The newborn grandchild tar is here! Launch the uncompressor. */
program_name = _("tar (grandchild)");
set_program_name (_("tar (grandchild)"));
xdup2 (child_pipe[PREAD], STDIN_FILENO);
xclose (child_pipe[PWRITE]);
execlp (use_compress_program_option, use_compress_program_option,
"-d", (char *) 0);
exec_fatal (use_compress_program_option);
priv_set_restore_linkdir ();
run_decompress_program ();
}
/* The child tar is still here! */
@@ -562,30 +594,13 @@ sys_child_open_for_uncompress (void)
xclose (STDOUT_FILENO);
/* Propagate any failure of the grandchild back to the parent. */
while (waitpid (grandchild_pid, &wait_status, 0) == -1)
if (errno != EINTR)
{
waitpid_error (use_compress_program_option);
break;
}
if (WIFSIGNALED (wait_status))
{
kill (child_pid, WTERMSIG (wait_status));
exit_status = TAREXIT_FAILURE;
}
else if (WEXITSTATUS (wait_status) != 0)
exit_status = WEXITSTATUS (wait_status);
exit (exit_status);
wait_for_grandchild (grandchild_pid);
}
static void
dec_to_env (char *envar, uintmax_t num)
dec_to_env (char const *envar, uintmax_t num)
{
char buf[UINTMAX_STRSIZE_BOUND];
char *numstr;
@@ -596,7 +611,7 @@ dec_to_env (char *envar, uintmax_t num)
}
static void
time_to_env (char *envar, struct timespec t)
time_to_env (char const *envar, struct timespec t)
{
char buf[TIMESPEC_STRSIZE_BOUND];
if (setenv (envar, code_timespec (t, buf), 1) != 0)
@@ -604,7 +619,7 @@ time_to_env (char *envar, struct timespec t)
}
static void
oct_to_env (char *envar, unsigned long num)
oct_to_env (char const *envar, unsigned long num)
{
char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
@@ -614,7 +629,7 @@ oct_to_env (char *envar, unsigned long num)
}
static void
str_to_env (char *envar, char const *str)
str_to_env (char const *envar, char const *str)
{
if (str)
{
@@ -626,7 +641,7 @@ str_to_env (char *envar, char const *str)
}
static void
chr_to_env (char *envar, char c)
chr_to_env (char const *envar, char c)
{
char buf[2];
buf[0] = c;
@@ -639,6 +654,12 @@ static void
stat_to_env (char *name, char type, struct tar_stat_info *st)
{
str_to_env ("TAR_VERSION", PACKAGE_VERSION);
str_to_env ("TAR_ARCHIVE", *archive_name_cursor);
dec_to_env ("TAR_VOLUME", archive_name_cursor - archive_name_array + 1);
dec_to_env ("TAR_BLOCKING_FACTOR", blocking_factor);
str_to_env ("TAR_FORMAT",
archive_format_string (current_format == DEFAULT_FORMAT ?
archive_format : current_format));
chr_to_env ("TAR_FILETYPE", type);
oct_to_env ("TAR_MODE", st->stat.st_mode);
str_to_env ("TAR_FILENAME", name);
@@ -706,6 +727,7 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
argv[2] = to_command_option;
argv[3] = NULL;
priv_set_restore_linkdir ();
execv ("/bin/sh", argv);
exec_fatal (file_name);
@@ -754,7 +776,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
char uintbuf[UINTMAX_STRSIZE_BOUND];
int p[2];
static RETSIGTYPE (*saved_handler) (int sig);
xpipe (p);
saved_handler = signal (SIGPIPE, SIG_IGN);
@@ -787,7 +809,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
}
signal (SIGPIPE, saved_handler);
if (WIFEXITED (status))
{
if (WEXITSTATUS (status) == 0 && rc > 0)
@@ -817,9 +839,10 @@ sys_exec_info_script (const char **archive_name, int volume_number)
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = (char*) info_script_option;
argv[2] = (char *) info_script_option;
argv[3] = NULL;
priv_set_restore_linkdir ();
execv (argv[0], argv);
exec_fatal (info_script_option);
@@ -864,9 +887,10 @@ sys_exec_checkpoint_script (const char *script_name,
archive_format : current_format), 1);
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = (char*) script_name;
argv[2] = (char *) script_name;
argv[3] = NULL;
priv_set_restore_linkdir ();
execv (argv[0], argv);
exec_fatal (script_name);

635
src/tar.c

File diff suppressed because it is too large Load Diff

View File

@@ -265,7 +265,7 @@ enum archive_format
struct sp_array
{
off_t offset;
size_t numbytes;
off_t numbytes;
};
struct xheader
@@ -311,12 +311,32 @@ struct tar_stat_info
/* Extended headers */
struct xheader xhdr;
/* For dumpdirs */
bool is_dumpdir; /* Is the member a dumpdir? */
bool skipped; /* The member contents is already read
(for GNUTYPE_DUMPDIR) */
char *dumpdir; /* Contents of the dump directory */
/* Parent directory, if creating an archive. This is null if the
file is at the top level. */
struct tar_stat_info *parent;
/* Directory stream. If this is not null, it is in control of FD,
and should be closed instead of FD. */
DIR *dirstream;
/* File descriptor, if creating an archive, and if a directory or a
regular file or a contiguous file.
It is zero if no file descriptor is available, either because it
was never needed or because it was open and then closed to
conserve on file descriptors. (Standard input is never used
here, so zero cannot be a valid file descriptor.)
It is negative if it could not be reopened after it was closed.
Negate it to find out what errno was when the reopen failed. */
int fd;
};
union block

View File

@@ -1,240 +0,0 @@
/* tcexparg.c - Unix-style command line wildcards for Turbo C 2.0
This file is in the public domain.
Compile your main program with -Dmain=_main and link with this file.
After that, it is just as if the operating system had expanded the
arguments, except that they are not sorted. The program name and all
arguments that are expanded from wildcards are lowercased.
Syntax for wildcards:
* Matches zero or more of any character (except a '.' at
the beginning of a name).
? Matches any single character.
[r3z] Matches 'r', '3', or 'z'.
[a-d] Matches a single character in the range 'a' through 'd'.
[!a-d] Matches any single character except a character in the
range 'a' through 'd'.
The period between the filename root and its extension need not be
given explicitly. Thus, the pattern `a*e' will match 'abacus.exe'
and 'axyz.e' as well as 'apple'. Comparisons are not case sensitive.
Authors:
The expargs code is a modification of wildcard expansion code
written for Turbo C 1.0 by
Richard Hargrove
Texas Instruments, Inc.
P.O. Box 869305, m/s 8473
Plano, Texas 75086
214/575-4128
and posted to USENET in September, 1987.
The wild_match code was written by Rich Salz, rsalz@bbn.com,
posted to net.sources in November, 1986.
The code connecting the two is by Mike Slomin, bellcore!lcuxa!mike2,
posted to comp.sys.ibm.pc in November, 1988.
Major performance enhancements and bug fixes, and source cleanup,
by David MacKenzie, djm@gnu.ai.mit.edu. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <dir.h>
/* Number of new arguments to allocate space for at a time. */
#define ARGS_INCREMENT 10
/* The name this program was run with, for error messages. */
static char *program_name;
static char **grow_argv (char **new_argv, int new_argc);
static void fatal_error (const char *message);
int wild_match (char *string, char *pattern);
char *basename (char *path);
char **expargs (int *, char **);
#ifdef main
#undef main
#endif
int
main (int argc, char **argv, char **envp)
{
argv = expargs (&argc, argv);
return _main (argc, argv, envp);
}
char **
expargs (int *pargc, char **argv)
{
char path[MAXPATH + 1];
char **new_argv;
struct ffblk block;
char *path_base;
char *arg_base;
int argind;
int new_argc;
int path_length;
int matched;
program_name = argv[0];
if (program_name && *program_name)
strlwr (program_name);
new_argv = grow_argv (NULL, 0);
new_argv[0] = argv[0];
new_argc = 1;
for (argind = 1; argind < *pargc; ++argind)
{
matched = 0;
if (strpbrk (argv[argind], "?*[") != NULL)
{
strncpy (path, argv[argind], MAXPATH - 3);
path_base = basename (path);
strcpy (path_base, "*.*");
arg_base = argv[argind] + (path_base - path);
if (!findfirst (path, &block, FA_DIREC))
{
strlwr (path);
do
{
/* Only match "." and ".." explicitly. */
if (*block.ff_name == '.' && *arg_base != '.')
continue;
path_length = stpcpy (path_base, block.ff_name) - path + 1;
strlwr (path_base);
if (wild_match (path, argv[argind]))
{
matched = 1;
new_argv[new_argc] = (char *) malloc (path_length);
if (new_argv[new_argc] == NULL)
fatal_error ("memory exhausted");
strcpy (new_argv[new_argc++], path);
new_argv = grow_argv (new_argv, new_argc);
}
} while (!findnext (&block));
}
}
if (matched == 0)
new_argv[new_argc++] = argv[argind];
new_argv = grow_argv (new_argv, new_argc);
}
*pargc = new_argc;
new_argv[new_argc] = NULL;
return &new_argv[0];
}
/* Return a pointer to the last element of PATH. */
char *
basename (char *path)
{
char *tail;
for (tail = path; *path; ++path)
if (*path == ':' || *path == '\\')
tail = path + 1;
return tail;
}
static char **
grow_argv (char **new_argv, int new_argc)
{
if (new_argc % ARGS_INCREMENT == 0)
{
new_argv = (char **) realloc
(new_argv, sizeof (char *) * (new_argc + ARGS_INCREMENT));
if (new_argv == NULL)
fatal_error ("memory exhausted");
}
return new_argv;
}
static void
fatal_error (const char *message)
{
putc ('\n', stderr);
if (program_name && *program_name)
{
fputs (program_name, stderr);
fputs (": ", stderr);
}
fputs (message, stderr);
putc ('\n', stderr);
exit (1);
}
/* Shell-style pattern matching for ?, \, [], and * characters.
I'm putting this replacement in the public domain.
Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. */
/* The character that inverts a character class; '!' or '^'. */
#define INVERT '!'
static int star (char *string, char *pattern);
/* Return nonzero if `string' matches Unix-style wildcard pattern
`pattern'; zero if not. */
int
wild_match (char *string, char *pattern)
{
int prev; /* Previous character in character class. */
int matched; /* If 1, character class has been matched. */
int reverse; /* If 1, character class is inverted. */
for (; *pattern; string++, pattern++)
switch (*pattern)
{
case '\\':
/* Literal match with following character; fall through. */
pattern++;
default:
if (*string != *pattern)
return 0;
continue;
case '?':
/* Match anything. */
if (*string == '\0')
return 0;
continue;
case '*':
/* Trailing star matches everything. */
return *++pattern ? star (string, pattern) : 1;
case '[':
/* Check for inverse character class. */
reverse = pattern[1] == INVERT;
if (reverse)
pattern++;
for (prev = 256, matched = 0; *++pattern && *pattern != ']';
prev = *pattern)
if (*pattern == '-'
? *string <= *++pattern && *string >= prev
: *string == *pattern)
matched = 1;
if (matched == reverse)
return 0;
continue;
}
return *string == '\0';
}
static int
star (char *string, char *pattern)
{
while (wild_match (string, pattern) == 0)
if (*++string == '\0')
return 0;
return 1;
}

View File

@@ -1,67 +0,0 @@
/* Find out if we need the pad field in the header for this machine
Copyright (C) 1991 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
struct inc
{
char a[20];
char b[20];
};
struct test1
{
char a;
struct inc in[5];
};
struct test2
{
char a;
char b;
struct inc in[5];
};
void
main ()
{
struct test1 t1;
struct test2 t2;
int t1diff, t2diff;
FILE *fp = fopen ("testpad.h", "w");
if (fp == 0)
{
fprintf (stderr, "testpad: cannot open ");
fflush (stderr);
perror ("testpad.h");
exit (1);
}
t1diff = (char *) &t1.in[0] - (char *) &t1;
t2diff = (char *) &t2.in[0] - (char *) &t2;
if (t2diff == t1diff + 1)
fprintf (fp, "#define NEEDPAD\n");
else if (t1diff != t2diff)
fprintf (stderr, "Cannot determine padding for tar struct, \n\
will try with none.\n");
fclose (fp);
exit (0);
}

View File

@@ -1,4 +1,4 @@
/* This file is part of GNU tar.
/* This file is part of GNU tar.
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -34,8 +34,8 @@ enum replace_segm_type
enum case_ctl_type
{
ctl_stop, /* Stop case conversion */
ctl_upcase_next,/* Turn the next character to uppercase */
ctl_stop, /* Stop case conversion */
ctl_upcase_next,/* Turn the next character to uppercase */
ctl_locase_next,/* Turn the next character to lowercase */
ctl_upcase, /* Turn the replacement to uppercase until ctl_stop */
ctl_locase /* Turn the replacement to lowercase until ctl_stop */
@@ -51,9 +51,9 @@ struct replace_segm
{
char *ptr;
size_t size;
} literal; /* type == segm_literal */
} literal; /* type == segm_literal */
size_t ref; /* type == segm_backref */
enum case_ctl_type ctl; /* type == segm_case_ctl */
enum case_ctl_type ctl; /* type == segm_case_ctl */
} v;
};
@@ -75,7 +75,7 @@ int transform_flags = XFORM_ALL;
static struct transform *transform_head, *transform_tail;
static struct transform *
new_transform ()
new_transform (void)
{
struct transform *p = xzalloc (sizeof *p);
if (transform_tail)
@@ -146,7 +146,7 @@ parse_xform_flags (int *pflags, int c)
case 'R':
*pflags &= ~XFORM_REGFILE;
break;
case 'h':
*pflags |= XFORM_LINK;
break;
@@ -154,7 +154,7 @@ parse_xform_flags (int *pflags, int c)
case 'H':
*pflags &= ~XFORM_LINK;
break;
case 's':
*pflags |= XFORM_SYMLINK;
break;
@@ -204,10 +204,10 @@ parse_transform_expr (const char *expr)
*expr));
}
return expr;
}
}
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
}
delim = expr[1];
/* Scan regular expression */
@@ -258,14 +258,14 @@ parse_transform_expr (const char *expr)
if (*p == ';')
p++;
/* Extract and compile regex */
str = xmalloc (i - 1);
memcpy (str, expr + 2, i - 2);
str[i - 2] = 0;
rc = regcomp (&tf->regex, str, cflags);
if (rc)
{
char errbuf[512];
@@ -275,7 +275,7 @@ parse_transform_expr (const char *expr)
if (str[0] == '^' || str[strlen (str) - 1] == '$')
tf->transform_type = transform_first;
free (str);
/* Extract and compile replacement expr */
@@ -289,7 +289,7 @@ parse_transform_expr (const char *expr)
if (*cur == '\\')
{
size_t n;
add_literal_segment (tf, beg, cur);
switch (*++cur)
{
@@ -310,32 +310,32 @@ parse_transform_expr (const char *expr)
add_char_segment (tf, '\a');
cur++;
break;
case 'b':
add_char_segment (tf, '\b');
cur++;
break;
case 'f':
add_char_segment (tf, '\f');
cur++;
break;
case 'n':
add_char_segment (tf, '\n');
cur++;
break;
case 'r':
add_char_segment (tf, '\r');
cur++;
break;
case 't':
add_char_segment (tf, '\t');
cur++;
break;
case 'v':
add_char_segment (tf, '\v');
cur++;
@@ -345,39 +345,39 @@ parse_transform_expr (const char *expr)
add_char_segment (tf, '&');
cur++;
break;
case 'L':
/* Turn the replacement to lowercase until a `\U' or `\E'
is found, */
add_case_ctl_segment (tf, ctl_locase);
cur++;
break;
case 'l':
/* Turn the next character to lowercase, */
add_case_ctl_segment (tf, ctl_locase_next);
cur++;
break;
case 'U':
/* Turn the replacement to uppercase until a `\L' or `\E'
is found, */
add_case_ctl_segment (tf, ctl_upcase);
cur++;
break;
case 'u':
/* Turn the next character to uppercase, */
add_case_ctl_segment (tf, ctl_upcase_next);
cur++;
break;
case 'E':
/* Stop case conversion started by `\L' or `\U'. */
add_case_ctl_segment (tf, ctl_stop);
cur++;
break;
default:
/* Try to be nice */
{
@@ -420,7 +420,7 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
static char *case_ctl_buffer;
static size_t case_ctl_bufsize;
char *p;
if (case_ctl_bufsize < size)
{
case_ctl_bufsize = size;
@@ -430,21 +430,21 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
switch (case_ctl)
{
case ctl_upcase_next:
case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
case_ctl_buffer[0] = toupper ((unsigned char) case_ctl_buffer[0]);
break;
case ctl_locase_next:
case_ctl_buffer[0] = tolower (case_ctl_buffer[0]);
case_ctl_buffer[0] = tolower ((unsigned char) case_ctl_buffer[0]);
break;
case ctl_upcase:
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
*p = toupper (*p);
*p = toupper ((unsigned char) *p);
break;
case ctl_locase:
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
*p = tolower (*p);
*p = tolower ((unsigned char) *p);
break;
case ctl_stop:
@@ -457,7 +457,7 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
static struct obstack stk;
static bool stk_init;
void
static void
_single_transform_name_to_obstack (struct transform *tf, char *input)
{
regmatch_t *rmp;
@@ -465,7 +465,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
size_t nmatches = 0;
enum case_ctl_type case_ctl = ctl_stop, /* Current case conversion op */
save_ctl = ctl_stop; /* Saved case_ctl for \u and \l */
/* Reset case conversion after a single-char operation */
#define CASE_CTL_RESET() if (case_ctl == ctl_upcase_next \
|| case_ctl == ctl_locase_next) \
@@ -473,20 +473,20 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
case_ctl = save_ctl; \
save_ctl = ctl_stop; \
}
rmp = xmalloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
while (*input)
{
size_t disp;
char *ptr;
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
if (rc == 0)
{
struct replace_segm *segm;
disp = rmp[0].rm_eo;
if (rmp[0].rm_so)
@@ -516,7 +516,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
}
obstack_grow (&stk, ptr, segm->v.literal.size);
break;
case segm_backref: /* Back-reference segment */
if (rmp[segm->v.ref].rm_so != -1
&& rmp[segm->v.ref].rm_eo != -1)
@@ -529,7 +529,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
ptr = run_case_conv (case_ctl, ptr, size);
CASE_CTL_RESET();
}
obstack_grow (&stk, ptr, size);
}
break;
@@ -549,7 +549,7 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
break;
}
/*FALL THROUGH*/
case ctl_upcase:
case ctl_locase:
case ctl_stop:
@@ -577,18 +577,18 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
free (rmp);
}
bool
static bool
_transform_name_to_obstack (int flags, char *input, char **output)
{
struct transform *tf;
bool alloced = false;
if (!stk_init)
{
obstack_init (&stk);
stk_init = true;
}
for (tf = transform_head; tf; tf = tf->next)
{
if (tf->flags & flags)
@@ -601,7 +601,7 @@ _transform_name_to_obstack (int flags, char *input, char **output)
*output = input;
return alloced;
}
bool
transform_name_fp (char **pinput, int flags,
char *(*fun)(char *, void *), void *dat)
@@ -628,4 +628,3 @@ transform_name (char **pinput, int type)
{
return transform_name_fp (pinput, type, NULL, NULL);
}

158
src/unlink.c Normal file
View File

@@ -0,0 +1,158 @@
/* This file is part of GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <system.h>
#include "common.h"
#include <quotearg.h>
struct deferred_unlink
{
struct deferred_unlink *next; /* Next unlink in the queue */
char *file_name; /* Absolute name of the file to unlink */
bool is_dir; /* True if file_name is a directory */
off_t records_written; /* Number of records written when this
entry got added to the queue */
};
/* The unlink queue */
static struct deferred_unlink *dunlink_head, *dunlink_tail;
/* Number of entries in the queue */
static size_t dunlink_count;
/* List of entries available for allocation */
static struct deferred_unlink *dunlink_avail;
/* Delay (number of records written) between adding entry to the
list and its actual removal. */
size_t deferred_unlink_delay = 0;
static struct deferred_unlink *
dunlink_alloc (void)
{
struct deferred_unlink *p;
if (dunlink_avail)
{
p = dunlink_avail;
dunlink_avail = p->next;
p->next = NULL;
}
else
p = xmalloc (sizeof (*p));
return p;
}
static void
dunlink_reclaim (struct deferred_unlink *p)
{
free (p->file_name);
p->next = dunlink_avail;
dunlink_avail = p;
}
static void
flush_deferred_unlinks (bool force)
{
struct deferred_unlink *p, *prev = NULL;
for (p = dunlink_head; p; )
{
struct deferred_unlink *next = p->next;
if (force
|| records_written > p->records_written + deferred_unlink_delay)
{
if (p->is_dir)
{
if (unlinkat (chdir_fd, p->file_name, AT_REMOVEDIR) != 0)
{
switch (errno)
{
case ENOENT:
/* nothing to worry about */
break;
case ENOTEMPTY:
if (!force)
{
/* Keep the record in list, in the hope we'll
be able to remove it later */
prev = p;
p = next;
continue;
}
/* fall through */
default:
rmdir_error (p->file_name);
}
}
}
else
{
if (unlinkat (chdir_fd, p->file_name, 0) != 0 && errno != ENOENT)
unlink_error (p->file_name);
}
dunlink_reclaim (p);
dunlink_count--;
p = next;
if (prev)
prev->next = p;
else
dunlink_head = p;
}
else
{
prev = p;
p = next;
}
}
if (!dunlink_head)
dunlink_tail = NULL;
}
void
finish_deferred_unlinks ()
{
flush_deferred_unlinks (true);
while (dunlink_avail)
{
struct deferred_unlink *next = dunlink_avail->next;
free (dunlink_avail);
dunlink_avail = next;
}
}
void
queue_deferred_unlink (const char *name, bool is_dir)
{
struct deferred_unlink *p;
if (dunlink_head
&& records_written > dunlink_head->records_written + deferred_unlink_delay)
flush_deferred_unlinks (false);
p = dunlink_alloc ();
p->next = NULL;
p->file_name = normalize_filename (name);
p->is_dir = is_dir;
p->records_written = records_written;
if (dunlink_tail)
dunlink_tail->next = p;
else
dunlink_head = p;
dunlink_tail = p;
dunlink_count++;
}

View File

@@ -1,7 +1,7 @@
/* Update a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
2004, 2005, 2007 Free Software Foundation, Inc.
2004, 2005, 2007, 2010 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
@@ -47,7 +47,7 @@ char *output_start;
static void
append_file (char *file_name)
{
int handle = open (file_name, O_RDONLY | O_BINARY);
int handle = openat (chdir_fd, file_name, O_RDONLY | O_BINARY);
struct stat stat_data;
if (handle < 0)
@@ -114,7 +114,9 @@ update_archive (void)
while (!found_end)
{
enum read_header status = read_header (false);
enum read_header status = read_header (&current_header,
&current_stat_info,
read_header_auto);
switch (status)
{
@@ -128,6 +130,8 @@ update_archive (void)
decode_header (current_header, &current_stat_info,
&current_format, 0);
transform_stat_info (current_header->header.typeflag,
&current_stat_info);
archive_format = current_format;
if (subcommand_option == UPDATE_SUBCOMMAND
@@ -136,12 +140,43 @@ update_archive (void)
struct stat s;
chdir_do (name->change_dir);
if (deref_stat (dereference_option,
current_stat_info.file_name, &s) == 0
&& (tar_timespec_cmp (get_stat_mtime (&s),
current_stat_info.mtime)
<= 0))
add_avoided_name (current_stat_info.file_name);
if (deref_stat (current_stat_info.file_name, &s) == 0)
{
if (S_ISDIR (s.st_mode))
{
char *p, *dirp;
DIR *stream;
int fd = openat (chdir_fd, name->name,
open_read_flags | O_DIRECTORY);
if (fd < 0)
open_error (name->name);
else if (! ((stream = fdopendir (fd))
&& (dirp = streamsavedir (stream))))
savedir_error (name->name);
else
{
namebuf_t nbuf = namebuf_create (name->name);
for (p = dirp; *p; p += strlen (p) + 1)
addname (namebuf_name (nbuf, p),
0, false, NULL);
namebuf_free (nbuf);
free (dirp);
remname (name);
}
if (stream
? closedir (stream) != 0
: 0 <= fd && close (fd) != 0)
savedir_error (name->name);
}
else if (tar_timespec_cmp (get_stat_mtime (&s),
current_stat_info.mtime)
<= 0)
remname (name);
}
}
skip_member ();
@@ -189,10 +224,10 @@ update_archive (void)
output_start = current_block->buffer;
{
char *file_name;
while ((file_name = name_from_list ()) != NULL)
struct name const *p;
while ((p = name_from_list ()) != NULL)
{
char *file_name = p->name;
if (excluded_name (file_name))
continue;
if (interactive_option && !confirm ("add", file_name))
@@ -200,11 +235,12 @@ update_archive (void)
if (subcommand_option == CAT_SUBCOMMAND)
append_file (file_name);
else
dump_file (file_name, 1, (dev_t) 0);
dump_file (0, file_name, file_name);
}
}
write_eot ();
close_archive ();
finish_deferred_unlinks ();
names_notfound ();
}

View File

@@ -1,20 +0,0 @@
/* Version info for tar.
Copyright (C) 1989, 1992, Free Software Foundation.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
char version_string[] = "GNU tar version 1.11";

99
src/warning.c Normal file
View File

@@ -0,0 +1,99 @@
/* This file is part of GNU tar.
Copyright (C) 2009 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <system.h>
#include <argmatch.h>
#include "common.h"
static char const *const warning_args[] = {
"all",
"alone-zero-block",
"bad-dumpdir",
"cachedir",
"contiguous-cast",
"file-changed",
"file-ignored",
"file-removed",
"file-shrank",
"file-unchanged",
"filename-with-nuls",
"ignore-archive",
"ignore-newer",
"new-directory",
"rename-directory",
"symlink-cast",
"timestamp",
"unknown-cast",
"unknown-keyword",
"xdev",
"decompress-program",
NULL
};
static int warning_types[] = {
WARN_ALL,
WARN_ALONE_ZERO_BLOCK,
WARN_BAD_DUMPDIR,
WARN_CACHEDIR,
WARN_CONTIGUOUS_CAST,
WARN_FILE_CHANGED,
WARN_FILE_IGNORED,
WARN_FILE_REMOVED,
WARN_FILE_SHRANK,
WARN_FILE_UNCHANGED,
WARN_FILENAME_WITH_NULS,
WARN_IGNORE_ARCHIVE,
WARN_IGNORE_NEWER,
WARN_NEW_DIRECTORY,
WARN_RENAME_DIRECTORY,
WARN_SYMLINK_CAST,
WARN_TIMESTAMP,
WARN_UNKNOWN_CAST,
WARN_UNKNOWN_KEYWORD,
WARN_XDEV,
WARN_DECOMPRESS_PROGRAM
};
ARGMATCH_VERIFY (warning_args, warning_types);
int warning_option = WARN_ALL;
void
set_warning_option (const char *arg)
{
int negate = 0;
int option;
if (strcmp (arg, "none") == 0)
{
warning_option = 0;
return;
}
if (strlen (arg) > 2 && memcmp (arg, "no-", 3) == 0)
{
negate = 1;
arg += 3;
}
option = XARGMATCH ("--warning", arg,
warning_args, warning_types);
if (negate)
warning_option &= ~option;
else
warning_option |= option;
}

View File

@@ -1,6 +1,7 @@
/* POSIX extended headers for tar.
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 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
@@ -25,6 +26,7 @@
#include "common.h"
static void xheader_init (struct xheader *xhdr);
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));
@@ -96,9 +98,15 @@ static struct keyword_list *global_header_override_list;
/* Template for the name field of an 'x' type header */
static char *exthdr_name;
static char *exthdr_mtime_option;
static time_t exthdr_mtime;
/* Template for the name field of a 'g' type header */
static char *globexthdr_name;
static char *globexthdr_mtime_option;
static time_t globexthdr_mtime;
bool
xheader_keyword_deleted_p (const char *kw)
{
@@ -156,6 +164,21 @@ xheader_set_single_keyword (char *kw)
USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet implemented"), kw));
}
static void
assign_time_option (char **sval, time_t *tval, const char *input)
{
uintmax_t u;
char *p;
time_t t = u = strtoumax (input, &p, 10);
if (t != u || *p || errno == ERANGE)
ERROR ((0, 0, _("Time stamp is out of allowed range")));
else
{
*tval = t;
assign_string (sval, input);
}
}
static void
xheader_set_keyword_equal (char *kw, char *eq)
{
@@ -168,12 +191,12 @@ xheader_set_keyword_equal (char *kw, char *eq)
global = false;
}
while (p > kw && isspace (*p))
while (p > kw && isspace ((unsigned char) *p))
p--;
*p = 0;
for (p = eq + 1; *p && isspace (*p); p++)
for (p = eq + 1; *p && isspace ((unsigned char) *p); p++)
;
if (strcmp (kw, "delete") == 0)
@@ -186,6 +209,10 @@ xheader_set_keyword_equal (char *kw, char *eq)
assign_string (&exthdr_name, p);
else if (strcmp (kw, "globexthdr.name") == 0)
assign_string (&globexthdr_name, p);
else if (strcmp (kw, "exthdr.mtime") == 0)
assign_time_option (&exthdr_mtime_option, &exthdr_mtime, p);
else if (strcmp (kw, "globexthdr.mtime") == 0)
assign_time_option (&globexthdr_mtime_option, &globexthdr_mtime, p);
else
{
if (xheader_protected_keyword_p (kw))
@@ -364,14 +391,26 @@ xheader_ghdr_name (void)
}
void
xheader_write (char type, char *name, struct xheader *xhdr)
xheader_write (char type, char *name, time_t t, struct xheader *xhdr)
{
union block *header;
size_t size;
char *p;
size = xhdr->size;
header = start_private_header (name, size);
switch (type)
{
case XGLTYPE:
if (globexthdr_mtime_option)
t = globexthdr_mtime;
break;
case XHDTYPE:
if (exthdr_mtime_option)
t = exthdr_mtime;
break;
}
header = start_private_header (name, size, t);
header->header.typeflag = type;
simple_finish_header (header);
@@ -403,30 +442,37 @@ xheader_write (char type, char *name, struct xheader *xhdr)
void
xheader_write_global (struct xheader *xhdr)
{
char *name;
struct keyword_list *kp;
if (keyword_global_override_list)
{
struct keyword_list *kp;
if (!keyword_global_override_list)
return;
xheader_init (xhdr);
for (kp = keyword_global_override_list; kp; kp = kp->next)
code_string (kp->value, kp->pattern, xhdr);
}
if (xhdr->stk)
{
char *name;
xheader_init (xhdr);
for (kp = keyword_global_override_list; kp; kp = kp->next)
code_string (kp->value, kp->pattern, xhdr);
xheader_finish (xhdr);
xheader_write (XGLTYPE, name = xheader_ghdr_name (), xhdr);
free (name);
xheader_finish (xhdr);
xheader_write (XGLTYPE, name = xheader_ghdr_name (), time (NULL), xhdr);
free (name);
}
}
/* General Interface */
#define XHDR_PROTECTED 0x01
#define XHDR_GLOBAL 0x02
struct xhdr_tab
{
char const *keyword;
void (*coder) (struct tar_stat_info const *, char const *,
struct xheader *, void const *data);
void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
bool protect;
int flags;
};
/* This declaration must be extern, because ISO C99 section 6.9.2
@@ -454,7 +500,7 @@ xheader_protected_pattern_p (const char *pattern)
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
if ((p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0)
return true;
return false;
}
@@ -465,7 +511,7 @@ xheader_protected_keyword_p (const char *keyword)
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
if (p->protect && strcmp (p->keyword, keyword) == 0)
if ((p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0)
return true;
return false;
}
@@ -571,8 +617,9 @@ decx (void *data, char const *keyword, char const *value, size_t size)
if (t)
t->decoder (st, keyword, value, size);
else
WARN((0, 0, _("Ignoring unknown extended header keyword `%s'"),
keyword));
WARNOPT (WARN_UNKNOWN_KEYWORD,
(0, 0, _("Ignoring unknown extended header keyword `%s'"),
keyword));
}
void
@@ -595,7 +642,11 @@ decg (void *data, char const *keyword, char const *value,
size_t size __attribute__((unused)))
{
struct keyword_list **kwl = data;
xheader_list_append (kwl, keyword, value);
struct xhdr_tab const *tab = locate_handler (keyword);
if (tab && (tab->flags & XHDR_GLOBAL))
tab->decoder (data, keyword, value, size);
else
xheader_list_append (kwl, keyword, value);
}
void
@@ -611,7 +662,7 @@ xheader_decode_global (struct xheader *xhdr)
}
}
void
static void
xheader_init (struct xheader *xhdr)
{
if (!xhdr->stk)
@@ -644,7 +695,6 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
{
size_t j = 0;
xheader_init (xhdr);
size += BLOCKSIZE;
xhdr->size = size;
xhdr->buffer = xmalloc (size + 1);
@@ -657,6 +707,9 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
if (len > BLOCKSIZE)
len = BLOCKSIZE;
if (!p)
FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
memcpy (&xhdr->buffer[j], p->buffer, len);
set_next_block_after (p);
@@ -1255,7 +1308,7 @@ sparse_numbytes_decoder (struct tar_stat_info *st,
size_t size __attribute__((unused)))
{
uintmax_t u;
if (decode_num (&u, arg, SIZE_MAX, keyword))
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
{
if (st->sparse_map_avail < st->sparse_map_size)
st->sparse_map[st->sparse_map_avail++].numbytes = u;
@@ -1303,7 +1356,7 @@ sparse_map_decoder (struct tar_stat_info *st,
e.numbytes = u;
if (!(u == e.numbytes && errno != ERANGE))
{
out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (size_t));
out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
return;
}
if (st->sparse_map_avail < st->sparse_map_size)
@@ -1453,51 +1506,53 @@ sparse_minor_decoder (struct tar_stat_info *st,
}
struct xhdr_tab const xhdr_tab[] = {
{ "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 },
{ "atime", atime_coder, atime_decoder, 0 },
{ "comment", dummy_coder, dummy_decoder, 0 },
{ "charset", dummy_coder, dummy_decoder, 0 },
{ "ctime", ctime_coder, ctime_decoder, 0 },
{ "gid", gid_coder, gid_decoder, 0 },
{ "gname", gname_coder, gname_decoder, 0 },
{ "linkpath", linkpath_coder, linkpath_decoder, 0 },
{ "mtime", mtime_coder, mtime_decoder, 0 },
{ "path", path_coder, path_decoder, 0 },
{ "size", size_coder, size_decoder, 0 },
{ "uid", uid_coder, uid_decoder, 0 },
{ "uname", uname_coder, uname_decoder, 0 },
/* Sparse file handling */
{ "GNU.sparse.name", path_coder, path_decoder,
true },
XHDR_PROTECTED },
{ "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
true },
XHDR_PROTECTED },
{ "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
true },
XHDR_PROTECTED },
{ "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
true },
XHDR_PROTECTED },
{ "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
true },
XHDR_PROTECTED },
/* tar 1.14 - 1.15.90 keywords. */
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder,
XHDR_PROTECTED },
/* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
headers, and each of them was meaningful. It confilcted with POSIX specs,
which requires that "when extended header records conflict, the last one
given in the header shall take precedence." */
{ "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
true },
XHDR_PROTECTED },
{ "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
true },
XHDR_PROTECTED },
/* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
{ "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
sparse_map_decoder, false },
sparse_map_decoder, 0 },
{ "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
true },
XHDR_PROTECTED },
/* Keeps the tape/volume label. May be present only in the global headers.
Equivalent to GNUTYPE_VOLHDR. */
{ "GNU.volume.label", volume_label_coder, volume_label_decoder, true },
{ "GNU.volume.label", volume_label_coder, volume_label_decoder,
XHDR_PROTECTED | XHDR_GLOBAL },
/* These may be present in a first global header of the archive.
They provide the same functionality as GNUTYPE_MULTIVOL header.
@@ -1506,9 +1561,11 @@ struct xhdr_tab const xhdr_tab[] = {
GNU.volume.offset keeps the offset of the start of this volume,
otherwise kept in oldgnu_header.offset. */
{ "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
true },
{ "GNU.volume.size", volume_size_coder, volume_size_decoder, true },
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, true },
XHDR_PROTECTED | XHDR_GLOBAL },
{ "GNU.volume.size", volume_size_coder, volume_size_decoder,
XHDR_PROTECTED | XHDR_GLOBAL },
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
XHDR_PROTECTED | XHDR_GLOBAL },
{ NULL, NULL, NULL, false }
{ NULL, NULL, NULL, 0 }
};

View File

@@ -1,6 +1,6 @@
# Makefile for GNU tar regression tests.
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
# 2006, 2007, 2009 Free Software Foundation, Inc.
# François Pinard <pinard@iro.umontreal.ca>, 1988.
@@ -52,6 +52,8 @@ TESTSUITE_AT = \
append.at\
append01.at\
append02.at\
append03.at\
backup01.at\
chtype.at\
comprec.at\
delete01.at\
@@ -60,6 +62,12 @@ TESTSUITE_AT = \
delete04.at\
delete05.at\
exclude.at\
exclude01.at\
exclude02.at\
exclude03.at\
exclude04.at\
exclude05.at\
exclude06.at\
extrac01.at\
extrac02.at\
extrac03.at\
@@ -67,6 +75,18 @@ TESTSUITE_AT = \
extrac05.at\
extrac06.at\
extrac07.at\
extrac08.at\
extrac09.at\
extrac10.at\
extrac11.at\
extrac12.at\
extrac13.at\
extrac14.at\
extrac15.at\
extrac16.at\
extrac17.at\
filerem01.at\
filerem02.at\
gzip.at\
grow.at\
incremental.at\
@@ -74,11 +94,22 @@ TESTSUITE_AT = \
incr02.at\
incr03.at\
incr04.at\
incr05.at\
incr06.at\
indexfile.at\
ignfail.at\
label01.at\
label02.at\
label03.at\
label04.at\
label05.at\
link01.at\
link02.at\
link03.at\
link04.at\
listed01.at\
listed02.at\
listed03.at\
long01.at\
longv7.at\
lustar01.at\
@@ -90,6 +121,8 @@ TESTSUITE_AT = \
multiv04.at\
multiv05.at\
multiv06.at\
multiv07.at\
multiv08.at\
old.at\
options.at\
options02.at\
@@ -100,11 +133,15 @@ TESTSUITE_AT = \
rename03.at\
rename04.at\
rename05.at\
remfiles01.at\
remfiles02.at\
remfiles03.at\
same-order01.at\
same-order02.at\
shortfile.at\
shortupd.at\
shortrec.at\
sigpipe.at\
sparse01.at\
sparse02.at\
sparse03.at\
@@ -115,10 +152,14 @@ TESTSUITE_AT = \
spmvp10.at\
truncate.at\
update.at\
update01.at\
update02.at\
volsize.at\
volume.at\
verbose.at\
version.at\
xform-h.at\
xform01.at\
star/gtarfail.at\
star/gtarfail2.at\
star/multi-fail.at\
@@ -140,7 +181,7 @@ clean-local:
test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
check-local: atconfig atlocal $(TESTSUITE)
$(SHELL) $(TESTSUITE)
$(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS)
check-full:
FULL_TEST=1 $(MAKE) check
@@ -149,7 +190,7 @@ check-full:
# Run the test suite on the *installed* tree.
installcheck-local:
$(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
$(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS) AUTOTEST_PATH=$(exec_prefix)/bin
## ------------ ##
@@ -163,4 +204,4 @@ genfile_SOURCES = genfile.c argcv.c argcv.h
localedir = $(datadir)/locale
INCLUDES = -I$(top_srcdir)/gnu -I../gnu -I$(top_srcdir)/gnu -I$(top_srcdir)/lib
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
LDADD = ../gnu/libgnu.a $(LIBINTL) $(LIB_CLOCK_GETTIME)
LDADD = ../gnu/libgnu.a $(LIBINTL) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)

View File

@@ -21,11 +21,11 @@
# When decoding a header tar was assigning 0 to oldgnu_header.isextended,
# which destroyed name prefix. When updating archive, modified prefix
# could have been written to disk thus producing invalid archive member.
# Reported by Adye, TJ (Tim), <T.J.Adye@rl.ac.uk>
# Reported by Adye, TJ (Tim), <T.J.Adye@rl.ac.uk>
# References:
# <7231C15EAC2F164CA6DC326D97493C8B36C25D@exchange35.fed.cclrc.ac.uk>
# http://lists.gnu.org/archive/html/bug-tar/2005-02/msg00032.html
AT_SETUP([appending files with long names])
AT_KEYWORDS([append append01])
@@ -45,4 +45,3 @@ PREFIX/file2
[],[],[],[oldgnu, ustar, posix, gnu])
AT_CLEANUP

View File

@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
# Copyright (C) 2006, 2007, 2009 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
@@ -20,19 +20,33 @@
# Using tar 1.15.x the following equivalent command sets:
#
# 1. tar cf archive file1 file2
# 1. tar cf archive file1 file2
# and
# 2. tar cfT archive /dev/null
# tar rf archive file1
# tar rt archive file2
#
# produced different archives (GNU format is assumed). Namely, in the
# second case the mode field of all members, except the first, was truncated
# to lower 3 octets (& 0777).
# produced different archives (GNU format is assumed). It was reported
# by TAMUKI Shoichi on 2006-07-21 [1].
#
# The bug was due to tar being unable to discern between GNU and OLDGNU
# formats and always assuming the latter. The main difference between
# the two is that OLDGNU preserves all bits in the mode field, whereas
# GNU format keeps only the lower 9 ones (mode & 0777).
#
# This was fixed on 2006-07-24 (commit f4e4adea80a) by making tar truncate
# the mode field even in OLDGNU format. Obviously, the fix broke the
# format backward compatibility, but it went unnoticed until 2009-10-03
# (after all, the OLDGNU format is not in much use nowadays), when
# Igor Zhbanov reported it [2].
#
# The final fix was applied on 2009-10-04.
#
# References:
# <200607210526.AA03440@tamuki.linet.gr.jp>
# http://lists.gnu.org/archive/html/bug-tar/2006-07/msg00029.html
# [1] <200607210526.AA03440@tamuki.linet.gr.jp>
# http://lists.gnu.org/archive/html/bug-tar/2006-07/msg00029.html
# [2] <f44001920910020335v4cadfesf54f6593d5124814@mail.gmail.com>
# http://lists.gnu.org/archive/html/bug-tar/2009-10/msg00006.html
# The test case below verifies that the equivalent create and append commands
# produce binary equivalent archives for all formats.
@@ -48,7 +62,7 @@ genfile --file file2
MTIME="--mtime=@0"
# For PAX archives, we need to make sure extended header names are
# reproducible and that their contents won't change with time
# reproducible and that their contents won't change with time
if test $[]TEST_TAR_FORMAT = posix; then
TAR_OPTIONS="$TAR_OPTIONS --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=mtime,delete=atime,delete=ctime"
fi

43
tests/append03.at Normal file
View File

@@ -0,0 +1,43 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([append with name transformation])
AT_KEYWORDS([append append03])
# Description: Make sure filenames are transformed during append.
AT_TAR_CHECK([
genfile --file file.1
genfile --file file.2
tar -c -f archive --transform 's/file/plik/' file.*
echo Appending
tar -r -f archive --transform 's/file/plik/' -v --show-transformed-names file.1
echo Testing
tar tf archive
],
[0],
[Appending
plik.1
Testing
plik.1
plik.2
plik.1
])
AT_CLEANUP

View File

@@ -16,17 +16,17 @@ fi
STAR_DATA_URL=ftp://ftp.berlios.de/pub/star/testscripts
if test -z "$STAR_TESTSCRIPTS"; then
STAR_TESTSCRIPTS=$TEST_DATA_DIR
fi
fi
# tarball_prereq file sum dir url
tarball_prereq() {
if test -d "$3"; then
if test -d "$3"; then
if test -r $3/$1; then
:
elif test -n "$FULL_TEST"; then
wget -q --directory-prefix=$3 $4/$1
fi
fi
fi
echo "$2 $3/$1" | md5sum --status --check - >/dev/null 2>&1
}
@@ -34,4 +34,3 @@ decho() {
echo $*
echo >&2 $*
}

49
tests/backup01.at Normal file
View File

@@ -0,0 +1,49 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# Description:
# When extracting, tar (<1.22) sometimes renamed a backup back to the
# original name (overwriting the newly-extracted file) for no good reason.
#
# Reported by: Carl Worth <cworth@cworth.org>,
# Eric Lammerts <eric@lammerts.org>
#
# References: <1249419998.4905.84.camel@yoom.home.cworth.org>
# http://lists.gnu.org/archive/html/bug-tar/2009-08/msg00005.html
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=508199
#
AT_SETUP([extracting existing dir with --backup])
AT_KEYWORDS([extract backup backup01])
AT_TAR_CHECK([
mkdir dir1 dir2
echo bla > dir1/file1
tar cf test.tar dir1 dir2
tar xfv test.tar --backup --warning=no-timestamp
],
[0],
[dir1/
dir1/file1
Renaming `dir1/file1' to `dir1/file1~'
dir2/
])
AT_CLEANUP

View File

@@ -51,9 +51,9 @@ tar --create --file=archive.2 --listed-incremental=db.2 directory
rm -r directory
echo Restore archive.1
tar -xf archive.1 --listed-incremental=/dev/null
tar -xf archive.1 --listed-incremental=/dev/null --warning=no-timestamp
echo Restore archive.2
tar -xf archive.2 --listed-incremental=/dev/null
tar -xf archive.2 --listed-incremental=/dev/null --warning=no-timestamp
find directory | sort
],
[0],

View File

@@ -29,7 +29,7 @@ echo "separator"
tar cfz archive file1
echo "separator"
mv file1 orig
tar xfv archive
tar xfv archive --warning=no-timestamp
cmp orig file1
],
[0],

View File

@@ -31,8 +31,8 @@ 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
tar --delete -f archive ./${prefix}5 &&
tar -tf archive
],
[0],
[./PREFIX[]1

View File

@@ -36,7 +36,7 @@ mkdir dir/rock
echo "Signature: 8a477f597d28d172789f06886806bc55" > dir/rock/CACHEDIR.TAG
echo "test" > dir/rock/file
for option in exclude-caches exclude-caches-under exclude-caches-all
for option in exclude-caches exclude-caches-under exclude-caches-all
do
echo OPTION $option
tar -cf archive.tar --$option -v dir 2>err | sort
@@ -45,7 +45,7 @@ do
tar tf archive.tar | sort
done
for option in exclude-tag exclude-tag-under exclude-tag-all
for option in exclude-tag exclude-tag-under exclude-tag-all
do
echo OPTION $option
tar -cf archive.tar --${option}=tagfile -v dir 2>err | sort

69
tests/exclude01.at Normal file
View File

@@ -0,0 +1,69 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Copyright (C) 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([exclude wildcards])
AT_KEYWORDS([exclude exclude01])
AT_TAR_CHECK([
AT_SORT_PREREQ
rm -rf testdir
mkdir -p testdir/dir1 testdir/dir2 testdir/dir3
touch testdir/dir1/file1
touch testdir/dir1/\*
touch testdir/dir2/file2
touch testdir/dir2/\*
touch testdir/dir3/file3
touch testdir/dir3/\*
tar cf archive --exclude=testdir/dir1/\* \
--no-wildcards \
--exclude=testdir/dir2/\* \
--wildcards \
--exclude=testdir/dir3/\* \
testdir
tar tf archive | sort
echo "NEXT"
tar cf archive testdir
tar t "testdir/dir1/*" -f archive | sort
echo "NEXT"
tar cf archive testdir/dir1
tar t --no-wildcards "testdir/dir1/*" -f archive | sort
echo "NEXT"
tar cf archive testdir
tar t --wildcards "testdir/dir1/*" -f archive | sort
rm -rf testdir
],
[0],
[testdir/
testdir/dir1/
testdir/dir2/
testdir/dir2/file2
testdir/dir3/
NEXT
testdir/dir1/*
NEXT
testdir/dir1/*
NEXT
testdir/dir1/*
testdir/dir1/file1
])
AT_CLEANUP

77
tests/exclude02.at Normal file
View File

@@ -0,0 +1,77 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Copyright (C) 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([exclude: anchoring])
AT_KEYWORDS([exclude exclude02])
AT_TAR_CHECK([
AT_SORT_PREREQ
rm -rf testdir
mkdir -p testdir
touch file1.txt
touch testdir/file1.txt
touch testdir/file2
tar cf archive --exclude="file1.txt" \
testdir
tar tf archive | sort
echo "SUB 1"
tar cf archive --no-anchored \
--exclude="file1.txt" \
testdir
tar tf archive | sort
echo "SUB 2"
tar cf archive --anchored \
--exclude="file1.txt" \
testdir
tar tf archive | sort
echo "SUB 3"
tar cf archive testdir file1.txt
tar t "file1.txt" -f archive | sort
echo "SUB 4"
tar t --no-anchored "file1.txt" -f archive | sort
echo "SUB 5"
tar t --anchored "file1.txt" -f archive | sort
rm -rf testdir file1.txt
],
[0],
[testdir/
testdir/file2
SUB 1
testdir/
testdir/file2
SUB 2
testdir/
testdir/file1.txt
testdir/file2
SUB 3
file1.txt
SUB 4
file1.txt
testdir/file1.txt
SUB 5
file1.txt
])
AT_CLEANUP

73
tests/exclude03.at Normal file
View File

@@ -0,0 +1,73 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Copyright (C) 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([exclude: wildcards match slash])
AT_KEYWORDS([exclude exclude03])
AT_TAR_CHECK([
AT_SORT_PREREQ
rm -rf testdir
mkdir -p testdir/dir1 testdir/dir2 testdir/dir3
touch testdir/\*f\*1
touch testdir/dir1/file1
touch testdir/dir1/\*
touch testdir/dir2/file2
touch testdir/dir2/\*
touch testdir/dir3/file3
touch testdir/dir3/\*
tar cf archive --exclude='testdir*f*1' \
--no-wildcards-match-slash \
--exclude='testdir*f*2' \
--wildcards-match-slash \
--exclude='testdir*f*3' \
testdir
tar tf archive | sort
echo "NEXT"
tar cf archive testdir
tar t --wildcards 'testdir/*f*1' -f archive | sort
echo "NEXT"
tar t --wildcards --no-wildcards-match-slash 'testdir/*f*1' -f archive | sort
echo "NEXT"
tar t --wildcards --wildcards-match-slash 'testdir/*f*1' -f archive | sort
rm -rf testdir
],
[0],
[testdir/
testdir/dir1/
testdir/dir1/*
testdir/dir2/
testdir/dir2/*
testdir/dir2/file2
testdir/dir3/
testdir/dir3/*
NEXT
testdir/*f*1
testdir/dir1/file1
NEXT
testdir/*f*1
NEXT
testdir/*f*1
testdir/dir1/file1
])
AT_CLEANUP

73
tests/exclude04.at Normal file
View File

@@ -0,0 +1,73 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Copyright (C) 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([exclude: case insensitive])
AT_KEYWORDS([exclude exclude04])
AT_TAR_CHECK([
AT_SORT_PREREQ
rm -rf testdir
mkdir -p testdir/dir
touch testdir/file1
touch testdir/file2
touch testdir/file3
touch testdir/file4
touch testdir/dir/File1
touch testdir/dir/File2
touch testdir/dir/File3
touch testdir/dir/File4
tar cf archive --exclude=FILE2 \
--exclude=file1 \
--ignore-case \
--exclude=file3 \
--no-ignore-case \
--exclude=FILE2 \
--exclude=file4 \
testdir
tar tf archive | sort
echo "SUB 1"
tar cf archive testdir
tar t --wildcards --wildcards-match-slash '*File2' -f archive | sort
echo "SUB 2"
tar t --wildcards --wildcards-match-slash --ignore-case '*File2' -f archive | sort
echo "SUB 3"
tar t --wildcards --wildcards-match-slash --no-ignore-case '*File2' -f archive | sort
rm -rf testdir
],
[0],
[testdir/
testdir/dir/
testdir/dir/File1
testdir/dir/File2
testdir/dir/File4
testdir/file2
SUB 1
testdir/dir/File2
SUB 2
testdir/dir/File2
testdir/file2
SUB 3
testdir/dir/File2
])
AT_CLEANUP

59
tests/exclude05.at Normal file
View File

@@ -0,0 +1,59 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Copyright (C) 2009, 2010 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Test the functioning of many items in an exclude list (should run quickly)
AT_SETUP([exclude: lots of excludes])
AT_KEYWORDS([exclude exclude05])
AT_TAR_CHECK([
AT_SORT_PREREQ
rm -rf testdir exclfile
mkdir -p testdir
awk 'BEGIN {for (i=9; i < 100; ++i ) { print "testdir/file" i; }}' < /dev/null | \
while read name
do
genfile --file $name
done
awk 'BEGIN {for (i=1000000; i >= 12; --i ) { print "testdir/file" i }}' < /dev/null > exclfile
tar cf archive --anchored --exclude-from=exclfile \
testdir
tar tf archive | sort
echo "NEXT"
tar cf archive --exclude-from=exclfile \
testdir
tar tf archive | sort
rm -rf testdir exclfile
],
[0],
[testdir/
testdir/file10
testdir/file11
testdir/file9
NEXT
testdir/
testdir/file10
testdir/file11
testdir/file9
])
AT_CLEANUP

47
tests/exclude06.at Normal file
View File

@@ -0,0 +1,47 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Copyright (C) 2010 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Tar 1.23 would fail to exclude names longer that 100 characters from
# pax format archives.
#
# Reported-by: Matthew Peterson <mrpeterson2@gmail.com>
# References: <AANLkTin0teb1dcl0HCNquHxvN4HQnJmP6aK7CJCqy0sd@mail.gmail.com>
# http://lists.gnu.org/archive/html/help-tar/2010-06/msg00000.html
AT_SETUP([exclude: long files in pax archives])
AT_KEYWORDS([exclude exclude06])
m4_define([test_base_dir],[one/two/three/four/five/six/seven/eight/nine/ten/eleven/twelve/thirteen/fourteen/fifteen/sixteen/seventeen])
AT_TAR_CHECK([
AT_TAR_MKHIER(test_base_dir)
genfile --length 20 -f test_base_dir[/1.txt]
genfile --length 20 -f test_base_dir[/1.c]
tar cf archive.tar test_base_dir
mkdir out
tar -C out -xf archive.tar --exclude='*.txt' --warning=no-timestamp
find out -type f
],
[0],
[[out/]test_base_dir[/1.c]
],
[],
[],
[],
[pax])
AT_CLEANUP

View File

@@ -27,7 +27,7 @@ AT_TAR_CHECK([
mkdir directory
touch directory/file
tar cf archive directory || exit 1
tar xf archive || exit 1
tar xf archive --warning=no-timestamp || exit 1
])
AT_CLEANUP

View File

@@ -27,7 +27,7 @@ AT_TAR_CHECK([
mkdir directory
tar -cPvf archive directory/../directory
echo separator
tar -xPvf archive],
tar -xPvf archive --warning=no-timestamp],
[0],
[directory/../directory/
separator

View File

@@ -36,7 +36,7 @@ tar -cf archive ./file1 directory
tar -tf archive \
--exclude='./*1' \
--exclude='d*/*1' \
--exclude='d*/s*/*2' | sort
--exclude='d*/s*/*2' | sort
],
[0],
[directory/

View File

@@ -30,16 +30,16 @@
AT_SETUP([extracting selected members from pax])
AT_KEYWORDS([extract extract05])
AT_DATA([list],
AT_DATA([list],
[jeden
cztery
])
AT_TAR_CHECK([
genfile --sparse --file sparsefile 0 ABCD 1M EFGH 2000K IJKL || AT_SKIP_TEST
genfile --length 118 --file jeden
genfile --length 223 --file dwa
genfile --length 517 --file trzy
genfile --sparse --file sparsefile 0 ABCD 1M EFGH 2000K IJKL
genfile --length 110 --file cztery
tar cf archive jeden dwa trzy cztery || exit 1
@@ -47,7 +47,7 @@ tar cf archive jeden dwa trzy cztery || exit 1
mkdir dir
cd dir
tar xvfT ../archive ../../list || exit 1
tar xvfT ../archive ../../list --warning=no-timestamp || exit 1
cd ..
],

View File

@@ -23,7 +23,7 @@
# permissions than your umask. In this case, the permissions of the
# existing directory will toggle between the version which complies with
# your umask (which would be correct, without -p) and the version from the
# tarfile.
# tarfile.
#
# Reported by: Ian Jackson <iwj@ubuntu.com>
#
@@ -41,7 +41,7 @@ umask 022
# Make sure user's umask is honored, even if we are superuser
TAR_OPTIONS="$TAR_OPTIONS --no-same-permissions"
# Create a directory
# Create a directory
mkdir directory
chmod 777 directory
genfile --stat=mode:777 directory
@@ -54,10 +54,10 @@ chmod 755 directory
genfile --stat=mode:777 directory
# ... and attempt to restore it twice
tar xf arc directory
tar xf arc directory --warning=no-timestamp
genfile --stat=mode:777 directory
tar xf arc directory
tar xf arc directory --warning=no-timestamp
genfile --stat=mode:777 directory
# After both restores, the directory mode should be 755

View File

@@ -28,13 +28,15 @@ AT_SETUP([extracting symlinks to a read-only dir])
AT_KEYWORDS([extract extract07 read-only symlink])
AT_TAR_CHECK([
AT_UNPRIVILEGED_PREREQ
echo Prepare the directory
mkdir dir
genfile -f foo
cd dir
ln -s ../foo .
cd ..
chmod -w dir
chmod a-w dir
echo Create the archive
tar cf archive dir || exit 1
@@ -52,8 +54,6 @@ Extract
dir/
dir/foo
],
[],[],[ustar]) # Testing one format is enough
[],[],[],[ustar]) # Testing one format is enough
AT_CLEANUP

52
tests/extrac08.at Normal file
View File

@@ -0,0 +1,52 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
# Copyright (C) 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# Description:
# When extracting, tar (<1.22) did not restore directory permissions on
# existing directories.
# This was discovered when fixing debian bug #508199. See also backup01.at.
#
# Reported by: Carl Worth <cworth@cworth.org>,
#
# References: <1249419998.4905.84.camel@yoom.home.cworth.org>
# http://lists.gnu.org/archive/html/bug-tar/2009-08/msg00005.html
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=508199
#
AT_SETUP([restoring mode on existing directory])
AT_KEYWORDS([extract extrac08])
AT_TAR_CHECK([
umask 000
mkdir dir
chmod 755 dir
echo bla > dir/file
tar cf test.tar dir
chmod 700 dir
tar xfv test.tar --warning=no-timestamp
genfile --stat=mode.777 dir
],
[0],
[dir/
dir/file
755
])
AT_CLEANUP

48
tests/extrac09.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) 2010 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This checks for the --listed-incremental bug reported by J Chapman Flack at
# http://lists.gnu.org/archive/html/bug-tar/2010-06/msg00000.html
AT_SETUP([no need to save dir with unreadable . and ..])
AT_KEYWORDS([extract extrac09])
AT_TAR_CHECK([
AT_UNPRIVILEGED_PREREQ
mkdir dir
mkdir dir/sub
mkdir dir/sub/extract
genfile --file dir/sub/f
cd dir/sub
tar -cf archive.tar f
chmod a-r . ..
tar -xvf archive.tar -C extract f
status=$?
chmod a+r . ..
cmp f extract/f || status=$?
exit $status
],
[0],
[f
],
[],[],[],[gnu])
AT_CLEANUP

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