Compare commits
144 Commits
release_1_
...
release_1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ecd700fbfb | ||
|
|
f1fed3996a | ||
|
|
b32edff5aa | ||
|
|
3913675640 | ||
|
|
b8feb2b142 | ||
|
|
3fe59ed5ef | ||
|
|
5af29cb944 | ||
|
|
7dd57ebdfa | ||
|
|
e23d123b93 | ||
|
|
6398c7a79c | ||
|
|
28e91b48f6 | ||
|
|
3c0bedd494 | ||
|
|
c520964e84 | ||
|
|
acb77ac5bd | ||
|
|
983113b140 | ||
|
|
9447e799ab | ||
|
|
502abd93bd | ||
|
|
241b72ffad | ||
|
|
c5c196310e | ||
|
|
14efeb9f95 | ||
|
|
efe26f98ec | ||
|
|
4bde4f39d0 | ||
|
|
fc5e44c99c | ||
|
|
098ad10c71 | ||
|
|
6e08ab7694 | ||
|
|
cecb7ac8e6 | ||
|
|
ea964cce81 | ||
|
|
e3fdb78d4b | ||
|
|
d945888643 | ||
|
|
ecbcb7b6d7 | ||
|
|
59146768ef | ||
|
|
0fb3020da0 | ||
|
|
d7db30d0e8 | ||
|
|
8da503cad6 | ||
|
|
c743301494 | ||
|
|
de328a580a | ||
|
|
bad4b0006c | ||
|
|
e985feb292 | ||
|
|
fbc54fa337 | ||
|
|
45a574151a | ||
|
|
0adf4027f5 | ||
|
|
fce1c1c8cb | ||
|
|
372ac37d01 | ||
|
|
a9895fd20c | ||
|
|
a59c819beb | ||
|
|
57b11473b0 | ||
|
|
fbcadc9592 | ||
|
|
3b219f943e | ||
|
|
37ddfb0b7e | ||
|
|
09f039050e | ||
|
|
34795cedb7 | ||
|
|
9764a6b1d3 | ||
|
|
a1a15e3202 | ||
|
|
0ab5e64ac0 | ||
|
|
0a694a16e5 | ||
|
|
b3b15f7cbc | ||
|
|
8c662c9f29 | ||
|
|
427b3b8c79 | ||
|
|
c1b30c268f | ||
|
|
cc40c57a37 | ||
|
|
ab6dd4948d | ||
|
|
b4bcb97e38 | ||
|
|
9c194c9942 | ||
|
|
80a6ef7d94 | ||
|
|
9b31db388e | ||
|
|
f6edb92580 | ||
|
|
e21d54e8cd | ||
|
|
c79f0d06bc | ||
|
|
2c97cb7ea2 | ||
|
|
fc61c17410 | ||
|
|
2981fcc5cb | ||
|
|
40dea1ae7f | ||
|
|
b60e56fdb6 | ||
|
|
340dbf5aab | ||
|
|
c1d3d13493 | ||
|
|
67b4f3519d | ||
|
|
0ba8bdf5f3 | ||
|
|
8d3cc6c3cf | ||
|
|
3f4a6d83f0 | ||
|
|
a3f1d933cc | ||
|
|
e8e0b6cb7a | ||
|
|
338add8d10 | ||
|
|
46b07a52f9 | ||
|
|
a06b3a29fb | ||
|
|
6f02669c7b | ||
|
|
e1e1f87eb4 | ||
|
|
bffe1074aa | ||
|
|
9a3e8a6f43 | ||
|
|
a0fd0d95e2 | ||
|
|
3925776b41 | ||
|
|
762be4f2bd | ||
|
|
b7899bb121 | ||
|
|
6e196273a4 | ||
|
|
bdb9de4b1e | ||
|
|
c4acbdaa97 | ||
|
|
c3fa22fc80 | ||
|
|
706bd01915 | ||
|
|
0057cd6803 | ||
|
|
45cf3a7426 | ||
|
|
28f2669b15 | ||
|
|
166b7c7d02 | ||
|
|
cd91cd3c62 | ||
|
|
cac45fffc5 | ||
|
|
0c6c288b53 | ||
|
|
87240ee7c4 | ||
|
|
84a55f12e5 | ||
|
|
a7e9b6a17b | ||
|
|
f0ceef8596 | ||
|
|
63e092548a | ||
|
|
7cb84c25ee | ||
|
|
4dfcd6c054 | ||
|
|
2947023d27 | ||
|
|
92773d860f | ||
|
|
dccb3806a6 | ||
|
|
0d8e324912 | ||
|
|
cef4d5e838 | ||
|
|
ba954ea1e1 | ||
|
|
006c1efbe8 | ||
|
|
aeffa4f266 | ||
|
|
829b3feb26 | ||
|
|
88347995b2 | ||
|
|
acd833fb98 | ||
|
|
51aee274e8 | ||
|
|
2b1bffbad6 | ||
|
|
df59690240 | ||
|
|
1bcbbcf1ff | ||
|
|
ac5288c1ac | ||
|
|
67a1a0eac5 | ||
|
|
471c0f76cd | ||
|
|
755c246588 | ||
|
|
5944f452b0 | ||
|
|
f74cab3a93 | ||
|
|
01c4475b17 | ||
|
|
b7d206cb1e | ||
|
|
c30c4ffb9f | ||
|
|
b216fed634 | ||
|
|
0d6720288b | ||
|
|
da760e3faa | ||
|
|
af30244849 | ||
|
|
be34933b63 | ||
|
|
8f390db92f | ||
|
|
705fab49eb | ||
|
|
f14558de94 | ||
|
|
67cad0792b |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -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
18
COPYING
@@ -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>.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
256
NEWS
@@ -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
7
README
@@ -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:
|
||||
|
||||
|
||||
@@ -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
4
THANKS
@@ -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
26
acinclude.m4
Normal 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
508
bootstrap
@@ -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:
|
||||
|
||||
26
configure.ac
26
configure.ac
@@ -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],
|
||||
|
||||
@@ -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
6
doc/.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
110
doc/fdl.texi
110
doc/fdl.texi
@@ -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
|
||||
|
||||
@@ -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 & GNU inquiries to
|
||||
Please send FSF & 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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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{}.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
1484
doc/tar.texi
1484
doc/tar.texi
File diff suppressed because it is too large
Load Diff
@@ -18,5 +18,3 @@
|
||||
@end ifclear
|
||||
@xopindex{\option\, summary}
|
||||
@end macro
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
445
lib/modechange.c
445
lib/modechange.c
@@ -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
852
rebox.el
@@ -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))))
|
||||
@@ -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 !!!!!\"
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
973
src/Makefile.in
973
src/Makefile.in
@@ -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:
|
||||
@@ -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>.
|
||||
720
src/ansi2knr.c
720
src/ansi2knr.c
@@ -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;
|
||||
}
|
||||
163
src/arith.c
163
src/arith.c
@@ -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 */
|
||||
@@ -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;
|
||||
|
||||
620
src/buffer.c
620
src/buffer.c
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
242
src/common.h
242
src/common.h
@@ -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);
|
||||
|
||||
@@ -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 (¤t_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, ¤t_stat_info, ¤t_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 (¤t_stat_info, -1);
|
||||
print_header (¤t_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 (¤t_header,
|
||||
¤t_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 (¤t_header, ¤t_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 (¤t_header, ¤t_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 (¤t_stat_info);
|
||||
}
|
||||
|
||||
751
src/create.c
751
src/create.c
File diff suppressed because it is too large
Load Diff
12
src/delete.c
12
src/delete.c
@@ -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 (¤t_header,
|
||||
¤t_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 (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
|
||||
xheader_decode (¤t_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);
|
||||
|
||||
759
src/diffarch.c
759
src/diffarch.c
@@ -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
37
src/exit.c
Normal 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 ();
|
||||
}
|
||||
1046
src/extract.c
1046
src/extract.c
File diff suppressed because it is too large
Load Diff
@@ -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
677
src/gnu.c
@@ -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;
|
||||
}
|
||||
378
src/incremen.c
378
src/incremen.c
@@ -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;
|
||||
}
|
||||
|
||||
368
src/list.c
368
src/list.c
@@ -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 (¤t_stat_info);
|
||||
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_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, ¤t_stat_info,
|
||||
¤t_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,
|
||||
¤t_stat_info, ¤t_format, 0);
|
||||
skip_member ();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
transform_stat_info (current_header->header.typeflag,
|
||||
¤t_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 (¤t_header, ¤t_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, ¤t_stat_info, ¤t_format, 0);
|
||||
/* Print the header block. */
|
||||
if (verbose_option)
|
||||
print_header (¤t_stat_info, block_ordinal);
|
||||
print_header (¤t_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 = ¤t_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, ¤t_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 (¤t_stat_info);
|
||||
mv_begin_read (¤t_stat_info);
|
||||
|
||||
if (current_stat_info.is_sparse)
|
||||
sparse_skip_file (¤t_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 (¤t_header, ¤t_stat_info, read_header_auto)
|
||||
== HEADER_SUCCESS)
|
||||
{
|
||||
decode_header (current_header,
|
||||
¤t_stat_info, ¤t_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 ();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
411
src/misc.c
411
src/misc.c
@@ -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;
|
||||
}
|
||||
|
||||
218
src/msd_dir.c
218
src/msd_dir.c
@@ -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(®, &nreg, &sreg);
|
||||
#else
|
||||
intdos(®, &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(®, &nreg, &sreg);
|
||||
#else
|
||||
reg.x.dx = (int) dtapnt;
|
||||
intdos(®, &nreg);
|
||||
#endif
|
||||
}
|
||||
@@ -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();
|
||||
543
src/names.c
543
src/names.c
@@ -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;
|
||||
|
||||
178
src/open3.c
178
src/open3.c
@@ -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 */
|
||||
69
src/open3.h
69
src/open3.h
@@ -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
1256
src/port.c
File diff suppressed because it is too large
Load Diff
215
src/port.h
215
src/port.h
@@ -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__ */
|
||||
@@ -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. */
|
||||
|
||||
|
||||
|
||||
|
||||
124
src/sparse.c
124
src/sparse.c
@@ -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,
|
||||
|
||||
42
src/suffix.c
42
src/suffix.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
138
src/system.c
138
src/system.c
@@ -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);
|
||||
|
||||
24
src/tar.h
24
src/tar.h
@@ -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
|
||||
|
||||
240
src/tcexparg.c
240
src/tcexparg.c
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
158
src/unlink.c
Normal 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++;
|
||||
}
|
||||
62
src/update.c
62
src/update.c
@@ -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 (¤t_header,
|
||||
¤t_stat_info,
|
||||
read_header_auto);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -128,6 +130,8 @@ update_archive (void)
|
||||
|
||||
decode_header (current_header, ¤t_stat_info,
|
||||
¤t_format, 0);
|
||||
transform_stat_info (current_header->header.typeflag,
|
||||
¤t_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 ();
|
||||
}
|
||||
|
||||
@@ -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
99
src/warning.c
Normal 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;
|
||||
}
|
||||
161
src/xheader.c
161
src/xheader.c
@@ -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 }
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
43
tests/append03.at
Normal 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
|
||||
@@ -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
49
tests/backup01.at
Normal 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
|
||||
@@ -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],
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
69
tests/exclude01.at
Normal 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
77
tests/exclude02.at
Normal 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
73
tests/exclude03.at
Normal 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
73
tests/exclude04.at
Normal 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
59
tests/exclude05.at
Normal 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
47
tests/exclude06.at
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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 ..
|
||||
],
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
52
tests/extrac08.at
Normal 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
48
tests/extrac09.at
Normal 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
Reference in New Issue
Block a user