Compare commits
318 Commits
release_1_
...
release_1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b500277de7 | ||
|
|
002bf86821 | ||
|
|
fcde08534b | ||
|
|
a5db4ba5cb | ||
|
|
20ab569dc3 | ||
|
|
f86e0605d0 | ||
|
|
4423e1743e | ||
|
|
8d087fbb0b | ||
|
|
dc72f4d114 | ||
|
|
576e99a21c | ||
|
|
fc58a8bd98 | ||
|
|
7808b6981b | ||
|
|
852895847f | ||
|
|
b0902369e7 | ||
|
|
da546e69af | ||
|
|
f24b30ec8c | ||
|
|
93906c238d | ||
|
|
9df17e6005 | ||
|
|
efbf4cce0b | ||
|
|
7fe7adcbb9 | ||
|
|
8e10d93d01 | ||
|
|
3cb4693c65 | ||
|
|
48a546b02c | ||
|
|
46da9968df | ||
|
|
29a6964af3 | ||
|
|
62497f0e26 | ||
|
|
c86b0c2149 | ||
|
|
8b6a1a5990 | ||
|
|
8cfcbfddd4 | ||
|
|
e9e94531f0 | ||
|
|
288dd472e3 | ||
|
|
8706301479 | ||
|
|
45ccda1193 | ||
|
|
1689ed4388 | ||
|
|
2af87fa277 | ||
|
|
95a51b93d0 | ||
|
|
f504821589 | ||
|
|
a09e840507 | ||
|
|
eb7e2aa933 | ||
|
|
717a07e208 | ||
|
|
f0a1f78196 | ||
|
|
7f21a4d3f5 | ||
|
|
2bd9c15391 | ||
|
|
481572c63f | ||
|
|
47da28892e | ||
|
|
5c5f62e0dc | ||
|
|
49f3145092 | ||
|
|
ca8cb48d02 | ||
|
|
b4afdd0e28 | ||
|
|
6e8bca8b56 | ||
|
|
00054440c7 | ||
|
|
a2e0cd0c05 | ||
|
|
f6c25db5fe | ||
|
|
6d5cfeb757 | ||
|
|
3de5db2a15 | ||
|
|
db9b81eb6b | ||
|
|
f3c8bc7c3f | ||
|
|
576e1fcd6a | ||
|
|
3125d311e1 | ||
|
|
74ce228f6d | ||
|
|
d28eee6b4f | ||
|
|
d3fd92c6fb | ||
|
|
f7077dd38b | ||
|
|
5cb79ed519 | ||
|
|
b41b004638 | ||
|
|
e3d28d84bd | ||
|
|
2c06a80918 | ||
|
|
570a2c5f3d | ||
|
|
b6979c7278 | ||
|
|
751b61ab25 | ||
|
|
738fb9c2f4 | ||
|
|
0ea6e68655 | ||
|
|
dd549cc257 | ||
|
|
28b44aaacb | ||
|
|
88cb5008a6 | ||
|
|
bff9c3637d | ||
|
|
1fe0c83de4 | ||
|
|
077d7bceff | ||
|
|
162bbcb45f | ||
|
|
69007e652a | ||
|
|
95d7b37a34 | ||
|
|
ddff3e9038 | ||
|
|
47560a0498 | ||
|
|
6e5e4420f4 | ||
|
|
26538c9bfc | ||
|
|
8a834dfa10 | ||
|
|
cf199be81d | ||
|
|
cfebb3cedf | ||
|
|
87369861f9 | ||
|
|
f547c0332d | ||
|
|
57e5a7a1e7 | ||
|
|
f678e47eb0 | ||
|
|
f92cb1fe16 | ||
|
|
beca89bccb | ||
|
|
a40e565719 | ||
|
|
17f99bc6f1 | ||
|
|
7b5e803963 | ||
|
|
20dcc4d122 | ||
|
|
9cf743abf8 | ||
|
|
2f6c03cba2 | ||
|
|
cd7bdd4076 | ||
|
|
d99ecd6c75 | ||
|
|
53358983eb | ||
|
|
7c43775f4f | ||
|
|
df7b55a8f6 | ||
|
|
d8ac237663 | ||
|
|
f39eadac4b | ||
|
|
8ebbef8a15 | ||
|
|
616e421350 | ||
|
|
cbc51277aa | ||
|
|
8c0146d2c9 | ||
|
|
4bfa82acd5 | ||
|
|
d350b509c0 | ||
|
|
383701a590 | ||
|
|
545e4cd69d | ||
|
|
a974e9c997 | ||
|
|
4a3564fe85 | ||
|
|
6bd463c97e | ||
|
|
3c4e51fad6 | ||
|
|
4ac671c49b | ||
|
|
085cace180 | ||
|
|
d36f5a3cc3 | ||
|
|
696338043e | ||
|
|
b997c90f9e | ||
|
|
643a8844a5 | ||
|
|
099f71f78d | ||
|
|
07ef59cab8 | ||
|
|
0708c153e4 | ||
|
|
1cd2725227 | ||
|
|
6a61354ea0 | ||
|
|
273dfb16cc | ||
|
|
2a61a3701f | ||
|
|
5bb0433507 | ||
|
|
8c75b1387a | ||
|
|
debc485626 | ||
|
|
6689e8db4f | ||
|
|
9a82a0215b | ||
|
|
03858cf583 | ||
|
|
7a5a3708cb | ||
|
|
02bf3a96a9 | ||
|
|
79138eaef1 | ||
|
|
d88b2a613f | ||
|
|
1e1fc0336b | ||
|
|
02533d1a60 | ||
|
|
d0dd0473f7 | ||
|
|
8f70a3294c | ||
|
|
a6cc856fbe | ||
|
|
51b272f572 | ||
|
|
1f9b376c90 | ||
|
|
9fe65e2520 | ||
|
|
fa307a6655 | ||
|
|
49bd102a1b | ||
|
|
189e436474 | ||
|
|
9708b248e8 | ||
|
|
afcdb89492 | ||
|
|
aea443b9e8 | ||
|
|
881e5626c5 | ||
|
|
67ae04ba31 | ||
|
|
2807513841 | ||
|
|
bb0af96c54 | ||
|
|
ec586b37e0 | ||
|
|
a7fc5ecead | ||
|
|
649b747913 | ||
|
|
bb971a1e8a | ||
|
|
50a57a0147 | ||
|
|
1584b72ff2 | ||
|
|
065cf0958c | ||
|
|
2a55b4b037 | ||
|
|
27225be1a3 | ||
|
|
73d0d1a0f8 | ||
|
|
ff2bc5c0a1 | ||
|
|
24214ca5d5 | ||
|
|
777042e024 | ||
|
|
1801399830 | ||
|
|
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 |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -11,21 +11,25 @@
|
||||
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/*.h
|
||||
gnu/*/
|
||||
gnu/.gitignore
|
||||
gnu/charset.alias
|
||||
gnulib
|
||||
libtool
|
||||
m4
|
||||
paxutils
|
||||
rmt
|
||||
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>.
|
||||
|
||||
|
||||
19
ChangeLog.1
19
ChangeLog.1
@@ -1,26 +1,23 @@
|
||||
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.
|
||||
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
Free Software Foundation, Inc.
|
||||
Copyright 1989-1997, 2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Tar.
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU Tar is free software; you can redistribute it and/or modify
|
||||
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.
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU Tar is distributed in the hope that it will be useful,
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
----- ChangeLog -----
|
||||
|
||||
113
ChangeLog.CVS
113
ChangeLog.CVS
@@ -1,3 +1,24 @@
|
||||
Currently the ChangeLog is generated automatically from the Git
|
||||
revision history, but from 1997 to 2009 the ChangeLog file was
|
||||
maintained by hand, under CVS. This file records the older log.
|
||||
|
||||
Copyright 1997-2001, 2003-2009, 2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
2009-03-05 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/incremen.c: --no-recursive works with --incremental.
|
||||
@@ -5,7 +26,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 +55,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 +84,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 +94,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 +107,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 +120,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 +132,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 +178,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 +214,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 +252,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 +277,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 +288,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 +324,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>
|
||||
|
||||
@@ -1007,7 +1028,7 @@
|
||||
this has undefined behavior. Likewise for assigning arbitrary
|
||||
uintmax_t values to other types.
|
||||
(read_negative_num, read_unsigned_num, read_timespec):
|
||||
New functions, to check input values a bit more carefuly.
|
||||
New functions, to check input values a bit more carefully.
|
||||
(read_num): Use read_unsigned_num. New arg MAX_VAL;
|
||||
all callers changed.
|
||||
(read_incr_db_2): Use these new functions.
|
||||
@@ -1187,7 +1208,7 @@
|
||||
* src/delete.c: Remove second argument from calls to name_scan
|
||||
* src/update.c: Likewise
|
||||
* src/incremen.c (procdir): Use is_individual_file to check for
|
||||
files explicitely specified in the command line. Fixes bug
|
||||
files explicitly specified in the command line. Fixes bug
|
||||
reported by Dat Head on 19 Jun 2006 (descending into mountpoints
|
||||
with --one-file-system in use)
|
||||
* src/misc.c (maybe_backup_file): Second argument is bool
|
||||
@@ -1246,7 +1267,7 @@
|
||||
* src/delete.c (records_skipped): Remove static qualifier, the
|
||||
variable is used by print_total_stats in buffer.c
|
||||
* src/extract.c (check_time): Use volume_start_time when checking
|
||||
for timestamp plausability.
|
||||
for timestamp plausibility.
|
||||
* src/tar.c: (options, parse_opt): Allow for optional argument to
|
||||
the --totals option, which specifies a signal upon delivery of which
|
||||
the statistics must be output.
|
||||
@@ -1304,7 +1325,7 @@
|
||||
|
||||
* src/transform.c (set_transform_expr,_transform_name_to_obstack):
|
||||
Implement NUMBER flag.
|
||||
(add_char_segment): Fix length assignement
|
||||
(add_char_segment): Fix length assignment
|
||||
|
||||
* doc/tar.texi: Update
|
||||
|
||||
@@ -1361,7 +1382,7 @@
|
||||
* doc/tar.texi: Update
|
||||
* configure.ac (AM_INIT_AUTOMAKE): Use tar-ustar option. Raise
|
||||
version requirement to 1.9
|
||||
* src/common.h (struct name): Refactured
|
||||
* src/common.h (struct name): Refactored
|
||||
(warn_regex_usage): New variable.
|
||||
(dump_file): First argument is const char*.
|
||||
(name_init,name_add): Removed
|
||||
@@ -1736,13 +1757,13 @@
|
||||
* src/common.h (struct name): New member `explicit'. Remove unused
|
||||
member `isdir'.
|
||||
* src/incremen.c (procdir): If name_scan() returns something,
|
||||
check if it was explicitely given in the command line
|
||||
check if it was explicitly given in the command line
|
||||
* src/names.c (addname,add_hierarchy_to_namelist): Initialize
|
||||
explicit member appropriately.
|
||||
|
||||
* src/incremen.c (procdir): If --one-file-system is given and a
|
||||
directory is found to be on another device, *and* this directory
|
||||
is explicitely given in the command line, then do not omit it.
|
||||
is explicitly given in the command line, then do not omit it.
|
||||
|
||||
2005-12-11 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
@@ -1777,7 +1798,7 @@
|
||||
(mode_to_chars, off_to_chars, size_to_chars, time_to_chars)
|
||||
(uid_to_chars, uintmax_to_chars): Return bool
|
||||
(to_chars): Return bool
|
||||
(start_header): Check return values of convertion routines. Fail
|
||||
(start_header): Check return values of conversion routines. Fail
|
||||
if unable to store data in the header.
|
||||
|
||||
2005-12-07 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
@@ -2077,13 +2098,13 @@
|
||||
archives.
|
||||
* src/incremen.c (dumpdir_size, get_gnu_dumpdir): New functions.
|
||||
(purge_directory): Use stat_info.dumpdir instead of getting its
|
||||
value explicitely.
|
||||
value explicitly.
|
||||
* src/list.c (list_archive): Handle incremental backups in pax
|
||||
format.
|
||||
(decode_header): Initialize stat_info.dumpdir
|
||||
* src/sparse.c (sparse_diff_file): Bugfix: set seekable.
|
||||
(pax_dump_header): Store sparse map in GNU.sparse.map. If this
|
||||
variable has been explicitely deleted, use GNU.sparse.offset/
|
||||
variable has been explicitly deleted, use GNU.sparse.offset/
|
||||
GNU.sparse.numbytes variables.
|
||||
* src/tar.c (decode_options): Incremental options are allowed with
|
||||
--format=pax
|
||||
@@ -2161,7 +2182,7 @@
|
||||
|
||||
* bootstrap: Fix quoting in help output.
|
||||
(update_po): Use backward-compatible wget option --cache instead
|
||||
of deprecated -C to accomodate for wget 1.10.
|
||||
of deprecated -C to accommodate for wget 1.10.
|
||||
Changes proposed by Eric Blake
|
||||
* THANKS: Add Eric Blake
|
||||
|
||||
@@ -2712,7 +2733,7 @@
|
||||
* src/list.c: Likewise
|
||||
|
||||
* tests/multiv03.at: Modified to match the new behavior
|
||||
* tests/multiv04.at: New file. Test splittind directory members between
|
||||
* tests/multiv04.at: New file. Test splitting directory members between
|
||||
the archive volumes.
|
||||
* tests/Makefile.am: Add multiv04.at
|
||||
* tests/testsuite.at: Likewise.
|
||||
@@ -4466,7 +4487,7 @@
|
||||
|
||||
* src/create.c: Do not zero-terminate name field if
|
||||
the name is exactly 100 characters long.
|
||||
(write_ustar_long_name): Fixed cheking for unsplittable
|
||||
(write_ustar_long_name): Fixed checking for unsplittable
|
||||
names.
|
||||
|
||||
2003-11-14 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
@@ -5163,7 +5184,7 @@
|
||||
interface.
|
||||
(child_open_for_compress): Do not increase size to BLOCKSIZE.
|
||||
(open_archive): Open index file name.
|
||||
Strip trailing slahes from file names.
|
||||
Strip trailing slashes from file names.
|
||||
(flush_write): Set size to 0 if not saving names.
|
||||
(flush_write, flush_read): Use safer_name_suffix rather than
|
||||
inline code.
|
||||
@@ -5996,7 +6017,7 @@
|
||||
(decode_options): Dates that look like an absolute path name,
|
||||
or that start with '.', are presumed to be file names whose
|
||||
dates are taken.
|
||||
Remove 'I' as an aliase for 'T'.
|
||||
Remove 'I' as an alias for 'T'.
|
||||
Update copyright.
|
||||
|
||||
* src/extract.c (<time.h>): Do not include; system.h now does this.
|
||||
@@ -8806,26 +8827,6 @@
|
||||
See ChangeLog.1 for earlier changes.
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
Local Variables:
|
||||
mode: change-log
|
||||
|
||||
70
ChangeLog.amend
Normal file
70
ChangeLog.amend
Normal file
@@ -0,0 +1,70 @@
|
||||
# Fix typos in tar ChangeLog entries generated from git log
|
||||
|
||||
f24b30ec8ca1851b7bd14694241de3b38194c99c
|
||||
s/commit 2bd9c153_\./commit 2bd9c153)./
|
||||
|
||||
29a6964af3e1baabe978ce608e0466e1250d08ab
|
||||
s/ORDER \(none, name, or order\)\./ORDER (none, name, or inode)./
|
||||
|
||||
2af87fa2776c8125a587a9b0c2c4fae3bf921ff7
|
||||
s/contant\./content./
|
||||
|
||||
2bd9c15391b0bd6ef0bff76aebf09cfb53003199
|
||||
s/ocurrence/occurrence/
|
||||
|
||||
47da28892e6860a3a6fc06745f640e3bb878c757
|
||||
s/aruond/around/
|
||||
|
||||
f7077dd38b018f19d3a5c7df6accc6b07b8a2356
|
||||
s/absoulte/absolute/
|
||||
|
||||
28b44aaacb45680aa6640e0a6d7ceab04cfdbf11
|
||||
s/warniing/warning/
|
||||
|
||||
47560a0498bde20621ce4e367b1d68bf8cd8f1a3
|
||||
s/interacton/interaction/
|
||||
|
||||
26538c9bfc5fd726d625bef5fa3f08212d50173a
|
||||
s/consuption/consumption/;
|
||||
s/misfunctioned/malfunctioned/;
|
||||
s/misssing/missing/;
|
||||
|
||||
696338043e52f440853e1143c52b81b41cd59723
|
||||
s/suuport/support/
|
||||
|
||||
643a8844a578ff146cfe746fe6091d29502b6c40
|
||||
s/incrfental/incremental/;
|
||||
s/afterwards/afterward/;
|
||||
|
||||
03858cf583ce299b836d8a848967ce290a6bf303
|
||||
s/Peformance/Performance/
|
||||
|
||||
fa307a665545753b6729191fd2559ce872fa470a
|
||||
s/filags/flags/
|
||||
|
||||
73d0d1a0f883be5f67534362c99382f1eae8d178
|
||||
s/contais/contains/
|
||||
|
||||
5af29cb944c84e2d539ce9df527d63c29f6012b9
|
||||
s/appendig/appending/
|
||||
|
||||
7dd57ebdfa9ac0d2af4622449f45b5025f6c184f
|
||||
s/encounted/encountered/
|
||||
|
||||
ecbcb7b6d74c2d69386c8d7e435486a4690c9993
|
||||
s/inadvertantly/inadvertently/
|
||||
|
||||
4dfcd6c054a5e9e1a371c822a3be90564dd9b690
|
||||
s/succesfully/successfully/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
35
Makefile.am
35
Makefile.am
@@ -1,29 +1,29 @@
|
||||
# Main Makefile for GNU tar.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2007,
|
||||
# 2009 Free Software Foundation, Inc.
|
||||
# Copyright 1994-1997, 1999-2001, 2003, 2007, 2009, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
## 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.
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
## 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.
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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,4 @@ include Make.rules
|
||||
gen_start_date = 2009-03-06
|
||||
prev_change_log = ChangeLog.CVS
|
||||
changelog_dir = .
|
||||
|
||||
|
||||
changelog_amend_file=ChangeLog.amend
|
||||
|
||||
560
NEWS
560
NEWS
@@ -1,19 +1,434 @@
|
||||
GNU tar NEWS - User visible changes. 2009-03-05
|
||||
GNU tar NEWS - User visible changes. 2014-07-27
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
version 1.28, 2014-07-28
|
||||
|
||||
* New checkpoint action: totals
|
||||
|
||||
The --checkpoint-action=totals option instructs tar to output the
|
||||
total number of bytes transferred at each checkpoint.
|
||||
|
||||
* Extended checkpoint format specification.
|
||||
|
||||
New conversion specifiers are implemented. Some of them take
|
||||
optional arguments, supplied in curly braces between the percent
|
||||
sign and the specifier letter.
|
||||
|
||||
%d - Number of seconds since tar started.
|
||||
%{r,w,d}T - I/O totals; optional arguments supply prefixes
|
||||
to be used before number of bytes read, written and
|
||||
deleted, correspondingly.
|
||||
%{FMT}t - Current local time using FMT as strftime(3) format.
|
||||
If {FMT} is omitted, use %c.
|
||||
%{N}* - Pad output with spaces to the Nth column, or to the
|
||||
current screen width, if {N} is not given.
|
||||
%c - A shortcut for "%{%Y-%m-%d %H:%M:%S}t: %ds, %{read,wrote}T%*\r"
|
||||
|
||||
* New option --one-top-level
|
||||
|
||||
The option --one-top-level tells tar to extract all files into a
|
||||
subdirectory named by the base name of the archive (minus standard
|
||||
compression suffixes recognizable by --auto-compress). When used with
|
||||
an argument, as in --one-top-level=DIR, the files are extracted into the
|
||||
supplied DIRectory. This ensures that no archive members are
|
||||
extracted outside of the specified directory, even if the archive is
|
||||
crafted so as to put them elsewhere.
|
||||
|
||||
* New option --sort
|
||||
|
||||
The --sort=ORDER option instructs tar to sort directory entries
|
||||
according to ORDER. It takes effect when creating archives.
|
||||
Available ORDERs are: none (the default), name and inode. The
|
||||
latter may be absent, if the underlying system does not provide
|
||||
the necessary information.
|
||||
|
||||
Using --sort=name ensures the member ordering in the created archive
|
||||
is uniform and reproducible. Using --sort=inode reduces the number
|
||||
of disk seeks made when creating the archive and thus can considerably
|
||||
speed up archivation.
|
||||
|
||||
* New exclusion options
|
||||
|
||||
--exclude-ignore=FILE Before dumping a directory check if it
|
||||
contains FILE, and if so read exclude
|
||||
patterns for this directory from FILE.
|
||||
--exclude-ignore-recursive=FILE
|
||||
Same as above, but the exclusion patterns
|
||||
read from FILE remain in effect for any
|
||||
subdirectory, recursively.
|
||||
--exclude-vcs-ignores Read exclude tags from VCS ignore files,
|
||||
where such files exist. Supported VCS's
|
||||
are: CVS, Git, Bazaar, Mercurial.
|
||||
|
||||
|
||||
* Tar refuses to read input from and write output to a tty device.
|
||||
|
||||
* Manpages
|
||||
|
||||
This release includes official tar(1) and rmt(8) manpages.
|
||||
Distribution maintainers are kindly asked to use these instead of the
|
||||
home-made pages they have been providing so far.
|
||||
|
||||
|
||||
version 1.27.1 - Sergey Poznyakoff, 2013-11-17
|
||||
|
||||
* Bug fixes
|
||||
|
||||
* Fix unquoting of file names obtained via the -T option.
|
||||
|
||||
* Fix GNU long link header timestamp (backward compatibility).
|
||||
|
||||
* Fix extracting sparse members from star archives.
|
||||
|
||||
|
||||
version 1.27 - Sergey Poznyakoff, 2013-10-05
|
||||
|
||||
* Bug fixes
|
||||
|
||||
** Sparse files with large data
|
||||
|
||||
When creating a PAX-format archive, tar no longer arbitrarily restricts
|
||||
the size of the representation of a sparse file to be less than 8 GiB.
|
||||
|
||||
* Quoting
|
||||
|
||||
In the default C locale, diagnostics and output of 'tar' have been
|
||||
adjusted to quote 'like this' (with apostrophes) instead of `like this'
|
||||
(with an accent grave character and an apostrophe). This tracks
|
||||
recent changes to the GNU coding standards.
|
||||
|
||||
* --owner and --group names and numbers
|
||||
|
||||
The --owner and --group options now accept operands of the form
|
||||
NAME:NUM, so that you can specify both symbolic name and numeric ID
|
||||
for owner and group. In these options, NAME no longer needs to be
|
||||
present in the current host's user and group databases.
|
||||
|
||||
* The --keep-old-files and --skip-old-files options.
|
||||
|
||||
This release restores the traditional functionality of the
|
||||
--keep-old-files. This option causes tar to avoid replacing
|
||||
existing files while extracting and to treat such files as errors.
|
||||
Tar will emit a prominent error message upon encountering such files
|
||||
and will exit with code 2 when finished extracting the archive.
|
||||
|
||||
A new option --skip-old-files is introduced, which acts exactly as
|
||||
--keep-old-files, except that it does not treat existing files as
|
||||
errors. Instead it just silently skips them. An additional level of
|
||||
verbosity can be obtained by using the option --warning=existing-file
|
||||
together with this option.
|
||||
|
||||
* Support for POSIX ACLs, extended attributes and SELinux context.
|
||||
|
||||
Starting with this version tar is able to store, extract and list
|
||||
extended file attributes, POSIX.1e ACLs and SELinux context. This is
|
||||
controlled by the command line options --xattrs, --acls and --selinux,
|
||||
correspondingly. Each of these options has a `--no-' counterpart
|
||||
(e.g. --no-xattrs), which disables the corresponding feature.
|
||||
Additionally, the options --xattrs-include and --xattrs-exclude allow
|
||||
you to selectively control for which files to store (or extract) the
|
||||
extended attributes.
|
||||
|
||||
* Passing command line arguments to external commands.
|
||||
|
||||
Any option taking a command name as its argument now accepts a full
|
||||
command line as well. Thus, it is now possible to pass additional
|
||||
arguments to invoked programs. The affected options are:
|
||||
|
||||
--checkpoint-action=exec
|
||||
-I, --use-compress-program
|
||||
-F, --info-script
|
||||
--to-command
|
||||
|
||||
Furthermore, if any additional information is supplied to such a
|
||||
command via environment variables, these variables can now be used in
|
||||
the command line itself. Care should be taken to escape them, to
|
||||
prevent from being expanded too early, for example:
|
||||
|
||||
tar -x -f a.tar --info-script='changevol $TAR_ARCHIVE $TAR_VOLUME'
|
||||
|
||||
* New configure option --enable-gcc-warnings, intended for debugging.
|
||||
|
||||
* New warning control option --warning=[no-]record-size
|
||||
|
||||
On extraction, this option controls whether to display actual record
|
||||
size, if it differs from the default.
|
||||
|
||||
* New command line option --keep-directory-symlink
|
||||
|
||||
By default, if trying to extract a directory from the archive,
|
||||
tar discovers that the corresponding file name already exists and is a
|
||||
symbolic link, it first unlinks the entry, and then extracts the directory.
|
||||
|
||||
This option disables this behavior and instructs tar to follow
|
||||
symlinks to directories when extracting from the archive.
|
||||
|
||||
It is mainly intended to provide compatibility with the Slackware
|
||||
installation scripts.
|
||||
|
||||
|
||||
version 1.26 - Sergey Poznyakoff, 2011-03-12
|
||||
|
||||
* Bugfixes
|
||||
|
||||
** Fix the --verify option, which broke in version 1.24.
|
||||
|
||||
** Fix storing long sparse file names in PAX archives.
|
||||
|
||||
** Fix correctness of --atime-preserve=replace
|
||||
|
||||
tar --atime-preserve=replace no longer tries to restore atime of
|
||||
zero-sized files.
|
||||
|
||||
** Work around POSIX incompatibilities on FreeBSD, NetBSD and Tru64
|
||||
|
||||
** Fix bug with --one-file-system --listed-incremental
|
||||
|
||||
When invoked with these two options, tar 1.25 would add only the
|
||||
top-level directory to the archive, but not its contents.
|
||||
|
||||
|
||||
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
|
||||
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,21 +481,21 @@ 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
|
||||
`H' means ``do not apply transformation to hard link targets.''
|
||||
'H' means "do not apply transformation to hard link targets".
|
||||
|
||||
The scope flags are listed in the third part of an `s' expression,
|
||||
The scope flags are listed in the third part of an 's' expression,
|
||||
e.g.:
|
||||
|
||||
tar --transform 's|^|/usr/local/|S'
|
||||
|
||||
Default is `rsh', which means that transformations are applied to
|
||||
Default is 'rsh', which means that transformations are applied to
|
||||
both regular archive members and to the targets of symbolic and hard
|
||||
links. If several transform expressions are used, the default flags
|
||||
can be changed using `flags=' statement before the expressions, e.g.:
|
||||
can be changed using 'flags=' statement before the expressions, e.g.:
|
||||
|
||||
tar --transform 'flags=S;s|^|/usr/local/|S'
|
||||
|
||||
@@ -88,10 +503,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.
|
||||
|
||||
|
||||
|
||||
@@ -116,36 +531,36 @@ they refer to, instead of creating usual hard link members (type '1').
|
||||
This action allows to specify an action to be executed upon hitting a
|
||||
checkpoint. Recognized actions are: dot, echo (the default),
|
||||
echo=string, ttyout=string, exec=cmdline, and sleep=value. Any number
|
||||
of `--checkpoint-action' options can be specified, the actions will be
|
||||
of '--checkpoint-action' options can be specified, the actions will be
|
||||
executed in order of their appearance in the command line. See
|
||||
chapter 3.8 "Checkpoints" for a complete description.
|
||||
|
||||
* New options --no-check-device, --check-device.
|
||||
|
||||
The `--no-check-device' option disables comparing device numbers during
|
||||
The '--no-check-device' option disables comparing device numbers during
|
||||
preparatory stage of an incremental dump. This allows to avoid
|
||||
creating full dumps if the device numbers change (e.g. when using an
|
||||
LVM snapshot).
|
||||
|
||||
The `--check-device' option enables comparing device numbers. This is
|
||||
The '--check-device' option enables comparing device numbers. This is
|
||||
the default. This option is provided to undo the effect of the previous
|
||||
`--no-check-device' option, e.g. if it was set in TAR_OPTIONS
|
||||
'--no-check-device' option, e.g. if it was set in TAR_OPTIONS
|
||||
environment variable.
|
||||
|
||||
* The --transform option.
|
||||
|
||||
Any number of `--transform' options can be given in the command line.
|
||||
Any number of '--transform' options can be given in the command line.
|
||||
The specified transformations will be applied in turn.
|
||||
|
||||
The argument to `--transform' option can be a list of replace
|
||||
expressions, separated by a semicolon (as in `sed').
|
||||
The argument to '--transform' option can be a list of replace
|
||||
expressions, separated by a semicolon (as in 'sed').
|
||||
|
||||
Filename transformations are applied to symbolic link targets
|
||||
during both creation and extraction. Tar 1.19 used them only
|
||||
during extraction.
|
||||
|
||||
For a detailed description, see chapter 6.7 "Modifying File and Member
|
||||
Names".
|
||||
Names".
|
||||
|
||||
* Info (end-of-volume) scripts
|
||||
|
||||
@@ -172,8 +587,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 +599,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 '/.'.
|
||||
@@ -224,7 +639,7 @@ option affects hard and soft link targets and the --strip-components
|
||||
option affects hard link targets as well.
|
||||
|
||||
* End-of-volume script can send the new volume name to tar by writing
|
||||
it to the file descriptor stored in the environment variable `TAR_FD'.
|
||||
it to the file descriptor stored in the environment variable TAR_FD.
|
||||
|
||||
|
||||
version 1.16.1 - Sergey Poznyakoff, 2006-12-09
|
||||
@@ -294,7 +709,7 @@ following command line options:
|
||||
--wildcards use wildcards
|
||||
--anchored patterns match file name start
|
||||
--ignore-case ignore case
|
||||
--wildcards-match-slash wildcards match `/'
|
||||
--wildcards-match-slash wildcards match '/'
|
||||
|
||||
Each of these options has a '--no-' counterpart that disables its
|
||||
effect (e.g. --no-wildcards).
|
||||
@@ -334,7 +749,7 @@ or archive. It generalizes --show-stored-names option, introduced in
|
||||
1.15.90. In particular, when creating an archive in verbose mode, it lists
|
||||
member names as stored in the archive, i.e., with any eventual prefixes
|
||||
removed and file name transformations applied. The option is useful,
|
||||
for example, while comparing `tar cv' and `tar tv' outputs.
|
||||
for example, while comparing 'tar cv' and 'tar tv' outputs.
|
||||
|
||||
** New incremental snapshot file format keeps information about file names
|
||||
as well as that about directories.
|
||||
@@ -359,7 +774,7 @@ version 1.15.90 - Sergey Poznyakoff, 2006-02-19
|
||||
* New features
|
||||
|
||||
** Any number of -T (--files-from) options may be used in the command line.
|
||||
The file specified with -T may include any valid `tar' options,
|
||||
The file specified with -T may include any valid 'tar' options,
|
||||
including another -T option.
|
||||
Compatibility note: older versions of tar would only recognize -C
|
||||
as an option name within the file list file. Now any file whose name
|
||||
@@ -370,7 +785,7 @@ dash, use the --add-file option.
|
||||
automatically. It is no longer necessary to give the --null option.
|
||||
|
||||
** New option --no-unquote disables the unquoting of input file names.
|
||||
This is useful for processing output from `find dir -print0'.
|
||||
This is useful for processing output from 'find dir -print0'.
|
||||
An orthogonal option --unquote is provided as well.
|
||||
|
||||
** New option --test-label tests the archive volume label.
|
||||
@@ -384,7 +799,7 @@ tar prints the label name if present and exits with code 0.
|
||||
** New option --show-stored-names. When creating an archive in verbose mode,
|
||||
it lists member names as stored in the archive, i.e., with any eventual
|
||||
prefixes removed. The option is useful, for example, while comparing
|
||||
`tar cv' and `tar tv' outputs.
|
||||
'tar cv' and 'tar tv' outputs.
|
||||
|
||||
** New option --to-command pipes the contents of archive members to the
|
||||
specified command.
|
||||
@@ -457,7 +872,7 @@ version 1.15 - Sergey Poznyakoff, 2004-12-20
|
||||
|
||||
* Compressed archives are recognised automatically, it is no longer
|
||||
necessary to specify -Z, -z, or -j options to read them. Thus, you can
|
||||
now run `tar tf archive.tar.gz'.
|
||||
now run 'tar tf archive.tar.gz'.
|
||||
|
||||
* When restoring incremental dumps, --one-file-system option
|
||||
prevents directory hierarchies residing on different devices
|
||||
@@ -477,7 +892,7 @@ seeks.
|
||||
* Restore script starts restoring only if it is given --all (-a) option,
|
||||
or some patterns. This is to prevent accidental restores.
|
||||
|
||||
* `tar --verify' prints a warning if during archive creation some of
|
||||
* 'tar --verify' prints a warning if during archive creation some of
|
||||
the file names had their prefixes stripped off.
|
||||
|
||||
* New option --exclude-caches instructs tar to exclude cache directories
|
||||
@@ -487,11 +902,11 @@ containing a standardized tag file, as specified at:
|
||||
http://www.brynosaurus.com/cachedir/spec.html
|
||||
|
||||
* New configure option --with-rmt allows to specify full path name to
|
||||
the `rmt' utility. This supersedes DEFAULT_RMT_COMMAND variable
|
||||
the 'rmt' utility. This supersedes DEFAULT_RMT_COMMAND variable
|
||||
introduced in version 1.14
|
||||
|
||||
* New configure variable DEFAULT_RMT_DIR allows to specify the directory
|
||||
where to install `rmt' utility. This is necessary since modifying
|
||||
where to install 'rmt' utility. This is necessary since modifying
|
||||
--libexecdir as was suggested for version 1.14 produced a side effect: it
|
||||
also modified installation prefix for backup scripts (if
|
||||
--enable-backup-scripts was given).
|
||||
@@ -545,12 +960,12 @@ version 1.14 - Sergey Poznyakoff, 2004-05-11
|
||||
the subcommands --delete, --diff, --extract or --list when a list of
|
||||
files is given either on the command line or via -T option. This
|
||||
option instructs tar to process only the Nth occurrence of each named
|
||||
file. N defaults to 1, so `tar -x -f archive --occurrence filename'
|
||||
extracts the first occurrence of `filename' from `archive'
|
||||
file. N defaults to 1, so 'tar -x -f archive --occurrence filename'
|
||||
extracts the first occurrence of 'filename' from 'archive'
|
||||
and terminates without scanning to the end of the archive.
|
||||
|
||||
* New option --pax-option allows to control the handling of POSIX
|
||||
keywords in `pax' extended headers. It is equivalent to `pax'
|
||||
keywords in 'pax' extended headers. It is equivalent to 'pax'
|
||||
-o option.
|
||||
|
||||
* --incremental and --listed-incremental options work correctly on
|
||||
@@ -656,7 +1071,7 @@ version 1.13.19 - Paul Eggert, 2001-01-13
|
||||
|
||||
version 1.13.18 - Paul Eggert, 2000-10-29
|
||||
|
||||
* Some security problems have been fixed. `tar -x' now modifies only
|
||||
* Some security problems have been fixed. 'tar -x' now modifies only
|
||||
files under the working directory, unless you also specify an unsafe
|
||||
option like --absolute-names or --overwrite.
|
||||
|
||||
@@ -682,12 +1097,12 @@ version 1.13.18 - Paul Eggert, 2000-10-29
|
||||
* This version of tar works best with GNU gzip test version 1.3 or later.
|
||||
Please see <ftp://alpha.gnu.org/gnu/gzip/>.
|
||||
|
||||
* `tar --delete -f -' now works again.
|
||||
* 'tar --delete -f -' now works again.
|
||||
|
||||
|
||||
version 1.13.17 - Paul Eggert, 2000-01-07.
|
||||
|
||||
* `tar --delete -f -' is no longer allowed; it was too buggy.
|
||||
* 'tar --delete -f -' is no longer allowed; it was too buggy.
|
||||
* Diagnostic messages have been made more regular and consistent.
|
||||
|
||||
|
||||
@@ -704,12 +1119,12 @@ version 1.13.16 - Paul Eggert, 1999-12-13.
|
||||
The new --overwrite option enables the old default behavior.
|
||||
|
||||
For regular files, tar implements this change by using the O_EXCL
|
||||
option of `open' to ensure that it creates the file; if this fails, it
|
||||
option of 'open' to ensure that it creates the file; if this fails, it
|
||||
removes the file and tries again. This is similar to the behavior of
|
||||
the --unlink-first option, but it is faster in the common case of
|
||||
extracting a new directory.
|
||||
|
||||
* By default, tar now ignores file names containing a component of `..'
|
||||
* By default, tar now ignores file names containing a component of '..'
|
||||
when extracting, and warns about such file names when creating an archive.
|
||||
To enable the old behavior, use the -P or --absolute-names option.
|
||||
|
||||
@@ -751,20 +1166,20 @@ version 1.13.14 - Paul Eggert, 1999-11-07.
|
||||
version 1.13.13 - Paul Eggert, 1999-10-11.
|
||||
|
||||
* Invalid headers in tar files now elicit errors, not just warnings.
|
||||
* `tar --version' output conforms to the latest GNU coding standards.
|
||||
* If you specify an invalid date, `tar' now substitutes (time_t) -1.
|
||||
* `configure --with-dmalloc' is no longer available.
|
||||
* 'tar --version' output conforms to the latest GNU coding standards.
|
||||
* If you specify an invalid date, 'tar' now substitutes (time_t) -1.
|
||||
* 'configure --with-dmalloc' is no longer available.
|
||||
|
||||
|
||||
version 1.13.12 - Paul Eggert, 1999-09-24.
|
||||
|
||||
* `tar' now supports hard links to symbolic links.
|
||||
* 'tar' now supports hard links to symbolic links.
|
||||
|
||||
* New options --no-same-owner, --no-same-permissions.
|
||||
|
||||
* --total now also outputs a human-readable size, and a throughput value.
|
||||
|
||||
* `tar' now uses two's-complement base-256 when outputting header
|
||||
* 'tar' now uses two's-complement base-256 when outputting header
|
||||
values that are out of the range of the standard unsigned base-8
|
||||
format. This affects archive members with negative or huge time
|
||||
stamps or uids, and archive members 8 GB or larger. The new tar
|
||||
@@ -773,12 +1188,12 @@ version 1.13.12 - Paul Eggert, 1999-09-24.
|
||||
behavior, which uses unportable representations for negative values,
|
||||
and which rejects large files.
|
||||
|
||||
* On 32-bit hosts, `tar' now assumes that an incoming time stamp T in
|
||||
* On 32-bit hosts, 'tar' now assumes that an incoming time stamp T in
|
||||
the range 2**31 <= T < 2**32 represents the negative time (T -
|
||||
2**32). This behavior is nonstandard and is not portable to 64-bit
|
||||
time_t hosts, so `tar' issues a warning.
|
||||
time_t hosts, so 'tar' issues a warning.
|
||||
|
||||
* `tar' no longer gives up extracting immediately upon discovering
|
||||
* 'tar' no longer gives up extracting immediately upon discovering
|
||||
that an archive contains garbage at the end. It attempts to extract
|
||||
as many files as possible from the good data before the garbage.
|
||||
|
||||
@@ -795,40 +1210,40 @@ version 1.13.11 - Paul Eggert, 1999-08-23.
|
||||
* -T /dev/null now matches nothing; previously, it matched anything
|
||||
if no explicit operands were given.
|
||||
|
||||
* The `--' option now works the same as with other GNU utilities;
|
||||
* The '--' option now works the same as with other GNU utilities;
|
||||
it causes later operands to be interpreted as file names, not options,
|
||||
even if they begin with `-'.
|
||||
even if they begin with '-'.
|
||||
|
||||
* For the --newer and --after-date options, the table of time zone
|
||||
abbreviations like `EST' has been updated to match current practice.
|
||||
abbreviations like 'EST' has been updated to match current practice.
|
||||
Also, local time abbreviations are now recognized, even if they are
|
||||
not in tar's hardwired table. Remember, though, that you should use
|
||||
numeric UTC offsets like `-0500' instead of abbreviations like
|
||||
`EST', as abbreviations are not standardized and are ambiguous.
|
||||
numeric UTC offsets like '-0500' instead of abbreviations like
|
||||
'EST', as abbreviations are not standardized and are ambiguous.
|
||||
|
||||
|
||||
version 1.13.10 - Paul Eggert, 1999-08-20.
|
||||
|
||||
* `tar' now uses signed base-64 when outputting header values that are
|
||||
* 'tar' now uses signed base-64 when outputting header values that are
|
||||
out of the range of the standard unsigned base-8 format. [This
|
||||
change was superseded in 1.13.12, described above.]
|
||||
|
||||
|
||||
version 1.13.9 - Paul Eggert, 1999-08-18.
|
||||
|
||||
* `tar' now writes two zero blocks at end-of-archive instead of just one.
|
||||
POSIX.1 requires this, and some other `tar' implementations check for it.
|
||||
* 'tar' now writes two zero blocks at end-of-archive instead of just one.
|
||||
POSIX.1 requires this, and some other 'tar' implementations check for it.
|
||||
|
||||
* `tar' no longer silently accepts a block containing nonzero checksum bytes
|
||||
* 'tar' no longer silently accepts a block containing nonzero checksum bytes
|
||||
as a zero block.
|
||||
|
||||
* `tar' now reads buggy tar files that have a null byte at the start of a
|
||||
* 'tar' now reads buggy tar files that have a null byte at the start of a
|
||||
numeric header field.
|
||||
|
||||
|
||||
version 1.13.8 - Paul Eggert, 1999-08-16.
|
||||
|
||||
* For compatibility with traditional `tar', intermediate directories
|
||||
* For compatibility with traditional 'tar', intermediate directories
|
||||
created automatically by root are no longer given the uid and gid of
|
||||
the original file or directory.
|
||||
|
||||
@@ -837,7 +1252,7 @@ version 1.13.7 - Paul Eggert, 1999-08-14.
|
||||
|
||||
* --listed-incremental and --newer are now incompatible options.
|
||||
|
||||
* When creating an archive, leading `./' is no longer stripped,
|
||||
* When creating an archive, leading './' is no longer stripped,
|
||||
to match traditional tar's behavior (and simplify the documentation).
|
||||
|
||||
* --diff without --absolute-names no longer falls back on absolute names.
|
||||
@@ -928,7 +1343,7 @@ Creation
|
||||
* Implement --numeric-owner for ignoring symbolic names at create time.
|
||||
* New --owner, --group --mode options, still preliminary.
|
||||
* Recognize creating an archive on /dev/null, so Amanda works faster.
|
||||
* Object to the creation of an empty archive (like in `tar cf FILE').
|
||||
* Object to the creation of an empty archive (like in 'tar cf FILE').
|
||||
* Barely start implementing --posix and POSIXLY_CORRECT.
|
||||
|
||||
Extraction
|
||||
@@ -1007,7 +1422,7 @@ Version 1.10.13 - 1992-01.
|
||||
|
||||
* Now uses GNU standard configure, generated by Autoconf.
|
||||
|
||||
* Long options now use `--'; use of `+' is deprecated and support
|
||||
* Long options now use '--'; use of '+' is deprecated and support
|
||||
for it will eventually be removed.
|
||||
|
||||
* New option --null causes filenames read by -T to be
|
||||
@@ -1036,8 +1451,8 @@ the various tape drives will get used in sequence and then wrap
|
||||
around to the beginning.
|
||||
|
||||
* Remote archive names no longer have to be in /dev: any file with a
|
||||
`:' is interpreted as remote. If new option --force-local is given,
|
||||
then even archive files with a `:' are considered local.
|
||||
':' is interpreted as remote. If new option --force-local is given,
|
||||
then even archive files with a ':' are considered local.
|
||||
|
||||
* New option --atime-preserve restores (if possible) atimes to
|
||||
their original values after dumping the file.
|
||||
@@ -1090,15 +1505,14 @@ 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.
|
||||
Copyright 1994-2001, 2003-2010, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -1106,9 +1520,7 @@ 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 tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Local variables:
|
||||
mode: outline
|
||||
|
||||
135
README
135
README
@@ -4,31 +4,31 @@ See the end of file for copying conditions.
|
||||
* Introduction
|
||||
|
||||
Please glance through *all* sections of this
|
||||
`README' file before starting configuration. Also make sure you read files
|
||||
`ABOUT-NLS' and `INSTALL' if you are not familiar with them already.
|
||||
'README' file before starting configuration. Also make sure you read files
|
||||
'ABOUT-NLS' and 'INSTALL' if you are not familiar with them already.
|
||||
|
||||
If you got the `tar' distribution in `shar' format, time stamps ought to be
|
||||
properly restored; do not ignore such complaints at `unshar' time.
|
||||
If you got the 'tar' distribution in 'shar' format, time stamps ought to be
|
||||
properly restored; do not ignore such complaints at 'unshar' time.
|
||||
|
||||
GNU `tar' saves many files together into a single tape or disk
|
||||
GNU 'tar' saves many files together into a single tape or disk
|
||||
archive, and can restore individual files from the archive. It includes
|
||||
multivolume support, the ability to archive sparse files, automatic archive
|
||||
compression/decompression, remote archives and special features that allow
|
||||
`tar' to be used for incremental and full backups. This distribution
|
||||
also includes `rmt', the remote tape server. The `mt' tape drive control
|
||||
program is in the GNU `cpio' distribution.
|
||||
'tar' to be used for incremental and full backups. This distribution
|
||||
also includes 'rmt', the remote tape server. The 'mt' tape drive control
|
||||
program is in the GNU 'cpio' distribution.
|
||||
|
||||
GNU `tar' is derived from John Gilmore's public domain `tar'.
|
||||
GNU 'tar' is derived from John Gilmore's public domain 'tar'.
|
||||
|
||||
See file `ABOUT-NLS' for how to customize this program to your language.
|
||||
See file `COPYING' for copying conditions.
|
||||
See file `INSTALL' for compilation and installation instructions.
|
||||
See file `PORTS' for various ports of GNU tar to non-Unix systems.
|
||||
See file `NEWS' for a list of major changes in the current release.
|
||||
See file `THANKS' for a list of contributors.
|
||||
See file 'ABOUT-NLS' for how to customize this program to your language.
|
||||
See file 'COPYING' for copying conditions.
|
||||
See file 'INSTALL' for compilation and installation instructions.
|
||||
See file 'PORTS' for various ports of GNU tar to non-Unix systems.
|
||||
See file 'NEWS' for a list of major changes in the current release.
|
||||
See file 'THANKS' for a list of contributors.
|
||||
|
||||
Besides those configure options documented in files `INSTALL' and
|
||||
`ABOUT-NLS', an extra option may be accepted after `./configure':
|
||||
Besides those configure options documented in files 'INSTALL' and
|
||||
'ABOUT-NLS', an extra option may be accepted after './configure':
|
||||
|
||||
* Install
|
||||
|
||||
@@ -40,11 +40,11 @@ values are GNU, V7, OLDGNU, USTAR and POSIX.
|
||||
|
||||
** Selecting the default archive device
|
||||
|
||||
The default archive device is now `stdin' on read and `stdout' on write.
|
||||
The installer can still override this by presetting `DEFAULT_ARCHIVE'
|
||||
in the environment before configuring (the behavior of `-[0-7]' or
|
||||
`-[0-7]lmh' options in `tar' are then derived automatically). Similarly,
|
||||
`DEFAULT_BLOCKING' can be preset to something else than 20.
|
||||
The default archive device is now 'stdin' on read and 'stdout' on write.
|
||||
The installer can still override this by presetting 'DEFAULT_ARCHIVE'
|
||||
in the environment before configuring (the behavior of '-[0-7]' or
|
||||
'-[0-7]lmh' options in 'tar' are then derived automatically). Similarly,
|
||||
'DEFAULT_BLOCKING' can be preset to something else than 20.
|
||||
|
||||
** Selecting full pathname of the "rmt" binary.
|
||||
|
||||
@@ -76,13 +76,13 @@ directory.
|
||||
Use option --enable-backup-scripts to compile and install these
|
||||
scripts.
|
||||
|
||||
** `--disable-largefile' omits support for large files, even if the
|
||||
** '--disable-largefile' omits support for large files, even if the
|
||||
operating system supports large files. Typically, large files are
|
||||
those larger than 2 GB on a 32-bit host.
|
||||
|
||||
* Installation hints
|
||||
|
||||
Here are a few hints which might help installing `tar' on some systems.
|
||||
Here are a few hints which might help installing 'tar' on some systems.
|
||||
|
||||
** gzip and bzip2.
|
||||
|
||||
@@ -103,7 +103,7 @@ then you have encountered a gzip incompatibility that should be fixed
|
||||
in gzip test version 1.3, which as of this writing is available at
|
||||
<ftp://alpha.gnu.org/gnu/gzip/>. You can work around the
|
||||
incompatibility by using a shell command like
|
||||
`gzip -d <file.tar.gz | tar -xzf -'.
|
||||
'gzip -d <file.tar.gz | tar -xzf -'.
|
||||
|
||||
** Solaris issues.
|
||||
|
||||
@@ -118,13 +118,13 @@ understand these headers.
|
||||
|
||||
** Static linking.
|
||||
|
||||
Some platform will, by default, prepare a smaller `tar' executable
|
||||
which depends on shared libraries. Since GNU `tar' may be used for
|
||||
Some platform will, by default, prepare a smaller 'tar' executable
|
||||
which depends on shared libraries. Since GNU 'tar' may be used for
|
||||
system-level backups and disaster recovery, installers might prefer to
|
||||
force static linking, making a bigger `tar' executable maybe, but able to
|
||||
force static linking, making a bigger 'tar' executable maybe, but able to
|
||||
work standalone, in situations where shared libraries are not available.
|
||||
The way to achieve static linking varies between systems. Set LDFLAGS
|
||||
to a value from the table below, before configuration (see `INSTALL').
|
||||
to a value from the table below, before configuration (see 'INSTALL').
|
||||
|
||||
Platform Compiler LDFLAGS
|
||||
|
||||
@@ -137,18 +137,18 @@ to a value from the table below, before configuration (see `INSTALL').
|
||||
Solaris (vendor) -Bstatic
|
||||
SunOS (vendor) -Bstatic
|
||||
|
||||
** Failed tests `ignfail.sh' or `incremen.sh'.
|
||||
** Failed tests 'ignfail.sh' or 'incremen.sh'.
|
||||
|
||||
In an NFS environment, lack of synchronization between machine clocks
|
||||
might create difficulties to any tool comparing dates and file time stamps,
|
||||
like `tar' in incremental dumps. This has been a recurrent problem with
|
||||
like 'tar' in incremental dumps. This has been a recurrent problem with
|
||||
GNU Make for the last few years. We would like a general solution.
|
||||
|
||||
** BSD compatibility matters.
|
||||
|
||||
Set LIBS to `-lbsd' before configuration (see `INSTALL') if the linker
|
||||
complains about `bsd_ioctl' (Slackware). Also set CPPFLAGS to
|
||||
`-I/usr/include/bsd' if <sgtty.h> is not found (Slackware).
|
||||
Set LIBS to '-lbsd' before configuration (see 'INSTALL') if the linker
|
||||
complains about 'bsd_ioctl' (Slackware). Also set CPPFLAGS to
|
||||
'-I/usr/include/bsd' if <sgtty.h> is not found (Slackware).
|
||||
|
||||
** OPENStep 4.2 swap files
|
||||
|
||||
@@ -159,43 +159,43 @@ the simplest workaround is to avoid tarring this file.
|
||||
|
||||
* Special topics
|
||||
|
||||
Here are a few special matters about GNU `tar', not related to build
|
||||
Here are a few special matters about GNU 'tar', not related to build
|
||||
matters. See previous section for such.
|
||||
|
||||
** File attributes.
|
||||
|
||||
About *security*, it is probable that future releases of `tar' will have
|
||||
About *security*, it is probable that future releases of 'tar' will have
|
||||
some behavior changed. There are many pending suggestions to choose from.
|
||||
Today, extracting an archive not being `root', `tar' will restore suid/sgid
|
||||
bits on files but owned by the extracting user. `root' automatically gets
|
||||
a lot of special privileges, `-p' might later become required to get them.
|
||||
Today, extracting an archive not being 'root', 'tar' will restore suid/sgid
|
||||
bits on files but owned by the extracting user. 'root' automatically gets
|
||||
a lot of special privileges, '-p' might later become required to get them.
|
||||
|
||||
GNU `tar' does not properly restore symlink attributes. Various systems
|
||||
GNU 'tar' does not properly restore symlink attributes. Various systems
|
||||
implement flavors of symbolic links showing different behavior and
|
||||
properties. We did not successfully sorted all these out yet. Currently,
|
||||
the `lchown' call will be used if available, but that's all.
|
||||
the 'lchown' call will be used if available, but that's all.
|
||||
|
||||
** POSIX compliance.
|
||||
|
||||
GNU `tar' is able to create archive in the following formats:
|
||||
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.
|
||||
In addition to those, GNU 'tar' is also able to read archives
|
||||
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
|
||||
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.
|
||||
and new 'tar' features.
|
||||
|
||||
* What's next?
|
||||
|
||||
@@ -216,36 +216,39 @@ to the report address; rather take special arrangement with the maintainer.
|
||||
|
||||
Your feedback will help us to make a better and more portable package.
|
||||
Consider documentation errors as bugs, and report them as such. If you
|
||||
develop anything pertaining to `tar' or have suggestions, let us know
|
||||
develop anything pertaining to 'tar' or have suggestions, let us know
|
||||
and share your findings by writing to <bug-tar@gnu.org>.
|
||||
|
||||
|
||||
* Copying
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1994, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
Copyright 1990-1992, 1994, 1997-2001, 2003-2004, 2007, 2012-2014 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
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 tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
NOTE ON COPYRIGHT YEARS
|
||||
|
||||
In copyright notices where the copyright holder is the Free Software
|
||||
Foundation, then where a range of years appears, this is an inclusive
|
||||
range that applies to every year in the range. For example: 2005-2008
|
||||
represents the years 2005, 2006, 2007, and 2008.
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
|
||||
11
README-alpha
11
README-alpha
@@ -62,14 +62,15 @@ some other value.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2001, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2001, 2003-2005, 2007, 2013-2014 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -77,6 +78,4 @@ 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 tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
@@ -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).
|
||||
@@ -36,30 +36,35 @@ Normally you will have to run bootstrap only once. However, if you
|
||||
intend to hack on GNU tar, you might need to run it again later. In
|
||||
this case, you will probably want to save some time and bandwidth by
|
||||
avoiding downloading the same files again. If so, create in GNU tar
|
||||
root directory the file named `.bootstrap' with the following
|
||||
root directory the file named '.bootstrap' with the following
|
||||
contents:
|
||||
|
||||
--gnulib-srcdir=$HOME/gnulib
|
||||
|
||||
Replace `$HOME/gnulib' with the actual directory where the Gnulib
|
||||
Replace '$HOME/gnulib' with the actual directory where the Gnulib
|
||||
sources reside.
|
||||
|
||||
For more information about `bootstrap', run `bootstrap --help'.
|
||||
|
||||
For more information about 'bootstrap', run 'bootstrap --help'.
|
||||
|
||||
|
||||
* Copyright information
|
||||
|
||||
Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
Copyright 2007-2009, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to anyone to make or distribute verbatim copies
|
||||
of this document as received, in any medium, provided that the
|
||||
copyright notice and this permission notice are preserved,
|
||||
thus giving the recipient permission to redistribute in turn.
|
||||
This file is part of GNU tar.
|
||||
|
||||
Permission is granted to distribute modified versions
|
||||
of this document, or of portions of it,
|
||||
under the above conditions, provided also that they
|
||||
carry prominent notices stating who last changed them.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
^L
|
||||
Local Variables:
|
||||
@@ -67,5 +72,3 @@ mode: outline
|
||||
paragraph-separate: "[ ^L]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
|
||||
|
||||
16
THANKS
16
THANKS
@@ -36,6 +36,7 @@ Andrew Torda torda@igc.chem.ethz.ch
|
||||
Andrey A. Chernov ache@astral.msk.su
|
||||
Andy Gay andy@rdl.co.uk
|
||||
Antonio Jose Coutinho ajc@di.uminho.pt
|
||||
Anthony G. Basile blueness@gentoo.org
|
||||
Ariel Faigon ariel@engr.sgi.com
|
||||
Arne Wichmann aw@math.uni-sb.de
|
||||
Arnold Robbins arnold@gnu.org
|
||||
@@ -70,6 +71,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
|
||||
@@ -90,6 +92,7 @@ Christian Kirsch ck@held.mind.de
|
||||
Christian Laubscher christian.laubscher@tiscalinet.ch
|
||||
Christian T. Dum ctd@mpe-garching.mpg.de
|
||||
Christian von Roques roques@pond.sub.org
|
||||
Christian Wetzel wetzel@phoenix-pacs.de
|
||||
Christoph Litauer litauer@mailhost.uni-koblenz.de
|
||||
Christophe Colle colle@krtkg1.rug.ac.be
|
||||
Christophe Kalt Christophe.Kalt@kbcfp.com
|
||||
@@ -99,6 +102,7 @@ Claude Scarpelli claude@genethon.fr
|
||||
Claus Heine Claus_Heine@ac2.maus.de
|
||||
Cliff Krumvieda cliff@cs.cornell.edu
|
||||
Clinton Carr clint@netcom.com
|
||||
Connor Behan connor.behan@gmail.com
|
||||
Conrad Hughes chughes@maths.tcd.ie
|
||||
Constantin Belous const@cris.net
|
||||
Coranth Gryphon gryphon@bur.visidyne.com
|
||||
@@ -117,6 +121,7 @@ Danny R. Johnston danny@cs.weber.edu
|
||||
Dave Barr barr@math.psu.edu
|
||||
Dave Gentzel gentzel@nova.enet.dec.com
|
||||
Dave Gregorich dtg@ipac.caltech.edu
|
||||
David Barri japgolly@gmail.com
|
||||
David Brown davidb@davidb.org
|
||||
David J. MacKenzie djm@uunet.uu.net
|
||||
David Johnson David.W.Johnson@colorado.edu
|
||||
@@ -132,6 +137,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
|
||||
@@ -239,6 +245,7 @@ Jim Clausing jac@postbox.acs.ohio-state.edu
|
||||
Jim Farrell jwf@platinum.com
|
||||
Jim Meyering meyering@na-net.ornl.gov
|
||||
Jim Murray jjm@jjm.com
|
||||
Jivko Angelov jivko@siteground.com
|
||||
Joachim Holzfuss Joachim.Holzfuss@iap.physik.th-darmstadt.de
|
||||
Joachim Seelig joachim@kruemel.han.de
|
||||
Joe DeBattista joed@itsa.ucsf.edu
|
||||
@@ -294,6 +301,7 @@ Kimmy Posey kimmyd@bnr.ca
|
||||
Koji Kishi kis@rqa.sony.co.jp
|
||||
Konno Hiroharu konno@pac.co.jp
|
||||
Kurt Jaeger pi@lf.net
|
||||
James Antill jantill@redhat.com
|
||||
Larry Creech lcreech@lonestar.rcclub.org
|
||||
Larry Schwimmer rosebud@cyclone.stanford.edu
|
||||
Lasse Collin lasse.collin@tukaani.org
|
||||
@@ -347,6 +355,7 @@ Michael P Urban urban@cobra.jpl.nasa.gov
|
||||
Michael Schmidt michael@muc.de
|
||||
Michael Schwingen m.schwingen@stochastik.rwth-aachen.de
|
||||
Michael Smolsky fnsiguc@astro.weizmann.ac.il
|
||||
Michal Žejdl zejdl@suas.cz
|
||||
Mike Muuss mike@brl.mil
|
||||
Mike Nolan nolan@lpl.arizona.edu
|
||||
Mike Rogers mike@demon.net
|
||||
@@ -355,11 +364,14 @@ Mike Walker M.D.Walker@larc.nasa.gov
|
||||
Milan Hodoscek milan@kihp6.ki.si
|
||||
Minh Tran-Le tranle@intellicorp.com
|
||||
Mitsuaki Masuhara masuhara@mcprv.mec.mei.co.jp
|
||||
Natalie Alifanova na@nxc.no
|
||||
Nate Eldredge nate@cs.hmc.edu
|
||||
Nathan Stratton Treadway nathanst+bugtar@ontko.com
|
||||
Neil Faulks neil@dcs.kcl.ac.uk
|
||||
Neil Jerram nj104@cus.cam.ac.uk
|
||||
Nelson H.F. Beebe beebe@math.utah.edu
|
||||
Nick Barron nikb@cix.compulink.co.uk
|
||||
Nicolas Dudebout nicolas.dudebout@gmail.com
|
||||
Noah Friedman friedman@gnu.org
|
||||
Noel Cragg noel@red-bean.com
|
||||
Norbert Kiesel norbert@rwthi3.informatik.rwth-aachen.de
|
||||
@@ -367,10 +379,12 @@ 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
|
||||
Patrick Timmons timmons@electech.polymtl.ca
|
||||
Pavel Raiskup praiskup@redhat.com
|
||||
Paul Eggert eggert@twinsun.com
|
||||
Paul Kanz paul@icx.com
|
||||
Paul Mitchell P.Mitchell@surrey.ac.uk
|
||||
@@ -388,9 +402,11 @@ 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
|
||||
Piotr Rotter piotr.rotter@active24.pl
|
||||
R. Kent Dybvig dyb@cadence.bloomington.in.us
|
||||
R. Scott Butler butler@prism.es.dupont.com
|
||||
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
|
||||
|
||||
26
TODO
26
TODO
@@ -45,24 +45,22 @@ Suggestions for improving GNU tar.
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2003-2004, 2007, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
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 tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Local variables:
|
||||
|
||||
76
acinclude.m4
Normal file
76
acinclude.m4
Normal file
@@ -0,0 +1,76 @@
|
||||
dnl Special Autoconf macros for GNU tar -*- autoconf -*-
|
||||
|
||||
dnl Copyright 2009, 2013-2014 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl This file is part of GNU tar.
|
||||
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 of the License, or
|
||||
dnl (at your option) 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
|
||||
dnl along with this program. 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])])
|
||||
|
||||
# Provide <attr/xattr.h>, if necessary
|
||||
|
||||
AC_DEFUN([TAR_HEADERS_ATTR_XATTR_H],
|
||||
[
|
||||
AC_ARG_WITH([xattrs],
|
||||
AS_HELP_STRING([--without-xattrs], [don't use linux extended attributes]),
|
||||
[], [with_xattrs=maybe]
|
||||
)
|
||||
|
||||
# First check for <sys/xattr.h>
|
||||
AC_CHECK_HEADERS([sys/xattr.h])
|
||||
AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_sys_xattr_h" = yes])
|
||||
AM_CONDITIONAL([TAR_LIB_ATTR],[false])
|
||||
if test "$ac_cv_header_sys_xattr_h" = yes; then
|
||||
AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \
|
||||
setxattr fsetxattr lsetxattr \
|
||||
listxattr flistxattr llistxattr,
|
||||
# only when functions are present
|
||||
AC_DEFINE([HAVE_SYS_XATTR_H], [1],
|
||||
[define to 1 if we have <sys/xattr.h> header])
|
||||
if test "$with_xattrs" != no; then
|
||||
AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
|
||||
fi
|
||||
)
|
||||
fi
|
||||
|
||||
# If <sys/xattr.h> is not found, then check for <attr/xattr.h>
|
||||
if test "$ac_cv_header_sys_xattr_h" != yes; then
|
||||
AC_CHECK_HEADERS([attr/xattr.h])
|
||||
AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_attr_xattr_h" = yes])
|
||||
AC_CHECK_LIB([attr],[fgetxattr])
|
||||
AM_CONDITIONAL([TAR_LIB_ATTR],[test "$ac_cv_lib_attr_fgetxattr" = yes])
|
||||
if test "$ac_cv_header_attr_xattr_h" = yes; then
|
||||
AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \
|
||||
setxattr fsetxattr lsetxattr \
|
||||
listxattr flistxattr llistxattr,
|
||||
# only when functions are present
|
||||
AC_DEFINE([HAVE_ATTR_XATTR_H], [1],
|
||||
[define to 1 if we have <attr/xattr.h> header])
|
||||
if test "$with_xattrs" != no; then
|
||||
AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
|
||||
fi
|
||||
)
|
||||
fi
|
||||
fi
|
||||
])
|
||||
507
bootstrap
507
bootstrap
@@ -1,8 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Print a version string.
|
||||
scriptversion=2012-12-31.16; # UTC
|
||||
|
||||
# Bootstrap this package from checked-out sources.
|
||||
|
||||
# Copyright (C) 2003-2008, 2009 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003-2010, 2013-2014 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,13 @@ 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/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 +152,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 +172,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 +262,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 +289,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 +427,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 +458,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 +473,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 +528,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 +554,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 +593,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 +662,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 +695,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 +713,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 +756,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 +799,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 +820,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 +839,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 +885,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 +923,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 +940,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:
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
# Bootstrap configuration for GNU tar.
|
||||
|
||||
# Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
# Copyright 2006-2009, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
source_base=gnu
|
||||
gnulib_name=libgnu
|
||||
gnulib_mk=Makefile.am
|
||||
|
||||
# We don't need these modules, even though gnulib-tool mistakenly
|
||||
# includes them because of gettext dependencies.
|
||||
@@ -68,7 +67,7 @@ fi
|
||||
test -d m4 || mkdir m4
|
||||
test -d $source_base || mkdir $source_base
|
||||
|
||||
cat > ChangeLog <<EOT
|
||||
test -f ChangeLog || cat > ChangeLog <<EOT
|
||||
This file is a placeholder. It will be replaced with the actual ChangeLog
|
||||
by make dist. Run make ChangeLog if you wish to create it earlier.
|
||||
EOT
|
||||
|
||||
179
configure.ac
179
configure.ac
@@ -1,43 +1,45 @@
|
||||
# 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.
|
||||
# Copyright 1991, 1994-2010, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AC_INIT([GNU tar], [1.22], [bug-tar@gnu.org])
|
||||
AC_INIT([GNU tar], [1.28], [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 std-options silent-rules])
|
||||
|
||||
AC_PROG_CC
|
||||
# Enable silent rules by default:
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_PROG_CC_STDC
|
||||
AC_EXEEXT
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_YACC
|
||||
gl_EARLY
|
||||
AC_CHECK_TOOLS([AR], [ar])
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
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)
|
||||
@@ -47,12 +49,7 @@ AC_CHECK_HEADERS([sys/buf.h], [], [],
|
||||
#include <sys/param.h>
|
||||
#endif])
|
||||
|
||||
AC_HEADER_SYS_WAIT
|
||||
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_MAJOR
|
||||
AC_HEADER_STAT
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_MSG_CHECKING([for st_fstype string in struct stat])
|
||||
AC_CACHE_VAL(diff_cv_st_fstype_string,
|
||||
@@ -66,11 +63,33 @@ if test $diff_cv_st_fstype_string = yes; then
|
||||
[Define if struct stat has a char st_fstype[] member.])
|
||||
fi
|
||||
|
||||
AC_TYPE_SIGNAL
|
||||
# even if we use gnulib's acl.h with integrated m4 file later on (used because
|
||||
# of very useful file_has_acl() function) we need following checks that restrict
|
||||
# tar to use POSIX.1e ACLs only.
|
||||
AC_ARG_WITH([posix-acls],
|
||||
AS_HELP_STRING([--without-posix-acls],
|
||||
[do not use POSIX.1e access control lists]),
|
||||
[],
|
||||
[with_posix_acls=yes])
|
||||
if test "x$with_posix_acls" != "xno"; then
|
||||
AC_CHECK_HEADERS(sys/acl.h,, [with_posix_acls=no])
|
||||
for tar_acl_func in acl_get_file acl_get_fd acl_set_file acl_set_fd \
|
||||
acl_to_text acl_from_text acl_delete_def_file \
|
||||
acl_free; do \
|
||||
test "x$with_posix_acls" = xno && break
|
||||
AC_SEARCH_LIBS([$tar_acl_func], [acl pacl], [], [with_posix_acls=no])
|
||||
done
|
||||
if test "x$with_posix_acls" != xno; then
|
||||
AC_DEFINE(HAVE_POSIX_ACLS,,[Define when we have working POSIX acls])
|
||||
fi
|
||||
else
|
||||
# disable acls in gnulib's checks
|
||||
export enable_acl=no
|
||||
fi
|
||||
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_UID_T
|
||||
AC_CHECK_TYPE(major_t, , AC_DEFINE(major_t, int,
|
||||
[Type of major device numbers.]))
|
||||
@@ -86,13 +105,115 @@ gl_INIT
|
||||
# paxutils modules
|
||||
tar_PAXUTILS
|
||||
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink symlink setlocale utimes)
|
||||
# gl_GCC_VERSION_IFELSE([major], [minor], [run-if-found], [run-if-not-found])
|
||||
# ------------------------------------------------
|
||||
# If $CPP is gcc-MAJOR.MINOR or newer, then run RUN-IF-FOUND.
|
||||
# Otherwise, run RUN-IF-NOT-FOUND.
|
||||
AC_DEFUN([gl_GCC_VERSION_IFELSE],
|
||||
[AC_PREPROC_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#if ($1) < __GNUC__ || (($1) == __GNUC__ && ($2) <= __GNUC_MINOR__)
|
||||
/* ok */
|
||||
#else
|
||||
# error "your version of gcc is older than $1.$2"
|
||||
#endif
|
||||
]]),
|
||||
], [$3], [$4])
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([gcc-warnings],
|
||||
[AS_HELP_STRING([--enable-gcc-warnings],
|
||||
[turn on many GCC warnings (for developers; best with GNU make)])],
|
||||
[case $enableval in
|
||||
yes|no) ;;
|
||||
*) AC_MSG_ERROR([bad value $enableval for gcc-warnings option]) ;;
|
||||
esac
|
||||
gl_gcc_warnings=$enableval],
|
||||
[gl_gcc_warnings=no
|
||||
if test -d "$srcdir"/.git; then
|
||||
gl_GCC_VERSION_IFELSE([4], [6], [gl_gcc_warnings=yes])
|
||||
fi]
|
||||
)
|
||||
|
||||
if test "$gl_gcc_warnings" = yes; then
|
||||
gl_WARN_ADD([-Werror], [WERROR_CFLAGS])
|
||||
AC_SUBST([WERROR_CFLAGS])
|
||||
|
||||
nw=
|
||||
# This, $nw, is the list of warnings we disable.
|
||||
nw="$nw -Wformat-nonliteral" # warnings in Fedora 17 stdio.h
|
||||
nw="$nw -Wvla" # warnings in gettext.h
|
||||
nw="$nw -Wswitch-default" # Too many warnings for now
|
||||
nw="$nw -Wunsafe-loop-optimizations" # It's OK to omit unsafe optimizations.
|
||||
nw="$nw -Winline" # It's OK to not inline.
|
||||
nw="$nw -Wstrict-overflow" # It's OK to optimize strictly.
|
||||
nw="$nw -Wsuggest-attribute=pure" # Too many warnings for now.
|
||||
|
||||
gl_MANYWARN_ALL_GCC([ws])
|
||||
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
|
||||
for w in $ws; do
|
||||
gl_WARN_ADD([$w])
|
||||
done
|
||||
gl_WARN_ADD([-Wno-sign-compare]) # Too many warnings for now
|
||||
gl_WARN_ADD([-Wno-type-limits]) # It's OK to optimize based on types.
|
||||
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
|
||||
gl_WARN_ADD([-Wno-format-nonliteral])
|
||||
|
||||
gl_WARN_ADD([-fdiagnostics-show-option])
|
||||
gl_WARN_ADD([-funit-at-a-time])
|
||||
|
||||
AC_SUBST([WARN_CFLAGS])
|
||||
|
||||
AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
|
||||
AH_VERBATIM([FORTIFY_SOURCE],
|
||||
[/* Enable compile-time and run-time bounds-checking, and some warnings,
|
||||
without upsetting glibc 2.15+. */
|
||||
#if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__
|
||||
# define _FORTIFY_SOURCE 2
|
||||
#endif
|
||||
])
|
||||
AC_DEFINE([GNULIB_PORTCHECK], [1], [enable some gnulib portability checks])
|
||||
|
||||
# Use a slightly smaller set of warning options for lib/.
|
||||
# Remove the following and save the result in GNULIB_WARN_CFLAGS.
|
||||
nw=
|
||||
nw="$nw -Wmissing-prototypes"
|
||||
nw="$nw -Wunused-macros"
|
||||
#
|
||||
# These are for argp.
|
||||
nw="$nw -Wmissing-field-initializers"
|
||||
nw="$nw -Wshadow"
|
||||
#
|
||||
gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw])
|
||||
|
||||
# This is also for argp.
|
||||
gl_WARN_ADD([-Wno-missing-field-initializers], [GNULIB_WARN_CFLAGS])
|
||||
|
||||
AC_SUBST([GNULIB_WARN_CFLAGS])
|
||||
|
||||
# For gnulib-tests, the set is slightly smaller still.
|
||||
nw=
|
||||
# It's not worth being this picky about test programs.
|
||||
nw="$nw -Wsuggest-attribute=const"
|
||||
gl_MANYWARN_COMPLEMENT([GNULIB_TEST_WARN_CFLAGS],
|
||||
[$GNULIB_WARN_CFLAGS], [$nw])
|
||||
AC_SUBST([GNULIB_TEST_WARN_CFLAGS])
|
||||
fi
|
||||
|
||||
TAR_HEADERS_ATTR_XATTR_H
|
||||
|
||||
AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink grantpt])
|
||||
AM_CONDITIONAL([TAR_COND_GRANTPT], [test $ac_cv_func_grantpt = yes])
|
||||
|
||||
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
|
||||
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
|
||||
AC_CHECK_DECLS([time],,, [#include <time.h>])
|
||||
|
||||
AC_REPLACE_FUNCS(waitpid)
|
||||
|
||||
AC_ARG_VAR([RSH], [Configure absolute path to default remote shell binary])
|
||||
AC_CACHE_CHECK(for remote shell, tar_cv_path_RSH,
|
||||
[if test -n "$RSH"; then
|
||||
tar_cv_path_RSH=$RSH
|
||||
@@ -121,6 +242,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],
|
||||
@@ -145,7 +274,7 @@ if test -z "$DEFAULT_ARCHIVE"; then
|
||||
DEFAULT_ARCHIVE=-
|
||||
else
|
||||
if test -z "`ls $DEFAULT_ARCHIVE 2>/dev/null`"; then
|
||||
AC_MSG_WARN(DEFAULT_ARCHIVE \`$DEFAULT_ARCHIVE' not found on this system)
|
||||
AC_MSG_WARN(DEFAULT_ARCHIVE '$DEFAULT_ARCHIVE' not found on this system)
|
||||
fi
|
||||
# FIXME: Look for DEFTAPE in <sys/mtio.h>.
|
||||
# FIXME: Let DEVICE_PREFIX be configured from the environment.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
%%comments:
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
Copyright 2004, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2 or
|
||||
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, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the file COPYING.
|
||||
Texts. For a copy of the license, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
%%name: tar
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
# Makefile for GNU tar documentation.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
|
||||
# 2007 Free Software Foundation, Inc.
|
||||
# Copyright 1994-1997, 1999-2001, 2003, 2006-2007, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
## 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.
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
## 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.
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
info_TEXINFOS = tar.texi
|
||||
tar_TEXINFOS = \
|
||||
@@ -24,17 +25,23 @@ tar_TEXINFOS = \
|
||||
fdl.texi\
|
||||
freemanuals.texi\
|
||||
genfile.texi\
|
||||
getdate.texi\
|
||||
header.texi\
|
||||
intern.texi\
|
||||
parse-datetime.texi\
|
||||
rendition.texi\
|
||||
snapshot.texi\
|
||||
sparse.texi\
|
||||
value.texi
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el
|
||||
|
||||
dist_man_MANS=tar.1 $(RMT_8)
|
||||
if PU_RMT_COND
|
||||
RMT_8=rmt.8
|
||||
endif
|
||||
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el rmt.8
|
||||
|
||||
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
|
||||
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
|
||||
# Just call 'make RENDITION=PROOF [target]' if you want PROOF rendition.
|
||||
RENDITION = DISTRIB
|
||||
|
||||
MAKEINFOFLAGS=-D$(RENDITION)
|
||||
@@ -59,25 +66,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 +131,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 +151,3 @@ manual:
|
||||
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
|
||||
$(GENDOCS) --texi2html tar 'GNU tar manual'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 2006-2007, 2014 Free Software Foundation, Inc.
|
||||
@c Written by Sergey Poznyakoff
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
@@ -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
|
||||
|
||||
111
doc/fdl.texi
111
doc/fdl.texi
@@ -1,13 +1,13 @@
|
||||
@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-2002, 2007-2008, 2014 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 +93,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 +112,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 +383,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 +424,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 +473,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 +482,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
|
||||
@@ -106,7 +106,7 @@ Please send broken links and other corrections (or suggestions) to
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.,
|
||||
Copyright 2004, 2013-2014 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02111, USA
|
||||
<br />
|
||||
Verbatim copying and distribution of this entire article is
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 2006, 2014 Free Software Foundation, Inc.
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,37 +1,36 @@
|
||||
;;; mastermenu.el --- Redefinition of texinfo-master-menu-list
|
||||
|
||||
;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
;; Copyright 2006-2007, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Sergey Poznyakoff
|
||||
;; Maintainer: bug-tar@gnu.org
|
||||
;; Keywords: maint, tex, docs
|
||||
|
||||
;; This file is part of GNU tar documentation suite
|
||||
;; This file is part of GNU tar.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; GNU tar is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 3, or (at your option)
|
||||
;; any later version.
|
||||
;; the Free Software Foundation; either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; GNU tar is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program; if not, write to the Free Software Foundation,
|
||||
;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file redefines texinfo-master-menu-list so that it takes into
|
||||
;; account included files.
|
||||
|
||||
;; Known bugs: @menu without previous sectioning command will inherit
|
||||
;; 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)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@c This is part of GNU tar manual.
|
||||
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
@c 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
@c Copyright 1992, 1994-1997, 1999-2004, 2006, 2013-2014 Free Software
|
||||
@c Foundation, Inc.
|
||||
@c See file tar.texi for copying conditions.
|
||||
|
||||
@c This file contains support for 'renditions' by Fran@,{c}ois Pinard
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 2005, 2007, 2014 Free Software Foundation, Inc.
|
||||
@c Written by Sergey Poznyakoff
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
@@ -11,11 +11,11 @@ used to determine which files were modified since the last backup.
|
||||
|
||||
@GNUTAR{} version @value{VERSION} supports three snapshot file
|
||||
formats. The first format, called @dfn{format 0}, is the one used by
|
||||
@GNUTAR{} versions up to 1.15.1. The second format, called @dfn{format
|
||||
1} is an extended version of this format, that contains more metadata
|
||||
and allows for further extensions. It was used by version
|
||||
1.15.1. Starting from version 1.16 and up to @value{VERSION}, the
|
||||
@dfn{format 2} is used.
|
||||
@GNUTAR{} versions up to and including 1.15.1. The second format, called
|
||||
@dfn{format 1} is an extended version of this format, that contains more
|
||||
metadata and allows for further extensions. It was used by alpha release
|
||||
version 1.15.90. For alpha version 1.15.91 and stable releases
|
||||
version 1.16 up through @value{VERSION}, the @dfn{format 2} is used.
|
||||
|
||||
@GNUTAR{} is able to read all three formats, but will create
|
||||
snapshots only in format 2.
|
||||
@@ -23,17 +23,17 @@ 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}
|
||||
[@var{nfs}]@var{dev} @var{inode} @var{name}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
@@ -42,7 +42,10 @@ where:
|
||||
@table @var
|
||||
@item nfs
|
||||
A single plus character (@samp{+}), if this directory is located on
|
||||
an @acronym{NFS}-mounted partition, or a single space otherwise;
|
||||
an @acronym{NFS}-mounted partition, otherwise empty.
|
||||
|
||||
(That is, for non-NFS directories, the first character on the
|
||||
description line contains the start of the @var{dev} field.)
|
||||
|
||||
@item dev
|
||||
Device number of the directory;
|
||||
@@ -55,9 +58,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 +72,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 +92,10 @@ 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
|
||||
@samp{Format 2} snapshot file begins with a format identifier, as described for
|
||||
version 1, e.g.:
|
||||
|
||||
@smallexample
|
||||
@@ -105,37 +107,58 @@ records, separated by null (@acronym{ASCII} 0)
|
||||
characters. Thus, in contrast to the previous formats, format 2
|
||||
snapshot is a binary file.
|
||||
|
||||
First two records are decimal numbers, representing the
|
||||
First two records are decimal integers, representing the
|
||||
time of the last backup. First number is the number of seconds, the
|
||||
second one is the number of nanoseconds, since the beginning of the
|
||||
epoch. These are followed by arbitrary number of directory records.
|
||||
|
||||
|
||||
Each @dfn{directory record} contains a set of metadata describing a
|
||||
particular directory. Parts of a directory record are delimited with
|
||||
@acronym{ASCII} 0 characters. The following table describes each
|
||||
part. The @dfn{Number} type in this table stands for a decimal number
|
||||
in @acronym{ASCII} notation.
|
||||
part. The @dfn{Number} type in this table stands for a decimal integer
|
||||
in @acronym{ASCII} notation. (Negative values are preceeded with a "-"
|
||||
character, while positive values have no leading punctuation.)
|
||||
|
||||
@multitable @columnfractions 0.2 0.2 0.6
|
||||
@multitable @columnfractions 0.25 0.15 0.6
|
||||
@headitem Field @tab Type @tab Description
|
||||
@item nfs @tab Character @tab @samp{1} if the directory is located on
|
||||
an @acronym{NFS}-mounted partition, or @samp{0} otherwise;
|
||||
@item mtime-sec @tab Number @tab Modification time, seconds;
|
||||
@item mtime-nano @tab Number @tab Modification time, nanoseconds;
|
||||
@item dev-no @tab Number @tab Device number;
|
||||
@item i-no @tab Number @tab I-node number;
|
||||
@item name @tab String @tab Directory name; In contrast to the
|
||||
previous versions it is not quoted.
|
||||
@item timestamp_sec @tab Number @tab Modification time, seconds;
|
||||
@item timestamp_nsec @tab Number @tab Modification time, nanoseconds;
|
||||
@item dev @tab Number @tab Device number;
|
||||
@item ino @tab Number @tab I-node number;
|
||||
@item name @tab String @tab Directory name; in contrast to the
|
||||
previous versions it is not quoted;
|
||||
@item contents @tab Dumpdir @tab Contents of the directory;
|
||||
@xref{Dumpdir}, for a description of its format.
|
||||
@item
|
||||
@item
|
||||
@end multitable
|
||||
|
||||
Dumpdirs stored in snapshot files contain only records of types
|
||||
@samp{Y}, @samp{N} and @samp{D}.
|
||||
|
||||
@cindex snapshot file field ranges
|
||||
@opindex show-snapshot-field-ranges
|
||||
The specific range of values allowed in each of the @dfn{Number} fields
|
||||
depends on the underlying C datatypes as determined when @command{tar}
|
||||
is compiled. To see the specific ranges allowed for a particular
|
||||
@command{tar} binary, you can use the
|
||||
@option{--show-snapshot-field-ranges} option:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar --show-shapshot-field-ranges}
|
||||
This tar's snapshot file field ranges are
|
||||
(field name => [ min, max ]):
|
||||
|
||||
nfs => [ 0, 1 ],
|
||||
timestamp_sec => [ -9223372036854775808, 9223372036854775807 ],
|
||||
timestamp_nsec => [ 0, 999999999 ],
|
||||
dev => [ 0, 18446744073709551615 ],
|
||||
ino => [ 0, 18446744073709551615 ],
|
||||
@end smallexample
|
||||
|
||||
(This example is from a GNU/Linux x86_64 system.)
|
||||
|
||||
@end enumerate
|
||||
|
||||
@c End of snapshot.texi
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 2006, 2014 Free Software Foundation, Inc.
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
@@ -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{}.
|
||||
|
||||
|
||||
@@ -1,29 +1,33 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 2007, 2014 Free Software Foundation, Inc.
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
@cindex Device numbers, changing
|
||||
@cindex snapshot files, editing
|
||||
@cindex snapshot files, fixing device numbers
|
||||
Sometimes device numbers can change after upgrading your kernel
|
||||
version or recofiguring the harvare. Reportedly this is the case with
|
||||
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
|
||||
Various situations can cause device numbers to change: upgrading your
|
||||
kernel version, reconfiguring your hardware, loading kernel modules in a
|
||||
different order, using virtual volumes that are assembled dynamically
|
||||
(such as with @acronym{LVM} or @acronym{RAID}), hot-plugging drives
|
||||
(e.g. external USB or Firewire drives), etc. In the majority of
|
||||
cases this change is unnoticed by the users. However, it influences
|
||||
@command{tar} incremental backups: the device number is stored in tar
|
||||
snapshot files (@pxref{Snapshot Files}) and is used to determine whether
|
||||
the file has changed since the last backup. If the device numbers
|
||||
change for some reason, the next backup you run will be a full backup.
|
||||
change for some reason, by default the next backup you run will be a
|
||||
full backup.
|
||||
|
||||
|
||||
@pindex tar-snapshot-edit
|
||||
To minimize the impact in these cases, GNU @command{tar} comes with
|
||||
the @command{tar-snapshot-edit} utility for inspecting and updating
|
||||
device numbers in snapshot files. The utility, written by
|
||||
Dustin J.@: Mitchell, is available from
|
||||
device numbers in snapshot files. (The utility, written by
|
||||
Dustin J.@: Mitchell, is also available from the
|
||||
@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 a summary of the device numbers found in the snapshot file, run
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar-snapshot-edit @var{snapfile}}
|
||||
@@ -31,10 +35,19 @@ $ @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). You can then compare the
|
||||
numbers across snapshot files, or against those currently in use on the
|
||||
live filesystem (using @command{ls -l} or @command{stat}).
|
||||
|
||||
To update all occurrences of the given device number in the file, use
|
||||
@option{-r} option. It takes a single argument of the form
|
||||
Assuming the device numbers have indeed changed, it's often possible
|
||||
to simply tell @GNUTAR{} to ignore the device number when processing the
|
||||
incremental snapshot files for these backups, using the
|
||||
@option{--no-check-device} option (@pxref{device numbers}).
|
||||
|
||||
Alternatively, you can use the @command{tar-edit-snapshot} script's
|
||||
@option{-r} option to update all occurrences of the given device
|
||||
number in the snapshot file(s). It takes a single argument
|
||||
of the form
|
||||
@samp{@var{olddev}-@var{newdev}}, where @var{olddev} is the device number
|
||||
used in the snapshot file, and @var{newdev} is the corresponding new device
|
||||
number. Both numbers may be specified in hex (e.g., @samp{0xfe01}),
|
||||
@@ -49,10 +62,30 @@ backup file is obtained by appending @samp{~} to the original file name.
|
||||
|
||||
An example session:
|
||||
@smallexample
|
||||
$ @kbd{tar-snapshot-edit /var/backup/snap.a}
|
||||
file version 2
|
||||
/tmp/snap: Device 0x0306 occurs 634 times.
|
||||
$ @kbd{tar-snapshot-edit -b -r 0x0306-0x4500 /var/backup/snap.a}
|
||||
file version 2
|
||||
@end smallexample
|
||||
$ @kbd{tar-snapshot-edit root_snap.0 boot_snap.0}
|
||||
File: root_snap.0
|
||||
Detected snapshot file version: 2
|
||||
|
||||
Device 0x0000 occurs 1 times.
|
||||
Device 0x0003 occurs 1 times.
|
||||
Device 0x0005 occurs 1 times.
|
||||
Device 0x0013 occurs 1 times.
|
||||
Device 0x6801 occurs 1 times.
|
||||
Device 0x6803 occurs 6626 times.
|
||||
Device 0xfb00 occurs 1 times.
|
||||
|
||||
File: boot_snap.0
|
||||
Detected snapshot file version: 2
|
||||
|
||||
Device 0x6801 occurs 3 times.
|
||||
$ @kbd{tar-snapshot-edit -b -r 0x6801-0x6901,0x6803-0x6903 root_snap.0 boot_snap.0}
|
||||
File: root_snap.0
|
||||
Detected snapshot file version: 2
|
||||
|
||||
Updated 6627 records.
|
||||
|
||||
File: boot_snap.0
|
||||
Detected snapshot file version: 2
|
||||
|
||||
Updated 3 records.
|
||||
@end smallexample
|
||||
|
||||
2274
doc/tar.texi
2274
doc/tar.texi
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,19 @@
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# GNU tar is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3, or (at
|
||||
# your option) any later version.
|
||||
#
|
||||
# GNU tar is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# Copyright 2006-2007, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU tar; if not, write to the Free Software
|
||||
# Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
1{s,/\*,@comment ,
|
||||
b
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@c This is part of GNU tar manual.
|
||||
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
@c 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
@c Copyright 1992, 1994-1997, 1999-2006, 2013-2014 Free Software
|
||||
@c Foundation, Inc.
|
||||
@c See file tar.texi for copying conditions.
|
||||
|
||||
@macro GNUTAR
|
||||
@@ -18,5 +18,3 @@
|
||||
@end ifclear
|
||||
@xopindex{\option\, summary}
|
||||
@end macro
|
||||
|
||||
|
||||
|
||||
3
gnu/Makefile.am
Normal file
3
gnu/Makefile.am
Normal file
@@ -0,0 +1,3 @@
|
||||
# Make the subset of Gnulib that GNU tar needs.
|
||||
include gnulib.mk
|
||||
AM_CFLAGS += $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
@@ -1,42 +1,83 @@
|
||||
# List of gnulib modules needed for GNU tar.
|
||||
# A module name per line. Empty lines and comments are ignored.
|
||||
|
||||
# Copyright 2005-2010, 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
acl
|
||||
alloca
|
||||
argmatch
|
||||
argp
|
||||
argp-version-etc
|
||||
backupfile
|
||||
closeout
|
||||
configmake
|
||||
dirname
|
||||
error
|
||||
exclude
|
||||
extern-inline
|
||||
exitfail
|
||||
faccessat
|
||||
fchmodat
|
||||
fchownat
|
||||
fcntl-h
|
||||
fdopendir
|
||||
fdutimensat
|
||||
fileblocks
|
||||
fnmatch-gnu
|
||||
fprintftime
|
||||
fseeko
|
||||
ftruncate
|
||||
fstatat
|
||||
full-write
|
||||
getdate
|
||||
futimens
|
||||
getline
|
||||
getopt
|
||||
getopt-gnu
|
||||
getpagesize
|
||||
gettext
|
||||
gettime
|
||||
gitlog-to-changelog
|
||||
hash
|
||||
human
|
||||
inttostr
|
||||
inttypes
|
||||
lchown
|
||||
linkat
|
||||
localcharset
|
||||
manywarnings
|
||||
mkdirat
|
||||
mkdtemp
|
||||
mkfifoat
|
||||
modechange
|
||||
obstack
|
||||
openat
|
||||
parse-datetime
|
||||
posix_openpt
|
||||
ptsname
|
||||
priv-set
|
||||
progname
|
||||
quote
|
||||
quotearg
|
||||
readlinkat
|
||||
renameat
|
||||
root-uid
|
||||
rpmatch
|
||||
safe-read
|
||||
save-cwd
|
||||
savedir
|
||||
selinux-at
|
||||
setenv
|
||||
snprintf
|
||||
stat-time
|
||||
@@ -45,15 +86,20 @@ stdint
|
||||
stpcpy
|
||||
strdup-posix
|
||||
strerror
|
||||
strtoimax
|
||||
strtol
|
||||
strtoul
|
||||
strtoumax
|
||||
symlinkat
|
||||
timespec
|
||||
unlinkat
|
||||
unlinkdir
|
||||
unlocked-io
|
||||
utime
|
||||
utimens
|
||||
unlockpt
|
||||
utimensat
|
||||
version-etc-fsf
|
||||
xalloc
|
||||
xalloc-die
|
||||
xgetcwd
|
||||
xstrtoumax
|
||||
xvasprintf
|
||||
|
||||
10
lib/.gitignore
vendored
Normal file
10
lib/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
paxerror.c
|
||||
paxexit-status.c
|
||||
paxexit.c
|
||||
paxlib.h
|
||||
paxnames.c
|
||||
rmt-command.h
|
||||
rmt.h
|
||||
rtapelib.c
|
||||
system-ioctl.h
|
||||
system.h
|
||||
@@ -1,39 +1,62 @@
|
||||
# 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.
|
||||
# Copyright 1994-1997, 1999-2001, 2003-2007, 2009-2010, 2013-2014 Free
|
||||
# Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu
|
||||
AM_CFLAGS = $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
|
||||
noinst_HEADERS = \
|
||||
paxlib.h\
|
||||
rmt.h\
|
||||
stdopen.h\
|
||||
system.h\
|
||||
system-ioctl.h\
|
||||
wordsplit.h\
|
||||
xattr-at.h
|
||||
|
||||
noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h
|
||||
libtar_a_SOURCES = \
|
||||
paxerror.c paxexit.c paxlib.h paxnames.c \
|
||||
paxerror.c paxexit-status.c paxlib.h paxnames.c \
|
||||
prepargs.c prepargs.h \
|
||||
rtapelib.c \
|
||||
rmt.h \
|
||||
stdopen.c stdopen.h \
|
||||
system.h system-ioctl.h
|
||||
system.h system-ioctl.h \
|
||||
wordsplit.c\
|
||||
xattr-at.c
|
||||
|
||||
if !TAR_COND_XATTR_H
|
||||
BUILT_SOURCES += attr/xattr.h
|
||||
attr/xattr.h: attr-xattr.in.h $(top_builddir)/config.status
|
||||
$(AM_V_at)$(MKDIR_P) attr
|
||||
$(AM_V_GEN)rm -f $@-t $@ && \
|
||||
cp $(srcdir)/attr-xattr.in.h attr/xattr.h
|
||||
endif
|
||||
|
||||
MOSTLYCLEANFILES = attr/xattr.h
|
||||
|
||||
EXTRA_DIST = attr-xattr.in.h
|
||||
|
||||
60
lib/attr-xattr.in.h
Normal file
60
lib/attr-xattr.in.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Replacement <attr/xattr.h> for platforms that lack it.
|
||||
Copyright 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef TAR_ATTR_XATTR_H
|
||||
#define TAR_ATTR_XATTR_H
|
||||
#include <errno.h>
|
||||
#ifndef ENOATTR
|
||||
# define ENOATTR ENODATA /* No such attribute */
|
||||
#endif
|
||||
|
||||
/* setting */
|
||||
static inline int setxattr (const char *path, const char *name, const void
|
||||
*value, size_t size, int flags)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
|
||||
static inline int lsetxattr (const char *path, const char *name, const void
|
||||
*value, size_t size, int flags)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
|
||||
static inline int fsetxattr (int filedes, const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
|
||||
|
||||
/* getting */
|
||||
static inline ssize_t getxattr (const char *path, const char *name, void *value,
|
||||
size_t size)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
static inline ssize_t lgetxattr (const char *path, const char *name, void
|
||||
*value, size_t size)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
static inline ssize_t fgetxattr (int filedes, const char *name, void *value,
|
||||
size_t size)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
|
||||
|
||||
/* listing */
|
||||
static inline ssize_t listxattr (const char *path, char *list, size_t size)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
|
||||
static inline ssize_t llistxattr (const char *path, char *list, size_t size)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
|
||||
static inline ssize_t flistxattr (int filedes, char *list, size_t size)
|
||||
{ errno = ENOTSUP; return -1; }
|
||||
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Parse arguments from a string and prepend them to an argv.
|
||||
Copyright 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
|
||||
Copyright 1999-2001, 2007, 2013-2014 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
|
||||
@@ -12,9 +12,7 @@
|
||||
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. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com>. */
|
||||
|
||||
@@ -31,16 +29,6 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
|
||||
as an argument to <ctype.h> macros like "isspace". */
|
||||
#ifdef STDC_HEADERS
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# define IN_CTYPE_DOMAIN(c) ((c) <= 0177)
|
||||
#endif
|
||||
|
||||
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
|
||||
|
||||
/* Find the white-space-separated options specified by OPTIONS, and
|
||||
using BUF to store copies of these options, set ARGV[0], ARGV[1],
|
||||
etc. to the option copies. Return the number N of options found.
|
||||
@@ -55,7 +43,7 @@ prepend_args (char const *options, char *buf, char **argv)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (ISSPACE ((unsigned char) *o))
|
||||
while (isspace ((unsigned char) *o))
|
||||
o++;
|
||||
if (!*o)
|
||||
return n;
|
||||
@@ -66,7 +54,7 @@ prepend_args (char const *options, char *buf, char **argv)
|
||||
do
|
||||
if ((*b++ = *o++) == '\\' && *o)
|
||||
b[-1] = *o++;
|
||||
while (*o && ! ISSPACE ((unsigned char) *o));
|
||||
while (*o && ! isspace ((unsigned char) *o));
|
||||
|
||||
*b++ = '\0';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* stdopen.c - ensure that the three standard file descriptors are in use
|
||||
|
||||
Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2005, 2007, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -13,8 +13,7 @@
|
||||
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. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert and Jim Meyering. */
|
||||
|
||||
|
||||
1628
lib/wordsplit.c
Normal file
1628
lib/wordsplit.c
Normal file
File diff suppressed because it is too large
Load Diff
162
lib/wordsplit.h
Normal file
162
lib/wordsplit.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/* wordsplit - a word splitter
|
||||
Copyright (C) 2009-2014 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Written by Sergey Poznyakoff
|
||||
*/
|
||||
|
||||
#ifndef __WORDSPLIT_H
|
||||
#define __WORDSPLIT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct wordsplit
|
||||
{
|
||||
size_t ws_wordc;
|
||||
char **ws_wordv;
|
||||
size_t ws_offs;
|
||||
size_t ws_wordn;
|
||||
int ws_flags;
|
||||
const char *ws_delim;
|
||||
const char *ws_comment;
|
||||
const char *ws_escape;
|
||||
void (*ws_alloc_die) (struct wordsplit * wsp);
|
||||
void (*ws_error) (const char *, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
void (*ws_debug) (const char *, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
const char **ws_env;
|
||||
const char *(*ws_getvar) (const char *, size_t, void *);
|
||||
void *ws_closure;
|
||||
|
||||
const char *ws_input;
|
||||
size_t ws_len;
|
||||
size_t ws_endp;
|
||||
int ws_errno;
|
||||
struct wordsplit_node *ws_head, *ws_tail;
|
||||
};
|
||||
|
||||
/* Wordsplit flags. Only 2 bits of a 32-bit word remain unused.
|
||||
It is getting crowded... */
|
||||
/* Append the words found to the array resulting from a previous
|
||||
call. */
|
||||
#define WRDSF_APPEND 0x00000001
|
||||
/* Insert we_offs initial NULLs in the array ws_wordv.
|
||||
(These are not counted in the returned ws_wordc.) */
|
||||
#define WRDSF_DOOFFS 0x00000002
|
||||
/* Don't do command substitution. Reserved for future use. */
|
||||
#define WRDSF_NOCMD 0x00000004
|
||||
/* The parameter p resulted from a previous call to
|
||||
wordsplit(), and wordsplit_free() was not called. Reuse the
|
||||
allocated storage. */
|
||||
#define WRDSF_REUSE 0x00000008
|
||||
/* Print errors */
|
||||
#define WRDSF_SHOWERR 0x00000010
|
||||
/* Consider it an error if an undefined shell variable
|
||||
is expanded. */
|
||||
#define WRDSF_UNDEF 0x00000020
|
||||
|
||||
/* Don't do variable expansion. */
|
||||
#define WRDSF_NOVAR 0x00000040
|
||||
/* Abort on ENOMEM error */
|
||||
#define WRDSF_ENOMEMABRT 0x00000080
|
||||
/* Trim off any leading and trailind whitespace */
|
||||
#define WRDSF_WS 0x00000100
|
||||
/* Handle single quotes */
|
||||
#define WRDSF_SQUOTE 0x00000200
|
||||
/* Handle double quotes */
|
||||
#define WRDSF_DQUOTE 0x00000400
|
||||
/* Handle quotes and escape directives */
|
||||
#define WRDSF_QUOTE (WRDSF_SQUOTE|WRDSF_DQUOTE)
|
||||
/* Replace each input sequence of repeated delimiters with a single
|
||||
delimiter */
|
||||
#define WRDSF_SQUEEZE_DELIMS 0x00000800
|
||||
/* Return delimiters */
|
||||
#define WRDSF_RETURN_DELIMS 0x00001000
|
||||
/* Treat sed expressions as words */
|
||||
#define WRDSF_SED_EXPR 0x00002000
|
||||
/* ws_delim field is initialized */
|
||||
#define WRDSF_DELIM 0x00004000
|
||||
/* ws_comment field is initialized */
|
||||
#define WRDSF_COMMENT 0x00008000
|
||||
/* ws_alloc_die field is initialized */
|
||||
#define WRDSF_ALLOC_DIE 0x00010000
|
||||
/* ws_error field is initialized */
|
||||
#define WRDSF_ERROR 0x00020000
|
||||
/* ws_debug field is initialized */
|
||||
#define WRDSF_DEBUG 0x00040000
|
||||
/* ws_env field is initialized */
|
||||
#define WRDSF_ENV 0x00080000
|
||||
/* ws_getvar field is initialized */
|
||||
#define WRDSF_GETVAR 0x00100000
|
||||
/* enable debugging */
|
||||
#define WRDSF_SHOWDBG 0x00200000
|
||||
/* Don't split input into words. Useful for side effects. */
|
||||
#define WRDSF_NOSPLIT 0x00400000
|
||||
/* Keep undefined variables in place, instead of expanding them to
|
||||
empty string */
|
||||
#define WRDSF_KEEPUNDEF 0x00800000
|
||||
/* Warn about undefined variables */
|
||||
#define WRDSF_WARNUNDEF 0x01000000
|
||||
/* Handle C escapes */
|
||||
#define WRDSF_CESCAPES 0x02000000
|
||||
|
||||
/* ws_closure is set */
|
||||
#define WRDSF_CLOSURE 0x04000000
|
||||
/* ws_env is a Key/Value environment, i.e. the value of a variable is
|
||||
stored in the element that follows its name. */
|
||||
#define WRDSF_ENV_KV 0x08000000
|
||||
|
||||
/* ws_escape is set */
|
||||
#define WRDSF_ESCAPE 0x10000000
|
||||
|
||||
/* Incremental mode */
|
||||
#define WRDSF_INCREMENTAL 0x20000000
|
||||
|
||||
#define WRDSF_DEFFLAGS \
|
||||
(WRDSF_NOVAR | WRDSF_NOCMD | \
|
||||
WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_CESCAPES)
|
||||
|
||||
#define WRDSE_EOF 0
|
||||
#define WRDSE_QUOTE 1
|
||||
#define WRDSE_NOSPACE 2
|
||||
#define WRDSE_NOSUPP 3
|
||||
#define WRDSE_USAGE 4
|
||||
#define WRDSE_CBRACE 5
|
||||
#define WRDSE_UNDEF 6
|
||||
#define WRDSE_NOINPUT 7
|
||||
|
||||
int wordsplit (const char *s, struct wordsplit *p, int flags);
|
||||
int wordsplit_len (const char *s, size_t len,
|
||||
struct wordsplit *p, int flags);
|
||||
void wordsplit_free (struct wordsplit *p);
|
||||
void wordsplit_free_words (struct wordsplit *ws);
|
||||
|
||||
int wordsplit_c_unquote_char (int c);
|
||||
int wordsplit_c_quote_char (int c);
|
||||
size_t wordsplit_c_quoted_length (const char *str, int quote_hex,
|
||||
int *quote);
|
||||
void wordsplit_general_unquote_copy (char *dst, const char *src, size_t n,
|
||||
const char *escapable);
|
||||
void wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n);
|
||||
void wordsplit_c_unquote_copy (char *dst, const char *src, size_t n);
|
||||
void wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex);
|
||||
|
||||
void wordsplit_perror (struct wordsplit *ws);
|
||||
const char *wordsplit_strerror (struct wordsplit *ws);
|
||||
|
||||
|
||||
#endif
|
||||
110
lib/xattr-at.c
Normal file
110
lib/xattr-at.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/* openat-style fd-relative functions for operating with extended file
|
||||
attributes.
|
||||
|
||||
Copyright 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "xattr-at.h"
|
||||
#include "openat.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
|
||||
#include "save-cwd.h"
|
||||
|
||||
#include "openat-priv.h"
|
||||
|
||||
/* setxattrat */
|
||||
#define AT_FUNC_NAME setxattrat
|
||||
#define AT_FUNC_F1 setxattr
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, const void *value \
|
||||
, size_t size, int flags
|
||||
#define AT_FUNC_POST_FILE_ARGS , name, value, size, flags
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* lsetxattrat */
|
||||
#define AT_FUNC_NAME lsetxattrat
|
||||
#define AT_FUNC_F1 lsetxattr
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, const void *value \
|
||||
, size_t size, int flags
|
||||
#define AT_FUNC_POST_FILE_ARGS , name, value, size, flags
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* getxattrat */
|
||||
#define AT_FUNC_NAME getxattrat
|
||||
#define AT_FUNC_RESULT ssize_t
|
||||
#define AT_FUNC_F1 getxattr
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, void *value \
|
||||
, size_t size
|
||||
#define AT_FUNC_POST_FILE_ARGS , name, value, size
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_RESULT
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* lgetxattrat */
|
||||
#define AT_FUNC_NAME lgetxattrat
|
||||
#define AT_FUNC_RESULT ssize_t
|
||||
#define AT_FUNC_F1 lgetxattr
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , const char *name, void *value \
|
||||
, size_t size
|
||||
#define AT_FUNC_POST_FILE_ARGS , name, value, size
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_RESULT
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* listxattrat */
|
||||
#define AT_FUNC_NAME listxattrat
|
||||
#define AT_FUNC_RESULT ssize_t
|
||||
#define AT_FUNC_F1 listxattr
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , char *list , size_t size
|
||||
#define AT_FUNC_POST_FILE_ARGS , list , size
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_RESULT
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* llistxattrat */
|
||||
#define AT_FUNC_NAME llistxattrat
|
||||
#define AT_FUNC_RESULT ssize_t
|
||||
#define AT_FUNC_F1 llistxattr
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , char *list , size_t size
|
||||
#define AT_FUNC_POST_FILE_ARGS , list , size
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_RESULT
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
74
lib/xattr-at.h
Normal file
74
lib/xattr-at.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Prototypes for openat-style fd-relative functions for operating with
|
||||
extended file attributes.
|
||||
|
||||
Copyright 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef XATTRS_AT_H
|
||||
#define XATTRS_AT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(HAVE_SYS_XATTR_H)
|
||||
# include <sys/xattr.h>
|
||||
#elif defined(HAVE_ATTR_XATTR_H)
|
||||
# include <attr/xattr.h>
|
||||
#endif
|
||||
|
||||
#ifndef ENOATTR
|
||||
# define ENOATTR ENODATA /* No such attribute */
|
||||
#endif
|
||||
|
||||
/* These are the dir-fd-relative variants of the functions without the
|
||||
"at" suffix. For example, setxattrat (AT_FDCWD, path, name, value, size,
|
||||
flags &c) is usually equivalent to setxattr (file, name, value, size,
|
||||
flags). For more info use the setxattr(2), getxattr(2) or listxattr(2)
|
||||
manpages. */
|
||||
|
||||
/* dir-fd-relative setxattr. Operation sets the VALUE of the extended
|
||||
attribute identified by NAME and associated with the given PATH in the
|
||||
filesystem relatively to directory identified by DIR_FD. See the
|
||||
setxattr(2) manpage for the description of all parameters. */
|
||||
int setxattrat (int dir_fd, const char *path, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
|
||||
/* dir-fd-relative lsetxattr. This function is just like setxattrat,
|
||||
except when DIR_FD and FILE specify a symlink: lsetxattrat operates on the
|
||||
symlink, while the setxattrat operates on the referent of the symlink. */
|
||||
int lsetxattrat (int dir_fd, const char *path, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
|
||||
/* dir-fd-relative getxattr. Operation gets the VALUE of the extended
|
||||
attribute idenfified by NAME and associated with the given PATH in the
|
||||
filesystem relatively to directory identified by DIR_FD. For more info
|
||||
about all parameters see the getxattr(2) manpage. */
|
||||
ssize_t getxattrat (int dir_fd, const char *path, const char *name,
|
||||
void *value, size_t size);
|
||||
|
||||
/* dir-fd-relative lgetxattr. This function is just like getxattrat,
|
||||
except when DIR_FD and FILE specify a symlink: lgetxattrat operates on the
|
||||
symlink, while the getxattrat operates on the referent of the symlink. */
|
||||
ssize_t lgetxattrat (int dir_fd, const char *path, const char *name,
|
||||
void *value, size_t size);
|
||||
|
||||
/* dir-fd-relative listxattr. Obtain the list of extended attrubtes names. For
|
||||
more info see the listxattr(2) manpage. */
|
||||
ssize_t listxattrat (int dir_fd, const char *path, char *list, size_t size);
|
||||
|
||||
/* dir-fd-relative llistxattr. This function is just like listxattrat,
|
||||
except when DIR_FD and FILE specify a symlink: llistxattr operates on the
|
||||
symlink, while the listxattrat operates on the referent of the symlink. */
|
||||
ssize_t llistxattrat (int dir_fd, const char *path, char *list, size_t size);
|
||||
|
||||
#endif /* XATTRS_AT_H */
|
||||
@@ -1,22 +1,22 @@
|
||||
# List of files which contain translatable strings.
|
||||
|
||||
# Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005, 2007 Free Software
|
||||
# Copyright 1996, 1999-2000, 2003-2005, 2007, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Library files
|
||||
gnu/argmatch.c
|
||||
@@ -37,7 +37,6 @@ gnu/version-etc.c
|
||||
gnu/xalloc-die.c
|
||||
|
||||
lib/paxerror.c
|
||||
lib/paxexit.c
|
||||
lib/paxnames.c
|
||||
lib/rtapelib.c
|
||||
|
||||
|
||||
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))))
|
||||
@@ -1,19 +1,21 @@
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Make GNU tar scripts.
|
||||
|
||||
## 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.
|
||||
# Copyright 2004, 2006-2007, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
## 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.
|
||||
# This file is part of GNU tar.
|
||||
|
||||
## 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.
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
BACKUP_LIBEXEC_SCRIPTS_LIST=backup.sh dump-remind
|
||||
BACKUP_SBIN_SCRIPTS_LIST=backup restore
|
||||
|
||||
@@ -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,26 +75,26 @@ 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 !!!!!\"
|
||||
}' /dev/null`"
|
||||
|
||||
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
# Copyright 2004, 2007, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
## 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.
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
## 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.
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright (C) 2004, 2005, 2006 Free Software Foundation
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# Make backups.
|
||||
|
||||
# Copyright 2004-2006, 2013 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 1, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Load library routines
|
||||
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
@@ -72,8 +73,9 @@ do
|
||||
--l=*|--le=*|--lev=*|--leve=*|--level=*)
|
||||
DUMP_LEVEL=$optarg
|
||||
;;
|
||||
-l?*) DUMP_LEVEL=`expr $option : '-l\(.*\)'`;;
|
||||
-l|--l|--le|--lev|--leve|--level)
|
||||
prev=$option
|
||||
prev=--level
|
||||
;;
|
||||
--verb=*|--verbo=*|--verbos=*|--verbose=*)
|
||||
VERBOSE=$optarg
|
||||
@@ -81,14 +83,13 @@ do
|
||||
-v|--verb|--verbo|--verbos|--verbose)
|
||||
VERBOSE=100
|
||||
;;
|
||||
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
|
||||
-v*) VERBOSE=`expr $option : '-v\(.*\)'`;;
|
||||
--t=*|--ti=*|--tim=*|--time=*)
|
||||
TIME=$optarg
|
||||
;;
|
||||
-t) prev=--t;;
|
||||
-t*) TIME=`expr $option : "-t\(.*\)"`;;
|
||||
--t|--ti|--tim|--time)
|
||||
prev=$option
|
||||
-t?*) TIME=`expr $option : '-t\(.*\)'`;;
|
||||
-t|--t|--ti|--tim|--time)
|
||||
prev=--time
|
||||
;;
|
||||
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "backup (@PACKAGE_NAME@) @VERSION@"
|
||||
@@ -149,7 +150,7 @@ message 20 "BACKUP_DIRS=$BACKUP_DIRS"
|
||||
message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
|
||||
# The buch of commands below is run in a subshell for which all output is
|
||||
# piped through `tee' to the logfile. Doing this, instead of having
|
||||
# piped through 'tee' to the logfile. Doing this, instead of having
|
||||
# multiple pipelines all over the place, is cleaner and allows access to
|
||||
# the exit value from various commands more easily.
|
||||
(
|
||||
@@ -187,7 +188,7 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
"--label='`print_level` backup of ${fs} on ${remotehost} at ${NOW}'" \
|
||||
-C ${fs} .
|
||||
|
||||
# `rsh' doesn't exit with the exit status of the remote command. What
|
||||
# 'rsh' doesn't exit with the exit status of the remote command. What
|
||||
# stupid lossage. TODO: think of a reliable workaround.
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Backup of ${1} failed." 1>&2
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# Make backups.
|
||||
|
||||
# Copyright 2004-2006, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 1, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
PROGNAME=`basename $0`
|
||||
CONFIGPATH="$SYSCONFDIR/backup"
|
||||
@@ -48,7 +49,7 @@ MT_REWIND=mt_rewind
|
||||
MT_OFFLINE=mt_offline
|
||||
MT_STATUS=mt_status
|
||||
|
||||
# Insure `mail' is in PATH.
|
||||
# Insure 'mail' is in PATH.
|
||||
PATH="/usr/ucb:${PATH}"
|
||||
export PATH
|
||||
# Put startdate in the subject line of mailed report, since if it happens
|
||||
@@ -211,8 +212,8 @@ init_backup() {
|
||||
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
|
||||
fi
|
||||
# Set logfile name
|
||||
# Logfile name should be in the form ``log-1993-03-18-level-0''
|
||||
# They go in the directory `@sysconfdir@/log'.
|
||||
# Logfile name should be in the form 'log-1993-03-18-level-0'
|
||||
# They go in the directory '@sysconfdir@/log'.
|
||||
# i.e. year-month-date. This format is useful for sorting by name, since
|
||||
# logfiles are intentionally kept online for future reference.
|
||||
LOGFILE="${LOGPATH}/log-`now`-level-${DUMP_LEVEL}"
|
||||
@@ -305,7 +306,7 @@ backup_host() {
|
||||
if [ "z${localhost}" != "z$rhost" ] ; then
|
||||
$RSH "$rhost" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" $@
|
||||
else
|
||||
# Using `sh -c exec' causes nested quoting and shell substitution
|
||||
# Using 'sh -c exec' causes nested quoting and shell substitution
|
||||
# to be handled here in the same way rsh handles it.
|
||||
CMD="exec ${TAR_PART1} -f \"${TAPE_FILE}\" $@"
|
||||
message 10 "CMD: $CMD"
|
||||
@@ -339,9 +340,9 @@ remote_run() {
|
||||
|
||||
license() {
|
||||
cat - <<EOF
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
Copyright (C) 2013 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -2,14 +2,30 @@
|
||||
# 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.
|
||||
# Copyright 2004-2005, 2010, 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Include location of 'sendmail' and GNU finger.
|
||||
PATH="/usr/lib:/usr/local/gnubin:${PATH}"
|
||||
export PATH
|
||||
|
||||
@@ -25,9 +41,9 @@ MT_OFFLINE
|
||||
# which users are logged into consoles (and thus in the office and capable
|
||||
# of changing tapes).
|
||||
#
|
||||
# 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.
|
||||
# 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.
|
||||
recipients="`
|
||||
finger .clients 2> /dev/null \
|
||||
| sed -ne '
|
||||
@@ -69,8 +85,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 +108,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__
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# Restore backups.
|
||||
|
||||
# Copyright 2004, 2006, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 1, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Load library routines
|
||||
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
@@ -60,8 +61,9 @@ do
|
||||
--l=*|--le=*|--lev=*|--leve=*|--level=*)
|
||||
DUMP_LEVEL=$optarg
|
||||
;;
|
||||
-l?*) DUMP_LEVEL=`expr $option : '-l\(.*\)'`;;
|
||||
-l|--l|--le|--lev|--leve|--level)
|
||||
prev=$option
|
||||
prev=--level
|
||||
;;
|
||||
--verb=*|--verbo=*|--verbos=*|--verbose=*)
|
||||
VERBOSE=$optarg
|
||||
@@ -69,7 +71,7 @@ do
|
||||
-v|--verb|--verbo|--verbos|--verbose)
|
||||
VERBOSE=100
|
||||
;;
|
||||
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
|
||||
-v*) VERBOSE=`expr $option : '-v\(.*\)'`;;
|
||||
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "restore (@PACKAGE_NAME@) @VERSION@"
|
||||
license
|
||||
|
||||
@@ -1,31 +1,66 @@
|
||||
#! /usr/bin/perl -w
|
||||
# Display and edit the 'dev' field in tar's snapshots
|
||||
# Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# Copyright 2007, 2011, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# Author: Dustin J. Mitchell <dustin@zmanda.com>
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# tar-snapshot-edit
|
||||
#
|
||||
# This script is capable of replacing values in the 'dev' field of an
|
||||
# incremental backup 'snapshot' file. This is useful when the device
|
||||
# used to store files in a tar archive changes, without the files
|
||||
# themselves changing. This may happen when, for example, a device
|
||||
# driver changes major or minor numbers.
|
||||
#
|
||||
# It can also run a check on all the field values found in the
|
||||
# snapshot file, printing out a detailed message when it finds values
|
||||
# that would cause an "Unexpected field value in snapshot file",
|
||||
# "Numerical result out of range", or "Invalid argument" error
|
||||
# if tar were run using that snapshot file as input. (See the
|
||||
# comments included in the definition of the check_field_values
|
||||
# routine for more detailed information regarding these checks.)
|
||||
#
|
||||
#
|
||||
#
|
||||
# Author: Dustin J. Mitchell <dustin@zmanda.com>
|
||||
#
|
||||
# Modified Aug 25, 2011 by Nathan Stratton Treadway <nathanst AT ontko.com>:
|
||||
# * update Perl syntax to work correctly with more recent versions of
|
||||
# Perl. (The original code worked with in the v5.8 timeframe but
|
||||
# not with Perl v5.10.1 and later.)
|
||||
# * added a "-c" option to check the snapshot file for invalid field values.
|
||||
# * handle NFS indicator character ("+") in version 0 and 1 files
|
||||
# * preserve the original header/version line when editing version 1
|
||||
# or 2 files.
|
||||
# * tweak output formatting
|
||||
#
|
||||
# Modified March 13, 2013 by Nathan Stratton Treadway <nathanst AT ontko.com>:
|
||||
# * configure field ranges used for -c option based on the system
|
||||
# architecture (in response to the December 2012 update to GNU tar
|
||||
# enabling support for systems with signed dev_t values).
|
||||
# * when printing the list of device ids found in the snapshot file
|
||||
# (when run in the default mode), print the raw device id values
|
||||
# instead of the hex-string version in those cases where they
|
||||
# can't be converted successfully.
|
||||
|
||||
use Getopt::Std;
|
||||
use Config;
|
||||
|
||||
my %snapshot_field_ranges; # used in check_field_values function
|
||||
|
||||
## reading
|
||||
|
||||
@@ -41,14 +76,15 @@ sub read_incr_db ($) {
|
||||
$file_version = 0;
|
||||
}
|
||||
|
||||
print "file version $file_version\n";
|
||||
print "\nFile: $filename\n";
|
||||
print " Detected snapshot file version: $file_version\n\n";
|
||||
|
||||
if ($file_version == 0) {
|
||||
return read_incr_db_0($file, $header_str);
|
||||
} elsif ($file_version == 1) {
|
||||
return read_incr_db_1($file);
|
||||
return read_incr_db_1($file, $header_str);
|
||||
} elsif ($file_version == 2) {
|
||||
return read_incr_db_2($file);
|
||||
return read_incr_db_2($file, $header_str);
|
||||
} else {
|
||||
die "Unrecognized snapshot version in header '$header_str'";
|
||||
}
|
||||
@@ -62,48 +98,66 @@ sub read_incr_db_0 ($$) {
|
||||
chop $hdr_timestamp_sec;
|
||||
my $hdr_timestamp_nsec = ''; # not present in file format 0
|
||||
|
||||
my $nfs;
|
||||
my @dirs;
|
||||
|
||||
while (<$file>) {
|
||||
/^([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
|
||||
/^(\+?)([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
|
||||
|
||||
push @dirs, { dev=>$1,
|
||||
ino=>$2,
|
||||
name=>$3 };
|
||||
if ( $1 eq "+" ) {
|
||||
$nfs="1";
|
||||
} else {
|
||||
$nfs="0";
|
||||
}
|
||||
push @dirs, { nfs=>$nfs,
|
||||
dev=>$2,
|
||||
ino=>$3,
|
||||
name=>$4 };
|
||||
}
|
||||
|
||||
close($file);
|
||||
|
||||
# file version, timestamp, timestamp, dir list
|
||||
return [ 0, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
|
||||
# file version, timestamp, timestamp, dir list, file header line
|
||||
return [ 0, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs, ""];
|
||||
}
|
||||
|
||||
sub read_incr_db_1 ($) {
|
||||
sub read_incr_db_1 ($$) {
|
||||
my $file = shift;
|
||||
my $header_str = shift;
|
||||
|
||||
|
||||
my $timestamp = <$file>; # "sec nsec"
|
||||
my ($hdr_timestamp_sec, $hdr_timestamp_nsec) = ($timestamp =~ /([0-9]*) ([0-9]*)/);
|
||||
|
||||
my $nfs;
|
||||
my @dirs;
|
||||
|
||||
while (<$file>) {
|
||||
/^([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
|
||||
/^(\+?)([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
|
||||
|
||||
push @dirs, { timestamp_sec=>$1,
|
||||
timestamp_nsec=>$2,
|
||||
dev=>$3,
|
||||
ino=>$4,
|
||||
name=>$5 };
|
||||
if ( $1 eq "+" ) {
|
||||
$nfs="1";
|
||||
} else {
|
||||
$nfs="0";
|
||||
}
|
||||
|
||||
push @dirs, { nfs=>$nfs,
|
||||
timestamp_sec=>$2,
|
||||
timestamp_nsec=>$3,
|
||||
dev=>$4,
|
||||
ino=>$5,
|
||||
name=>$6 };
|
||||
}
|
||||
|
||||
close($file);
|
||||
|
||||
# file version, timestamp, timestamp, dir list
|
||||
return [ 1, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
|
||||
# file version, timestamp, timestamp, dir list, file header line
|
||||
return [ 1, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs, $header_str ];
|
||||
}
|
||||
|
||||
sub read_incr_db_2 ($) {
|
||||
sub read_incr_db_2 ($$) {
|
||||
my $file = shift;
|
||||
my $header_str = shift;
|
||||
|
||||
$/="\0"; # $INPUT_RECORD_SEPARATOR
|
||||
my $hdr_timestamp_sec = <$file>;
|
||||
@@ -150,40 +204,257 @@ sub read_incr_db_2 ($) {
|
||||
close($file);
|
||||
$/ = "\n"; # reset to normal
|
||||
|
||||
# file version, timestamp, timestamp, dir list
|
||||
return [ 2, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
|
||||
# file version, timestamp, timestamp, dir list, file header line
|
||||
return [ 2, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs, $header_str];
|
||||
}
|
||||
|
||||
## display
|
||||
|
||||
sub show_device_counts ($$) {
|
||||
sub show_device_counts ($) {
|
||||
my $info = shift;
|
||||
my $filename = shift;
|
||||
my %devices;
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
my $dev = ${%$dir}{'dev'};
|
||||
foreach my $dir (@{$info->[3]}) {
|
||||
my $dev = $dir->{'dev'};
|
||||
$devices{$dev}++;
|
||||
}
|
||||
|
||||
foreach $dev (sort keys %devices) {
|
||||
printf "$filename: Device 0x%04x occurs $devices{$dev} times.\n", $dev;
|
||||
my $devstr;
|
||||
foreach $dev (sort {$a <=> $b} keys %devices) {
|
||||
$devstr = sprintf ("0x%04x", $dev);
|
||||
if ( $dev > 0xffffffff or $dev < 0 or hex($devstr) != $dev ) {
|
||||
# sprintf "%x" will not return a useful value for device ids
|
||||
# that are negative or which overflow the integer size on this
|
||||
# instance of Perl, so we convert the hex string back to a
|
||||
# number, and if it doesn't (numerically) equal the original
|
||||
# device id value, we know the hex conversion hasn't worked.
|
||||
#
|
||||
# Unfortunately, since we're running in "-w" mode, Perl will
|
||||
# also print a warning message if the hex() routine is called
|
||||
# on anything larger than "0xffffffff", even in 64-bit Perl
|
||||
# where such values are actually supported... so we have to
|
||||
# avoid calling hex() at all if the device id is too large or
|
||||
# negative. (If it's negative, the conversion to an unsigned
|
||||
# integer for the "%x" specifier will mean the result will
|
||||
# always trigger hex()'s warning on a 64-bit machine.)
|
||||
#
|
||||
# These situations don't seem to occur very often, so for now
|
||||
# when they do occur, we simply print the original text value
|
||||
# that was read from the snapshot file; it will look a bit
|
||||
# funny next to the values that do print in hex, but that's
|
||||
# preferable to printing values that aren't actually correct.
|
||||
$devstr = $dev;
|
||||
}
|
||||
printf " Device %s occurs $devices{$dev} times.\n", $devstr;
|
||||
}
|
||||
}
|
||||
|
||||
## check field values
|
||||
|
||||
# initializes the global %snapshot_field_ranges hash, based on the "-a"
|
||||
# command-line option if given, otherwise based on the "archname" of
|
||||
# the current system.
|
||||
#
|
||||
# Each value in the hash is a two-element array containing the minimum
|
||||
# and maximum allowed values, respectively, for that field in the snapshot
|
||||
# file. GNU tar's allowed values for each architecture are determined
|
||||
# in the incremen.c source file, where the TYPE_MIN and TYPE_MAX
|
||||
# pre-processor expressions are used to determine the range that can be
|
||||
# expressed by the C data type used for each field; the values in the
|
||||
# array defined below should match those calculations. (For tar v1.27
|
||||
# and later, the valid ranges for a particular tar binary can easily
|
||||
# be determined using the "tar --show-snapshot-field-ranges" command.)
|
||||
|
||||
sub choose_architecture ($) {
|
||||
my $opt_a = shift;
|
||||
|
||||
my $arch = $opt_a ? $opt_a : $Config{'archname'};
|
||||
|
||||
# These ranges apply to Linux 2.4/2.6 on iX86 systems, but are used
|
||||
# by default on unrecognized/unsupported systems, too.
|
||||
%iX86_linux_field_ranges = (
|
||||
timestamp_sec => [ -2147483648, 2147483647 ], # min/max of time_t
|
||||
timestamp_nsec => [ 0, 999999999 ], # 0 to BILLION-1
|
||||
nfs => [ 0, 1 ],
|
||||
dev => [ 0, 18446744073709551615 ], # min/max of dev_t
|
||||
ino => [ 0, 4294967295 ], # min/max of ino_t
|
||||
);
|
||||
|
||||
|
||||
if ( $arch =~ m/^i[\dxX]86-linux/i ) {
|
||||
%snapshot_field_ranges = %iX86_linux_field_ranges;
|
||||
print "Checking snapshot field values using \"iX86-linux\" ranges.\n\n";
|
||||
} elsif ( $arch =~ m/^x86_64-linux/i ) {
|
||||
%snapshot_field_ranges = (
|
||||
timestamp_sec => [ -9223372036854775808, 9223372036854775807 ],
|
||||
timestamp_nsec => [ 0, 999999999 ],
|
||||
nfs => [ 0, 1 ],
|
||||
dev => [ 0, 18446744073709551615 ],
|
||||
ino => [ 0, 18446744073709551615 ],
|
||||
);
|
||||
print "Checking snapshot field values using \"x86_64-linux\" ranges.\n\n";
|
||||
} elsif ( $arch =~ m/^IA64.ARCHREV_0/i ) {
|
||||
# HP/UX running on Itanium/ia64 architecture
|
||||
%snapshot_field_ranges = (
|
||||
timestamp_sec => [ -2147483648, 2147483647 ],
|
||||
timestamp_nsec => [ 0, 999999999 ],
|
||||
nfs => [ 0, 1 ],
|
||||
dev => [ -2147483648, 2147483647 ],
|
||||
ino => [ 0, 4294967295 ],
|
||||
);
|
||||
print "Checking snapshot field values using \"IA64.ARCHREV_0\" (HP/UX) ranges.\n\n";
|
||||
} else {
|
||||
%snapshot_field_ranges = %iX86_linux_field_ranges;
|
||||
print "Unrecognized architecture \"$arch\"; defaulting to \"iX86-linux\".\n";
|
||||
print "(Use -a option to override.)\n" unless $opt_a;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
if ( ref(1) ne "" ) {
|
||||
print "(\"bignum\" mode is in effect; skipping 64-bit-integer check.)\n\n"
|
||||
} else {
|
||||
# find the largest max value in the current set of ranges
|
||||
my $maxmax = 0;
|
||||
for $v (values %snapshot_field_ranges ) {
|
||||
$maxmax = $v->[1] if ($v->[1] > $maxmax);
|
||||
}
|
||||
|
||||
# "~0" translates into a platform-native integer with all bits turned
|
||||
# on -- that is, the largest value that can be represented as
|
||||
# an integer. We print a warning if our $maxmax value is greater
|
||||
# than that largest integer, since in that case Perl will switch
|
||||
# to using floats for those large max values. The wording of
|
||||
# the message assumes that the only way this situation can exist
|
||||
# is that the platform uses 32-bit integers but some of the
|
||||
# snapshot-file fields have 64-bit values.
|
||||
if ( ~0 < $maxmax ) {
|
||||
print <<EOF
|
||||
Note: this version of Perl uses 32-bit integers, which means that it
|
||||
will switch to using floating-point numbers when checking the ranges
|
||||
for 64-bit snapshot-file fields. This normally will work fine, but
|
||||
might fail to detect cases where the value in the input field value is
|
||||
only slightly out of range. (For example, a "9223372036854775808"
|
||||
might not be recognized as being larger than 9223372036854775807.)
|
||||
If you suspect you are experiencing this problem, you can try running
|
||||
the program using the "-Mbignum" option, as in
|
||||
\$ perl $0 -Mbignum -c [FILES]
|
||||
(but doing so will make the program run *much* slower).
|
||||
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
# returns a warning message if $field_value isn't a valid string
|
||||
# representation of an integer, or if the resulting integer is out of range
|
||||
# defined by the two-element array retrieved using up the $field_name key in
|
||||
# the global %snapshot_field_ranges hash.
|
||||
sub validate_integer_field ($$) {
|
||||
my $field_value = shift;
|
||||
my $field_name = shift;
|
||||
|
||||
my ($min, $max) = @{$snapshot_field_ranges{$field_name}};
|
||||
|
||||
my $msg = "";
|
||||
|
||||
if ( not $field_value =~ /^-?\d+$/ ) {
|
||||
$msg = " $field_name value contains invalid characters: \"$field_value\"\n";
|
||||
} else {
|
||||
if ( $field_value < $min ) {
|
||||
$msg = " $field_name value too low: \"$field_value\" < $min \n";
|
||||
} elsif ( $field_value > $max ) {
|
||||
$msg = " $field_name value too high: \"$field_value\" > $max \n";
|
||||
}
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
|
||||
# This routine loops through each directory entry in the $info data
|
||||
# structure and prints a warning message if tar would abort with an
|
||||
# "Unexpected field value in snapshot file", "Numerical result out of
|
||||
# range", or "Invalid argument" error upon reading this snapshot file.
|
||||
#
|
||||
# (Note that the "Unexpected field value in snapshot file" error message
|
||||
# was introduced along with the change to snapshot file format "2",
|
||||
# starting with tar v1.16 [or, more precisely, v1.15.91], while the
|
||||
# other two were introduced in v1.27.)
|
||||
#
|
||||
# The checks here are intended to match those found in the incremen.c
|
||||
# source file. See the choose_architecture() function (above) for more
|
||||
# information on how to configure the range of values considered valid
|
||||
# by this script.
|
||||
#
|
||||
# (Note: the checks here are taken from the code that processes
|
||||
# version 2 snapshot files, but to keep things simple we apply those
|
||||
# same checks to files having earlier versions -- but only for
|
||||
# the fields that actually exist in those input files.)
|
||||
|
||||
sub check_field_values ($) {
|
||||
my $info = shift;
|
||||
|
||||
my $msg;
|
||||
my $error_found = 0;
|
||||
|
||||
print " Checking field values in snapshot file...\n";
|
||||
|
||||
$snapver = $info->[0];
|
||||
|
||||
$msg = "";
|
||||
$msg .= validate_integer_field($info->[1], 'timestamp_sec');
|
||||
if ($snapver >= 1) {
|
||||
$msg .= validate_integer_field($info->[2], 'timestamp_nsec');
|
||||
}
|
||||
if ( $msg ne "" ) {
|
||||
$error_found = 1;
|
||||
print "\n shapshot file header:\n";
|
||||
print $msg;
|
||||
}
|
||||
|
||||
|
||||
foreach my $dir (@{$info->[3]}) {
|
||||
|
||||
$msg = "";
|
||||
|
||||
$msg .= validate_integer_field($dir->{'nfs'}, 'nfs');
|
||||
if ($snapver >= 1) {
|
||||
$msg .= validate_integer_field($dir->{'timestamp_sec'}, 'timestamp_sec');
|
||||
$msg .= validate_integer_field($dir->{'timestamp_nsec'}, 'timestamp_nsec');
|
||||
}
|
||||
$msg .= validate_integer_field($dir->{'dev'}, 'dev');
|
||||
$msg .= validate_integer_field($dir->{'ino'}, 'ino');
|
||||
|
||||
if ( $msg ne "" ) {
|
||||
$error_found = 1;
|
||||
print "\n directory: $dir->{'name'}\n";
|
||||
print $msg;
|
||||
}
|
||||
}
|
||||
|
||||
print "\n Snapshot field value check complete" ,
|
||||
$error_found ? "" : ", no errors found" ,
|
||||
".\n";
|
||||
}
|
||||
|
||||
## editing
|
||||
|
||||
sub replace_device_number ($@) {
|
||||
my $info = shift(@_);
|
||||
my @repl = @_;
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
foreach $x (@repl) {
|
||||
if (${%$dir}{'dev'} eq $$x[0]) {
|
||||
${%$dir}{'dev'} = $$x[1];
|
||||
last;
|
||||
}
|
||||
my $count = 0;
|
||||
|
||||
foreach my $dir (@{$info->[3]}) {
|
||||
foreach $x (@repl) {
|
||||
if ($dir->{'dev'} eq $$x[0]) {
|
||||
$dir->{'dev'} = $$x[1];
|
||||
$count++;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
print " Updated $count records.\n"
|
||||
}
|
||||
|
||||
## writing
|
||||
@@ -211,14 +482,17 @@ 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";
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
print $file "${%$dir}{'dev'} ";
|
||||
print $file "${%$dir}{'ino'} ";
|
||||
print $file "${%$dir}{'name'}\n";
|
||||
foreach my $dir (@{$info->[3]}) {
|
||||
if ($dir->{'nfs'}) {
|
||||
print $file '+'
|
||||
}
|
||||
print $file "$dir->{'dev'} ";
|
||||
print $file "$dir->{'ino'} ";
|
||||
print $file "$dir->{'name'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,19 +500,22 @@ sub write_incr_db_0 ($$) {
|
||||
sub write_incr_db_1 ($$) {
|
||||
my $info = shift;
|
||||
my $file = shift;
|
||||
|
||||
print $file "GNU tar-1.15-1\n";
|
||||
|
||||
print $file $info->[4];
|
||||
|
||||
my $timestamp_sec = $info->[1];
|
||||
my $timestamp_nsec = $info->[2];
|
||||
print $file "$timestamp_sec $timestamp_nsec\n";
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
print $file "${%$dir}{'timestamp_sec'} ";
|
||||
print $file "${%$dir}{'timestamp_nsec'} ";
|
||||
print $file "${%$dir}{'dev'} ";
|
||||
print $file "${%$dir}{'ino'} ";
|
||||
print $file "${%$dir}{'name'}\n";
|
||||
foreach my $dir (@{$info->[3]}) {
|
||||
if ($dir->{'nfs'}) {
|
||||
print $file '+'
|
||||
}
|
||||
print $file "$dir->{'timestamp_sec'} ";
|
||||
print $file "$dir->{'timestamp_nsec'} ";
|
||||
print $file "$dir->{'dev'} ";
|
||||
print $file "$dir->{'ino'} ";
|
||||
print $file "$dir->{'name'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,22 +523,22 @@ sub write_incr_db_1 ($$) {
|
||||
sub write_incr_db_2 ($$) {
|
||||
my $info = shift;
|
||||
my $file = shift;
|
||||
|
||||
print $file "GNU tar-1.16-2\n";
|
||||
|
||||
print $file $info->[4];
|
||||
|
||||
my $timestamp_sec = $info->[1];
|
||||
my $timestamp_nsec = $info->[2];
|
||||
print $file $timestamp_sec . "\0";
|
||||
print $file $timestamp_nsec . "\0";
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
print $file ${%$dir}{'nfs'} . "\0";
|
||||
print $file ${%$dir}{'timestamp_sec'} . "\0";
|
||||
print $file ${%$dir}{'timestamp_nsec'} . "\0";
|
||||
print $file ${%$dir}{'dev'} . "\0";
|
||||
print $file ${%$dir}{'ino'} . "\0";
|
||||
print $file ${%$dir}{'name'} . "\0";
|
||||
foreach my $dirent (@{${%$dir}{'dirents'}}) {
|
||||
foreach my $dir (@{$info->[3]}) {
|
||||
print $file $dir->{'nfs'} . "\0";
|
||||
print $file $dir->{'timestamp_sec'} . "\0";
|
||||
print $file $dir->{'timestamp_nsec'} . "\0";
|
||||
print $file $dir->{'dev'} . "\0";
|
||||
print $file $dir->{'ino'} . "\0";
|
||||
print $file $dir->{'name'} . "\0";
|
||||
foreach my $dirent (@{$dir->{'dirents'}}) {
|
||||
print $file $dirent . "\0";
|
||||
}
|
||||
print $file "\0";
|
||||
@@ -271,9 +548,10 @@ sub write_incr_db_2 ($$) {
|
||||
## main
|
||||
|
||||
sub main {
|
||||
our ($opt_b, $opt_r, $opt_h);
|
||||
getopts('br:h');
|
||||
HELP_MESSAGE() if ($opt_h || $#ARGV == -1 || ($opt_b && !$opt_r));
|
||||
our ($opt_b, $opt_r, $opt_h, $opt_c, $opt_a);
|
||||
getopts('br:hca:');
|
||||
HELP_MESSAGE() if ($opt_h || $#ARGV == -1 || ($opt_b && !$opt_r) ||
|
||||
($opt_a && !$opt_c) || ($opt_r && $opt_c) );
|
||||
|
||||
my @repl;
|
||||
if ($opt_r) {
|
||||
@@ -283,31 +561,61 @@ sub main {
|
||||
}
|
||||
}
|
||||
|
||||
choose_architecture($opt_a) if ($opt_c);
|
||||
|
||||
foreach my $snapfile (@ARGV) {
|
||||
my $info = read_incr_db($snapfile);
|
||||
if ($opt_r ) {
|
||||
if ($opt_r) {
|
||||
if ($opt_b) {
|
||||
rename($snapfile, $snapfile . "~") || die "Could not rename '$snapfile' to backup";
|
||||
}
|
||||
|
||||
replace_device_number($info, @repl);
|
||||
write_incr_db($info, $snapfile);
|
||||
} elsif ($opt_c) {
|
||||
check_field_values($info);
|
||||
} else {
|
||||
show_device_counts($info, $snapfile);
|
||||
show_device_counts($info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub HELP_MESSAGE {
|
||||
print "Usage: tar-snapshot-edit.pl [-r 'DEV1-DEV2[,DEV3-DEV4...]' [-b]] SNAPFILE [SNAPFILE [..]]\n";
|
||||
print "\n";
|
||||
print " Without -r, summarize the 'device' values in each SNAPFILE.\n";
|
||||
print "\n";
|
||||
print " With -r, replace occurrences of DEV1 with DEV2 in each SNAPFILE.\n";
|
||||
print " DEV1 and DEV2 may be specified in hex (e.g., 0xfe01), decimal (e.g.,\n";
|
||||
print " 65025), or MAJ:MIN (e.g., 254:1). To replace multiple occurrences,\n";
|
||||
print " separate them with commas. If -b is also specified, backup\n";
|
||||
print " files (ending with '~') will be created.\n";
|
||||
print <<EOF;
|
||||
|
||||
Usage:
|
||||
tar-snapshot-edit SNAPFILE [SNAPFILE [...]]
|
||||
tar-snapshot-edit -r 'DEV1-DEV2[,DEV3-DEV4...]' [-b] SNAPFILE [SNAPFILE [...]]
|
||||
tar-snapshot-edit -c [-aARCH] SNAPFILE [SNAPFILE [...]]
|
||||
|
||||
With no options specified: print a summary of the 'device' values
|
||||
found in each SNAPFILE.
|
||||
|
||||
With -r: replace occurrences of DEV1 with DEV2 in each SNAPFILE.
|
||||
DEV1 and DEV2 may be specified in hex (e.g., 0xfe01), decimal (e.g.,
|
||||
65025), or MAJ:MIN (e.g., 254:1). To replace multiple occurrences,
|
||||
separate them with commas. If -b is also specified, backup files
|
||||
(ending with '~') will be created.
|
||||
|
||||
With -c: Check the field values in each SNAPFILE and print warning
|
||||
messages if any invalid values are found. (An invalid value is one
|
||||
that would cause \"tar\" to abort with an error message such as
|
||||
Unexpected field value in snapshot file
|
||||
Numerical result out of range
|
||||
or
|
||||
Invalid argument
|
||||
as it processed the snapshot file.)
|
||||
|
||||
Normally the program automatically chooses the valid ranges for
|
||||
the fields based on the current system's architecture, but the
|
||||
-a option can be used to override the selection, e.g. in order
|
||||
to validate a snapshot file generated on a some other system.
|
||||
(Currently only three architectures are supported, "iX86-linux",
|
||||
"x86_64-linux", and "IA64.ARCHREV_0" [HP/UX running on Itanium/ia64],
|
||||
and if the current system isn't recognized, then the iX86-linux
|
||||
values are used by default.)
|
||||
|
||||
EOF
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,23 @@
|
||||
# concatenates a GNU tar multi-volume archive into a single tar archive.
|
||||
# Author: Bruno Haible <bruno@clisp.org>, Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
# Copyright 2004-2005, 2010, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar.
|
||||
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# dump_type FILE [N]
|
||||
# Print type character from block N (default 0) of tar archive FILE
|
||||
dump_type() {
|
||||
@@ -35,8 +52,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,27 +1,30 @@
|
||||
/* xsparse - expands compressed sparse file images extracted from GNU tar
|
||||
archives.
|
||||
|
||||
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2006-2007, 2010, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
Written by Sergey Poznyakoff
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
This file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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. */
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Written by Sergey Poznyakoff */
|
||||
|
||||
#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 +41,7 @@
|
||||
struct sp_array
|
||||
{
|
||||
off_t offset;
|
||||
size_t numbytes;
|
||||
off_t numbytes;
|
||||
};
|
||||
|
||||
char *progname;
|
||||
@@ -128,12 +131,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);
|
||||
@@ -162,7 +165,7 @@ get_var (FILE *fp, char **name, char **value)
|
||||
p += 11;
|
||||
q = strchr (p, '=');
|
||||
if (!q)
|
||||
die (1, "malformed header: expected `=' not found");
|
||||
die (1, "malformed header: expected '=' not found");
|
||||
*q++ = 0;
|
||||
q[strlen (q) - 1] = 0;
|
||||
*name = p;
|
||||
@@ -185,14 +188,14 @@ 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'",
|
||||
die (1, "bad keyword sequence: expected '%s' but found '%s'",
|
||||
expect, kw);
|
||||
expect = NULL;
|
||||
if (strcmp (kw, "name") == 0)
|
||||
@@ -225,7 +228,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)
|
||||
{
|
||||
@@ -233,13 +236,13 @@ read_xheader (char *name)
|
||||
{
|
||||
sparse_map[i].offset = string_to_off (val, &val);
|
||||
if (*val != ',')
|
||||
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
|
||||
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))
|
||||
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
|
||||
die (1, "bad GNU.sparse.map: expected ',' but found '%c'",
|
||||
*val);
|
||||
}
|
||||
else
|
||||
@@ -250,7 +253,7 @@ read_xheader (char *name)
|
||||
}
|
||||
}
|
||||
if (expect)
|
||||
die (1, "bad keyword sequence: expected `%s' not found", expect);
|
||||
die (1, "bad keyword sequence: expected '%s' not found", expect);
|
||||
if (version_major == 0 && sparse_map_size == 0)
|
||||
die (1, "size of the sparse map unknown");
|
||||
if (i != sparse_map_size)
|
||||
@@ -266,7 +269,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 +279,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 +347,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 +363,7 @@ guess_outname (char *name)
|
||||
for (p--; p > name && *p != '/'; p--)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
if (*p != '/')
|
||||
{
|
||||
if (s)
|
||||
@@ -388,7 +394,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 +413,7 @@ main (int argc, char **argv)
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
exit (1);
|
||||
}
|
||||
@@ -428,30 +434,30 @@ 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);
|
||||
|
||||
if (verbose)
|
||||
printf ("Expanding file `%s' to `%s'\n", inname, outname);
|
||||
printf ("Expanding file '%s' to '%s'\n", inname, outname);
|
||||
|
||||
if (dry_run)
|
||||
{
|
||||
printf ("Finished dry run\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
expand_sparse (ifp, ofd);
|
||||
|
||||
fclose (ifp);
|
||||
@@ -459,7 +465,7 @@ main (int argc, char **argv)
|
||||
|
||||
if (verbose)
|
||||
printf ("Done\n");
|
||||
|
||||
|
||||
if (outsize)
|
||||
{
|
||||
if (stat (outname, &st))
|
||||
@@ -467,7 +473,6 @@ main (int argc, char **argv)
|
||||
if (st.st_size != outsize)
|
||||
die (1, "expanded file has wrong size");
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
# Makefile for GNU tar sources.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
|
||||
# 2007, 2009 Free Software Foundation, Inc.
|
||||
# Copyright 1994-1997, 1999-2001, 2003, 2006-2007, 2009, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
## 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.
|
||||
# GNU tar is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
## 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.
|
||||
# GNU tar is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
bin_PROGRAMS = tar
|
||||
|
||||
noinst_HEADERS = arith.h common.h tar.h
|
||||
noinst_HEADERS = arith.h common.h tar.h xattrs.h
|
||||
tar_SOURCES = \
|
||||
buffer.c\
|
||||
checkpoint.c\
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
exit.c\
|
||||
exclist.c\
|
||||
extract.c\
|
||||
xheader.c\
|
||||
incremen.c\
|
||||
@@ -38,11 +40,19 @@ tar_SOURCES = \
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
unlink.c\
|
||||
update.c\
|
||||
utf8.c
|
||||
utf8.c\
|
||||
warning.c\
|
||||
xattrs.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
|
||||
AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
|
||||
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
|
||||
|
||||
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
|
||||
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)
|
||||
|
||||
if TAR_LIB_ATTR
|
||||
tar_LDADD += -lattr
|
||||
endif
|
||||
|
||||
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 */
|
||||
17
src/arith.h
17
src/arith.h
@@ -1,19 +1,20 @@
|
||||
/* Long integers, for GNU tar.
|
||||
Copyright 1999, 2007 Free Software Foundation, Inc.
|
||||
Copyright 1999, 2007, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Handle large integers for calculating big tape lengths and the
|
||||
like. In practice, double precision does for now. On the vast
|
||||
@@ -22,6 +23,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;
|
||||
|
||||
798
src/buffer.c
798
src/buffer.c
File diff suppressed because it is too large
Load Diff
344
src/checkpoint.c
344
src/checkpoint.c
@@ -1,22 +1,28 @@
|
||||
/* Checkpoint management for tar.
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
Copyright 2007, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
#include "wordsplit.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include "fprintftime.h"
|
||||
|
||||
enum checkpoint_opcode
|
||||
{
|
||||
@@ -25,7 +31,8 @@ enum checkpoint_opcode
|
||||
cop_echo,
|
||||
cop_ttyout,
|
||||
cop_sleep,
|
||||
cop_exec
|
||||
cop_exec,
|
||||
cop_totals
|
||||
};
|
||||
|
||||
struct checkpoint_action
|
||||
@@ -77,7 +84,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)
|
||||
@@ -108,87 +115,232 @@ checkpoint_compile_action (const char *str)
|
||||
act = alloc_action (cop_sleep);
|
||||
act->v.time = n;
|
||||
}
|
||||
else if (strcmp (str, "totals") == 0)
|
||||
alloc_action (cop_totals);
|
||||
else
|
||||
FATAL_ERROR ((0, 0, _("%s: unknown checkpoint action"), str));
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_finish_compile ()
|
||||
checkpoint_finish_compile (void)
|
||||
{
|
||||
if (checkpoint_option)
|
||||
{
|
||||
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 *
|
||||
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
|
||||
{
|
||||
const char *opstr = do_write ? gettext ("write") : gettext ("read");
|
||||
size_t opstrlen = strlen (opstr);
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
|
||||
size_t cpslen = strlen (cps);
|
||||
const char *ip;
|
||||
char *op;
|
||||
char *output;
|
||||
size_t outlen = strlen (input); /* Initial guess */
|
||||
static const char *checkpoint_total_format[] = {
|
||||
"R",
|
||||
"W",
|
||||
"D"
|
||||
};
|
||||
|
||||
/* Fix the initial length guess */
|
||||
for (ip = input; (ip = strchr (ip, '%')) != NULL; )
|
||||
static long
|
||||
getwidth (FILE *fp)
|
||||
{
|
||||
char const *columns;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
struct winsize ws;
|
||||
if (ioctl (fileno (fp), TIOCGWINSZ, &ws) == 0 && 0 < ws.ws_col)
|
||||
return ws.ws_col;
|
||||
#endif
|
||||
|
||||
columns = getenv ("COLUMNS");
|
||||
if (columns)
|
||||
{
|
||||
switch (ip[1])
|
||||
{
|
||||
case 'u':
|
||||
outlen += cpslen - 2;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
outlen += opstrlen - 2;
|
||||
}
|
||||
ip++;
|
||||
long int col = strtol (columns, NULL, 10);
|
||||
if (0 < col)
|
||||
return col;
|
||||
}
|
||||
|
||||
output = xmalloc (outlen + 1);
|
||||
for (ip = input, op = output; *ip; )
|
||||
return 80;
|
||||
}
|
||||
|
||||
static char *
|
||||
getarg (const char *input, const char ** endp, char **argbuf, size_t *arglen)
|
||||
{
|
||||
if (input[0] == '{')
|
||||
{
|
||||
char *p = strchr (input + 1, '}');
|
||||
if (p)
|
||||
{
|
||||
size_t n = p - input;
|
||||
if (n > *arglen)
|
||||
{
|
||||
*arglen = n;
|
||||
*argbuf = xrealloc (*argbuf, *arglen);
|
||||
}
|
||||
n--;
|
||||
memcpy (*argbuf, input + 1, n);
|
||||
(*argbuf)[n] = 0;
|
||||
*endp = p + 1;
|
||||
return *argbuf;
|
||||
}
|
||||
}
|
||||
|
||||
*endp = input;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int tty_cleanup;
|
||||
|
||||
static const char *def_format =
|
||||
"%{%Y-%m-%d %H:%M:%S}t: %ds, %{read,wrote}T%*\r";
|
||||
|
||||
static int
|
||||
format_checkpoint_string (FILE *fp, size_t len,
|
||||
const char *input, bool do_write,
|
||||
unsigned cpn)
|
||||
{
|
||||
const char *opstr = do_write ? gettext ("write") : gettext ("read");
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
|
||||
const char *ip;
|
||||
|
||||
static char *argbuf = NULL;
|
||||
static size_t arglen = 0;
|
||||
char *arg = NULL;
|
||||
|
||||
if (!input)
|
||||
{
|
||||
if (do_write)
|
||||
/* TRANSLATORS: This is a "checkpoint of write operation",
|
||||
*not* "Writing a checkpoint".
|
||||
E.g. in Spanish "Punto de comprobaci@'on de escritura",
|
||||
*not* "Escribiendo un punto de comprobaci@'on" */
|
||||
input = gettext ("Write checkpoint %u");
|
||||
else
|
||||
/* TRANSLATORS: This is a "checkpoint of read operation",
|
||||
*not* "Reading a checkpoint".
|
||||
E.g. in Spanish "Punto de comprobaci@'on de lectura",
|
||||
*not* "Leyendo un punto de comprobaci@'on" */
|
||||
input = gettext ("Read checkpoint %u");
|
||||
}
|
||||
|
||||
for (ip = input; *ip; ip++)
|
||||
{
|
||||
if (*ip == '%')
|
||||
{
|
||||
switch (*++ip)
|
||||
if (*++ip == '{')
|
||||
{
|
||||
arg = getarg (ip, &ip, &argbuf, &arglen);
|
||||
if (!arg)
|
||||
{
|
||||
fputc ('%', fp);
|
||||
fputc (*ip, fp);
|
||||
len += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
switch (*ip)
|
||||
{
|
||||
case 'c':
|
||||
len += format_checkpoint_string (fp, len, def_format, do_write,
|
||||
cpn);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
op = stpcpy (op, cps);
|
||||
fputs (cps, fp);
|
||||
len += strlen (cps);
|
||||
break;
|
||||
|
||||
|
||||
case 's':
|
||||
op = stpcpy (op, opstr);
|
||||
fputs (opstr, fp);
|
||||
len += strlen (opstr);
|
||||
break;
|
||||
|
||||
|
||||
case 'd':
|
||||
len += fprintf (fp, "%.0f", compute_duration ());
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
{
|
||||
const char **fmt = checkpoint_total_format, *fmtbuf[3];
|
||||
struct wordsplit ws;
|
||||
compute_duration ();
|
||||
|
||||
if (arg)
|
||||
{
|
||||
ws.ws_delim = ",";
|
||||
if (wordsplit (arg, &ws, WRDSF_NOVAR | WRDSF_NOCMD |
|
||||
WRDSF_QUOTE | WRDSF_DELIM))
|
||||
ERROR ((0, 0, _("cannot split string '%s': %s"),
|
||||
arg, wordsplit_strerror (&ws)));
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ws.ws_wordc; i++)
|
||||
fmtbuf[i] = ws.ws_wordv[i];
|
||||
for (; i < 3; i++)
|
||||
fmtbuf[i] = NULL;
|
||||
fmt = fmtbuf;
|
||||
}
|
||||
}
|
||||
len += format_total_stats (fp, fmt, ',', 0);
|
||||
if (arg)
|
||||
wordsplit_free (&ws);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
const char *fmt = arg ? arg : "%c";
|
||||
|
||||
gettimeofday (&tv, NULL);
|
||||
tm = localtime (&tv.tv_sec);
|
||||
len += fprintftime (fp, fmt, tm, 0, tv.tv_usec * 1000);
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
{
|
||||
long w = arg ? strtol (arg, NULL, 10) : getwidth (fp);
|
||||
for (; w > len; len++)
|
||||
fputc (' ', fp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*op++ = '%';
|
||||
*op++ = *ip;
|
||||
fputc ('%', fp);
|
||||
fputc (*ip, fp);
|
||||
len += 2;
|
||||
break;
|
||||
}
|
||||
ip++;
|
||||
arg = NULL;
|
||||
}
|
||||
else
|
||||
*op++ = *ip++;
|
||||
{
|
||||
fputc (*ip, fp);
|
||||
if (*ip == '\r')
|
||||
{
|
||||
len = 0;
|
||||
tty_cleanup = 1;
|
||||
}
|
||||
else
|
||||
len++;
|
||||
}
|
||||
}
|
||||
*op = 0;
|
||||
return output;
|
||||
fflush (fp);
|
||||
return len;
|
||||
}
|
||||
|
||||
static FILE *tty = NULL;
|
||||
|
||||
static void
|
||||
run_checkpoint_actions (bool do_write)
|
||||
{
|
||||
struct checkpoint_action *p;
|
||||
FILE *tty = NULL;
|
||||
|
||||
|
||||
for (p = checkpoint_action; p; p = p->next)
|
||||
{
|
||||
switch (p->opcode)
|
||||
@@ -207,58 +359,64 @@ run_checkpoint_actions (bool do_write)
|
||||
fflush (tty);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case cop_echo:
|
||||
{
|
||||
char *tmp;
|
||||
const char *str = p->v.command;
|
||||
if (!str)
|
||||
{
|
||||
if (do_write)
|
||||
/* TRANSLATORS: This is a ``checkpoint of write operation'',
|
||||
*not* ``Writing a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
|
||||
*not* ``Escribiendo un punto de comprobaci@'on'' */
|
||||
str = gettext ("Write checkpoint %u");
|
||||
else
|
||||
/* TRANSLATORS: This is a ``checkpoint of read operation'',
|
||||
*not* ``Reading a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
|
||||
*not* ``Leyendo un punto de comprobaci@'on'' */
|
||||
str = gettext ("Read checkpoint %u");
|
||||
}
|
||||
tmp = expand_checkpoint_string (str, do_write, checkpoint);
|
||||
WARN ((0, 0, "%s", tmp));
|
||||
free (tmp);
|
||||
int n = fprintf (stderr, "%s: ", program_name);
|
||||
format_checkpoint_string (stderr, n, p->v.command, do_write,
|
||||
checkpoint);
|
||||
fputc ('\n', stderr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case cop_ttyout:
|
||||
if (!tty)
|
||||
tty = fopen ("/dev/tty", "w");
|
||||
if (tty)
|
||||
{
|
||||
char *tmp = expand_checkpoint_string (p->v.command, do_write,
|
||||
checkpoint);
|
||||
fprintf (tty, "%s", tmp);
|
||||
fflush (tty);
|
||||
free (tmp);
|
||||
}
|
||||
format_checkpoint_string (tty, 0, p->v.command, do_write,
|
||||
checkpoint);
|
||||
break;
|
||||
|
||||
|
||||
case cop_sleep:
|
||||
sleep (p->v.time);
|
||||
break;
|
||||
|
||||
|
||||
case cop_exec:
|
||||
sys_exec_checkpoint_script (p->v.command,
|
||||
archive_name_cursor[0],
|
||||
checkpoint);
|
||||
break;
|
||||
|
||||
case cop_totals:
|
||||
compute_duration ();
|
||||
print_total_stats ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_flush_actions (void)
|
||||
{
|
||||
struct checkpoint_action *p;
|
||||
|
||||
for (p = checkpoint_action; p; p = p->next)
|
||||
{
|
||||
switch (p->opcode)
|
||||
{
|
||||
case cop_ttyout:
|
||||
if (tty && tty_cleanup)
|
||||
{
|
||||
long w = getwidth (tty);
|
||||
while (w--)
|
||||
fputc (' ', tty);
|
||||
fputc ('\r', tty);
|
||||
fflush (tty);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* nothing */;
|
||||
}
|
||||
}
|
||||
if (tty)
|
||||
fclose (tty);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -266,5 +424,15 @@ checkpoint_run (bool do_write)
|
||||
{
|
||||
if (checkpoint_option && !(++checkpoint % checkpoint_option))
|
||||
run_checkpoint_actions (do_write);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_finish (void)
|
||||
{
|
||||
if (checkpoint_option)
|
||||
{
|
||||
checkpoint_flush_actions ();
|
||||
if (tty)
|
||||
fclose (tty);
|
||||
}
|
||||
}
|
||||
|
||||
394
src/common.h
394
src/common.h
@@ -1,21 +1,22 @@
|
||||
/* 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.
|
||||
Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2012-2014 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 file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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. */
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Declare the GNU tar archive format. */
|
||||
#include "tar.h"
|
||||
@@ -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>
|
||||
|
||||
@@ -67,12 +70,14 @@
|
||||
#define LG_8 3
|
||||
#define LG_64 6
|
||||
#define LG_256 8
|
||||
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
#ifndef COMMON_INLINE
|
||||
# define COMMON_INLINE _GL_INLINE
|
||||
#endif
|
||||
|
||||
/* Information gleaned from the command line. */
|
||||
|
||||
/* Name of this program. */
|
||||
GLOBAL const char *program_name;
|
||||
|
||||
/* Main command option. */
|
||||
|
||||
enum subcommand
|
||||
@@ -85,7 +90,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 +110,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.
|
||||
@@ -135,9 +143,6 @@ GLOBAL const char *use_compress_program_option;
|
||||
GLOBAL bool dereference_option;
|
||||
GLOBAL bool hard_dereference_option;
|
||||
|
||||
/* Print a message if not all links are dumped */
|
||||
GLOBAL int check_links_option;
|
||||
|
||||
/* Patterns that match file names to be excluded. */
|
||||
GLOBAL struct exclude *excluded;
|
||||
|
||||
@@ -155,7 +160,8 @@ enum exclusion_tag_type
|
||||
};
|
||||
|
||||
/* Specified value to be put into tar file in place of stat () results, or
|
||||
just -1 if such an override should not take place. */
|
||||
just null and -1 if such an override should not take place. */
|
||||
GLOBAL char const *group_name_option;
|
||||
GLOBAL gid_t group_option;
|
||||
|
||||
GLOBAL bool ignore_failed_read_option;
|
||||
@@ -179,12 +185,17 @@ enum old_files
|
||||
OVERWRITE_OLD_FILES, /* --overwrite */
|
||||
UNLINK_FIRST_OLD_FILES, /* --unlink-first */
|
||||
KEEP_OLD_FILES, /* --keep-old-files */
|
||||
SKIP_OLD_FILES, /* --skip-old-files */
|
||||
KEEP_NEWER_FILES /* --keep-newer-files */
|
||||
};
|
||||
GLOBAL enum old_files old_files_option;
|
||||
|
||||
GLOBAL bool keep_directory_symlink_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;
|
||||
|
||||
@@ -224,8 +235,13 @@ GLOBAL bool numeric_owner_option;
|
||||
|
||||
GLOBAL bool one_file_system_option;
|
||||
|
||||
/* Create a top-level directory for extracting based on the archive name. */
|
||||
GLOBAL bool one_top_level_option;
|
||||
GLOBAL char *one_top_level_dir;
|
||||
|
||||
/* Specified value to be put into tar file in place of stat () results, or
|
||||
just -1 if such an override should not take place. */
|
||||
just null and -1 if such an override should not take place. */
|
||||
GLOBAL char const *owner_name_option;
|
||||
GLOBAL uid_t owner_option;
|
||||
|
||||
GLOBAL bool recursive_unlink_option;
|
||||
@@ -234,9 +250,6 @@ GLOBAL bool read_full_records_option;
|
||||
|
||||
GLOBAL bool remove_files_option;
|
||||
|
||||
/* Specified rmt command. */
|
||||
GLOBAL const char *rmt_command_option;
|
||||
|
||||
/* Specified remote shell command. */
|
||||
GLOBAL const char *rsh_command_option;
|
||||
|
||||
@@ -248,6 +261,15 @@ GLOBAL int same_owner_option;
|
||||
/* If positive, preserve permissions when extracting. */
|
||||
GLOBAL int same_permissions_option;
|
||||
|
||||
/* If positive, save the SELinux context. */
|
||||
GLOBAL int selinux_context_option;
|
||||
|
||||
/* If positive, save the ACLs. */
|
||||
GLOBAL int acls_option;
|
||||
|
||||
/* If positive, save the user and root xattrs. */
|
||||
GLOBAL int xattrs_option;
|
||||
|
||||
/* When set, strip the given number of file name components from the file name
|
||||
before extracting */
|
||||
GLOBAL size_t strip_name_components;
|
||||
@@ -308,35 +330,55 @@ GLOBAL struct timespec last_stat_time; /* when the statistics was last
|
||||
|
||||
GLOBAL struct tar_stat_info current_stat_info;
|
||||
|
||||
/* List of tape drive names, number of such tape drives, allocated number,
|
||||
/* List of tape drive names, number of such tape drives,
|
||||
and current cursor in list. */
|
||||
GLOBAL const char **archive_name_array;
|
||||
GLOBAL size_t archive_names;
|
||||
GLOBAL size_t allocated_archive_names;
|
||||
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,7 +386,7 @@ GLOBAL dev_t root_device;
|
||||
/* Unquote filenames */
|
||||
GLOBAL bool unquote_option;
|
||||
|
||||
GLOBAL bool test_label_option; /* Test archive volume label and exit */
|
||||
GLOBAL int savedir_sort_order;
|
||||
|
||||
/* Show file or archive names after transformation.
|
||||
In particular, when creating archive in verbose mode, list member names
|
||||
@@ -379,15 +421,19 @@ 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);
|
||||
void close_archive (void);
|
||||
void closeout_volume_number (void);
|
||||
void compute_duration (void);
|
||||
double compute_duration (void);
|
||||
union block *find_next_block (void);
|
||||
void flush_read (void);
|
||||
void flush_write (void);
|
||||
@@ -404,13 +450,23 @@ 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);
|
||||
#define TF_READ 0
|
||||
#define TF_WRITE 1
|
||||
#define TF_DELETED 2
|
||||
int format_total_stats (FILE *fp, const char **formats, int eor, int eol);
|
||||
void print_total_stats (void);
|
||||
|
||||
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 +478,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,27 +528,26 @@ 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 show_snapshot_field_ranges (void);
|
||||
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);
|
||||
void clear_directory_table (void);
|
||||
|
||||
/* Module list.c. */
|
||||
|
||||
@@ -520,6 +561,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,50 +579,88 @@ 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);
|
||||
|
||||
/* Module misc.c. */
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define max(a, b) ((a) < (b) ? (b) : (a))
|
||||
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 (int cdidx, const char *name);
|
||||
void normalize_filename_x (char *name);
|
||||
void replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen);
|
||||
char *tar_savedir (const char *name, int must_exist);
|
||||
|
||||
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 namebuf_add_dir (namebuf_t buf, const char *name);
|
||||
char *namebuf_finish (namebuf_t buf);
|
||||
|
||||
const char *tar_dirname (void);
|
||||
|
||||
/* Represent N using a signed integer I such that (uintmax_t) I == N.
|
||||
With a good optimizing compiler, this is equivalent to (intmax_t) i
|
||||
and requires zero machine instructions. */
|
||||
#if ! (UINTMAX_MAX / 2 <= INTMAX_MAX)
|
||||
# error "represent_uintmax returns intmax_t to represent uintmax_t"
|
||||
#endif
|
||||
COMMON_INLINE intmax_t
|
||||
represent_uintmax (uintmax_t n)
|
||||
{
|
||||
if (n <= INTMAX_MAX)
|
||||
return n;
|
||||
else
|
||||
{
|
||||
/* Avoid signed integer overflow on picky platforms. */
|
||||
intmax_t nd = n - INTMAX_MIN;
|
||||
return nd + INTMAX_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
enum { SYSINT_BUFSIZE =
|
||||
max (UINTMAX_STRSIZE_BOUND, INT_BUFSIZE_BOUND (intmax_t)) };
|
||||
char *sysinttostr (uintmax_t, intmax_t, uintmax_t, char buf[SYSINT_BUFSIZE]);
|
||||
intmax_t strtosysint (char const *, char **, intmax_t, uintmax_t);
|
||||
void code_ns_fraction (int ns, char *p);
|
||||
char const *code_timespec (struct timespec ts, char *sbuf);
|
||||
enum { BILLION = 1000000000, LOG10_BILLION = 9 };
|
||||
enum { TIMESPEC_STRSIZE_BOUND =
|
||||
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
|
||||
struct timespec decode_timespec (char const *, char **, bool);
|
||||
|
||||
/* Return true if T does not represent an out-of-range or invalid value. */
|
||||
COMMON_INLINE bool
|
||||
valid_timespec (struct timespec t)
|
||||
{
|
||||
return 0 <= t.tv_nsec;
|
||||
}
|
||||
|
||||
bool must_be_dot_or_slash (char const *);
|
||||
|
||||
enum remove_option
|
||||
{
|
||||
@@ -590,10 +680,16 @@ 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);
|
||||
|
||||
size_t blocking_read (int fd, void *buf, size_t count);
|
||||
size_t blocking_write (int fd, void const *buf, size_t count);
|
||||
|
||||
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 +698,8 @@ 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 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 +709,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);
|
||||
@@ -626,25 +725,26 @@ int uname_to_uid (char const *uname, uid_t *puid);
|
||||
void name_init (void);
|
||||
void name_add_name (const char *name, int matching_flags);
|
||||
void name_add_dir (const char *name);
|
||||
void name_add_file (const char *name, int term);
|
||||
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);
|
||||
bool all_names_found (struct tar_stat_info *st);
|
||||
|
||||
bool excluded_name (char const *name);
|
||||
|
||||
void add_avoided_name (char const *name);
|
||||
bool is_avoided_name (char const *name);
|
||||
bool is_individual_file (char const *name);
|
||||
|
||||
bool contains_dot_dot (char const *name);
|
||||
|
||||
@@ -658,14 +758,18 @@ 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);
|
||||
|
||||
void request_stdin (const char *option);
|
||||
void more_options (int argc, char **argv);
|
||||
|
||||
/* Module update.c. */
|
||||
|
||||
@@ -673,15 +777,17 @@ extern char *output_start;
|
||||
|
||||
void update_archive (void);
|
||||
|
||||
/* Module attrs.c. */
|
||||
#include "xattrs.h"
|
||||
|
||||
/* 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_read (struct xheader *xhdr, union block *header, off_t size);
|
||||
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);
|
||||
@@ -694,6 +800,12 @@ bool xheader_string_end (struct xheader *xhdr, char const *keyword);
|
||||
bool xheader_keyword_deleted_p (const char *kw);
|
||||
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
|
||||
size_t n);
|
||||
void xheader_xattr_init (struct tar_stat_info *st);
|
||||
void xheader_xattr_free (struct xattr_array *vals, size_t sz);
|
||||
void xheader_xattr_copy (const struct tar_stat_info *st,
|
||||
struct xattr_array **vals, size_t *sz);
|
||||
void xheader_xattr_add (struct tar_stat_info *st,
|
||||
const char *key, const char *val, size_t len);
|
||||
|
||||
/* Module system.c */
|
||||
|
||||
@@ -718,7 +830,8 @@ void sys_exec_checkpoint_script (const char *script_name,
|
||||
int checkpoint_number);
|
||||
|
||||
/* Module compare.c */
|
||||
void report_difference (struct tar_stat_info *st, const char *message, ...);
|
||||
void report_difference (struct tar_stat_info *st, const char *message, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
/* Module sparse.c */
|
||||
bool sparse_member_p (struct tar_stat_info *st);
|
||||
@@ -741,14 +854,81 @@ 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 *);
|
||||
bool transform_program_p (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);
|
||||
char *strip_compression_suffix (const char *name);
|
||||
|
||||
/* Module checkpoint.c */
|
||||
void checkpoint_compile_action (const char *str);
|
||||
void checkpoint_finish_compile (void);
|
||||
void checkpoint_run (bool do_write);
|
||||
void checkpoint_finish (void);
|
||||
void checkpoint_flush_actions (void);
|
||||
|
||||
/* 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
|
||||
#define WARN_EXISTING_FILE 0x00100000
|
||||
#define WARN_XATTR_WRITE 0x00200000
|
||||
#define WARN_RECORD_SIZE 0x00400000
|
||||
|
||||
/* These warnings are enabled by default in verbose mode: */
|
||||
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
|
||||
WARN_DECOMPRESS_PROGRAM|WARN_EXISTING_FILE|\
|
||||
WARN_RECORD_SIZE)
|
||||
#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);
|
||||
|
||||
/* Module exclist.c */
|
||||
#define EXCL_DEFAULT 0x00
|
||||
#define EXCL_RECURSIVE 0x01
|
||||
#define EXCL_NON_RECURSIVE 0x02
|
||||
|
||||
void excfile_add (const char *name, int flags);
|
||||
void info_attach_exclist (struct tar_stat_info *dir);
|
||||
void info_cleanup_exclist (struct tar_stat_info *dir);
|
||||
void info_free_exclist (struct tar_stat_info *dir);
|
||||
bool excluded_name (char const *name, struct tar_stat_info *st);
|
||||
void exclude_vcs_ignores (void);
|
||||
|
||||
_GL_INLINE_HEADER_END
|
||||
|
||||
152
src/compare.c
152
src/compare.c
@@ -1,23 +1,24 @@
|
||||
/* 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.
|
||||
Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2007,
|
||||
2009-2010, 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1987-04-30.
|
||||
This file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
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 John Gilmore, on 1987-04-30. */
|
||||
|
||||
#include <system.h>
|
||||
#include <system-ioctl.h>
|
||||
@@ -66,8 +67,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. */
|
||||
@@ -81,7 +81,7 @@ process_noop (size_t size __attribute__ ((unused)),
|
||||
static int
|
||||
process_rawdata (size_t bytes, char *buffer)
|
||||
{
|
||||
size_t status = safe_read (diff_handle, diff_buffer, bytes);
|
||||
size_t status = blocking_read (diff_handle, diff_buffer, bytes);
|
||||
|
||||
if (status != bytes)
|
||||
{
|
||||
@@ -123,7 +123,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 +152,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 +218,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)
|
||||
{
|
||||
@@ -240,12 +235,12 @@ diff_file (void)
|
||||
else
|
||||
read_and_process (¤t_stat_info, process_rawdata);
|
||||
|
||||
if (atime_preserve_option == replace_atime_preserve)
|
||||
if (atime_preserve_option == replace_atime_preserve
|
||||
&& stat_data.st_size != 0)
|
||||
{
|
||||
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 +273,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 +328,7 @@ static int
|
||||
dumpdir_cmp (const char *a, const char *b)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
|
||||
while (*a)
|
||||
switch (*a)
|
||||
{
|
||||
@@ -346,7 +342,7 @@ dumpdir_cmp (const char *a, const char *b)
|
||||
a += len;
|
||||
b += len;
|
||||
break;
|
||||
|
||||
|
||||
case 'D':
|
||||
if (strcmp(a, b))
|
||||
return 1;
|
||||
@@ -354,7 +350,7 @@ dumpdir_cmp (const char *a, const char *b)
|
||||
a += len;
|
||||
b += len;
|
||||
break;
|
||||
|
||||
|
||||
case 'R':
|
||||
case 'T':
|
||||
case 'X':
|
||||
@@ -364,31 +360,38 @@ dumpdir_cmp (const char *a, const char *b)
|
||||
}
|
||||
|
||||
static void
|
||||
diff_dumpdir (void)
|
||||
diff_dumpdir (struct tar_stat_info *dir)
|
||||
{
|
||||
const char *dumpdir_buffer;
|
||||
dev_t dev = 0;
|
||||
struct stat stat_data;
|
||||
|
||||
if (deref_stat (true, current_stat_info.file_name, &stat_data))
|
||||
if (dir->fd == 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
stat_warn (current_stat_info.file_name);
|
||||
void (*diag) (char const *) = NULL;
|
||||
int fd = subfile_open (dir->parent, dir->orig_file_name, open_read_flags);
|
||||
if (fd < 0)
|
||||
diag = open_diag;
|
||||
else if (fstat (fd, &dir->stat))
|
||||
{
|
||||
diag = stat_diag;
|
||||
close (fd);
|
||||
}
|
||||
else
|
||||
stat_error (current_stat_info.file_name);
|
||||
dir->fd = fd;
|
||||
if (diag)
|
||||
{
|
||||
file_removed_diag (dir->orig_file_name, false, diag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
dev = stat_data.st_dev;
|
||||
|
||||
dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev);
|
||||
dumpdir_buffer = directory_contents (scan_directory (dir));
|
||||
|
||||
if (dumpdir_buffer)
|
||||
{
|
||||
if (dumpdir_cmp (current_stat_info.dumpdir, dumpdir_buffer))
|
||||
report_difference (¤t_stat_info, _("Contents differ"));
|
||||
if (dumpdir_cmp (dir->dumpdir, dumpdir_buffer))
|
||||
report_difference (dir, _("Contents differ"));
|
||||
}
|
||||
else
|
||||
read_and_process (¤t_stat_info, process_noop);
|
||||
read_and_process (dir, process_noop);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -415,14 +418,17 @@ diff_multivol (void)
|
||||
}
|
||||
|
||||
offset = OFF_FROM_HEADER (current_header->oldgnu_header.offset);
|
||||
if (stat_data.st_size != current_stat_info.stat.st_size + offset)
|
||||
if (offset < 0
|
||||
|| INT_ADD_OVERFLOW (current_stat_info.stat.st_size, offset)
|
||||
|| stat_data.st_size != current_stat_info.stat.st_size + offset)
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Size differs"));
|
||||
skip_member ();
|
||||
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)
|
||||
{
|
||||
@@ -436,10 +442,9 @@ diff_multivol (void)
|
||||
{
|
||||
seek_error_details (current_stat_info.file_name, offset);
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
read_and_process (¤t_stat_info, process_rawdata);
|
||||
else
|
||||
read_and_process (¤t_stat_info, process_rawdata);
|
||||
|
||||
status = close (fd);
|
||||
if (status != 0)
|
||||
@@ -452,7 +457,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,13 +464,13 @@ 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)
|
||||
{
|
||||
default:
|
||||
ERROR ((0, 0, _("%s: Unknown file type `%c', diffed as normal file"),
|
||||
ERROR ((0, 0, _("%s: Unknown file type '%c', diffed as normal file"),
|
||||
quotearg_colon (current_stat_info.file_name),
|
||||
current_header->header.typeflag));
|
||||
/* Fall through. */
|
||||
@@ -503,7 +507,7 @@ diff_archive (void)
|
||||
case GNUTYPE_DUMPDIR:
|
||||
case DIRTYPE:
|
||||
if (is_dumpdir (¤t_stat_info))
|
||||
diff_dumpdir ();
|
||||
diff_dumpdir (¤t_stat_info);
|
||||
diff_dir ();
|
||||
break;
|
||||
|
||||
@@ -518,13 +522,24 @@ diff_archive (void)
|
||||
void
|
||||
verify_volume (void)
|
||||
{
|
||||
int may_fail = 0;
|
||||
if (removed_prefixes_p ())
|
||||
{
|
||||
WARN((0, 0,
|
||||
_("Archive contains file names with leading prefixes removed.")));
|
||||
WARN((0, 0,
|
||||
_("Verification may fail to locate original files.")));
|
||||
may_fail = 1;
|
||||
}
|
||||
if (transform_program_p ())
|
||||
{
|
||||
WARN((0, 0,
|
||||
_("Archive contains transformed file names.")));
|
||||
may_fail = 1;
|
||||
}
|
||||
if (may_fail)
|
||||
WARN((0, 0,
|
||||
_("Verification may fail to locate original files.")));
|
||||
|
||||
clear_directory_table ();
|
||||
|
||||
if (!diff_buffer)
|
||||
diff_init ();
|
||||
@@ -578,7 +593,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 +605,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 +624,18 @@ 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)));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
||||
diff_archive ();
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(tar.h)
|
||||
PROGS="tar"
|
||||
AC_SUBST(PROGS)dnl
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_GCC_TRADITIONAL
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_YACC
|
||||
AC_AIX
|
||||
AC_MINIX
|
||||
AC_ISC_POSIX
|
||||
AC_CONST
|
||||
AC_RETSIGTYPE
|
||||
AC_SIZE_T
|
||||
AC_MAJOR_HEADER
|
||||
AC_DIR_HEADER
|
||||
# The 3-argument open happens to go along with the O_* defines,
|
||||
# which are easier to check for.
|
||||
AC_HEADER_CHECK(fcntl.h, open_header=fcntl.h, open_header=sys/file.h)
|
||||
AC_COMPILE_CHECK(3-argument open,
|
||||
[#include <$open_header>], [int x = O_RDONLY;], , AC_DEFINE(EMUL_OPEN3))
|
||||
AC_REMOTE_TAPE
|
||||
AC_RSH
|
||||
AC_STDC_HEADERS
|
||||
AC_UNISTD_H
|
||||
echo checking for getgrgid declaration
|
||||
AC_HEADER_EGREP(getgrgid, grp.h, AC_DEFINE(HAVE_GETGRGID))
|
||||
echo checking for getpwuid declaration
|
||||
AC_HEADER_EGREP(getpwuid, pwd.h, AC_DEFINE(HAVE_GETPWUID))
|
||||
AC_HAVE_HEADERS(string.h limits.h)
|
||||
echo checking default archive
|
||||
# This might guess wrong, but it's not very important.
|
||||
for dev in rmt8 rmt0 rmt0h rct0 rst0 tape rct/c7d0s2
|
||||
do
|
||||
if test -n "`ls /dev/$dev 2>/dev/null`"; then
|
||||
DEF_AR_FILE=/dev/$dev
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$DEF_AR_FILE"; then
|
||||
DEF_AR_FILE=-
|
||||
fi
|
||||
|
||||
AC_SUBST(DEF_AR_FILE)dnl
|
||||
AC_HAVE_FUNCS(strstr valloc mkdir mknod rename ftruncate ftime getcwd)
|
||||
AC_VPRINTF
|
||||
AC_ALLOCA
|
||||
echo checking for BSD
|
||||
( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && AC_DEFINE(BSD42)
|
||||
echo checking for HP-UX
|
||||
test "`(uname -s) 2> /dev/null`" = 'HP-UX' && MALLOC=malloc.o
|
||||
AC_SUBST(MALLOC)
|
||||
AC_XENIX_DIR
|
||||
AC_HAVE_LIBRARY(socket, [LIBS="$LIBS -lsocket"])
|
||||
AC_HAVE_LIBRARY(nsl, [LIBS="$LIBS -lnsl"])
|
||||
AC_OUTPUT(Makefile)
|
||||
860
src/create.c
860
src/create.c
File diff suppressed because it is too large
Load Diff
37
src/delete.c
37
src/delete.c
@@ -1,21 +1,22 @@
|
||||
/* Delete entries from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
|
||||
2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright 1988, 1992, 1994, 1996-1997, 2000-2001, 2003-2006, 2010,
|
||||
2013-2014 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 file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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. */
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include <system-ioctl.h>
|
||||
@@ -35,7 +36,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 +166,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 +263,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 +297,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);
|
||||
}
|
||||
}
|
||||
361
src/exclist.c
Normal file
361
src/exclist.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/* Per-directory exclusion files for tar.
|
||||
|
||||
Copyright 2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <system.h>
|
||||
#include <quotearg.h>
|
||||
#include <fnmatch.h>
|
||||
#include <wordsplit.h>
|
||||
#include "common.h"
|
||||
|
||||
typedef void (*add_fn) (struct exclude *, char const *, int, void *);
|
||||
|
||||
struct vcs_ignore_file
|
||||
{
|
||||
char const *filename;
|
||||
int flags;
|
||||
add_fn addfn;
|
||||
void *(*initfn) (void *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static struct vcs_ignore_file *get_vcs_ignore_file (const char *name);
|
||||
|
||||
struct excfile
|
||||
{
|
||||
struct excfile *next;
|
||||
int flags;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
struct excfile *excfile_head, *excfile_tail;
|
||||
|
||||
void
|
||||
excfile_add (const char *name, int flags)
|
||||
{
|
||||
struct excfile *p = xmalloc (sizeof (*p) + strlen (name));
|
||||
p->next = NULL;
|
||||
p->flags = flags;
|
||||
strcpy (p->name, name);
|
||||
if (excfile_tail)
|
||||
excfile_tail->next = p;
|
||||
else
|
||||
excfile_head = p;
|
||||
excfile_tail = p;
|
||||
}
|
||||
|
||||
struct exclist
|
||||
{
|
||||
struct exclist *next, *prev;
|
||||
int flags;
|
||||
struct exclude *excluded;
|
||||
};
|
||||
|
||||
void
|
||||
info_attach_exclist (struct tar_stat_info *dir)
|
||||
{
|
||||
struct excfile *file;
|
||||
struct exclist *head = NULL, *tail = NULL, *ent;
|
||||
struct vcs_ignore_file *vcsfile;
|
||||
|
||||
if (dir->exclude_list)
|
||||
return;
|
||||
for (file = excfile_head; file; file = file->next)
|
||||
{
|
||||
if (faccessat (dir ? dir->fd : chdir_fd, file->name, F_OK, 0) == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
struct exclude *ex = NULL;
|
||||
int fd = subfile_open (dir, file->name, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
open_error (file->name);
|
||||
continue;
|
||||
}
|
||||
fp = fdopen (fd, "r");
|
||||
if (!fp)
|
||||
{
|
||||
ERROR ((0, errno, _("%s: fdopen failed"), file->name));
|
||||
close (fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ex)
|
||||
ex = new_exclude ();
|
||||
|
||||
vcsfile = get_vcs_ignore_file (file->name);
|
||||
|
||||
if (vcsfile->initfn)
|
||||
vcsfile->data = vcsfile->initfn (vcsfile->data);
|
||||
|
||||
if (add_exclude_fp (vcsfile->addfn, ex, fp,
|
||||
EXCLUDE_WILDCARDS|EXCLUDE_ANCHORED, '\n',
|
||||
vcsfile->data))
|
||||
{
|
||||
int e = errno;
|
||||
FATAL_ERROR ((0, e, "%s", quotearg_colon (file->name)));
|
||||
}
|
||||
fclose (fp);
|
||||
|
||||
ent = xmalloc (sizeof (*ent));
|
||||
ent->excluded = ex;
|
||||
ent->flags = file->flags == EXCL_DEFAULT
|
||||
? file->flags : vcsfile->flags;
|
||||
ent->prev = tail;
|
||||
ent->next = NULL;
|
||||
|
||||
if (tail)
|
||||
tail->next = ent;
|
||||
else
|
||||
head = ent;
|
||||
tail = ent;
|
||||
}
|
||||
}
|
||||
dir->exclude_list = head;
|
||||
}
|
||||
|
||||
void
|
||||
info_cleanup_exclist (struct tar_stat_info *dir)
|
||||
{
|
||||
struct exclist *ep = dir->exclude_list;
|
||||
|
||||
while (ep)
|
||||
{
|
||||
struct exclist *next = ep->next;
|
||||
|
||||
if (ep->flags & EXCL_NON_RECURSIVE)
|
||||
{
|
||||
|
||||
/* Remove the entry */
|
||||
if (ep->prev)
|
||||
ep->prev->next = ep->next;
|
||||
else
|
||||
dir->exclude_list = ep->next;
|
||||
|
||||
if (ep->next)
|
||||
ep->next->prev = ep->prev;
|
||||
|
||||
free_exclude (ep->excluded);
|
||||
free (ep);
|
||||
}
|
||||
ep = next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
info_free_exclist (struct tar_stat_info *dir)
|
||||
{
|
||||
struct exclist *ep = dir->exclude_list;
|
||||
|
||||
while (ep)
|
||||
{
|
||||
struct exclist *next = ep->next;
|
||||
free_exclude (ep->excluded);
|
||||
free (ep);
|
||||
ep = next;
|
||||
}
|
||||
|
||||
dir->exclude_list = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Return nonzero if file NAME is excluded. */
|
||||
bool
|
||||
excluded_name (char const *name, struct tar_stat_info *st)
|
||||
{
|
||||
struct exclist *ep;
|
||||
const char *rname = NULL;
|
||||
char *bname = NULL;
|
||||
bool result;
|
||||
int nr = 0;
|
||||
|
||||
name += FILE_SYSTEM_PREFIX_LEN (name);
|
||||
|
||||
/* Try global exclusion list first */
|
||||
if (excluded_file_name (excluded, name))
|
||||
return true;
|
||||
|
||||
if (!st)
|
||||
return false;
|
||||
|
||||
for (result = false; st && !result; st = st->parent, nr = EXCL_NON_RECURSIVE)
|
||||
{
|
||||
for (ep = st->exclude_list; ep; ep = ep->next)
|
||||
{
|
||||
if (ep->flags & nr)
|
||||
continue;
|
||||
if ((result = excluded_file_name (ep->excluded, name)))
|
||||
break;
|
||||
|
||||
if (!rname)
|
||||
{
|
||||
rname = name;
|
||||
/* Skip leading ./ */
|
||||
while (*rname == '.' && ISSLASH (rname[1]))
|
||||
rname += 2;
|
||||
}
|
||||
if ((result = excluded_file_name (ep->excluded, rname)))
|
||||
break;
|
||||
|
||||
if (!bname)
|
||||
bname = base_name (name);
|
||||
if ((result = excluded_file_name (ep->excluded, bname)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (bname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cvs_addfn (struct exclude *ex, char const *pattern, int options, void *data)
|
||||
{
|
||||
struct wordsplit ws;
|
||||
size_t i;
|
||||
|
||||
if (wordsplit (pattern, &ws,
|
||||
WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS))
|
||||
return;
|
||||
for (i = 0; i < ws.ws_wordc; i++)
|
||||
add_exclude (ex, ws.ws_wordv[i], options);
|
||||
wordsplit_free (&ws);
|
||||
}
|
||||
|
||||
static void
|
||||
git_addfn (struct exclude *ex, char const *pattern, int options, void *data)
|
||||
{
|
||||
while (isspace (*pattern))
|
||||
++pattern;
|
||||
if (*pattern == 0 || *pattern == '#')
|
||||
return;
|
||||
if (*pattern == '\\' && pattern[1] == '#')
|
||||
++pattern;
|
||||
add_exclude (ex, pattern, options);
|
||||
}
|
||||
|
||||
static void
|
||||
bzr_addfn (struct exclude *ex, char const *pattern, int options, void *data)
|
||||
{
|
||||
while (isspace (*pattern))
|
||||
++pattern;
|
||||
if (*pattern == 0 || *pattern == '#')
|
||||
return;
|
||||
if (*pattern == '!')
|
||||
{
|
||||
if (*++pattern == '!')
|
||||
++pattern;
|
||||
else
|
||||
options |= EXCLUDE_INCLUDE;
|
||||
}
|
||||
/* FIXME: According to the docs, globbing patterns are rsync-style,
|
||||
and regexps are perl-style. */
|
||||
if (strncmp (pattern, "RE:", 3) == 0)
|
||||
{
|
||||
pattern += 3;
|
||||
options &= ~EXCLUDE_WILDCARDS;
|
||||
options |= EXCLUDE_REGEX;
|
||||
}
|
||||
add_exclude (ex, pattern, options);
|
||||
}
|
||||
|
||||
static void *
|
||||
hg_initfn (void *data)
|
||||
{
|
||||
int *hgopt;
|
||||
static int hg_options;
|
||||
|
||||
if (!data)
|
||||
hgopt = &hg_options;
|
||||
|
||||
*hgopt = EXCLUDE_REGEX;
|
||||
return hgopt;
|
||||
}
|
||||
|
||||
static void
|
||||
hg_addfn (struct exclude *ex, char const *pattern, int options, void *data)
|
||||
{
|
||||
int *hgopt = data;
|
||||
size_t len;
|
||||
|
||||
while (isspace (*pattern))
|
||||
++pattern;
|
||||
if (*pattern == 0 || *pattern == '#')
|
||||
return;
|
||||
if (strncmp (pattern, "syntax:", 7) == 0)
|
||||
{
|
||||
for (pattern += 7; isspace (*pattern); ++pattern)
|
||||
;
|
||||
if (strcmp (pattern, "regexp") == 0)
|
||||
/* FIXME: Regexps must be perl-style */
|
||||
*hgopt = EXCLUDE_REGEX;
|
||||
else if (strcmp (pattern, "glob") == 0)
|
||||
*hgopt = EXCLUDE_WILDCARDS;
|
||||
/* Ignore unknown syntax */
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(pattern);
|
||||
if (pattern[len-1] == '/')
|
||||
{
|
||||
char *p;
|
||||
|
||||
--len;
|
||||
p = xmalloc (len+1);
|
||||
memcpy (p, pattern, len);
|
||||
p[len] = 0;
|
||||
pattern = p;
|
||||
exclude_add_pattern_buffer (ex, p);
|
||||
options |= FNM_LEADING_DIR|EXCLUDE_ALLOC;
|
||||
}
|
||||
|
||||
add_exclude (ex, pattern,
|
||||
((*hgopt == EXCLUDE_REGEX)
|
||||
? (options & ~EXCLUDE_WILDCARDS)
|
||||
: (options & ~EXCLUDE_REGEX)) | *hgopt);
|
||||
}
|
||||
|
||||
struct vcs_ignore_file vcs_ignore_files[] = {
|
||||
{ ".cvsignore", EXCL_NON_RECURSIVE, cvs_addfn, NULL, NULL },
|
||||
{ ".gitignore", 0, git_addfn, NULL, NULL },
|
||||
{ ".bzrignore", 0, bzr_addfn, NULL, NULL },
|
||||
{ ".hgignore", 0, hg_addfn, hg_initfn , NULL },
|
||||
{ NULL, 0, git_addfn, NULL, NULL }
|
||||
};
|
||||
|
||||
static struct vcs_ignore_file *
|
||||
get_vcs_ignore_file (const char *name)
|
||||
{
|
||||
struct vcs_ignore_file *p;
|
||||
|
||||
for (p = vcs_ignore_files; p->filename; p++)
|
||||
if (strcmp (p->filename, name) == 0)
|
||||
break;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
exclude_vcs_ignores (void)
|
||||
{
|
||||
struct vcs_ignore_file *p;
|
||||
|
||||
for (p = vcs_ignore_files; p->filename; p++)
|
||||
excfile_add (p->filename, EXCL_DEFAULT);
|
||||
}
|
||||
39
src/exit.c
Normal file
39
src/exit.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Exit from GNU tar.
|
||||
|
||||
Copyright 2009, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#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 ();
|
||||
}
|
||||
1263
src/extract.c
1263
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;
|
||||
}
|
||||
874
src/incremen.c
874
src/incremen.c
File diff suppressed because it is too large
Load Diff
578
src/list.c
578
src/list.c
@@ -1,23 +1,24 @@
|
||||
/* 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.
|
||||
Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-26.
|
||||
This file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
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 John Gilmore, on 1985-08-26. */
|
||||
|
||||
#include <system.h>
|
||||
#include <inttostr.h>
|
||||
@@ -25,17 +26,30 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define max(a, b) ((a) < (b) ? (b) : (a))
|
||||
|
||||
union block *current_header; /* points to current archive header */
|
||||
enum archive_format current_format; /* recognized format */
|
||||
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 */
|
||||
static union block *recent_global_header; /* Recent global header block */
|
||||
|
||||
static uintmax_t from_header (const char *, size_t, const char *,
|
||||
uintmax_t, uintmax_t, bool, bool);
|
||||
#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, bool *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 intmax_t from_header (const char *, size_t, const char *,
|
||||
intmax_t, uintmax_t, bool, bool);
|
||||
|
||||
/* Base 64 digits; see Internet RFC 2045 Table 1. */
|
||||
static char const base_64_digits[64] =
|
||||
@@ -60,6 +74,93 @@ 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);
|
||||
}
|
||||
|
||||
static void
|
||||
enforce_one_top_level (char **pfile_name)
|
||||
{
|
||||
char *file_name = *pfile_name;
|
||||
char *p;
|
||||
|
||||
for (p = file_name; *p && (ISSLASH (*p) || *p == '.'); p++)
|
||||
;
|
||||
|
||||
if (!*p)
|
||||
return;
|
||||
|
||||
if (strncmp (p, one_top_level_dir, strlen (one_top_level_dir)) == 0)
|
||||
{
|
||||
int pos = strlen (one_top_level_dir);
|
||||
if (ISSLASH (p[pos]) || p[pos] == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
*pfile_name = new_name (one_top_level_dir, file_name);
|
||||
normalize_filename_x (*pfile_name);
|
||||
free (file_name);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (one_top_level_option)
|
||||
enforce_one_top_level (¤t_stat_info.file_name);
|
||||
}
|
||||
|
||||
/* Main loop for reading an archive. */
|
||||
void
|
||||
read_and (void (*do_something) (void))
|
||||
@@ -77,7 +178,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 +190,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
|
||||
@@ -100,7 +203,8 @@ read_and (void (*do_something) (void))
|
||||
mtime.tv_nsec = 0,
|
||||
current_stat_info.mtime = mtime,
|
||||
OLDER_TAR_STAT_TIME (current_stat_info, m)))
|
||||
|| excluded_name (current_stat_info.file_name))
|
||||
|| excluded_name (current_stat_info.file_name,
|
||||
current_stat_info.parent))
|
||||
{
|
||||
switch (current_header->header.typeflag)
|
||||
{
|
||||
@@ -114,13 +218,13 @@ 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 +242,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 +310,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)
|
||||
{
|
||||
@@ -240,7 +345,7 @@ tar_checksum (union block *header, bool silent)
|
||||
int unsigned_sum = 0; /* the POSIX one :-) */
|
||||
int signed_sum = 0; /* the Sun one :-( */
|
||||
int recorded_sum;
|
||||
uintmax_t parsed_sum;
|
||||
int parsed_sum;
|
||||
char *p;
|
||||
|
||||
p = header->buffer;
|
||||
@@ -265,9 +370,8 @@ tar_checksum (union block *header, bool silent)
|
||||
|
||||
parsed_sum = from_header (header->header.chksum,
|
||||
sizeof header->header.chksum, 0,
|
||||
(uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (int), true, silent);
|
||||
if (parsed_sum == (uintmax_t) -1)
|
||||
0, INT_MAX, true, silent);
|
||||
if (parsed_sum < 0)
|
||||
return HEADER_FAILURE;
|
||||
|
||||
recorded_sum = parsed_sum;
|
||||
@@ -279,20 +383,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 +422,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;
|
||||
|
||||
@@ -321,7 +434,11 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
if (header->header.typeflag == LNKTYPE)
|
||||
info->stat.st_size = 0; /* links 0 size on tape */
|
||||
else
|
||||
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
|
||||
{
|
||||
info->stat.st_size = OFF_FROM_HEADER (header->header.size);
|
||||
if (info->stat.st_size < 0)
|
||||
return HEADER_FAILURE;
|
||||
}
|
||||
|
||||
if (header->header.typeflag == GNUTYPE_LONGNAME
|
||||
|| header->header.typeflag == GNUTYPE_LONGLINK
|
||||
@@ -329,7 +446,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)
|
||||
@@ -347,15 +464,13 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
|
||||
if (header->header.typeflag == GNUTYPE_LONGNAME)
|
||||
{
|
||||
if (next_long_name)
|
||||
free (next_long_name);
|
||||
free (next_long_name);
|
||||
next_long_name = header_copy;
|
||||
next_long_name_blocks = size / BLOCKSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (next_long_link)
|
||||
free (next_long_link);
|
||||
free (next_long_link);
|
||||
next_long_link = header_copy;
|
||||
next_long_link_blocks = size / BLOCKSIZE;
|
||||
}
|
||||
@@ -391,11 +506,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,11 +526,10 @@ 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)
|
||||
free (recent_long_name);
|
||||
free (recent_long_name);
|
||||
|
||||
if (next_long_name)
|
||||
{
|
||||
@@ -439,8 +560,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
assign_string (&info->file_name, name);
|
||||
info->had_trailing_slash = strip_trailing_slashes (info->file_name);
|
||||
|
||||
if (recent_long_link)
|
||||
free (recent_long_link);
|
||||
free (recent_long_link);
|
||||
|
||||
if (next_long_link)
|
||||
{
|
||||
@@ -463,53 +583,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 +603,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;
|
||||
bool hbits;
|
||||
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
|
||||
|
||||
if (strcmp (header->header.magic, TMAGIC) == 0)
|
||||
{
|
||||
@@ -544,13 +619,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,
|
||||
@@ -558,6 +635,8 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
assign_string (&stat_info->gname,
|
||||
header->header.gname[0] ? header->header.gname : NULL);
|
||||
|
||||
xheader_xattr_init (stat_info);
|
||||
|
||||
if (format == OLDGNU_FORMAT && incremental_option)
|
||||
{
|
||||
stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
|
||||
@@ -627,34 +706,34 @@ 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
|
||||
-MINUS_MINVAL through MAXVAL. If OCTAL_ONLY, allow only octal
|
||||
intmax_t. DIGS must be positive. If TYPE is nonnull, the data are
|
||||
of type TYPE. The buffer must represent a value in the range
|
||||
MINVAL through MAXVAL; if the mathematically correct result V would
|
||||
be greater than INTMAX_MAX, return a negative integer V such that
|
||||
(uintmax_t) V yields the correct result. If OCTAL_ONLY, allow only octal
|
||||
numbers instead of the other GNU extensions. Return -1 on error,
|
||||
diagnosing the error if TYPE is nonnull and if !SILENT. */
|
||||
static uintmax_t
|
||||
#if ! (INTMAX_MAX <= UINTMAX_MAX && - (INTMAX_MIN + 1) <= UINTMAX_MAX)
|
||||
# error "from_header internally represents intmax_t as uintmax_t + sign"
|
||||
#endif
|
||||
#if ! (UINTMAX_MAX / 2 <= INTMAX_MAX)
|
||||
# error "from_header returns intmax_t to represent uintmax_t"
|
||||
#endif
|
||||
static intmax_t
|
||||
from_header (char const *where0, size_t digs, char const *type,
|
||||
uintmax_t minus_minval, uintmax_t maxval,
|
||||
intmax_t minval, uintmax_t maxval,
|
||||
bool octal_only, bool silent)
|
||||
{
|
||||
uintmax_t value;
|
||||
uintmax_t uminval = minval;
|
||||
uintmax_t minus_minval = - uminval;
|
||||
char const *where = where0;
|
||||
char const *lim = where + digs;
|
||||
int negative = 0;
|
||||
bool negative = false;
|
||||
|
||||
/* Accommodate buggy tar of unknown vintage, which outputs leading
|
||||
NUL if the previous field overflows. */
|
||||
@@ -667,12 +746,13 @@ 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;
|
||||
}
|
||||
if (!ISSPACE ((unsigned char) *where))
|
||||
if (!isspace ((unsigned char) *where))
|
||||
break;
|
||||
where++;
|
||||
}
|
||||
@@ -681,14 +761,14 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
if (ISODIGIT (*where))
|
||||
{
|
||||
char const *where1 = where;
|
||||
uintmax_t overflow = 0;
|
||||
bool overflow = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
value += *where++ - '0';
|
||||
if (where == lim || ! ISODIGIT (*where))
|
||||
break;
|
||||
overflow |= value ^ (value << LG_8 >> LG_8);
|
||||
overflow |= value != (value << LG_8 >> LG_8);
|
||||
value <<= LG_8;
|
||||
}
|
||||
|
||||
@@ -712,7 +792,7 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
if (where == lim || ! ISODIGIT (*where))
|
||||
break;
|
||||
digit = *where - '0';
|
||||
overflow |= value ^ (value << LG_8 >> LG_8);
|
||||
overflow |= value != (value << LG_8 >> LG_8);
|
||||
value <<= LG_8;
|
||||
}
|
||||
value++;
|
||||
@@ -725,7 +805,7 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
/* TRANSLATORS: Second %s is a type name (gid_t,uid_t,etc.) */
|
||||
_("Archive octal value %.*s is out of %s range; assuming two's complement"),
|
||||
(int) (where - where1), where1, type));
|
||||
negative = 1;
|
||||
negative = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,12 +885,12 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
negative = signbit;
|
||||
negative = signbit != 0;
|
||||
if (negative)
|
||||
value = -value;
|
||||
}
|
||||
|
||||
if (where != lim && *where && !ISSPACE ((unsigned char) *where))
|
||||
if (where != lim && *where && !isspace ((unsigned char) *where))
|
||||
{
|
||||
if (type)
|
||||
{
|
||||
@@ -825,7 +905,7 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
|
||||
while (where0 != lim && ! lim[-1])
|
||||
lim--;
|
||||
quotearg_buffer (buf, sizeof buf, where0, lim - where, o);
|
||||
quotearg_buffer (buf, sizeof buf, where0, lim - where0, o);
|
||||
if (!silent)
|
||||
ERROR ((0, 0,
|
||||
/* TRANSLATORS: Second %s is a type name (gid_t,uid_t,etc.) */
|
||||
@@ -837,7 +917,7 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
}
|
||||
|
||||
if (value <= (negative ? minus_minval : maxval))
|
||||
return negative ? -value : value;
|
||||
return represent_uintmax (negative ? -value : value);
|
||||
|
||||
if (type && !silent)
|
||||
{
|
||||
@@ -859,50 +939,52 @@ 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",
|
||||
- (uintmax_t) TYPE_MINIMUM (gid_t),
|
||||
(uintmax_t) TYPE_MAXIMUM (gid_t),
|
||||
TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t),
|
||||
false, false);
|
||||
}
|
||||
|
||||
major_t
|
||||
static major_t
|
||||
major_from_header (const char *p, size_t s)
|
||||
{
|
||||
return from_header (p, s, "major_t",
|
||||
- (uintmax_t) TYPE_MINIMUM (major_t),
|
||||
(uintmax_t) TYPE_MAXIMUM (major_t), false, false);
|
||||
TYPE_MINIMUM (major_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",
|
||||
- (uintmax_t) TYPE_MINIMUM (minor_t),
|
||||
(uintmax_t) TYPE_MAXIMUM (minor_t), false, false);
|
||||
TYPE_MINIMUM (minor_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.
|
||||
Set *HBITS if there are any unrecognized bits. */
|
||||
static mode_t
|
||||
mode_from_header (const char *p, size_t s, bool *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));
|
||||
intmax_t u = from_header (p, s, "mode_t",
|
||||
INTMAX_MIN, UINTMAX_MAX,
|
||||
false, false);
|
||||
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 = (u & ~07777) != 0;
|
||||
return mode;
|
||||
}
|
||||
|
||||
off_t
|
||||
@@ -910,38 +992,31 @@ off_from_header (const char *p, size_t s)
|
||||
{
|
||||
/* Negative offsets are not allowed in tar files, so invoke
|
||||
from_header with minimum value 0, not TYPE_MINIMUM (off_t). */
|
||||
return from_header (p, s, "off_t", (uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (off_t), false, false);
|
||||
return from_header (p, s, "off_t",
|
||||
0, 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",
|
||||
- (uintmax_t) TYPE_MINIMUM (time_t),
|
||||
(uintmax_t) TYPE_MAXIMUM (time_t), false, false);
|
||||
TYPE_MINIMUM (time_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",
|
||||
- (uintmax_t) TYPE_MINIMUM (uid_t),
|
||||
(uintmax_t) TYPE_MAXIMUM (uid_t), false, false);
|
||||
TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t),
|
||||
false, false);
|
||||
}
|
||||
|
||||
uintmax_t
|
||||
uintmax_from_header (const char *p, size_t s)
|
||||
{
|
||||
return from_header (p, s, "uintmax_t", (uintmax_t) 0,
|
||||
TYPE_MAXIMUM (uintmax_t), false, false);
|
||||
return from_header (p, s, "uintmax_t", 0, UINTMAX_MAX, false, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1013,9 +1088,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,16 +1100,20 @@ 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 modes[12];
|
||||
char const *time_stamp;
|
||||
int time_stamp_len;
|
||||
char *temp_name;
|
||||
|
||||
/* These hold formatted ints. */
|
||||
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
|
||||
char uform[max (INT_BUFSIZE_BOUND (intmax_t), UINTMAX_STRSIZE_BOUND)];
|
||||
char gform[sizeof uform];
|
||||
char *user, *group;
|
||||
char size[2 * UINTMAX_STRSIZE_BOUND];
|
||||
/* holds formatted size or major,minor */
|
||||
@@ -1045,9 +1121,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
|
||||
@@ -1067,16 +1140,20 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
if (verbose_option <= 1)
|
||||
{
|
||||
/* Just the fax, mam. */
|
||||
fprintf (stdlis, "%s\n", quotearg (temp_name));
|
||||
fputs (quotearg (temp_name), stdlis);
|
||||
if (show_transformed_names_option && st->had_trailing_slash)
|
||||
fputc ('/', stdlis);
|
||||
fputc ('\n', stdlis);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
|
||||
@@ -1093,9 +1170,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
case GNUTYPE_SPARSE:
|
||||
case REGTYPE:
|
||||
case AREGTYPE:
|
||||
modes[0] = '-';
|
||||
if (temp_name[strlen (temp_name) - 1] == '/')
|
||||
modes[0] = 'd';
|
||||
modes[0] = st->had_trailing_slash ? 'd' : '-';
|
||||
break;
|
||||
case LNKTYPE:
|
||||
modes[0] = 'h';
|
||||
@@ -1125,9 +1200,12 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
|
||||
pax_decode_mode (st->stat.st_mode, modes + 1);
|
||||
|
||||
/* extended attributes: GNU `ls -l'-like preview */
|
||||
xattrs_print_char (st, modes + 10);
|
||||
|
||||
/* 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,19 +1222,13 @@ 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) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
|
||||
uintmax_t u = from_header (blk->header.uid,
|
||||
sizeof blk->header.uid, 0,
|
||||
0, UINTMAX_MAX,
|
||||
false, false);
|
||||
if (u != -1)
|
||||
user = STRINGIFY_BIGINT (u, uform);
|
||||
else
|
||||
{
|
||||
sprintf (uform, "%ld",
|
||||
(long) UID_FROM_HEADER (current_header->header.uid));
|
||||
user = uform;
|
||||
}
|
||||
user = (u != -1
|
||||
? STRINGIFY_BIGINT (u, uform)
|
||||
: imaxtostr (UID_FROM_HEADER (blk->header.uid), uform));
|
||||
}
|
||||
|
||||
if (st->gname
|
||||
@@ -1169,24 +1241,18 @@ 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) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
|
||||
uintmax_t g = from_header (blk->header.gid,
|
||||
sizeof blk->header.gid, 0,
|
||||
0, UINTMAX_MAX,
|
||||
false, false);
|
||||
if (g != -1)
|
||||
group = STRINGIFY_BIGINT (g, gform);
|
||||
else
|
||||
{
|
||||
sprintf (gform, "%ld",
|
||||
(long) GID_FROM_HEADER (current_header->header.gid));
|
||||
group = gform;
|
||||
}
|
||||
group = (g != -1
|
||||
? STRINGIFY_BIGINT (g, gform)
|
||||
: imaxtostr (GID_FROM_HEADER (blk->header.gid), gform));
|
||||
}
|
||||
|
||||
/* Format the file size or major/minor device numbers. */
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case CHRTYPE:
|
||||
case BLKTYPE:
|
||||
@@ -1215,8 +1281,10 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
datewidth, time_stamp);
|
||||
|
||||
fprintf (stdlis, " %s", quotearg (temp_name));
|
||||
if (show_transformed_names_option && st->had_trailing_slash)
|
||||
fputc ('/', stdlis);
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case SYMTYPE:
|
||||
fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
|
||||
@@ -1229,7 +1297,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,13 +1331,48 @@ 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;
|
||||
}
|
||||
}
|
||||
fflush (stdlis);
|
||||
xattrs_print (st);
|
||||
}
|
||||
|
||||
|
||||
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. */
|
||||
@@ -1292,8 +1395,8 @@ print_for_mkdir (char *dirname, int length, mode_t mode)
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf));
|
||||
}
|
||||
|
||||
fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + 1 + datewidth,
|
||||
_("Creating directory:"), length, quotearg (dirname));
|
||||
fprintf (stdlis, "%s %*s %s\n", modes, ugswidth + 1 + datewidth,
|
||||
_("Creating directory:"), quotearg (dirname));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1303,7 +1406,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 +1441,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 +1451,34 @@ skip_member (void)
|
||||
mv_end ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_archive_label (void)
|
||||
{
|
||||
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
|
||||
718
src/misc.c
718
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.
|
||||
Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010,
|
||||
2012-2014 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
|
||||
@@ -14,25 +14,23 @@
|
||||
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. */
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define COMMON_INLINE _GL_EXTERN_INLINE
|
||||
#include <system.h>
|
||||
#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
|
||||
|
||||
static const char *tar_getcdpath (int);
|
||||
|
||||
|
||||
/* Handling strings. */
|
||||
|
||||
@@ -41,11 +39,13 @@
|
||||
void
|
||||
assign_string (char **string, const char *value)
|
||||
{
|
||||
if (*string)
|
||||
free (*string);
|
||||
free (*string);
|
||||
*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 +58,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 +99,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
|
||||
@@ -106,7 +107,7 @@ quote_copy_string (const char *string)
|
||||
completes the unquoting anyway.
|
||||
|
||||
This is used for reading the saved directory file in incremental
|
||||
dumps. It is used for decoding old `N' records (demangling names).
|
||||
dumps. It is used for decoding old 'N' records (demangling names).
|
||||
But also, it is used for decoding file arguments, would they come
|
||||
from the shell or a -T file, and for decoding the --exclude
|
||||
argument. */
|
||||
@@ -214,9 +215,194 @@ 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. */
|
||||
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 (int cdidx, const char *name)
|
||||
{
|
||||
char *copy = NULL;
|
||||
|
||||
if (IS_RELATIVE_FILE_NAME (name))
|
||||
{
|
||||
/* Set COPY to the absolute path for this name.
|
||||
|
||||
FIXME: There should be no need to get the absolute file name.
|
||||
tar_getcdpath does not return a true "canonical" path, so
|
||||
this following approach may lead to situations where the same
|
||||
file or directory is processed twice under different absolute
|
||||
paths without that duplication being detected. Perhaps we
|
||||
should use dev+ino pairs instead of names? (See listed03.at for
|
||||
a related test case.) */
|
||||
const char *cdpath = tar_getcdpath (cdidx);
|
||||
size_t copylen;
|
||||
bool need_separator;
|
||||
|
||||
if (!cdpath)
|
||||
call_arg_fatal ("getcwd", ".");
|
||||
copylen = strlen (cdpath);
|
||||
need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
&& copylen == 2 && ISSLASH (cdpath[1]));
|
||||
copy = xmalloc (copylen + need_separator + strlen (name) + 1);
|
||||
strcpy (copy, cdpath);
|
||||
copy[copylen] = DIRECTORY_SEPARATOR;
|
||||
strcpy (copy + copylen + need_separator, name);
|
||||
}
|
||||
|
||||
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. */
|
||||
|
||||
/* Convert VALUE, which is converted from a system integer type whose
|
||||
minimum value is MINVAL and maximum MINVAL, to an decimal
|
||||
integer string. Use the storage in BUF and return a pointer to the
|
||||
converted string. If VALUE is converted from a negative integer in
|
||||
the range MINVAL .. -1, represent it with a string representation
|
||||
of the negative integer, using leading '-'. */
|
||||
#if ! (INTMAX_MAX <= UINTMAX_MAX / 2)
|
||||
# error "sysinttostr: uintmax_t cannot represent all intmax_t values"
|
||||
#endif
|
||||
char *
|
||||
sysinttostr (uintmax_t value, intmax_t minval, uintmax_t maxval,
|
||||
char buf[SYSINT_BUFSIZE])
|
||||
{
|
||||
if (value <= maxval)
|
||||
return umaxtostr (value, buf);
|
||||
else
|
||||
{
|
||||
intmax_t i = value - minval;
|
||||
return imaxtostr (i + minval, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a prefix of the string ARG to a system integer type whose
|
||||
minimum value is MINVAL and maximum MAXVAL. If MINVAL is negative,
|
||||
negative integers MINVAL .. -1 are assumed to be represented using
|
||||
leading '-' in the usual way. If the represented value exceeds
|
||||
INTMAX_MAX, return a negative integer V such that (uintmax_t) V
|
||||
yields the represented value. If ARGLIM is nonnull, store into
|
||||
*ARGLIM a pointer to the first character after the prefix.
|
||||
|
||||
This is the inverse of sysinttostr.
|
||||
|
||||
On a normal return, set errno = 0.
|
||||
On conversion error, return 0 and set errno = EINVAL.
|
||||
On overflow, return an extreme value and set errno = ERANGE. */
|
||||
#if ! (INTMAX_MAX <= UINTMAX_MAX)
|
||||
# error "strtosysint: nonnegative intmax_t does not fit in uintmax_t"
|
||||
#endif
|
||||
intmax_t
|
||||
strtosysint (char const *arg, char **arglim, intmax_t minval, uintmax_t maxval)
|
||||
{
|
||||
errno = 0;
|
||||
if (maxval <= INTMAX_MAX)
|
||||
{
|
||||
if (ISDIGIT (arg[*arg == '-']))
|
||||
{
|
||||
intmax_t i = strtoimax (arg, arglim, 10);
|
||||
intmax_t imaxval = maxval;
|
||||
if (minval <= i && i <= imaxval)
|
||||
return i;
|
||||
errno = ERANGE;
|
||||
return i < minval ? minval : maxval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ISDIGIT (*arg))
|
||||
{
|
||||
uintmax_t i = strtoumax (arg, arglim, 10);
|
||||
if (i <= maxval)
|
||||
return represent_uintmax (i);
|
||||
errno = ERANGE;
|
||||
return maxval;
|
||||
}
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Output fraction and trailing digits appropriate for a nanoseconds
|
||||
count equal to NS, but don't output unnecessary '.' or trailing
|
||||
zeros. */
|
||||
@@ -257,6 +443,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++;
|
||||
@@ -269,6 +459,84 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
|
||||
code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND);
|
||||
return np;
|
||||
}
|
||||
|
||||
struct timespec
|
||||
decode_timespec (char const *arg, char **arg_lim, bool parse_fraction)
|
||||
{
|
||||
time_t s = TYPE_MINIMUM (time_t);
|
||||
int ns = -1;
|
||||
char const *p = arg;
|
||||
bool negative = *arg == '-';
|
||||
struct timespec r;
|
||||
|
||||
if (! ISDIGIT (arg[negative]))
|
||||
errno = EINVAL;
|
||||
else
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
if (negative)
|
||||
{
|
||||
intmax_t i = strtoimax (arg, arg_lim, 10);
|
||||
if (TYPE_SIGNED (time_t) ? TYPE_MINIMUM (time_t) <= i : 0 <= i)
|
||||
s = i;
|
||||
else
|
||||
errno = ERANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
uintmax_t i = strtoumax (arg, arg_lim, 10);
|
||||
if (i <= TYPE_MAXIMUM (time_t))
|
||||
s = i;
|
||||
else
|
||||
errno = ERANGE;
|
||||
}
|
||||
|
||||
p = *arg_lim;
|
||||
ns = 0;
|
||||
|
||||
if (parse_fraction && *p == '.')
|
||||
{
|
||||
int digits = 0;
|
||||
bool trailing_nonzero = false;
|
||||
|
||||
while (ISDIGIT (*++p))
|
||||
if (digits < LOG10_BILLION)
|
||||
digits++, ns = 10 * ns + (*p - '0');
|
||||
else
|
||||
trailing_nonzero |= *p != '0';
|
||||
|
||||
while (digits < LOG10_BILLION)
|
||||
digits++, ns *= 10;
|
||||
|
||||
if (negative)
|
||||
{
|
||||
/* Convert "-1.10000000000001" to s == -2, ns == 89999999.
|
||||
I.e., truncate time stamps towards minus infinity while
|
||||
converting them to internal form. */
|
||||
ns += trailing_nonzero;
|
||||
if (ns != 0)
|
||||
{
|
||||
if (s == TYPE_MINIMUM (time_t))
|
||||
ns = -1;
|
||||
else
|
||||
{
|
||||
s--;
|
||||
ns = BILLION - ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errno == ERANGE)
|
||||
ns = -1;
|
||||
}
|
||||
|
||||
*arg_lim = (char *) p;
|
||||
r.tv_sec = s;
|
||||
r.tv_nsec = ns;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* File handling. */
|
||||
|
||||
@@ -277,7 +545,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 +586,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 +606,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 +622,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:
|
||||
@@ -371,7 +639,7 @@ remove_any_file (const char *file_name, enum remove_option option)
|
||||
|
||||
case RECURSIVE_REMOVE_OPTION:
|
||||
{
|
||||
char *directory = savedir (file_name);
|
||||
char *directory = tar_savedir (file_name, 0);
|
||||
char const *entry;
|
||||
size_t entrylen;
|
||||
|
||||
@@ -417,12 +685,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 +715,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 +747,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,70 +763,142 @@ 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. */
|
||||
int
|
||||
set_file_atime (int fd, char const *file, struct timespec const timespec[2])
|
||||
/* Read from FD into the buffer BUF with COUNT bytes. Attempt to fill
|
||||
BUF. Wait until input is available; this matters because files are
|
||||
opened O_NONBLOCK for security reasons, and on some file systems
|
||||
this can cause read to fail with errno == EAGAIN. Return the
|
||||
actual number of bytes read, zero for EOF, or
|
||||
SAFE_READ_ERROR upon error. */
|
||||
size_t
|
||||
blocking_read (int fd, void *buf, size_t count)
|
||||
{
|
||||
#ifdef _FIOSATIME
|
||||
if (0 <= fd)
|
||||
size_t bytes = safe_read (fd, buf, count);
|
||||
|
||||
#if defined F_SETFL && O_NONBLOCK
|
||||
if (bytes == SAFE_READ_ERROR && errno == EAGAIN)
|
||||
{
|
||||
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;
|
||||
int flags = fcntl (fd, F_GETFL);
|
||||
if (0 <= flags && flags & O_NONBLOCK
|
||||
&& fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
|
||||
bytes = safe_read (fd, buf, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
return gl_futimens (fd, file, timespec);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* Write to FD from the buffer BUF with COUNT bytes. Do a full write.
|
||||
Wait until an output buffer is available; this matters because
|
||||
files are opened O_NONBLOCK for security reasons, and on some file
|
||||
systems this can cause write to fail with errno == EAGAIN. Return
|
||||
the actual number of bytes written, setting errno if that is less
|
||||
than COUNT. */
|
||||
size_t
|
||||
blocking_write (int fd, void const *buf, size_t count)
|
||||
{
|
||||
size_t bytes = full_write (fd, buf, count);
|
||||
|
||||
#if defined F_SETFL && O_NONBLOCK
|
||||
if (bytes < count && errno == EAGAIN)
|
||||
{
|
||||
int flags = fcntl (fd, F_GETFL);
|
||||
if (0 <= flags && flags & O_NONBLOCK
|
||||
&& fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
|
||||
{
|
||||
char const *buffer = buf;
|
||||
bytes += full_write (fd, buffer + bytes, count - bytes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* Set FD's (i.e., assuming the working directory is PARENTFD, FILE's)
|
||||
access time to ATIME. */
|
||||
int
|
||||
set_file_atime (int fd, int parentfd, char const *file, struct timespec atime)
|
||||
{
|
||||
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;
|
||||
/* "Absolute" path representing this directory; in the contrast to
|
||||
the real absolute pathname, it can contain /../ components (see
|
||||
normalize_filename_x for the reason of it). It is NULL if the
|
||||
absolute path could not be determined. */
|
||||
char *abspath;
|
||||
/* 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 (void)
|
||||
{
|
||||
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)
|
||||
char *absdir;
|
||||
|
||||
if (wd_count == wd_alloc)
|
||||
{
|
||||
if (wd_alloc == 0)
|
||||
{
|
||||
wd_alloc = 2;
|
||||
wd = xmalloc (sizeof *wd * wd_alloc);
|
||||
}
|
||||
else
|
||||
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
|
||||
wd_alloc = 2;
|
||||
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].abspath = xgetcwd ();
|
||||
wd[wd_count].fd = AT_FDCWD;
|
||||
wd_count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,71 +910,124 @@ 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++;
|
||||
|
||||
/* If the given name is absolute, use it to represent this directory;
|
||||
otherwise, construct a name based on the previous -C option. */
|
||||
if (IS_ABSOLUTE_FILE_NAME (dir))
|
||||
absdir = xstrdup (dir);
|
||||
else if (wd[wd_count - 1].abspath)
|
||||
{
|
||||
namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
|
||||
namebuf_add_dir (nbuf, dir);
|
||||
absdir = namebuf_finish (nbuf);
|
||||
}
|
||||
else
|
||||
absdir = 0;
|
||||
|
||||
wd[wd_count].name = dir;
|
||||
wd[wd_count].abspath = absdir;
|
||||
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 cur = wdcache[ci];
|
||||
wdcache[ci] = prev;
|
||||
if (cur == i)
|
||||
break;
|
||||
prev = cur;
|
||||
}
|
||||
wdcache[0] = i;
|
||||
}
|
||||
|
||||
chdir_current = i;
|
||||
chdir_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
tar_dirname (void)
|
||||
{
|
||||
return wd[chdir_current].name;
|
||||
}
|
||||
|
||||
/* Return the absolute path that represents the working
|
||||
directory referenced by IDX.
|
||||
|
||||
If wd is empty, then there were no -C options given, and
|
||||
chdir_args() has never been called, so we simply return the
|
||||
process's actual cwd. (Note that in this case IDX is ignored,
|
||||
since it should always be 0.) */
|
||||
static const char *
|
||||
tar_getcdpath (int idx)
|
||||
{
|
||||
if (!wd)
|
||||
{
|
||||
static char *cwd;
|
||||
if (!cwd)
|
||||
cwd = xgetcwd ();
|
||||
return cwd;
|
||||
}
|
||||
return wd[idx].abspath;
|
||||
}
|
||||
|
||||
void
|
||||
close_diag (char const *name)
|
||||
{
|
||||
@@ -695,6 +1091,21 @@ 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
|
||||
write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
{
|
||||
@@ -746,3 +1157,94 @@ 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;
|
||||
}
|
||||
|
||||
void
|
||||
namebuf_add_dir (namebuf_t buf, const char *name)
|
||||
{
|
||||
static char dirsep[] = { DIRECTORY_SEPARATOR, 0 };
|
||||
if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
|
||||
{
|
||||
namebuf_name (buf, dirsep);
|
||||
buf->dir_length++;
|
||||
}
|
||||
namebuf_name (buf, name);
|
||||
buf->dir_length += strlen (name);
|
||||
}
|
||||
|
||||
char *
|
||||
namebuf_finish (namebuf_t buf)
|
||||
{
|
||||
char *res = buf->buffer;
|
||||
|
||||
if (ISSLASH (buf->buffer[buf->dir_length - 1]))
|
||||
buf->buffer[buf->dir_length] = 0;
|
||||
free (buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Return the filenames in directory NAME, relative to the chdir_fd.
|
||||
If the directory does not exist, report error if MUST_EXIST is
|
||||
true.
|
||||
|
||||
Return NULL on errors.
|
||||
*/
|
||||
char *
|
||||
tar_savedir (const char *name, int must_exist)
|
||||
{
|
||||
char *ret = NULL;
|
||||
DIR *dir = NULL;
|
||||
int fd = openat (chdir_fd, name, open_read_flags | O_DIRECTORY);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (!must_exist && errno == ENOENT)
|
||||
return NULL;
|
||||
open_error (name);
|
||||
}
|
||||
else if (! ((dir = fdopendir (fd))
|
||||
&& (ret = streamsavedir (dir, savedir_sort_order))))
|
||||
savedir_error (name);
|
||||
|
||||
if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)
|
||||
savedir_error (name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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();
|
||||
901
src/names.c
901
src/names.c
File diff suppressed because it is too large
Load Diff
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. */
|
||||
|
||||
|
||||
|
||||
|
||||
183
src/sparse.c
183
src/sparse.c
@@ -1,6 +1,6 @@
|
||||
/* Functions for dealing with sparse files
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2003-2007, 2010, 2013-2014 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
|
||||
@@ -13,8 +13,7 @@
|
||||
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. */
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include <inttostr.h>
|
||||
@@ -216,43 +215,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 = blocking_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 +325,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 +334,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;
|
||||
@@ -358,7 +358,7 @@ sparse_extract_region (struct tar_sparse_file *file, size_t i)
|
||||
return false;
|
||||
}
|
||||
set_next_block_after (blk);
|
||||
count = full_write (file->fd, blk->buffer, wrbytes);
|
||||
count = blocking_write (file->fd, blk->buffer, wrbytes);
|
||||
write_size -= count;
|
||||
file->dumped_size += count;
|
||||
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
|
||||
@@ -398,10 +398,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 +509,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 +565,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 +580,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;
|
||||
}
|
||||
@@ -588,18 +589,18 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
|
||||
/* Old GNU Format. The sparse file information is stored in the
|
||||
oldgnu_header in the following manner:
|
||||
|
||||
The header is marked with type 'S'. Its `size' field contains
|
||||
The header is marked with type 'S'. Its 'size' field contains
|
||||
the cumulative size of all non-empty blocks of the file. The
|
||||
actual file size is stored in `realsize' member of oldgnu_header.
|
||||
actual file size is stored in 'realsize' member of oldgnu_header.
|
||||
|
||||
The map of the file is stored in a list of `struct sparse'.
|
||||
The map of the file is stored in a list of 'struct sparse'.
|
||||
Each struct contains offset to the block of data and its
|
||||
size (both as octal numbers). The first file header contains
|
||||
at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map
|
||||
contains more structs, then the field `isextended' of the main
|
||||
header is set to 1 (binary) and the `struct sparse_header'
|
||||
contains more structs, then the field 'isextended' of the main
|
||||
header is set to 1 (binary) and the 'struct sparse_header'
|
||||
header follows, containing at most 21 following structs
|
||||
(SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'
|
||||
(SPARSES_IN_SPARSE_HEADER). If more structs follow, 'isextended'
|
||||
field of the extended header is set and next next extension header
|
||||
follows, etc... */
|
||||
|
||||
@@ -625,8 +626,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);
|
||||
if (sp.offset < 0
|
||||
sp.numbytes = OFF_FROM_HEADER (s->numbytes);
|
||||
if (sp.offset < 0 || sp.numbytes < 0
|
||||
|| INT_ADD_OVERFLOW (sp.offset, sp.numbytes)
|
||||
|| file->stat_info->stat.st_size < sp.offset + sp.numbytes
|
||||
|| file->stat_info->archive_file_size < 0)
|
||||
return add_fail;
|
||||
@@ -640,10 +642,10 @@ oldgnu_fixup_header (struct tar_sparse_file *file)
|
||||
{
|
||||
/* NOTE! st_size was initialized from the header
|
||||
which actually contains archived size. The following fixes it */
|
||||
off_t realsize = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
|
||||
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
|
||||
file->stat_info->stat.st_size =
|
||||
OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
|
||||
return true;
|
||||
file->stat_info->stat.st_size = max (0, realsize);
|
||||
return 0 <= realsize;
|
||||
}
|
||||
|
||||
/* Convert old GNU format sparse data to internal representation */
|
||||
@@ -695,8 +697,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,10 +766,10 @@ star_fixup_header (struct tar_sparse_file *file)
|
||||
{
|
||||
/* NOTE! st_size was initialized from the header
|
||||
which actually contains archived size. The following fixes it */
|
||||
off_t realsize = OFF_FROM_HEADER (current_header->star_in_header.realsize);
|
||||
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
|
||||
file->stat_info->stat.st_size =
|
||||
OFF_FROM_HEADER (current_header->star_in_header.realsize);
|
||||
return true;
|
||||
file->stat_info->stat.st_size = max (0, realsize);
|
||||
return 0 <= realsize;
|
||||
}
|
||||
|
||||
/* Convert STAR format sparse data to internal representation */
|
||||
@@ -807,6 +809,7 @@ star_get_sparse_info (struct tar_sparse_file *file)
|
||||
set_next_block_after (h);
|
||||
for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++)
|
||||
rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]);
|
||||
file->dumped_size += BLOCKSIZE;
|
||||
}
|
||||
|
||||
if (rc == add_fail)
|
||||
@@ -851,13 +854,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 +878,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
|
||||
@@ -915,6 +918,18 @@ pax_sparse_member_p (struct tar_sparse_file *file)
|
||||
|| file->stat_info->sparse_major > 0;
|
||||
}
|
||||
|
||||
/* Start a header that uses the effective (shrunken) file size. */
|
||||
static union block *
|
||||
pax_start_header (struct tar_stat_info *st)
|
||||
{
|
||||
off_t realsize = st->stat.st_size;
|
||||
union block *blk;
|
||||
st->stat.st_size = st->archive_file_size;
|
||||
blk = start_header (st);
|
||||
st->stat.st_size = realsize;
|
||||
return blk;
|
||||
}
|
||||
|
||||
static bool
|
||||
pax_dump_header_0 (struct tar_sparse_file *file)
|
||||
{
|
||||
@@ -924,11 +939,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)
|
||||
{
|
||||
@@ -964,9 +979,7 @@ pax_dump_header_0 (struct tar_sparse_file *file)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
blk = start_header (file->stat_info);
|
||||
/* Store the effective (shrunken) file size */
|
||||
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
|
||||
blk = pax_start_header (file->stat_info);
|
||||
finish_header (file->stat_info, blk, block_ordinal);
|
||||
if (save_file_name)
|
||||
{
|
||||
@@ -991,7 +1004,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 +1016,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,19 +1031,20 @@ 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);
|
||||
|
||||
blk = start_header (file->stat_info);
|
||||
/* Store the effective (shrunken) file size */
|
||||
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
|
||||
file->stat_info->file_name =
|
||||
xheader_format_name (file->stat_info, "%d/GNUSparseFile.%p/%f", 0);
|
||||
/* Make sure the created header name is shorter than NAME_FIELD_SIZE: */
|
||||
if (strlen (file->stat_info->file_name) > NAME_FIELD_SIZE)
|
||||
file->stat_info->file_name[NAME_FIELD_SIZE] = 0;
|
||||
|
||||
blk = pax_start_header (file->stat_info);
|
||||
finish_header (file->stat_info, blk, block_ordinal);
|
||||
free (file->stat_info->file_name);
|
||||
file->stat_info->file_name = save_file_name;
|
||||
@@ -1072,12 +1086,13 @@ decode_num (uintmax_t *num, char const *arg, uintmax_t maxval)
|
||||
|
||||
if (!ISDIGIT (*arg))
|
||||
return false;
|
||||
|
||||
|
||||
errno = 0;
|
||||
u = strtoumax (arg, &arg_lim, 10);
|
||||
|
||||
if (! (u <= maxval && errno != ERANGE) || *arg_lim)
|
||||
return false;
|
||||
|
||||
|
||||
*num = u;
|
||||
return true;
|
||||
}
|
||||
@@ -1117,7 +1132,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 +1141,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 +1152,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 +1173,7 @@ pax_decode_header (struct tar_sparse_file *file)
|
||||
}
|
||||
set_next_block_after (blk);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1168,7 +1183,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,
|
||||
|
||||
106
src/suffix.c
106
src/suffix.c
@@ -1,5 +1,5 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2007, 2009 Free Software Foundation, Inc.
|
||||
Copyright 2007, 2009, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
Written by Sergey Poznyakoff.
|
||||
|
||||
@@ -26,55 +26,89 @@ 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)
|
||||
{ "tar", 3, NULL },
|
||||
{ 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) },
|
||||
{ S(txz, XZ) }, /* Slackware */
|
||||
{ NULL }
|
||||
#undef S
|
||||
#undef __CAT2__
|
||||
};
|
||||
|
||||
int nsuffixes = sizeof (compression_suffixes) /
|
||||
sizeof (compression_suffixes[0]);
|
||||
static struct compression_suffix const *
|
||||
find_compression_suffix (const char *name, size_t *ret_len)
|
||||
{
|
||||
char *suf = strrchr (name, '.');
|
||||
|
||||
if (suf)
|
||||
{
|
||||
size_t len;
|
||||
struct compression_suffix *p;
|
||||
|
||||
suf++;
|
||||
len = strlen (suf);
|
||||
|
||||
for (p = compression_suffixes; p->suffix; p++)
|
||||
{
|
||||
if (p->length == len && memcmp (p->suffix, suf, len) == 0)
|
||||
{
|
||||
if (ret_len)
|
||||
*ret_len = strlen (name) - len - 1;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
find_compression_program (const char *name, const char *defprog)
|
||||
{
|
||||
char *suf = strrchr (name, '.');
|
||||
|
||||
if (suf)
|
||||
{
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
suf++;
|
||||
len = strlen (suf);
|
||||
|
||||
for (i = 0; i < nsuffixes; i++)
|
||||
{
|
||||
if (compression_suffixes[i].length == len
|
||||
&& memcmp (compression_suffixes[i].suffix, suf, len) == 0)
|
||||
return compression_suffixes[i].program;
|
||||
}
|
||||
}
|
||||
struct compression_suffix const *p = find_compression_suffix (name, NULL);
|
||||
if (p)
|
||||
return p->program;
|
||||
return 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;
|
||||
}
|
||||
|
||||
char *
|
||||
strip_compression_suffix (const char *name)
|
||||
{
|
||||
char *s = NULL;
|
||||
size_t len;
|
||||
|
||||
if (find_compression_suffix (name, &len))
|
||||
{
|
||||
if (strncmp (name + len - 4, ".tar", 4) == 0)
|
||||
len -= 4;
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
s = xmalloc (len + 1);
|
||||
memcpy (s, name, len);
|
||||
s[len] = 0;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
208
src/system.c
208
src/system.c
@@ -1,7 +1,6 @@
|
||||
/* System-dependent calls for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007,
|
||||
2008 Free Software Foundation, Inc.
|
||||
Copyright 2003-2008, 2010, 2013-2014 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
|
||||
@@ -14,14 +13,28 @@
|
||||
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. */
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <priv-set.h>
|
||||
#include <rmt.h>
|
||||
#include <signal.h>
|
||||
#include <wordsplit.h>
|
||||
|
||||
static _Noreturn void
|
||||
xexec (const char *cmd)
|
||||
{
|
||||
struct wordsplit ws;
|
||||
|
||||
ws.ws_env = (const char **) environ;
|
||||
if (wordsplit (cmd, &ws, (WRDSF_DEFFLAGS | WRDSF_ENV) & ~WRDSF_NOVAR))
|
||||
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
|
||||
cmd, wordsplit_strerror (&ws)));
|
||||
execvp (ws.ws_wordv[0], ws.ws_wordv);
|
||||
exec_fatal (cmd);
|
||||
}
|
||||
|
||||
#if MSDOS
|
||||
|
||||
@@ -174,11 +187,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,7 +205,8 @@ sys_spawn_shell (void)
|
||||
child = xfork ();
|
||||
if (child == 0)
|
||||
{
|
||||
execlp (shell, "-sh", "-i", (char *) 0);
|
||||
priv_set_restore_linkdir ();
|
||||
execlp (shell, "-sh", "-i", NULL);
|
||||
exec_fatal (shell);
|
||||
}
|
||||
else
|
||||
@@ -283,6 +297,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 +329,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 +344,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,8 +376,8 @@ sys_child_open_for_compress (void)
|
||||
}
|
||||
xdup2 (archive, STDOUT_FILENO);
|
||||
}
|
||||
execlp (use_compress_program_option, use_compress_program_option, NULL);
|
||||
exec_fatal (use_compress_program_option);
|
||||
priv_set_restore_linkdir ();
|
||||
xexec (use_compress_program_option);
|
||||
}
|
||||
|
||||
/* We do need a grandchild tar. */
|
||||
@@ -351,13 +389,12 @@ 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]);
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
(char *) 0);
|
||||
exec_fatal (use_compress_program_option);
|
||||
priv_set_restore_linkdir ();
|
||||
xexec (use_compress_program_option);
|
||||
}
|
||||
|
||||
/* The child tar is still here! */
|
||||
@@ -424,24 +461,43 @@ 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;
|
||||
struct wordsplit ws;
|
||||
int wsflags = (WRDSF_DEFFLAGS | WRDSF_ENV | WRDSF_DOOFFS) & ~WRDSF_NOVAR;
|
||||
|
||||
if (WIFSIGNALED (wait_status))
|
||||
ws.ws_env = (const char **) environ;
|
||||
ws.ws_offs = 1;
|
||||
|
||||
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));
|
||||
}
|
||||
if (wordsplit (p, &ws, wsflags))
|
||||
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
|
||||
p, wordsplit_strerror (&ws)));
|
||||
wsflags |= WRDSF_REUSE;
|
||||
memmove(ws.ws_wordv, ws.ws_wordv + ws.ws_offs,
|
||||
sizeof(ws.ws_wordv[0])*ws.ws_wordc);
|
||||
ws.ws_wordv[ws.ws_wordc] = (char *) "-d";
|
||||
prog = p;
|
||||
execvp (ws.ws_wordv[0], ws.ws_wordv);
|
||||
ws.ws_wordv[ws.ws_wordc] = 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 +508,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 +523,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 +545,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 +558,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 +616,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 +633,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 +641,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 +651,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 +663,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 +676,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);
|
||||
@@ -677,13 +720,12 @@ stat_to_env (char *name, char type, struct tar_stat_info *st)
|
||||
}
|
||||
|
||||
static pid_t global_pid;
|
||||
static RETSIGTYPE (*pipe_handler) (int sig);
|
||||
static void (*pipe_handler) (int sig);
|
||||
|
||||
int
|
||||
sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
|
||||
{
|
||||
int p[2];
|
||||
char *argv[4];
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
@@ -701,14 +743,8 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
|
||||
|
||||
stat_to_env (file_name, typechar, st);
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = to_command_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv ("/bin/sh", argv);
|
||||
|
||||
exec_fatal (file_name);
|
||||
priv_set_restore_linkdir ();
|
||||
xexec (to_command_option);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -750,11 +786,10 @@ int
|
||||
sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
{
|
||||
pid_t pid;
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
int p[2];
|
||||
static RETSIGTYPE (*saved_handler) (int sig);
|
||||
|
||||
static void (*saved_handler) (int sig);
|
||||
|
||||
xpipe (p);
|
||||
saved_handler = signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
@@ -787,7 +822,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)
|
||||
@@ -815,14 +850,8 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
|
||||
xclose (p[PREAD]);
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*) info_script_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (info_script_option);
|
||||
priv_set_restore_linkdir ();
|
||||
xexec (info_script_option);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -831,7 +860,6 @@ sys_exec_checkpoint_script (const char *script_name,
|
||||
int checkpoint_number)
|
||||
{
|
||||
pid_t pid;
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
pid = xfork ();
|
||||
@@ -862,14 +890,8 @@ sys_exec_checkpoint_script (const char *script_name,
|
||||
setenv ("TAR_FORMAT",
|
||||
archive_format_string (current_format == DEFAULT_FORMAT ?
|
||||
archive_format : current_format), 1);
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*) script_name;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (script_name);
|
||||
priv_set_restore_linkdir ();
|
||||
xexec (script_name);
|
||||
}
|
||||
|
||||
#endif /* not MSDOS */
|
||||
|
||||
78
src/tar.h
78
src/tar.h
@@ -1,21 +1,22 @@
|
||||
/* GNU tar Archive Format description.
|
||||
|
||||
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright 1988-1989, 1991-1997, 2000-2001, 2003-2007, 2012-2014 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 file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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. */
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* tar Header Block, from POSIX 1003.1-1990. */
|
||||
|
||||
@@ -80,9 +81,9 @@ struct posix_header
|
||||
/* tar Header Block, GNU extensions. */
|
||||
|
||||
/* In GNU tar, SYMTYPE is for to symbolic links, and CONTTYPE is for
|
||||
contiguous files, so maybe disobeying the `reserved' comment in POSIX
|
||||
contiguous files, so maybe disobeying the "reserved" comment in POSIX
|
||||
header description. I suspect these were meant to be used this way, and
|
||||
should not have really been `reserved' in the published standards. */
|
||||
should not have really been "reserved" in the published standards. */
|
||||
|
||||
/* *BEWARE* *BEWARE* *BEWARE* that the following information is still
|
||||
boiling, and may change. Even if the OLDGNU format description should be
|
||||
@@ -265,7 +266,7 @@ enum archive_format
|
||||
struct sp_array
|
||||
{
|
||||
off_t offset;
|
||||
size_t numbytes;
|
||||
off_t numbytes;
|
||||
};
|
||||
|
||||
struct xheader
|
||||
@@ -276,6 +277,14 @@ struct xheader
|
||||
uintmax_t string_length;
|
||||
};
|
||||
|
||||
/* Information about xattrs for a file. */
|
||||
struct xattr_array
|
||||
{
|
||||
char *xkey;
|
||||
char *xval_ptr;
|
||||
size_t xval_len;
|
||||
};
|
||||
|
||||
struct tar_stat_info
|
||||
{
|
||||
char *orig_file_name; /* name of file read from the archive header */
|
||||
@@ -287,6 +296,15 @@ struct tar_stat_info
|
||||
|
||||
char *uname; /* user name of owner */
|
||||
char *gname; /* group name of owner */
|
||||
|
||||
char *cntx_name; /* SELinux context for the current archive entry. */
|
||||
|
||||
char *acls_a_ptr; /* Access ACLs for the current archive entry. */
|
||||
size_t acls_a_len; /* Access ACLs for the current archive entry. */
|
||||
|
||||
char *acls_d_ptr; /* Default ACLs for the current archive entry. */
|
||||
size_t acls_d_len; /* Default ACLs for the current archive entry. */
|
||||
|
||||
struct stat stat; /* regular filesystem stat */
|
||||
|
||||
/* STAT doesn't always have access, data modification, and status
|
||||
@@ -309,14 +327,40 @@ struct tar_stat_info
|
||||
size_t sparse_map_size; /* Size of the sparse map */
|
||||
struct sp_array *sparse_map;
|
||||
|
||||
size_t xattr_map_size; /* Size of the xattr map */
|
||||
struct xattr_array *xattr_map;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Exclusion list */
|
||||
struct exclist *exclude_list;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
112
src/transform.c
112
src/transform.c
@@ -1,5 +1,5 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
/* This file is part of GNU tar.
|
||||
Copyright 2006-2008, 2013-2014 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
|
||||
@@ -12,8 +12,7 @@
|
||||
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. */
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include <regex.h>
|
||||
@@ -34,8 +33,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 +50,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;
|
||||
};
|
||||
|
||||
@@ -71,11 +70,11 @@ struct transform
|
||||
|
||||
|
||||
|
||||
int transform_flags = XFORM_ALL;
|
||||
static 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 +145,7 @@ parse_xform_flags (int *pflags, int c)
|
||||
case 'R':
|
||||
*pflags &= ~XFORM_REGFILE;
|
||||
break;
|
||||
|
||||
|
||||
case 'h':
|
||||
*pflags |= XFORM_LINK;
|
||||
break;
|
||||
@@ -154,7 +153,7 @@ parse_xform_flags (int *pflags, int c)
|
||||
case 'H':
|
||||
*pflags &= ~XFORM_LINK;
|
||||
break;
|
||||
|
||||
|
||||
case 's':
|
||||
*pflags |= XFORM_SYMLINK;
|
||||
break;
|
||||
@@ -204,10 +203,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 +257,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 +274,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 +288,7 @@ parse_transform_expr (const char *expr)
|
||||
if (*cur == '\\')
|
||||
{
|
||||
size_t n;
|
||||
|
||||
|
||||
add_literal_segment (tf, beg, cur);
|
||||
switch (*++cur)
|
||||
{
|
||||
@@ -310,32 +309,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 +344,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'
|
||||
/* 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'
|
||||
/* 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'. */
|
||||
/* Stop case conversion started by '\L' or '\U'. */
|
||||
add_case_ctl_segment (tf, ctl_stop);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/* Try to be nice */
|
||||
{
|
||||
@@ -420,7 +419,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 +429,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 +456,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 +464,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 +472,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 +515,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 +528,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 +548,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 +576,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 +600,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)
|
||||
@@ -629,3 +628,8 @@ transform_name (char **pinput, int type)
|
||||
return transform_name_fp (pinput, type, NULL, NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
transform_program_p (void)
|
||||
{
|
||||
return transform_head != NULL;
|
||||
}
|
||||
|
||||
180
src/unlink.c
Normal file
180
src/unlink.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/* Unlink files.
|
||||
|
||||
Copyright 2009, 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
#include <quotearg.h>
|
||||
|
||||
struct deferred_unlink
|
||||
{
|
||||
struct deferred_unlink *next; /* Next unlink in the queue */
|
||||
int dir_idx; /* Directory index in wd */
|
||||
char *file_name; /* Name of the file to unlink, relative
|
||||
to dir_idx */
|
||||
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. */
|
||||
static 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;
|
||||
int saved_chdir = chdir_current;
|
||||
|
||||
for (p = dunlink_head; p; )
|
||||
{
|
||||
struct deferred_unlink *next = p->next;
|
||||
|
||||
if (force
|
||||
|| records_written > p->records_written + deferred_unlink_delay)
|
||||
{
|
||||
chdir_do (p->dir_idx);
|
||||
if (p->is_dir)
|
||||
{
|
||||
const char *fname;
|
||||
|
||||
if (p->dir_idx
|
||||
&& (p->file_name[0] == 0
|
||||
|| strcmp (p->file_name, ".") == 0))
|
||||
{
|
||||
fname = tar_dirname ();
|
||||
chdir_do (p->dir_idx - 1);
|
||||
}
|
||||
else
|
||||
fname = p->file_name;
|
||||
|
||||
if (unlinkat (chdir_fd, fname, 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 (fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
chdir_do (saved_chdir);
|
||||
}
|
||||
|
||||
void
|
||||
finish_deferred_unlinks (void)
|
||||
{
|
||||
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->dir_idx = chdir_current;
|
||||
p->file_name = xstrdup (name);
|
||||
normalize_filename_x (p->file_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++;
|
||||
}
|
||||
76
src/update.c
76
src/update.c
@@ -1,21 +1,22 @@
|
||||
/* Update a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
Copyright 1988, 1992, 1994, 1996-1997, 1999-2001, 2003-2005, 2007,
|
||||
2010, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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. */
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Implement the 'r', 'u' and 'A' options for tar. 'A' means that the
|
||||
file names are tar files, and they should simply be appended to the end
|
||||
@@ -47,7 +48,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 +115,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 +131,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 +141,30 @@ 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 = tar_savedir (name->name, 1);
|
||||
if (dirp)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else if (tar_timespec_cmp (get_stat_mtime (&s),
|
||||
current_stat_info.mtime)
|
||||
<= 0)
|
||||
remname (name);
|
||||
}
|
||||
}
|
||||
|
||||
skip_member ();
|
||||
@@ -189,22 +212,23 @@ 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)
|
||||
{
|
||||
if (excluded_name (file_name))
|
||||
char *file_name = p->name;
|
||||
if (excluded_name (file_name, NULL))
|
||||
continue;
|
||||
if (interactive_option && !confirm ("add", file_name))
|
||||
continue;
|
||||
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 ();
|
||||
}
|
||||
|
||||
25
src/utf8.c
25
src/utf8.c
@@ -1,20 +1,21 @@
|
||||
/* Charset handling for GNU tar.
|
||||
|
||||
Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2004, 2006-2007, 2013-2014 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 file is part of GNU tar.
|
||||
|
||||
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.
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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. */
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include <quotearg.h>
|
||||
|
||||
@@ -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";
|
||||
107
src/warning.c
Normal file
107
src/warning.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* Warnings for GNU tar.
|
||||
|
||||
Copyright 2009, 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#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",
|
||||
"existing-file",
|
||||
"xattr-write",
|
||||
"record-size",
|
||||
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,
|
||||
WARN_EXISTING_FILE,
|
||||
WARN_XATTR_WRITE,
|
||||
WARN_RECORD_SIZE
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
755
src/xattrs.c
Normal file
755
src/xattrs.c
Normal file
@@ -0,0 +1,755 @@
|
||||
/* Support for extended attributes.
|
||||
|
||||
Copyright (C) 2006-2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Written by James Antill, on 2006-07-27. */
|
||||
|
||||
#include <config.h>
|
||||
#include <system.h>
|
||||
|
||||
#include <fnmatch.h>
|
||||
#include <quotearg.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "xattr-at.h"
|
||||
#include "selinux-at.h"
|
||||
|
||||
struct xattrs_mask_map
|
||||
{
|
||||
const char **masks;
|
||||
size_t size;
|
||||
size_t used;
|
||||
};
|
||||
|
||||
/* list of fnmatch patterns */
|
||||
static struct
|
||||
{
|
||||
/* lists of fnmatch patterns */
|
||||
struct xattrs_mask_map incl;
|
||||
struct xattrs_mask_map excl;
|
||||
} xattrs_setup;
|
||||
|
||||
/* disable posix acls when problem found in gnulib script m4/acl.m4 */
|
||||
#if ! USE_ACL
|
||||
# undef HAVE_POSIX_ACLS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POSIX_ACLS
|
||||
# include "acl.h"
|
||||
# include <sys/acl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POSIX_ACLS
|
||||
|
||||
/* acl-at wrappers, TODO: move to gnulib in future? */
|
||||
static acl_t acl_get_file_at (int, const char *, acl_type_t);
|
||||
static int acl_set_file_at (int, const char *, acl_type_t, acl_t);
|
||||
static int file_has_acl_at (int, char const *, struct stat const *);
|
||||
static int acl_delete_def_file_at (int, char const *);
|
||||
|
||||
/* acl_get_file_at */
|
||||
#define AT_FUNC_NAME acl_get_file_at
|
||||
#define AT_FUNC_RESULT acl_t
|
||||
#define AT_FUNC_FAIL (acl_t)NULL
|
||||
#define AT_FUNC_F1 acl_get_file
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , acl_type_t type
|
||||
#define AT_FUNC_POST_FILE_ARGS , type
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_RESULT
|
||||
#undef AT_FUNC_FAIL
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* acl_set_file_at */
|
||||
#define AT_FUNC_NAME acl_set_file_at
|
||||
#define AT_FUNC_F1 acl_set_file
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , acl_type_t type, acl_t acl
|
||||
#define AT_FUNC_POST_FILE_ARGS , type, acl
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* acl_delete_def_file_at */
|
||||
#define AT_FUNC_NAME acl_delete_def_file_at
|
||||
#define AT_FUNC_F1 acl_delete_def_file
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#define AT_FUNC_POST_FILE_ARGS
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* gnulib file_has_acl_at */
|
||||
#define AT_FUNC_NAME file_has_acl_at
|
||||
#define AT_FUNC_F1 file_has_acl
|
||||
#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat const *st
|
||||
#define AT_FUNC_POST_FILE_ARGS , st
|
||||
#include "at-func.c"
|
||||
#undef AT_FUNC_NAME
|
||||
#undef AT_FUNC_F1
|
||||
#undef AT_FUNC_POST_FILE_PARAM_DECLS
|
||||
#undef AT_FUNC_POST_FILE_ARGS
|
||||
|
||||
/* convert unix permissions into an ACL ... needed due to "default" ACLs */
|
||||
static acl_t
|
||||
perms2acl (int perms)
|
||||
{
|
||||
char val[] = "user::---,group::---,other::---";
|
||||
/* 0123456789 123456789 123456789 123456789 */
|
||||
|
||||
/* user */
|
||||
if (perms & 0400)
|
||||
val[6] = 'r';
|
||||
if (perms & 0200)
|
||||
val[7] = 'w';
|
||||
if (perms & 0100)
|
||||
val[8] = 'x';
|
||||
|
||||
/* group */
|
||||
if (perms & 0040)
|
||||
val[17] = 'r';
|
||||
if (perms & 0020)
|
||||
val[18] = 'w';
|
||||
if (perms & 0010)
|
||||
val[19] = 'x';
|
||||
|
||||
/* other */
|
||||
if (perms & 0004)
|
||||
val[28] = 'r';
|
||||
if (perms & 0002)
|
||||
val[29] = 'w';
|
||||
if (perms & 0001)
|
||||
val[30] = 'x';
|
||||
|
||||
return acl_from_text (val);
|
||||
}
|
||||
|
||||
static char *
|
||||
skip_to_ext_fields (char *ptr)
|
||||
{
|
||||
/* skip tag name (user/group/default/mask) */
|
||||
ptr += strcspn (ptr, ":,\n");
|
||||
|
||||
if (*ptr != ':')
|
||||
return ptr;
|
||||
++ptr;
|
||||
|
||||
ptr += strcspn (ptr, ":,\n"); /* skip user/group name */
|
||||
|
||||
if (*ptr != ':')
|
||||
return ptr;
|
||||
++ptr;
|
||||
|
||||
ptr += strcspn (ptr, ":,\n"); /* skip perms */
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* The POSIX draft allows extra fields after the three main ones. Star
|
||||
uses this to add a fourth field for user/group which is the numeric ID.
|
||||
This function removes such extra fields by overwriting them with the
|
||||
characters that follow. */
|
||||
static char *
|
||||
fixup_extra_acl_fields (char *ptr)
|
||||
{
|
||||
char *src = ptr;
|
||||
char *dst = ptr;
|
||||
|
||||
while (*src)
|
||||
{
|
||||
const char *old = src;
|
||||
size_t len = 0;
|
||||
|
||||
src = skip_to_ext_fields (src);
|
||||
len = src - old;
|
||||
if (old != dst)
|
||||
memmove (dst, old, len);
|
||||
dst += len;
|
||||
|
||||
if (*src == ':') /* We have extra fields, skip them all */
|
||||
src += strcspn (src, "\n,");
|
||||
|
||||
if ((*src == '\n') || (*src == ','))
|
||||
*dst++ = *src++; /* also done when dst == src, but that's ok */
|
||||
}
|
||||
if (src != dst)
|
||||
*dst = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Set the "system.posix_acl_access/system.posix_acl_default" extended
|
||||
attribute. Called only when acls_option > 0. */
|
||||
static void
|
||||
xattrs__acls_set (struct tar_stat_info const *st,
|
||||
char const *file_name, int type,
|
||||
char *ptr, size_t len, bool def)
|
||||
{
|
||||
acl_t acl;
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
/* assert (strlen (ptr) == len); */
|
||||
ptr = fixup_extra_acl_fields (ptr);
|
||||
acl = acl_from_text (ptr);
|
||||
}
|
||||
else if (def)
|
||||
{
|
||||
/* No "default" IEEE 1003.1e ACL set for directory. At this moment,
|
||||
FILE_NAME may already have inherited default acls from parent
|
||||
directory; clean them up. */
|
||||
if (acl_delete_def_file_at (chdir_fd, file_name))
|
||||
WARNOPT (WARN_XATTR_WRITE,
|
||||
(0, errno,
|
||||
_("acl_delete_def_file_at: Cannot drop default POSIX ACLs "
|
||||
"for file '%s'"),
|
||||
file_name));
|
||||
return;
|
||||
}
|
||||
else
|
||||
acl = perms2acl (st->stat.st_mode);
|
||||
|
||||
if (!acl)
|
||||
{
|
||||
call_arg_warn ("acl_from_text", file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (acl_set_file_at (chdir_fd, file_name, type, acl) == -1)
|
||||
/* warn even if filesystem does not support acls */
|
||||
WARNOPT (WARN_XATTR_WRITE,
|
||||
(0, errno,
|
||||
_ ("acl_set_file_at: Cannot set POSIX ACLs for file '%s'"),
|
||||
file_name));
|
||||
|
||||
acl_free (acl);
|
||||
}
|
||||
|
||||
static void
|
||||
xattrs__acls_get_a (int parentfd, const char *file_name,
|
||||
struct tar_stat_info *st,
|
||||
char **ret_ptr, size_t * ret_len)
|
||||
{
|
||||
char *val = NULL;
|
||||
ssize_t len;
|
||||
acl_t acl;
|
||||
|
||||
if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_ACCESS)))
|
||||
{
|
||||
if (errno != ENOTSUP)
|
||||
call_arg_warn ("acl_get_file_at", file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
val = acl_to_text (acl, &len);
|
||||
acl_free (acl);
|
||||
|
||||
if (!val)
|
||||
{
|
||||
call_arg_warn ("acl_to_text", file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
*ret_ptr = xstrdup (val);
|
||||
*ret_len = len;
|
||||
|
||||
acl_free (val);
|
||||
}
|
||||
|
||||
/* "system.posix_acl_default" */
|
||||
static void
|
||||
xattrs__acls_get_d (int parentfd, char const *file_name,
|
||||
struct tar_stat_info *st,
|
||||
char **ret_ptr, size_t * ret_len)
|
||||
{
|
||||
char *val = NULL;
|
||||
ssize_t len;
|
||||
acl_t acl;
|
||||
|
||||
if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT)))
|
||||
{
|
||||
if (errno != ENOTSUP)
|
||||
call_arg_warn ("acl_get_file_at", file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
val = acl_to_text (acl, &len);
|
||||
acl_free (acl);
|
||||
|
||||
if (!val)
|
||||
{
|
||||
call_arg_warn ("acl_to_text", file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
*ret_ptr = xstrdup (val);
|
||||
*ret_len = len;
|
||||
|
||||
acl_free (val);
|
||||
}
|
||||
#endif /* HAVE_POSIX_ACLS */
|
||||
|
||||
static void
|
||||
acls_one_line (const char *prefix, char delim,
|
||||
const char *aclstring, size_t len)
|
||||
{
|
||||
/* support both long and short text representation of posix acls */
|
||||
struct obstack stk;
|
||||
int pref_len = strlen (prefix);
|
||||
const char *oldstring = aclstring;
|
||||
int pos = 0;
|
||||
|
||||
if (!aclstring || !len)
|
||||
return;
|
||||
|
||||
obstack_init (&stk);
|
||||
while (pos <= len)
|
||||
{
|
||||
int move = strcspn (aclstring, ",\n");
|
||||
if (!move)
|
||||
break;
|
||||
|
||||
if (oldstring != aclstring)
|
||||
obstack_1grow (&stk, delim);
|
||||
|
||||
obstack_grow (&stk, prefix, pref_len);
|
||||
obstack_grow (&stk, aclstring, move);
|
||||
|
||||
aclstring += move + 1;
|
||||
}
|
||||
|
||||
obstack_1grow (&stk, '\0');
|
||||
|
||||
fprintf (stdlis, "%s", (char *) obstack_finish (&stk));
|
||||
|
||||
obstack_free (&stk, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_acls_get (int parentfd, char const *file_name,
|
||||
struct tar_stat_info *st, int fd, int xisfile)
|
||||
{
|
||||
if (acls_option > 0)
|
||||
{
|
||||
#ifndef HAVE_POSIX_ACLS
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("POSIX ACL support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
int err = file_has_acl_at (parentfd, file_name, &st->stat);
|
||||
if (err == 0)
|
||||
return;
|
||||
if (err == -1)
|
||||
{
|
||||
call_arg_warn ("file_has_acl_at", file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
xattrs__acls_get_a (parentfd, file_name, st,
|
||||
&st->acls_a_ptr, &st->acls_a_len);
|
||||
if (!xisfile)
|
||||
xattrs__acls_get_d (parentfd, file_name, st,
|
||||
&st->acls_d_ptr, &st->acls_d_len);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_acls_set (struct tar_stat_info const *st,
|
||||
char const *file_name, char typeflag)
|
||||
{
|
||||
if (acls_option > 0 && typeflag != SYMTYPE)
|
||||
{
|
||||
#ifndef HAVE_POSIX_ACLS
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("POSIX ACL support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS,
|
||||
st->acls_a_ptr, st->acls_a_len, false);
|
||||
if (typeflag == DIRTYPE || typeflag == GNUTYPE_DUMPDIR)
|
||||
xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT,
|
||||
st->acls_d_ptr, st->acls_d_len, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mask_map_realloc (struct xattrs_mask_map *map)
|
||||
{
|
||||
if (map->used == map->size)
|
||||
{
|
||||
if (map->size == 0)
|
||||
map->size = 4;
|
||||
map->masks = x2nrealloc (map->masks, &map->size, sizeof (map->masks[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_mask_add (const char *mask, bool incl)
|
||||
{
|
||||
struct xattrs_mask_map *mask_map =
|
||||
incl ? &xattrs_setup.incl : &xattrs_setup.excl;
|
||||
/* ensure there is enough space */
|
||||
mask_map_realloc (mask_map);
|
||||
/* just assign pointers -- we silently expect that pointer "mask" is valid
|
||||
through the whole program (pointer to argv array) */
|
||||
mask_map->masks[mask_map->used++] = mask;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_mask_map (struct xattrs_mask_map *mask_map)
|
||||
{
|
||||
if (mask_map->size)
|
||||
free (mask_map->masks);
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_clear_setup (void)
|
||||
{
|
||||
clear_mask_map (&xattrs_setup.incl);
|
||||
clear_mask_map (&xattrs_setup.excl);
|
||||
}
|
||||
|
||||
/* get all xattrs from file given by FILE_NAME or FD (when non-zero). This
|
||||
includes all the user.*, security.*, system.*, etc. available domains */
|
||||
void
|
||||
xattrs_xattrs_get (int parentfd, char const *file_name,
|
||||
struct tar_stat_info *st, int fd)
|
||||
{
|
||||
if (xattrs_option > 0)
|
||||
{
|
||||
#ifndef HAVE_XATTRS
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("XATTR support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
static size_t xsz = 1024;
|
||||
static char *xatrs = NULL;
|
||||
ssize_t xret = -1;
|
||||
|
||||
if (!xatrs)
|
||||
xatrs = x2nrealloc (xatrs, &xsz, 1);
|
||||
|
||||
while (((fd == 0) ?
|
||||
((xret =
|
||||
llistxattrat (parentfd, file_name, xatrs, xsz)) == -1) :
|
||||
((xret = flistxattr (fd, xatrs, xsz)) == -1))
|
||||
&& (errno == ERANGE))
|
||||
{
|
||||
xatrs = x2nrealloc (xatrs, &xsz, 1);
|
||||
}
|
||||
|
||||
if (xret == -1)
|
||||
call_arg_warn ((fd == 0) ? "llistxattrat" : "flistxattr", file_name);
|
||||
else
|
||||
{
|
||||
const char *attr = xatrs;
|
||||
static size_t asz = 1024;
|
||||
static char *val = NULL;
|
||||
|
||||
if (!val)
|
||||
val = x2nrealloc (val, &asz, 1);
|
||||
|
||||
while (xret > 0)
|
||||
{
|
||||
size_t len = strlen (attr);
|
||||
ssize_t aret = 0;
|
||||
|
||||
/* Archive all xattrs during creation, decide at extraction time
|
||||
* which ones are of interest/use for the target filesystem. */
|
||||
while (((fd == 0)
|
||||
? ((aret = lgetxattrat (parentfd, file_name, attr,
|
||||
val, asz)) == -1)
|
||||
: ((aret = fgetxattr (fd, attr, val, asz)) == -1))
|
||||
&& (errno == ERANGE))
|
||||
{
|
||||
val = x2nrealloc (val, &asz, 1);
|
||||
}
|
||||
|
||||
if (aret != -1)
|
||||
xheader_xattr_add (st, attr, val, aret);
|
||||
else if (errno != ENOATTR)
|
||||
call_arg_warn ((fd == 0) ? "lgetxattrat"
|
||||
: "fgetxattr", file_name);
|
||||
|
||||
attr += len + 1;
|
||||
xret -= len + 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_XATTRS
|
||||
static void
|
||||
xattrs__fd_set (struct tar_stat_info const *st,
|
||||
char const *file_name, char typeflag,
|
||||
const char *attr, const char *ptr, size_t len)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
const char *sysname = "setxattrat";
|
||||
int ret = -1;
|
||||
|
||||
if (typeflag != SYMTYPE)
|
||||
ret = setxattrat (chdir_fd, file_name, attr, ptr, len, 0);
|
||||
else
|
||||
{
|
||||
sysname = "lsetxattr";
|
||||
ret = lsetxattrat (chdir_fd, file_name, attr, ptr, len, 0);
|
||||
}
|
||||
|
||||
if (ret == -1)
|
||||
WARNOPT (WARN_XATTR_WRITE,
|
||||
(0, errno,
|
||||
_("%s: Cannot set '%s' extended attribute for file '%s'"),
|
||||
sysname, attr, file_name));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* lgetfileconat is called against FILE_NAME iff the FD parameter is set to
|
||||
zero, otherwise the fgetfileconat is used against correct file descriptor */
|
||||
void
|
||||
xattrs_selinux_get (int parentfd, char const *file_name,
|
||||
struct tar_stat_info *st, int fd)
|
||||
{
|
||||
if (selinux_context_option > 0)
|
||||
{
|
||||
#if HAVE_SELINUX_SELINUX_H != 1
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("SELinux support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
int result = fd ?
|
||||
fgetfilecon (fd, &st->cntx_name)
|
||||
: lgetfileconat (parentfd, file_name, &st->cntx_name);
|
||||
|
||||
if (result == -1 && errno != ENODATA && errno != ENOTSUP)
|
||||
call_arg_warn (fd ? "fgetfilecon" : "lgetfileconat", file_name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_selinux_set (struct tar_stat_info const *st,
|
||||
char const *file_name, char typeflag)
|
||||
{
|
||||
if (selinux_context_option > 0)
|
||||
{
|
||||
#if HAVE_SELINUX_SELINUX_H != 1
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("SELinux support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
const char *sysname = "setfilecon";
|
||||
int ret;
|
||||
|
||||
if (!st->cntx_name)
|
||||
return;
|
||||
|
||||
if (typeflag != SYMTYPE)
|
||||
{
|
||||
ret = setfileconat (chdir_fd, file_name, st->cntx_name);
|
||||
sysname = "setfileconat";
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = lsetfileconat (chdir_fd, file_name, st->cntx_name);
|
||||
sysname = "lsetfileconat";
|
||||
}
|
||||
|
||||
if (ret == -1)
|
||||
WARNOPT (WARN_XATTR_WRITE,
|
||||
(0, errno,
|
||||
_("%s: Cannot set SELinux context for file '%s'"),
|
||||
sysname, file_name));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
xattrs_matches_mask (const char *kw, struct xattrs_mask_map *mm)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mm->size)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < mm->used; i++)
|
||||
if (fnmatch (mm->masks[i], kw, 0) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define USER_DOT_PFX "user."
|
||||
|
||||
static bool
|
||||
xattrs_kw_included (const char *kw, bool archiving)
|
||||
{
|
||||
if (xattrs_setup.incl.size)
|
||||
return xattrs_matches_mask (kw, &xattrs_setup.incl);
|
||||
else if (archiving)
|
||||
return true;
|
||||
else
|
||||
return strncmp (kw, USER_DOT_PFX, sizeof (USER_DOT_PFX) - 1) == 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
xattrs_kw_excluded (const char *kw, bool archiving)
|
||||
{
|
||||
return xattrs_setup.excl.size ?
|
||||
xattrs_matches_mask (kw, &xattrs_setup.excl) : false;
|
||||
}
|
||||
|
||||
/* Check whether the xattr with keyword KW should be discarded from list of
|
||||
attributes that are going to be archived/excluded (set ARCHIVING=true for
|
||||
archiving, false for excluding) */
|
||||
static bool
|
||||
xattrs_masked_out (const char *kw, bool archiving)
|
||||
{
|
||||
return xattrs_kw_included (kw, archiving) ?
|
||||
xattrs_kw_excluded (kw, archiving) : true;
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_xattrs_set (struct tar_stat_info const *st,
|
||||
char const *file_name, char typeflag, int later_run)
|
||||
{
|
||||
if (xattrs_option > 0)
|
||||
{
|
||||
#ifndef HAVE_XATTRS
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("XATTR support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
size_t scan = 0;
|
||||
|
||||
if (!st->xattr_map_size)
|
||||
return;
|
||||
|
||||
for (; scan < st->xattr_map_size; ++scan)
|
||||
{
|
||||
char *keyword = st->xattr_map[scan].xkey;
|
||||
keyword += strlen ("SCHILY.xattr.");
|
||||
|
||||
/* TODO: this 'later_run' workaround is temporary solution -> once
|
||||
capabilities should become fully supported by it's API and there
|
||||
should exist something like xattrs_capabilities_set() call.
|
||||
For a regular files: all extended attributes are restored during
|
||||
the first run except 'security.capability' which is restored in
|
||||
'later_run == 1'. */
|
||||
if (typeflag == REGTYPE
|
||||
&& later_run == !!strcmp (keyword, "security.capability"))
|
||||
continue;
|
||||
|
||||
if (xattrs_masked_out (keyword, false /* extracting */ ))
|
||||
/* we don't want to restore this keyword */
|
||||
continue;
|
||||
|
||||
xattrs__fd_set (st, file_name, typeflag, keyword,
|
||||
st->xattr_map[scan].xval_ptr,
|
||||
st->xattr_map[scan].xval_len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_print_char (struct tar_stat_info const *st, char *output)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (verbose_option < 2)
|
||||
{
|
||||
*output = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (xattrs_option > 0 || selinux_context_option > 0 || acls_option > 0)
|
||||
{
|
||||
/* placeholders */
|
||||
*output = ' ';
|
||||
output[1] = 0;
|
||||
}
|
||||
|
||||
if (xattrs_option > 0 && st->xattr_map_size)
|
||||
for (i = 0; i < st->xattr_map_size; ++i)
|
||||
{
|
||||
char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
|
||||
if (!xattrs_masked_out (keyword, false /* like extracting */ ))
|
||||
{
|
||||
*output = '*';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (selinux_context_option > 0 && st->cntx_name)
|
||||
*output = '.';
|
||||
|
||||
if (acls_option > 0 && (st->acls_a_len || st->acls_d_len))
|
||||
*output = '+';
|
||||
}
|
||||
|
||||
void
|
||||
xattrs_print (struct tar_stat_info const *st)
|
||||
{
|
||||
if (verbose_option < 3)
|
||||
return;
|
||||
|
||||
/* selinux */
|
||||
if (selinux_context_option > 0 && st->cntx_name)
|
||||
fprintf (stdlis, " s: %s\n", st->cntx_name);
|
||||
|
||||
/* acls */
|
||||
if (acls_option > 0 && (st->acls_a_len || st->acls_d_len))
|
||||
{
|
||||
fprintf (stdlis, " a: ");
|
||||
acls_one_line ("", ',', st->acls_a_ptr, st->acls_a_len);
|
||||
acls_one_line ("default:", ',', st->acls_d_ptr, st->acls_d_len);
|
||||
fprintf (stdlis, "\n");
|
||||
}
|
||||
|
||||
/* xattrs */
|
||||
if (xattrs_option > 0 && st->xattr_map_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < st->xattr_map_size; ++i)
|
||||
{
|
||||
char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
|
||||
if (!xattrs_masked_out (keyword, false /* like extracting */ ))
|
||||
fprintf (stdlis, " x: %lu %s\n",
|
||||
(unsigned long) st->xattr_map[i].xval_len, keyword);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user