Compare commits
1083 Commits
release_1_
...
release_1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
532b2dd31f | ||
|
|
3358f5fcc3 | ||
|
|
51e3f3f1ca | ||
|
|
caf6b29f1e | ||
|
|
12ae9f6912 | ||
|
|
64041696c9 | ||
|
|
8ee09b9939 | ||
|
|
72f60f9e5f | ||
|
|
378818cb3e | ||
|
|
c980a06329 | ||
|
|
4c7a2b10b8 | ||
|
|
8f3ed604b9 | ||
|
|
b886724818 | ||
|
|
f143fa5d64 | ||
|
|
1e3568d947 | ||
|
|
b229a86dd7 | ||
|
|
05b250d4a4 | ||
|
|
42d180b24e | ||
|
|
8c10111c66 | ||
|
|
15a55db341 | ||
|
|
e721e74259 | ||
|
|
1bea3b4b25 | ||
|
|
4ef056729e | ||
|
|
37986cdff9 | ||
|
|
5fe07ac97d | ||
|
|
a35935e973 | ||
|
|
e832cab432 | ||
|
|
578f46309f | ||
|
|
4396675861 | ||
|
|
a3dd97d9be | ||
|
|
13adf3f762 | ||
|
|
f1b1e9a476 | ||
|
|
fc4502c17e | ||
|
|
0abf3a5ac9 | ||
|
|
19b36aaf60 | ||
|
|
9b44f8efed | ||
|
|
97bfe578ed | ||
|
|
fb88325f56 | ||
|
|
a1b2406646 | ||
|
|
5e14ef32c0 | ||
|
|
f9bd340c1b | ||
|
|
46defea70e | ||
|
|
5daab19c27 | ||
|
|
7214086d3d | ||
|
|
93560dd669 | ||
|
|
c1f55f1c37 | ||
|
|
2d2e1d411e | ||
|
|
5591fa407a | ||
|
|
e2dbba2f07 | ||
|
|
018de58373 | ||
|
|
17111bef8f | ||
|
|
3a9f2ea587 | ||
|
|
02c7b862a3 | ||
|
|
9154c0c43b | ||
|
|
5108a3dc41 | ||
|
|
c52e5fc4e8 | ||
|
|
0fc3177ed2 | ||
|
|
6be1349236 | ||
|
|
a2625311c8 | ||
|
|
6e2760f7d7 | ||
|
|
8b2f4ad670 | ||
|
|
d4c0836ec2 | ||
|
|
40afe4d362 | ||
|
|
435edb824e | ||
|
|
9d2e8df195 | ||
|
|
aa7476a68e | ||
|
|
16c48ef8d0 | ||
|
|
0da8aac59f | ||
|
|
bb6f707781 | ||
|
|
7cb01d37bb | ||
|
|
d79bbe0fd1 | ||
|
|
f984c43b82 | ||
|
|
d75890c1b8 | ||
|
|
b3b4347821 | ||
|
|
39080c7628 | ||
|
|
c58063c17a | ||
|
|
ae7bd36423 | ||
|
|
973b611290 | ||
|
|
29fb7356df | ||
|
|
bbee515590 | ||
|
|
c8aa01c80c | ||
|
|
43ba23114f | ||
|
|
7bfcbd6a27 | ||
|
|
c5fd5f9e8d | ||
|
|
a23a95b4a0 | ||
|
|
19498c9172 | ||
|
|
edff149522 | ||
|
|
f20e08dd45 | ||
|
|
e6d15fc7af | ||
|
|
c96ba08e06 | ||
|
|
6f89b1fce5 | ||
|
|
93f8f6780a | ||
|
|
75f37f4cef | ||
|
|
3947e63c25 | ||
|
|
8b471d55ff | ||
|
|
c2c2df6c93 | ||
|
|
cf857388c1 | ||
|
|
9dfad74683 | ||
|
|
57267f7ed9 | ||
|
|
476abe556b | ||
|
|
fe72c79ad8 | ||
|
|
8fea578b22 | ||
|
|
a46704b1bf | ||
|
|
6f8cbc5ca8 | ||
|
|
c03131aba9 | ||
|
|
c9195c75be | ||
|
|
5632d195f5 | ||
|
|
ef90e05363 | ||
|
|
939d63b92d | ||
|
|
0ff13351f0 | ||
|
|
c57418b462 | ||
|
|
3c7dd57a17 | ||
|
|
0b3fe146dd | ||
|
|
90088ff00d | ||
|
|
a183d6f7f5 | ||
|
|
4883aab47d | ||
|
|
30873dbd97 | ||
|
|
74849d8119 | ||
|
|
3962eb6a3e | ||
|
|
c99076e925 | ||
|
|
6315d1700b | ||
|
|
520104f5f8 | ||
|
|
34e5f66589 | ||
|
|
d2b3114a3b | ||
|
|
2b27e8de1f | ||
|
|
a85cfd69e3 | ||
|
|
4b951034f3 | ||
|
|
1524831224 | ||
|
|
ee6f14194d | ||
|
|
ac7f4e853d | ||
|
|
47dd75e87b | ||
|
|
6054b5e9d5 | ||
|
|
edd6df370d | ||
|
|
fd89d5a3cd | ||
|
|
71f2e412ae | ||
|
|
67877f7de2 | ||
|
|
c9e7465642 | ||
|
|
a0b4431f26 | ||
|
|
192ac7136a | ||
|
|
c2775aedf1 | ||
|
|
f1fe157dfe | ||
|
|
dd197c5ccb | ||
|
|
c576ac1354 | ||
|
|
53d1279719 | ||
|
|
729b91adb1 | ||
|
|
dc7c0f1309 | ||
|
|
783e58b394 | ||
|
|
c0e5268e75 | ||
|
|
1518cef987 | ||
|
|
8dd9a2105e | ||
|
|
9ec31e3438 | ||
|
|
d4a41d5311 | ||
|
|
a46e6aa4dc | ||
|
|
b4d40436fd | ||
|
|
f97d80335a | ||
|
|
90b061cf55 | ||
|
|
8300c820d5 | ||
|
|
e0b3fc61e1 | ||
|
|
533854fd45 | ||
|
|
e99d4f83df | ||
|
|
b8d5835375 | ||
|
|
61dd37ec86 | ||
|
|
48d20d8f9e | ||
|
|
adbbde5d4f | ||
|
|
208389f3ad | ||
|
|
db0f0804f5 | ||
|
|
18486cf8d7 | ||
|
|
6c1020d386 | ||
|
|
38c0884898 | ||
|
|
7bcb876c5a | ||
|
|
dfd5ec2519 | ||
|
|
e81556858b | ||
|
|
92554b7c94 | ||
|
|
631de61428 | ||
|
|
8bfefd8854 | ||
|
|
f7a29307e2 | ||
|
|
66ef04d4c8 | ||
|
|
b6ffcac4db | ||
|
|
28698a5334 | ||
|
|
e304b58fff | ||
|
|
c532f12464 | ||
|
|
9fdd5baa0c | ||
|
|
31ef7e3afb | ||
|
|
f2bf9f2ffa | ||
|
|
cad45a0bae | ||
|
|
f6ede25815 | ||
|
|
476019d083 | ||
|
|
cf440a191f | ||
|
|
588f444efe | ||
|
|
b4051cb07c | ||
|
|
5032e08eb9 | ||
|
|
36f41eabf4 | ||
|
|
108edf3692 | ||
|
|
780cf6f079 | ||
|
|
84378fa99a | ||
|
|
78b078b455 | ||
|
|
e86e864544 | ||
|
|
d21d48dfba | ||
|
|
cf1e8b086b | ||
|
|
6912b7fb15 | ||
|
|
6c28751ca7 | ||
|
|
0e848e7b2c | ||
|
|
ab8a184336 | ||
|
|
48ce2946d9 | ||
|
|
dde5c2391b | ||
|
|
860577ee0e | ||
|
|
a349bd80b9 | ||
|
|
ba10157a0c | ||
|
|
514ea6ead4 | ||
|
|
6a97a00688 | ||
|
|
7d822e225e | ||
|
|
38f08784bc | ||
|
|
c17a9f91d0 | ||
|
|
0f4660c786 | ||
|
|
5e01ba7dbe | ||
|
|
288315211a | ||
|
|
dacac1b6be | ||
|
|
85cf996677 | ||
|
|
6cbd7e1608 | ||
|
|
b794387cba | ||
|
|
91abd3da82 | ||
|
|
5b3dc9e3dd | ||
|
|
d3e525009d | ||
|
|
86ef91adff | ||
|
|
a92a8ff22d | ||
|
|
1cdb7823ae | ||
|
|
e73e4428e2 | ||
|
|
d2dd096f1d | ||
|
|
fb0a0aaf52 | ||
|
|
d102bc35a5 | ||
|
|
bb8c1d6a72 | ||
|
|
f03fc1e078 | ||
|
|
273810a9f7 | ||
|
|
69abc76d13 | ||
|
|
12cd9cea81 | ||
|
|
bfa1bba5fd | ||
|
|
09b46a0b47 | ||
|
|
a169d65b94 | ||
|
|
89e65f936d | ||
|
|
c9ac15ae0f | ||
|
|
67770b89f2 | ||
|
|
f3e6ea7d49 | ||
|
|
0d2cdcb797 | ||
|
|
49e7ba5b17 | ||
|
|
3f6d87a61c | ||
|
|
80855932f0 | ||
|
|
9e50e81558 | ||
|
|
02ec34f473 | ||
|
|
075c726752 | ||
|
|
2e7a943d0e | ||
|
|
4ba3b41e2e | ||
|
|
4669306854 | ||
|
|
ffc4fb7bdd | ||
|
|
c7ab8eaba4 | ||
|
|
3f166ce0f5 | ||
|
|
ac74317f46 | ||
|
|
ce522dce26 | ||
|
|
f018d69aac | ||
|
|
ea019af0cc | ||
|
|
0251059267 | ||
|
|
13d43c302f | ||
|
|
a5da71b142 | ||
|
|
853edfaff4 | ||
|
|
ca43ee9769 | ||
|
|
888b0d82b7 | ||
|
|
b84053c7be | ||
|
|
c040cabb98 | ||
|
|
ae00dc0d37 | ||
|
|
5249a99377 | ||
|
|
2edff367d9 | ||
|
|
f8f4f49011 | ||
|
|
3fbdf738de | ||
|
|
7209cbed6c | ||
|
|
aa976a5170 | ||
|
|
7b00db5675 | ||
|
|
36be286c03 | ||
|
|
d543d2dbbd | ||
|
|
5df61b429a | ||
|
|
9590e781c0 | ||
|
|
87dfaf3176 | ||
|
|
c81a5e8bf5 | ||
|
|
b5775215d7 | ||
|
|
df970c7332 | ||
|
|
f1f3b524f6 | ||
|
|
575ea074cc | ||
|
|
6204e3c718 | ||
|
|
ecce6f3e9a | ||
|
|
85890103ae | ||
|
|
7e51be5fe2 | ||
|
|
05ba292a93 | ||
|
|
1ebdd88caf | ||
|
|
b6d3432810 | ||
|
|
1e8f6d41c4 | ||
|
|
5b1df7b55e | ||
|
|
692f449623 | ||
|
|
5f060c2025 | ||
|
|
d1867fd76c | ||
|
|
813aa07a89 | ||
|
|
9a42d94543 | ||
|
|
b9b37ee191 | ||
|
|
04549e1f21 | ||
|
|
f3a24a7a51 | ||
|
|
e1286c1989 | ||
|
|
5eecc4c994 | ||
|
|
cb3d8b0db9 | ||
|
|
52429bb956 | ||
|
|
7200f4f5f7 | ||
|
|
737b0251de | ||
|
|
48d508b78b | ||
|
|
57c2124d68 | ||
|
|
06379466c1 | ||
|
|
3eec6b3f46 | ||
|
|
60f8dd83b8 | ||
|
|
cfbf693855 | ||
|
|
35f5b48815 | ||
|
|
374ae10d39 | ||
|
|
4d22cbd47c | ||
|
|
e20e79e7ff | ||
|
|
f865597c89 | ||
|
|
1b9c48d934 | ||
|
|
f6458a827a | ||
|
|
08a8d2dec6 | ||
|
|
aea1d50da9 | ||
|
|
588232f859 | ||
|
|
4c4c5a4dc1 | ||
|
|
d144e7c217 | ||
|
|
ef9ad717ba | ||
|
|
85ce2c24f8 | ||
|
|
d01f65092c | ||
|
|
04e2551256 | ||
|
|
8b2504deca | ||
|
|
ad09c8373b | ||
|
|
5b91f80787 | ||
|
|
ef981aae38 | ||
|
|
36f1d689e4 | ||
|
|
1e304fc5fd | ||
|
|
b100f6ae5b | ||
|
|
a6d2158837 | ||
|
|
c641a16cba | ||
|
|
65a7536d1f | ||
|
|
8c119485a9 | ||
|
|
a02a9ed099 | ||
|
|
71976fa77e | ||
|
|
c2552c6c40 | ||
|
|
b272b3e2cf | ||
|
|
c44d0d037f | ||
|
|
9c50f854a6 | ||
|
|
fc42672fe0 | ||
|
|
64aea5de53 | ||
|
|
391c6f6bdb | ||
|
|
9684c2728d | ||
|
|
cb8aacd9ef | ||
|
|
3ae9e51181 | ||
|
|
7a246ab602 | ||
|
|
35b9ca72db | ||
|
|
ecdef9daaa | ||
|
|
eb744655a8 | ||
|
|
57fcb1639e | ||
|
|
49f39c25b4 | ||
|
|
40da86b2a1 | ||
|
|
15b75f848e | ||
|
|
2a25112552 | ||
|
|
b2b60efaaf | ||
|
|
ddb0f96f00 | ||
|
|
13aead50a8 | ||
|
|
8f1d2fd9c3 | ||
|
|
a274294656 | ||
|
|
63f64e4aaf | ||
|
|
3209329337 | ||
|
|
2f800ce3fb | ||
|
|
ae5473fe02 | ||
|
|
1f4437aa66 | ||
|
|
8952196bc1 | ||
|
|
9093ca15d8 | ||
|
|
76efed4ca4 | ||
|
|
a2b6327eda | ||
|
|
af5d05729a | ||
|
|
3070fff7d7 | ||
|
|
6bb5c17aea | ||
|
|
ecd43c1314 | ||
|
|
f58c189f3e | ||
|
|
931e305002 | ||
|
|
a57ecc51aa | ||
|
|
a5375b618c | ||
|
|
c40ba72fd3 | ||
|
|
eacde4bca7 | ||
|
|
220ffceb44 | ||
|
|
b65b1ff9eb | ||
|
|
e0b0becead | ||
|
|
c9c76e7d56 | ||
|
|
9d23481b5f | ||
|
|
aa76a67b76 | ||
|
|
59a4026674 | ||
|
|
9106e53684 | ||
|
|
a34b0ad8c9 | ||
|
|
1992b53b8c | ||
|
|
f319c5575b | ||
|
|
44ce72fa96 | ||
|
|
2e9ea5f4a7 | ||
|
|
4bd38118e0 | ||
|
|
b65039526c | ||
|
|
fb1b9e3d0f | ||
|
|
aedacf9d29 | ||
|
|
d9045bf409 | ||
|
|
8d52260315 | ||
|
|
225e690142 | ||
|
|
c877b48d68 | ||
|
|
37d2462d7c | ||
|
|
040b5ab5f9 | ||
|
|
4f4a858eb6 | ||
|
|
d659cbaccd | ||
|
|
f6445e4ed6 | ||
|
|
3fe8fc3ef9 | ||
|
|
372ff169e7 | ||
|
|
c6cde895e3 | ||
|
|
28b44cc69c | ||
|
|
eb70fd51cb | ||
|
|
5c4ea58bd7 | ||
|
|
85ad04d822 | ||
|
|
fb7b2f3645 | ||
|
|
ab03bd6a2c | ||
|
|
9d5fd390dc | ||
|
|
e5e43aa7a4 | ||
|
|
77e56f876d | ||
|
|
2c49c610be | ||
|
|
ec89da307c | ||
|
|
ee870c97b9 | ||
|
|
ca5e64504b | ||
|
|
cc07b9e170 | ||
|
|
f2c8b1dff3 | ||
|
|
9129c846e7 | ||
|
|
df0913f3fe | ||
|
|
e20fdceb38 | ||
|
|
5c35fdb275 | ||
|
|
113b619383 | ||
|
|
517205c31c | ||
|
|
dfabe2397a | ||
|
|
8f1f0955cf | ||
|
|
1672258959 | ||
|
|
c172481f41 | ||
|
|
46f09016e8 | ||
|
|
120e96c480 | ||
|
|
271ed97494 | ||
|
|
3ac99bc540 | ||
|
|
a33b37a9a3 | ||
|
|
c9365a1d09 | ||
|
|
8d064bb816 | ||
|
|
29c902bc49 | ||
|
|
d78f85d61d | ||
|
|
73be90ea0d | ||
|
|
9adc789138 | ||
|
|
cfe4eef5c2 | ||
|
|
0e61fd397f | ||
|
|
bb8dcc1e8c | ||
|
|
87bd7f5d1c | ||
|
|
ecac16a4a0 | ||
|
|
89a4824c73 | ||
|
|
9b7c6df82b | ||
|
|
e2c431e9c2 | ||
|
|
82c746410d | ||
|
|
2e025f2dea | ||
|
|
f2e17c0d8c | ||
|
|
ed08ef0458 | ||
|
|
3ab983facf | ||
|
|
6c6fe16aaa | ||
|
|
27b98aa8ae | ||
|
|
18850a18f1 | ||
|
|
005d0d455c | ||
|
|
a71807a247 | ||
|
|
d7af510d49 | ||
|
|
ef0e611663 | ||
|
|
8f9ecca0db | ||
|
|
9147c6c9f6 | ||
|
|
ee738da4a8 | ||
|
|
42e53a98e1 | ||
|
|
2d34da98d5 | ||
|
|
781d3818e5 | ||
|
|
c861b96651 | ||
|
|
2872a5ae81 | ||
|
|
62599b5285 | ||
|
|
263604c2ec | ||
|
|
7ebf107f89 | ||
|
|
5fe7f641e8 | ||
|
|
dbf96ec903 | ||
|
|
5d87077565 | ||
|
|
7d4bd5b38d | ||
|
|
ad0bd3c9c4 | ||
|
|
95fa3422d7 | ||
|
|
67c7284d07 | ||
|
|
6811232d8f | ||
|
|
fdbb1d8c7c | ||
|
|
f04c7701fa | ||
|
|
63e90fdc62 | ||
|
|
b320151a23 | ||
|
|
9fc348aae9 | ||
|
|
0fd49f51a0 | ||
|
|
002cd6843a | ||
|
|
b4fb3e9f74 | ||
|
|
549a691ada | ||
|
|
e7e66c4426 | ||
|
|
ea9df3c243 | ||
|
|
1d804e4f68 | ||
|
|
eaa66dc858 | ||
|
|
a66ab8591f | ||
|
|
6e63133691 | ||
|
|
b480196651 | ||
|
|
371af209a7 | ||
|
|
5c2e32780e | ||
|
|
4d8ddc720e | ||
|
|
5f405b1a2d | ||
|
|
ef68503367 | ||
|
|
64ba4757bc | ||
|
|
cd02b0855c | ||
|
|
35bb355734 | ||
|
|
fa63755f6b | ||
|
|
ea12939af0 | ||
|
|
9a71d32d2f | ||
|
|
6609c2a607 | ||
|
|
c580a1c407 | ||
|
|
91ce177fc7 | ||
|
|
4d24adbecb | ||
|
|
0b939d7dbc | ||
|
|
75a16f75a9 | ||
|
|
e758088191 | ||
|
|
f96dc77bbc | ||
|
|
23cf312ef1 | ||
|
|
0e4b59b4b2 | ||
|
|
a6f6974f75 | ||
|
|
8f0112cb23 | ||
|
|
9c2f942930 | ||
|
|
5422166048 | ||
|
|
0ad4063606 | ||
|
|
db2d3f2344 | ||
|
|
5179c0b5e6 | ||
|
|
87a7b31a82 | ||
|
|
1044149e3a | ||
|
|
d8dc269927 | ||
|
|
1e2e868af5 | ||
|
|
c8764440d9 | ||
|
|
59f314a2c4 | ||
|
|
0e45413e1e | ||
|
|
2fcd454e17 | ||
|
|
e318ac6fe8 | ||
|
|
71b7086ff7 | ||
|
|
5cf84df777 | ||
|
|
4a7703ff21 | ||
|
|
91c69c885b | ||
|
|
63c140752f | ||
|
|
ce852113e0 | ||
|
|
ccb2072c7e | ||
|
|
d8b24b63e8 | ||
|
|
0dcb0ad279 | ||
|
|
0cde2ad44c | ||
|
|
88e9b05867 | ||
|
|
198596f161 | ||
|
|
ccac216e67 | ||
|
|
660d760587 | ||
|
|
771ac30e0f | ||
|
|
ebd88883f5 | ||
|
|
81572b57a3 | ||
|
|
5be8e9d4c7 | ||
|
|
4e52e75bbe | ||
|
|
4caea8d763 | ||
|
|
0037ae7f9e | ||
|
|
01778aa4a9 | ||
|
|
3360b2cce4 | ||
|
|
5f19de0372 | ||
|
|
cdb27293db | ||
|
|
937202acb9 | ||
|
|
3971a56b22 | ||
|
|
18ee9a103a | ||
|
|
de772cad88 | ||
|
|
2c9d869851 | ||
|
|
2b9556cb8e | ||
|
|
47b2def4a2 | ||
|
|
f389e8657d | ||
|
|
c6ca601327 | ||
|
|
5dc9944b5a | ||
|
|
fabcc30f69 | ||
|
|
8a59f40796 | ||
|
|
1859998c22 | ||
|
|
e7db56c0ef | ||
|
|
14d8c8a035 | ||
|
|
471cf501e5 | ||
|
|
4719a5d55b | ||
|
|
cff5cfb5ce | ||
|
|
ef96e14fe1 | ||
|
|
248069ea4a | ||
|
|
d882e8f39b | ||
|
|
3e5686c1ec | ||
|
|
b8efe40f54 | ||
|
|
73777093b1 | ||
|
|
746e6b45b6 | ||
|
|
c251377da9 | ||
|
|
39a00a8f4f | ||
|
|
85d8f1d2a2 | ||
|
|
2266e14d8c | ||
|
|
941d7586db | ||
|
|
1c7a6c11ce | ||
|
|
2ad41b6fe0 | ||
|
|
af2fa08aa0 | ||
|
|
93e4188e60 | ||
|
|
c0eaf364d0 | ||
|
|
86c379f7c1 | ||
|
|
3352016cf0 | ||
|
|
6bc808b25f | ||
|
|
19f60610d1 | ||
|
|
2433f6813e | ||
|
|
76bbb5710f | ||
|
|
e8fbac5ec1 | ||
|
|
5842962ed6 | ||
|
|
368172bf25 | ||
|
|
0f9b299745 | ||
|
|
ab3b31cfef | ||
|
|
f152367c57 | ||
|
|
a34d0e906f | ||
|
|
dcedecad2b | ||
|
|
436741221c | ||
|
|
8ccde495f4 | ||
|
|
29a6b977e9 | ||
|
|
5129d9eb8c | ||
|
|
b5c890b887 | ||
|
|
2d57bb240d | ||
|
|
554e50b438 | ||
|
|
c6834baaf6 | ||
|
|
17600e0de8 | ||
|
|
fb782b023f | ||
|
|
8d44c6b51e | ||
|
|
c575787495 | ||
|
|
71850c6ab3 | ||
|
|
fa87656256 | ||
|
|
7c3510b40d | ||
|
|
5f1e6a6a3b | ||
|
|
aa600ee769 | ||
|
|
bf2b8556e8 | ||
|
|
8263cc7bc0 | ||
|
|
6af2e16b9b | ||
|
|
664ec232d4 | ||
|
|
90b1e24487 | ||
|
|
94f7d4e7c1 | ||
|
|
6323ff0880 | ||
|
|
7b29b10847 | ||
|
|
e6a67c2eb5 | ||
|
|
2e7378e819 | ||
|
|
849ec50941 | ||
|
|
889b8a1046 | ||
|
|
2f034ae71b | ||
|
|
bf8852627a | ||
|
|
73b52b1b9b | ||
|
|
c69d2f6539 | ||
|
|
412fbeb90d | ||
|
|
322114744f | ||
|
|
b5db978830 | ||
|
|
4674867a23 | ||
|
|
d5f1626556 | ||
|
|
c8b0fd28c2 | ||
|
|
dcdbe18968 | ||
|
|
6c941e0826 | ||
|
|
ff989f4b84 | ||
|
|
b2a65edf5c | ||
|
|
d305c258bf | ||
|
|
8ff11f27c1 | ||
|
|
5dee0c1348 | ||
|
|
b55daca933 | ||
|
|
f218c29b13 | ||
|
|
1625cc5f67 | ||
|
|
c0f0d25271 | ||
|
|
2ab1422c04 | ||
|
|
53a80edafc | ||
|
|
75284507b3 | ||
|
|
9b712b0fc8 | ||
|
|
d47a177d3d | ||
|
|
2c7d98238b | ||
|
|
9e2233007c | ||
|
|
06742ec624 | ||
|
|
5b56886a72 | ||
|
|
5db60955f5 | ||
|
|
52030539f7 | ||
|
|
e370518b43 | ||
|
|
3cb52ac16a | ||
|
|
75bf036edc | ||
|
|
6cf99ce8ae | ||
|
|
ae3238495d | ||
|
|
33491a8d7c | ||
|
|
5fd2daf959 | ||
|
|
37ac08b3fe | ||
|
|
35cae74c4c | ||
|
|
a1c8c7bd47 | ||
|
|
71c05b230c | ||
|
|
cf2fa13bc5 | ||
|
|
7d6865480e | ||
|
|
cadabfc4c7 | ||
|
|
6b401f904a | ||
|
|
f3f06e8a71 | ||
|
|
8fed513af1 | ||
|
|
00478f4bd3 | ||
|
|
4ad940344a | ||
|
|
b5d9942a35 | ||
|
|
c0b641f055 | ||
|
|
7347b4f5d5 | ||
|
|
e3bd2a63a6 | ||
|
|
430b139592 | ||
|
|
06bb349ca9 | ||
|
|
2e419759d1 | ||
|
|
da3f3e0b3b | ||
|
|
a0404319e2 | ||
|
|
a2a6547e2d | ||
|
|
5e30076bfd | ||
|
|
7c7da5f79f | ||
|
|
d1f3689d96 | ||
|
|
ac830291f1 | ||
|
|
44283eb6ca | ||
|
|
4ad0f97e2c | ||
|
|
d14f101217 | ||
|
|
19335cdfb4 | ||
|
|
4e4e8c57fd | ||
|
|
df6161b9fe | ||
|
|
33da1b2f64 | ||
|
|
28efbf6944 | ||
|
|
678a4411ea | ||
|
|
001e5cf813 | ||
|
|
fc264a87a8 | ||
|
|
68bd7ac50a | ||
|
|
3f4f5a4bf4 | ||
|
|
e563240b95 | ||
|
|
6522c25b8d | ||
|
|
0ec47c16a9 | ||
|
|
b1f2c77860 | ||
|
|
607c1bf3b4 | ||
|
|
74b3e8ab49 | ||
|
|
8771e7c560 | ||
|
|
1992ef9496 | ||
|
|
73030de19f | ||
|
|
a5f5e75388 | ||
|
|
bd599facc8 | ||
|
|
7f27104062 | ||
|
|
e24d4efed0 | ||
|
|
a418ef678e | ||
|
|
83acd3c604 | ||
|
|
303132dcdc | ||
|
|
3848b93af6 | ||
|
|
93becc4f52 | ||
|
|
03092879ac | ||
|
|
38f39174f2 | ||
|
|
1c0a13aade | ||
|
|
2d041189aa | ||
|
|
f6c0aee290 | ||
|
|
54e4a0df65 | ||
|
|
34ff480be9 | ||
|
|
260acce7a3 | ||
|
|
5a8a98cffe | ||
|
|
320298c663 | ||
|
|
4f3e70b0f9 | ||
|
|
c50565d965 | ||
|
|
df2c78e32b | ||
|
|
56389381fc | ||
|
|
45a6a18d85 | ||
|
|
68ff77508c | ||
|
|
43ca8709c0 | ||
|
|
c4e054673b | ||
|
|
df6200e97e | ||
|
|
9ae5a981fc | ||
|
|
7287be445e | ||
|
|
cafa07d966 | ||
|
|
9038410bb7 | ||
|
|
f3da0c26b8 | ||
|
|
82eff37f6f | ||
|
|
6869d0f6b3 | ||
|
|
81460a0349 | ||
|
|
ae29dcca87 | ||
|
|
ac7c2b7116 | ||
|
|
08cba4e4e5 | ||
|
|
d81b5d6f1e | ||
|
|
55ec665a41 | ||
|
|
4ab8cff6b3 | ||
|
|
e4afe72b7a | ||
|
|
0a3a9744f7 | ||
|
|
ad548198f3 | ||
|
|
4f732c1595 | ||
|
|
f94cf6216b | ||
|
|
44391cb932 | ||
|
|
af15956c4d | ||
|
|
402b50d4d2 | ||
|
|
240a4ed90a | ||
|
|
6938706958 | ||
|
|
cd2c8d4fbb | ||
|
|
421043b6b1 | ||
|
|
24aa94e5cf | ||
|
|
8160c0dae9 | ||
|
|
53614b3dff | ||
|
|
23c2244ddf | ||
|
|
ebdf1bc7a6 | ||
|
|
ba08e339a6 | ||
|
|
951b0370df | ||
|
|
167f5ba2bc | ||
|
|
488430f739 | ||
|
|
80c29e6315 | ||
|
|
432b157a28 | ||
|
|
b121917368 | ||
|
|
fa8cb1895c | ||
|
|
64759986a9 | ||
|
|
d4d6c23008 | ||
|
|
325a45f0f1 | ||
|
|
f41e484f23 | ||
|
|
141d267691 | ||
|
|
3331593d8d | ||
|
|
3344bf9380 | ||
|
|
463d99453f | ||
|
|
d2d5d64cb4 | ||
|
|
32ebe16224 | ||
|
|
a447fd3714 | ||
|
|
792965270b | ||
|
|
916019e417 | ||
|
|
3ee93d341e | ||
|
|
dd4cef1699 | ||
|
|
8286de0946 | ||
|
|
a65779d558 | ||
|
|
e1a4fea80d | ||
|
|
5608be67f7 | ||
|
|
0a79415a97 | ||
|
|
f730b47314 | ||
|
|
48c24ac711 | ||
|
|
3e8f210904 | ||
|
|
ee56bd0d0b | ||
|
|
ecb338ad8e | ||
|
|
ce486a8fd7 | ||
|
|
abba83af27 | ||
|
|
823f96841c |
28
.cvsignore
28
.cvsignore
@@ -1,21 +1,17 @@
|
||||
config
|
||||
configure
|
||||
aclocal.m4
|
||||
*.bz2
|
||||
*.gz
|
||||
*.tar
|
||||
.bootstrap
|
||||
ABOUT-NLS
|
||||
autom4te.cache
|
||||
config.hin
|
||||
COPYING
|
||||
INSTALL
|
||||
Makefile.in
|
||||
config.log
|
||||
config.status
|
||||
Makefile
|
||||
config.h
|
||||
stamp-h1
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.tar.bz2
|
||||
*.shar.gz
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
config.*
|
||||
configure
|
||||
gnulib
|
||||
gnulib/*
|
||||
gnulib/*/*
|
||||
rmt
|
||||
stamp-h1
|
||||
|
||||
@@ -19,8 +19,8 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
----- ChangeLog -----
|
||||
|
||||
18
Makefile.am
18
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,
|
||||
@@ -15,9 +15,17 @@
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
## 02111-1307, USA.
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
EXTRA_DIST = ChangeLog.1 PORTS
|
||||
SUBDIRS = doc lib src scripts po tests
|
||||
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
|
||||
|
||||
416
NEWS
416
NEWS
@@ -1,11 +1,323 @@
|
||||
GNU tar NEWS - User visible changes.
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
See the end for copying conditions.
|
||||
|
||||
GNU tar NEWS - User visible changes. 2007-06-29
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
** Globbing
|
||||
|
||||
Previous versions of GNU tar assumed shell-style globbing when
|
||||
extracting from or listing an archive. For example:
|
||||
|
||||
tar xf foo.tar '*.c'
|
||||
|
||||
would extract all files whose names end in '.c'. This behavior
|
||||
was not documented and was incompatible with traditional tar
|
||||
implementations. Therefore, starting from this version, GNU tar
|
||||
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.
|
||||
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
|
||||
--anchored patterns match file name start
|
||||
--ignore-case ignore case
|
||||
--wildcards-match-slash wildcards match `/'
|
||||
|
||||
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
|
||||
command line and that of the exclusion patterns (given with --exclude
|
||||
and --exclude-from options). The defaults are:
|
||||
|
||||
1. For member names: --no-wildcards --anchored
|
||||
2. For exclusion patterns: --wildcards --no-anchored --wildcards-match-slash
|
||||
|
||||
The options can appear multiple times in the command line, thereby
|
||||
changing the way command line arguments are interpreted. For example,
|
||||
to use case-insensitive matching in exclude patterns and to revert to
|
||||
case-sensitive matching for the rest of command line, one could write:
|
||||
|
||||
tar xf foo.tar --ignore-case --exclude-from=FILE --no-ignore-case file.name
|
||||
|
||||
** 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
|
||||
in the archive or member names before extracting. The option takes a
|
||||
sed replace expression as its argument. For example,
|
||||
|
||||
tar cf foo.tar --transform 's,^,prefix/,'
|
||||
|
||||
will add 'prefix/' to all file names stored in foo.tar.
|
||||
|
||||
** --strip-components option works when deleting and comparing. In previous
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
** The --totals option can be used with any tar operation (previous versions
|
||||
understood it only with --create). If an argument to this option is
|
||||
given, it specifies the signal upon delivery of which the statistics
|
||||
is to be printed. Both forms of this option (with and without
|
||||
argument) can be given to in a single invocation of tar.
|
||||
|
||||
* Bug fixes
|
||||
** Detect attempts to update compressed archives.
|
||||
|
||||
|
||||
version 1.15.90 - Sergey Poznyakoff, 2006-02-19
|
||||
|
||||
* New features
|
||||
|
||||
** Any number of -T (--files-from) options may be used in the command line.
|
||||
The file specified with -T may include any valid `tar' options,
|
||||
including another -T option.
|
||||
Compatibility note: older versions of tar would only recognize -C
|
||||
as an option name within the file list file. Now any file whose name
|
||||
starts with - is handled as an option. To insert file names starting with
|
||||
dash, use the --add-file option.
|
||||
|
||||
** List files containing null-separated file names are detected and processed
|
||||
automatically. It is no longer necessary to give the --null option.
|
||||
|
||||
** New option --no-unquote disables the unquoting of input file names.
|
||||
This is useful for processing output from `find dir -print0'.
|
||||
An orthogonal option --unquote is provided as well.
|
||||
|
||||
** New option --test-label tests the archive volume label.
|
||||
If an argument is specified, the label is compared against its value.
|
||||
Tar exits with code 0 if the two strings match, and with code 2 if
|
||||
they do not.
|
||||
|
||||
If no argument is given, the --verbose option is implied. In this case,
|
||||
tar prints the label name if present and exits with code 0.
|
||||
|
||||
** New option --show-stored-names. When creating an archive in verbose mode,
|
||||
it lists member names as stored in the archive, i.e., with any eventual
|
||||
prefixes removed. The option is useful, for example, while comparing
|
||||
`tar cv' and `tar tv' outputs.
|
||||
|
||||
** New option --to-command pipes the contents of archive members to the
|
||||
specified command.
|
||||
|
||||
** New option --atime-preserve=system, which uses the O_NOATIME feature
|
||||
of recent Linux kernels to avoid some problems when preserving file
|
||||
access times.
|
||||
|
||||
** New option --delay-directory-restore delays restoring modification times
|
||||
and permissions of extracted directories until the end of extraction.
|
||||
This is necessary for restoring from archives with unusual member
|
||||
ordering (in particular, those created with --no-recursion option).
|
||||
This option is implied when restoring from incremental archives.
|
||||
|
||||
** New option --restrict prohibits use of some potentially harmful tar
|
||||
options. Currently it disables '!' escape in multi-volume name menu.
|
||||
|
||||
** New options --quoting-style and --quote-chars control the way tar
|
||||
quotes member names on output. The --quoting-style takes an argument
|
||||
specifying the quoting style to use (literal, shell, shell-always,
|
||||
c, escape, locale, clocale). The argument to --quote-chars is a string
|
||||
specifying characters to quote, even if the selected quoting style
|
||||
would not quote them otherwise. The option --no-quote-chars is
|
||||
provided to disable quoting certain characters.
|
||||
|
||||
** The end-of-volume script (introduced with --info-script option) can
|
||||
get current archive name from the environment variable TAR_ARCHIVE and
|
||||
the volume number from the variable TAR_VOLUME. It can alter the
|
||||
archive name by writing new name to the file descriptor 3.
|
||||
|
||||
** Better support for full-resolution time stamps. Tar cannot restore
|
||||
time stamps to full nanosecond resolution, though, until the kernel
|
||||
guys get their act together and give us a system call to set file time
|
||||
stamps to nanosecond resolution.
|
||||
|
||||
** The -v option now prints time stamps only to 1-minute resolution,
|
||||
not full resolution, to avoid using up too many output columns.
|
||||
Nanosecond resolution is now supported, but that would be too much.
|
||||
|
||||
* Bug fixes
|
||||
|
||||
** Allow non-option arguments to be interspersed with options.
|
||||
** When extracting or listing archives in old GNU format, tar
|
||||
used to read an extra block of data after a long name header
|
||||
if length of the member name was divisible by block size (512).
|
||||
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) 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
|
||||
meta-data cannot be stored in the header due to format limitations
|
||||
(for ustar and v7 formats).
|
||||
** The --version option now also outputs information about copyright,
|
||||
license, and credits. This reverts to the behavior of tar 1.14 and
|
||||
earlier, and conforms to the GNU coding standards. The --license (-L)
|
||||
option introduced in tar 1.15 has been removed, since it's no longer
|
||||
needed.
|
||||
|
||||
|
||||
version 1.15.1 - Sergey Poznyakoff, 2004-12-21
|
||||
|
||||
This version fixes a bug introduced in 1.15 which caused
|
||||
tar to refuse to extract files from standard input.
|
||||
|
||||
|
||||
version 1.15 - Sergey Poznyakoff, 2004-12-20
|
||||
|
||||
* Compressed archives are recognised automatically, it is no longer
|
||||
necessary to specify -Z, -z, or -j options to read them. Thus, you can
|
||||
now run `tar tf archive.tar.gz'.
|
||||
|
||||
* When restoring incremental dumps, --one-file-system option
|
||||
prevents directory hierarchies residing on different devices
|
||||
from being purged.
|
||||
|
||||
With the previous versions of tar it was dangerous to create
|
||||
incremental dumps with --one-file-system option, since they
|
||||
would recursively remove mount points when restoring from the
|
||||
back up. This change fixes the bug.
|
||||
|
||||
* Renamed --strip-path to --strip-components for consistency with
|
||||
the GNU convention.
|
||||
|
||||
* Skipping archive members is sped up if the archive media supports
|
||||
seeks.
|
||||
|
||||
* Restore script starts restoring only if it is given --all (-a) option,
|
||||
or some patterns. This is to prevent accidental restores.
|
||||
|
||||
* `tar --verify' prints a warning if during archive creation some of
|
||||
the file names had their prefixes stripped off.
|
||||
|
||||
* New option --exclude-caches instructs tar to exclude cache directories
|
||||
automatically on archive creation. Cache directories are those
|
||||
containing a standardized tag file, as specified at:
|
||||
|
||||
http://www.brynosaurus.com/cachedir/spec.html
|
||||
|
||||
* New configure option --with-rmt allows to specify full path name to
|
||||
the `rmt' utility. This supersedes DEFAULT_RMT_COMMAND variable
|
||||
introduced in version 1.14
|
||||
|
||||
* New configure variable DEFAULT_RMT_DIR allows to specify the directory
|
||||
where to install `rmt' utility. This is necessary since modifying
|
||||
--libexecdir as was suggested for version 1.14 produced a side effect: it
|
||||
also modified installation prefix for backup scripts (if
|
||||
--enable-backup-scripts was given).
|
||||
|
||||
* Bug fixes:
|
||||
** Fixed flow in recognizing files to be included in incremental dumps.
|
||||
** Correctly recognize sparse archive members when used with -T option.
|
||||
** GNU multivolume headers cannot store filenames longer than 100 characters.
|
||||
Do not allow multivolume archives to begin with such filenames.
|
||||
** If a member with link count > 2 was stored in the archive twice,
|
||||
previous versions of tar were not able to extract it, since they
|
||||
were trying to link the file to itself, which always failed and
|
||||
lead to removing the already extracted copy. Preserve the first
|
||||
extracted copy in such cases.
|
||||
** Restore script was passing improper argument to tar --listed option (which
|
||||
didn't affect the functionality, but was logically incorrect).
|
||||
** Fixed verification of created archives.
|
||||
** Fixed unquoting of file names containing backslash escapes (previous
|
||||
versions failed to recognize \a and \v).
|
||||
** When attempting to delete a non-existing member from the archive, previous
|
||||
versions of tar used to overwrite last archive block with zeroes.
|
||||
|
||||
|
||||
version 1.14 - Sergey Poznyakoff, 2004-05-11
|
||||
|
||||
* Added support for POSIX.1-2001 and ustar archive formats.
|
||||
@@ -20,28 +332,28 @@ version 1.14 - Sergey Poznyakoff, 2004-05-11
|
||||
option is now the default; use --no-overwrite-dir if you prefer
|
||||
the previous default behavior.
|
||||
|
||||
* The semantics of -o option is changed. When extracting, it
|
||||
does the same as --no-same-owner GNU tar option. This is compatible
|
||||
with UNIX98 tar. Otherwise, its effect is the same as that of
|
||||
--old-archive option. This latter is deprecated and will be removed
|
||||
* The semantics of -o option is changed. When extracting, it
|
||||
does the same as --no-same-owner GNU tar option. This is compatible
|
||||
with UNIX98 tar. Otherwise, its effect is the same as that of
|
||||
--old-archive option. This latter is deprecated and will be removed
|
||||
in future.
|
||||
|
||||
* New option --check-links prints a message if not all links are dumped
|
||||
for a file being archived. This corresponds to the UNIX98 -l option.
|
||||
for a file being archived. This corresponds to the UNIX98 -l option.
|
||||
The current semantics of the -l option is retained for compatibility
|
||||
with previous releases, however such usage is strongly deprecated as
|
||||
the option will change to its UNIX98 semantics in the future releases.
|
||||
|
||||
* New option --occurrence[=N] can be used in conjunction with one of
|
||||
* New option --occurrence[=N] can be used in conjunction with one of
|
||||
the subcommands --delete, --diff, --extract or --list when a list of
|
||||
files is given either on the command line or via -T option. This
|
||||
files is given either on the command line or via -T option. This
|
||||
option instructs tar to process only the Nth occurrence of each named
|
||||
file. N defaults to 1, so `tar -x -f archive --occurrence filename'
|
||||
file. N defaults to 1, so `tar -x -f archive --occurrence filename'
|
||||
extracts the first occurrence of `filename' from `archive'
|
||||
and terminates without scanning to the end of the archive.
|
||||
|
||||
* New option --pax-option allows to control the handling of POSIX
|
||||
keywords in `pax' extended headers. It is equivalent to `pax'
|
||||
keywords in `pax' extended headers. It is equivalent to `pax'
|
||||
-o option.
|
||||
|
||||
* --incremental and --listed-incremental options work correctly on
|
||||
@@ -53,18 +365,18 @@ option is given to configure.
|
||||
|
||||
* By default tar searches "rmt" utility in "$prefix/libexec/rmt",
|
||||
which is consistent with the location where the version of "rmt"
|
||||
included in the package is installed. Previous versions of tar
|
||||
used "/etc/rmt". To install "rmt" to its traditional location,
|
||||
run configure with option --libexecdir=/etc. Otherwise, if you
|
||||
included in the package is installed. Previous versions of tar
|
||||
used "/etc/rmt". To install "rmt" to its traditional location,
|
||||
run configure with option --libexecdir=/etc. Otherwise, if you
|
||||
already have rmt installed and wish to use it, instead of the
|
||||
shipped in version, set the variable DEFAULT_RMT_COMMAND to
|
||||
the full path name of the utility, e.g. ./configure
|
||||
the full path name of the utility, e.g., ./configure
|
||||
DEFAULT_RMT_COMMAND=/etc/rmt.
|
||||
|
||||
Notice also that the full path name of the "rmt" utility to
|
||||
use can be set at runtime, by giving option --rmt-command to
|
||||
tar.
|
||||
|
||||
tar.
|
||||
|
||||
* Removed obsolete command line options:
|
||||
** --absolute-paths superseded by --absolute-names
|
||||
** --block-compress is not needed any longer
|
||||
@@ -77,32 +389,38 @@ tar.
|
||||
* New message translations fi (Finnish), gl (Galician), hr (Croatian),
|
||||
hu (Hungarian), ms (Malaysian), nb (Norwegian), ro (Romanian), sk
|
||||
(Slovak), zh_CN (Chinese simplified), zh_TW (Chinese traditional).
|
||||
The code 'no' for Norwegian (Bokm<EFBFBD>l) has been withdrawn; use 'nb' instead.
|
||||
The code 'no' for Norwegian (Bokmål) has been withdrawn; use 'nb' instead.
|
||||
|
||||
* Bug fixes.
|
||||
|
||||
|
||||
version 1.13.25 - Paul Eggert, 2001-09-26
|
||||
|
||||
* Bug fixes.
|
||||
|
||||
|
||||
version 1.13.24 - Paul Eggert, 2001-09-22
|
||||
|
||||
* New option --overwrite-dir.
|
||||
* Fixes for buffer overrun, porting, and copyright notice problems.
|
||||
* The message translations for Korean are available again.
|
||||
|
||||
|
||||
version 1.13.23 - Paul Eggert, 2001-09-13
|
||||
|
||||
* Bug, porting, and copyright notice fixes.
|
||||
|
||||
|
||||
version 1.13.22 - Paul Eggert, 2001-08-29
|
||||
|
||||
* Bug fixes.
|
||||
|
||||
|
||||
version 1.13.21 - Paul Eggert, 2001-08-28
|
||||
|
||||
* Porting and copyright notice fixes.
|
||||
|
||||
|
||||
version 1.13.20 - Paul Eggert, 2001-08-27
|
||||
|
||||
* Some bugs were fixed:
|
||||
@@ -129,6 +447,7 @@ version 1.13.20 - Paul Eggert, 2001-08-27
|
||||
The translation for Korean has been withdrawn due to encoding errors.
|
||||
It will be reissued once those are fixed.
|
||||
|
||||
|
||||
version 1.13.19 - Paul Eggert, 2001-01-13
|
||||
|
||||
* The -I option has been withdrawn, as it was buggy and confusing.
|
||||
@@ -137,6 +456,7 @@ version 1.13.19 - Paul Eggert, 2001-01-13
|
||||
* With an option like -N DATE, if DATE starts with "/" or ".", it is taken
|
||||
to be a file name; the last-modified time of that file is used as the date.
|
||||
|
||||
|
||||
version 1.13.18 - Paul Eggert, 2000-10-29
|
||||
|
||||
* Some security problems have been fixed. `tar -x' now modifies only
|
||||
@@ -164,14 +484,16 @@ version 1.13.18 - Paul Eggert, 2000-10-29
|
||||
|
||||
* This version of tar works best with GNU gzip test version 1.3 or later.
|
||||
Please see <ftp://alpha.gnu.org/gnu/gzip/>.
|
||||
|
||||
|
||||
* `tar --delete -f -' now works again.
|
||||
|
||||
|
||||
version 1.13.17 - Paul Eggert, 2000-01-07.
|
||||
|
||||
* `tar --delete -f -' is no longer allowed; it was too buggy.
|
||||
* Diagnostic messages have been made more regular and consistent.
|
||||
|
||||
|
||||
version 1.13.16 - Paul Eggert, 1999-12-13.
|
||||
|
||||
* By default, tar now refuses to overwrite an existing file when
|
||||
@@ -194,7 +516,7 @@ version 1.13.16 - Paul Eggert, 1999-12-13.
|
||||
when extracting, and warns about such file names when creating an archive.
|
||||
To enable the old behavior, use the -P or --absolute-names option.
|
||||
|
||||
* Tar now handles file names with multibyte encodings (e.g. UTF-8, Shift-JIS)
|
||||
* Tar now handles file names with multibyte encodings (e.g., UTF-8, Shift-JIS)
|
||||
correctly. It relies on the mbrtowc function to handle multibyte characters.
|
||||
|
||||
* The file generated by -g or --listed-incremental now uses a format
|
||||
@@ -209,23 +531,26 @@ version 1.13.16 - Paul Eggert, 1999-12-13.
|
||||
`quoted like this' (in the default C locale) or are followed by
|
||||
colon, newline, or space, depending on context. Unprintable
|
||||
characters are escaped with a C-like backslash conventions.
|
||||
Terminating characters (e.g. close-quote, colon, newline)
|
||||
Terminating characters (e.g., close-quote, colon, newline)
|
||||
are also escaped as needed.
|
||||
|
||||
* tar now ignores socket files when creating an archive.
|
||||
Previously tar archived sockets as fifos, which caused problems.
|
||||
|
||||
|
||||
version 1.13.15 - Paul Eggert, 1999-12-03.
|
||||
|
||||
* If a file's ctime changes when being archived, report an error.
|
||||
Previously tar looked at mtime, which missed some errors.
|
||||
|
||||
|
||||
version 1.13.14 - Paul Eggert, 1999-11-07.
|
||||
|
||||
* New translations ja, pt_BR.
|
||||
* New options --help and --version for rmt.
|
||||
* Ignore Solaris door files when creating an archive.
|
||||
|
||||
|
||||
version 1.13.13 - Paul Eggert, 1999-10-11.
|
||||
|
||||
* Invalid headers in tar files now elicit errors, not just warnings.
|
||||
@@ -233,6 +558,7 @@ version 1.13.13 - Paul Eggert, 1999-10-11.
|
||||
* If you specify an invalid date, `tar' now substitutes (time_t) -1.
|
||||
* `configure --with-dmalloc' is no longer available.
|
||||
|
||||
|
||||
version 1.13.12 - Paul Eggert, 1999-09-24.
|
||||
|
||||
* `tar' now supports hard links to symbolic links.
|
||||
@@ -263,7 +589,7 @@ version 1.13.12 - Paul Eggert, 1999-09-24.
|
||||
|
||||
* Some diagnostics have been reworded for consistency.
|
||||
|
||||
|
||||
|
||||
version 1.13.11 - Paul Eggert, 1999-08-23.
|
||||
|
||||
* The short name of the --bzip option has been changed to -I,
|
||||
@@ -283,14 +609,14 @@ version 1.13.11 - Paul Eggert, 1999-08-23.
|
||||
numeric UTC offsets like `-0500' instead of abbreviations like
|
||||
`EST', as abbreviations are not standardized and are ambiguous.
|
||||
|
||||
|
||||
|
||||
version 1.13.10 - Paul Eggert, 1999-08-20.
|
||||
|
||||
* `tar' now uses signed base-64 when outputting header values that are
|
||||
out of the range of the standard unsigned base-8 format. [This
|
||||
change was superseded in 1.13.12, described above.]
|
||||
|
||||
|
||||
|
||||
version 1.13.9 - Paul Eggert, 1999-08-18.
|
||||
|
||||
* `tar' now writes two zero blocks at end-of-archive instead of just one.
|
||||
@@ -302,14 +628,14 @@ version 1.13.9 - Paul Eggert, 1999-08-18.
|
||||
* `tar' now reads buggy tar files that have a null byte at the start of a
|
||||
numeric header field.
|
||||
|
||||
|
||||
|
||||
version 1.13.8 - Paul Eggert, 1999-08-16.
|
||||
|
||||
* For compatibility with traditional `tar', intermediate directories
|
||||
created automatically by root are no longer given the uid and gid of
|
||||
the original file or directory.
|
||||
|
||||
|
||||
|
||||
version 1.13.7 - Paul Eggert, 1999-08-14.
|
||||
|
||||
* --listed-incremental and --newer are now incompatible options.
|
||||
@@ -319,7 +645,7 @@ version 1.13.7 - Paul Eggert, 1999-08-14.
|
||||
|
||||
* --diff without --absolute-names no longer falls back on absolute names.
|
||||
|
||||
|
||||
|
||||
version 1.13.6 - Paul Eggert, 1999-08-11.
|
||||
|
||||
* An --exclude pattern containing / now excludes a file only if it matches an
|
||||
@@ -328,7 +654,7 @@ version 1.13.6 - Paul Eggert, 1999-08-11.
|
||||
|
||||
* The protocol for talking to rmt has been extended slightly.
|
||||
Open flags are now communicated in symbolic format as well as numeric.
|
||||
The symbolic format (e.g. "O_WRONLY|O_CREAT|O_TRUNC") is for portability
|
||||
The symbolic format (e.g., "O_WRONLY|O_CREAT|O_TRUNC") is for portability
|
||||
when rmt is operating on a different operating system from tar.
|
||||
The numeric format is retained, and rmt uses it if symbolic format is absent,
|
||||
for backward compatibility with older versions of tar and rmt.
|
||||
@@ -346,37 +672,37 @@ version 1.13.6 - Paul Eggert, 1999-08-11.
|
||||
|
||||
* New option -y or --bzip2 for bzip2 compression, by popular request.
|
||||
|
||||
|
||||
|
||||
version 1.13.5 - Paul Eggert, 1999-07-20.
|
||||
|
||||
* Do the delayed updates of file metadata even after a fatal error.
|
||||
|
||||
|
||||
|
||||
version 1.13.4 - Paul Eggert, 1999-07-20.
|
||||
|
||||
* Do not chmod unless we are root or the -p option was given;
|
||||
this matches historical practice.
|
||||
|
||||
|
||||
|
||||
version 1.13.3 - Paul Eggert, 1999-07-16.
|
||||
|
||||
* A path name is excluded if any of its file name components matches an
|
||||
excluded pattern, even if the path name was specified on the command line.
|
||||
Also see 1.13.6 for later changes in this area.
|
||||
|
||||
|
||||
|
||||
version 1.13.2 - Paul Eggert, 1999-07-14.
|
||||
|
||||
* Bug reporting address changed to <bug-tar@gnu.org>.
|
||||
|
||||
|
||||
|
||||
version 1.13.1 - Paul Eggert, 1999-07-12.
|
||||
|
||||
* Bug fixes only.
|
||||
|
||||
version 1.13 - Paul Eggert, 1999-07-08.
|
||||
|
||||
* Support for large files, e.g. files larger than 2 GB on many 32-bit hosts.
|
||||
* Support for large files, e.g., files larger than 2 GB on many 32-bit hosts.
|
||||
Also, support for larger uids, device ids, etc.
|
||||
* Many bug fixes and porting fixes.
|
||||
* This release is only for fixes. A more ambitious test release,
|
||||
@@ -567,14 +893,14 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 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,
|
||||
@@ -584,10 +910,14 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
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:
|
||||
|
||||
294
PORTS
294
PORTS
@@ -1,20 +1,157 @@
|
||||
* Ports of GNU tar and other tars -*- outline -*-
|
||||
Ports of GNU tar and other tars
|
||||
See the end of file for copying conditions.
|
||||
|
||||
Many entries in this file are out of date, unfortunately.
|
||||
* Introduction
|
||||
|
||||
Most entries in this file are out of date, unfortunately. Such
|
||||
entries are marked with an `X'. Run grep '^\*\*[^X]' PORTS to
|
||||
extract valid entries.
|
||||
|
||||
Please write bug-tar@gnu.org if you are aware of various ports of GNU tar
|
||||
to non-GNU and non-Unix systems not listed here, or for corrections.
|
||||
Please provide the goal system, a complete and stable URL, the maintainer
|
||||
name and address, the tar version used as a base, and your comments.
|
||||
|
||||
.* Copyright notice
|
||||
* GNU/Linux and Unix
|
||||
|
||||
Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc.
|
||||
** Star is a tape archiver similar to tar.
|
||||
<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/star.html>
|
||||
|
||||
* Amiga
|
||||
|
||||
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/GNUtar-1.11.8.lha
|
||||
maintained by Enrico Forestieri <enrico@com.unipr.it>
|
||||
Based on tar 1.11.8.
|
||||
|
||||
**X ftp://ftp.ninemoons.com/pub/ade/current/amiga-bin/tar-1.11.8-bin.lha
|
||||
maintained by the ADE group <fnf@fishpond.ninemoons.com>
|
||||
Based on tar 1.11.8, needs ixemul.library.
|
||||
|
||||
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/gnutar.lha
|
||||
maintained by <mscheler@wuarchive.wustl.edu>
|
||||
|
||||
* DEC alpha (NT)
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
|
||||
* DEC VAX (VMS)
|
||||
|
||||
**X http://www.lp.se/free/vmstar/
|
||||
maintained by Richard Levitte <levitte@lp.se>
|
||||
This is not GNU tar, but a separate implementation.
|
||||
|
||||
** maintained by William Bader <william@nscs.fast.net>
|
||||
For V4.7. Based on an old PDtar. Requires compatible shared libraries
|
||||
to run V5 or V6 executables.
|
||||
|
||||
* IBM/PC (DV/X)
|
||||
|
||||
**X ftp://qdeck.com/ (?)
|
||||
maintained by David Ronis <ronis@gibbs.chem.mcgill.ca>
|
||||
For Desqview/X. Everything works besides compression. Copy of hacked
|
||||
sources available, some of DV/X's programmer's library also needed.
|
||||
|
||||
* IBM/PC (MSDOS)
|
||||
|
||||
**X http://www.simtel.net/simtel.net/
|
||||
http://www.leo.org/pub/comp/platforms/pc/gnuish (Germany)
|
||||
ftp://ftp.simtel.net/simtelnet/gnu
|
||||
ftp://ftp.leo.org/pub/comp/platforms/pc/gnuish
|
||||
maintained by Darrel Hankerson <hankedr@mail.auburn.edu>
|
||||
You get many GNU tools, not only `tar'. The GNUish project is described
|
||||
in `gnuish_t.htm'.
|
||||
|
||||
** The DJGPP development tools also include some `tar' utilities.
|
||||
|
||||
**X ftp://ftp.mcs.com/mcsnet.users/les/dos-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Based on tar 1.11.2. Support for SCSI (via ASPI) and network (rsh over
|
||||
packet driver). No support for win95 long file names.
|
||||
|
||||
**X ftp://ftp.wu-wien.ac.at/pub/src/PCmisc/aspi-tar/*
|
||||
maintained by Christoph Splittgerber <chris@orion.sdata.de>
|
||||
Based on tar 1.10. Support for SCSI (via ASPI).
|
||||
|
||||
**X ftp://wuarchive (?)
|
||||
Several DOS version based on PDtar. John Gilmore <gnu@toad.com> says
|
||||
he has copies of several vintages saved.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.exe
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.taz
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.zip
|
||||
|
||||
**X ftp://ftp.cdrom.com/.4/os2/archiver/tar.zip
|
||||
Based on PDtar.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
**X http://people.darmstadt.netsurf.de/tst/tar.htm
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
This is not a `tar' port, but an index of them.
|
||||
|
||||
* IBM/PC (OS/2)
|
||||
|
||||
**X http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtar254.zip
|
||||
http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtak254.zip
|
||||
maintained by Andreas Kaiser <Andreas.Kaiser@stuttgart.netsurf.de>
|
||||
Version 2.54. Based on tar 1.10. The second archive contains SCSI
|
||||
drivers (DAT streamers notably) and rmt-type programs.
|
||||
|
||||
* IBM/PC (Win32: Windows 95, NT 3.5 or NT 4.0)
|
||||
|
||||
**X ftp://ftp.cygnus.com:~ftp/pub/sac/win32/usersrc/*
|
||||
maintained by Cygnus
|
||||
GNU-Win32 B17.1 distribution. Download all files, `cat' them together,
|
||||
and `untar' the result. You get many GNU tools, not only `tar'.
|
||||
Based on tar 1.11.2.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
* IBM/PC (Windows 3.1)
|
||||
|
||||
**X ftp://ftp.mcs.com/mcsnet.users/les/win-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Support for network (rsh over winsock). No support for win95 long
|
||||
file names.
|
||||
|
||||
**X ftp://ftp.gamesdomain.ru/.1/os/windows/programr/tar.zip
|
||||
Based on GNU tar 1.11.2.
|
||||
|
||||
* Macintosh
|
||||
|
||||
** Paulo Abreu (paulotex at yahoo dot com) did a
|
||||
limited port of GNU tar to Darwin, with support for resource forks
|
||||
and finder info, but this no longer seems to be available.
|
||||
|
||||
** There is a tar in Stuffit Expander which is available many places and
|
||||
comes with MacOS. It creates some spurious files but works on average.
|
||||
|
||||
** There is an excellent GNU tar bundled in Tenon MachTen, but it does not
|
||||
seem to be available separately.
|
||||
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 1999, 2001, 2003, 2004, 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,
|
||||
@@ -24,142 +161,13 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
.* GNU/Linux and Unix
|
||||
|
||||
. + Star is a tape archiver similar to tar.
|
||||
<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/star.html>
|
||||
|
||||
.* Amiga
|
||||
|
||||
. + ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/GNUtar-1.11.8.lha
|
||||
maintained by Enrico Forestieri <enrico@com.unipr.it>
|
||||
Based on tar 1.11.8.
|
||||
|
||||
. + [This link seems to be dead:]
|
||||
ftp://ftp.ninemoons.com/pub/ade/current/amiga-bin/tar-1.11.8-bin.lha
|
||||
maintained by the ADE group <fnf@fishpond.ninemoons.com>
|
||||
Based on tar 1.11.8, needs ixemul.library.
|
||||
|
||||
. + ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/gnutar.lha
|
||||
maintained by <mscheler@wuarchive.wustl.edu>
|
||||
|
||||
.* DEC alpha (NT)
|
||||
|
||||
. + [This link seems to be dead:]
|
||||
ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
|
||||
.* DEC VAX (VMS)
|
||||
|
||||
. + [This link seems to be dead:]
|
||||
http://www.lp.se/free/vmstar/
|
||||
maintained by Richard Levitte <levitte@lp.se>
|
||||
This is not GNU tar, but a separate implementation.
|
||||
|
||||
. + maintained by William Bader <william@nscs.fast.net>
|
||||
For V4.7. Based on an old PDtar. Requires compatible shared libraries
|
||||
to run V5 or V6 executables.
|
||||
|
||||
.* IBM/PC (DV/X)
|
||||
|
||||
. + ftp://qdeck.com/ (?)
|
||||
maintained by David Ronis <ronis@gibbs.chem.mcgill.ca>
|
||||
For Desqview/X. Everything works besides compression. Copy of hacked
|
||||
sources available, some of DV/X's programmer's library also needed.
|
||||
|
||||
.* IBM/PC (MSDOS)
|
||||
|
||||
. + http://www.simtel.net/simtel.net/
|
||||
http://www.leo.org/pub/comp/platforms/pc/gnuish (Germany)
|
||||
ftp://ftp.simtel.net/simtelnet/gnu
|
||||
ftp://ftp.leo.org/pub/comp/platforms/pc/gnuish
|
||||
maintained by Darrel Hankerson <hankedr@mail.auburn.edu>
|
||||
You get many GNU tools, not only `tar'. The GNUish project is described
|
||||
in `gnuish_t.htm'.
|
||||
|
||||
. + The DJGPP development tools also include some `tar' utilities.
|
||||
|
||||
. + ftp://ftp.mcs.com/mcsnet.users/les/dos-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Based on tar 1.11.2. Support for SCSI (via ASPI) and network (rsh over
|
||||
packet driver). No support for win95 long file names.
|
||||
|
||||
. + ftp://ftp.wu-wien.ac.at:pub/src/PCmisc/aspi-tar/*
|
||||
maintained by Christoph Splittgerber <chris@orion.sdata.de>
|
||||
Based on tar 1.10. Support for SCSI (via ASPI).
|
||||
|
||||
. + ftp://wuarchive (?)
|
||||
Several DOS version based on PDtar. John Gilmore <gnu@toad.com> says
|
||||
he has copies of several vintages saved.
|
||||
|
||||
. + ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.exe
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.taz
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.zip
|
||||
|
||||
. + ftp://ftp.cdrom.com/.4/os2/archiver/tar.zip
|
||||
Based on PDtar.
|
||||
|
||||
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
. + http://people.darmstadt.netsurf.de/tst/tar.htm
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
This is not a `tar' port, but an index of them.
|
||||
|
||||
.* IBM/PC (OS/2)
|
||||
|
||||
. + http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtar254.zip
|
||||
http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtak254.zip
|
||||
maintained by Andreas Kaiser <Andreas.Kaiser@stuttgart.netsurf.de>
|
||||
Version 2.54. Based on tar 1.10. The second archive contains SCSI
|
||||
drivers (DAT streamers notably) and rmt-type programs.
|
||||
|
||||
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
.* IBM/PC (Win32: Windows 95, NT 3.5 or NT 4.0)
|
||||
|
||||
. + ftp://ftp.cygnus.com:~ftp/pub/sac/win32/usersrc/*
|
||||
maintained by Cygnus
|
||||
GNU-Win32 B17.1 distribution. Download all files, `cat' them together,
|
||||
and `untar' the result. You get many GNU tools, not only `tar'.
|
||||
Based on tar 1.11.2.
|
||||
|
||||
. + ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
. + ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
.* IBM/PC (Windows 3.1)
|
||||
|
||||
. + ftp://ftp.mcs.com/mcsnet.users/les/win-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Support for network (rsh over winsock). No support for win95 long
|
||||
file names.
|
||||
|
||||
. + ftp://ftp.gamesdomain.ru/.1/os/windows/programr/tar.zip
|
||||
Based on GNU tar 1.11.2.
|
||||
|
||||
.* Macintosh
|
||||
|
||||
. + Paulo Abreu (paulotex at yahoo dot com) did a
|
||||
limited port of GNU tar to Darwin, with support for resource forks
|
||||
and finder info, but this no longer seems to be available.
|
||||
|
||||
. + There is a tar in Stuffit Expander which is available many places and
|
||||
comes with MacOS. It creates some spurious files but works on average.
|
||||
|
||||
. + There is an excellent GNU tar bundled in Tenon MachTen, but it does not
|
||||
seem to be available separately.
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
|
||||
26
README
26
README
@@ -48,14 +48,22 @@ in the environment before configuring (the behavior of `-[0-7]' or
|
||||
|
||||
** Selecting full pathname of the "rmt" binary.
|
||||
|
||||
Previous versions of tar always looked for "rmt" binary using
|
||||
hardcoded path "/etc/rmt". However, the "rmt" program included
|
||||
Previous versions of tar always looked for "rmt" binary in the
|
||||
directory "/etc/rmt". However, the "rmt" program included
|
||||
in the distribution was installed under "$prefix/libexec/rmt".
|
||||
To fix this discrepancy, tar now looks for "$prefix/libexec/rmt".
|
||||
If you do not want this behavior, specify full path name of
|
||||
"rmt" binary using DEFAULT_RMT_COMMAND variable, e.g.:
|
||||
"rmt" binary using DEFAULT_RMT_DIR variable, e.g.:
|
||||
|
||||
./configure DEFAULT_RMT_COMMAND=/etc/rmt
|
||||
./configure DEFAULT_RMT_DIR=/etc
|
||||
|
||||
If you already have a copy of "rmt" installed and wish to use it
|
||||
instead of the version supplied with the distribution, use --with-rmt
|
||||
option:
|
||||
|
||||
./configure --with-rmt=/etc/rmt
|
||||
|
||||
This will also disable building the included version of rmt.
|
||||
|
||||
** Installing backup scripts.
|
||||
|
||||
@@ -70,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
|
||||
|
||||
@@ -215,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,
|
||||
@@ -231,8 +239,8 @@ and share your findings by writing to <bug-tar@gnu.org>.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
Local Variables:
|
||||
|
||||
58
README-alpha
58
README-alpha
@@ -5,44 +5,55 @@ Please send comments and problem reports to <bug-tar@gnu.org>.
|
||||
|
||||
If you have taken the sources from CVS you will need the following
|
||||
packages (or later) to build GNU tar. We don't make any extra effort
|
||||
to accommodate older versions of these packages. If we discover that
|
||||
newer versions are needed to bootstrap, we'll update the version
|
||||
numbers in this list.
|
||||
to accommodate older versions of these packages, so please make sure
|
||||
that you have the latest stable version.
|
||||
|
||||
autoconf 2.59
|
||||
automake 1.8
|
||||
bison 1.875
|
||||
gettext 0.12.1
|
||||
m4 1.4
|
||||
wget 1.7
|
||||
- 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/>
|
||||
- M4 <http://www.gnu.org/software/m4/>
|
||||
- Texinfo <http://www.gnu.org/software/texinfo>
|
||||
- Wget <http://www.gnu.org/software/wget/>
|
||||
|
||||
For GNU m4 1.4, we recommend also installing the `translit' patch; see
|
||||
Debian bug 211477 <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=211477>.
|
||||
This patch is bundled into Debian m4 1.4-17 or later.
|
||||
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.
|
||||
|
||||
Before building the package, run "bootstrap". It obtains various
|
||||
additional files from the CVS repository and the Translation Project
|
||||
site and prepares the source directory for building.
|
||||
|
||||
When run without arguments, bootstrap will try to obtain gnulib files
|
||||
from CVS repository on savannah using anonymous SSH access. Then, it
|
||||
will fetch the po files from tar page at Translation Project, and,
|
||||
finally, it will start autoconfiguration process. Simply running
|
||||
it without arguments should do in most cases. Several options
|
||||
allow to control the behavior of bootstrap:
|
||||
|
||||
When run without arguments, bootstrap will try to obtain gnulib and
|
||||
paxutils files from their corresponding CVS repositories on Savannah
|
||||
using anonymous SSH access. Then, it will fetch the po files from tar
|
||||
page at Translation Project, and, finally, it will start autoconfiguration
|
||||
process. Simply running it without arguments should do in most cases.
|
||||
Several options allow to control the behavior of bootstrap:
|
||||
|
||||
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
|
||||
sources reside. Use this if you already
|
||||
have gnulib sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
|
||||
--paxutils-srcdir=DIRNAME Specify the local directory where paxutils
|
||||
sources reside. Use this if you already
|
||||
have paxutils sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
them again.
|
||||
|
||||
--cvs-auth=METHOD Set the CVS access method used for downloading
|
||||
gnulib files. METHOD is one of the keywords
|
||||
accepted by cvs -d option (see info cvs
|
||||
repository).
|
||||
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the gnulib repository.
|
||||
|
||||
--no-po Do not download po files.
|
||||
|
||||
Notice also that when using CVS authentication method "ext", bootstrap
|
||||
@@ -51,13 +62,13 @@ some other value.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2001, 2003, 2004 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,
|
||||
@@ -67,6 +78,5 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
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.
|
||||
68
THANKS
68
THANKS
@@ -4,8 +4,8 @@ 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<EFBFBD>§ois
|
||||
Pinard and Paul Eggert.
|
||||
Jay Fenlason and Joy Kendall, and was maintained in turn by François
|
||||
Pinard, Paul Eggert and Sergey Poznyakoff.
|
||||
|
||||
Many people further contributed to GNU tar by reporting problems,
|
||||
suggesting various improvements or submitting actual code. Here is a
|
||||
@@ -13,6 +13,7 @@ list of these people. Help me keep it complete and exempt of errors.
|
||||
See various ChangeLogs for a detailed description of contributions.
|
||||
|
||||
Aage Robeck aagero@ifi.uio.no
|
||||
Adye, TJ (Tim) T.J.Adye@rl.ac.uk
|
||||
Akiko Matsushita matusita@sra.co.jp
|
||||
Alan Bawden Alan@lcs.mit.edu
|
||||
Alan Cox alan@cymru.net
|
||||
@@ -32,7 +33,7 @@ Andreas Haumer andreas@vlsivie.tuwien.ac.at
|
||||
Andreas Jaeger aj@arthur.pfalz.de
|
||||
Andreas Koppenhoefer koppenh@trick.informatik.uni-stuttgart.de
|
||||
Andreas Reuter ar205@bonzo.geowiss.nat.tu-bs.de
|
||||
Andreas Schuldei andreas@schuldei.org
|
||||
Andreas Schuldei andreas@schuldei.org
|
||||
Andreas Schwab schwab@issan.informatik.uni-dortmund.de
|
||||
Andrew A. Ivanov ivanov@mics.msu.su
|
||||
Andrew J. Schorr schorr@ead.dsa.com
|
||||
@@ -52,6 +53,7 @@ Bela Lubkin filbo@armory.com
|
||||
Ben A. Mesander ben@piglet.cr.usgs.gov
|
||||
Benedikt Stockebrand benedikt@devnull.ruhr.de
|
||||
Bennett Todd bet@mordor.com
|
||||
Benno Schulenberg benno@nietvergeten.nl
|
||||
Benny Holmgren benny@hgs.se
|
||||
Bernard Chen bern@cs.ucla.edu
|
||||
Bernard Derval derval@iro.umontreal.ca
|
||||
@@ -67,6 +69,7 @@ Brian R. Smith brian@cygnus.com
|
||||
Bruce Evans bde@runx.oz.au
|
||||
Bruce Jerrick bruce@cse.ogi.edu
|
||||
Bruno Haible haible@ilog.fr
|
||||
Bryan Ford baford@mit.edu
|
||||
Bryant Fujimoto fujimoto@denali.chem.washington.edu
|
||||
Burkhard Plache plache@krusty.optimax.ns.ca
|
||||
Calvin Cliff cliff@trifid.astro.ucla.edu
|
||||
@@ -89,7 +92,7 @@ Chris Metcalf metcalf@catfish.lcs.mit.edu
|
||||
Chris Ransom chris@quests.com
|
||||
Christian Callsen Christian.Callsen@eng.sun.com
|
||||
Christian Kirsch ck@held.mind.de
|
||||
Christian Laubscher <christian.laubscher@tiscalinet.ch>
|
||||
Christian Laubscher christian.laubscher@tiscalinet.ch
|
||||
Christian T. Dum ctd@mpe-garching.mpg.de
|
||||
Christian von Roques roques@pond.sub.org
|
||||
Christoph Litauer litauer@mailhost.uni-koblenz.de
|
||||
@@ -117,6 +120,7 @@ Danny R. Johnston danny@cs.weber.edu
|
||||
Dave Barr barr@math.psu.edu
|
||||
Dave Gentzel gentzel@nova.enet.dec.com
|
||||
Dave Gregorich dtg@ipac.caltech.edu
|
||||
David Brown davidb@davidb.org
|
||||
David J. MacKenzie djm@uunet.uu.net
|
||||
David Johnson David.W.Johnson@colorado.edu
|
||||
David K. Drum ccdavid@mizzou1.missouri.edu
|
||||
@@ -154,6 +158,7 @@ Elmar Heeb heeb@itp.ethz.ch
|
||||
Elmer Fittery elmerf@ptw.com
|
||||
Eric Backus ericb@lsid.hp.com
|
||||
Eric Benson eb@amazon.com
|
||||
Eric Blake ebb9@byu.net
|
||||
Eric M. Boehm Eric.M.Boehm@optimumtech.com
|
||||
Eric Norum eric@ee.ualberta.ca
|
||||
Erich Stefan Boleyn erich@uruk.org
|
||||
@@ -162,9 +167,10 @@ Erik D. Frederick edf@deckard.mc.duke.edu
|
||||
Esa Karell karell@cs.helsinki.fi
|
||||
Ezra Peisach epeisach@mit.edu
|
||||
Fabio d'Alessi cars@civ.bio.unipd.it
|
||||
Frank Heckenbach frank@g-n-u.de
|
||||
Frank Koenen koenfr@lidp.com
|
||||
Franz-Werner Gergen gergen@edvulx.mpi-stuttgart.mpg.de
|
||||
Fran<EFBFBD>§ois Pinard pinard@iro.umontreal.ca
|
||||
François Pinard pinard@iro.umontreal.ca
|
||||
Fritz Elfert fritz@fsun.triltsch.de
|
||||
George Chyu gschyu@ccgate.dp.beckman.com
|
||||
Gerben Wierda gerben@rna.indiv.nluug.nl
|
||||
@@ -178,12 +184,16 @@ Greg Chung gchung@caip.rutgers.edu
|
||||
Greg Hudson ghudson@mit.edu
|
||||
Greg Maples greg@clari.net
|
||||
Greg McGary gkm@cstone.net
|
||||
G<EFBFBD>¶ran Uddeborg gvran@uddeborg.pp.se
|
||||
Greg Schafer gschafer@zip.com.au
|
||||
Göran Uddeborg gvran@uddeborg.pp.se
|
||||
Gürkan Karaman karaman@dssgmbh.de
|
||||
Hans Guerth 100664.3101@compuserve.com
|
||||
Harald K<>¶nig koenig@tat.physik.uni-tuebingen.de
|
||||
Hansjörg Lipp hjlipp@web.de
|
||||
Harald König koenig@tat.physik.uni-tuebingen.de
|
||||
Harald Milz hm@seneca.ix.de
|
||||
Heiko Schinke mdqac@biochemtech.uni-halle.de
|
||||
Heiko Schlichting heiko@fu-berlin.de
|
||||
Helmut Waitzmann Helmut.Waitzmann@web.de
|
||||
Henrik Bakman hb@csd.uu.se
|
||||
Hernan Prieto Schmidt hernan@pea.usp.br
|
||||
Hiroyuki Bessho bsh@grotto.iijnet.or.jp
|
||||
@@ -193,6 +203,7 @@ Hunyue Yau hunyue.yau@picksys.com
|
||||
Ian Jackson ijackson@gnu.org
|
||||
Ian Lance Taylor ian@cygnus.com
|
||||
Ian T. Zimmerman itz@crl.com
|
||||
Ian Turner ian@zmanda.com
|
||||
Indra Singhal indra@synoptics.com
|
||||
J. Dean Brock brock@cs.unca.edu
|
||||
J.J. Bailey jjb@jagware.bcc.com
|
||||
@@ -209,6 +220,7 @@ Jan Djarv jan.djarv@mbox200.swipnet.se
|
||||
Janice Burton r06a165@bcc25.kodak.com
|
||||
Janne Snabb snabb@niksula.hut.fi
|
||||
Jason R. Mastaler jason@webmaster.net
|
||||
Jason Armistead Jason.Armistead@otis.com
|
||||
Jay Fenlason hack@gnu.org
|
||||
Jean-Michel Soenen soenen@lectra.fr
|
||||
Jean-Ph. Martin-Flatin syj@ecmwf.int
|
||||
@@ -237,13 +249,16 @@ John David Anglin dave@hiauly1.hia.nrc.ca
|
||||
John Gilmore gnu@toad.com
|
||||
John J. Szetela johns@angelo.amd.com
|
||||
John L. Chmielewski jlc@attmail.com
|
||||
John L. Males jlmales@yahoo.com
|
||||
John Oleynick juo@klinzhai.rutgers.edu
|
||||
John R. Vanderpool fish@daacdev1.stx.com
|
||||
John Rouillard rouilj@cs.umb.edu
|
||||
John Thomas McDole john.thomas.mcdole@nagra.com
|
||||
Jon Lewis jlewis@inorganic5.fdt.net
|
||||
Jonathan I. Kamens jik@cam.ov.com
|
||||
Jonathan N. Sherman sysjns@etacrs1.safb.af.mil
|
||||
Jonathan Thornburg thornbur@theory.physics.ubc.ca
|
||||
Josef Bauer Josef.Bauer@mchp.siemens.de
|
||||
Joseph E. Sacco jsacco@ssl.com
|
||||
Joshua R. Poulson jrp@plaza.ds.adp.com
|
||||
Joutsiniemi Tommi Il tj75064@cs.tut.fi
|
||||
@@ -251,12 +266,14 @@ Joy Kendall jak8@world.std.com
|
||||
Judy Ricker jricker@gdstech.grumman.com
|
||||
Juha Sarlin juha@tds.kth.se
|
||||
Jurgen Botz jbotz@orixa.mtholyoke.edu
|
||||
J<EFBFBD>¼rgen L<>¼ters jlueters@t-online.de
|
||||
J<EFBFBD>¼rgen Reiss reiss@psychologie.uni-wuerzburg.de
|
||||
Jyh-Shyang Wang erik@vsp.ee.nctu.edu.tw
|
||||
J<EFBFBD>¶rg Weule weule@cs.uni-duesseldorf.de
|
||||
J<EFBFBD>¶rgen H<>¤gg Jorgen.Hagg@axis.se
|
||||
J<EFBFBD>¶rgen Weigert jw@suse.de
|
||||
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
|
||||
Jürgen Reiss reiss@psychologie.uni-wuerzburg.de
|
||||
Kai Petzke wpp@marie.physik.tu-berlin.de
|
||||
Kai Schlichting kai@computel.com
|
||||
Karl Berry karl@cs.umb.edu
|
||||
@@ -283,10 +300,10 @@ Laurent Sainte-Marthe smarthe@genethon.fr
|
||||
Leland Lucius llucius@tiny.net
|
||||
Les Mikesell les@mcs.com
|
||||
Loren J. Rittle rittle@comm.mot.com
|
||||
Lo<EFBFBD>¯c Prylli Loic.Prylli@lip.ens-lyon.fr
|
||||
Loïc Prylli Loic.Prylli@lip.ens-lyon.fr
|
||||
Luke Mewburn lukem@connect.com.au
|
||||
Mads Martin Joergensen mmj@suse.de
|
||||
Machael Stone mstone@cs.loyola.edu
|
||||
Mads Martin Joergensen mmj@suse.de
|
||||
Manfred Weichel Manfred.Weichel@mch.sni.de
|
||||
Manuel Munier Manuel.Munier@loria.fr
|
||||
Marc Boucher marc@cam.org
|
||||
@@ -302,6 +319,7 @@ Markus Kuhn mskuhn@cip.informatik.uni-erlangen.de
|
||||
Martin Bellenberg sunsoft@ifm.uni-hamburg.de
|
||||
Martin Goik goik@HDM-Stuttgart.de
|
||||
Martin Mares mj@k332.feld.cvut.cz
|
||||
Martin Simmons ZYHYLCRMZPRP@spammotel.com
|
||||
Marty Leisner leisner@eso.mc.xerox.com
|
||||
Massimo Dal Zotto dz@cs.unitn.it
|
||||
Mats Lofkvist d87-mal@nada.kth.se
|
||||
@@ -374,7 +392,10 @@ 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
|
||||
Ralph Schleicher rs@purple.ul.bawue.de
|
||||
Randy Bias randyb@edge.edge.net
|
||||
Ray Dassen jdassen@wi.leidenuniv.nl
|
||||
@@ -408,15 +429,15 @@ Rodney Brown RBrown@cocam.com.au
|
||||
Roland McGrath roland@gnu.org
|
||||
Roland Schemers III schemers@vela.acs.oakland.edu
|
||||
Rolf Niepraschk niepraschk@chbrb.berlin.ptb.de
|
||||
Roman Gollent roman@portal.stwing.upenn.edu
|
||||
Roman Czyborra czyborra@cs.tu-berlin.de
|
||||
Roman Gollent roman@portal.stwing.upenn.edu
|
||||
Ron Guilmette rfg@netcom.com
|
||||
Roy Marantz marantz@nbcs.rutgers.edu
|
||||
Russ Evans e_gs18@ub.nmh.ac.uk
|
||||
Russell Cattelan cattelan@thebarn.com
|
||||
Ryutaro Susukita susukita@pn.scphys.kyoto-u.ac.jp
|
||||
Sam Richards sam@blueskyprod.com
|
||||
Sakai Kiyotaka ksakai@netwk.ntt-at.co.jp
|
||||
Sam Richards sam@blueskyprod.com
|
||||
Santiago Vila Doncel sanvila@unex.es
|
||||
Sarah Quady squady@warp10.keck.hawaii.edu
|
||||
Saul Lubkin lubkin@cs.rochester.edu
|
||||
@@ -429,9 +450,9 @@ Serge Granik serge@euler.berkeley.edu
|
||||
Seth Robertson seth@ctr.columbia.edu
|
||||
Sherwood Botsford sherwood@space.ualberta.ca
|
||||
Simon Wright simon.j.wright@gecm.com
|
||||
Simon Wright simon@pogner.demon.co.uk
|
||||
Sisira Jayasinghe sisira.jayasinghe@sdrc.com
|
||||
Skip Montanaro skip@mojam.com http://www.musi-cal.com/~skip/
|
||||
Simon Wright simon@pogner.demon.co.uk
|
||||
Solar Designer solar@openwall.com
|
||||
Stefan Skoglund sp2stes1@ida.his.se
|
||||
Steffen Stempel stempel@ira.uka.de
|
||||
@@ -445,9 +466,10 @@ Sylvain Rougier un@grolier.fr
|
||||
Tarang Kumar Patel mombasa@ptolemy.arc.nasa.gov
|
||||
Ted Rule Ted_Rule@flextech.co.uk
|
||||
The King elvis@gnu.org
|
||||
Thomas metaf4@users.askja.de
|
||||
Thomas Bushnell n/BSG thomas@gnu.org
|
||||
Thomas K<>¶nig Thomas.Koenig@ciw.uni-karlsruhe.de
|
||||
Thomas Krebs krebs@faps.uni-erlangen.de
|
||||
Thomas König Thomas.Koenig@ciw.uni-karlsruhe.de
|
||||
Thomas M. Browder Jr. browder@use1.eglin.af.mil
|
||||
Thomas Priesner priesner@flo.sh.bosch.de
|
||||
Thomas Waas waas@echild.aiss.de
|
||||
@@ -460,9 +482,10 @@ Tim P. Starrin noid@cyborg.larc.nasa.gov
|
||||
Tim Ramsey tar@ksu.ksu.edu
|
||||
Tim Rylance tkr@puffball.demon.co.uk
|
||||
Tim Towers tzt@uniplex.co.uk
|
||||
Timothy J. Lee timlee@netcom.com
|
||||
Timothy Fossum fossum@cs.uwp.edu
|
||||
Timothy J. Lee timlee@netcom.com
|
||||
Tito Flagella tito@di.unipi.it
|
||||
Todd Vierling tv@duh.org
|
||||
Tom Popovitch tpop@informix.com
|
||||
Tom Quinn trq@astro.washington.edu
|
||||
Tom Tromey tromey@drip.colorado.edu
|
||||
@@ -487,16 +510,17 @@ Werner Almesberger werner.almesberger@lrc.di.epfl.ch
|
||||
William Bader william@nscs.fast.net
|
||||
William J. Eaton wje@hoffman.rstnu.bcm.tmc.edu
|
||||
William Kucharski kucharsk@netcom.com
|
||||
Włodzimierz Jan Martin wjm@pg.gda.pl
|
||||
Wojciech Polak polak@gnu.org
|
||||
Wolfgang Rupprecht wolfgang@wsrcc.com
|
||||
Wolfram Gloger Wolfram.Gloger@dent.med.uni-muenchen.de
|
||||
Wolfram Kleff bugreport@wkleff.intergenia.de
|
||||
Wolfram Wagner ww@mpi-sb.mpg.de
|
||||
Włodzimierz Jan Martin wjm@pg.gda.pl
|
||||
Yasushi Suzudo SGR00413@niftyserve.or.jp
|
||||
Yu-Min Liang min@taz.ho.att.com
|
||||
|
||||
|
||||
;;;; Local variables:
|
||||
;;;; Local Variables:
|
||||
;;;; mode: Fundamental
|
||||
;;;; buffer-file-coding-system: utf-8
|
||||
;;;; coding: utf-8
|
||||
;;;; End:
|
||||
|
||||
35
TODO
35
TODO
@@ -1,25 +1,20 @@
|
||||
Suggestions for improving GNU tar.
|
||||
|
||||
* <45BEC0DB.8040903@unix-beratung.de>
|
||||
|
||||
* Incorporate fixes from major distributions, e.g., Debian GNU/Linux.
|
||||
|
||||
* 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 restoring file time stamps to sub-second resolution,
|
||||
if the file system supports this.
|
||||
|
||||
* Add support for restoring the attributes of symbolic links, for
|
||||
OSes like FreeBSD that have the lutimes and lchmod functions.
|
||||
|
||||
* --append should bail out if the two archives are of different types.
|
||||
|
||||
* Add support for a 'pax' command that conforms to POSIX 1003.1-2001.
|
||||
This would unify paxutils with tar.
|
||||
|
||||
* Remove command-line incompatibilities between GNU tar and UNIX tar
|
||||
as specified by UNIX98. The main problem is:
|
||||
|
||||
l GNU tar doesn't cross filesystem boundaries.
|
||||
UNIX98 tar warns if all links cannot be resolved.
|
||||
(GNU tar --check-links option)
|
||||
|
||||
Perhaps we could announce a phase-in period where "l" changes in semantics.
|
||||
In the meanwhile we could make the "l" semantics to be determined by the
|
||||
value of POSIXLY_CORRECT variable.
|
||||
|
||||
* Interoperate better with Joerg Schilling's star implementation.
|
||||
|
||||
* Add an option to remove files that compare successfully.
|
||||
@@ -30,7 +25,7 @@ so that the GNU extensions (--incremental, --label and
|
||||
It would be useful to be able to use '--remove-files' with '--diff',
|
||||
to remove all files that compare successfully, when verifying a backup.
|
||||
|
||||
* Add tests for testing the added functonality.
|
||||
* Add tests for the new functonality.
|
||||
|
||||
* Consider this:
|
||||
|
||||
@@ -47,16 +42,16 @@ so that the GNU extensions (--incremental, --label and
|
||||
|
||||
(http://mail.gnu.org/archive/html/bug-gnu-utils/2002-05/msg00022.html)
|
||||
|
||||
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 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,
|
||||
@@ -66,8 +61,8 @@ so that the GNU extensions (--incremental, --label and
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
Local variables:
|
||||
|
||||
758
bootstrap
758
bootstrap
@@ -1,12 +1,12 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Bootstrap 'tar' from CVS.
|
||||
# Bootstrap this package from CVS.
|
||||
|
||||
# Copyright (C) 2003, 2004 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,
|
||||
@@ -16,224 +16,636 @@
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Written by Paul Eggert.
|
||||
# Written by Paul Eggert and Sergey Poznyakoff.
|
||||
|
||||
# URL of our text domain page in Translation Project
|
||||
TP_URL="http://www2.iro.umontreal.ca/~gnutra/po/maint/tar/"
|
||||
nl='
|
||||
'
|
||||
|
||||
# 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][--cvs-auth=AUTH-METHOD][--cvs-user=USERNAME][--no-po]
|
||||
Options are:
|
||||
--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.
|
||||
echo >&2 "\
|
||||
Usage: $0 [OPTION]...
|
||||
Bootstrap this package from the checked-out sources.
|
||||
|
||||
Running without arguments will suffice in most cases. It is equivalent
|
||||
to
|
||||
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[=LANG] Update po file(s) and exit.
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the gnulib repository.
|
||||
|
||||
./bootstrap --cvs-auth=ext --cvs-user=anoncvs
|
||||
If the file bootstrap.conf exists in the current working directory, its
|
||||
contents are read as shell variables to configure the bootstrap.
|
||||
|
||||
EOF
|
||||
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.
|
||||
|
||||
Running without arguments will suffice in most cases.
|
||||
"
|
||||
}
|
||||
|
||||
checkout() {
|
||||
if [ ! -d $1 ]; then
|
||||
echo "$0: getting $1 files..."
|
||||
|
||||
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
|
||||
|
||||
trap "cleanup $1" 1 2 13 15
|
||||
|
||||
cvs -z3 -q -d ${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1" co $1 ||
|
||||
cleanup $1
|
||||
|
||||
trap - 1 2 13 15
|
||||
fi
|
||||
}
|
||||
|
||||
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=
|
||||
|
||||
# Translation Project URL, for the registry of all projects
|
||||
# and for the translation-team master directory.
|
||||
tp_url() {
|
||||
echo "http://translationproject.org/domain/$1.html"
|
||||
}
|
||||
|
||||
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;;
|
||||
--paxutils-srcdir=*)
|
||||
PAXUTILS_SRCDIR=`expr "$option" : '--paxutils-srcdir=\(.*\)'`;;
|
||||
--gnulib-srcdir=*)
|
||||
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
|
||||
--cvs-auth=*)
|
||||
CVS_AUTH=`expr "$option" : '--cvs-auth=\(.*\)'`;;
|
||||
--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
|
||||
|
||||
echo "$0: Bootstrapping CVS tar..."
|
||||
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
|
||||
|
||||
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
|
||||
echo "$0: Bootstrapping CVS $package..."
|
||||
|
||||
# Get translations.
|
||||
|
||||
get_translations() {
|
||||
subdir=$1
|
||||
domain=$2
|
||||
po_file=$3
|
||||
|
||||
case $WGET_COMMAND in
|
||||
'')
|
||||
echo "$0: wget not available; skipping translations";;
|
||||
?*)
|
||||
url=`tp_url $domain`
|
||||
baseurl=`expr "$url" : '\(.*\)/.*'`
|
||||
echo "$0: getting translations into $subdir for $domain..." &&
|
||||
case $po_file in
|
||||
'') (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'`);;
|
||||
esac &&
|
||||
|
||||
$WGET_COMMAND -O "$subdir/$domain.html" "$url" &&
|
||||
|
||||
sed -n 's|.*href="\(.*\)/\([^/][^/]*\)/'"$domain"'-\([^/"]*\)\.[^."]*\.po".*|\2:\3:\1|p' <"$subdir/$domain.html" |
|
||||
sort -t: -k 1,1 -k 2,2n -k2,2 -k3,3n -k3,3 -k4,4n -k4,4 -k5,5n -k5.5 |
|
||||
awk -F: '
|
||||
{ if (lang && $1 != lang) print lang, ver, $3 }
|
||||
{ lang = $1; ver = $2 }
|
||||
END { if (lang) print lang, ver, $3 }
|
||||
' | awk -v domain="$domain" -v baseurl="$baseurl" -v subdir="$subdir" \
|
||||
-v po_file="$po_file" '
|
||||
{
|
||||
lang = $1
|
||||
if (po_file && po_file != (lang ".po")) next
|
||||
ver = $2
|
||||
printf "{ $WGET_COMMAND -O %s/%s.po %s/%s/%s/%s-%s.%s.po &&\n", subdir, lang, baseurl, $3, lang, domain, ver, lang
|
||||
printf " msgfmt -c -o /dev/null %s/%s.po || {\n", subdir, lang
|
||||
printf " echo >&2 '\'"$0"': omitting translation for %s'\''\n", lang
|
||||
printf " rm -f %s/%s.po; }; } &&\n", subdir, lang
|
||||
}
|
||||
END { print ":" }
|
||||
' | WGET_COMMAND="$WGET_COMMAND" sh
|
||||
;;
|
||||
esac &&
|
||||
ls "$subdir"/*.po 2>/dev/null |
|
||||
sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS" &&
|
||||
rm -f "$subdir/$domain.html"
|
||||
}
|
||||
|
||||
case `wget --help` in
|
||||
*'--no-cache'*)
|
||||
WGET_COMMAND='wget -nv --no-cache';;
|
||||
*'--cache=on/off'*)
|
||||
WGET_COMMAND='wget -nv --cache=off';;
|
||||
*'--non-verbose'*)
|
||||
WGET_COMMAND='wget -nv';;
|
||||
*)
|
||||
WGET_COMMAND='';;
|
||||
esac
|
||||
|
||||
case $DOWNLOAD_PO in
|
||||
'skip')
|
||||
;;
|
||||
'')
|
||||
get_translations po $package || exit
|
||||
;;
|
||||
'only')
|
||||
get_translations po $package
|
||||
exit
|
||||
;;
|
||||
*.po)
|
||||
get_translations po $package "$DOWNLOAD_PO"
|
||||
exit
|
||||
;;
|
||||
*)
|
||||
get_translations po $package "${DOWNLOAD_PO}.po"
|
||||
exit
|
||||
esac
|
||||
|
||||
# Get paxutils files.
|
||||
|
||||
case ${PAXUTILS_SRCDIR--} in
|
||||
-) checkout paxutils
|
||||
PAXUTILS_SRCDIR=paxutils
|
||||
esac
|
||||
|
||||
if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
|
||||
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`
|
||||
do
|
||||
case $file in
|
||||
"#*") continue;;
|
||||
esac
|
||||
dst=`echo $file | sed 's^.*/^^'`
|
||||
if [ $# -eq 3 ]; then
|
||||
case $dst in
|
||||
${3}*) ;;
|
||||
*) dst=${3}$dst;;
|
||||
esac
|
||||
fi
|
||||
echo "$0: Copying file $1/$file to $2/$dst"
|
||||
cp -p $1/$file $2/$dst
|
||||
ignorefile $2 $dst
|
||||
done
|
||||
}
|
||||
|
||||
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([${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
|
||||
:
|
||||
else
|
||||
mkdir rmt
|
||||
fi
|
||||
|
||||
for dir in doc rmt lib tests
|
||||
do
|
||||
copy_files ${PAXUTILS_SRCDIR}/$dir $dir
|
||||
done
|
||||
|
||||
copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
|
||||
|
||||
# Get gnulib files.
|
||||
|
||||
case ${GNULIB_SRCDIR--} in
|
||||
-)
|
||||
if [ ! -d gnulib ]; then
|
||||
echo "$0: getting gnulib files..."
|
||||
|
||||
trap exit 1 2 13 15
|
||||
trap 'rm -fr gnulib; exit 1' 0
|
||||
|
||||
case "${CVS_AUTH--}" in
|
||||
-) build_cvs_prefix ext anoncvs;;
|
||||
pserver) build_cvs_prefix $CVS_AUTH ${CVS_USER:-anoncvs};;
|
||||
gserver|server)
|
||||
build_cvs_prefix $CVS_AUTH ${CVS_USER--};;
|
||||
ext) build_cvs_prefix $CVS_AUTH ${CVS_USER--};;
|
||||
*) echo "$0: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
if [ "${CVS_AUTH--}" = "pserver" ]; then
|
||||
cvs -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/gnulib login || exit
|
||||
fi
|
||||
cvs -q -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/gnulib co gnulib || exit
|
||||
|
||||
trap 0
|
||||
fi
|
||||
checkout gnulib
|
||||
GNULIB_SRCDIR=gnulib
|
||||
esac
|
||||
|
||||
<$GNULIB_SRCDIR/gnulib-tool || exit
|
||||
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
|
||||
<$gnulib_tool || exit
|
||||
|
||||
gnulib_modules='
|
||||
alloca
|
||||
argmatch
|
||||
backupfile
|
||||
dirname
|
||||
error
|
||||
exclude
|
||||
fileblocks
|
||||
fnmatch-gnu
|
||||
ftruncate
|
||||
full-write
|
||||
getdate
|
||||
getline
|
||||
getopt
|
||||
gettext
|
||||
gettime
|
||||
hash
|
||||
human
|
||||
lchown
|
||||
memset
|
||||
modechange
|
||||
obstack
|
||||
quote
|
||||
quotearg
|
||||
rmdir
|
||||
safe-read
|
||||
save-cwd
|
||||
savedir
|
||||
stdbool
|
||||
stpcpy
|
||||
strtol
|
||||
strtoul
|
||||
timespec
|
||||
unlocked-io
|
||||
utime
|
||||
xalloc
|
||||
xgetcwd
|
||||
xstrtoumax
|
||||
'
|
||||
symlink_to_gnulib()
|
||||
{
|
||||
src=$GNULIB_SRCDIR/$1
|
||||
dst=${2-$1}
|
||||
|
||||
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
|
||||
`
|
||||
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" &&
|
||||
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" &&
|
||||
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
|
||||
|
||||
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
|
||||
# Import from gettext.
|
||||
|
||||
for gnulib_file in $gnulib_files; do
|
||||
dest=$gnulib_file
|
||||
echo "$0: (cd $bt2; autopoint) ..."
|
||||
cp configure.ac $bt2 &&
|
||||
(cd $bt2 && autopoint && rm configure.ac) &&
|
||||
slurp $bt2 $bt || exit
|
||||
|
||||
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/ulonglong.m4) dest=m4/ulonglong_gl.m4;;
|
||||
m4/inttypes_h.m4) dest=m4/inttypes_h_gl.m4;;
|
||||
m4/stdint_h.m4) dest=m4/stdint_h_gl.m4;;
|
||||
m4/uintmax_t.m4) dest=m4/uintmax_t_gl.m4;;
|
||||
esac
|
||||
rm -fr $bt $bt2 || exit
|
||||
|
||||
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"
|
||||
(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
|
||||
echo "$0: getting translations into po..."
|
||||
(cd po &&
|
||||
rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'` &&
|
||||
wget -nv -nd -r -l 1 -A .po -C off $TP_URL &&
|
||||
ls *.po | sed 's/\.po$//' >LINGUAS
|
||||
) || exit
|
||||
fi
|
||||
|
||||
# Reconfigure, getting other files.
|
||||
|
||||
echo "$0: autoreconf --verbose --install --force ..."
|
||||
autoreconf --verbose --install --force
|
||||
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
|
||||
'
|
||||
135
configure.ac
135
configure.ac
@@ -1,11 +1,11 @@
|
||||
# Configure template for GNU tar.
|
||||
|
||||
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
# 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 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,
|
||||
@@ -15,31 +15,32 @@
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
AC_INIT([GNU tar], [1.14], [bug-tar@gnu.org])
|
||||
AC_INIT([GNU tar], [1.18], [bug-tar@gnu.org])
|
||||
AC_CONFIG_SRCDIR([src/tar.c])
|
||||
AC_CONFIG_AUX_DIR([config])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h:config.hin])
|
||||
AC_PREREQ([2.59])
|
||||
AM_INIT_AUTOMAKE([1.8 gnits dist-bzip2 dist-shar std-options])
|
||||
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
|
||||
|
||||
AC_CHECK_HEADERS(fcntl.h linux/fd.h memory.h net/errno.h \
|
||||
sgtty.h string.h \
|
||||
sys/param.h sys/device.h sys/gentape.h \
|
||||
AC_CHECK_HEADERS_ONCE(fcntl.h linux/fd.h memory.h net/errno.h \
|
||||
sgtty.h string.h stropts.h \
|
||||
sys/param.h sys/device.h sys/filio.h sys/gentape.h \
|
||||
sys/inet.h sys/io/trioctl.h \
|
||||
sys/mtio.h sys/time.h sys/tprintf.h sys/tape.h \
|
||||
unistd.h)
|
||||
unistd.h locale.h)
|
||||
|
||||
AC_CHECK_HEADERS([sys/buf.h], [], [],
|
||||
[#if HAVE_SYS_PARAM_H
|
||||
@@ -49,32 +50,11 @@ AC_CHECK_HEADERS([sys/buf.h], [], [],
|
||||
AC_HEADER_SYS_WAIT
|
||||
AM_STDBOOL_H
|
||||
|
||||
if test $ac_cv_header_sys_mtio_h = yes; then
|
||||
AC_CACHE_CHECK(for remote tape header files, tar_cv_header_rmt,
|
||||
[AC_TRY_CPP([
|
||||
#if HAVE_SGTTY_H
|
||||
# include <sgtty.h>
|
||||
#endif
|
||||
#include <sys/socket.h>],
|
||||
tar_cv_header_rmt=yes, tar_cv_header_rmt=no)])
|
||||
test $tar_cv_header_rmt = yes && RMT='rmt$(EXEEXT)'
|
||||
AC_SUBST(RMT)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK(which ioctl field to test for reversed bytes,
|
||||
tar_cv_header_mtio_check_field,
|
||||
[AC_EGREP_HEADER(mt_model, sys/mtio.h,
|
||||
tar_cv_header_mtio_check_field=mt_model,
|
||||
tar_cv_header_mtio_check_field=mt_type)])
|
||||
AC_DEFINE_UNQUOTED(MTIO_CHECK_FIELD, $tar_cv_header_mtio_check_field,
|
||||
[Define to mt_model (v.g., for DG/UX), else to mt_type.])
|
||||
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_MAJOR
|
||||
AC_HEADER_STAT
|
||||
AC_HEADER_STDC
|
||||
AC_STRUCT_ST_BLKSIZE
|
||||
AC_STRUCT_ST_BLOCKS
|
||||
|
||||
AC_MSG_CHECKING([for st_fstype string in struct stat])
|
||||
AC_CACHE_VAL(diff_cv_st_fstype_string,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
@@ -101,53 +81,17 @@ 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_MEMBERS([struct stat.st_spare1, struct stat.st_atim.tv_nsec, struct stat.st_atimespec.tv_nsec, struct stat.st_atimensec], , ,
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>])
|
||||
|
||||
# Save and restore LIBS so e.g., -lrt, isn't added to it. Otherwise, *all*
|
||||
# programs in the package would end up linked with that potentially-shared
|
||||
# library, inducing unnecessary run-time overhead.
|
||||
|
||||
# Solaris 2.5.1 needs -lposix4 to get the clock_gettime function.
|
||||
# Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4.
|
||||
tar_save_LIBS=$LIBS
|
||||
LIB_CLOCK_GETTIME=
|
||||
AC_SEARCH_LIBS(clock_gettime, [rt posix4])
|
||||
case "$ac_cv_search_clock_gettime" in
|
||||
-l*) LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime;;
|
||||
esac
|
||||
AC_SUBST(LIB_CLOCK_GETTIME)
|
||||
AC_CHECK_FUNCS(clock_gettime)
|
||||
LIBS=$tar_save_LIBS
|
||||
|
||||
AC_CHECK_FUNCS(fsync lstat mkfifo readlink strerror symlink setlocale utimes)
|
||||
AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink strerror symlink setlocale utimes)
|
||||
AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
|
||||
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
|
||||
AC_CHECK_DECLS([valloc])
|
||||
AC_CHECK_DECLS([time],,, [#include <time.h>])
|
||||
|
||||
# Set LIB_SETSOCKOPT to -lnsl -lsocket if necessary.
|
||||
tar_save_LIBS=$LIBS
|
||||
LIB_SETSOCKOPT=
|
||||
AC_SEARCH_LIBS(setsockopt, [socket], ,
|
||||
[AC_SEARCH_LIBS(setsockopt, [socket], , , [-lnsl])])
|
||||
AC_SEARCH_LIBS(setsockopt, [nsl])
|
||||
|
||||
case "$ac_cv_search_setsockopt" in
|
||||
-l*) LIB_SETSOCKOPT=$ac_cv_search_setsockopt
|
||||
esac
|
||||
AC_SUBST(LIB_SETSOCKOPT)
|
||||
LIBS=$tar_save_LIBS
|
||||
|
||||
AC_REPLACE_FUNCS(waitpid)
|
||||
|
||||
AC_CACHE_CHECK(for remote shell, tar_cv_path_RSH,
|
||||
@@ -210,7 +154,7 @@ else
|
||||
case $DEFAULT_ARCHIVE in
|
||||
*[[0-7][lmh]])
|
||||
AC_DEFINE(DENSITY_LETTER, 1,
|
||||
[[Define to 1 if density may be indicated by [lmh] at end of device.]])
|
||||
[Define to 1 if density may be indicated by [lmh] at end of device.])
|
||||
device_prefix=`echo $DEFAULT_ARCHIVE | sed 's/[0-7][lmh]$//'`
|
||||
;;
|
||||
*[[0-7]])
|
||||
@@ -239,16 +183,22 @@ AC_DEFINE_UNQUOTED(DEFAULT_BLOCKING, $DEFAULT_BLOCKING,
|
||||
[Define to a number giving the default blocking size for archives.])
|
||||
AC_MSG_RESULT($DEFAULT_BLOCKING)
|
||||
|
||||
AC_ARG_VAR([DEFAULT_RMT_COMMAND],
|
||||
[Define full pathname of rmt program.])
|
||||
if test "x$DEFAULT_RMT_COMMAND" != x; then
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_RMT_COMMAND, "$DEFAULT_RMT_COMMAND",
|
||||
[Define full pathname of rmt program.])
|
||||
fi
|
||||
AC_MSG_CHECKING(for default quoting style)
|
||||
|
||||
# Gettext.
|
||||
AM_GNU_GETTEXT([external], [need-ngettext])
|
||||
AM_GNU_GETTEXT_VERSION(0.12.1)
|
||||
m4_define([QUOTING_STYLES],dnl
|
||||
[literal|shell|shell-always|c|escape|locale|clocale])
|
||||
DEFAULT_QUOTING_STYLE="escape"
|
||||
AC_ARG_VAR([DEFAULT_QUOTING_STYLE],
|
||||
[Set the default quoting style. Allowed values are: ] m4_bpatsubst(QUOTING_STYLES,[|], [[, ]]) [. Default is "escape".])
|
||||
|
||||
case $DEFAULT_QUOTING_STYLE in
|
||||
QUOTING_STYLES) ;;
|
||||
*) AC_MSG_ERROR(Invalid quoting style);;
|
||||
esac
|
||||
AC_MSG_RESULT($DEFAULT_QUOTING_STYLE)
|
||||
DEFAULT_QUOTING_STYLE=`echo ${DEFAULT_QUOTING_STYLE}|sed 's/-/_/g'`_quoting_style
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_QUOTING_STYLE, $DEFAULT_QUOTING_STYLE,
|
||||
[Define to a default quoting style (see lib/quoteargs.c for the list)])
|
||||
|
||||
# Iconv
|
||||
AM_ICONV
|
||||
@@ -262,6 +212,15 @@ AC_CHECK_TYPE(iconv_t,:,
|
||||
#endif
|
||||
])
|
||||
|
||||
# Gettext.
|
||||
AM_GNU_GETTEXT([external], [need-formatstring-macros])
|
||||
AM_GNU_GETTEXT_VERSION([0.16])
|
||||
|
||||
# Initialize the test suite.
|
||||
AC_CONFIG_TESTDIR(tests)
|
||||
AC_CONFIG_FILES([tests/Makefile tests/atlocal]) # FIXME: tests/preset?
|
||||
AM_MISSING_PROG([AUTOM4TE], [autom4te])
|
||||
|
||||
AC_SUBST(BACKUP_LIBEXEC_SCRIPTS)
|
||||
AC_SUBST(BACKUP_SBIN_SCRIPTS)
|
||||
AC_ARG_ENABLE(backup-scripts,
|
||||
@@ -280,12 +239,10 @@ 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\
|
||||
po/Makefile.in\
|
||||
scripts/Makefile\
|
||||
src/Makefile\
|
||||
tests/Makefile\
|
||||
tests/preset])
|
||||
rmt/Makefile\
|
||||
src/Makefile])
|
||||
|
||||
87
directory
Normal file
87
directory
Normal file
@@ -0,0 +1,87 @@
|
||||
%%comments:
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the file COPYING.
|
||||
|
||||
%%name: tar
|
||||
|
||||
%%short-description: Creates tar archives
|
||||
|
||||
%%full-description:
|
||||
GNU tar is an archiver that creates and handles file archives in various
|
||||
formats. You can use tar to create file archives, to extract files from
|
||||
previously created archives, store additional files, or update or list
|
||||
files which were already stored.
|
||||
|
||||
The program saves many files together into a single tape or disk
|
||||
archive, and can restore individual files from the archive. It
|
||||
includes multivolume support, the ability to archive sparse files,
|
||||
automatic archive compression/decompression, remote archives and
|
||||
special features that allow 'tar' to be used for incremental and full
|
||||
backups.
|
||||
|
||||
The supported archive formats are: V7 tar, GNU, ustar and POSIX (also
|
||||
known as pax interchange format). GNU tar is also able to read and
|
||||
extract 'star' archives.
|
||||
|
||||
Tar can direct its output to available devices, files, or other
|
||||
programs (using pipes); tar can even access remote devices or files
|
||||
(as archives).
|
||||
|
||||
%%category: system, backup
|
||||
|
||||
%%license: GPL
|
||||
|
||||
%%maintainer: Sergey Poznyakoff <gray@Mirddin.farlep.net>,
|
||||
Jeff Bailey <jbailey@nisa.net>,
|
||||
Paul Eggert <eggert@CS.UCLA.EDU>
|
||||
|
||||
%%updated: 21 Dec 2004
|
||||
|
||||
%%keywords: archive, backup, tar, pax
|
||||
|
||||
%%interface: Command line
|
||||
|
||||
%%programs: tar, rmt
|
||||
|
||||
%%GNU: yes
|
||||
|
||||
%%web-page: http://www.gnu.org/software/tar
|
||||
|
||||
%%doc: English user reference included
|
||||
|
||||
%%doc: English user manual in Texinfo, Dvi, Postscript, HTML, Plaintext is available from http://www.gnu.org/software/tar/manual/tar.html
|
||||
|
||||
%%developers:
|
||||
John Gilmore,
|
||||
Thomas Bushnell,
|
||||
Paul Eggert <eggert@twinsun.com>,
|
||||
Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
%%contributors: Jay Fenlason,
|
||||
Joy Kendall,
|
||||
Francois Pinard <pinard@iro.umontreal.ca>
|
||||
|
||||
%%source-tarball: ftp://ftp.gnu.org/pub/gnu/tar/tar-1.15.1.tar.gz
|
||||
%%source-info: http://savannah.gnu.org/projects/tar
|
||||
|
||||
%%repository:
|
||||
:pserver:anoncvs@subversions.gnu.org:/cvsroot/tar login,
|
||||
:pserver:anoncvs@subversions.gnu.org:/cvsroot/tar co tar,
|
||||
http://savannah.gnu.org/cvs/?group=tar,
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/tar/tar,
|
||||
|
||||
%%source-language: C
|
||||
|
||||
%%related-programs: GNU cpio
|
||||
|
||||
%%version: 1.15.1 (stable) released on 21 Dec 2004
|
||||
|
||||
%%bug-list: bug-tar@gnu.org bug-tar@gnu.org http://mail.gnu.org/mailman/listinfo/bug-tar
|
||||
|
||||
%%entry-written-by: Sergey Poznyakoff <gray@gnu.org>
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
Makefile.in
|
||||
*.stamp
|
||||
Makefile
|
||||
Makefile.in
|
||||
genfile.texi
|
||||
getdate.texi
|
||||
header.texi
|
||||
tar.info
|
||||
version.texi
|
||||
html_chapter
|
||||
html_mono
|
||||
html_node
|
||||
stamp-vti
|
||||
tar.html
|
||||
tar.log
|
||||
tar.dvi
|
||||
tar.aux
|
||||
tar.toc
|
||||
tar.cp
|
||||
tar.fn
|
||||
tar.vr
|
||||
tar.tp
|
||||
tar.ky
|
||||
tar.pg
|
||||
tar.ps
|
||||
tar.cps
|
||||
tar.fns
|
||||
tar.pgs
|
||||
tar.vrs
|
||||
tar.at
|
||||
tar.kw
|
||||
tar.ex
|
||||
tar.ats
|
||||
tar.aux
|
||||
tar.cp
|
||||
tar.cps
|
||||
tar.dvi
|
||||
tar.ex
|
||||
tar.exs
|
||||
tar.fn
|
||||
tar.fns
|
||||
tar.html
|
||||
tar.info*
|
||||
tar.kw
|
||||
tar.kws
|
||||
tmp-tar.*
|
||||
tar.ky
|
||||
tar.log
|
||||
tar.op
|
||||
tar.ops
|
||||
tar.pdf
|
||||
tar.pg
|
||||
tar.pgs
|
||||
tar.ps
|
||||
tar.toc
|
||||
tar.tp
|
||||
tar.vr
|
||||
tar.vrs
|
||||
version.texi
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Makefile for GNU tar documentation.
|
||||
|
||||
# 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,
|
||||
@@ -15,37 +15,72 @@
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software Foundation,
|
||||
## Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
info_TEXINFOS = tar.texi
|
||||
|
||||
EXTRA_DIST = convtexi.pl fdl.texi freemanuals.texi getdate.texi header.texi
|
||||
|
||||
CLEANFILES = tmp-*
|
||||
tar_TEXINFOS = \
|
||||
dumpdir.texi\
|
||||
tar-snapshot-edit.texi\
|
||||
fdl.texi\
|
||||
freemanuals.texi\
|
||||
genfile.texi\
|
||||
getdate.texi\
|
||||
header.texi\
|
||||
intern.texi\
|
||||
rendition.texi\
|
||||
snapshot.texi\
|
||||
sparse.texi\
|
||||
value.texi
|
||||
EXTRA_DIST = gendocs_template mastermenu.el texify.sed
|
||||
|
||||
# The rendering level is anyone of PUBLISH, DISTRIB or PROOF.
|
||||
# Just call `make dvi RENDITION=PROOF' if you want PROOF rendition.
|
||||
# Just call `make RENDITION=PROOF [target]' if you want PROOF rendition.
|
||||
RENDITION = DISTRIB
|
||||
|
||||
$(srcdir)/tar.info: tar.texi fdl.texi freemanuals.texi getdate.texi \
|
||||
$(srcdir)/header.texi version.texi
|
||||
$(MAKEINFO) --no-split -D$(RENDITION) -I$(srcdir) tar.texi -o $@
|
||||
MAKEINFOFLAGS=-D$(RENDITION)
|
||||
|
||||
tar.dvi: tar.texi getdate.texi $(srcdir)/header.texi version.texi
|
||||
$(MAKEINFO) -D$(RENDITION) -Etmp-tar.tmp -otmp-tar.info \
|
||||
-I$(srcdir) tar.texi
|
||||
rm -f tmp-tar.sed tmp-tar.info*
|
||||
test $(RENDITION) = DISTRIB \
|
||||
|| echo >>tmp-tar.sed 's/^@set DISTRIB/@set $(RENDITION)/'
|
||||
test $(RENDITION) = PUBLISH \
|
||||
|| echo >>tmp-tar.sed '/^@smallbook/d'
|
||||
sed -f tmp-tar.sed tmp-tar.tmp > tmp-tar.texi
|
||||
rm -f tmp-tar.sed tmp-tar.tmp
|
||||
TEXINPUTS=$(top_srcdir)/config:$$TEXINPUTS \
|
||||
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
||||
$(TEXI2DVI) tmp-tar.texi
|
||||
mv tmp-tar.dvi $@
|
||||
header.texi: $(top_srcdir)/src/tar.h
|
||||
sed -f $(srcdir)/texify.sed $(top_srcdir)/src/tar.h \
|
||||
| expand >$@
|
||||
|
||||
master-menu: $(tar_TEXINFOS)
|
||||
emacs -batch -l mastermenu.el -f make-master-menu $(info_TEXINFOS)
|
||||
|
||||
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' \
|
||||
$(top_builddir)/src/tar --usage | \
|
||||
sed -n 's/^\[--\([^]\=\[]*\).*/\1/p' | sort | uniq > opts.$$$$;\
|
||||
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
|
||||
$(info_TEXINFOS) | \
|
||||
sed -n '/^@macro/,/^@end macro/d;s/@opindex *\([^@,]*\).*/\1/p' \
|
||||
| sort | uniq > docs.$$$$;\
|
||||
(echo 'Not documented options:';\
|
||||
join -v1 opts.$$$$ docs.$$$$;\
|
||||
echo 'Non-existing options:';\
|
||||
join -v2 opts.$$$$ docs.$$$$) > report.$$$$;\
|
||||
rm opts.$$$$ docs.$$$$;\
|
||||
if [ -n "`sed '1,2d' report.$$$$`" ]; then \
|
||||
cat report.$$$$;\
|
||||
rm report.$$$$;\
|
||||
exit 1;\
|
||||
fi;\
|
||||
rm report.$$$$
|
||||
|
||||
|
||||
clean-local:
|
||||
rm -rf manual
|
||||
|
||||
GENDOCS=gendocs.sh
|
||||
|
||||
TEXI2DVI=texi2dvi -t '@set $(RENDITION)' -E
|
||||
|
||||
# Make sure you set TEXINPUTS
|
||||
# Usual value is:
|
||||
# /usr/share/texmf/pdftex/plain/misc:/usr/share/texmf/pdftex/config
|
||||
manual:
|
||||
TEXINPUTS=$(srcdir):$(top_srcdir)/build-tex:$(TEXINPUTS) \
|
||||
MAKEINFO="$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
TEXI2DVI="$(TEXI2DVI) -t @finalout" \
|
||||
$(GENDOCS) tar 'GNU tar manual'
|
||||
|
||||
$(srcdir)/header.texi: $(top_srcdir)/src/tar.h
|
||||
sed -n '/Archive Format/,/End of Format/p' $(top_srcdir)/src/tar.h \
|
||||
| expand | sed 's/\([{}]\)/@\1/g' >$@
|
||||
|
||||
134
doc/convtexi.pl
134
doc/convtexi.pl
@@ -1,134 +0,0 @@
|
||||
#!/usr/local/bin/perl -- # -*-Perl-*-
|
||||
eval "exec /usr/local/bin/perl -S $0 $*"
|
||||
if 0;
|
||||
|
||||
# Copy a Texinfo file, replacing @value's, @FIXME's and other gooddies.
|
||||
|
||||
# Copyright (C) 1996, 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# François Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
$_ = <>;
|
||||
while ($_)
|
||||
{
|
||||
if (/^\@c()$/ || /^\@c (.*)/ || /^\@(include .*)/)
|
||||
{
|
||||
if ($topseen)
|
||||
{
|
||||
print "\@format\n";
|
||||
print "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
while (/\@c (.*)/)
|
||||
{
|
||||
print "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
}
|
||||
print "\@end format\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$delay .= "\@format\n";
|
||||
$delay .= "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
while (/\@c (.*)/)
|
||||
{
|
||||
$delay .= "\@strong{\@\@c} $1\n";
|
||||
$_ = <>;
|
||||
}
|
||||
$delay .= "\@end format\n";
|
||||
}
|
||||
}
|
||||
elsif (/^\@chapter /)
|
||||
{
|
||||
print;
|
||||
# print $delay;
|
||||
$delay = '';
|
||||
$topseen = 1;
|
||||
$_ = <>;
|
||||
}
|
||||
elsif (/^\@macro /)
|
||||
{
|
||||
$_ = <> while ($_ && ! /^\@end macro/);
|
||||
$_ = <>;
|
||||
}
|
||||
elsif (/^\@set ([^ ]+) (.*)/)
|
||||
{
|
||||
$set{$1} = $2;
|
||||
$_ = <>;
|
||||
}
|
||||
elsif (/^\@UNREVISED/)
|
||||
{
|
||||
print "\@quotation\n";
|
||||
print "\@emph{(This message will disappear, once this node is revised.)}\n";
|
||||
print "\@end quotation\n";
|
||||
$_ = <>;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (/\@value{([^\}]*)}/)
|
||||
{
|
||||
if (defined $set{$1})
|
||||
{
|
||||
$_ = "$`$set{$1}$'";
|
||||
}
|
||||
else
|
||||
{
|
||||
$_ = "$`\@strong{<UNDEFINED>}$1\@strong{</UNDEFINED>}$'";
|
||||
}
|
||||
}
|
||||
while (/\@FIXME-?([a-z]*)\{/)
|
||||
{
|
||||
$tag = $1 eq '' ? 'fixme' : $1;
|
||||
$tag =~ y/a-z/A-Z/;
|
||||
print "$`\@strong{<$tag>}";
|
||||
$_ = $';
|
||||
$level = 1;
|
||||
while ($level > 0)
|
||||
{
|
||||
if (/([{}])/)
|
||||
{
|
||||
if ($1 eq '{')
|
||||
{
|
||||
$level++;
|
||||
print "$`\{";
|
||||
$_ = $';
|
||||
}
|
||||
elsif ($level > 1)
|
||||
{
|
||||
$level--;
|
||||
print "$`\}";
|
||||
$_ = $';
|
||||
}
|
||||
else
|
||||
{
|
||||
$level = 0;
|
||||
print "$`\@strong{</$tag>}";
|
||||
$_ = $';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print;
|
||||
$_ = <>;
|
||||
}
|
||||
}
|
||||
}
|
||||
print;
|
||||
$_ = <>;
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
132
doc/dumpdir.texi
Normal file
132
doc/dumpdir.texi
Normal file
@@ -0,0 +1,132 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2006 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.
|
||||
|
||||
Incremental archives keep information about contents of each
|
||||
dumped directory in special data blocks called @dfn{dumpdirs}.
|
||||
|
||||
Dumpdir is a sequence of entries of the following form:
|
||||
|
||||
@smallexample
|
||||
@var{C} @var{filename} \0
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
where @var{C} is one of the @dfn{control codes} described below,
|
||||
@var{filename} is the name of the file @var{C} operates upon, and
|
||||
@samp{\0} represents a nul character (ASCII 0). The white space
|
||||
characters were added for readability, real dumpdirs do not contain
|
||||
them.
|
||||
|
||||
Each dumpdir ends with a single nul character.
|
||||
|
||||
The following table describes control codes and their meanings:
|
||||
|
||||
@table @samp
|
||||
@item Y
|
||||
@var{filename} is contained in the archive.
|
||||
|
||||
@item N
|
||||
@var{filename} was present in the directory at the time the archive
|
||||
was made, yet it was not dumped to the archive, because it had not
|
||||
changed since the last backup.
|
||||
|
||||
@item D
|
||||
@var{filename} is a directory.
|
||||
|
||||
@item R
|
||||
This code requests renaming of the @var{filename} to the name
|
||||
specified with the following @samp{T} command.
|
||||
|
||||
@item T
|
||||
Specify target file name for @samp{R} command (see below).
|
||||
|
||||
@item X
|
||||
Specify @dfn{temporary directory} name for a rename operation (see below).
|
||||
@end table
|
||||
|
||||
Codes @samp{Y}, @samp{N} and @samp{D} require @var{filename} argument
|
||||
to be a relative file name to the directory this dumpdir describes,
|
||||
whereas codes @samp{R}, @samp{T} and @samp{X} require their argument
|
||||
to be an absolute file name.
|
||||
|
||||
The three codes @samp{R}, @samp{T} and @samp{X} specify a
|
||||
@dfn{renaming operation}. In the simplest case it is:
|
||||
|
||||
@smallexample
|
||||
R@file{source}\0T@file{dest}\0
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
which means ``rename file @file{source} to file @file{dest}''.
|
||||
|
||||
However, there are cases that require using a @dfn{temporary
|
||||
directory}. For example, consider the following scenario:
|
||||
|
||||
@enumerate 1
|
||||
@item
|
||||
Previous run dumped a directory @file{foo} which contained the
|
||||
following three directories:
|
||||
|
||||
@smallexample
|
||||
a
|
||||
b
|
||||
c
|
||||
@end smallexample
|
||||
|
||||
@item
|
||||
They were renamed @emph{cyclically}, so that:
|
||||
|
||||
@example
|
||||
@file{a} became @file{b}
|
||||
@file{b} became @file{c}
|
||||
@file{c} became @file{a}
|
||||
@end example
|
||||
|
||||
@item
|
||||
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
|
||||
readability):
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
Xfoo\0
|
||||
Rfoo/a\0T\0
|
||||
Rfoo/b\0Tfoo/c\0
|
||||
Rfoo/c\0Tfoo/a\0
|
||||
R\0Tfoo/a\0
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
The first command, @samp{Xfoo\0}, instructs the extractor to create a
|
||||
temporary directory in the directory @file{foo}. Second command,
|
||||
@samp{Rfoo/aT\0}, says ``rename file @file{foo/a} to the temporary
|
||||
directory that has just been created'' (empty file name after a
|
||||
command means use temporary directory). Third and fourth commands
|
||||
work as usual, and, finally, the last command, @samp{R\0Tfoo/a\0}
|
||||
tells tar to rename the temporary directory to @file{foo/a}.
|
||||
|
||||
The exact placement of a dumpdir in the archive depends on the
|
||||
archive format (@pxref{Formats}):
|
||||
|
||||
@itemize
|
||||
@item PAX archives
|
||||
|
||||
In PAX archives, dumpdir is stored in the extended header of the
|
||||
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 precedes a data
|
||||
block containing the dumpdir.
|
||||
@end itemize
|
||||
|
||||
@c End of dumpdir.texi
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
@display
|
||||
Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
108
doc/gendocs_template
Executable file
108
doc/gendocs_template
Executable file
@@ -0,0 +1,108 @@
|
||||
<?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.3 2007/01/19 15:41:39 gray Exp $ -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
|
||||
<head>
|
||||
<title>%%TITLE%% - GNU Project - Free Software Foundation (FSF)</title>
|
||||
<meta http-equiv="content-type" content='text/html; charset=utf-8' />
|
||||
<link rel="stylesheet" type="text/css" href="/gnu.css" />
|
||||
<link rev="made" href="mailto:gray@gnu.org" />
|
||||
<link rel="icon" type="image/png" href="/graphics/gnu-head-icon.png" />
|
||||
</head>
|
||||
|
||||
<!-- This document is in XML, and xhtml 1.0 -->
|
||||
<!-- Please make sure to properly nest your tags -->
|
||||
<!-- and ensure that your final document validates -->
|
||||
<!-- consistent with W3C xhtml 1.0 and CSS standards -->
|
||||
<!-- See validator.w3.org -->
|
||||
|
||||
<body>
|
||||
|
||||
<h3>%%TITLE%%</h3>
|
||||
|
||||
<address>Free Software Foundation</address>
|
||||
<address>last updated %%DATE%%</address>
|
||||
<p>
|
||||
<a href="/graphics/gnu-head.jpg">
|
||||
<img src="/graphics/gnu-head-sm.jpg"
|
||||
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>
|
||||
|
||||
<ul>
|
||||
<li><a href="%%PACKAGE%%.html">HTML
|
||||
(%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li>
|
||||
<li><a href="html_node/index.html">HTML</a> - with one web page per
|
||||
node.</li>
|
||||
<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
|
||||
(%%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
|
||||
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt">ASCII text
|
||||
(%%ASCII_SIZE%%K characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed
|
||||
(%%ASCII_GZ_SIZE%%K gzipped characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file
|
||||
(%%DVI_GZ_SIZE%%K characters gzipped)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.ps.gz">PostScript file
|
||||
(%%PS_GZ_SIZE%%K characters gzipped)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.pdf">PDF file
|
||||
(%%PDF_SIZE%%K characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source
|
||||
(%%TEXI_TGZ_SIZE%%K characters gzipped tar file)</a></li>
|
||||
</ul>
|
||||
|
||||
<p>(This page generated by the <a
|
||||
href="%%SCRIPTURL%%">%%SCRIPTNAME%%</a> script.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0!" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
<div class="copyright">
|
||||
<p>
|
||||
Return to the <a href="/home.html">GNU Project home page</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Please send FSF & GNU inquiries to
|
||||
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
|
||||
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
|
||||
the FSF.
|
||||
<br />
|
||||
Please send broken links and other corrections (or suggestions) to
|
||||
<a href="mailto:webmasters@gnu.org"><em>webmasters@gnu.org</em></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02111, USA
|
||||
<br />
|
||||
Verbatim copying and distribution of this entire article is
|
||||
permitted in any medium, provided this notice is preserved.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Updated:
|
||||
<!-- timestamp start -->
|
||||
$Date: 2007/01/19 15:41:39 $ $Author: gray $
|
||||
<!-- timestamp end -->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
478
doc/getdate.texi
478
doc/getdate.texi
@@ -1,478 +0,0 @@
|
||||
@c GNU date syntax documentation
|
||||
|
||||
@c Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
@c 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
@c Permission is granted to copy, distribute and/or modify this document
|
||||
@c under the terms of the GNU Free Documentation License, Version 1.1 or
|
||||
@c any later version published by the Free Software Foundation; with no
|
||||
@c Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
@c Texts. A copy of the license is included in the ``GNU Free
|
||||
@c Documentation License'' file as part of this distribution.
|
||||
|
||||
@node Date input formats
|
||||
@chapter Date input formats
|
||||
|
||||
@cindex date input formats
|
||||
@findex get_date
|
||||
|
||||
First, a quote:
|
||||
|
||||
@quotation
|
||||
Our units of temporal measurement, from seconds on up to months, are so
|
||||
complicated, asymmetrical and disjunctive so as to make coherent mental
|
||||
reckoning in time all but impossible. Indeed, had some tyrannical god
|
||||
contrived to enslave our minds to time, to make it all but impossible
|
||||
for us to escape subjection to sodden routines and unpleasant surprises,
|
||||
he could hardly have done better than handing down our present system.
|
||||
It is like a set of trapezoidal building blocks, with no vertical or
|
||||
horizontal surfaces, like a language in which the simplest thought
|
||||
demands ornate constructions, useless particles and lengthy
|
||||
circumlocutions. Unlike the more successful patterns of language and
|
||||
science, which enable us to face experience boldly or at least
|
||||
level-headedly, our system of temporal calculation silently and
|
||||
persistently encourages our terror of time.
|
||||
|
||||
@dots{} It is as though architects had to measure length in feet, width
|
||||
in meters and height in ells; as though basic instruction manuals
|
||||
demanded a knowledge of five different languages. It is no wonder then
|
||||
that we often look into our own immediate past or future, last Tuesday
|
||||
or a week from Sunday, with feelings of helpless confusion. @dots{}
|
||||
|
||||
--- Robert Grudin, @cite{Time and the Art of Living}.
|
||||
@end quotation
|
||||
|
||||
This section describes the textual date representations that @sc{gnu}
|
||||
programs accept. These are the strings you, as a user, can supply as
|
||||
arguments to the various programs. The C interface (via the
|
||||
@code{get_date} function) is not described here.
|
||||
|
||||
@menu
|
||||
* General date syntax:: Common rules.
|
||||
* Calendar date items:: 19 Dec 1994.
|
||||
* Time of day items:: 9:20pm.
|
||||
* Time zone items:: @sc{est}, @sc{pdt}, @sc{gmt}, ...
|
||||
* Day of week items:: Monday and others.
|
||||
* Relative items in date strings:: next tuesday, 2 years ago.
|
||||
* Pure numbers in date strings:: 19931219, 1440.
|
||||
* Seconds since the Epoch:: @@1078100502.
|
||||
* Authors of get_date:: Bellovin, Eggert, Salz, Berets, et al.
|
||||
@end menu
|
||||
|
||||
|
||||
@node General date syntax
|
||||
@section General date syntax
|
||||
|
||||
@cindex general date syntax
|
||||
|
||||
@cindex items in date strings
|
||||
A @dfn{date} is a string, possibly empty, containing many items
|
||||
separated by whitespace. The whitespace may be omitted when no
|
||||
ambiguity arises. The empty string means the beginning of today (i.e.,
|
||||
midnight). Order of the items is immaterial. A date string may contain
|
||||
many flavors of items:
|
||||
|
||||
@itemize @bullet
|
||||
@item calendar date items
|
||||
@item time of the day items
|
||||
@item time zone items
|
||||
@item day of the week items
|
||||
@item relative items
|
||||
@item pure numbers.
|
||||
@end itemize
|
||||
|
||||
@noindent We describe each of these item types in turn, below.
|
||||
|
||||
@cindex numbers, written-out
|
||||
@cindex ordinal numbers
|
||||
@findex first @r{in date strings}
|
||||
@findex next @r{in date strings}
|
||||
@findex last @r{in date strings}
|
||||
A few numbers may be written out in words in most contexts. This is
|
||||
most useful for specifying day of the week items or relative items (see
|
||||
below). Here is the list: @samp{first} for 1, @samp{next} for 2,
|
||||
@samp{third} for 3, @samp{fourth} for 4, @samp{fifth} for 5,
|
||||
@samp{sixth} for 6, @samp{seventh} for 7, @samp{eighth} for 8,
|
||||
@samp{ninth} for 9, @samp{tenth} for 10, @samp{eleventh} for 11 and
|
||||
@samp{twelfth} for 12. Also, @samp{last} means exactly @math{-1}.
|
||||
|
||||
@cindex months, written-out
|
||||
When a month is written this way, it is still considered to be written
|
||||
numerically, instead of being ``spelled in full''; this changes the
|
||||
allowed strings.
|
||||
|
||||
@cindex language, in dates
|
||||
In the current implementation, only English is supported for words and
|
||||
abbreviations like @samp{AM}, @samp{DST}, @samp{EST}, @samp{first},
|
||||
@samp{January}, @samp{Sunday}, @samp{tomorrow}, and @samp{year}.
|
||||
|
||||
@cindex language, in dates
|
||||
@cindex time zone item
|
||||
The output of @command{date} is not always acceptable as a date string,
|
||||
not only because of the language problem, but also because there is no
|
||||
standard meaning for time zone items like @samp{IST}. When using
|
||||
@command{date} to generate a date string intended to be parsed later,
|
||||
specify a date format that is independent of language and that does not
|
||||
use time zone items other than @samp{UTC} and @samp{Z}. Here are some
|
||||
ways to do this:
|
||||
|
||||
@example
|
||||
$ LC_ALL=C TZ=UTC0 date
|
||||
Mon Mar 1 00:21:42 UTC 2004
|
||||
$ TZ=UTC0 date +'%Y-%m-%d %H:%M:%SZ'
|
||||
2004-03-01 00:21:42Z
|
||||
$ date --iso-8601=ns # a GNU extension
|
||||
2004-02-29T16:21:42,692722128-0800
|
||||
$ date --rfc-2822 # a GNU extension
|
||||
Sun, 29 Feb 2004 16:21:42 -0800
|
||||
$ date +'%Y-%m-%d %H:%M:%S %z' # %z is a GNU extension.
|
||||
2004-02-29 16:21:42 -0800
|
||||
$ date +'@@%s.%N' # %s and %N are GNU extensions.
|
||||
@@1078100502.692722128
|
||||
@end example
|
||||
|
||||
@cindex case, ignored in dates
|
||||
@cindex comments, in dates
|
||||
Alphabetic case is completely ignored in dates. Comments may be introduced
|
||||
between round parentheses, as long as included parentheses are properly
|
||||
nested. Hyphens not followed by a digit are currently ignored. Leading
|
||||
zeros on numbers are ignored.
|
||||
|
||||
|
||||
@node Calendar date items
|
||||
@section Calendar date items
|
||||
|
||||
@cindex calendar date item
|
||||
|
||||
A @dfn{calendar date item} specifies a day of the year. It is
|
||||
specified differently, depending on whether the month is specified
|
||||
numerically or literally. All these strings specify the same calendar date:
|
||||
|
||||
@example
|
||||
1972-09-24 # @sc{iso} 8601.
|
||||
72-9-24 # Assume 19xx for 69 through 99,
|
||||
# 20xx for 00 through 68.
|
||||
72-09-24 # Leading zeros are ignored.
|
||||
9/24/72 # Common U.S. writing.
|
||||
24 September 1972
|
||||
24 Sept 72 # September has a special abbreviation.
|
||||
24 Sep 72 # Three-letter abbreviations always allowed.
|
||||
Sep 24, 1972
|
||||
24-sep-72
|
||||
24sep72
|
||||
@end example
|
||||
|
||||
The year can also be omitted. In this case, the last specified year is
|
||||
used, or the current year if none. For example:
|
||||
|
||||
@example
|
||||
9/24
|
||||
sep 24
|
||||
@end example
|
||||
|
||||
Here are the rules.
|
||||
|
||||
@cindex @sc{iso} 8601 date format
|
||||
@cindex date format, @sc{iso} 8601
|
||||
For numeric months, the @sc{iso} 8601 format
|
||||
@samp{@var{year}-@var{month}-@var{day}} is allowed, where @var{year} is
|
||||
any positive number, @var{month} is a number between 01 and 12, and
|
||||
@var{day} is a number between 01 and 31. A leading zero must be present
|
||||
if a number is less than ten. If @var{year} is 68 or smaller, then 2000
|
||||
is added to it; otherwise, if @var{year} is less than 100,
|
||||
then 1900 is added to it. The construct
|
||||
@samp{@var{month}/@var{day}/@var{year}}, popular in the United States,
|
||||
is accepted. Also @samp{@var{month}/@var{day}}, omitting the year.
|
||||
|
||||
@cindex month names in date strings
|
||||
@cindex abbreviations for months
|
||||
Literal months may be spelled out in full: @samp{January},
|
||||
@samp{February}, @samp{March}, @samp{April}, @samp{May}, @samp{June},
|
||||
@samp{July}, @samp{August}, @samp{September}, @samp{October},
|
||||
@samp{November} or @samp{December}. Literal months may be abbreviated
|
||||
to their first three letters, possibly followed by an abbreviating dot.
|
||||
It is also permitted to write @samp{Sept} instead of @samp{September}.
|
||||
|
||||
When months are written literally, the calendar date may be given as any
|
||||
of the following:
|
||||
|
||||
@example
|
||||
@var{day} @var{month} @var{year}
|
||||
@var{day} @var{month}
|
||||
@var{month} @var{day} @var{year}
|
||||
@var{day}-@var{month}-@var{year}
|
||||
@end example
|
||||
|
||||
Or, omitting the year:
|
||||
|
||||
@example
|
||||
@var{month} @var{day}
|
||||
@end example
|
||||
|
||||
|
||||
@node Time of day items
|
||||
@section Time of day items
|
||||
|
||||
@cindex time of day item
|
||||
|
||||
A @dfn{time of day item} in date strings specifies the time on a given
|
||||
day. Here are some examples, all of which represent the same time:
|
||||
|
||||
@example
|
||||
20:02:00.000000
|
||||
20:02
|
||||
8:02pm
|
||||
20:02-0500 # In @sc{est} (U.S. Eastern Standard Time).
|
||||
@end example
|
||||
|
||||
More generally, the time of the day may be given as
|
||||
@samp{@var{hour}:@var{minute}:@var{second}}, where @var{hour} is
|
||||
a number between 0 and 23, @var{minute} is a number between 0 and
|
||||
59, and @var{second} is a number between 0 and 59 possibly followed by
|
||||
@samp{.} or @samp{,} and a fraction containing one or more digits.
|
||||
Alternatively,
|
||||
@samp{:@var{second}} can be omitted, in which case it is taken to
|
||||
be zero.
|
||||
|
||||
@findex am @r{in date strings}
|
||||
@findex pm @r{in date strings}
|
||||
@findex midnight @r{in date strings}
|
||||
@findex noon @r{in date strings}
|
||||
If the time is followed by @samp{am} or @samp{pm} (or @samp{a.m.}
|
||||
or @samp{p.m.}), @var{hour} is restricted to run from 1 to 12, and
|
||||
@samp{:@var{minute}} may be omitted (taken to be zero). @samp{am}
|
||||
indicates the first half of the day, @samp{pm} indicates the second
|
||||
half of the day. In this notation, 12 is the predecessor of 1:
|
||||
midnight is @samp{12am} while noon is @samp{12pm}.
|
||||
(This is the zero-oriented interpretation of @samp{12am} and @samp{12pm},
|
||||
as opposed to the old tradition derived from Latin
|
||||
which uses @samp{12m} for noon and @samp{12pm} for midnight.)
|
||||
|
||||
@cindex time zone correction
|
||||
@cindex minutes, time zone correction by
|
||||
The time may alternatively be followed by a time zone correction,
|
||||
expressed as @samp{@var{s}@var{hh}@var{mm}}, where @var{s} is @samp{+}
|
||||
or @samp{-}, @var{hh} is a number of zone hours and @var{mm} is a number
|
||||
of zone minutes. When a time zone correction is given this way, it
|
||||
forces interpretation of the time relative to
|
||||
Coordinated Universal Time (@sc{utc}), overriding any previous
|
||||
specification for the time zone or the local time zone. The @var{minute}
|
||||
part of the time of the day may not be elided when a time zone correction
|
||||
is used. This is the best way to specify a time zone correction by
|
||||
fractional parts of an hour.
|
||||
|
||||
Either @samp{am}/@samp{pm} or a time zone correction may be specified,
|
||||
but not both.
|
||||
|
||||
|
||||
@node Time zone items
|
||||
@section Time zone items
|
||||
|
||||
@cindex time zone item
|
||||
|
||||
A @dfn{time zone item} specifies an international time zone, indicated
|
||||
by a small set of letters, e.g., @samp{UTC} or @samp{Z}
|
||||
for Coordinated Universal
|
||||
Time. Any included periods are ignored. By following a
|
||||
non-daylight-saving time zone by the string @samp{DST} in a separate
|
||||
word (that is, separated by some white space), the corresponding
|
||||
daylight saving time zone may be specified.
|
||||
|
||||
Time zone items other than @samp{UTC} and @samp{Z}
|
||||
are obsolescent and are not recommended, because they
|
||||
are ambiguous; for example, @samp{EST} has a different meaning in
|
||||
Australia than in the United States. Instead, it's better to use
|
||||
unambiguous numeric time zone corrections like @samp{-0500}, as
|
||||
described in the previous section.
|
||||
|
||||
|
||||
@node Day of week items
|
||||
@section Day of week items
|
||||
|
||||
@cindex day of week item
|
||||
|
||||
The explicit mention of a day of the week will forward the date
|
||||
(only if necessary) to reach that day of the week in the future.
|
||||
|
||||
Days of the week may be spelled out in full: @samp{Sunday},
|
||||
@samp{Monday}, @samp{Tuesday}, @samp{Wednesday}, @samp{Thursday},
|
||||
@samp{Friday} or @samp{Saturday}. Days may be abbreviated to their
|
||||
first three letters, optionally followed by a period. The special
|
||||
abbreviations @samp{Tues} for @samp{Tuesday}, @samp{Wednes} for
|
||||
@samp{Wednesday} and @samp{Thur} or @samp{Thurs} for @samp{Thursday} are
|
||||
also allowed.
|
||||
|
||||
@findex next @var{day}
|
||||
@findex last @var{day}
|
||||
A number may precede a day of the week item to move forward
|
||||
supplementary weeks. It is best used in expression like @samp{third
|
||||
monday}. In this context, @samp{last @var{day}} or @samp{next
|
||||
@var{day}} is also acceptable; they move one week before or after
|
||||
the day that @var{day} by itself would represent.
|
||||
|
||||
A comma following a day of the week item is ignored.
|
||||
|
||||
|
||||
@node Relative items in date strings
|
||||
@section Relative items in date strings
|
||||
|
||||
@cindex relative items in date strings
|
||||
@cindex displacement of dates
|
||||
|
||||
@dfn{Relative items} adjust a date (or the current date if none) forward
|
||||
or backward. The effects of relative items accumulate. Here are some
|
||||
examples:
|
||||
|
||||
@example
|
||||
1 year
|
||||
1 year ago
|
||||
3 years
|
||||
2 days
|
||||
@end example
|
||||
|
||||
@findex year @r{in date strings}
|
||||
@findex month @r{in date strings}
|
||||
@findex fortnight @r{in date strings}
|
||||
@findex week @r{in date strings}
|
||||
@findex day @r{in date strings}
|
||||
@findex hour @r{in date strings}
|
||||
@findex minute @r{in date strings}
|
||||
The unit of time displacement may be selected by the string @samp{year}
|
||||
or @samp{month} for moving by whole years or months. These are fuzzy
|
||||
units, as years and months are not all of equal duration. More precise
|
||||
units are @samp{fortnight} which is worth 14 days, @samp{week} worth 7
|
||||
days, @samp{day} worth 24 hours, @samp{hour} worth 60 minutes,
|
||||
@samp{minute} or @samp{min} worth 60 seconds, and @samp{second} or
|
||||
@samp{sec} worth one second. An @samp{s} suffix on these units is
|
||||
accepted and ignored.
|
||||
|
||||
@findex ago @r{in date strings}
|
||||
The unit of time may be preceded by a multiplier, given as an optionally
|
||||
signed number. Unsigned numbers are taken as positively signed. No
|
||||
number at all implies 1 for a multiplier. Following a relative item by
|
||||
the string @samp{ago} is equivalent to preceding the unit by a
|
||||
multiplier with value @math{-1}.
|
||||
|
||||
@findex day @r{in date strings}
|
||||
@findex tomorrow @r{in date strings}
|
||||
@findex yesterday @r{in date strings}
|
||||
The string @samp{tomorrow} is worth one day in the future (equivalent
|
||||
to @samp{day}), the string @samp{yesterday} is worth
|
||||
one day in the past (equivalent to @samp{day ago}).
|
||||
|
||||
@findex now @r{in date strings}
|
||||
@findex today @r{in date strings}
|
||||
@findex this @r{in date strings}
|
||||
The strings @samp{now} or @samp{today} are relative items corresponding
|
||||
to zero-valued time displacement, these strings come from the fact
|
||||
a zero-valued time displacement represents the current time when not
|
||||
otherwise changed by previous items. They may be used to stress other
|
||||
items, like in @samp{12:00 today}. The string @samp{this} also has
|
||||
the meaning of a zero-valued time displacement, but is preferred in
|
||||
date strings like @samp{this thursday}.
|
||||
|
||||
When a relative item causes the resulting date to cross a boundary
|
||||
where the clocks were adjusted, typically for daylight-saving time,
|
||||
the resulting date and time are adjusted accordingly.
|
||||
|
||||
The fuzz in units can cause problems with relative items. For
|
||||
example, @samp{2003-07-31 -1 month} might evaluate to 2003-07-01,
|
||||
because 2003-06-31 is an invalid date. To determine the previous
|
||||
month more reliably, you can ask for the month before the 15th of the
|
||||
current month. For example:
|
||||
|
||||
@example
|
||||
$ date -R
|
||||
Thu, 31 Jul 2003 13:02:39 -0700
|
||||
$ date --date='-1 month' +'Last month was %B?'
|
||||
Last month was July?
|
||||
$ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
|
||||
Last month was June!
|
||||
@end example
|
||||
|
||||
Also, take care when manipulating dates around clock changes such as
|
||||
daylight saving leaps. In a few cases these have added or subtracted
|
||||
as much as 24 hours from the clock, so it is often wise to adopt
|
||||
universal time by setting the @env{TZ} environment variable to
|
||||
@samp{UTC0} before embarking on calendrical calculations.
|
||||
|
||||
@node Pure numbers in date strings
|
||||
@section Pure numbers in date strings
|
||||
|
||||
@cindex pure numbers in date strings
|
||||
|
||||
The precise interpretation of a pure decimal number depends
|
||||
on the context in the date string.
|
||||
|
||||
If the decimal number is of the form @var{yyyy}@var{mm}@var{dd} and no
|
||||
other calendar date item (@pxref{Calendar date items}) appears before it
|
||||
in the date string, then @var{yyyy} is read as the year, @var{mm} as the
|
||||
month number and @var{dd} as the day of the month, for the specified
|
||||
calendar date.
|
||||
|
||||
If the decimal number is of the form @var{hh}@var{mm} and no other time
|
||||
of day item appears before it in the date string, then @var{hh} is read
|
||||
as the hour of the day and @var{mm} as the minute of the hour, for the
|
||||
specified time of the day. @var{mm} can also be omitted.
|
||||
|
||||
If both a calendar date and a time of day appear to the left of a number
|
||||
in the date string, but no relative item, then the number overrides the
|
||||
year.
|
||||
|
||||
|
||||
@node Seconds since the Epoch
|
||||
@section Seconds since the Epoch
|
||||
|
||||
If you precede a number with @samp{@@}, it represents an internal time
|
||||
stamp as a count of seconds. The number can contain an internal
|
||||
decimal point (either @samp{.} or @samp{,}); any excess precision not
|
||||
supported by the internal representation is truncated toward minus
|
||||
infinity.
|
||||
|
||||
@cindex beginning of time, for @acronym{POSIX}
|
||||
@cindex epoch, for @acronym{POSIX}
|
||||
Internally, computer times are represented as a count of seconds since
|
||||
an epoch---a well-defined point of time. On @acronym{GNU} and
|
||||
@acronym{POSIX} systems, the epoch is 1970-01-01 00:00:00 @sc{utc}, so
|
||||
@samp{@@0} represents this time, @samp{@@1} represents 1970-01-01
|
||||
00:00:01 @sc{utc}, and so forth. @acronym{GNU} and most other
|
||||
@acronym{POSIX}-compliant systems support such times as an extension
|
||||
to @acronym{POSIX}, using negative counts, so that @samp{@@-1}
|
||||
represents 1969-12-31 23:59:59 @sc{utc}.
|
||||
|
||||
Traditional Unix systems count seconds with 32-bit two's-complement
|
||||
integers and can represent times from 1901-12-13 20:45:52 through
|
||||
2038-01-19 03:14:07 @sc{utc}. More modern systems use 64-bit counts
|
||||
of seconds with nanosecond subcounts, and can represent all the times
|
||||
in the known lifetime of the universe to a resolution of 1 nanosecond.
|
||||
|
||||
On most systems, these counts ignore the presence of leap seconds.
|
||||
For example, on most systems @samp{@@915148799} represents 1998-12-31
|
||||
23:59:59 @sc{utc}, @samp{@@915148800} represents 1999-01-01 00:00:00
|
||||
@sc{utc}, and there is no way to represent the intervening leap second
|
||||
1998-12-31 23:59:60 @sc{utc}.
|
||||
|
||||
@node Authors of get_date
|
||||
@section Authors of @code{get_date}
|
||||
|
||||
@cindex authors of @code{get_date}
|
||||
|
||||
@cindex Bellovin, Steven M.
|
||||
@cindex Salz, Rich
|
||||
@cindex Berets, Jim
|
||||
@cindex MacKenzie, David
|
||||
@cindex Meyering, Jim
|
||||
@cindex Eggert, Paul
|
||||
@code{get_date} was originally implemented by Steven M. Bellovin
|
||||
(@email{smb@@research.att.com}) while at the University of North Carolina
|
||||
at Chapel Hill. The code was later tweaked by a couple of people on
|
||||
Usenet, then completely overhauled by Rich $alz (@email{rsalz@@bbn.com})
|
||||
and Jim Berets (@email{jberets@@bbn.com}) in August, 1990. Various
|
||||
revisions for the @sc{gnu} system were made by David MacKenzie, Jim Meyering,
|
||||
Paul Eggert and others.
|
||||
|
||||
@cindex Pinard, F.
|
||||
@cindex Berry, K.
|
||||
This chapter was originally produced by Fran@,{c}ois Pinard
|
||||
(@email{pinard@@iro.umontreal.ca}) from the @file{getdate.y} source code,
|
||||
and then edited by K.@: Berry (@email{kb@@cs.umb.edu}).
|
||||
335
doc/intern.texi
Normal file
335
doc/intern.texi
Normal file
@@ -0,0 +1,335 @@
|
||||
@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.
|
||||
|
||||
@menu
|
||||
* Standard:: Basic Tar Format
|
||||
* Extensions:: @acronym{GNU} Extensions to the Archive Format
|
||||
* Sparse Formats:: Storing Sparse Files
|
||||
* Snapshot Files::
|
||||
* Dumpdir::
|
||||
@end menu
|
||||
|
||||
@node Standard
|
||||
@unnumberedsec Basic Tar Format
|
||||
@UNREVISED
|
||||
|
||||
While an archive may contain many files, the archive itself is a
|
||||
single ordinary file. Like any other file, an archive file can be
|
||||
written to a storage device such as a tape or disk, sent through a
|
||||
pipe or over a network, saved on the active file system, or even
|
||||
stored in another archive. An archive file is not easy to read or
|
||||
manipulate without using the @command{tar} utility or Tar mode in
|
||||
@acronym{GNU} Emacs.
|
||||
|
||||
Physically, an archive consists of a series of file entries terminated
|
||||
by an end-of-archive entry, which consists of two 512 blocks of zero
|
||||
bytes. A file
|
||||
entry usually describes one of the files in the archive (an
|
||||
@dfn{archive member}), and consists of a file header and the contents
|
||||
of the file. File headers contain file names and statistics, checksum
|
||||
information which @command{tar} uses to detect file corruption, and
|
||||
information about file types.
|
||||
|
||||
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.
|
||||
@xref{label}, for an example of such an archive entry.
|
||||
|
||||
A @command{tar} archive file contains a series of blocks. Each block
|
||||
contains @code{BLOCKSIZE} bytes. Although this format may be thought
|
||||
of as being on magnetic tape, other media are often used.
|
||||
|
||||
Each file archived is represented by a header block which describes
|
||||
the file, followed by zero or more blocks which give the contents
|
||||
of the file. At the end of the archive file there are two 512-byte blocks
|
||||
filled with binary zeros as an end-of-file marker. A reasonable system
|
||||
should write such end-of-file marker at the end of an archive, but
|
||||
must not assume that such a block exists when reading an archive. In
|
||||
particular @GNUTAR{} always issues a warning if it does not encounter it.
|
||||
|
||||
The blocks may be @dfn{blocked} for physical I/O operations.
|
||||
Each record of @var{n} blocks (where @var{n} is set by the
|
||||
@option{--blocking-factor=@var{512-size}} (@option{-b @var{512-size}}) option to @command{tar}) is written with a single
|
||||
@w{@samp{write ()}} operation. On magnetic tapes, the result of
|
||||
such a write is a single record. When writing an archive,
|
||||
the last record of blocks should be written at the full size, with
|
||||
blocks after the zero block containing all zeros. When reading
|
||||
an archive, a reasonable system should properly handle an archive
|
||||
whose last record is shorter than the rest, or which contains garbage
|
||||
records after a zero block.
|
||||
|
||||
The header block is defined in C as follows. In the @GNUTAR{}
|
||||
distribution, this is part of file @file{src/tar.h}:
|
||||
|
||||
@smallexample
|
||||
@include header.texi
|
||||
@end smallexample
|
||||
|
||||
All characters in header blocks are represented by using 8-bit
|
||||
characters in the local variant of ASCII. Each field within the
|
||||
structure is contiguous; that is, there is no padding used within
|
||||
the structure. Each character on the archive medium is stored
|
||||
contiguously.
|
||||
|
||||
Bytes representing the contents of files (after the header block
|
||||
of each file) are not translated in any way and are not constrained
|
||||
to represent characters in any character set. The @command{tar} format
|
||||
does not distinguish text files from binary files, and no translation
|
||||
of file contents is performed.
|
||||
|
||||
The @code{name}, @code{linkname}, @code{magic}, @code{uname}, and
|
||||
@code{gname} are null-terminated character strings. All other fields
|
||||
are zero-filled octal numbers in ASCII. Each numeric field of width
|
||||
@var{w} contains @var{w} minus 1 digits, and a null.
|
||||
|
||||
The @code{name} field is the file name of the file, with directory names
|
||||
(if any) preceding the file name, separated by slashes.
|
||||
|
||||
@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 @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
|
||||
permissions, the mode bit(s) specifying those special permissions
|
||||
are ignored. Modes which are not supported by the operating system
|
||||
restoring files from the archive will be ignored. Unsupported modes
|
||||
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
|
||||
@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.}
|
||||
|
||||
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
|
||||
value of the last time the file's contents were modified, represented
|
||||
as an integer number of
|
||||
seconds since January 1, 1970, 00:00 Coordinated Universal Time.
|
||||
|
||||
The @code{chksum} field is the ASCII representation of the octal value
|
||||
of the simple sum of all bytes in the header block. Each 8-bit
|
||||
byte in the header is added to an unsigned integer, initialized to
|
||||
zero, the precision of which shall be no less than seventeen bits.
|
||||
When calculating the checksum, the @code{chksum} field is treated as
|
||||
if it were all blanks.
|
||||
|
||||
The @code{typeflag} field specifies the type of file archived. If a
|
||||
particular implementation does not recognize or permit the specified
|
||||
type, the file will be extracted as if it were a regular file. As this
|
||||
action occurs, @command{tar} issues a warning to the standard error.
|
||||
|
||||
The @code{atime} and @code{ctime} fields are used in making incremental
|
||||
backups; they store, respectively, the particular file's access and
|
||||
status change times.
|
||||
|
||||
The @code{offset} is used by the @option{--multi-volume} (@option{-M}) option, when
|
||||
making a multi-volume archive. The offset is number of bytes into
|
||||
the file that we need to restart at to continue the file on the next
|
||||
tape, i.e., where we store the location that a continued file is
|
||||
continued at.
|
||||
|
||||
The following fields were added to deal with sparse files. A file
|
||||
is @dfn{sparse} if it takes in unallocated blocks which end up being
|
||||
represented as zeros, i.e., no useful data. A test to see if a file
|
||||
is sparse is to look at the number blocks allocated for it versus the
|
||||
number of characters in the file; if there are fewer blocks allocated
|
||||
for the file than would normally be allocated for a file of that
|
||||
size, then the file is sparse. This is the method @command{tar} uses to
|
||||
detect a sparse file, and once such a file is detected, it is treated
|
||||
differently from non-sparse files.
|
||||
|
||||
Sparse files are often @code{dbm} files, or other database-type files
|
||||
which have data at some points and emptiness in the greater part of
|
||||
the file. Such files can appear to be very large when an @samp{ls
|
||||
-l} is done on them, when in truth, there may be a very small amount
|
||||
of important data contained in the file. It is thus undesirable
|
||||
to have @command{tar} think that it must back up this entire file, as
|
||||
great quantities of room are wasted on empty blocks, which can lead
|
||||
to running out of room on a tape far earlier than is necessary.
|
||||
Thus, sparse files are dealt with so that these empty blocks are
|
||||
not written to the tape. Instead, what is written to the tape is a
|
||||
description, of sorts, of the sparse file: where the holes are, how
|
||||
big the holes are, and how much data is found at the end of the hole.
|
||||
This way, the file takes up potentially far less room on the tape,
|
||||
and when the file is extracted later on, it will look exactly the way
|
||||
it looked beforehand. The following is a description of the fields
|
||||
used to handle a sparse file:
|
||||
|
||||
The @code{sp} is an array of @code{struct sparse}. Each @code{struct
|
||||
sparse} contains two 12-character strings which represent an offset
|
||||
into the file and a number of bytes to be written at that offset.
|
||||
The offset is absolute, and not relative to the offset in preceding
|
||||
array element.
|
||||
|
||||
The header can hold four of these @code{struct sparse} at the moment;
|
||||
if more are needed, they are not stored in the header.
|
||||
|
||||
The @code{isextended} flag is set when an @code{extended_header}
|
||||
is needed to deal with a file. Note that this means that this flag
|
||||
can only be set when dealing with a sparse file, and it is only set
|
||||
in the event that the description of the file will not fit in the
|
||||
allotted room for sparse structures in the header. In other words,
|
||||
an extended_header is needed.
|
||||
|
||||
The @code{extended_header} structure is used for sparse files which
|
||||
need more sparse structures than can fit in the header. The header can
|
||||
fit 4 such structures; if more are needed, the flag @code{isextended}
|
||||
gets set and the next block is an @code{extended_header}.
|
||||
|
||||
Each @code{extended_header} structure contains an array of 21
|
||||
sparse structures, along with a similar @code{isextended} flag
|
||||
that the header had. There can be an indeterminate number of such
|
||||
@code{extended_header}s to describe a sparse file.
|
||||
|
||||
@table @asis
|
||||
|
||||
@item @code{REGTYPE}
|
||||
@itemx @code{AREGTYPE}
|
||||
These flags represent a regular file. In order to be compatible
|
||||
with older versions of @command{tar}, a @code{typeflag} value of
|
||||
@code{AREGTYPE} should be silently recognized as a regular file.
|
||||
New archives should be created using @code{REGTYPE}. Also, for
|
||||
backward compatibility, @command{tar} treats a regular file whose name
|
||||
ends with a slash as a directory.
|
||||
|
||||
@item @code{LNKTYPE}
|
||||
This flag represents a file linked to another file, of any type,
|
||||
previously archived. Such files are identified in Unix by each
|
||||
file having the same device and inode number. The linked-to name is
|
||||
specified in the @code{linkname} field with a trailing null.
|
||||
|
||||
@item @code{SYMTYPE}
|
||||
This represents a symbolic link to another file. The linked-to name
|
||||
is specified in the @code{linkname} field with a trailing null.
|
||||
|
||||
@item @code{CHRTYPE}
|
||||
@itemx @code{BLKTYPE}
|
||||
These represent character special files and block special files
|
||||
respectively. In this case the @code{devmajor} and @code{devminor}
|
||||
fields will contain the major and minor device numbers respectively.
|
||||
Operating systems may map the device specifications to their own
|
||||
local specification, or may ignore the entry.
|
||||
|
||||
@item @code{DIRTYPE}
|
||||
This flag specifies a directory or sub-directory. The directory
|
||||
name in the @code{name} field should end with a slash. On systems where
|
||||
disk allocation is performed on a directory basis, the @code{size} field
|
||||
will contain the maximum number of bytes (which may be rounded to
|
||||
the nearest disk block allocation unit) which the directory may
|
||||
hold. A @code{size} field of zero indicates no such limiting. Systems
|
||||
which do not support limiting in this manner should ignore the
|
||||
@code{size} field.
|
||||
|
||||
@item @code{FIFOTYPE}
|
||||
This specifies a FIFO special file. Note that the archiving of a
|
||||
FIFO file archives the existence of this file and not its contents.
|
||||
|
||||
@item @code{CONTTYPE}
|
||||
This specifies a contiguous file, which is the same as a normal
|
||||
file except that, in operating systems which support it, all its
|
||||
space is allocated contiguously on the disk. Operating systems
|
||||
which do not allow contiguous allocation should silently treat this
|
||||
type as a normal file.
|
||||
|
||||
@item @code{A} @dots{} @code{Z}
|
||||
These are reserved for custom implementations. Some of these are
|
||||
used in the @acronym{GNU} modified format, as described below.
|
||||
|
||||
@end table
|
||||
|
||||
Other values are reserved for specification in future revisions of
|
||||
the P1003 standard, and should not be used by any @command{tar} program.
|
||||
|
||||
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 @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
|
||||
169-173 (section 10.1) for @cite{Archive/Interchange File Format}; and
|
||||
IEEE Std 1003.2-1992, pages 380-388 (section 4.48) and pages 936-940
|
||||
(section E.4.48) for @cite{pax - Portable archive interchange}.
|
||||
|
||||
@node Extensions
|
||||
@unnumberedsec @acronym{GNU} Extensions to the Archive Format
|
||||
@UNREVISED
|
||||
|
||||
The @acronym{GNU} format uses additional file types to describe new types of
|
||||
files in an archive. These are listed below.
|
||||
|
||||
@table @code
|
||||
@item GNUTYPE_DUMPDIR
|
||||
@itemx 'D'
|
||||
This represents a directory and a list of files created by the
|
||||
@option{--incremental} (@option{-G}) option. The @code{size} field gives the total
|
||||
size of the associated list of files. Each file name is preceded by
|
||||
either a @samp{Y} (the file should be in this archive) or an @samp{N}.
|
||||
(The file is a directory, or is not stored in the archive.) Each file
|
||||
name is terminated by a null. There is an additional null after the
|
||||
last file name.
|
||||
|
||||
@item GNUTYPE_MULTIVOL
|
||||
@itemx 'M'
|
||||
This represents a file continued from another volume of a multi-volume
|
||||
archive created with the @option{--multi-volume} (@option{-M}) option. The original
|
||||
type of the file is not given here. The @code{size} field gives the
|
||||
maximum size of this piece of the file (assuming the volume does
|
||||
not end before the file is written out). The @code{offset} field
|
||||
gives the offset from the beginning of the file where this part of
|
||||
the file begins. Thus @code{size} plus @code{offset} should equal
|
||||
the original size of the file.
|
||||
|
||||
@item GNUTYPE_SPARSE
|
||||
@itemx 'S'
|
||||
This flag indicates that we are dealing with a sparse file. Note
|
||||
that archiving a sparse file requires special operations to find
|
||||
holes in the file, which mark the positions of these holes, along
|
||||
with the number of bytes of data to be found after the hole.
|
||||
|
||||
@item GNUTYPE_VOLHDR
|
||||
@itemx 'V'
|
||||
This file type is used to mark the volume header that was given with
|
||||
the @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) option when the archive was created. The @code{name}
|
||||
field contains the @code{name} given after the @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) option.
|
||||
The @code{size} field is zero. Only the first file in each volume
|
||||
of an archive should have this type.
|
||||
|
||||
@end table
|
||||
|
||||
You may have trouble reading a @acronym{GNU} format archive on a
|
||||
non-@acronym{GNU} system if the options @option{--incremental} (@option{-G}),
|
||||
@option{--multi-volume} (@option{-M}), @option{--sparse} (@option{-S}), or @option{--label=@var{archive-label}} (@option{-V @var{archive-label}}) were
|
||||
used when writing the archive. In general, if @command{tar} does not
|
||||
use the @acronym{GNU}-added fields of the header, other versions of
|
||||
@command{tar} should be able to read the archive. Otherwise, the
|
||||
@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
|
||||
|
||||
@node Dumpdir
|
||||
@unnumberedsec Dumpdir
|
||||
@include dumpdir.texi
|
||||
|
||||
91
doc/mastermenu.el
Normal file
91
doc/mastermenu.el
Normal file
@@ -0,0 +1,91 @@
|
||||
;;; mastermenu.el --- Redefinition of texinfo-master-menu-list
|
||||
|
||||
;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Sergey Poznyakoff
|
||||
;; Maintainer: bug-tar@gnu.org
|
||||
;; Keywords: maint, tex, docs
|
||||
|
||||
;; This file is part of GNU tar documentation suite
|
||||
|
||||
;; This 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.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file redefines texinfo-master-menu-list so that it takes into
|
||||
;; account included files.
|
||||
|
||||
;; Known bugs: @menu without previous sectioning command will inherit
|
||||
;; documentation string from the previous menu. However, since such a
|
||||
;; menu is illegal in a texinfo file, we can live with it.
|
||||
|
||||
(require 'texinfo)
|
||||
(require 'texnfo-upd)
|
||||
|
||||
(defun texinfo-master-menu-list-recursive (title)
|
||||
"Auxiliary function used by `texinfo-master-menu-list'."
|
||||
(save-excursion
|
||||
(let (master-menu-list)
|
||||
(while (re-search-forward "\\(^@menu\\|^@include\\)" nil t)
|
||||
(cond
|
||||
((string= (match-string 0) "@include")
|
||||
(skip-chars-forward " \t")
|
||||
(let ((included-name (let ((start (point)))
|
||||
(end-of-line)
|
||||
(skip-chars-backward " \t")
|
||||
(buffer-substring start (point)))))
|
||||
(end-of-line)
|
||||
(let ((prev-title (texinfo-copy-menu-title)))
|
||||
(save-excursion
|
||||
(set-buffer (find-file-noselect included-name))
|
||||
(setq master-menu-list
|
||||
(append (texinfo-master-menu-list-recursive prev-title)
|
||||
master-menu-list))))))
|
||||
(t
|
||||
(setq master-menu-list
|
||||
(cons (list
|
||||
(texinfo-copy-menu)
|
||||
(let ((menu-title (texinfo-copy-menu-title)))
|
||||
(if (string= menu-title "")
|
||||
title
|
||||
menu-title)))
|
||||
master-menu-list)))))
|
||||
master-menu-list)))
|
||||
|
||||
(defun texinfo-master-menu-list ()
|
||||
"Return a list of menu entries and header lines for the master menu,
|
||||
recursing into included files.
|
||||
|
||||
Start with the menu for chapters and indices and then find each
|
||||
following menu and the title of the node preceding that menu.
|
||||
|
||||
The master menu list has this form:
|
||||
|
||||
\(\(\(... \"entry-1-2\" \"entry-1\"\) \"title-1\"\)
|
||||
\(\(... \"entry-2-2\" \"entry-2-1\"\) \"title-2\"\)
|
||||
...\)
|
||||
|
||||
However, there does not need to be a title field."
|
||||
|
||||
(reverse (texinfo-master-menu-list-recursive "")))
|
||||
|
||||
(defun make-master-menu ()
|
||||
"Create master menu in the first Emacs argument."
|
||||
(find-file (car command-line-args-left))
|
||||
(texinfo-master-menu nil)
|
||||
(save-buffer))
|
||||
|
||||
|
||||
;;; mastermenu.el ends here
|
||||
90
doc/rendition.texi
Normal file
90
doc/rendition.texi
Normal file
@@ -0,0 +1,90 @@
|
||||
@c This is part of GNU tar manual.
|
||||
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
@c 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
@c See file tar.texi for copying conditions.
|
||||
|
||||
@c This file contains support for 'renditions' by Fran@,{c}ois Pinard
|
||||
@c I extended it by adding a FIXME_FOOTNOTE variable, which controls
|
||||
@c whether FIXME information should be placed in footnotes or
|
||||
@c inlined. --gray
|
||||
|
||||
@c ======================================================================
|
||||
@c This document has three levels of rendition: PUBLISH, DISTRIB or PROOF,
|
||||
@c as decided by @set symbols. The PUBLISH rendition does not show
|
||||
@c notes or marks asking for revision. Most users will prefer having more
|
||||
@c information, even if this information is not fully revised for adequacy,
|
||||
@c so DISTRIB is the default for distributions. The PROOF rendition
|
||||
@c show all marks to the point of ugliness, but is nevertheless useful to
|
||||
@c those working on the manual itself.
|
||||
@c ======================================================================
|
||||
|
||||
@c Set this symbol if you wish FIXMEs to appear in footnotes, instead
|
||||
@c of being inserted into the text.
|
||||
@c @set PROOF_FOOTNOTED
|
||||
|
||||
@ifclear PUBLISH
|
||||
@ifclear DISTRIB
|
||||
@ifclear PROOF
|
||||
@set DISTRIB
|
||||
@end ifclear
|
||||
@end ifclear
|
||||
@end ifclear
|
||||
|
||||
@ifset PUBLISH
|
||||
@set RENDITION The book, version
|
||||
@end ifset
|
||||
|
||||
@ifset DISTRIB
|
||||
@set RENDITION FTP release, version
|
||||
@end ifset
|
||||
|
||||
@ifset PROOF
|
||||
@set RENDITION Proof reading version
|
||||
@end ifset
|
||||
|
||||
@c Output marks for nodes needing revision, but not in PUBLISH rendition.
|
||||
|
||||
@macro UNREVISED
|
||||
@ifclear PUBLISH
|
||||
@quotation
|
||||
@emph{(This message will disappear, once this node revised.)}
|
||||
@end quotation
|
||||
@end ifclear
|
||||
@end macro
|
||||
|
||||
@c Output various FIXME information only in PROOF rendition.
|
||||
|
||||
@macro FIXME{string}
|
||||
@ifset PROOF
|
||||
@ifset PROOF_FOOTNOTED
|
||||
@footnote{@strong{FIXME:} \string\}
|
||||
@end ifset
|
||||
@ifclear PROOF_FOOTNOTED
|
||||
@cartouche
|
||||
@strong{<FIXME>} \string\ @strong{</>}
|
||||
@end cartouche
|
||||
@end ifclear
|
||||
@end ifset
|
||||
|
||||
@end macro
|
||||
|
||||
@macro FIXME-ref{string}
|
||||
@ifset PROOF
|
||||
@strong{<REF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@end macro
|
||||
|
||||
@macro FIXME-pxref{string}
|
||||
@ifset PROOF
|
||||
@strong{<PXREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
|
||||
@end macro
|
||||
|
||||
@macro FIXME-xref{string}
|
||||
@ifset PROOF
|
||||
@strong{<XREF>} \string\ @strong{</>}
|
||||
@end ifset
|
||||
@end macro
|
||||
|
||||
@c End of rendition.texi
|
||||
66
doc/snapshot.texi
Normal file
66
doc/snapshot.texi
Normal file
@@ -0,0 +1,66 @@
|
||||
@c This is part of the paxutils manual.
|
||||
@c Copyright (C) 2005 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 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
|
||||
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.
|
||||
|
||||
@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:
|
||||
|
||||
@smallexample
|
||||
[@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.
|
||||
|
||||
@samp{Format 1} snapshot file begins with a line specifying the
|
||||
format of the file. This line has the following structure:
|
||||
|
||||
@smallexample
|
||||
@samp{GNU tar-}@var{tar-version}@samp{-}@var{incr-format-version}
|
||||
@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}).
|
||||
|
||||
The following 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 metadata, one line per
|
||||
directory. The line format is:
|
||||
|
||||
@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
|
||||
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}.
|
||||
|
||||
|
||||
@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
|
||||
|
||||
8514
doc/tar.texi
8514
doc/tar.texi
File diff suppressed because it is too large
Load Diff
26
doc/texify.sed
Normal file
26
doc/texify.sed
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# GNU tar is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3, or (at
|
||||
# your option) any later version.
|
||||
#
|
||||
# GNU tar is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU tar; if not, write to the Free Software
|
||||
# Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
1{s,/\*,@comment ,
|
||||
b
|
||||
}
|
||||
2,/.*\*\//{s,\*/,,;s/^/@comment/
|
||||
b
|
||||
}
|
||||
/\/* END \*\//,$d
|
||||
s/\([{}]\)/@\1/g
|
||||
s,/\*,&@r{,
|
||||
s,\*/,}&,
|
||||
22
doc/value.texi
Normal file
22
doc/value.texi
Normal file
@@ -0,0 +1,22 @@
|
||||
@c This is part of GNU tar manual.
|
||||
@c Copyright (C) 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
@c 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
@c See file tar.texi for copying conditions.
|
||||
|
||||
@macro GNUTAR
|
||||
@acronym{GNU} @command{tar}
|
||||
@end macro
|
||||
|
||||
@macro xopindex{option,text}
|
||||
@opindex \option\@r{, \text\}
|
||||
@end macro
|
||||
|
||||
@macro opsummary{option}
|
||||
@ifclear ANCHOR--\option\
|
||||
@set ANCHOR--\option\ 1
|
||||
@anchor{--\option\}
|
||||
@end ifclear
|
||||
@xopindex{\option\, summary}
|
||||
@end macro
|
||||
|
||||
|
||||
58
gnulib.modules
Normal file
58
gnulib.modules
Normal file
@@ -0,0 +1,58 @@
|
||||
# List of gnulib modules needed for GNU tar.
|
||||
# A module name per line. Empty lines and comments are ignored.
|
||||
|
||||
alloca
|
||||
argmatch
|
||||
argp
|
||||
backupfile
|
||||
closeout
|
||||
configmake
|
||||
dirname
|
||||
error
|
||||
exclude
|
||||
exitfail
|
||||
fileblocks
|
||||
fnmatch-gnu
|
||||
ftruncate
|
||||
full-write
|
||||
getdate
|
||||
getline
|
||||
getopt
|
||||
getpagesize
|
||||
gettext
|
||||
gettime
|
||||
hash
|
||||
human
|
||||
inttypes
|
||||
lchown
|
||||
localcharset
|
||||
memset
|
||||
mkdtemp
|
||||
modechange
|
||||
obstack
|
||||
quote
|
||||
quotearg
|
||||
rmdir
|
||||
rpmatch
|
||||
safe-read
|
||||
save-cwd
|
||||
savedir
|
||||
setenv
|
||||
stat-time
|
||||
stdbool
|
||||
stdint
|
||||
stpcpy
|
||||
strdup
|
||||
strerror
|
||||
strtol
|
||||
strtoul
|
||||
timespec
|
||||
unlinkdir
|
||||
unlocked-io
|
||||
utime
|
||||
utimens
|
||||
version-etc-fsf
|
||||
xalloc
|
||||
xalloc-die
|
||||
xgetcwd
|
||||
xstrtoumax
|
||||
166
lib/.cvsignore
166
lib/.cvsignore
@@ -1,99 +1,235 @@
|
||||
.deps
|
||||
.cvsignore
|
||||
Makefile
|
||||
Makefile.am
|
||||
Makefile.in
|
||||
addext.c
|
||||
__fpending.c
|
||||
__fpending.h
|
||||
alloca.c
|
||||
alloca.h
|
||||
alloca_.h
|
||||
allocsa.c
|
||||
allocsa.h
|
||||
allocsa.valgrind
|
||||
argmatch.c
|
||||
argmatch.h
|
||||
argp-ba.c
|
||||
argp-eexst.c
|
||||
argp-fmtstream.c
|
||||
argp-fmtstream.h
|
||||
argp-fs-xinl.c
|
||||
argp-help.c
|
||||
argp-namefrob.h
|
||||
argp-parse.c
|
||||
argp-pin.c
|
||||
argp-pv.c
|
||||
argp-pvh.c
|
||||
argp-xinl.c
|
||||
argp.h
|
||||
asnprintf.c
|
||||
at-func.c
|
||||
backupfile.c
|
||||
backupfile.h
|
||||
basename.c
|
||||
canonicalize-lgpl.c
|
||||
canonicalize.h
|
||||
chdir-long.c
|
||||
chdir-long.h
|
||||
chown.c
|
||||
close-stream.c
|
||||
close-stream.h
|
||||
closeout.c
|
||||
closeout.h
|
||||
config.charset
|
||||
creat-safer.c
|
||||
dirent_.h
|
||||
dirfd.c
|
||||
dirfd.h
|
||||
dirname.c
|
||||
dirname.h
|
||||
dup-safer.c
|
||||
dup2.c
|
||||
error.c
|
||||
error.h
|
||||
exclude.c
|
||||
exclude.h
|
||||
exit.h
|
||||
exitfail.c
|
||||
exitfail.h
|
||||
fchdir.c
|
||||
fchmodat.c
|
||||
fchown-stub.c
|
||||
fchownat.c
|
||||
fcntl--.h
|
||||
fcntl-safer.h
|
||||
fcntl_.h
|
||||
fd-safer.c
|
||||
fileblocks.c
|
||||
float+.h
|
||||
float_.h
|
||||
fnmatch.c
|
||||
fnmatch_.h
|
||||
fnmatch_loop.c
|
||||
fstatat.c
|
||||
ftruncate.c
|
||||
full-write.c
|
||||
full-write.h
|
||||
getdate.c
|
||||
getcwd.c
|
||||
getdate.h
|
||||
getdate.y
|
||||
getdelim.c
|
||||
getdelim.h
|
||||
getline.c
|
||||
getline.h
|
||||
getndelim2.c
|
||||
getndelim2.h
|
||||
getopt.c
|
||||
getopt.h
|
||||
getopt1.c
|
||||
getopt_.h
|
||||
getopt_int.h
|
||||
getpagesize.h
|
||||
gettext.h
|
||||
gettime.c
|
||||
gettimeofday.c
|
||||
gnulib.mk
|
||||
hash.c
|
||||
hash.h
|
||||
human.c
|
||||
human.h
|
||||
imaxtostr.c
|
||||
intprops.h
|
||||
inttostr.c
|
||||
inttostr.h
|
||||
inttypes_.h
|
||||
lchown.c
|
||||
lchown.h
|
||||
localcharset.c
|
||||
localcharset.h
|
||||
lstat.c
|
||||
lstat.h
|
||||
malloc.c
|
||||
malloca.c
|
||||
malloca.h
|
||||
malloca.valgrind
|
||||
mbchar.c
|
||||
mbchar.h
|
||||
mbscasecmp.c
|
||||
mbuiter.h
|
||||
memchr.c
|
||||
mempcpy.c
|
||||
memrchr.c
|
||||
memset.c
|
||||
mkdirat.c
|
||||
mkdtemp.c
|
||||
mktime.c
|
||||
modechange.c
|
||||
modechange.h
|
||||
obstack.c
|
||||
obstack.h
|
||||
offtostr.c
|
||||
open-safer.c
|
||||
openat-die.c
|
||||
openat-priv.h
|
||||
openat-proc.c
|
||||
openat.c
|
||||
openat.h
|
||||
pathmax.h
|
||||
paxerror.c
|
||||
paxexit.c
|
||||
paxlib.h
|
||||
paxnames.c
|
||||
pipe-safer.c
|
||||
printf-args.c
|
||||
printf-args.h
|
||||
printf-parse.c
|
||||
printf-parse.h
|
||||
quote.c
|
||||
quote.h
|
||||
quotearg.c
|
||||
quotearg.h
|
||||
realloc.c
|
||||
readlink.c
|
||||
ref-add.sin
|
||||
ref-del.sin
|
||||
regcomp.c
|
||||
regex.c
|
||||
regex.h
|
||||
regex_internal.c
|
||||
regex_internal.h
|
||||
regexec.c
|
||||
rmdir.c
|
||||
rmt.h
|
||||
rpmatch.c
|
||||
rtapelib.c
|
||||
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
|
||||
stdbool.h
|
||||
setenv.c
|
||||
setenv.h
|
||||
sleep.c
|
||||
stat-macros.h
|
||||
stat-time.h
|
||||
stdbool_.h
|
||||
stdint_.h
|
||||
stdio_.h
|
||||
stdlib_.h
|
||||
stpcpy.c
|
||||
stpcpy.h
|
||||
strcase.h
|
||||
strcasecmp.c
|
||||
strchrnul.c
|
||||
strdup.c
|
||||
strerror.c
|
||||
string_.h
|
||||
stripslash.c
|
||||
strncasecmp.c
|
||||
strndup.c
|
||||
strnlen.c
|
||||
strnlen1.c
|
||||
strnlen1.h
|
||||
strtoimax.c
|
||||
strtol.c
|
||||
strtoll.c
|
||||
strtoul.c
|
||||
strtoull.c
|
||||
strtoumax.c
|
||||
sys_stat_.h
|
||||
sys_time_.h
|
||||
sysexits_.h
|
||||
system-ioctl.h
|
||||
system.h
|
||||
tempname.c
|
||||
tempname.h
|
||||
time_.h
|
||||
time_r.c
|
||||
time_r.h
|
||||
timespec.h
|
||||
uinttostr.c
|
||||
umaxtostr.c
|
||||
unistd--.h
|
||||
unistd-safer.h
|
||||
unistd_.h
|
||||
unlinkdir.c
|
||||
unlinkdir.h
|
||||
unlocked-io.h
|
||||
unsetenv.c
|
||||
utime.c
|
||||
utimens.c
|
||||
utimens.h
|
||||
vasnprintf.c
|
||||
vasnprintf.h
|
||||
verify.h
|
||||
version-etc-fsf.c
|
||||
version-etc.c
|
||||
version-etc.h
|
||||
vsnprintf.c
|
||||
wchar_.h
|
||||
wctype_.h
|
||||
wcwidth.h
|
||||
xalloc-die.c
|
||||
xalloc.h
|
||||
xgetcwd.c
|
||||
xgetcwd.h
|
||||
xmalloc.c
|
||||
xstrdup.c
|
||||
xsize.h
|
||||
xstrndup.c
|
||||
xstrndup.h
|
||||
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,43 +0,0 @@
|
||||
# Makefile for GNU tar library.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2, or (at your option)
|
||||
## any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
## 02111-1307, USA.
|
||||
|
||||
noinst_LIBRARIES = libtar.a
|
||||
|
||||
libtar_a_SOURCES = prepargs.c prepargs.h
|
||||
|
||||
libtar_a_LIBADD = $(LIBOBJS) $(ALLOCA)
|
||||
libtar_a_DEPENDENCIES = $(libtar_a_LIBADD)
|
||||
|
||||
BUILT_SOURCES =
|
||||
EXTRA_DIST = Makefile.tmpl
|
||||
MAINTAINERCLEANFILES =
|
||||
MOSTLYCLEANFILES =
|
||||
lib_OBJECTS = $(libtar_a_OBJECTS)
|
||||
|
||||
# Special rule for getdate
|
||||
#
|
||||
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
|
||||
$(srcdir)/getdate.c: getdate.y
|
||||
cd $(srcdir) && \
|
||||
$(YACC) $(YFLAGS) getdate.y && \
|
||||
mv -f y.tab.c getdate.c
|
||||
|
||||
# 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,
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com>. */
|
||||
|
||||
|
||||
77
lib/stdopen.c
Normal file
77
lib/stdopen.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/* stdopen.c - ensure that the three standard file descriptors are in use
|
||||
|
||||
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 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. */
|
||||
|
||||
/* Written by Paul Eggert and Jim Meyering. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "stdopen.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Try to ensure that all of the standard file numbers (0, 1, 2)
|
||||
are in use. Without this, each application would have to guard
|
||||
every call to open, dup, fopen, etc. with tests to ensure they
|
||||
don't use one of the special file numbers when opening a file.
|
||||
Return false if at least one of the file descriptors is initially
|
||||
closed and an attempt to reopen it fails. Otherwise, return true. */
|
||||
bool
|
||||
stdopen (void)
|
||||
{
|
||||
int fd;
|
||||
bool ok = true;
|
||||
|
||||
for (fd = 0; fd <= 2; fd++)
|
||||
{
|
||||
if (fcntl (fd, F_GETFD) < 0)
|
||||
{
|
||||
if (errno != EBADF)
|
||||
ok = false;
|
||||
else
|
||||
{
|
||||
static const int contrary_mode[]
|
||||
= { O_WRONLY, O_RDONLY, O_RDONLY };
|
||||
int mode = contrary_mode[fd];
|
||||
int new_fd;
|
||||
/* Open /dev/null with the contrary mode so that the typical
|
||||
read (stdin) or write (stdout, stderr) operation will fail.
|
||||
With descriptor 0, we can do even better on systems that
|
||||
have /dev/full, by opening that write-only instead of
|
||||
/dev/null. The only drawback is that a write-provoked
|
||||
failure comes with a misleading errno value, ENOSPC. */
|
||||
if (mode == O_RDONLY
|
||||
|| (new_fd = open ("/dev/full", mode) != fd))
|
||||
new_fd = open ("/dev/null", mode);
|
||||
if (new_fd != fd)
|
||||
{
|
||||
if (0 <= new_fd)
|
||||
close (new_fd);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
16
lib/stdopen.h
Normal file
16
lib/stdopen.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef STDOPEN_H
|
||||
# define STDOPEN_H 1
|
||||
|
||||
# include <stdbool.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
bool stdopen (void);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -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,
|
||||
@@ -14,7 +14,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
|
||||
100
m4/.cvsignore
100
m4/.cvsignore
@@ -1,100 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
alloca.m4
|
||||
backupfile.m4
|
||||
bison.m4
|
||||
chown.m4
|
||||
clock_time.m4
|
||||
codeset.m4
|
||||
d-ino.m4
|
||||
dirname.m4
|
||||
dos.m4
|
||||
error.m4
|
||||
exclude.m4
|
||||
exitfail.m4
|
||||
extensions.m4
|
||||
fileblocks.m4
|
||||
fnmatch.m4
|
||||
ftruncate.m4
|
||||
getcwd.m4
|
||||
getdate.m4
|
||||
getline.m4
|
||||
getndelim2.m4
|
||||
getopt.m4
|
||||
gettext.m4
|
||||
gettime.m4
|
||||
gettimeofday.m4
|
||||
glibc21.m4
|
||||
hash.m4
|
||||
human.m4
|
||||
iconv.m4
|
||||
intdiv0.m4
|
||||
intmax.m4
|
||||
intmax_t.m4
|
||||
inttypes-pri.m4
|
||||
inttypes.m4
|
||||
inttypes_h.m4
|
||||
isc-posix.m4
|
||||
lchown.m4
|
||||
lcmessage.m4
|
||||
lib-ld.m4
|
||||
lib-link.m4
|
||||
lib-prefix.m4
|
||||
longdouble.m4
|
||||
longlong.m4
|
||||
mbrtowc.m4
|
||||
mbstate_t.m4
|
||||
memset.m4
|
||||
mktime.m4
|
||||
modechange.m4
|
||||
nls.m4
|
||||
obstack.m4
|
||||
onceonly.m4
|
||||
pathmax.m4
|
||||
po.m4
|
||||
printf-posix.m4
|
||||
progtest.m4
|
||||
quote.m4
|
||||
quotearg.m4
|
||||
restrict.m4
|
||||
rmdir.m4
|
||||
safe-read.m4
|
||||
safe-write.m4
|
||||
save-cwd.m4
|
||||
savedir.m4
|
||||
signed.m4
|
||||
size_max.m4
|
||||
ssize_t.m4
|
||||
st_mtim.m4
|
||||
stdbool.m4
|
||||
stdint_h.m4
|
||||
stpcpy.m4
|
||||
strcase.m4
|
||||
strerror_r.m4
|
||||
strtoimax.m4
|
||||
strtol.m4
|
||||
strtoll.m4
|
||||
strtoul.m4
|
||||
strtoull.m4
|
||||
strtoumax.m4
|
||||
time_r.m4
|
||||
timespec.m4
|
||||
tm_gmtoff.m4
|
||||
uintmax_t.m4
|
||||
ulonglong.m4
|
||||
unlocked-io.m4
|
||||
utimbuf.m4
|
||||
utime.m4
|
||||
utimes-null.m4
|
||||
utimes.m4
|
||||
wchar_t.m4
|
||||
wint_t.m4
|
||||
xalloc.m4
|
||||
xgetcwd.m4
|
||||
xsize.m4
|
||||
xstrtol.m4
|
||||
xstrtoumax.m4
|
||||
*_gl.m4
|
||||
gnulib.m4
|
||||
malloc.m4
|
||||
realloc.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,10 +1,11 @@
|
||||
# List of files which contain translatable strings.
|
||||
|
||||
# Copyright (C) 1996, 1999, 2000, 2003 Free Software Foundation, Inc.
|
||||
# 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,
|
||||
@@ -14,17 +15,28 @@
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Library files
|
||||
lib/argmatch.c
|
||||
lib/argp-help.c
|
||||
lib/argp-parse.c
|
||||
lib/error.c
|
||||
lib/getopt.c
|
||||
lib/human.c
|
||||
lib/obstack.c
|
||||
lib/paxerror.c
|
||||
lib/paxexit.c
|
||||
lib/paxnames.c
|
||||
lib/quotearg.c
|
||||
lib/rpmatch.c
|
||||
lib/rtapelib.c
|
||||
lib/xalloc-die.c
|
||||
lib/xmalloc.c
|
||||
|
||||
rmt/rmt.c
|
||||
|
||||
# Package source files
|
||||
src/buffer.c
|
||||
src/common.h
|
||||
@@ -34,11 +46,11 @@ src/delete.c
|
||||
src/extract.c
|
||||
src/incremen.c
|
||||
src/list.c
|
||||
src/mangle.c
|
||||
src/misc.c
|
||||
src/names.c
|
||||
src/rmt.c
|
||||
src/rtapelib.c
|
||||
src/tar.c
|
||||
src/update.c
|
||||
src/xheader.c
|
||||
|
||||
# Testsuite
|
||||
tests/genfile.c
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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,
|
||||
@@ -12,15 +12,15 @@
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
## 02111-1307, USA.
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
BACKUP_LIBEXEC_SCRIPTS_LIST=backup.sh dump-remind
|
||||
BACKUP_SBIN_SCRIPTS_LIST=backup restore
|
||||
libexec_SCRIPTS=@BACKUP_LIBEXEC_SCRIPTS@
|
||||
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=backup.sh dump-remind
|
||||
sbin_SCRIPTS=@BACKUP_SBIN_SCRIPTS@
|
||||
EXTRA_SCRIPTS=
|
||||
EXTRA_SCRIPTS=tarcat
|
||||
EXTRA_DIST=\
|
||||
backup.sh.in\
|
||||
backup.in\
|
||||
@@ -31,7 +31,7 @@ CLEANFILES=backup.sh backup restore dump-remind
|
||||
|
||||
SED_CMD="s,\@libexecdir\@,$(libexecdir),;\
|
||||
s,\@sysconfdir\@,$(sysconfdir),;\
|
||||
s,\@PACKAGE\@,$(PACKAGE),;\
|
||||
s,\@PACKAGE_NAME\@,$(PACKAGE_NAME),;\
|
||||
s,\@VERSION\@,$(VERSION),;\
|
||||
s,\@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),;\
|
||||
s,\@DATE_FORMAT_OK\@,$(DATE_FORMAT_OK),;@BACKUP_SED_COND@"
|
||||
@@ -46,4 +46,4 @@ restore: $(srcdir)/restore.in
|
||||
sed $(SED_CMD) $? > $@
|
||||
|
||||
dump-remind: $(srcdir)/dump-remind.in
|
||||
sed $(SED_CMD) $? > $@
|
||||
sed $(SED_CMD) $? > $@
|
||||
|
||||
@@ -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,
|
||||
@@ -96,5 +96,5 @@ SLEEP_MESSAGE="`awk '
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
## 02111-1307, USA.
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright 2004, Free Software Foundation
|
||||
# Copyright (C) 2004, 2005, 2006 Free Software Foundation
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -14,12 +14,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Load library routines
|
||||
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
. ${LIBPATH-@libexecdir@}/backup.sh
|
||||
. ${LIBDIR-@libexecdir@}/backup.sh
|
||||
|
||||
DUMP_LEVEL=0
|
||||
TIME=
|
||||
@@ -34,11 +34,10 @@ Options are:
|
||||
-f, --force Force backup even if today's log file already
|
||||
exists.
|
||||
-v, --verbose[=LEVEL] Set verbosity level. Default 100.
|
||||
-t, --time=TIME Wait till TIME, then do backup.
|
||||
-t, --time=TIME Wait till TIME, then do backup.
|
||||
|
||||
Informational options:
|
||||
Informational options:
|
||||
-h, --help Display this help message.
|
||||
-L, --license Display program license.
|
||||
-V, --version Display program version.
|
||||
|
||||
Optional argument WHEN is for backward compatibility only. It has been
|
||||
@@ -87,16 +86,14 @@ do
|
||||
TIME=$optarg
|
||||
;;
|
||||
-t) prev=--t;;
|
||||
-t*) TIME=`expr $option : "-t\(.*\)"`;;
|
||||
-t*) TIME=`expr $option : "-t\(.*\)"`;;
|
||||
--t|--ti|--tim|--time)
|
||||
prev=$option
|
||||
;;
|
||||
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "backup (@PACKAGE@ @VERSION@)"
|
||||
exit 0;;
|
||||
-L|--li|--lic|--lice|--licen|--licens|--license)
|
||||
license
|
||||
exit;;
|
||||
echo "backup (@PACKAGE_NAME@) @VERSION@"
|
||||
license
|
||||
exit;;
|
||||
-h|--h|--he|--hel|--help)
|
||||
usage
|
||||
exit;;
|
||||
@@ -108,13 +105,13 @@ do
|
||||
else
|
||||
TIME=$option
|
||||
fi;;
|
||||
esac
|
||||
done
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "x$TIME" = x ]; then
|
||||
bailout "No backup time specified. Try $PROGNAME --help for more info."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
init_backup
|
||||
|
||||
@@ -124,7 +121,7 @@ wait_time $TIME
|
||||
if [ $DUMP_LEVEL -ne 0 ]; then
|
||||
PREV_LEVEL=`expr $DUMP_LEVEL - 1`
|
||||
PREV_DATE=`ls -t ${LOGPATH}/log-*-level-$PREV_LEVEL|
|
||||
head -1|
|
||||
head -n 1|
|
||||
sed "s,${LOGPATH}/log-\(.*\)-level.*,\1,"`
|
||||
if [ "x$PREV_DATE" = x ]; then
|
||||
bailout "Can't determine date of the previous backup"
|
||||
@@ -138,10 +135,10 @@ fi
|
||||
|
||||
if [ "x$FORCE" = "xyes" ]; then
|
||||
rm ${LOGFILE}
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "${LOGFILE}" ] ; then
|
||||
bailout "Log file ${LOGFILE} already exists."
|
||||
bailout "Log file ${LOGFILE} already exists."
|
||||
else
|
||||
touch "${LOGFILE}"
|
||||
fi
|
||||
@@ -166,12 +163,13 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
while [ $# -ne 0 ] ; do
|
||||
date="`date`"
|
||||
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
|
||||
fs=`root_fs $fs`
|
||||
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
|
||||
remotehost="`expr \"${1}\" : '\([^/][^/]*\):.*'`"
|
||||
if [ -z "$remotehost" ]; then
|
||||
remotehost=$localhost
|
||||
fi
|
||||
|
||||
|
||||
echo "Backing up ${1} at ${date}"
|
||||
message 10 "fs=$fs"
|
||||
message 10 "fsname=$fsname"
|
||||
@@ -182,7 +180,7 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
echo "Last `prev_level` dump on this filesystem was on $PREV_DATE"
|
||||
remote_run "${remotehost}" cp "`level_log_name ${fsname} $PREV_LEVEL`" "`level_log_name temp`"
|
||||
fi
|
||||
|
||||
|
||||
${DUMP_BEGIN-:} $DUMP_LEVEL $remotehost $fs $fsname
|
||||
backup_host ${remotehost} \
|
||||
"--listed=`level_log_name temp`" \
|
||||
@@ -198,7 +196,7 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
else
|
||||
flush_level_log ${remotehost} ${fsname}
|
||||
fi
|
||||
${MT_STATUS}
|
||||
${MT_STATUS} "$TAPE_FILE"
|
||||
${DUMP_END-:} $DUMP_LEVEL $remotehost $fs $fsname
|
||||
echo "sleeping ${SLEEP_TIME} seconds"
|
||||
sleep ${SLEEP_TIME}
|
||||
@@ -213,14 +211,14 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
date="`date`"
|
||||
|
||||
if [ $DUMP_LEVEL -eq 0 ]; then
|
||||
make_level_log $localhost
|
||||
make_level_log $localhost
|
||||
else
|
||||
echo "Last `prev_level` dump on this filesystem was on $PREV_DATE"
|
||||
remote_run "${localhost}" cp "`level_log_name MISC $PREV_LEVEL`" "`level_log_name temp`"
|
||||
fi
|
||||
|
||||
echo "Backing up miscellaneous files at ${date}"
|
||||
|
||||
|
||||
${DUMP_BEGIN-:} $DUMP_LEVEL $localhost MISC MISC
|
||||
backup_host $localhost \
|
||||
"--listed=`level_log_name temp`"\
|
||||
@@ -234,7 +232,7 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
else
|
||||
flush_level_log $localhost MISC
|
||||
fi
|
||||
${MT_STATUS}
|
||||
${MT_STATUS} "$TAPE_FILE"
|
||||
${DUMP_END-:} $DUMP_LEVEL $localhost MISC MISC
|
||||
else
|
||||
echo "No miscellaneous files specified"
|
||||
@@ -242,12 +240,14 @@ message 20 "BACKUP_FILES=$BACKUP_FILES"
|
||||
|
||||
message 1 "final cleanup"
|
||||
|
||||
$MT_REWIND "${TAPE_FILE}"
|
||||
$MT_REWIND "${TAPE_FILE}"
|
||||
$MT_OFFLINE "${TAPE_FILE}"
|
||||
echo "."
|
||||
) 2>&1 | tee -a "${LOGFILE}"
|
||||
|
||||
echo "Sending the dump log to ${ADMINISTRATOR}"
|
||||
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
|
||||
if test "${ADMINISTRATOR}" != NONE; then
|
||||
echo "Sending the dump log to ${ADMINISTRATOR}"
|
||||
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
|
||||
fi
|
||||
|
||||
# EOF
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright 2004, Free Software Foundation
|
||||
# Copyright (C) 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
|
||||
@@ -14,8 +14,8 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
PROGNAME=`basename $0`
|
||||
CONFIGPATH="$SYSCONFDIR/backup"
|
||||
@@ -27,25 +27,25 @@ LOGPATH=${CONFIGPATH}/log
|
||||
|
||||
# Default functions for running various magnetic tape commands
|
||||
mt_begin() {
|
||||
mt -f "$1" retension
|
||||
$MT -f "$1" retension
|
||||
}
|
||||
|
||||
mt_rewind() {
|
||||
mt -f "$1" rewind
|
||||
$MT -f "$1" rewind
|
||||
}
|
||||
|
||||
mt_offline() {
|
||||
mt -f "$1" offl
|
||||
$MT -f "$1" offl
|
||||
}
|
||||
|
||||
mt_status() {
|
||||
mt -f "$1" status
|
||||
$MT -f "$1" status
|
||||
}
|
||||
|
||||
# The main configuration file may override any of these variables
|
||||
MT_BEGIN=mt_begin
|
||||
MT_REWIND=mt_rewind
|
||||
MT_OFFLINE=mt_offl
|
||||
MT_OFFLINE=mt_offline
|
||||
MT_STATUS=mt_status
|
||||
|
||||
# Insure `mail' is in PATH.
|
||||
@@ -78,7 +78,7 @@ bailout() {
|
||||
|
||||
# Return current date
|
||||
now() {
|
||||
#IF_DATE_FORMAT_OK
|
||||
#IF_DATE_FORMAT_OK
|
||||
date +%Y-%m-%d
|
||||
#ELSE_DATE_FORMAT_OK
|
||||
LC_ALL=C date | \
|
||||
@@ -106,6 +106,10 @@ test_root() {
|
||||
fi
|
||||
}
|
||||
|
||||
root_fs() {
|
||||
echo "${ROOT_FS}$1" | tr -s /
|
||||
}
|
||||
|
||||
advice() {
|
||||
echo "Directory $1 is not found." >&2
|
||||
cat >&2 <<EOF
|
||||
@@ -135,7 +139,7 @@ init_common() {
|
||||
advice $LOGPATH
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
|
||||
if [ ! -r $CONFIGFILE ]; then
|
||||
echo "$PROGNAME: cannot read $CONFIGFILE. Stop." >&2
|
||||
@@ -147,7 +151,7 @@ init_common() {
|
||||
|
||||
test_root
|
||||
|
||||
if [ x"${ADMINISTRATOR}" = x ]; then
|
||||
if [ x"${ADMINISTRATOR}" = x ]; then
|
||||
bailout "ADMINISTRATOR not defined"
|
||||
fi
|
||||
|
||||
@@ -155,7 +159,7 @@ init_common() {
|
||||
[ x"$SLEEP_TIME" = x ] && SLEEP_TIME=60
|
||||
|
||||
if [ x$VOLNO_FILE = x ]; then
|
||||
bailout "VOLNO_FILE not specified"
|
||||
bailout "VOLNO_FILE not specified"
|
||||
fi
|
||||
|
||||
if [ -r $DIRLIST ]; then
|
||||
@@ -168,9 +172,23 @@ init_common() {
|
||||
if [ \( x"$BACKUP_DIRS" = x \) -a \( x"$BACKUP_FILES" = x \) ]; then
|
||||
bailout "Neither BACKUP_DIRS nor BACKUP_FILES specified"
|
||||
fi
|
||||
if [ "$RSH" = "" ]; then
|
||||
if [ -z "$RSH" ]; then
|
||||
RSH=rsh
|
||||
MT_RSH_OPTION=
|
||||
else
|
||||
MT_RSH_OPTION="--rsh-command=$RSH"
|
||||
fi
|
||||
if [ -z "$TAPE_FILE" ]; then
|
||||
TAPE_FILE=/dev/tape
|
||||
fi
|
||||
|
||||
# If TAPE_FILE is a remote device, update mt invocation accordingly
|
||||
: ${MT:=mt}
|
||||
case $TAPE_FILE in
|
||||
*:*) MT="$MT $MT_RSH_OPTION";;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
POSIXLY_CORRECT=1
|
||||
export POSIXLY_CORRECT
|
||||
}
|
||||
@@ -235,7 +253,7 @@ wait_time() {
|
||||
diff = 3600 * (time[1] - now[1]) + 60 * (time[2] - now[2]);
|
||||
if (diff < 0)
|
||||
diff += 3600 * 24
|
||||
print diff
|
||||
print diff
|
||||
}'`"
|
||||
clear
|
||||
echo "${SLEEP_MESSAGE}"
|
||||
@@ -274,7 +292,7 @@ flush_level_log() {
|
||||
# usage: get_dump_time LEVEL
|
||||
get_dump_time() {
|
||||
ls -r ${LOGPATH}/log-*-level-$1 \
|
||||
| head -1 \
|
||||
| head -n 1 \
|
||||
| sed "s,.*log-\(.*\)-level-$1,\1,"
|
||||
}
|
||||
|
||||
@@ -302,7 +320,7 @@ print_level() {
|
||||
else
|
||||
echo "Level ${1-$DUMP_LEVEL}"
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
prev_level() {
|
||||
print_level `expr $DUMP_LEVEL - 1` | tr A-Z a-z
|
||||
@@ -321,22 +339,9 @@ remote_run() {
|
||||
|
||||
license() {
|
||||
cat - <<EOF
|
||||
This program is part of GNU tar
|
||||
Copyright 2004, Free Software Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -20,11 +20,6 @@ SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
MT_REWIND
|
||||
MT_OFFLINE
|
||||
|
||||
volno="`cat \"${VOLNO_FILE}\" 2> /dev/null`"
|
||||
if [ $? -ne 0 ]; then
|
||||
volno=0
|
||||
fi
|
||||
|
||||
# Get a list of people to whom to mail a request for changing the tape.
|
||||
# This egregious nightmare parses the output from GNU finger which shows
|
||||
# which users are logged into consoles (and thus in the office and capable
|
||||
@@ -71,30 +66,30 @@ sendmail -oi -t << __EOF__
|
||||
From: `basename $0` (backup tape-changing reminder)
|
||||
To: ${recipients}
|
||||
Cc: ${ADMINISTRATOR}
|
||||
Subject: Backup needs new tape for volume ${volno}
|
||||
Subject: Backup needs new tape for volume ${TAR_VOLUME}
|
||||
Reply-To: ${ADMINISTRATOR}
|
||||
|
||||
This is an automated report from the backup script running on
|
||||
`hostname`.
|
||||
|
||||
Volume ${volno} of the backup needs to be put in the tape drive. Usually
|
||||
whoever prepared the backup leaves labeled tapes on top of the drive
|
||||
itself. If there aren't any more, information about where to find tapes
|
||||
and how to label them are posted on the wall by apple-gunkies (unhelpfully
|
||||
obscured by a bookshelf). An online copy (which is probably more
|
||||
up-to-date) can also be found in ~friedman/etc/fsf/backup.how.
|
||||
Volume ${TAR_VOLUME} of the backup needs to be put in the tape drive.
|
||||
Usually whoever prepared the backup leaves labeled tapes on top of the
|
||||
drive itself. If there aren't any more, information about where to find
|
||||
tapes and how to label them are posted on the wall by apple-gunkies
|
||||
(unhelpfully obscured by a bookshelf). An online copy (which is probably
|
||||
more up-to-date) can also be found in ~friedman/etc/fsf/backup.how.
|
||||
__EOF__
|
||||
|
||||
|
||||
echo "Please put volume ${volno} in tape drive and press RETURN"
|
||||
echo "Please put volume ${TAR_VOLUME} in tape drive and press RETURN"
|
||||
read input
|
||||
echo "Writing volume ${volno}..."
|
||||
echo "Writing volume ${TAR_VOLUME}..."
|
||||
|
||||
sendmail -oi -t << __EOF__
|
||||
From: `basename $0` (backup tape-changing reminder)
|
||||
To: ${recipients}
|
||||
Cc: ${ADMINISTRATOR}
|
||||
Subject: Volume ${volno} for backup has been added
|
||||
Subject: Volume ${TAR_VOLUME} for backup has been added
|
||||
Reply-To: ${ADMINISTRATOR}
|
||||
|
||||
This is an automated report from the backup script running on
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# This program is part of GNU tar
|
||||
# Copyright 2004, Free Software Foundation
|
||||
# Copyright (C) 2004, 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
|
||||
@@ -14,24 +14,25 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Load library routines
|
||||
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
|
||||
. ${LIBPATH-@libexecdir@}/backup.sh
|
||||
. ${LIBDIR-@libexecdir@}/backup.sh
|
||||
|
||||
usage() {
|
||||
cat - <<EOF
|
||||
usage: $PROGNAME [OPTIONS] [PATTERN [PATTERN...]]
|
||||
Options are:
|
||||
|
||||
-l, --level=LEVEL Start restoring from backup level LEVEL (default $DUMP_LEVEL).
|
||||
-a, --all Restore all filesystems.
|
||||
-l, --level=LEVEL Start restoring from the given backup LEVEL
|
||||
(default $DUMP_LEVEL).
|
||||
-v, --verbose[=LEVEL] Set verbosity level. Default 100.
|
||||
|
||||
Informational options:
|
||||
Informational options:
|
||||
-h, --help Display this help message.
|
||||
-L, --license Display program license.
|
||||
-V, --version Display program version.
|
||||
|
||||
Send bug reports to @PACKAGE_BUGREPORT@.
|
||||
@@ -53,6 +54,9 @@ do
|
||||
optarg=$opt
|
||||
fi
|
||||
case $option in
|
||||
-a|--a|--al|--all)
|
||||
RESTORE_ALL=1
|
||||
;;
|
||||
--l=*|--le=*|--lev=*|--leve=*|--level=*)
|
||||
DUMP_LEVEL=$optarg
|
||||
;;
|
||||
@@ -67,23 +71,28 @@ do
|
||||
;;
|
||||
-v*) VERBOSE=`expr $option : "-v\(.*\)"`;;
|
||||
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "restore (@PACKAGE@ @VERSION@)"
|
||||
exit 0;;
|
||||
-L|--li|--lic|--lice|--licen|--licens|--license)
|
||||
license
|
||||
exit;;
|
||||
echo "restore (@PACKAGE_NAME@) @VERSION@"
|
||||
license
|
||||
exit;;
|
||||
-h|--h|--he|--hel|--help)
|
||||
usage
|
||||
exit;;
|
||||
-*) bailout "Unknown option $opt. Try $PROGNAME --help for more info.";;
|
||||
*) if [ -z "$PATTERN" ]; then
|
||||
PATTERN=$opt
|
||||
else
|
||||
else
|
||||
PATTERN="$PATTERN|$opt"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$RESTORE_ALL" ]; then
|
||||
if [ -z "$PATTERN" ]; then
|
||||
usage
|
||||
exit;
|
||||
fi
|
||||
fi
|
||||
|
||||
init_restore
|
||||
cat > $LOGFILE <<EOF
|
||||
@@ -93,12 +102,13 @@ It was created by GNU $PROGNAME, from @PACKAGE@ (@VERSION@).
|
||||
Invocation command line was
|
||||
|
||||
\$ $CMDLINE
|
||||
|
||||
|
||||
EOF
|
||||
|
||||
restore_fs()
|
||||
{
|
||||
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
|
||||
fs=`root_fs $fs`
|
||||
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
|
||||
remotehost="`expr \"${1}\" : '\([^/][^/]*\):.*'`"
|
||||
if [ -z "$remotehost" ]; then
|
||||
@@ -128,14 +138,14 @@ restore_fs()
|
||||
DATE=`get_dump_time $level`
|
||||
FILE="`level_log_name ${fsname} ${level}`"
|
||||
message 10 "FILE=$FILE"
|
||||
|
||||
|
||||
LABEL="`print_level $level` backup of ${fs} on ${remotehost} at ${DATE}"
|
||||
${RESTORE_BEGIN-:} $level $remotehost $fs $fsname
|
||||
backup_host ${remotehost} \
|
||||
"--listed=`level_log_name $fs $level`" \
|
||||
"--listed=\"$FILE\"" \
|
||||
"--label=\"$LABEL\"" \
|
||||
-C ${ROOT_FS-/}$fs
|
||||
${RESTORE_END-:} $level $remotehost $fs $fsname
|
||||
-C $fs
|
||||
${RESTORE_END-:} $level $remotehost $fs $fsname
|
||||
done
|
||||
}
|
||||
|
||||
@@ -156,15 +166,15 @@ restore_files()
|
||||
continue;
|
||||
fi
|
||||
message 10 "Restoring level $level"
|
||||
|
||||
|
||||
DATE=`get_dump_time $level`
|
||||
FILE="`level_log_name MISC ${level}`"
|
||||
message 10 "FILE=$FILE"
|
||||
|
||||
|
||||
LABEL="`print_level $level` backup of miscellaneous files at ${DATE}"
|
||||
${RESTORE_BEGIN-:} $level $localhost MISC MISC
|
||||
backup_host ${localhost} \
|
||||
"--listed=`level_log_name MISC $level`" \
|
||||
"--listed=\"$FILE\"" \
|
||||
"--label=\"$LABEL\"" \
|
||||
-C ${ROOT_FS-/} $@
|
||||
${RESTORE_END-:} $level $localhost MISC MISC
|
||||
@@ -213,12 +223,7 @@ if [ "x${BACKUP_FILES}" != "x" ] ; then
|
||||
done
|
||||
[ -z "$RESTORE_FILES" ] || restore_files $RESTORE_FILES
|
||||
fi
|
||||
|
||||
|
||||
fi) 2>&1 | tee -a "${LOGFILE}"
|
||||
|
||||
# EOF
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# EOF
|
||||
|
||||
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
|
||||
42
scripts/tarcat
Executable file
42
scripts/tarcat
Executable file
@@ -0,0 +1,42 @@
|
||||
#! /bin/sh
|
||||
# Usage: tarcat volume1 volume2 ...
|
||||
# concatenates a GNU tar multi-volume archive into a single tar archive.
|
||||
# Author: Bruno Haible <bruno@clisp.org>, Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
# dump_type FILE [N]
|
||||
# Print type character from block N (default 0) of tar archive FILE
|
||||
dump_type() {
|
||||
dd if="$1" skip=${2:-0} bs=512 count=1 2>/dev/null |
|
||||
tr '\0' ' ' |
|
||||
cut -c157
|
||||
}
|
||||
|
||||
case `dump_type "$1"` in
|
||||
[gx]) PAX=1;;
|
||||
esac
|
||||
|
||||
cat "$1"
|
||||
shift
|
||||
for f
|
||||
do
|
||||
SKIP=0
|
||||
T=`dump_type "$f"`
|
||||
if [ -n "$PAX" ]; then
|
||||
if [ "$T" = "g" ]; then
|
||||
# Global extended header.... 2 blocks
|
||||
# Extended header........... 2 blocks
|
||||
# Ustar header.............. 1 block
|
||||
# FIXME: This calculation is will fail for very long file names.
|
||||
SKIP=5
|
||||
fi
|
||||
else
|
||||
if [ "$T" = "V" ]; then
|
||||
T=`dump_type "$f" 1`
|
||||
fi
|
||||
if [ "$T" = "M" ]; then
|
||||
SKIP=$(($SKIP + 1))
|
||||
fi
|
||||
fi
|
||||
dd skip=$SKIP if="$f"
|
||||
done
|
||||
|
||||
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,
|
||||
@@ -15,15 +15,12 @@
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
## 02111-1307, USA.
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
bin_PROGRAMS = tar
|
||||
libexec_PROGRAMS = @RMT@
|
||||
EXTRA_PROGRAMS = rmt
|
||||
|
||||
noinst_HEADERS = arith.h common.h rmt.h system.h tar.h
|
||||
rmt_SOURCES = rmt.c
|
||||
noinst_HEADERS = arith.h common.h tar.h
|
||||
tar_SOURCES = \
|
||||
buffer.c\
|
||||
compare.c\
|
||||
@@ -33,29 +30,17 @@ tar_SOURCES = \
|
||||
xheader.c\
|
||||
incremen.c\
|
||||
list.c\
|
||||
mangle.c\
|
||||
misc.c\
|
||||
names.c\
|
||||
rtapelib.c\
|
||||
sparse.c\
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
update.c\
|
||||
utf8.c
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../lib
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
|
||||
|
||||
DISTCLEANFILES = localedir.h
|
||||
localedir.h : Makefile
|
||||
echo '#define LOCALEDIR "$(localedir)"' >$@
|
||||
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@
|
||||
echo "# define DEFAULT_RMT_COMMAND \"$(libexecdir)/`echo \"rmt\" | sed 's,^.*/,,;$(transform)'`$(EXEEXT)\"" >> $@
|
||||
echo "#endif" >> $@
|
||||
LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
|
||||
|
||||
rmt.o tar.o : localedir.h
|
||||
|
||||
LDADD = ../lib/libtar.a $(LIBINTL)
|
||||
|
||||
rmt_LDADD = $(LDADD) $(LIB_SETSOCKOPT)
|
||||
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
|
||||
|
||||
124
src/arith.h
124
src/arith.h
@@ -1,9 +1,9 @@
|
||||
/* Simple arithmetic for numbers greater than a long int, for GNU tar.
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
/* Long integers, for GNU tar.
|
||||
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,
|
||||
@@ -13,111 +13,15 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Also, see comments at beginning of arith.c. */
|
||||
|
||||
#define BITS_PER_BYTE 8 /* number of bits in each sizeof unit */
|
||||
#define BITS_PER_TARLONG 42 /* wanted number of bits in each tarlong */
|
||||
|
||||
/* In all cases, tarlong is the proper type for a big number.
|
||||
|
||||
For simulated arithmetic, SUPERDIGIT is the base, TARLONG_FORMAT is the
|
||||
format to print a single super-digit filled with zeroes to the left, and
|
||||
BITS_PER_SUPERDIGIT is the smallest number of bits required to fully
|
||||
represent each super-digit. LONGS_PER_TARLONG says how many longs are
|
||||
required for a full tarlong, and SIZEOF_TARLONG is the size of a tarlong
|
||||
in bytes.
|
||||
|
||||
For straight compiler arithmetic, SUPERDIGIT is zero and TARLONG_FORMAT
|
||||
is the format to directly print a tarlong (without zero-filling).
|
||||
|
||||
The values of SIZEOF_LONG_LONG and SIZEOF_UNSIGNED_LONG, below, are
|
||||
obtained through the configuration process. */
|
||||
|
||||
#if BITS_PER_BYTE * SIZEOF_UNSIGNED_LONG >= BITS_PER_TARLONG
|
||||
# define SUPERDIGIT 0
|
||||
# define TARLONG_FORMAT "%uld"
|
||||
typedef unsigned long tarlong;
|
||||
#else
|
||||
# if BITS_PER_BYTE * SIZEOF_LONG_LONG >= BITS_PER_TARLONG + 1
|
||||
# define SUPERDIGIT 0
|
||||
# define TARLONG_FORMAT "%lld"
|
||||
typedef long long tarlong;
|
||||
# else
|
||||
# if BITS_PER_BYTE * SIZEOF_UNSIGNED_LONG >= 64
|
||||
# define SUPERDIGIT 1000000000L
|
||||
# define BITS_PER_SUPERDIGIT 29
|
||||
# define TARLONG_FORMAT "%09uld"
|
||||
# else
|
||||
# if BITS_PER_BYTE * SIZEOF_UNSIGNED_LONG >= 32
|
||||
# define SUPERDIGIT 10000L
|
||||
# define BITS_PER_SUPERDIGIT 14
|
||||
# define TARLONG_FORMAT "%04uld"
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if SUPERDIGIT
|
||||
|
||||
# define LONGS_PER_TARLONG \
|
||||
((BITS_PER_TARLONG + BITS_PER_SUPERDIGIT - 1) / BITS_PER_SUPERDIGIT)
|
||||
# define SIZEOF_TARLONG (LONGS_PER_TARLONG * sizeof (unsigned long))
|
||||
|
||||
/* The NEC EWS 4.2 C compiler gets confused by a pointer to a typedef that
|
||||
is an array. So we wrap the array into a struct. (Pouah!) */
|
||||
|
||||
struct tarlong
|
||||
{
|
||||
unsigned long digit[LONGS_PER_TARLONG];
|
||||
};
|
||||
|
||||
typedef struct tarlong tarlong;
|
||||
|
||||
int zerop_tarlong_helper PARAMS ((unsigned long *));
|
||||
int lessp_tarlong_helper PARAMS ((unsigned long *, unsigned long *));
|
||||
void clear_tarlong_helper PARAMS ((unsigned long *));
|
||||
void add_to_tarlong_helper PARAMS ((unsigned long *, int));
|
||||
void mult_tarlong_helper PARAMS ((unsigned long *, int));
|
||||
void print_tarlong_helper PARAMS ((unsigned long *, FILE *));
|
||||
|
||||
# define zerop_tarlong(Accumulator) \
|
||||
zerop_tarlong_helper (&(Accumulator).digit[0])
|
||||
|
||||
# define lessp_tarlong(First, Second) \
|
||||
lessp_tarlong_helper (&(First).digit[0], &(Second).digit[0])
|
||||
|
||||
# define clear_tarlong(Accumulator) \
|
||||
clear_tarlong_helper (&(Accumulator).digit[0])
|
||||
|
||||
# define add_to_tarlong(Accumulator, Value) \
|
||||
add_to_tarlong_helper (&(Accumulator).digit[0], (Value))
|
||||
|
||||
# define mult_tarlong(Accumulator, Value) \
|
||||
mult_tarlong_helper (&(Accumulator).digit[0], (Value))
|
||||
|
||||
# define print_tarlong(Accumulator, File) \
|
||||
print_tarlong_helper (&(Accumulator).digit[0], (File))
|
||||
|
||||
#else /* not SUPERDIGIT */
|
||||
|
||||
# define zerop_tarlong(Accumulator) \
|
||||
((Accumulator) == 0)
|
||||
|
||||
# define lessp_tarlong(First, Second) \
|
||||
((First) < (Second))
|
||||
|
||||
# define clear_tarlong(Accumulator) \
|
||||
((Accumulator) = 0)
|
||||
|
||||
# define add_to_tarlong(Accumulator, Value) \
|
||||
((Accumulator) += (Value))
|
||||
|
||||
# define mult_tarlong(Accumulator, Value) \
|
||||
((Accumulator) *= (Value))
|
||||
|
||||
# define print_tarlong(Accumulator, File) \
|
||||
(fprintf ((File), TARLONG_FORMAT, (Accumulator)))
|
||||
|
||||
#endif /* not SUPERDIGIT */
|
||||
/* Handle large integers for calculating big tape lengths and the
|
||||
like. In practice, double precision does for now. On the vast
|
||||
majority of machines, it counts up to 2**52 bytes without any loss
|
||||
of information, and counts up to 2**62 bytes if data are always
|
||||
blocked in 1 kB boundaries. We'll need arbitrary precision
|
||||
arithmetic anyway once we get into the 2**64 range, so there's no
|
||||
point doing anything fancy before then. */
|
||||
|
||||
#define TARLONG_FORMAT "%.0f"
|
||||
typedef double tarlong;
|
||||
|
||||
1609
src/buffer.c
1609
src/buffer.c
File diff suppressed because it is too large
Load Diff
476
src/common.h
476
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 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
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Declare the GNU tar archive format. */
|
||||
#include "tar.h"
|
||||
@@ -29,20 +29,11 @@
|
||||
#define UNAME_FIELD_SIZE 32
|
||||
#define GNAME_FIELD_SIZE 32
|
||||
|
||||
/* FIXME */
|
||||
#define MAXOCTAL11 017777777777L
|
||||
#define MAXOCTAL7 07777777
|
||||
|
||||
|
||||
|
||||
/* Some various global definitions. */
|
||||
|
||||
/* Name of file to use for interacting with user. */
|
||||
#if MSDOS
|
||||
# define TTY_NAME "con"
|
||||
#else
|
||||
# define TTY_NAME "/dev/tty"
|
||||
#endif
|
||||
|
||||
/* GLOBAL is defined to empty in tar.c only, and left alone in other *.c
|
||||
modules. Here, we merely set it to "extern" if it is not already set.
|
||||
@@ -52,31 +43,10 @@
|
||||
# define GLOBAL extern
|
||||
#endif
|
||||
|
||||
/* Exit status for GNU tar. Let's try to keep this list as simple as
|
||||
possible. -d option strongly invites a status different for unequal
|
||||
comparison and other errors. */
|
||||
GLOBAL int exit_status;
|
||||
#define TAREXIT_SUCCESS PAXEXIT_SUCCESS
|
||||
#define TAREXIT_DIFFERS PAXEXIT_DIFFERS
|
||||
#define TAREXIT_FAILURE PAXEXIT_FAILURE
|
||||
|
||||
#define TAREXIT_SUCCESS 0
|
||||
#define TAREXIT_DIFFERS 1
|
||||
#define TAREXIT_FAILURE 2
|
||||
|
||||
/* Both WARN and ERROR write a message on stderr and continue processing,
|
||||
however ERROR manages so tar will exit unsuccessfully. FATAL_ERROR
|
||||
writes a message on stderr and aborts immediately, with another message
|
||||
line telling so. USAGE_ERROR works like FATAL_ERROR except that the
|
||||
other message line suggests trying --help. All four macros accept a
|
||||
single argument of the form ((0, errno, _("FORMAT"), Args...)). errno
|
||||
is zero when the error is not being detected by the system. */
|
||||
|
||||
#define WARN(Args) \
|
||||
error Args
|
||||
#define ERROR(Args) \
|
||||
(error Args, exit_status = TAREXIT_FAILURE)
|
||||
#define FATAL_ERROR(Args) \
|
||||
(error Args, fatal_exit ())
|
||||
#define USAGE_ERROR(Args) \
|
||||
(error Args, usage (TAREXIT_FAILURE))
|
||||
|
||||
#include "arith.h"
|
||||
#include <backupfile.h>
|
||||
@@ -85,7 +55,13 @@ GLOBAL int exit_status;
|
||||
#include <modechange.h>
|
||||
#include <quote.h>
|
||||
#include <safe-read.h>
|
||||
#include <stat-time.h>
|
||||
#include <timespec.h>
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
#include <obstack.h>
|
||||
|
||||
#include <paxlib.h>
|
||||
|
||||
/* Log base 2 of common values. */
|
||||
#define LG_8 3
|
||||
@@ -138,7 +114,13 @@ GLOBAL bool utc_option;
|
||||
than newer_mtime_option. */
|
||||
GLOBAL int after_date_option;
|
||||
|
||||
GLOBAL bool atime_preserve_option;
|
||||
enum atime_preserve
|
||||
{
|
||||
no_atime_preserve,
|
||||
replace_atime_preserve,
|
||||
system_atime_preserve
|
||||
};
|
||||
GLOBAL enum atime_preserve atime_preserve_option;
|
||||
|
||||
GLOBAL bool backup_option;
|
||||
|
||||
@@ -147,7 +129,15 @@ GLOBAL enum backup_type backup_type;
|
||||
|
||||
GLOBAL bool block_number_option;
|
||||
|
||||
GLOBAL bool checkpoint_option;
|
||||
GLOBAL unsigned checkpoint_option;
|
||||
|
||||
enum checkpoint_style
|
||||
{
|
||||
checkpoint_text,
|
||||
checkpoint_dot
|
||||
};
|
||||
|
||||
GLOBAL enum checkpoint_style checkpoint_style;
|
||||
|
||||
/* Specified name of compression program, or "gzip" as implied by -z. */
|
||||
GLOBAL const char *use_compress_program_option;
|
||||
@@ -160,10 +150,18 @@ GLOBAL int check_links_option;
|
||||
/* Patterns that match file names to be excluded. */
|
||||
GLOBAL struct exclude *excluded;
|
||||
|
||||
/* Specified file containing names to work on. */
|
||||
GLOBAL const char *files_from_option;
|
||||
|
||||
GLOBAL bool force_local_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. */
|
||||
@@ -200,25 +198,31 @@ GLOBAL const char *listed_incremental_option;
|
||||
/* Specified mode change string. */
|
||||
GLOBAL struct mode_change *mode_option;
|
||||
|
||||
GLOBAL bool multi_volume_option;
|
||||
/* Initial umask, if needed for mode change string. */
|
||||
GLOBAL mode_t initial_umask;
|
||||
|
||||
/* The same variable holds the time, whether mtime or ctime. Just fake a
|
||||
non-existing option, for making the code clearer, elsewhere. */
|
||||
#define newer_ctime_option newer_mtime_option
|
||||
GLOBAL bool multi_volume_option;
|
||||
|
||||
/* Specified threshold date and time. Files having an older time stamp
|
||||
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)
|
||||
|
||||
/* Return true if the struct stat ST's M time is less than
|
||||
newer_mtime_option. */
|
||||
#define OLDER_STAT_TIME(st, m) \
|
||||
((st).st_##m##time < newer_mtime_option.tv_sec \
|
||||
|| ((st).st_##m##time == newer_mtime_option.tv_sec \
|
||||
&& TIMESPEC_NS ((st).st_##m##tim) < newer_mtime_option.tv_nsec))
|
||||
(timespec_cmp (get_stat_##m##time (&(st)), newer_mtime_option) < 0)
|
||||
|
||||
/* Likewise, for struct tar_stat_info ST. */
|
||||
#define OLDER_TAR_STAT_TIME(st, m) \
|
||||
(timespec_cmp ((st).m##time, newer_mtime_option) < 0)
|
||||
|
||||
/* Zero if there is no recursion, otherwise FNM_LEADING_DIR. */
|
||||
GLOBAL int recursion_option;
|
||||
@@ -251,13 +255,15 @@ GLOBAL int same_owner_option;
|
||||
/* If positive, preserve permissions when extracting. */
|
||||
GLOBAL int same_permissions_option;
|
||||
|
||||
/* When set, strip the given number of path elements from the file name
|
||||
/* When set, strip the given number of file name components from the file name
|
||||
before extracting */
|
||||
GLOBAL size_t strip_path_elements;
|
||||
GLOBAL size_t strip_name_components;
|
||||
|
||||
GLOBAL bool show_omitted_dirs_option;
|
||||
|
||||
GLOBAL bool sparse_option;
|
||||
GLOBAL unsigned tar_sparse_major;
|
||||
GLOBAL unsigned tar_sparse_minor;
|
||||
|
||||
GLOBAL bool starting_file_option;
|
||||
|
||||
@@ -270,6 +276,15 @@ GLOBAL bool totals_option;
|
||||
|
||||
GLOBAL bool touch_option;
|
||||
|
||||
GLOBAL char *to_command_option;
|
||||
GLOBAL bool ignore_command_error_option;
|
||||
|
||||
/* Restrict some potentially harmful tar options */
|
||||
GLOBAL bool restrict_option;
|
||||
|
||||
/* Return true if the extracted files are not being written to disk */
|
||||
#define EXTRACT_OVER_PIPE (to_stdout_option || to_command_option)
|
||||
|
||||
/* Count how many times the option has been set, multiple setting yields
|
||||
more verbose behavior. Value 0 means no verbosity, 1 means file name
|
||||
only, 2 means file name and all attributes. More than 2 is just like 2. */
|
||||
@@ -291,21 +306,20 @@ GLOBAL int archive;
|
||||
/* Nonzero when outputting to /dev/null. */
|
||||
GLOBAL bool dev_null_output;
|
||||
|
||||
/* Timestamp for when we started execution. */
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
GLOBAL struct timespec start_timespec;
|
||||
# define start_time (start_timespec.tv_sec)
|
||||
#else
|
||||
GLOBAL time_t start_time;
|
||||
#endif
|
||||
/* Timestamps: */
|
||||
GLOBAL struct timespec start_time; /* when we started execution */
|
||||
GLOBAL struct timespec volume_start_time; /* when the current volume was
|
||||
opened*/
|
||||
GLOBAL struct timespec last_stat_time; /* when the statistics was last
|
||||
computed */
|
||||
|
||||
GLOBAL struct tar_stat_info current_stat_info;
|
||||
|
||||
/* List of tape drive names, number of such tape drives, allocated number,
|
||||
and current cursor in list. */
|
||||
GLOBAL const char **archive_name_array;
|
||||
GLOBAL int archive_names;
|
||||
GLOBAL int allocated_archive_names;
|
||||
GLOBAL size_t archive_names;
|
||||
GLOBAL size_t allocated_archive_names;
|
||||
GLOBAL const char **archive_name_cursor;
|
||||
|
||||
/* Output index file name. */
|
||||
@@ -314,16 +328,15 @@ GLOBAL char const *index_file_name;
|
||||
/* Structure for keeping track of filenames and lists thereof. */
|
||||
struct name
|
||||
{
|
||||
struct name *next;
|
||||
size_t length; /* cached strlen(name) */
|
||||
struct name *next; /* Link to the next element */
|
||||
int change_dir; /* Number of the directory to change to.
|
||||
Set with the -C option. */
|
||||
uintmax_t found_count; /* number of times a matching file has
|
||||
been found */
|
||||
int isdir;
|
||||
char firstch; /* first char is literally matched */
|
||||
char regexp; /* this name is a regexp, not literal */
|
||||
int change_dir; /* set with the -C option */
|
||||
int matching_flags; /* this name is a regexp, not literal */
|
||||
char const *dir_contents; /* for incremental_option */
|
||||
char fake; /* dummy entry */
|
||||
|
||||
size_t length; /* cached strlen(name) */
|
||||
char name[1];
|
||||
};
|
||||
|
||||
@@ -331,6 +344,29 @@ struct name
|
||||
GLOBAL dev_t ar_dev;
|
||||
GLOBAL ino_t ar_ino;
|
||||
|
||||
GLOBAL bool seekable_archive;
|
||||
|
||||
GLOBAL dev_t root_device;
|
||||
|
||||
/* Unquote filenames */
|
||||
GLOBAL bool unquote_option;
|
||||
|
||||
GLOBAL bool test_label_option; /* Test archive volume label and exit */
|
||||
|
||||
/* Show file or archive names after transformation.
|
||||
In particular, when creating archive in verbose mode, list member names
|
||||
as stored in the archive */
|
||||
GLOBAL bool show_transformed_names_option;
|
||||
|
||||
/* Delay setting modification times and permissions of extracted directories
|
||||
until the end of extraction. This variable helps correctly restore directory
|
||||
timestamps from archives with an unusual member order. It is automatically
|
||||
set for incremental archives. */
|
||||
GLOBAL bool delay_directory_restore_option;
|
||||
|
||||
/* Warn about implicit use of the wildcards in command line arguments.
|
||||
(Default for tar prior to 1.15.91, but changed afterwards */
|
||||
GLOBAL bool warn_regex_usage;
|
||||
|
||||
/* Declarations for each module. */
|
||||
|
||||
@@ -348,28 +384,39 @@ extern enum access_mode access_mode;
|
||||
/* Module buffer.c. */
|
||||
|
||||
extern FILE *stdlis;
|
||||
extern char *save_name;
|
||||
extern off_t save_sizeleft;
|
||||
extern off_t save_totsize;
|
||||
extern bool write_archive_to_stdout;
|
||||
extern char *volume_label;
|
||||
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 print_total_written (void);
|
||||
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);
|
||||
|
||||
void mv_begin (struct tar_stat_info *st);
|
||||
void mv_end (void);
|
||||
void mv_total_size (off_t size);
|
||||
void mv_size_left (off_t size);
|
||||
|
||||
void buffer_write_global_xheader (void);
|
||||
|
||||
/* Module create.c. */
|
||||
|
||||
@@ -381,13 +428,20 @@ 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 (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);
|
||||
@@ -404,16 +458,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))
|
||||
|
||||
void gid_to_chars (gid_t, char *, size_t);
|
||||
void major_to_chars (major_t, char *, size_t);
|
||||
void minor_to_chars (minor_t, char *, size_t);
|
||||
void mode_to_chars (mode_t, char *, size_t);
|
||||
void off_to_chars (off_t, char *, size_t);
|
||||
void size_to_chars (size_t, char *, size_t);
|
||||
void time_to_chars (time_t, char *, size_t);
|
||||
void uid_to_chars (uid_t, char *, size_t);
|
||||
void uintmax_to_chars (uintmax_t, char *, size_t);
|
||||
void string_to_chars (char *, 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. */
|
||||
|
||||
@@ -425,11 +479,10 @@ void verify_volume (void);
|
||||
|
||||
/* Module extract.c. */
|
||||
|
||||
extern bool we_are_root;
|
||||
void extr_init (void);
|
||||
void extract_archive (void);
|
||||
void extract_finish (void);
|
||||
void fatal_exit (void) __attribute__ ((noreturn));
|
||||
bool rename_directory (char *src, char *dst);
|
||||
|
||||
/* Module delete.c. */
|
||||
|
||||
@@ -437,10 +490,16 @@ void delete_archive_members (void);
|
||||
|
||||
/* Module incremen.c. */
|
||||
|
||||
char *get_directory_contents (char *, dev_t);
|
||||
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 gnu_restore (char const *);
|
||||
void purge_directory (char const *directory_name);
|
||||
void list_dumpdir (char *buffer, size_t size);
|
||||
void update_parent_directory (const char *name);
|
||||
|
||||
size_t dumpdir_size (const char *p);
|
||||
bool is_dumpdir (struct tar_stat_info *stat_info);
|
||||
|
||||
/* Module list.c. */
|
||||
|
||||
@@ -454,25 +513,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);
|
||||
#define STRINGIFY_BIGINT(i, b) \
|
||||
stringify_uintmax_t_backwards ((uintmax_t) (i), (b) + UINTMAX_STRSIZE_BOUND)
|
||||
char *stringify_uintmax_t_backwards (uintmax_t, char *);
|
||||
char const *tartime (time_t);
|
||||
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))
|
||||
@@ -484,137 +532,114 @@ char const *tartime (time_t);
|
||||
#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));
|
||||
enum read_header read_header (bool);
|
||||
void skip_file (off_t);
|
||||
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 raw_extended_headers);
|
||||
enum read_header tar_checksum (union block *header, bool silent);
|
||||
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);
|
||||
|
||||
size_t dot_dot_prefix_len (char const *);
|
||||
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 };
|
||||
|
||||
enum remove_option
|
||||
{
|
||||
ORDINARY_REMOVE_OPTION,
|
||||
RECURSIVE_REMOVE_OPTION,
|
||||
|
||||
/* FIXME: The following value is never used. It seems to be intended
|
||||
as a placeholder for a hypothetical option that should instruct tar
|
||||
to recursively remove subdirectories in purge_directory(),
|
||||
as opposed to the functionality of --recursive-unlink
|
||||
(RECURSIVE_REMOVE_OPTION value), which removes them in
|
||||
prepare_to_extract() phase. However, with the addition of more
|
||||
meta-info to the incremental dumps, this should become unnecessary */
|
||||
WANT_DIRECTORY_REMOVE_OPTION
|
||||
};
|
||||
int remove_any_file (const char *, enum remove_option);
|
||||
bool maybe_backup_file (const char *, int);
|
||||
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 decode_mode (mode_t, char *);
|
||||
|
||||
void chdir_fatal (char const *) __attribute__ ((noreturn));
|
||||
void chmod_error_details (char const *, mode_t);
|
||||
void chown_error_details (char const *, uid_t, gid_t);
|
||||
void close_error (char const *);
|
||||
void close_warn (char const *);
|
||||
void close_diag (char const *name);
|
||||
void exec_fatal (char const *) __attribute__ ((noreturn));
|
||||
void link_error (char const *, char const *);
|
||||
void mkdir_error (char const *);
|
||||
void mkfifo_error (char const *);
|
||||
void mknod_error (char const *);
|
||||
void open_error (char const *);
|
||||
void open_fatal (char const *) __attribute__ ((noreturn));
|
||||
void open_warn (char const *);
|
||||
void open_diag (char const *name);
|
||||
void read_error (char const *);
|
||||
void read_error_details (char const *, off_t, size_t);
|
||||
void read_fatal (char const *) __attribute__ ((noreturn));
|
||||
void read_fatal_details (char const *, off_t, size_t) __attribute__ ((noreturn));
|
||||
void read_warn_details (char const *, off_t, size_t);
|
||||
void read_diag_details (char const *name, off_t offset, size_t size);
|
||||
void readlink_error (char const *);
|
||||
void readlink_warn (char const *);
|
||||
void readlink_diag (char const *name);
|
||||
void savedir_error (char const *);
|
||||
void savedir_warn (char const *);
|
||||
void savedir_diag (char const *name);
|
||||
void seek_error (char const *);
|
||||
void seek_error_details (char const *, off_t);
|
||||
void seek_warn (char const *);
|
||||
void seek_warn_details (char const *, off_t);
|
||||
void seek_diag_details (char const *, off_t);
|
||||
void stat_error (char const *);
|
||||
void stat_warn (char const *);
|
||||
void seek_diag_details (char const *name, off_t offset);
|
||||
void stat_diag (char const *name);
|
||||
void symlink_error (char const *, char const *);
|
||||
void truncate_error (char const *);
|
||||
void truncate_warn (char const *);
|
||||
void unlink_error (char const *);
|
||||
void utime_error (char const *);
|
||||
void waitpid_error (char const *);
|
||||
void write_error (char const *);
|
||||
void write_error_details (char const *, 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 **ptr, size_t size);
|
||||
int set_file_atime (int fd, char const *file,
|
||||
struct timespec const timespec[2]);
|
||||
|
||||
/* Module names.c. */
|
||||
|
||||
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 (const char *);
|
||||
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);
|
||||
char *name_next (int);
|
||||
void name_close (void);
|
||||
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 *);
|
||||
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 *safer_name_suffix (char const *, bool);
|
||||
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 *);
|
||||
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)
|
||||
@@ -625,12 +650,15 @@ 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);
|
||||
void usage (int) __attribute__ ((noreturn));
|
||||
int tar_timespec_cmp (struct timespec a, struct timespec b);
|
||||
const char *archive_format_string (enum archive_format fmt);
|
||||
const char *subcommand_string (enum subcommand c);
|
||||
|
||||
/* Module update.c. */
|
||||
|
||||
@@ -640,23 +668,28 @@ void update_archive (void);
|
||||
|
||||
/* Module xheader.c. */
|
||||
|
||||
void xheader_decode (struct tar_stat_info *);
|
||||
void xheader_decode_global (void);
|
||||
void xheader_store (char const *, struct tar_stat_info const *, void *);
|
||||
void xheader_read (union block *, size_t);
|
||||
void xheader_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 (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);
|
||||
|
||||
/* Module system.c */
|
||||
|
||||
void sys_stat_nanoseconds (struct tar_stat_info *);
|
||||
void sys_detect_dev_null_output (void);
|
||||
void sys_save_archive_dev_ino (void);
|
||||
void sys_drain_input_pipe (void);
|
||||
@@ -667,26 +700,39 @@ bool sys_compare_gid (struct stat *a, struct stat *b);
|
||||
bool sys_file_is_archive (struct tar_stat_info *p);
|
||||
bool sys_compare_links (struct stat *link_data, struct stat *stat_data);
|
||||
int sys_truncate (int fd);
|
||||
void sys_reset_uid_gid (void);
|
||||
pid_t sys_child_open_for_compress (void);
|
||||
pid_t sys_child_open_for_uncompress (void);
|
||||
void sys_reset_uid_gid (void);
|
||||
size_t sys_write_archive_buffer (void);
|
||||
bool sys_get_archive_stat (void);
|
||||
void sys_reset_uid_gid (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);
|
||||
|
||||
/* 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 */
|
||||
typedef enum
|
||||
{
|
||||
xform_regfile,
|
||||
xform_link,
|
||||
xform_symlink
|
||||
} xform_type;
|
||||
|
||||
void set_transform_expr (const char *expr);
|
||||
bool transform_name (char **pinput);
|
||||
bool transform_member_name (char **pinput, xform_type type);
|
||||
bool transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *);
|
||||
|
||||
607
src/compare.c
607
src/compare.c
@@ -1,13 +1,13 @@
|
||||
/* Diff files from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004 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
|
||||
@@ -17,28 +17,18 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#if HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#else
|
||||
struct utimbuf
|
||||
{
|
||||
long actime;
|
||||
long modtime;
|
||||
};
|
||||
#endif
|
||||
#include <system.h>
|
||||
#include <system-ioctl.h>
|
||||
|
||||
#if HAVE_LINUX_FD_H
|
||||
# include <linux/fd.h>
|
||||
#endif
|
||||
|
||||
#include <quotearg.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "rmt.h"
|
||||
#include <quotearg.h>
|
||||
#include <rmt.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Nonzero if we are verifying at the moment. */
|
||||
@@ -54,22 +44,22 @@ static char *diff_buffer;
|
||||
void
|
||||
diff_init (void)
|
||||
{
|
||||
diff_buffer = valloc (record_size);
|
||||
if (!diff_buffer)
|
||||
xalloc_die ();
|
||||
void *ptr;
|
||||
diff_buffer = page_aligned_alloc (&ptr, record_size);
|
||||
if (listed_incremental_option)
|
||||
read_directory_file ();
|
||||
}
|
||||
|
||||
/* Sigh about something that differs by writing a MESSAGE to stdlis,
|
||||
given MESSAGE is nonzero. Also set the exit status if not already. */
|
||||
void
|
||||
report_difference (struct tar_stat_info *st __attribute__ ((unused)),
|
||||
const char *fmt, ...)
|
||||
report_difference (struct tar_stat_info *st, const char *fmt, ...)
|
||||
{
|
||||
if (fmt)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf (stdlis, "%s: ", quotearg_colon (current_stat_info.file_name));
|
||||
fprintf (stdlis, "%s: ", quotearg_colon (st->file_name));
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stdlis, fmt, ap);
|
||||
va_end (ap);
|
||||
@@ -112,45 +102,28 @@ process_rawdata (size_t bytes, char *buffer)
|
||||
}
|
||||
|
||||
if (memcmp (buffer, diff_buffer, bytes))
|
||||
{
|
||||
report_difference (¤t_stat_info,
|
||||
_("Contents differ"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
read_and_process (off_t size, int (*processor) (size_t, char *))
|
||||
read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
|
||||
{
|
||||
union block *data_block;
|
||||
size_t data_size;
|
||||
off_t size = st->stat.st_size;
|
||||
|
||||
if (multi_volume_option)
|
||||
save_sizeleft = size;
|
||||
mv_begin (st);
|
||||
while (size)
|
||||
{
|
||||
data_block = find_next_block ();
|
||||
@@ -168,9 +141,9 @@ read_and_process (off_t size, int (*processor) (size_t, char *))
|
||||
set_next_block_after ((union block *)
|
||||
(data_block->buffer + data_size - 1));
|
||||
size -= data_size;
|
||||
if (multi_volume_option)
|
||||
save_sizeleft -= data_size;
|
||||
mv_size_left (size);
|
||||
}
|
||||
mv_end ();
|
||||
}
|
||||
|
||||
/* Call either stat or lstat over STAT_DATA, depending on
|
||||
@@ -194,13 +167,289 @@ get_stat_data (char const *file_name, struct stat *stat_data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
diff_dir (void)
|
||||
{
|
||||
struct stat stat_data;
|
||||
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
return;
|
||||
|
||||
if (!S_ISDIR (stat_data.st_mode))
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
else if ((current_stat_info.stat.st_mode & MODE_ALL) !=
|
||||
(stat_data.st_mode & MODE_ALL))
|
||||
report_difference (¤t_stat_info, _("Mode differs"));
|
||||
}
|
||||
|
||||
static void
|
||||
diff_file (void)
|
||||
{
|
||||
char const *file_name = current_stat_info.file_name;
|
||||
struct stat stat_data;
|
||||
|
||||
if (!get_stat_data (file_name, &stat_data))
|
||||
skip_member ();
|
||||
else if (!S_ISREG (stat_data.st_mode))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
skip_member ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) !=
|
||||
(stat_data.st_mode & MODE_ALL))
|
||||
report_difference (¤t_stat_info, _("Mode differs"));
|
||||
|
||||
if (!sys_compare_uid (&stat_data, ¤t_stat_info.stat))
|
||||
report_difference (¤t_stat_info, _("Uid differs"));
|
||||
if (!sys_compare_gid (&stat_data, ¤t_stat_info.stat))
|
||||
report_difference (¤t_stat_info, _("Gid differs"));
|
||||
|
||||
if (tar_timespec_cmp (get_stat_mtime (&stat_data),
|
||||
current_stat_info.mtime))
|
||||
report_difference (¤t_stat_info, _("Mod time differs"));
|
||||
if (current_header->header.typeflag != GNUTYPE_SPARSE
|
||||
&& stat_data.st_size != current_stat_info.stat.st_size)
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Size differs"));
|
||||
skip_member ();
|
||||
}
|
||||
else
|
||||
{
|
||||
int atime_flag =
|
||||
(atime_preserve_option == system_atime_preserve
|
||||
? O_NOATIME
|
||||
: 0);
|
||||
|
||||
diff_handle = open (file_name, O_RDONLY | O_BINARY | atime_flag);
|
||||
|
||||
if (diff_handle < 0)
|
||||
{
|
||||
open_error (file_name);
|
||||
skip_member ();
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int status;
|
||||
|
||||
if (current_stat_info.is_sparse)
|
||||
sparse_diff_file (diff_handle, ¤t_stat_info);
|
||||
else
|
||||
read_and_process (¤t_stat_info, process_rawdata);
|
||||
|
||||
if (atime_preserve_option == replace_atime_preserve)
|
||||
{
|
||||
struct timespec ts[2];
|
||||
ts[0] = get_stat_atime (&stat_data);
|
||||
ts[1] = get_stat_mtime (&stat_data);
|
||||
if (set_file_atime (diff_handle, file_name, ts) != 0)
|
||||
utime_error (file_name);
|
||||
}
|
||||
|
||||
status = close (diff_handle);
|
||||
if (status != 0)
|
||||
close_error (file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
diff_link (void)
|
||||
{
|
||||
struct stat file_data;
|
||||
struct stat link_data;
|
||||
|
||||
if (get_stat_data (current_stat_info.file_name, &file_data)
|
||||
&& get_stat_data (current_stat_info.link_name, &link_data)
|
||||
&& !sys_compare_links (&file_data, &link_data))
|
||||
report_difference (¤t_stat_info,
|
||||
_("Not linked to %s"),
|
||||
quote (current_stat_info.link_name));
|
||||
}
|
||||
|
||||
#ifdef HAVE_READLINK
|
||||
static void
|
||||
diff_symlink (void)
|
||||
{
|
||||
size_t len = strlen (current_stat_info.link_name);
|
||||
char *linkbuf = alloca (len + 1);
|
||||
|
||||
int status = readlink (current_stat_info.file_name, linkbuf, len + 1);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
readlink_warn (current_stat_info.file_name);
|
||||
else
|
||||
readlink_error (current_stat_info.file_name);
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
}
|
||||
else if (status != len
|
||||
|| strncmp (current_stat_info.link_name, linkbuf, len) != 0)
|
||||
report_difference (¤t_stat_info, _("Symlink differs"));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
diff_special (void)
|
||||
{
|
||||
struct stat stat_data;
|
||||
|
||||
/* FIXME: deal with umask. */
|
||||
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
return;
|
||||
|
||||
if (current_header->header.typeflag == CHRTYPE
|
||||
? !S_ISCHR (stat_data.st_mode)
|
||||
: current_header->header.typeflag == BLKTYPE
|
||||
? !S_ISBLK (stat_data.st_mode)
|
||||
: /* current_header->header.typeflag == FIFOTYPE */
|
||||
!S_ISFIFO (stat_data.st_mode))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((current_header->header.typeflag == CHRTYPE
|
||||
|| current_header->header.typeflag == BLKTYPE)
|
||||
&& current_stat_info.stat.st_rdev != stat_data.st_rdev)
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Device number differs"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) !=
|
||||
(stat_data.st_mode & MODE_ALL))
|
||||
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;
|
||||
dev_t dev = 0;
|
||||
struct stat stat;
|
||||
|
||||
if (deref_stat (true, current_stat_info.file_name, &stat))
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
stat_warn (current_stat_info.file_name);
|
||||
else
|
||||
stat_error (current_stat_info.file_name);
|
||||
}
|
||||
else
|
||||
dev = stat.st_dev;
|
||||
|
||||
dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev);
|
||||
|
||||
if (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);
|
||||
}
|
||||
|
||||
static void
|
||||
diff_multivol (void)
|
||||
{
|
||||
struct stat stat_data;
|
||||
int fd, status;
|
||||
off_t offset;
|
||||
|
||||
if (current_stat_info.had_trailing_slash)
|
||||
{
|
||||
diff_dir ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
return;
|
||||
|
||||
if (!S_ISREG (stat_data.st_mode))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
skip_member ();
|
||||
return;
|
||||
}
|
||||
|
||||
offset = OFF_FROM_HEADER (current_header->oldgnu_header.offset);
|
||||
if (stat_data.st_size != current_stat_info.stat.st_size + offset)
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Size differs"));
|
||||
skip_member ();
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
open_error (current_stat_info.file_name);
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
skip_member ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (lseek (fd, offset, SEEK_SET) < 0)
|
||||
{
|
||||
seek_error_details (current_stat_info.file_name, offset);
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
read_and_process (¤t_stat_info, process_rawdata);
|
||||
|
||||
status = close (fd);
|
||||
if (status != 0)
|
||||
close_error (current_stat_info.file_name);
|
||||
}
|
||||
|
||||
/* Diff a file against the archive. */
|
||||
void
|
||||
diff_archive (void)
|
||||
{
|
||||
struct stat stat_data;
|
||||
int status;
|
||||
struct utimbuf restore_times;
|
||||
|
||||
set_next_block_after (current_header);
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
||||
@@ -217,7 +466,7 @@ diff_archive (void)
|
||||
switch (current_header->header.typeflag)
|
||||
{
|
||||
default:
|
||||
ERROR ((0, 0, _("%s: Unknown file type '%c', diffed as normal file"),
|
||||
ERROR ((0, 0, _("%s: Unknown file type `%c', diffed as normal file"),
|
||||
quotearg_colon (current_stat_info.file_name),
|
||||
current_header->header.typeflag));
|
||||
/* Fall through. */
|
||||
@@ -230,271 +479,53 @@ diff_archive (void)
|
||||
/* Appears to be a file. See if it's really a directory. */
|
||||
|
||||
if (current_stat_info.had_trailing_slash)
|
||||
goto really_dir;
|
||||
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
{
|
||||
skip_member ();
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (!S_ISREG (stat_data.st_mode))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
skip_member ();
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) !=
|
||||
(stat_data.st_mode & MODE_ALL))
|
||||
report_difference (¤t_stat_info, _("Mode differs"));
|
||||
|
||||
if (!sys_compare_uid (&stat_data, ¤t_stat_info.stat))
|
||||
report_difference (¤t_stat_info, _("Uid differs"));
|
||||
if (!sys_compare_gid (&stat_data, ¤t_stat_info.stat))
|
||||
report_difference (¤t_stat_info, _("Gid differs"));
|
||||
|
||||
if (stat_data.st_mtime != current_stat_info.stat.st_mtime)
|
||||
report_difference (¤t_stat_info, _("Mod time differs"));
|
||||
if (current_header->header.typeflag != GNUTYPE_SPARSE &&
|
||||
stat_data.st_size != current_stat_info.stat.st_size)
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Size differs"));
|
||||
skip_member ();
|
||||
goto quit;
|
||||
}
|
||||
|
||||
diff_handle = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_handle < 0)
|
||||
{
|
||||
open_error (current_stat_info.file_name);
|
||||
skip_member ();
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
restore_times.actime = stat_data.st_atime;
|
||||
restore_times.modtime = stat_data.st_mtime;
|
||||
|
||||
/* Need to treat sparse files completely differently here. */
|
||||
|
||||
if (current_stat_info.is_sparse)
|
||||
sparse_diff_file (diff_handle, ¤t_stat_info);
|
||||
diff_dir ();
|
||||
else
|
||||
{
|
||||
if (multi_volume_option)
|
||||
{
|
||||
assign_string (&save_name, current_stat_info.file_name);
|
||||
save_totsize = current_stat_info.stat.st_size;
|
||||
/* save_sizeleft is set in read_and_process. */
|
||||
}
|
||||
|
||||
read_and_process (current_stat_info.stat.st_size, process_rawdata);
|
||||
|
||||
if (multi_volume_option)
|
||||
assign_string (&save_name, 0);
|
||||
}
|
||||
|
||||
status = close (diff_handle);
|
||||
if (status != 0)
|
||||
close_error (current_stat_info.file_name);
|
||||
|
||||
if (atime_preserve_option)
|
||||
utime (current_stat_info.file_name, &restore_times);
|
||||
|
||||
quit:
|
||||
diff_file ();
|
||||
break;
|
||||
|
||||
case LNKTYPE:
|
||||
{
|
||||
struct stat file_data;
|
||||
struct stat link_data;
|
||||
|
||||
if (!get_stat_data (current_stat_info.file_name, &file_data))
|
||||
break;
|
||||
if (!get_stat_data (current_stat_info.link_name, &link_data))
|
||||
break;
|
||||
if (!sys_compare_links (&file_data, &link_data))
|
||||
report_difference (¤t_stat_info,
|
||||
_("Not linked to %s"),
|
||||
quote (current_stat_info.link_name));
|
||||
}
|
||||
diff_link ();
|
||||
break;
|
||||
|
||||
#ifdef HAVE_READLINK
|
||||
case SYMTYPE:
|
||||
{
|
||||
size_t len = strlen (current_stat_info.link_name);
|
||||
char *linkbuf = alloca (len + 1);
|
||||
|
||||
status = readlink (current_stat_info.file_name, linkbuf, len + 1);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
readlink_warn (current_stat_info.file_name);
|
||||
else
|
||||
readlink_error (current_stat_info.file_name);
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
}
|
||||
else if (status != len
|
||||
|| strncmp (current_stat_info.link_name, linkbuf, len) != 0)
|
||||
report_difference (¤t_stat_info, _("Symlink differs"));
|
||||
|
||||
break;
|
||||
}
|
||||
diff_symlink ();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CHRTYPE:
|
||||
case BLKTYPE:
|
||||
case FIFOTYPE:
|
||||
|
||||
/* FIXME: deal with umask. */
|
||||
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
break;
|
||||
|
||||
if (current_header->header.typeflag == CHRTYPE
|
||||
? !S_ISCHR (stat_data.st_mode)
|
||||
: current_header->header.typeflag == BLKTYPE
|
||||
? !S_ISBLK (stat_data.st_mode)
|
||||
: /* current_header->header.typeflag == FIFOTYPE */
|
||||
!S_ISFIFO (stat_data.st_mode))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((current_header->header.typeflag == CHRTYPE
|
||||
|| current_header->header.typeflag == BLKTYPE)
|
||||
&& current_stat_info.stat.st_rdev != stat_data.st_rdev)
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Device number differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Mode differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
diff_special ();
|
||||
break;
|
||||
|
||||
case GNUTYPE_DUMPDIR:
|
||||
{
|
||||
char *dumpdir_buffer = get_directory_contents (current_stat_info.file_name, 0);
|
||||
|
||||
if (multi_volume_option)
|
||||
{
|
||||
assign_string (&save_name, current_stat_info.file_name);
|
||||
save_totsize = current_stat_info.stat.st_size;
|
||||
/* save_sizeleft is set in read_and_process. */
|
||||
}
|
||||
|
||||
if (dumpdir_buffer)
|
||||
{
|
||||
dumpdir_cursor = dumpdir_buffer;
|
||||
read_and_process (current_stat_info.stat.st_size, process_dumpdir);
|
||||
free (dumpdir_buffer);
|
||||
}
|
||||
else
|
||||
read_and_process (current_stat_info.stat.st_size, process_noop);
|
||||
|
||||
if (multi_volume_option)
|
||||
assign_string (&save_name, 0);
|
||||
/* Fall through. */
|
||||
}
|
||||
|
||||
case DIRTYPE:
|
||||
really_dir:
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
break;
|
||||
|
||||
if (!S_ISDIR (stat_data.st_mode))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((current_stat_info.stat.st_mode & MODE_ALL) != (stat_data.st_mode & MODE_ALL))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Mode differs"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_dumpdir (¤t_stat_info))
|
||||
diff_dumpdir ();
|
||||
diff_dir ();
|
||||
break;
|
||||
|
||||
case GNUTYPE_VOLHDR:
|
||||
break;
|
||||
|
||||
case GNUTYPE_MULTIVOL:
|
||||
{
|
||||
off_t offset;
|
||||
|
||||
if (current_stat_info.had_trailing_slash)
|
||||
goto really_dir;
|
||||
|
||||
if (!get_stat_data (current_stat_info.file_name, &stat_data))
|
||||
break;
|
||||
|
||||
if (!S_ISREG (stat_data.st_mode))
|
||||
{
|
||||
report_difference (¤t_stat_info, _("File type differs"));
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
offset = OFF_FROM_HEADER (current_header->oldgnu_header.offset);
|
||||
if (stat_data.st_size != current_stat_info.stat.st_size + offset)
|
||||
{
|
||||
report_difference (¤t_stat_info, _("Size differs"));
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
diff_handle = open (current_stat_info.file_name, O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_handle < 0)
|
||||
{
|
||||
open_error (current_stat_info.file_name);
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
if (lseek (diff_handle, offset, SEEK_SET) < 0)
|
||||
{
|
||||
seek_error_details (current_stat_info.file_name, offset);
|
||||
report_difference (¤t_stat_info, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (multi_volume_option)
|
||||
{
|
||||
assign_string (&save_name, current_stat_info.file_name);
|
||||
save_totsize = stat_data.st_size;
|
||||
/* save_sizeleft is set in read_and_process. */
|
||||
}
|
||||
|
||||
read_and_process (current_stat_info.stat.st_size, process_rawdata);
|
||||
|
||||
if (multi_volume_option)
|
||||
assign_string (&save_name, 0);
|
||||
|
||||
status = close (diff_handle);
|
||||
if (status != 0)
|
||||
close_error (current_stat_info.file_name);
|
||||
|
||||
break;
|
||||
}
|
||||
diff_multivol ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
verify_volume (void)
|
||||
{
|
||||
if (removed_prefixes_p ())
|
||||
{
|
||||
WARN((0, 0,
|
||||
_("Archive contains file names with leading prefixes removed.")));
|
||||
WARN((0, 0,
|
||||
_("Verification may fail to locate original files.")));
|
||||
}
|
||||
|
||||
if (!diff_buffer)
|
||||
diff_init ();
|
||||
|
||||
@@ -556,6 +587,7 @@ verify_volume (void)
|
||||
do
|
||||
{
|
||||
counter++;
|
||||
set_next_block_after (current_header);
|
||||
status = read_header (false);
|
||||
}
|
||||
while (status == HEADER_FAILURE);
|
||||
@@ -569,6 +601,7 @@ verify_volume (void)
|
||||
break;
|
||||
|
||||
diff_archive ();
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
}
|
||||
|
||||
access_mode = ACCESS_WRITE;
|
||||
|
||||
1114
src/create.c
1114
src/create.c
File diff suppressed because it is too large
Load Diff
72
src/delete.c
72
src/delete.c
@@ -1,11 +1,11 @@
|
||||
/* Delete entries from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 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
|
||||
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
|
||||
@@ -15,12 +15,13 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "system.h"
|
||||
#include <system.h>
|
||||
#include <system-ioctl.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "rmt.h"
|
||||
#include <rmt.h>
|
||||
|
||||
static union block *new_record;
|
||||
static int new_blocks;
|
||||
@@ -33,12 +34,12 @@ extern union block *record_end;
|
||||
extern union block *current_block;
|
||||
extern union block *recent_long_name;
|
||||
extern union block *recent_long_link;
|
||||
extern off_t records_read;
|
||||
extern off_t records_read;
|
||||
extern off_t records_written;
|
||||
|
||||
/* The number of records skipped at the start of the archive, when
|
||||
passing over members that are not deleted. */
|
||||
static off_t records_skipped;
|
||||
off_t records_skipped;
|
||||
|
||||
/* Move archive descriptor by COUNT records worth. If COUNT is
|
||||
positive we move forward, else we move negative. If it's a tape,
|
||||
@@ -184,7 +185,7 @@ delete_archive_members (void)
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Fall through. */
|
||||
case HEADER_SUCCESS_EXTENDED:
|
||||
logical_status = status;
|
||||
@@ -261,9 +262,9 @@ delete_archive_members (void)
|
||||
if (current_block == record_end)
|
||||
flush_archive ();
|
||||
status = read_header (false);
|
||||
|
||||
|
||||
xheader_decode (¤t_stat_info);
|
||||
|
||||
|
||||
if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
@@ -293,7 +294,7 @@ delete_archive_members (void)
|
||||
set_next_block_after (current_header);
|
||||
blocks_to_skip = (current_stat_info.stat.st_size
|
||||
+ BLOCKSIZE - 1) / BLOCKSIZE;
|
||||
|
||||
|
||||
while (record_end - current_block <= blocks_to_skip)
|
||||
{
|
||||
blocks_to_skip -= (record_end - current_block);
|
||||
@@ -306,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
|
||||
{
|
||||
@@ -359,33 +360,32 @@ delete_archive_members (void)
|
||||
write_record (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (logical_status == HEADER_END_OF_FILE)
|
||||
{
|
||||
/* Write the end of tape. FIXME: we can't use write_eot here,
|
||||
as it gets confused when the input is at end of file. */
|
||||
|
||||
int total_zero_blocks = 0;
|
||||
|
||||
do
|
||||
if (logical_status == HEADER_END_OF_FILE)
|
||||
{
|
||||
int zero_blocks = blocking_factor - new_blocks;
|
||||
memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
|
||||
total_zero_blocks += zero_blocks;
|
||||
write_record (total_zero_blocks < 2);
|
||||
/* Write the end of tape. FIXME: we can't use write_eot here,
|
||||
as it gets confused when the input is at end of file. */
|
||||
|
||||
int total_zero_blocks = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int zero_blocks = blocking_factor - new_blocks;
|
||||
memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
|
||||
total_zero_blocks += zero_blocks;
|
||||
write_record (total_zero_blocks < 2);
|
||||
}
|
||||
while (total_zero_blocks < 2);
|
||||
}
|
||||
while (total_zero_blocks < 2);
|
||||
}
|
||||
|
||||
if (! acting_as_filter && ! _isrmt (archive))
|
||||
{
|
||||
if (sys_truncate (archive))
|
||||
truncate_warn (archive_name_array[0]);
|
||||
}
|
||||
}
|
||||
free (new_record);
|
||||
|
||||
if (! acting_as_filter && ! _isrmt (archive))
|
||||
{
|
||||
if (sys_truncate (archive))
|
||||
truncate_warn (archive_name_array[0]);
|
||||
}
|
||||
|
||||
close_archive ();
|
||||
names_notfound ();
|
||||
}
|
||||
|
||||
1368
src/extract.c
1368
src/extract.c
File diff suppressed because it is too large
Load Diff
1528
src/incremen.c
1528
src/incremen.c
File diff suppressed because it is too large
Load Diff
605
src/list.c
605
src/list.c
File diff suppressed because it is too large
Load Diff
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.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
|
||||
}
|
||||
}
|
||||
600
src/misc.c
600
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 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
|
||||
@@ -15,16 +15,24 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "system.h"
|
||||
#include "rmt.h"
|
||||
#include <system.h>
|
||||
#include <rmt.h>
|
||||
#include "common.h"
|
||||
#include <quotearg.h>
|
||||
#include <save-cwd.h>
|
||||
#include <xgetcwd.h>
|
||||
#include <unlinkdir.h>
|
||||
#include <utimens.h>
|
||||
|
||||
#if HAVE_STROPTS_H
|
||||
# include <stropts.h>
|
||||
#endif
|
||||
#if HAVE_SYS_FILIO_H
|
||||
# include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
static void call_arg_fatal (char const *, char const *)
|
||||
__attribute__ ((noreturn));
|
||||
|
||||
/* Handling strings. */
|
||||
|
||||
@@ -123,18 +131,8 @@ unquote_string (char *string)
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
*destination++ = '\n';
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
*destination++ = '\t';
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
*destination++ = '\f';
|
||||
case 'a':
|
||||
*destination++ = '\a';
|
||||
source++;
|
||||
break;
|
||||
|
||||
@@ -143,11 +141,31 @@ unquote_string (char *string)
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
*destination++ = '\f';
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
*destination++ = '\n';
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
*destination++ = '\r';
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
*destination++ = '\t';
|
||||
source++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
*destination++ = '\v';
|
||||
source++;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
*destination++ = 0177;
|
||||
source++;
|
||||
@@ -197,38 +215,94 @@ unquote_string (char *string)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handling numbers. */
|
||||
|
||||
/* Output fraction and trailing digits appropriate for a nanoseconds
|
||||
count equal to NS, but don't output unnecessary '.' or trailing
|
||||
zeros. */
|
||||
|
||||
void
|
||||
code_ns_fraction (int ns, char *p)
|
||||
{
|
||||
if (ns == 0)
|
||||
*p = '\0';
|
||||
else
|
||||
{
|
||||
int i = 9;
|
||||
*p++ = '.';
|
||||
|
||||
while (ns % 10 == 0)
|
||||
{
|
||||
ns /= 10;
|
||||
i--;
|
||||
}
|
||||
|
||||
p[i] = '\0';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
p[--i] = '0' + ns % 10;
|
||||
if (i == 0)
|
||||
break;
|
||||
ns /= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char const *
|
||||
code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
|
||||
{
|
||||
time_t s = t.tv_sec;
|
||||
int ns = t.tv_nsec;
|
||||
char *np;
|
||||
bool negative = s < 0;
|
||||
|
||||
if (negative && ns != 0)
|
||||
{
|
||||
s++;
|
||||
ns = BILLION - ns;
|
||||
}
|
||||
|
||||
np = umaxtostr (negative ? - (uintmax_t) s : (uintmax_t) s, sbuf + 1);
|
||||
if (negative)
|
||||
*--np = '-';
|
||||
code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND);
|
||||
return np;
|
||||
}
|
||||
|
||||
/* File handling. */
|
||||
|
||||
/* Saved names in case backup needs to be undone. */
|
||||
static char *before_backup_name;
|
||||
static char *after_backup_name;
|
||||
|
||||
/* Return 1 if PATH is obviously "." or "/". */
|
||||
/* Return 1 if FILE_NAME is obviously "." or "/". */
|
||||
static bool
|
||||
must_be_dot_or_slash (char const *path)
|
||||
must_be_dot_or_slash (char const *file_name)
|
||||
{
|
||||
path += FILESYSTEM_PREFIX_LEN (path);
|
||||
file_name += FILE_SYSTEM_PREFIX_LEN (file_name);
|
||||
|
||||
if (ISSLASH (path[0]))
|
||||
if (ISSLASH (file_name[0]))
|
||||
{
|
||||
for (;;)
|
||||
if (ISSLASH (path[1]))
|
||||
path++;
|
||||
else if (path[1] == '.' && ISSLASH (path[2 + (path[2] == '.')]))
|
||||
path += 2 + (path[2] == '.');
|
||||
if (ISSLASH (file_name[1]))
|
||||
file_name++;
|
||||
else if (file_name[1] == '.'
|
||||
&& ISSLASH (file_name[2 + (file_name[2] == '.')]))
|
||||
file_name += 2 + (file_name[2] == '.');
|
||||
else
|
||||
return ! path[1];
|
||||
return ! file_name[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
while (path[0] == '.' && ISSLASH (path[1]))
|
||||
while (file_name[0] == '.' && ISSLASH (file_name[1]))
|
||||
{
|
||||
path += 2;
|
||||
while (ISSLASH (*path))
|
||||
path++;
|
||||
file_name += 2;
|
||||
while (ISSLASH (*file_name))
|
||||
file_name++;
|
||||
}
|
||||
|
||||
return ! path[0] || (path[0] == '.' && ! path[1]);
|
||||
return ! file_name[0] || (file_name[0] == '.' && ! file_name[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,32 +310,35 @@ must_be_dot_or_slash (char const *path)
|
||||
Report an error with errno set to zero for obvious cases of this;
|
||||
otherwise call rmdir. */
|
||||
static int
|
||||
safer_rmdir (const char *path)
|
||||
safer_rmdir (const char *file_name)
|
||||
{
|
||||
if (must_be_dot_or_slash (path))
|
||||
if (must_be_dot_or_slash (file_name))
|
||||
{
|
||||
errno = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rmdir (path);
|
||||
return rmdir (file_name);
|
||||
}
|
||||
|
||||
/* Remove PATH, returning 1 on success. If PATH is a directory, then
|
||||
if OPTION is RECURSIVE_REMOVE_OPTION is set remove PATH
|
||||
recursively; otherwise, remove it only if it is empty. If PATH is
|
||||
/* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory,
|
||||
then if OPTION is RECURSIVE_REMOVE_OPTION is set remove FILE_NAME
|
||||
recursively; otherwise, remove it only if it is empty. If FILE_NAME is
|
||||
a directory that cannot be removed (e.g., because it is nonempty)
|
||||
and if OPTION is WANT_DIRECTORY_REMOVE_OPTION, then return -1.
|
||||
Return 0 on error, with errno set; if PATH is obviously the working
|
||||
Return 0 on error, with errno set; if FILE_NAME is obviously the working
|
||||
directory return zero with errno set to zero. */
|
||||
int
|
||||
remove_any_file (const char *path, enum remove_option option)
|
||||
remove_any_file (const char *file_name, enum remove_option option)
|
||||
{
|
||||
/* Try unlink first if we are not root, as this saves us a system
|
||||
call in the common case where we're removing a non-directory. */
|
||||
if (! we_are_root)
|
||||
/* Try unlink first if we cannot unlink directories, as this saves
|
||||
us a system call in the common case where we're removing a
|
||||
non-directory. */
|
||||
bool try_unlink_first = cannot_unlink_dir ();
|
||||
|
||||
if (try_unlink_first)
|
||||
{
|
||||
if (unlink (path) == 0)
|
||||
if (unlink (file_name) == 0)
|
||||
return 1;
|
||||
|
||||
/* POSIX 1003.1-2001 requires EPERM when attempting to unlink a
|
||||
@@ -271,13 +348,13 @@ remove_any_file (const char *path, enum remove_option option)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (safer_rmdir (path) == 0)
|
||||
if (safer_rmdir (file_name) == 0)
|
||||
return 1;
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case ENOTDIR:
|
||||
return we_are_root && unlink (path) == 0;
|
||||
return !try_unlink_first && unlink (file_name) == 0;
|
||||
|
||||
case 0:
|
||||
case EEXIST:
|
||||
@@ -294,7 +371,7 @@ remove_any_file (const char *path, enum remove_option option)
|
||||
|
||||
case RECURSIVE_REMOVE_OPTION:
|
||||
{
|
||||
char *directory = savedir (path);
|
||||
char *directory = savedir (file_name);
|
||||
char const *entry;
|
||||
size_t entrylen;
|
||||
|
||||
@@ -305,10 +382,11 @@ remove_any_file (const char *path, enum remove_option option)
|
||||
(entrylen = strlen (entry)) != 0;
|
||||
entry += entrylen + 1)
|
||||
{
|
||||
char *path_buffer = new_name (path, entry);
|
||||
int r = remove_any_file (path_buffer, 1);
|
||||
char *file_name_buffer = new_name (file_name, entry);
|
||||
int r = remove_any_file (file_name_buffer,
|
||||
RECURSIVE_REMOVE_OPTION);
|
||||
int e = errno;
|
||||
free (path_buffer);
|
||||
free (file_name_buffer);
|
||||
|
||||
if (! r)
|
||||
{
|
||||
@@ -319,7 +397,7 @@ remove_any_file (const char *path, enum remove_option option)
|
||||
}
|
||||
|
||||
free (directory);
|
||||
return safer_rmdir (path) == 0;
|
||||
return safer_rmdir (file_name) == 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -328,28 +406,28 @@ remove_any_file (const char *path, enum remove_option option)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if PATH already exists and make a backup of it right now.
|
||||
/* Check if FILE_NAME already exists and make a backup of it right now.
|
||||
Return success (nonzero) only if the backup is either unneeded, or
|
||||
successful. For now, directories are considered to never need
|
||||
backup. If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and
|
||||
so, we do not have to backup block or character devices, nor remote
|
||||
entities. */
|
||||
bool
|
||||
maybe_backup_file (const char *path, int this_is_the_archive)
|
||||
maybe_backup_file (const char *file_name, bool this_is_the_archive)
|
||||
{
|
||||
struct stat file_stat;
|
||||
|
||||
/* Check if we really need to backup the file. */
|
||||
|
||||
if (this_is_the_archive && _remdev (path))
|
||||
if (this_is_the_archive && _remdev (file_name))
|
||||
return true;
|
||||
|
||||
if (stat (path, &file_stat))
|
||||
if (stat (file_name, &file_stat))
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
return true;
|
||||
|
||||
stat_error (path);
|
||||
stat_error (file_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -360,7 +438,7 @@ maybe_backup_file (const char *path, int this_is_the_archive)
|
||||
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
|
||||
return true;
|
||||
|
||||
assign_string (&before_backup_name, path);
|
||||
assign_string (&before_backup_name, file_name);
|
||||
|
||||
/* A run situation may exist between Emacs or other GNU programs trying to
|
||||
make a backup for the same file simultaneously. If theoretically
|
||||
@@ -368,7 +446,7 @@ maybe_backup_file (const char *path, int this_is_the_archive)
|
||||
convention, GNU-wide, for all programs doing backups. */
|
||||
|
||||
assign_string (&after_backup_name, 0);
|
||||
after_backup_name = find_backup_file_name (path, backup_type);
|
||||
after_backup_name = find_backup_file_name (file_name, backup_type);
|
||||
if (! after_backup_name)
|
||||
xalloc_die ();
|
||||
|
||||
@@ -421,6 +499,26 @@ deref_stat (bool deref, char const *name, struct stat *buf)
|
||||
return deref ? stat (name, buf) : lstat (name, buf);
|
||||
}
|
||||
|
||||
/* Set FD's (i.e., FILE's) access time to TIMESPEC[0]. If that's not
|
||||
possible to do by itself, set its access and data modification
|
||||
times to TIMESPEC[0] and TIMESPEC[1], respectively. */
|
||||
int
|
||||
set_file_atime (int fd, char const *file, struct timespec const timespec[2])
|
||||
{
|
||||
#ifdef _FIOSATIME
|
||||
if (0 <= fd)
|
||||
{
|
||||
struct timeval timeval;
|
||||
timeval.tv_sec = timespec[0].tv_sec;
|
||||
timeval.tv_usec = timespec[0].tv_nsec / 1000;
|
||||
if (ioctl (fd, _FIOSATIME, &timeval) == 0)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return gl_futimens (fd, file, timespec);
|
||||
}
|
||||
|
||||
/* A description of a working directory. */
|
||||
struct wd
|
||||
{
|
||||
@@ -445,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 = ".";
|
||||
@@ -485,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)
|
||||
@@ -507,93 +632,6 @@ chdir_do (int i)
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode MODE from its binary form in a stat structure, and encode it
|
||||
into a 9-byte string STRING, terminated with a NUL. */
|
||||
|
||||
void
|
||||
decode_mode (mode_t mode, char *string)
|
||||
{
|
||||
*string++ = mode & S_IRUSR ? 'r' : '-';
|
||||
*string++ = mode & S_IWUSR ? 'w' : '-';
|
||||
*string++ = (mode & S_ISUID
|
||||
? (mode & S_IXUSR ? 's' : 'S')
|
||||
: (mode & S_IXUSR ? 'x' : '-'));
|
||||
*string++ = mode & S_IRGRP ? 'r' : '-';
|
||||
*string++ = mode & S_IWGRP ? 'w' : '-';
|
||||
*string++ = (mode & S_ISGID
|
||||
? (mode & S_IXGRP ? 's' : 'S')
|
||||
: (mode & S_IXGRP ? 'x' : '-'));
|
||||
*string++ = mode & S_IROTH ? 'r' : '-';
|
||||
*string++ = mode & S_IWOTH ? 'w' : '-';
|
||||
*string++ = (mode & S_ISVTX
|
||||
? (mode & S_IXOTH ? 't' : 'T')
|
||||
: (mode & S_IXOTH ? 'x' : '-'));
|
||||
*string = '\0';
|
||||
}
|
||||
|
||||
/* Report an error associated with the system call CALL and the
|
||||
optional name NAME. */
|
||||
static void
|
||||
call_arg_error (char const *call, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
|
||||
}
|
||||
|
||||
/* Report a fatal error associated with the system call CALL and
|
||||
the optional file name NAME. */
|
||||
static void
|
||||
call_arg_fatal (char const *call, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
FATAL_ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
|
||||
}
|
||||
|
||||
/* Report a warning associated with the system call CALL and
|
||||
the optional file name NAME. */
|
||||
static void
|
||||
call_arg_warn (char const *call, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
WARN ((0, e, _("%s: Warning: Cannot %s"), quotearg_colon (name), call));
|
||||
}
|
||||
|
||||
void
|
||||
chdir_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("chdir", name);
|
||||
}
|
||||
|
||||
void
|
||||
chmod_error_details (char const *name, mode_t mode)
|
||||
{
|
||||
int e = errno;
|
||||
char buf[10];
|
||||
decode_mode (mode, buf);
|
||||
ERROR ((0, e, _("%s: Cannot change mode to %s"),
|
||||
quotearg_colon (name), buf));
|
||||
}
|
||||
|
||||
void
|
||||
chown_error_details (char const *name, uid_t uid, gid_t gid)
|
||||
{
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot change ownership to uid %lu, gid %lu"),
|
||||
quotearg_colon (name), (unsigned long) uid, (unsigned long) gid));
|
||||
}
|
||||
|
||||
void
|
||||
close_error (char const *name)
|
||||
{
|
||||
call_arg_error ("close", name);
|
||||
}
|
||||
|
||||
void
|
||||
close_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("close", name);
|
||||
}
|
||||
|
||||
void
|
||||
close_diag (char const *name)
|
||||
{
|
||||
@@ -603,56 +641,6 @@ close_diag (char const *name)
|
||||
close_error (name);
|
||||
}
|
||||
|
||||
void
|
||||
exec_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("exec", name);
|
||||
}
|
||||
|
||||
void
|
||||
link_error (char const *target, char const *source)
|
||||
{
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot hard link to %s"),
|
||||
quotearg_colon (source), quote_n (1, target)));
|
||||
}
|
||||
|
||||
void
|
||||
mkdir_error (char const *name)
|
||||
{
|
||||
call_arg_error ("mkdir", name);
|
||||
}
|
||||
|
||||
void
|
||||
mkfifo_error (char const *name)
|
||||
{
|
||||
call_arg_error ("mkfifo", name);
|
||||
}
|
||||
|
||||
void
|
||||
mknod_error (char const *name)
|
||||
{
|
||||
call_arg_error ("mknod", name);
|
||||
}
|
||||
|
||||
void
|
||||
open_error (char const *name)
|
||||
{
|
||||
call_arg_error ("open", name);
|
||||
}
|
||||
|
||||
void
|
||||
open_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("open", name);
|
||||
}
|
||||
|
||||
void
|
||||
open_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("open", name);
|
||||
}
|
||||
|
||||
void
|
||||
open_diag (char const *name)
|
||||
{
|
||||
@@ -662,38 +650,6 @@ open_diag (char const *name)
|
||||
open_error (name);
|
||||
}
|
||||
|
||||
void
|
||||
read_error (char const *name)
|
||||
{
|
||||
call_arg_error ("read", name);
|
||||
}
|
||||
|
||||
void
|
||||
read_error_details (char const *name, off_t offset, size_t size)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
ERROR ((0, e,
|
||||
ngettext ("%s: Read error at byte %s, reading %lu byte",
|
||||
"%s: Read error at byte %s, reading %lu bytes",
|
||||
size),
|
||||
quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
|
||||
(unsigned long) size));
|
||||
}
|
||||
|
||||
void
|
||||
read_warn_details (char const *name, off_t offset, size_t size)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
WARN ((0, e,
|
||||
ngettext ("%s: Warning: Read error at byte %s, reading %lu byte",
|
||||
"%s: Warning: Read error at byte %s, reading %lu bytes",
|
||||
size),
|
||||
quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
|
||||
(unsigned long) size));
|
||||
}
|
||||
|
||||
void
|
||||
read_diag_details (char const *name, off_t offset, size_t size)
|
||||
{
|
||||
@@ -703,37 +659,6 @@ read_diag_details (char const *name, off_t offset, size_t size)
|
||||
read_error_details (name, offset, size);
|
||||
}
|
||||
|
||||
void
|
||||
read_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("read", name);
|
||||
}
|
||||
|
||||
void
|
||||
read_fatal_details (char const *name, off_t offset, size_t size)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
FATAL_ERROR ((0, e,
|
||||
ngettext ("%s: Read error at byte %s, reading %lu byte",
|
||||
"%s: Read error at byte %s, reading %lu bytes",
|
||||
size),
|
||||
quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
|
||||
(unsigned long) size));
|
||||
}
|
||||
|
||||
void
|
||||
readlink_error (char const *name)
|
||||
{
|
||||
call_arg_error ("readlink", name);
|
||||
}
|
||||
|
||||
void
|
||||
readlink_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("readlink", name);
|
||||
}
|
||||
|
||||
void
|
||||
readlink_diag (char const *name)
|
||||
{
|
||||
@@ -743,18 +668,6 @@ readlink_diag (char const *name)
|
||||
readlink_error (name);
|
||||
}
|
||||
|
||||
void
|
||||
savedir_error (char const *name)
|
||||
{
|
||||
call_arg_error ("savedir", name);
|
||||
}
|
||||
|
||||
void
|
||||
savedir_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("savedir", name);
|
||||
}
|
||||
|
||||
void
|
||||
savedir_diag (char const *name)
|
||||
{
|
||||
@@ -764,38 +677,6 @@ savedir_diag (char const *name)
|
||||
savedir_error (name);
|
||||
}
|
||||
|
||||
void
|
||||
seek_error (char const *name)
|
||||
{
|
||||
call_arg_error ("seek", name);
|
||||
}
|
||||
|
||||
void
|
||||
seek_error_details (char const *name, off_t offset)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot seek to %s"),
|
||||
quotearg_colon (name),
|
||||
STRINGIFY_BIGINT (offset, buf)));
|
||||
}
|
||||
|
||||
void
|
||||
seek_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("seek", name);
|
||||
}
|
||||
|
||||
void
|
||||
seek_warn_details (char const *name, off_t offset)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
WARN ((0, e, _("%s: Warning: Cannot seek to %s"),
|
||||
quotearg_colon (name),
|
||||
STRINGIFY_BIGINT (offset, buf)));
|
||||
}
|
||||
|
||||
void
|
||||
seek_diag_details (char const *name, off_t offset)
|
||||
{
|
||||
@@ -805,26 +686,6 @@ seek_diag_details (char const *name, off_t offset)
|
||||
seek_error_details (name, offset);
|
||||
}
|
||||
|
||||
void
|
||||
symlink_error (char const *contents, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot create symlink to %s"),
|
||||
quotearg_colon (name), quote_n (1, contents)));
|
||||
}
|
||||
|
||||
void
|
||||
stat_error (char const *name)
|
||||
{
|
||||
call_arg_error ("stat", name);
|
||||
}
|
||||
|
||||
void
|
||||
stat_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("stat", name);
|
||||
}
|
||||
|
||||
void
|
||||
stat_diag (char const *name)
|
||||
{
|
||||
@@ -834,61 +695,6 @@ stat_diag (char const *name)
|
||||
stat_error (name);
|
||||
}
|
||||
|
||||
void
|
||||
truncate_error (char const *name)
|
||||
{
|
||||
call_arg_error ("truncate", name);
|
||||
}
|
||||
|
||||
void
|
||||
truncate_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("truncate", name);
|
||||
}
|
||||
|
||||
void
|
||||
unlink_error (char const *name)
|
||||
{
|
||||
call_arg_error ("unlink", name);
|
||||
}
|
||||
|
||||
void
|
||||
utime_error (char const *name)
|
||||
{
|
||||
call_arg_error ("utime", name);
|
||||
}
|
||||
|
||||
void
|
||||
waitpid_error (char const *name)
|
||||
{
|
||||
call_arg_error ("waitpid", name);
|
||||
}
|
||||
|
||||
void
|
||||
write_error (char const *name)
|
||||
{
|
||||
call_arg_error ("write", name);
|
||||
}
|
||||
|
||||
void
|
||||
write_error_details (char const *name, size_t status, size_t size)
|
||||
{
|
||||
if (status == 0)
|
||||
write_error (name);
|
||||
else
|
||||
ERROR ((0, 0,
|
||||
ngettext ("%s: Wrote only %lu of %lu byte",
|
||||
"%s: Wrote only %lu of %lu bytes",
|
||||
size),
|
||||
name, (unsigned long int) status, (unsigned long int) size));
|
||||
}
|
||||
|
||||
void
|
||||
write_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("write", name);
|
||||
}
|
||||
|
||||
void
|
||||
write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
{
|
||||
@@ -896,7 +702,6 @@ write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
fatal_exit ();
|
||||
}
|
||||
|
||||
|
||||
/* Fork, aborting if unsuccessful. */
|
||||
pid_t
|
||||
xfork (void)
|
||||
@@ -915,18 +720,29 @@ xpipe (int fd[2])
|
||||
call_arg_fatal ("pipe", _("interprocess channel"));
|
||||
}
|
||||
|
||||
/* Return an unambiguous printable representation, allocated in slot N,
|
||||
for NAME, suitable for diagnostics. */
|
||||
char const *
|
||||
quote_n (int n, char const *name)
|
||||
/* Return PTR, aligned upward to the next multiple of ALIGNMENT.
|
||||
ALIGNMENT must be nonzero. The caller must arrange for ((char *)
|
||||
PTR) through ((char *) PTR + ALIGNMENT - 1) to be addressable
|
||||
locations. */
|
||||
|
||||
static inline void *
|
||||
ptr_align (void *ptr, size_t alignment)
|
||||
{
|
||||
return quotearg_n_style (n, locale_quoting_style, name);
|
||||
char *p0 = ptr;
|
||||
char *p1 = p0 + alignment - 1;
|
||||
return p1 - (size_t) p1 % alignment;
|
||||
}
|
||||
|
||||
/* Return an unambiguous printable representation of NAME, suitable
|
||||
for diagnostics. */
|
||||
char const *
|
||||
quote (char const *name)
|
||||
/* Return the address of a page-aligned buffer of at least SIZE bytes.
|
||||
The caller should free *PTR when done with the buffer. */
|
||||
|
||||
void *
|
||||
page_aligned_alloc (void **ptr, size_t size)
|
||||
{
|
||||
return quote_n (0, name);
|
||||
size_t alignment = getpagesize ();
|
||||
size_t size1 = size + alignment;
|
||||
if (size1 < size)
|
||||
xalloc_die ();
|
||||
*ptr = xmalloc (size1);
|
||||
return ptr_align (*ptr, alignment);
|
||||
}
|
||||
|
||||
626
src/names.c
626
src/names.c
@@ -1,11 +1,11 @@
|
||||
/* Various processing of names.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2003, 2004 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
|
||||
@@ -15,9 +15,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "system.h"
|
||||
#include <system.h>
|
||||
|
||||
#include <fnmatch.h>
|
||||
#include <hash.h>
|
||||
@@ -56,6 +56,8 @@ static char *cached_no_such_gname;
|
||||
static uid_t cached_no_such_uid;
|
||||
static gid_t cached_no_such_gid;
|
||||
|
||||
static void register_individual_file (char const *name);
|
||||
|
||||
/* Given UID, find the corresponding UNAME. */
|
||||
void
|
||||
uid_to_uname (uid_t uid, char **uname)
|
||||
@@ -64,7 +66,7 @@ uid_to_uname (uid_t uid, char **uname)
|
||||
|
||||
if (uid != 0 && uid == cached_no_such_uid)
|
||||
{
|
||||
*uname = strdup ("");
|
||||
*uname = xstrdup ("");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,11 +81,11 @@ uid_to_uname (uid_t uid, char **uname)
|
||||
else
|
||||
{
|
||||
cached_no_such_uid = uid;
|
||||
*uname = strdup ("");
|
||||
*uname = xstrdup ("");
|
||||
return;
|
||||
}
|
||||
}
|
||||
*uname = strdup (cached_uname);
|
||||
*uname = xstrdup (cached_uname);
|
||||
}
|
||||
|
||||
/* Given GID, find the corresponding GNAME. */
|
||||
@@ -94,7 +96,7 @@ gid_to_gname (gid_t gid, char **gname)
|
||||
|
||||
if (gid != 0 && gid == cached_no_such_gid)
|
||||
{
|
||||
*gname = strdup ("");
|
||||
*gname = xstrdup ("");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -109,11 +111,11 @@ gid_to_gname (gid_t gid, char **gname)
|
||||
else
|
||||
{
|
||||
cached_no_such_gid = gid;
|
||||
*gname = strdup ("");
|
||||
*gname = xstrdup ("");
|
||||
return;
|
||||
}
|
||||
}
|
||||
*gname = strdup (cached_gname);
|
||||
*gname = xstrdup (cached_gname);
|
||||
}
|
||||
|
||||
/* Given UNAME, set the corresponding UID and return 1, or else, return 0. */
|
||||
@@ -181,49 +183,90 @@ gname_to_gid (char const *gname, gid_t *gidp)
|
||||
|
||||
static struct name *namelist; /* first name in list, if any */
|
||||
static struct name **nametail = &namelist; /* end of name list */
|
||||
static const char **name_array; /* store an array of names */
|
||||
static int allocated_names; /* how big is the array? */
|
||||
static int names; /* how many entries does it have? */
|
||||
static int name_index; /* how many of the entries have we scanned? */
|
||||
|
||||
/* Initialize structures. */
|
||||
void
|
||||
init_names (void)
|
||||
/* File name arguments are processed in two stages: first a
|
||||
name_array (see below) is filled, then the names from it
|
||||
are moved into the namelist.
|
||||
|
||||
This awkward process is needed only to implement --same-order option,
|
||||
which is meant to help process large archives on machines with
|
||||
limited memory. With this option on, namelist contains at most one
|
||||
entry, which diminishes the memory consumption.
|
||||
|
||||
However, I very much doubt if we still need this -- Sergey */
|
||||
|
||||
/* A name_array element contains entries of three types: */
|
||||
|
||||
#define NELT_NAME 0 /* File name */
|
||||
#define NELT_CHDIR 1 /* Change directory request */
|
||||
#define NELT_FMASK 2 /* Change fnmatch options request */
|
||||
|
||||
struct name_elt /* A name_array element. */
|
||||
{
|
||||
allocated_names = 10;
|
||||
name_array = xmalloc (sizeof (const char *) * allocated_names);
|
||||
names = 0;
|
||||
}
|
||||
char type; /* Element type, see NELT_* constants above */
|
||||
union
|
||||
{
|
||||
const char *name; /* File or directory name */
|
||||
int matching_flags;/* fnmatch options if type == NELT_FMASK */
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Add NAME at end of name_array, reallocating it as necessary. */
|
||||
void
|
||||
name_add (const char *name)
|
||||
static struct name_elt *name_array; /* store an array of names */
|
||||
static size_t allocated_names; /* how big is the array? */
|
||||
static size_t names; /* how many entries does it have? */
|
||||
static size_t name_index; /* how many of the entries have we scanned? */
|
||||
|
||||
/* Check the size of name_array, reallocating it as necessary. */
|
||||
static void
|
||||
check_name_alloc ()
|
||||
{
|
||||
if (names == allocated_names)
|
||||
{
|
||||
allocated_names *= 2;
|
||||
name_array =
|
||||
xrealloc (name_array, sizeof (const char *) * allocated_names);
|
||||
if (allocated_names == 0)
|
||||
allocated_names = 10; /* Set initial allocation */
|
||||
name_array = x2nrealloc (name_array, &allocated_names,
|
||||
sizeof (name_array[0]));
|
||||
}
|
||||
name_array[names++] = name;
|
||||
}
|
||||
|
||||
/* Add to name_array the file NAME with fnmatch options MATCHING_FLAGS */
|
||||
void
|
||||
name_add_name (const char *name, int matching_flags)
|
||||
{
|
||||
static int prev_flags = 0; /* FIXME: Or EXCLUDE_ANCHORED? */
|
||||
struct name_elt *ep;
|
||||
|
||||
check_name_alloc ();
|
||||
ep = &name_array[names++];
|
||||
if (prev_flags != matching_flags)
|
||||
{
|
||||
ep->type = NELT_FMASK;
|
||||
ep->v.matching_flags = matching_flags;
|
||||
prev_flags = matching_flags;
|
||||
check_name_alloc ();
|
||||
ep = &name_array[names++];
|
||||
}
|
||||
ep->type = NELT_NAME;
|
||||
ep->v.name = name;
|
||||
}
|
||||
|
||||
/* Add to name_array a chdir request for the directory NAME */
|
||||
void
|
||||
name_add_dir (const char *name)
|
||||
{
|
||||
struct name_elt *ep;
|
||||
check_name_alloc ();
|
||||
ep = &name_array[names++];
|
||||
ep->type = NELT_CHDIR;
|
||||
ep->v.name = name;
|
||||
}
|
||||
|
||||
|
||||
/* Names from external name file. */
|
||||
|
||||
static FILE *name_file; /* file to read names from */
|
||||
static char *name_buffer; /* buffer to hold the current file name */
|
||||
static size_t name_buffer_length; /* allocated length of name_buffer */
|
||||
|
||||
/* FIXME: I should better check more closely. It seems at first glance that
|
||||
is_pattern is only used when reading a file, and ignored for all
|
||||
command line arguments. */
|
||||
|
||||
static inline int
|
||||
is_pattern (const char *string)
|
||||
{
|
||||
return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
|
||||
}
|
||||
|
||||
/* Set up to gather file names for tar. They can either come from a
|
||||
file or were saved from decoding arguments. */
|
||||
void
|
||||
@@ -231,17 +274,6 @@ name_init (void)
|
||||
{
|
||||
name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
|
||||
name_buffer_length = NAME_FIELD_SIZE;
|
||||
|
||||
if (files_from_option)
|
||||
{
|
||||
if (!strcmp (files_from_option, "-"))
|
||||
{
|
||||
request_stdin ("-T");
|
||||
name_file = stdin;
|
||||
}
|
||||
else if (name_file = fopen (files_from_option, "r"), !name_file)
|
||||
open_fatal (files_from_option);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -251,95 +283,55 @@ name_term (void)
|
||||
free (name_array);
|
||||
}
|
||||
|
||||
/* Read the next filename from name_file and null-terminate it. Put
|
||||
it into name_buffer, reallocating and adjusting name_buffer_length
|
||||
if necessary. Return 0 at end of file, 1 otherwise. */
|
||||
static int
|
||||
read_name_from_file (void)
|
||||
{
|
||||
int character;
|
||||
size_t counter = 0;
|
||||
static int matching_flags; /* exclude_fnmatch options */
|
||||
|
||||
/* FIXME: getc may be called even if character was EOF the last time here. */
|
||||
|
||||
/* FIXME: This + 2 allocation might serve no purpose. */
|
||||
|
||||
while (character = getc (name_file),
|
||||
character != EOF && character != filename_terminator)
|
||||
{
|
||||
if (counter == name_buffer_length)
|
||||
{
|
||||
if (name_buffer_length * 2 < name_buffer_length)
|
||||
xalloc_die ();
|
||||
name_buffer_length *= 2;
|
||||
name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
|
||||
}
|
||||
name_buffer[counter++] = character;
|
||||
}
|
||||
|
||||
if (counter == 0 && character == EOF)
|
||||
return 0;
|
||||
|
||||
if (counter == name_buffer_length)
|
||||
{
|
||||
if (name_buffer_length * 2 < name_buffer_length)
|
||||
xalloc_die ();
|
||||
name_buffer_length *= 2;
|
||||
name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
|
||||
}
|
||||
name_buffer[counter] = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the next name from ARGV or the file of names. Result is in
|
||||
/* Get the next NELT_NAME element from name_array. Result is in
|
||||
static storage and can't be relied upon across two calls.
|
||||
|
||||
If CHANGE_DIRS is true, treat a filename of the form "-C" as
|
||||
meaning that the next filename is the name of a directory to change
|
||||
to. If filename_terminator is NUL, CHANGE_DIRS is effectively
|
||||
always false. */
|
||||
char *
|
||||
name_next (int change_dirs)
|
||||
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.
|
||||
|
||||
Entries of type NELT_FMASK cause updates of the matching_flags
|
||||
value. */
|
||||
struct name_elt *
|
||||
name_next_elt (int change_dirs)
|
||||
{
|
||||
static struct name_elt entry;
|
||||
const char *source;
|
||||
char *cursor;
|
||||
int chdir_flag = 0;
|
||||
|
||||
if (filename_terminator == '\0')
|
||||
change_dirs = 0;
|
||||
|
||||
while (1)
|
||||
while (name_index != names)
|
||||
{
|
||||
/* Get a name, either from file or from saved arguments. */
|
||||
|
||||
if (name_index == names)
|
||||
struct name_elt *ep;
|
||||
size_t source_len;
|
||||
|
||||
ep = &name_array[name_index++];
|
||||
if (ep->type == NELT_FMASK)
|
||||
{
|
||||
if (! name_file)
|
||||
break;
|
||||
if (! read_name_from_file ())
|
||||
break;
|
||||
matching_flags = ep->v.matching_flags;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
source = ep->v.name;
|
||||
source_len = strlen (source);
|
||||
if (name_buffer_length < source_len)
|
||||
{
|
||||
size_t source_len;
|
||||
source = name_array[name_index++];
|
||||
source_len = strlen (source);
|
||||
if (name_buffer_length < source_len)
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
name_buffer_length *= 2;
|
||||
if (! name_buffer_length)
|
||||
xalloc_die ();
|
||||
}
|
||||
while (name_buffer_length < source_len);
|
||||
|
||||
free (name_buffer);
|
||||
name_buffer = xmalloc (name_buffer_length + 2);
|
||||
name_buffer_length *= 2;
|
||||
if (! name_buffer_length)
|
||||
xalloc_die ();
|
||||
}
|
||||
strcpy (name_buffer, source);
|
||||
while (name_buffer_length < source_len);
|
||||
|
||||
free (name_buffer);
|
||||
name_buffer = xmalloc (name_buffer_length + 2);
|
||||
}
|
||||
strcpy (name_buffer, source);
|
||||
|
||||
/* Zap trailing slashes. */
|
||||
|
||||
@@ -347,36 +339,31 @@ name_next (int change_dirs)
|
||||
while (cursor > name_buffer && ISSLASH (*cursor))
|
||||
*cursor-- = '\0';
|
||||
|
||||
if (chdir_flag)
|
||||
if (change_dirs && ep->type == NELT_CHDIR)
|
||||
{
|
||||
if (chdir (name_buffer) < 0)
|
||||
chdir_fatal (name_buffer);
|
||||
chdir_flag = 0;
|
||||
}
|
||||
else if (change_dirs && strcmp (name_buffer, "-C") == 0)
|
||||
chdir_flag = 1;
|
||||
else
|
||||
{
|
||||
unquote_string (name_buffer);
|
||||
return name_buffer;
|
||||
if (unquote_option)
|
||||
unquote_string (name_buffer);
|
||||
if (incremental_option)
|
||||
register_individual_file (name_buffer);
|
||||
entry.type = ep->type;
|
||||
entry.v.name = name_buffer;
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
|
||||
/* No more names in file. */
|
||||
|
||||
if (name_file && chdir_flag)
|
||||
FATAL_ERROR ((0, 0, _("Missing file name after -C")));
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Close the name file, if any. */
|
||||
void
|
||||
name_close (void)
|
||||
const char *
|
||||
name_next (int change_dirs)
|
||||
{
|
||||
if (name_file && name_file != stdin)
|
||||
if (fclose (name_file) != 0)
|
||||
close_error (name_buffer);
|
||||
struct name_elt *nelt = name_next_elt (change_dirs);
|
||||
return nelt ? nelt->v.name : NULL;
|
||||
}
|
||||
|
||||
/* Gather names in a list for scanning. Could hash them later if we
|
||||
@@ -396,7 +383,7 @@ name_gather (void)
|
||||
static struct name *buffer;
|
||||
static size_t allocated_size;
|
||||
|
||||
char const *name;
|
||||
struct name_elt *ep;
|
||||
|
||||
if (same_order_option)
|
||||
{
|
||||
@@ -409,19 +396,15 @@ name_gather (void)
|
||||
/* FIXME: This memset is overkill, and ugly... */
|
||||
memset (buffer, 0, allocated_size);
|
||||
}
|
||||
|
||||
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name));
|
||||
|
||||
while ((name = name_next (0)) && strcmp (name, "-C") == 0)
|
||||
{
|
||||
char const *dir = name_next (0);
|
||||
if (! dir)
|
||||
FATAL_ERROR ((0, 0, _("Missing file name after -C")));
|
||||
change_dir = chdir_arg (xstrdup (dir));
|
||||
}
|
||||
|
||||
if (name)
|
||||
if (ep)
|
||||
{
|
||||
size_t needed_size;
|
||||
buffer->length = strlen (name);
|
||||
|
||||
buffer->length = strlen (ep->v.name);
|
||||
needed_size = offsetof (struct name, name) + buffer->length + 1;
|
||||
if (allocated_size < needed_size)
|
||||
{
|
||||
@@ -436,10 +419,11 @@ name_gather (void)
|
||||
buffer = xrealloc (buffer, allocated_size);
|
||||
}
|
||||
buffer->change_dir = change_dir;
|
||||
strcpy (buffer->name, name);
|
||||
strcpy (buffer->name, ep->v.name);
|
||||
buffer->next = 0;
|
||||
buffer->found_count = 0;
|
||||
|
||||
buffer->matching_flags = matching_flags;
|
||||
|
||||
namelist = buffer;
|
||||
nametail = &namelist->next;
|
||||
}
|
||||
@@ -454,15 +438,11 @@ name_gather (void)
|
||||
for (;;)
|
||||
{
|
||||
int change_dir0 = change_dir;
|
||||
while ((name = name_next (0)) && strcmp (name, "-C") == 0)
|
||||
{
|
||||
char const *dir = name_next (0);
|
||||
if (! dir)
|
||||
FATAL_ERROR ((0, 0, _("Missing file name after -C")));
|
||||
change_dir = chdir_arg (xstrdup (dir));
|
||||
}
|
||||
if (name)
|
||||
addname (name, change_dir);
|
||||
while ((ep = name_next_elt (0)) && ep->type == NELT_CHDIR)
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name));
|
||||
|
||||
if (ep)
|
||||
addname (ep->v.name, change_dir);
|
||||
else
|
||||
{
|
||||
if (change_dir != change_dir0)
|
||||
@@ -481,92 +461,65 @@ addname (char const *string, int change_dir)
|
||||
struct name *name = xmalloc (offsetof (struct name, name) + length + 1);
|
||||
|
||||
if (string)
|
||||
{
|
||||
name->fake = 0;
|
||||
strcpy (name->name, string);
|
||||
}
|
||||
strcpy (name->name, string);
|
||||
else
|
||||
{
|
||||
name->fake = 1;
|
||||
name->name[0] = 0;
|
||||
|
||||
/* FIXME: This initialization (and the byte of memory that it
|
||||
initializes) is probably not needed, but we are currently in
|
||||
bug-fix mode so we'll leave it in for now. */
|
||||
name->name[0] = 0;
|
||||
}
|
||||
|
||||
name->next = 0;
|
||||
name->next = NULL;
|
||||
name->length = length;
|
||||
name->found_count = 0;
|
||||
name->regexp = 0; /* assume not a regular expression */
|
||||
name->firstch = 1; /* assume first char is literal */
|
||||
name->matching_flags = matching_flags;
|
||||
name->change_dir = change_dir;
|
||||
name->dir_contents = 0;
|
||||
|
||||
if (string && is_pattern (string))
|
||||
{
|
||||
name->regexp = 1;
|
||||
if (string[0] == '*' || string[0] == '[' || string[0] == '?')
|
||||
name->firstch = 0;
|
||||
}
|
||||
name->dir_contents = NULL;
|
||||
|
||||
*nametail = name;
|
||||
nametail = &name->next;
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Find a match for PATH (whose string length is LENGTH) in the name
|
||||
/* Find a match for FILE_NAME (whose string length is LENGTH) in the name
|
||||
list. */
|
||||
static struct name *
|
||||
namelist_match (char const *path, size_t length)
|
||||
namelist_match (char const *file_name, size_t length)
|
||||
{
|
||||
struct name *p;
|
||||
|
||||
for (p = namelist; p; p = p->next)
|
||||
{
|
||||
/* If first chars don't match, quick skip. */
|
||||
|
||||
if (p->firstch && p->name[0] != path[0])
|
||||
continue;
|
||||
|
||||
if (p->regexp
|
||||
? fnmatch (p->name, path, recursion_option) == 0
|
||||
: (p->length <= length
|
||||
&& (path[p->length] == '\0'
|
||||
|| (ISSLASH (path[p->length]) && recursion_option))
|
||||
&& memcmp (path, p->name, p->length) == 0))
|
||||
if (p->name[0]
|
||||
&& exclude_fnmatch (p->name, file_name, p->matching_flags))
|
||||
return p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return true if and only if name PATH (from an archive) matches any
|
||||
/* Return true if and only if name FILE_NAME (from an archive) matches any
|
||||
name from the namelist. */
|
||||
int
|
||||
name_match (const char *path)
|
||||
bool
|
||||
name_match (const char *file_name)
|
||||
{
|
||||
size_t length = strlen (path);
|
||||
size_t length = strlen (file_name);
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct name *cursor = namelist;
|
||||
|
||||
if (!cursor)
|
||||
return ! files_from_option;
|
||||
|
||||
if (cursor->fake)
|
||||
return true;
|
||||
|
||||
if (cursor->name[0] == 0)
|
||||
{
|
||||
chdir_do (cursor->change_dir);
|
||||
namelist = 0;
|
||||
nametail = &namelist;
|
||||
return ! files_from_option;
|
||||
return true;
|
||||
}
|
||||
|
||||
cursor = namelist_match (path, length);
|
||||
cursor = namelist_match (file_name, length);
|
||||
if (cursor)
|
||||
{
|
||||
if (!(ISSLASH (path[cursor->length]) && recursion_option)
|
||||
if (!(ISSLASH (file_name[cursor->length]) && recursion_option)
|
||||
|| cursor->found_count == 0)
|
||||
cursor->found_count++; /* remember it matched */
|
||||
if (starting_file_option)
|
||||
@@ -590,10 +543,10 @@ name_match (const char *path)
|
||||
{
|
||||
name_gather (); /* read one more */
|
||||
if (namelist->found_count)
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,19 +565,45 @@ all_names_found (struct tar_stat_info *p)
|
||||
struct name const *cursor;
|
||||
size_t len;
|
||||
|
||||
if (test_label_option)
|
||||
return true;
|
||||
if (!p->file_name || occurrence_option == 0 || p->had_trailing_slash)
|
||||
return false;
|
||||
len = strlen (p->file_name);
|
||||
for (cursor = namelist; cursor; cursor = cursor->next)
|
||||
{
|
||||
if (cursor->regexp
|
||||
|| (!WASFOUND(cursor) && !cursor->fake)
|
||||
if ((cursor->name[0] && !WASFOUND (cursor))
|
||||
|| (len >= cursor->length && ISSLASH (p->file_name[cursor->length])))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_pattern (const char *string)
|
||||
{
|
||||
return strchr (string, '*') || strchr (string, '[') || strchr (string, '?');
|
||||
}
|
||||
|
||||
static void
|
||||
regex_usage_warning (const char *name)
|
||||
{
|
||||
static int warned_once = 0;
|
||||
|
||||
if (warn_regex_usage && is_pattern (name))
|
||||
{
|
||||
warned_once = 1;
|
||||
WARN ((0, 0,
|
||||
/* TRANSLATORS: The following three msgids form a single sentence.
|
||||
*/
|
||||
_("Pattern matching characters used in file names. Please,")));
|
||||
WARN ((0, 0,
|
||||
_("use --wildcards to enable pattern matching, or --no-wildcards to")));
|
||||
WARN ((0, 0,
|
||||
_("suppress this warning.")));
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the names of things in the namelist that were not matched. */
|
||||
void
|
||||
names_notfound (void)
|
||||
@@ -632,14 +611,15 @@ names_notfound (void)
|
||||
struct name const *cursor;
|
||||
|
||||
for (cursor = namelist; cursor; cursor = cursor->next)
|
||||
if (!WASFOUND(cursor) && !cursor->fake)
|
||||
if (!WASFOUND (cursor) && cursor->name[0])
|
||||
{
|
||||
regex_usage_warning (cursor->name);
|
||||
if (cursor->found_count == 0)
|
||||
ERROR ((0, 0, _("%s: Not found in archive"),
|
||||
quotearg_colon (cursor->name)));
|
||||
else
|
||||
ERROR ((0, 0, _("%s: Required occurrence not found in archive"),
|
||||
quotearg_colon (cursor->name)));
|
||||
quotearg_colon (cursor->name)));
|
||||
}
|
||||
|
||||
/* Don't bother freeing the name list; we're about to exit. */
|
||||
@@ -648,11 +628,14 @@ names_notfound (void)
|
||||
|
||||
if (same_order_option)
|
||||
{
|
||||
char *name;
|
||||
const char *name;
|
||||
|
||||
while ((name = name_next (1)) != NULL)
|
||||
ERROR ((0, 0, _("%s: Not found in archive"),
|
||||
quotearg_colon (name)));
|
||||
{
|
||||
regex_usage_warning (name);
|
||||
ERROR ((0, 0, _("%s: Not found in archive"),
|
||||
quotearg_colon (name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,8 +733,8 @@ compare_names (struct name const *n1, struct name const *n2)
|
||||
static void
|
||||
add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
{
|
||||
char *path = name->name;
|
||||
char *buffer = get_directory_contents (path, device);
|
||||
char *file_name = name->name;
|
||||
char *buffer = get_directory_contents (file_name, device);
|
||||
|
||||
if (! buffer)
|
||||
name->dir_contents = "\0\0\0\0";
|
||||
@@ -768,7 +751,7 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
int change_dir = name->change_dir;
|
||||
|
||||
name->dir_contents = buffer;
|
||||
strcpy (namebuf, path);
|
||||
strcpy (namebuf, file_name);
|
||||
if (! ISSLASH (namebuf[name_length - 1]))
|
||||
{
|
||||
namebuf[name_length++] = '/';
|
||||
@@ -780,6 +763,8 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
string_length = strlen (string);
|
||||
if (*string == 'D')
|
||||
{
|
||||
struct name *np;
|
||||
|
||||
if (allocated_length <= name_length + string_length)
|
||||
{
|
||||
do
|
||||
@@ -793,8 +778,8 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
|
||||
namebuf = xrealloc (namebuf, allocated_length + 1);
|
||||
}
|
||||
strcpy (namebuf + name_length, string + 1);
|
||||
add_hierarchy_to_namelist (addname (namebuf, change_dir),
|
||||
device);
|
||||
np = addname (namebuf, change_dir);
|
||||
add_hierarchy_to_namelist (np, device);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,10 +812,12 @@ collect_and_sort_names (void)
|
||||
next_name = name->next;
|
||||
if (name->found_count || name->dir_contents)
|
||||
continue;
|
||||
if (name->regexp) /* FIXME: just skip regexps for now */
|
||||
if (name->matching_flags & EXCLUDE_WILDCARDS)
|
||||
/* NOTE: EXCLUDE_ANCHORED is not relevant here */
|
||||
/* FIXME: just skip regexps for now */
|
||||
continue;
|
||||
chdir_do (name->change_dir);
|
||||
if (name->fake)
|
||||
if (name->name[0] == 0)
|
||||
continue;
|
||||
|
||||
if (deref_stat (dereference_option, name->name, &statbuf) != 0)
|
||||
@@ -852,20 +839,29 @@ collect_and_sort_names (void)
|
||||
|
||||
for (name = namelist; name; name = name->next)
|
||||
name->found_count = 0;
|
||||
|
||||
if (listed_incremental_option)
|
||||
{
|
||||
for (name = namelist; name && name->name[0] == 0; name++)
|
||||
;
|
||||
if (name)
|
||||
name->dir_contents = append_incremental_renames (name->dir_contents);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is like name_match, except that 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. Oh, and if the namelist is
|
||||
empty, it returns null, unlike name_match, which returns TRUE. */
|
||||
/* This is like name_match, except that
|
||||
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. */
|
||||
struct name *
|
||||
name_scan (const char *path)
|
||||
name_scan (const char *file_name)
|
||||
{
|
||||
size_t length = strlen (path);
|
||||
size_t length = strlen (file_name);
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct name *cursor = namelist_match (path, length);
|
||||
struct name *cursor = namelist_match (file_name, length);
|
||||
if (cursor)
|
||||
return cursor;
|
||||
|
||||
@@ -895,7 +891,8 @@ name_from_list (void)
|
||||
{
|
||||
if (!gnu_list_name)
|
||||
gnu_list_name = namelist;
|
||||
while (gnu_list_name && (gnu_list_name->found_count || gnu_list_name->fake))
|
||||
while (gnu_list_name
|
||||
&& (gnu_list_name->found_count || gnu_list_name->name[0] == 0))
|
||||
gnu_list_name = gnu_list_name->next;
|
||||
if (gnu_list_name)
|
||||
{
|
||||
@@ -916,18 +913,18 @@ blank_name_list (void)
|
||||
name->found_count = 0;
|
||||
}
|
||||
|
||||
/* Yield a newly allocated file name consisting of PATH concatenated to
|
||||
NAME, with an intervening slash if PATH does not already end in one. */
|
||||
/* Yield a newly allocated file name consisting of FILE_NAME concatenated to
|
||||
NAME, with an intervening slash if FILE_NAME does not already end in one. */
|
||||
char *
|
||||
new_name (const char *path, const char *name)
|
||||
new_name (const char *file_name, const char *name)
|
||||
{
|
||||
size_t pathlen = strlen (path);
|
||||
size_t file_name_len = strlen (file_name);
|
||||
size_t namesize = strlen (name) + 1;
|
||||
int slash = pathlen && ! ISSLASH (path[pathlen - 1]);
|
||||
char *buffer = xmalloc (pathlen + slash + namesize);
|
||||
memcpy (buffer, path, pathlen);
|
||||
buffer[pathlen] = '/';
|
||||
memcpy (buffer + pathlen + slash, name, namesize);
|
||||
int slash = file_name_len && ! ISSLASH (file_name[file_name_len - 1]);
|
||||
char *buffer = xmalloc (file_name_len + slash + namesize);
|
||||
memcpy (buffer, file_name, file_name_len);
|
||||
buffer[file_name_len] = '/';
|
||||
memcpy (buffer + file_name_len + slash, name, namesize);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -935,54 +932,7 @@ new_name (const char *path, const char *name)
|
||||
bool
|
||||
excluded_name (char const *name)
|
||||
{
|
||||
return excluded_filename (excluded, name + FILESYSTEM_PREFIX_LEN (name));
|
||||
}
|
||||
|
||||
/* Hash tables of strings. */
|
||||
|
||||
/* Calculate the hash of a string. */
|
||||
static unsigned
|
||||
hash_string_hasher (void const *name, unsigned n_buckets)
|
||||
{
|
||||
return hash_string (name, n_buckets);
|
||||
}
|
||||
|
||||
/* Compare two strings for equality. */
|
||||
static bool
|
||||
hash_string_compare (void const *name1, void const *name2)
|
||||
{
|
||||
return strcmp (name1, name2) == 0;
|
||||
}
|
||||
|
||||
/* Return zero if TABLE contains a copy of STRING; otherwise, insert a
|
||||
copy of STRING to TABLE and return 1. */
|
||||
static bool
|
||||
hash_string_insert (Hash_table **table, char const *string)
|
||||
{
|
||||
Hash_table *t = *table;
|
||||
char *s = xstrdup (string);
|
||||
char *e;
|
||||
|
||||
if (! ((t
|
||||
|| (*table = t = hash_initialize (0, 0, hash_string_hasher,
|
||||
hash_string_compare, 0)))
|
||||
&& (e = hash_insert (t, s))))
|
||||
xalloc_die ();
|
||||
|
||||
if (e == s)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
free (s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if TABLE contains STRING. */
|
||||
static bool
|
||||
hash_string_lookup (Hash_table const *table, char const *string)
|
||||
{
|
||||
return table && hash_lookup (table, string);
|
||||
return excluded_file_name (excluded, name + FILE_SYSTEM_PREFIX_LEN (name));
|
||||
}
|
||||
|
||||
/* Names to avoid dumping. */
|
||||
@@ -1001,89 +951,39 @@ is_avoided_name (char const *name)
|
||||
{
|
||||
return hash_string_lookup (avoided_name_table, name);
|
||||
}
|
||||
|
||||
/* Return a safer suffix of FILE_NAME, or "." if it has no safer
|
||||
suffix. Check for fully specified file names and other atrocities.
|
||||
Warn the user if we do not return NAME. If LINK_TARGET is 1,
|
||||
FILE_NAME is the target of a hard link, not a member name. */
|
||||
|
||||
char *
|
||||
safer_name_suffix (char const *file_name, bool link_target)
|
||||
|
||||
static Hash_table *individual_file_table;
|
||||
|
||||
static void
|
||||
register_individual_file (char const *name)
|
||||
{
|
||||
char const *p;
|
||||
struct stat st;
|
||||
|
||||
if (absolute_names_option)
|
||||
p = file_name;
|
||||
else
|
||||
{
|
||||
/* Skip file system prefixes, leading pathnames that contain
|
||||
"..", and leading slashes. */
|
||||
if (deref_stat (dereference_option, name, &st) != 0)
|
||||
return; /* Will be complained about later */
|
||||
if (S_ISDIR (st.st_mode))
|
||||
return;
|
||||
|
||||
size_t prefix_len = FILESYSTEM_PREFIX_LEN (file_name);
|
||||
|
||||
for (p = file_name + prefix_len; *p; )
|
||||
{
|
||||
if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
|
||||
prefix_len = p + 2 - file_name;
|
||||
|
||||
do
|
||||
{
|
||||
char c = *p++;
|
||||
if (ISSLASH (c))
|
||||
break;
|
||||
}
|
||||
while (*p);
|
||||
}
|
||||
|
||||
for (p = file_name + prefix_len; ISSLASH (*p); p++)
|
||||
continue;
|
||||
prefix_len = p - file_name;
|
||||
|
||||
if (prefix_len)
|
||||
{
|
||||
static Hash_table *prefix_table[2];
|
||||
char *prefix = alloca (prefix_len + 1);
|
||||
memcpy (prefix, file_name, prefix_len);
|
||||
prefix[prefix_len] = '\0';
|
||||
|
||||
if (hash_string_insert (&prefix_table[link_target], prefix))
|
||||
{
|
||||
static char const *const diagnostic[] =
|
||||
{
|
||||
N_("Removing leading `%s' from member names"),
|
||||
N_("Removing leading `%s' from hard link targets")
|
||||
};
|
||||
WARN ((0, 0, _(diagnostic[link_target]), prefix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! *p)
|
||||
{
|
||||
if (p == file_name)
|
||||
{
|
||||
static char const *const diagnostic[] =
|
||||
{
|
||||
N_("Substituting `.' for empty member name"),
|
||||
N_("Substituting `.' for empty hard link target")
|
||||
};
|
||||
WARN ((0, 0, _(diagnostic[link_target])));
|
||||
}
|
||||
|
||||
p = ".";
|
||||
}
|
||||
|
||||
return (char *) p;
|
||||
hash_string_insert (&individual_file_table, name);
|
||||
}
|
||||
|
||||
bool
|
||||
is_individual_file (char const *name)
|
||||
{
|
||||
return hash_string_lookup (individual_file_table, name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Return the size of the prefix of FILE_NAME that is removed after
|
||||
stripping NUM leading path name components. NUM must be
|
||||
stripping NUM leading file name components. NUM must be
|
||||
positive. */
|
||||
|
||||
size_t
|
||||
stripped_prefix_len (char const *file_name, size_t num)
|
||||
{
|
||||
char const *p = file_name + FILESYSTEM_PREFIX_LEN (file_name);
|
||||
char const *p = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
|
||||
while (ISSLASH (*p))
|
||||
p++;
|
||||
while (*p)
|
||||
@@ -1101,11 +1001,11 @@ stripped_prefix_len (char const *file_name, size_t num)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return nonzero if NAME contains ".." as a path name component. */
|
||||
/* Return nonzero if NAME contains ".." as a file name component. */
|
||||
bool
|
||||
contains_dot_dot (char const *name)
|
||||
{
|
||||
char const *p = name + FILESYSTEM_PREFIX_LEN (name);
|
||||
char const *p = name + FILE_SYSTEM_PREFIX_LEN (name);
|
||||
|
||||
for (;; p++)
|
||||
{
|
||||
|
||||
577
src/rmt.c
577
src/rmt.c
@@ -1,577 +0,0 @@
|
||||
/* Remote connection server.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Copyright (C) 1983 Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms are permitted provided
|
||||
that the above copyright notice and this paragraph are duplicated in all
|
||||
such forms and that any documentation, advertising materials, and other
|
||||
materials related to such distribution and use acknowledge that the
|
||||
software was developed by the University of California, Berkeley. The
|
||||
name of the University may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
|
||||
|
||||
#include "system.h"
|
||||
#include <localedir.h>
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
#ifndef EXIT_SUCCESS
|
||||
# define EXIT_SUCCESS 0
|
||||
#endif
|
||||
|
||||
/* Maximum size of a string from the requesting program. */
|
||||
#define STRING_SIZE 64
|
||||
|
||||
/* Name of executing program. */
|
||||
const char *program_name;
|
||||
|
||||
/* File descriptor of the tape device, or negative if none open. */
|
||||
static int tape = -1;
|
||||
|
||||
/* Buffer containing transferred data, and its allocated size. */
|
||||
static char *record_buffer;
|
||||
static size_t allocated_size;
|
||||
|
||||
/* Buffer for constructing the reply. */
|
||||
static char reply_buffer[BUFSIZ];
|
||||
|
||||
/* Debugging tools. */
|
||||
|
||||
static FILE *debug_file;
|
||||
|
||||
#define DEBUG(File) \
|
||||
if (debug_file) fprintf(debug_file, File)
|
||||
|
||||
#define DEBUG1(File, Arg) \
|
||||
if (debug_file) fprintf(debug_file, File, Arg)
|
||||
|
||||
#define DEBUG2(File, Arg1, Arg2) \
|
||||
if (debug_file) fprintf(debug_file, File, Arg1, Arg2)
|
||||
|
||||
/* Return an error string, given an error number. */
|
||||
#if HAVE_STRERROR
|
||||
# ifndef strerror
|
||||
char *strerror ();
|
||||
# endif
|
||||
#else
|
||||
static char *
|
||||
private_strerror (int errnum)
|
||||
{
|
||||
extern char *sys_errlist[];
|
||||
extern int sys_nerr;
|
||||
|
||||
if (errnum > 0 && errnum <= sys_nerr)
|
||||
return _(sys_errlist[errnum]);
|
||||
return _("Unknown system error");
|
||||
}
|
||||
# define strerror private_strerror
|
||||
#endif
|
||||
|
||||
static void
|
||||
report_error_message (const char *string)
|
||||
{
|
||||
DEBUG1 ("rmtd: E 0 (%s)\n", string);
|
||||
|
||||
sprintf (reply_buffer, "E0\n%s\n", string);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
}
|
||||
|
||||
static void
|
||||
report_numbered_error (int num)
|
||||
{
|
||||
DEBUG2 ("rmtd: E %d (%s)\n", num, strerror (num));
|
||||
|
||||
sprintf (reply_buffer, "E%d\n%s\n", num, strerror (num));
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
}
|
||||
|
||||
static void
|
||||
get_string (char *string)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = 0; ; counter++)
|
||||
{
|
||||
if (safe_read (STDIN_FILENO, string + counter, 1) != 1)
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
if (string[counter] == '\n' || counter == STRING_SIZE - 1)
|
||||
break;
|
||||
}
|
||||
string[counter] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_input_buffer (int fd, size_t size)
|
||||
{
|
||||
if (size <= allocated_size)
|
||||
return;
|
||||
|
||||
if (record_buffer)
|
||||
free (record_buffer);
|
||||
|
||||
record_buffer = malloc (size);
|
||||
|
||||
if (! record_buffer)
|
||||
{
|
||||
DEBUG (_("rmtd: Cannot allocate buffer space\n"));
|
||||
|
||||
report_error_message (N_("Cannot allocate buffer space"));
|
||||
exit (EXIT_FAILURE); /* exit status used to be 4 */
|
||||
}
|
||||
|
||||
allocated_size = size;
|
||||
|
||||
#ifdef SO_RCVBUF
|
||||
if (0 <= fd)
|
||||
{
|
||||
int isize = size < INT_MAX ? size : INT_MAX;
|
||||
while (setsockopt (fd, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *) &isize, sizeof isize)
|
||||
&& 1024 < isize)
|
||||
isize >>= 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Decode OFLAG_STRING, which represents the 2nd argument to `open'.
|
||||
OFLAG_STRING should contain an optional integer, followed by an optional
|
||||
symbolic representation of an open flag using only '|' to separate its
|
||||
components (e.g. "O_WRONLY|O_CREAT|O_TRUNC"). Prefer the symbolic
|
||||
representation if available, falling back on the numeric
|
||||
representation, or to zero if both formats are absent.
|
||||
|
||||
This function should be the inverse of encode_oflag. The numeric
|
||||
representation is not portable from one host to another, but it is
|
||||
for backward compatibility with old-fashioned clients that do not
|
||||
emit symbolic open flags. */
|
||||
|
||||
static int
|
||||
decode_oflag (char const *oflag_string)
|
||||
{
|
||||
char *oflag_num_end;
|
||||
int numeric_oflag = strtol (oflag_string, &oflag_num_end, 10);
|
||||
int symbolic_oflag = 0;
|
||||
|
||||
oflag_string = oflag_num_end;
|
||||
while (ISSPACE ((unsigned char) *oflag_string))
|
||||
oflag_string++;
|
||||
|
||||
do
|
||||
{
|
||||
struct name_value_pair { char const *name; int value; };
|
||||
static struct name_value_pair const table[] =
|
||||
{
|
||||
#ifdef O_APPEND
|
||||
{"APPEND", O_APPEND},
|
||||
#endif
|
||||
{"CREAT", O_CREAT},
|
||||
#ifdef O_DSYNC
|
||||
{"DSYNC", O_DSYNC},
|
||||
#endif
|
||||
{"EXCL", O_EXCL},
|
||||
#ifdef O_LARGEFILE
|
||||
{"LARGEFILE", O_LARGEFILE}, /* LFS extension for opening large files */
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
{"NOCTTY", O_NOCTTY},
|
||||
#endif
|
||||
#ifdef O_NONBLOCK
|
||||
{"NONBLOCK", O_NONBLOCK},
|
||||
#endif
|
||||
{"RDONLY", O_RDONLY},
|
||||
{"RDWR", O_RDWR},
|
||||
#ifdef O_RSYNC
|
||||
{"RSYNC", O_RSYNC},
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
{"SYNC", O_SYNC},
|
||||
#endif
|
||||
{"TRUNC", O_TRUNC},
|
||||
{"WRONLY", O_WRONLY}
|
||||
};
|
||||
struct name_value_pair const *t;
|
||||
size_t s;
|
||||
|
||||
if (*oflag_string++ != 'O' || *oflag_string++ != '_')
|
||||
return numeric_oflag;
|
||||
|
||||
for (t = table;
|
||||
(strncmp (oflag_string, t->name, s = strlen (t->name)) != 0
|
||||
|| (oflag_string[s]
|
||||
&& strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789",
|
||||
oflag_string[s])));
|
||||
t++)
|
||||
if (t == table + sizeof table / sizeof *table - 1)
|
||||
return numeric_oflag;
|
||||
|
||||
symbolic_oflag |= t->value;
|
||||
oflag_string += s;
|
||||
}
|
||||
while (*oflag_string++ == '|');
|
||||
|
||||
return symbolic_oflag;
|
||||
}
|
||||
|
||||
static struct option const long_opts[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void usage (int) __attribute__ ((noreturn));
|
||||
|
||||
static void
|
||||
usage (int status)
|
||||
{
|
||||
if (status != EXIT_SUCCESS)
|
||||
fprintf (stderr, _("Try `%s --help' for more information.\n"),
|
||||
program_name);
|
||||
else
|
||||
{
|
||||
printf (_("\
|
||||
Usage: %s [OPTION]\n\
|
||||
Manipulate a tape drive, accepting commands from a remote process.\n\
|
||||
\n\
|
||||
--version Output version info.\n\
|
||||
--help Output this help.\n"),
|
||||
program_name);
|
||||
printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
|
||||
}
|
||||
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *const *argv)
|
||||
{
|
||||
char command;
|
||||
size_t status;
|
||||
|
||||
/* FIXME: Localization is meaningless, unless --help and --version are
|
||||
locally used. Localization would be best accomplished by the calling
|
||||
tar, on messages found within error packets. */
|
||||
|
||||
program_name = argv[0];
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
switch (getopt_long (argc, argv, "", long_opts, NULL))
|
||||
{
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
|
||||
case 'h':
|
||||
usage (EXIT_SUCCESS);
|
||||
|
||||
case 'v':
|
||||
{
|
||||
printf ("rmt (%s) %s\n%s\n", PACKAGE_NAME, PACKAGE_VERSION,
|
||||
"Copyright (C) 2004 Free Software Foundation, Inc.");
|
||||
puts (_("\
|
||||
This program comes with NO WARRANTY, to the extent permitted by law.\n\
|
||||
You may redistribute it under the terms of the GNU General Public License;\n\
|
||||
see the file named COPYING for details."));
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
case -1:
|
||||
break;
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
if (optind != argc - 1)
|
||||
usage (EXIT_FAILURE);
|
||||
debug_file = fopen (argv[optind], "w");
|
||||
if (debug_file == 0)
|
||||
{
|
||||
report_numbered_error (errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
setbuf (debug_file, 0);
|
||||
}
|
||||
|
||||
top:
|
||||
errno = 0;
|
||||
status = 0;
|
||||
if (safe_read (STDIN_FILENO, &command, 1) != 1)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
/* FIXME: Maybe 'H' and 'V' for --help and --version output? */
|
||||
|
||||
case 'O':
|
||||
{
|
||||
char device_string[STRING_SIZE];
|
||||
char oflag_string[STRING_SIZE];
|
||||
|
||||
get_string (device_string);
|
||||
get_string (oflag_string);
|
||||
DEBUG2 ("rmtd: O %s %s\n", device_string, oflag_string);
|
||||
|
||||
if (tape >= 0)
|
||||
close (tape);
|
||||
|
||||
tape = open (device_string, decode_oflag (oflag_string), MODE_RW);
|
||||
if (tape < 0)
|
||||
goto ioerror;
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
{
|
||||
char device_string[STRING_SIZE];
|
||||
|
||||
get_string (device_string); /* discard */
|
||||
DEBUG ("rmtd: C\n");
|
||||
|
||||
if (close (tape) < 0)
|
||||
goto ioerror;
|
||||
tape = -1;
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
char count_string[STRING_SIZE];
|
||||
char position_string[STRING_SIZE];
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
int whence;
|
||||
char *p;
|
||||
|
||||
get_string (count_string);
|
||||
get_string (position_string);
|
||||
DEBUG2 ("rmtd: L %s %s\n", count_string, position_string);
|
||||
|
||||
/* Parse count_string, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
for (p = count_string; *p == ' ' || *p == '\t'; p++)
|
||||
continue;
|
||||
|
||||
negative = *p == '-';
|
||||
p += negative || *p == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *p++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
{
|
||||
report_error_message (N_("Seek offset out of range"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
switch (atoi (position_string))
|
||||
{
|
||||
case 0: whence = SEEK_SET; break;
|
||||
case 1: whence = SEEK_CUR; break;
|
||||
case 2: whence = SEEK_END; break;
|
||||
default:
|
||||
report_error_message (N_("Seek direction out of range"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
count = lseek (tape, count, whence);
|
||||
if (count < 0)
|
||||
goto ioerror;
|
||||
|
||||
/* Convert count back to string for reply.
|
||||
We can't use sprintf, since off_t might be longer than long. */
|
||||
p = count_string + sizeof count_string;
|
||||
*--p = '\0';
|
||||
do
|
||||
*--p = '0' + (int) (count % 10);
|
||||
while ((count /= 10) != 0);
|
||||
|
||||
DEBUG1 ("rmtd: A %s\n", p);
|
||||
|
||||
sprintf (reply_buffer, "A%s\n", p);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
goto top;
|
||||
}
|
||||
|
||||
case 'W':
|
||||
{
|
||||
char count_string[STRING_SIZE];
|
||||
size_t size;
|
||||
size_t counter;
|
||||
|
||||
get_string (count_string);
|
||||
size = atol (count_string);
|
||||
DEBUG1 ("rmtd: W %s\n", count_string);
|
||||
|
||||
prepare_input_buffer (STDIN_FILENO, size);
|
||||
for (counter = 0; counter < size; counter += status)
|
||||
{
|
||||
status = safe_read (STDIN_FILENO, &record_buffer[counter],
|
||||
size - counter);
|
||||
if (status == SAFE_READ_ERROR || status == 0)
|
||||
{
|
||||
DEBUG (_("rmtd: Premature eof\n"));
|
||||
|
||||
report_error_message (N_("Premature end of file"));
|
||||
return EXIT_FAILURE; /* exit status used to be 2 */
|
||||
}
|
||||
}
|
||||
status = full_write (tape, record_buffer, size);
|
||||
if (status != size)
|
||||
goto ioerror;
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'R':
|
||||
{
|
||||
char count_string[STRING_SIZE];
|
||||
size_t size;
|
||||
|
||||
get_string (count_string);
|
||||
DEBUG1 ("rmtd: R %s\n", count_string);
|
||||
|
||||
size = atol (count_string);
|
||||
prepare_input_buffer (-1, size);
|
||||
status = safe_read (tape, record_buffer, size);
|
||||
if (status == SAFE_READ_ERROR)
|
||||
goto ioerror;
|
||||
sprintf (reply_buffer, "A%lu\n", (unsigned long int) status);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
full_write (STDOUT_FILENO, record_buffer, status);
|
||||
goto top;
|
||||
}
|
||||
|
||||
case 'I':
|
||||
{
|
||||
char operation_string[STRING_SIZE];
|
||||
char count_string[STRING_SIZE];
|
||||
|
||||
get_string (operation_string);
|
||||
get_string (count_string);
|
||||
DEBUG2 ("rmtd: I %s %s\n", operation_string, count_string);
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
{
|
||||
struct mtop mtop;
|
||||
const char *p;
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
|
||||
/* Parse count_string, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
for (p = count_string; *p == ' ' || *p == '\t'; p++)
|
||||
continue;
|
||||
|
||||
negative = *p == '-';
|
||||
p += negative || *p == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *p++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
{
|
||||
report_error_message (N_("Seek offset out of range"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
mtop.mt_count = count;
|
||||
if (mtop.mt_count != count)
|
||||
{
|
||||
report_error_message (N_("Seek offset out of range"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
mtop.mt_op = atoi (operation_string);
|
||||
|
||||
if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
|
||||
goto ioerror;
|
||||
}
|
||||
#endif
|
||||
goto respond;
|
||||
}
|
||||
|
||||
case 'S': /* status */
|
||||
{
|
||||
DEBUG ("rmtd: S\n");
|
||||
|
||||
#ifdef MTIOCGET
|
||||
{
|
||||
struct mtget operation;
|
||||
|
||||
if (ioctl (tape, MTIOCGET, (char *) &operation) < 0)
|
||||
goto ioerror;
|
||||
status = sizeof operation;
|
||||
sprintf (reply_buffer, "A%ld\n", (long) status);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
full_write (STDOUT_FILENO, (char *) &operation, sizeof operation);
|
||||
}
|
||||
#endif
|
||||
goto top;
|
||||
}
|
||||
|
||||
default:
|
||||
DEBUG1 (_("rmtd: Garbage command %c\n"), command);
|
||||
|
||||
report_error_message (N_("Garbage command"));
|
||||
return EXIT_FAILURE; /* exit status used to be 3 */
|
||||
}
|
||||
|
||||
respond:
|
||||
DEBUG1 ("rmtd: A %ld\n", (long) status);
|
||||
|
||||
sprintf (reply_buffer, "A%ld\n", (long) status);
|
||||
full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
|
||||
goto top;
|
||||
|
||||
ioerror:
|
||||
report_numbered_error (errno);
|
||||
goto top;
|
||||
}
|
||||
95
src/rmt.h
95
src/rmt.h
@@ -1,95 +0,0 @@
|
||||
/* Definitions for communicating with a remote tape drive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1996, 1997, 2001, 2003, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
extern char *rmt_path__;
|
||||
|
||||
int rmt_open__ (const char *, int, int, const char *);
|
||||
int rmt_close__ (int);
|
||||
size_t rmt_read__ (int, char *, size_t);
|
||||
size_t rmt_write__ (int, char *, size_t);
|
||||
off_t rmt_lseek__ (int, off_t, int);
|
||||
int rmt_ioctl__ (int, int, char *);
|
||||
|
||||
/* A filename is remote if it contains a colon not preceded by a slash,
|
||||
to take care of `/:/' which is a shorthand for `/.../<CELL-NAME>/fs'
|
||||
on machines running OSF's Distributing Computing Environment (DCE) and
|
||||
Distributed File System (DFS). However, when --force-local, a
|
||||
filename is never remote. */
|
||||
|
||||
#define _remdev(Path) \
|
||||
(!force_local_option && (rmt_path__ = strchr (Path, ':')) \
|
||||
&& rmt_path__ > (Path) && ! memchr (Path, '/', rmt_path__ - (Path)))
|
||||
|
||||
#define _isrmt(Fd) \
|
||||
((Fd) >= __REM_BIAS)
|
||||
|
||||
#define __REM_BIAS (1 << 30)
|
||||
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 01000
|
||||
#endif
|
||||
|
||||
#define rmtopen(Path, Oflag, Mode, Command) \
|
||||
(_remdev (Path) ? rmt_open__ (Path, Oflag, __REM_BIAS, Command) \
|
||||
: open (Path, Oflag, Mode))
|
||||
|
||||
#define rmtaccess(Path, Amode) \
|
||||
(_remdev (Path) ? 0 : access (Path, Amode))
|
||||
|
||||
#define rmtstat(Path, Buffer) \
|
||||
(_remdev (Path) ? (errno = EOPNOTSUPP), -1 : stat (Path, Buffer))
|
||||
|
||||
#define rmtcreat(Path, Mode, Command) \
|
||||
(_remdev (Path) \
|
||||
? rmt_open__ (Path, 1 | O_CREAT, __REM_BIAS, Command) \
|
||||
: creat (Path, Mode))
|
||||
|
||||
#define rmtlstat(Path, Buffer) \
|
||||
(_remdev (Path) ? (errno = EOPNOTSUPP), -1 : lstat (Path, Buffer))
|
||||
|
||||
#define rmtread(Fd, Buffer, Length) \
|
||||
(_isrmt (Fd) ? rmt_read__ (Fd - __REM_BIAS, Buffer, Length) \
|
||||
: safe_read (Fd, Buffer, Length))
|
||||
|
||||
#define rmtwrite(Fd, Buffer, Length) \
|
||||
(_isrmt (Fd) ? rmt_write__ (Fd - __REM_BIAS, Buffer, Length) \
|
||||
: full_write (Fd, Buffer, Length))
|
||||
|
||||
#define rmtlseek(Fd, Offset, Where) \
|
||||
(_isrmt (Fd) ? rmt_lseek__ (Fd - __REM_BIAS, Offset, Where) \
|
||||
: lseek (Fd, Offset, Where))
|
||||
|
||||
#define rmtclose(Fd) \
|
||||
(_isrmt (Fd) ? rmt_close__ (Fd - __REM_BIAS) : close (Fd))
|
||||
|
||||
#define rmtioctl(Fd, Request, Argument) \
|
||||
(_isrmt (Fd) ? rmt_ioctl__ (Fd - __REM_BIAS, Request, Argument) \
|
||||
: ioctl (Fd, Request, Argument))
|
||||
|
||||
#define rmtdup(Fd) \
|
||||
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : dup (Fd))
|
||||
|
||||
#define rmtfstat(Fd, Buffer) \
|
||||
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : fstat (Fd, Buffer))
|
||||
|
||||
#define rmtfcntl(Fd, Command, Argument) \
|
||||
(_isrmt (Fd) ? (errno = EOPNOTSUPP), -1 : fcntl (Fd, Command, Argument))
|
||||
|
||||
#define rmtisatty(Fd) \
|
||||
(_isrmt (Fd) ? 0 : isatty (Fd))
|
||||
734
src/rtapelib.c
734
src/rtapelib.c
@@ -1,734 +0,0 @@
|
||||
/* Functions for communicating with a remote tape drive.
|
||||
|
||||
Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* The man page rmt(8) for /etc/rmt documents the remote mag tape protocol
|
||||
which rdump and rrestore use. Unfortunately, the man page is *WRONG*.
|
||||
The author of the routines I'm including originally wrote his code just
|
||||
based on the man page, and it didn't work, so he went to the rdump source
|
||||
to figure out why. The only thing he had to change was to check for the
|
||||
'F' return code in addition to the 'E', and to separate the various
|
||||
arguments with \n instead of a space. I personally don't think that this
|
||||
is much of a problem, but I wanted to point it out. -- Arnold Robbins
|
||||
|
||||
Originally written by Jeff Lee, modified some by Arnold Robbins. Redone
|
||||
as a library that can replace open, read, write, etc., by Fred Fish, with
|
||||
some additional work by Arnold Robbins. Modified to make all rmt* calls
|
||||
into macros for speed by Jay Fenlason. Use -DWITH_REXEC for rexec
|
||||
code, courtesy of Dan Kegel. */
|
||||
|
||||
#include "system.h"
|
||||
#include "common.h"
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
|
||||
/* Try hard to get EOPNOTSUPP defined. 486/ISC has it in net/errno.h,
|
||||
3B2/SVR3 has it in sys/inet.h. Otherwise, like on MSDOS, use EINVAL. */
|
||||
|
||||
#ifndef EOPNOTSUPP
|
||||
# if HAVE_NET_ERRNO_H
|
||||
# include <net/errno.h>
|
||||
# endif
|
||||
# if HAVE_SYS_INET_H
|
||||
# include <sys/inet.h>
|
||||
# endif
|
||||
# ifndef EOPNOTSUPP
|
||||
# define EOPNOTSUPP EINVAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#if HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "rmt.h"
|
||||
|
||||
/* Exit status if exec errors. */
|
||||
#define EXIT_ON_EXEC_ERROR 128
|
||||
|
||||
/* FIXME: Size of buffers for reading and writing commands to rmt. */
|
||||
#define COMMAND_BUFFER_SIZE 64
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
# define RETSIGTYPE void
|
||||
#endif
|
||||
|
||||
/* FIXME: Maximum number of simultaneous remote tape connections. */
|
||||
#define MAXUNIT 4
|
||||
|
||||
#define PREAD 0 /* read file descriptor from pipe() */
|
||||
#define PWRITE 1 /* write file descriptor from pipe() */
|
||||
|
||||
/* Return the parent's read side of remote tape connection Fd. */
|
||||
#define READ_SIDE(Fd) (from_remote[Fd][PREAD])
|
||||
|
||||
/* Return the parent's write side of remote tape connection Fd. */
|
||||
#define WRITE_SIDE(Fd) (to_remote[Fd][PWRITE])
|
||||
|
||||
/* The pipes for receiving data from remote tape drives. */
|
||||
static int from_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
/* The pipes for sending data to remote tape drives. */
|
||||
static int to_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
#define RMT_COMMAND (rmt_command_option ? rmt_command_option : "/etc/rmt")
|
||||
|
||||
/* Temporary variable used by macros in rmt.h. */
|
||||
char *rmt_path__;
|
||||
|
||||
|
||||
/* Close remote tape connection HANDLE, and reset errno to ERRNO_VALUE. */
|
||||
static void
|
||||
_rmt_shutdown (int handle, int errno_value)
|
||||
{
|
||||
close (READ_SIDE (handle));
|
||||
close (WRITE_SIDE (handle));
|
||||
READ_SIDE (handle) = -1;
|
||||
WRITE_SIDE (handle) = -1;
|
||||
errno = errno_value;
|
||||
}
|
||||
|
||||
/* Attempt to perform the remote tape command specified in BUFFER on
|
||||
remote tape connection HANDLE. Return 0 if successful, -1 on
|
||||
error. */
|
||||
static int
|
||||
do_command (int handle, const char *buffer)
|
||||
{
|
||||
/* Save the current pipe handler and try to make the request. */
|
||||
|
||||
size_t length = strlen (buffer);
|
||||
RETSIGTYPE (*pipe_handler) () = signal (SIGPIPE, SIG_IGN);
|
||||
ssize_t written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
|
||||
if (written == length)
|
||||
return 0;
|
||||
|
||||
/* Something went wrong. Close down and go home. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_status_string (int handle, char *command_buffer)
|
||||
{
|
||||
char *cursor;
|
||||
int counter;
|
||||
|
||||
/* Read the reply command line. */
|
||||
|
||||
for (counter = 0, cursor = command_buffer;
|
||||
counter < COMMAND_BUFFER_SIZE;
|
||||
counter++, cursor++)
|
||||
{
|
||||
if (safe_read (READ_SIDE (handle), cursor, 1) != 1)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
if (*cursor == '\n')
|
||||
{
|
||||
*cursor = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == COMMAND_BUFFER_SIZE)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the return status. */
|
||||
|
||||
for (cursor = command_buffer; *cursor; cursor++)
|
||||
if (*cursor != ' ')
|
||||
break;
|
||||
|
||||
if (*cursor == 'E' || *cursor == 'F')
|
||||
{
|
||||
/* Skip the error message line. */
|
||||
|
||||
/* FIXME: there is better to do than merely ignoring error messages
|
||||
coming from the remote end. Translate them, too... */
|
||||
|
||||
{
|
||||
char character;
|
||||
|
||||
while (safe_read (READ_SIDE (handle), &character, 1) == 1)
|
||||
if (character == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
errno = atoi (cursor + 1);
|
||||
|
||||
if (*cursor == 'F')
|
||||
_rmt_shutdown (handle, errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for mis-synced pipes. */
|
||||
|
||||
if (*cursor != 'A')
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Got an `A' (success) response. */
|
||||
|
||||
return cursor + 1;
|
||||
}
|
||||
|
||||
/* Read and return the status from remote tape connection HANDLE. If
|
||||
an error occurred, return -1 and set errno. */
|
||||
static long int
|
||||
get_status (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
if (status)
|
||||
{
|
||||
long int result = atol (status);
|
||||
if (0 <= result)
|
||||
return result;
|
||||
errno = EIO;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static off_t
|
||||
get_status_off (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
|
||||
if (! status)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
/* Parse status, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
|
||||
for (; *status == ' ' || *status == '\t'; status++)
|
||||
continue;
|
||||
|
||||
negative = *status == '-';
|
||||
status += negative || *status == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *status++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
return -1;
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* Execute /etc/rmt as user USER on remote system HOST using rexec.
|
||||
Return a file descriptor of a bidirectional socket for stdin and
|
||||
stdout. If USER is zero, use the current username.
|
||||
|
||||
By default, this code is not used, since it requires that the user
|
||||
have a .netrc file in his/her home directory, or that the
|
||||
application designer be willing to have rexec prompt for login and
|
||||
password info. This may be unacceptable, and .rhosts files for use
|
||||
with rsh are much more common on BSD systems. */
|
||||
static int
|
||||
_rmt_rexec (char *host, char *user)
|
||||
{
|
||||
int saved_stdin = dup (STDIN_FILENO);
|
||||
int saved_stdout = dup (STDOUT_FILENO);
|
||||
struct servent *rexecserv;
|
||||
int result;
|
||||
|
||||
/* When using cpio -o < filename, stdin is no longer the tty. But the
|
||||
rexec subroutine reads the login and the passwd on stdin, to allow
|
||||
remote execution of the command. So, reopen stdin and stdout on
|
||||
/dev/tty before the rexec and give them back their original value
|
||||
after. */
|
||||
|
||||
if (! freopen ("/dev/tty", "r", stdin))
|
||||
freopen ("/dev/null", "r", stdin);
|
||||
if (! freopen ("/dev/tty", "w", stdout))
|
||||
freopen ("/dev/null", "w", stdout);
|
||||
|
||||
if (rexecserv = getservbyname ("exec", "tcp"), !rexecserv)
|
||||
error (EXIT_ON_EXEC_ERROR, 0, _("exec/tcp: Service not available"));
|
||||
|
||||
result = rexec (&host, rexecserv->s_port, user, 0, RMT_COMMAND, 0);
|
||||
if (fclose (stdin) == EOF)
|
||||
error (0, errno, _("stdin"));
|
||||
fdopen (saved_stdin, "r");
|
||||
if (fclose (stdout) == EOF)
|
||||
error (0, errno, _("stdout"));
|
||||
fdopen (saved_stdout, "w");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* WITH_REXEC */
|
||||
|
||||
/* Place into BUF a string representing OFLAG, which must be suitable
|
||||
as argument 2 of `open'. BUF must be large enough to hold the
|
||||
result. This function should generate a string that decode_oflag
|
||||
can parse. */
|
||||
static void
|
||||
encode_oflag (char *buf, int oflag)
|
||||
{
|
||||
sprintf (buf, "%d ", oflag);
|
||||
|
||||
switch (oflag & O_ACCMODE)
|
||||
{
|
||||
case O_RDONLY: strcat (buf, "O_RDONLY"); break;
|
||||
case O_RDWR: strcat (buf, "O_RDWR"); break;
|
||||
case O_WRONLY: strcat (buf, "O_WRONLY"); break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
#ifdef O_APPEND
|
||||
if (oflag & O_APPEND) strcat (buf, "|O_APPEND");
|
||||
#endif
|
||||
if (oflag & O_CREAT) strcat (buf, "|O_CREAT");
|
||||
#ifdef O_DSYNC
|
||||
if (oflag & O_DSYNC) strcat (buf, "|O_DSYNC");
|
||||
#endif
|
||||
if (oflag & O_EXCL) strcat (buf, "|O_EXCL");
|
||||
#ifdef O_LARGEFILE
|
||||
if (oflag & O_LARGEFILE) strcat (buf, "|O_LARGEFILE");
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
|
||||
#endif
|
||||
#ifdef O_NONBLOCK
|
||||
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
|
||||
#endif
|
||||
#ifdef O_RSYNC
|
||||
if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
if (oflag & O_SYNC) strcat (buf, "|O_SYNC");
|
||||
#endif
|
||||
if (oflag & O_TRUNC) strcat (buf, "|O_TRUNC");
|
||||
}
|
||||
|
||||
/* Open a file (a magnetic tape device?) on the system specified in
|
||||
PATH, as the given user. PATH has the form `[USER@]HOST:FILE'.
|
||||
OPEN_MODE is O_RDONLY, O_WRONLY, etc. If successful, return the
|
||||
remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On
|
||||
error, return -1. */
|
||||
int
|
||||
rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
|
||||
{
|
||||
int remote_pipe_number; /* pseudo, biased file descriptor */
|
||||
char *path_copy ; /* copy of path string */
|
||||
char *remote_host; /* remote host name */
|
||||
char *remote_file; /* remote file name (often a device) */
|
||||
char *remote_user; /* remote user name */
|
||||
|
||||
/* Find an unused pair of file descriptors. */
|
||||
|
||||
for (remote_pipe_number = 0;
|
||||
remote_pipe_number < MAXUNIT;
|
||||
remote_pipe_number++)
|
||||
if (READ_SIDE (remote_pipe_number) == -1
|
||||
&& WRITE_SIDE (remote_pipe_number) == -1)
|
||||
break;
|
||||
|
||||
if (remote_pipe_number == MAXUNIT)
|
||||
{
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pull apart the system and device, and optional user. */
|
||||
|
||||
{
|
||||
char *cursor;
|
||||
|
||||
path_copy = xstrdup (path);
|
||||
remote_host = path_copy;
|
||||
remote_user = 0;
|
||||
remote_file = 0;
|
||||
|
||||
for (cursor = path_copy; *cursor; cursor++)
|
||||
switch (*cursor)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
/* Do not allow newlines in the path, since the protocol
|
||||
uses newline delimiters. */
|
||||
free (path_copy);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
|
||||
case '@':
|
||||
if (!remote_user)
|
||||
{
|
||||
remote_user = remote_host;
|
||||
*cursor = '\0';
|
||||
remote_host = cursor + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (!remote_file)
|
||||
{
|
||||
*cursor = '\0';
|
||||
remote_file = cursor + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Should somewhat validate the decoding, here. */
|
||||
|
||||
if (remote_user && *remote_user == '\0')
|
||||
remote_user = 0;
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* Execute the remote command using rexec. */
|
||||
|
||||
READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
|
||||
if (READ_SIDE (remote_pipe_number) < 0)
|
||||
{
|
||||
int e = errno;
|
||||
free (path_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WRITE_SIDE (remote_pipe_number) = READ_SIDE (remote_pipe_number);
|
||||
|
||||
#else /* not WITH_REXEC */
|
||||
{
|
||||
const char *remote_shell_basename;
|
||||
pid_t status;
|
||||
|
||||
/* Identify the remote command to be executed. */
|
||||
|
||||
if (!remote_shell)
|
||||
{
|
||||
#ifdef REMOTE_SHELL
|
||||
remote_shell = REMOTE_SHELL;
|
||||
#else
|
||||
free (path_copy);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
remote_shell_basename = base_name (remote_shell);
|
||||
|
||||
/* Set up the pipes for the `rsh' command, and fork. */
|
||||
|
||||
if (pipe (to_remote[remote_pipe_number]) == -1
|
||||
|| pipe (from_remote[remote_pipe_number]) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (path_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = fork ();
|
||||
if (status == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (path_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
/* Child. */
|
||||
|
||||
close (STDIN_FILENO);
|
||||
dup (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
close (STDOUT_FILENO);
|
||||
dup (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (from_remote[remote_pipe_number][PREAD]);
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
sys_reset_uid_gid ();
|
||||
|
||||
if (remote_user)
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
"-l", remote_user, RMT_COMMAND, (char *) 0);
|
||||
else
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
RMT_COMMAND, (char *) 0);
|
||||
|
||||
/* Bad problems if we get here. */
|
||||
|
||||
/* In a previous version, _exit was used here instead of exit. */
|
||||
error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell"));
|
||||
}
|
||||
|
||||
/* Parent. */
|
||||
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
}
|
||||
#endif /* not WITH_REXEC */
|
||||
|
||||
/* Attempt to open the tape device. */
|
||||
|
||||
{
|
||||
size_t remote_file_len = strlen (remote_file);
|
||||
char *command_buffer = xmalloc (remote_file_len + 1000);
|
||||
sprintf (command_buffer, "O%s\n", remote_file);
|
||||
encode_oflag (command_buffer + remote_file_len + 2, open_mode);
|
||||
strcat (command_buffer, "\n");
|
||||
if (do_command (remote_pipe_number, command_buffer) == -1
|
||||
|| get_status (remote_pipe_number) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (command_buffer);
|
||||
free (path_copy);
|
||||
_rmt_shutdown (remote_pipe_number, e);
|
||||
return -1;
|
||||
}
|
||||
free (command_buffer);
|
||||
}
|
||||
|
||||
free (path_copy);
|
||||
return remote_pipe_number + bias;
|
||||
}
|
||||
|
||||
/* Close remote tape connection HANDLE and shut down. Return 0 if
|
||||
successful, -1 on error. */
|
||||
int
|
||||
rmt_close__ (int handle)
|
||||
{
|
||||
long int status;
|
||||
|
||||
if (do_command (handle, "C\n") == -1)
|
||||
return -1;
|
||||
|
||||
status = get_status (handle);
|
||||
_rmt_shutdown (handle, errno);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE.
|
||||
Return the number of bytes read on success, SAFE_READ_ERROR on error. */
|
||||
size_t
|
||||
rmt_read__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
size_t status;
|
||||
size_t rlen;
|
||||
size_t counter;
|
||||
|
||||
sprintf (command_buffer, "R%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1
|
||||
|| (status = get_status (handle)) == SAFE_READ_ERROR)
|
||||
return SAFE_READ_ERROR;
|
||||
|
||||
for (counter = 0; counter < status; counter += rlen, buffer += rlen)
|
||||
{
|
||||
rlen = safe_read (READ_SIDE (handle), buffer, status - counter);
|
||||
if (rlen == SAFE_READ_ERROR || rlen == 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return SAFE_READ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Write LENGTH bytes from BUFFER to remote tape connection HANDLE.
|
||||
Return the number of bytes written. */
|
||||
size_t
|
||||
rmt_write__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
RETSIGTYPE (*pipe_handler) ();
|
||||
size_t written;
|
||||
|
||||
sprintf (command_buffer, "W%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return 0;
|
||||
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
if (written == length)
|
||||
{
|
||||
long int r = get_status (handle);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
if (r == length)
|
||||
return length;
|
||||
written = r;
|
||||
}
|
||||
|
||||
/* Write error. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Perform an imitation lseek operation on remote tape connection
|
||||
HANDLE. Return the new file offset if successful, -1 if on error. */
|
||||
off_t
|
||||
rmt_lseek__ (int handle, off_t offset, int whence)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = offset < 0 ? - (uintmax_t) offset : (uintmax_t) offset;
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
*--p = 0;
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (offset < 0)
|
||||
*--p = '-';
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET: whence = 0; break;
|
||||
case SEEK_CUR: whence = 1; break;
|
||||
case SEEK_END: whence = 2; break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
sprintf (command_buffer, "L%s\n%d\n", p, whence);
|
||||
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status_off (handle);
|
||||
}
|
||||
|
||||
/* Perform a raw tape operation on remote tape connection HANDLE.
|
||||
Return the results of the ioctl, or -1 on error. */
|
||||
int
|
||||
rmt_ioctl__ (int handle, int operation, char *argument)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
default:
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
case MTIOCTOP:
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = (((struct mtop *) argument)->mt_count < 0
|
||||
? - (uintmax_t) ((struct mtop *) argument)->mt_count
|
||||
: (uintmax_t) ((struct mtop *) argument)->mt_count);
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
*--p = 0;
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (((struct mtop *) argument)->mt_count < 0)
|
||||
*--p = '-';
|
||||
|
||||
/* MTIOCTOP is the easy one. Nothing is transferred in binary. */
|
||||
|
||||
sprintf (command_buffer, "I%d\n%s\n",
|
||||
((struct mtop *) argument)->mt_op, p);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status (handle);
|
||||
}
|
||||
#endif /* MTIOCTOP */
|
||||
|
||||
#ifdef MTIOCGET
|
||||
case MTIOCGET:
|
||||
{
|
||||
ssize_t status;
|
||||
size_t counter;
|
||||
|
||||
/* Grab the status and read it directly into the structure. This
|
||||
assumes that the status buffer is not padded and that 2 shorts
|
||||
fit in a long without any word alignment problems; i.e., the
|
||||
whole struct is contiguous. NOTE - this is probably NOT a good
|
||||
assumption. */
|
||||
|
||||
if (do_command (handle, "S") == -1
|
||||
|| (status = get_status (handle), status == -1))
|
||||
return -1;
|
||||
|
||||
for (; status > 0; status -= counter, argument += counter)
|
||||
{
|
||||
counter = safe_read (READ_SIDE (handle), argument, status);
|
||||
if (counter == SAFE_READ_ERROR || counter == 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for byte position. mt_type (or mt_model) is a small integer
|
||||
field (normally) so we will check its magnitude. If it is larger
|
||||
than 256, we will assume that the bytes are swapped and go through
|
||||
and reverse all the bytes. */
|
||||
|
||||
if (((struct mtget *) argument)->MTIO_CHECK_FIELD < 256)
|
||||
return 0;
|
||||
|
||||
for (counter = 0; counter < status; counter += 2)
|
||||
{
|
||||
char copy = argument[counter];
|
||||
|
||||
argument[counter] = argument[counter + 1];
|
||||
argument[counter + 1] = copy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MTIOCGET */
|
||||
|
||||
}
|
||||
}
|
||||
566
src/sparse.c
566
src/sparse.c
@@ -1,10 +1,10 @@
|
||||
/* Functions for dealing with sparse files
|
||||
|
||||
Copyright (C) 2003, 2004 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
|
||||
@@ -14,13 +14,15 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "system.h"
|
||||
#include <system.h>
|
||||
#include <inttostr.h>
|
||||
#include <quotearg.h>
|
||||
#include "common.h"
|
||||
|
||||
struct tar_sparse_file;
|
||||
static bool sparse_select_optab (struct tar_sparse_file *file);
|
||||
|
||||
enum sparse_scan_state
|
||||
{
|
||||
@@ -46,14 +48,50 @@ struct tar_sparse_optab
|
||||
struct tar_sparse_file
|
||||
{
|
||||
int fd; /* File descriptor */
|
||||
size_t dumped_size; /* Number of bytes actually written
|
||||
bool seekable; /* Is fd seekable? */
|
||||
off_t offset; /* Current offset in fd if seekable==false.
|
||||
Otherwise unused */
|
||||
off_t dumped_size; /* Number of bytes actually written
|
||||
to the archive */
|
||||
struct tar_stat_info *stat_info; /* Information about the file */
|
||||
struct tar_sparse_optab *optab;
|
||||
struct tar_sparse_optab const *optab; /* Operation table */
|
||||
void *closure; /* Any additional data optab calls might
|
||||
reqiure */
|
||||
require */
|
||||
};
|
||||
|
||||
/* Dump zeros to file->fd until offset is reached. It is used instead of
|
||||
lseek if the output file is not seekable */
|
||||
static bool
|
||||
dump_zeros (struct tar_sparse_file *file, off_t offset)
|
||||
{
|
||||
static char const zero_buf[BLOCKSIZE];
|
||||
|
||||
if (offset < file->offset)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
while (file->offset < offset)
|
||||
{
|
||||
size_t size = (BLOCKSIZE < offset - file->offset
|
||||
? BLOCKSIZE
|
||||
: offset - file->offset);
|
||||
ssize_t wrbytes;
|
||||
|
||||
wrbytes = write (file->fd, zero_buf, size);
|
||||
if (wrbytes <= 0)
|
||||
{
|
||||
if (wrbytes == 0)
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
file->offset += wrbytes;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
tar_sparse_member_p (struct tar_sparse_file *file)
|
||||
{
|
||||
@@ -65,9 +103,14 @@ tar_sparse_member_p (struct tar_sparse_file *file)
|
||||
static bool
|
||||
tar_sparse_init (struct tar_sparse_file *file)
|
||||
{
|
||||
file->dumped_size = 0;
|
||||
memset (file, 0, sizeof *file);
|
||||
|
||||
if (!sparse_select_optab (file))
|
||||
return false;
|
||||
|
||||
if (file->optab->init)
|
||||
return file->optab->init (file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -130,9 +173,11 @@ tar_sparse_fixup_header (struct tar_sparse_file *file)
|
||||
|
||||
|
||||
static bool
|
||||
lseek_or_error (struct tar_sparse_file *file, off_t offset, int whence)
|
||||
lseek_or_error (struct tar_sparse_file *file, off_t offset)
|
||||
{
|
||||
if (lseek (file->fd, offset, whence) < 0)
|
||||
if (file->seekable
|
||||
? lseek (file->fd, offset, SEEK_SET) < 0
|
||||
: ! dump_zeros (file, offset))
|
||||
{
|
||||
seek_diag_details (file->stat_info->orig_file_name, offset);
|
||||
return false;
|
||||
@@ -144,7 +189,7 @@ lseek_or_error (struct tar_sparse_file *file, off_t offset, int whence)
|
||||
it's made *entirely* of zeros, returning a 0 the instant it finds
|
||||
something that is a nonzero, i.e., useful data. */
|
||||
static bool
|
||||
zero_block_p (char *buffer, size_t size)
|
||||
zero_block_p (char const *buffer, size_t size)
|
||||
{
|
||||
while (size--)
|
||||
if (*buffer++)
|
||||
@@ -152,58 +197,46 @@ zero_block_p (char *buffer, size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define clear_block(p) memset (p, 0, BLOCKSIZE);
|
||||
|
||||
#define SPARSES_INIT_COUNT SPARSES_IN_SPARSE_HEADER
|
||||
|
||||
static void
|
||||
sparse_add_map (struct tar_sparse_file *file, struct sp_array *sp)
|
||||
sparse_add_map (struct tar_stat_info *st, struct sp_array const *sp)
|
||||
{
|
||||
if (file->stat_info->sparse_map == NULL)
|
||||
{
|
||||
file->stat_info->sparse_map =
|
||||
xmalloc (SPARSES_INIT_COUNT * sizeof file->stat_info->sparse_map[0]);
|
||||
file->stat_info->sparse_map_size = SPARSES_INIT_COUNT;
|
||||
}
|
||||
else if (file->stat_info->sparse_map_avail == file->stat_info->sparse_map_size)
|
||||
{
|
||||
file->stat_info->sparse_map_size *= 2;
|
||||
file->stat_info->sparse_map =
|
||||
xrealloc (file->stat_info->sparse_map,
|
||||
file->stat_info->sparse_map_size
|
||||
* sizeof file->stat_info->sparse_map[0]);
|
||||
}
|
||||
file->stat_info->sparse_map[file->stat_info->sparse_map_avail++] = *sp;
|
||||
struct sp_array *sparse_map = st->sparse_map;
|
||||
size_t avail = st->sparse_map_avail;
|
||||
if (avail == st->sparse_map_size)
|
||||
st->sparse_map = sparse_map =
|
||||
x2nrealloc (sparse_map, &st->sparse_map_size, sizeof *sparse_map);
|
||||
sparse_map[avail] = *sp;
|
||||
st->sparse_map_avail = avail + 1;
|
||||
}
|
||||
|
||||
/* Scan the sparse file and create its map */
|
||||
static bool
|
||||
sparse_scan_file (struct tar_sparse_file *file)
|
||||
{
|
||||
static char buffer[BLOCKSIZE];
|
||||
struct tar_stat_info *st = file->stat_info;
|
||||
int fd = file->fd;
|
||||
char buffer[BLOCKSIZE];
|
||||
size_t count;
|
||||
size_t offset = 0;
|
||||
off_t offset = 0;
|
||||
struct sp_array sp = {0, 0};
|
||||
|
||||
if (!lseek_or_error (file, 0, SEEK_SET))
|
||||
if (!lseek_or_error (file, 0))
|
||||
return false;
|
||||
clear_block (buffer);
|
||||
|
||||
file->stat_info->sparse_map_size = 0;
|
||||
file->stat_info->archive_file_size = 0;
|
||||
|
||||
st->archive_file_size = 0;
|
||||
|
||||
if (!tar_sparse_scan (file, scan_begin, NULL))
|
||||
return false;
|
||||
|
||||
while ((count = safe_read (file->fd, buffer, sizeof buffer)) != 0
|
||||
while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
|
||||
&& count != SAFE_READ_ERROR)
|
||||
{
|
||||
/* Analize the block */
|
||||
/* Analyze the block. */
|
||||
if (zero_block_p (buffer, count))
|
||||
{
|
||||
if (sp.numbytes)
|
||||
{
|
||||
sparse_add_map (file, &sp);
|
||||
sparse_add_map (st, &sp);
|
||||
sp.numbytes = 0;
|
||||
if (!tar_sparse_scan (file, scan_block, NULL))
|
||||
return false;
|
||||
@@ -214,26 +247,25 @@ sparse_scan_file (struct tar_sparse_file *file)
|
||||
if (sp.numbytes == 0)
|
||||
sp.offset = offset;
|
||||
sp.numbytes += count;
|
||||
file->stat_info->archive_file_size += count;
|
||||
st->archive_file_size += count;
|
||||
if (!tar_sparse_scan (file, scan_block, buffer))
|
||||
return false;
|
||||
}
|
||||
|
||||
offset += count;
|
||||
clear_block (buffer);
|
||||
}
|
||||
|
||||
if (sp.numbytes == 0)
|
||||
sp.offset = offset;
|
||||
|
||||
sparse_add_map (file, &sp);
|
||||
file->stat_info->archive_file_size += count;
|
||||
sparse_add_map (st, &sp);
|
||||
st->archive_file_size += count;
|
||||
return tar_sparse_scan (file, scan_end, NULL);
|
||||
}
|
||||
|
||||
static struct tar_sparse_optab oldgnu_optab;
|
||||
static struct tar_sparse_optab star_optab;
|
||||
static struct tar_sparse_optab pax_optab;
|
||||
static struct tar_sparse_optab const oldgnu_optab;
|
||||
static struct tar_sparse_optab const star_optab;
|
||||
static struct tar_sparse_optab const pax_optab;
|
||||
|
||||
static bool
|
||||
sparse_select_optab (struct tar_sparse_file *file)
|
||||
@@ -269,8 +301,7 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
|
||||
union block *blk;
|
||||
off_t bytes_left = file->stat_info->sparse_map[i].numbytes;
|
||||
|
||||
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
|
||||
SEEK_SET))
|
||||
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
|
||||
return false;
|
||||
|
||||
while (bytes_left > 0)
|
||||
@@ -279,20 +310,21 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
|
||||
size_t bytes_read;
|
||||
|
||||
blk = find_next_block ();
|
||||
memset (blk->buffer, 0, BLOCKSIZE);
|
||||
bytes_read = safe_read (file->fd, blk->buffer, bufsize);
|
||||
if (bytes_read == SAFE_READ_ERROR)
|
||||
{
|
||||
read_diag_details (file->stat_info->orig_file_name,
|
||||
file->stat_info->sparse_map[i].offset
|
||||
+ file->stat_info->sparse_map[i].numbytes
|
||||
- bytes_left,
|
||||
bufsize);
|
||||
(file->stat_info->sparse_map[i].offset
|
||||
+ file->stat_info->sparse_map[i].numbytes
|
||||
- bytes_left),
|
||||
bufsize);
|
||||
return false;
|
||||
}
|
||||
|
||||
memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
|
||||
bytes_left -= bytes_read;
|
||||
file->dumped_size += bytes_read;
|
||||
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
|
||||
set_next_block_after (blk);
|
||||
}
|
||||
|
||||
@@ -304,8 +336,7 @@ sparse_extract_region (struct tar_sparse_file *file, size_t i)
|
||||
{
|
||||
size_t write_size;
|
||||
|
||||
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
|
||||
SEEK_SET))
|
||||
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
|
||||
return false;
|
||||
|
||||
write_size = file->stat_info->sparse_map[i].numbytes;
|
||||
@@ -313,7 +344,7 @@ sparse_extract_region (struct tar_sparse_file *file, size_t i)
|
||||
if (write_size == 0)
|
||||
{
|
||||
/* Last block of the file is a hole */
|
||||
if (sys_truncate (file->fd))
|
||||
if (file->seekable && sys_truncate (file->fd))
|
||||
truncate_warn (file->stat_info->orig_file_name);
|
||||
}
|
||||
else while (write_size > 0)
|
||||
@@ -330,6 +361,8 @@ sparse_extract_region (struct tar_sparse_file *file, size_t i)
|
||||
count = full_write (file->fd, blk->buffer, wrbytes);
|
||||
write_size -= count;
|
||||
file->dumped_size += count;
|
||||
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
|
||||
file->offset += count;
|
||||
if (count != wrbytes)
|
||||
{
|
||||
write_error_details (file->stat_info->orig_file_name,
|
||||
@@ -349,12 +382,12 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
|
||||
bool rc;
|
||||
struct tar_sparse_file file;
|
||||
|
||||
if (!tar_sparse_init (&file))
|
||||
return dump_status_not_implemented;
|
||||
|
||||
file.stat_info = st;
|
||||
file.fd = fd;
|
||||
|
||||
if (!sparse_select_optab (&file)
|
||||
|| !tar_sparse_init (&file))
|
||||
return dump_status_not_implemented;
|
||||
file.seekable = true; /* File *must* be seekable for dump to work */
|
||||
|
||||
rc = sparse_scan_file (&file);
|
||||
if (rc && file.optab->dump_region)
|
||||
@@ -365,30 +398,23 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
mv_begin (file.stat_info);
|
||||
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
|
||||
rc = tar_sparse_dump_region (&file, i);
|
||||
mv_end ();
|
||||
}
|
||||
}
|
||||
|
||||
pad_archive(file.stat_info->archive_file_size - file.dumped_size);
|
||||
pad_archive (file.stat_info->archive_file_size - file.dumped_size);
|
||||
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)
|
||||
{
|
||||
struct tar_sparse_file file;
|
||||
|
||||
if (!sparse_select_optab (&file))
|
||||
if (!tar_sparse_init (&file))
|
||||
return false;
|
||||
file.stat_info = st;
|
||||
return tar_sparse_member_p (&file);
|
||||
@@ -399,7 +425,7 @@ sparse_fixup_header (struct tar_stat_info *st)
|
||||
{
|
||||
struct tar_sparse_file file;
|
||||
|
||||
if (!sparse_select_optab (&file))
|
||||
if (!tar_sparse_init (&file))
|
||||
return false;
|
||||
file.stat_info = st;
|
||||
return tar_sparse_fixup_header (&file);
|
||||
@@ -412,12 +438,13 @@ sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
|
||||
struct tar_sparse_file file;
|
||||
size_t i;
|
||||
|
||||
if (!tar_sparse_init (&file))
|
||||
return dump_status_not_implemented;
|
||||
|
||||
file.stat_info = st;
|
||||
file.fd = fd;
|
||||
|
||||
if (!sparse_select_optab (&file)
|
||||
|| !tar_sparse_init (&file))
|
||||
return dump_status_not_implemented;
|
||||
file.seekable = lseek (fd, 0, SEEK_SET) == 0;
|
||||
file.offset = 0;
|
||||
|
||||
rc = tar_sparse_decode_header (&file);
|
||||
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
|
||||
@@ -432,35 +459,30 @@ sparse_skip_file (struct tar_stat_info *st)
|
||||
bool rc = true;
|
||||
struct tar_sparse_file file;
|
||||
|
||||
if (!tar_sparse_init (&file))
|
||||
return dump_status_not_implemented;
|
||||
|
||||
file.stat_info = st;
|
||||
file.fd = -1;
|
||||
|
||||
if (!sparse_select_optab (&file)
|
||||
|| !tar_sparse_init (&file))
|
||||
return dump_status_not_implemented;
|
||||
|
||||
rc = tar_sparse_decode_header (&file);
|
||||
skip_file (file.stat_info->archive_file_size);
|
||||
skip_file (file.stat_info->archive_file_size - file.dumped_size);
|
||||
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
|
||||
}
|
||||
|
||||
|
||||
static char diff_buffer[BLOCKSIZE];
|
||||
|
||||
static bool
|
||||
check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
|
||||
{
|
||||
if (!lseek_or_error (file, beg, SEEK_SET))
|
||||
if (!lseek_or_error (file, beg))
|
||||
return false;
|
||||
|
||||
while (beg < end)
|
||||
{
|
||||
size_t bytes_read;
|
||||
size_t rdsize = end - beg;
|
||||
size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;
|
||||
char diff_buffer[BLOCKSIZE];
|
||||
|
||||
if (rdsize > BLOCKSIZE)
|
||||
rdsize = BLOCKSIZE;
|
||||
clear_block (diff_buffer);
|
||||
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
|
||||
if (bytes_read == SAFE_READ_ERROR)
|
||||
{
|
||||
@@ -471,8 +493,10 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
|
||||
}
|
||||
if (!zero_block_p (diff_buffer, bytes_read))
|
||||
{
|
||||
char begbuf[INT_BUFSIZE_BOUND (off_t)];
|
||||
report_difference (file->stat_info,
|
||||
_("File fragment at %lu is not a hole"), beg);
|
||||
_("File fragment at %s is not a hole"),
|
||||
offtostr (beg, begbuf));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -486,14 +510,16 @@ check_data_region (struct tar_sparse_file *file, size_t i)
|
||||
{
|
||||
size_t size_left;
|
||||
|
||||
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
|
||||
SEEK_SET))
|
||||
if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
|
||||
return false;
|
||||
size_left = file->stat_info->sparse_map[i].numbytes;
|
||||
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
|
||||
|
||||
while (size_left > 0)
|
||||
{
|
||||
size_t bytes_read;
|
||||
size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
|
||||
char diff_buffer[BLOCKSIZE];
|
||||
|
||||
union block *blk = find_next_block ();
|
||||
if (!blk)
|
||||
@@ -506,14 +532,15 @@ check_data_region (struct tar_sparse_file *file, size_t i)
|
||||
if (bytes_read == SAFE_READ_ERROR)
|
||||
{
|
||||
read_diag_details (file->stat_info->orig_file_name,
|
||||
file->stat_info->sparse_map[i].offset
|
||||
+ file->stat_info->sparse_map[i].numbytes
|
||||
- size_left,
|
||||
(file->stat_info->sparse_map[i].offset
|
||||
+ file->stat_info->sparse_map[i].numbytes
|
||||
- size_left),
|
||||
rdsize);
|
||||
return false;
|
||||
}
|
||||
file->dumped_size += bytes_read;
|
||||
size_left -= bytes_read;
|
||||
mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
|
||||
if (memcmp (blk->buffer, diff_buffer, rdsize))
|
||||
{
|
||||
report_difference (file->stat_info, _("Contents differ"));
|
||||
@@ -531,26 +558,28 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
|
||||
size_t i;
|
||||
off_t offset = 0;
|
||||
|
||||
file.stat_info = st;
|
||||
file.fd = fd;
|
||||
|
||||
if (!sparse_select_optab (&file)
|
||||
|| !tar_sparse_init (&file))
|
||||
if (!tar_sparse_init (&file))
|
||||
return dump_status_not_implemented;
|
||||
|
||||
file.stat_info = st;
|
||||
file.fd = fd;
|
||||
file.seekable = true; /* File *must* be seekable for compare to work */
|
||||
|
||||
rc = tar_sparse_decode_header (&file);
|
||||
mv_begin (st);
|
||||
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
|
||||
{
|
||||
rc = check_sparse_region (&file,
|
||||
offset, file.stat_info->sparse_map[i].offset)
|
||||
&& check_data_region (&file, i);
|
||||
&& check_data_region (&file, i);
|
||||
offset = file.stat_info->sparse_map[i].offset
|
||||
+ file.stat_info->sparse_map[i].numbytes;
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
skip_file (file.stat_info->archive_file_size - file.dumped_size);
|
||||
|
||||
mv_end ();
|
||||
|
||||
tar_sparse_done (&file);
|
||||
return rc;
|
||||
}
|
||||
@@ -602,7 +631,7 @@ oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
|
||||
|| file->stat_info->archive_file_size < 0)
|
||||
return add_fail;
|
||||
|
||||
sparse_add_map (file, &sp);
|
||||
sparse_add_map (file->stat_info, &sp);
|
||||
return add_ok;
|
||||
}
|
||||
|
||||
@@ -613,7 +642,7 @@ oldgnu_fixup_header (struct tar_sparse_file *file)
|
||||
which actually contains archived size. The following fixes it */
|
||||
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
|
||||
file->stat_info->stat.st_size =
|
||||
OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
|
||||
OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -624,9 +653,9 @@ oldgnu_get_sparse_info (struct tar_sparse_file *file)
|
||||
size_t i;
|
||||
union block *h = current_header;
|
||||
int ext_p;
|
||||
static enum oldgnu_add_status rc;
|
||||
enum oldgnu_add_status rc;
|
||||
|
||||
file->stat_info->sparse_map_size = 0;
|
||||
file->stat_info->sparse_map_avail = 0;
|
||||
for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
|
||||
{
|
||||
rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
|
||||
@@ -702,16 +731,14 @@ 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;
|
||||
}
|
||||
|
||||
static struct tar_sparse_optab oldgnu_optab = {
|
||||
static struct tar_sparse_optab const oldgnu_optab = {
|
||||
NULL, /* No init function */
|
||||
NULL, /* No done function */
|
||||
oldgnu_sparse_member_p,
|
||||
@@ -750,9 +777,9 @@ star_get_sparse_info (struct tar_sparse_file *file)
|
||||
size_t i;
|
||||
union block *h = current_header;
|
||||
int ext_p;
|
||||
static enum oldgnu_add_status rc;
|
||||
enum oldgnu_add_status rc = add_ok;
|
||||
|
||||
file->stat_info->sparse_map_size = 0;
|
||||
file->stat_info->sparse_map_avail = 0;
|
||||
|
||||
if (h->star_in_header.prefix[0] == '\0'
|
||||
&& h->star_in_header.sp[0].offset[10] != '\0')
|
||||
@@ -792,7 +819,7 @@ star_get_sparse_info (struct tar_sparse_file *file)
|
||||
}
|
||||
|
||||
|
||||
static struct tar_sparse_optab star_optab = {
|
||||
static struct tar_sparse_optab const star_optab = {
|
||||
NULL, /* No init function */
|
||||
NULL, /* No done function */
|
||||
star_sparse_member_p,
|
||||
@@ -805,8 +832,12 @@ static struct tar_sparse_optab 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
|
||||
@@ -814,46 +845,331 @@ static struct tar_sparse_optab star_optab = {
|
||||
GNU.sparse.offset Offset of the next data block
|
||||
GNU.sparse.numbytes Size of the next data block
|
||||
end repeat
|
||||
|
||||
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, whereas
|
||||
POSIX requires the latest occurrence of the variable to override all
|
||||
previous occurrences.
|
||||
|
||||
To avoid this incompatibility two following versions were introduced.
|
||||
|
||||
* 0.1
|
||||
|
||||
Used by tar 1.15.2 -- 1.15.91 (alpha releases).
|
||||
|
||||
The sparse file map is stored in
|
||||
x header:
|
||||
|
||||
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->archive_file_size != file->stat_info->stat.st_size;
|
||||
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);
|
||||
|
||||
if (xheader_keyword_deleted_p ("GNU.sparse.map")
|
||||
|| tar_sparse_minor == 0)
|
||||
{
|
||||
for (i = 0; i < file->stat_info->sparse_map_avail; i++)
|
||||
{
|
||||
xheader_store ("GNU.sparse.offset", file->stat_info, &i);
|
||||
xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 (&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;
|
||||
}
|
||||
}
|
||||
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++)
|
||||
{
|
||||
xheader_store ("GNU.sparse.offset", file->stat_info, &i);
|
||||
xheader_store ("GNU.sparse.numbytes", file->stat_info, &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 struct tar_sparse_optab pax_optab = {
|
||||
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;
|
||||
}
|
||||
|
||||
static struct tar_sparse_optab const pax_optab = {
|
||||
NULL, /* No init function */
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
319
src/system.c
319
src/system.c
@@ -1,10 +1,10 @@
|
||||
/* System-dependent calls for tar.
|
||||
|
||||
Copyright (C) 2003, 2004 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
|
||||
@@ -14,38 +14,16 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "system.h"
|
||||
#include <system.h>
|
||||
#include <getline.h>
|
||||
#include <setenv.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "rmt.h"
|
||||
#include <rmt.h>
|
||||
#include <signal.h>
|
||||
|
||||
void
|
||||
sys_stat_nanoseconds (struct tar_stat_info *st)
|
||||
{
|
||||
#if defined(HAVE_STRUCT_STAT_ST_SPARE1)
|
||||
st->atime_nsec = st->stat.st_spare1 * 1000;
|
||||
st->mtime_nsec = st->stat.st_spare2 * 1000;
|
||||
st->ctime_nsec = st->stat.st_spare3 * 1000;
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
|
||||
st->atime_nsec = st->stat.st_atim.tv_nsec;
|
||||
st->mtime_nsec = st->stat.st_mtim.tv_nsec;
|
||||
st->ctime_nsec = st->stat.st_ctim.tv_nsec;
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
|
||||
st->atime_nsec = st->stat.st_atimespec.tv_nsec;
|
||||
st->mtime_nsec = st->stat.st_mtimespec.tv_nsec;
|
||||
st->ctime_nsec = st->stat.st_ctimespec.tv_nsec;
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
|
||||
st->atime_nsec = st->stat.st_atimensec;
|
||||
st->mtime_nsec = st->stat.st_mtimensec;
|
||||
st->ctime_nsec = st->stat.st_ctimensec;
|
||||
#else
|
||||
st->atime_nsec = st->mtime_nsec = st->ctime_nsec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MSDOS
|
||||
|
||||
bool
|
||||
@@ -118,11 +96,6 @@ sys_truncate (int fd)
|
||||
return write (fd, "", 0);
|
||||
}
|
||||
|
||||
void
|
||||
sys_reset_uid_gid (void)
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
sys_write_archive_buffer (void)
|
||||
{
|
||||
@@ -281,13 +254,6 @@ sys_truncate (int fd)
|
||||
return pos < 0 ? -1 : ftruncate (fd, pos);
|
||||
}
|
||||
|
||||
void
|
||||
sys_reset_uid_gid (void)
|
||||
{
|
||||
setuid (getuid ());
|
||||
setgid (getgid ());
|
||||
}
|
||||
|
||||
/* Return nonzero if NAME is the name of a regular file, or if the file
|
||||
does not exist (so it would be created as a regular file). */
|
||||
static int
|
||||
@@ -368,12 +334,10 @@ sys_child_open_for_compress (void)
|
||||
xclose (parent_pipe[PWRITE]);
|
||||
|
||||
/* Check if we need a grandchild tar. This happens only if either:
|
||||
a) we are writing stdout: to force reblocking;
|
||||
b) the file is to be accessed by rmt: compressor doesn't know how;
|
||||
c) the file is not a plain file. */
|
||||
a) the file is to be accessed by rmt: compressor doesn't know how;
|
||||
b) the file is not a plain file. */
|
||||
|
||||
if (strcmp (archive_name_array[0], "-") != 0
|
||||
&& !_remdev (archive_name_array[0])
|
||||
if (!_remdev (archive_name_array[0])
|
||||
&& is_regular_file (archive_name_array[0]))
|
||||
{
|
||||
if (backup_option)
|
||||
@@ -381,20 +345,21 @@ sys_child_open_for_compress (void)
|
||||
|
||||
/* We don't need a grandchild tar. Open the archive and launch the
|
||||
compressor. */
|
||||
|
||||
archive = creat (archive_name_array[0], MODE_RW);
|
||||
if (archive < 0)
|
||||
if (strcmp (archive_name_array[0], "-"))
|
||||
{
|
||||
int saved_errno = errno;
|
||||
archive = creat (archive_name_array[0], MODE_RW);
|
||||
if (archive < 0)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
|
||||
if (backup_option)
|
||||
undo_last_backup ();
|
||||
errno = saved_errno;
|
||||
open_fatal (archive_name_array[0]);
|
||||
if (backup_option)
|
||||
undo_last_backup ();
|
||||
errno = saved_errno;
|
||||
open_fatal (archive_name_array[0]);
|
||||
}
|
||||
xdup2 (archive, STDOUT_FILENO);
|
||||
}
|
||||
xdup2 (archive, STDOUT_FILENO);
|
||||
execlp (use_compress_program_option, use_compress_program_option,
|
||||
(char *) 0);
|
||||
execlp (use_compress_program_option, use_compress_program_option, NULL);
|
||||
exec_fatal (use_compress_program_option);
|
||||
}
|
||||
|
||||
@@ -517,7 +482,6 @@ sys_child_open_for_uncompress (void)
|
||||
{
|
||||
/* The parent tar is still here! Just clean up. */
|
||||
|
||||
read_full_records_option = true;
|
||||
archive = parent_pipe[PREAD];
|
||||
xclose (parent_pipe[PWRITE]);
|
||||
return child_pid;
|
||||
@@ -639,5 +603,242 @@ sys_child_open_for_uncompress (void)
|
||||
exit (exit_status);
|
||||
}
|
||||
|
||||
#endif /* not MSDOS */
|
||||
|
||||
|
||||
static void
|
||||
dec_to_env (char *envar, uintmax_t num)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
char *numstr;
|
||||
|
||||
numstr = STRINGIFY_BIGINT (num, buf);
|
||||
if (setenv (envar, numstr, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
time_to_env (char *envar, struct timespec t)
|
||||
{
|
||||
char buf[TIMESPEC_STRSIZE_BOUND];
|
||||
if (setenv (envar, code_timespec (t, buf), 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
oct_to_env (char *envar, unsigned long num)
|
||||
{
|
||||
char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
|
||||
|
||||
snprintf (buf, sizeof buf, "0%lo", num);
|
||||
if (setenv (envar, buf, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
str_to_env (char *envar, char const *str)
|
||||
{
|
||||
if (str)
|
||||
{
|
||||
if (setenv (envar, str, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
else
|
||||
unsetenv (envar);
|
||||
}
|
||||
|
||||
static void
|
||||
chr_to_env (char *envar, char c)
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
if (setenv (envar, buf, 1) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
static void
|
||||
stat_to_env (char *name, char type, struct tar_stat_info *st)
|
||||
{
|
||||
str_to_env ("TAR_VERSION", PACKAGE_VERSION);
|
||||
chr_to_env ("TAR_FILETYPE", type);
|
||||
oct_to_env ("TAR_MODE", st->stat.st_mode);
|
||||
str_to_env ("TAR_FILENAME", name);
|
||||
str_to_env ("TAR_REALNAME", st->file_name);
|
||||
str_to_env ("TAR_UNAME", st->uname);
|
||||
str_to_env ("TAR_GNAME", st->gname);
|
||||
time_to_env ("TAR_ATIME", st->atime);
|
||||
time_to_env ("TAR_MTIME", st->mtime);
|
||||
time_to_env ("TAR_CTIME", st->ctime);
|
||||
dec_to_env ("TAR_SIZE", st->stat.st_size);
|
||||
dec_to_env ("TAR_UID", st->stat.st_uid);
|
||||
dec_to_env ("TAR_GID", st->stat.st_gid);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 'b':
|
||||
case 'c':
|
||||
dec_to_env ("TAR_MINOR", minor (st->stat.st_rdev));
|
||||
dec_to_env ("TAR_MAJOR", major (st->stat.st_rdev));
|
||||
unsetenv ("TAR_LINKNAME");
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case 'h':
|
||||
unsetenv ("TAR_MINOR");
|
||||
unsetenv ("TAR_MAJOR");
|
||||
str_to_env ("TAR_LINKNAME", st->link_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
unsetenv ("TAR_MINOR");
|
||||
unsetenv ("TAR_MAJOR");
|
||||
unsetenv ("TAR_LINKNAME");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static pid_t pid;
|
||||
static RETSIGTYPE (*pipe_handler) (int sig);
|
||||
|
||||
int
|
||||
sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
|
||||
{
|
||||
int p[2];
|
||||
char *argv[4];
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
pid = xfork ();
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
xclose (p[PREAD]);
|
||||
return p[PWRITE];
|
||||
}
|
||||
|
||||
/* Child */
|
||||
xdup2 (p[PREAD], STDIN_FILENO);
|
||||
xclose (p[PWRITE]);
|
||||
|
||||
stat_to_env (file_name, typechar, st);
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = to_command_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv ("/bin/sh", argv);
|
||||
|
||||
exec_fatal (file_name);
|
||||
}
|
||||
|
||||
void
|
||||
sys_wait_command (void)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (pid < 0)
|
||||
return;
|
||||
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
pid = -1;
|
||||
waitpid_error (to_command_option);
|
||||
return;
|
||||
}
|
||||
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
if (!ignore_command_error_option && WEXITSTATUS (status))
|
||||
ERROR ((0, 0, _("%lu: Child returned status %d"),
|
||||
(unsigned long) pid, WEXITSTATUS (status)));
|
||||
}
|
||||
else if (WIFSIGNALED (status))
|
||||
{
|
||||
WARN ((0, 0, _("%lu: Child terminated on signal %d"),
|
||||
(unsigned long) pid, WTERMSIG (status)));
|
||||
}
|
||||
else
|
||||
ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
|
||||
(unsigned long) pid));
|
||||
|
||||
pid = -1;
|
||||
}
|
||||
|
||||
int
|
||||
sys_exec_info_script (const char **archive_name, int volume_number)
|
||||
{
|
||||
pid_t pid;
|
||||
char *argv[4];
|
||||
char uintbuf[UINTMAX_STRSIZE_BOUND];
|
||||
int p[2];
|
||||
|
||||
xpipe (p);
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
pid = xfork ();
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
/* Master */
|
||||
|
||||
int rc;
|
||||
int status;
|
||||
char *buf;
|
||||
size_t size = 0;
|
||||
FILE *fp;
|
||||
|
||||
xclose (p[PWRITE]);
|
||||
fp = fdopen (p[PREAD], "r");
|
||||
rc = getline (&buf, &size, fp);
|
||||
fclose (fp);
|
||||
|
||||
if (rc > 0 && buf[rc-1] == '\n')
|
||||
buf[--rc] = 0;
|
||||
|
||||
while (waitpid (pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
{
|
||||
waitpid_error (info_script_option);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
if (WEXITSTATUS (status) == 0 && rc > 0)
|
||||
*archive_name = buf;
|
||||
else
|
||||
free (buf);
|
||||
return WEXITSTATUS (status);
|
||||
}
|
||||
|
||||
free (buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Child */
|
||||
setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
|
||||
setenv ("TAR_ARCHIVE", *archive_name, 1);
|
||||
setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, 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]);
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*) info_script_option;
|
||||
argv[3] = NULL;
|
||||
|
||||
execv (argv[0], argv);
|
||||
|
||||
exec_fatal (info_script_option);
|
||||
}
|
||||
|
||||
|
||||
#endif /* not MSDOS */
|
||||
|
||||
523
src/system.h
523
src/system.h
@@ -1,523 +0,0 @@
|
||||
/* System dependent definitions for GNU tar.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
|
||||
as an argument to <ctype.h> macros like `isspace'. */
|
||||
#if STDC_HEADERS
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# define IN_CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177)
|
||||
#endif
|
||||
|
||||
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
|
||||
#define ISODIGIT(c) ((unsigned) (c) - '0' <= 7)
|
||||
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
|
||||
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
|
||||
|
||||
/* Declare string and memory handling routines. Take care that an ANSI
|
||||
string.h and pre-ANSI memory.h might conflict, and that memory.h and
|
||||
strings.h conflict on some systems. */
|
||||
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif
|
||||
#else
|
||||
# include <strings.h>
|
||||
# ifndef strchr
|
||||
# define strchr index
|
||||
# endif
|
||||
# ifndef strrchr
|
||||
# define strrchr rindex
|
||||
# endif
|
||||
# ifndef memcpy
|
||||
# define memcpy(d, s, n) bcopy ((char const *) (s), (char *) (d), n)
|
||||
# endif
|
||||
# ifndef memcmp
|
||||
# define memcmp(a, b, n) bcmp ((char const *) (a), (char const *) (b), n)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare errno. */
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Declare open parameters. */
|
||||
|
||||
#if HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
/* Pick only one of the next three: */
|
||||
#ifndef O_RDONLY
|
||||
# define O_RDONLY 0 /* only allow read */
|
||||
#endif
|
||||
#ifndef O_WRONLY
|
||||
# define O_WRONLY 1 /* only allow write */
|
||||
#endif
|
||||
#ifndef O_RDWR
|
||||
# define O_RDWR 2 /* both are allowed */
|
||||
#endif
|
||||
#ifndef O_ACCMODE
|
||||
# define O_ACCMODE (O_RDONLY | O_RDWR | O_WRONLY)
|
||||
#endif
|
||||
/* The rest can be OR-ed in to the above: */
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 8 /* create file if needed */
|
||||
#endif
|
||||
#ifndef O_EXCL
|
||||
# define O_EXCL 16 /* file cannot already exist */
|
||||
#endif
|
||||
#ifndef O_TRUNC
|
||||
# define O_TRUNC 32 /* truncate file on open */
|
||||
#endif
|
||||
/* MS-DOG forever, with my love! */
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/* Declare file status routines and bits. */
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !HAVE_LSTAT && !defined lstat
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
#if STX_HIDDEN && !_LARGE_FILES /* AIX */
|
||||
# ifdef stat
|
||||
# undef stat
|
||||
# endif
|
||||
# define stat(path, buf) statx (path, buf, STATSIZE, STX_HIDDEN)
|
||||
# ifdef lstat
|
||||
# undef lstat
|
||||
# endif
|
||||
# define lstat(path, buf) statx (path, buf, STATSIZE, STX_HIDDEN | STX_LINK)
|
||||
#endif
|
||||
|
||||
#if STAT_MACROS_BROKEN
|
||||
# undef S_ISBLK
|
||||
# undef S_ISCHR
|
||||
# undef S_ISCTG
|
||||
# undef S_ISDIR
|
||||
# undef S_ISFIFO
|
||||
# undef S_ISLNK
|
||||
# undef S_ISREG
|
||||
# undef S_ISSOCK
|
||||
#endif
|
||||
|
||||
/* On MSDOS, there are missing things from <sys/stat.h>. */
|
||||
#if MSDOS
|
||||
# define S_ISUID 0
|
||||
# define S_ISGID 0
|
||||
# define S_ISVTX 0
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(Mode) (((Mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#ifndef S_ISREG
|
||||
# define S_ISREG(Mode) (((Mode) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISBLK
|
||||
# ifdef S_IFBLK
|
||||
# define S_ISBLK(Mode) (((Mode) & S_IFMT) == S_IFBLK)
|
||||
# else
|
||||
# define S_ISBLK(Mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCHR
|
||||
# ifdef S_IFCHR
|
||||
# define S_ISCHR(Mode) (((Mode) & S_IFMT) == S_IFCHR)
|
||||
# else
|
||||
# define S_ISCHR(Mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCTG
|
||||
# ifdef S_IFCTG
|
||||
# define S_ISCTG(Mode) (((Mode) & S_IFMT) == S_IFCTG)
|
||||
# else
|
||||
# define S_ISCTG(Mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISDOOR
|
||||
# define S_ISDOOR(Mode) 0
|
||||
#endif
|
||||
#ifndef S_ISFIFO
|
||||
# ifdef S_IFIFO
|
||||
# define S_ISFIFO(Mode) (((Mode) & S_IFMT) == S_IFIFO)
|
||||
# else
|
||||
# define S_ISFIFO(Mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISLNK
|
||||
# ifdef S_IFLNK
|
||||
# define S_ISLNK(Mode) (((Mode) & S_IFMT) == S_IFLNK)
|
||||
# else
|
||||
# define S_ISLNK(Mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISSOCK
|
||||
# ifdef S_IFSOCK
|
||||
# define S_ISSOCK(Mode) (((Mode) & S_IFMT) == S_IFSOCK)
|
||||
# else
|
||||
# define S_ISSOCK(Mode) 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !HAVE_MKFIFO && !defined mkfifo && defined S_IFIFO
|
||||
# define mkfifo(Path, Mode) (mknod (Path, (Mode) | S_IFIFO, 0))
|
||||
#endif
|
||||
|
||||
#ifndef S_ISUID
|
||||
# define S_ISUID 0004000
|
||||
#endif
|
||||
#ifndef S_ISGID
|
||||
# define S_ISGID 0002000
|
||||
#endif
|
||||
#ifndef S_ISVTX
|
||||
# define S_ISVTX 0001000
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR 0000400
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR 0000200
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
# define S_IXUSR 0000100
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
# define S_IRGRP 0000040
|
||||
#endif
|
||||
#ifndef S_IWGRP
|
||||
# define S_IWGRP 0000020
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
# define S_IXGRP 0000010
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
# define S_IROTH 0000004
|
||||
#endif
|
||||
#ifndef S_IWOTH
|
||||
# define S_IWOTH 0000002
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
# define S_IXOTH 0000001
|
||||
#endif
|
||||
|
||||
#define MODE_WXUSR (S_IWUSR | S_IXUSR)
|
||||
#define MODE_R (S_IRUSR | S_IRGRP | S_IROTH)
|
||||
#define MODE_RW (S_IWUSR | S_IWGRP | S_IWOTH | MODE_R)
|
||||
#define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
|
||||
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
||||
|
||||
/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
# define SEEK_CUR 1
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
# define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
# define STDOUT_FILENO 1
|
||||
#endif
|
||||
#ifndef STDERR_FILENO
|
||||
# define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
/* Declare make device, major and minor. Since major is a function on
|
||||
SVR4, we have to resort to GOT_MAJOR instead of just testing if
|
||||
major is #define'd. */
|
||||
|
||||
#if MAJOR_IN_MKDEV
|
||||
# include <sys/mkdev.h>
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#if MAJOR_IN_SYSMACROS
|
||||
# include <sys/sysmacros.h>
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
/* Some <sys/types.h> defines the macros. */
|
||||
#ifdef major
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# if MSDOS
|
||||
# define major(Device) (Device)
|
||||
# define minor(Device) (Device)
|
||||
# define makedev(Major, Minor) (((Major) << 8) | (Minor))
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For HP-UX before HP-UX 8, major/minor are not in <sys/sysmacros.h>. */
|
||||
#ifndef GOT_MAJOR
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# include <sys/mknod.h>
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# define major(Device) (((Device) >> 8) & 0xff)
|
||||
# define minor(Device) ((Device) & 0xff)
|
||||
# define makedev(Major, Minor) (((Major) << 8) | (Minor))
|
||||
#endif
|
||||
|
||||
#undef GOT_MAJOR
|
||||
|
||||
/* Declare wait status. */
|
||||
|
||||
#if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
#ifndef WEXITSTATUS
|
||||
# define WEXITSTATUS(s) (((s) >> 8) & 0xff)
|
||||
#endif
|
||||
#ifndef WIFSIGNALED
|
||||
# define WIFSIGNALED(s) (((s) & 0xffff) - 1 < (unsigned) 0xff)
|
||||
#endif
|
||||
#ifndef WTERMSIG
|
||||
# define WTERMSIG(s) ((s) & 0x7f)
|
||||
#endif
|
||||
|
||||
/* FIXME: It is wrong to use BLOCKSIZE for buffers when the logical block
|
||||
size is greater than 512 bytes; so ST_BLKSIZE code below, in preparation
|
||||
for some cleanup in this area, later. */
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_BLKSIZE gives the
|
||||
optimal I/O blocksize for the file, in bytes. Some systems, like
|
||||
Sequents, return st_blksize of 0 on pipes. */
|
||||
|
||||
#define DEFAULT_ST_BLKSIZE 512
|
||||
|
||||
#if !HAVE_ST_BLKSIZE
|
||||
# define ST_BLKSIZE(Statbuf) DEFAULT_ST_BLKSIZE
|
||||
#else
|
||||
# define ST_BLKSIZE(Statbuf) \
|
||||
((Statbuf).st_blksize > 0 ? (Statbuf).st_blksize : DEFAULT_ST_BLKSIZE)
|
||||
#endif
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_NBLOCKS gives the
|
||||
number of ST_NBLOCKSIZE-byte blocks in the file (including indirect blocks).
|
||||
HP-UX counts st_blocks in 1024-byte units,
|
||||
this loses when mixing HP-UX and BSD filesystems with NFS. AIX PS/2
|
||||
counts st_blocks in 4K units. */
|
||||
|
||||
#if !HAVE_ST_BLOCKS
|
||||
# if defined(_POSIX_SOURCE) || !defined(BSIZE)
|
||||
# define ST_NBLOCKS(Statbuf) ((Statbuf).st_size / ST_NBLOCKSIZE + ((Statbuf).st_size % ST_NBLOCKSIZE != 0))
|
||||
# else
|
||||
off_t st_blocks ();
|
||||
# define ST_NBLOCKS(Statbuf) (st_blocks ((Statbuf).st_size))
|
||||
# endif
|
||||
#else
|
||||
# define ST_NBLOCKS(Statbuf) ((Statbuf).st_blocks)
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# define ST_NBLOCKSIZE 1024
|
||||
# else
|
||||
# if defined(_AIX) && defined(_I386)
|
||||
# define ST_NBLOCKSIZE (4 * 1024)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ST_NBLOCKSIZE
|
||||
#define ST_NBLOCKSIZE 512
|
||||
#endif
|
||||
|
||||
/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses
|
||||
<sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires
|
||||
<sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It
|
||||
seems that the rest use <sys/mtio.h>, which itself requires other files,
|
||||
depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
|
||||
|
||||
#if HAVE_SYS_GENTAPE_H
|
||||
# include <sys/gentape.h>
|
||||
#else
|
||||
# if HAVE_SYS_TAPE_H
|
||||
# if HAVE_SYS_DEVICE_H
|
||||
# include <sys/device.h>
|
||||
# endif
|
||||
# if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if HAVE_SYS_BUF_H
|
||||
# include <sys/buf.h>
|
||||
# endif
|
||||
# if HAVE_SYS_TPRINTF_H
|
||||
# include <sys/tprintf.h>
|
||||
# endif
|
||||
# include <sys/tape.h>
|
||||
# else
|
||||
# if HAVE_SYS_MTIO_H
|
||||
# include <sys/ioctl.h>
|
||||
# if HAVE_SGTTY_H
|
||||
# include <sgtty.h>
|
||||
# endif
|
||||
# if HAVE_SYS_IO_TRIOCTL_H
|
||||
# include <sys/io/trioctl.h>
|
||||
# endif
|
||||
# include <sys/mtio.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare standard functions. */
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
void *malloc ();
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#if !defined _POSIX_VERSION && MSDOS
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if WITH_DMALLOC
|
||||
# undef HAVE_DECL_VALLOC
|
||||
# define DMALLOC_FUNC_CHECK
|
||||
# include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef MB_LEN_MAX
|
||||
# define MB_LEN_MAX 1
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* These macros work even on ones'-complement hosts (!).
|
||||
The extra casts work around common compiler bugs. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
#define TYPE_MINIMUM(t) (TYPE_SIGNED (t) \
|
||||
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
|
||||
: (t) 0)
|
||||
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
|
||||
|
||||
/* Bound on length of the string representing an integer value of type t.
|
||||
Subtract one for the sign bit if t is signed;
|
||||
302 / 1000 is log10 (2) rounded up;
|
||||
add one for integer division truncation;
|
||||
add one more for a minus sign if t is signed. */
|
||||
#define INT_STRLEN_BOUND(t) \
|
||||
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
|
||||
+ 1 + TYPE_SIGNED (t))
|
||||
|
||||
#define UINTMAX_STRSIZE_BOUND (INT_STRLEN_BOUND (uintmax_t) + 1)
|
||||
|
||||
/* Prototypes for external functions. */
|
||||
|
||||
#if HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
#if !HAVE_SETLOCALE
|
||||
# define setlocale(Category, Locale) /* empty */
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#if defined(HAVE_SYS_TIME_H) && defined(TIME_WITH_SYS_TIME)
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#if ! HAVE_DECL_TIME
|
||||
time_t time ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
|
||||
/* Library modules. */
|
||||
|
||||
#include <dirname.h>
|
||||
#include <error.h>
|
||||
#include <savedir.h>
|
||||
#include <unlocked-io.h>
|
||||
#include <xalloc.h>
|
||||
|
||||
#include <gettext.h>
|
||||
#define _(msgid) gettext (msgid)
|
||||
#define N_(msgid) msgid
|
||||
|
||||
#if ! defined valloc && ! HAVE_DECL_VALLOC
|
||||
# define valloc(Size) malloc (Size)
|
||||
#endif
|
||||
|
||||
#if MSDOS
|
||||
# include <process.h>
|
||||
# define SET_BINARY_MODE(arc) setmode(arc, O_BINARY)
|
||||
# define ERRNO_IS_EACCES errno == EACCES
|
||||
# define mkdir(file, mode) (mkdir) (file)
|
||||
#else
|
||||
# include <pwd.h>
|
||||
# include <grp.h>
|
||||
# define SET_BINARY_MODE(arc)
|
||||
# define ERRNO_IS_EACCES 0
|
||||
#endif
|
||||
|
||||
#if XENIX
|
||||
# include <sys/inode.h>
|
||||
#endif
|
||||
74
src/tar.h
74
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 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
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* tar Header Block, from POSIX 1003.1-1990. */
|
||||
|
||||
@@ -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,17 +181,16 @@ 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'
|
||||
|
||||
/* This file is a tape/volume header. Ignore it on extraction. */
|
||||
#define GNUTYPE_VOLHDR 'V'
|
||||
|
||||
|
||||
/* J<>rg Schilling star header */
|
||||
/* Solaris extended header */
|
||||
#define SOLARIS_XHDTYPE 'X'
|
||||
|
||||
/* J@"org Schilling star header */
|
||||
|
||||
struct star_header
|
||||
{ /* byte offset */
|
||||
@@ -218,7 +218,8 @@ struct star_header
|
||||
#define SPARSES_IN_STAR_HEADER 4
|
||||
#define SPARSES_IN_STAR_EXT_HEADER 21
|
||||
|
||||
struct star_in_header {
|
||||
struct star_in_header
|
||||
{
|
||||
char fill[345]; /* 0 Everything that is before t_prefix */
|
||||
char prefix[1]; /* 345 t_name prefix */
|
||||
char fill2; /* 346 */
|
||||
@@ -233,11 +234,13 @@ struct star_in_header {
|
||||
char xmagic[4]; /* 508 "tar" */
|
||||
};
|
||||
|
||||
struct star_ext_header {
|
||||
struct star_ext_header
|
||||
{
|
||||
struct sparse sp[SPARSES_IN_STAR_EXT_HEADER];
|
||||
char isextended;
|
||||
};
|
||||
|
||||
/* END */
|
||||
|
||||
|
||||
/* tar Header Block, overall structure. */
|
||||
@@ -260,41 +263,60 @@ enum archive_format
|
||||
|
||||
/* Information about a sparse file. */
|
||||
struct sp_array
|
||||
{
|
||||
off_t offset;
|
||||
size_t numbytes;
|
||||
};
|
||||
{
|
||||
off_t offset;
|
||||
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 */
|
||||
char *file_name; /* name of file for the current archive entry
|
||||
after being normalized. */
|
||||
int had_trailing_slash; /* nonzero if the current archive entry had a
|
||||
bool had_trailing_slash; /* true if the current archive entry had a
|
||||
trailing slash before it was normalized. */
|
||||
char *link_name; /* name of link for the current archive entry. */
|
||||
|
||||
unsigned int devminor; /* device minor number */
|
||||
unsigned int devmajor; /* device major number */
|
||||
char *uname; /* user name of owner */
|
||||
char *gname; /* group name of owner */
|
||||
struct stat stat; /* regular filesystem stat */
|
||||
|
||||
/* Nanosecond parts of file timestamps (if available) */
|
||||
unsigned long atime_nsec;
|
||||
unsigned long mtime_nsec;
|
||||
unsigned long ctime_nsec;
|
||||
|
||||
/* STAT doesn't always have access, data modification, and status
|
||||
change times in a convenient form, so store them separately. */
|
||||
struct timespec atime;
|
||||
struct timespec mtime;
|
||||
struct timespec ctime;
|
||||
|
||||
off_t archive_file_size; /* Size of file as stored in the archive.
|
||||
Equals stat.st_size for non-sparse files */
|
||||
|
||||
bool is_sparse; /* Is the file sparse */
|
||||
|
||||
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;
|
||||
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
|
||||
(for GNUTYPE_DUMPDIR) */
|
||||
char *dumpdir; /* Contents of the dump directory */
|
||||
};
|
||||
|
||||
union block
|
||||
@@ -307,5 +329,3 @@ union block
|
||||
struct star_in_header star_in_header;
|
||||
struct star_ext_header star_ext_header;
|
||||
};
|
||||
|
||||
/* End of Format description. */
|
||||
|
||||
527
src/transform.c
Normal file
527
src/transform.c
Normal file
@@ -0,0 +1,527 @@
|
||||
/* This file is part of 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. */
|
||||
|
||||
#include <system.h>
|
||||
#include <regex.h>
|
||||
#include "common.h"
|
||||
|
||||
static 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
|
||||
{
|
||||
segm_literal, /* Literal segment */
|
||||
segm_backref, /* Back-reference segment */
|
||||
segm_case_ctl /* Case control segment (GNU extension) */
|
||||
};
|
||||
|
||||
enum case_ctl_type
|
||||
{
|
||||
ctl_stop, /* Stop case conversion */
|
||||
ctl_upcase_next,/* Turn the next character to uppercase */
|
||||
ctl_locase_next,/* Turn the next character to lowercase */
|
||||
ctl_upcase, /* Turn the replacement to uppercase until ctl_stop */
|
||||
ctl_locase /* Turn the replacement to lowercase until ctl_stop */
|
||||
};
|
||||
|
||||
struct replace_segm
|
||||
{
|
||||
struct replace_segm *next;
|
||||
enum replace_segm_type type;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
char *ptr;
|
||||
size_t size;
|
||||
} literal; /* type == segm_literal */
|
||||
size_t ref; /* type == segm_backref */
|
||||
enum case_ctl_type ctl; /* type == segm_case_ctl */
|
||||
} v;
|
||||
};
|
||||
|
||||
/* Compiled replacement expression */
|
||||
static struct replace_segm *repl_head, *repl_tail;
|
||||
static size_t segm_count; /* Number of elements in the above list */
|
||||
|
||||
static struct replace_segm *
|
||||
add_segment (void)
|
||||
{
|
||||
struct replace_segm *segm = xmalloc (sizeof *segm);
|
||||
segm->next = NULL;
|
||||
if (repl_tail)
|
||||
repl_tail->next = segm;
|
||||
else
|
||||
repl_head = segm;
|
||||
repl_tail = segm;
|
||||
segm_count++;
|
||||
return segm;
|
||||
}
|
||||
|
||||
static void
|
||||
add_literal_segment (char *str, char *end)
|
||||
{
|
||||
size_t len = end - str;
|
||||
if (len)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (len + 1);
|
||||
memcpy (segm->v.literal.ptr, str, len);
|
||||
segm->v.literal.ptr[len] = 0;
|
||||
segm->v.literal.size = len;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_char_segment (int chr)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_literal;
|
||||
segm->v.literal.ptr = xmalloc (2);
|
||||
segm->v.literal.ptr[0] = chr;
|
||||
segm->v.literal.ptr[1] = 0;
|
||||
segm->v.literal.size = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
add_backref_segment (size_t ref)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_backref;
|
||||
segm->v.ref = ref;
|
||||
}
|
||||
|
||||
static void
|
||||
add_case_ctl_segment (enum case_ctl_type ctl)
|
||||
{
|
||||
struct replace_segm *segm = add_segment ();
|
||||
segm->type = segm_case_ctl;
|
||||
segm->v.ctl = ctl;
|
||||
}
|
||||
|
||||
void
|
||||
set_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);
|
||||
}
|
||||
|
||||
if (expr[0] != 's')
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
delim = expr[1];
|
||||
|
||||
/* Scan regular expression */
|
||||
for (i = 2; expr[i] && expr[i] != delim; i++)
|
||||
if (expr[i] == '\\' && expr[i+1])
|
||||
i++;
|
||||
|
||||
if (expr[i] != delim)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
/* Scan replacement expression */
|
||||
for (j = i + 1; expr[j] && expr[j] != delim; j++)
|
||||
if (expr[j] == '\\' && expr[j+1])
|
||||
j++;
|
||||
|
||||
if (expr[j] != delim)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression")));
|
||||
|
||||
/* Check flags */
|
||||
transform_type = transform_first;
|
||||
for (p = expr + j + 1; *p; p++)
|
||||
switch (*p)
|
||||
{
|
||||
case 'g':
|
||||
transform_type = transform_global;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
cflags |= REG_ICASE;
|
||||
break;
|
||||
|
||||
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);
|
||||
p--;
|
||||
break;
|
||||
|
||||
default:
|
||||
USAGE_ERROR ((0, 0, _("Unknown flag in transform expression")));
|
||||
}
|
||||
|
||||
/* Extract and compile regex */
|
||||
str = xmalloc (i - 1);
|
||||
memcpy (str, expr + 2, i - 2);
|
||||
str[i - 2] = 0;
|
||||
|
||||
rc = regcomp (®ex, str, cflags);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
char errbuf[512];
|
||||
regerror (rc, ®ex, errbuf, sizeof (errbuf));
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf));
|
||||
}
|
||||
|
||||
if (str[0] == '^' || str[strlen (str) - 1] == '$')
|
||||
transform_type = transform_first;
|
||||
|
||||
free (str);
|
||||
|
||||
/* Extract and compile replacement expr */
|
||||
i++;
|
||||
str = xmalloc (j - i + 1);
|
||||
memcpy (str, expr + i, j - i);
|
||||
str[j - i] = 0;
|
||||
|
||||
for (cur = beg = str; *cur;)
|
||||
{
|
||||
if (*cur == '\\')
|
||||
{
|
||||
size_t n;
|
||||
|
||||
add_literal_segment (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)
|
||||
USAGE_ERROR ((0, 0, _("Invalid transform replacement: back reference out of range")));
|
||||
add_backref_segment (n);
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
add_char_segment ('\\');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
add_char_segment ('\a');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
add_char_segment ('\b');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
add_char_segment ('\f');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
add_char_segment ('\n');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
add_char_segment ('\r');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
add_char_segment ('\t');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
add_char_segment ('\v');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
add_char_segment ('&');
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
/* Turn the replacement to lowercase until a `\U' or `\E'
|
||||
is found, */
|
||||
add_case_ctl_segment (ctl_locase);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
/* Turn the next character to lowercase, */
|
||||
add_case_ctl_segment (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);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
/* Turn the next character to uppercase, */
|
||||
add_case_ctl_segment (ctl_upcase_next);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
/* Stop case conversion started by `\L' or `\U'. */
|
||||
add_case_ctl_segment (ctl_stop);
|
||||
cur++;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Try to be nice */
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = '\\';
|
||||
buf[1] = *cur;
|
||||
add_literal_segment (buf, buf + 2);
|
||||
}
|
||||
cur++;
|
||||
break;
|
||||
}
|
||||
beg = cur;
|
||||
}
|
||||
else if (*cur == '&')
|
||||
{
|
||||
add_literal_segment (beg, cur);
|
||||
add_backref_segment (0);
|
||||
beg = ++cur;
|
||||
}
|
||||
else
|
||||
cur++;
|
||||
}
|
||||
add_literal_segment (beg, cur);
|
||||
|
||||
}
|
||||
|
||||
/* Run case conversion specified by CASE_CTL on array PTR of SIZE
|
||||
characters. Returns pointer to statically allocated storage. */
|
||||
static char *
|
||||
run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
|
||||
{
|
||||
static char *case_ctl_buffer;
|
||||
static size_t case_ctl_bufsize;
|
||||
char *p;
|
||||
|
||||
if (case_ctl_bufsize < size)
|
||||
{
|
||||
case_ctl_bufsize = size;
|
||||
case_ctl_buffer = xrealloc (case_ctl_buffer, case_ctl_bufsize);
|
||||
}
|
||||
memcpy (case_ctl_buffer, ptr, size);
|
||||
switch (case_ctl)
|
||||
{
|
||||
case ctl_upcase_next:
|
||||
case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
|
||||
break;
|
||||
|
||||
case ctl_locase_next:
|
||||
case_ctl_buffer[0] = tolower (case_ctl_buffer[0]);
|
||||
break;
|
||||
|
||||
case ctl_upcase:
|
||||
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
||||
*p = toupper (*p);
|
||||
break;
|
||||
|
||||
case ctl_locase:
|
||||
for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
||||
*p = tolower (*p);
|
||||
break;
|
||||
|
||||
case ctl_stop:
|
||||
break;
|
||||
}
|
||||
return case_ctl_buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
_transform_name_to_obstack (char *input)
|
||||
{
|
||||
regmatch_t *rmp;
|
||||
int rc;
|
||||
size_t nmatches = 0;
|
||||
enum case_ctl_type case_ctl = ctl_stop, /* Current case conversion op */
|
||||
save_ctl = ctl_stop; /* Saved case_ctl for \u and \l */
|
||||
|
||||
/* Reset case conversion after a single-char operation */
|
||||
#define CASE_CTL_RESET() if (case_ctl == ctl_upcase_next \
|
||||
|| case_ctl == ctl_locase_next) \
|
||||
{ \
|
||||
case_ctl = save_ctl; \
|
||||
save_ctl = ctl_stop; \
|
||||
}
|
||||
|
||||
if (transform_type == transform_none)
|
||||
return false;
|
||||
|
||||
rmp = xmalloc ((regex.re_nsub + 1) * sizeof (*rmp));
|
||||
|
||||
while (*input)
|
||||
{
|
||||
size_t disp;
|
||||
char *ptr;
|
||||
|
||||
rc = regexec (®ex, input, regex.re_nsub + 1, rmp, 0);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
struct replace_segm *segm;
|
||||
|
||||
disp = rmp[0].rm_eo;
|
||||
|
||||
if (rmp[0].rm_so)
|
||||
obstack_grow (&stk, input, rmp[0].rm_so);
|
||||
|
||||
nmatches++;
|
||||
if (match_number && nmatches < match_number)
|
||||
{
|
||||
obstack_grow (&stk, input, disp);
|
||||
input += disp;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (segm = repl_head; segm; segm = segm->next)
|
||||
{
|
||||
switch (segm->type)
|
||||
{
|
||||
case segm_literal: /* Literal segment */
|
||||
if (case_ctl == ctl_stop)
|
||||
ptr = segm->v.literal.ptr;
|
||||
else
|
||||
{
|
||||
ptr = run_case_conv (case_ctl,
|
||||
segm->v.literal.ptr,
|
||||
segm->v.literal.size);
|
||||
CASE_CTL_RESET();
|
||||
}
|
||||
obstack_grow (&stk, ptr, segm->v.literal.size);
|
||||
break;
|
||||
|
||||
case segm_backref: /* Back-reference segment */
|
||||
if (rmp[segm->v.ref].rm_so != -1
|
||||
&& rmp[segm->v.ref].rm_eo != -1)
|
||||
{
|
||||
size_t size = rmp[segm->v.ref].rm_eo
|
||||
- rmp[segm->v.ref].rm_so;
|
||||
ptr = input + rmp[segm->v.ref].rm_so;
|
||||
if (case_ctl != ctl_stop)
|
||||
{
|
||||
ptr = run_case_conv (case_ctl, ptr, size);
|
||||
CASE_CTL_RESET();
|
||||
}
|
||||
|
||||
obstack_grow (&stk, ptr, size);
|
||||
}
|
||||
break;
|
||||
|
||||
case segm_case_ctl:
|
||||
switch (segm->v.ctl)
|
||||
{
|
||||
case ctl_upcase_next:
|
||||
case ctl_locase_next:
|
||||
switch (save_ctl)
|
||||
{
|
||||
case ctl_stop:
|
||||
case ctl_upcase:
|
||||
case ctl_locase:
|
||||
save_ctl = case_ctl;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*FALL THROUGH*/
|
||||
|
||||
case ctl_upcase:
|
||||
case ctl_locase:
|
||||
case ctl_stop:
|
||||
case_ctl = segm->v.ctl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
disp = strlen (input);
|
||||
obstack_grow (&stk, input, disp);
|
||||
}
|
||||
|
||||
input += disp;
|
||||
|
||||
if (transform_type == transform_first)
|
||||
{
|
||||
obstack_grow (&stk, input, strlen (input));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
obstack_1grow (&stk, 0);
|
||||
free (rmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name_fp (char **pinput, char *(*fun)(char *, void *), void *dat)
|
||||
{
|
||||
char *str;
|
||||
bool ret = _transform_name_to_obstack (*pinput);
|
||||
if (ret)
|
||||
{
|
||||
str = obstack_finish (&stk);
|
||||
assign_string (pinput, fun ? fun (str, dat) : str);
|
||||
obstack_free (&stk, str);
|
||||
}
|
||||
else if (fun)
|
||||
{
|
||||
str = *pinput;
|
||||
*pinput = NULL;
|
||||
assign_string (pinput, fun (str, dat));
|
||||
free (str);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
transform_name (char **pinput)
|
||||
{
|
||||
return transform_name_fp (pinput, NULL, NULL);
|
||||
}
|
||||
|
||||
56
src/update.c
56
src/update.c
@@ -1,11 +1,11 @@
|
||||
/* Update a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
|
||||
2004 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
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Implement the 'r', 'u' and 'A' options for tar. 'A' means that the
|
||||
file names are tar files, and they should simply be appended to the end
|
||||
of the archive. No attempt is made to record the reads from the args; if
|
||||
they're on raw tape or something like that, it'll probably lose... */
|
||||
|
||||
#include "system.h"
|
||||
#include <system.h>
|
||||
#include <quotearg.h>
|
||||
#include "common.h"
|
||||
|
||||
@@ -42,22 +42,22 @@ bool time_to_start_writing;
|
||||
first part of the record. */
|
||||
char *output_start;
|
||||
|
||||
/* Catenate file PATH to the archive without creating a header for it.
|
||||
/* Catenate file FILE_NAME to the archive without creating a header for it.
|
||||
It had better be a tar file or the archive is screwed. */
|
||||
static void
|
||||
append_file (char *path)
|
||||
append_file (char *file_name)
|
||||
{
|
||||
int handle = open (path, O_RDONLY | O_BINARY);
|
||||
int handle = open (file_name, O_RDONLY | O_BINARY);
|
||||
struct stat stat_data;
|
||||
|
||||
if (handle < 0)
|
||||
{
|
||||
open_error (path);
|
||||
open_error (file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fstat (handle, &stat_data) != 0)
|
||||
stat_error (path);
|
||||
stat_error (file_name);
|
||||
else
|
||||
{
|
||||
off_t bytes_left = stat_data.st_size;
|
||||
@@ -79,14 +79,14 @@ append_file (char *path)
|
||||
|
||||
status = safe_read (handle, start->buffer, buffer_size);
|
||||
if (status == SAFE_READ_ERROR)
|
||||
read_fatal_details (path, stat_data.st_size - bytes_left,
|
||||
read_fatal_details (file_name, stat_data.st_size - bytes_left,
|
||||
buffer_size);
|
||||
if (status == 0)
|
||||
FATAL_ERROR ((0, 0,
|
||||
ngettext ("%s: File shrank by %s byte",
|
||||
"%s: File shrank by %s bytes",
|
||||
bytes_left),
|
||||
quotearg_colon (path),
|
||||
quotearg_colon (file_name),
|
||||
STRINGIFY_BIGINT (bytes_left, buf)));
|
||||
|
||||
bytes_left -= status;
|
||||
@@ -96,7 +96,7 @@ append_file (char *path)
|
||||
}
|
||||
|
||||
if (close (handle) != 0)
|
||||
close_error (path);
|
||||
close_error (file_name);
|
||||
}
|
||||
|
||||
/* Implement the 'r' (add files to end of archive), and 'u' (add files
|
||||
@@ -106,11 +106,11 @@ void
|
||||
update_archive (void)
|
||||
{
|
||||
enum read_header previous_status = HEADER_STILL_UNREAD;
|
||||
int found_end = 0;
|
||||
bool found_end = false;
|
||||
|
||||
name_gather ();
|
||||
open_archive (ACCESS_UPDATE);
|
||||
xheader_write_global ();
|
||||
buffer_write_global_xheader ();
|
||||
|
||||
while (!found_end)
|
||||
{
|
||||
@@ -126,30 +126,35 @@ update_archive (void)
|
||||
{
|
||||
struct name *name;
|
||||
|
||||
decode_header (current_header, ¤t_stat_info,
|
||||
¤t_format, 0);
|
||||
archive_format = current_format;
|
||||
|
||||
if (subcommand_option == UPDATE_SUBCOMMAND
|
||||
&& (name = name_scan (current_stat_info.file_name)) != NULL)
|
||||
{
|
||||
struct stat s;
|
||||
enum archive_format unused;
|
||||
|
||||
decode_header (current_header, ¤t_stat_info, &unused, 0);
|
||||
chdir_do (name->change_dir);
|
||||
if (deref_stat (dereference_option,
|
||||
current_stat_info.file_name, &s) == 0
|
||||
&& s.st_mtime <= current_stat_info.stat.st_mtime)
|
||||
&& (tar_timespec_cmp (get_stat_mtime (&s),
|
||||
current_stat_info.mtime)
|
||||
<= 0))
|
||||
add_avoided_name (current_stat_info.file_name);
|
||||
}
|
||||
|
||||
skip_member ();
|
||||
break;
|
||||
}
|
||||
|
||||
case HEADER_ZERO_BLOCK:
|
||||
current_block = current_header;
|
||||
found_end = 1;
|
||||
found_end = true;
|
||||
break;
|
||||
|
||||
case HEADER_END_OF_FILE:
|
||||
found_end = 1;
|
||||
found_end = true;
|
||||
break;
|
||||
|
||||
case HEADER_FAILURE:
|
||||
@@ -175,6 +180,7 @@ update_archive (void)
|
||||
break;
|
||||
}
|
||||
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
previous_status = status;
|
||||
}
|
||||
|
||||
@@ -183,18 +189,18 @@ update_archive (void)
|
||||
output_start = current_block->buffer;
|
||||
|
||||
{
|
||||
char *path;
|
||||
char *file_name;
|
||||
|
||||
while ((path = name_from_list ()) != NULL)
|
||||
while ((file_name = name_from_list ()) != NULL)
|
||||
{
|
||||
if (excluded_name (path))
|
||||
if (excluded_name (file_name))
|
||||
continue;
|
||||
if (interactive_option && !confirm ("add", path))
|
||||
if (interactive_option && !confirm ("add", file_name))
|
||||
continue;
|
||||
if (subcommand_option == CAT_SUBCOMMAND)
|
||||
append_file (path);
|
||||
append_file (file_name);
|
||||
else
|
||||
dump_file (path, 1, (dev_t) 0);
|
||||
dump_file (file_name, 1, (dev_t) 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
269
src/utf8.c
269
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
|
||||
@@ -14,10 +14,11 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "system.h"
|
||||
#include <system.h>
|
||||
#include <quotearg.h>
|
||||
#include <localcharset.h>
|
||||
#include "common.h"
|
||||
#ifdef HAVE_ICONV_H
|
||||
# include <iconv.h>
|
||||
@@ -27,254 +28,7 @@
|
||||
# define ICONV_CONST
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBICONV
|
||||
|
||||
struct langtab
|
||||
{
|
||||
char const *lang; /* Language code */
|
||||
char const *terr; /* Territory code */
|
||||
char const *charset; /* Corresponding charset */
|
||||
};
|
||||
|
||||
/* The list of language codes defined in ISO 639 with the corresponding
|
||||
default character sets.
|
||||
|
||||
NOTES:
|
||||
|
||||
1) The list must be ordered by:
|
||||
a) lang field in ascending order
|
||||
b) terr field in descending order.
|
||||
NULL fields are considered less than non-null ones.
|
||||
2) Many entries have NULL charset fields. Please help fill them!
|
||||
3) The "default" character set for a given language is a matter
|
||||
of preference. Possibly the table should contain a *list* of
|
||||
possible character sets.
|
||||
4) LC_ALL "modifier" field is not taken into account */
|
||||
|
||||
static struct langtab langtab[] = {
|
||||
{ "C", NULL, "ASCII"},
|
||||
{ "POSIX", NULL, "ASCII" },
|
||||
{ "aa", NULL, NULL}, /* Afar */
|
||||
{ "ab", NULL, NULL}, /* Abkhazian */
|
||||
{ "ae", NULL, NULL}, /* Avestan */
|
||||
{ "af", NULL, "iso-8859-1"}, /* Afrikaans */
|
||||
{ "am", NULL, "UTF-8"}, /* Amharic */
|
||||
{ "ar", NULL, "iso-8859-6"}, /* Arabic */
|
||||
{ "as", NULL, NULL}, /* Assamese */
|
||||
{ "ay", NULL, "iso-8859-1"}, /* Aymara */
|
||||
{ "az", NULL, NULL}, /* Azerbaijani */
|
||||
{ "ba", NULL, NULL}, /* Bashkir */
|
||||
{ "be", NULL, "UTF-8"}, /* Byelorussian; Belarusian */
|
||||
{ "bg", NULL, "iso-8859-5"}, /* Bulgarian */
|
||||
{ "bh", NULL, NULL}, /* Bihari */
|
||||
{ "bi", NULL, NULL}, /* Bislama */
|
||||
{ "bn", NULL, NULL}, /* Bengali; Bangla */
|
||||
{ "bo", NULL, NULL}, /* Tibetan */
|
||||
{ "br", NULL, "iso-8859-1"}, /* Breton: 1,5,8,9 */
|
||||
{ "bs", NULL, NULL}, /* Bosnian */
|
||||
{ "ca", NULL, "iso-8859-1"}, /* Catalan: 1,5,8,9 */
|
||||
{ "ce", NULL, NULL}, /* Chechen */
|
||||
{ "ch", NULL, NULL}, /* Chamorro */
|
||||
{ "co", NULL, "iso-8859-1"}, /* Corsican */
|
||||
{ "cs", NULL, "iso-8859-2"}, /* Czech */
|
||||
{ "cu", NULL, NULL }, /* Church Slavic */
|
||||
{ "cv", NULL, NULL}, /* Chuvash */
|
||||
{ "cy", NULL, "iso-8859-1"}, /* Welsh */
|
||||
{ "da", NULL, "iso-8859-1"}, /* Danish: 4-9 */
|
||||
{ "de", NULL, "iso-8859-1"}, /* German */
|
||||
{ "dz", NULL, NULL }, /* Dzongkha; Bhutani */
|
||||
{ "el", NULL, "iso-8859-7"}, /* Greek */
|
||||
{ "en", NULL, "iso-8859-1"}, /* English */
|
||||
{ "eo", NULL, "iso-8859-3"}, /* Esperanto */
|
||||
{ "es", NULL, "iso-8859-1"}, /* Spanish */
|
||||
{ "et", NULL, "iso-8859-15"}, /* Estonian: 6,7,9 */
|
||||
{ "eu", NULL, "iso-8859-1"}, /* Basque: 5,8,9 */
|
||||
{ "fa", NULL, "UTF-8"}, /* Persian */
|
||||
{ "fi", NULL, "iso-8859-15"}, /* Finnish */
|
||||
{ "fj", NULL, NULL }, /* Fijian; Fiji */
|
||||
{ "fo", NULL, "iso-8859-1"}, /* Faroese: 6,9 */
|
||||
{ "fr", NULL, "iso-8859-1"}, /* French */
|
||||
{ "fy", NULL, "iso-8859-1"}, /* Frisian */
|
||||
{ "ga", NULL, "iso-8859-14"}, /* Irish */
|
||||
{ "gd", NULL, "iso-8859-14" }, /* Scots; Gaelic */
|
||||
{ "gl", NULL, NULL }, /* Gallegan; Galician */
|
||||
{ "gn", NULL, NULL}, /* Guarani */
|
||||
{ "gu", NULL, NULL}, /* Gujarati */
|
||||
{ "gv", NULL, "iso-8859-14"}, /* Manx */
|
||||
{ "ha", NULL, NULL }, /* Hausa (?) */
|
||||
{ "he", NULL, "iso-8859-8" }, /* Hebrew */
|
||||
{ "hi", NULL, NULL}, /* Hindi */
|
||||
{ "ho", NULL, NULL}, /* Hiri Motu */
|
||||
{ "hr", NULL, "iso-8859-2"}, /* Croatian: 10 */
|
||||
{ "hu", NULL, "iso-8859-2"}, /* Hungarian */
|
||||
{ "hy", NULL, NULL}, /* Armenian */
|
||||
{ "hz", NULL, NULL}, /* Herero */
|
||||
{ "id", NULL, "iso-8859-1"}, /* Indonesian (formerly in) */
|
||||
{ "ia", NULL, NULL}, /* Interlingua */
|
||||
{ "ie", NULL, NULL}, /* Interlingue */
|
||||
{ "ik", NULL, NULL}, /* Inupiak */
|
||||
{ "io", NULL, NULL}, /* Ido */
|
||||
{ "is", NULL, "iso-8859-1"}, /* Icelandic */
|
||||
{ "it", NULL, "iso-8859-1"}, /* Italian */
|
||||
{ "iu", NULL, NULL}, /* Inuktitut */
|
||||
{ "ja", NULL, "EUC-JP"}, /* Japanese */
|
||||
{ "jv", NULL, NULL}, /* Javanese */
|
||||
{ "ka", NULL, NULL}, /* Georgian */
|
||||
{ "ki", NULL, NULL}, /* Kikuyu */
|
||||
{ "kj", NULL, NULL}, /* Kuanyama */
|
||||
{ "kk", NULL, NULL}, /* Kazakh */
|
||||
{ "kl", NULL, "iso-8859-1"}, /* Kalaallisut; Greenlandic */
|
||||
{ "km", NULL, NULL}, /* Khmer; Cambodian */
|
||||
{ "kn", NULL, NULL}, /* Kannada */
|
||||
{ "ko", NULL, "EUC-KR"}, /* Korean */
|
||||
{ "ks", NULL, NULL}, /* Kashmiri */
|
||||
{ "ku", NULL, NULL}, /* Kurdish */
|
||||
{ "kv", NULL, NULL}, /* Komi */
|
||||
{ "kw", NULL, "iso-8859-14"}, /* Cornish: 1,5,8 */
|
||||
{ "ky", NULL, NULL}, /* Kirghiz */
|
||||
{ "la", NULL, "iso-8859-1"}, /* Latin */
|
||||
{ "lb", NULL, "iso-8859-1"}, /* Letzeburgesch */
|
||||
{ "ln", NULL, NULL}, /* Lingala */
|
||||
{ "lo", NULL, NULL}, /* Lao; Laotian */
|
||||
{ "lt", NULL, "iso-8859-4"}, /* Lithuanian */
|
||||
{ "lv", NULL, "iso-8859-4"}, /* Latvian; Lettish */
|
||||
{ "mg", NULL, NULL}, /* Malagasy */
|
||||
{ "mh", NULL, NULL}, /* Marshall */
|
||||
{ "mi", NULL, NULL}, /* Maori */
|
||||
{ "mk", NULL, NULL}, /* Macedonian */
|
||||
{ "ml", NULL, NULL}, /* Malayalam */
|
||||
{ "mn", NULL, NULL}, /* Mongolian */
|
||||
{ "mo", NULL, "iso-8859-2"}, /* Moldavian */
|
||||
{ "mr", NULL, NULL}, /* Marathi */
|
||||
{ "ms", NULL, NULL}, /* Malay */
|
||||
{ "mt", NULL, "iso-8859-3"}, /* Maltese */
|
||||
{ "my", NULL, NULL}, /* Burmese */
|
||||
{ "na", NULL, NULL}, /* Nauru */
|
||||
{ "nb", NULL, "iso-8859-1"}, /* Norwegian Bokm<6B>l; Bokm@aa{}l */
|
||||
{ "nd", NULL, NULL}, /* Ndebele, North */
|
||||
{ "ne", NULL, NULL}, /* Nepali */
|
||||
{ "ng", NULL, NULL}, /* Ndonga */
|
||||
{ "nl", NULL, "iso-8859-1"}, /* Dutch: 5,9 */
|
||||
{ "nn", NULL, "iso-8859-1"}, /* Norwegian Nynorsk */
|
||||
{ "no", NULL, "iso-8859-1"}, /* Norwegian */
|
||||
{ "nr", NULL, NULL}, /* Ndebele, South */
|
||||
{ "nv", NULL, NULL}, /* Navajo */
|
||||
{ "ny", NULL, NULL}, /* Chichewa; Nyanja */
|
||||
{ "oc", NULL, NULL}, /* Occitan; Proven<65>al; Proven@,{c}al */
|
||||
{ "om", NULL, NULL}, /* (Afan) Oromo */
|
||||
{ "or", NULL, NULL}, /* Oriya */
|
||||
{ "os", NULL, NULL}, /* Ossetian; Ossetic */
|
||||
{ "pa", NULL, NULL}, /* Panjabi; Punjabi */
|
||||
{ "pi", NULL, NULL}, /* Pali */
|
||||
{ "pl", NULL, "iso-8859-2"}, /* Polish */
|
||||
{ "ps", NULL, NULL}, /* Pashto, Pushto */
|
||||
{ "pt", NULL, "iso-8859-1"}, /* Portuguese */
|
||||
{ "qu", NULL, "iso-8859-1"}, /* Quechua */
|
||||
{ "rm", NULL, "iso-8859-1"}, /* Rhaeto-Romance */
|
||||
{ "rn", NULL, NULL }, /* Rundi; Kirundi */
|
||||
{ "ro", NULL, "iso-8859-2"}, /* Romanian */
|
||||
{ "ru", NULL, "koi8-r"}, /* Russian */
|
||||
{ "rw", NULL, NULL}, /* Kinyarwanda */
|
||||
{ "sa", NULL, NULL}, /* Sanskrit */
|
||||
{ "sc", NULL, "iso-8859-1"}, /* Sardinian */
|
||||
{ "sd", NULL, NULL}, /* Sindhi */
|
||||
{ "se", NULL, "iso-8859-10"}, /* Northern Sami */
|
||||
{ "sg", NULL, NULL}, /* Sango; Sangro */
|
||||
{ "si", NULL, NULL}, /* Sinhalese */
|
||||
{ "sk", NULL, "iso-8859-2"}, /* Slovak */
|
||||
{ "sl", NULL, "iso-8859-1"}, /* Slovenian */
|
||||
{ "sm", NULL, NULL}, /* Samoan */
|
||||
{ "sn", NULL, NULL}, /* Shona */
|
||||
{ "so", NULL, NULL}, /* Somali */
|
||||
{ "sq", NULL, "iso-8859-1"}, /* Albanian: 2,5,8,9,10 */
|
||||
{ "sr", NULL, "iso-8859-2"}, /* Serbian */
|
||||
{ "ss", NULL, NULL}, /* Swati; Siswati */
|
||||
{ "st", NULL, NULL}, /* Sesotho; Sotho, Southern */
|
||||
{ "su", NULL, NULL}, /* Sundanese */
|
||||
{ "sv", NULL, "iso-8859-1"}, /* Swedish */
|
||||
{ "sw", NULL, NULL}, /* Swahili */
|
||||
{ "ta", NULL, NULL}, /* Tamil */
|
||||
{ "te", NULL, NULL}, /* Telugu */
|
||||
{ "tg", NULL, NULL}, /* Tajik */
|
||||
{ "th", NULL, "iso-8859-11"}, /* Thai */
|
||||
{ "ti", NULL, NULL}, /* Tigrinya */
|
||||
{ "tk", NULL, NULL}, /* Turkmen */
|
||||
{ "tl", NULL, "iso-8859-1"}, /* Tagalog */
|
||||
{ "tn", NULL, NULL}, /* Tswana; Setswana */
|
||||
{ "to", NULL, NULL}, /* Tonga (?) */
|
||||
{ "tr", NULL, "iso-8859-9"}, /* Turkish */
|
||||
{ "ts", NULL, NULL}, /* Tsonga */
|
||||
{ "tt", NULL, NULL}, /* Tatar */
|
||||
{ "tw", NULL, NULL}, /* Twi */
|
||||
{ "ty", NULL, NULL}, /* Tahitian */
|
||||
{ "ug", NULL, NULL}, /* Uighur */
|
||||
{ "uk", NULL, "koi8-u"}, /* Ukrainian */
|
||||
{ "ur", NULL, NULL}, /* Urdu */
|
||||
{ "uz", NULL, NULL}, /* Uzbek */
|
||||
{ "vi", NULL, NULL}, /* Vietnamese */
|
||||
{ "vo", NULL, NULL}, /* Volap<61>k; Volap@"{u}k; Volapuk */
|
||||
{ "wa", NULL, "iso-8859-1"}, /* Walloon */
|
||||
{ "wo", NULL, NULL}, /* Wolof */
|
||||
{ "xh", NULL, NULL}, /* Xhosa */
|
||||
{ "yi", NULL, "iso-8859-8"}, /* Yiddish (formerly ji) */
|
||||
{ "yo", NULL, NULL}, /* Yoruba */
|
||||
{ "za", NULL, NULL}, /* Zhuang */
|
||||
{ "zh", "TW", "big5"}, /* Chinese */
|
||||
{ "zh", NULL, "gb2312"}, /* Chinese */
|
||||
{ "zu", NULL, NULL}, /* Zulu */
|
||||
{ NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* Given the language and (optionally) territory code, return the
|
||||
default character set for that language. See notes above. */
|
||||
|
||||
static char const *
|
||||
charset_lookup (char const *lang, char const *terr)
|
||||
{
|
||||
struct langtab const *p;
|
||||
|
||||
if (!lang)
|
||||
return NULL;
|
||||
for (p = langtab; p->lang; p++)
|
||||
if (strcasecmp (p->lang, lang) == 0
|
||||
&& (terr == NULL
|
||||
|| p->terr == NULL
|
||||
|| !strcasecmp (p->terr, terr) == 0))
|
||||
return p->charset;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_input_charset (void)
|
||||
{
|
||||
const char *charset = NULL;
|
||||
char *tmp;
|
||||
|
||||
/* Try to deduce the charset from LC_ALL or LANG variables */
|
||||
|
||||
tmp = getenv ("LC_ALL");
|
||||
if (!tmp)
|
||||
tmp = getenv ("LANG");
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
char *lang;
|
||||
char *terr;
|
||||
|
||||
lang = strtok (tmp, "_");
|
||||
terr = strtok (NULL, ".");
|
||||
charset = strtok (NULL, "@");
|
||||
|
||||
if (!charset)
|
||||
charset = charset_lookup (lang, terr);
|
||||
}
|
||||
|
||||
if (!charset)
|
||||
charset = "iso-8859-1";
|
||||
return charset;
|
||||
}
|
||||
|
||||
#else /* !defined HAVE_LIBICONV */
|
||||
#ifndef HAVE_ICONV
|
||||
|
||||
# undef iconv_open
|
||||
# define iconv_open(tocode, fromcode) ((iconv_t) -1)
|
||||
@@ -285,7 +39,7 @@ get_input_charset (void)
|
||||
# undef iconv_close
|
||||
# define iconv_close(cd) 0
|
||||
|
||||
#endif /* !defined HAVE_LIBICONV */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -298,9 +52,9 @@ utf8_init (bool to_utf)
|
||||
if (conv_desc[(int) to_utf] == (iconv_t) -1)
|
||||
{
|
||||
if (to_utf)
|
||||
conv_desc[(int) to_utf] = iconv_open ("UTF-8", get_input_charset ());
|
||||
conv_desc[(int) to_utf] = iconv_open ("UTF-8", locale_charset ());
|
||||
else
|
||||
conv_desc[(int) to_utf] = iconv_open (get_input_charset (), "UTF-8");
|
||||
conv_desc[(int) to_utf] = iconv_open (locale_charset (), "UTF-8");
|
||||
}
|
||||
return conv_desc[(int) to_utf];
|
||||
}
|
||||
@@ -334,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 (! (0 <= *p && *p <= 127))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
990
src/xheader.c
990
src/xheader.c
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,17 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
preset
|
||||
*.bz2
|
||||
*.gz
|
||||
*.tar
|
||||
*.gtar
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
argcv.c
|
||||
argcv.h
|
||||
atconfig
|
||||
atlocal
|
||||
genfile
|
||||
mksparse
|
||||
tmp-*
|
||||
directory
|
||||
archive
|
||||
genfile.c
|
||||
package.m4
|
||||
testsuite
|
||||
testsuite.dir
|
||||
testsuite.log
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# Makefile for GNU tar regression tests.
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003 Free Software
|
||||
# Foundation, Inc.
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||
# 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,
|
||||
@@ -17,55 +18,144 @@
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
## 02111-1307, USA.
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
## 02110-1301, USA.
|
||||
|
||||
check_PROGRAMS = genfile mksparse
|
||||
BUILT_SOURCES = preset
|
||||
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 star/README star/quicktest.sh
|
||||
DISTCLEANFILES = atconfig $(check_SCRIPTS)
|
||||
MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
|
||||
|
||||
TESTS = \
|
||||
version.sh\
|
||||
append.sh\
|
||||
delete01.sh\
|
||||
delete02.sh\
|
||||
delete03.sh\
|
||||
delete04.sh\
|
||||
extrac01.sh\
|
||||
extrac02.sh\
|
||||
extrac03.sh\
|
||||
extrac04.sh\
|
||||
gzip.sh\
|
||||
incremen.sh\
|
||||
ignfail.sh\
|
||||
listed01.sh\
|
||||
longv7.sh\
|
||||
multiv01.sh\
|
||||
multiv02.sh\
|
||||
old.sh\
|
||||
options.sh\
|
||||
same-order01.sh\
|
||||
same-order02.sh\
|
||||
volume.sh\
|
||||
recurse.sh\
|
||||
sparse01.sh\
|
||||
star/gtarfail.sh\
|
||||
star/gtarfail2.sh\
|
||||
star/multi-fail.sh\
|
||||
star/ustar-big-2g.sh\
|
||||
star/ustar-big-8g.sh\
|
||||
star/pax-big-10g.sh\
|
||||
star/qucktest.sh
|
||||
## ------------ ##
|
||||
## package.m4. ##
|
||||
## ------------ ##
|
||||
|
||||
genfile_SOURCES = genfile.c
|
||||
mksparse_SOURCES = mksparse.c
|
||||
EXTRA_DIST = after before preset.in $(TESTS) star/README
|
||||
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
|
||||
{ \
|
||||
echo '# Signature of the current package.'; \
|
||||
echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \
|
||||
echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \
|
||||
} >$(srcdir)/package.m4
|
||||
|
||||
#
|
||||
|
||||
## ------------ ##
|
||||
## Test suite. ##
|
||||
## ------------ ##
|
||||
|
||||
TESTSUITE_AT = \
|
||||
T-empty.at\
|
||||
T-null.at\
|
||||
testsuite.at\
|
||||
append.at\
|
||||
append01.at\
|
||||
append02.at\
|
||||
chtype.at\
|
||||
comprec.at\
|
||||
delete01.at\
|
||||
delete02.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\
|
||||
listed02.at\
|
||||
long01.at\
|
||||
longv7.at\
|
||||
lustar01.at\
|
||||
lustar02.at\
|
||||
lustar03.at\
|
||||
multiv01.at\
|
||||
multiv02.at\
|
||||
multiv03.at\
|
||||
multiv04.at\
|
||||
multiv05.at\
|
||||
old.at\
|
||||
options.at\
|
||||
options02.at\
|
||||
pipe.at\
|
||||
recurse.at\
|
||||
rename01.at\
|
||||
rename02.at\
|
||||
rename03.at\
|
||||
same-order01.at\
|
||||
same-order02.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\
|
||||
star/multi-fail.at\
|
||||
star/ustar-big-2g.at\
|
||||
star/ustar-big-8g.at\
|
||||
star/pax-big-10g.at
|
||||
|
||||
TESTSUITE = $(srcdir)/testsuite
|
||||
|
||||
AUTOTEST = $(AUTOM4TE) --language=autotest
|
||||
$(TESTSUITE): package.m4 $(TESTSUITE_AT)
|
||||
$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
atconfig: $(top_builddir)/config.status
|
||||
cd $(top_builddir) && ./config.status tests/$@
|
||||
|
||||
clean-local:
|
||||
test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
|
||||
|
||||
check-local: atconfig atlocal $(TESTSUITE)
|
||||
$(SHELL) $(TESTSUITE)
|
||||
|
||||
check-full:
|
||||
FULL_TEST=1 $(MAKE) check
|
||||
|
||||
#check_SCRIPTS = tar
|
||||
|
||||
# Run the test suite on the *installed* tree.
|
||||
installcheck-local:
|
||||
$(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
|
||||
|
||||
|
||||
## ------------ ##
|
||||
## genfile ##
|
||||
## ------------ ##
|
||||
|
||||
check_PROGRAMS = genfile
|
||||
|
||||
genfile_SOURCES = genfile.c argcv.c argcv.h
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../lib -I$(top_srcdir)/src
|
||||
|
||||
LDADD = ../lib/libtar.a $(LIBINTL)
|
||||
|
||||
mostlyclean:
|
||||
rm -rf tmp-*
|
||||
|
||||
$(TESTS): genfile mksparse
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
|
||||
LDADD = ../lib/libtar.a $(LIBINTL) $(LIB_CLOCK_GETTIME)
|
||||
|
||||
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
|
||||
46
tests/T-null.at
Normal file
46
tests/T-null.at
Normal file
@@ -0,0 +1,46 @@
|
||||
# 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])
|
||||
|
||||
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],
|
||||
[jeden\ndwa
|
||||
trzy
|
||||
],
|
||||
[tar: file-list: file name read contains nul character
|
||||
],[],[],[ustar]) # Testing one format is enough
|
||||
|
||||
AT_CLEANUP
|
||||
55
tests/after
55
tests/after
@@ -1,55 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Do common operations after a particular test.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
cd ..
|
||||
exec 1> /dev/null
|
||||
exec 2> /dev/null
|
||||
|
||||
compare() {
|
||||
eval tempfile=tmp-$$/std${1}
|
||||
eval echo \""\${$1}"\" | sed '$d' > ${tempfile}0
|
||||
|
||||
sedscript=tmp-$$/${1}.sed
|
||||
if eval test \".\${${1}_ignore}\" = .; then
|
||||
:
|
||||
else
|
||||
eval echo \"\${${1}_ignore}\" | sed 's,^.*$,/&/d,;' > $sedscript
|
||||
sed -f $sedscript ${tempfile} > ${tempfile}.1
|
||||
mv ${tempfile}.1 ${tempfile}
|
||||
fi
|
||||
|
||||
if eval test -z \"\${${1}_regex}\" ; then
|
||||
cmp -s ${tempfile}0 ${tempfile} || exit 1
|
||||
else
|
||||
awk '{print NR " " $0}' ${tempfile}0 > ${tempfile}.1
|
||||
awk '{print NR " " $0}' ${tempfile} | join ${tempfile}.1 - |
|
||||
while read NUM RE LINE
|
||||
do
|
||||
echo "$LINE" | grep -- "$RE" >/dev/null || exit 1
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
compare out
|
||||
compare err
|
||||
|
||||
rm -rf tmp-$$
|
||||
34
tests/append.at
Normal file
34
tests/append.at
Normal file
@@ -0,0 +1,34 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# 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 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([append])
|
||||
AT_KEYWORDS([append append00])
|
||||
|
||||
AT_TAR_CHECK([touch file1
|
||||
touch file2
|
||||
tar cf archive file1
|
||||
tar rf archive file2
|
||||
tar tf archive],
|
||||
[0],
|
||||
[file1
|
||||
file2
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
48
tests/append01.at
Normal file
48
tests/append01.at
Normal file
@@ -0,0 +1,48 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# 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 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.
|
||||
|
||||
# When decoding a header tar was assigning 0 to oldgnu_header.isextended,
|
||||
# which destroyed name prefix. When updating archive, modified prefix
|
||||
# could have been written to disk thus producing invalid archive member.
|
||||
# Reported by Adye, TJ (Tim), <T.J.Adye@rl.ac.uk>
|
||||
# References:
|
||||
# <7231C15EAC2F164CA6DC326D97493C8B36C25D@exchange35.fed.cclrc.ac.uk>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2005-02/msg00032.html
|
||||
|
||||
AT_SETUP([appending files with long names])
|
||||
AT_KEYWORDS([append append01])
|
||||
|
||||
m4_define([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_appending_long_file_names_that_run_into_a_limit_of_the_ustar_tarX])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir PREFIX
|
||||
touch PREFIX/file1 PREFIX/file2
|
||||
tar cf archive PREFIX/file1
|
||||
tar rf archive PREFIX/file2
|
||||
tar tf archive
|
||||
],
|
||||
[0],
|
||||
[PREFIX/file1
|
||||
PREFIX/file2
|
||||
],
|
||||
[],[],[],[oldgnu, ustar, posix, gnu])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
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
|
||||
33
tests/atlocal.in
Normal file
33
tests/atlocal.in
Normal file
@@ -0,0 +1,33 @@
|
||||
# @configure_input@ -*- shell-script -*-
|
||||
# Configurable variable values for tar test suite.
|
||||
# Copyright (C) 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
PATH=@abs_builddir@:@abs_top_builddir@/src:@abs_top_srcdir@/build-aux:$top_srcdir:$srcdir:$PATH
|
||||
|
||||
XFAILFILE=$abs_builddir/.badversion
|
||||
|
||||
trap "test -r $XFAILFILE && cat $XFAILFILE; exit $?" 1 2 13 15
|
||||
|
||||
TEST_DATA_URL=ftp://download.gnu.org.ua/pub/tests/tar
|
||||
if test -z "$TEST_DATA_DIR"; then
|
||||
TEST_DATA_DIR=$abs_builddir
|
||||
fi
|
||||
|
||||
STAR_DATA_URL=http://download.berlios.de/pub/star/testscripts
|
||||
if test -z "$STAR_TESTSCRIPTS"; then
|
||||
STAR_TESTSCRIPTS=$TEST_DATA_DIR
|
||||
fi
|
||||
|
||||
# tarball_prereq file sum dir url
|
||||
tarball_prereq() {
|
||||
if test -d "$3"; then
|
||||
if test -r $3/$1; then
|
||||
:
|
||||
elif test -n "$FULL_TEST"; then
|
||||
wget -q --directory-prefix=$3 $4/$1
|
||||
fi
|
||||
fi
|
||||
echo "$2 $3/$1" | md5sum --status --check - >/dev/null 2>&1
|
||||
}
|
||||
|
||||
|
||||
53
tests/before
53
tests/before
@@ -1,53 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Do common operations before a particular test.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
case $# in
|
||||
0) TAR_ARCHIVE_FORMATS="${TAR_ARCHIVE_FORMATS:-v7 oldgnu ustar posix gnu}"
|
||||
for format in $TAR_ARCHIVE_FORMATS
|
||||
do
|
||||
$0 $format
|
||||
R=$?
|
||||
test $R -eq 0 || exit $R
|
||||
done
|
||||
exit 0;;
|
||||
1) if test "x$1" = xauto; then
|
||||
TAR_OPTIONS=
|
||||
else
|
||||
TAR_OPTIONS="--format=$1"
|
||||
fi;;
|
||||
*) echo "Too many arguments" >&2
|
||||
exit 2;;
|
||||
esac
|
||||
|
||||
mkdir tmp-$$
|
||||
cd tmp-$$
|
||||
|
||||
out=
|
||||
err=
|
||||
|
||||
export TAR_OPTIONS
|
||||
#echo "$0 $1"
|
||||
echo "$0 $1" > checking
|
||||
exec 1> stdout
|
||||
exec 2> stderr
|
||||
|
||||
|
||||
73
tests/chtype.at
Normal file
73
tests/chtype.at
Normal file
@@ -0,0 +1,73 @@
|
||||
# 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.
|
||||
|
||||
# Description: Incremental restore malfunctions if an archive member
|
||||
# changes type before restoration, e.g. from directory to file or vice
|
||||
# versa.
|
||||
# Reported by: Wolfram Kleff <bugreport@wkleff.intergenia.de>
|
||||
# References: <200605101232.25031.bugreport@wkleff.intergenia.de>
|
||||
|
||||
AT_SETUP([changed file types in incrementals])
|
||||
AT_KEYWORDS([incremental chtype])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_SORT_PREREQ
|
||||
AT_TAR_MKHIER([directory/b/c],[x])
|
||||
mkdir directory/a
|
||||
genfile --file directory/a/a
|
||||
|
||||
echo First backup
|
||||
tar --create --file=archive.1 --listed-incremental=db.1 directory
|
||||
|
||||
sleep 2
|
||||
|
||||
# Remove directory b and create a file with this name.
|
||||
# Previous versions were not able to restore over this file.
|
||||
rm -r directory/b
|
||||
genfile --file directory/b
|
||||
genfile --file directory/a/b
|
||||
|
||||
echo Second backup
|
||||
tar --create --file=archive.2 --listed-incremental=db.2 directory
|
||||
|
||||
# Delete a
|
||||
rm -r directory
|
||||
|
||||
echo Restore archive.1
|
||||
tar -xf archive.1 --listed-incremental=/dev/null
|
||||
echo Restore archive.2
|
||||
tar -xf archive.2 --listed-incremental=/dev/null
|
||||
find directory | sort
|
||||
],
|
||||
[0],
|
||||
[First backup
|
||||
Second backup
|
||||
Restore archive.1
|
||||
Restore archive.2
|
||||
directory
|
||||
directory/a
|
||||
directory/a/a
|
||||
directory/a/b
|
||||
directory/b
|
||||
],[],[],[],[gnu, oldgnu, posix])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
# End of chtype.at
|
||||
41
tests/comprec.at
Normal file
41
tests/comprec.at
Normal file
@@ -0,0 +1,41 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# 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 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([compressed format recognition])
|
||||
|
||||
AT_KEYWORDS([comprec])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
AT_GZIP_PREREQ
|
||||
genfile --length 10240 --file file1
|
||||
echo "separator"
|
||||
tar cfz archive file1
|
||||
echo "separator"
|
||||
mv file1 orig
|
||||
tar xfv archive
|
||||
cmp orig file1
|
||||
],
|
||||
[0],
|
||||
[separator
|
||||
separator
|
||||
file1
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
41
tests/delete01.sh → tests/delete01.at
Executable file → Normal file
41
tests/delete01.sh → tests/delete01.at
Executable file → Normal file
@@ -1,37 +1,36 @@
|
||||
#! /bin/sh
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Deleting a member after a big one was destroying the archive.
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
. ./preset
|
||||
. $srcdir/before
|
||||
# Deleting a member after a big one was destroying the archive.
|
||||
|
||||
set -e
|
||||
genfile -l 50000 > file1
|
||||
genfile -l 1024 > file2
|
||||
AT_SETUP([deleting a member after a big one])
|
||||
AT_KEYWORDS([delete delete01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile -l 50000 --file file1
|
||||
genfile -l 1024 --file file2
|
||||
tar cf archive file1 file2
|
||||
tar f archive --delete file2
|
||||
tar tf archive
|
||||
tar tf archive],
|
||||
[0],
|
||||
[file1
|
||||
])
|
||||
|
||||
out="\
|
||||
file1
|
||||
"
|
||||
|
||||
. $srcdir/after
|
||||
AT_CLEANUP
|
||||
43
tests/delete02.sh → tests/delete02.at
Executable file → Normal file
43
tests/delete02.sh → tests/delete02.at
Executable file → Normal file
@@ -1,45 +1,44 @@
|
||||
#! /bin/sh
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Deleting a member with the archive from stdin was not working correctly.
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
. ./preset
|
||||
. $srcdir/before
|
||||
# Deleting a member with the archive from stdin was not working correctly.
|
||||
|
||||
set -e
|
||||
genfile -l 3073 -p zeros > 1
|
||||
AT_SETUP([deleting a member from stdin archive])
|
||||
AT_KEYWORDS([delete delete02])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile -l 3073 -p zeros --file 1
|
||||
cp 1 2
|
||||
cp 2 3
|
||||
tar cf archive 1 2 3
|
||||
tar tf archive
|
||||
cat archive | tar f - --delete 2 > archive2
|
||||
echo -----
|
||||
tar tf archive2
|
||||
|
||||
out="\
|
||||
1
|
||||
echo separator
|
||||
tar tf archive2],
|
||||
[0],
|
||||
[1
|
||||
2
|
||||
3
|
||||
-----
|
||||
separator
|
||||
1
|
||||
3
|
||||
"
|
||||
])
|
||||
|
||||
. $srcdir/after
|
||||
AT_CLEANUP
|
||||
48
tests/delete03.at
Normal file
48
tests/delete03.at
Normal file
@@ -0,0 +1,48 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# 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 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([deleting members with long names])
|
||||
AT_KEYWORDS([delete delete03])
|
||||
|
||||
m4_define([PREFIX],[This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_file_names_that_run_into_a_limit_of_the_posix_tar_formatXX])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
|
||||
prefix=PREFIX
|
||||
rm -f $prefix*
|
||||
for i in 1 2 3 4 5 6 7 8 9
|
||||
do touch $prefix$i
|
||||
done
|
||||
tar -cf archive ./$prefix* &&
|
||||
tar --delete -f archive ./${prefix}5 &&
|
||||
tar -tf archive
|
||||
],
|
||||
[0],
|
||||
[./PREFIX[]1
|
||||
./PREFIX[]2
|
||||
./PREFIX[]3
|
||||
./PREFIX[]4
|
||||
./PREFIX[]6
|
||||
./PREFIX[]7
|
||||
./PREFIX[]8
|
||||
./PREFIX[]9
|
||||
],[],[],[],[gnu, oldgnu, posix])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -1,46 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Deleting members with long file names.
|
||||
|
||||
# Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
. ./preset
|
||||
TAR_ARCHIVE_FORMATS="gnu oldgnu posix"
|
||||
. $srcdir/before
|
||||
|
||||
set -e
|
||||
prefix=This_is_a_very_long_file_name_prefix_that_is_designed_to_cause_problems_with_file_names_that_run_into_a_limit_of_the_posix_tar_formatXX
|
||||
rm -f $prefix*
|
||||
for i in 1 2 3 4 5 6 7 8 9
|
||||
do touch $prefix$i
|
||||
done
|
||||
tar -cf archive ./$prefix*
|
||||
tar --delete -f archive ./${prefix}5
|
||||
tar -tf archive
|
||||
|
||||
out="\
|
||||
./${prefix}1
|
||||
./${prefix}2
|
||||
./${prefix}3
|
||||
./${prefix}4
|
||||
./${prefix}6
|
||||
./${prefix}7
|
||||
./${prefix}8
|
||||
./${prefix}9
|
||||
"
|
||||
|
||||
. $srcdir/after
|
||||
56
tests/delete04.sh → tests/delete04.at
Executable file → Normal file
56
tests/delete04.sh → tests/delete04.at
Executable file → Normal file
@@ -1,45 +1,45 @@
|
||||
#! /bin/sh
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Deleting a large last member was destroying earlier members.
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
. ./preset
|
||||
. $srcdir/before
|
||||
# Deleting a large last member was destroying earlier members.
|
||||
|
||||
set -e
|
||||
genfile -l 3 >file1
|
||||
genfile -l 5 >file2
|
||||
genfile -l 3 >file3
|
||||
genfile -l 6 >file4
|
||||
genfile -l 24 >file5
|
||||
genfile -l 13 >file6
|
||||
genfile -l 1385 >file7
|
||||
genfile -l 30 >file8
|
||||
genfile -l 10 >file9
|
||||
genfile -l 256000 >file10
|
||||
AT_SETUP([deleting a large last member])
|
||||
AT_KEYWORDS([delete delete04])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile -l 3 -f file1
|
||||
genfile -l 5 -f file2
|
||||
genfile -l 3 -f file3
|
||||
genfile -l 6 -f file4
|
||||
genfile -l 24 -f file5
|
||||
genfile -l 13 -f file6
|
||||
genfile -l 1385 -f file7
|
||||
genfile -l 30 -f file8
|
||||
genfile -l 10 -f file9
|
||||
genfile -l 256000 -f file10
|
||||
tar cf archive file1 file2 file3 file4 file5 file6 file7 file8 file9 file10
|
||||
tar f archive --delete file10
|
||||
tar tf archive
|
||||
|
||||
out="\
|
||||
file1
|
||||
],
|
||||
[0],
|
||||
[file1
|
||||
file2
|
||||
file3
|
||||
file4
|
||||
@@ -48,6 +48,6 @@ file6
|
||||
file7
|
||||
file8
|
||||
file9
|
||||
"
|
||||
])
|
||||
|
||||
. $srcdir/after
|
||||
AT_CLEANUP
|
||||
48
tests/delete05.at
Normal file
48
tests/delete05.at
Normal file
@@ -0,0 +1,48 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# 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 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.
|
||||
|
||||
# When attempted to delete a non-existing member, tar used to destroy
|
||||
# last blocking_factor blocks.
|
||||
# References:
|
||||
# <Pine.LNX.4.10.10412160956460.30933-100000@electra.znyx.com>
|
||||
# http://lists.gnu.org/archive/html/bug-tar/2004-12/msg00016.html
|
||||
|
||||
AT_SETUP([deleting non-existing member])
|
||||
AT_KEYWORDS([delete delete05])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
genfile -l 1024 -f en
|
||||
genfile -l 1024 -f to
|
||||
|
||||
tar cf archive en to
|
||||
# Make sure we don't use bogus blocking factor.
|
||||
# GNU tar up to and including 1.14.91 produced an empty archive this way:
|
||||
tar --file archive --blocking-factor=20 --delete tre
|
||||
tar tf archive
|
||||
],
|
||||
[0],
|
||||
[en
|
||||
to
|
||||
],
|
||||
[tar: tre: Not found in archive
|
||||
tar: Error exit delayed from previous errors
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
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
|
||||
29
tests/extrac01.sh → tests/extrac01.at
Executable file → Normal file
29
tests/extrac01.sh → tests/extrac01.at
Executable file → Normal file
@@ -1,32 +1,33 @@
|
||||
#! /bin/sh
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# There was a diagnostic when directory already exists.
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
. ./preset
|
||||
. $srcdir/before
|
||||
# There was a diagnostic when directory already exists.
|
||||
|
||||
set -e
|
||||
AT_SETUP([extract over an existing directory])
|
||||
AT_KEYWORDS([extract extract01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir directory
|
||||
touch directory/file
|
||||
tar cf archive directory || exit 1
|
||||
tar xf archive || exit 1
|
||||
])
|
||||
|
||||
. $srcdir/after
|
||||
AT_CLEANUP
|
||||
31
tests/extrac02.sh → tests/extrac02.at
Executable file → Normal file
31
tests/extrac02.sh → tests/extrac02.at
Executable file → Normal file
@@ -1,34 +1,37 @@
|
||||
#! /bin/sh
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Could not extract symlinks over an existing file.
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
. ./preset
|
||||
. $srcdir/before
|
||||
# Could not extract symlinks over an existing file.
|
||||
|
||||
set -e
|
||||
AT_SETUP([extracting symlinks over an existing file])
|
||||
AT_KEYWORDS([extract extract02 symlink])
|
||||
|
||||
# FIXME: Skip if symlinks are not supported on the system
|
||||
|
||||
AT_TAR_CHECK([
|
||||
touch file
|
||||
ln -s file link 2> /dev/null || ln file link
|
||||
tar cf archive link
|
||||
rm link
|
||||
touch link
|
||||
tar xf archive
|
||||
])
|
||||
|
||||
. $srcdir/after
|
||||
AT_CLEANUP
|
||||
41
tests/extrac03.sh → tests/extrac03.at
Executable file → Normal file
41
tests/extrac03.sh → tests/extrac03.at
Executable file → Normal file
@@ -1,38 +1,37 @@
|
||||
#! /bin/sh
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Paths going up and down were inducing extraction loops.
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
# This file is part of GNU tar testsuite.
|
||||
# Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
. ./preset
|
||||
. $srcdir/before
|
||||
# Paths going up and down were inducing extraction loops.
|
||||
|
||||
set -e
|
||||
AT_SETUP([extraction loops])
|
||||
AT_KEYWORDS([extract extract03])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
mkdir directory
|
||||
tar -cPvf archive directory/../directory
|
||||
echo -----
|
||||
tar -xPvf archive
|
||||
|
||||
out="\
|
||||
echo separator
|
||||
tar -xPvf archive],
|
||||
[0],
|
||||
[directory/../directory/
|
||||
separator
|
||||
directory/../directory/
|
||||
-----
|
||||
directory/../directory/
|
||||
"
|
||||
])
|
||||
|
||||
. $srcdir/after
|
||||
AT_CLEANUP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user