Compare commits
387 Commits
alpha_1_15
...
origin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
970f999818 | ||
|
|
cd39b5a1b7 | ||
|
|
7f6e6e6a3e | ||
|
|
99e3a2604f | ||
|
|
b4ec8aedf9 | ||
|
|
5354888e40 | ||
|
|
57bfbbde90 | ||
|
|
7b69ee5a24 | ||
|
|
1428b7f176 | ||
|
|
6901594ac4 | ||
|
|
c78356feda | ||
|
|
60c00c18b5 | ||
|
|
c1b55e02b1 | ||
|
|
15abf5c4d9 | ||
|
|
1353511226 | ||
|
|
85c7909497 | ||
|
|
db83069aea | ||
|
|
dbbffde583 | ||
|
|
1d79c6734c | ||
|
|
3af9cc0f15 | ||
|
|
c9a7297a8a | ||
|
|
985637ab5a | ||
|
|
1024343a2b | ||
|
|
1efa1f3b43 | ||
|
|
5f1a4f9f12 | ||
|
|
969d2b986b | ||
|
|
d5f2066cac | ||
|
|
79ce0e6789 | ||
|
|
6a052fd5a3 | ||
|
|
8aa729b90e | ||
|
|
057dd26a60 | ||
|
|
b94eed6d03 | ||
|
|
192860abb8 | ||
|
|
c2d2e806a1 | ||
|
|
2a89f7a0a8 | ||
|
|
71d2a66f42 | ||
|
|
e496c1b529 | ||
|
|
6667fa7fb8 | ||
|
|
a16ad3112e | ||
|
|
7efe3850f6 | ||
|
|
d0694ee604 | ||
|
|
37f0faf1c0 | ||
|
|
b893aee6d2 | ||
|
|
f60d655908 | ||
|
|
549481a0a7 | ||
|
|
e08afc2002 | ||
|
|
338591a486 | ||
|
|
c0e0d06e69 | ||
|
|
6e85425618 | ||
|
|
336519aa4f | ||
|
|
5f4d99491d | ||
|
|
48d83be336 | ||
|
|
60d351cc5a | ||
|
|
e33be3d0a1 | ||
|
|
32562b9412 | ||
|
|
dfd87ba1d0 | ||
|
|
5d4a682a55 | ||
|
|
8e3a2a520d | ||
|
|
745832a280 | ||
|
|
458efab23b | ||
|
|
23dcaa117f | ||
|
|
5099ddf6cc | ||
|
|
8476145508 | ||
|
|
362492fe70 | ||
|
|
7111008659 | ||
|
|
ec4741d732 | ||
|
|
bed7de0271 | ||
|
|
eaaadcfd36 | ||
|
|
a8830fbb86 | ||
|
|
848659f1c6 | ||
|
|
17cbd4862c | ||
|
|
64ded9e702 | ||
|
|
ccd0a527e4 | ||
|
|
3f869877a4 | ||
|
|
8c528937a9 | ||
|
|
460f4ec146 | ||
|
|
eb59c14a1f | ||
|
|
3c4f4ca423 | ||
|
|
506b4db5d0 | ||
|
|
5bfb6c5f9d | ||
|
|
3725b5606f | ||
|
|
d1a7eebc30 | ||
|
|
dfe280dcca | ||
|
|
620a136e74 | ||
|
|
3fb5d67b28 | ||
|
|
c30a794679 | ||
|
|
00bb0d8f5c | ||
|
|
af3e05b6af | ||
|
|
6060d613d1 | ||
|
|
3f12066739 | ||
|
|
3b74fbfc3b | ||
|
|
14d39a2c14 | ||
|
|
7b57922073 | ||
|
|
05c6da4c62 | ||
|
|
4ece30109d | ||
|
|
55f1eadbf2 | ||
|
|
9b22262fc6 | ||
|
|
2de140fa95 | ||
|
|
6f6864df13 | ||
|
|
519a7c0c75 | ||
|
|
1ef212d0fb | ||
|
|
333780b227 | ||
|
|
2c56ca0e7f | ||
|
|
63f8de655b | ||
|
|
2743e1ba5b | ||
|
|
40ece6bf4d | ||
|
|
63e835f5c0 | ||
|
|
efe6609cd9 | ||
|
|
b0d5935cb0 | ||
|
|
a1b1b7cc8a | ||
|
|
8940247418 | ||
|
|
0dacafbbb0 | ||
|
|
e3e50c987b | ||
|
|
923f0cda43 | ||
|
|
c485b7984d | ||
|
|
d769b724f4 | ||
|
|
a0eb52da3f | ||
|
|
87ac3207fb | ||
|
|
c634f2c6f1 | ||
|
|
5416153391 | ||
|
|
5bb69a88d8 | ||
|
|
0a848ff669 | ||
|
|
7c0b81cbb9 | ||
|
|
862770bf91 | ||
|
|
89d682d0b9 | ||
|
|
764174dc1d | ||
|
|
5ab30f709a | ||
|
|
e2b8c8fa9f | ||
|
|
42250f5010 | ||
|
|
62571aa7c3 | ||
|
|
32f7047037 | ||
|
|
a69be0adce | ||
|
|
1fb35e7374 | ||
|
|
7e69b14775 | ||
|
|
625c45d304 | ||
|
|
3fe0f0d7f8 | ||
|
|
c3d4fee823 | ||
|
|
a0fb51e136 | ||
|
|
ac8690fc4e | ||
|
|
395df04927 | ||
|
|
89a91c7b44 | ||
|
|
5635a428ab | ||
|
|
8b5f10a6c4 | ||
|
|
6e98015774 | ||
|
|
bd13e18a63 | ||
|
|
01cf5c5315 | ||
|
|
0dd814fac2 | ||
|
|
b27b516b68 | ||
|
|
c7f69c265b | ||
|
|
bc00f45420 | ||
|
|
57304e8b0a | ||
|
|
d3f04456e8 | ||
|
|
d78083e82c | ||
|
|
c8d4ceccc1 | ||
|
|
6287d3045f | ||
|
|
9d3142805b | ||
|
|
05eddc1a58 | ||
|
|
78bfbb5661 | ||
|
|
fe576585e6 | ||
|
|
080a6b2ac5 | ||
|
|
f236f33643 | ||
|
|
a4ffcfb875 | ||
|
|
967fcb9318 | ||
|
|
12b3a5d5b1 | ||
|
|
eeb610da48 | ||
|
|
749e20e6fa | ||
|
|
56f6556f94 | ||
|
|
43c5343194 | ||
|
|
250db35f17 | ||
|
|
6f929b2c89 | ||
|
|
64cddf2fbc | ||
|
|
ccdbafb276 | ||
|
|
bd222d606a | ||
|
|
94fb06f5db | ||
|
|
74d217db74 | ||
|
|
17ef61b2fd | ||
|
|
f32828d577 | ||
|
|
e67e085421 | ||
|
|
ca856c2585 | ||
|
|
18641602c1 | ||
|
|
8bdbc08a89 | ||
|
|
a5d5cc599f | ||
|
|
761895d43c | ||
|
|
5d4f057e31 | ||
|
|
7c0ba663c8 | ||
|
|
51118be241 | ||
|
|
69f5d77383 | ||
|
|
d989864712 | ||
|
|
983d328ff2 | ||
|
|
586c684815 | ||
|
|
bbf7dec45e | ||
|
|
40f79286ab | ||
|
|
ebc522d521 | ||
|
|
ad85f632c6 | ||
|
|
062b37115f | ||
|
|
6261c58ae8 | ||
|
|
427bda01a3 | ||
|
|
1d26fff0f3 | ||
|
|
bb6b92e37d | ||
|
|
8ca4064a8c | ||
|
|
5c890a6003 | ||
|
|
3705fd6452 | ||
|
|
bde442ba15 | ||
|
|
c9a8f1bc33 | ||
|
|
66e9b9cd6c | ||
|
|
b9588c4722 | ||
|
|
9a41b3b3db | ||
|
|
990e7d4437 | ||
|
|
173d3229e3 | ||
|
|
2d261da8f9 | ||
|
|
99527fa17b | ||
|
|
868ee74028 | ||
|
|
8c90bf0414 | ||
|
|
892cdea8a1 | ||
|
|
00763876f1 | ||
|
|
1a1cfaafa6 | ||
|
|
445d95be07 | ||
|
|
6fe55234c9 | ||
|
|
e24d8574a8 | ||
|
|
4da5205ed6 | ||
|
|
8241687465 | ||
|
|
8e3f3adf98 | ||
|
|
e5ef01710a | ||
|
|
e70e63612a | ||
|
|
28b26242c7 | ||
|
|
6b279a6f8c | ||
|
|
079f2d6807 | ||
|
|
b09417ca8d | ||
|
|
b15e3f1bbd | ||
|
|
1616b1d1b4 | ||
|
|
f23bc997fd | ||
|
|
8ec119a27f | ||
|
|
e35d05b1d2 | ||
|
|
cdb77dcd7b | ||
|
|
9bf87b195e | ||
|
|
643e3f2441 | ||
|
|
6e75833cb7 | ||
|
|
908d78d208 | ||
|
|
192f55e2a0 | ||
|
|
9d99fd13cd | ||
|
|
07902e9f9a | ||
|
|
0c94a109b9 | ||
|
|
27094c4fc3 | ||
|
|
5aca761e1b | ||
|
|
cc82db7f2d | ||
|
|
137ebf41fd | ||
|
|
49ea4c5057 | ||
|
|
409bddf38c | ||
|
|
c930802f31 | ||
|
|
ca14885884 | ||
|
|
01d6188297 | ||
|
|
759c5208c5 | ||
|
|
8457e06b99 | ||
|
|
8719c4f680 | ||
|
|
574022ab78 | ||
|
|
304d8b9f0c | ||
|
|
6712656eb2 | ||
|
|
415d9c9e15 | ||
|
|
1a8141ab8a | ||
|
|
023c766600 | ||
|
|
fdb46aa2e2 | ||
|
|
2504e7d3ae | ||
|
|
b0765e257c | ||
|
|
73d4c40a87 | ||
|
|
7aed52718f | ||
|
|
f572ca0cfb | ||
|
|
29236a68fa | ||
|
|
a4b1564d4a | ||
|
|
94d0385a57 | ||
|
|
603c1d60a6 | ||
|
|
29e9004b69 | ||
|
|
8da152d2b3 | ||
|
|
00746182f3 | ||
|
|
6c8815909d | ||
|
|
fde336b21a | ||
|
|
394b12d950 | ||
|
|
372638ae7a | ||
|
|
c455373e5b | ||
|
|
f2541c66cd | ||
|
|
7e6d54d0c0 | ||
|
|
876e554157 | ||
|
|
1118d24fd3 | ||
|
|
dc6f7ebf20 | ||
|
|
1102eeef1f | ||
|
|
e8a4c35a73 | ||
|
|
e359fad641 | ||
|
|
f5504a3bae | ||
|
|
341be8f405 | ||
|
|
4f2a22f306 | ||
|
|
a76ab340dd | ||
|
|
3ad3ca8734 | ||
|
|
82b2829e10 | ||
|
|
f852428d5f | ||
|
|
86e91a5bfc | ||
|
|
ec5743a628 | ||
|
|
bf7f4fdc1e | ||
|
|
98b9522499 | ||
|
|
6398dbe1a5 | ||
|
|
37724f5e20 | ||
|
|
c8c351684c | ||
|
|
01b6fb98bf | ||
|
|
f1309bffbf | ||
|
|
c732eb584e | ||
|
|
0680ad4d42 | ||
|
|
1942370acd | ||
|
|
94de7c4c77 | ||
|
|
05805868f2 | ||
|
|
57aa98047e | ||
|
|
7573967406 | ||
|
|
ab8711413c | ||
|
|
9fd9a0913d | ||
|
|
f4e4adea80 | ||
|
|
7110641821 | ||
|
|
fce454b5ca | ||
|
|
8ad985ea6c | ||
|
|
37edfd9e8f | ||
|
|
016f7c87a7 | ||
|
|
52b8bea074 | ||
|
|
5addfdcb03 | ||
|
|
e707b47aba | ||
|
|
76dc519f9f | ||
|
|
2a00376816 | ||
|
|
9766528b07 | ||
|
|
f26a90783b | ||
|
|
36fe16aaf5 | ||
|
|
89f1667fdb | ||
|
|
f2d65dda39 | ||
|
|
8370746251 | ||
|
|
2614af6d3c | ||
|
|
614def3113 | ||
|
|
b6365e9b03 | ||
|
|
bf789e3642 | ||
|
|
1421ee630d | ||
|
|
9869d0ae17 | ||
|
|
edc0b12c5e | ||
|
|
808cafa454 | ||
|
|
d1dedae402 | ||
|
|
de754902da | ||
|
|
bc7f4ad027 | ||
|
|
55abc110f5 | ||
|
|
4d753fced1 | ||
|
|
85a4e0fdeb | ||
|
|
583415c2c1 | ||
|
|
6488588c5f | ||
|
|
ac40b1e6f6 | ||
|
|
4bf5f6dca4 | ||
|
|
ecaff7cbba | ||
|
|
ea9e2d8d8e | ||
|
|
39e5d9182c | ||
|
|
c7aa519f09 | ||
|
|
bf5ba3dbef | ||
|
|
ea368b6d1b | ||
|
|
d0201294c0 | ||
|
|
c5b15c4ac1 | ||
|
|
4b3dd17c00 | ||
|
|
d339cc38af | ||
|
|
796a69787e | ||
|
|
4c54e234c1 | ||
|
|
c027e03924 | ||
|
|
6d615f12d4 | ||
|
|
8f970d2c1e | ||
|
|
d04af8f714 | ||
|
|
e2ecb82711 | ||
|
|
8e2e731733 | ||
|
|
19a63e523d | ||
|
|
5679d3020e | ||
|
|
1001c1b326 | ||
|
|
090d1d36ae | ||
|
|
2e1f904f2c | ||
|
|
6a0b5421b9 | ||
|
|
9c764b14a9 | ||
|
|
ae67839879 | ||
|
|
9588a106a7 | ||
|
|
b3627f3f07 | ||
|
|
ca7df3fe6b | ||
|
|
ab19642053 | ||
|
|
a71b154289 | ||
|
|
ceaef10443 | ||
|
|
5da6733724 | ||
|
|
8d6c177ecb | ||
|
|
1ecd6672e1 | ||
|
|
ca2f855c90 | ||
|
|
693134a4e7 | ||
|
|
90cec95580 | ||
|
|
b6fcb4ba8f | ||
|
|
6d1e9ab67e | ||
|
|
300210aa15 |
@@ -3,7 +3,6 @@
|
||||
*.tar
|
||||
.bootstrap
|
||||
ABOUT-NLS
|
||||
COPYING
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -13,5 +12,7 @@ build-aux
|
||||
config.*
|
||||
configure
|
||||
gnulib
|
||||
m4
|
||||
rmt
|
||||
stamp-h1
|
||||
tar-[0-9]*
|
||||
|
||||
41
AUTHORS
41
AUTHORS
@@ -1,34 +1,15 @@
|
||||
Authors of GNU tar.
|
||||
|
||||
The following contributions warranted legal paper exchanges with the
|
||||
Free Software Foundation. Also see files ChangeLog and THANKS.
|
||||
Public domain tar was written by John Gilmore, with contributions from
|
||||
Henry Spencer, Fred Fish, Ian Darwin, Geoff Collyer, Stan Barber, Guy
|
||||
Harris, Dave Brower, Richard Todd, Michael Rendell, Stu Heiss, and
|
||||
Rich Salz.
|
||||
|
||||
TAR Sergey Poznyakoff 2003-10
|
||||
Assigns his past and future changes.
|
||||
The FSF version, named GNU tar, was derived from public domain tar by
|
||||
Jay Fenlason and Joy Kendall. Amy Gorin and Melissa Weisshaus
|
||||
contributed to the manual. GNU tar has been maintained in turn by
|
||||
Thomas Bushnell BSG, François Pinard, Paul Eggert, and Sergey
|
||||
Poznyakoff.
|
||||
|
||||
TAR Paul Eggert 2000-10
|
||||
Assigns his past and future changes.
|
||||
|
||||
TAR Jay Fenlason
|
||||
Assigns his changes.
|
||||
|
||||
TAR Richard E Salz 1993-03-11
|
||||
Disclaims changes to getdate.y.
|
||||
|
||||
TAR MANUAL (?) Amy Gorin (US 1963) 1995-01-10
|
||||
Assigns the Tar Manual.
|
||||
|
||||
TAR Francois Pinard Canada 1949 1996-02-01
|
||||
Assigns past and future changes.
|
||||
|
||||
TAR Melissa Weisshaus US 1966 1997-04-09
|
||||
Assigns changes to the manual and future changes.
|
||||
melissa@gnu.ai.mit.edu
|
||||
|
||||
TAR Thomas Michael Innis Bushnell US 1967 1997-04-09
|
||||
Assigns changes.
|
||||
thomas@gnu.ai.mit.edu
|
||||
|
||||
TAR Thomas Michael Innis Bushnell US 1967 1997-04-09
|
||||
Assigns changes to manual.
|
||||
thomas@gnu.ai.mit.edu
|
||||
Many others have contributed to GNU tar; please see the files THANKS
|
||||
and ChangeLog.
|
||||
|
||||
676
COPYING
Normal file
676
COPYING
Normal file
@@ -0,0 +1,676 @@
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
11
Makefile.am
11
Makefile.am
@@ -1,11 +1,11 @@
|
||||
# Main Makefile for GNU tar.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2007 Free
|
||||
# Software Foundation, Inc.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## the Free Software Foundation; either version 3, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
@@ -22,3 +22,10 @@ ACLOCAL_AMFLAGS = -I m4
|
||||
EXTRA_DIST = ChangeLog.1 PORTS
|
||||
SUBDIRS = doc lib rmt src scripts po tests
|
||||
|
||||
dist-hook:
|
||||
-rm -f $(distdir).cpio
|
||||
find $(distdir) | cpio -Hcrc -o | \
|
||||
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
|
||||
|
||||
distclean-local:
|
||||
-rm -f $(distdir).cpio.gz
|
||||
|
||||
268
NEWS
268
NEWS
@@ -1,7 +1,245 @@
|
||||
GNU tar NEWS - User visible changes.
|
||||
GNU tar NEWS - User visible changes. 2008-12-27
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
version 1.15.91 - Sergey Poznyakoff, (CVS version)
|
||||
version 1.21 - Sergey Poznyakoff, 2008-12-27
|
||||
|
||||
* New short option -J
|
||||
|
||||
A shortcut for --lzma.
|
||||
|
||||
* New option --lzop
|
||||
|
||||
* New option --no-auto-compress
|
||||
|
||||
Cancels the effect of previous --auto-compress (-a) option.
|
||||
|
||||
* New option --no-null
|
||||
|
||||
Cancels the effect of previous --null option.
|
||||
|
||||
* Compressed format recognition
|
||||
|
||||
If tar is unable to determine archive compression format, it falls
|
||||
back to using archive suffix to determine it.
|
||||
|
||||
* VCS support.
|
||||
|
||||
Using --exclude-vcs handles also files used internally by Bazaar,
|
||||
Mercurial and Darcs.
|
||||
|
||||
* Transformation scope flags
|
||||
|
||||
Name transformation expressions understand additional flags that
|
||||
control type of archive members affected by them. The flags are:
|
||||
|
||||
- r
|
||||
Apply transformation to regular archive members.
|
||||
|
||||
- s
|
||||
Apply transformation to symbolic link targets.
|
||||
|
||||
- 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.''
|
||||
|
||||
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
|
||||
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.:
|
||||
|
||||
tar --transform 'flags=S;s|^|/usr/local/|S'
|
||||
|
||||
* Bugfixes
|
||||
|
||||
** 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.
|
||||
|
||||
|
||||
|
||||
version 1.20 - Sergey Poznyakoff, 2008-04-14
|
||||
|
||||
* New option --auto-compress (-a)
|
||||
|
||||
With --create, selects compression algorithm basing on the suffix
|
||||
of the archive file name.
|
||||
|
||||
* New option --lzma
|
||||
|
||||
Selects LZMA compression algorithm
|
||||
|
||||
* New option --hard-dereference
|
||||
|
||||
During archive creation, dereferences hard links and stores the files
|
||||
they refer to, instead of creating usual hard link members (type '1').
|
||||
|
||||
* New option --checkpoint-action
|
||||
|
||||
This action allows to specify an action to be executed upon hitting a
|
||||
checkpoint. Recognized actions are: dot, echo (the default),
|
||||
echo=string, ttyout=string, exec=cmdline, and sleep=value. Any number
|
||||
of `--checkpoint-action' options can be specified, the actions will be
|
||||
executed in order of their appearance in the command line. See
|
||||
chapter 3.8 "Checkpoints" for a complete description.
|
||||
|
||||
* New options --no-check-device, --check-device.
|
||||
|
||||
The `--no-check-device' option disables comparing device numbers during
|
||||
preparatory stage of an incremental dump. This allows to avoid
|
||||
creating full dumps if the device numbers change (e.g. when using an
|
||||
LVM snapshot).
|
||||
|
||||
The `--check-device' option enables comparing device numbers. This is
|
||||
the default. This option is provided to undo the effect of the previous
|
||||
`--no-check-device' option, e.g. if it was set in TAR_OPTIONS
|
||||
environment variable.
|
||||
|
||||
* The --transform option.
|
||||
|
||||
Any number of `--transform' options can be given in the command line.
|
||||
The specified transformations will be applied in turn.
|
||||
|
||||
The argument to `--transform' option can be a list of replace
|
||||
expressions, separated by a semicolon (as in `sed').
|
||||
|
||||
Filename transformations are applied to symbolic link targets
|
||||
during both creation and extraction. Tar 1.19 used them only
|
||||
during extraction.
|
||||
|
||||
For a detailed description, see chapter 6.7 "Modifying File and Member
|
||||
Names".
|
||||
|
||||
* Info (end-of-volume) scripts
|
||||
|
||||
The value of the blocking factor is made available to info and
|
||||
checkpoint scripts via environment variable TAR_BLOCKING_FACTOR.
|
||||
|
||||
* Incremental archives
|
||||
|
||||
Improved (sped up) extracting from incremental archives.
|
||||
|
||||
* Bugfixes.
|
||||
** Fix bug introduced in version 1.19: tar refused to update non-existing
|
||||
archives.
|
||||
|
||||
|
||||
version 1.19 - Sergey Poznyakoff, 2007-10-10
|
||||
|
||||
* New option --exclude-vcs
|
||||
|
||||
Excludes directories and files, created by several widely used version
|
||||
control systems, e.g. "CVS/", ".svn/", etc.
|
||||
|
||||
* --exclude-tag and --exclude-cache options
|
||||
|
||||
The following options now work with incremental archives as well:
|
||||
|
||||
--exclude-caches
|
||||
--exclude-caches-all
|
||||
--exclude-tag
|
||||
--exclude-tag-all
|
||||
--exclude-tag-under
|
||||
|
||||
* Fix handling of renamed files in listed incremental archives.
|
||||
|
||||
Previous versions always stored absolute file names in rename
|
||||
records, even if -P was not used. This is fixed: rename records
|
||||
contain file names processed in accordance with the command line
|
||||
settings.
|
||||
|
||||
* Fix --version output.
|
||||
|
||||
* Recognition of broken archives.
|
||||
|
||||
When supplied an archive smaller than 512 bytes in reading mode (-x,
|
||||
-t), the previous version of tar silently ignored it, exiting with
|
||||
code 0. It is fixed. Tar now issues the following diagnostic message:
|
||||
'This does not look like a tar archive', and exits with code 2.
|
||||
|
||||
* Fix double-dot recognition in archive member names in case of duplicate '/.'.
|
||||
|
||||
* Fix file padding in case of truncation of the input file to zero size.
|
||||
|
||||
|
||||
version 1.18 - Sergey Poznyakoff, 2007-06-29
|
||||
|
||||
* Licensed under the GPLv3
|
||||
|
||||
* Fixed several bugs in the testsuite
|
||||
|
||||
|
||||
version 1.17 - Sergey Poznyakoff, 2007-06-08
|
||||
|
||||
* Fix archivation of sparse files in posix mode. Previous versions padded
|
||||
sparse members with spurious zero blocks.
|
||||
|
||||
* Fix operation of --verify --listed-incremental. Version 1.16.1 produced
|
||||
a full dump when both options were given.
|
||||
|
||||
* Fix --occurrence. In previous versions it continued scanning the archive
|
||||
even though all requested members has already been extracted.
|
||||
|
||||
* Scope of --transform and --strip-components options.
|
||||
|
||||
In addition to affecting regular archive members, the --transform
|
||||
option affects hard and soft link targets and the --strip-components
|
||||
option affects hard link targets as well.
|
||||
|
||||
* End-of-volume script can send the new volume name to tar by writing
|
||||
it to the file descriptor stored in the environment variable `TAR_FD'.
|
||||
|
||||
|
||||
version 1.16.1 - Sergey Poznyakoff, 2006-12-09
|
||||
|
||||
* New option --exclude-tag allows to specify "exclusion tag files", i.e.
|
||||
files whose presence in a directory means that the directory should not
|
||||
be archived.
|
||||
|
||||
* The --exclude-cache option excludes directories that contain the
|
||||
CACHEDIR.TAG file from being archived. Previous versions excluded
|
||||
directory contents only, while the directories themselves were
|
||||
still added to the archive.
|
||||
|
||||
* Support for reading ustar type 'N' header logical records has been removed.
|
||||
This GNU extension was generated only by very old versions of GNU 'tar'.
|
||||
Unfortunately its implementation had security holes; see
|
||||
<http://archives.neohapsis.com/archives/fulldisclosure/2006-11/0344.html>.
|
||||
We don't expect that any tar archives in practical use have type 'N'
|
||||
records, but if you have one and you trust its contents, you can
|
||||
decode it with GNU tar 1.16 or earlier.
|
||||
|
||||
* Race conditions have been fixed that in some cases briefly allowed
|
||||
files extracted by 'tar -x --same-owner' (or plain 'tar -x', when
|
||||
running as root) to be accessed by users that they shouldn't have been.
|
||||
|
||||
|
||||
version 1.16 - Sergey Poznyakoff, 2006-10-21
|
||||
|
||||
* After creating an archive, tar exits with code 1 if some files were
|
||||
changed while being read. Previous versions exited with code 2 (fatal
|
||||
error), and only if some files were truncated while being archived.
|
||||
|
||||
* New option --mtime allows to set modification times for all archive
|
||||
members during creation.
|
||||
|
||||
* Bug fixes
|
||||
** Avoid running off file descriptors when using multiple -C options.
|
||||
** tar --index-file=FILE --file=- sent the archive to FILE, and
|
||||
the listing to stderr.
|
||||
|
||||
|
||||
version 1.15.91 - Sergey Poznyakoff, 2006-06-16
|
||||
|
||||
* Incompatible changes
|
||||
|
||||
@@ -19,14 +257,14 @@ no longer uses globbing by default. For example, the above invocation
|
||||
is now interpreted as a request to extract from the archive the file
|
||||
named '*.c'.
|
||||
|
||||
To treat member names as globbing patterns, use --wildcards option.
|
||||
To treat member names as globbing patterns, use --wildcards option.
|
||||
If you wish tar to mimic the behavior of versions up to 1.15.90,
|
||||
add --wildcards to the value of the environment variable TAR_OPTIONS.
|
||||
|
||||
The exact way in which tar interprets member names is controlled by the
|
||||
following command line options:
|
||||
|
||||
--wildcards use wildcards
|
||||
--wildcards use wildcards
|
||||
--anchored patterns match file name start
|
||||
--ignore-case ignore case
|
||||
--wildcards-match-slash wildcards match `/'
|
||||
@@ -34,7 +272,7 @@ following command line options:
|
||||
Each of these options has a '--no-' counterpart that disables its
|
||||
effect (e.g. --no-wildcards).
|
||||
|
||||
These options affect both the interpretation of member names from
|
||||
These options affect both the interpretation of member names from
|
||||
command line and that of the exclusion patterns (given with --exclude
|
||||
and --exclude-from options). The defaults are:
|
||||
|
||||
@@ -50,7 +288,7 @@ case-sensitive matching for the rest of command line, one could write:
|
||||
|
||||
** Short option -l is now an alias of --check-links option, which complies
|
||||
with UNIX98. This ends the transition period started with version 1.14.
|
||||
|
||||
|
||||
* New features
|
||||
|
||||
** New option --transform allows to transform file names before storing them
|
||||
@@ -65,19 +303,19 @@ will add 'prefix/' to all file names stored in foo.tar.
|
||||
versions it worked only with --extract.
|
||||
|
||||
** New option --show-transformed-names enables display of transformed file
|
||||
or archive. It generalizes --show-stored-names option, introduced in
|
||||
1.15.90. In particular, when creating an archive in verbose mode, it lists
|
||||
or archive. It generalizes --show-stored-names option, introduced in
|
||||
1.15.90. In particular, when creating an archive in verbose mode, it lists
|
||||
member names as stored in the archive, i.e., with any eventual prefixes
|
||||
removed and file name transformations applied. The option is useful,
|
||||
for example, while comparing `tar cv' and `tar tv' outputs.
|
||||
|
||||
** New incremental snapshot file format keeps information about file names
|
||||
** New incremental snapshot file format keeps information about file names
|
||||
as well as that about directories.
|
||||
|
||||
** The --checkpoint option takes an optional argument specifying the number
|
||||
of records between the two successive checkpoints. Optional dot
|
||||
starting the argument intructs tar to print dots instead of textual
|
||||
checkpoints.
|
||||
checkpoints.
|
||||
|
||||
** The --totals option can be used with any tar operation (previous versions
|
||||
understood it only with --create). If an argument to this option is
|
||||
@@ -169,7 +407,7 @@ Consequently, the file pointer was set off and the next member
|
||||
was not processed correctly.
|
||||
** Previous version created invalid archives when files shrink
|
||||
during reading.
|
||||
** Compare mode (tar d) hanged when trying to compare file contents.
|
||||
** Compare mode (tar d) hung when trying to compare file contents.
|
||||
** Previous versions in certain cases failed to restore directory
|
||||
modification times.
|
||||
** When creating an archive, do not attempt to store files whose
|
||||
@@ -826,13 +1064,13 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
|
||||
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
@@ -848,4 +1086,8 @@ Boston, MA 02110-1301, USA.
|
||||
Local variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
time-stamp-start: "changes. "
|
||||
time-stamp-format: "%:y-%02m-%02d"
|
||||
time-stamp-end: "\n"
|
||||
end:
|
||||
|
||||
6
PORTS
6
PORTS
@@ -145,13 +145,13 @@ See the end of file for copying conditions.
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 1999, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2001, 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
@@ -170,4 +170,4 @@ mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
|
||||
|
||||
6
README
6
README
@@ -78,7 +78,7 @@ scripts.
|
||||
|
||||
** `--disable-largefile' omits support for large files, even if the
|
||||
operating system supports large files. Typically, large files are
|
||||
those larger on 2 GB on a 32-bit host.
|
||||
those larger than 2 GB on a 32-bit host.
|
||||
|
||||
* Installation hints
|
||||
|
||||
@@ -223,13 +223,13 @@ and share your findings by writing to <bug-tar@gnu.org>.
|
||||
* Copying
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1994, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
2001, 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -14,6 +14,7 @@ that you have the latest stable version.
|
||||
- Gettext <http://www.gnu.org/software/gettext/>
|
||||
- Gzip <http://www.gnu.org/software/gzip/>
|
||||
- M4 <http://www.gnu.org/software/m4/>
|
||||
- Texinfo <http://www.gnu.org/software/texinfo>
|
||||
- Wget <http://www.gnu.org/software/wget/>
|
||||
|
||||
As of this writing, the latest stable version of Gzip is 1.2.4 but we
|
||||
@@ -61,13 +62,13 @@ some other value.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
|
||||
70
README-cvs
Normal file
70
README-cvs
Normal file
@@ -0,0 +1,70 @@
|
||||
-*- outline -*-
|
||||
|
||||
These notes intend to help people working on the CVS version of
|
||||
this package.
|
||||
|
||||
* Requirements
|
||||
|
||||
Only the sources are installed in the CVS repository (to ease the
|
||||
maintenance, merges etc.), therefore you will have to get the latest
|
||||
stable versions of the maintainer tools we depend upon, including:
|
||||
|
||||
- Automake <http://www.gnu.org/software/automake/>
|
||||
- Autoconf <http://www.gnu.org/software/autoconf/>
|
||||
- Bison <http://www.gnu.org/software/bison/>
|
||||
- Gettext <http://www.gnu.org/software/gettext/>
|
||||
- Gzip <http://www.gnu.org/software/gzip/>
|
||||
- Tar <http://www.gnu.org/software/tar/>
|
||||
- Wget <http://www.gnu.org/software/wget/>
|
||||
|
||||
As of this writing, the latest stable version of Gzip is 1.2.4 but we
|
||||
suggest using test version 1.3.5 (or later, if one becomes available).
|
||||
|
||||
Valgrind <http://valgrind.org/> is also highly recommended, if
|
||||
Valgrind supports your architecture.
|
||||
|
||||
Only building the initial full source tree will be a bit painful,
|
||||
later, a plain `cvs update -P && make' should be sufficient.
|
||||
|
||||
* First CVS checkout
|
||||
|
||||
Obviously, if you are reading these notes, you did manage to check out
|
||||
this package from CVS. The next step is to get other files needed to
|
||||
build, which are extracted from other source packages:
|
||||
|
||||
$ ./bootstrap
|
||||
|
||||
And there you are! Just
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
|
||||
At this point, there should be no difference between your local copy,
|
||||
and the CVS master copy:
|
||||
|
||||
$ cvs diff
|
||||
|
||||
should output no difference.
|
||||
|
||||
Enjoy!
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA.
|
||||
20
THANKS
20
THANKS
@@ -1,11 +1,6 @@
|
||||
GNU tar THANKS file
|
||||
|
||||
Public domain tar was written by John Gilmore, with contributions
|
||||
from Henry Spencer, Fred Fish, Ian Darwin, Geoff Collyer, Stan Barber,
|
||||
Guy Harris, Dave Brower, Richard Todd, Michael Rendell, Stu Heiss and
|
||||
Rich $alz. The FSF version, named GNU tar, was derived from PDTAR by
|
||||
Jay Fenlason and Joy Kendall, and was maintained in turn by François
|
||||
Pinard, Paul Eggert and Sergey Poznyakoff.
|
||||
Please see the AUTHORS file for the list of principal authors.
|
||||
|
||||
Many people further contributed to GNU tar by reporting problems,
|
||||
suggesting various improvements or submitting actual code. Here is a
|
||||
@@ -107,9 +102,11 @@ Clinton Carr clint@netcom.com
|
||||
Conrad Hughes chughes@maths.tcd.ie
|
||||
Constantin Belous const@cris.net
|
||||
Coranth Gryphon gryphon@bur.visidyne.com
|
||||
Cyril Strejc strejc@unicontrols.cz
|
||||
Dale R. Worley worley@world.std.com
|
||||
Dale Wiles wiles@geordi.calspan.com
|
||||
Dan Bloch dan@transarc.com
|
||||
Dan Drake dan@dandrake.org
|
||||
Dan Reish dreish@izzy.net
|
||||
Daniel Hagerty hag@gnu.org
|
||||
Daniel Quinlan quinlan@pathname.com
|
||||
@@ -150,12 +147,14 @@ Drew Sullivan drew@sni.ca
|
||||
Drew Trieger trieger@woodstock.abbott.com
|
||||
Dunstan Vavasour dev@cegelecproj.co.uk
|
||||
Ed Childs echilds@bgs.com
|
||||
Ed Leaver ewleaver@comcast.net
|
||||
Edgar Taube et@immd8.informatik.uni-erlangen.de
|
||||
Eduardo Kortright eduardo@cs.ua.edu
|
||||
Eduardo V. de Rivas eddie@asterion.com
|
||||
Edward Welbourne eddy@gen.cam.ac.uk
|
||||
Elmar Heeb heeb@itp.ethz.ch
|
||||
Elmer Fittery elmerf@ptw.com
|
||||
Enric Hernandez ehernandez@notariado.org
|
||||
Eric Backus ericb@lsid.hp.com
|
||||
Eric Benson eb@amazon.com
|
||||
Eric Blake ebb9@byu.net
|
||||
@@ -222,10 +221,12 @@ Janne Snabb snabb@niksula.hut.fi
|
||||
Jason R. Mastaler jason@webmaster.net
|
||||
Jason Armistead Jason.Armistead@otis.com
|
||||
Jay Fenlason hack@gnu.org
|
||||
Jean-Louis Martineau martineau@zmanda.com
|
||||
Jean-Michel Soenen soenen@lectra.fr
|
||||
Jean-Ph. Martin-Flatin syj@ecmwf.int
|
||||
Jean-loup Gailly jloup@chorus.fr
|
||||
Jean-Loup Gailly jloup@chorus.fr
|
||||
Jeff Moskow jeff@rtr.com
|
||||
Jean-Ph. Martin-Flatin syj@ecmwf.int
|
||||
Jean-Pierre Demailly Jean-Pierre.Demailly@ujf-grenoble.fr
|
||||
Jeff Prothero jsp@betz.biostr.washington.edu
|
||||
Jeff Siegel js@hornet.att.com
|
||||
Jeff Sorensen sorenj@alumni.rpi.edu
|
||||
@@ -269,6 +270,7 @@ Jurgen Botz jbotz@orixa.mtholyoke.edu
|
||||
Jyh-Shyang Wang erik@vsp.ee.nctu.edu.tw
|
||||
Jörg Schilling schilling@fokus.fraunhofer.de
|
||||
Jörg Weule weule@cs.uni-duesseldorf.de
|
||||
Jörg Weilbier gnu@weilbier.net
|
||||
Jörgen Hågg Jorgen.Hagg@axis.se
|
||||
Jörgen Weigert jw@suse.de
|
||||
Jürgen Lüters jlueters@t-online.de
|
||||
@@ -294,6 +296,7 @@ Konno Hiroharu konno@pac.co.jp
|
||||
Kurt Jaeger pi@lf.net
|
||||
Larry Creech lcreech@lonestar.rcclub.org
|
||||
Larry Schwimmer rosebud@cyclone.stanford.edu
|
||||
Lasse Collin lasse.collin@tukaani.org
|
||||
Laurent Caillat-Vallet caillat@noe.lyon.cemagref.fr
|
||||
Laurent Sainte-Marthe smarthe@genethon.fr
|
||||
Leland Lucius llucius@tiny.net
|
||||
@@ -391,6 +394,7 @@ Pierce Cantrell cantrell@ee.tamu.edu
|
||||
R. Kent Dybvig dyb@cadence.bloomington.in.us
|
||||
R. Scott Butler butler@prism.es.dupont.com
|
||||
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
|
||||
Ralf Wildenhues Ralf.Wildenhues@gmx.de
|
||||
Ralf S. Engelschall rse@engelschall.com
|
||||
Ralf Suckow suckow@contrib.de
|
||||
Ralph Corderoy ralph@inputplus.co.uk
|
||||
|
||||
10
TODO
10
TODO
@@ -1,5 +1,7 @@
|
||||
Suggestions for improving GNU tar.
|
||||
|
||||
* <45BEC0DB.8040903@unix-beratung.de>
|
||||
|
||||
* Incorporate fixes from major distributions, e.g., Debian GNU/Linux.
|
||||
|
||||
* Add support for restoring file time stamps to sub-second resolution,
|
||||
@@ -10,10 +12,6 @@ Suggestions for improving GNU tar.
|
||||
|
||||
* --append should bail out if the two archives are of different types.
|
||||
|
||||
* Add support for GNU private keywords in POSIX 1003.1-2001 headers,
|
||||
so that the GNU extensions (--incremental, --label and
|
||||
--multi-volume) may be used with POSIX archives.
|
||||
|
||||
* Add support for a 'pax' command that conforms to POSIX 1003.1-2001.
|
||||
This would unify paxutils with tar.
|
||||
|
||||
@@ -47,13 +45,13 @@ so that the GNU extensions (--incremental, --label and
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful,
|
||||
|
||||
732
bootstrap
732
bootstrap
@@ -1,12 +1,12 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Bootstrap 'tar' from CVS.
|
||||
# Bootstrap this package from CVS.
|
||||
|
||||
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -21,174 +21,298 @@
|
||||
|
||||
# Written by Paul Eggert and Sergey Poznyakoff.
|
||||
|
||||
# URL of our text domain page in Translation Project
|
||||
TP_URL="http://www.iro.umontreal.ca/translation/maint/tar/"
|
||||
nl='
|
||||
'
|
||||
|
||||
# Ensure file names are sorted consistently across platforms;
|
||||
# e.g., m4/ulonglong_gl.m4 should follow m4/ulonglong.m4.
|
||||
# Ensure file names are sorted consistently across platforms.
|
||||
# Also, ensure diagnostics are in English, e.g., "wget --help" below.
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: $0 [--gnulib-srcdir=DIR][--paxutils-srcdir=DIR][--cvs-auth=AUTH-METHOD][--cvs-user=USERNAME][--no-po]
|
||||
Options are:
|
||||
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
|
||||
sources reside. Use this if you already
|
||||
have paxutils sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
|
||||
sources reside. Use this if you already
|
||||
have gnulib sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
--cvs-auth=METHOD Set the CVS access method used for downloading
|
||||
gnulib files. METHOD is one of the keywords
|
||||
accepted by cvs -d option (see info cvs
|
||||
repository).
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the gnulib repository.
|
||||
--no-po Do not download po files.
|
||||
--update-po[=LANG] Update po file(s) and exit.
|
||||
echo >&2 "\
|
||||
Usage: $0 [OPTION]...
|
||||
Bootstrap this package from the checked-out sources.
|
||||
|
||||
If the file \`.bootstrap' exists in the current working directory, its
|
||||
contents is read, comments and empty lines removed, shell variables expanded
|
||||
and the result is prepended to the command line options.
|
||||
Options:
|
||||
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
|
||||
sources reside. Use this if you already
|
||||
have paxutils sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
|
||||
sources reside. Use this if you already
|
||||
have gnulib sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
--copy Copy files instead of creating symbolic links.
|
||||
--force Attempt to bootstrap even if the sources seem
|
||||
not to have been checked out.
|
||||
--skip-po Do not download po files.
|
||||
--update-po Update po files and exit.
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the paxutils repository.
|
||||
|
||||
Running without arguments will suffice in most cases. It is equivalent
|
||||
to
|
||||
If the file bootstrap.conf exists in the current working directory, its
|
||||
contents are read as shell variables to configure the bootstrap.
|
||||
|
||||
./bootstrap --cvs-auth=pserver
|
||||
Local defaults can be provided by placing the file \`.bootstrap' in the
|
||||
current working directory. The file is read after bootstrap.conf, comments
|
||||
and empty lines are removed, shell variables expanded and the result is
|
||||
prepended to the command line options.
|
||||
|
||||
EOF
|
||||
Running without arguments will suffice in most cases.
|
||||
"
|
||||
}
|
||||
|
||||
update_po() {
|
||||
if [ $# = 1 ]; then
|
||||
checkout() {
|
||||
if [ ! -d $1 ]; then
|
||||
echo "$0: getting $1 files..."
|
||||
|
||||
case $1 in
|
||||
*.po) POFILE=$1;;
|
||||
*) POFILE=${1}.po;;
|
||||
paxutils)
|
||||
case ${CVS_AUTH-pserver} in
|
||||
pserver)
|
||||
CVS_PREFIX=':pserver:anonymous@';;
|
||||
ssh)
|
||||
CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
|
||||
*)
|
||||
echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
case $CVS_RSH in
|
||||
'') CVS_RSH=ssh; export CVS_RSH;;
|
||||
esac
|
||||
|
||||
CVSURL=${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1"
|
||||
;;
|
||||
|
||||
gnulib)
|
||||
CVSURL=:pserver:anonymous@pserver.git.sv.gnu.org:/gnulib.git
|
||||
;;
|
||||
|
||||
esac
|
||||
echo "$0: getting translation for $1..."
|
||||
wget -r --cache=off $TP_URL/$POFILE
|
||||
else
|
||||
echo "$0: getting translations into po..."
|
||||
(cd po &&
|
||||
rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'` &&
|
||||
wget -nv -nd -r -l 1 -A .po --cache off $TP_URL &&
|
||||
rm -f index.html index.html.[0-9]*
|
||||
ls *.po | sed 's/\.po$//' >LINGUAS
|
||||
) || exit
|
||||
|
||||
trap "cleanup $1" 1 2 13 15
|
||||
|
||||
cvs -z3 -q -d $CVSURL co $1 || cleanup $1
|
||||
|
||||
trap - 1 2 13 15
|
||||
fi
|
||||
}
|
||||
|
||||
# Read configuration file
|
||||
cleanup() {
|
||||
status=$?
|
||||
rm -fr $1
|
||||
exit $status
|
||||
}
|
||||
|
||||
# Configuration.
|
||||
|
||||
# List of gnulib modules needed.
|
||||
gnulib_modules=
|
||||
|
||||
# Any gnulib files needed that are not in modules.
|
||||
gnulib_files=
|
||||
|
||||
# The command to download all .po files for a specified domain into
|
||||
# a specified directory. Fill in the first %s is the domain name, and
|
||||
# the second with the destination directory. Use rsync's -L and -r
|
||||
# options because the latest/%s directory and the .po files within are
|
||||
# all symlinks.
|
||||
po_download_command_format=\
|
||||
"rsync -Lrtvz 'translationproject.org::tp/latest/%s/' '%s'"
|
||||
|
||||
extract_package_name='
|
||||
/^AC_INIT(/{
|
||||
/.*,.*,.*,/{
|
||||
s///
|
||||
s/[][]//g
|
||||
p
|
||||
q
|
||||
}
|
||||
s/AC_INIT(\[*//
|
||||
s/]*,.*//
|
||||
s/^GNU //
|
||||
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
|
||||
s/[^A-Za-z0-9_]/-/g
|
||||
p
|
||||
}
|
||||
'
|
||||
package=`sed -n "$extract_package_name" configure.ac` || exit
|
||||
|
||||
# Extra files from gnulib, which override files from other sources.
|
||||
gnulib_extra_files='
|
||||
build-aux/announce-gen
|
||||
build-aux/install-sh
|
||||
build-aux/missing
|
||||
build-aux/mdate-sh
|
||||
build-aux/texinfo.tex
|
||||
build-aux/depcomp
|
||||
build-aux/config.guess
|
||||
build-aux/config.sub
|
||||
doc/INSTALL
|
||||
'
|
||||
|
||||
# Other locale categories that need message catalogs.
|
||||
EXTRA_LOCALE_CATEGORIES=
|
||||
|
||||
# Additional xgettext options to use. Use "\\\newline" to break lines.
|
||||
XGETTEXT_OPTIONS='\\\
|
||||
--flag=_:1:pass-c-format\\\
|
||||
--flag=N_:1:pass-c-format\\\
|
||||
--flag=error:3:c-format --flag=error_at_line:5:c-format\\\
|
||||
'
|
||||
|
||||
# Files we don't want to import.
|
||||
excluded_files=
|
||||
|
||||
# File that should exist in the top directory of a checked out hierarchy,
|
||||
# but not in a distribution tarball.
|
||||
CVS_only_file=README-cvs
|
||||
|
||||
# Whether to use copies instead of symlinks.
|
||||
copy=false
|
||||
|
||||
# Override the default configuration, if necessary.
|
||||
test -r bootstrap.conf && . ./bootstrap.conf
|
||||
|
||||
# Read local configuration file
|
||||
if [ -r .bootstrap ]; then
|
||||
echo "$0: Reading configuration file .bootstrap"
|
||||
eval set -- "`sed 's/#.*$//;/^$/d' .bootstrap | tr '\n' ' '` $*"
|
||||
fi
|
||||
|
||||
# Translate configuration into internal form.
|
||||
|
||||
# Parse options.
|
||||
|
||||
DOWNLOAD_PO=yes
|
||||
for option
|
||||
do
|
||||
case $option in
|
||||
--help)
|
||||
usage
|
||||
exit;;
|
||||
--gnulib-srcdir=*)
|
||||
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
|
||||
--paxutils-srcdir=*)
|
||||
PAXUTILS_SRCDIR=`expr "$option" : '--paxutils-srcdir=\(.*\)'`;;
|
||||
--cvs-auth=*)
|
||||
CVS_AUTH=`expr "$option" : '--cvs-auth=\(.*\)'`;;
|
||||
--gnulib-srcdir=*)
|
||||
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
|
||||
--cvs-user=*)
|
||||
CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
|
||||
--no-po)
|
||||
DOWNLOAD_PO=no;;
|
||||
--skip-po | --no-po) # --no-po is for compatibility with 'tar' tradition.
|
||||
DOWNLOAD_PO=skip;;
|
||||
--update-po=*)
|
||||
DOWNLOAD_PO=`expr "$option" : '--update-po=\(.*\)'`;;
|
||||
--update-po)
|
||||
DOWNLOAD_PO=only;;
|
||||
--force)
|
||||
CVS_only_file=;;
|
||||
--copy)
|
||||
copy=true;;
|
||||
*)
|
||||
echo >&2 "$0: $option: unknown option"
|
||||
exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test -n "$CVS_only_file" && test ! -r "$CVS_only_file"; then
|
||||
echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$0: Bootstrapping CVS $package..."
|
||||
|
||||
# Get translations.
|
||||
|
||||
download_po_files() {
|
||||
subdir=$1
|
||||
domain=$2
|
||||
echo "$0: getting translations into $subdir for $domain..."
|
||||
cmd=`printf "$po_download_command_format" "$domain" "$subdir"`
|
||||
eval "$cmd"
|
||||
}
|
||||
|
||||
# Download .po files to $po_dir/.reference and copy only the new
|
||||
# or modified ones into $po_dir. Also update $po_dir/LINGUAS.
|
||||
update_po_files() {
|
||||
# Directory containing primary .po files.
|
||||
# Overwrite them only when we're sure a .po file is new.
|
||||
po_dir=$1
|
||||
domain=$2
|
||||
|
||||
# Download *.po files into this dir.
|
||||
# Usually contains *.s1 checksum files.
|
||||
ref_po_dir="$po_dir/.reference"
|
||||
|
||||
test -d $ref_po_dir || mkdir $ref_po_dir || return
|
||||
download_po_files $ref_po_dir $domain \
|
||||
&& ls "$ref_po_dir"/*.po 2>/dev/null |
|
||||
sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS"
|
||||
|
||||
langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
|
||||
test "$langs" = '*' && langs=x
|
||||
for po in `cd $ref_po_dir && echo *.po|sed 's/\.po//g'`; do
|
||||
case $po in x) continue;; esac
|
||||
new_po="$ref_po_dir/$po.po"
|
||||
cksum_file="$ref_po_dir/$po.s1"
|
||||
if ! test -f "$cksum_file" ||
|
||||
! test -f "$po_dir/$po.po" ||
|
||||
! sha1sum -c --status "$cksum_file" < "$new_po" > /dev/null; then
|
||||
echo "updated $po_dir/$po.po..."
|
||||
cp "$new_po" "$po_dir/$po.po" && sha1sum < "$new_po" > "$cksum_file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
case $DOWNLOAD_PO in
|
||||
only) update_po
|
||||
exit 0
|
||||
;;
|
||||
no|yes) ;;
|
||||
*) update_po $DOWNLOAD_PO
|
||||
exit 0
|
||||
'skip')
|
||||
;;
|
||||
'')
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
;;
|
||||
'only')
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$0: Bootstrapping CVS tar..."
|
||||
# Get paxutils files.
|
||||
|
||||
build_cvs_prefix() {
|
||||
CVS_PREFIX=:${1}:
|
||||
if [ "${2}" != - ]; then
|
||||
CVS_PREFIX=${CVS_PREFIX}${2}@
|
||||
fi
|
||||
if [ "$1" = "ext" ]; then
|
||||
if [ -z "${CVS_RSH}" ]; then
|
||||
CVS_RSH=ssh
|
||||
export CVS_RSH
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# checkout package
|
||||
checkout() {
|
||||
if [ ! -d $1 ]; then
|
||||
echo "$0: getting $1 files..."
|
||||
|
||||
trap exit 1 2 13 15
|
||||
trap 'rm -fr $1; exit 1' 0
|
||||
|
||||
case "${CVS_AUTH-pserver}" in
|
||||
pserver) build_cvs_prefix pserver ${CVS_USER:-anonymous}
|
||||
;;
|
||||
gserver|server)
|
||||
build_cvs_prefix $CVS_AUTH ${CVS_USER--}
|
||||
;;
|
||||
ext) build_cvs_prefix $CVS_AUTH ${CVS_USER--}
|
||||
;;
|
||||
*) echo "$0: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
cvs -q -d ${CVS_PREFIX}cvs.sv.gnu.org:/cvsroot/$1 co $1 || exit
|
||||
|
||||
trap - 0
|
||||
fi
|
||||
}
|
||||
|
||||
gnulib_modules=
|
||||
newline='
|
||||
'
|
||||
|
||||
get_modules() {
|
||||
new_gnulib_modules=`sed '/^[ ]*#/d; /^[ ]*$/d' $*`
|
||||
case $gnulib_modules,$new_gnulib_modules in
|
||||
?*,?*) new_gnulib_modules=$newline$new_gnulib_modules;;
|
||||
esac
|
||||
gnulib_modules=$gnulib_modules$new_gnulib_modules
|
||||
}
|
||||
|
||||
# Get paxutils files
|
||||
case ${PAXUTILS_SRCDIR--} in
|
||||
-) checkout paxutils
|
||||
PAXUTILS_SRCDIR=paxutils
|
||||
esac
|
||||
|
||||
if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
|
||||
get_modules $PAXUTILS_SRCDIR/gnulib.modules
|
||||
gnulib_modules=`
|
||||
(echo "$gnulib_modules"; grep '^[^#]' $PAXUTILS_SRCDIR/gnulib.modules) |
|
||||
sort -u
|
||||
`
|
||||
fi
|
||||
|
||||
ignore_file_list=
|
||||
cleanup_ifl() {
|
||||
test -n "$ignore_file_list" && rm -f $ignore_file_list
|
||||
}
|
||||
|
||||
trap 'cleanup_ifl' 1 2 3 15
|
||||
|
||||
# ignorefile DIR FILE
|
||||
# add FILE to the temporary ignorelist in the directory DIR
|
||||
ignorefile() {
|
||||
file=$1/.ignore.$$
|
||||
echo "$2" >> $file
|
||||
if `echo $ignore_list | grep -qv $file`; then
|
||||
ignore_file_list="$ignore_file_list
|
||||
$file"
|
||||
fi
|
||||
}
|
||||
|
||||
# copy_files srcdir dstdir
|
||||
copy_files() {
|
||||
for file in `cat $1/DISTFILES`
|
||||
@@ -205,16 +329,258 @@ copy_files() {
|
||||
fi
|
||||
echo "$0: Copying file $1/$file to $2/$dst"
|
||||
cp -p $1/$file $2/$dst
|
||||
ignorefile $2 $dst
|
||||
done
|
||||
}
|
||||
|
||||
# Get gnulib files.
|
||||
|
||||
case ${GNULIB_SRCDIR--} in
|
||||
-)
|
||||
checkout gnulib
|
||||
GNULIB_SRCDIR=gnulib
|
||||
esac
|
||||
|
||||
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
|
||||
<$gnulib_tool || exit
|
||||
|
||||
ensure_dir_exists()
|
||||
{
|
||||
d=`dirname $dst`
|
||||
test -d "$d" || mkdir -p -- "$d"
|
||||
}
|
||||
|
||||
symlink_to_gnulib()
|
||||
{
|
||||
src=$GNULIB_SRCDIR/$1
|
||||
dst=${2-$1}
|
||||
|
||||
test -f "$src" && {
|
||||
if $copy; then
|
||||
{
|
||||
test ! -h "$dst" || {
|
||||
echo "$0: rm -f $dst" &&
|
||||
rm -f "$dst"
|
||||
}
|
||||
} &&
|
||||
test -f "$dst" &&
|
||||
cmp -s "$src" "$dst" || {
|
||||
echo "$0: cp -fp $src $dst" &&
|
||||
ensure_dir_exists $dst &&
|
||||
cp -fp "$src" "$dst"
|
||||
}
|
||||
else
|
||||
test -h "$dst" &&
|
||||
src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
|
||||
dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
|
||||
test "$src_i" = "$dst_i" || {
|
||||
dot_dots=
|
||||
case $src in
|
||||
/*) ;;
|
||||
*)
|
||||
case /$dst/ in
|
||||
*//* | */../* | */./* | /*/*/*/*/*/)
|
||||
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
|
||||
exit 1;;
|
||||
/*/*/*/*/) dot_dots=../../../;;
|
||||
/*/*/*/) dot_dots=../../;;
|
||||
/*/*/) dot_dots=../;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
echo "$0: ln -fs $dot_dots$src $dst" &&
|
||||
ensure_dir_exists $dst &&
|
||||
ln -fs "$dot_dots$src" "$dst"
|
||||
}
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
cp_mark_as_generated()
|
||||
{
|
||||
cp_src=$1
|
||||
cp_dst=$2
|
||||
|
||||
if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
|
||||
symlink_to_gnulib "$cp_dst"
|
||||
else
|
||||
case $cp_dst in
|
||||
*.[ch]) c1='/* '; c2=' */';;
|
||||
*.texi) c1='@c '; c2= ;;
|
||||
*.m4|*/Make*|Make*) c1='# ' ; c2= ;;
|
||||
*) c1= ; c2= ;;
|
||||
esac
|
||||
|
||||
if test -z "$c1"; then
|
||||
cmp -s "$cp_src" "$cp_dst" || {
|
||||
echo "$0: cp -f $cp_src $cp_dst" &&
|
||||
cp -f "$cp_src" "$cp_dst"
|
||||
}
|
||||
else
|
||||
# Copy the file first to get proper permissions if it
|
||||
# doesn't already exist. Then overwrite the copy.
|
||||
cp "$cp_src" "$cp_dst-t" &&
|
||||
(
|
||||
echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
|
||||
echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
|
||||
cat "$cp_src"
|
||||
) > $cp_dst-t &&
|
||||
if cmp -s "$cp_dst-t" "$cp_dst"; then
|
||||
rm -f "$cp_dst-t"
|
||||
else
|
||||
echo "$0: cp $cp_src $cp_dst # with edits" &&
|
||||
mv -f "$cp_dst-t" "$cp_dst"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
version_controlled_file() {
|
||||
dir=$1
|
||||
file=$2
|
||||
found=no
|
||||
if test -d CVS; then
|
||||
grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
|
||||
grep '^/[^/]*/[0-9]' > /dev/null && found=yes
|
||||
elif test -d .git; then
|
||||
git-rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
|
||||
else
|
||||
echo "$0: no version control for $dir/$file?" >&2
|
||||
fi
|
||||
test $found = yes
|
||||
}
|
||||
|
||||
slurp() {
|
||||
for dir in . `(cd $1 && find * -type d -print)`; do
|
||||
copied=
|
||||
sep=
|
||||
for file in `ls $1/$dir`; do
|
||||
test -d $1/$dir/$file && continue
|
||||
for excluded_file in $excluded_files; do
|
||||
test "$dir/$file" = "$excluded_file" && continue 2
|
||||
done
|
||||
if test $file = Makefile.am; then
|
||||
copied=$copied${sep}gnulib.mk; sep=$nl
|
||||
remove_intl='/^[^#].*\/intl/s/^/#/;'"s,/$bt,,g"
|
||||
sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/gnulib.mk || {
|
||||
echo "$0: Copying $1/$dir/$file to $dir/gnulib.mk ..." &&
|
||||
rm -f $dir/gnulib.mk &&
|
||||
sed "$remove_intl" $1/$dir/$file >$dir/gnulib.mk
|
||||
}
|
||||
elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
|
||||
version_controlled_file $dir $file; then
|
||||
echo "$0: $dir/$file overrides $1/$dir/$file"
|
||||
else
|
||||
copied=$copied$sep$file; sep=$nl
|
||||
if test $file = gettext.m4; then
|
||||
echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
|
||||
rm -f $dir/$file
|
||||
sed '
|
||||
/^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
|
||||
AC_DEFUN([AM_INTL_SUBDIR], [
|
||||
/^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
|
||||
AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
|
||||
$a\
|
||||
AC_DEFUN([gl_LOCK_EARLY], [])
|
||||
' $1/$dir/$file >$dir/$file
|
||||
else
|
||||
cp_mark_as_generated $1/$dir/$file $dir/$file
|
||||
fi
|
||||
fi || exit
|
||||
done
|
||||
|
||||
if test -n "$copied"; then
|
||||
copied="Makefile
|
||||
Makefile.in
|
||||
$copied"
|
||||
if test -d CVS; then
|
||||
dot_ig=.cvsignore
|
||||
else
|
||||
dor_ig=.gitignore
|
||||
fi
|
||||
|
||||
ig=$dir/$dot_ig
|
||||
if [ -f $dir/.ignore.$$ ]; then
|
||||
tfile=$dir/.ignore.$$
|
||||
else
|
||||
tfile=
|
||||
fi
|
||||
if test -f $ig; then
|
||||
echo "$copied" | sort -u - $ig | cmp -s - $ig ||
|
||||
echo "$copied" | sort -u - $ig $tfile -o $ig
|
||||
else
|
||||
copied="$dot_ig
|
||||
$copied"
|
||||
if [ "$dir" = "po" ]; then
|
||||
copied="LINGUAS
|
||||
Makevars
|
||||
POTFILES
|
||||
*.mo
|
||||
*.gmo
|
||||
*.po
|
||||
remove-potcdate.sed
|
||||
stamp-po
|
||||
$package.pot
|
||||
$copied"
|
||||
fi
|
||||
echo "$copied" | sort -u - $tfile -o $ig
|
||||
fi || exit
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# Create boot temporary directories to import from gnulib and gettext.
|
||||
|
||||
bt='.#bootmp'
|
||||
bt2=${bt}2
|
||||
rm -fr $bt $bt2 &&
|
||||
mkdir $bt $bt2 || exit
|
||||
|
||||
# Import from gnulib.
|
||||
|
||||
test -d build-aux || {
|
||||
echo "$0: mkdir build-aux ..." &&
|
||||
mkdir build-aux
|
||||
} || exit
|
||||
gnulib_tool_options="\
|
||||
--import\
|
||||
--no-changelog\
|
||||
--aux-dir $bt/build-aux\
|
||||
--doc-base $bt/doc\
|
||||
--lib lib$package\
|
||||
--m4-base $bt/m4/\
|
||||
--source-base $bt/lib/\
|
||||
--tests-base $bt/tests\
|
||||
--local-dir gl\
|
||||
"
|
||||
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
|
||||
$gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
|
||||
slurp $bt || exit
|
||||
|
||||
for file in $gnulib_files; do
|
||||
symlink_to_gnulib $file || exit
|
||||
done
|
||||
|
||||
|
||||
# Import from gettext.
|
||||
|
||||
echo "$0: (cd $bt2; autopoint) ..."
|
||||
cp configure.ac $bt2 &&
|
||||
(cd $bt2 && autopoint && rm configure.ac) &&
|
||||
slurp $bt2 $bt || exit
|
||||
|
||||
rm -fr $bt $bt2 || exit
|
||||
|
||||
# Import from paxutils
|
||||
copy_files ${PAXUTILS_SRCDIR}/m4 m4
|
||||
echo "$0: Creating m4/paxutils.m4"
|
||||
(echo "# This file is generated automatically. Please, do not edit."
|
||||
echo "#"
|
||||
echo "AC_DEFUN([tar_PAXUTILS],["
|
||||
echo "AC_DEFUN([${package}_PAXUTILS],["
|
||||
cat ${PAXUTILS_SRCDIR}/m4/DISTFILES | sed '/^#/d;s/\(.*\)\.m4/pu_\1/' | tr a-z A-Z
|
||||
echo "])") > ./m4/paxutils.m4
|
||||
ignorefile m4 paxutils.m4
|
||||
|
||||
if [ -d rmt ]; then
|
||||
:
|
||||
@@ -229,89 +595,59 @@ done
|
||||
|
||||
copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
|
||||
|
||||
# Get gnulib files.
|
||||
|
||||
case ${GNULIB_SRCDIR--} in
|
||||
-) checkout gnulib
|
||||
GNULIB_SRCDIR=gnulib
|
||||
esac
|
||||
|
||||
<$GNULIB_SRCDIR/gnulib-tool || exit
|
||||
|
||||
get_modules gnulib.modules
|
||||
|
||||
gnulib_modules=`echo "$gnulib_modules" | sort -u`
|
||||
previous_gnulib_modules=
|
||||
while [ "$gnulib_modules" != "$previous_gnulib_modules" ]; do
|
||||
previous_gnulib_modules=$gnulib_modules
|
||||
gnulib_modules=`
|
||||
(echo "$gnulib_modules"
|
||||
for gnulib_module in $gnulib_modules; do
|
||||
$GNULIB_SRCDIR/gnulib-tool --extract-dependencies $gnulib_module
|
||||
done) | sort -u
|
||||
`
|
||||
done
|
||||
|
||||
gnulib_files=`
|
||||
(for gnulib_module in $gnulib_modules; do
|
||||
$GNULIB_SRCDIR/gnulib-tool --extract-filelist $gnulib_module
|
||||
done) | sort -u
|
||||
`
|
||||
|
||||
gnulib_dirs=`echo "$gnulib_files" | sed 's,/[^/]*$,,' | sort -u`
|
||||
mkdir -p $gnulib_dirs || exit
|
||||
|
||||
for gnulib_file in $gnulib_files; do
|
||||
dest=$gnulib_file
|
||||
|
||||
case $gnulib_file in
|
||||
m4/codeset.m4) continue;;
|
||||
m4/intdiv0.m4) continue;;
|
||||
m4/inttypes-pri.m4) continue;;
|
||||
m4/isc-posix.m4) continue;;
|
||||
m4/lcmessage.m4) continue;;
|
||||
m4/onceonly_2_57.m4) dest=m4/onceonly.m4;;
|
||||
# These will be overwritten by autopoint, which still uses
|
||||
# old jm_.* macro names, so we have to keep both copies.
|
||||
m4/gettext.m4 | m4/glibc21.m4 | m4/inttypes_h.m4 | m4/lib-ld.m4 | \
|
||||
m4/lib-prefix.m4 | m4/po.m4 | m4/stdint_h.m4 | m4/uintmax_t.m4 | \
|
||||
m4/ulonglong.m4)
|
||||
dest=`expr $gnulib_file : '\(.*\).m4'`_gl.m4;;
|
||||
esac
|
||||
|
||||
rm -f $dest &&
|
||||
echo "$0: Copying file $GNULIB_SRCDIR/$gnulib_file" &&
|
||||
cp -p $GNULIB_SRCDIR/$gnulib_file $dest || exit
|
||||
done
|
||||
|
||||
echo "$0: Creating m4/gnulib.m4"
|
||||
(echo "# This file is generated automatically. Please, do not edit."
|
||||
echo "#"
|
||||
echo "AC_DEFUN([tar_GNULIB],["
|
||||
for gnulib_module in $gnulib_modules; do
|
||||
echo "# $gnulib_module"
|
||||
$GNULIB_SRCDIR/gnulib-tool --extract-autoconf-snippet $gnulib_module
|
||||
done | sed '/AM_GNU_GETTEXT/d'
|
||||
echo "])") > ./m4/gnulib.m4
|
||||
|
||||
echo "$0: Creating lib/Makefile.am"
|
||||
(echo "# This file is generated automatically. Do not edit!"
|
||||
cat lib/Makefile.tmpl
|
||||
|
||||
for gnulib_module in $gnulib_modules; do
|
||||
echo "# $gnulib_module"
|
||||
$GNULIB_SRCDIR/gnulib-tool --extract-automake-snippet $gnulib_module
|
||||
done | sed 's/lib_SOURCES/libtar_a_SOURCES/g' ) > lib/Makefile.am
|
||||
|
||||
# Get translations.
|
||||
if test "$DOWNLOAD_PO" = "yes"; then
|
||||
update_po
|
||||
fi
|
||||
|
||||
# Reconfigure, getting other files.
|
||||
|
||||
echo "$0: autoreconf --verbose --install --force ..."
|
||||
autoreconf --verbose --install --force || exit 1
|
||||
for command in \
|
||||
'aclocal --force -I m4' \
|
||||
'autoconf --force' \
|
||||
'autoheader --force' \
|
||||
'automake --add-missing --copy --force-missing';
|
||||
do
|
||||
echo "$0: $command ..."
|
||||
$command || exit
|
||||
done
|
||||
|
||||
|
||||
# Get some extra files from gnulib, overriding existing files.
|
||||
|
||||
for file in $gnulib_extra_files; do
|
||||
case $file in
|
||||
*/INSTALL) dst=INSTALL;;
|
||||
*) dst=$file;;
|
||||
esac
|
||||
symlink_to_gnulib $file $dst || exit
|
||||
done
|
||||
|
||||
|
||||
# Create gettext configuration.
|
||||
echo "$0: Creating po/Makevars from po/Makevars.template ..."
|
||||
rm -f po/Makevars
|
||||
sed '
|
||||
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
|
||||
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
|
||||
/^XGETTEXT_OPTIONS *=/{
|
||||
s/$/ \\/
|
||||
a\
|
||||
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
|
||||
}
|
||||
' po/Makevars.template >po/Makevars
|
||||
|
||||
if test -d runtime-po; then
|
||||
# Similarly for runtime-po/Makevars, but not quite the same.
|
||||
rm -f runtime-po/Makevars
|
||||
sed '
|
||||
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
|
||||
/^subdir *=.*/s/=.*/= runtime-po/
|
||||
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
|
||||
/^XGETTEXT_OPTIONS *=/{
|
||||
s/$/ \\/
|
||||
a\
|
||||
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
|
||||
}
|
||||
' <po/Makevars.template >runtime-po/Makevars
|
||||
|
||||
# Copy identical files from po to runtime-po.
|
||||
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
|
||||
fi
|
||||
cleanup_ifl
|
||||
echo "$0: done. Now you can run './configure'."
|
||||
|
||||
59
bootstrap.conf
Normal file
59
bootstrap.conf
Normal file
@@ -0,0 +1,59 @@
|
||||
# Bootstrap configuration.
|
||||
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
|
||||
# We don't need these modules, even though gnulib-tool mistakenly
|
||||
# includes them because of gettext dependencies.
|
||||
avoided_gnulib_modules='
|
||||
--avoid=lock
|
||||
--avoid=size_max
|
||||
'
|
||||
|
||||
# gnulib modules used by this package.
|
||||
gnulib_modules="$avoided_gnulib_modules
|
||||
`grep '^[^#]' gnulib.modules`
|
||||
"
|
||||
|
||||
# Additional xgettext options to use. Use "\\\newline" to break lines.
|
||||
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
|
||||
--flag=_:1:pass-c-format\\\
|
||||
--flag=N_:1:pass-c-format\\\
|
||||
--flag=error:3:c-format --flag=error_at_line:5:c-format\\\
|
||||
--flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format\\\
|
||||
--flag=argp_error:2:c-format\\\
|
||||
--flag=__argp_error:2:c-format\\\
|
||||
--flag=argp_failure:4:c-format\\\
|
||||
--flag=__argp_failure:4:c-format\\\
|
||||
--flag=argp_fmtstream_printf:2:c-format\\\
|
||||
--flag=__argp_fmtstream_printf:2:c-format\\\
|
||||
'
|
||||
|
||||
# Gettext supplies these files, but we don't need them since
|
||||
# we don't have an intl subdirectory.
|
||||
excluded_files='
|
||||
m4/glibc2.m4
|
||||
m4/intdiv0.m4
|
||||
m4/lcmessage.m4
|
||||
m4/lock.m4
|
||||
m4/printf-posix.m4
|
||||
m4/size_max.m4
|
||||
m4/uintmax_t.m4
|
||||
m4/ulonglong.m4
|
||||
m4/visibility.m4
|
||||
'
|
||||
24
configure.ac
24
configure.ac
@@ -1,11 +1,11 @@
|
||||
# Configure template for GNU tar.
|
||||
# Configure template for GNU tar. -*- autoconf -*-
|
||||
|
||||
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -18,18 +18,19 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
AC_INIT([GNU tar], [1.15.91], [bug-tar@gnu.org])
|
||||
AC_INIT([GNU tar], [1.21], [bug-tar@gnu.org])
|
||||
AC_CONFIG_SRCDIR([src/tar.c])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h:config.hin])
|
||||
AC_PREREQ([2.59])
|
||||
AC_PREREQ([2.60])
|
||||
AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
|
||||
|
||||
gl_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_CC
|
||||
AC_EXEEXT
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_YACC
|
||||
gl_EARLY
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
AC_ISC_POSIX
|
||||
AC_C_INLINE
|
||||
@@ -80,15 +81,13 @@ AC_CHECK_TYPE(dev_t, unsigned)
|
||||
AC_CHECK_TYPE(ino_t, unsigned)
|
||||
|
||||
gt_TYPE_SSIZE_T
|
||||
gl_AC_TYPE_INTMAX_T
|
||||
jm_AC_TYPE_UINTMAX_T
|
||||
|
||||
# gnulib modules
|
||||
tar_GNULIB
|
||||
gl_INIT
|
||||
# paxutils modules
|
||||
tar_PAXUTILS
|
||||
|
||||
AC_CHECK_FUNCS(fsync lstat mkfifo readlink strerror symlink setlocale utimes)
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink symlink setlocale utimes)
|
||||
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
|
||||
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
|
||||
AC_CHECK_DECLS([time],,, [#include <time.h>])
|
||||
@@ -214,8 +213,8 @@ AC_CHECK_TYPE(iconv_t,:,
|
||||
])
|
||||
|
||||
# Gettext.
|
||||
AM_GNU_GETTEXT([external], [need-ngettext])
|
||||
AM_GNU_GETTEXT_VERSION(0.12.1)
|
||||
AM_GNU_GETTEXT([external], [need-formatstring-macros])
|
||||
AM_GNU_GETTEXT_VERSION([0.16])
|
||||
|
||||
# Initialize the test suite.
|
||||
AC_CONFIG_TESTDIR(tests)
|
||||
@@ -240,7 +239,6 @@ else
|
||||
BACKUP_SED_COND='/^\#IF_DATE_FORMAT_OK/,/^\#ELSE_DATE_FORMAT_OK/d;/^\#ENDIF_DATE_FORMAT_OK/d'
|
||||
fi
|
||||
|
||||
|
||||
AC_OUTPUT([Makefile\
|
||||
doc/Makefile\
|
||||
lib/Makefile\
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Makefile for GNU tar documentation.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006 Free
|
||||
# Software Foundation, Inc.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
|
||||
# 2007 Free Software Foundation, Inc.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## the Free Software Foundation; either version 3, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
@@ -20,17 +20,18 @@
|
||||
info_TEXINFOS = tar.texi
|
||||
tar_TEXINFOS = \
|
||||
dumpdir.texi\
|
||||
tar-snapshot-edit.texi\
|
||||
fdl.texi\
|
||||
freemanuals.texi\
|
||||
genfile.texi\
|
||||
getdate.texi\
|
||||
intern.texi\
|
||||
header.texi\
|
||||
intern.texi\
|
||||
rendition.texi\
|
||||
snapshot.texi\
|
||||
sparse.texi\
|
||||
value.texi
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed
|
||||
DISTCLEANFILES=*.info*
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed untabify.el
|
||||
|
||||
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
|
||||
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
|
||||
@@ -45,6 +46,18 @@ header.texi: $(top_srcdir)/src/tar.h
|
||||
master-menu: $(tar_TEXINFOS)
|
||||
emacs -batch -l mastermenu.el -f make-master-menu $(info_TEXINFOS)
|
||||
|
||||
untabify:
|
||||
emacs -batch -l untabify.el $(info_TEXINFOS) $(tar_TEXINFOS)
|
||||
|
||||
final: untabify master-menu
|
||||
|
||||
# Checking
|
||||
check-format:
|
||||
@if test -n "`cat $(info_TEXINFOS) $(tar_TEXINFOS) | tr -d -c '\t'`"; then \
|
||||
echo "Sources contain tabs; run make untabify"; \
|
||||
false; \
|
||||
fi
|
||||
|
||||
check-options:
|
||||
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
|
||||
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
@@ -66,6 +79,52 @@ doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
fi;\
|
||||
rm report.$$$$
|
||||
|
||||
check-refs:
|
||||
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
|
||||
do \
|
||||
sed -e = $$file | \
|
||||
sed -n 'N;/@FIXME-.*ref/{s/\(^[0-9][0-9]*\).*@FIXME-.*ref{\([^}]*\).*/'$$file':\1: \2/gp}'; \
|
||||
done > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unresolved cross-references:"; \
|
||||
cat $@-t;\
|
||||
rm $@-t; \
|
||||
else \
|
||||
rm -f $@-t; \
|
||||
fi
|
||||
|
||||
check-fixmes:
|
||||
@for file in $(info_TEXINFOS); \
|
||||
do \
|
||||
sed -e = $$file | \
|
||||
sed -n 'N;/@FIXME{/{s/\(^[0-9][0-9]*\).*@FIXME{\([^}]*\).*/'$$file':\1: \2/gp}'; \
|
||||
done > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unresolved FIXMEs:"; \
|
||||
cat $@-t; \
|
||||
rm $@-t; \
|
||||
false; \
|
||||
else \
|
||||
rm -f $@-t; \
|
||||
fi
|
||||
|
||||
check-unrevised:
|
||||
@grep -Hn @UNREVISED $(info_TEXINFOS) > $@-t; \
|
||||
if [ -s $@-t ]; then \
|
||||
echo "Unrevised nodes:"; \
|
||||
cat $@-t; \
|
||||
rm $@-t; \
|
||||
false;\
|
||||
else \
|
||||
rm $@-t; \
|
||||
fi
|
||||
|
||||
all-check-docs: check-format check-options check-refs check-fixmes check-unrevised
|
||||
|
||||
check-docs:
|
||||
$(MAKE) -k all-check-docs
|
||||
|
||||
#
|
||||
|
||||
clean-local:
|
||||
rm -rf manual
|
||||
@@ -78,8 +137,8 @@ TEXI2DVI=texi2dvi -t '@set $(RENDITION)' -E
|
||||
# Usual value is:
|
||||
# /usr/share/texmf/pdftex/plain/misc:/usr/share/texmf/pdftex/config
|
||||
manual:
|
||||
TEXINPUTS=$(srcdir):$(top_srcdir)/config:$(TEXINPUTS) \
|
||||
TEXINPUTS=$(srcdir):$(top_srcdir)/build-tex:$(TEXINPUTS) \
|
||||
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
|
||||
$(GENDOCS) tar 'GNU tar manual'
|
||||
$(GENDOCS) --texi2html tar 'GNU tar manual'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
@c Written by Sergey Poznyakoff
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
@@ -38,7 +38,7 @@ changed since the last backup.
|
||||
|
||||
@item R
|
||||
This code requests renaming of the @var{filename} to the name
|
||||
specified with the following @samp{T} command.
|
||||
specified with the @samp{T} command, that immediately follows it.
|
||||
|
||||
@item T
|
||||
Specify target file name for @samp{R} command (see below).
|
||||
@@ -90,9 +90,9 @@ New incremental dump was made.
|
||||
@end enumerate
|
||||
|
||||
This case cannot be handled by three successive renames, since
|
||||
renaming @file{a} to @file{b} will destroy existing directory.
|
||||
To handle such case a temporary directory is required. @GNUTAR{}
|
||||
will create the following dumpdir (newlines have been added for
|
||||
renaming @file{a} to @file{b} will destroy the existing directory.
|
||||
To correctly process it, @GNUTAR{} needs a temporary directory, so
|
||||
it creates the following dumpdir (newlines have been added for
|
||||
readability):
|
||||
|
||||
@smallexample
|
||||
@@ -125,7 +125,7 @@ corresponding directory, in variable @code{GNU.dumpdir}.
|
||||
@item GNU and old GNU archives
|
||||
|
||||
These formats implement special header type @samp{D}, which is similar
|
||||
to ustar header @samp{5} (directory), except that it preceeds a data
|
||||
to ustar header @samp{5} (directory), except that it precedes a data
|
||||
block containing the dumpdir.
|
||||
@end itemize
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<!-- $Id: gendocs_template,v 1.2 2005/05/15 03:59:09 eggert Exp $ -->
|
||||
<!-- $Id: gendocs_template,v 1.5 2007/10/30 14:58:52 gray Exp $ -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
|
||||
<head>
|
||||
@@ -30,24 +30,41 @@
|
||||
alt=" [image of the head of a GNU] "
|
||||
width="129" height="122" />
|
||||
</a>
|
||||
<a href="/philosophy/gif.html">(no gifs due to patent problems)</a>
|
||||
</p>
|
||||
<hr />
|
||||
|
||||
The manual for %%PACKAGE%% is available in the following formats:</p>
|
||||
<p>The manual for %%PACKAGE%% is available in the following formats:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="%%PACKAGE%%.html">HTML
|
||||
(%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li>
|
||||
(%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
|
||||
<li><a href="html_node/index.html">HTML</a> - with one web page per
|
||||
node.</li>
|
||||
%%IF HTML_SECTION%%
|
||||
<li><a href="html_section/index.html">HTML</a> - with one web page per
|
||||
section.</li>
|
||||
%%ENDIF HTML_SECTION%%
|
||||
%%IF HTML_CHAPTER%%
|
||||
<li><a href="html_chapter/index.html">HTML</a> - with one web page per
|
||||
chapter.</li>
|
||||
%%ENDIF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
|
||||
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
|
||||
one web page.</li>
|
||||
<li><a href="%%PACKAGE%%_html_node.tar.gz">HTML compressed
|
||||
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
|
||||
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per node.</li>
|
||||
<li><a href="%%PACKAGE%%-info.tar.gz">Info document
|
||||
%%IF HTML_SECTION%%
|
||||
<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
|
||||
(%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per section.</li>
|
||||
%%ENDIF HTML_SECTION%%
|
||||
%%IF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
|
||||
(%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per chapter.</li>
|
||||
%%ENDIF HTML_CHAPTER%%
|
||||
<li><a href="%%PACKAGE%%.info.tar.gz">Info document
|
||||
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt">ASCII text
|
||||
(%%ASCII_SIZE%%K characters)</a>.</li>
|
||||
@@ -99,7 +116,7 @@ permitted in any medium, provided this notice is preserved.
|
||||
<p>
|
||||
Updated:
|
||||
<!-- timestamp start -->
|
||||
$Date: 2005/05/15 03:59:09 $ $Author: eggert $
|
||||
$Date: 2007/10/30 14:58:52 $ $Author: gray $
|
||||
<!-- timestamp end -->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
@menu
|
||||
* Standard:: Basic Tar Format
|
||||
* Extensions:: @acronym{GNU} Extensions to the Archive Format
|
||||
* Sparse Formats:: Storing Sparse Files
|
||||
* Snapshot Files::
|
||||
* Dumpdir::
|
||||
@end menu
|
||||
@@ -35,8 +36,6 @@ Archives are permitted to have more than one member with the same
|
||||
member name. One way this situation can occur is if more than one
|
||||
version of a file has been stored in the archive. For information
|
||||
about adding new versions of a file to an archive, see @ref{update}.
|
||||
@FIXME-xref{To learn more about having more than one archive member with the
|
||||
same name, see -backup node, when it's written.}
|
||||
|
||||
In addition to entries describing archive members, an archive may
|
||||
contain entries which @command{tar} itself uses to store information.
|
||||
@@ -95,7 +94,7 @@ The @code{name} field is the file name of the file, with directory names
|
||||
@FIXME{how big a name before field overflows?}
|
||||
|
||||
The @code{mode} field provides nine bits specifying file permissions
|
||||
and three bits to specify the Set UID, Set GID, and Save Text
|
||||
and three bits to specify the Set @acronym{UID}, Set @acronym{GID}, and Save Text
|
||||
(@dfn{sticky}) modes. Values for these bits are defined above.
|
||||
When special permissions are required to create a file with a given
|
||||
mode, and the user restoring files from the archive does not hold such
|
||||
@@ -106,12 +105,12 @@ should be faked up when creating or updating an archive; e.g., the
|
||||
group permission could be copied from the @emph{other} permission.
|
||||
|
||||
The @code{uid} and @code{gid} fields are the numeric user and group
|
||||
ID of the file owners, respectively. If the operating system does
|
||||
not support numeric user or group IDs, these fields should be ignored.
|
||||
@acronym{ID} of the file owners, respectively. If the operating system does
|
||||
not support numeric user or group @acronym{ID}s, these fields should
|
||||
be ignored.
|
||||
|
||||
The @code{size} field is the size of the file in bytes; linked files
|
||||
are archived with this field specified as zero. @FIXME-xref{Modifiers, in
|
||||
particular the @option{--incremental} (@option{-G}) option.}
|
||||
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
|
||||
@@ -257,7 +256,7 @@ The @code{magic} field indicates that this archive was output in
|
||||
the P1003 archive format. If this field contains @code{TMAGIC},
|
||||
the @code{uname} and @code{gname} fields will contain the ASCII
|
||||
representation of the owner and group of the file respectively.
|
||||
If found, the user and group IDs are used rather than the values in
|
||||
If found, the user and group @acronym{ID}s are used rather than the values in
|
||||
the @code{uid} and @code{gid} fields.
|
||||
|
||||
For references, see ISO/IEC 9945-1:1990 or IEEE Std 1003.1-1990, pages
|
||||
@@ -320,6 +319,10 @@ use the @acronym{GNU}-added fields of the header, other versions of
|
||||
@command{tar} program will give an error, the most likely one being a
|
||||
checksum error.
|
||||
|
||||
@node Sparse Formats
|
||||
@unnumberedsec Storing Sparse Files
|
||||
@include sparse.texi
|
||||
|
||||
@node Snapshot Files
|
||||
@unnumberedsec Format of the Incremental Snapshot Files
|
||||
@include snapshot.texi
|
||||
@@ -327,3 +330,4 @@ checksum error.
|
||||
@node Dumpdir
|
||||
@unnumberedsec Dumpdir
|
||||
@include dumpdir.texi
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; mastermenu.el --- Redefinition of texinfo-master-menu-list
|
||||
|
||||
;; Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Sergey Poznyakoff
|
||||
;; Maintainer: bug-tar@gnu.org
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; 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,
|
||||
|
||||
@@ -55,8 +55,6 @@
|
||||
@c Output various FIXME information only in PROOF rendition.
|
||||
|
||||
@macro FIXME{string}
|
||||
@allow-recursion
|
||||
@quote-arg
|
||||
@ifset PROOF
|
||||
@ifset PROOF_FOOTNOTED
|
||||
@footnote{@strong{FIXME:} \string\}
|
||||
@@ -71,25 +69,31 @@
|
||||
@end macro
|
||||
|
||||
@macro FIXME-ref{string}
|
||||
@quote-arg
|
||||
@ifset PROOF
|
||||
@strong{<REF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
@cite{\string\}
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@macro FIXME-pxref{string}
|
||||
@quote-arg
|
||||
@ifset PROOF
|
||||
@strong{<PXREF>} \string\ @strong{</>}
|
||||
See @strong{<PXREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
See @cite{\string\}
|
||||
@end ifclear
|
||||
|
||||
@end macro
|
||||
|
||||
@macro FIXME-xref{string}
|
||||
@quote-arg
|
||||
@ifset PROOF
|
||||
@strong{<XREF>} \string\ @strong{</>}
|
||||
See @strong{<XREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@ifclear PROOF
|
||||
See @cite{\string\}
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@c End of rendition.texi
|
||||
|
||||
@@ -1,35 +1,63 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||
@c Written by Sergey Poznyakoff
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
A @dfn{snapshot file} (or @dfn{directory file}) is created during
|
||||
incremental backups (@pxref{Incremental Dumps}). It
|
||||
contains the status of the filesystem at the time of the dump and is
|
||||
contains the status of the file system at the time of the dump and is
|
||||
used to determine which files were modified since the last backup.
|
||||
|
||||
@GNUTAR{} version @value{VERSION} supports two snapshot file
|
||||
@GNUTAR{} version @value{VERSION} supports three snapshot file
|
||||
formats. The first format, called @dfn{format 0}, is the one used by
|
||||
@GNUTAR{} versions up to 1.15.1. The second format, called @dfn{format
|
||||
1} is an extended version of this format, that contains more metadata
|
||||
and allows for further extensions.
|
||||
and allows for further extensions. It was used by version
|
||||
1.15.1. Starting from version 1.16 and up to @value{VERSION}, the
|
||||
@dfn{format 2} is used.
|
||||
|
||||
@GNUTAR{} is able to read all three formats, but will create
|
||||
snapshots only in format 2.
|
||||
|
||||
This appendix describes all three formats in detail.
|
||||
|
||||
@enumerate 0
|
||||
@cindex format 0, snapshot file
|
||||
@cindex snapshot file, format 0
|
||||
@item
|
||||
@samp{Format 0} snapshot file begins with a line containing a
|
||||
decimal number that represents the UNIX timestamp of the beginning of
|
||||
the last archivation. This line is followed by directory metadata
|
||||
descriptions, one per line. Each description has the following format:
|
||||
decimal number that represents a @acronym{UNIX} timestamp of the
|
||||
beginning of the last archivation. This line is followed by directory
|
||||
metadata descriptions, one per line. Each description has the
|
||||
following format:
|
||||
|
||||
@smallexample
|
||||
[@var{nfs}]@var{dev} @var{inode} @var{name}
|
||||
@var{nfs}@var{dev} @var{inode} @var{name}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where optional @var{nfs} is a single plus character (@samp{+}) if this
|
||||
directory is located on an NFS-mounted partition, @var{dev} and
|
||||
@var{inode} are the device and inode numbers of the directory, and
|
||||
@var{name} is the directory name.
|
||||
where:
|
||||
|
||||
@table @var
|
||||
@item nfs
|
||||
A single plus character (@samp{+}), if this directory is located on
|
||||
an @acronym{NFS}-mounted partition, or a single space otherwise;
|
||||
|
||||
@item dev
|
||||
Device number of the directory;
|
||||
|
||||
@item inode
|
||||
I-node number of the directory;
|
||||
|
||||
@item name
|
||||
Name of the directory. Any special characters (white-space,
|
||||
backslashes, etc.) are quoted.
|
||||
@end table
|
||||
|
||||
@cindex format 1, snapshot file
|
||||
@cindex snapshot file, format 1
|
||||
@item
|
||||
@samp{Format 1} snapshot file begins with a line specifying the
|
||||
format of the file. This line has the following structure:
|
||||
|
||||
@@ -38,28 +66,75 @@ format of the file. This line has the following structure:
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where @var{tar-version} is the version of @GNUTAR{} implementation
|
||||
that created this snapshot, and @var{incr-format-version} is the
|
||||
version number of the snapshot format (in this case @samp{1}).
|
||||
where @var{tar-version} is the version number of @GNUTAR{}
|
||||
implementation that created this snapshot, and
|
||||
@var{incr-format-version} is the version number of the snapshot format
|
||||
(in this case @samp{1}).
|
||||
|
||||
The following line contains two decimal numbers, representing the
|
||||
Next line contains two decimal numbers, representing the
|
||||
time of the last backup. First number is the number of seconds, the
|
||||
second one is the number of nanoseconds, since the beginning of the
|
||||
epoch.
|
||||
|
||||
Following lines contain directory metadate, one line per
|
||||
directory. The line format is:
|
||||
Lines that follow contain directory metadata, one line per
|
||||
directory. Each line is formatted as follows:
|
||||
|
||||
@smallexample
|
||||
[@var{nfs}]@var{mtime-sec} @var{mtime-nsec} @var{dev} @var{inode} @var{name}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where @var{mtime-sec} and @var{mtime-nsec} represent the last
|
||||
where @var{mtime-sec} and @var{mtime-nsec} represent last
|
||||
modification time of this directory with nanosecond precision;
|
||||
@var{nfs}, @var{dev}, @var{inode} and @var{name} have the same meaning
|
||||
as with @samp{format 0}.
|
||||
|
||||
@cindex format 2, snapshot file
|
||||
@cindex snapshot file, format 2
|
||||
@item
|
||||
@FIXME{}
|
||||
A snapshot file begins with a format identifier, as described for
|
||||
version 1, e.g.:
|
||||
|
||||
@smallexample
|
||||
GNU tar-@value{VERSION}-2
|
||||
@end smallexample
|
||||
|
||||
This line is followed by newline. Rest of file consists of
|
||||
records, separated by null (@acronym{ASCII} 0)
|
||||
characters. Thus, in contrast to the previous formats, format 2
|
||||
snapshot is a binary file.
|
||||
|
||||
First two records are decimal numbers, representing the
|
||||
time of the last backup. First number is the number of seconds, the
|
||||
second one is the number of nanoseconds, since the beginning of the
|
||||
epoch. These are followed by arbitrary number of directory records.
|
||||
|
||||
Each @dfn{directory record} contains a set of metadata describing a
|
||||
particular directory. Parts of a directory record are delimited with
|
||||
@acronym{ASCII} 0 characters. The following table describes each
|
||||
part. The @dfn{Number} type in this table stands for a decimal number
|
||||
in @acronym{ASCII} notation.
|
||||
|
||||
@multitable @columnfractions 0.2 0.2 0.6
|
||||
@headitem Field @tab Type @tab Description
|
||||
@item nfs @tab Character @tab @samp{1} if the directory is located on
|
||||
an @acronym{NFS}-mounted partition, or @samp{0} otherwise;
|
||||
@item mtime-sec @tab Number @tab Modification time, seconds;
|
||||
@item mtime-nano @tab Number @tab Modification time, nanoseconds;
|
||||
@item dev-no @tab Number @tab Device number;
|
||||
@item i-no @tab Number @tab I-node number;
|
||||
@item name @tab String @tab Directory name; In contrast to the
|
||||
previous versions it is not quoted.
|
||||
@item contents @tab Dumpdir @tab Contents of the directory;
|
||||
@xref{Dumpdir}, for a description of its format.
|
||||
@item
|
||||
@end multitable
|
||||
|
||||
Dumpdirs stored in snapshot files contain only records of types
|
||||
@samp{Y}, @samp{N} and @samp{D}.
|
||||
|
||||
@end enumerate
|
||||
|
||||
@c End of snapshot.texi
|
||||
|
||||
|
||||
235
doc/sparse.texi
Normal file
235
doc/sparse.texi
Normal file
@@ -0,0 +1,235 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
@cindex sparse formats
|
||||
@cindex sparse versions
|
||||
The notion of sparse file, and the ways of handling it from the point
|
||||
of view of @GNUTAR{} user have been described in detail in
|
||||
@ref{sparse}. This chapter describes the internal format @GNUTAR{}
|
||||
uses to store such files.
|
||||
|
||||
The support for sparse files in @GNUTAR{} has a long history. The
|
||||
earliest version featuring this support that I was able to find was 1.09,
|
||||
released in November, 1990. The format introduced back then is called
|
||||
@dfn{old GNU} sparse format and in spite of the fact that its design
|
||||
contained many flaws, it was the only format @GNUTAR{} supported
|
||||
until version 1.14 (May, 2004), which introduced initial support for
|
||||
sparse archives in @acronym{PAX} archives (@pxref{posix}). This
|
||||
format was not free from design flows, either and it was subsequently
|
||||
improved in versions 1.15.2 (November, 2005) and 1.15.92 (June,
|
||||
2006).
|
||||
|
||||
In addition to GNU sparse format, @GNUTAR{} is able to read and
|
||||
extract sparse files archived by @command{star}.
|
||||
|
||||
The following subsections describe each format in detail.
|
||||
|
||||
@menu
|
||||
* Old GNU Format::
|
||||
* PAX 0:: PAX Format, Versions 0.0 and 0.1
|
||||
* PAX 1:: PAX Format, Version 1.0
|
||||
@end menu
|
||||
|
||||
@node Old GNU Format
|
||||
@appendixsubsec Old GNU Format
|
||||
|
||||
@cindex sparse formats, Old GNU
|
||||
@cindex Old GNU sparse format
|
||||
The format introduced some time around 1990 (v. 1.09). It was
|
||||
designed on top of standard @code{ustar} headers in such an
|
||||
unfortunate way that some of its fields overwrote fields required by
|
||||
POSIX.
|
||||
|
||||
An old GNU sparse header is designated by type @samp{S}
|
||||
(@code{GNUTYPE_SPARSE}) and has the following layout:
|
||||
|
||||
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
|
||||
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
|
||||
@item 0 @tab 345 @tab @tab N/A @tab Not used.
|
||||
@item 345 @tab 12 @tab atime @tab Number @tab @code{atime} of the file.
|
||||
@item 357 @tab 12 @tab ctime @tab Number @tab @code{ctime} of the file .
|
||||
@item 369 @tab 12 @tab offset @tab Number @tab For
|
||||
multivolume archives: the offset of the start of this volume.
|
||||
@item 381 @tab 4 @tab @tab N/A @tab Not used.
|
||||
@item 385 @tab 1 @tab @tab N/A @tab Not used.
|
||||
@item 386 @tab 96 @tab sp @tab @code{sparse_header} @tab (4 entries) File map.
|
||||
@item 482 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
|
||||
extension sparse header follows, @code{0} otherwise.
|
||||
@item 483 @tab 12 @tab realsize @tab Number @tab Real size of the file.
|
||||
@end multitable
|
||||
|
||||
Each of @code{sparse_header} object at offset 386 describes a single
|
||||
data chunk. It has the following structure:
|
||||
|
||||
@multitable @columnfractions 0.10 0.10 0.20 0.60
|
||||
@headitem Offset @tab Size @tab Data type @tab Contents
|
||||
@item 0 @tab 12 @tab Number @tab Offset of the
|
||||
beginning of the chunk.
|
||||
@item 12 @tab 12 @tab Number @tab Size of the chunk.
|
||||
@end multitable
|
||||
|
||||
If the member contains more than four chunks, the @code{isextended}
|
||||
field of the header has the value @code{1} and the main header is
|
||||
followed by one or more @dfn{extension headers}. Each such header has
|
||||
the following structure:
|
||||
|
||||
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
|
||||
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
|
||||
@item 0 @tab 21 @tab sp @tab @code{sparse_header} @tab
|
||||
(21 entires) File map.
|
||||
@item 504 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
|
||||
extension sparse header follows, or @code{0} otherwise.
|
||||
@end multitable
|
||||
|
||||
A header with @code{isextended=0} ends the map.
|
||||
|
||||
@node PAX 0
|
||||
@appendixsubsec PAX Format, Versions 0.0 and 0.1
|
||||
|
||||
@cindex sparse formats, v.0.0
|
||||
There are two formats available in this branch. The version @code{0.0}
|
||||
is the initial version of sparse format used by @command{tar}
|
||||
versions 1.14--1.15.1. The sparse file map is kept in extended
|
||||
(@code{x}) PAX header variables:
|
||||
|
||||
@table @code
|
||||
@vrindex GNU.sparse.size, extended header variable
|
||||
@item GNU.sparse.size
|
||||
Real size of the stored file
|
||||
|
||||
@item GNU.sparse.numblocks
|
||||
@vrindex GNU.sparse.numblocks, extended header variable
|
||||
Number of blocks in the sparse map
|
||||
|
||||
@item GNU.sparse.offset
|
||||
@vrindex GNU.sparse.offset, extended header variable
|
||||
Offset of the data block
|
||||
|
||||
@item GNU.sparse.numbytes
|
||||
@vrindex GNU.sparse.numbytes, extended header variable
|
||||
Size of the data block
|
||||
@end table
|
||||
|
||||
The latter two variables repeat for each data block, so the overall
|
||||
structure is like this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
GNU.sparse.size=@var{size}
|
||||
GNU.sparse.numblocks=@var{numblocks}
|
||||
repeat @var{numblocks} times
|
||||
GNU.sparse.offset=@var{offset}
|
||||
GNU.sparse.numbytes=@var{numbytes}
|
||||
end repeat
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
This format presented the following two problems:
|
||||
|
||||
@enumerate 1
|
||||
@item
|
||||
Whereas the POSIX specification allows a variable to appear multiple
|
||||
times in a header, it requires that only the last occurrence be
|
||||
meaningful. Thus, multiple occurrences of @code{GNU.sparse.offset} and
|
||||
@code{GNU.sparse.numbytes} are conflicting with the POSIX specs.
|
||||
|
||||
@item
|
||||
Attempting to extract such archives using a third-party @command{tar}s
|
||||
results in extraction of sparse files in @emph{compressed form}. If
|
||||
the @command{tar} implementation in question does not support POSIX
|
||||
format, it will also extract a file containing extension header
|
||||
attributes. This file can be used to expand the file to its original
|
||||
state. However, posix-aware @command{tar}s will usually ignore the
|
||||
unknown variables, which makes restoring the file more
|
||||
difficult. @xref{extracting sparse v.0.x, Extraction of sparse
|
||||
members in v.0.0 format}, for the detailed description of how to
|
||||
restore such members using non-GNU @command{tar}s.
|
||||
@end enumerate
|
||||
|
||||
@cindex sparse formats, v.0.1
|
||||
@GNUTAR{} 1.15.2 introduced sparse format version @code{0.1}, which
|
||||
attempted to solve these problems. As its predecessor, this format
|
||||
stores sparse map in the extended POSIX header. It retains
|
||||
@code{GNU.sparse.size} and @code{GNU.sparse.numblocks} variables, but
|
||||
instead of @code{GNU.sparse.offset}/@code{GNU.sparse.numbytes} pairs
|
||||
it uses a single variable:
|
||||
|
||||
@table @code
|
||||
@item GNU.sparse.map
|
||||
@vrindex GNU.sparse.map, extended header variable
|
||||
Map of non-null data chunks. It is a string consisting of
|
||||
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
|
||||
@end table
|
||||
|
||||
To address the 2nd problem, the @code{name} field in @code{ustar}
|
||||
is replaced with a special name, constructed using the following pattern:
|
||||
|
||||
@smallexample
|
||||
%d/GNUSparseFile.%p/%f
|
||||
@end smallexample
|
||||
|
||||
@vrindex GNU.sparse.name, extended header variable
|
||||
The real name of the sparse file is stored in the variable
|
||||
@code{GNU.sparse.name}. Thus, those @command{tar} implementations
|
||||
that are not aware of GNU extensions will at least extract the files
|
||||
into separate directories, giving the user a possibility to expand it
|
||||
afterwards. @xref{extracting sparse v.0.x, Extraction of sparse
|
||||
members in v.0.1 format}, for the detailed description of how to
|
||||
restore such members using non-GNU @command{tar}s.
|
||||
|
||||
The resulting @code{GNU.sparse.map} string can be @emph{very} long.
|
||||
Although POSIX does not impose any limit on the length of a @code{x}
|
||||
header variable, this possibly can confuse some tars.
|
||||
|
||||
@node PAX 1
|
||||
@appendixsubsec PAX Format, Version 1.0
|
||||
|
||||
@cindex sparse formats, v.1.0
|
||||
The version @code{1.0} of sparse format was introduced with @GNUTAR{}
|
||||
1.15.92. Its main objective was to make the resulting file
|
||||
extractable with little effort even by non-posix aware @command{tar}
|
||||
implementations. Starting from this version, the extended header
|
||||
preceding a sparse member always contains the following variables that
|
||||
identify the format being used:
|
||||
|
||||
@table @code
|
||||
@item GNU.sparse.major
|
||||
@vrindex GNU.sparse.major, extended header variable
|
||||
Major version
|
||||
|
||||
@item GNU.sparse.minor
|
||||
@vrindex GNU.sparse.minor, extended header variable
|
||||
Minor version
|
||||
@end table
|
||||
|
||||
The @code{name} field in @code{ustar} header contains a special name,
|
||||
constructed using the following pattern:
|
||||
|
||||
@smallexample
|
||||
%d/GNUSparseFile.%p/%f
|
||||
@end smallexample
|
||||
|
||||
@vrindex GNU.sparse.name, extended header variable, in v.1.0
|
||||
@vrindex GNU.sparse.realsize, extended header variable
|
||||
The real name of the sparse file is stored in the variable
|
||||
@code{GNU.sparse.name}. The real size of the file is stored in the
|
||||
variable @code{GNU.sparse.realsize}.
|
||||
|
||||
The sparse map itself is stored in the file data block, preceding the actual
|
||||
file data. It consists of a series of octal numbers of arbitrary length, delimited
|
||||
by newlines. The map is padded with nulls to the nearest block boundary.
|
||||
|
||||
The first number gives the number of entries in the map. Following are map entries,
|
||||
each one consisting of two numbers giving the offset and size of the
|
||||
data block it describes.
|
||||
|
||||
The format is designed in such a way that non-posix aware tars and tars not
|
||||
supporting @code{GNU.sparse.*} keywords will extract each sparse file
|
||||
in its condensed form with the file map prepended and will place it
|
||||
into a separate directory. Then, using a simple program it would be
|
||||
possible to expand the file to its original form even without @GNUTAR{}.
|
||||
@xref{Sparse Recovery}, for the detailed information on how to extract
|
||||
sparse members without @GNUTAR{}.
|
||||
|
||||
58
doc/tar-snapshot-edit.texi
Normal file
58
doc/tar-snapshot-edit.texi
Normal file
@@ -0,0 +1,58 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
@c This file is distributed under GFDL 1.1 or any later version
|
||||
@c published by the Free Software Foundation.
|
||||
|
||||
@cindex Device numbers, changing
|
||||
@cindex snapshot files, editing
|
||||
@cindex snapshot files, fixing device numbers
|
||||
Sometimes device numbers can change after upgrading your kernel
|
||||
version or recofiguring the harvare. Reportedly this is the case with
|
||||
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
|
||||
cases this change is unnoticed by the users. However, it influences
|
||||
@command{tar} incremental backups: the device number is stored in tar
|
||||
snapshot files (@pxref{Snapshot Files}) and is used to determine whether
|
||||
the file has changed since the last backup. If the device numbers
|
||||
change for some reason, the next backup you run will be a full backup.
|
||||
|
||||
@pindex tar-snapshot-edit
|
||||
To minimize the impact in these cases, GNU @command{tar} comes with
|
||||
the @command{tar-snapshot-edit} utility for inspecting and updating
|
||||
device numbers in snapshot files. The utility, written by
|
||||
Dustin J.@: Mitchell, is available from
|
||||
@uref{http://www.gnu.org/@/software/@/tar/@/utils/@/tar-snapshot-edit.html,
|
||||
@GNUTAR{} home page}.
|
||||
|
||||
To obtain the device numbers used in the snapshot file, run
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar-snapshot-edit @var{snapfile}}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where @var{snapfile} is the name of the snapshot file (you can supply as many
|
||||
files as you wish in a single command line ).
|
||||
|
||||
To update all occurrences of the given device number in the file, use
|
||||
@option{-r} option. It takes a single argument of the form
|
||||
@samp{@var{olddev}-@var{newdev}}, where @var{olddev} is the device number
|
||||
used in the snapshot file, and @var{newdev} is the corresponding new device
|
||||
number. Both numbers may be specified in hex (e.g., @samp{0xfe01}),
|
||||
decimal (e.g., @samp{65025}), or as a major:minor number pair (e.g.,
|
||||
@samp{254:1}). To change several device numbers at once, specify them
|
||||
in a single comma-separated list, as in
|
||||
@option{-r 0x3060-0x4500,0x307-0x4600}.
|
||||
|
||||
Before updating the snapshot file, it is a good idea to create a backup
|
||||
copy of it. This is accomplished by @samp{-b} option. The name of the
|
||||
backup file is obtained by appending @samp{~} to the original file name.
|
||||
|
||||
An example session:
|
||||
@smallexample
|
||||
$ @kbd{tar-snapshot-edit /var/backup/snap.a}
|
||||
file version 2
|
||||
/tmp/snap: Device 0x0306 occurs 634 times.
|
||||
$ @kbd{tar-snapshot-edit -b -r 0x0306-0x4500 /var/backup/snap.a}
|
||||
file version 2
|
||||
@end smallexample
|
||||
|
||||
2826
doc/tar.texi
2826
doc/tar.texi
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
# 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 2, or (at
|
||||
# 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
|
||||
|
||||
13
doc/untabify.el
Normal file
13
doc/untabify.el
Normal file
@@ -0,0 +1,13 @@
|
||||
;;;; Untabify the sources.
|
||||
;;;; Usage: emacs -batch -l untabify.el [file ...]
|
||||
|
||||
(defun global-untabify (buflist)
|
||||
(mapcar
|
||||
(lambda (bufname)
|
||||
(set-buffer (find-file bufname))
|
||||
(untabify (point-min) (point-max))
|
||||
(save-buffer)
|
||||
(kill-buffer (current-buffer)))
|
||||
buflist))
|
||||
|
||||
(global-untabify command-line-args-left)
|
||||
@@ -6,12 +6,14 @@ argmatch
|
||||
argp
|
||||
backupfile
|
||||
closeout
|
||||
configmake
|
||||
dirname
|
||||
error
|
||||
exclude
|
||||
exitfail
|
||||
fileblocks
|
||||
fnmatch-gnu
|
||||
fseeko
|
||||
ftruncate
|
||||
full-write
|
||||
getdate
|
||||
@@ -22,6 +24,7 @@ gettext
|
||||
gettime
|
||||
hash
|
||||
human
|
||||
inttypes
|
||||
lchown
|
||||
localcharset
|
||||
memset
|
||||
@@ -36,10 +39,13 @@ safe-read
|
||||
save-cwd
|
||||
savedir
|
||||
setenv
|
||||
snprintf
|
||||
stat-time
|
||||
stdbool
|
||||
stdint
|
||||
stpcpy
|
||||
strdup
|
||||
strerror
|
||||
strtol
|
||||
strtoul
|
||||
timespec
|
||||
|
||||
132
lib/.cvsignore
132
lib/.cvsignore
@@ -1,15 +1,10 @@
|
||||
.cvsignore
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.am
|
||||
Makefile.in
|
||||
__fpending.c
|
||||
__fpending.h
|
||||
alloca.c
|
||||
alloca.h
|
||||
alloca_.h
|
||||
allocsa.c
|
||||
allocsa.h
|
||||
allocsa.valgrind
|
||||
alloca.in.h
|
||||
argmatch.c
|
||||
argmatch.h
|
||||
argp-ba.c
|
||||
@@ -26,61 +21,83 @@ argp-pvh.c
|
||||
argp-xinl.c
|
||||
argp.h
|
||||
asnprintf.c
|
||||
atexit.c
|
||||
at-func.c
|
||||
backupfile.c
|
||||
backupfile.h
|
||||
basename.c
|
||||
c-ctype.c
|
||||
c-ctype.h
|
||||
canonicalize-lgpl.c
|
||||
canonicalize.h
|
||||
charset.alias
|
||||
chdir-long.c
|
||||
chdir-long.h
|
||||
chown.c
|
||||
close-stream.c
|
||||
close-stream.h
|
||||
close.c
|
||||
closeout.c
|
||||
closeout.h
|
||||
config.charset
|
||||
configmake.h
|
||||
creat-safer.c
|
||||
dirent.h
|
||||
dirent.in.h
|
||||
dirfd.c
|
||||
dirfd.h
|
||||
dirname.c
|
||||
dirname.h
|
||||
dup-safer.c
|
||||
dup2.c
|
||||
errno.in.h
|
||||
error.c
|
||||
error.h
|
||||
exclude.c
|
||||
exclude.h
|
||||
exit.c
|
||||
exit.h
|
||||
exitfail.c
|
||||
exitfail.h
|
||||
fchdir.c
|
||||
fchmodat.c
|
||||
fchown-stub.c
|
||||
fchownat.c
|
||||
fclose.c
|
||||
fcntl--.h
|
||||
fcntl-safer.h
|
||||
fcntl.h
|
||||
fcntl.in.h
|
||||
fd-safer.c
|
||||
fileblocks.c
|
||||
float+.h
|
||||
float.h
|
||||
float.in.h
|
||||
fnmatch.c
|
||||
fnmatch.h
|
||||
fnmatch_.h
|
||||
fnmatch.in.h
|
||||
fnmatch_loop.c
|
||||
fpending.c
|
||||
fpending.h
|
||||
fseeko.c
|
||||
fstatat.c
|
||||
ftruncate.c
|
||||
full-write.c
|
||||
full-write.h
|
||||
getcwd.c
|
||||
getcwd.h
|
||||
getdate.c
|
||||
getdate.h
|
||||
getdate.y
|
||||
getdelim.c
|
||||
getdelim.h
|
||||
getline.c
|
||||
getline.h
|
||||
getndelim2.c
|
||||
getndelim2.h
|
||||
getopt.c
|
||||
getopt.h
|
||||
getopt.in.h
|
||||
getopt1.c
|
||||
getopt_.h
|
||||
getopt_int.h
|
||||
getpagesize.c
|
||||
getpagesize.h
|
||||
gettext.h
|
||||
gettime.c
|
||||
gettimeofday.c
|
||||
gnulib.mk
|
||||
hash.c
|
||||
hash.h
|
||||
human.c
|
||||
@@ -89,39 +106,43 @@ imaxtostr.c
|
||||
intprops.h
|
||||
inttostr.c
|
||||
inttostr.h
|
||||
inttypes.h
|
||||
inttypes.in.h
|
||||
lchown.c
|
||||
lchown.h
|
||||
localcharset.c
|
||||
localcharset.h
|
||||
localedir.h
|
||||
lseek.c
|
||||
lstat.c
|
||||
lstat.h
|
||||
malloc.c
|
||||
malloca.c
|
||||
malloca.h
|
||||
malloca.valgrind
|
||||
mbchar.c
|
||||
mbchar.h
|
||||
mbscasecmp.c
|
||||
mbuiter.h
|
||||
memchr.c
|
||||
mempcpy.c
|
||||
mempcpy.h
|
||||
memrchr.c
|
||||
memrchr.h
|
||||
memset.c
|
||||
minmax.h
|
||||
mkdirat.c
|
||||
mkdtemp.c
|
||||
mkdtemp.h
|
||||
mktime.c
|
||||
modechange.c
|
||||
modechange.h
|
||||
obstack.c
|
||||
obstack.h
|
||||
offtostr.c
|
||||
open-safer.c
|
||||
open.c
|
||||
openat-die.c
|
||||
openat-priv.h
|
||||
openat-proc.c
|
||||
openat.c
|
||||
openat.h
|
||||
pathmax.h
|
||||
paxconvert.c
|
||||
paxerror.c
|
||||
paxerror.h
|
||||
paxexit.c
|
||||
paxlib.h
|
||||
paxnames.c
|
||||
@@ -134,6 +155,10 @@ quote.c
|
||||
quote.h
|
||||
quotearg.c
|
||||
quotearg.h
|
||||
rawmemchr.c
|
||||
rawmemchr.valgrind
|
||||
readlink.c
|
||||
realloc.c
|
||||
ref-add.sed
|
||||
ref-add.sin
|
||||
ref-del.sed
|
||||
@@ -145,6 +170,7 @@ regex_internal.c
|
||||
regex_internal.h
|
||||
regexec.c
|
||||
rmdir.c
|
||||
rmt-command.h
|
||||
rmt.h
|
||||
rpmatch.c
|
||||
rtapelib.c
|
||||
@@ -152,31 +178,42 @@ safe-read.c
|
||||
safe-read.h
|
||||
safe-write.c
|
||||
safe-write.h
|
||||
same-inode.h
|
||||
save-cwd.c
|
||||
save-cwd.h
|
||||
savedir.c
|
||||
savedir.h
|
||||
setenv.c
|
||||
setenv.h
|
||||
size_max.h
|
||||
sleep.c
|
||||
snprintf.c
|
||||
stat-macros.h
|
||||
stat-time.h
|
||||
stdarg.in.h
|
||||
stdbool.h
|
||||
stdbool_.h
|
||||
stdbool.in.h
|
||||
stdint.h
|
||||
stdint.in.h
|
||||
stdio-impl.h
|
||||
stdio-write.c
|
||||
stdio.h
|
||||
stdio.in.h
|
||||
stdlib.h
|
||||
stdlib.in.h
|
||||
stpcpy.c
|
||||
stpcpy.h
|
||||
strcase.h
|
||||
strcasecmp.c
|
||||
strchrnul.c
|
||||
strchrnul.h
|
||||
strchrnul.valgrind
|
||||
strdup.c
|
||||
strdup.h
|
||||
streq.h
|
||||
strerror.c
|
||||
string.h
|
||||
string.in.h
|
||||
strings.in.h
|
||||
stripslash.c
|
||||
strncasecmp.c
|
||||
strndup.c
|
||||
strndup.h
|
||||
strnlen.c
|
||||
strnlen.h
|
||||
strnlen1.c
|
||||
strnlen1.h
|
||||
strtoimax.c
|
||||
@@ -185,16 +222,30 @@ strtoll.c
|
||||
strtoul.c
|
||||
strtoull.c
|
||||
strtoumax.c
|
||||
sysexit_.h
|
||||
sys
|
||||
sys_stat.h
|
||||
sys_stat.in.h
|
||||
sys_time.h
|
||||
sys_time.in.h
|
||||
sysexits.h
|
||||
sysexits.in.h
|
||||
system-ioctl.h
|
||||
system.h
|
||||
tempname.c
|
||||
tempname.h
|
||||
time.h
|
||||
time.in.h
|
||||
time_r.c
|
||||
time_r.h
|
||||
timespec.h
|
||||
uinttostr.c
|
||||
umaxtostr.c
|
||||
unistd--.h
|
||||
unistd-safer.h
|
||||
unistd.h
|
||||
unistd.in.h
|
||||
unitypes.h
|
||||
uniwidth
|
||||
uniwidth.h
|
||||
unlinkdir.c
|
||||
unlinkdir.h
|
||||
unlocked-io.h
|
||||
@@ -209,14 +260,21 @@ version-etc-fsf.c
|
||||
version-etc.c
|
||||
version-etc.h
|
||||
vsnprintf.c
|
||||
vsnprintf.h
|
||||
wchar.h
|
||||
wchar.in.h
|
||||
wctype.h
|
||||
wctype.in.h
|
||||
wcwidth.c
|
||||
write.c
|
||||
xalloc-die.c
|
||||
xalloc.h
|
||||
xgetcwd.c
|
||||
xgetcwd.h
|
||||
xmalloc.c
|
||||
xsize.h
|
||||
xstrdup.c
|
||||
xstrndup.c
|
||||
xstrndup.h
|
||||
xstrtol-error.c
|
||||
xstrtol.c
|
||||
xstrtol.h
|
||||
xstrtoul.c
|
||||
|
||||
41
lib/Makefile.am
Normal file
41
lib/Makefile.am
Normal file
@@ -0,0 +1,41 @@
|
||||
# Makefile for GNU tar library. -*- Makefile -*-
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
|
||||
# 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
include gnulib.mk
|
||||
|
||||
rmt-command.h : Makefile
|
||||
rm -f $@-t $@
|
||||
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
|
||||
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
|
||||
echo "#endif" >> $@-t
|
||||
mv $@-t $@
|
||||
BUILT_SOURCES += rmt-command.h
|
||||
CLEANFILES += rmt-command.h rmt-command.h-t
|
||||
|
||||
noinst_HEADERS += system.h system-ioctl.h rmt.h paxlib.h stdopen.h
|
||||
libtar_a_SOURCES += \
|
||||
paxerror.c paxexit.c paxlib.h paxnames.c \
|
||||
prepargs.c prepargs.h \
|
||||
rtapelib.c \
|
||||
rmt.h \
|
||||
stdopen.c stdopen.h \
|
||||
system.h system-ioctl.h
|
||||
|
||||
libtar_a_LIBADD += $(LIBOBJS)
|
||||
libtar_a_DEPENDENCIES += $(LIBOBJS)
|
||||
@@ -1,56 +0,0 @@
|
||||
# Makefile for GNU tar library. -*- Makefile -*-
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
|
||||
# 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
noinst_LIBRARIES = libtar.a
|
||||
noinst_HEADERS = system.h system-ioctl.h localedir.h rmt.h paxlib.h stdopen.h
|
||||
libtar_a_SOURCES = prepargs.c prepargs.h rtapelib.c paxerror.c paxexit.c paxnames.c stdopen.c
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
|
||||
DISTCLEANFILES = localedir.h
|
||||
localedir.h : Makefile
|
||||
echo '#define LOCALEDIR "$(localedir)"' >$@
|
||||
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@
|
||||
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@
|
||||
echo "#endif" >> $@
|
||||
|
||||
rtapelib.o: localedir.h
|
||||
|
||||
libtar_a_LIBADD = $(LIBOBJS) $(ALLOCA)
|
||||
libtar_a_DEPENDENCIES = $(libtar_a_LIBADD)
|
||||
|
||||
BUILT_SOURCES =
|
||||
AM_CPPFLAGS =
|
||||
EXTRA_DIST = Makefile.tmpl
|
||||
MAINTAINERCLEANFILES =
|
||||
MOSTLYCLEANFILES =
|
||||
lib_OBJECTS = $(libtar_a_OBJECTS)
|
||||
|
||||
# Special rule for getdate
|
||||
#
|
||||
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
|
||||
$(srcdir)/getdate.c: getdate.y
|
||||
cd $(srcdir) && \
|
||||
$(YACC) $(YFLAGS) getdate.y && \
|
||||
mv -f y.tab.c getdate.c
|
||||
|
||||
SUFFIXES = .o .c .h
|
||||
CLEANFILES =
|
||||
# gnulib modules
|
||||
@@ -1,9 +1,9 @@
|
||||
/* Parse arguments from a string and prepend them to an argv.
|
||||
Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
Copyright 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* stdopen.c - ensure that the three standard file descriptors are in use
|
||||
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* Emulate waitpid on systems that just have wait.
|
||||
Copyright 1994, 1995, 1998, 1999 Free Software Foundation, Inc.
|
||||
Copyright 1994, 1995, 1998, 1999, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.m4
|
||||
@@ -1,20 +0,0 @@
|
||||
index.html
|
||||
*.po
|
||||
LINGUAS
|
||||
Makefile.in.in
|
||||
Makevars.template
|
||||
Rules-quot
|
||||
boldquot.sed
|
||||
en@boldquot.header
|
||||
en@quot.header
|
||||
insert-header.sin
|
||||
quot.sed
|
||||
remove-potcdate.sin
|
||||
Makefile.in
|
||||
POTFILES
|
||||
Makefile
|
||||
tar.pot
|
||||
remove-potcdate.sed
|
||||
*.gmo
|
||||
*.mo
|
||||
stamp-po
|
||||
41
po/Makevars
41
po/Makevars
@@ -1,41 +0,0 @@
|
||||
# Makefile variables for PO directory in any package using GNU gettext.
|
||||
|
||||
# Usually the message domain is the same as the package name.
|
||||
DOMAIN = $(PACKAGE)
|
||||
|
||||
# These two variables depend on the location of this directory.
|
||||
subdir = po
|
||||
top_builddir = ..
|
||||
|
||||
# These options get passed to xgettext.
|
||||
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
|
||||
|
||||
# This is the copyright holder that gets inserted into the header of the
|
||||
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
|
||||
# package. (Note that the msgstr strings, extracted from the package's
|
||||
# sources, belong to the copyright holder of the package.) Translators are
|
||||
# expected to transfer the copyright for their translations to this person
|
||||
# or entity, or to disclaim their copyright. The empty string stands for
|
||||
# the public domain; in this case the translators are expected to disclaim
|
||||
# their copyright.
|
||||
COPYRIGHT_HOLDER = Free Software Foundation, Inc.
|
||||
|
||||
# This is the email address or URL to which the translators shall report
|
||||
# bugs in the untranslated strings:
|
||||
# - Strings which are not entire sentences, see the maintainer guidelines
|
||||
# in the GNU gettext documentation, section 'Preparing Strings'.
|
||||
# - Strings which use unclear terms or require additional context to be
|
||||
# understood.
|
||||
# - Strings which make invalid assumptions about notation of date, time or
|
||||
# money.
|
||||
# - Pluralisation problems.
|
||||
# - Incorrect English spelling.
|
||||
# - Incorrect formatting.
|
||||
# It can be your email address, or a mailing list address where translators
|
||||
# can write to without being subscribed, or the URL of a web page through
|
||||
# which the translators can contact you.
|
||||
MSGID_BUGS_ADDRESS = bug-tar@gnu.org
|
||||
|
||||
# This is the list of locale categories, beyond LC_MESSAGES, for which the
|
||||
# message catalogs shall be used. It is usually empty.
|
||||
EXTRA_LOCALE_CATEGORIES =
|
||||
@@ -1,11 +1,11 @@
|
||||
# List of files which contain translatable strings.
|
||||
|
||||
# Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005 Free Software
|
||||
# Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005, 2007 Free Software
|
||||
# Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -22,10 +22,13 @@
|
||||
lib/argmatch.c
|
||||
lib/argp-help.c
|
||||
lib/argp-parse.c
|
||||
lib/closeout.c
|
||||
lib/error.c
|
||||
lib/getopt.c
|
||||
lib/obstack.c
|
||||
lib/human.c
|
||||
lib/obstack.c
|
||||
lib/openat-die.c
|
||||
lib/paxerror.c
|
||||
lib/paxexit.c
|
||||
lib/paxnames.c
|
||||
@@ -34,6 +37,8 @@ lib/rpmatch.c
|
||||
lib/rtapelib.c
|
||||
lib/xalloc-die.c
|
||||
lib/xmalloc.c
|
||||
lib/version-etc.c
|
||||
lib/xalloc-die.c
|
||||
|
||||
rmt/rmt.c
|
||||
|
||||
@@ -46,12 +51,12 @@ src/delete.c
|
||||
src/extract.c
|
||||
src/incremen.c
|
||||
src/list.c
|
||||
src/mangle.c
|
||||
src/misc.c
|
||||
src/names.c
|
||||
src/tar.c
|
||||
src/update.c
|
||||
src/xheader.c
|
||||
src/checkpoint.c
|
||||
|
||||
# Testsuite
|
||||
tests/genfile.c
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## the Free Software Foundation; either version 3, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -82,11 +82,11 @@ SLEEP_MESSAGE="`awk '
|
||||
}' /dev/null`"
|
||||
|
||||
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## the Free Software Foundation; either version 3, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
|
||||
328
scripts/tar-snapshot-edit
Executable file
328
scripts/tar-snapshot-edit
Executable file
@@ -0,0 +1,328 @@
|
||||
#! /usr/bin/perl -w
|
||||
# Display and edit the 'dev' field in tar's snapshots
|
||||
# Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# Author: Dustin J. Mitchell <dustin@zmanda.com>
|
||||
#
|
||||
# This script is capable of replacing values in the 'dev' field of an
|
||||
# incremental backup 'snapshot' file. This is useful when the device
|
||||
# used to store files in a tar archive changes, without the files
|
||||
# themselves changing. This may happen when, for example, a device
|
||||
# driver changes major or minor numbers.
|
||||
|
||||
use Getopt::Std;
|
||||
|
||||
## reading
|
||||
|
||||
sub read_incr_db ($) {
|
||||
my $filename = shift;
|
||||
open(my $file, "<$filename") || die "Could not open '$filename' for reading";
|
||||
|
||||
my $header_str = <$file>;
|
||||
my $file_version;
|
||||
if ($header_str =~ /^GNU tar-[^-]*-([0-9]+)\n$/) {
|
||||
$file_version = $1+0;
|
||||
} else {
|
||||
$file_version = 0;
|
||||
}
|
||||
|
||||
print "file version $file_version\n";
|
||||
|
||||
if ($file_version == 0) {
|
||||
return read_incr_db_0($file, $header_str);
|
||||
} elsif ($file_version == 1) {
|
||||
return read_incr_db_1($file);
|
||||
} elsif ($file_version == 2) {
|
||||
return read_incr_db_2($file);
|
||||
} else {
|
||||
die "Unrecognized snapshot version in header '$header_str'";
|
||||
}
|
||||
}
|
||||
|
||||
sub read_incr_db_0 ($$) {
|
||||
my $file = shift;
|
||||
my $header_str = shift;
|
||||
|
||||
my $hdr_timestamp_sec = $header_str;
|
||||
chop $hdr_timestamp_sec;
|
||||
my $hdr_timestamp_nsec = ''; # not present in file format 0
|
||||
|
||||
my @dirs;
|
||||
|
||||
while (<$file>) {
|
||||
/^([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
|
||||
|
||||
push @dirs, { dev=>$1,
|
||||
ino=>$2,
|
||||
name=>$3 };
|
||||
}
|
||||
|
||||
close($file);
|
||||
|
||||
# file version, timestamp, timestamp, dir list
|
||||
return [ 0, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
|
||||
}
|
||||
|
||||
sub read_incr_db_1 ($) {
|
||||
my $file = shift;
|
||||
|
||||
my $timestamp = <$file>; # "sec nsec"
|
||||
my ($hdr_timestamp_sec, $hdr_timestamp_nsec) = ($timestamp =~ /([0-9]*) ([0-9]*)/);
|
||||
|
||||
my @dirs;
|
||||
|
||||
while (<$file>) {
|
||||
/^([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*) (.*)\n$/ || die("Bad snapshot line $_");
|
||||
|
||||
push @dirs, { timestamp_sec=>$1,
|
||||
timestamp_nsec=>$2,
|
||||
dev=>$3,
|
||||
ino=>$4,
|
||||
name=>$5 };
|
||||
}
|
||||
|
||||
close($file);
|
||||
|
||||
# file version, timestamp, timestamp, dir list
|
||||
return [ 1, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
|
||||
}
|
||||
|
||||
sub read_incr_db_2 ($) {
|
||||
my $file = shift;
|
||||
|
||||
$/="\0"; # $INPUT_RECORD_SEPARATOR
|
||||
my $hdr_timestamp_sec = <$file>;
|
||||
chop $hdr_timestamp_sec;
|
||||
my $hdr_timestamp_nsec = <$file>;
|
||||
chop $hdr_timestamp_nsec;
|
||||
my @dirs;
|
||||
|
||||
while (1) {
|
||||
last if eof($file);
|
||||
|
||||
my $nfs = <$file>;
|
||||
my $timestamp_sec = <$file>;
|
||||
my $timestamp_nsec = <$file>;
|
||||
my $dev = <$file>;
|
||||
my $ino = <$file>;
|
||||
my $name = <$file>;
|
||||
|
||||
# get rid of trailing NULs
|
||||
chop $nfs;
|
||||
chop $timestamp_sec;
|
||||
chop $timestamp_nsec;
|
||||
chop $dev;
|
||||
chop $ino;
|
||||
chop $name;
|
||||
|
||||
my @dirents;
|
||||
while (my $dirent = <$file>) {
|
||||
chop $dirent;
|
||||
push @dirents, $dirent;
|
||||
last if ($dirent eq "");
|
||||
}
|
||||
die "missing terminator" unless (<$file> eq "\0");
|
||||
|
||||
push @dirs, { nfs=>$nfs,
|
||||
timestamp_sec=>$timestamp_sec,
|
||||
timestamp_nsec=>$timestamp_nsec,
|
||||
dev=>$dev,
|
||||
ino=>$ino,
|
||||
name=>$name,
|
||||
dirents=>\@dirents };
|
||||
}
|
||||
|
||||
close($file);
|
||||
$/ = "\n"; # reset to normal
|
||||
|
||||
# file version, timestamp, timestamp, dir list
|
||||
return [ 2, $hdr_timestamp_sec, $hdr_timestamp_nsec, \@dirs ];
|
||||
}
|
||||
|
||||
## display
|
||||
|
||||
sub show_device_counts ($$) {
|
||||
my $info = shift;
|
||||
my $filename = shift;
|
||||
my %devices;
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
my $dev = ${%$dir}{'dev'};
|
||||
$devices{$dev}++;
|
||||
}
|
||||
|
||||
foreach $dev (sort keys %devices) {
|
||||
printf "$filename: Device 0x%04x occurs $devices{$dev} times.\n", $dev;
|
||||
}
|
||||
}
|
||||
|
||||
## editing
|
||||
|
||||
sub replace_device_number ($@) {
|
||||
my $info = shift(@_);
|
||||
my @repl = @_;
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
foreach $x (@repl) {
|
||||
if (${%$dir}{'dev'} eq $$x[0]) {
|
||||
${%$dir}{'dev'} = $$x[1];
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## writing
|
||||
|
||||
sub write_incr_db ($$) {
|
||||
my $info = shift;
|
||||
my $filename = shift;
|
||||
my $file_version = $$info[0];
|
||||
|
||||
open($file, ">$filename") || die "Could not open '$filename' for writing";
|
||||
|
||||
if ($file_version == 0) {
|
||||
write_incr_db_0($info, $file);
|
||||
} elsif ($file_version == 1) {
|
||||
write_incr_db_1($info, $file);
|
||||
} elsif ($file_version == 2) {
|
||||
write_incr_db_2($info, $file);
|
||||
} else {
|
||||
die "Unknown file version $file_version.";
|
||||
}
|
||||
|
||||
close($file);
|
||||
}
|
||||
|
||||
sub write_incr_db_0 ($$) {
|
||||
my $info = shift;
|
||||
my $file = shift;
|
||||
|
||||
my $timestamp_sec = $info->[1];
|
||||
print $file "$timestamp_sec\n";
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
print $file "${%$dir}{'dev'} ";
|
||||
print $file "${%$dir}{'ino'} ";
|
||||
print $file "${%$dir}{'name'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub write_incr_db_1 ($$) {
|
||||
my $info = shift;
|
||||
my $file = shift;
|
||||
|
||||
print $file "GNU tar-1.15-1\n";
|
||||
|
||||
my $timestamp_sec = $info->[1];
|
||||
my $timestamp_nsec = $info->[2];
|
||||
print $file "$timestamp_sec $timestamp_nsec\n";
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
print $file "${%$dir}{'timestamp_sec'} ";
|
||||
print $file "${%$dir}{'timestamp_nsec'} ";
|
||||
print $file "${%$dir}{'dev'} ";
|
||||
print $file "${%$dir}{'ino'} ";
|
||||
print $file "${%$dir}{'name'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub write_incr_db_2 ($$) {
|
||||
my $info = shift;
|
||||
my $file = shift;
|
||||
|
||||
print $file "GNU tar-1.16-2\n";
|
||||
|
||||
my $timestamp_sec = $info->[1];
|
||||
my $timestamp_nsec = $info->[2];
|
||||
print $file $timestamp_sec . "\0";
|
||||
print $file $timestamp_nsec . "\0";
|
||||
|
||||
foreach my $dir (@{${@$info}[3]}) {
|
||||
print $file ${%$dir}{'nfs'} . "\0";
|
||||
print $file ${%$dir}{'timestamp_sec'} . "\0";
|
||||
print $file ${%$dir}{'timestamp_nsec'} . "\0";
|
||||
print $file ${%$dir}{'dev'} . "\0";
|
||||
print $file ${%$dir}{'ino'} . "\0";
|
||||
print $file ${%$dir}{'name'} . "\0";
|
||||
foreach my $dirent (@{${%$dir}{'dirents'}}) {
|
||||
print $file $dirent . "\0";
|
||||
}
|
||||
print $file "\0";
|
||||
}
|
||||
}
|
||||
|
||||
## main
|
||||
|
||||
sub main {
|
||||
our ($opt_b, $opt_r, $opt_h);
|
||||
getopts('br:h');
|
||||
HELP_MESSAGE() if ($opt_h || $#ARGV == -1 || ($opt_b && !$opt_r));
|
||||
|
||||
my @repl;
|
||||
if ($opt_r) {
|
||||
foreach my $spec (split(/,/, $opt_r)) {
|
||||
($spec =~ /^([^-]+)-([^-]+)/) || die "Invalid replacement specification '$opt_r'";
|
||||
push @repl, [interpret_dev($1), interpret_dev($2)];
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $snapfile (@ARGV) {
|
||||
my $info = read_incr_db($snapfile);
|
||||
if ($opt_r ) {
|
||||
if ($opt_b) {
|
||||
rename($snapfile, $snapfile . "~") || die "Could not rename '$snapfile' to backup";
|
||||
}
|
||||
|
||||
replace_device_number($info, @repl);
|
||||
write_incr_db($info, $snapfile);
|
||||
} else {
|
||||
show_device_counts($info, $snapfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub HELP_MESSAGE {
|
||||
print "Usage: tar-snapshot-edit.pl [-r 'DEV1-DEV2[,DEV3-DEV4...]' [-b]] SNAPFILE [SNAPFILE [..]]\n";
|
||||
print "\n";
|
||||
print " Without -r, summarize the 'device' values in each SNAPFILE.\n";
|
||||
print "\n";
|
||||
print " With -r, replace occurrences of DEV1 with DEV2 in each SNAPFILE.\n";
|
||||
print " DEV1 and DEV2 may be specified in hex (e.g., 0xfe01), decimal (e.g.,\n";
|
||||
print " 65025), or MAJ:MIN (e.g., 254:1). To replace multiple occurrences,\n";
|
||||
print " separate them with commas. If -b is also specified, backup\n";
|
||||
print " files (ending with '~') will be created.\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub interpret_dev ($) {
|
||||
my $dev = shift;
|
||||
|
||||
if ($dev =~ /^([0-9]+):([0-9]+)$/) {
|
||||
return $1 * 256 + $2;
|
||||
} elsif ($dev =~ /^0x[0-9a-fA-F]+$/) {
|
||||
return oct $dev;
|
||||
} elsif ($dev =~ /^[0-9]+$/) {
|
||||
return $dev+0;
|
||||
} else {
|
||||
die "Invalid device specification '$dev'";
|
||||
}
|
||||
}
|
||||
|
||||
main
|
||||
473
scripts/xsparse.c
Normal file
473
scripts/xsparse.c
Normal file
@@ -0,0 +1,473 @@
|
||||
/* xsparse - expands compressed sparse file images extracted from GNU tar
|
||||
archives.
|
||||
|
||||
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by Sergey Poznyakoff
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Bound on length of the string representing an off_t.
|
||||
See INT_STRLEN_BOUND in intprops.h for explanation */
|
||||
#define OFF_T_STRLEN_BOUND ((sizeof (off_t) * CHAR_BIT) * 146 / 485 + 1)
|
||||
#define OFF_T_STRSIZE_BOUND (OFF_T_STRLEN_BOUND+1)
|
||||
|
||||
#define BLOCKSIZE 512
|
||||
|
||||
struct sp_array
|
||||
{
|
||||
off_t offset;
|
||||
size_t numbytes;
|
||||
};
|
||||
|
||||
char *progname;
|
||||
int verbose;
|
||||
|
||||
void
|
||||
die (int code, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
fprintf (stderr, "\n");
|
||||
exit (code);
|
||||
}
|
||||
|
||||
void *
|
||||
emalloc (size_t size)
|
||||
{
|
||||
char *p = malloc (size);
|
||||
if (!p)
|
||||
die (1, "not enough memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
off_t
|
||||
string_to_off (char *p, char **endp)
|
||||
{
|
||||
off_t v = 0;
|
||||
|
||||
for (; *p; p++)
|
||||
{
|
||||
int digit = *p - '0';
|
||||
off_t x = v * 10;
|
||||
if (9 < (unsigned) digit)
|
||||
{
|
||||
if (endp)
|
||||
{
|
||||
*endp = p;
|
||||
break;
|
||||
}
|
||||
die (1, "number parse error near %s", p);
|
||||
}
|
||||
else if (x / 10 != v)
|
||||
die (1, "number out of allowed range, near %s", p);
|
||||
v = x + digit;
|
||||
if (v < 0)
|
||||
die (1, "negative number");
|
||||
}
|
||||
if (endp)
|
||||
*endp = p;
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t
|
||||
string_to_size (char *p, char **endp)
|
||||
{
|
||||
off_t v = string_to_off (p, endp);
|
||||
size_t ret = v;
|
||||
if (ret != v)
|
||||
die (1, "number too big");
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t sparse_map_size;
|
||||
struct sp_array *sparse_map;
|
||||
|
||||
void
|
||||
get_line (char *s, int size, FILE *stream)
|
||||
{
|
||||
char *p = fgets (s, size, stream);
|
||||
size_t len;
|
||||
|
||||
if (!p)
|
||||
die (1, "unexpected end of file");
|
||||
len = strlen (p);
|
||||
if (s[len - 1] != '\n')
|
||||
die (1, "buffer overflow");
|
||||
s[len - 1] = 0;
|
||||
}
|
||||
|
||||
int
|
||||
get_var (FILE *fp, char **name, char **value)
|
||||
{
|
||||
static char *buffer;
|
||||
static size_t bufsize = OFF_T_STRSIZE_BOUND;
|
||||
char *p, *q;
|
||||
|
||||
buffer = emalloc (bufsize);
|
||||
do
|
||||
{
|
||||
size_t len, s;
|
||||
|
||||
if (!fgets (buffer, bufsize, fp))
|
||||
return 0;
|
||||
len = strlen (buffer);
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
s = string_to_size (buffer, &p);
|
||||
if (*p != ' ')
|
||||
die (1, "malformed header: expected space but found %s", p);
|
||||
if (buffer[len-1] != '\n')
|
||||
{
|
||||
if (bufsize < s + 1)
|
||||
{
|
||||
bufsize = s + 1;
|
||||
buffer = realloc (buffer, bufsize);
|
||||
if (!buffer)
|
||||
die (1, "not enough memory");
|
||||
}
|
||||
if (!fgets (buffer + len, s - len + 1, fp))
|
||||
die (1, "unexpected end of file or read error");
|
||||
}
|
||||
p++;
|
||||
}
|
||||
while (memcmp (p, "GNU.sparse.", 11));
|
||||
|
||||
p += 11;
|
||||
q = strchr (p, '=');
|
||||
if (!q)
|
||||
die (1, "malformed header: expected `=' not found");
|
||||
*q++ = 0;
|
||||
q[strlen (q) - 1] = 0;
|
||||
*name = p;
|
||||
*value = q;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *outname;
|
||||
off_t outsize;
|
||||
unsigned version_major;
|
||||
unsigned version_minor;
|
||||
|
||||
void
|
||||
read_xheader (char *name)
|
||||
{
|
||||
char *kw, *val;
|
||||
FILE *fp = fopen (name, "r");
|
||||
char *expect = NULL;
|
||||
size_t i = 0;
|
||||
|
||||
if (verbose)
|
||||
printf ("Reading extended header file\n");
|
||||
|
||||
while (get_var (fp, &kw, &val))
|
||||
{
|
||||
if (verbose)
|
||||
printf ("Found variable GNU.sparse.%s = %s\n", kw, val);
|
||||
|
||||
if (expect && strcmp (kw, expect))
|
||||
die (1, "bad keyword sequence: expected `%s' but found `%s'",
|
||||
expect, kw);
|
||||
expect = NULL;
|
||||
if (strcmp (kw, "name") == 0)
|
||||
{
|
||||
outname = emalloc (strlen (val) + 1);
|
||||
strcpy (outname, val);
|
||||
}
|
||||
else if (strcmp (kw, "major") == 0)
|
||||
{
|
||||
version_major = string_to_size (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "minor") == 0)
|
||||
{
|
||||
version_minor = string_to_size (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "realsize") == 0
|
||||
|| strcmp (kw, "size") == 0)
|
||||
{
|
||||
outsize = string_to_off (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "numblocks") == 0)
|
||||
{
|
||||
sparse_map_size = string_to_size (val, NULL);
|
||||
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
|
||||
}
|
||||
else if (strcmp (kw, "offset") == 0)
|
||||
{
|
||||
sparse_map[i].offset = string_to_off (val, NULL);
|
||||
expect = "numbytes";
|
||||
}
|
||||
else if (strcmp (kw, "numbytes") == 0)
|
||||
{
|
||||
sparse_map[i++].numbytes = string_to_size (val, NULL);
|
||||
}
|
||||
else if (strcmp (kw, "map") == 0)
|
||||
{
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
{
|
||||
sparse_map[i].offset = string_to_off (val, &val);
|
||||
if (*val != ',')
|
||||
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
|
||||
*val);
|
||||
sparse_map[i].numbytes = string_to_size (val+1, &val);
|
||||
if (*val != ',')
|
||||
{
|
||||
if (!(*val == 0 && i == sparse_map_size-1))
|
||||
die (1, "bad GNU.sparse.map: expected `,' but found `%c'",
|
||||
*val);
|
||||
}
|
||||
else
|
||||
val++;
|
||||
}
|
||||
if (*val)
|
||||
die (1, "bad GNU.sparse.map: garbage at the end");
|
||||
}
|
||||
}
|
||||
if (expect)
|
||||
die (1, "bad keyword sequence: expected `%s' not found", expect);
|
||||
if (version_major == 0 && sparse_map_size == 0)
|
||||
die (1, "size of the sparse map unknown");
|
||||
if (i != sparse_map_size)
|
||||
die (1, "not all sparse entries supplied");
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
void
|
||||
read_map (FILE *ifp)
|
||||
{
|
||||
size_t i;
|
||||
char nbuf[OFF_T_STRSIZE_BOUND];
|
||||
|
||||
if (verbose)
|
||||
printf ("Reading v.1.0 sparse map\n");
|
||||
|
||||
get_line (nbuf, sizeof nbuf, ifp);
|
||||
sparse_map_size = string_to_size (nbuf, NULL);
|
||||
sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
|
||||
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
{
|
||||
get_line (nbuf, sizeof nbuf, ifp);
|
||||
sparse_map[i].offset = string_to_off (nbuf, NULL);
|
||||
get_line (nbuf, sizeof nbuf, ifp);
|
||||
sparse_map[i].numbytes = string_to_size (nbuf, NULL);
|
||||
}
|
||||
|
||||
fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
|
||||
SEEK_SET);
|
||||
}
|
||||
|
||||
void
|
||||
expand_sparse (FILE *sfp, int ofd)
|
||||
{
|
||||
size_t i;
|
||||
size_t maxbytes = 0;
|
||||
char *buffer;
|
||||
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
if (maxbytes < sparse_map[i].numbytes)
|
||||
maxbytes = sparse_map[i].numbytes;
|
||||
|
||||
for (buffer = malloc (maxbytes); !buffer; maxbytes /= 2)
|
||||
if (maxbytes == 0)
|
||||
die (1, "not enough memory");
|
||||
|
||||
for (i = 0; i < sparse_map_size; i++)
|
||||
{
|
||||
size_t size = sparse_map[i].numbytes;
|
||||
|
||||
if (size == 0)
|
||||
ftruncate (ofd, sparse_map[i].offset);
|
||||
else
|
||||
{
|
||||
lseek (ofd, sparse_map[i].offset, SEEK_SET);
|
||||
while (size)
|
||||
{
|
||||
size_t rdsize = (size < maxbytes) ? size : maxbytes;
|
||||
if (rdsize != fread (buffer, 1, rdsize, sfp))
|
||||
die (1, "read error (%d)", errno);
|
||||
if (rdsize != write (ofd, buffer, rdsize))
|
||||
die (1, "write error (%d)", errno);
|
||||
size -= rdsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
usage (int code)
|
||||
{
|
||||
printf ("Usage: %s [OPTIONS] infile [outfile]\n", progname);
|
||||
printf ("%s: expand sparse files extracted from GNU archives\n",
|
||||
progname);
|
||||
printf ("\nOPTIONS are:\n\n");
|
||||
printf (" -h Display this help list\n");
|
||||
printf (" -n Dry run: do nothing, print what would have been done\n");
|
||||
printf (" -v Increase verbosity level\n");
|
||||
printf (" -x FILE Parse extended header FILE\n\n");
|
||||
|
||||
exit (code);
|
||||
}
|
||||
|
||||
void
|
||||
guess_outname (char *name)
|
||||
{
|
||||
char *p;
|
||||
char *s;
|
||||
|
||||
if (name[0] == '.' && name[1] == '/')
|
||||
name += 2;
|
||||
|
||||
p = name + strlen (name) - 1;
|
||||
s = NULL;
|
||||
|
||||
for (; p > name && *p != '/'; p--)
|
||||
;
|
||||
if (*p == '/')
|
||||
s = p + 1;
|
||||
if (p != name)
|
||||
{
|
||||
for (p--; p > name && *p != '/'; p--)
|
||||
;
|
||||
}
|
||||
|
||||
if (*p != '/')
|
||||
{
|
||||
if (s)
|
||||
outname = s;
|
||||
else
|
||||
{
|
||||
outname = emalloc (4 + strlen (name));
|
||||
strcpy (outname, "../");
|
||||
strcpy (outname + 3, name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = p - name + 1;
|
||||
outname = emalloc (len + strlen (s) + 1);
|
||||
memcpy (outname, name, len);
|
||||
strcpy (outname + len, s);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int dry_run = 0;
|
||||
char *xheader_file = NULL;
|
||||
char *inname;
|
||||
FILE *ifp;
|
||||
struct stat st;
|
||||
int ofd;
|
||||
|
||||
progname = argv[0];
|
||||
while ((c = getopt (argc, argv, "hnvx:")) != EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'h':
|
||||
usage (0);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
xheader_file = optarg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
dry_run = 1;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
default:
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0 || argc > 2)
|
||||
usage (1);
|
||||
|
||||
if (xheader_file)
|
||||
read_xheader (xheader_file);
|
||||
|
||||
inname = argv[0];
|
||||
if (argv[1])
|
||||
outname = argv[1];
|
||||
|
||||
if (stat (inname, &st))
|
||||
die (1, "cannot stat %s (%d)", inname, errno);
|
||||
|
||||
ifp = fopen (inname, "r");
|
||||
if (ifp == NULL)
|
||||
die (1, "cannot open file %s (%d)", inname, errno);
|
||||
|
||||
if (!xheader_file || version_major == 1)
|
||||
read_map (ifp);
|
||||
|
||||
if (!outname)
|
||||
guess_outname (inname);
|
||||
|
||||
ofd = open (outname, O_RDWR|O_CREAT|O_TRUNC, st.st_mode);
|
||||
if (ofd == -1)
|
||||
die (1, "cannot open file %s (%d)", outname, errno);
|
||||
|
||||
if (verbose)
|
||||
printf ("Expanding file `%s' to `%s'\n", inname, outname);
|
||||
|
||||
if (dry_run)
|
||||
{
|
||||
printf ("Finished dry run\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
expand_sparse (ifp, ofd);
|
||||
|
||||
fclose (ifp);
|
||||
close (ofd);
|
||||
|
||||
if (verbose)
|
||||
printf ("Done\n");
|
||||
|
||||
if (outsize)
|
||||
{
|
||||
if (stat (outname, &st))
|
||||
die (1, "cannot stat output file %s (%d)", outname, errno);
|
||||
if (st.st_size != outsize)
|
||||
die (1, "expanded file has wrong size");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
localedir.h
|
||||
rmt
|
||||
tar
|
||||
.deps
|
||||
.gdbinit
|
||||
Makefile
|
||||
Makefile.in
|
||||
rmt
|
||||
tar
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Makefile for GNU tar sources.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
|
||||
# Software Foundation, Inc.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
|
||||
# 2007 Free Software Foundation, Inc.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## the Free Software Foundation; either version 3, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
@@ -23,6 +23,7 @@ bin_PROGRAMS = tar
|
||||
noinst_HEADERS = arith.h common.h tar.h
|
||||
tar_SOURCES = \
|
||||
buffer.c\
|
||||
checkpoint.c\
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
@@ -30,19 +31,17 @@ tar_SOURCES = \
|
||||
xheader.c\
|
||||
incremen.c\
|
||||
list.c\
|
||||
mangle.c\
|
||||
misc.c\
|
||||
names.c\
|
||||
sparse.c\
|
||||
suffix.c\
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
update.c\
|
||||
utf8.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
|
||||
|
||||
tar.o: ../lib/localedir.h
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
|
||||
|
||||
LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* Long integers, for GNU tar.
|
||||
Copyright 1999 Free Software Foundation, Inc.
|
||||
Copyright 1999, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
|
||||
885
src/buffer.c
885
src/buffer.c
File diff suppressed because it is too large
Load Diff
270
src/checkpoint.c
Normal file
270
src/checkpoint.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/* Checkpoint management for tar.
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
|
||||
enum checkpoint_opcode
|
||||
{
|
||||
cop_dot,
|
||||
cop_bell,
|
||||
cop_echo,
|
||||
cop_ttyout,
|
||||
cop_sleep,
|
||||
cop_exec
|
||||
};
|
||||
|
||||
struct checkpoint_action
|
||||
{
|
||||
struct checkpoint_action *next;
|
||||
enum checkpoint_opcode opcode;
|
||||
union
|
||||
{
|
||||
time_t time;
|
||||
char *command;
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Checkpointing counter */
|
||||
static unsigned checkpoint;
|
||||
|
||||
/* List of checkpoint actions */
|
||||
static struct checkpoint_action *checkpoint_action, *checkpoint_action_tail;
|
||||
|
||||
static struct checkpoint_action *
|
||||
alloc_action (enum checkpoint_opcode opcode)
|
||||
{
|
||||
struct checkpoint_action *p = xzalloc (sizeof *p);
|
||||
if (checkpoint_action_tail)
|
||||
checkpoint_action_tail->next = p;
|
||||
else
|
||||
checkpoint_action = p;
|
||||
checkpoint_action_tail = p;
|
||||
p->opcode = opcode;
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *
|
||||
copy_string_unquote (const char *str)
|
||||
{
|
||||
char *output = xstrdup (str);
|
||||
size_t len = strlen (output);
|
||||
if ((*output == '"' || *output == '\'')
|
||||
&& output[len-1] == *output)
|
||||
{
|
||||
memmove (output, output+1, len-2);
|
||||
output[len-2] = 0;
|
||||
}
|
||||
unquote_string (output);
|
||||
return output;
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_compile_action (const char *str)
|
||||
{
|
||||
struct checkpoint_action *act;
|
||||
|
||||
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
|
||||
alloc_action (cop_dot);
|
||||
else if (strcmp (str, "bell") == 0)
|
||||
alloc_action (cop_bell);
|
||||
else if (strcmp (str, "echo") == 0)
|
||||
alloc_action (cop_echo);
|
||||
else if (strncmp (str, "echo=", 5) == 0)
|
||||
{
|
||||
act = alloc_action (cop_echo);
|
||||
act->v.command = copy_string_unquote (str + 5);
|
||||
}
|
||||
else if (strncmp (str, "exec=", 5) == 0)
|
||||
{
|
||||
act = alloc_action (cop_exec);
|
||||
act->v.command = copy_string_unquote (str + 5);
|
||||
}
|
||||
else if (strncmp (str, "ttyout=", 7) == 0)
|
||||
{
|
||||
act = alloc_action (cop_ttyout);
|
||||
act->v.command = copy_string_unquote (str + 7);
|
||||
}
|
||||
else if (strncmp (str, "sleep=", 6) == 0)
|
||||
{
|
||||
char *p;
|
||||
time_t n = strtoul (str+6, &p, 10);
|
||||
if (*p)
|
||||
FATAL_ERROR ((0, 0, _("%s: not a valid timeout"), str));
|
||||
act = alloc_action (cop_sleep);
|
||||
act->v.time = n;
|
||||
}
|
||||
else
|
||||
FATAL_ERROR ((0, 0, _("%s: unknown checkpoint action"), str));
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_finish_compile ()
|
||||
{
|
||||
if (checkpoint_option)
|
||||
{
|
||||
if (!checkpoint_action)
|
||||
/* Provide a historical default */
|
||||
checkpoint_compile_action ("echo");
|
||||
}
|
||||
else if (checkpoint_action)
|
||||
/* Otherwise, set default checkpoint rate */
|
||||
checkpoint_option = DEFAULT_CHECKPOINT;
|
||||
}
|
||||
|
||||
char *
|
||||
expand_checkpoint_string (const char *input, bool do_write, unsigned cpn)
|
||||
{
|
||||
const char *opstr = do_write ? gettext ("write") : gettext ("read");
|
||||
size_t opstrlen = strlen (opstr);
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
|
||||
size_t cpslen = strlen (cps);
|
||||
const char *ip;
|
||||
char *op;
|
||||
char *output;
|
||||
size_t outlen = strlen (input); /* Initial guess */
|
||||
|
||||
/* Fix the initial length guess */
|
||||
for (ip = input; (ip = strchr (ip, '%')) != NULL; )
|
||||
{
|
||||
switch (ip[1])
|
||||
{
|
||||
case 'u':
|
||||
outlen += cpslen - 2;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
outlen += opstrlen - 2;
|
||||
}
|
||||
ip++;
|
||||
}
|
||||
|
||||
output = xmalloc (outlen + 1);
|
||||
for (ip = input, op = output; *ip; )
|
||||
{
|
||||
if (*ip == '%')
|
||||
{
|
||||
switch (*++ip)
|
||||
{
|
||||
case 'u':
|
||||
op = stpcpy (op, cps);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
op = stpcpy (op, opstr);
|
||||
break;
|
||||
|
||||
default:
|
||||
*op++ = '%';
|
||||
*op++ = *ip;
|
||||
break;
|
||||
}
|
||||
ip++;
|
||||
}
|
||||
else
|
||||
*op++ = *ip++;
|
||||
}
|
||||
*op = 0;
|
||||
return output;
|
||||
}
|
||||
|
||||
static void
|
||||
run_checkpoint_actions (bool do_write)
|
||||
{
|
||||
struct checkpoint_action *p;
|
||||
FILE *tty = NULL;
|
||||
|
||||
for (p = checkpoint_action; p; p = p->next)
|
||||
{
|
||||
switch (p->opcode)
|
||||
{
|
||||
case cop_dot:
|
||||
fputc ('.', stdlis);
|
||||
fflush (stdlis);
|
||||
break;
|
||||
|
||||
case cop_bell:
|
||||
if (!tty)
|
||||
tty = fopen ("/dev/tty", "w");
|
||||
if (tty)
|
||||
{
|
||||
fputc ('\a', tty);
|
||||
fflush (tty);
|
||||
}
|
||||
break;
|
||||
|
||||
case cop_echo:
|
||||
{
|
||||
char *tmp;
|
||||
const char *str = p->v.command;
|
||||
if (!str)
|
||||
{
|
||||
if (do_write)
|
||||
/* TRANSLATORS: This is a ``checkpoint of write operation'',
|
||||
*not* ``Writing a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
|
||||
*not* ``Escribiendo un punto de comprobaci@'on'' */
|
||||
str = gettext ("Write checkpoint %u");
|
||||
else
|
||||
/* TRANSLATORS: This is a ``checkpoint of read operation'',
|
||||
*not* ``Reading a checkpoint''.
|
||||
E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
|
||||
*not* ``Leyendo un punto de comprobaci@'on'' */
|
||||
str = gettext ("Read checkpoint %u");
|
||||
}
|
||||
tmp = expand_checkpoint_string (str, do_write, checkpoint);
|
||||
WARN ((0, 0, "%s", tmp));
|
||||
free (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case cop_ttyout:
|
||||
if (!tty)
|
||||
tty = fopen ("/dev/tty", "w");
|
||||
if (tty)
|
||||
{
|
||||
char *tmp = expand_checkpoint_string (p->v.command, do_write,
|
||||
checkpoint);
|
||||
fprintf (tty, "%s", tmp);
|
||||
fflush (tty);
|
||||
free (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case cop_sleep:
|
||||
sleep (p->v.time);
|
||||
break;
|
||||
|
||||
case cop_exec:
|
||||
sys_exec_checkpoint_script (p->v.command,
|
||||
archive_name_cursor[0],
|
||||
checkpoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tty)
|
||||
fclose (tty);
|
||||
}
|
||||
|
||||
void
|
||||
checkpoint_run (bool do_write)
|
||||
{
|
||||
if (checkpoint_option && !(++checkpoint % checkpoint_option))
|
||||
run_checkpoint_actions (do_write);
|
||||
}
|
||||
|
||||
288
src/common.h
288
src/common.h
@@ -1,11 +1,11 @@
|
||||
/* Common declarations for the tar program.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -93,9 +93,6 @@ GLOBAL enum subcommand subcommand_option;
|
||||
/* Selected format for output archive. */
|
||||
GLOBAL enum archive_format archive_format;
|
||||
|
||||
/* Either NL or NUL, as decided by the --null option. */
|
||||
GLOBAL char filename_terminator;
|
||||
|
||||
/* Size of each record, once in blocks, once in bytes. Those two variables
|
||||
are always related, the second being BLOCKSIZE times the first. They do
|
||||
not have _option in their name, even if their values is derived from
|
||||
@@ -130,19 +127,13 @@ GLOBAL enum backup_type backup_type;
|
||||
GLOBAL bool block_number_option;
|
||||
|
||||
GLOBAL unsigned checkpoint_option;
|
||||
|
||||
enum checkpoint_style
|
||||
{
|
||||
checkpoint_text,
|
||||
checkpoint_dot
|
||||
};
|
||||
|
||||
GLOBAL enum checkpoint_style checkpoint_style;
|
||||
#define DEFAULT_CHECKPOINT 10
|
||||
|
||||
/* Specified name of compression program, or "gzip" as implied by -z. */
|
||||
GLOBAL const char *use_compress_program_option;
|
||||
|
||||
GLOBAL bool dereference_option;
|
||||
GLOBAL bool hard_dereference_option;
|
||||
|
||||
/* Print a message if not all links are dumped */
|
||||
GLOBAL int check_links_option;
|
||||
@@ -150,8 +141,18 @@ GLOBAL int check_links_option;
|
||||
/* Patterns that match file names to be excluded. */
|
||||
GLOBAL struct exclude *excluded;
|
||||
|
||||
/* Exclude directories containing a cache directory tag. */
|
||||
GLOBAL bool exclude_caches_option;
|
||||
enum exclusion_tag_type
|
||||
{
|
||||
exclusion_tag_none,
|
||||
/* Exclude the directory contents, but preserve the directory
|
||||
itself and the exclusion tag file */
|
||||
exclusion_tag_contents,
|
||||
/* Exclude everything below the directory, preserving the directory
|
||||
itself */
|
||||
exclusion_tag_under,
|
||||
/* Exclude entire directory */
|
||||
exclusion_tag_all,
|
||||
};
|
||||
|
||||
/* Specified value to be put into tar file in place of stat () results, or
|
||||
just -1 if such an override should not take place. */
|
||||
@@ -184,6 +185,8 @@ GLOBAL enum old_files old_files_option;
|
||||
|
||||
/* Specified file name for incremental list. */
|
||||
GLOBAL const char *listed_incremental_option;
|
||||
/* Check device numbers when doing incremental dumps. */
|
||||
GLOBAL bool check_device_option;
|
||||
|
||||
/* Specified mode change string. */
|
||||
GLOBAL struct mode_change *mode_option;
|
||||
@@ -197,6 +200,11 @@ GLOBAL bool multi_volume_option;
|
||||
do not get archived (also see after_date_option above). */
|
||||
GLOBAL struct timespec newer_mtime_option;
|
||||
|
||||
/* If true, override actual mtime (see below) */
|
||||
GLOBAL bool set_mtime_option;
|
||||
/* Value to be put in mtime header field instead of the actual mtime */
|
||||
GLOBAL struct timespec mtime_option;
|
||||
|
||||
/* Return true if newer_mtime_option is initialized. */
|
||||
#define NEWER_OPTION_INITIALIZED(opt) (0 <= (opt).tv_nsec)
|
||||
|
||||
@@ -247,6 +255,8 @@ GLOBAL size_t strip_name_components;
|
||||
GLOBAL bool show_omitted_dirs_option;
|
||||
|
||||
GLOBAL bool sparse_option;
|
||||
GLOBAL unsigned tar_sparse_major;
|
||||
GLOBAL unsigned tar_sparse_minor;
|
||||
|
||||
GLOBAL bool starting_file_option;
|
||||
|
||||
@@ -289,7 +299,7 @@ GLOBAL int archive;
|
||||
/* Nonzero when outputting to /dev/null. */
|
||||
GLOBAL bool dev_null_output;
|
||||
|
||||
/* Timestamps: */
|
||||
/* Timestamps: */
|
||||
GLOBAL struct timespec start_time; /* when we started execution */
|
||||
GLOBAL struct timespec volume_start_time; /* when the current volume was
|
||||
opened*/
|
||||
@@ -316,8 +326,6 @@ struct name
|
||||
Set with the -C option. */
|
||||
uintmax_t found_count; /* number of times a matching file has
|
||||
been found */
|
||||
int explicit; /* this name was explicitely given in the
|
||||
command line */
|
||||
int matching_flags; /* this name is a regexp, not literal */
|
||||
char const *dir_contents; /* for incremental_option */
|
||||
|
||||
@@ -375,22 +383,23 @@ extern char *continued_file_name;
|
||||
extern uintmax_t continued_file_size;
|
||||
extern uintmax_t continued_file_offset;
|
||||
|
||||
size_t available_space_after (union block *);
|
||||
size_t available_space_after (union block *pointer);
|
||||
off_t current_block_ordinal (void);
|
||||
void close_archive (void);
|
||||
void closeout_volume_number (void);
|
||||
void compute_duration (void);
|
||||
union block *find_next_block (void);
|
||||
void flush_read (void);
|
||||
void flush_write (void);
|
||||
void flush_archive (void);
|
||||
void init_volume_number (void);
|
||||
void open_archive (enum access_mode);
|
||||
void open_archive (enum access_mode mode);
|
||||
void print_total_stats (void);
|
||||
void reset_eof (void);
|
||||
void set_next_block_after (union block *);
|
||||
void set_next_block_after (union block *block);
|
||||
void clear_read_error_count (void);
|
||||
void xclose (int fd);
|
||||
void archive_write_error (ssize_t) __attribute__ ((noreturn));
|
||||
void archive_write_error (ssize_t status) __attribute__ ((noreturn));
|
||||
void archive_read_error (void);
|
||||
off_t seek_archive (off_t size);
|
||||
void set_start_time (void);
|
||||
@@ -400,6 +409,7 @@ void mv_end (void);
|
||||
void mv_total_size (off_t size);
|
||||
void mv_size_left (off_t size);
|
||||
|
||||
void buffer_write_global_xheader (void);
|
||||
|
||||
/* Module create.c. */
|
||||
|
||||
@@ -411,19 +421,28 @@ enum dump_status
|
||||
dump_status_not_implemented
|
||||
};
|
||||
|
||||
bool file_dumpable_p (struct tar_stat_info *);
|
||||
void add_exclusion_tag (const char *name, enum exclusion_tag_type type,
|
||||
bool (*)(const char*));
|
||||
bool cachedir_file_p (const char *name);
|
||||
|
||||
bool file_dumpable_p (struct tar_stat_info *st);
|
||||
void create_archive (void);
|
||||
void pad_archive (off_t size_left);
|
||||
void dump_file (const char *, int, dev_t);
|
||||
void dump_file (const char *st, int top_level, dev_t parent_device);
|
||||
union block *start_header (struct tar_stat_info *st);
|
||||
void finish_header (struct tar_stat_info *, union block *, off_t);
|
||||
void finish_header (struct tar_stat_info *st, union block *header,
|
||||
off_t block_ordinal);
|
||||
void simple_finish_header (union block *header);
|
||||
union block * write_extended (bool global, struct tar_stat_info *st,
|
||||
union block *old_header);
|
||||
union block *start_private_header (const char *name, size_t size);
|
||||
void write_eot (void);
|
||||
void check_links (void);
|
||||
|
||||
void exclusion_tag_warning (const char *dirname, const char *tagname,
|
||||
const char *message);
|
||||
enum exclusion_tag_type check_exclusion_tags (char *dirname,
|
||||
const char **tag_file_name);
|
||||
|
||||
#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
|
||||
#define MAJOR_TO_CHARS(val, where) major_to_chars (val, where, sizeof (where))
|
||||
#define MINOR_TO_CHARS(val, where) minor_to_chars (val, where, sizeof (where))
|
||||
@@ -436,16 +455,16 @@ void check_links (void);
|
||||
#define UNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
|
||||
#define GNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
|
||||
|
||||
bool gid_to_chars (gid_t, char *, size_t);
|
||||
bool major_to_chars (major_t, char *, size_t);
|
||||
bool minor_to_chars (minor_t, char *, size_t);
|
||||
bool mode_to_chars (mode_t, char *, size_t);
|
||||
bool off_to_chars (off_t, char *, size_t);
|
||||
bool size_to_chars (size_t, char *, size_t);
|
||||
bool time_to_chars (time_t, char *, size_t);
|
||||
bool uid_to_chars (uid_t, char *, size_t);
|
||||
bool uintmax_to_chars (uintmax_t, char *, size_t);
|
||||
void string_to_chars (char const *, char *, size_t);
|
||||
bool gid_to_chars (gid_t gid, char *buf, size_t size);
|
||||
bool major_to_chars (major_t m, char *buf, size_t size);
|
||||
bool minor_to_chars (minor_t m, char *buf, size_t size);
|
||||
bool mode_to_chars (mode_t m, char *buf, size_t size);
|
||||
bool off_to_chars (off_t off, char *buf, size_t size);
|
||||
bool size_to_chars (size_t v, char *buf, size_t size);
|
||||
bool time_to_chars (time_t t, char *buf, size_t size);
|
||||
bool uid_to_chars (uid_t uid, char *buf, size_t size);
|
||||
bool uintmax_to_chars (uintmax_t v, char *buf, size_t size);
|
||||
void string_to_chars (char const *s, char *buf, size_t size);
|
||||
|
||||
/* Module diffarch.c. */
|
||||
|
||||
@@ -467,12 +486,22 @@ 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;
|
||||
|
||||
char *get_directory_contents (char *, dev_t);
|
||||
dumpdir_t dumpdir_create0 (const char *contents, const char *cmask);
|
||||
dumpdir_t dumpdir_create (const char *contents);
|
||||
void dumpdir_free (dumpdir_t);
|
||||
char *dumpdir_locate (dumpdir_t dump, const char *name);
|
||||
char *dumpdir_next (dumpdir_iter_t itr);
|
||||
char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
|
||||
|
||||
|
||||
const char *get_directory_contents (char *dir_name, dev_t device);
|
||||
const char *append_incremental_renames (const char *dump);
|
||||
void read_directory_file (void);
|
||||
void write_directory_file (void);
|
||||
void purge_directory (char const *);
|
||||
void purge_directory (char const *directory_name);
|
||||
void list_dumpdir (char *buffer, size_t size);
|
||||
void update_parent_directory (const char *name);
|
||||
|
||||
@@ -491,22 +520,14 @@ enum read_header
|
||||
HEADER_FAILURE /* ill-formed header, or bad checksum */
|
||||
};
|
||||
|
||||
struct xheader
|
||||
{
|
||||
struct obstack *stk;
|
||||
size_t size;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
GLOBAL struct xheader extended_header;
|
||||
extern union block *current_header;
|
||||
extern enum archive_format current_format;
|
||||
extern size_t recent_long_name_blocks;
|
||||
extern size_t recent_long_link_blocks;
|
||||
|
||||
void decode_header (union block *, struct tar_stat_info *,
|
||||
enum archive_format *, int);
|
||||
char const *tartime (struct timespec, bool);
|
||||
void decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
enum archive_format *format_pointer, int do_user_group);
|
||||
char const *tartime (struct timespec t, bool full_time);
|
||||
|
||||
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
|
||||
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
|
||||
@@ -518,45 +539,39 @@ char const *tartime (struct timespec, bool);
|
||||
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
|
||||
#define UINTMAX_FROM_HEADER(where) uintmax_from_header (where, sizeof (where))
|
||||
|
||||
gid_t gid_from_header (const char *, size_t);
|
||||
major_t major_from_header (const char *, size_t);
|
||||
minor_t minor_from_header (const char *, size_t);
|
||||
mode_t mode_from_header (const char *, size_t);
|
||||
off_t off_from_header (const char *, size_t);
|
||||
size_t size_from_header (const char *, size_t);
|
||||
time_t time_from_header (const char *, size_t);
|
||||
uid_t uid_from_header (const char *, size_t);
|
||||
uintmax_t uintmax_from_header (const char *, size_t);
|
||||
gid_t gid_from_header (const char *buf, size_t size);
|
||||
major_t major_from_header (const char *buf, size_t size);
|
||||
minor_t minor_from_header (const char *buf, size_t size);
|
||||
mode_t mode_from_header (const char *buf, size_t size);
|
||||
off_t off_from_header (const char *buf, size_t size);
|
||||
size_t size_from_header (const char *buf, size_t size);
|
||||
time_t time_from_header (const char *buf, size_t size);
|
||||
uid_t uid_from_header (const char *buf, size_t size);
|
||||
uintmax_t uintmax_from_header (const char * buf, size_t size);
|
||||
|
||||
void list_archive (void);
|
||||
void print_for_mkdir (char *, int, mode_t);
|
||||
void print_header (struct tar_stat_info *, off_t);
|
||||
void read_and (void (*) (void));
|
||||
void print_for_mkdir (char *dirname, int length, mode_t mode);
|
||||
void print_header (struct tar_stat_info *st, off_t block_ordinal);
|
||||
void read_and (void (*do_something) (void));
|
||||
enum read_header read_header_primitive (bool raw_extended_headers,
|
||||
struct tar_stat_info *info);
|
||||
enum read_header read_header (bool);
|
||||
enum read_header read_header (bool raw_extended_headers);
|
||||
enum read_header tar_checksum (union block *header, bool silent);
|
||||
void skip_file (off_t);
|
||||
void skip_file (off_t size);
|
||||
void skip_member (void);
|
||||
|
||||
/* Module mangle.c. */
|
||||
|
||||
void extract_mangle (void);
|
||||
|
||||
/* Module misc.c. */
|
||||
|
||||
void assign_string (char **, const char *);
|
||||
char *quote_copy_string (const char *);
|
||||
int unquote_string (char *);
|
||||
void assign_string (char **dest, const char *src);
|
||||
char *quote_copy_string (const char *str);
|
||||
int unquote_string (char *str);
|
||||
|
||||
void code_ns_fraction (int, char *);
|
||||
char const *code_timespec (struct timespec, char *);
|
||||
void code_ns_fraction (int ns, char *p);
|
||||
char const *code_timespec (struct timespec ts, char *sbuf);
|
||||
enum { BILLION = 1000000000, LOG10_BILLION = 9 };
|
||||
enum { TIMESPEC_STRSIZE_BOUND =
|
||||
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
|
||||
|
||||
size_t dot_dot_prefix_len (char const *);
|
||||
|
||||
enum remove_option
|
||||
{
|
||||
ORDINARY_REMOVE_OPTION,
|
||||
@@ -571,31 +586,31 @@ enum remove_option
|
||||
meta-info to the incremental dumps, this should become unnecessary */
|
||||
WANT_DIRECTORY_REMOVE_OPTION
|
||||
};
|
||||
int remove_any_file (const char *, enum remove_option);
|
||||
bool maybe_backup_file (const char *, int);
|
||||
int remove_any_file (const char *file_name, enum remove_option option);
|
||||
bool maybe_backup_file (const char *file_name, bool this_is_the_archive);
|
||||
void undo_last_backup (void);
|
||||
|
||||
int deref_stat (bool, char const *, struct stat *);
|
||||
int deref_stat (bool deref, char const *name, struct stat *buf);
|
||||
|
||||
int chdir_arg (char const *);
|
||||
void chdir_do (int);
|
||||
int chdir_arg (char const *dir);
|
||||
void chdir_do (int dir);
|
||||
|
||||
void close_diag (char const *name);
|
||||
void open_diag (char const *name);
|
||||
void read_diag_details (char const *name, off_t offset, size_t size);
|
||||
void readlink_diag (char const *name);
|
||||
void savedir_diag (char const *name);
|
||||
void seek_diag_details (char const *, off_t);
|
||||
void seek_diag_details (char const *name, off_t offset);
|
||||
void stat_diag (char const *name);
|
||||
void write_error_details (char const *, size_t, size_t);
|
||||
void write_fatal (char const *) __attribute__ ((noreturn));
|
||||
void write_fatal_details (char const *, ssize_t, size_t)
|
||||
void write_error_details (char const *name, size_t status, size_t size);
|
||||
void write_fatal (char const *name) __attribute__ ((noreturn));
|
||||
void write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
__attribute__ ((noreturn));
|
||||
|
||||
pid_t xfork (void);
|
||||
void xpipe (int[2]);
|
||||
void xpipe (int fd[2]);
|
||||
|
||||
void *page_aligned_alloc (void **, size_t);
|
||||
void *page_aligned_alloc (void **ptr, size_t size);
|
||||
int set_file_atime (int fd, char const *file,
|
||||
struct timespec const timespec[2]);
|
||||
|
||||
@@ -603,35 +618,35 @@ int set_file_atime (int fd, char const *file,
|
||||
|
||||
extern struct name *gnu_list_name;
|
||||
|
||||
void gid_to_gname (gid_t, char **gname);
|
||||
int gname_to_gid (char const *, gid_t *);
|
||||
void uid_to_uname (uid_t, char **uname);
|
||||
int uname_to_uid (char const *, uid_t *);
|
||||
void gid_to_gname (gid_t gid, char **gname);
|
||||
int gname_to_gid (char const *gname, gid_t *pgid);
|
||||
void uid_to_uname (uid_t uid, char **uname);
|
||||
int uname_to_uid (char const *uname, uid_t *puid);
|
||||
|
||||
void init_names (void);
|
||||
void name_add_name (const char *, int);
|
||||
void name_init (void);
|
||||
void name_add_name (const char *name, int matching_flags);
|
||||
void name_add_dir (const char *name);
|
||||
void name_term (void);
|
||||
const char *name_next (int);
|
||||
const char *name_next (int change_dirs);
|
||||
void name_gather (void);
|
||||
struct name *addname (char const *, int);
|
||||
int name_match (const char *);
|
||||
struct name *addname (char const *string, int change_dir);
|
||||
bool name_match (const char *name);
|
||||
void names_notfound (void);
|
||||
void collect_and_sort_names (void);
|
||||
struct name *name_scan (const char *, bool);
|
||||
struct name *name_scan (const char *name);
|
||||
char *name_from_list (void);
|
||||
void blank_name_list (void);
|
||||
char *new_name (const char *, const char *);
|
||||
char *new_name (const char *dir_name, const char *name);
|
||||
size_t stripped_prefix_len (char const *file_name, size_t num);
|
||||
bool all_names_found (struct tar_stat_info *);
|
||||
bool all_names_found (struct tar_stat_info *st);
|
||||
|
||||
bool excluded_name (char const *);
|
||||
bool excluded_name (char const *name);
|
||||
|
||||
void add_avoided_name (char const *);
|
||||
bool is_avoided_name (char const *);
|
||||
bool is_individual_file (char const *);
|
||||
void add_avoided_name (char const *name);
|
||||
bool is_avoided_name (char const *name);
|
||||
bool is_individual_file (char const *name);
|
||||
|
||||
bool contains_dot_dot (char const *);
|
||||
bool contains_dot_dot (char const *name);
|
||||
|
||||
#define ISFOUND(c) ((occurrence_option == 0) ? (c)->found_count : \
|
||||
(c)->found_count == occurrence_option)
|
||||
@@ -642,8 +657,8 @@ bool contains_dot_dot (char const *);
|
||||
|
||||
void usage (int);
|
||||
|
||||
int confirm (const char *, const char *);
|
||||
void request_stdin (const char *);
|
||||
int confirm (const char *message_action, const char *name);
|
||||
void request_stdin (const char *option);
|
||||
|
||||
void tar_stat_init (struct tar_stat_info *st);
|
||||
void tar_stat_destroy (struct tar_stat_info *st);
|
||||
@@ -660,22 +675,22 @@ void update_archive (void);
|
||||
|
||||
/* Module xheader.c. */
|
||||
|
||||
void xheader_decode (struct tar_stat_info *);
|
||||
void xheader_decode_global (void);
|
||||
void xheader_store (char const *, struct tar_stat_info const *, void const *);
|
||||
void xheader_read (union block *, size_t);
|
||||
void xheader_init (struct xheader *xhdr);
|
||||
void xheader_decode (struct tar_stat_info *stat);
|
||||
void xheader_decode_global (struct xheader *xhdr);
|
||||
void xheader_store (char const *keyword, struct tar_stat_info *st,
|
||||
void const *data);
|
||||
void xheader_read (struct xheader *xhdr, union block *header, size_t size);
|
||||
void xheader_write (char type, char *name, struct xheader *xhdr);
|
||||
void xheader_write_global (void);
|
||||
void xheader_finish (struct xheader *);
|
||||
void xheader_destroy (struct xheader *);
|
||||
void xheader_write_global (struct xheader *xhdr);
|
||||
void xheader_finish (struct xheader *hdr);
|
||||
void xheader_destroy (struct xheader *hdr);
|
||||
char *xheader_xhdr_name (struct tar_stat_info *st);
|
||||
char *xheader_ghdr_name (void);
|
||||
void xheader_write (char, char *, struct xheader *);
|
||||
void xheader_write_global (void);
|
||||
void xheader_set_option (char *string);
|
||||
void xheader_string_begin (void);
|
||||
void xheader_string_add (char const *s);
|
||||
void xheader_string_end (char const *keyword);
|
||||
void xheader_string_begin (struct xheader *xhdr);
|
||||
void xheader_string_add (struct xheader *xhdr, char const *s);
|
||||
bool xheader_string_end (struct xheader *xhdr, char const *keyword);
|
||||
bool xheader_keyword_deleted_p (const char *kw);
|
||||
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
|
||||
size_t n);
|
||||
@@ -684,8 +699,7 @@ char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
|
||||
|
||||
void sys_detect_dev_null_output (void);
|
||||
void sys_save_archive_dev_ino (void);
|
||||
void sys_drain_input_pipe (void);
|
||||
void sys_wait_for_child (pid_t);
|
||||
void sys_wait_for_child (pid_t, bool);
|
||||
void sys_spawn_shell (void);
|
||||
bool sys_compare_uid (struct stat *a, struct stat *b);
|
||||
bool sys_compare_gid (struct stat *a, struct stat *b);
|
||||
@@ -699,26 +713,42 @@ bool sys_get_archive_stat (void);
|
||||
int sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st);
|
||||
void sys_wait_command (void);
|
||||
int sys_exec_info_script (const char **archive_name, int volume_number);
|
||||
void sys_exec_checkpoint_script (const char *script_name,
|
||||
const char *archive_name,
|
||||
int checkpoint_number);
|
||||
|
||||
/* Module compare.c */
|
||||
void report_difference (struct tar_stat_info *st, const char *message, ...);
|
||||
|
||||
/* Module sparse.c */
|
||||
bool sparse_file_p (struct tar_stat_info *);
|
||||
bool sparse_member_p (struct tar_stat_info *);
|
||||
bool sparse_fixup_header (struct tar_stat_info *);
|
||||
enum dump_status sparse_dump_file (int, struct tar_stat_info *);
|
||||
enum dump_status sparse_extract_file (int, struct tar_stat_info *, off_t *);
|
||||
enum dump_status sparse_skip_file (struct tar_stat_info *);
|
||||
bool sparse_diff_file (int, struct tar_stat_info *);
|
||||
bool sparse_member_p (struct tar_stat_info *st);
|
||||
bool sparse_fixup_header (struct tar_stat_info *st);
|
||||
enum dump_status sparse_dump_file (int, struct tar_stat_info *st);
|
||||
enum dump_status sparse_extract_file (int fd, struct tar_stat_info *st,
|
||||
off_t *size);
|
||||
enum dump_status sparse_skip_file (struct tar_stat_info *st);
|
||||
bool sparse_diff_file (int, struct tar_stat_info *st);
|
||||
|
||||
/* Module utf8.c */
|
||||
bool string_ascii_p (const char *str);
|
||||
bool utf8_convert (bool to_utf, char const *input, char **output);
|
||||
|
||||
/* Module transform.c */
|
||||
#define XFORM_REGFILE 0x01
|
||||
#define XFORM_LINK 0x02
|
||||
#define XFORM_SYMLINK 0x04
|
||||
#define XFORM_ALL (XFORM_REGFILE|XFORM_LINK|XFORM_SYMLINK)
|
||||
|
||||
void set_transform_expr (const char *expr);
|
||||
bool transform_name (char **pinput);
|
||||
bool transform_name_fp (char **pinput, char *(*fun)(char *));
|
||||
|
||||
|
||||
bool transform_name (char **pinput, int type);
|
||||
bool transform_member_name (char **pinput, int type);
|
||||
bool transform_name_fp (char **pinput, int type,
|
||||
char *(*fun)(char *, void *), void *);
|
||||
|
||||
/* Module suffix.c */
|
||||
void set_comression_program_by_suffix (const char *name, const char *defprog);
|
||||
|
||||
/* Module checkpoint.c */
|
||||
void checkpoint_compile_action (const char *str);
|
||||
void checkpoint_finish_compile (void);
|
||||
void checkpoint_run (bool do_write);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* Diff files from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1987-04-30.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -110,27 +110,10 @@ process_rawdata (size_t bytes, char *buffer)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Directory contents, only for GNUTYPE_DUMPDIR. */
|
||||
|
||||
static char *dumpdir_cursor;
|
||||
|
||||
static int
|
||||
process_dumpdir (size_t bytes, char *buffer)
|
||||
{
|
||||
if (memcmp (buffer, dumpdir_cursor, bytes))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Contents differ"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
dumpdir_cursor += bytes;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Some other routine wants SIZE bytes in the archive. For each chunk
|
||||
of the archive, call PROCESSOR with the size of the chunk, and the
|
||||
address of the chunk it can work with. The PROCESSOR should return
|
||||
nonzero for success. It it return error once, continue skipping
|
||||
nonzero for success. Once it returns error, continue skipping
|
||||
without calling PROCESSOR anymore. */
|
||||
|
||||
static void
|
||||
@@ -138,7 +121,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
|
||||
{
|
||||
union block *data_block;
|
||||
size_t data_size;
|
||||
size_t size = st->stat.st_size;
|
||||
off_t size = st->stat.st_size;
|
||||
|
||||
mv_begin (st);
|
||||
while (size)
|
||||
@@ -345,14 +328,49 @@ diff_special (void)
|
||||
report_difference (¤t_stat_info, _("Mode differs"));
|
||||
}
|
||||
|
||||
static int
|
||||
dumpdir_cmp (const char *a, const char *b)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
while (*a)
|
||||
switch (*a)
|
||||
{
|
||||
case 'Y':
|
||||
case 'N':
|
||||
if (!strchr ("YN", *b))
|
||||
return 1;
|
||||
if (strcmp(a + 1, b + 1))
|
||||
return 1;
|
||||
len = strlen (a) + 1;
|
||||
a += len;
|
||||
b += len;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (strcmp(a, b))
|
||||
return 1;
|
||||
len = strlen (a) + 1;
|
||||
a += len;
|
||||
b += len;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
case 'T':
|
||||
case 'X':
|
||||
return *b;
|
||||
}
|
||||
return *b;
|
||||
}
|
||||
|
||||
static void
|
||||
diff_dumpdir (void)
|
||||
{
|
||||
char *dumpdir_buffer;
|
||||
const char *dumpdir_buffer;
|
||||
dev_t dev = 0;
|
||||
struct stat stat;
|
||||
struct stat stat_data;
|
||||
|
||||
if (deref_stat (true, current_stat_info.file_name, &stat))
|
||||
if (deref_stat (true, current_stat_info.file_name, &stat_data))
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
stat_warn (current_stat_info.file_name);
|
||||
@@ -360,15 +378,14 @@ diff_dumpdir (void)
|
||||
stat_error (current_stat_info.file_name);
|
||||
}
|
||||
else
|
||||
dev = stat.st_dev;
|
||||
dev = stat_data.st_dev;
|
||||
|
||||
dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev);
|
||||
|
||||
if (dumpdir_buffer)
|
||||
{
|
||||
dumpdir_cursor = dumpdir_buffer;
|
||||
read_and_process (¤t_stat_info, process_dumpdir);
|
||||
free (dumpdir_buffer);
|
||||
if (dumpdir_cmp (current_stat_info.dumpdir, dumpdir_buffer))
|
||||
report_difference (¤t_stat_info, _("Contents differ"));
|
||||
}
|
||||
else
|
||||
read_and_process (¤t_stat_info, process_noop);
|
||||
@@ -484,10 +501,9 @@ diff_archive (void)
|
||||
break;
|
||||
|
||||
case GNUTYPE_DUMPDIR:
|
||||
diff_dumpdir ();
|
||||
/* Fall through. */
|
||||
|
||||
case DIRTYPE:
|
||||
if (is_dumpdir (¤t_stat_info))
|
||||
diff_dumpdir ();
|
||||
diff_dir ();
|
||||
break;
|
||||
|
||||
@@ -581,12 +597,25 @@ verify_volume (void)
|
||||
"VERIFY FAILURE: %d invalid headers detected",
|
||||
counter), counter));
|
||||
}
|
||||
if (status == HEADER_ZERO_BLOCK || status == HEADER_END_OF_FILE)
|
||||
if (status == HEADER_END_OF_FILE)
|
||||
break;
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
if (!ignore_zeros_option)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
status = read_header (false);
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
break;
|
||||
WARN ((0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
}
|
||||
}
|
||||
|
||||
diff_archive ();
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
xheader_destroy (&extended_header);
|
||||
}
|
||||
|
||||
access_mode = ACCESS_WRITE;
|
||||
|
||||
333
src/create.c
333
src/create.c
@@ -1,13 +1,13 @@
|
||||
/* Create a tar archive.
|
||||
|
||||
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-25.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -33,6 +33,111 @@ struct link
|
||||
size_t nlink;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
struct exclusion_tag
|
||||
{
|
||||
const char *name;
|
||||
size_t length;
|
||||
enum exclusion_tag_type type;
|
||||
bool (*predicate) (const char *name);
|
||||
struct exclusion_tag *next;
|
||||
};
|
||||
|
||||
static struct exclusion_tag *exclusion_tags;
|
||||
|
||||
void
|
||||
add_exclusion_tag (const char *name, enum exclusion_tag_type type,
|
||||
bool (*predicate) (const char *name))
|
||||
{
|
||||
struct exclusion_tag *tag = xmalloc (sizeof tag[0]);
|
||||
tag->next = exclusion_tags;
|
||||
tag->name = name;
|
||||
tag->type = type;
|
||||
tag->predicate = predicate;
|
||||
tag->length = strlen (name);
|
||||
exclusion_tags = tag;
|
||||
}
|
||||
|
||||
void
|
||||
exclusion_tag_warning (const char *dirname, const char *tagname,
|
||||
const char *message)
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0,
|
||||
_("%s: contains a cache directory tag %s; %s"),
|
||||
quotearg_colon (dirname),
|
||||
quotearg_n (1, tagname),
|
||||
message));
|
||||
}
|
||||
|
||||
enum exclusion_tag_type
|
||||
check_exclusion_tags (char *dirname, const char **tag_file_name)
|
||||
{
|
||||
static char *tagname;
|
||||
static size_t tagsize;
|
||||
struct exclusion_tag *tag;
|
||||
size_t dlen = strlen (dirname);
|
||||
int addslash = dirname[dlen-1] != '/';
|
||||
char *nptr = NULL;
|
||||
|
||||
for (tag = exclusion_tags; tag; tag = tag->next)
|
||||
{
|
||||
size_t size = dlen + addslash + tag->length + 1;
|
||||
if (size > tagsize)
|
||||
{
|
||||
tagsize = size;
|
||||
tagname = xrealloc (tagname, tagsize);
|
||||
}
|
||||
|
||||
if (!nptr)
|
||||
{
|
||||
strcpy (tagname, dirname);
|
||||
nptr = tagname + dlen;
|
||||
if (addslash)
|
||||
*nptr++ = '/';
|
||||
}
|
||||
strcpy (nptr, tag->name);
|
||||
if (access (tagname, F_OK) == 0
|
||||
&& (!tag->predicate || tag->predicate (tagname)))
|
||||
{
|
||||
if (tag_file_name)
|
||||
*tag_file_name = tag->name;
|
||||
return tag->type;
|
||||
}
|
||||
}
|
||||
|
||||
return exclusion_tag_none;
|
||||
}
|
||||
|
||||
/* Exclusion predicate to test if the named file (usually "CACHEDIR.TAG")
|
||||
contains a valid header, as described at:
|
||||
http://www.brynosaurus.com/cachedir
|
||||
Applications can write this file into directories they create
|
||||
for use as caches containing purely regenerable, non-precious data,
|
||||
allowing us to avoid archiving them if --exclude-caches is specified. */
|
||||
|
||||
#define CACHEDIR_SIGNATURE "Signature: 8a477f597d28d172789f06886806bc55"
|
||||
#define CACHEDIR_SIGNATURE_SIZE (sizeof CACHEDIR_SIGNATURE - 1)
|
||||
|
||||
bool
|
||||
cachedir_file_p (const char *name)
|
||||
{
|
||||
bool tag_present = false;
|
||||
int fd = open (name, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
static char tagbuf[CACHEDIR_SIGNATURE_SIZE];
|
||||
|
||||
if (read (fd, tagbuf, CACHEDIR_SIGNATURE_SIZE)
|
||||
== CACHEDIR_SIGNATURE_SIZE
|
||||
&& memcmp (tagbuf, CACHEDIR_SIGNATURE, CACHEDIR_SIGNATURE_SIZE) == 0)
|
||||
tag_present = true;
|
||||
|
||||
close (fd);
|
||||
}
|
||||
return tag_present;
|
||||
}
|
||||
|
||||
|
||||
/* The maximum uintmax_t value that can be represented with DIGITS digits,
|
||||
assuming that each digit is BITS_PER_DIGIT wide. */
|
||||
@@ -128,7 +233,7 @@ to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
|
||||
char const *minval_string;
|
||||
char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
|
||||
char const *value_string;
|
||||
|
||||
|
||||
if (gnu_format)
|
||||
{
|
||||
uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
|
||||
@@ -138,7 +243,7 @@ to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
|
||||
}
|
||||
else
|
||||
minval_string = "0";
|
||||
|
||||
|
||||
if (negative)
|
||||
{
|
||||
char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
|
||||
@@ -147,13 +252,18 @@ to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
|
||||
}
|
||||
else
|
||||
value_string = STRINGIFY_BIGINT (value, valbuf);
|
||||
|
||||
|
||||
if (substitute)
|
||||
{
|
||||
int negsub;
|
||||
uintmax_t sub = substitute (&negsub) & maxval;
|
||||
/* FIXME: This is the only place where GNU_FORMAT differs from
|
||||
OLDGNU_FORMAT. Apart from this they are completely identical. */
|
||||
/* NOTE: This is one of the few places where GNU_FORMAT differs from
|
||||
OLDGNU_FORMAT. The actual differences are:
|
||||
|
||||
1. In OLDGNU_FORMAT all strings in a tar header end in \0
|
||||
2. Incremental archives use oldgnu_header.
|
||||
|
||||
Apart from this they are completely identical. */
|
||||
uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
|
||||
char subbuf[UINTMAX_STRSIZE_BOUND + 1];
|
||||
char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
|
||||
@@ -236,7 +346,7 @@ to_chars (int negative, uintmax_t value, size_t valsize,
|
||||
}
|
||||
else
|
||||
substitute = NULL; /* No substitution for formats, other than GNU */
|
||||
|
||||
|
||||
return to_chars_subst (negative, gnu_format, value, valsize, substitute,
|
||||
where, size, type);
|
||||
}
|
||||
@@ -291,7 +401,8 @@ mode_to_chars (mode_t v, char *p, size_t s)
|
||||
&& S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
|
||||
&& archive_format != POSIX_FORMAT
|
||||
&& archive_format != USTAR_FORMAT
|
||||
&& archive_format != GNU_FORMAT)
|
||||
&& archive_format != GNU_FORMAT
|
||||
&& archive_format != OLDGNU_FORMAT)
|
||||
{
|
||||
negative = v < 0;
|
||||
u = v;
|
||||
@@ -380,7 +491,7 @@ bool
|
||||
file_dumpable_p (struct tar_stat_info *st)
|
||||
{
|
||||
if (dev_null_output)
|
||||
return totals_option && sparse_option && sparse_file_p (st);
|
||||
return totals_option && sparse_option && ST_IS_SPARSE (st->stat);
|
||||
return !(st->archive_file_size == 0
|
||||
&& (st->stat.st_mode & MODE_R) == MODE_R);
|
||||
}
|
||||
@@ -602,10 +713,10 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
|
||||
char *p;
|
||||
int type;
|
||||
|
||||
if (extended_header.buffer || extended_header.stk == NULL)
|
||||
if (st->xhdr.buffer || st->xhdr.stk == NULL)
|
||||
return old_header;
|
||||
|
||||
xheader_finish (&extended_header);
|
||||
xheader_finish (&st->xhdr);
|
||||
memcpy (hp.buffer, old_header, sizeof (hp));
|
||||
if (global)
|
||||
{
|
||||
@@ -617,7 +728,7 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
|
||||
type = XHDTYPE;
|
||||
p = xheader_xhdr_name (st);
|
||||
}
|
||||
xheader_write (type, p, &extended_header);
|
||||
xheader_write (type, p, &st->xhdr);
|
||||
free (p);
|
||||
header = find_next_block ();
|
||||
memcpy (header, &hp.buffer, sizeof (hp.buffer));
|
||||
@@ -663,7 +774,8 @@ start_header (struct tar_stat_info *st)
|
||||
if (mode_option)
|
||||
st->stat.st_mode =
|
||||
((st->stat.st_mode & ~MODE_ALL)
|
||||
| mode_adjust (st->stat.st_mode, mode_option, initial_umask));
|
||||
| mode_adjust (st->stat.st_mode, S_ISDIR (st->stat.st_mode) != 0,
|
||||
initial_umask, mode_option, NULL));
|
||||
|
||||
/* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
|
||||
for a few tars and came up with the following interoperability
|
||||
@@ -730,12 +842,12 @@ start_header (struct tar_stat_info *st)
|
||||
}
|
||||
|
||||
{
|
||||
struct timespec mtime = st->mtime;
|
||||
struct timespec mtime = set_mtime_option ? mtime_option : st->mtime;
|
||||
if (archive_format == POSIX_FORMAT)
|
||||
{
|
||||
if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec
|
||||
|| mtime.tv_nsec != 0)
|
||||
xheader_store ("mtime", st, NULL);
|
||||
xheader_store ("mtime", st, &mtime);
|
||||
if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec)
|
||||
mtime.tv_sec = 0;
|
||||
}
|
||||
@@ -929,7 +1041,7 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
while (size_left > 0)
|
||||
{
|
||||
size_t bufsize, count;
|
||||
|
||||
|
||||
mv_size_left (size_left);
|
||||
|
||||
blk = find_next_block ();
|
||||
@@ -954,8 +1066,7 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
return dump_status_short;
|
||||
}
|
||||
size_left -= count;
|
||||
if (count)
|
||||
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
|
||||
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
|
||||
|
||||
if (count != bufsize)
|
||||
{
|
||||
@@ -967,62 +1078,23 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
size_left),
|
||||
quotearg_colon (st->orig_file_name),
|
||||
STRINGIFY_BIGINT (size_left, buf)));
|
||||
if (! ignore_failed_read_option)
|
||||
exit_status = TAREXIT_FAILURE;
|
||||
pad_archive (size_left - (bufsize-count));
|
||||
if (! ignore_failed_read_option)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
pad_archive (size_left - (bufsize - count));
|
||||
return dump_status_short;
|
||||
}
|
||||
}
|
||||
return dump_status_ok;
|
||||
}
|
||||
|
||||
/* Look in directory DIRNAME for a cache directory tag file
|
||||
with the magic name "CACHEDIR.TAG" and a standard header,
|
||||
as described at:
|
||||
http://www.brynosaurus.com/cachedir
|
||||
Applications can write this file into directories they create
|
||||
for use as caches containing purely regenerable, non-precious data,
|
||||
allowing us to avoid archiving them if --exclude-caches is specified. */
|
||||
|
||||
#define CACHEDIR_SIGNATURE "Signature: 8a477f597d28d172789f06886806bc55"
|
||||
#define CACHEDIR_SIGNATURE_SIZE (sizeof CACHEDIR_SIGNATURE - 1)
|
||||
|
||||
static bool
|
||||
check_cache_directory (char *dirname)
|
||||
{
|
||||
static char tagname[] = "CACHEDIR.TAG";
|
||||
char *tagpath;
|
||||
int fd;
|
||||
int tag_present = false;
|
||||
|
||||
tagpath = xmalloc (strlen (dirname) + strlen (tagname) + 1);
|
||||
strcpy (tagpath, dirname);
|
||||
strcat (tagpath, tagname);
|
||||
|
||||
fd = open (tagpath, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
static char tagbuf[CACHEDIR_SIGNATURE_SIZE];
|
||||
|
||||
if (read (fd, tagbuf, CACHEDIR_SIGNATURE_SIZE)
|
||||
== CACHEDIR_SIGNATURE_SIZE
|
||||
&& memcmp (tagbuf, CACHEDIR_SIGNATURE, CACHEDIR_SIGNATURE_SIZE) == 0)
|
||||
tag_present = true;
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
free (tagpath);
|
||||
|
||||
return tag_present;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_dir0 (char *directory,
|
||||
struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
{
|
||||
dev_t our_device = st->stat.st_dev;
|
||||
|
||||
const char *tag_file_name;
|
||||
|
||||
if (!is_avoided_name (st->orig_file_name))
|
||||
{
|
||||
union block *blk = NULL;
|
||||
@@ -1104,44 +1176,63 @@ dump_dir0 (char *directory,
|
||||
WARN ((0, 0,
|
||||
_("%s: file is on a different filesystem; not dumped"),
|
||||
quotearg_colon (st->orig_file_name)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (exclude_caches_option
|
||||
&& check_cache_directory(st->orig_file_name))
|
||||
else
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0,
|
||||
_("%s: contains a cache directory tag; not dumped"),
|
||||
quotearg_colon (st->orig_file_name)));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
char const *entry;
|
||||
size_t entry_len;
|
||||
char *name_buf = xstrdup (st->orig_file_name);
|
||||
size_t name_size = strlen (name_buf);
|
||||
size_t name_len = name_size;
|
||||
|
||||
/* Now output all the files in the directory. */
|
||||
/* FIXME: Should speed this up by cd-ing into the dir. */
|
||||
|
||||
for (entry = directory; (entry_len = strlen (entry)) != 0;
|
||||
entry += entry_len + 1)
|
||||
{
|
||||
if (name_size < name_len + entry_len)
|
||||
char *name_buf;
|
||||
size_t name_size;
|
||||
|
||||
switch (check_exclusion_tags (st->orig_file_name, &tag_file_name))
|
||||
{
|
||||
case exclusion_tag_all:
|
||||
/* Handled in dump_file0 */
|
||||
break;
|
||||
|
||||
case exclusion_tag_none:
|
||||
{
|
||||
name_size = name_len + entry_len;
|
||||
name_buf = xrealloc (name_buf, name_size + 1);
|
||||
}
|
||||
strcpy (name_buf + name_len, entry);
|
||||
if (!excluded_name (name_buf))
|
||||
dump_file (name_buf, 0, our_device);
|
||||
}
|
||||
char const *entry;
|
||||
size_t entry_len;
|
||||
size_t name_len;
|
||||
|
||||
free (name_buf);
|
||||
}
|
||||
name_buf = xstrdup (st->orig_file_name);
|
||||
name_size = name_len = strlen (name_buf);
|
||||
|
||||
/* Now output all the files in the directory. */
|
||||
/* FIXME: Should speed this up by cd-ing into the dir. */
|
||||
for (entry = directory; (entry_len = strlen (entry)) != 0;
|
||||
entry += entry_len + 1)
|
||||
{
|
||||
if (name_size < name_len + entry_len)
|
||||
{
|
||||
name_size = name_len + entry_len;
|
||||
name_buf = xrealloc (name_buf, name_size + 1);
|
||||
}
|
||||
strcpy (name_buf + name_len, entry);
|
||||
if (!excluded_name (name_buf))
|
||||
dump_file (name_buf, 0, our_device);
|
||||
}
|
||||
|
||||
free (name_buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case exclusion_tag_contents:
|
||||
exclusion_tag_warning (st->orig_file_name, tag_file_name,
|
||||
_("contents not dumped"));
|
||||
name_size = strlen (st->orig_file_name) + strlen (tag_file_name) + 1;
|
||||
name_buf = xmalloc (name_size);
|
||||
strcpy (name_buf, st->orig_file_name);
|
||||
strcat (name_buf, tag_file_name);
|
||||
dump_file (name_buf, 0, our_device);
|
||||
free (name_buf);
|
||||
break;
|
||||
|
||||
case exclusion_tag_under:
|
||||
exclusion_tag_warning (st->orig_file_name, tag_file_name,
|
||||
_("contents not dumped"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure exactly one trailing slash. */
|
||||
@@ -1167,9 +1258,6 @@ dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
return false;
|
||||
}
|
||||
|
||||
ensure_slash (&st->orig_file_name);
|
||||
ensure_slash (&st->file_name);
|
||||
|
||||
dump_dir0 (directory, st, top_level, parent_device);
|
||||
|
||||
free (directory);
|
||||
@@ -1185,7 +1273,7 @@ create_archive (void)
|
||||
const char *p;
|
||||
|
||||
open_archive (ACCESS_WRITE);
|
||||
xheader_write_global ();
|
||||
buffer_write_global_xheader ();
|
||||
|
||||
if (incremental_option)
|
||||
{
|
||||
@@ -1334,6 +1422,8 @@ dump_hard_link (struct tar_stat_info *st)
|
||||
static void
|
||||
file_count_links (struct tar_stat_info *st)
|
||||
{
|
||||
if (hard_dereference_option)
|
||||
return;
|
||||
if (st->stat.st_nlink > 1)
|
||||
{
|
||||
struct link *duplicate;
|
||||
@@ -1392,6 +1482,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
{
|
||||
union block *header;
|
||||
char type;
|
||||
off_t original_size;
|
||||
struct timespec original_ctime;
|
||||
struct timespec restore_times[2];
|
||||
off_t block_ordinal = -1;
|
||||
@@ -1404,14 +1495,14 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
assign_string (&st->file_name,
|
||||
safer_name_suffix (p, false, absolute_names_option));
|
||||
|
||||
transform_name (&st->file_name);
|
||||
transform_name (&st->file_name, XFORM_REGFILE);
|
||||
|
||||
if (deref_stat (dereference_option, p, &st->stat) != 0)
|
||||
{
|
||||
stat_diag (p);
|
||||
return;
|
||||
}
|
||||
st->archive_file_size = st->stat.st_size;
|
||||
st->archive_file_size = original_size = st->stat.st_size;
|
||||
st->atime = restore_times[0] = get_stat_atime (&st->stat);
|
||||
st->mtime = restore_times[1] = get_stat_mtime (&st->stat);
|
||||
st->ctime = original_ctime = get_stat_ctime (&st->stat);
|
||||
@@ -1489,6 +1580,18 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
const char *tag_file_name;
|
||||
ensure_slash (&st->orig_file_name);
|
||||
ensure_slash (&st->file_name);
|
||||
|
||||
if (check_exclusion_tags (st->orig_file_name, &tag_file_name)
|
||||
== exclusion_tag_all)
|
||||
{
|
||||
exclusion_tag_warning (st->orig_file_name, tag_file_name,
|
||||
_("directory not dumped"));
|
||||
return;
|
||||
}
|
||||
|
||||
ok = dump_dir (fd, st, top_level, parent_device);
|
||||
|
||||
/* dump_dir consumes FD if successful. */
|
||||
@@ -1499,7 +1602,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
{
|
||||
enum dump_status status;
|
||||
|
||||
if (fd != -1 && sparse_option && sparse_file_p (st))
|
||||
if (fd != -1 && sparse_option && ST_IS_SPARSE (st->stat))
|
||||
{
|
||||
status = sparse_dump_file (fd, st);
|
||||
if (status == dump_status_not_implemented)
|
||||
@@ -1513,6 +1616,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
case dump_status_ok:
|
||||
case dump_status_short:
|
||||
mv_end ();
|
||||
file_count_links (st);
|
||||
break;
|
||||
|
||||
case dump_status_fail:
|
||||
@@ -1522,8 +1626,6 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
abort ();
|
||||
}
|
||||
|
||||
file_count_links (st);
|
||||
|
||||
ok = status == dump_status_ok;
|
||||
}
|
||||
|
||||
@@ -1548,9 +1650,17 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
if (ok)
|
||||
{
|
||||
if (timespec_cmp (get_stat_ctime (&final_stat), original_ctime) != 0)
|
||||
WARN ((0, 0, _("%s: file changed as we read it"),
|
||||
quotearg_colon (p)));
|
||||
if ((timespec_cmp (get_stat_ctime (&final_stat), original_ctime) != 0
|
||||
/* Original ctime will change if the file is a directory and
|
||||
--remove-files is given */
|
||||
&& !(remove_files_option && is_dir))
|
||||
|| original_size < final_stat.st_size)
|
||||
{
|
||||
WARN ((0, 0, _("%s: file changed as we read it"),
|
||||
quotearg_colon (p)));
|
||||
if (exit_status == TAREXIT_SUCCESS)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
}
|
||||
else if (atime_preserve_option == replace_atime_preserve
|
||||
&& set_file_atime (fd, p, restore_times) != 0)
|
||||
utime_error (p);
|
||||
@@ -1595,6 +1705,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
}
|
||||
buffer[size] = '\0';
|
||||
assign_string (&st->link_name, buffer);
|
||||
transform_name (&st->link_name, XFORM_SYMLINK);
|
||||
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
|
||||
write_long_link (st);
|
||||
|
||||
@@ -1603,7 +1714,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
header = start_header (st);
|
||||
if (!header)
|
||||
return;
|
||||
tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE);
|
||||
tar_copy_str (header->header.linkname, st->link_name, NAME_FIELD_SIZE);
|
||||
header->header.typeflag = SYMTYPE;
|
||||
finish_header (st, header, block_ordinal);
|
||||
/* nothing more to do to it */
|
||||
|
||||
12
src/delete.c
12
src/delete.c
@@ -5,7 +5,7 @@
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -174,7 +174,7 @@ delete_archive_members (void)
|
||||
abort ();
|
||||
|
||||
case HEADER_SUCCESS:
|
||||
if ((name = name_scan (current_stat_info.file_name, false)) == NULL)
|
||||
if ((name = name_scan (current_stat_info.file_name)) == NULL)
|
||||
{
|
||||
skip_member ();
|
||||
break;
|
||||
@@ -285,7 +285,7 @@ delete_archive_members (void)
|
||||
|
||||
/* Found another header. */
|
||||
|
||||
if ((name = name_scan (current_stat_info.file_name, false)) != NULL)
|
||||
if ((name = name_scan (current_stat_info.file_name)) != NULL)
|
||||
{
|
||||
name->found_count++;
|
||||
if (ISFOUND(name))
|
||||
@@ -307,10 +307,10 @@ delete_archive_members (void)
|
||||
}
|
||||
/* Copy header. */
|
||||
|
||||
if (extended_header.size)
|
||||
if (current_stat_info.xhdr.size)
|
||||
{
|
||||
write_recent_bytes (extended_header.buffer,
|
||||
extended_header.size);
|
||||
write_recent_bytes (current_stat_info.xhdr.buffer,
|
||||
current_stat_info.xhdr.size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
138
src/extract.c
138
src/extract.c
@@ -1,13 +1,13 @@
|
||||
/* Extract files from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-11-19.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -37,7 +37,8 @@ enum permstatus
|
||||
/* This file may have existed already; its permissions are unknown. */
|
||||
UNKNOWN_PERMSTATUS,
|
||||
|
||||
/* This file was created using the permissions from the archive. */
|
||||
/* This file was created using the permissions from the archive,
|
||||
except with S_IRWXG | S_IRWXO masked out if 0 < same_owner_option. */
|
||||
ARCHIVED_PERMSTATUS,
|
||||
|
||||
/* This is an intermediate directory; the archive did not specify
|
||||
@@ -149,12 +150,15 @@ set_mode (char const *file_name,
|
||||
{
|
||||
mode = stat_info->st_mode;
|
||||
|
||||
/* If we created the file and it has a usual mode, then its mode
|
||||
is normally set correctly already. But on many hosts, some
|
||||
/* If we created the file and it has a mode that we set already
|
||||
with O_CREAT, then its mode is often set correctly already.
|
||||
But if we are changing ownership, the mode's group and and
|
||||
other permission bits were omitted originally, so it's less
|
||||
likely that the mode is OK now. Also, on many hosts, some
|
||||
directories inherit the setgid bits from their parents, so we
|
||||
we must set directories' modes explicitly. */
|
||||
if (permstatus == ARCHIVED_PERMSTATUS
|
||||
&& ! (mode & ~ MODE_RWX)
|
||||
if ((permstatus == ARCHIVED_PERMSTATUS
|
||||
&& ! (mode & ~ (0 < same_owner_option ? S_IRWXU : MODE_RWX)))
|
||||
&& typeflag != DIRTYPE
|
||||
&& typeflag != GNUTYPE_DUMPDIR)
|
||||
return;
|
||||
@@ -217,7 +221,7 @@ check_time (char const *file_name, struct timespec t)
|
||||
/* Restore stat attributes (owner, group, mode and times) for
|
||||
FILE_NAME, using information given in *ST.
|
||||
If CUR_INFO is nonzero, *CUR_INFO is the
|
||||
file's currernt status.
|
||||
file's current status.
|
||||
If not restoring permissions, invert the
|
||||
INVERT_PERMISSIONS bits from the file's current permissions.
|
||||
PERMSTATUS specifies the status of the file's permissions.
|
||||
@@ -265,11 +269,11 @@ set_stat (char const *file_name,
|
||||
}
|
||||
|
||||
/* Some systems allow non-root users to give files away. Once this
|
||||
done, it is not possible anymore to change file permissions, so we
|
||||
have to set permissions prior to possibly giving files away. */
|
||||
|
||||
set_mode (file_name, &st->stat, cur_info,
|
||||
invert_permissions, permstatus, typeflag);
|
||||
done, it is not possible anymore to change file permissions.
|
||||
However, setting file permissions now would be incorrect, since
|
||||
they would apply to the wrong user, and there would be a race
|
||||
condition. So, don't use systems that allow non-root users to
|
||||
give files away. */
|
||||
}
|
||||
|
||||
if (0 < same_owner_option && permstatus != INTERDIR_PERMSTATUS)
|
||||
@@ -278,29 +282,36 @@ set_stat (char const *file_name,
|
||||
the symbolic link itself. In this case, a mere chown would change
|
||||
the attributes of the file the symbolic link is pointing to, and
|
||||
should be avoided. */
|
||||
int chown_result = 1;
|
||||
|
||||
if (typeflag == SYMTYPE)
|
||||
{
|
||||
#if HAVE_LCHOWN
|
||||
if (lchown (file_name, st->stat.st_uid, st->stat.st_gid) < 0)
|
||||
chown_error_details (file_name,
|
||||
st->stat.st_uid, st->stat.st_gid);
|
||||
chown_result = lchown (file_name, st->stat.st_uid, st->stat.st_gid);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (chown (file_name, st->stat.st_uid, st->stat.st_gid) < 0)
|
||||
chown_error_details (file_name,
|
||||
st->stat.st_uid, st->stat.st_gid);
|
||||
|
||||
/* On a few systems, and in particular, those allowing to give files
|
||||
away, changing the owner or group destroys the suid or sgid bits.
|
||||
So let's attempt setting these bits once more. */
|
||||
if (st->stat.st_mode & (S_ISUID | S_ISGID | S_ISVTX))
|
||||
set_mode (file_name, &st->stat, 0,
|
||||
invert_permissions, permstatus, typeflag);
|
||||
chown_result = chown (file_name, st->stat.st_uid, st->stat.st_gid);
|
||||
}
|
||||
|
||||
if (chown_result == 0)
|
||||
{
|
||||
/* Changing the owner can flip st_mode bits in some cases, so
|
||||
ignore cur_info if it might be obsolete now. */
|
||||
if (cur_info
|
||||
&& cur_info->st_mode & S_IXUGO
|
||||
&& cur_info->st_mode & (S_ISUID | S_ISGID))
|
||||
cur_info = NULL;
|
||||
}
|
||||
else if (chown_result < 0)
|
||||
chown_error_details (file_name,
|
||||
st->stat.st_uid, st->stat.st_gid);
|
||||
}
|
||||
|
||||
if (typeflag != SYMTYPE)
|
||||
set_mode (file_name, &st->stat, cur_info,
|
||||
invert_permissions, permstatus, typeflag);
|
||||
}
|
||||
|
||||
/* Remember to restore stat attributes (owner, group, mode and times)
|
||||
@@ -374,7 +385,8 @@ repair_delayed_set_stat (char const *dir,
|
||||
data->atime = current_stat_info.atime;
|
||||
data->mtime = current_stat_info.mtime;
|
||||
data->invert_permissions =
|
||||
(MODE_RWX & (current_stat_info.stat.st_mode ^ st.st_mode));
|
||||
((current_stat_info.stat.st_mode ^ st.st_mode)
|
||||
& MODE_RWX & ~ current_umask);
|
||||
data->permstatus = ARCHIVED_PERMSTATUS;
|
||||
return;
|
||||
}
|
||||
@@ -581,13 +593,13 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
|
||||
|
||||
if (! skip_this_one)
|
||||
{
|
||||
struct tar_stat_info st;
|
||||
st.stat.st_mode = data->mode;
|
||||
st.stat.st_uid = data->uid;
|
||||
st.stat.st_gid = data->gid;
|
||||
st.atime = data->atime;
|
||||
st.mtime = data->mtime;
|
||||
set_stat (data->file_name, &st, cur_info,
|
||||
struct tar_stat_info sb;
|
||||
sb.stat.st_mode = data->mode;
|
||||
sb.stat.st_uid = data->uid;
|
||||
sb.stat.st_gid = data->gid;
|
||||
sb.atime = data->atime;
|
||||
sb.mtime = data->mtime;
|
||||
set_stat (data->file_name, &sb, cur_info,
|
||||
data->invert_permissions, data->permstatus, DIRTYPE);
|
||||
}
|
||||
|
||||
@@ -626,8 +638,9 @@ extract_dir (char *file_name, int typeflag)
|
||||
else if (typeflag == GNUTYPE_DUMPDIR)
|
||||
skip_member ();
|
||||
|
||||
mode = (current_stat_info.stat.st_mode |
|
||||
(we_are_root ? 0 : MODE_WXUSR)) & MODE_RWX;
|
||||
mode = current_stat_info.stat.st_mode | (we_are_root ? 0 : MODE_WXUSR);
|
||||
if (0 < same_owner_option || current_stat_info.stat.st_mode & ~ MODE_RWX)
|
||||
mode &= S_IRWXU;
|
||||
|
||||
while ((status = mkdir (file_name, mode)))
|
||||
{
|
||||
@@ -670,7 +683,8 @@ extract_dir (char *file_name, int typeflag)
|
||||
{
|
||||
if (status == 0)
|
||||
delay_set_stat (file_name, ¤t_stat_info,
|
||||
MODE_RWX & (mode ^ current_stat_info.stat.st_mode),
|
||||
((mode ^ current_stat_info.stat.st_mode)
|
||||
& MODE_RWX & ~ current_umask),
|
||||
ARCHIVED_PERMSTATUS);
|
||||
else /* For an already existing directory, invert_perms must be 0 */
|
||||
delay_set_stat (file_name, ¤t_stat_info,
|
||||
@@ -682,14 +696,13 @@ extract_dir (char *file_name, int typeflag)
|
||||
|
||||
|
||||
static int
|
||||
open_output_file (char *file_name, int typeflag)
|
||||
open_output_file (char *file_name, int typeflag, mode_t mode)
|
||||
{
|
||||
int fd;
|
||||
int openflag = (O_WRONLY | O_BINARY | O_CREAT
|
||||
| (old_files_option == OVERWRITE_OLD_FILES
|
||||
? O_TRUNC
|
||||
: O_EXCL));
|
||||
mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
|
||||
|
||||
#if O_CTG
|
||||
/* Contiguous files (on the Masscomp) have to specify the size in
|
||||
@@ -728,6 +741,9 @@ extract_file (char *file_name, int typeflag)
|
||||
size_t count;
|
||||
size_t written;
|
||||
int interdir_made = 0;
|
||||
mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
|
||||
mode_t invert_permissions =
|
||||
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
|
||||
|
||||
/* FIXME: deal with protection issues. */
|
||||
|
||||
@@ -745,11 +761,12 @@ extract_file (char *file_name, int typeflag)
|
||||
else
|
||||
{
|
||||
do
|
||||
fd = open_output_file (file_name, typeflag);
|
||||
fd = open_output_file (file_name, typeflag, mode ^ invert_permissions);
|
||||
while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
skip_member ();
|
||||
open_error (file_name);
|
||||
return 1;
|
||||
}
|
||||
@@ -810,7 +827,7 @@ extract_file (char *file_name, int typeflag)
|
||||
if (to_command_option)
|
||||
sys_wait_command ();
|
||||
else
|
||||
set_stat (file_name, ¤t_stat_info, NULL, 0,
|
||||
set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
|
||||
(old_files_option == OVERWRITE_OLD_FILES ?
|
||||
UNKNOWN_PERMSTATUS : ARCHIVED_PERMSTATUS),
|
||||
typeflag);
|
||||
@@ -871,7 +888,7 @@ create_placeholder_file (char *file_name, bool is_symlink, int *interdir_made)
|
||||
if (h && ! h->after_links
|
||||
&& strncmp (file_name, h->file_name, h->file_name_len) == 0
|
||||
&& ISSLASH (file_name[h->file_name_len])
|
||||
&& (base_name (file_name) == file_name + h->file_name_len + 1))
|
||||
&& (last_component (file_name) == file_name + h->file_name_len + 1))
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -897,10 +914,11 @@ create_placeholder_file (char *file_name, bool is_symlink, int *interdir_made)
|
||||
static int
|
||||
extract_link (char *file_name, int typeflag)
|
||||
{
|
||||
char const *link_name = safer_name_suffix (current_stat_info.link_name,
|
||||
true, absolute_names_option);
|
||||
int interdir_made = 0;
|
||||
char const *link_name;
|
||||
|
||||
link_name = current_stat_info.link_name;
|
||||
|
||||
if (! absolute_names_option && contains_dot_dot (link_name))
|
||||
return create_placeholder_file (file_name, false, &interdir_made);
|
||||
|
||||
@@ -988,16 +1006,19 @@ extract_node (char *file_name, int typeflag)
|
||||
{
|
||||
int status;
|
||||
int interdir_made = 0;
|
||||
mode_t mode = current_stat_info.stat.st_mode & ~ current_umask;
|
||||
mode_t invert_permissions =
|
||||
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
|
||||
|
||||
do
|
||||
status = mknod (file_name, current_stat_info.stat.st_mode,
|
||||
status = mknod (file_name, mode ^ invert_permissions,
|
||||
current_stat_info.stat.st_rdev);
|
||||
while (status && maybe_recoverable (file_name, &interdir_made));
|
||||
|
||||
if (status != 0)
|
||||
mknod_error (file_name);
|
||||
else
|
||||
set_stat (file_name, ¤t_stat_info, NULL, 0,
|
||||
set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
|
||||
ARCHIVED_PERMSTATUS, typeflag);
|
||||
return status;
|
||||
}
|
||||
@@ -1009,13 +1030,16 @@ extract_fifo (char *file_name, int typeflag)
|
||||
{
|
||||
int status;
|
||||
int interdir_made = 0;
|
||||
mode_t mode = current_stat_info.stat.st_mode & ~ current_umask;
|
||||
mode_t invert_permissions =
|
||||
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
|
||||
|
||||
while ((status = mkfifo (file_name, current_stat_info.stat.st_mode)))
|
||||
while ((status = mkfifo (file_name, mode)) != 0)
|
||||
if (!maybe_recoverable (file_name, &interdir_made))
|
||||
break;
|
||||
|
||||
if (status == 0)
|
||||
set_stat (file_name, ¤t_stat_info, NULL, 0,
|
||||
set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
|
||||
ARCHIVED_PERMSTATUS, typeflag);
|
||||
else
|
||||
mkfifo_error (file_name);
|
||||
@@ -1023,19 +1047,13 @@ extract_fifo (char *file_name, int typeflag)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
extract_mangle_wrapper (char *file_name, int typeflag)
|
||||
{
|
||||
extract_mangle ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
extract_volhdr (char *file_name, int typeflag)
|
||||
{
|
||||
if (verbose_option)
|
||||
fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
|
||||
skip_member ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1120,10 +1138,6 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
||||
*fun = extract_volhdr;
|
||||
break;
|
||||
|
||||
case GNUTYPE_NAMES:
|
||||
*fun = extract_mangle_wrapper;
|
||||
break;
|
||||
|
||||
case GNUTYPE_MULTIVOL:
|
||||
ERROR ((0, 0,
|
||||
_("%s: Cannot extract -- file is continued from another volume"),
|
||||
@@ -1330,10 +1344,10 @@ rename_directory (char *src, char *dst)
|
||||
e = errno;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case EXDEV:
|
||||
/* FIXME: Fall back to recursive copying */
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1345,7 +1359,7 @@ rename_directory (char *src, char *dst)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fatal_exit (void)
|
||||
{
|
||||
|
||||
946
src/incremen.c
946
src/incremen.c
File diff suppressed because it is too large
Load Diff
73
src/list.c
73
src/list.c
@@ -1,13 +1,13 @@
|
||||
/* List a tar archive, with support routines for reading a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-26.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -76,7 +76,6 @@ read_and (void (*do_something) (void))
|
||||
{
|
||||
prev_status = status;
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
xheader_destroy (&extended_header);
|
||||
|
||||
status = read_header (false);
|
||||
switch (status)
|
||||
@@ -107,7 +106,6 @@ read_and (void (*do_something) (void))
|
||||
{
|
||||
case GNUTYPE_VOLHDR:
|
||||
case GNUTYPE_MULTIVOL:
|
||||
case GNUTYPE_NAMES:
|
||||
break;
|
||||
|
||||
case DIRTYPE:
|
||||
@@ -303,8 +301,8 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
size_t size, written;
|
||||
union block *next_long_name = 0;
|
||||
union block *next_long_link = 0;
|
||||
size_t next_long_name_blocks;
|
||||
size_t next_long_link_blocks;
|
||||
size_t next_long_name_blocks = 0;
|
||||
size_t next_long_link_blocks = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -388,12 +386,16 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
}
|
||||
else if (header->header.typeflag == XHDTYPE
|
||||
|| header->header.typeflag == SOLARIS_XHDTYPE)
|
||||
xheader_read (header, OFF_FROM_HEADER (header->header.size));
|
||||
xheader_read (&info->xhdr, header,
|
||||
OFF_FROM_HEADER (header->header.size));
|
||||
else if (header->header.typeflag == XGLTYPE)
|
||||
{
|
||||
xheader_read (header, OFF_FROM_HEADER (header->header.size));
|
||||
xheader_decode_global ();
|
||||
xheader_destroy (&extended_header);
|
||||
struct xheader xhdr;
|
||||
memset (&xhdr, 0, sizeof xhdr);
|
||||
xheader_read (&xhdr, header,
|
||||
OFF_FROM_HEADER (header->header.size));
|
||||
xheader_decode_global (&xhdr);
|
||||
xheader_destroy (&xhdr);
|
||||
}
|
||||
|
||||
/* Loop! */
|
||||
@@ -468,9 +470,29 @@ read_header (bool raw_extended_headers)
|
||||
}
|
||||
|
||||
static char *
|
||||
decode_xform (char *file_name)
|
||||
decode_xform (char *file_name, void *data)
|
||||
{
|
||||
file_name = safer_name_suffix (file_name, false, absolute_names_option);
|
||||
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,
|
||||
@@ -482,6 +504,12 @@ decode_xform (char *file_name)
|
||||
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
|
||||
@@ -511,7 +539,7 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
&& ISOCTAL (header->star_header.ctime[0])
|
||||
&& header->star_header.ctime[11] == ' ')
|
||||
format = STAR_FORMAT;
|
||||
else if (extended_header.size)
|
||||
else if (stat_info->xhdr.size)
|
||||
format = POSIX_FORMAT;
|
||||
else
|
||||
format = USTAR_FORMAT;
|
||||
@@ -600,7 +628,16 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
stat_info->is_dumpdir = true;
|
||||
}
|
||||
|
||||
transform_name_fp (&stat_info->file_name, decode_xform);
|
||||
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
|
||||
@@ -1047,10 +1084,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
modes[0] = 'M';
|
||||
break;
|
||||
|
||||
case GNUTYPE_NAMES:
|
||||
modes[0] = 'N';
|
||||
break;
|
||||
|
||||
case GNUTYPE_LONGNAME:
|
||||
case GNUTYPE_LONGLINK:
|
||||
modes[0] = 'L';
|
||||
@@ -1234,10 +1267,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
uintbuf));
|
||||
fprintf (stdlis, _("--Continued at byte %s--\n"), size);
|
||||
break;
|
||||
|
||||
case GNUTYPE_NAMES:
|
||||
fprintf (stdlis, _("--Mangled file names--\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
fflush (stdlis);
|
||||
|
||||
121
src/mangle.c
121
src/mangle.c
@@ -1,121 +0,0 @@
|
||||
/* Encode long filenames for GNU tar.
|
||||
Copyright 1988, 92, 94, 96, 97, 99, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
#include <quotearg.h>
|
||||
|
||||
struct mangled
|
||||
{
|
||||
struct mangled *next;
|
||||
int type;
|
||||
char mangled[NAME_FIELD_SIZE];
|
||||
char *linked_to;
|
||||
char normal[1];
|
||||
};
|
||||
|
||||
/* Extract a GNUTYPE_NAMES record contents. It seems that such are
|
||||
not produced anymore by GNU tar, but we leave the reading code
|
||||
around nevertheless, for salvaging old tapes. */
|
||||
void
|
||||
extract_mangle (void)
|
||||
{
|
||||
off_t size = current_stat_info.stat.st_size;
|
||||
char *buffer = xmalloc ((size_t) (size + 1));
|
||||
char *copy = buffer;
|
||||
char *cursor = buffer;
|
||||
|
||||
if (size != (size_t) size || size == (size_t) -1)
|
||||
xalloc_die ();
|
||||
|
||||
buffer[size] = '\0';
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
union block *block = find_next_block ();
|
||||
size_t available;
|
||||
|
||||
if (!block)
|
||||
{
|
||||
ERROR ((0, 0, _("Unexpected EOF in mangled names")));
|
||||
return;
|
||||
}
|
||||
available = available_space_after (block);
|
||||
if (available > size)
|
||||
available = size;
|
||||
memcpy (copy, block->buffer, available);
|
||||
copy += available;
|
||||
size -= available;
|
||||
set_next_block_after ((union block *) (block->buffer + available - 1));
|
||||
}
|
||||
|
||||
while (*cursor)
|
||||
{
|
||||
char *next_cursor;
|
||||
char *name;
|
||||
char *name_end;
|
||||
|
||||
next_cursor = strchr (cursor, '\n');
|
||||
*next_cursor++ = '\0';
|
||||
|
||||
if (!strncmp (cursor, "Rename ", 7))
|
||||
{
|
||||
|
||||
name = cursor + 7;
|
||||
name_end = strchr (name, ' ');
|
||||
while (strncmp (name_end, " to ", 4))
|
||||
{
|
||||
name_end++;
|
||||
name_end = strchr (name_end, ' ');
|
||||
}
|
||||
*name_end = '\0';
|
||||
if (next_cursor[-2] == '/')
|
||||
next_cursor[-2] = '\0';
|
||||
unquote_string (name_end + 4);
|
||||
if (rename (name, name_end + 4))
|
||||
ERROR ((0, errno, _("%s: Cannot rename to %s"),
|
||||
quotearg_colon (name), quote_n (1, name_end + 4)));
|
||||
else if (verbose_option)
|
||||
WARN ((0, 0, _("Renamed %s to %s"), name, name_end + 4));
|
||||
}
|
||||
#ifdef HAVE_SYMLINK
|
||||
else if (!strncmp (cursor, "Symlink ", 8))
|
||||
{
|
||||
name = cursor + 8;
|
||||
name_end = strchr (name, ' ');
|
||||
while (strncmp (name_end, " to ", 4))
|
||||
{
|
||||
name_end++;
|
||||
name_end = strchr (name_end, ' ');
|
||||
}
|
||||
*name_end = '\0';
|
||||
unquote_string (name);
|
||||
unquote_string (name_end + 4);
|
||||
if (symlink (name, name_end + 4)
|
||||
&& (unlink (name_end + 4) || symlink (name, name_end + 4)))
|
||||
ERROR ((0, errno, _("%s: Cannot symlink to %s"),
|
||||
quotearg_colon (name), quote_n (1, name_end + 4)));
|
||||
else if (verbose_option)
|
||||
WARN ((0, 0, _("Symlinked %s to %s"), name, name_end + 4));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ERROR ((0, 0, _("Unknown demangling command %s"), cursor));
|
||||
|
||||
cursor = next_cursor;
|
||||
}
|
||||
}
|
||||
42
src/misc.c
42
src/misc.c
@@ -1,11 +1,11 @@
|
||||
/* Miscellaneous functions, not really specific to GNU tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "common.h"
|
||||
#include <quotearg.h>
|
||||
#include <save-cwd.h>
|
||||
#include <xgetcwd.h>
|
||||
#include <unlinkdir.h>
|
||||
#include <utimens.h>
|
||||
|
||||
@@ -412,7 +413,7 @@ remove_any_file (const char *file_name, enum remove_option option)
|
||||
so, we do not have to backup block or character devices, nor remote
|
||||
entities. */
|
||||
bool
|
||||
maybe_backup_file (const char *file_name, int this_is_the_archive)
|
||||
maybe_backup_file (const char *file_name, bool this_is_the_archive)
|
||||
{
|
||||
struct stat file_stat;
|
||||
|
||||
@@ -515,7 +516,7 @@ set_file_atime (int fd, char const *file, struct timespec const timespec[2])
|
||||
}
|
||||
#endif
|
||||
|
||||
return futimens (fd, file, timespec);
|
||||
return gl_futimens (fd, file, timespec);
|
||||
}
|
||||
|
||||
/* A description of a working directory. */
|
||||
@@ -542,8 +543,14 @@ chdir_arg (char const *dir)
|
||||
{
|
||||
if (wds == wd_alloc)
|
||||
{
|
||||
wd_alloc = 2 * (wd_alloc + 1);
|
||||
wd = xrealloc (wd, sizeof *wd * wd_alloc);
|
||||
if (wd_alloc == 0)
|
||||
{
|
||||
wd_alloc = 2;
|
||||
wd = xmalloc (sizeof *wd * wd_alloc);
|
||||
}
|
||||
else
|
||||
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
|
||||
|
||||
if (! wds)
|
||||
{
|
||||
wd[wds].name = ".";
|
||||
@@ -582,9 +589,30 @@ chdir_do (int i)
|
||||
|
||||
if (! prev->saved)
|
||||
{
|
||||
int err = 0;
|
||||
prev->saved = 1;
|
||||
if (save_cwd (&prev->saved_cwd) != 0)
|
||||
FATAL_ERROR ((0, 0, _("Cannot save working directory")));
|
||||
err = errno;
|
||||
else if (0 <= prev->saved_cwd.desc)
|
||||
{
|
||||
/* Make sure we still have at least one descriptor available. */
|
||||
int fd1 = prev->saved_cwd.desc;
|
||||
int fd2 = dup (fd1);
|
||||
if (0 <= fd2)
|
||||
close (fd2);
|
||||
else if (errno == EMFILE)
|
||||
{
|
||||
/* Force restore_cwd to use chdir_long. */
|
||||
close (fd1);
|
||||
prev->saved_cwd.desc = -1;
|
||||
prev->saved_cwd.name = xgetcwd ();
|
||||
}
|
||||
else
|
||||
err = errno;
|
||||
}
|
||||
|
||||
if (err)
|
||||
FATAL_ERROR ((0, err, _("Cannot save working directory")));
|
||||
}
|
||||
|
||||
if (curr->saved)
|
||||
|
||||
53
src/names.c
53
src/names.c
@@ -1,11 +1,11 @@
|
||||
/* Various processing of names.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -289,9 +289,8 @@ static int matching_flags; /* exclude_fnmatch options */
|
||||
static storage and can't be relied upon across two calls.
|
||||
|
||||
If CHANGE_DIRS is true, treat any entries of type NELT_CHDIR as
|
||||
the request to change to the given directory. If filename_terminator
|
||||
is NUL, CHANGE_DIRS is effectively always false.
|
||||
|
||||
the request to change to the given directory.
|
||||
|
||||
Entries of type NELT_FMASK cause updates of the matching_flags
|
||||
value. */
|
||||
struct name_elt *
|
||||
@@ -301,9 +300,6 @@ name_next_elt (int change_dirs)
|
||||
const char *source;
|
||||
char *cursor;
|
||||
|
||||
if (filename_terminator == '\0')
|
||||
change_dirs = 0;
|
||||
|
||||
while (name_index != names)
|
||||
{
|
||||
struct name_elt *ep;
|
||||
@@ -392,9 +388,7 @@ name_gather (void)
|
||||
if (allocated_size == 0)
|
||||
{
|
||||
allocated_size = offsetof (struct name, name) + NAME_FIELD_SIZE + 1;
|
||||
buffer = xmalloc (allocated_size);
|
||||
/* FIXME: This memset is overkill, and ugly... */
|
||||
memset (buffer, 0, allocated_size);
|
||||
buffer = xzalloc (allocated_size);
|
||||
}
|
||||
|
||||
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
|
||||
@@ -471,7 +465,6 @@ addname (char const *string, int change_dir)
|
||||
name->matching_flags = matching_flags;
|
||||
name->change_dir = change_dir;
|
||||
name->dir_contents = NULL;
|
||||
name->explicit = 1;
|
||||
|
||||
*nametail = name;
|
||||
nametail = &name->next;
|
||||
@@ -481,7 +474,7 @@ addname (char const *string, int change_dir)
|
||||
/* Find a match for FILE_NAME (whose string length is LENGTH) in the name
|
||||
list. */
|
||||
static struct name *
|
||||
namelist_match (char const *file_name, size_t length, bool exact)
|
||||
namelist_match (char const *file_name, size_t length)
|
||||
{
|
||||
struct name *p;
|
||||
|
||||
@@ -497,7 +490,7 @@ namelist_match (char const *file_name, size_t length, bool exact)
|
||||
|
||||
/* Return true if and only if name FILE_NAME (from an archive) matches any
|
||||
name from the namelist. */
|
||||
int
|
||||
bool
|
||||
name_match (const char *file_name)
|
||||
{
|
||||
size_t length = strlen (file_name);
|
||||
@@ -507,17 +500,17 @@ name_match (const char *file_name)
|
||||
struct name *cursor = namelist;
|
||||
|
||||
if (!cursor)
|
||||
return 1;
|
||||
|
||||
return true;
|
||||
|
||||
if (cursor->name[0] == 0)
|
||||
{
|
||||
chdir_do (cursor->change_dir);
|
||||
namelist = 0;
|
||||
nametail = &namelist;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
cursor = namelist_match (file_name, length, false);
|
||||
cursor = namelist_match (file_name, length);
|
||||
if (cursor)
|
||||
{
|
||||
if (!(ISSLASH (file_name[cursor->length]) && recursion_option)
|
||||
@@ -544,10 +537,10 @@ name_match (const char *file_name)
|
||||
{
|
||||
name_gather (); /* read one more */
|
||||
if (namelist->found_count)
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,8 +566,7 @@ all_names_found (struct tar_stat_info *p)
|
||||
len = strlen (p->file_name);
|
||||
for (cursor = namelist; cursor; cursor = cursor->next)
|
||||
{
|
||||
if (cursor->matching_flags /* FIXME: check this */
|
||||
|| (!WASFOUND (cursor) && cursor->name[0])
|
||||
if ((cursor->name[0] && !WASFOUND (cursor))
|
||||
|| (len >= cursor->length && ISSLASH (p->file_name[cursor->length])))
|
||||
return false;
|
||||
}
|
||||
@@ -736,7 +728,7 @@ static void
|
||||
add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
{
|
||||
char *file_name = name->name;
|
||||
char *buffer = get_directory_contents (file_name, device);
|
||||
const char *buffer = get_directory_contents (file_name, device);
|
||||
|
||||
if (! buffer)
|
||||
name->dir_contents = "\0\0\0\0";
|
||||
@@ -748,7 +740,7 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
: NAME_FIELD_SIZE);
|
||||
char *namebuf = xmalloc (allocated_length + 1);
|
||||
/* FIXME: + 2 above? */
|
||||
char *string;
|
||||
const char *string;
|
||||
size_t string_length;
|
||||
int change_dir = name->change_dir;
|
||||
|
||||
@@ -781,7 +773,6 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
}
|
||||
strcpy (namebuf + name_length, string + 1);
|
||||
np = addname (namebuf, change_dir);
|
||||
np->explicit = 0;
|
||||
add_hierarchy_to_namelist (np, device);
|
||||
}
|
||||
}
|
||||
@@ -856,18 +847,15 @@ collect_and_sort_names (void)
|
||||
1. It returns a pointer to the name it matched, and doesn't set FOUND
|
||||
in structure. The caller will have to do that if it wants to.
|
||||
2. If the namelist is empty, it returns null, unlike name_match, which
|
||||
returns TRUE.
|
||||
3. The second argument (EXACT) controls matching algorithm. If it
|
||||
is TRUE, the exact matching is used. However, regular expressions are
|
||||
always matched as such, no matter what the value of EXACT is. */
|
||||
returns TRUE. */
|
||||
struct name *
|
||||
name_scan (const char *file_name, bool exact)
|
||||
name_scan (const char *file_name)
|
||||
{
|
||||
size_t length = strlen (file_name);
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct name *cursor = namelist_match (file_name, length, exact);
|
||||
struct name *cursor = namelist_match (file_name, length);
|
||||
if (cursor)
|
||||
return cursor;
|
||||
|
||||
@@ -1018,11 +1006,10 @@ contains_dot_dot (char const *name)
|
||||
if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
|
||||
return 1;
|
||||
|
||||
do
|
||||
while (! ISSLASH (*p))
|
||||
{
|
||||
if (! *p++)
|
||||
return 0;
|
||||
}
|
||||
while (! ISSLASH (*p));
|
||||
}
|
||||
}
|
||||
|
||||
331
src/sparse.c
331
src/sparse.c
@@ -1,10 +1,10 @@
|
||||
/* Functions for dealing with sparse files
|
||||
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -409,15 +409,6 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
|
||||
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
|
||||
}
|
||||
|
||||
/* Returns true if the file represented by stat is a sparse one */
|
||||
bool
|
||||
sparse_file_p (struct tar_stat_info *st)
|
||||
{
|
||||
return (ST_NBLOCKS (st->stat)
|
||||
< (st->stat.st_size / ST_NBLOCKSIZE
|
||||
+ (st->stat.st_size % ST_NBLOCKSIZE != 0)));
|
||||
}
|
||||
|
||||
bool
|
||||
sparse_member_p (struct tar_stat_info *st)
|
||||
{
|
||||
@@ -475,7 +466,7 @@ sparse_skip_file (struct tar_stat_info *st)
|
||||
file.fd = -1;
|
||||
|
||||
rc = tar_sparse_decode_header (&file);
|
||||
skip_file (file.stat_info->archive_file_size);
|
||||
skip_file (file.stat_info->archive_file_size - file.dumped_size);
|
||||
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
|
||||
}
|
||||
|
||||
@@ -740,11 +731,9 @@ oldgnu_dump_header (struct tar_sparse_file *file)
|
||||
oldgnu_store_sparse_info (file, &i,
|
||||
blk->sparse_header.sp,
|
||||
SPARSES_IN_SPARSE_HEADER);
|
||||
set_next_block_after (blk);
|
||||
if (i < file->stat_info->sparse_map_avail)
|
||||
blk->sparse_header.isextended = 1;
|
||||
else
|
||||
break;
|
||||
set_next_block_after (blk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -843,16 +832,15 @@ static struct tar_sparse_optab const star_optab = {
|
||||
};
|
||||
|
||||
|
||||
/* GNU PAX sparse file format. The sparse file map is stored in
|
||||
x header:
|
||||
/* GNU PAX sparse file format. There are several versions:
|
||||
|
||||
* 0.0
|
||||
|
||||
The initial version of sparse format used by tar 1.14-1.15.1.
|
||||
The sparse file map is stored in x header:
|
||||
|
||||
GNU.sparse.size Real size of the stored file
|
||||
GNU.sparse.numblocks Number of blocks in the sparse map
|
||||
GNU.sparse.map Map of non-null data chunks. A string consisting
|
||||
of comma-separated values "offset,size[,offset,size]..."
|
||||
|
||||
Tar versions 1.14-1.15.1 instead of the latter used:
|
||||
|
||||
repeat numblocks time
|
||||
GNU.sparse.offset Offset of the next data block
|
||||
GNU.sparse.numbytes Size of the next data block
|
||||
@@ -860,44 +848,89 @@ static struct tar_sparse_optab const star_optab = {
|
||||
|
||||
This has been reported as conflicting with the POSIX specs. The reason is
|
||||
that offsets and sizes of non-zero data blocks were stored in multiple
|
||||
instances of GNU.sparse.offset/GNU.sparse.numbytes variables. However,
|
||||
instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
|
||||
POSIX requires the latest occurrence of the variable to override all
|
||||
previous occurrences.
|
||||
|
||||
To avoid this incompatibility new keyword GNU.sparse.map was introduced
|
||||
in tar 1.15.2. Some people might still need the 1.14 way of handling
|
||||
sparse files for the compatibility reasons: it can be achieved by
|
||||
specifying `--pax-option delete=GNU.sparse.map' in the command line.
|
||||
|
||||
To avoid this incompatibility two following versions were introduced.
|
||||
|
||||
See FIXME-1.14-1.15.1-1.20, below.
|
||||
* 0.1
|
||||
|
||||
Used by tar 1.15.2 -- 1.15.91 (alpha releases).
|
||||
|
||||
The sparse file map is stored in
|
||||
x header:
|
||||
|
||||
GNU.sparse.size Real size of the stored file
|
||||
GNU.sparse.numblocks Number of blocks in the sparse map
|
||||
GNU.sparse.map Map of non-null data chunks. A string consisting
|
||||
of comma-separated values "offset,size[,offset,size]..."
|
||||
|
||||
The resulting GNU.sparse.map string can be *very* long. While POSIX does not
|
||||
impose any limit on the length of a x header variable, this can confuse some
|
||||
tars.
|
||||
|
||||
* 1.0
|
||||
|
||||
Starting from this version, the exact sparse format version is specified
|
||||
explicitely in the header using the following variables:
|
||||
|
||||
GNU.sparse.major Major version
|
||||
GNU.sparse.minor Minor version
|
||||
|
||||
X header keeps the following variables:
|
||||
|
||||
GNU.sparse.name Real file name of the sparse file
|
||||
GNU.sparse.realsize Real size of the stored file (corresponds to the old
|
||||
GNU.sparse.size variable)
|
||||
|
||||
The name field of the ustar header is constructed using the pattern
|
||||
"%d/GNUSparseFile.%p/%f".
|
||||
|
||||
The sparse map itself is stored in the file data block, preceding the actual
|
||||
file data. It consists of a series of octal numbers of arbitrary length,
|
||||
delimited by newlines. The map is padded with nulls to the nearest block
|
||||
boundary.
|
||||
|
||||
The first number gives the number of entries in the map. Following are map
|
||||
entries, each one consisting of two numbers giving the offset and size of
|
||||
the data block it describes.
|
||||
|
||||
The format is designed in such a way that non-posix aware tars and tars not
|
||||
supporting GNU.sparse.* keywords will extract each sparse file in its
|
||||
condensed form with the file map attached and will place it into a separate
|
||||
directory. Then, using a simple program it would be possible to expand the
|
||||
file to its original form even without GNU tar.
|
||||
|
||||
Bu default, v.1.0 archives are created. To use other formats,
|
||||
--sparse-version option is provided. Additionally, v.0.0 can be obtained
|
||||
by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
|
||||
--pax-option delete=GNU.sparse.map
|
||||
*/
|
||||
|
||||
static bool
|
||||
pax_sparse_member_p (struct tar_sparse_file *file)
|
||||
{
|
||||
return file->stat_info->sparse_map_avail > 0;
|
||||
return file->stat_info->sparse_map_avail > 0
|
||||
|| file->stat_info->sparse_major > 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
pax_dump_header (struct tar_sparse_file *file)
|
||||
pax_dump_header_0 (struct tar_sparse_file *file)
|
||||
{
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
union block *blk;
|
||||
size_t i;
|
||||
char nbuf[UINTMAX_STRSIZE_BOUND];
|
||||
struct sp_array *map = file->stat_info->sparse_map;
|
||||
|
||||
char *save_file_name = NULL;
|
||||
|
||||
/* Store the real file size */
|
||||
xheader_store ("GNU.sparse.size", file->stat_info, NULL);
|
||||
xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
|
||||
|
||||
/* FIXME-1.14-1.15.1-1.20: See the comment above.
|
||||
Starting with 1.17 this should display a warning about POSIX-incompatible
|
||||
keywords being generated. In 1.20, the true branch of the if block below
|
||||
will be removed and GNU.sparse.map will be marked in xhdr_tab as
|
||||
protected. */
|
||||
|
||||
if (xheader_keyword_deleted_p ("GNU.sparse.map"))
|
||||
if (xheader_keyword_deleted_p ("GNU.sparse.map")
|
||||
|| tar_sparse_minor == 0)
|
||||
{
|
||||
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
|
||||
{
|
||||
@@ -907,21 +940,225 @@ pax_dump_header (struct tar_sparse_file *file)
|
||||
}
|
||||
else
|
||||
{
|
||||
xheader_string_begin ();
|
||||
xheader_store ("GNU.sparse.name", file->stat_info, NULL);
|
||||
save_file_name = file->stat_info->file_name;
|
||||
file->stat_info->file_name = xheader_format_name (file->stat_info,
|
||||
"%d/GNUSparseFile.%p/%f", 0);
|
||||
|
||||
xheader_string_begin (&file->stat_info->xhdr);
|
||||
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
|
||||
{
|
||||
if (i)
|
||||
xheader_string_add (",");
|
||||
xheader_string_add (umaxtostr (map[i].offset, nbuf));
|
||||
xheader_string_add (",");
|
||||
xheader_string_add (umaxtostr (map[i].numbytes, nbuf));
|
||||
xheader_string_add (&file->stat_info->xhdr, ",");
|
||||
xheader_string_add (&file->stat_info->xhdr,
|
||||
umaxtostr (map[i].offset, nbuf));
|
||||
xheader_string_add (&file->stat_info->xhdr, ",");
|
||||
xheader_string_add (&file->stat_info->xhdr,
|
||||
umaxtostr (map[i].numbytes, nbuf));
|
||||
}
|
||||
if (!xheader_string_end (&file->stat_info->xhdr,
|
||||
"GNU.sparse.map"))
|
||||
{
|
||||
free (file->stat_info->file_name);
|
||||
file->stat_info->file_name = save_file_name;
|
||||
return false;
|
||||
}
|
||||
xheader_string_end ("GNU.sparse.map");
|
||||
}
|
||||
blk = start_header (file->stat_info);
|
||||
/* Store the effective (shrunken) file size */
|
||||
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
|
||||
finish_header (file->stat_info, blk, block_ordinal);
|
||||
if (save_file_name)
|
||||
{
|
||||
free (file->stat_info->file_name);
|
||||
file->stat_info->file_name = save_file_name;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
pax_dump_header_1 (struct tar_sparse_file *file)
|
||||
{
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
union block *blk;
|
||||
char *p, *q;
|
||||
size_t i;
|
||||
char nbuf[UINTMAX_STRSIZE_BOUND];
|
||||
off_t size = 0;
|
||||
struct sp_array *map = file->stat_info->sparse_map;
|
||||
char *save_file_name = file->stat_info->file_name;
|
||||
|
||||
#define COPY_STRING(b,dst,src) do \
|
||||
{ \
|
||||
char *endp = b->buffer + BLOCKSIZE; \
|
||||
char *srcp = src; \
|
||||
while (*srcp) \
|
||||
{ \
|
||||
if (dst == endp) \
|
||||
{ \
|
||||
set_next_block_after (b); \
|
||||
b = find_next_block (); \
|
||||
dst = b->buffer; \
|
||||
endp = b->buffer + BLOCKSIZE; \
|
||||
} \
|
||||
*dst++ = *srcp++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Compute stored file size */
|
||||
p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
|
||||
size += strlen (p) + 1;
|
||||
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
|
||||
{
|
||||
p = umaxtostr (map[i].offset, nbuf);
|
||||
size += strlen (p) + 1;
|
||||
p = umaxtostr (map[i].numbytes, nbuf);
|
||||
size += strlen (p) + 1;
|
||||
}
|
||||
size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
file->stat_info->archive_file_size += size * BLOCKSIZE;
|
||||
file->dumped_size += size * BLOCKSIZE;
|
||||
|
||||
/* Store sparse file identification */
|
||||
xheader_store ("GNU.sparse.major", file->stat_info, NULL);
|
||||
xheader_store ("GNU.sparse.minor", file->stat_info, NULL);
|
||||
xheader_store ("GNU.sparse.name", file->stat_info, NULL);
|
||||
xheader_store ("GNU.sparse.realsize", file->stat_info, NULL);
|
||||
|
||||
file->stat_info->file_name = xheader_format_name (file->stat_info,
|
||||
"%d/GNUSparseFile.%p/%f", 0);
|
||||
|
||||
blk = start_header (file->stat_info);
|
||||
/* Store the effective (shrunken) file size */
|
||||
OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
|
||||
finish_header (file->stat_info, blk, block_ordinal);
|
||||
free (file->stat_info->file_name);
|
||||
file->stat_info->file_name = save_file_name;
|
||||
|
||||
blk = find_next_block ();
|
||||
q = blk->buffer;
|
||||
p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
|
||||
COPY_STRING (blk, q, p);
|
||||
COPY_STRING (blk, q, "\n");
|
||||
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
|
||||
{
|
||||
p = umaxtostr (map[i].offset, nbuf);
|
||||
COPY_STRING (blk, q, p);
|
||||
COPY_STRING (blk, q, "\n");
|
||||
p = umaxtostr (map[i].numbytes, nbuf);
|
||||
COPY_STRING (blk, q, p);
|
||||
COPY_STRING (blk, q, "\n");
|
||||
}
|
||||
memset (q, 0, BLOCKSIZE - (q - blk->buffer));
|
||||
set_next_block_after (blk);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
pax_dump_header (struct tar_sparse_file *file)
|
||||
{
|
||||
file->stat_info->sparse_major = tar_sparse_major;
|
||||
file->stat_info->sparse_minor = tar_sparse_minor;
|
||||
|
||||
return (file->stat_info->sparse_major == 0) ?
|
||||
pax_dump_header_0 (file) : pax_dump_header_1 (file);
|
||||
}
|
||||
|
||||
static bool
|
||||
decode_num (uintmax_t *num, char const *arg, uintmax_t maxval)
|
||||
{
|
||||
uintmax_t u;
|
||||
char *arg_lim;
|
||||
|
||||
if (!ISDIGIT (*arg))
|
||||
return false;
|
||||
|
||||
u = strtoumax (arg, &arg_lim, 10);
|
||||
|
||||
if (! (u <= maxval && errno != ERANGE) || *arg_lim)
|
||||
return false;
|
||||
|
||||
*num = u;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
pax_decode_header (struct tar_sparse_file *file)
|
||||
{
|
||||
if (file->stat_info->sparse_major > 0)
|
||||
{
|
||||
uintmax_t u;
|
||||
char nbuf[UINTMAX_STRSIZE_BOUND];
|
||||
union block *blk;
|
||||
char *p;
|
||||
size_t i;
|
||||
|
||||
#define COPY_BUF(b,buf,src) do \
|
||||
{ \
|
||||
char *endp = b->buffer + BLOCKSIZE; \
|
||||
char *dst = buf; \
|
||||
do \
|
||||
{ \
|
||||
if (dst == buf + UINTMAX_STRSIZE_BOUND -1) \
|
||||
{ \
|
||||
ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \
|
||||
file->stat_info->orig_file_name)); \
|
||||
return false; \
|
||||
} \
|
||||
if (src == endp) \
|
||||
{ \
|
||||
set_next_block_after (b); \
|
||||
file->dumped_size += BLOCKSIZE; \
|
||||
b = find_next_block (); \
|
||||
src = b->buffer; \
|
||||
endp = b->buffer + BLOCKSIZE; \
|
||||
} \
|
||||
*dst = *src++; \
|
||||
} \
|
||||
while (*dst++ != '\n'); \
|
||||
dst[-1] = 0; \
|
||||
} while (0)
|
||||
|
||||
set_next_block_after (current_header);
|
||||
file->dumped_size += BLOCKSIZE;
|
||||
blk = find_next_block ();
|
||||
p = blk->buffer;
|
||||
COPY_BUF (blk,nbuf,p);
|
||||
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
|
||||
{
|
||||
ERROR ((0, 0, _("%s: malformed sparse archive member"),
|
||||
file->stat_info->orig_file_name));
|
||||
return false;
|
||||
}
|
||||
file->stat_info->sparse_map_size = u;
|
||||
file->stat_info->sparse_map = xcalloc (file->stat_info->sparse_map_size,
|
||||
sizeof (*file->stat_info->sparse_map));
|
||||
file->stat_info->sparse_map_avail = 0;
|
||||
for (i = 0; i < file->stat_info->sparse_map_size; i++)
|
||||
{
|
||||
struct sp_array sp;
|
||||
|
||||
COPY_BUF (blk,nbuf,p);
|
||||
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
|
||||
{
|
||||
ERROR ((0, 0, _("%s: malformed sparse archive member"),
|
||||
file->stat_info->orig_file_name));
|
||||
return false;
|
||||
}
|
||||
sp.offset = u;
|
||||
COPY_BUF (blk,nbuf,p);
|
||||
if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
|
||||
{
|
||||
ERROR ((0, 0, _("%s: malformed sparse archive member"),
|
||||
file->stat_info->orig_file_name));
|
||||
return false;
|
||||
}
|
||||
sp.numbytes = u;
|
||||
sparse_add_map (file->stat_info, &sp);
|
||||
}
|
||||
set_next_block_after (blk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -930,8 +1167,8 @@ static struct tar_sparse_optab const pax_optab = {
|
||||
NULL, /* No done function */
|
||||
pax_sparse_member_p,
|
||||
pax_dump_header,
|
||||
NULL, /* No decode_header function */
|
||||
NULL, /* No fixup_header function */
|
||||
NULL,
|
||||
pax_decode_header,
|
||||
NULL, /* No scan_block function */
|
||||
sparse_dump_region,
|
||||
sparse_extract_region,
|
||||
|
||||
79
src/suffix.c
Normal file
79
src/suffix.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by Sergey Poznyakoff.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GNU tar is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with GNU tar. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
|
||||
struct compression_suffix
|
||||
{
|
||||
const char *suffix;
|
||||
size_t length;
|
||||
const char *program;
|
||||
};
|
||||
|
||||
struct compression_suffix compression_suffixes[] = {
|
||||
#define S(s,p) #s, sizeof (#s) - 1, #p
|
||||
{ S(gz, gzip) },
|
||||
{ S(tgz, gzip) },
|
||||
{ S(taz, gzip) },
|
||||
{ S(Z, compress) },
|
||||
{ S(taZ, compress) },
|
||||
{ S(bz2, bzip2) },
|
||||
{ S(tbz, bzip2) },
|
||||
{ S(tbz2, bzip2) },
|
||||
{ S(tz2, bzip2) },
|
||||
{ S(lzma, lzma) },
|
||||
{ S(tlz, lzma) },
|
||||
{ S(lzo, lzop) },
|
||||
#undef S
|
||||
};
|
||||
|
||||
int nsuffixes = sizeof (compression_suffixes) /
|
||||
sizeof (compression_suffixes[0]);
|
||||
|
||||
static const char *
|
||||
find_compression_program (const char *name, const char *defprog)
|
||||
{
|
||||
char *suf = strrchr (name, '.');
|
||||
|
||||
if (suf)
|
||||
{
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
suf++;
|
||||
len = strlen (suf);
|
||||
|
||||
for (i = 0; i < nsuffixes; i++)
|
||||
{
|
||||
if (compression_suffixes[i].length == len
|
||||
&& memcmp (compression_suffixes[i].suffix, suf, len) == 0)
|
||||
return compression_suffixes[i].program;
|
||||
}
|
||||
}
|
||||
return defprog;
|
||||
}
|
||||
|
||||
void
|
||||
set_comression_program_by_suffix (const char *name, const char *defprog)
|
||||
{
|
||||
const char *program = find_compression_program (name, defprog);
|
||||
if (program)
|
||||
use_compress_program_option = program;
|
||||
}
|
||||
|
||||
121
src/system.c
121
src/system.c
@@ -1,10 +1,11 @@
|
||||
/* System-dependent calls for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007,
|
||||
2008 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -17,8 +18,6 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <getline.h>
|
||||
#include <setenv.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <rmt.h>
|
||||
@@ -53,12 +52,7 @@ sys_detect_dev_null_output (void)
|
||||
}
|
||||
|
||||
void
|
||||
sys_drain_input_pipe (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_for_child (pid_t child_pid)
|
||||
sys_wait_for_child (pid_t child_pid, bool eof)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -162,26 +156,8 @@ sys_detect_dev_null_output (void)
|
||||
&& archive_stat.st_ino == dev_null_stat.st_ino));
|
||||
}
|
||||
|
||||
/* Manage to fully drain a pipe we might be reading, so to not break it on
|
||||
the producer after the EOF block. FIXME: one of these days, GNU tar
|
||||
might become clever enough to just stop working, once there is no more
|
||||
work to do, we might have to revise this area in such time. */
|
||||
|
||||
void
|
||||
sys_drain_input_pipe (void)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
if (access_mode == ACCESS_READ
|
||||
&& ! _isrmt (archive)
|
||||
&& (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
|
||||
while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
|
||||
&& r != SAFE_READ_ERROR)
|
||||
continue;
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_for_child (pid_t child_pid)
|
||||
sys_wait_for_child (pid_t child_pid, bool eof)
|
||||
{
|
||||
if (child_pid)
|
||||
{
|
||||
@@ -195,8 +171,11 @@ sys_wait_for_child (pid_t child_pid)
|
||||
}
|
||||
|
||||
if (WIFSIGNALED (wait_status))
|
||||
ERROR ((0, 0, _("Child died with signal %d"),
|
||||
WTERMSIG (wait_status)));
|
||||
{
|
||||
int sig = WTERMSIG (wait_status);
|
||||
if (!(!eof && sig == SIGPIPE))
|
||||
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)));
|
||||
@@ -697,7 +676,7 @@ stat_to_env (char *name, char type, struct tar_stat_info *st)
|
||||
}
|
||||
}
|
||||
|
||||
static pid_t pid;
|
||||
static pid_t global_pid;
|
||||
static RETSIGTYPE (*pipe_handler) (int sig);
|
||||
|
||||
int
|
||||
@@ -708,9 +687,9 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
pid = xfork ();
|
||||
global_pid = xfork ();
|
||||
|
||||
if (pid != 0)
|
||||
if (global_pid != 0)
|
||||
{
|
||||
xclose (p[PREAD]);
|
||||
return p[PWRITE];
|
||||
@@ -737,14 +716,14 @@ sys_wait_command (void)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (pid < 0)
|
||||
if (global_pid < 0)
|
||||
return;
|
||||
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
while (waitpid (global_pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
pid = -1;
|
||||
global_pid = -1;
|
||||
waitpid_error (to_command_option);
|
||||
return;
|
||||
}
|
||||
@@ -753,18 +732,18 @@ sys_wait_command (void)
|
||||
{
|
||||
if (!ignore_command_error_option && WEXITSTATUS (status))
|
||||
ERROR ((0, 0, _("%lu: Child returned status %d"),
|
||||
(unsigned long) pid, WEXITSTATUS (status)));
|
||||
(unsigned long) global_pid, WEXITSTATUS (status)));
|
||||
}
|
||||
else if (WIFSIGNALED (status))
|
||||
{
|
||||
WARN ((0, 0, _("%lu: Child terminated on signal %d"),
|
||||
(unsigned long) pid, WTERMSIG (status)));
|
||||
(unsigned long) global_pid, WTERMSIG (status)));
|
||||
}
|
||||
else
|
||||
ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
|
||||
(unsigned long) pid));
|
||||
(unsigned long) global_pid));
|
||||
|
||||
pid = -1;
|
||||
global_pid = -1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -774,9 +753,10 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
int p[2];
|
||||
|
||||
static RETSIGTYPE (*saved_handler) (int sig);
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
saved_handler = signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
pid = xfork ();
|
||||
|
||||
@@ -786,7 +766,7 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
|
||||
int rc;
|
||||
int status;
|
||||
char *buf;
|
||||
char *buf = NULL;
|
||||
size_t size = 0;
|
||||
FILE *fp;
|
||||
|
||||
@@ -801,10 +781,13 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
signal (SIGPIPE, saved_handler);
|
||||
waitpid_error (info_script_option);
|
||||
return -1;
|
||||
}
|
||||
|
||||
signal (SIGPIPE, saved_handler);
|
||||
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
if (WEXITSTATUS (status) == 0 && rc > 0)
|
||||
@@ -822,13 +805,15 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
|
||||
setenv ("TAR_ARCHIVE", *archive_name, 1);
|
||||
setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
|
||||
setenv ("TAR_BLOCKING_FACTOR",
|
||||
STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
|
||||
setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
|
||||
setenv ("TAR_FORMAT",
|
||||
archive_format_string (current_format == DEFAULT_FORMAT ?
|
||||
archive_format : current_format), 1);
|
||||
setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
|
||||
|
||||
xclose (p[PREAD]);
|
||||
xdup2 (p[PWRITE], 3);
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
@@ -840,5 +825,51 @@ sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
exec_fatal (info_script_option);
|
||||
}
|
||||
|
||||
void
|
||||
sys_exec_checkpoint_script (const char *script_name,
|
||||
const char *archive_name,
|
||||
int checkpoint_number)
|
||||
{
|
||||
pid_t pid;
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
pid = xfork ();
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
/* Master */
|
||||
|
||||
int status;
|
||||
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (script_name);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Child */
|
||||
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
|
||||
setenv ("TAR_ARCHIVE", archive_name, 1);
|
||||
setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1);
|
||||
setenv ("TAR_BLOCKING_FACTOR",
|
||||
STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
|
||||
setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
|
||||
setenv ("TAR_FORMAT",
|
||||
archive_format_string (current_format == DEFAULT_FORMAT ?
|
||||
archive_format : current_format), 1);
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*) script_name;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (script_name);
|
||||
}
|
||||
|
||||
#endif /* not MSDOS */
|
||||
|
||||
23
src/tar.h
23
src/tar.h
@@ -1,11 +1,11 @@
|
||||
/* GNU tar Archive Format description.
|
||||
|
||||
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
2000, 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -165,6 +165,7 @@ struct oldgnu_header
|
||||
'A' Solaris Access Control List
|
||||
'E' Solaris Extended Attribute File
|
||||
'I' Inode only, as in 'star'
|
||||
'N' Obsolete GNU tar, for file names that do not fit into the main header.
|
||||
'X' POSIX 1003.1-2001 eXtended (VU version) */
|
||||
|
||||
/* This is a dir entry that contains the names of files that were in the
|
||||
@@ -180,9 +181,6 @@ struct oldgnu_header
|
||||
/* This is the continuation of a file that began on another volume. */
|
||||
#define GNUTYPE_MULTIVOL 'M'
|
||||
|
||||
/* For storing filenames that do not fit into the main header. */
|
||||
#define GNUTYPE_NAMES 'N'
|
||||
|
||||
/* This is for sparse files. */
|
||||
#define GNUTYPE_SPARSE 'S'
|
||||
|
||||
@@ -270,6 +268,14 @@ struct sp_array
|
||||
size_t numbytes;
|
||||
};
|
||||
|
||||
struct xheader
|
||||
{
|
||||
struct obstack *stk;
|
||||
size_t size;
|
||||
char *buffer;
|
||||
uintmax_t string_length;
|
||||
};
|
||||
|
||||
struct tar_stat_info
|
||||
{
|
||||
char *orig_file_name; /* name of file read from the archive header */
|
||||
@@ -295,12 +301,17 @@ struct tar_stat_info
|
||||
bool is_sparse; /* Is the file sparse */
|
||||
|
||||
/* For sparse files: */
|
||||
unsigned sparse_major;
|
||||
unsigned sparse_minor;
|
||||
size_t sparse_map_avail; /* Index to the first unused element in
|
||||
sparse_map array. Zero if the file is
|
||||
not sparse */
|
||||
size_t sparse_map_size; /* Size of the sparse map */
|
||||
struct sp_array *sparse_map;
|
||||
|
||||
/* Extended headers */
|
||||
struct xheader xhdr;
|
||||
|
||||
/* For dumpdirs */
|
||||
bool is_dumpdir; /* Is the member a dumpdir? */
|
||||
bool skipped; /* The member contents is already read
|
||||
@@ -318,5 +329,3 @@ union block
|
||||
struct star_in_header star_in_header;
|
||||
struct star_ext_header star_ext_header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
287
src/transform.c
287
src/transform.c
@@ -1,9 +1,9 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -19,16 +19,11 @@
|
||||
#include <regex.h>
|
||||
#include "common.h"
|
||||
|
||||
static enum transform_type
|
||||
enum transform_type
|
||||
{
|
||||
transform_none,
|
||||
transform_first,
|
||||
transform_global
|
||||
}
|
||||
transform_type = transform_none;
|
||||
static unsigned match_number = 0;
|
||||
static regex_t regex;
|
||||
static struct obstack stk;
|
||||
};
|
||||
|
||||
enum replace_segm_type
|
||||
{
|
||||
@@ -62,31 +57,56 @@ struct replace_segm
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Compiled replacement expression */
|
||||
static struct replace_segm *repl_head, *repl_tail;
|
||||
static segm_count; /* Number of elements in the above list */
|
||||
struct transform
|
||||
{
|
||||
struct transform *next;
|
||||
enum transform_type transform_type;
|
||||
int flags;
|
||||
unsigned match_number;
|
||||
regex_t regex;
|
||||
/* Compiled replacement expression */
|
||||
struct replace_segm *repl_head, *repl_tail;
|
||||
size_t segm_count; /* Number of elements in the above list */
|
||||
};
|
||||
|
||||
|
||||
|
||||
int transform_flags = XFORM_ALL;
|
||||
static struct transform *transform_head, *transform_tail;
|
||||
|
||||
static struct transform *
|
||||
new_transform ()
|
||||
{
|
||||
struct transform *p = xzalloc (sizeof *p);
|
||||
if (transform_tail)
|
||||
transform_tail->next = p;
|
||||
else
|
||||
transform_head = p;
|
||||
transform_tail = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct replace_segm *
|
||||
add_segment (void)
|
||||
add_segment (struct transform *tf)
|
||||
{
|
||||
struct replace_segm *segm = xmalloc (sizeof *segm);
|
||||
segm->next = NULL;
|
||||
if (repl_tail)
|
||||
repl_tail->next = segm;
|
||||
if (tf->repl_tail)
|
||||
tf->repl_tail->next = segm;
|
||||
else
|
||||
repl_head = segm;
|
||||
repl_tail = segm;
|
||||
segm_count++;
|
||||
tf->repl_head = segm;
|
||||
tf->repl_tail = segm;
|
||||
tf->segm_count++;
|
||||
return segm;
|
||||
}
|
||||
|
||||
static void
|
||||
add_literal_segment (char *str, char *end)
|
||||
add_literal_segment (struct transform *tf, char *str, char *end)
|
||||
{
|
||||
size_t len = end - str;
|
||||
if (len)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (len + 1);
|
||||
memcpy (segm->v.literal.ptr, str, len);
|
||||
@@ -96,9 +116,9 @@ add_literal_segment (char *str, char *end)
|
||||
}
|
||||
|
||||
static void
|
||||
add_char_segment (int chr)
|
||||
add_char_segment (struct transform *tf, int chr)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (2);
|
||||
segm->v.literal.ptr[0] = chr;
|
||||
@@ -107,41 +127,87 @@ add_char_segment (int chr)
|
||||
}
|
||||
|
||||
static void
|
||||
add_backref_segment (size_t ref)
|
||||
add_backref_segment (struct transform *tf, size_t ref)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_backref;
|
||||
segm->v.ref = ref;
|
||||
}
|
||||
|
||||
static void
|
||||
add_case_ctl_segment (enum case_ctl_type ctl)
|
||||
static int
|
||||
parse_xform_flags (int *pflags, int c)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
switch (c)
|
||||
{
|
||||
case 'r':
|
||||
*pflags |= XFORM_REGFILE;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
*pflags &= ~XFORM_REGFILE;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
*pflags |= XFORM_LINK;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
*pflags &= ~XFORM_LINK;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
*pflags |= XFORM_SYMLINK;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
*pflags &= ~XFORM_SYMLINK;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl)
|
||||
{
|
||||
struct replace_segm *segm = add_segment (tf);
|
||||
segm->type = segm_case_ctl;
|
||||
segm->v.ctl = ctl;
|
||||
}
|
||||
|
||||
void
|
||||
set_transform_expr (const char *expr)
|
||||
static const char *
|
||||
parse_transform_expr (const char *expr)
|
||||
{
|
||||
int delim;
|
||||
int i, j, rc;
|
||||
char *str, *beg, *cur;
|
||||
const char *p;
|
||||
int cflags = 0;
|
||||
|
||||
if (transform_type == transform_none)
|
||||
obstack_init (&stk);
|
||||
else
|
||||
{
|
||||
/* Redefinition of the transform expression */
|
||||
regfree (®ex);
|
||||
}
|
||||
struct transform *tf = new_transform ();
|
||||
|
||||
if (expr[0] != 's')
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
{
|
||||
if (strncmp (expr, "flags=", 6) == 0)
|
||||
{
|
||||
transform_flags = 0;
|
||||
for (expr += 6; *expr; expr++)
|
||||
{
|
||||
if (*expr == ';')
|
||||
{
|
||||
expr++;
|
||||
break;
|
||||
}
|
||||
if (parse_xform_flags (&transform_flags, *expr))
|
||||
USAGE_ERROR ((0, 0, _("Unknown transform flag: %c"),
|
||||
*expr));
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
}
|
||||
|
||||
delim = expr[1];
|
||||
|
||||
/* Scan regular expression */
|
||||
@@ -161,12 +227,13 @@ set_transform_expr (const char *expr)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
/* Check flags */
|
||||
transform_type = transform_first;
|
||||
for (p = expr + j + 1; *p; p++)
|
||||
tf->transform_type = transform_first;
|
||||
tf->flags = transform_flags;
|
||||
for (p = expr + j + 1; *p && *p != ';'; p++)
|
||||
switch (*p)
|
||||
{
|
||||
case 'g':
|
||||
transform_type = transform_global;
|
||||
tf->transform_type = transform_global;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
@@ -176,33 +243,38 @@ set_transform_expr (const char *expr)
|
||||
case 'x':
|
||||
cflags |= REG_EXTENDED;
|
||||
break;
|
||||
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
match_number = strtoul (p, (char**) &p, 0);
|
||||
tf->match_number = strtoul (p, (char**) &p, 0);
|
||||
p--;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression")));
|
||||
if (parse_xform_flags (&tf->flags, *p))
|
||||
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression: %c"),
|
||||
*p));
|
||||
}
|
||||
|
||||
if (*p == ';')
|
||||
p++;
|
||||
|
||||
/* Extract and compile regex */
|
||||
str = xmalloc (i - 1);
|
||||
memcpy (str, expr + 2, i - 2);
|
||||
str[i - 2] = 0;
|
||||
|
||||
rc = regcomp (®ex, str, cflags);
|
||||
rc = regcomp (&tf->regex, str, cflags);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
char errbuf[512];
|
||||
regerror (rc, ®ex, errbuf, sizeof (errbuf));
|
||||
regerror (rc, &tf->regex, errbuf, sizeof (errbuf));
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf));
|
||||
}
|
||||
|
||||
if (str[0] == '^' || str[strlen (str) - 1] == '$')
|
||||
transform_type = transform_first;
|
||||
tf->transform_type = transform_first;
|
||||
|
||||
free (str);
|
||||
|
||||
@@ -218,91 +290,91 @@ set_transform_expr (const char *expr)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
add_literal_segment (beg, cur);
|
||||
add_literal_segment (tf, beg, cur);
|
||||
switch (*++cur)
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
n = strtoul (cur, &cur, 10);
|
||||
if (n > regex.re_nsub)
|
||||
if (n > tf->regex.re_nsub)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform replacement: back reference out of range")));
|
||||
add_backref_segment (n);
|
||||
add_backref_segment (tf, n);
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
add_char_segment ('\\');
|
||||
add_char_segment (tf, '\\');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
add_char_segment ('\a');
|
||||
add_char_segment (tf, '\a');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
add_char_segment ('\b');
|
||||
add_char_segment (tf, '\b');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
add_char_segment ('\f');
|
||||
add_char_segment (tf, '\f');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
add_char_segment ('\n');
|
||||
add_char_segment (tf, '\n');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
add_char_segment ('\r');
|
||||
add_char_segment (tf, '\r');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
add_char_segment ('\t');
|
||||
add_char_segment (tf, '\t');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
add_char_segment ('\v');
|
||||
add_char_segment (tf, '\v');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
add_char_segment ('&');
|
||||
add_char_segment (tf, '&');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
/* Turn the replacement to lowercase until a `\U' or `\E'
|
||||
is found, */
|
||||
add_case_ctl_segment (ctl_locase);
|
||||
add_case_ctl_segment (tf, ctl_locase);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
/* Turn the next character to lowercase, */
|
||||
add_case_ctl_segment (ctl_locase_next);
|
||||
add_case_ctl_segment (tf, ctl_locase_next);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
/* Turn the replacement to uppercase until a `\L' or `\E'
|
||||
is found, */
|
||||
add_case_ctl_segment (ctl_upcase);
|
||||
add_case_ctl_segment (tf, ctl_upcase);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
/* Turn the next character to uppercase, */
|
||||
add_case_ctl_segment (ctl_upcase_next);
|
||||
add_case_ctl_segment (tf, ctl_upcase_next);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
/* Stop case conversion started by `\L' or `\U'. */
|
||||
add_case_ctl_segment (ctl_stop);
|
||||
add_case_ctl_segment (tf, ctl_stop);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
@@ -312,7 +384,7 @@ set_transform_expr (const char *expr)
|
||||
char buf[2];
|
||||
buf[0] = '\\';
|
||||
buf[1] = *cur;
|
||||
add_literal_segment (buf, buf + 2);
|
||||
add_literal_segment (tf, buf, buf + 2);
|
||||
}
|
||||
cur++;
|
||||
break;
|
||||
@@ -321,15 +393,23 @@ set_transform_expr (const char *expr)
|
||||
}
|
||||
else if (*cur == '&')
|
||||
{
|
||||
add_literal_segment (beg, cur);
|
||||
add_backref_segment (0);
|
||||
add_literal_segment (tf, beg, cur);
|
||||
add_backref_segment (tf, 0);
|
||||
beg = ++cur;
|
||||
}
|
||||
else
|
||||
cur++;
|
||||
}
|
||||
add_literal_segment (beg, cur);
|
||||
|
||||
add_literal_segment (tf, beg, cur);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
set_transform_expr (const char *expr)
|
||||
{
|
||||
while (*expr)
|
||||
expr = parse_transform_expr (expr);
|
||||
}
|
||||
|
||||
/* Run case conversion specified by CASE_CTL on array PTR of SIZE
|
||||
@@ -373,11 +453,14 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
|
||||
return case_ctl_buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
_transform_name_to_obstack (char *input)
|
||||
|
||||
static struct obstack stk;
|
||||
static bool stk_init;
|
||||
|
||||
void
|
||||
_single_transform_name_to_obstack (struct transform *tf, char *input)
|
||||
{
|
||||
regmatch_t *rmp;
|
||||
char *p;
|
||||
int rc;
|
||||
size_t nmatches = 0;
|
||||
enum case_ctl_type case_ctl = ctl_stop, /* Current case conversion op */
|
||||
@@ -391,17 +474,14 @@ _transform_name_to_obstack (char *input)
|
||||
save_ctl = ctl_stop; \
|
||||
}
|
||||
|
||||
if (transform_type == transform_none)
|
||||
return false;
|
||||
|
||||
rmp = xmalloc ((regex.re_nsub + 1) * sizeof (*rmp));
|
||||
rmp = xmalloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
|
||||
|
||||
while (*input)
|
||||
{
|
||||
size_t disp;
|
||||
char *ptr;
|
||||
|
||||
rc = regexec (®ex, input, regex.re_nsub + 1, rmp, 0);
|
||||
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
@@ -413,14 +493,14 @@ _transform_name_to_obstack (char *input)
|
||||
obstack_grow (&stk, input, rmp[0].rm_so);
|
||||
|
||||
nmatches++;
|
||||
if (match_number && nmatches < match_number)
|
||||
if (tf->match_number && nmatches < tf->match_number)
|
||||
{
|
||||
obstack_grow (&stk, input, disp);
|
||||
input += disp;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (segm = repl_head; segm; segm = segm->next)
|
||||
for (segm = tf->repl_head; segm; segm = segm->next)
|
||||
{
|
||||
switch (segm->type)
|
||||
{
|
||||
@@ -486,7 +566,7 @@ _transform_name_to_obstack (char *input)
|
||||
|
||||
input += disp;
|
||||
|
||||
if (transform_type == transform_first)
|
||||
if (tf->transform_type == transform_first)
|
||||
{
|
||||
obstack_grow (&stk, input, strlen (input));
|
||||
break;
|
||||
@@ -495,25 +575,48 @@ _transform_name_to_obstack (char *input)
|
||||
|
||||
obstack_1grow (&stk, 0);
|
||||
free (rmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
_single_transform_name_to_obstack (tf, input);
|
||||
input = obstack_finish (&stk);
|
||||
alloced = true;
|
||||
}
|
||||
}
|
||||
*output = input;
|
||||
return alloced;
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name_fp (char **pinput, char *(*fun)(char *))
|
||||
transform_name_fp (char **pinput, int flags,
|
||||
char *(*fun)(char *, void *), void *dat)
|
||||
{
|
||||
char *str, *p;
|
||||
bool ret = _transform_name_to_obstack (*pinput);
|
||||
char *str;
|
||||
bool ret = _transform_name_to_obstack (flags, *pinput, &str);
|
||||
if (ret)
|
||||
{
|
||||
str = obstack_finish (&stk);
|
||||
assign_string (pinput, fun ? fun (str) : str);
|
||||
assign_string (pinput, fun ? fun (str, dat) : str);
|
||||
obstack_free (&stk, str);
|
||||
}
|
||||
else if (fun)
|
||||
{
|
||||
str = *pinput;
|
||||
*pinput = NULL;
|
||||
assign_string (pinput, fun (str));
|
||||
assign_string (pinput, fun (str, dat));
|
||||
free (str);
|
||||
ret = true;
|
||||
}
|
||||
@@ -521,8 +624,8 @@ transform_name_fp (char **pinput, char *(*fun)(char *))
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name (char **pinput)
|
||||
transform_name (char **pinput, int type)
|
||||
{
|
||||
return transform_name_fp (pinput, NULL);
|
||||
return transform_name_fp (pinput, type, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Update a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
|
||||
2004, 2005 Free Software Foundation, Inc.
|
||||
2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -110,7 +110,7 @@ update_archive (void)
|
||||
|
||||
name_gather ();
|
||||
open_archive (ACCESS_UPDATE);
|
||||
xheader_write_global ();
|
||||
buffer_write_global_xheader ();
|
||||
|
||||
while (!found_end)
|
||||
{
|
||||
@@ -131,7 +131,7 @@ update_archive (void)
|
||||
archive_format = current_format;
|
||||
|
||||
if (subcommand_option == UPDATE_SUBCOMMAND
|
||||
&& (name = name_scan (current_stat_info.file_name, false)) != NULL)
|
||||
&& (name = name_scan (current_stat_info.file_name)) != NULL)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
@@ -181,7 +181,6 @@ update_archive (void)
|
||||
}
|
||||
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
xheader_destroy (&extended_header);
|
||||
previous_status = status;
|
||||
}
|
||||
|
||||
|
||||
13
src/utf8.c
13
src/utf8.c
@@ -1,10 +1,10 @@
|
||||
/* Charset handling for GNU tar.
|
||||
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -28,7 +28,7 @@
|
||||
# define ICONV_CONST
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ICONV
|
||||
#ifndef HAVE_ICONV
|
||||
|
||||
# undef iconv_open
|
||||
# define iconv_open(tocode, fromcode) ((iconv_t) -1)
|
||||
@@ -39,7 +39,7 @@
|
||||
# undef iconv_close
|
||||
# define iconv_close(cd) 0
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -88,11 +88,10 @@ utf8_convert (bool to_utf, char const *input, char **output)
|
||||
|
||||
|
||||
bool
|
||||
string_ascii_p (const char *str)
|
||||
string_ascii_p (char const *p)
|
||||
{
|
||||
const unsigned char *p = (const unsigned char *)str;
|
||||
for (; *p; p++)
|
||||
if (*p > 127)
|
||||
if (*p & ~0x7f)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
327
src/xheader.c
327
src/xheader.c
@@ -1,10 +1,10 @@
|
||||
/* POSIX extended headers for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
Free Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
@@ -22,12 +22,9 @@
|
||||
#include <hash.h>
|
||||
#include <inttostr.h>
|
||||
#include <quotearg.h>
|
||||
#include <stpcpy.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <fnmatch.h>
|
||||
|
||||
static bool xheader_protected_pattern_p (char const *pattern);
|
||||
static bool xheader_protected_keyword_p (char const *keyword);
|
||||
static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
|
||||
@@ -35,7 +32,6 @@ static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
|
||||
/* Used by xheader_finish() */
|
||||
static void code_string (char const *string, char const *keyword,
|
||||
struct xheader *xhdr);
|
||||
static void extended_header_init (void);
|
||||
|
||||
/* Number of global headers written so far. */
|
||||
static size_t global_header_count;
|
||||
@@ -225,7 +221,7 @@ xheader_set_option (char *string)
|
||||
to the result of the basename
|
||||
utility on the translated file name.
|
||||
%p The process ID of the pax process.
|
||||
%n The value of the 3rd argument.
|
||||
%n The value of the 3rd argument.
|
||||
%% A '%' character. */
|
||||
|
||||
char *
|
||||
@@ -264,7 +260,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
|
||||
case 'f':
|
||||
if (st)
|
||||
{
|
||||
base = base_name (st->orig_file_name);
|
||||
base = last_component (st->orig_file_name);
|
||||
len += strlen (base) - 2;
|
||||
}
|
||||
break;
|
||||
@@ -331,7 +327,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
|
||||
}
|
||||
|
||||
free (dirp);
|
||||
|
||||
|
||||
/* Do not allow it to end in a slash */
|
||||
while (q > buf && ISSLASH (q[-1]))
|
||||
q--;
|
||||
@@ -405,7 +401,7 @@ xheader_write (char type, char *name, struct xheader *xhdr)
|
||||
}
|
||||
|
||||
void
|
||||
xheader_write_global (void)
|
||||
xheader_write_global (struct xheader *xhdr)
|
||||
{
|
||||
char *name;
|
||||
struct keyword_list *kp;
|
||||
@@ -413,12 +409,11 @@ xheader_write_global (void)
|
||||
if (!keyword_global_override_list)
|
||||
return;
|
||||
|
||||
extended_header_init ();
|
||||
xheader_init (xhdr);
|
||||
for (kp = keyword_global_override_list; kp; kp = kp->next)
|
||||
code_string (kp->value, kp->pattern, &extended_header);
|
||||
xheader_finish (&extended_header);
|
||||
xheader_write (XGLTYPE, name = xheader_ghdr_name (),
|
||||
&extended_header);
|
||||
code_string (kp->value, kp->pattern, xhdr);
|
||||
xheader_finish (xhdr);
|
||||
xheader_write (XGLTYPE, name = xheader_ghdr_name (), xhdr);
|
||||
free (name);
|
||||
}
|
||||
|
||||
@@ -430,7 +425,7 @@ struct xhdr_tab
|
||||
char const *keyword;
|
||||
void (*coder) (struct tar_stat_info const *, char const *,
|
||||
struct xheader *, void const *data);
|
||||
void (*decoder) (struct tar_stat_info *, char const *, size_t);
|
||||
void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
|
||||
bool protect;
|
||||
};
|
||||
|
||||
@@ -478,17 +473,19 @@ xheader_protected_keyword_p (const char *keyword)
|
||||
/* Decode a single extended header record, advancing *PTR to the next record.
|
||||
Return true on success, false otherwise. */
|
||||
static bool
|
||||
decode_record (char **ptr,
|
||||
decode_record (struct xheader *xhdr,
|
||||
char **ptr,
|
||||
void (*handler) (void *, char const *, char const *, size_t),
|
||||
void *data)
|
||||
{
|
||||
char *start = *ptr;
|
||||
char *p = start;
|
||||
unsigned long int len;
|
||||
uintmax_t u;
|
||||
size_t len;
|
||||
char *len_lim;
|
||||
char const *keyword;
|
||||
char *nextp;
|
||||
size_t len_max = extended_header.buffer + extended_header.size - start;
|
||||
size_t len_max = xhdr->buffer + xhdr->size - start;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
@@ -501,7 +498,12 @@ decode_record (char **ptr,
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
len = strtoul (p, &len_lim, 10);
|
||||
len = u = strtoumax (p, &len_lim, 10);
|
||||
if (len != u || errno == ERANGE)
|
||||
{
|
||||
ERROR ((0, 0, _("Extended header length is out of allowed range")));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len_max < len)
|
||||
{
|
||||
@@ -551,7 +553,7 @@ run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
|
||||
{
|
||||
struct xhdr_tab const *t = locate_handler (kp->pattern);
|
||||
if (t)
|
||||
t->decoder (st, kp->value, strlen (kp->value));
|
||||
t->decoder (st, t->keyword, kp->value, strlen (kp->value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,10 +569,10 @@ decx (void *data, char const *keyword, char const *value, size_t size)
|
||||
|
||||
t = locate_handler (keyword);
|
||||
if (t)
|
||||
t->decoder (st, value, size);
|
||||
t->decoder (st, keyword, value, size);
|
||||
else
|
||||
ERROR((0, 0, _("Ignoring unknown extended header keyword `%s'"),
|
||||
keyword));
|
||||
WARN((0, 0, _("Ignoring unknown extended header keyword `%s'"),
|
||||
keyword));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -579,10 +581,10 @@ xheader_decode (struct tar_stat_info *st)
|
||||
run_override_list (keyword_global_override_list, st);
|
||||
run_override_list (global_header_override_list, st);
|
||||
|
||||
if (extended_header.size)
|
||||
if (st->xhdr.size)
|
||||
{
|
||||
char *p = extended_header.buffer + BLOCKSIZE;
|
||||
while (decode_record (&p, decx, st))
|
||||
char *p = st->xhdr.buffer + BLOCKSIZE;
|
||||
while (decode_record (&st->xhdr, &p, decx, st))
|
||||
continue;
|
||||
}
|
||||
run_override_list (keyword_override_list, st);
|
||||
@@ -597,35 +599,35 @@ decg (void *data, char const *keyword, char const *value,
|
||||
}
|
||||
|
||||
void
|
||||
xheader_decode_global (void)
|
||||
xheader_decode_global (struct xheader *xhdr)
|
||||
{
|
||||
if (extended_header.size)
|
||||
if (xhdr->size)
|
||||
{
|
||||
char *p = extended_header.buffer + BLOCKSIZE;
|
||||
char *p = xhdr->buffer + BLOCKSIZE;
|
||||
|
||||
xheader_list_destroy (&global_header_override_list);
|
||||
while (decode_record (&p, decg, &global_header_override_list))
|
||||
while (decode_record (xhdr, &p, decg, &global_header_override_list))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
extended_header_init (void)
|
||||
void
|
||||
xheader_init (struct xheader *xhdr)
|
||||
{
|
||||
if (!extended_header.stk)
|
||||
if (!xhdr->stk)
|
||||
{
|
||||
extended_header.stk = xmalloc (sizeof *extended_header.stk);
|
||||
obstack_init (extended_header.stk);
|
||||
xhdr->stk = xmalloc (sizeof *xhdr->stk);
|
||||
obstack_init (xhdr->stk);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xheader_store (char const *keyword, struct tar_stat_info const *st,
|
||||
xheader_store (char const *keyword, struct tar_stat_info *st,
|
||||
void const *data)
|
||||
{
|
||||
struct xhdr_tab const *t;
|
||||
|
||||
if (extended_header.buffer)
|
||||
if (st->xhdr.buffer)
|
||||
return;
|
||||
t = locate_handler (keyword);
|
||||
if (!t || !t->coder)
|
||||
@@ -633,22 +635,20 @@ xheader_store (char const *keyword, struct tar_stat_info const *st,
|
||||
if (xheader_keyword_deleted_p (keyword)
|
||||
|| xheader_keyword_override_p (keyword))
|
||||
return;
|
||||
extended_header_init ();
|
||||
t->coder (st, keyword, &extended_header, data);
|
||||
xheader_init (&st->xhdr);
|
||||
t->coder (st, keyword, &st->xhdr, data);
|
||||
}
|
||||
|
||||
void
|
||||
xheader_read (union block *p, size_t size)
|
||||
xheader_read (struct xheader *xhdr, union block *p, size_t size)
|
||||
{
|
||||
size_t j = 0;
|
||||
size_t nblocks;
|
||||
|
||||
free (extended_header.buffer);
|
||||
xheader_init (xhdr);
|
||||
size += BLOCKSIZE;
|
||||
extended_header.size = size;
|
||||
nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
extended_header.buffer = xmalloc (size + 1);
|
||||
extended_header.buffer[size] = '\0';
|
||||
xhdr->size = size;
|
||||
xhdr->buffer = xmalloc (size + 1);
|
||||
xhdr->buffer[size] = '\0';
|
||||
|
||||
do
|
||||
{
|
||||
@@ -657,7 +657,7 @@ xheader_read (union block *p, size_t size)
|
||||
if (len > BLOCKSIZE)
|
||||
len = BLOCKSIZE;
|
||||
|
||||
memcpy (&extended_header.buffer[j], p->buffer, len);
|
||||
memcpy (&xhdr->buffer[j], p->buffer, len);
|
||||
set_next_block_after (p);
|
||||
|
||||
p = find_next_block ();
|
||||
@@ -728,39 +728,39 @@ xheader_destroy (struct xheader *xhdr)
|
||||
|
||||
|
||||
/* Buildable strings */
|
||||
static uintmax_t string_length;
|
||||
|
||||
void
|
||||
xheader_string_begin ()
|
||||
xheader_string_begin (struct xheader *xhdr)
|
||||
{
|
||||
string_length = 0;
|
||||
xhdr->string_length = 0;
|
||||
}
|
||||
|
||||
void
|
||||
xheader_string_add (char const *s)
|
||||
xheader_string_add (struct xheader *xhdr, char const *s)
|
||||
{
|
||||
if (extended_header.buffer)
|
||||
if (xhdr->buffer)
|
||||
return;
|
||||
extended_header_init ();
|
||||
string_length += strlen (s);
|
||||
x_obstack_grow (&extended_header, s, strlen (s));
|
||||
xheader_init (xhdr);
|
||||
xhdr->string_length += strlen (s);
|
||||
x_obstack_grow (xhdr, s, strlen (s));
|
||||
}
|
||||
|
||||
void
|
||||
xheader_string_end (char const *keyword)
|
||||
bool
|
||||
xheader_string_end (struct xheader *xhdr, char const *keyword)
|
||||
{
|
||||
size_t len;
|
||||
size_t p;
|
||||
size_t n = 0;
|
||||
uintmax_t len;
|
||||
uintmax_t p;
|
||||
uintmax_t n = 0;
|
||||
size_t size;
|
||||
char nbuf[UINTMAX_STRSIZE_BOUND];
|
||||
char const *np;
|
||||
char *cp;
|
||||
|
||||
if (extended_header.buffer)
|
||||
return;
|
||||
extended_header_init ();
|
||||
if (xhdr->buffer)
|
||||
return false;
|
||||
xheader_init (xhdr);
|
||||
|
||||
len = strlen (keyword) + string_length + 3; /* ' ' + '=' + '\n' */
|
||||
len = strlen (keyword) + xhdr->string_length + 3; /* ' ' + '=' + '\n' */
|
||||
|
||||
do
|
||||
{
|
||||
@@ -771,14 +771,24 @@ xheader_string_end (char const *keyword)
|
||||
while (n != p);
|
||||
|
||||
p = strlen (keyword) + n + 2;
|
||||
x_obstack_blank (&extended_header, p);
|
||||
x_obstack_1grow (&extended_header, '\n');
|
||||
cp = obstack_next_free (extended_header.stk) - string_length - p - 1;
|
||||
memmove (cp + p, cp, string_length);
|
||||
size = p;
|
||||
if (size != p)
|
||||
{
|
||||
ERROR ((0, 0,
|
||||
_("Generated keyword/value pair is too long (keyword=%s, length=%s)"),
|
||||
keyword, nbuf));
|
||||
obstack_free (xhdr->stk, obstack_finish (xhdr->stk));
|
||||
return false;
|
||||
}
|
||||
x_obstack_blank (xhdr, p);
|
||||
x_obstack_1grow (xhdr, '\n');
|
||||
cp = obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1;
|
||||
memmove (cp + p, cp, xhdr->string_length);
|
||||
cp = stpcpy (cp, np);
|
||||
*cp++ = ' ';
|
||||
cp = stpcpy (cp, keyword);
|
||||
*cp++ = '=';
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -939,7 +949,7 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
|
||||
@@ -983,6 +993,7 @@ dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
|
||||
|
||||
static void
|
||||
dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
|
||||
char const *keyword __attribute__ ((unused)),
|
||||
char const *arg __attribute__ ((unused)),
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
@@ -996,11 +1007,13 @@ atime_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
atime_decoder (struct tar_stat_info *st, char const *arg,
|
||||
atime_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
struct timespec ts;
|
||||
if (decode_time (&ts, arg, "atime"))
|
||||
if (decode_time (&ts, arg, keyword))
|
||||
st->atime = ts;
|
||||
}
|
||||
|
||||
@@ -1012,11 +1025,13 @@ gid_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
gid_decoder (struct tar_stat_info *st, char const *arg,
|
||||
gid_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), "gid"))
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), keyword))
|
||||
st->stat.st_gid = u;
|
||||
}
|
||||
|
||||
@@ -1028,7 +1043,9 @@ gname_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
gname_decoder (struct tar_stat_info *st, char const *arg,
|
||||
gname_decoder (struct tar_stat_info *st,
|
||||
char const *keyword __attribute__((unused)),
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
decode_string (&st->gname, arg);
|
||||
@@ -1042,7 +1059,9 @@ linkpath_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
linkpath_decoder (struct tar_stat_info *st, char const *arg,
|
||||
linkpath_decoder (struct tar_stat_info *st,
|
||||
char const *keyword __attribute__((unused)),
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
decode_string (&st->link_name, arg);
|
||||
@@ -1056,27 +1075,32 @@ ctime_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
ctime_decoder (struct tar_stat_info *st, char const *arg,
|
||||
ctime_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
struct timespec ts;
|
||||
if (decode_time (&ts, arg, "ctime"))
|
||||
if (decode_time (&ts, arg, keyword))
|
||||
st->ctime = ts;
|
||||
}
|
||||
|
||||
static void
|
||||
mtime_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
struct xheader *xhdr, void const *data __attribute__ ((unused)))
|
||||
struct xheader *xhdr, void const *data)
|
||||
{
|
||||
code_time (st->mtime, keyword, xhdr);
|
||||
struct timespec const *mtime = data;
|
||||
code_time (mtime ? *mtime : st->mtime, keyword, xhdr);
|
||||
}
|
||||
|
||||
static void
|
||||
mtime_decoder (struct tar_stat_info *st, char const *arg,
|
||||
mtime_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
struct timespec ts;
|
||||
if (decode_time (&ts, arg, "mtime"))
|
||||
if (decode_time (&ts, arg, keyword))
|
||||
st->mtime = ts;
|
||||
}
|
||||
|
||||
@@ -1088,7 +1112,9 @@ path_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
path_decoder (struct tar_stat_info *st, char const *arg,
|
||||
path_decoder (struct tar_stat_info *st,
|
||||
char const *keyword __attribute__((unused)),
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
decode_string (&st->orig_file_name, arg);
|
||||
@@ -1104,11 +1130,13 @@ size_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
size_decoder (struct tar_stat_info *st, char const *arg,
|
||||
size_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "size"))
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
|
||||
st->stat.st_size = u;
|
||||
}
|
||||
|
||||
@@ -1120,11 +1148,13 @@ uid_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
uid_decoder (struct tar_stat_info *st, char const *arg,
|
||||
uid_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), "uid"))
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), keyword))
|
||||
st->stat.st_uid = u;
|
||||
}
|
||||
|
||||
@@ -1136,7 +1166,9 @@ uname_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
uname_decoder (struct tar_stat_info *st, char const *arg,
|
||||
uname_decoder (struct tar_stat_info *st,
|
||||
char const *keyword __attribute__((unused)),
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
decode_string (&st->uname, arg);
|
||||
@@ -1150,11 +1182,13 @@ sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_size_decoder (struct tar_stat_info *st, char const *arg,
|
||||
sparse_size_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "GNU.sparse.size"))
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
|
||||
st->stat.st_size = u;
|
||||
}
|
||||
|
||||
@@ -1167,11 +1201,13 @@ sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg,
|
||||
sparse_numblocks_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, SIZE_MAX, "GNU.sparse.numblocks"))
|
||||
if (decode_num (&u, arg, SIZE_MAX, keyword))
|
||||
{
|
||||
st->sparse_map_size = u;
|
||||
st->sparse_map = xcalloc (u, sizeof st->sparse_map[0]);
|
||||
@@ -1188,11 +1224,13 @@ sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_offset_decoder (struct tar_stat_info *st, char const *arg,
|
||||
sparse_offset_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), "GNU.sparse.offset"))
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
|
||||
{
|
||||
if (st->sparse_map_avail < st->sparse_map_size)
|
||||
st->sparse_map[st->sparse_map_avail].offset = u;
|
||||
@@ -1211,26 +1249,29 @@ sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg,
|
||||
sparse_numbytes_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, SIZE_MAX, "GNU.sparse.numbytes"))
|
||||
if (decode_num (&u, arg, SIZE_MAX, keyword))
|
||||
{
|
||||
if (st->sparse_map_avail < st->sparse_map_size)
|
||||
st->sparse_map[st->sparse_map_avail++].numbytes = u;
|
||||
else
|
||||
ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
|
||||
"GNU.sparse.numbytes", arg));
|
||||
keyword, arg));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_map_decoder (struct tar_stat_info *st, char const *arg,
|
||||
sparse_map_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
int offset = 1;
|
||||
static char *keyword = "GNU.sparse.map";
|
||||
|
||||
st->sparse_map_avail = 0;
|
||||
while (1)
|
||||
@@ -1304,7 +1345,9 @@ dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
dumpdir_decoder (struct tar_stat_info *st, char const *arg,
|
||||
dumpdir_decoder (struct tar_stat_info *st,
|
||||
char const *keyword __attribute__((unused)),
|
||||
char const *arg,
|
||||
size_t size)
|
||||
{
|
||||
st->dumpdir = xmalloc (size);
|
||||
@@ -1319,7 +1362,10 @@ volume_label_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
}
|
||||
|
||||
static void
|
||||
volume_label_decoder (struct tar_stat_info *st, char const *arg, size_t size)
|
||||
volume_label_decoder (struct tar_stat_info *st,
|
||||
char const *keyword __attribute__((unused)),
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
decode_string (&volume_label, arg);
|
||||
}
|
||||
@@ -1328,15 +1374,17 @@ static void
|
||||
volume_size_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
struct xheader *xhdr, void const *data)
|
||||
{
|
||||
off_t v = *(off_t*)data;
|
||||
code_num (v, keyword, xhdr);
|
||||
off_t const *v = data;
|
||||
code_num (*v, keyword, xhdr);
|
||||
}
|
||||
|
||||
static void
|
||||
volume_size_decoder (struct tar_stat_info *st, char const *arg, size_t size)
|
||||
volume_size_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg, size_t size)
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.size"))
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
|
||||
continued_file_size = u;
|
||||
}
|
||||
|
||||
@@ -1345,25 +1393,64 @@ static void
|
||||
volume_offset_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
struct xheader *xhdr, void const *data)
|
||||
{
|
||||
off_t v = *(off_t*)data;
|
||||
code_num (v, keyword, xhdr);
|
||||
off_t const *v = data;
|
||||
code_num (*v, keyword, xhdr);
|
||||
}
|
||||
|
||||
static void
|
||||
volume_offset_decoder (struct tar_stat_info *st, char const *arg, size_t size)
|
||||
volume_offset_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg, size_t size)
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.offset"))
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
|
||||
continued_file_offset = u;
|
||||
}
|
||||
|
||||
static void
|
||||
volume_filename_decoder (struct tar_stat_info *st, char const *arg,
|
||||
size_t size)
|
||||
volume_filename_decoder (struct tar_stat_info *st,
|
||||
char const *keyword __attribute__((unused)),
|
||||
char const *arg,
|
||||
size_t size __attribute__((unused)))
|
||||
{
|
||||
decode_string (&continued_file_name, arg);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
struct xheader *xhdr, void const *data)
|
||||
{
|
||||
code_num (st->sparse_major, keyword, xhdr);
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_major_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size)
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
|
||||
st->sparse_major = u;
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_minor_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
struct xheader *xhdr, void const *data)
|
||||
{
|
||||
code_num (st->sparse_minor, keyword, xhdr);
|
||||
}
|
||||
|
||||
static void
|
||||
sparse_minor_decoder (struct tar_stat_info *st,
|
||||
char const *keyword,
|
||||
char const *arg,
|
||||
size_t size)
|
||||
{
|
||||
uintmax_t u;
|
||||
if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
|
||||
st->sparse_minor = u;
|
||||
}
|
||||
|
||||
struct xhdr_tab const xhdr_tab[] = {
|
||||
{ "atime", atime_coder, atime_decoder, false },
|
||||
@@ -1380,10 +1467,20 @@ struct xhdr_tab const xhdr_tab[] = {
|
||||
{ "uname", uname_coder, uname_decoder, false },
|
||||
|
||||
/* Sparse file handling */
|
||||
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
|
||||
{ "GNU.sparse.name", path_coder, path_decoder,
|
||||
true },
|
||||
{ "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
|
||||
true },
|
||||
{ "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
|
||||
true },
|
||||
{ "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
|
||||
true },
|
||||
{ "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
|
||||
true },
|
||||
/* tar 1.14 - 1.15.1 keywords. Multiplse instances of these appeared in 'x'
|
||||
|
||||
/* tar 1.14 - 1.15.90 keywords. */
|
||||
{ "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
|
||||
/* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
|
||||
headers, and each of them was meaningful. It confilcted with POSIX specs,
|
||||
which requires that "when extended header records conflict, the last one
|
||||
given in the header shall take precedence." */
|
||||
@@ -1391,7 +1488,7 @@ struct xhdr_tab const xhdr_tab[] = {
|
||||
true },
|
||||
{ "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
|
||||
true },
|
||||
/* tar >=1.16 keyword, introduced to remove the above-mentioned conflict. */
|
||||
/* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
|
||||
{ "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
|
||||
sparse_map_decoder, false },
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Makefile for GNU tar regression tests.
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||
# 2006 Free Software Foundation, Inc.
|
||||
# 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# François Pinard <pinard@iro.umontreal.ca>, 1988.
|
||||
# Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## the Free Software Foundation; either version 3, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
@@ -46,9 +46,12 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
|
||||
## ------------ ##
|
||||
|
||||
TESTSUITE_AT = \
|
||||
T-empty.at\
|
||||
T-null.at\
|
||||
testsuite.at\
|
||||
append.at\
|
||||
append01.at\
|
||||
append02.at\
|
||||
chtype.at\
|
||||
comprec.at\
|
||||
delete01.at\
|
||||
@@ -56,18 +59,22 @@ TESTSUITE_AT = \
|
||||
delete03.at\
|
||||
delete04.at\
|
||||
delete05.at\
|
||||
exclude.at\
|
||||
extrac01.at\
|
||||
extrac02.at\
|
||||
extrac03.at\
|
||||
extrac04.at\
|
||||
extrac05.at\
|
||||
extrac06.at\
|
||||
extrac07.at\
|
||||
gzip.at\
|
||||
grow.at\
|
||||
incremental.at\
|
||||
incr01.at\
|
||||
incr02.at\
|
||||
incr03.at\
|
||||
incr04.at\
|
||||
indexfile.at\
|
||||
ignfail.at\
|
||||
link01.at\
|
||||
listed01.at\
|
||||
@@ -81,6 +88,8 @@ TESTSUITE_AT = \
|
||||
multiv02.at\
|
||||
multiv03.at\
|
||||
multiv04.at\
|
||||
multiv05.at\
|
||||
multiv06.at\
|
||||
old.at\
|
||||
options.at\
|
||||
options02.at\
|
||||
@@ -89,18 +98,26 @@ TESTSUITE_AT = \
|
||||
rename01.at\
|
||||
rename02.at\
|
||||
rename03.at\
|
||||
rename04.at\
|
||||
rename05.at\
|
||||
same-order01.at\
|
||||
same-order02.at\
|
||||
shortfile.at\
|
||||
shortupd.at\
|
||||
shortrec.at\
|
||||
sparse01.at\
|
||||
sparse02.at\
|
||||
sparse03.at\
|
||||
sparsemv.at\
|
||||
sparsemvp.at\
|
||||
spmvp00.at\
|
||||
spmvp01.at\
|
||||
spmvp10.at\
|
||||
truncate.at\
|
||||
update.at\
|
||||
volsize.at\
|
||||
volume.at\
|
||||
verbose.at\
|
||||
version.at\
|
||||
star/gtarfail.at\
|
||||
star/gtarfail2.at\
|
||||
|
||||
52
tests/T-empty.at
Normal file
52
tests/T-empty.at
Normal file
@@ -0,0 +1,52 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Tar 1.16 coredumped if a filelist file contained empty (zero-length)
|
||||
# entries
|
||||
# Reported by: Karl Berry <karl@freefriends.org>
|
||||
# References: <200610301353.k9UDr1O30680@f7.net>
|
||||
|
||||
AT_SETUP([files-from: empty entries])
|
||||
AT_KEYWORDS([files-from empty])
|
||||
|
||||
AT_DATA([file-list],
|
||||
[jeden
|
||||
dwa
|
||||
|
||||
trzy
|
||||
])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
genfile --file jeden
|
||||
genfile --file dwa
|
||||
genfile --file trzy
|
||||
|
||||
tar cfvT archive ../file-list | sort
|
||||
],
|
||||
[0],
|
||||
[dwa
|
||||
jeden
|
||||
trzy
|
||||
],
|
||||
[],[],[],[ustar]) # Testing one format is enough
|
||||
|
||||
AT_CLEANUP
|
||||
48
tests/T-null.at
Normal file
48
tests/T-null.at
Normal file
@@ -0,0 +1,48 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
AT_SETUP([files-from: 0-separated file without -0])
|
||||
AT_KEYWORDS([files-from null T-null])
|
||||
|
||||
AT_DATA([expout],[jeden\ndwa
|
||||
trzy
|
||||
])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
echo dwa > temp
|
||||
echo trzy >> temp
|
||||
cat temp | tr '\n' '\0' > temp1
|
||||
echo jeden > file-list
|
||||
cat temp1 >> file-list
|
||||
|
||||
genfile -f "jeden
|
||||
dwa" || AT_SKIP_TEST
|
||||
genfile -f trzy
|
||||
|
||||
tar cfTv archive file-list | sort
|
||||
],
|
||||
[0],
|
||||
[expout],
|
||||
[tar: file-list: file name read contains nul character
|
||||
],[],[],[ustar]) # Testing one format is enough
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2005, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
75
tests/append02.at
Normal file
75
tests/append02.at
Normal file
@@ -0,0 +1,75 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Using tar 1.15.x the following equivalent command sets:
|
||||
#
|
||||
# 1. tar cf archive file1 file2
|
||||
# and
|
||||
# 2. tar cfT archive /dev/null
|
||||
# tar rf archive file1
|
||||
# tar rt archive file2
|
||||
#
|
||||
# produced different archives (GNU format is assumed). Namely, in the
|
||||
# second case the mode field of all members, except the first, was truncated
|
||||
# to lower 3 octets (& 0777).
|
||||
#
|
||||
# References:
|
||||
# <200607210526.AA03440@tamuki.linet.gr.jp>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2006-07/msg00029.html
|
||||
|
||||
# The test case below verifies that the equivalent create and append commands
|
||||
# produce binary equivalent archives for all formats.
|
||||
|
||||
AT_SETUP([append vs. create])
|
||||
AT_KEYWORDS([append append02 append-gnu])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile --file file1
|
||||
genfile --file file2
|
||||
|
||||
# Make sure file timestamps in the archive will not differ
|
||||
MTIME="--mtime=@0"
|
||||
|
||||
# For PAX archives, we need to make sure extended header names are
|
||||
# reproducible and that their contents won't change with time
|
||||
if test $[]TEST_TAR_FORMAT = posix; then
|
||||
TAR_OPTIONS="$TAR_OPTIONS --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=mtime,delete=atime,delete=ctime"
|
||||
fi
|
||||
|
||||
echo Creating archive.1
|
||||
tar $MTIME -cf archive.1 file1 file2
|
||||
|
||||
echo Creating archive.2
|
||||
tar $MTIME -cf archive.2 -T /dev/null
|
||||
tar $MTIME -rf archive.2 file1
|
||||
tar $MTIME -rf archive.2 file2
|
||||
|
||||
echo Comparing archives
|
||||
cmp archive.1 archive.2
|
||||
],
|
||||
[0],
|
||||
[Creating archive.1
|
||||
Creating archive.2
|
||||
Comparing archives
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
# End of append02.at
|
||||
@@ -13,7 +13,7 @@ if test -z "$TEST_DATA_DIR"; then
|
||||
TEST_DATA_DIR=$abs_builddir
|
||||
fi
|
||||
|
||||
STAR_DATA_URL=http://download.berlios.de/pub/star/testscripts
|
||||
STAR_DATA_URL=ftp://ftp.berlios.de/pub/star/testscripts
|
||||
if test -z "$STAR_TESTSCRIPTS"; then
|
||||
STAR_TESTSCRIPTS=$TEST_DATA_DIR
|
||||
fi
|
||||
@@ -27,7 +27,11 @@ tarball_prereq() {
|
||||
wget -q --directory-prefix=$3 $4/$1
|
||||
fi
|
||||
fi
|
||||
echo "$2 $3/$1" | md5sum --status --check -
|
||||
echo "$2 $3/$1" | md5sum --status --check - >/dev/null 2>&1
|
||||
}
|
||||
|
||||
decho() {
|
||||
echo $*
|
||||
echo >&2 $*
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -42,7 +42,7 @@ tar tf archive
|
||||
to
|
||||
],
|
||||
[tar: tre: Not found in archive
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
163
tests/exclude.at
Normal file
163
tests/exclude.at
Normal file
@@ -0,0 +1,163 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Test the functioning of --exclude-caches and --exclude-tag option families
|
||||
|
||||
AT_SETUP([exclude])
|
||||
AT_KEYWORDS([exclude])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
mkdir dir
|
||||
echo blues > dir/blues
|
||||
echo jazz > dir/jazz
|
||||
mkdir dir/folk
|
||||
echo tagfile > dir/folk/tagfile
|
||||
echo sanjuan > dir/folk/sanjuan
|
||||
mkdir dir/rock
|
||||
echo "Signature: 8a477f597d28d172789f06886806bc55" > dir/rock/CACHEDIR.TAG
|
||||
echo "test" > dir/rock/file
|
||||
|
||||
for option in exclude-caches exclude-caches-under exclude-caches-all
|
||||
do
|
||||
echo OPTION $option
|
||||
tar -cf archive.tar --$option -v dir 2>err | sort
|
||||
cat err
|
||||
echo ARCHIVE
|
||||
tar tf archive.tar | sort
|
||||
done
|
||||
|
||||
for option in exclude-tag exclude-tag-under exclude-tag-all
|
||||
do
|
||||
echo OPTION $option
|
||||
tar -cf archive.tar --${option}=tagfile -v dir 2>err | sort
|
||||
cat err
|
||||
echo ARCHIVE
|
||||
tar tf archive.tar | sort
|
||||
done
|
||||
],
|
||||
[0],
|
||||
[OPTION exclude-caches
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/sanjuan
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
tar: dir/rock/: contains a cache directory tag CACHEDIR.TAG; contents not dumped
|
||||
ARCHIVE
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/sanjuan
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
OPTION exclude-caches-under
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/sanjuan
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
tar: dir/rock/: contains a cache directory tag CACHEDIR.TAG; contents not dumped
|
||||
ARCHIVE
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/sanjuan
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
OPTION exclude-caches-all
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/sanjuan
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
tar: dir/rock/: contains a cache directory tag CACHEDIR.TAG; directory not dumped
|
||||
ARCHIVE
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/sanjuan
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
OPTION exclude-tag
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
dir/rock/file
|
||||
tar: dir/folk/: contains a cache directory tag tagfile; contents not dumped
|
||||
ARCHIVE
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/folk/tagfile
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
dir/rock/file
|
||||
OPTION exclude-tag-under
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
dir/rock/file
|
||||
tar: dir/folk/: contains a cache directory tag tagfile; contents not dumped
|
||||
ARCHIVE
|
||||
dir/
|
||||
dir/blues
|
||||
dir/folk/
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
dir/rock/file
|
||||
OPTION exclude-tag-all
|
||||
dir/
|
||||
dir/blues
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
dir/rock/file
|
||||
tar: dir/folk/: contains a cache directory tag tagfile; directory not dumped
|
||||
ARCHIVE
|
||||
dir/
|
||||
dir/blues
|
||||
dir/jazz
|
||||
dir/rock/
|
||||
dir/rock/CACHEDIR.TAG
|
||||
dir/rock/file
|
||||
],
|
||||
[],[],[],[ustar])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -21,7 +21,7 @@
|
||||
# Could not extract symlinks over an existing file.
|
||||
|
||||
AT_SETUP([extracting symlinks over an existing file])
|
||||
AT_KEYWORDS([extract extract02])
|
||||
AT_KEYWORDS([extract extract02 symlink])
|
||||
|
||||
# FIXME: Skip if symlinks are not supported on the system
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -21,7 +21,7 @@
|
||||
# Check for fnmatch problems in glibc 2.1.95.
|
||||
|
||||
AT_SETUP([extract + fnmatch])
|
||||
AT_KEYWORDS([extract extract04])
|
||||
AT_KEYWORDS([extract extract04 fnmatch])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -31,7 +31,7 @@
|
||||
#
|
||||
|
||||
AT_SETUP([mode of extracted directories])
|
||||
AT_KEYWORDS([extract extract06])
|
||||
AT_KEYWORDS([extract extract06 directory mode])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
|
||||
|
||||
59
tests/extrac07.at
Normal file
59
tests/extrac07.at
Normal file
@@ -0,0 +1,59 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Tar 1.16 failed to extract archives that have symlinks
|
||||
# in read-only directories.
|
||||
#
|
||||
# Reported-by: Eelco Dolstra <eelco@cs.uu.nl>
|
||||
# References: <45475D78.8050708@cs.uu.nl>
|
||||
|
||||
AT_SETUP([extracting symlinks to a read-only dir])
|
||||
AT_KEYWORDS([extract extract07 read-only symlink])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
echo Prepare the directory
|
||||
mkdir dir
|
||||
genfile -f foo
|
||||
cd dir
|
||||
ln -s ../foo .
|
||||
cd ..
|
||||
chmod -w dir
|
||||
|
||||
echo Create the archive
|
||||
tar cf archive dir || exit 1
|
||||
|
||||
chmod +w dir
|
||||
|
||||
echo Extract
|
||||
mkdir out
|
||||
tar -C out -xvf archive
|
||||
],
|
||||
[0],
|
||||
[Prepare the directory
|
||||
Create the archive
|
||||
Extract
|
||||
dir/
|
||||
dir/foo
|
||||
],
|
||||
[],[],[ustar]) # Testing one format is enough
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
40
tests/grow.at
Normal file
40
tests/grow.at
Normal file
@@ -0,0 +1,40 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Tar should exit with error code 1 (file differs) if any files have
|
||||
# changed during archiving.
|
||||
|
||||
AT_SETUP([grow])
|
||||
AT_KEYWORDS([grow filechange])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile --file foo --length 50000k
|
||||
genfile --file baz
|
||||
genfile --run 'tar -vcf bar foo baz' --checkpoint 10 --length 1024 \
|
||||
--append foo
|
||||
],
|
||||
[1],
|
||||
[foo
|
||||
baz
|
||||
],
|
||||
[tar: foo: file changed as we read it
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -35,7 +35,7 @@ test $? = 2 || exit 1
|
||||
[
|
||||
gzip: stdin: unexpected end of file
|
||||
tar: Child returned status 1
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
],
|
||||
[],[])
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -64,12 +64,12 @@ test $status = 0
|
||||
[
|
||||
-----
|
||||
tar: file: Cannot open: Permission denied
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
-----
|
||||
tar: file: Warning: Cannot open: Permission denied
|
||||
-----
|
||||
tar: directory: Cannot open: Permission denied
|
||||
tar: Error exit delayed from previous errors
|
||||
tar: Exiting with failure status due to previous errors
|
||||
-----
|
||||
tar: directory: Warning: Cannot open: Permission denied
|
||||
])
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -34,6 +34,8 @@ mkdir directory
|
||||
genfile --file=directory/x
|
||||
genfile --file=directory/y
|
||||
|
||||
sleep 1
|
||||
|
||||
tar -cf archive.1 -g db directory
|
||||
|
||||
mv directory/x directory/z
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -38,6 +38,8 @@ awk 'BEGIN {
|
||||
printf("NAME_PREFIX[%03d]\n", i);
|
||||
}' < /dev/null | genfile --files-from -
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Initial dump"
|
||||
tar cvf a0.tar -g a.sna a
|
||||
mv a/b a/c
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -44,7 +44,10 @@ sleep 1
|
||||
tar cf archive --listed=list structure
|
||||
tar cfv archive --listed=list structure
|
||||
echo separator
|
||||
sleep 1
|
||||
# ReiserFS often offsets the timestamps of newly created files
|
||||
# 1 second to the past. Try to compensate for it, until a better
|
||||
# solution is found.
|
||||
sleep 2
|
||||
echo y >structure/file
|
||||
tar cfv archive --listed=list structure
|
||||
],
|
||||
|
||||
47
tests/indexfile.at
Normal file
47
tests/indexfile.at
Normal file
@@ -0,0 +1,47 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# tar --index-file=FILE --file=- sent the archive to FILE, and
|
||||
# the listing to stderr.
|
||||
# Reported by Marcin Gryszkalis <mg@fork.pl>
|
||||
# References: <200607061943.06645.mg@fork.pl>
|
||||
|
||||
AT_SETUP([tar --index-file=FILE --file=-])
|
||||
AT_KEYWORDS([stdout indexfile])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
|
||||
mkdir directory
|
||||
genfile --file=directory/a --length=1035
|
||||
|
||||
echo "Creating the archive"
|
||||
tar -c -v -f - --index-file=idx directory > archive
|
||||
|
||||
echo "Testing the archive"
|
||||
tar -tf archive
|
||||
],
|
||||
[0],
|
||||
[Creating the archive
|
||||
Testing the archive
|
||||
directory/
|
||||
directory/a
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
@@ -39,7 +39,7 @@ tar --create \
|
||||
|
||||
tar tf archive.1 || exit 1
|
||||
|
||||
sleep 1
|
||||
sleep 2
|
||||
|
||||
genfile --length 10240 --pattern zeros --file directory/file2
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user