mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-24 23:05:52 -04:00
Compare commits
2910 Commits
v2.6.2
...
v3.0.0pre2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44ae628c59 | ||
|
|
44a7ba4587 | ||
|
|
44c4492acf | ||
|
|
609e6dda6b | ||
|
|
3f30927214 | ||
|
|
ae11e4ee2d | ||
|
|
b61665d5b6 | ||
|
|
38943d29d3 | ||
|
|
ff0284ddc4 | ||
|
|
3f65576881 | ||
|
|
3caf40356d | ||
|
|
26bbb6aa4b | ||
|
|
bf66c2da14 | ||
|
|
65f6b6b0ef | ||
|
|
983f647c7e | ||
|
|
14dfad3873 | ||
|
|
215465713b | ||
|
|
6be5ac61bd | ||
|
|
90c71caeb3 | ||
|
|
d46b5646c6 | ||
|
|
da564b51a1 | ||
|
|
f89617f7f2 | ||
|
|
0f8984ed78 | ||
|
|
306847ea67 | ||
|
|
d4eba300c9 | ||
|
|
dd589118d0 | ||
|
|
f92e15efd5 | ||
|
|
4f3c1df6c3 | ||
|
|
eb8f5c74e1 | ||
|
|
a960239f39 | ||
|
|
5621e5105a | ||
|
|
a1d2685b08 | ||
|
|
0f6b4909db | ||
|
|
b0ca7d2500 | ||
|
|
7ed6bc53b9 | ||
|
|
f57ab2f718 | ||
|
|
5ebb7935d2 | ||
|
|
c50a9076e1 | ||
|
|
d417c51669 | ||
|
|
5b934f5133 | ||
|
|
49ea69b3ff | ||
|
|
578219bed5 | ||
|
|
2e4a3d17b4 | ||
|
|
b4b24520f6 | ||
|
|
13710874ce | ||
|
|
7341ee2dfd | ||
|
|
e0cfd15bcc | ||
|
|
5a47354882 | ||
|
|
f5b532b144 | ||
|
|
c0dba635ba | ||
|
|
e1ac7791fe | ||
|
|
5b3f6a2730 | ||
|
|
f203266889 | ||
|
|
21914d8135 | ||
|
|
200aec7db4 | ||
|
|
a15c4b38b5 | ||
|
|
40e383765a | ||
|
|
5441088298 | ||
|
|
d0a6cdb62e | ||
|
|
19531e1f74 | ||
|
|
6f0805f564 | ||
|
|
6191429b50 | ||
|
|
89b76bac1f | ||
|
|
0758b2db30 | ||
|
|
74db1f1498 | ||
|
|
4f802c6637 | ||
|
|
33a04593ee | ||
|
|
6303f9a25f | ||
|
|
3932c42373 | ||
|
|
bc5df0f4e6 | ||
|
|
4b163f00c2 | ||
|
|
f07992739a | ||
|
|
c605c2cdbd | ||
|
|
1b42f628f4 | ||
|
|
5dafe360de | ||
|
|
6619d5fcc1 | ||
|
|
b960483e99 | ||
|
|
dd4a039515 | ||
|
|
229554084d | ||
|
|
4a1edb63dd | ||
|
|
3170b20967 | ||
|
|
d34cd639fc | ||
|
|
236df01b15 | ||
|
|
21cafc50cc | ||
|
|
de80679b67 | ||
|
|
27999abab4 | ||
|
|
82f37486a1 | ||
|
|
7820fa949f | ||
|
|
2ac9793064 | ||
|
|
a4453606cc | ||
|
|
71605b0f4d | ||
|
|
ba525f770c | ||
|
|
2509753fd3 | ||
|
|
5688c74d25 | ||
|
|
2ac081ff60 | ||
|
|
5d3e5f641d | ||
|
|
a0f29ed824 | ||
|
|
0b515981fc | ||
|
|
2e8259bb0b | ||
|
|
d274524317 | ||
|
|
71845bd2a0 | ||
|
|
bdd53557a8 | ||
|
|
d6ca255c21 | ||
|
|
2dc7b91dd2 | ||
|
|
288b12eefe | ||
|
|
f7d6dce6c8 | ||
|
|
48a481c4d0 | ||
|
|
8db8eacbdd | ||
|
|
e8e9e12c3a | ||
|
|
6e6daf5ac6 | ||
|
|
e73eed8563 | ||
|
|
da1319128a | ||
|
|
f2179fd370 | ||
|
|
969cdffbea | ||
|
|
3b7bcaaf34 | ||
|
|
4abe379c05 | ||
|
|
c980db5f08 | ||
|
|
c35d6e3522 | ||
|
|
044dc29307 | ||
|
|
7a4addaa74 | ||
|
|
f7e5068d94 | ||
|
|
67b8f3dfe7 | ||
|
|
95a44066da | ||
|
|
7909e65f83 | ||
|
|
f74a3d813b | ||
|
|
ac59386027 | ||
|
|
73a649b7cb | ||
|
|
9b49704959 | ||
|
|
ffbffc647b | ||
|
|
968061bb65 | ||
|
|
c47e3ee1b6 | ||
|
|
549a3efbb7 | ||
|
|
accf8d12bc | ||
|
|
0eeb9f5481 | ||
|
|
7b46e30fd4 | ||
|
|
35c8fd761f | ||
|
|
ba2d43d702 | ||
|
|
29349024c4 | ||
|
|
d108e04f38 | ||
|
|
d4d6646aae | ||
|
|
cf2d26656d | ||
|
|
7918f24405 | ||
|
|
9544261a45 | ||
|
|
354c9da60d | ||
|
|
626065702f | ||
|
|
9863bdbc93 | ||
|
|
83135e8f6a | ||
|
|
369233927c | ||
|
|
7e4b6b7bc4 | ||
|
|
a2dc4d687b | ||
|
|
a4431563e8 | ||
|
|
fbd91cae0c | ||
|
|
eb7a6e09cb | ||
|
|
9889a34bf2 | ||
|
|
8e1e60e98f | ||
|
|
f9998046a3 | ||
|
|
07bbf8703f | ||
|
|
77502cbade | ||
|
|
936fa865e1 | ||
|
|
2f188c8d96 | ||
|
|
83f5394810 | ||
|
|
24d677fc16 | ||
|
|
65a22a5ff7 | ||
|
|
a0f70237f5 | ||
|
|
4eff3051a0 | ||
|
|
e208631a5b | ||
|
|
b553a3dd20 | ||
|
|
e5f1a96ff8 | ||
|
|
eb7e7b2499 | ||
|
|
3caafdfd2f | ||
|
|
26ac181223 | ||
|
|
7fa60281bf | ||
|
|
73f2fa8189 | ||
|
|
75f162e46f | ||
|
|
1d2ca00703 | ||
|
|
4d91a5f8f4 | ||
|
|
61cb031ca4 | ||
|
|
ff0c27c926 | ||
|
|
d1d0a7051f | ||
|
|
444f9f7b04 | ||
|
|
411c04f06f | ||
|
|
5d935dce63 | ||
|
|
b88f6fe7e5 | ||
|
|
e6109f496c | ||
|
|
836ce36a4f | ||
|
|
35da2ec35a | ||
|
|
7b9598b2d5 | ||
|
|
4a4622bbe5 | ||
|
|
c9ec460807 | ||
|
|
79cd0c7fa4 | ||
|
|
de8c8b28c0 | ||
|
|
569e6f432b | ||
|
|
0d585188f9 | ||
|
|
34ca58d440 | ||
|
|
9c528e2935 | ||
|
|
2b967218eb | ||
|
|
6e058b4b60 | ||
|
|
b1e436ec17 | ||
|
|
4319cc56d8 | ||
|
|
952ae75138 | ||
|
|
4d745d3cf5 | ||
|
|
8798be8e63 | ||
|
|
42b06481c3 | ||
|
|
dbe287b701 | ||
|
|
8e3b627d07 | ||
|
|
809724d7e2 | ||
|
|
8e41b68e8f | ||
|
|
dc77edf218 | ||
|
|
65ba6af61b | ||
|
|
83d5e90054 | ||
|
|
e434f0ebfe | ||
|
|
a08979d564 | ||
|
|
252af65bb4 | ||
|
|
d048c2f225 | ||
|
|
9b9d5f89b3 | ||
|
|
e5bf3b5855 | ||
|
|
6755a7d742 | ||
|
|
5459e693a3 | ||
|
|
24108eb854 | ||
|
|
4635fb9995 | ||
|
|
9decb4d2ef | ||
|
|
b3b326016a | ||
|
|
4bde45f60e | ||
|
|
4fd842f98d | ||
|
|
f92f5b166e | ||
|
|
9b25ef35bd | ||
|
|
7c73536c25 | ||
|
|
33cbd577ad | ||
|
|
524eaa8245 | ||
|
|
9742b386b3 | ||
|
|
8b498b9f1a | ||
|
|
c04af69701 | ||
|
|
f87fb190b3 | ||
|
|
a21e72c3e6 | ||
|
|
1c4ffe64db | ||
|
|
abdcb21a7a | ||
|
|
f5ba7bfbb6 | ||
|
|
676e604135 | ||
|
|
3fac8ca8d1 | ||
|
|
33766a8daa | ||
|
|
e3d27df444 | ||
|
|
6aa27a7ce5 | ||
|
|
47cffb77de | ||
|
|
565a340b0a | ||
|
|
f45b64d8dd | ||
|
|
56ce72c447 | ||
|
|
898fab2577 | ||
|
|
0e5dd89866 | ||
|
|
79028af116 | ||
|
|
a572e12675 | ||
|
|
c8e8394615 | ||
|
|
8487f9cf29 | ||
|
|
d750be6ad8 | ||
|
|
0bb8616535 | ||
|
|
1faa1a6da9 | ||
|
|
b5ae4e25c2 | ||
|
|
3d0a159d96 | ||
|
|
8ea07c0030 | ||
|
|
59fd2a5e7d | ||
|
|
ae87c43452 | ||
|
|
f1599b9ef2 | ||
|
|
ee83e1bd4d | ||
|
|
7455467c17 | ||
|
|
19395697b9 | ||
|
|
7787579ad4 | ||
|
|
58a37ed34a | ||
|
|
fe8d61e5d5 | ||
|
|
87b0cc726b | ||
|
|
4504b2259f | ||
|
|
cf1b4969b9 | ||
|
|
434e77193c | ||
|
|
858d45f160 | ||
|
|
63186ec077 | ||
|
|
dfcb386569 | ||
|
|
d15f2ff0cf | ||
|
|
c395acd804 | ||
|
|
030820d5dc | ||
|
|
043ef55b22 | ||
|
|
a30dcbc0a8 | ||
|
|
02f0227e87 | ||
|
|
142a5e7b8b | ||
|
|
fdfc67406c | ||
|
|
fb7b9ddcb1 | ||
|
|
4ade505c7e | ||
|
|
1564cd5a87 | ||
|
|
33233b4900 | ||
|
|
d6b422a61c | ||
|
|
ff2001b91b | ||
|
|
d858b27400 | ||
|
|
1874f7e2e1 | ||
|
|
377d22ab9f | ||
|
|
4f3797c7e2 | ||
|
|
6b5a8f80fc | ||
|
|
bf10faa9dc | ||
|
|
548ca46fec | ||
|
|
e8c64ffdc7 | ||
|
|
0eb05245f1 | ||
|
|
0156c7842d | ||
|
|
1acb8f5119 | ||
|
|
76e754a0fd | ||
|
|
e7f905accb | ||
|
|
a9a8bc962c | ||
|
|
a6e7b97868 | ||
|
|
1befb74b13 | ||
|
|
8f3335a18c | ||
|
|
505c0579f7 | ||
|
|
a430691df1 | ||
|
|
332cf6df7c | ||
|
|
3f7afe7ec1 | ||
|
|
8fc4033ef0 | ||
|
|
ef35abb2b7 | ||
|
|
0b68d6b6f4 | ||
|
|
f1271537a4 | ||
|
|
b13505da1d | ||
|
|
7ea6ea98c8 | ||
|
|
d1798a2fda | ||
|
|
e911ff75d6 | ||
|
|
49f7162e7d | ||
|
|
3bb88b4388 | ||
|
|
b3fbe3ce35 | ||
|
|
9557eabaa7 | ||
|
|
acac1f5c6f | ||
|
|
3427355422 | ||
|
|
cbf626fd62 | ||
|
|
1c702303eb | ||
|
|
9a234269ed | ||
|
|
db9c9e2766 | ||
|
|
9439c0cb5a | ||
|
|
2ed790f354 | ||
|
|
486f8cd1ab | ||
|
|
875a13b42c | ||
|
|
719522b9bd | ||
|
|
753849fdbc | ||
|
|
bb25779de7 | ||
|
|
348d54d6d1 | ||
|
|
4471d9e570 | ||
|
|
19d4cac996 | ||
|
|
e4c877cf70 | ||
|
|
f14b3ef430 | ||
|
|
f3c93b1761 | ||
|
|
a72ba0cfac | ||
|
|
ba59bd68fc | ||
|
|
1c60d21947 | ||
|
|
473feecff3 | ||
|
|
351e23ad8e | ||
|
|
f31514adb7 | ||
|
|
2fcc265c2f | ||
|
|
b58e40332f | ||
|
|
a217c45359 | ||
|
|
764782662d | ||
|
|
4b24f4a2b5 | ||
|
|
c64ff141b8 | ||
|
|
1b896f8d1e | ||
|
|
01894cf01f | ||
|
|
16edf86595 | ||
|
|
1c53e5171c | ||
|
|
63d83e9477 | ||
|
|
5463453489 | ||
|
|
108133689d | ||
|
|
46ad63b7cf | ||
|
|
dbb20f6bc0 | ||
|
|
25c2a6ac0e | ||
|
|
161fba6903 | ||
|
|
55edf18c42 | ||
|
|
a0456b9c46 | ||
|
|
1a515b494b | ||
|
|
33cd9ad54b | ||
|
|
896f046f79 | ||
|
|
b9d5eea5c6 | ||
|
|
5275029d11 | ||
|
|
271aeaa49e | ||
|
|
91763a9c2f | ||
|
|
18438f0bac | ||
|
|
057f649fc9 | ||
|
|
88467ec444 | ||
|
|
1b897d50a9 | ||
|
|
d4a013edb7 | ||
|
|
545584cb9a | ||
|
|
e5abce8e0d | ||
|
|
3060ca8d42 | ||
|
|
ab14d01a0e | ||
|
|
987838fd2c | ||
|
|
6d4e718f5f | ||
|
|
1c3344a105 | ||
|
|
085e2fd588 | ||
|
|
f41152d393 | ||
|
|
d0c59b0e88 | ||
|
|
f49c837651 | ||
|
|
c12895089c | ||
|
|
27122338dc | ||
|
|
d762dfe94b | ||
|
|
c4750c2a07 | ||
|
|
3831f06319 | ||
|
|
be91bd81b8 | ||
|
|
2a40b503c0 | ||
|
|
ba2133d6ad | ||
|
|
4f47fec04d | ||
|
|
ab3d6c6025 | ||
|
|
121bfb2b4d | ||
|
|
100018b7cd | ||
|
|
1ff66d4c68 | ||
|
|
87a34ce56a | ||
|
|
04c722d5e0 | ||
|
|
7730114b30 | ||
|
|
7a2fa0c2d3 | ||
|
|
4eeaa16253 | ||
|
|
8dca155fca | ||
|
|
2a5df86299 | ||
|
|
3ea6e0e7a1 | ||
|
|
051ad69634 | ||
|
|
744e63fb2a | ||
|
|
cc7b86bf9b | ||
|
|
8c18ebe81d | ||
|
|
33689f4803 | ||
|
|
424d369179 | ||
|
|
d0221f1d2b | ||
|
|
3be97bf931 | ||
|
|
4afab31607 | ||
|
|
be21e29c35 | ||
|
|
c5b6e57a13 | ||
|
|
ca947dea3e | ||
|
|
2aea85ab54 | ||
|
|
05a41409b1 | ||
|
|
7a28d18448 | ||
|
|
1e05b590c4 | ||
|
|
ce5fddc3ed | ||
|
|
fd3f5af2aa | ||
|
|
dde5b77226 | ||
|
|
f845ef7dec | ||
|
|
9ae7a2cddb | ||
|
|
8a65e0ce00 | ||
|
|
98b1689dcb | ||
|
|
012d1a01f5 | ||
|
|
d9f46544a3 | ||
|
|
42c6b13901 | ||
|
|
f1482c3391 | ||
|
|
5bb7348509 | ||
|
|
4c9d5fef07 | ||
|
|
5607803376 | ||
|
|
76e0a49efe | ||
|
|
76a1013cc6 | ||
|
|
496c809f8c | ||
|
|
3ac830b9f9 | ||
|
|
f3d6d4800b | ||
|
|
8ef246e0b5 | ||
|
|
c7e6f84f89 | ||
|
|
fe04532ad2 | ||
|
|
e4b619b46d | ||
|
|
9ec3828b03 | ||
|
|
e0e3203156 | ||
|
|
edb977215b | ||
|
|
18233a170e | ||
|
|
283887d777 | ||
|
|
c2f0e4d965 | ||
|
|
8576397c3e | ||
|
|
c09af06d0c | ||
|
|
ded73ed90f | ||
|
|
f335eb1f83 | ||
|
|
7afa34fd27 | ||
|
|
1f56188f8c | ||
|
|
3162ea6f67 | ||
|
|
327c559aff | ||
|
|
99effefc81 | ||
|
|
e8dad39518 | ||
|
|
09a54c399c | ||
|
|
9586e59370 | ||
|
|
ce455b03e7 | ||
|
|
a39da29ac5 | ||
|
|
794a0b6c25 | ||
|
|
1b81f797a2 | ||
|
|
889ae39d7a | ||
|
|
5f4e991c70 | ||
|
|
c96f6eb584 | ||
|
|
e10664c5e8 | ||
|
|
99a957d3f4 | ||
|
|
658a63694b | ||
|
|
30e50494bb | ||
|
|
719985cb9c | ||
|
|
2d2414f39e | ||
|
|
edb4ba5fdb | ||
|
|
007996b40d | ||
|
|
dbd9ea3e5a | ||
|
|
2ef0340517 | ||
|
|
9d737ecb7a | ||
|
|
bd6edd3fa2 | ||
|
|
6eee13cf58 | ||
|
|
9602b5cfbd | ||
|
|
48ffc11e9c | ||
|
|
5a3e9ff608 | ||
|
|
aac5cab80b | ||
|
|
a3e18c763a | ||
|
|
403dbc1377 | ||
|
|
5b30412c68 | ||
|
|
d5833800a8 | ||
|
|
8d3a785fa5 | ||
|
|
3a5a7de6c9 | ||
|
|
c58c1dc446 | ||
|
|
eefe189e1d | ||
|
|
f05c801194 | ||
|
|
c905bf37f6 | ||
|
|
8cae71ebc3 | ||
|
|
14d776ff0c | ||
|
|
c7565dad84 | ||
|
|
b7cfb9e2c0 | ||
|
|
0d152437df | ||
|
|
6aef83c97d | ||
|
|
225aeca346 | ||
|
|
0a62f5f382 | ||
|
|
234844915e | ||
|
|
263d3bfb40 | ||
|
|
bf466c0f82 | ||
|
|
8b58407586 | ||
|
|
64119c792d | ||
|
|
8388e011ae | ||
|
|
0fddbd8a09 | ||
|
|
badb8c24b9 | ||
|
|
bfd3137246 | ||
|
|
6de0d06259 | ||
|
|
89d730a098 | ||
|
|
18979194cf | ||
|
|
aadc84d359 | ||
|
|
9d155ecd12 | ||
|
|
60af946576 | ||
|
|
ca0e8296bc | ||
|
|
c4a28da3ad | ||
|
|
20319fd9ed | ||
|
|
01d29d7b02 | ||
|
|
1183260426 | ||
|
|
07613def0a | ||
|
|
c2a608d9f1 | ||
|
|
49b86442ff | ||
|
|
4785cd43d1 | ||
|
|
e238c9977d | ||
|
|
b37b7c9949 | ||
|
|
f7d7fb381d | ||
|
|
3481bdf493 | ||
|
|
d365e22967 | ||
|
|
d02363609a | ||
|
|
1e1ca25343 | ||
|
|
a2ebbffca7 | ||
|
|
0395130c06 | ||
|
|
b8c167e804 | ||
|
|
17026f2741 | ||
|
|
112d728f48 | ||
|
|
96293cf991 | ||
|
|
f0fbf1d670 | ||
|
|
7a821d518b | ||
|
|
663b2857eb | ||
|
|
155d9206a4 | ||
|
|
6b2a3d5de6 | ||
|
|
82ad07c418 | ||
|
|
d144e43bb3 | ||
|
|
d2aee174e6 | ||
|
|
20f0d0f9b9 | ||
|
|
b675ba6f79 | ||
|
|
d1c178dd53 | ||
|
|
d619ff1376 | ||
|
|
db0f7613e1 | ||
|
|
45d8bfe09e | ||
|
|
d521e1c2a1 | ||
|
|
4ea4acf17b | ||
|
|
3a993aa4bf | ||
|
|
c7871d9892 | ||
|
|
482f48cca9 | ||
|
|
36e6594dce | ||
|
|
e17883827b | ||
|
|
37a4386d2c | ||
|
|
fd0a130c14 | ||
|
|
5e77efaf41 | ||
|
|
b0cacef14b | ||
|
|
b20830b338 | ||
|
|
c63625d41a | ||
|
|
7de7b49f6c | ||
|
|
d0d0e41fd2 | ||
|
|
2a28dd32fd | ||
|
|
65e83e097c | ||
|
|
4f37559232 | ||
|
|
604dbf6d94 | ||
|
|
53593085cf | ||
|
|
eb0144d79b | ||
|
|
54b0dfa0f7 | ||
|
|
264042760b | ||
|
|
1e999f9f1b | ||
|
|
f9b66bc464 | ||
|
|
60d465dbdd | ||
|
|
3ebdd3c7fc | ||
|
|
f0fa8c6df2 | ||
|
|
9d33e6f7cf | ||
|
|
4a19c3b254 | ||
|
|
4743f0f41b | ||
|
|
0abe148fd9 | ||
|
|
39411fa876 | ||
|
|
662fd70b54 | ||
|
|
cd87e2f59a | ||
|
|
2c70847654 | ||
|
|
eaf895e6ef | ||
|
|
149a78e33f | ||
|
|
88897638a9 | ||
|
|
c575f8ce87 | ||
|
|
5303941021 | ||
|
|
c0f1e57b51 | ||
|
|
ccdb23bb90 | ||
|
|
146c2c368c | ||
|
|
60cc01a6c6 | ||
|
|
f5761a342b | ||
|
|
caf8299e2e | ||
|
|
c6fadc0ee1 | ||
|
|
2dc3db2a3e | ||
|
|
771d0add8f | ||
|
|
e5e85283a9 | ||
|
|
21068d8e87 | ||
|
|
4d2ea5a838 | ||
|
|
9ba53f26a3 | ||
|
|
3aeedbfd11 | ||
|
|
989b0b8802 | ||
|
|
b2e4811db2 | ||
|
|
b467495cd0 | ||
|
|
3b8ed84245 | ||
|
|
3a72cc2929 | ||
|
|
c202424a03 | ||
|
|
083f75ee42 | ||
|
|
45760f5f05 | ||
|
|
116a4769c1 | ||
|
|
1e4f5f6342 | ||
|
|
a19d285ae3 | ||
|
|
564782ba95 | ||
|
|
2dc7b8bd0e | ||
|
|
e0930845ce | ||
|
|
cf81788366 | ||
|
|
89a0e3a927 | ||
|
|
a8facdc090 | ||
|
|
c5e29261f3 | ||
|
|
1acb2e15b4 | ||
|
|
06898c80d9 | ||
|
|
684576ff45 | ||
|
|
574a24a2ec | ||
|
|
9775d6ab66 | ||
|
|
2b916250d8 | ||
|
|
2955529bb4 | ||
|
|
d094b5eb3c | ||
|
|
bc93ee842f | ||
|
|
0c6d79528a | ||
|
|
556e03a3c9 | ||
|
|
e4887738bb | ||
|
|
0f5c1c193a | ||
|
|
ab6dcad61c | ||
|
|
b6855ddc9c | ||
|
|
0cbb958f34 | ||
|
|
418da6d952 | ||
|
|
51d133d686 | ||
|
|
cbb95d3d24 | ||
|
|
d9126a861f | ||
|
|
b4768a1397 | ||
|
|
47b032e97f | ||
|
|
50dfd5b4fe | ||
|
|
1de02c273d | ||
|
|
9ce7fc3887 | ||
|
|
dc1f7b9ea3 | ||
|
|
ee7cf95b13 | ||
|
|
492fc3536d | ||
|
|
5e61bdb4d5 | ||
|
|
f964ac5eee | ||
|
|
c55b39afad | ||
|
|
a27463a9a2 | ||
|
|
590eb6c02d | ||
|
|
0d7a6b4906 | ||
|
|
b4f0287197 | ||
|
|
8d6386809e | ||
|
|
230328a30a | ||
|
|
5819d6b14a | ||
|
|
7b4a40ed70 | ||
|
|
f210dcadf4 | ||
|
|
178a1d2048 | ||
|
|
a4b4e0770b | ||
|
|
2a6e35db31 | ||
|
|
e3794138d8 | ||
|
|
fdd10da6f7 | ||
|
|
5f12a07bff | ||
|
|
6a4a1d0cb0 | ||
|
|
434c40986d | ||
|
|
8ee6857702 | ||
|
|
721ddc903f | ||
|
|
154c345db0 | ||
|
|
25f637a334 | ||
|
|
2356d73bb4 | ||
|
|
4968423e71 | ||
|
|
99eba67585 | ||
|
|
5abe03d6e8 | ||
|
|
83078af5b0 | ||
|
|
185aa5b0e5 | ||
|
|
cabd60fdce | ||
|
|
10944395bf | ||
|
|
204f4f4d09 | ||
|
|
c9bce0b8f8 | ||
|
|
deee574b11 | ||
|
|
55410368e5 | ||
|
|
e4fdf1debe | ||
|
|
1580899c1d | ||
|
|
f863b76300 | ||
|
|
5e1ec06f09 | ||
|
|
36e2ea6068 | ||
|
|
f4164b73b4 | ||
|
|
9ef506a2b2 | ||
|
|
b1b54199ef | ||
|
|
33394b769d | ||
|
|
011e85a5e3 | ||
|
|
d5dcb6f775 | ||
|
|
0c25dedf31 | ||
|
|
6105464b79 | ||
|
|
4d51f0db79 | ||
|
|
ff530f04a0 | ||
|
|
e8b21fe406 | ||
|
|
71cb9df386 | ||
|
|
f97c2d4a9b | ||
|
|
b8a6dae038 | ||
|
|
969f7ed5b7 | ||
|
|
e825409a84 | ||
|
|
b8d29fd8e6 | ||
|
|
200f2d98db | ||
|
|
1a7f3d99c5 | ||
|
|
e80876700c | ||
|
|
ec55b4f2fb | ||
|
|
798cde474f | ||
|
|
558d482c47 | ||
|
|
418b6a2703 | ||
|
|
1ef5bf3cfd | ||
|
|
2a94207ad6 | ||
|
|
ddcba3f075 | ||
|
|
db3ae95cac | ||
|
|
1a05de2bff | ||
|
|
d9163a4cf5 | ||
|
|
44885a398f | ||
|
|
dfe1ed5e97 | ||
|
|
242f6052c2 | ||
|
|
519d55a950 | ||
|
|
b6008dc645 | ||
|
|
6f3684ffb5 | ||
|
|
615a5415c9 | ||
|
|
ba081be327 | ||
|
|
3e88414e4e | ||
|
|
0888952768 | ||
|
|
5dcd9a2b70 | ||
|
|
6ce9432d75 | ||
|
|
6c8507724b | ||
|
|
d04e95e968 | ||
|
|
b06050f9ad | ||
|
|
ad75d18d2e | ||
|
|
ed4b8da048 | ||
|
|
2cd421d809 | ||
|
|
ea0ea357f4 | ||
|
|
0480a946f5 | ||
|
|
67f8a41be5 | ||
|
|
5e1f082d0c | ||
|
|
a633351962 | ||
|
|
2edfe52230 | ||
|
|
acee1ad853 | ||
|
|
8f4ae68ca7 | ||
|
|
ff1b9344c9 | ||
|
|
a923437bc0 | ||
|
|
dde698c2e8 | ||
|
|
c2b47e31a5 | ||
|
|
4e0bf97716 | ||
|
|
174e51b5bf | ||
|
|
30cd7ec1cf | ||
|
|
48459ba15c | ||
|
|
48ecccce2d | ||
|
|
a739128df9 | ||
|
|
2c1775620a | ||
|
|
40f910c43a | ||
|
|
503114a782 | ||
|
|
71f9e4673e | ||
|
|
176e8e94c3 | ||
|
|
814b340c27 | ||
|
|
f167879035 | ||
|
|
4187572616 | ||
|
|
ff43d8b449 | ||
|
|
97bf86f8ee | ||
|
|
8c449e6285 | ||
|
|
29930a9fd2 | ||
|
|
c98ad3df96 | ||
|
|
9c3c30e5c7 | ||
|
|
b4a09b72ee | ||
|
|
5a3810b463 | ||
|
|
e8d97006e5 | ||
|
|
8adc22e362 | ||
|
|
dcebf78fe0 | ||
|
|
651c8510e8 | ||
|
|
1ed3f5ed61 | ||
|
|
70c81b0c07 | ||
|
|
47c1197534 | ||
|
|
fb41a3c669 | ||
|
|
2700069d5a | ||
|
|
044ccbaacf | ||
|
|
841d943651 | ||
|
|
04cd8789cb | ||
|
|
9578783a71 | ||
|
|
4cff5fa462 | ||
|
|
cc1b4f776a | ||
|
|
72d1b262ac | ||
|
|
6fb7cc38a2 | ||
|
|
8a7b8400e7 | ||
|
|
d2ab094dec | ||
|
|
ccd2966da9 | ||
|
|
6dc9b74bc6 | ||
|
|
04c841190f | ||
|
|
d20ce6e144 | ||
|
|
a7d461fccd | ||
|
|
4c5a2da65f | ||
|
|
caff33228e | ||
|
|
f38f6f80b7 | ||
|
|
e848e06618 | ||
|
|
eece5fe32c | ||
|
|
8590993185 | ||
|
|
b64ee91a41 | ||
|
|
d0133e6eba | ||
|
|
1925c3448c | ||
|
|
19b8587654 | ||
|
|
051f5df526 | ||
|
|
e525519509 | ||
|
|
4b90820d9f | ||
|
|
2873603ab5 | ||
|
|
ec52c3b9da | ||
|
|
10ae3406ee | ||
|
|
232658d9d3 | ||
|
|
c000002f46 | ||
|
|
2fedf3d596 | ||
|
|
887d745549 | ||
|
|
20f90d5e8a | ||
|
|
17bda2d109 | ||
|
|
b534351058 | ||
|
|
b3e4e7ef2e | ||
|
|
a3f6dbdf5c | ||
|
|
95ae5224b0 | ||
|
|
03dbc0b831 | ||
|
|
ffa8ab8eb5 | ||
|
|
a17e119d8b | ||
|
|
6bfc7b4d79 | ||
|
|
b3e8e7c79e | ||
|
|
bdd3a4fef5 | ||
|
|
a00f5a371e | ||
|
|
55c412630c | ||
|
|
778ee637ee | ||
|
|
80aff93b32 | ||
|
|
6721973e37 | ||
|
|
a2ed5801d3 | ||
|
|
15ce4b24fc | ||
|
|
c5260884d6 | ||
|
|
ea124cb324 | ||
|
|
13b597fa71 | ||
|
|
ecc7623e7f | ||
|
|
87c0f9d6b4 | ||
|
|
1cfcb8af11 | ||
|
|
56aaa4c44c | ||
|
|
4b6a7bd706 | ||
|
|
5bc933a285 | ||
|
|
01d124d9e2 | ||
|
|
58a06312a4 | ||
|
|
c2c8db9195 | ||
|
|
d1e6b0e225 | ||
|
|
8936367695 | ||
|
|
8517e9c10a | ||
|
|
fcecb70b1d | ||
|
|
582c1589f3 | ||
|
|
cb15269eb0 | ||
|
|
f47807900b | ||
|
|
40410a38bc | ||
|
|
6b54a688cf | ||
|
|
b59dc8d5ae | ||
|
|
45ba206a94 | ||
|
|
2220ec0a69 | ||
|
|
5fdbb87df8 | ||
|
|
f1c9bcd0fc | ||
|
|
3723548ded | ||
|
|
12ccc73ae7 | ||
|
|
ee8d9636d1 | ||
|
|
38de2866e5 | ||
|
|
bdac7621ee | ||
|
|
8ac4774675 | ||
|
|
229e1950ed | ||
|
|
93977bca10 | ||
|
|
c2a2147a5b | ||
|
|
73173af955 | ||
|
|
a2248aea2e | ||
|
|
a8167c6611 | ||
|
|
91f4b31fe1 | ||
|
|
cad8f6f980 | ||
|
|
d8bf7ea8e9 | ||
|
|
d8f28a663c | ||
|
|
2ae4126a9e | ||
|
|
6f1c2aab43 | ||
|
|
e71c1c26df | ||
|
|
b24498ec2c | ||
|
|
b2d4639543 | ||
|
|
d3ef985954 | ||
|
|
7c58c99184 | ||
|
|
ad77db8b71 | ||
|
|
e7c67065c0 | ||
|
|
0f78b81511 | ||
|
|
d051056f92 | ||
|
|
a4a38e8df0 | ||
|
|
60ef8ed128 | ||
|
|
8aa0dc7838 | ||
|
|
4177f09b83 | ||
|
|
acaadb55c1 | ||
|
|
b88c2e8ffe | ||
|
|
f4ea5f47dc | ||
|
|
62ae66d43b | ||
|
|
8641d28740 | ||
|
|
de3438407c | ||
|
|
434764269c | ||
|
|
ba212fe0b6 | ||
|
|
5f93b4d35e | ||
|
|
f8db4a8ab4 | ||
|
|
398612ba07 | ||
|
|
77b013afb5 | ||
|
|
08c0cd8a42 | ||
|
|
1c6e9dfabc | ||
|
|
0037bf23fc | ||
|
|
285edc9169 | ||
|
|
c4aa84ad50 | ||
|
|
b635bc92d1 | ||
|
|
146d2228cc | ||
|
|
b2501ccf12 | ||
|
|
e60bba3fbc | ||
|
|
e26cfccf16 | ||
|
|
74f80abce2 | ||
|
|
5899b8cf3e | ||
|
|
08e0a62956 | ||
|
|
2bd17a51ae | ||
|
|
c7b9ebb598 | ||
|
|
e3db43ffe5 | ||
|
|
f61ab01d96 | ||
|
|
ceca8ccac8 | ||
|
|
374c3e1278 | ||
|
|
e09d8a304c | ||
|
|
2a7d9fe9b8 | ||
|
|
e63aeb6d68 | ||
|
|
077d5d4ebc | ||
|
|
e2d774cdd7 | ||
|
|
415b598346 | ||
|
|
69627d66f8 | ||
|
|
ac98cd98e3 | ||
|
|
91d324b4ea | ||
|
|
89fb50263b | ||
|
|
e257c6c20b | ||
|
|
43eae40e45 | ||
|
|
920240a687 | ||
|
|
f8b9da1a2c | ||
|
|
3c987ee956 | ||
|
|
5c6d46329b | ||
|
|
8b3e964d14 | ||
|
|
91a93df049 | ||
|
|
19826af5f0 | ||
|
|
49f4cfdf39 | ||
|
|
b3222792ad | ||
|
|
0640710115 | ||
|
|
fa65989a8b | ||
|
|
4209f079dd | ||
|
|
a7704777ce | ||
|
|
7d51b8374d | ||
|
|
a27042b521 | ||
|
|
5b51c893c5 | ||
|
|
408e69396c | ||
|
|
954bbed84a | ||
|
|
7c329ec72c | ||
|
|
07a8a360a5 | ||
|
|
1618c9e6d1 | ||
|
|
ba0147ac42 | ||
|
|
9e88f057b4 | ||
|
|
f171bf5b8f | ||
|
|
1b1628b90a | ||
|
|
50cf25672e | ||
|
|
b316862831 | ||
|
|
38a4b9c297 | ||
|
|
a058cbc410 | ||
|
|
1ef7913497 | ||
|
|
88a16c8b4f | ||
|
|
8030b28ff8 | ||
|
|
1c598b1db8 | ||
|
|
6854bf69a8 | ||
|
|
293def601d | ||
|
|
651dc65efc | ||
|
|
c2b2bd6a93 | ||
|
|
e32a48d256 | ||
|
|
b5cf121d70 | ||
|
|
44c26bf2a1 | ||
|
|
cc8c5057fe | ||
|
|
b4c7c1ca99 | ||
|
|
16d3b31b2c | ||
|
|
89a8180c5e | ||
|
|
34f961bbf3 | ||
|
|
2384f9e1db | ||
|
|
48cce779a2 | ||
|
|
6820753732 | ||
|
|
fbbe9a016d | ||
|
|
c64ca7ef58 | ||
|
|
900cfcb584 | ||
|
|
beab3078d6 | ||
|
|
530a2199da | ||
|
|
d9bca0c32f | ||
|
|
d733de97f5 | ||
|
|
f06c11ed40 | ||
|
|
c638caa63e | ||
|
|
d775372a34 | ||
|
|
07affc3d93 | ||
|
|
f2ebbebead | ||
|
|
a695b379b5 | ||
|
|
88c2190a7c | ||
|
|
2dbf36ef55 | ||
|
|
cca9208697 | ||
|
|
aa37022ef7 | ||
|
|
85c417579f | ||
|
|
baed67efc4 | ||
|
|
c5b7aa1532 | ||
|
|
904e5af128 | ||
|
|
a41d110647 | ||
|
|
a92d6ff13c | ||
|
|
05278935a3 | ||
|
|
a56cdef9b1 | ||
|
|
e9357a2deb | ||
|
|
8d94d27af0 | ||
|
|
6f2a222c59 | ||
|
|
8470a515ef | ||
|
|
06982ac43b | ||
|
|
865c3b5f92 | ||
|
|
8c9e06d7b9 | ||
|
|
a9cc128308 | ||
|
|
ccb16b467b | ||
|
|
1e44aeb92a | ||
|
|
c897f7119a | ||
|
|
ee8e2b1547 | ||
|
|
5fa38cd679 | ||
|
|
65535b5482 | ||
|
|
439a198d02 | ||
|
|
f041b02557 | ||
|
|
4d8639eb2d | ||
|
|
519c8de16f | ||
|
|
7f20af4674 | ||
|
|
55d24e5fed | ||
|
|
81f654e396 | ||
|
|
8f1dc165e2 | ||
|
|
9a0cfff57f | ||
|
|
d749eb6896 | ||
|
|
6d59ac192b | ||
|
|
94d3725cf2 | ||
|
|
8840ec0f49 | ||
|
|
44a8e86d47 | ||
|
|
73abdda442 | ||
|
|
15b03ab1a8 | ||
|
|
dc5245679a | ||
|
|
60414e5bce | ||
|
|
af40c7d667 | ||
|
|
7eb2ecda0f | ||
|
|
6d12a859bc | ||
|
|
920071e242 | ||
|
|
2a24b4bd0c | ||
|
|
a753502200 | ||
|
|
8958fae362 | ||
|
|
e2d68210d7 | ||
|
|
99534debc8 | ||
|
|
5b98629747 | ||
|
|
42003f6af3 | ||
|
|
434573b226 | ||
|
|
d6081c829c | ||
|
|
58718881ef | ||
|
|
ac669e8b92 | ||
|
|
567f1566a9 | ||
|
|
59a5687105 | ||
|
|
7b13ff9704 | ||
|
|
5e7b826a4f | ||
|
|
cbc63b9b48 | ||
|
|
71a84cbab0 | ||
|
|
55e54e464b | ||
|
|
467688dc06 | ||
|
|
375d8f913b | ||
|
|
021849204a | ||
|
|
b635f2e964 | ||
|
|
1e2b96bbee | ||
|
|
2857451ca2 | ||
|
|
2bc3835ee0 | ||
|
|
4f417448b4 | ||
|
|
503f163446 | ||
|
|
f17e769e28 | ||
|
|
f65e6a1276 | ||
|
|
4c248a3615 | ||
|
|
7794db7c0d | ||
|
|
3ca9e5d8ad | ||
|
|
5ca8a90c24 | ||
|
|
0679ac4ca9 | ||
|
|
20a0269782 | ||
|
|
a892d905bb | ||
|
|
bc880cb8d2 | ||
|
|
2243a9353e | ||
|
|
10f994a52a | ||
|
|
0f86c74eba | ||
|
|
c2b5407678 | ||
|
|
350879d8d1 | ||
|
|
a6a276027c | ||
|
|
45b79c8959 | ||
|
|
d0022dd908 | ||
|
|
e0f4a661be | ||
|
|
507433f6ca | ||
|
|
5974c662ff | ||
|
|
aa0bec8a52 | ||
|
|
2d2f71fb27 | ||
|
|
36f59b5802 | ||
|
|
7fc87d2daf | ||
|
|
3648ab3a24 | ||
|
|
7a9d183fc4 | ||
|
|
2a62f5ee19 | ||
|
|
f9cfaae952 | ||
|
|
bd4576fe4b | ||
|
|
4e194bf178 | ||
|
|
ef4e0d5e7e | ||
|
|
e6d8e70925 | ||
|
|
a6c5741c37 | ||
|
|
3ea7fc6ccf | ||
|
|
20926fbd63 | ||
|
|
2a3f3ba45d | ||
|
|
662127e6c7 | ||
|
|
0be05d6038 | ||
|
|
1f77038ef2 | ||
|
|
77ed253c73 | ||
|
|
b988781801 | ||
|
|
595251de24 | ||
|
|
c85631421d | ||
|
|
12c8cd02fc | ||
|
|
9656de5d13 | ||
|
|
9a31746b10 | ||
|
|
ceccbacc34 | ||
|
|
ff2e2ccfc1 | ||
|
|
12bda6f710 | ||
|
|
c53b6fd0ac | ||
|
|
b31243b472 | ||
|
|
c8d19f90a6 | ||
|
|
114bafe0d0 | ||
|
|
5ef8c5c6d4 | ||
|
|
9b499e9537 | ||
|
|
00f00f846b | ||
|
|
998113fedf | ||
|
|
ee5544112a | ||
|
|
7eaabd8fac | ||
|
|
4fc808dd98 | ||
|
|
7cfb250c93 | ||
|
|
47f480b619 | ||
|
|
fa9e950b1a | ||
|
|
49f4d850ce | ||
|
|
b3e15181ae | ||
|
|
aca5500aea | ||
|
|
427b6179b9 | ||
|
|
afa73c75b5 | ||
|
|
8261af7422 | ||
|
|
44e604f416 | ||
|
|
5173f99e68 | ||
|
|
8a3d4658eb | ||
|
|
6b43924848 | ||
|
|
eace352b39 | ||
|
|
fdbe8989fe | ||
|
|
18d7e9f46e | ||
|
|
c6fbd563d8 | ||
|
|
a5df33bb62 | ||
|
|
5cf4896050 | ||
|
|
2fb450bd99 | ||
|
|
4ea58045e2 | ||
|
|
29433538ff | ||
|
|
d382140904 | ||
|
|
b8e9c234e6 | ||
|
|
60ee01f517 | ||
|
|
2b28968dfb | ||
|
|
90b13cf606 | ||
|
|
d81894fc21 | ||
|
|
f5cbae9329 | ||
|
|
7a6653bc6c | ||
|
|
72f2d1b384 | ||
|
|
b66e31bf15 | ||
|
|
ea26c854af | ||
|
|
ef1f62807e | ||
|
|
d8aeda1e50 | ||
|
|
07efba8ec0 | ||
|
|
2959fe7447 | ||
|
|
4601589720 | ||
|
|
9f8225566e | ||
|
|
5e65c96705 | ||
|
|
a9d6e6fcac | ||
|
|
860dcf68ad | ||
|
|
812848323b | ||
|
|
344f9ba7fa | ||
|
|
2d5279ac9a | ||
|
|
fa3e4a0548 | ||
|
|
656c20715e | ||
|
|
a72885e042 | ||
|
|
b587adda1f | ||
|
|
50fd4832c2 | ||
|
|
c094d9320d | ||
|
|
aaccaa887d | ||
|
|
5481e42cd6 | ||
|
|
b3964d1d86 | ||
|
|
e35d9f2d6d | ||
|
|
4d16780366 | ||
|
|
1661fe9b0c | ||
|
|
63344ad4e1 | ||
|
|
90cf7d199f | ||
|
|
730df9d222 | ||
|
|
882d8c1cab | ||
|
|
17af842d2d | ||
|
|
bbe42182df | ||
|
|
81b096feef | ||
|
|
7627e92c54 | ||
|
|
f7bce90cf0 | ||
|
|
b33ce4c800 | ||
|
|
757287d8a5 | ||
|
|
3ed8eafccb | ||
|
|
d8b1c923ef | ||
|
|
4a4d2b1ba0 | ||
|
|
12fa790ea0 | ||
|
|
21955d9c92 | ||
|
|
a0d9819f8c | ||
|
|
a9af5d8eba | ||
|
|
65854cf91a | ||
|
|
9ec1ef2535 | ||
|
|
36119f6e2a | ||
|
|
e912bd4dfb | ||
|
|
c3ef136d41 | ||
|
|
8eda7a4bb8 | ||
|
|
78d146e866 | ||
|
|
77860bacd0 | ||
|
|
63cf5ae72c | ||
|
|
120cde9562 | ||
|
|
e6ffb966dd | ||
|
|
207522aef5 | ||
|
|
a1cc199b34 | ||
|
|
c22260706c | ||
|
|
d5782b52a2 | ||
|
|
85aecef6c3 | ||
|
|
876c993680 | ||
|
|
a272ff8c1b | ||
|
|
7402d58369 | ||
|
|
c0b134a445 | ||
|
|
a324d49bfc | ||
|
|
9c000f5e7b | ||
|
|
0e887ef29a | ||
|
|
fb72aaba48 | ||
|
|
a3869e9227 | ||
|
|
d671ccfc8e | ||
|
|
35bf8fa084 | ||
|
|
f7916cbf3f | ||
|
|
2b7dab686c | ||
|
|
a98cad00eb | ||
|
|
facdce2c1f | ||
|
|
34937987a6 | ||
|
|
831f06a5a5 | ||
|
|
5fe3c86f25 | ||
|
|
04f48837d1 | ||
|
|
f5b14759fb | ||
|
|
def97ff9a9 | ||
|
|
d38772e06f | ||
|
|
351f5e2f6c | ||
|
|
8778174936 | ||
|
|
e5f6a04d15 | ||
|
|
f8d47c1cb4 | ||
|
|
b5c6a6aeeb | ||
|
|
4e7d07c8d4 | ||
|
|
fc2dd77ec7 | ||
|
|
7b6fa00ff8 | ||
|
|
9ac3591366 | ||
|
|
6a819e02da | ||
|
|
4cff7c50db | ||
|
|
669302a172 | ||
|
|
c738605098 | ||
|
|
90cf838b18 | ||
|
|
67e4043e8c | ||
|
|
5e58e3f9cf | ||
|
|
49140b27c6 | ||
|
|
9cdadbb13a | ||
|
|
0ace7b2567 | ||
|
|
ccb8f5788b | ||
|
|
4e5baafedf | ||
|
|
0e82af2d27 | ||
|
|
535737bf39 | ||
|
|
6e6cc16399 | ||
|
|
bb0d8edfad | ||
|
|
ebec5eb689 | ||
|
|
5cb31dcf92 | ||
|
|
0ccffd7c80 | ||
|
|
57b66a2458 | ||
|
|
b8a39ed58a | ||
|
|
f5a910dd73 | ||
|
|
e16adcdff3 | ||
|
|
cf9b4794fd | ||
|
|
6d8c6bdbe5 | ||
|
|
8bbe41b53b | ||
|
|
ba30fb5c3c | ||
|
|
0938e8eee5 | ||
|
|
3b17384631 | ||
|
|
243c995f5f | ||
|
|
96b87581ff | ||
|
|
3de73827d7 | ||
|
|
458aeea4a6 | ||
|
|
14cbb64539 | ||
|
|
a9e4762634 | ||
|
|
487094a0d7 | ||
|
|
f608ebb106 | ||
|
|
87001ac6c2 | ||
|
|
ede1f0ebc9 | ||
|
|
b435d7174c | ||
|
|
2a59d2cc31 | ||
|
|
b8595e609a | ||
|
|
d37bc73a48 | ||
|
|
1902a7652f | ||
|
|
6ab423a5b6 | ||
|
|
c2be690cc6 | ||
|
|
f5a49d0e44 | ||
|
|
03e23e0730 | ||
|
|
eb598fac4f | ||
|
|
be0602ec3c | ||
|
|
6cbde57d88 | ||
|
|
5e4ff5f9c5 | ||
|
|
18e1289f27 | ||
|
|
99aaa6ca25 | ||
|
|
24172e4b2f | ||
|
|
beaf495400 | ||
|
|
79f48760f3 | ||
|
|
785abd4802 | ||
|
|
0ee6ca9800 | ||
|
|
7543020807 | ||
|
|
47b50b9bd0 | ||
|
|
45c49b52a4 | ||
|
|
0ee32c62d3 | ||
|
|
70e98a4348 | ||
|
|
fddf529df9 | ||
|
|
141c62659e | ||
|
|
61e16468f0 | ||
|
|
b74b3d538e | ||
|
|
d3db3eef1b | ||
|
|
90d5b12e72 | ||
|
|
955a3a3ded | ||
|
|
aec75b037b | ||
|
|
e5daa2731a | ||
|
|
390621a7ab | ||
|
|
478bb47c40 | ||
|
|
685517abd1 | ||
|
|
515afe7cf1 | ||
|
|
ec497df1a0 | ||
|
|
8e74463643 | ||
|
|
933d1dfd0f | ||
|
|
0fe987e226 | ||
|
|
770de8994e | ||
|
|
37cf7b4191 | ||
|
|
1a3ef40da9 | ||
|
|
0314302e9c | ||
|
|
9639c71842 | ||
|
|
d2da915cd0 | ||
|
|
e725abcf4e | ||
|
|
de01941274 | ||
|
|
d802ea54da | ||
|
|
c81a20fb7a | ||
|
|
6bf32edb8c | ||
|
|
4a50a2176e | ||
|
|
9e90555fd1 | ||
|
|
2067ec7342 | ||
|
|
c2c5682c0b | ||
|
|
4c72f27dd9 | ||
|
|
36d8d1a626 | ||
|
|
3447d61048 | ||
|
|
a3887c2644 | ||
|
|
8a1f3153b9 | ||
|
|
165dd4a636 | ||
|
|
541b23d144 | ||
|
|
7987ece7cc | ||
|
|
48224e4c43 | ||
|
|
6d4ecad122 | ||
|
|
1578919c37 | ||
|
|
10a1d6b4a0 | ||
|
|
2b7e12924d | ||
|
|
82f0c63e8a | ||
|
|
5d9530fe47 | ||
|
|
37f35d89d1 | ||
|
|
08c88178aa | ||
|
|
0fb2fc4a1d | ||
|
|
da2d13e3ce | ||
|
|
64318670a8 | ||
|
|
3c19f72c16 | ||
|
|
8938d67ef8 | ||
|
|
05724c07cf | ||
|
|
955c3145c3 | ||
|
|
8ea17b5098 | ||
|
|
b20fe0e6ac | ||
|
|
24787acd08 | ||
|
|
d71dad3bd3 | ||
|
|
889439c205 | ||
|
|
bee9df73c1 | ||
|
|
60613dc896 | ||
|
|
e175fb07f7 | ||
|
|
4a70af6f81 | ||
|
|
8f14cc496b | ||
|
|
3b4ecc6b80 | ||
|
|
a7e60f0c59 | ||
|
|
3d7cc5710d | ||
|
|
86fc7e6880 | ||
|
|
acee11fc60 | ||
|
|
b2e7c91313 | ||
|
|
97b7bff4d6 | ||
|
|
e16ca9ef31 | ||
|
|
b2e6caa01e | ||
|
|
2997e9f769 | ||
|
|
2374023982 | ||
|
|
902f03d101 | ||
|
|
cfe3978049 | ||
|
|
7752df41b7 | ||
|
|
d8b108c2a1 | ||
|
|
184dd27a18 | ||
|
|
0e5665d3ab | ||
|
|
ef3bb69ad8 | ||
|
|
45d41d08bd | ||
|
|
dd32e2c3d4 | ||
|
|
2b7e0f33a6 | ||
|
|
0582cdae8d | ||
|
|
9e8ea423e2 | ||
|
|
0c983c1fd4 | ||
|
|
3381ffa6ea | ||
|
|
3b15340966 | ||
|
|
91683c434b | ||
|
|
9e7530c414 | ||
|
|
8fd30fc43c | ||
|
|
b1b04fcdd4 | ||
|
|
56f0c976be | ||
|
|
9aacb4df0e | ||
|
|
0fdb1aa8ff | ||
|
|
bad0110609 | ||
|
|
3cc185a088 | ||
|
|
e8a8167ad9 | ||
|
|
854a1aad35 | ||
|
|
84e6d6fdcd | ||
|
|
f14a65d94c | ||
|
|
37439b36e7 | ||
|
|
c95ca2a228 | ||
|
|
97d8e7095f | ||
|
|
20c1926a01 | ||
|
|
d030233def | ||
|
|
35812ea1f9 | ||
|
|
d649b78920 | ||
|
|
7e43da819e | ||
|
|
40aaa571b4 | ||
|
|
470319d33b | ||
|
|
1db954e9bc | ||
|
|
d697314b42 | ||
|
|
59dd678603 | ||
|
|
02b5cb238b | ||
|
|
74de13d19c | ||
|
|
837d01dd5a | ||
|
|
926d86d1f9 | ||
|
|
aeb213ea0c | ||
|
|
7c6ea3d8c7 | ||
|
|
d409c6ac9c | ||
|
|
92f0b9d6ab | ||
|
|
2c8c8bbaad | ||
|
|
4fc8140a60 | ||
|
|
699f7024f1 | ||
|
|
ce0da32a9c | ||
|
|
82360c6b17 | ||
|
|
493568465b | ||
|
|
bf485d3d6b | ||
|
|
e90aab4982 | ||
|
|
550d4e2346 | ||
|
|
991daf008d | ||
|
|
505ada146c | ||
|
|
75c51953f1 | ||
|
|
8d6c1c4e97 | ||
|
|
10a1a3f511 | ||
|
|
40e6752fba | ||
|
|
dbefb6b4e4 | ||
|
|
6016841086 | ||
|
|
0047f535ef | ||
|
|
90eca40d27 | ||
|
|
0417c34e2d | ||
|
|
d64c2b226a | ||
|
|
868676dc15 | ||
|
|
e31058d41e | ||
|
|
ea8291d8f7 | ||
|
|
1348267518 | ||
|
|
f0323d68eb | ||
|
|
12a01be14f | ||
|
|
e0a18ce3f7 | ||
|
|
8ad5cea371 | ||
|
|
9059e0ac2f | ||
|
|
29fad7a3d8 | ||
|
|
02efda9f01 | ||
|
|
35a388b141 | ||
|
|
9a4a237ede | ||
|
|
5efbddbadb | ||
|
|
6a94c58b00 | ||
|
|
e3f8395360 | ||
|
|
f2b4c0840e | ||
|
|
08d82b84cb | ||
|
|
fbe57fdc95 | ||
|
|
92cdc39372 | ||
|
|
78be8e0fc9 | ||
|
|
a5b786d80f | ||
|
|
f853b777be | ||
|
|
fed1f3f4fe | ||
|
|
18cad44967 | ||
|
|
d17c9a4486 | ||
|
|
b6e22a47d3 | ||
|
|
ec69bdbd64 | ||
|
|
a8cbb57c9b | ||
|
|
b8cc35874e | ||
|
|
c3851185f3 | ||
|
|
e7ee91defc | ||
|
|
cfce9f6dc3 | ||
|
|
4afcb709a7 | ||
|
|
a912a980ec | ||
|
|
2c64b25827 | ||
|
|
38b9170c52 | ||
|
|
f40aa6fb07 | ||
|
|
b616493883 | ||
|
|
e86e2fa173 | ||
|
|
11bfaf6351 | ||
|
|
d37d1c44ff | ||
|
|
c89330313e | ||
|
|
c9dc1300ba | ||
|
|
53cf0b8bfb | ||
|
|
56961becc2 | ||
|
|
1dc42d123d | ||
|
|
d2ea5980ba | ||
|
|
15cf186b85 | ||
|
|
4fdb03a648 | ||
|
|
8f5b554f0b | ||
|
|
8cd3db27b6 | ||
|
|
273a7ed59f | ||
|
|
23deb0bcee | ||
|
|
7ea7bebf6b | ||
|
|
97894c6473 | ||
|
|
1f86fcf5dc | ||
|
|
bb9bdba4c9 | ||
|
|
5b9cc6953a | ||
|
|
33544bf422 | ||
|
|
20accf4d06 | ||
|
|
3fac51e21e | ||
|
|
d999d312c4 | ||
|
|
a22ca88565 | ||
|
|
9ec8bd87bb | ||
|
|
f11ece28ff | ||
|
|
f90f71498e | ||
|
|
32199c6b00 | ||
|
|
870dddc5eb | ||
|
|
9d0d18b590 | ||
|
|
bec617b934 | ||
|
|
c20936b88b | ||
|
|
0869881764 | ||
|
|
a840b5c736 | ||
|
|
2907884f94 | ||
|
|
754a080ffc | ||
|
|
94f20a9f45 | ||
|
|
6cc1198288 | ||
|
|
a015788d21 | ||
|
|
c8d3465726 | ||
|
|
00b9618460 | ||
|
|
d11f5c6e2b | ||
|
|
25007999df | ||
|
|
8ce6546310 | ||
|
|
151f59f155 | ||
|
|
89f2a4c231 | ||
|
|
496be30db6 | ||
|
|
cd426074e1 | ||
|
|
3f7bfac2a0 | ||
|
|
9425918d74 | ||
|
|
cc637fcc51 | ||
|
|
9db1743490 | ||
|
|
ba3542cfcb | ||
|
|
81f5b275db | ||
|
|
f3ee726894 | ||
|
|
b5be9e6c5f | ||
|
|
1e1cf68934 | ||
|
|
4a2744cee3 | ||
|
|
12febd804f | ||
|
|
687c6b14a0 | ||
|
|
a1f99493b3 | ||
|
|
9819f005b6 | ||
|
|
2a6793bf1f | ||
|
|
bf287ee946 | ||
|
|
b8b0668e85 | ||
|
|
092906933b | ||
|
|
e8432be95f | ||
|
|
6ff2f4ba67 | ||
|
|
309a5be873 | ||
|
|
26c87bb630 | ||
|
|
ea9b2add97 | ||
|
|
301569f081 | ||
|
|
b21456102a | ||
|
|
b8a47c9bc6 | ||
|
|
85fbfa10a8 | ||
|
|
555bc0e31a | ||
|
|
ef1233cbb3 | ||
|
|
1524815ed3 | ||
|
|
985af7035e | ||
|
|
b3181708f2 | ||
|
|
3f6c17cf14 | ||
|
|
2e5a7629c0 | ||
|
|
70318468df | ||
|
|
782d109121 | ||
|
|
30e7b0b28d | ||
|
|
910ee8c92e | ||
|
|
8af1bc9011 | ||
|
|
6a12f0d619 | ||
|
|
4f3be36e30 | ||
|
|
fc9d64c947 | ||
|
|
db10766ab2 | ||
|
|
a3dcb79085 | ||
|
|
20667b6d7f | ||
|
|
93e28fbd99 | ||
|
|
87a57a3072 | ||
|
|
bad1fa4476 | ||
|
|
8fe27e7631 | ||
|
|
a1c75ed05c | ||
|
|
e73ad2be54 | ||
|
|
59b0e7a82d | ||
|
|
b4fc3987f2 | ||
|
|
58418cb0c4 | ||
|
|
5794112ad0 | ||
|
|
f2b6fe44a6 | ||
|
|
215b444cae | ||
|
|
a45f581b2a | ||
|
|
dfdd71ecff | ||
|
|
2dfe1c37ad | ||
|
|
b9949780f4 | ||
|
|
5fe857d4be | ||
|
|
3d86c6b18f | ||
|
|
0f0b2e66b8 | ||
|
|
5d24ee71ad | ||
|
|
3a05c5d3ce | ||
|
|
89ec535af5 | ||
|
|
e96d7972c4 | ||
|
|
962a3f0b6e | ||
|
|
cbb5fa4f07 | ||
|
|
b57907efb2 | ||
|
|
26beb7861f | ||
|
|
6e8b9f1341 | ||
|
|
6efe94167f | ||
|
|
51cc96e469 | ||
|
|
bdedced84b | ||
|
|
f497ad722d | ||
|
|
339eb8943e | ||
|
|
c36864e40e | ||
|
|
af6155bb0e | ||
|
|
605fed4b46 | ||
|
|
ac40b74788 | ||
|
|
3e6ddb3738 | ||
|
|
9ac756c6ea | ||
|
|
3b0a30eba8 | ||
|
|
bac7259081 | ||
|
|
4d474ad513 | ||
|
|
e50e82ab40 | ||
|
|
4922175589 | ||
|
|
a289f89fbe | ||
|
|
ba64001df8 | ||
|
|
b225b089b8 | ||
|
|
557a35f55b | ||
|
|
1848fd6fa1 | ||
|
|
f2a4853c93 | ||
|
|
e65154085c | ||
|
|
e4676bb59b | ||
|
|
3b968014c9 | ||
|
|
21b9b93377 | ||
|
|
c4d1b2983d | ||
|
|
7d7a34aeb2 | ||
|
|
65c84700fc | ||
|
|
5a727522f0 | ||
|
|
1599754727 | ||
|
|
d90338cec6 | ||
|
|
d0e94abb40 | ||
|
|
d8c4d6de10 | ||
|
|
74ba98a51b | ||
|
|
c296031d9f | ||
|
|
81c453b16a | ||
|
|
4a34c6f176 | ||
|
|
9b3150bd2e | ||
|
|
6f2245c8fa | ||
|
|
0f9941dc5a | ||
|
|
060f31500b | ||
|
|
7c2a83c635 | ||
|
|
97e3c50cd9 | ||
|
|
b2360dabf6 | ||
|
|
723160280f | ||
|
|
fa92818af3 | ||
|
|
289a32167c | ||
|
|
95e107db96 | ||
|
|
513fd04d21 | ||
|
|
7a16e12207 | ||
|
|
de8252f67f | ||
|
|
98e4741463 | ||
|
|
028245a57b | ||
|
|
2765f2e4a7 | ||
|
|
79db59d1a7 | ||
|
|
c48cff9fbe | ||
|
|
f4b8e829e9 | ||
|
|
468d766819 | ||
|
|
f3ab64d3a8 | ||
|
|
a234bca4ef | ||
|
|
42e9c7eb56 | ||
|
|
9d19f8a5fe | ||
|
|
24e61cffe3 | ||
|
|
3556fe5d86 | ||
|
|
ee887d98f6 | ||
|
|
5c7b1feb4c | ||
|
|
3cd5301f40 | ||
|
|
d8169e6f6b | ||
|
|
c4833b024e | ||
|
|
2a5d5a8cc4 | ||
|
|
f7112154e9 | ||
|
|
f83051b2e3 | ||
|
|
2e42adb302 | ||
|
|
c09ebb8c04 | ||
|
|
042dc7360e | ||
|
|
7a6e294f7b | ||
|
|
97e786c331 | ||
|
|
8ee6adefe3 | ||
|
|
64c37826e4 | ||
|
|
2e8015e0da | ||
|
|
5b6281afcf | ||
|
|
e732fb0c4f | ||
|
|
b10917a426 | ||
|
|
7ae64260e0 | ||
|
|
f97f6bcd3a | ||
|
|
e86d98cbaa | ||
|
|
6afb90778b | ||
|
|
32c7f91a14 | ||
|
|
b28a27e9e9 | ||
|
|
15164c0aa9 | ||
|
|
bf011fedfc | ||
|
|
d7d11b7ebd | ||
|
|
9a929c8f68 | ||
|
|
298d8c0a9b | ||
|
|
a054570942 | ||
|
|
a0009fc30d | ||
|
|
beb51aa09e | ||
|
|
e8a96e275e | ||
|
|
11e758a430 | ||
|
|
d630f53e0d | ||
|
|
5918daf8a4 | ||
|
|
326bb56e40 | ||
|
|
f96154f44c | ||
|
|
45c5b903eb | ||
|
|
5037cf3adf | ||
|
|
180443af42 | ||
|
|
4f3f97fbde | ||
|
|
664cf3278a | ||
|
|
cd36049cd1 | ||
|
|
c2523a0541 | ||
|
|
92739a0aa7 | ||
|
|
cd908ef4ff | ||
|
|
ebd33e0cea | ||
|
|
5f2c5bf110 | ||
|
|
417099fa20 | ||
|
|
626bec8e84 | ||
|
|
a06e2b7cab | ||
|
|
3ae5367ff2 | ||
|
|
b4ef0bca47 | ||
|
|
4313d6f9c0 | ||
|
|
2a0dd9bd70 | ||
|
|
3eeac9bc7e | ||
|
|
67de72bd9b | ||
|
|
552a218468 | ||
|
|
d940151496 | ||
|
|
f5c7f4abe7 | ||
|
|
3ae6c1875d | ||
|
|
1ad6a7f611 | ||
|
|
89d26123ff | ||
|
|
46bffd98cb | ||
|
|
41b84ce012 | ||
|
|
de392f1e5c | ||
|
|
0455cd933d | ||
|
|
d9c0051fae | ||
|
|
126e7affb7 | ||
|
|
624d6be2a5 | ||
|
|
16f960feb5 | ||
|
|
e145d51ba6 | ||
|
|
dcbae65444 | ||
|
|
b4bf2b5a7e | ||
|
|
9baed7609c | ||
|
|
1c2efa1706 | ||
|
|
80a24d52d4 | ||
|
|
af9f56a09d | ||
|
|
ddd74b67be | ||
|
|
7b558d7f8b | ||
|
|
c87ae64a82 | ||
|
|
b9f0ca7274 | ||
|
|
c1759b9fa2 | ||
|
|
9c63d83d3d | ||
|
|
1ed91a04fe | ||
|
|
154cdaaa40 | ||
|
|
33c4b445ef | ||
|
|
53135fe89a | ||
|
|
083acd496d | ||
|
|
00348fd793 | ||
|
|
ddb6fc696b | ||
|
|
f7e48a5cb8 | ||
|
|
70352269ba | ||
|
|
0b94147928 | ||
|
|
da9f59264f | ||
|
|
96b7b48efa | ||
|
|
aea4bf2894 | ||
|
|
855ef72f3f | ||
|
|
98dc857b32 | ||
|
|
94af17a6eb | ||
|
|
00fd35482e | ||
|
|
cc3e0770bc | ||
|
|
e7f7064cc5 | ||
|
|
7b759fe0df | ||
|
|
254ee3baab | ||
|
|
f957e8fdf9 | ||
|
|
822012eea9 | ||
|
|
bb21ecac5b | ||
|
|
648859bda2 | ||
|
|
f328e0f3a8 | ||
|
|
6012eaa183 | ||
|
|
da2a6c1f1c | ||
|
|
0438f100ae | ||
|
|
b95ad9ac55 | ||
|
|
828a256123 | ||
|
|
ebf447ac81 | ||
|
|
124f349ea1 | ||
|
|
26718401fb | ||
|
|
f463e20753 | ||
|
|
1129070514 | ||
|
|
ac3f7b81f8 | ||
|
|
62f9573fb3 | ||
|
|
6d0e5d2e62 | ||
|
|
8b48bf1154 | ||
|
|
42be53201f | ||
|
|
c7791b8cb2 | ||
|
|
7e9059d60f | ||
|
|
f3ebe1a77e | ||
|
|
301fb56ce9 | ||
|
|
aa7a6e878b | ||
|
|
0a39837a62 | ||
|
|
b2e8a9b293 | ||
|
|
a98ad81760 | ||
|
|
ccc51c8331 | ||
|
|
ee171c6da9 | ||
|
|
d5609e969d | ||
|
|
927c806841 | ||
|
|
2da9dda1c0 | ||
|
|
3117bc16a5 | ||
|
|
717b04306a | ||
|
|
271220c542 | ||
|
|
566a874141 | ||
|
|
967866d4df | ||
|
|
1de3e99bc5 | ||
|
|
3e13004b6b | ||
|
|
2f03ce67d6 | ||
|
|
b9232d45eb | ||
|
|
6087ef2a84 | ||
|
|
1f1d368ad5 | ||
|
|
dd18526e5b | ||
|
|
4d53c4dd46 | ||
|
|
9e4a8d29b5 | ||
|
|
ef20efcbb6 | ||
|
|
c70e07d9ac | ||
|
|
b7d4d28bb3 | ||
|
|
9a6ed83f2c | ||
|
|
fd84673e54 | ||
|
|
57b12568e6 | ||
|
|
f9a9f54720 | ||
|
|
3019a9bafd | ||
|
|
278e3d4f6e | ||
|
|
9b9dd06894 | ||
|
|
1f7e29b99c | ||
|
|
c2f0e6e5e3 | ||
|
|
c2b11ba017 | ||
|
|
f75a53e71b | ||
|
|
054abde25f | ||
|
|
24cecf1365 | ||
|
|
821ff7f49a | ||
|
|
ff3d3c32d5 | ||
|
|
3b2ef5b11c | ||
|
|
0394e34a69 | ||
|
|
56efa56474 | ||
|
|
ed7e79553e | ||
|
|
dec71e94f3 | ||
|
|
ac4f91a5ee | ||
|
|
e957626347 | ||
|
|
b4875de45c | ||
|
|
2cfe44eee4 | ||
|
|
fad3dc421c | ||
|
|
22907b6bd9 | ||
|
|
3485ae8321 | ||
|
|
ca62acc3ca | ||
|
|
cdf236aaf5 | ||
|
|
9f2e3c3f52 | ||
|
|
ee1d11c495 | ||
|
|
669e76717c | ||
|
|
4e107712f3 | ||
|
|
85aa57a7dd | ||
|
|
58a14ed950 | ||
|
|
165e6d446c | ||
|
|
1c3e3679ef | ||
|
|
8a513e55b0 | ||
|
|
a314f7c155 | ||
|
|
9497b0d4e9 | ||
|
|
b694f8a245 | ||
|
|
afc65a5acf | ||
|
|
5f40615cd5 | ||
|
|
c6816b9444 | ||
|
|
46e99b09b9 | ||
|
|
af436313a0 | ||
|
|
d64e6f42b4 | ||
|
|
a00628b335 | ||
|
|
33ab4ad879 | ||
|
|
99eb41b25f | ||
|
|
e86ae6bc1f | ||
|
|
c3cbcfb8ef | ||
|
|
a1d23b5314 | ||
|
|
d4d4890d4e | ||
|
|
30e66e53de | ||
|
|
e224331729 | ||
|
|
70b54e4e43 | ||
|
|
9ba463435b | ||
|
|
05ee48661c | ||
|
|
aef9882581 | ||
|
|
78bcddcc6a | ||
|
|
68e169ab4d | ||
|
|
f62eaa24f1 | ||
|
|
d3e553b4bd | ||
|
|
3753975f48 | ||
|
|
2d81114b23 | ||
|
|
472135e0bc | ||
|
|
c60b7056b2 | ||
|
|
42ccb4c091 | ||
|
|
b31c92edcc | ||
|
|
08b018304f | ||
|
|
d19320fdf6 | ||
|
|
860236bf90 | ||
|
|
4d3abf1360 | ||
|
|
305666bf59 | ||
|
|
b03c719f04 | ||
|
|
62f27e3c02 | ||
|
|
4dc67d5e30 | ||
|
|
8ebdc9724e | ||
|
|
9e0582f9bf | ||
|
|
705de51a73 | ||
|
|
1a8e5c97eb | ||
|
|
55bb7fff14 | ||
|
|
662bdcd4ac | ||
|
|
fef101a548 | ||
|
|
18a11cfd48 | ||
|
|
0f80c3e886 | ||
|
|
f122383179 | ||
|
|
e6bc6f4232 | ||
|
|
ac1cb9380d | ||
|
|
40df65fdb4 | ||
|
|
cb2e1f18c2 | ||
|
|
0ecd03e396 | ||
|
|
e6f5ac116b | ||
|
|
051182cb75 | ||
|
|
574c250093 | ||
|
|
8dad7fc6ea | ||
|
|
b558728875 | ||
|
|
e777afad6f | ||
|
|
87703a1b1f | ||
|
|
981b202661 | ||
|
|
13725744fd | ||
|
|
363c3ece3a | ||
|
|
47780ddfef | ||
|
|
251f22b5d7 | ||
|
|
4e0fcd85ae | ||
|
|
59faec8b8b | ||
|
|
32cbfe7b17 | ||
|
|
f08ca43472 | ||
|
|
8eb6cf784b | ||
|
|
7433d73adc | ||
|
|
3221f451a0 | ||
|
|
9e4536748d | ||
|
|
ea67c71505 | ||
|
|
ea38b5af72 | ||
|
|
89d19eedef | ||
|
|
41b5b5e756 | ||
|
|
a3e1363aaa | ||
|
|
2217b30adf | ||
|
|
9ac2395bf0 | ||
|
|
9e2409ab22 | ||
|
|
8e6cf5d189 | ||
|
|
d17190df44 | ||
|
|
fbe5eeb831 | ||
|
|
ed9d969c4c | ||
|
|
7f2a1f651e | ||
|
|
bbbb44ee0f | ||
|
|
29fbd1eea6 | ||
|
|
33f839b319 | ||
|
|
bc83274ad6 | ||
|
|
38e3910b6f | ||
|
|
c26c51a7ee | ||
|
|
e9973668a4 | ||
|
|
4104c3bf52 | ||
|
|
b7c2481933 | ||
|
|
cfb691ac9a | ||
|
|
cb8240a291 | ||
|
|
352963ddc3 | ||
|
|
8c57732324 | ||
|
|
8a33c406b3 | ||
|
|
340bd68f59 | ||
|
|
8237f9305b | ||
|
|
5b1c1eefda | ||
|
|
6258626751 | ||
|
|
87fd439059 | ||
|
|
564ef546a9 | ||
|
|
94dcbf8367 | ||
|
|
1bad11c759 | ||
|
|
ba679d5194 | ||
|
|
e1ad7fe63d | ||
|
|
f18d87b6ed | ||
|
|
a6c15e9a38 | ||
|
|
64bba1465b | ||
|
|
638e106568 | ||
|
|
34e18ecd61 | ||
|
|
d4021b6d9b | ||
|
|
40b1393880 | ||
|
|
30688bf11b | ||
|
|
a7d7a805dc | ||
|
|
4a239e98f6 | ||
|
|
7b97c38898 | ||
|
|
1f35babc6b | ||
|
|
80ffc3de12 | ||
|
|
507b61d5a6 | ||
|
|
8db3106e0b | ||
|
|
1b1fef20b3 | ||
|
|
22c7c5fb0b | ||
|
|
13d00101e8 | ||
|
|
3e7934a5fb | ||
|
|
815193e89e | ||
|
|
4fd4b3d667 | ||
|
|
1526b8b17d | ||
|
|
732537212b | ||
|
|
4adbb5f246 | ||
|
|
30fa772457 | ||
|
|
ee03617b3d | ||
|
|
19cb6106d2 | ||
|
|
cd6bececc1 | ||
|
|
88b93c6159 | ||
|
|
b62fd39392 | ||
|
|
95306d9d50 | ||
|
|
3e870a6444 | ||
|
|
bf26aa2219 | ||
|
|
9981c27ef1 | ||
|
|
fe96018750 | ||
|
|
07c6ae7de8 | ||
|
|
e163683020 | ||
|
|
961103049b | ||
|
|
0254bd46ec | ||
|
|
8b806ed347 | ||
|
|
8e3ead09a3 | ||
|
|
8715db2cab | ||
|
|
50839b4bb0 | ||
|
|
e1f40891c7 | ||
|
|
042f470ef9 | ||
|
|
40cc28516d | ||
|
|
8174bc3506 | ||
|
|
9118a09c77 | ||
|
|
8324bd5c21 | ||
|
|
7f37167da5 | ||
|
|
227a9c41c1 | ||
|
|
6c3862fae3 | ||
|
|
1eec003a80 | ||
|
|
684d7582b6 | ||
|
|
f39b2060fe | ||
|
|
4f2ba7e056 | ||
|
|
1dcf3b4345 | ||
|
|
aa57d14ae7 | ||
|
|
3c54d8a3ad | ||
|
|
c0814b813f | ||
|
|
088aff1a48 | ||
|
|
d6707171e6 | ||
|
|
5c5e159892 | ||
|
|
6d7b3d52dc | ||
|
|
591b908fbf | ||
|
|
742be97ce4 | ||
|
|
1f30a674cd | ||
|
|
19bc826d8b | ||
|
|
c786a7aec5 | ||
|
|
8a8356b7db | ||
|
|
0d67e00af8 | ||
|
|
7448177753 | ||
|
|
90d151f423 | ||
|
|
9f7c5dabf8 | ||
|
|
a85a151430 | ||
|
|
5dd97ab999 | ||
|
|
8daa9925cc | ||
|
|
e844be4e7b | ||
|
|
88b218fa5c | ||
|
|
e66d70e34c | ||
|
|
9361f83933 | ||
|
|
3b2bebbf90 | ||
|
|
4f90eb433a | ||
|
|
b485e0c16c | ||
|
|
bc1fac9648 | ||
|
|
c78779cce3 | ||
|
|
702cd15cb0 | ||
|
|
1da05366ad | ||
|
|
2267efeac5 | ||
|
|
15954da08f | ||
|
|
b2dc7bad39 | ||
|
|
d4e0196346 | ||
|
|
2fc50f5a98 | ||
|
|
bd5b85dbc7 | ||
|
|
8a8324657e | ||
|
|
4bb0af79b7 | ||
|
|
e3bcd89319 | ||
|
|
87383697e8 | ||
|
|
e4b808989e | ||
|
|
59e52bf276 | ||
|
|
9b40e44ef4 | ||
|
|
e92f21d2f7 | ||
|
|
910e89b963 | ||
|
|
8a9cfb2459 | ||
|
|
41961db0bd | ||
|
|
e76518843d | ||
|
|
ef74f5d626 | ||
|
|
c557eb8cec | ||
|
|
0cc279e0d3 | ||
|
|
0cfdf22655 | ||
|
|
527a010f10 | ||
|
|
c8ca974634 | ||
|
|
3296f91bb0 | ||
|
|
e2124620eb | ||
|
|
69864a5ccf | ||
|
|
5b4e1f318d | ||
|
|
b78296cb0b | ||
|
|
06a1dbad61 | ||
|
|
93c31c1a6d | ||
|
|
a8ed495833 | ||
|
|
4a14ed068c | ||
|
|
dc0f24976d | ||
|
|
1e7098b5e3 | ||
|
|
2f24fb18c4 | ||
|
|
96a8ca6d98 | ||
|
|
37a5644576 | ||
|
|
a1cbe76e2c | ||
|
|
98bf61c80e | ||
|
|
01f439ec6e | ||
|
|
acc461c7da | ||
|
|
1585958497 | ||
|
|
7cacd47edd | ||
|
|
e461b9bed4 | ||
|
|
3723c04850 | ||
|
|
73273075c8 | ||
|
|
8e85be0a16 | ||
|
|
37802f40dc | ||
|
|
06b96ffa86 | ||
|
|
c4ed1487f9 | ||
|
|
e64ae6d766 | ||
|
|
5b4837552b | ||
|
|
d2004814f0 | ||
|
|
bf0c5bec45 | ||
|
|
0dd046d36f | ||
|
|
4f5b0756df | ||
|
|
fe1c19dcdf | ||
|
|
24b2096e86 | ||
|
|
86e97e178d | ||
|
|
905d906d69 | ||
|
|
abce74bb93 | ||
|
|
f5db099330 | ||
|
|
122d1771db | ||
|
|
8824e2cee4 | ||
|
|
8a6f3fead8 | ||
|
|
9c71f56a25 | ||
|
|
f924946eba | ||
|
|
32a5edf43f | ||
|
|
9a338344da | ||
|
|
df337831dc | ||
|
|
bb558f6791 | ||
|
|
22558cdd7e | ||
|
|
28c54e81c1 | ||
|
|
0dfffb88e1 | ||
|
|
ed243f8c29 | ||
|
|
a427e8938a | ||
|
|
cc25d29132 | ||
|
|
134f43385b | ||
|
|
a5a264842e | ||
|
|
eed47b6b9c | ||
|
|
3841a04e88 | ||
|
|
9eef8f0b73 | ||
|
|
c258230722 | ||
|
|
345e0988cb | ||
|
|
3671987f4d | ||
|
|
5aa7b20a3e | ||
|
|
68795c640b | ||
|
|
4f1f94d1de | ||
|
|
0f7e31f7d7 | ||
|
|
2f3cad893b | ||
|
|
e79666267d | ||
|
|
d91de04671 | ||
|
|
64b761c19a | ||
|
|
a1ac8edd66 | ||
|
|
1dca857b5b | ||
|
|
f8cd88dbd1 | ||
|
|
71903f601a | ||
|
|
719bc858b5 | ||
|
|
a6126d678b | ||
|
|
4875d6b64d | ||
|
|
54b4059856 | ||
|
|
38059f8e8e | ||
|
|
bb5f4e7285 | ||
|
|
448797a1e6 | ||
|
|
a261103ce0 | ||
|
|
7b82b5adb3 | ||
|
|
397a344364 | ||
|
|
bafa48759f | ||
|
|
46db185081 | ||
|
|
1412da7c32 | ||
|
|
d09e800a0e | ||
|
|
53b417e414 | ||
|
|
57dee64e82 | ||
|
|
fdc795015f | ||
|
|
3a5e9224d0 | ||
|
|
ebfd1a1cf7 | ||
|
|
dd667c2301 | ||
|
|
d727f0ff48 | ||
|
|
eb9b2e53c8 | ||
|
|
b6f06b8e8b | ||
|
|
0a68f869d7 | ||
|
|
3b2461cf2e | ||
|
|
346402ddbf | ||
|
|
44d60d5f83 | ||
|
|
f2ae9e8583 | ||
|
|
7c8e23bd9f | ||
|
|
0752721dc3 | ||
|
|
68a94ac30f | ||
|
|
ee3751c8d7 | ||
|
|
ec33e0e6bd | ||
|
|
31937d363b | ||
|
|
8982a89b24 | ||
|
|
0492fdfb2e | ||
|
|
14698a3a1a | ||
|
|
8c2ffaf095 | ||
|
|
afd72c78bd | ||
|
|
6bf822649b | ||
|
|
67dde16163 | ||
|
|
f1d5ba4005 | ||
|
|
794b0a037f | ||
|
|
c32edbe02e | ||
|
|
f3c3ed44e6 | ||
|
|
f805730493 | ||
|
|
2b1366635d | ||
|
|
42f23f479d | ||
|
|
62bf783f06 | ||
|
|
0b2901b72d | ||
|
|
faa82484a5 | ||
|
|
4ccfd96cfe | ||
|
|
408aa7b24c | ||
|
|
776b9d1c00 | ||
|
|
c93fad5ee0 | ||
|
|
19b2a5d9fd | ||
|
|
f1773e09ab | ||
|
|
462c51d9a1 | ||
|
|
2430e98412 | ||
|
|
78fc60cd29 | ||
|
|
864146de58 | ||
|
|
45478cc79b | ||
|
|
5454d22ad8 | ||
|
|
dc1488ae47 | ||
|
|
0121a8ecad | ||
|
|
7bc90b3066 | ||
|
|
bf39270e0c | ||
|
|
211bc43b6e | ||
|
|
91c5833bd0 | ||
|
|
8311f1c11e | ||
|
|
ae2836325f | ||
|
|
a897af2cde | ||
|
|
cc80022e84 | ||
|
|
5a016db9b6 | ||
|
|
92e1aeede7 | ||
|
|
f846a9bfe9 | ||
|
|
3db859e8b5 | ||
|
|
0eeb1cf83a | ||
|
|
5f238db203 | ||
|
|
422696201a | ||
|
|
58fef0ac38 | ||
|
|
25e1181466 | ||
|
|
5b5f7e3b59 | ||
|
|
dc3afaf6aa | ||
|
|
1164f67827 | ||
|
|
c83a2c8ec5 | ||
|
|
43d0f38b24 | ||
|
|
e95538ca2c | ||
|
|
25ff04417e | ||
|
|
63ecee4d1a | ||
|
|
4c8f6b6a06 | ||
|
|
2161111900 | ||
|
|
24b0922b0e | ||
|
|
186387301f | ||
|
|
1bd9db74ba | ||
|
|
df6933406f | ||
|
|
d679c8390a | ||
|
|
d4daa7b68c | ||
|
|
44d98d6166 | ||
|
|
b3708acf27 | ||
|
|
2c0fa6c5df | ||
|
|
57f74bd1c2 | ||
|
|
598c409e63 | ||
|
|
c6eb7fad68 | ||
|
|
c561edaa72 | ||
|
|
031fa9ad4d | ||
|
|
d622d4bf30 | ||
|
|
e32db5c9aa | ||
|
|
4a6c209a13 | ||
|
|
0d2aa5d9d7 | ||
|
|
e30b1fb8fd | ||
|
|
da1b6eeaf2 | ||
|
|
01b835c237 | ||
|
|
48e1c8c69d | ||
|
|
f06e708282 | ||
|
|
f0f7e760ae | ||
|
|
31b4d25d10 | ||
|
|
d41988232e | ||
|
|
880570f228 | ||
|
|
72a90c750a | ||
|
|
e1988bc744 | ||
|
|
d6a3e37b83 | ||
|
|
8261047b1e | ||
|
|
417b59997f | ||
|
|
4366d2c428 | ||
|
|
217cc3b045 | ||
|
|
757e0a5445 | ||
|
|
ddf6410130 | ||
|
|
7842418b7b | ||
|
|
9624b86426 | ||
|
|
201a2fe5ff | ||
|
|
ed032a88b8 | ||
|
|
ae76a74043 | ||
|
|
3359acb8cb | ||
|
|
a2b371cd52 | ||
|
|
dd69b3976a | ||
|
|
16e5de84da | ||
|
|
46fa602530 | ||
|
|
aa4d3b4cc0 | ||
|
|
73ed23495e | ||
|
|
c7d970f782 | ||
|
|
6dfd07d025 | ||
|
|
e7bf7c0161 | ||
|
|
f5a7b9e716 | ||
|
|
b951e023ec | ||
|
|
3ea9bbd632 | ||
|
|
aaca3daa27 | ||
|
|
a51b316824 | ||
|
|
928a00c474 | ||
|
|
fa13f396d5 | ||
|
|
3ab56a20ee | ||
|
|
649f874292 | ||
|
|
90fdd89a0b | ||
|
|
54e66f1d59 | ||
|
|
82471e68a8 | ||
|
|
20fb7b9175 | ||
|
|
859fdaad45 | ||
|
|
09ed309996 | ||
|
|
65e4cda059 | ||
|
|
7e037c4226 | ||
|
|
f636c38440 | ||
|
|
b98f040ef2 | ||
|
|
e57211c544 | ||
|
|
48a1ff0d45 | ||
|
|
032dcf74b0 | ||
|
|
51d4839861 | ||
|
|
9f125ea7c1 | ||
|
|
9bcb25958d | ||
|
|
866925bfb7 | ||
|
|
f8b3c05311 | ||
|
|
353f272434 | ||
|
|
3d54c6ec46 | ||
|
|
71e27c463d | ||
|
|
8c48382049 | ||
|
|
11781089d1 | ||
|
|
d97fd43a72 | ||
|
|
f5ea4b3b39 | ||
|
|
f227ffe4b9 | ||
|
|
027428eb1d | ||
|
|
15778afbdc | ||
|
|
d06f63287e | ||
|
|
1490812ab2 | ||
|
|
707415d4fc | ||
|
|
9cea6ef1b6 | ||
|
|
48ea74bf01 | ||
|
|
026deaf759 | ||
|
|
4c59971194 | ||
|
|
fd8571c2c9 | ||
|
|
dd096ae080 | ||
|
|
eb1accaa91 | ||
|
|
7e38410e47 | ||
|
|
d336388403 | ||
|
|
c207d7ec62 | ||
|
|
018b28328c | ||
|
|
0957a7463e | ||
|
|
c72f5bd9c4 | ||
|
|
0f57446da7 | ||
|
|
3a90ea0acd | ||
|
|
58af2f958c | ||
|
|
a8fd4161bb | ||
|
|
53f8519a38 | ||
|
|
eb162f3b0a | ||
|
|
4ce838e1f1 | ||
|
|
a36ffd3910 | ||
|
|
17b5b32f75 | ||
|
|
9b919d590a | ||
|
|
80264051d8 | ||
|
|
188fed9570 | ||
|
|
eae7165c79 | ||
|
|
54281fe733 | ||
|
|
2b2ea368aa | ||
|
|
67a28eb256 | ||
|
|
f5d96a6f80 | ||
|
|
44ac015598 | ||
|
|
89a9c0545e | ||
|
|
3b26bba0c4 | ||
|
|
2be2fb3ed3 | ||
|
|
e341588a8a | ||
|
|
c56595d749 | ||
|
|
ce0b384fa6 | ||
|
|
dfd7d541b0 | ||
|
|
ded4daf049 | ||
|
|
361428213b | ||
|
|
12a79db2f6 | ||
|
|
e8b155a3be | ||
|
|
716b46c550 | ||
|
|
9d954dca8c | ||
|
|
7162c65df7 | ||
|
|
bd9fca4708 | ||
|
|
14d496cc8b | ||
|
|
106a8ad918 | ||
|
|
44a82a175d | ||
|
|
99248631aa | ||
|
|
2836ee9b02 | ||
|
|
d82773ffe9 | ||
|
|
ec626b3f0e | ||
|
|
997d9ea67f | ||
|
|
aec6b9f86f | ||
|
|
d45898df80 | ||
|
|
b0da4b23a0 | ||
|
|
bf18b7ca67 | ||
|
|
cc17fbfe7d | ||
|
|
fa170b2e5a | ||
|
|
c61ba345f2 | ||
|
|
ae09fb1f91 | ||
|
|
70a2c84cd2 | ||
|
|
21524e3083 | ||
|
|
fbe2aba2e7 | ||
|
|
a41a1e8718 | ||
|
|
051547603a | ||
|
|
80a25bb880 | ||
|
|
0301b334c7 | ||
|
|
1492b4b2b2 | ||
|
|
5b7bcac260 | ||
|
|
7fcbf9e43e | ||
|
|
6c495e0da4 | ||
|
|
a06b419d42 | ||
|
|
a255c592e8 | ||
|
|
7aac6604c4 | ||
|
|
deb5bf1dff | ||
|
|
3dfe6e97a7 | ||
|
|
43bab4035b | ||
|
|
ef0c03ff70 | ||
|
|
ad54dcc827 | ||
|
|
c0ab28d1d9 | ||
|
|
5b2f48da27 | ||
|
|
132fcf36b2 | ||
|
|
4571df58c6 | ||
|
|
f6b384d41f | ||
|
|
c259892c3a | ||
|
|
b471329591 | ||
|
|
3add5835db | ||
|
|
cf510ad2c5 | ||
|
|
696a8d6191 | ||
|
|
01f8a1155f | ||
|
|
986aaaaa4b | ||
|
|
c96ee2310d | ||
|
|
76cb2a3a4f | ||
|
|
9bef934c76 | ||
|
|
85f14172dc | ||
|
|
4539c0d79f | ||
|
|
c3131af90a | ||
|
|
c2c14fa26e | ||
|
|
e49f61f5fc | ||
|
|
22f5bd5e35 | ||
|
|
7a1b73b983 | ||
|
|
0c56b1add7 | ||
|
|
1e60969646 | ||
|
|
ee29752217 | ||
|
|
e012f858d6 | ||
|
|
c3fad2e227 | ||
|
|
b7e8628c4b | ||
|
|
e4977b0b9f | ||
|
|
b127c1dc58 | ||
|
|
07bff66fb5 | ||
|
|
4a888ae6d4 | ||
|
|
a0a33ee506 | ||
|
|
98f8c9a5e5 | ||
|
|
1f69bec480 | ||
|
|
8f1b4f3642 | ||
|
|
ca39ebf9fb | ||
|
|
9fb0844100 | ||
|
|
bdf278f7a5 | ||
|
|
c8f2f8572f | ||
|
|
5d54f33962 | ||
|
|
ba449e444b | ||
|
|
87ba7282f6 | ||
|
|
7d1bfaf7be | ||
|
|
7d5acf1d44 | ||
|
|
3610c4583a | ||
|
|
41cfde6be3 | ||
|
|
34bde8d54a | ||
|
|
1ed55e3e3e | ||
|
|
f80a8520e8 | ||
|
|
740bab942d | ||
|
|
08b1b4860f | ||
|
|
18ea5dc0d7 | ||
|
|
3ac7f5d4c1 | ||
|
|
ad71500818 | ||
|
|
b2ad840a6b | ||
|
|
8db7cc2cff | ||
|
|
ac1541f4b7 | ||
|
|
09e2bbce8a | ||
|
|
73496a36a1 | ||
|
|
8303cc1021 | ||
|
|
ab759cd27b | ||
|
|
64444de582 | ||
|
|
e425fbe85d | ||
|
|
4f4b2f0927 | ||
|
|
da6eb9d123 | ||
|
|
1b15e07e99 | ||
|
|
e49d720081 | ||
|
|
3267d6a9ce | ||
|
|
3ba2c330e1 | ||
|
|
618c8a73db | ||
|
|
aa0ea373cd | ||
|
|
6c3fda83ba | ||
|
|
a3571c6cce | ||
|
|
6fcedb7dbe | ||
|
|
18882701d2 | ||
|
|
30c041f9ad | ||
|
|
be7cf82299 | ||
|
|
fde045cd77 | ||
|
|
183150b741 | ||
|
|
a2570930e8 | ||
|
|
fdb6716c0f | ||
|
|
a20a88d235 | ||
|
|
48d3ff94c9 | ||
|
|
a33857da09 | ||
|
|
13791b1eeb | ||
|
|
9a5e37fca8 | ||
|
|
3e976df0fb | ||
|
|
42afed9c1a | ||
|
|
37c36e2692 | ||
|
|
7fbc7031f4 | ||
|
|
9f004a9ea9 | ||
|
|
23f4587f2b | ||
|
|
4d8f5b0ae7 | ||
|
|
89389a29ef | ||
|
|
29fe3961ab | ||
|
|
4e8a085ac9 | ||
|
|
fb22c2774d | ||
|
|
7d059d4c37 | ||
|
|
9715c5899a | ||
|
|
cc07f21211 | ||
|
|
b4d1e854ef | ||
|
|
075aa18fd4 | ||
|
|
e0204f5621 | ||
|
|
a9ac4411e5 | ||
|
|
50b31539c2 | ||
|
|
56194bcd95 | ||
|
|
eb8ffa9040 | ||
|
|
a7a1cc2c75 | ||
|
|
ab217f7ffa | ||
|
|
a20c9893e4 | ||
|
|
3bb400ca14 | ||
|
|
cd6aa5b5c0 | ||
|
|
dc55d7bdab | ||
|
|
8b115ac8dc | ||
|
|
c94e4afbfa | ||
|
|
6566d205e2 | ||
|
|
e484f0cc04 | ||
|
|
bd397b8cba | ||
|
|
f8c8ef9eac | ||
|
|
72c19bb3de | ||
|
|
89f7eff382 | ||
|
|
b90a6d9ff6 | ||
|
|
584ba4ebae | ||
|
|
ba3db4795e | ||
|
|
59d73bf3d2 | ||
|
|
919ca3a3cc | ||
|
|
5886edfac2 | ||
|
|
d414962af4 | ||
|
|
8fb7db245a | ||
|
|
6f0fc27e33 | ||
|
|
9c54ad58f8 | ||
|
|
f55c2dfc03 | ||
|
|
675ef1aa3a | ||
|
|
ef57235623 | ||
|
|
d66d07e883 | ||
|
|
b92693daba | ||
|
|
58b1999e08 | ||
|
|
8e5f029e02 | ||
|
|
2d41264e9e | ||
|
|
82c6be7edf | ||
|
|
0219d4dfba | ||
|
|
391516da51 | ||
|
|
1d6b8f9ad2 | ||
|
|
10796f4b6e | ||
|
|
33ffd7c37d | ||
|
|
21d1e929a0 | ||
|
|
d0bc3520de | ||
|
|
9f18657889 | ||
|
|
c16d69b292 | ||
|
|
ebeacb36fb | ||
|
|
6558854dbe | ||
|
|
7d9d5d9478 | ||
|
|
630f548ff4 | ||
|
|
100b62bb69 | ||
|
|
e012b94f21 | ||
|
|
3104620cf0 | ||
|
|
ebdd24d6d0 | ||
|
|
7cd72c79ec | ||
|
|
84a6379565 | ||
|
|
0a5f12720e | ||
|
|
73f7af0e88 | ||
|
|
e5a96f0f54 | ||
|
|
d73e7f6edd | ||
|
|
61542c41de | ||
|
|
bd1a581bee | ||
|
|
6e8a1782ab | ||
|
|
96d910c770 | ||
|
|
7560c17adc | ||
|
|
9cd339eb39 | ||
|
|
f310029387 | ||
|
|
3ed8eb3f9c | ||
|
|
007351494d | ||
|
|
6dcb93208d | ||
|
|
84e1a698bf | ||
|
|
0d7638eafd | ||
|
|
86e2f445f7 | ||
|
|
093e816c37 | ||
|
|
1cb0a3edc6 | ||
|
|
06a5054273 | ||
|
|
acd0299243 | ||
|
|
dca68b0aad | ||
|
|
c3ea09906d | ||
|
|
bf4679e8a0 | ||
|
|
c4054610c8 | ||
|
|
f6c0d3d70b | ||
|
|
ef855d198e | ||
|
|
81b07870c8 | ||
|
|
bb6721dce6 | ||
|
|
446a2987cd | ||
|
|
4de2a17409 | ||
|
|
99d24f77ed | ||
|
|
c0422cea9f | ||
|
|
8b6ad0193d | ||
|
|
33eff8bfd6 | ||
|
|
65af3dab03 | ||
|
|
065a605270 | ||
|
|
a7260c4037 | ||
|
|
44cad59f2b | ||
|
|
c52461f911 | ||
|
|
7f459268d9 | ||
|
|
9eeb3b9c88 | ||
|
|
d1b31da71e | ||
|
|
89e540e638 | ||
|
|
fab65a5bc2 | ||
|
|
e7d13fe532 | ||
|
|
ecc81fce17 | ||
|
|
b4afd23c30 | ||
|
|
af1a3f9b6e | ||
|
|
820b6c9aa0 | ||
|
|
3cb22c204c | ||
|
|
7432ccf4ed | ||
|
|
6a48e792c1 | ||
|
|
9459290ae7 | ||
|
|
741d654495 | ||
|
|
d3e182af09 | ||
|
|
d9b4d267c7 | ||
|
|
58c5c24555 | ||
|
|
341c9a137f | ||
|
|
871446fc98 | ||
|
|
0abda1b176 | ||
|
|
394bcdb5e3 | ||
|
|
28deecca55 | ||
|
|
4db88e5b8f | ||
|
|
75b243a51d | ||
|
|
9bccfc429c | ||
|
|
077e59b769 | ||
|
|
007e3c0e9a | ||
|
|
e2bc412669 | ||
|
|
e344209582 | ||
|
|
e76ca1458c | ||
|
|
16cc9ca2c9 | ||
|
|
8c90957ff5 | ||
|
|
c0d8e84c9d | ||
|
|
b0ad542928 | ||
|
|
727b35f665 | ||
|
|
aa4343211f | ||
|
|
3611989355 | ||
|
|
3381b77d71 | ||
|
|
dce70db374 | ||
|
|
2adbcdc7ea | ||
|
|
7e5fa372cf | ||
|
|
6e45e1dd86 | ||
|
|
7f290d5c82 | ||
|
|
b6609cafae | ||
|
|
efa95a1842 | ||
|
|
51bd4f0f3a | ||
|
|
562b61695e | ||
|
|
98f51bfb56 | ||
|
|
73f0ce69e7 | ||
|
|
cf338ab1be | ||
|
|
66a9dc9639 | ||
|
|
8ed9d849dc | ||
|
|
5ebab6c10c | ||
|
|
e7a69008e6 | ||
|
|
73e015683c | ||
|
|
b462781fd0 | ||
|
|
93095cbe99 | ||
|
|
399371e7b5 | ||
|
|
d7142e2328 | ||
|
|
1f75bb1066 | ||
|
|
088adfacc1 | ||
|
|
da3478b2a7 | ||
|
|
5126ed1ef0 | ||
|
|
61fb21ad28 | ||
|
|
a3221d2ac1 | ||
|
|
2c713fcdfa | ||
|
|
afd8bdb907 | ||
|
|
efd5ee5786 | ||
|
|
510b4cd4d5 | ||
|
|
de584c658c | ||
|
|
6eb770bbcc | ||
|
|
c7e11bfdc0 | ||
|
|
94327ff0c2 | ||
|
|
4602eafa87 | ||
|
|
bb3edc3b47 | ||
|
|
c769702fe5 | ||
|
|
dbbab0c4d2 | ||
|
|
9b3318b0df | ||
|
|
0fac7fe8b8 | ||
|
|
b9f592fbf5 | ||
|
|
c7b1a56b3d | ||
|
|
3896bca4d8 | ||
|
|
9774cc3344 | ||
|
|
d3979b025d | ||
|
|
01966df4f7 | ||
|
|
f38bd4a072 | ||
|
|
b1df18d76f | ||
|
|
7daccb8e72 | ||
|
|
bb91a624f1 | ||
|
|
a04d77bcbc | ||
|
|
25bd99451c | ||
|
|
ed43d0a76d | ||
|
|
066a844c4e | ||
|
|
5e252dea4b | ||
|
|
d2a918b454 | ||
|
|
da38e779ea | ||
|
|
8186ae6bc0 | ||
|
|
e1f67417d7 | ||
|
|
fd322eef82 | ||
|
|
d3a4375f78 | ||
|
|
78112d305b | ||
|
|
f7c3ee9932 | ||
|
|
e7a392c77c | ||
|
|
887e553f05 | ||
|
|
beb227ddf1 | ||
|
|
84acca07ae | ||
|
|
cc1e997dcd | ||
|
|
a7026ba90a | ||
|
|
3a69fad0f6 | ||
|
|
40564811ee | ||
|
|
dcd08dc51c | ||
|
|
fdf57ede8c | ||
|
|
bd717af8ab | ||
|
|
c54f5170bf | ||
|
|
eae4e1f9f0 | ||
|
|
9c513d678d | ||
|
|
d16c245fc4 | ||
|
|
ec8290c897 | ||
|
|
b293a7f62c | ||
|
|
d67c8bdfc3 | ||
|
|
e2ccd3578c | ||
|
|
4e834af140 | ||
|
|
7e5614383d | ||
|
|
eb84a83b47 | ||
|
|
2c2898a388 | ||
|
|
1732b6c037 | ||
|
|
314f459161 | ||
|
|
83926d3cae | ||
|
|
6218c7bf42 | ||
|
|
566fce3237 | ||
|
|
373ef16010 | ||
|
|
ea76e76104 | ||
|
|
9fd62d1588 | ||
|
|
b7061c82b4 | ||
|
|
6fb812f747 | ||
|
|
40e8d11e64 | ||
|
|
73042aae5b | ||
|
|
e5ce3bcf2c | ||
|
|
c399d22a19 | ||
|
|
1ea087a794 | ||
|
|
00bdf89977 | ||
|
|
0bb4d17634 | ||
|
|
f9c6b3e7d6 | ||
|
|
9e5a5ddb4c | ||
|
|
8c0d6a8432 | ||
|
|
553f93758a | ||
|
|
a4a7e64c19 | ||
|
|
22832c30a0 | ||
|
|
1a21666286 | ||
|
|
4033b80b51 | ||
|
|
99218d821b | ||
|
|
e626b29e10 | ||
|
|
f89b936801 | ||
|
|
17f59e818d | ||
|
|
b5bd5542eb | ||
|
|
2e94e70e2b | ||
|
|
4e1f385711 | ||
|
|
716e73d483 | ||
|
|
5b36173d11 | ||
|
|
b2ef4f6134 | ||
|
|
c7be6dec11 | ||
|
|
bd1574b208 | ||
|
|
f376e67420 | ||
|
|
ef0bc0abff | ||
|
|
71e586304b | ||
|
|
3c74c3a358 | ||
|
|
edad5898f2 | ||
|
|
fa0c1939ed | ||
|
|
9a5ade185c | ||
|
|
f1dd0f27cb | ||
|
|
f9e5a0cde2 | ||
|
|
ead751c62b | ||
|
|
0058c58edd | ||
|
|
221ddb9456 | ||
|
|
65e2487096 | ||
|
|
0501f36390 | ||
|
|
96981b9cff | ||
|
|
f51e87f5ad | ||
|
|
cb213f1c1b | ||
|
|
c8d895de26 | ||
|
|
e51094b721 | ||
|
|
b03bded70b | ||
|
|
ee1df1ccae | ||
|
|
bc6ebcd248 | ||
|
|
ba582f753a | ||
|
|
cbd85b472e | ||
|
|
7a92ded39a | ||
|
|
831f05df51 | ||
|
|
0d94a6a66c | ||
|
|
3e35c34b6b | ||
|
|
03a9ca0a97 | ||
|
|
6f481bb0e0 | ||
|
|
f98cc5685d | ||
|
|
9135621ff9 | ||
|
|
8624daa7f8 | ||
|
|
3051c46dc3 | ||
|
|
e920830ec5 | ||
|
|
7892e5ac77 | ||
|
|
b0e9bafc78 | ||
|
|
44aa070770 | ||
|
|
97f9dcae6a | ||
|
|
8cbf495a57 | ||
|
|
c1b29492c5 | ||
|
|
669a31924e | ||
|
|
5e972dcf34 | ||
|
|
8fcdc444df | ||
|
|
619d21ffc9 | ||
|
|
d62bcc17f3 | ||
|
|
982e05bbd5 | ||
|
|
a3c8b36863 | ||
|
|
630e3c408b | ||
|
|
1082b52bd4 | ||
|
|
914f3066bb | ||
|
|
de91e75724 | ||
|
|
384431886a | ||
|
|
82b302d928 | ||
|
|
4ecc9e6b64 | ||
|
|
55e50d890b | ||
|
|
6e86c951d7 | ||
|
|
c41b52c487 | ||
|
|
5c6fc4a6a3 | ||
|
|
edecdad54d | ||
|
|
5291364f1d | ||
|
|
41cc97ae64 | ||
|
|
bf2b7ddfc5 | ||
|
|
eb0cbdaa90 | ||
|
|
0d0142e812 | ||
|
|
a43e21e05c | ||
|
|
4135d091a6 | ||
|
|
534407b1f4 | ||
|
|
18cc8c7ef1 | ||
|
|
58c9b4b7f6 | ||
|
|
cde719f49f | ||
|
|
38cab94d9a | ||
|
|
6ed6d7f5a8 | ||
|
|
e40a46de71 | ||
|
|
c5bf99a1c2 | ||
|
|
2c7d63c765 | ||
|
|
3dd22903ac | ||
|
|
d8d36af452 | ||
|
|
e610e50f9c | ||
|
|
935c64173f | ||
|
|
377dbd2075 | ||
|
|
93272700d2 | ||
|
|
d508258ad8 | ||
|
|
f57b2e6150 | ||
|
|
af45f9e27e | ||
|
|
4c4d61b046 | ||
|
|
7561c3e132 | ||
|
|
1514ad2a80 |
@@ -6,8 +6,7 @@ config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
conftest.c
|
||||
conftest.log
|
||||
conftest*
|
||||
dox
|
||||
getgroups
|
||||
gmon.out
|
||||
@@ -16,8 +15,11 @@ shconfig
|
||||
testdir
|
||||
tests-dont-exist
|
||||
testtmp
|
||||
testtmp.*
|
||||
tls
|
||||
trimslash
|
||||
t_unsafe
|
||||
wildtest
|
||||
getfsdev
|
||||
.rsync-filter
|
||||
mkrounding
|
||||
rounding.h
|
||||
|
||||
19
.ignore
19
.ignore
@@ -1,19 +0,0 @@
|
||||
.#*
|
||||
*.log
|
||||
Makefile
|
||||
config.h
|
||||
*.o
|
||||
CVS
|
||||
.ignore
|
||||
.cvsignore
|
||||
*~
|
||||
rsync
|
||||
config.status
|
||||
config.cache
|
||||
TAGS
|
||||
config.log
|
||||
test
|
||||
*.gz
|
||||
rsync-*
|
||||
*.dvi
|
||||
*.aux
|
||||
849
COPYING
849
COPYING
@@ -1,285 +1,626 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
0. Definitions.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
1. Source Code.
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
14. Revised Versions of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
NO WARRANTY
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
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 of the License, or
|
||||
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,
|
||||
@@ -304,36 +645,30 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
23
INSTALL
23
INSTALL
@@ -1,4 +1,4 @@
|
||||
To build and install rsync
|
||||
To build and install rsync:
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
@@ -9,8 +9,15 @@ to ./configure. To see them, use:
|
||||
|
||||
$ ./configure --help
|
||||
|
||||
Configure tries to figure out if the local system uses group "nobody" or
|
||||
"nogroup" by looking in the /etc/group file. (This is only used for the
|
||||
default group of an rsync daemon, which attempts to run with "nobody"
|
||||
user and group permissions.) You can change the default user and group
|
||||
for the daemon by editing the NOBODY_USER and NOBODY_GROUP defines in
|
||||
config.h, or just override them in your /etc/rsyncd.conf file.
|
||||
|
||||
As of 2.4.7, rsync uses Eric Troan's popt option-parsing library. A
|
||||
cut-down copy of release 1.5 is included in the rsync distribution,
|
||||
cut-down copy of release 1.6.4 is included in the rsync distribution,
|
||||
and will be used if there is no popt library on your build host, or if
|
||||
the --with-included-popt option is passed to ./configure.
|
||||
|
||||
@@ -18,7 +25,6 @@ If you configure using --enable-maintainer-mode, then rsync will try
|
||||
to pop up an xterm on DISPLAY=:0 if it crashes. You might find this
|
||||
useful, but it should be turned off for production builds.
|
||||
|
||||
|
||||
RPM NOTES
|
||||
---------
|
||||
|
||||
@@ -37,16 +43,15 @@ fails:
|
||||
|
||||
Install gcc or HP's "ANSI/C Compiler".
|
||||
|
||||
|
||||
|
||||
MAC OSX NOTES
|
||||
-------------
|
||||
|
||||
Mac OS X (Darwin) seems to have an IPv6 stack, but it does not
|
||||
completely implement the "New Sockets" API.
|
||||
Some versions of Mac OS X (Darwin) seem to have an IPv6 stack, but do
|
||||
not completely implement the "New Sockets" API.
|
||||
|
||||
<http://www.ipv6.org/impl/mac.html> says that Apple do not support
|
||||
IPv6 yet. If your build fails, try again with --disable-ipv6.
|
||||
<http://www.ipv6.org/impl/mac.html> says that Apple started to support
|
||||
IPv6 in 10.2 (Jaguar). If your build fails, try again after running
|
||||
configure with --disable-ipv6.
|
||||
|
||||
IBM AIX NOTES
|
||||
-------------
|
||||
|
||||
97
Makefile.in
97
Makefile.in
@@ -2,6 +2,7 @@
|
||||
# Makefile
|
||||
|
||||
prefix=@prefix@
|
||||
datarootdir=@datarootdir@
|
||||
exec_prefix=@exec_prefix@
|
||||
bindir=@bindir@
|
||||
mandir=@mandir@
|
||||
@@ -25,30 +26,31 @@ VERSION=@VERSION@
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h lib/pool_alloc.h
|
||||
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
|
||||
lib/permstring.o lib/pool_alloc.o @LIBOBJS@
|
||||
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
|
||||
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
|
||||
zlib/zutil.o zlib/adler32.o
|
||||
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o \
|
||||
main.o checksum.o match.o syscall.o log.o backup.o
|
||||
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \
|
||||
fileio.o batch.o clientname.o
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h lib/pool_alloc.h
|
||||
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
|
||||
lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o @LIBOBJS@
|
||||
ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
|
||||
zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o
|
||||
OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
|
||||
util.o main.o checksum.o match.o syscall.o log.o backup.o
|
||||
OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
|
||||
fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
|
||||
OBJS3=progress.o pipe.o
|
||||
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
|
||||
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
|
||||
popt/popthelp.o popt/poptparse.o
|
||||
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
|
||||
|
||||
TLS_OBJ = tls.o syscall.o lib/permstring.o
|
||||
TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
|
||||
|
||||
# Programs we must have to run the test cases
|
||||
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) \
|
||||
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
|
||||
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
|
||||
|
||||
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
|
||||
|
||||
# Objects for CHECK_PROGS to clean
|
||||
CHECK_OBJS=getgroups.o t_stub.o t_unsafe.o trimslash.o wildtest.o
|
||||
CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
|
||||
|
||||
# note that the -I. is needed to handle config.h when using VPATH
|
||||
.c.o:
|
||||
@@ -58,31 +60,42 @@ CHECK_OBJS=getgroups.o t_stub.o t_unsafe.o trimslash.o wildtest.o
|
||||
|
||||
all: rsync$(EXEEXT)
|
||||
|
||||
man: rsync.1 rsyncd.conf.5
|
||||
|
||||
install: all
|
||||
-mkdir -p ${DESTDIR}${bindir}
|
||||
${INSTALLCMD} ${STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
|
||||
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
|
||||
-mkdir -p ${DESTDIR}${mandir}/man1
|
||||
-mkdir -p ${DESTDIR}${mandir}/man5
|
||||
${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1
|
||||
${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5
|
||||
|
||||
install-strip:
|
||||
$(MAKE) STRIP='-s' install
|
||||
$(MAKE) INSTALL_STRIP='-s' install
|
||||
|
||||
rsync$(EXEEXT): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJS): $(HEADERS)
|
||||
|
||||
flist.o: rounding.h
|
||||
|
||||
rounding.h: mkrounding$(EXEEXT)
|
||||
./mkrounding$(EXEEXT) >rounding.h
|
||||
|
||||
mkrounding$(EXEEXT): mkrounding.c rsync.h
|
||||
@sed '1,/^struct file_struct/d; /^}/,$$d' <$(srcdir)/rsync.h >mkrounding.h
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -I. $(srcdir)/mkrounding.c
|
||||
@rm mkrounding.h
|
||||
|
||||
tls$(EXEEXT): $(TLS_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
|
||||
|
||||
getgroups$(EXEEXT): getgroups.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getgroups.o $(LIBS)
|
||||
|
||||
TRIMSLASH_OBJ = trimslash.o syscall.o
|
||||
getfsdev$(EXEEXT): getfsdev.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
|
||||
|
||||
TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
|
||||
trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
|
||||
|
||||
@@ -90,29 +103,18 @@ T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o
|
||||
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
|
||||
|
||||
# I don't like these rules because CVS can skew the timestamps and
|
||||
# produce spurious warnings, and also make "make install" fail if the
|
||||
# source directory can no longer be found. Since we don't rebuild
|
||||
# automatically they're kind of lame anyhow.
|
||||
gen:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
|
||||
|
||||
#Makefile: Makefile.in configure config.status
|
||||
# echo "WARNING: You need to run ./config.status --recheck"
|
||||
|
||||
# don't actually run autoconf, just issue a warning
|
||||
#configure: configure.in
|
||||
# echo "WARNING: you need to rerun autoconf"
|
||||
|
||||
$(srcdir)/rsync.1: $(srcdir)/rsync.yo
|
||||
yodl2man -o $(srcdir)/rsync.1 $(srcdir)/rsync.yo
|
||||
|
||||
$(srcdir)/rsyncd.conf.5: $(srcdir)/rsyncd.conf.yo
|
||||
yodl2man -o $(srcdir)/rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
|
||||
man:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
|
||||
|
||||
proto:
|
||||
cat $(srcdir)/*.c $(srcdir)/lib/compat.c | awk -f $(srcdir)/mkproto.awk > $(srcdir)/proto.h
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
|
||||
|
||||
clean: cleantests
|
||||
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS)
|
||||
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
mkrounding mkrounding.h rounding.h
|
||||
|
||||
cleantests:
|
||||
rm -rf ./testtmp*
|
||||
@@ -142,13 +144,9 @@ finddead:
|
||||
|
||||
test: check
|
||||
|
||||
|
||||
# There seems to be no standard way to specify some variables as
|
||||
# exported from a Makefile apart from listing them like this.
|
||||
|
||||
# TODO: Tests that depend on built test aide programs like tls need to
|
||||
# know where the build directory is.
|
||||
|
||||
# This depends on building rsync; if we need any helper programs it
|
||||
# should depend on them too.
|
||||
|
||||
@@ -156,18 +154,27 @@ test: check
|
||||
# catch Bash-isms earlier even if we're running on GNU. Of course, we
|
||||
# might lose in the future where POSIX diverges from old sh.
|
||||
|
||||
check: all $(CHECK_PROGS)
|
||||
POSIXLY_CORRECT=1 TOOLDIR=`pwd` rsync_bin=`pwd`/rsync$(EXEEXT) srcdir="$(srcdir)" $(srcdir)/runtests.sh
|
||||
check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
|
||||
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh
|
||||
|
||||
check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
|
||||
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
|
||||
|
||||
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
|
||||
wildtest$(EXEEXT): wildtest.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o @BUILD_POPT@ $(LIBS)
|
||||
wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
|
||||
|
||||
testsuite/chown-fake.test:
|
||||
ln -s chown.test $(srcdir)/testsuite/chown-fake.test
|
||||
|
||||
testsuite/devices-fake.test:
|
||||
ln -s devices.test $(srcdir)/testsuite/devices-fake.test
|
||||
|
||||
# This does *not* depend on building or installing: you can use it to
|
||||
# check a version installed from a binary or some other source tree,
|
||||
# if you want.
|
||||
|
||||
installcheck: $(CHECK_PROGS)
|
||||
installcheck: $(CHECK_PROGS) $(CHECK_SYMLINKS)
|
||||
POSIXLY_CORRECT=1 TOOLDIR=`pwd` rsync_bin="$(bindir)/rsync$(EXEEXT)" srcdir="$(srcdir)" $(srcdir)/runtests.sh
|
||||
|
||||
# TODO: Add 'dist' target; need to know which files will be included
|
||||
|
||||
347
NEWS
347
NEWS
@@ -1,229 +1,232 @@
|
||||
NEWS for rsync 2.6.2 (30 Apr 2004)
|
||||
Protocol: 28 (unchanged)
|
||||
Changes since 2.6.1:
|
||||
NEWS for rsync 3.0.0 (UNRELEASED)
|
||||
Protocol: 30 (changed)
|
||||
Changes since 2.6.9:
|
||||
|
||||
NOTABLE CHANGES IN BEHAVIOR:
|
||||
|
||||
- The handling of implied directories when using --relative has changed to
|
||||
send them as directories (e.g. no implied dir is ever sent as a symlink).
|
||||
This avoids unexpected behavior and should not adversely affect most
|
||||
people. If you're one of those rare people who relied upon having an
|
||||
implied dir be duplicated as a symlink, you should specify the transfer
|
||||
of the symlink and the transfer of the referent directory as separate
|
||||
args. (See also --keep-dirlinks and --no-implied-dirs.)
|
||||
|
||||
- Requesting a remote file list without specifying -r (--recursive) now
|
||||
sends the -d (--dirs) option to the remote rsync rather than sending -r
|
||||
along with an extra exclude of /*/*. If the remote rsync does not
|
||||
understand the -d option (i.e. it is 2.6.3 or older), you will need to
|
||||
either turn off -d (--no-d), or specify -r --exclude='/*/*' manually.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Fixed a major bug in the sorting of the filenames when --relative
|
||||
is used for some sources (just sources such as "/" and "/*" were
|
||||
affected). This fix ensures that we ask for the right file-list
|
||||
item when requesting changes from the sender.
|
||||
- Fixed the output of -ii when combined with one of the --*-dest options:
|
||||
it now itemizes all the items, not just the changed ones.
|
||||
|
||||
- Rsync now checks the return value of the close() function to
|
||||
better report disk-full problems on an NFS file system.
|
||||
- Made the output of all file types consistent when using a --*-dest
|
||||
option. Prior versions used to output too many creation events for
|
||||
matching items.
|
||||
|
||||
- Restored the old daemon-server behavior of logging error messages
|
||||
rather than returning them to the user. (A better long-term fix
|
||||
will be sought in the future.)
|
||||
- The code that waits for a child pid now handles being interrupted by a
|
||||
signal. This fixes a problem with the pre-xfer exec function not being
|
||||
able to get the exit status from the script.
|
||||
|
||||
- An obscure uninitialized-variable bug was fixed in the uid/gid
|
||||
code. (This bug probably had no ill effects.)
|
||||
- A negated filter rule (with a '!' modifier) no longer loses the negation
|
||||
when sending the filter rules to the remote rsync.
|
||||
|
||||
- Got rid of the configure check for sys/sysctl.h (it wasn't used
|
||||
and was causing a problem on some systems). Also improved the
|
||||
broken-largefile-locking test to try to avoid failure due to an
|
||||
NFS build-dir.
|
||||
- Fixed a problem with the --out-format (aka --log-format) option %f: it
|
||||
would output superfluous directory information for a non-daemon rsync.
|
||||
|
||||
- Fixed a compile problem on systems that don't define
|
||||
AI_NUMERICHOST.
|
||||
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
|
||||
files (which includes local copies). Version 2.6.9 would complete the
|
||||
copy, but exit with an error when the receiver output its memory stats.
|
||||
|
||||
- Fixed a compile problem in the popt source for compilers that
|
||||
don't support __attribute__.
|
||||
- If --password-file is used on a non-daemon transfer, rsync now complains
|
||||
and exits. This should help users figure out that they can't use this
|
||||
option to control a remote shell's password prompt.
|
||||
|
||||
INTERNAL:
|
||||
- Make sure that directory permissions of a newly-created destination
|
||||
directory are handled right when --perms is left off.
|
||||
|
||||
- Improved the testsuite's "merge" test to work on OSF1.
|
||||
- The itemized output of a newly-created destination directory is now
|
||||
output as a creation event, not a change event.
|
||||
|
||||
- Two new diffs were added to the patches dir.
|
||||
- Improved --hard-link so that more corner cases are handled correctly
|
||||
when combined with options such as --link-dest and/or --ignore-existing.
|
||||
|
||||
|
||||
NEWS for rsync 2.6.1 (26 Apr 2004)
|
||||
Protocol: 28 (changed)
|
||||
Changes since 2.6.0:
|
||||
- The --append option no longer updates a file that has the same size.
|
||||
|
||||
SECURITY FIXES:
|
||||
- Fixed a bug when combining --backup and --backup-dir with --inplace:
|
||||
any missing backup directories are now created.
|
||||
|
||||
- Paths sent to an rsync daemon are more thoroughly sanitized when
|
||||
chroot is not used. If you're running a non-read-only rsync
|
||||
daemon with chroot disabled, *please upgrade*, ESPECIALLY if the
|
||||
user privs you run rsync under is anything above "nobody".
|
||||
- Fixed a bug when using --backup and --inplace with --whole-file or
|
||||
--read-batch: backup files are actually created now.
|
||||
|
||||
- Starting up an extra copy of an rsync daemon does not delete the pidfile
|
||||
for the running daemon -- if the pidfile exists, the extra program will
|
||||
exit with an error.
|
||||
|
||||
- The daemon pidfile is checked and created sooner in the startup sequence.
|
||||
|
||||
- If a daemon module's "path" value is not an absolute pathname, the code
|
||||
now makes it absolute internally (making it work properly).
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Lower memory use, more optimal transfer of data over the socket,
|
||||
and lower CPU usage (see the INTERNAL section for details).
|
||||
- A new incremental-recursion algorithm is now used when rsync is talking
|
||||
to another 3.x version. This starts the transfer going more quickly
|
||||
(before all the files have been found), and requires much less memory.
|
||||
See the --recursive option in the manpage for some restrictions.
|
||||
|
||||
- The RSYNC_PROXY environment variable can now contain a
|
||||
"USER:PASS@" prefix before the "HOST:PORT" information.
|
||||
(Bardur Arantsson)
|
||||
- Lowered memory use in the non-incremental-recursion algorithm for typical
|
||||
option values (usually saving from 21-29 bytes per file).
|
||||
|
||||
- The --progress output now mentions how far along in the transfer
|
||||
we are, including both a count of files transferred and a
|
||||
percentage of the total file-count that we've processed. It also
|
||||
shows better current-rate-of-transfer and remaining-transfer-time
|
||||
values.
|
||||
- The default --delete algorithm is now --delete-during when talking to a
|
||||
3.x rsync. This is a faster scan than using --delete-before (which is
|
||||
the default when talking to older rsync versions), and is compatible with
|
||||
the new incremental recursion mode.
|
||||
|
||||
- The configure script now accepts --with-rsyncd-conf=PATH to
|
||||
override the default value of the /etc/rsyncd.conf file.
|
||||
- Rsync now allows multiple remote-source args to be specified rather than
|
||||
having to rely on a special space-splitting side-effect of the remote-
|
||||
shell. Additional remote args must specify the same host or have an
|
||||
empty hostname, as seen here: :file1 ::module/file2. This means that
|
||||
local use of brace expansion now works: rsync -av host:path/{f1,f2} .
|
||||
|
||||
- Added a couple extra diffs in the "patches" dir, removed the ones
|
||||
that got applied, and rebuilt the rest.
|
||||
- Added the --protect-args (-s) option, that tells rsync to send most of
|
||||
the command-line args at the start of the transfer rather than as args
|
||||
to the remote-shell command. This protects them from space-splitting,
|
||||
and only interprets basic wildcard special shell characters (*?[).
|
||||
|
||||
- Documentation changes now attempt to describe some often mis-
|
||||
understood features more clearly.
|
||||
- Added the --delete-delay option, which is a more efficient way to delete
|
||||
files at the end of the transfer without needing a separate delete pass.
|
||||
|
||||
BUG FIXES:
|
||||
- Added the --acls (-A) option to preserve Access Control Lists. This is
|
||||
an improved version of the prior patch that was available, and it even
|
||||
supports OS X ACLs. (If you need to have backward compatibility with
|
||||
old, patched versions of rsync, apply the acls.diff file from the patches
|
||||
dir.)
|
||||
|
||||
- When -x (--one-file-system) is combined with -L (--copy-links) or
|
||||
--copy-unsafe-links, no symlinked files are skipped, even if the
|
||||
referent file is on a different filesystem.
|
||||
- Added the --xattrs (-X) option to preserver extended attributes. This is
|
||||
an improved version of the prior patch that was available. (If you need
|
||||
to have backward compatibility with old, patched versions of rsync, apply
|
||||
the xattrs.diff file from the patches dir.)
|
||||
|
||||
- The --link-dest code now works properly for a non-root user when
|
||||
(1) the UIDs of the source and destination differ and -o was
|
||||
specified, or (2) when the group of the source can't be used on
|
||||
the destination and -g was specified.
|
||||
- Added the --fake-super option that allows a non-super user to preserve
|
||||
all attributes of a file by using a special extended-attribute idiom.
|
||||
There is also an analogous "fake super" option for an rsync daemon.
|
||||
|
||||
- Fixed a bug in the handling of -H (hard-links) that might cause
|
||||
the expanded PATH/NAME value of the current item to get
|
||||
overwritten (due to an expanded-name caching bug).
|
||||
- Added the --iconv option, which allows rsync to convert filenames from
|
||||
one character-set to another during the transfer. The default is to make
|
||||
this feature available as long as your system has iconv_open(). If
|
||||
compilation fails, specify --disable-iconv to configure, and then
|
||||
rebuild. If you want rsync to perform character-set conversions by
|
||||
default, you can specify --enable-iconv=CONVERT_STRING with the default
|
||||
value for the --iconv option that you wish to use. For example,
|
||||
"--enable-iconv=." is a good choice. See the rsync manpage for an
|
||||
explanation of the --iconv option's settings.
|
||||
|
||||
- Added the --skip-compress=LIST option to override the default list of
|
||||
file suffixes that will not be compressed when using --compress.
|
||||
|
||||
- We now reset the "new data has been sent" flag at the start of
|
||||
each file we send. This makes sure that an interrupted transfer
|
||||
with the --partial option set doesn't keep a shorter temp file
|
||||
than the current basis file when no new data has been transfered
|
||||
over the wire for that file.
|
||||
- The daemon's default for "dont compress" was extended to include:
|
||||
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
|
||||
The matching routine was also optimized to run more quickly.
|
||||
|
||||
- Fixed a byte-order problem in --batch-mode on big-endian machines.
|
||||
(Jay Fenlason)
|
||||
- The --max-delete option now outputs a warning if it skipped any file
|
||||
deletions, including a count of how many deletions were skipped. (Older
|
||||
versions just silently stopped deleting things.)
|
||||
|
||||
- Fixed configure bug when running "./configure --disable-ipv6".
|
||||
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
|
||||
about extraneous files without deleting anything. If you're not sure
|
||||
what version the client is, you can use the less-obvious --max-delete=-1,
|
||||
as both old and new versions will treat that as the same request (though
|
||||
older versions don't warn).
|
||||
|
||||
- Fixed "make test" bug when build dir is not the source dir.
|
||||
- The --hard-link option now uses less memory on both the sending and
|
||||
receiving side for all protocol versions. For protocol 30, the use of a
|
||||
hashtable on the sending side allows us to more efficiently convey to the
|
||||
receiver what files are linked together. This reduces the amount of data
|
||||
sent over the socket by a considerable margin (rather than adding more
|
||||
data), and limits the in-memory storage of the device+inode information
|
||||
to just the sending side for the new protocol 30, or to the receiving
|
||||
side when speaking an older protocol (note that older rsync versions kept
|
||||
the device+inode information on both sides).
|
||||
|
||||
- When using --cvs-exclude, the exclude items we get from a
|
||||
per-directory's .cvsignore file once again only affect that one
|
||||
directory (not all following directories too). The items are also
|
||||
now properly word-split and parsed without any +/- prefix parsing.
|
||||
- The filter rules now support a perishable ("p") modifier that marks rules
|
||||
that should not have an effect in a directory that is being deleted. e.g.
|
||||
-f '-p .svn/' would only affect "live" .svn directories.
|
||||
|
||||
- When specifying the USER@HOST: prefix for a file, the USER part
|
||||
can now contain an '@', if needed (i.e. the last '@' is used to
|
||||
find the HOST, not the first).
|
||||
- If we get an error setting the time on a symlink, we don't complain about
|
||||
it anymore (since some operating systems don't support that, and it's not
|
||||
that important).
|
||||
|
||||
- Fixed some bugs in the handling of group IDs for non-root users:
|
||||
(1) It properly handles a group that the sender didn't have a name
|
||||
for (it would previously skip changing the group on any files in
|
||||
that group). (2) If --numeric-ids is used, rsync no longer
|
||||
attempts to set groups that the user doesn't have the permission
|
||||
to set.
|
||||
- Protocol 30 now uses MD5 checksums instead of MD4.
|
||||
|
||||
- Fixed the "refuse options" setting in the rsyncd.conf file.
|
||||
- Changed the --append option to not checksum the existing data in the
|
||||
destination file, which speeds up file appending.
|
||||
|
||||
- Improved the -x (--one-file-system) flag's handling of any mount-
|
||||
point directories we encounter. It is both more optimal (in that
|
||||
it no longer does a useless scan of the contents of the mount-
|
||||
point dirs) and also fixes a bug where a remapped mount of the
|
||||
original filesystem could get discovered in a subdir we should be
|
||||
ignoring.
|
||||
- Added the --append-verify option, which works like the older --append
|
||||
option (verifying the existing data in the destination file). For
|
||||
compatibility with older rsync versions, any use of --append that is
|
||||
talking protocol 29 or older will revert to the --append-verify method.
|
||||
|
||||
- Rsync no longer discards a double-slash at the start of a filename
|
||||
when trying to open the file. It also no longer constructs names
|
||||
that start with a double slash (unless the user supplied them).
|
||||
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
|
||||
that can be used to enhance the client side of a daemon connection.
|
||||
|
||||
- Path-specifying options to a daemon should now work the same with
|
||||
or without chroot turned on. Previously, such a option (such as
|
||||
--link-dest) would get its absolute path munged into a relative
|
||||
one if chroot was not on, making that setting fairly useless.
|
||||
Rsync now transforms the path into one that is based on the
|
||||
module's base dir when chroot is not enabled.
|
||||
- Improved the dashes and double-quotes in the nroff manpage output.
|
||||
|
||||
- Fixed compilation problem on Tru64 Unix (having to do with
|
||||
sockaddr.sa_len and sockaddr.sin_len).
|
||||
|
||||
- Fixed a compatibility problem interacting with older rsync
|
||||
versions that might send us an empty --suffix value without
|
||||
telling us that --backup-dir was specified.
|
||||
|
||||
- The "hosts allow" option for a daemon-over-remote-shell process
|
||||
now has improved support for IPv6 addresses and a fix for systems
|
||||
that have a length field in their socket structs.
|
||||
|
||||
- Fixed the ability to request an empty backup --suffix when sending
|
||||
files to an rsync daemon.
|
||||
- We now support a lot more --no-OPTION override options.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- Most of the I/O is now buffered, which results in a pretty large
|
||||
speedup when running under MS Windows. (Craig Barratt)
|
||||
- The file-list sorting algorithm now uses a sort that keeps any same-
|
||||
named items in the same order as they were specified. This allows
|
||||
rsync to always ensure that the first of the duplicates is the one
|
||||
that will be included in the copy. The new sort was also faster
|
||||
than the glibc version of qsort() and mergesort() in my testing.
|
||||
|
||||
- Optimizations to the name-handling/comparing code have made some
|
||||
significant reductions in user-CPU time for large file sets.
|
||||
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
|
||||
|
||||
- Some cleanup of the variable types make the code more consistent.
|
||||
- Fixed a build problem with older (2.x) versions of gcc.
|
||||
|
||||
- Reduced memory requirements of hard link preservation.
|
||||
(J.W. Schultz)
|
||||
- Added some isType() functions that make dealing with signed characters
|
||||
easier without forcing variables via casts.
|
||||
|
||||
- Implemented a new algorithm for hard-link handling that speeds up
|
||||
the code significantly. (J.W. Schultz and Wayne Davison)
|
||||
- Changed strcat/strcpy/sprintf function calls to use safer versions.
|
||||
|
||||
- The --hard-link option now uses the first existing file in the
|
||||
group of linked files as the basis for the transfer. This
|
||||
prevents the sub-optimal transfer of a file's data when a new
|
||||
hardlink is added on the sending side and it sorts alphabetically
|
||||
earlier in the list than the files that are already present on the
|
||||
receiving side.
|
||||
- Upgraded the included popt version to 1.10.2 and improved its use of
|
||||
string-handling functions.
|
||||
|
||||
- Dropped support for protocol versions less than 20 (2.3.0 released
|
||||
15 Mar 1999) and activated warnings for protocols less than 25
|
||||
(2.5.0 released 23 Aug 2001). (Wayne Davison and J.W. Schultz,
|
||||
severally)
|
||||
- Added missing prototypes for compatibility functions from the lib dir.
|
||||
|
||||
- More optimal data transmission for --hard-links (protocol 28).
|
||||
- Configure determines if iconv() has a const arg, allowing us to avoid a
|
||||
compiler warning.
|
||||
|
||||
- More optimal data transmission for --checksum (protocol 28).
|
||||
- Made the sending of some numbers more efficient for protocol 30.
|
||||
|
||||
- Less memory is used when --checksum is specified.
|
||||
- Make sure that a daemon process doesn't mind if the client was weird and
|
||||
omitted the --server option.
|
||||
|
||||
- Less memory is used in the file list (a per-file savings).
|
||||
- Improved the use of "const" on pointers.
|
||||
|
||||
- The generator is now better about not modifying the file list
|
||||
during the transfer in order to avoid a copy-on-write memory
|
||||
bifurcation (on systems where fork() uses shared memory).
|
||||
Previously, rsync's shared memory would slowly become unshared,
|
||||
resulting in real memory usage nearly doubling on the receiving
|
||||
side by the end of the transfer. Now, as long as permissions
|
||||
are being preserved, the shared memory should remain that way
|
||||
for the entire transfer.
|
||||
- Improved J.W.'s pool_alloc routines to add a way of freeing older
|
||||
sections of a pool's memory.
|
||||
|
||||
- Changed hardlink info and file_struct + strings to use allocation
|
||||
pools. This reduces memory use for large file-sets and permits
|
||||
freeing memory to the OS. (J.W. Schultz)
|
||||
DEVELOPER RELATED:
|
||||
|
||||
- The 2 pipes used between the receiver and generator processes
|
||||
(which are forked on the same machine) were reduced to 1 pipe and
|
||||
the protocol improved so that (1) it is now impossible to have the
|
||||
"redo" pipe fill up and hang rsync, and (2) trailing messages from
|
||||
the receiver don't get lost on their way through the generator
|
||||
over to the sender (which mainly affected hard-link messages and
|
||||
verbose --stats output).
|
||||
- Rsync is now licensed under the GPLv3 or later.
|
||||
|
||||
- Improved the internal uid/gid code to be more portable and a
|
||||
little more optimized.
|
||||
- When running the tests, we now put our per-test temp dirs into a sub-
|
||||
directory named testtmp (which is created, if missing). This allows
|
||||
someone to symlink the testtmp directory to another filesystem (which is
|
||||
useful if the build dir's filesystem does not support ACLs and xattrs,
|
||||
and another file system does).
|
||||
|
||||
- The device numbers sent when using --devices are now sent as
|
||||
separate major/minor values with 32-bit accuracy (protocol 28).
|
||||
Previously, the copied devices were sent as a single 32-bit
|
||||
number. This will make inter-operation of 64-bit binaries more
|
||||
compatible with their 32-bit brethren (with both ends of the
|
||||
connection are using protocol 28). Note that optimizations in the
|
||||
binary protocol for sending the device numbers often results in
|
||||
fewer bytes being used than before, even though more precision is
|
||||
now available.
|
||||
|
||||
- Some cleanup of the exclude/include structures and its code made
|
||||
things clearer (internally), simpler, and more efficient.
|
||||
|
||||
- The reading & writing of the file-list in batch-mode is now
|
||||
handled by the same code that sends & receives the list over the
|
||||
wire. This makes it much easier to maintain. (Note that the
|
||||
batch code is still considered to be experimental.)
|
||||
- Rsync now has a way of handling protocol-version changes during the
|
||||
development of a new protocol version. This causes any out-of-sync
|
||||
versions to speak an older protocol rather than fail in a cryptic manner.
|
||||
This addition makes it safe to deploy a pre-release version that may
|
||||
interact with the public. This new exchange of sub-version info does not
|
||||
interfere with the {MIN,MAX}_PROTOCOL_VERSION checking algorithm (which
|
||||
does not have enough range to allow the main protocol number to be
|
||||
incremented for every minor tweak in that happens during development).
|
||||
|
||||
27
README
27
README
@@ -1,7 +1,7 @@
|
||||
WHAT IS RSYNC?
|
||||
--------------
|
||||
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
rsync is a replacement for scp/rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
@@ -29,9 +29,9 @@ and see the manual for more information.
|
||||
SETUP
|
||||
-----
|
||||
|
||||
Rsync normally uses rsh or ssh for communication. It does not need to
|
||||
Rsync normally uses ssh or rsh for communication. It does not need to
|
||||
be setuid and requires no special privileges for installation. You
|
||||
must, however, have a working rsh or ssh system. Using ssh is
|
||||
must, however, have a working ssh or rsh system. Using ssh is
|
||||
recommended for its security features.
|
||||
|
||||
Alternatively, rsync can run in `daemon' mode, listening on a socket.
|
||||
@@ -51,13 +51,13 @@ case.
|
||||
Once built put a copy of rsync in your search path on the local and
|
||||
remote systems (or use "make install"). That's it!
|
||||
|
||||
RSYNC SERVERS
|
||||
RSYNC DAEMONS
|
||||
-------------
|
||||
|
||||
rsync can also talk to "rsync servers" which can provide anonymous or
|
||||
rsync can also talk to "rsync daemons" which can provide anonymous or
|
||||
authenticated rsync. See the rsyncd.conf(5) man page for details on how
|
||||
to setup a rsync server. See the rsync(1) man page for info on how to
|
||||
connect to a rsync server.
|
||||
to setup an rsync daemon. See the rsync(1) man page for info on how to
|
||||
connect to an rsync daemon.
|
||||
|
||||
|
||||
MAILING LIST
|
||||
@@ -69,7 +69,7 @@ versions on this list.
|
||||
|
||||
To join the mailing list see the web page at http://lists.samba.org/
|
||||
|
||||
To send mail to everyone on the list send it to rsync@samba.org
|
||||
To send mail to everyone on the list send it to rsync@lists.samba.org
|
||||
|
||||
|
||||
BUG REPORTS
|
||||
@@ -77,7 +77,7 @@ BUG REPORTS
|
||||
|
||||
If you have web access then please look at
|
||||
|
||||
http://rsync.samba.org
|
||||
http://rsync.samba.org/
|
||||
|
||||
That page contains links to the current bug list, and information on
|
||||
how to report a bug well. You might also like to try searching the
|
||||
@@ -86,9 +86,11 @@ mailing list archives at
|
||||
|
||||
http://mail-archive.com/rsync@lists.samba.org/
|
||||
|
||||
Please send bug reports to
|
||||
To send a bug report, follow the instructions on the bug-tracking
|
||||
page of the web site.
|
||||
|
||||
rsync@lists.samba.org
|
||||
If you don't have web access, email your bug report to
|
||||
rsync@lists.samba.org.
|
||||
|
||||
|
||||
CVS TREE
|
||||
@@ -103,8 +105,7 @@ recent version of cvs then use the following commands:
|
||||
|
||||
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot co rsync
|
||||
|
||||
Look at the cvs documentation, or http://samba.org/cvs.html, for more
|
||||
details.
|
||||
Look at the cvs documentation for more details.
|
||||
|
||||
|
||||
COPYRIGHT
|
||||
|
||||
380
TODO
380
TODO
@@ -1,61 +1,38 @@
|
||||
-*- indented-text -*-
|
||||
|
||||
BUGS ---------------------------------------------------------------
|
||||
Fix progress indicator to not corrupt log
|
||||
lchmod question
|
||||
Do not rely on having a group called "nobody"
|
||||
Incorrect timestamps (Debian #100295)
|
||||
Win32
|
||||
|
||||
FEATURES ------------------------------------------------------------
|
||||
server-imposed bandwidth limits
|
||||
rsyncd over ssh
|
||||
Use chroot only if supported
|
||||
Allow supplementary groups in rsyncd.conf 2002/04/09
|
||||
Handling IPv6 on old machines
|
||||
Other IPv6 stuff:
|
||||
Other IPv6 stuff
|
||||
Add ACL support 2001/12/02
|
||||
Lazy directory creation
|
||||
proxy authentication 2002/01/23
|
||||
SOCKS 2002/01/23
|
||||
FAT support
|
||||
Allow forcing arbitrary permissions 2002/03/12
|
||||
--diff david.e.sewell 2002/03/15
|
||||
Add daemon --no-detach and --no-fork options
|
||||
Create more granular verbosity jw 2003/05/15
|
||||
Add daemon --no-fork option
|
||||
Create more granular verbosity 2003/05/15
|
||||
|
||||
DOCUMENTATION --------------------------------------------------------
|
||||
Update README
|
||||
Keep list of open issues and todos on the web site
|
||||
Update web site from CVS
|
||||
Perhaps redo manual as SGML
|
||||
|
||||
LOGGING --------------------------------------------------------------
|
||||
Make dry run list all updates 2002/04/03
|
||||
Memory accounting
|
||||
Improve error messages
|
||||
Better statistics: Rasmus 2002/03/08
|
||||
Better statistics Rasmus 2002/03/08
|
||||
Perhaps flush stdout like syslog
|
||||
Log deamon sessions that just list modules
|
||||
Log child death on signal
|
||||
Keep stderr and stdout properly separated (Debian #23626)
|
||||
Log errors with function that reports process of origin
|
||||
verbose output David Stein 2001/12/20
|
||||
Add reason for transfer to file logging
|
||||
debugging of daemon 2002/04/08
|
||||
internationalization
|
||||
|
||||
DEVELOPMENT --------------------------------------------------------
|
||||
Handling duplicate names
|
||||
Use generic zlib 2002/02/25
|
||||
TDB: 2002/03/12
|
||||
TDB 2002/03/12
|
||||
Splint 2002/03/12
|
||||
Memory debugger
|
||||
Create release script
|
||||
Add machines to build farm
|
||||
|
||||
PERFORMANCE ----------------------------------------------------------
|
||||
File list structure in memory
|
||||
Traverse just one directory at a time
|
||||
Allow skipping MD4 file_sum 2002/04/08
|
||||
Accelerate MD4
|
||||
@@ -67,8 +44,6 @@ Test on kernel source
|
||||
Test large files
|
||||
Create mutator program for testing
|
||||
Create configure option to enable dangerous tests
|
||||
If tests are skipped, say why.
|
||||
Test daemon feature to disallow particular options.
|
||||
Create pipe program for testing
|
||||
Create test makefile target for some tests
|
||||
|
||||
@@ -81,82 +56,8 @@ reverse rsync over HTTP Range
|
||||
|
||||
|
||||
|
||||
BUGS ---------------------------------------------------------------
|
||||
|
||||
Fix progress indicator to not corrupt log
|
||||
|
||||
Progress indicator can produce corrupt output when transferring directories:
|
||||
|
||||
main/binary-arm/
|
||||
main/binary-arm/admin/
|
||||
main/binary-arm/base/
|
||||
main/binary-arm/comm/8.56kB/s 0:00:52
|
||||
main/binary-arm/devel/
|
||||
main/binary-arm/doc/
|
||||
main/binary-arm/editors/
|
||||
main/binary-arm/electronics/s 0:00:53
|
||||
main/binary-arm/games/
|
||||
main/binary-arm/graphics/
|
||||
main/binary-arm/hamradio/
|
||||
main/binary-arm/interpreters/
|
||||
main/binary-arm/libs/6.61kB/s 0:00:54
|
||||
main/binary-arm/mail/
|
||||
main/binary-arm/math/
|
||||
main/binary-arm/misc/
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
lchmod question
|
||||
|
||||
I don't think we handle this properly on systems that don't have the
|
||||
call. Are there any such?
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Do not rely on having a group called "nobody"
|
||||
|
||||
http://www.linuxbase.org/spec/refspecs/LSB_1.1.0/gLSB/usernames.html
|
||||
|
||||
On Debian it's "nogroup"
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Incorrect timestamps (Debian #100295)
|
||||
|
||||
A bit hard to believe, but apparently it happens.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Win32
|
||||
|
||||
Don't detach, because this messes up --srvany.
|
||||
|
||||
http://sources.redhat.com/ml/cygwin/2001-08/msg00234.html
|
||||
|
||||
|
||||
|
||||
-- --
|
||||
|
||||
FEATURES ------------------------------------------------------------
|
||||
|
||||
server-imposed bandwidth limits
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
rsyncd over ssh
|
||||
|
||||
There are already some patches to do this.
|
||||
|
||||
BitKeeper uses a server whose login shell is set to bkd. That's
|
||||
probably a reasonable approach.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Use chroot only if supported
|
||||
|
||||
@@ -211,7 +112,7 @@ Handling IPv6 on old machines
|
||||
-- --
|
||||
|
||||
|
||||
Other IPv6 stuff:
|
||||
Other IPv6 stuff
|
||||
|
||||
Implement suggestions from http://www.kame.net/newsletter/19980604/
|
||||
and ftp://ftp.iij.ad.jp/pub/RFC/rfc2553.txt
|
||||
@@ -224,14 +125,6 @@ Other IPv6 stuff:
|
||||
multiple passive addresses. This might be a bit harder, because we
|
||||
may need to select on all of them. Hm.
|
||||
|
||||
Define a syntax for IPv6 literal addresses. Since they include
|
||||
colons, they tend to break most naming systems, including ours.
|
||||
Based on the HTTP IPv6 syntax, I think we should use
|
||||
|
||||
rsync://[::1]/foo/bar [::1]::bar
|
||||
|
||||
which should just take a small change to the parser code.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
@@ -240,15 +133,7 @@ Add ACL support 2001/12/02
|
||||
Transfer ACLs. Need to think of a standard representation.
|
||||
Probably better not to even try to convert between NT and POSIX.
|
||||
Possibly can share some code with Samba.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Lazy directory creation
|
||||
|
||||
With the current common --include '*/' --exclude '*' pattern, people
|
||||
can end up with many empty directories. We might avoid this by
|
||||
lazily creating such directories.
|
||||
NOTE: there is a patch that implements this in the "patches" subdir.
|
||||
|
||||
-- --
|
||||
|
||||
@@ -284,33 +169,6 @@ FAT support
|
||||
-- --
|
||||
|
||||
|
||||
Allow forcing arbitrary permissions 2002/03/12
|
||||
|
||||
On 12 Mar 2002, Dave Dykstra <dwd@bell-labs.com> wrote:
|
||||
> If we would add an option to do that functionality, I
|
||||
> would vote for one that was more general which could mask
|
||||
> off any set of permission bits and possibly add any set of
|
||||
> bits. Perhaps a chmod-like syntax if it could be
|
||||
> implemented simply.
|
||||
|
||||
I think that would be good too. For example, people uploading files
|
||||
to a web server might like to say
|
||||
|
||||
rsync -avzP --chmod a+rX ./ sourcefrog.net:/home/www/sourcefrog/
|
||||
|
||||
Ideally the patch would implement as many of the gnu chmod semantics
|
||||
as possible. I think the mode parser should be a separate function
|
||||
that passes back something like (mask,set) description to the rest
|
||||
of the program. For bonus points there would be a test case for the
|
||||
parser.
|
||||
|
||||
Possibly also --chown
|
||||
|
||||
(Debian #23628)
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
--diff david.e.sewell 2002/03/15
|
||||
|
||||
Allow people to specify the diff command. (Might want to use wdiff,
|
||||
@@ -326,7 +184,7 @@ Allow forcing arbitrary permissions 2002/03/12
|
||||
-- --
|
||||
|
||||
|
||||
Add daemon --no-detach and --no-fork options
|
||||
Add daemon --no-fork option
|
||||
|
||||
Very useful for debugging. Also good when running under a
|
||||
daemon-monitoring process that tries to restart the service when the
|
||||
@@ -335,7 +193,7 @@ Add daemon --no-detach and --no-fork options
|
||||
-- --
|
||||
|
||||
|
||||
Create more granular verbosity jw 2003/05/15
|
||||
Create more granular verbosity 2003/05/15
|
||||
|
||||
Control output with the --report option.
|
||||
|
||||
@@ -352,21 +210,12 @@ Create more granular verbosity jw 2003/05/15
|
||||
|
||||
DOCUMENTATION --------------------------------------------------------
|
||||
|
||||
Update README
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Keep list of open issues and todos on the web site
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Update web site from CVS
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Perhaps redo manual as SGML
|
||||
|
||||
The man page is getting rather large, and there is more information
|
||||
@@ -382,17 +231,6 @@ Perhaps redo manual as SGML
|
||||
|
||||
LOGGING --------------------------------------------------------------
|
||||
|
||||
Make dry run list all updates 2002/04/03
|
||||
|
||||
--dry-run is too dry
|
||||
|
||||
Mark Santcroos points out that -n fails to list files which have
|
||||
only metadata changes, though it probably should.
|
||||
|
||||
There may be a Debian bug about this as well.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Memory accounting
|
||||
|
||||
@@ -425,14 +263,10 @@ Improve error messages
|
||||
our load? (Debian #28416) Probably fixed now, but a test case would
|
||||
be good.
|
||||
|
||||
When running as a daemon, some errors should both be returned to the
|
||||
user and logged. This will make interacting with a daemon less
|
||||
cryptic.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Better statistics: Rasmus 2002/03/08
|
||||
Better statistics Rasmus 2002/03/08
|
||||
|
||||
<Rasmus>
|
||||
hey, how about an rsync option that just gives you the
|
||||
@@ -458,14 +292,6 @@ Perhaps flush stdout like syslog
|
||||
-- --
|
||||
|
||||
|
||||
Log deamon sessions that just list modules
|
||||
|
||||
At the connections that just get a list of modules are not logged,
|
||||
but they should be.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Log child death on signal
|
||||
|
||||
If a child of the rsync daemon dies with a signal, we should notice
|
||||
@@ -474,45 +300,14 @@ Log child death on signal
|
||||
-- --
|
||||
|
||||
|
||||
Keep stderr and stdout properly separated (Debian #23626)
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Log errors with function that reports process of origin
|
||||
|
||||
Use a separate function for reporting errors; prefix it with
|
||||
"rsync:" or "rsync(remote)", or perhaps even "rsync(local
|
||||
generator): ".
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
verbose output David Stein 2001/12/20
|
||||
|
||||
Indicate whether files are new, updated, or deleted
|
||||
|
||||
At end of transfer, show how many files were or were not transferred
|
||||
correctly.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Add reason for transfer to file logging
|
||||
|
||||
Explain *why* every file is transferred or not (e.g. "local mtime
|
||||
123123 newer than 1283198")
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
debugging of daemon 2002/04/08
|
||||
|
||||
Add an rsyncd.conf parameter to turn on debugging on the server.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
internationalization
|
||||
|
||||
Change to using gettext(). Probably need to ship this for platforms
|
||||
@@ -530,46 +325,16 @@ DEVELOPMENT --------------------------------------------------------
|
||||
|
||||
Handling duplicate names
|
||||
|
||||
We need to be careful of duplicate names getting into the file list.
|
||||
See clean_flist(). This could happen if multiple arguments include
|
||||
the same file. Bad.
|
||||
|
||||
I think duplicates are only a problem if they're both flowing
|
||||
through the pipeline at the same time. For example we might have
|
||||
updated the first occurrence after reading the checksums for the
|
||||
second. So possibly we just need to make sure that we don't have
|
||||
both in the pipeline at the same time.
|
||||
|
||||
Possibly if we did one directory at a time that would be sufficient.
|
||||
|
||||
Alternatively we could pre-process the arguments to make sure no
|
||||
duplicates will ever be inserted. There could be some bad cases
|
||||
when we're collapsing symlinks.
|
||||
|
||||
We could have a hash table.
|
||||
|
||||
The root of the problem is that we do not want more than one file
|
||||
list entry referring to the same file. At first glance there are
|
||||
several ways this could happen: symlinks, hardlinks, and repeated
|
||||
names on the command line.
|
||||
|
||||
If names are repeated on the command line, they may be present in
|
||||
different forms, perhaps by traversing directory paths in different
|
||||
ways, traversing paths including symlinks. Also we need to allow
|
||||
for expansion of globs by rsync.
|
||||
|
||||
At the moment, clean_flist() requires having the entire file list in
|
||||
memory. Duplicate names are detected just by a string comparison.
|
||||
|
||||
We don't need to worry about hard links causing duplicates because
|
||||
files are never updated in place. Similarly for symlinks.
|
||||
|
||||
I think even if we're using a different symlink mode we don't need
|
||||
to worry.
|
||||
|
||||
Unless we're really clever this will introduce a protocol
|
||||
incompatibility, so we need to be able to accept the old format as
|
||||
well.
|
||||
Some folks would like rsync to be deterministic in how it handles
|
||||
duplicate names that come from mering multiple source directories
|
||||
into a single destination directory; e.g. the last name wins. We
|
||||
could do this by switching our sort algorithm to one that will
|
||||
guarantee that the names won't be reordered. Alternately, we could
|
||||
assign an ever-increasing number to each item as we insert it into
|
||||
the list and then make sure that we leave the largest number when
|
||||
cleaning the file list (see clean_flist()). Another solution would
|
||||
be to add a hash table, and thus never put any duplicate names into
|
||||
the file list (and bump the protocol to handle this).
|
||||
|
||||
-- --
|
||||
|
||||
@@ -600,21 +365,6 @@ Use generic zlib 2002/02/25
|
||||
-- --
|
||||
|
||||
|
||||
TDB: 2002/03/12
|
||||
|
||||
Rather than storing the file list in memory, store it in a TDB.
|
||||
|
||||
This *might* make memory usage lower while building the file list.
|
||||
|
||||
Hashtable lookup will mean files are not transmitted in order,
|
||||
though... hm.
|
||||
|
||||
This would neatly eliminate one of the major post-fork shared data
|
||||
structures.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Splint 2002/03/12
|
||||
|
||||
Build rsync with SPLINT to try to find security holes. Add
|
||||
@@ -625,72 +375,8 @@ Splint 2002/03/12
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Memory debugger
|
||||
|
||||
jra recommends Valgrind:
|
||||
|
||||
http://devel-home.kde.org/~sewardj/
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Create release script
|
||||
|
||||
Script would:
|
||||
|
||||
Update spec files
|
||||
|
||||
Build tar file; upload
|
||||
|
||||
Send announcement to mailing list and c.o.l.a.
|
||||
|
||||
Make freshmeat announcement
|
||||
|
||||
Update web site
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Add machines to build farm
|
||||
|
||||
Cygwin (on different versions of Win32?)
|
||||
|
||||
HP-UX variants (via HP?)
|
||||
|
||||
SCO
|
||||
|
||||
|
||||
|
||||
-- --
|
||||
|
||||
PERFORMANCE ----------------------------------------------------------
|
||||
|
||||
File list structure in memory
|
||||
|
||||
Rather than one big array, perhaps have a tree in memory mirroring
|
||||
the directory tree.
|
||||
|
||||
This might make sorting much faster! (I'm not sure it's a big CPU
|
||||
problem, mind you.)
|
||||
|
||||
It might also reduce memory use in storing repeated directory names
|
||||
-- again I'm not sure this is a problem.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Traverse just one directory at a time
|
||||
|
||||
Traverse just one directory at a time. Tridge says it's possible.
|
||||
|
||||
At the moment rsync reads the whole file list into memory at the
|
||||
start, which makes us use a lot of memory and also not pipeline
|
||||
network access as much as we could.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Allow skipping MD4 file_sum 2002/04/08
|
||||
|
||||
If we're doing a local transfer, or using -W, then perhaps don't
|
||||
@@ -698,14 +384,10 @@ Allow skipping MD4 file_sum 2002/04/08
|
||||
calculating MD4 checksums uses 90% of CPU and is unlikely to be
|
||||
useful.
|
||||
|
||||
Indeed for transfers over zlib or ssh we can also rely on the
|
||||
transport to have quite strong protection against corruption.
|
||||
|
||||
Perhaps we should have an option to disable this,
|
||||
analogous to --whole-file, although it would default to
|
||||
disabled. The file checksum takes up a definite space in
|
||||
the protocol -- we can either set it to 0, or perhaps just
|
||||
leave it out.
|
||||
We should not allow it to be disabled separately from -W, though
|
||||
as it is the only thing that lets us know when the rsync algorithm
|
||||
got out of sync and messed the file up (i.e. if the basis file
|
||||
changed between checksum generation and reception).
|
||||
|
||||
-- --
|
||||
|
||||
@@ -784,16 +466,6 @@ Create configure option to enable dangerous tests
|
||||
-- --
|
||||
|
||||
|
||||
If tests are skipped, say why.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Test daemon feature to disallow particular options.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Create pipe program for testing
|
||||
|
||||
Create pipe program that makes slow/jerky connections for
|
||||
@@ -848,5 +520,9 @@ reverse rsync over HTTP Range
|
||||
Goswin Brederlow suggested this on Debian; I think tridge and I
|
||||
talked about it previous in relation to rproxy.
|
||||
|
||||
Addendum: It looks like someone is working on a version of this:
|
||||
|
||||
http://zsync.moria.org.uk/
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
134
access.c
134
access.c
@@ -1,32 +1,29 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
hosts allow/deny code for rsync
|
||||
|
||||
*/
|
||||
* Routines to authenticate access to a daemon (hosts allow/deny).
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
|
||||
static int match_hostname(char *host, char *tok)
|
||||
{
|
||||
if (!host || !*host) return 0;
|
||||
if (!host || !*host)
|
||||
return 0;
|
||||
return wildmatch(tok, host);
|
||||
}
|
||||
|
||||
@@ -34,16 +31,16 @@ static int match_binary(char *b1, char *b2, char *mask, int addrlen)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<addrlen; i++) {
|
||||
if ((b1[i]^b2[i])&mask[i]) {
|
||||
for (i = 0; i < addrlen; i++) {
|
||||
if ((b1[i] ^ b2[i]) & mask[i])
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void make_mask(char *mask, int plen, int addrlen) {
|
||||
static void make_mask(char *mask, int plen, int addrlen)
|
||||
{
|
||||
int w, b;
|
||||
|
||||
w = plen >> 3;
|
||||
@@ -75,22 +72,26 @@ static int match_address(char *addr, char *tok)
|
||||
char *a = NULL, *t = NULL;
|
||||
unsigned int len;
|
||||
|
||||
if (!addr || !*addr) return 0;
|
||||
if (!addr || !*addr)
|
||||
return 0;
|
||||
|
||||
p = strchr(tok,'/');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
len = p - tok;
|
||||
}
|
||||
else
|
||||
} else
|
||||
len = strlen(tok);
|
||||
|
||||
/* Fail quietly if tok is a hostname (not an address) */
|
||||
if (strspn(tok, ".0123456789") != len
|
||||
#ifdef INET6
|
||||
&& !strchr(tok, ':')
|
||||
&& strchr(tok, ':') == NULL
|
||||
#endif
|
||||
) return 0;
|
||||
) {
|
||||
if (p)
|
||||
*p = '/';
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
@@ -99,17 +100,18 @@ static int match_address(char *addr, char *tok)
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
#endif
|
||||
|
||||
gai = getaddrinfo(addr, NULL, &hints, &resa);
|
||||
if (gai) return 0;
|
||||
if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
|
||||
if (p)
|
||||
*p = '/';
|
||||
return 0;
|
||||
}
|
||||
|
||||
gai = getaddrinfo(tok, NULL, &hints, &rest);
|
||||
if (p)
|
||||
*p++ = '/';
|
||||
if (gai) {
|
||||
rprintf(FERROR,
|
||||
"error matching address %s: %s\n",
|
||||
tok,
|
||||
gai_strerror(gai));
|
||||
if (gai != 0) {
|
||||
rprintf(FLOG, "error matching address %s: %s\n",
|
||||
tok, gai_strerror(gai));
|
||||
freeaddrinfo(resa);
|
||||
return 0;
|
||||
}
|
||||
@@ -152,7 +154,7 @@ static int match_address(char *addr, char *tok)
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
rprintf(FERROR,"unknown family %u\n", rest->ai_family);
|
||||
rprintf(FLOG, "unknown family %u\n", rest->ai_family);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
@@ -169,14 +171,14 @@ static int match_address(char *addr, char *tok)
|
||||
#ifdef HAVE_STRTOL
|
||||
bits = strtol(p, &ep, 10);
|
||||
if (!*p || *ep) {
|
||||
rprintf(FERROR,"malformed mask in %s\n", tok);
|
||||
rprintf(FLOG, "malformed mask in %s\n", tok);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
for (pp = (unsigned char *)p; *pp; pp++) {
|
||||
if (!isascii(*pp) || !isdigit(*pp)) {
|
||||
rprintf(FERROR,"malformed mask in %s\n", tok);
|
||||
rprintf(FLOG, "malformed mask in %s\n", tok);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
@@ -188,7 +190,7 @@ static int match_address(char *addr, char *tok)
|
||||
goto out;
|
||||
}
|
||||
if (bits < 0 || bits > (addrlen << 3)) {
|
||||
rprintf(FERROR,"malformed mask in %s\n", tok);
|
||||
rprintf(FLOG, "malformed mask in %s\n", tok);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
@@ -202,7 +204,7 @@ static int match_address(char *addr, char *tok)
|
||||
|
||||
ret = match_binary(a, t, mask, addrlen);
|
||||
|
||||
out:
|
||||
out:
|
||||
freeaddrinfo(resa);
|
||||
freeaddrinfo(rest);
|
||||
return ret;
|
||||
@@ -213,12 +215,14 @@ static int access_match(char *list, char *addr, char *host)
|
||||
char *tok;
|
||||
char *list2 = strdup(list);
|
||||
|
||||
if (!list2) out_of_memory("access_match");
|
||||
if (!list2)
|
||||
out_of_memory("access_match");
|
||||
|
||||
strlower(list2);
|
||||
if (host) strlower(host);
|
||||
if (host)
|
||||
strlower(host);
|
||||
|
||||
for (tok=strtok(list2," ,\t"); tok; tok=strtok(NULL," ,\t")) {
|
||||
for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
|
||||
if (match_hostname(host, tok) || match_address(addr, tok)) {
|
||||
free(list2);
|
||||
return 1;
|
||||
@@ -231,29 +235,25 @@ static int access_match(char *list, char *addr, char *host)
|
||||
|
||||
int allow_access(char *addr, char *host, char *allow_list, char *deny_list)
|
||||
{
|
||||
/* if theres no deny list and no allow list then allow access */
|
||||
if ((!deny_list || !*deny_list) && (!allow_list || !*allow_list))
|
||||
return 1;
|
||||
if (allow_list && !*allow_list)
|
||||
allow_list = NULL;
|
||||
if (deny_list && !*deny_list)
|
||||
deny_list = NULL;
|
||||
|
||||
/* if there is an allow list but no deny list then allow only hosts
|
||||
on the allow list */
|
||||
if (!deny_list || !*deny_list)
|
||||
return(access_match(allow_list, addr, host));
|
||||
/* If we match an allow-list item, we always allow access. */
|
||||
if (allow_list) {
|
||||
if (access_match(allow_list, addr, host))
|
||||
return 1;
|
||||
/* For an allow-list w/o a deny-list, disallow non-matches. */
|
||||
if (!deny_list)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if theres a deny list but no allow list then allow
|
||||
all hosts not on the deny list */
|
||||
if (!allow_list || !*allow_list)
|
||||
return(!access_match(deny_list,addr,host));
|
||||
|
||||
/* if there are both type of list then allow all hosts on the
|
||||
allow list */
|
||||
if (access_match(allow_list,addr,host))
|
||||
return 1;
|
||||
|
||||
/* if there are both type of list and it's not on the allow then
|
||||
allow it if its not on the deny */
|
||||
if (access_match(deny_list,addr,host))
|
||||
/* If we match a deny-list item (and got past any allow-list
|
||||
* items), we always disallow access. */
|
||||
if (deny_list && access_match(deny_list, addr, host))
|
||||
return 0;
|
||||
|
||||
/* Allow all other access. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
332
authenticate.c
332
authenticate.c
@@ -1,38 +1,38 @@
|
||||
/* -*- c-file-style: "linux"; -*-
|
||||
|
||||
Copyright (C) 1998-2000 by Andrew Tridgell
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* Support rsync daemon authentication.
|
||||
*
|
||||
* Copyright (C) 1998-2000 Andrew Tridgell
|
||||
* Copyright (C) 2002-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* support rsync authentication */
|
||||
#include "rsync.h"
|
||||
|
||||
extern char *password_file;
|
||||
|
||||
/***************************************************************************
|
||||
encode a buffer using base64 - simple and slow algorithm. null terminates
|
||||
the result.
|
||||
***************************************************************************/
|
||||
void base64_encode(char *buf, int len, char *out)
|
||||
void base64_encode(const char *buf, int len, char *out, int pad)
|
||||
{
|
||||
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
int bit_offset, byte_offset, idx, i;
|
||||
unsigned char *d = (unsigned char *)buf;
|
||||
const uchar *d = (const uchar *)buf;
|
||||
int bytes = (len*8 + 5)/6;
|
||||
|
||||
memset(out, 0, bytes+1);
|
||||
|
||||
for (i = 0; i < bytes; i++) {
|
||||
byte_offset = (i*6)/8;
|
||||
bit_offset = (i*6)%8;
|
||||
@@ -46,233 +46,258 @@ void base64_encode(char *buf, int len, char *out)
|
||||
}
|
||||
out[i] = b64[idx];
|
||||
}
|
||||
|
||||
while (pad && (i % 4))
|
||||
out[i++] = '=';
|
||||
|
||||
out[i] = '\0';
|
||||
}
|
||||
|
||||
/* create a 16 byte challenge buffer */
|
||||
static void gen_challenge(char *addr, char *challenge)
|
||||
/* Generate a challenge buffer and return it base64-encoded. */
|
||||
static void gen_challenge(const char *addr, char *challenge)
|
||||
{
|
||||
char input[32];
|
||||
char digest[MAX_DIGEST_LEN];
|
||||
struct timeval tv;
|
||||
int len;
|
||||
|
||||
memset(input, 0, sizeof(input));
|
||||
memset(input, 0, sizeof input);
|
||||
|
||||
strlcpy((char *)input, addr, 17);
|
||||
strlcpy(input, addr, 17);
|
||||
sys_gettimeofday(&tv);
|
||||
SIVAL(input, 16, tv.tv_sec);
|
||||
SIVAL(input, 20, tv.tv_usec);
|
||||
SIVAL(input, 24, getpid());
|
||||
|
||||
sum_init();
|
||||
sum_update(input, sizeof(input));
|
||||
sum_end(challenge);
|
||||
sum_init(0);
|
||||
sum_update(input, sizeof input);
|
||||
len = sum_end(digest);
|
||||
|
||||
base64_encode(digest, len, challenge, 0);
|
||||
}
|
||||
|
||||
|
||||
/* return the secret for a user from the sercret file. maximum length
|
||||
is len. null terminate it */
|
||||
static int get_secret(int module, char *user, char *secret, int len)
|
||||
/* Return the secret for a user from the secret file, null terminated.
|
||||
* Maximum length is len (not counting the null). */
|
||||
static int get_secret(int module, const char *user, char *secret, int len)
|
||||
{
|
||||
char *fname = lp_secrets_file(module);
|
||||
int fd, found=0;
|
||||
char line[MAXPATHLEN];
|
||||
char *p, *pass=NULL;
|
||||
const char *fname = lp_secrets_file(module);
|
||||
STRUCT_STAT st;
|
||||
int ok = 1;
|
||||
extern int am_root;
|
||||
int fd, ok = 1;
|
||||
const char *p;
|
||||
char ch, *s;
|
||||
|
||||
if (!fname || !*fname) return 0;
|
||||
if (!fname || !*fname)
|
||||
return 0;
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) return 0;
|
||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
|
||||
if (do_stat(fname, &st) == -1) {
|
||||
rsyserr(FERROR, errno, "stat(%s)", fname);
|
||||
rsyserr(FLOG, errno, "stat(%s)", fname);
|
||||
ok = 0;
|
||||
} else if (lp_strict_modes(module)) {
|
||||
if ((st.st_mode & 06) != 0) {
|
||||
rprintf(FERROR,"secrets file must not be other-accessible (see strict modes option)\n");
|
||||
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
|
||||
ok = 0;
|
||||
} else if (am_root && (st.st_uid != 0)) {
|
||||
rprintf(FERROR,"secrets file must be owned by root when running as root (see strict modes)\n");
|
||||
} else if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
rprintf(FERROR,"continuing without secrets file\n");
|
||||
rprintf(FLOG, "continuing without secrets file\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!found) {
|
||||
int i = 0;
|
||||
memset(line, 0, sizeof line);
|
||||
while ((size_t) i < (sizeof(line)-1)) {
|
||||
if (read(fd, &line[i], 1) != 1) {
|
||||
memset(line, 0, sizeof(line));
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (line[i] == '\r') continue;
|
||||
if (line[i] == '\n') break;
|
||||
i++;
|
||||
}
|
||||
line[i] = 0;
|
||||
if (line[0] == '#') continue;
|
||||
p = strchr(line,':');
|
||||
if (!p) continue;
|
||||
*p = 0;
|
||||
if (strcmp(user, line)) continue;
|
||||
pass = p+1;
|
||||
found = 1;
|
||||
if (*user == '#') {
|
||||
/* Reject attempt to match a comment. */
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
if (!found) return 0;
|
||||
/* Try to find a line that starts with the user name and a ':'. */
|
||||
p = user;
|
||||
while (1) {
|
||||
if (read(fd, &ch, 1) != 1) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (ch == '\n')
|
||||
p = user;
|
||||
else if (p) {
|
||||
if (*p == ch)
|
||||
p++;
|
||||
else if (!*p && ch == ':')
|
||||
break;
|
||||
else
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Slurp the secret into the "secret" buffer. */
|
||||
s = secret;
|
||||
while (len > 0) {
|
||||
if (read(fd, s, 1) != 1 || *s == '\n')
|
||||
break;
|
||||
if (*s == '\r')
|
||||
continue;
|
||||
s++;
|
||||
len--;
|
||||
}
|
||||
*s = '\0';
|
||||
close(fd);
|
||||
|
||||
strlcpy(secret, pass, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *getpassf(char *filename)
|
||||
static const char *getpassf(const char *filename)
|
||||
{
|
||||
char buffer[100];
|
||||
int fd=0;
|
||||
STRUCT_STAT st;
|
||||
int ok = 1;
|
||||
extern int am_root;
|
||||
char *envpw=getenv("RSYNC_PASSWORD");
|
||||
char buffer[512], *p;
|
||||
int fd, n, ok = 1;
|
||||
const char *envpw = getenv("RSYNC_PASSWORD");
|
||||
|
||||
if (!filename) return NULL;
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
if ( (fd=open(filename,O_RDONLY)) == -1) {
|
||||
rsyserr(FERROR, errno, "could not open password file \"%s\"",filename);
|
||||
if (envpw) rprintf(FERROR,"falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
if ((fd = open(filename,O_RDONLY)) < 0) {
|
||||
rsyserr(FERROR, errno, "could not open password file \"%s\"",
|
||||
filename);
|
||||
if (envpw)
|
||||
rprintf(FERROR, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (do_stat(filename, &st) == -1) {
|
||||
rsyserr(FERROR, errno, "stat(%s)", filename);
|
||||
ok = 0;
|
||||
} else if ((st.st_mode & 06) != 0) {
|
||||
rprintf(FERROR,"password file must not be other-accessible\n");
|
||||
ok = 0;
|
||||
} else if (am_root && (st.st_uid != 0)) {
|
||||
} else if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
rprintf(FERROR,"password file must be owned by root when running as root\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (!ok) {
|
||||
rprintf(FERROR,"continuing without password file\n");
|
||||
if (envpw) rprintf(FERROR,"using RSYNC_PASSWORD environment variable.\n");
|
||||
if (envpw)
|
||||
rprintf(FERROR, "using RSYNC_PASSWORD environment variable.\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (envpw) rprintf(FERROR,"RSYNC_PASSWORD environment variable ignored\n");
|
||||
if (envpw)
|
||||
rprintf(FERROR, "RSYNC_PASSWORD environment variable ignored\n");
|
||||
|
||||
buffer[sizeof(buffer)-1]='\0';
|
||||
if (read(fd,buffer,sizeof(buffer)-1) > 0)
|
||||
{
|
||||
char *p = strtok(buffer,"\n\r");
|
||||
close(fd);
|
||||
if (p) p = strdup(p);
|
||||
return p;
|
||||
}
|
||||
n = read(fd, buffer, sizeof buffer - 1);
|
||||
close(fd);
|
||||
if (n > 0) {
|
||||
buffer[n] = '\0';
|
||||
if ((p = strtok(buffer, "\n\r")) != NULL)
|
||||
return strdup(p);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* generate a 16 byte hash from a password and challenge */
|
||||
static void generate_hash(char *in, char *challenge, char *out)
|
||||
/* Generate an MD4 hash created from the combination of the password
|
||||
* and the challenge string and return it base64-encoded. */
|
||||
static void generate_hash(const char *in, const char *challenge, char *out)
|
||||
{
|
||||
char buf[16];
|
||||
char buf[MAX_DIGEST_LEN];
|
||||
int len;
|
||||
|
||||
sum_init();
|
||||
sum_init(0);
|
||||
sum_update(in, strlen(in));
|
||||
sum_update(challenge, strlen(challenge));
|
||||
sum_end(buf);
|
||||
len = sum_end(buf);
|
||||
|
||||
base64_encode(buf, 16, out);
|
||||
base64_encode(buf, len, out, 0);
|
||||
}
|
||||
|
||||
/* possible negotiate authentication with the client. Use "leader" to
|
||||
start off the auth if necessary
|
||||
|
||||
return NULL if authentication failed
|
||||
|
||||
return "" if anonymous access
|
||||
|
||||
otherwise return username
|
||||
*/
|
||||
char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
|
||||
/* Possibly negotiate authentication with the client. Use "leader" to
|
||||
* start off the auth if necessary.
|
||||
*
|
||||
* Return NULL if authentication failed. Return "" if anonymous access.
|
||||
* Otherwise return username.
|
||||
*/
|
||||
char *auth_server(int f_in, int f_out, int module, const char *host,
|
||||
const char *addr, const char *leader)
|
||||
{
|
||||
char *users = lp_auth_users(module);
|
||||
char challenge[16];
|
||||
char b64_challenge[30];
|
||||
char line[MAXPATHLEN];
|
||||
static char user[100];
|
||||
char secret[100];
|
||||
char pass[30];
|
||||
char pass2[30];
|
||||
char *tok;
|
||||
char challenge[MAX_DIGEST_LEN*2];
|
||||
char line[BIGPATHBUFLEN];
|
||||
char secret[512];
|
||||
char pass2[MAX_DIGEST_LEN*2];
|
||||
char *tok, *pass;
|
||||
|
||||
/* if no auth list then allow anyone in! */
|
||||
if (!users || !*users) return "";
|
||||
if (!users || !*users)
|
||||
return "";
|
||||
|
||||
gen_challenge(addr, challenge);
|
||||
|
||||
base64_encode(challenge, 16, b64_challenge);
|
||||
|
||||
io_printf(f_out, "%s%s\n", leader, b64_challenge);
|
||||
io_printf(f_out, "%s%s\n", leader, challenge);
|
||||
|
||||
if (!read_line(f_in, line, sizeof(line)-1)) {
|
||||
if (!read_line_old(f_in, line, sizeof line)
|
||||
|| (pass = strchr(line, ' ')) == NULL) {
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"invalid challenge response\n",
|
||||
lp_name(module), host, addr);
|
||||
return NULL;
|
||||
}
|
||||
*pass++ = '\0';
|
||||
|
||||
memset(user, 0, sizeof(user));
|
||||
memset(pass, 0, sizeof(pass));
|
||||
if (!(users = strdup(users)))
|
||||
out_of_memory("auth_server");
|
||||
|
||||
if (sscanf(line,"%99s %29s", user, pass) != 2) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
users = strdup(users);
|
||||
if (!users) return NULL;
|
||||
|
||||
for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
|
||||
if (wildmatch(tok, user)) break;
|
||||
for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
|
||||
if (wildmatch(tok, line))
|
||||
break;
|
||||
}
|
||||
free(users);
|
||||
|
||||
if (!tok) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(secret, 0, sizeof(secret));
|
||||
if (!get_secret(module, user, secret, sizeof(secret)-1)) {
|
||||
memset(secret, 0, sizeof(secret));
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"unauthorized user\n",
|
||||
lp_name(module), host, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
generate_hash(secret, b64_challenge, pass2);
|
||||
memset(secret, 0, sizeof(secret));
|
||||
|
||||
if (strcmp(pass, pass2) == 0)
|
||||
return user;
|
||||
memset(secret, 0, sizeof secret);
|
||||
if (!get_secret(module, line, secret, sizeof secret - 1)) {
|
||||
memset(secret, 0, sizeof secret);
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"missing secret for user \"%s\"\n",
|
||||
lp_name(module), host, addr, line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
generate_hash(secret, challenge, pass2);
|
||||
memset(secret, 0, sizeof secret);
|
||||
|
||||
if (strcmp(pass, pass2) != 0) {
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"password mismatch\n",
|
||||
lp_name(module), host, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return strdup(line);
|
||||
}
|
||||
|
||||
|
||||
void auth_client(int fd, char *user, char *challenge)
|
||||
void auth_client(int fd, const char *user, const char *challenge)
|
||||
{
|
||||
char *pass;
|
||||
char pass2[30];
|
||||
extern char *password_file;
|
||||
const char *pass;
|
||||
char pass2[MAX_DIGEST_LEN*2];
|
||||
|
||||
if (!user || !*user)
|
||||
user = "nobody";
|
||||
|
||||
if (!(pass=getpassf(password_file)) && !(pass=getenv("RSYNC_PASSWORD"))) {
|
||||
if (!(pass = getpassf(password_file))
|
||||
&& !(pass = getenv("RSYNC_PASSWORD"))) {
|
||||
/* XXX: cyeoh says that getpass is deprecated, because
|
||||
* it may return a truncated password on some systems,
|
||||
* and it is not in the LSB.
|
||||
@@ -285,12 +310,9 @@ void auth_client(int fd, char *user, char *challenge)
|
||||
pass = getpass("Password: ");
|
||||
}
|
||||
|
||||
if (!pass || !*pass) {
|
||||
if (!pass)
|
||||
pass = "";
|
||||
}
|
||||
|
||||
generate_hash(pass, challenge, pass2);
|
||||
io_printf(fd, "%s %s\n", user, pass2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
329
backup.c
329
backup.c
@@ -1,59 +1,89 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1999
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* backup handling code */
|
||||
* Backup handling code.
|
||||
*
|
||||
* Copyright (C) 1999 Andrew Tridgell
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int backup_suffix_len;
|
||||
extern int am_root;
|
||||
extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_specials;
|
||||
extern int preserve_links;
|
||||
extern int safe_symlinks;
|
||||
extern int backup_dir_len;
|
||||
extern unsigned int backup_dir_remainder;
|
||||
extern char backup_dir_buf[MAXPATHLEN];
|
||||
extern char *backup_suffix;
|
||||
extern char *backup_dir;
|
||||
|
||||
extern int am_root;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_links;
|
||||
extern int preserve_hard_links;
|
||||
extern int orig_umask;
|
||||
/* make a complete pathname for backup file */
|
||||
char *get_backup_name(const char *fname)
|
||||
{
|
||||
if (backup_dir) {
|
||||
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
|
||||
fname, backup_suffix, NULL) < backup_dir_remainder)
|
||||
return backup_dir_buf;
|
||||
} else {
|
||||
if (stringjoin(backup_dir_buf, MAXPATHLEN,
|
||||
fname, backup_suffix, NULL) < MAXPATHLEN)
|
||||
return backup_dir_buf;
|
||||
}
|
||||
|
||||
rprintf(FERROR, "backup filename too long\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* simple backup creates a backup with a suffix in the same directory */
|
||||
static int make_simple_backup(char *fname)
|
||||
static int make_simple_backup(const char *fname)
|
||||
{
|
||||
char fnamebak[MAXPATHLEN];
|
||||
int rename_errno;
|
||||
const char *fnamebak = get_backup_name(fname);
|
||||
|
||||
if (stringjoin(fnamebak, sizeof fnamebak, fname, backup_suffix, NULL)
|
||||
>= sizeof fnamebak) {
|
||||
rprintf(FERROR, "backup filename too long\n");
|
||||
if (!fnamebak)
|
||||
return 0;
|
||||
|
||||
while (1) {
|
||||
if (do_rename(fname, fnamebak) == 0) {
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "backed up %s to %s\n",
|
||||
fname, fnamebak);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* cygwin (at least version b19) reports EINVAL */
|
||||
if (errno == ENOENT || errno == EINVAL)
|
||||
break;
|
||||
|
||||
rename_errno = errno;
|
||||
if (errno == EISDIR && do_rmdir(fnamebak) == 0)
|
||||
continue;
|
||||
if (errno == ENOTDIR && do_unlink(fnamebak) == 0)
|
||||
continue;
|
||||
|
||||
rsyserr(FERROR, rename_errno, "rename %s to backup %s",
|
||||
fname, fnamebak);
|
||||
errno = rename_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (do_rename(fname, fnamebak) != 0) {
|
||||
/* cygwin (at least version b19) reports EINVAL */
|
||||
if (errno != ENOENT && errno != EINVAL) {
|
||||
rsyserr(FERROR, errno, "rename %s to backup %s", fname, fnamebak);
|
||||
return 0;
|
||||
}
|
||||
} else if (verbose > 1) {
|
||||
rprintf(FINFO, "backed up %s to %s\n", fname, fnamebak);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -62,31 +92,37 @@ static int make_simple_backup(char *fname)
|
||||
Create a directory given an absolute path, perms based upon another directory
|
||||
path
|
||||
****************************************************************************/
|
||||
static int make_bak_dir(char *fullpath)
|
||||
int make_bak_dir(const char *fullpath)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
char *rel = fullpath + backup_dir_len;
|
||||
char *end = rel + strlen(rel);
|
||||
char *p = end;
|
||||
char fbuf[MAXPATHLEN], *rel, *end, *p;
|
||||
struct file_struct *file;
|
||||
int len = backup_dir_len;
|
||||
stat_x sx;
|
||||
|
||||
while (strncmp(fullpath, "./", 2) == 0)
|
||||
while (*fullpath == '.' && fullpath[1] == '/') {
|
||||
fullpath += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
if (strlcpy(fbuf, fullpath, sizeof fbuf) >= sizeof fbuf)
|
||||
return -1;
|
||||
|
||||
rel = fbuf + len;
|
||||
end = p = rel + strlen(rel);
|
||||
|
||||
/* Try to find an existing dir, starting from the deepest dir. */
|
||||
while (1) {
|
||||
if (--p == fullpath) {
|
||||
p += strlen(p);
|
||||
goto failure;
|
||||
}
|
||||
if (--p == fbuf)
|
||||
return -1;
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
if (do_mkdir(fullpath, 0777 & ~orig_umask) == 0)
|
||||
if (mkdir_defmode(fbuf) == 0)
|
||||
break;
|
||||
if (errno != ENOENT) {
|
||||
rprintf(FERROR,
|
||||
"make_bak_dir mkdir %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
goto failure;
|
||||
rsyserr(FERROR, errno,
|
||||
"make_bak_dir mkdir %s failed",
|
||||
full_fname(fbuf));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,42 +132,57 @@ static int make_bak_dir(char *fullpath)
|
||||
if (p >= rel) {
|
||||
/* Try to transfer the directory settings of the
|
||||
* actual dir that the files are coming from. */
|
||||
if (do_lstat(rel, &st) != 0) {
|
||||
rprintf(FERROR,
|
||||
"make_bak_dir stat %s failed: %s\n",
|
||||
full_fname(rel), strerror(errno));
|
||||
if (x_stat(rel, &sx.st, NULL) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"make_bak_dir stat %s failed",
|
||||
full_fname(rel));
|
||||
} else {
|
||||
set_modtime(fullpath, st.st_mtime);
|
||||
do_lchown(fullpath, st.st_uid, st.st_gid);
|
||||
do_chmod(fullpath, st.st_mode);
|
||||
#ifdef SUPPORT_ACLS
|
||||
sx.acc_acl = sx.def_acl = NULL;
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
sx.xattr = NULL;
|
||||
#endif
|
||||
if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
|
||||
continue;
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode)) {
|
||||
get_acl(rel, &sx);
|
||||
cache_acl(file, &sx);
|
||||
free_acl(&sx);
|
||||
}
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs) {
|
||||
get_xattr(rel, &sx);
|
||||
cache_xattr(file, &sx);
|
||||
free_xattr(&sx);
|
||||
}
|
||||
#endif
|
||||
set_file_attrs(fbuf, file, NULL, NULL, 0);
|
||||
unmake_file(file);
|
||||
}
|
||||
}
|
||||
*p = '/';
|
||||
p += strlen(p);
|
||||
if (p == end)
|
||||
break;
|
||||
if (do_mkdir(fullpath, 0777 & ~orig_umask) < 0) {
|
||||
rprintf(FERROR,
|
||||
"make_bak_dir mkdir %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
goto failure;
|
||||
if (mkdir_defmode(fbuf) < 0) {
|
||||
rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
|
||||
full_fname(fbuf));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
while (p != end) {
|
||||
*p = '/';
|
||||
p += strlen(p);
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* robustly move a file, creating new directory structures if necessary */
|
||||
static int robust_move(char *src, char *dst)
|
||||
static int robust_move(const char *src, char *dst)
|
||||
{
|
||||
if (robust_rename(src, dst, 0755) < 0 && (errno != ENOENT
|
||||
|| make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) < 0))
|
||||
if (robust_rename(src, dst, NULL, 0755) < 0
|
||||
&& (errno != ENOENT || make_bak_dir(dst) < 0
|
||||
|| robust_rename(src, dst, NULL, 0755) < 0))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -139,57 +190,76 @@ static int robust_move(char *src, char *dst)
|
||||
|
||||
/* If we have a --backup-dir, then we get here from make_backup().
|
||||
* We will move the file to be deleted into a parallel directory tree. */
|
||||
static int keep_backup(char *fname)
|
||||
static int keep_backup(const char *fname)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
stat_x sx;
|
||||
struct file_struct *file;
|
||||
char *buf;
|
||||
int kept = 0;
|
||||
int ret_code;
|
||||
|
||||
/* return if no file to keep */
|
||||
#if SUPPORT_LINKS
|
||||
if (do_lstat(fname, &st)) return 1;
|
||||
#else
|
||||
if (do_stat(fname, &st)) return 1;
|
||||
if (x_lstat(fname, &sx.st, NULL) < 0)
|
||||
return 1;
|
||||
#ifdef SUPPORT_ACLS
|
||||
sx.acc_acl = sx.def_acl = NULL;
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
sx.xattr = NULL;
|
||||
#endif
|
||||
|
||||
file = make_file(fname, NULL, NO_EXCLUDES);
|
||||
if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
|
||||
return 1; /* the file could have disappeared */
|
||||
|
||||
/* the file could have disappeared */
|
||||
if (!file) return 1;
|
||||
|
||||
/* make a complete pathname for backup file */
|
||||
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
|
||||
fname, backup_suffix, NULL) >= backup_dir_remainder) {
|
||||
rprintf(FERROR, "keep_backup filename too long\n");
|
||||
if (!(buf = get_backup_name(fname))) {
|
||||
unmake_file(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MKNOD
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode)) {
|
||||
get_acl(fname, &sx);
|
||||
cache_acl(file, &sx);
|
||||
free_acl(&sx);
|
||||
}
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs) {
|
||||
get_xattr(fname, &sx);
|
||||
cache_xattr(file, &sx);
|
||||
free_xattr(&sx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check to see if this is a device file, or link */
|
||||
if (IS_DEVICE(file->mode)) {
|
||||
if (am_root && preserve_devices) {
|
||||
make_bak_dir(backup_dir_buf);
|
||||
if (do_mknod(backup_dir_buf, file->mode, file->u.rdev) != 0) {
|
||||
rprintf(FERROR, "mknod %s failed: %s\n",
|
||||
full_fname(backup_dir_buf), strerror(errno));
|
||||
} else if (verbose > 2) {
|
||||
rprintf(FINFO,
|
||||
"make_backup: DEVICE %s successful.\n",
|
||||
fname);
|
||||
}
|
||||
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|
||||
|| (preserve_specials && IS_SPECIAL(file->mode))) {
|
||||
uint32 *devp = F_RDEV_P(file);
|
||||
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
|
||||
do_unlink(buf);
|
||||
if (do_mknod(buf, file->mode, rdev) < 0
|
||||
&& (errno != ENOENT || make_bak_dir(buf) < 0
|
||||
|| do_mknod(buf, file->mode, rdev) < 0)) {
|
||||
rsyserr(FERROR, errno, "mknod %s failed",
|
||||
full_fname(buf));
|
||||
} else if (verbose > 2) {
|
||||
rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
|
||||
fname);
|
||||
}
|
||||
kept = 1;
|
||||
do_unlink(fname);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!kept && S_ISDIR(file->mode)) {
|
||||
/* make an empty directory */
|
||||
make_bak_dir(backup_dir_buf);
|
||||
do_mkdir(backup_dir_buf, file->mode);
|
||||
ret_code = do_rmdir(fname);
|
||||
if (do_mkdir(buf, file->mode) < 0
|
||||
&& (errno != ENOENT || make_bak_dir(buf) < 0
|
||||
|| do_mkdir(buf, file->mode) < 0)) {
|
||||
rsyserr(FINFO, errno, "mkdir %s failed",
|
||||
full_fname(buf));
|
||||
}
|
||||
|
||||
ret_code = do_rmdir(fname);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
|
||||
full_fname(fname), ret_code);
|
||||
@@ -197,49 +267,60 @@ static int keep_backup(char *fname)
|
||||
kept = 1;
|
||||
}
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
#ifdef SUPPORT_LINKS
|
||||
if (!kept && preserve_links && S_ISLNK(file->mode)) {
|
||||
extern int safe_symlinks;
|
||||
if (safe_symlinks && unsafe_symlink(file->u.link, backup_dir_buf)) {
|
||||
const char *sl = F_SYMLINK(file);
|
||||
if (safe_symlinks && unsafe_symlink(sl, buf)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
|
||||
full_fname(backup_dir_buf), file->u.link);
|
||||
full_fname(buf), sl);
|
||||
}
|
||||
kept = 1;
|
||||
} else {
|
||||
do_unlink(buf);
|
||||
if (do_symlink(sl, buf) < 0
|
||||
&& (errno != ENOENT || make_bak_dir(buf) < 0
|
||||
|| do_symlink(sl, buf) < 0)) {
|
||||
rsyserr(FERROR, errno, "link %s -> \"%s\"",
|
||||
full_fname(buf), sl);
|
||||
}
|
||||
do_unlink(fname);
|
||||
kept = 1;
|
||||
}
|
||||
make_bak_dir(backup_dir_buf);
|
||||
if (do_symlink(file->u.link, backup_dir_buf) != 0) {
|
||||
rprintf(FERROR, "link %s -> %s : %s\n",
|
||||
full_fname(backup_dir_buf), file->u.link, strerror(errno));
|
||||
}
|
||||
do_unlink(fname);
|
||||
kept = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!kept && !S_ISREG(file->mode)) {
|
||||
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
|
||||
fname);
|
||||
unmake_file(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* move to keep tree if a file */
|
||||
if (!kept) {
|
||||
if (robust_move(fname, backup_dir_buf) != 0) {
|
||||
rprintf(FERROR, "keep_backup failed: %s -> \"%s\": %s\n",
|
||||
full_fname(fname), backup_dir_buf, strerror(errno));
|
||||
if (robust_move(fname, buf) != 0) {
|
||||
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
|
||||
full_fname(fname), buf);
|
||||
} else if (sx.st.st_nlink > 1) {
|
||||
/* If someone has hard-linked the file into the backup
|
||||
* dir, rename() might return success but do nothing! */
|
||||
robust_unlink(fname); /* Just in case... */
|
||||
}
|
||||
}
|
||||
set_perms(backup_dir_buf, file, NULL, 0);
|
||||
free(file);
|
||||
set_file_attrs(buf, file, NULL, fname, 0);
|
||||
unmake_file(file);
|
||||
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "keep_backup %s -> %s\n", fname, backup_dir_buf);
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "backed up %s to %s\n",
|
||||
fname, buf);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* main backup switch routine */
|
||||
int make_backup(char *fname)
|
||||
int make_backup(const char *fname)
|
||||
{
|
||||
if (backup_dir)
|
||||
return keep_backup(fname);
|
||||
|
||||
545
batch.c
545
batch.c
@@ -1,369 +1,230 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Weiss 1/1999
|
||||
Batch utilities for rsync.
|
||||
|
||||
*/
|
||||
/*
|
||||
* Support for the batch-file options.
|
||||
*
|
||||
* Copyright (C) 1999 Weiss
|
||||
* Copyright (C) 2004 Chris Shoemaker
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "zlib/zlib.h"
|
||||
#include <time.h>
|
||||
|
||||
extern char *batch_prefix;
|
||||
extern int csum_length;
|
||||
extern int eol_nulls;
|
||||
extern int recurse;
|
||||
extern int xfer_dirs;
|
||||
extern int preserve_links;
|
||||
extern int preserve_hard_links;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int always_checksum;
|
||||
extern int do_compression;
|
||||
extern int def_compress_level;
|
||||
extern int protocol_version;
|
||||
extern struct stats stats;
|
||||
extern char *batch_name;
|
||||
|
||||
struct file_list *batch_flist;
|
||||
extern struct filter_list_struct filter_list;
|
||||
|
||||
static char rsync_flist_file[] = ".rsync_flist";
|
||||
static char rsync_csums_file[] = ".rsync_csums";
|
||||
static char rsync_delta_file[] = ".rsync_delta";
|
||||
static char rsync_argvs_file[] = ".rsync_argvs";
|
||||
static int tweaked_compress_level;
|
||||
|
||||
static int f_csums = -1;
|
||||
static int f_delta = -1;
|
||||
static int *flag_ptr[] = {
|
||||
&recurse, /* 0 */
|
||||
&preserve_uid, /* 1 */
|
||||
&preserve_gid, /* 2 */
|
||||
&preserve_links, /* 3 */
|
||||
&preserve_devices, /* 4 */
|
||||
&preserve_hard_links, /* 5 */
|
||||
&always_checksum, /* 6 */
|
||||
&xfer_dirs, /* 7 (protocol 29) */
|
||||
&tweaked_compress_level,/* 8 (protocol 29) */
|
||||
NULL
|
||||
};
|
||||
|
||||
void write_batch_flist_info(int flist_count, struct file_struct **files)
|
||||
static char *flag_name[] = {
|
||||
"--recurse (-r)",
|
||||
"--owner (-o)",
|
||||
"--group (-g)",
|
||||
"--links (-l)",
|
||||
"--devices (-D)",
|
||||
"--hard-links (-H)",
|
||||
"--checksum (-c)",
|
||||
"--dirs (-d)",
|
||||
"--compress (-z)",
|
||||
NULL
|
||||
};
|
||||
|
||||
void write_stream_flags(int fd)
|
||||
{
|
||||
char filename[MAXPATHLEN];
|
||||
int i, f, save_pv;
|
||||
int64 save_written;
|
||||
int i, flags;
|
||||
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_flist_file, NULL);
|
||||
#if Z_DEFAULT_COMPRESSION == -1
|
||||
tweaked_compress_level = do_compression ? def_compress_level + 2 : 0;
|
||||
#else
|
||||
#error internal logic error! Fix def_compress_level logic above and below too!
|
||||
#endif
|
||||
|
||||
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (f < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
exit_cleanup(1);
|
||||
/* Start the batch file with a bitmap of data-stream-affecting
|
||||
* flags. */
|
||||
if (protocol_version < 29)
|
||||
flag_ptr[7] = NULL;
|
||||
for (i = 0, flags = 0; flag_ptr[i]; i++) {
|
||||
if (*flag_ptr[i])
|
||||
flags |= 1 << i;
|
||||
}
|
||||
|
||||
save_written = stats.total_written;
|
||||
save_pv = protocol_version;
|
||||
protocol_version = PROTOCOL_VERSION;
|
||||
write_int(f, protocol_version);
|
||||
write_int(f, flist_count);
|
||||
|
||||
for (i = 0; i < flist_count; i++) {
|
||||
send_file_entry(files[i], f,
|
||||
files[i]->flags & FLAG_TOP_DIR ? XMIT_TOP_DIR : 0);
|
||||
}
|
||||
send_file_entry(NULL, f, 0);
|
||||
|
||||
protocol_version = save_pv;
|
||||
stats.total_written = save_written;
|
||||
|
||||
close(f);
|
||||
write_int(fd, flags);
|
||||
}
|
||||
|
||||
|
||||
void write_batch_argvs_file(int argc, char *argv[])
|
||||
void read_stream_flags(int fd)
|
||||
{
|
||||
int f;
|
||||
int i;
|
||||
char buff[256]; /* XXX */
|
||||
char buff2[MAXPATHLEN + 6];
|
||||
char filename[MAXPATHLEN];
|
||||
int i, flags;
|
||||
|
||||
if (protocol_version < 29)
|
||||
flag_ptr[7] = NULL;
|
||||
for (i = 0, flags = read_int(fd); flag_ptr[i]; i++) {
|
||||
int set = flags & (1 << i) ? 1 : 0;
|
||||
if (*flag_ptr[i] != set) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO,
|
||||
"%sing the %s option to match the batchfile.\n",
|
||||
set ? "Sett" : "Clear", flag_name[i]);
|
||||
}
|
||||
*flag_ptr[i] = set;
|
||||
}
|
||||
}
|
||||
if (protocol_version < 29) {
|
||||
if (recurse)
|
||||
xfer_dirs |= 1;
|
||||
else if (xfer_dirs < 2)
|
||||
xfer_dirs = 0;
|
||||
}
|
||||
|
||||
if (tweaked_compress_level == 0 || tweaked_compress_level == 2)
|
||||
do_compression = 0;
|
||||
else {
|
||||
do_compression = 1;
|
||||
def_compress_level = tweaked_compress_level - 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_arg(int fd, char *arg)
|
||||
{
|
||||
char *x, *s;
|
||||
|
||||
if (*arg == '-' && (x = strchr(arg, '=')) != NULL) {
|
||||
write(fd, arg, x - arg + 1);
|
||||
arg += x - arg + 1;
|
||||
}
|
||||
|
||||
if (strpbrk(arg, " \"'&;|[]()$#!*?^\\") != NULL) {
|
||||
write(fd, "'", 1);
|
||||
for (s = arg; (x = strchr(s, '\'')) != NULL; s = x + 1) {
|
||||
write(fd, s, x - s + 1);
|
||||
write(fd, "'", 1);
|
||||
}
|
||||
write(fd, s, strlen(s));
|
||||
write(fd, "'", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
write(fd, arg, strlen(arg));
|
||||
}
|
||||
|
||||
static void write_filter_rules(int fd)
|
||||
{
|
||||
struct filter_struct *ent;
|
||||
|
||||
write_sbuf(fd, " <<'#E#'\n");
|
||||
for (ent = filter_list.head; ent; ent = ent->next) {
|
||||
unsigned int plen;
|
||||
char *p = get_rule_prefix(ent->match_flags, "- ", 0, &plen);
|
||||
write_buf(fd, p, plen);
|
||||
write_sbuf(fd, ent->pattern);
|
||||
if (ent->match_flags & MATCHFLG_DIRECTORY)
|
||||
write_byte(fd, '/');
|
||||
write_byte(fd, eol_nulls ? 0 : '\n');
|
||||
}
|
||||
if (eol_nulls)
|
||||
write_sbuf(fd, ";\n");
|
||||
write_sbuf(fd, "#E#");
|
||||
}
|
||||
|
||||
/* This routine tries to write out an equivalent --read-batch command
|
||||
* given the user's --write-batch args. However, it doesn't really
|
||||
* understand most of the options, so it uses some overly simple
|
||||
* heuristics to munge the command line into something that will
|
||||
* (hopefully) work. */
|
||||
void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
|
||||
{
|
||||
int fd, i, len;
|
||||
char *p, filename[MAXPATHLEN];
|
||||
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_argvs_file, NULL);
|
||||
|
||||
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IEXEC);
|
||||
if (f < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
batch_name, ".sh", NULL);
|
||||
fd = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IEXEC);
|
||||
if (fd < 0) {
|
||||
rsyserr(FERROR, errno, "Batch file %s open error",
|
||||
filename);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
buff[0] = '\0';
|
||||
|
||||
/* Write argvs info to batch file */
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (i == argc - 2) /* Skip source directory on cmdline */
|
||||
/* Write argvs info to BATCH.sh file */
|
||||
write_arg(fd, argv[0]);
|
||||
if (filter_list.head) {
|
||||
if (protocol_version >= 29)
|
||||
write_sbuf(fd, " --filter=._-");
|
||||
else
|
||||
write_sbuf(fd, " --exclude-from=-");
|
||||
}
|
||||
for (i = 1; i < argc - file_arg_cnt; i++) {
|
||||
p = argv[i];
|
||||
if (strncmp(p, "--files-from", 12) == 0
|
||||
|| strncmp(p, "--filter", 8) == 0
|
||||
|| strncmp(p, "--include", 9) == 0
|
||||
|| strncmp(p, "--exclude", 9) == 0) {
|
||||
if (strchr(p, '=') == NULL)
|
||||
i++;
|
||||
continue;
|
||||
/*
|
||||
* FIXME:
|
||||
* I think directly manipulating argv[] is probably bogus
|
||||
*/
|
||||
if (!strncmp(argv[i], "--write-batch",
|
||||
strlen("--write-batch"))) {
|
||||
/* Safer to change it here than script */
|
||||
/*
|
||||
* Change to --read-batch=prefix
|
||||
* to get ready for remote
|
||||
*/
|
||||
strlcat(buff, "--read-batch=", sizeof buff);
|
||||
strlcat(buff, batch_prefix, sizeof buff);
|
||||
}
|
||||
if (strcmp(p, "-f") == 0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
write(fd, " ", 1);
|
||||
if (strncmp(p, "--write-batch", len = 13) == 0
|
||||
|| strncmp(p, "--only-write-batch", len = 18) == 0) {
|
||||
write(fd, "--read-batch", 12);
|
||||
if (p[len] == '=') {
|
||||
write(fd, "=", 1);
|
||||
write_arg(fd, p + len + 1);
|
||||
}
|
||||
} else
|
||||
if (i == argc - 1) {
|
||||
snprintf(buff2, sizeof buff2, "${1:-%s}", argv[i]);
|
||||
strlcat(buff, buff2, sizeof buff);
|
||||
}
|
||||
else {
|
||||
strlcat(buff, argv[i], sizeof buff);
|
||||
}
|
||||
|
||||
if (i < (argc - 1)) {
|
||||
strlcat(buff, " ", sizeof buff);
|
||||
}
|
||||
write_arg(fd, p);
|
||||
}
|
||||
strlcat(buff, "\n", sizeof buff);
|
||||
if (!write(f, buff, strlen(buff))) {
|
||||
rprintf(FERROR, "Batch file %s write error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
close(f);
|
||||
}
|
||||
|
||||
struct file_list *create_flist_from_batch(void)
|
||||
{
|
||||
char filename[MAXPATHLEN];
|
||||
unsigned short flags;
|
||||
int i, f, save_pv;
|
||||
int64 save_read;
|
||||
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_flist_file, NULL);
|
||||
|
||||
f = do_open(filename, O_RDONLY, 0);
|
||||
if (f < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
batch_flist = flist_new(WITH_HLINK, "create_flist_from_batch");
|
||||
|
||||
save_read = stats.total_read;
|
||||
save_pv = protocol_version;
|
||||
protocol_version = read_int(f);
|
||||
|
||||
batch_flist->count = read_int(f);
|
||||
flist_expand(batch_flist);
|
||||
|
||||
for (i = 0; (flags = read_byte(f)) != 0; i++) {
|
||||
if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS))
|
||||
flags |= read_byte(f) << 8;
|
||||
receive_file_entry(&batch_flist->files[i], flags, batch_flist, f);
|
||||
}
|
||||
receive_file_entry(NULL, 0, NULL, 0); /* Signal that we're done. */
|
||||
|
||||
protocol_version = save_pv;
|
||||
stats.total_read = save_read;
|
||||
|
||||
return batch_flist;
|
||||
}
|
||||
|
||||
void write_batch_csums_file(void *buff, int bytes_to_write)
|
||||
{
|
||||
if (write(f_csums, buff, bytes_to_write) < 0) {
|
||||
rprintf(FERROR, "Batch file write error: %s\n",
|
||||
strerror(errno));
|
||||
close(f_csums);
|
||||
if (!(p = check_for_hostspec(argv[argc - 1], &p, &i)))
|
||||
p = argv[argc - 1];
|
||||
write(fd, " ${1:-", 6);
|
||||
write_arg(fd, p);
|
||||
write_byte(fd, '}');
|
||||
if (filter_list.head)
|
||||
write_filter_rules(fd);
|
||||
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
|
||||
rsyserr(FERROR, errno, "Batch file %s write error",
|
||||
filename);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
void close_batch_csums_file(void)
|
||||
{
|
||||
close(f_csums);
|
||||
f_csums = -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write csum info to batch file
|
||||
*
|
||||
* @todo This will break if s->count is ever larger than maxint. The
|
||||
* batch code should probably be changed to consistently use the
|
||||
* variable-length integer routines, which is probably a compatible
|
||||
* change.
|
||||
**/
|
||||
void write_batch_csum_info(int *flist_entry, struct sum_struct *s)
|
||||
{
|
||||
size_t i;
|
||||
int int_count;
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (f_csums < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_csums_file, NULL);
|
||||
|
||||
f_csums = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (f_csums < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_csums);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
write_batch_csums_file(flist_entry, sizeof (int));
|
||||
int_count = s ? (int) s->count : 0;
|
||||
write_batch_csums_file(&int_count, sizeof int_count);
|
||||
|
||||
if (s) {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
write_batch_csums_file(&s->sums[i].sum1,
|
||||
sizeof (uint32));
|
||||
write_batch_csums_file(s->sums[i].sum2, csum_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int read_batch_csums_file(char *buff, int len)
|
||||
{
|
||||
int bytes_read;
|
||||
|
||||
if ((bytes_read = read(f_csums, buff, len)) < 0) {
|
||||
rprintf(FERROR, "Batch file read error: %s\n", strerror(errno));
|
||||
close(f_csums);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
void read_batch_csum_info(int flist_entry, struct sum_struct *s,
|
||||
int *checksums_match)
|
||||
{
|
||||
int i;
|
||||
int file_flist_entry;
|
||||
int file_chunk_ct;
|
||||
uint32 file_sum1;
|
||||
char file_sum2[SUM_LENGTH];
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (f_csums < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_csums_file, NULL);
|
||||
|
||||
f_csums = do_open(filename, O_RDONLY, 0);
|
||||
if (f_csums < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_csums);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
read_batch_csums_file((char *) &file_flist_entry, sizeof (int));
|
||||
if (file_flist_entry != flist_entry) {
|
||||
rprintf(FINFO, "file_flist_entry (%d) != flist_entry (%d)\n",
|
||||
file_flist_entry, flist_entry);
|
||||
close(f_csums);
|
||||
exit_cleanup(1);
|
||||
|
||||
} else {
|
||||
read_batch_csums_file((char *) &file_chunk_ct, sizeof (int));
|
||||
*checksums_match = 1;
|
||||
for (i = 0; i < file_chunk_ct; i++) {
|
||||
read_batch_csums_file((char *) &file_sum1,
|
||||
sizeof (uint32));
|
||||
read_batch_csums_file(file_sum2, csum_length);
|
||||
|
||||
if ((s->sums[i].sum1 != file_sum1)
|
||||
|| memcmp(s->sums[i].sum2, file_sum2, csum_length))
|
||||
*checksums_match = 0;
|
||||
} /* end for */
|
||||
}
|
||||
}
|
||||
|
||||
void write_batch_delta_file(char *buff, int bytes_to_write)
|
||||
{
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (f_delta < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_delta_file, NULL);
|
||||
|
||||
f_delta = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (f_delta < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (write(f_delta, buff, bytes_to_write) < 0) {
|
||||
rprintf(FERROR, "Batch file %s write error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_delta);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
void close_batch_delta_file(void)
|
||||
{
|
||||
close(f_delta);
|
||||
f_delta = -1;
|
||||
}
|
||||
|
||||
int read_batch_delta_file(char *buff, int len)
|
||||
{
|
||||
int bytes_read;
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (f_delta < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_delta_file, NULL);
|
||||
|
||||
f_delta = do_open(filename, O_RDONLY, 0);
|
||||
if (f_delta < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_delta);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
bytes_read = read(f_delta, buff, len);
|
||||
if (bytes_read < 0) {
|
||||
rprintf(FERROR, "Batch file %s read error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_delta);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
void show_flist(int index, struct file_struct **fptr)
|
||||
{
|
||||
/* for debugging show_flist(flist->count, flist->files * */
|
||||
|
||||
int i;
|
||||
for (i = 0; i < index; i++) {
|
||||
rprintf(FINFO, "flist->flags=%#x\n", fptr[i]->flags);
|
||||
rprintf(FINFO, "flist->modtime=%#lx\n",
|
||||
(long unsigned) fptr[i]->modtime);
|
||||
rprintf(FINFO, "flist->length=%.0f\n",
|
||||
(double) fptr[i]->length);
|
||||
rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);
|
||||
rprintf(FINFO, "flist->basename=%s\n", fptr[i]->basename);
|
||||
if (fptr[i]->dirname)
|
||||
rprintf(FINFO, "flist->dirname=%s\n",
|
||||
fptr[i]->dirname);
|
||||
if (fptr[i]->basedir)
|
||||
rprintf(FINFO, "flist->basedir=%s\n",
|
||||
fptr[i]->basedir);
|
||||
}
|
||||
}
|
||||
|
||||
void show_argvs(int argc, char *argv[])
|
||||
{
|
||||
/* for debugging * */
|
||||
|
||||
int i;
|
||||
rprintf(FINFO, "BATCH.C:show_argvs,argc=%d\n", argc);
|
||||
for (i = 0; i < argc; i++) {
|
||||
/* if (argv[i]) */
|
||||
rprintf(FINFO, "i=%d,argv[i]=%s\n", i, argv[i]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
50
byteorder.h
50
byteorder.h
@@ -1,26 +1,27 @@
|
||||
/*
|
||||
simple byteorder handling
|
||||
Copyright (C) Andrew Tridgell 1992-1995
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* Simple byteorder handling.
|
||||
*
|
||||
* Copyright (C) 1992-1995 Andrew Tridgell
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#undef CAREFUL_ALIGNMENT
|
||||
|
||||
/* we know that the x86 can handle misalignment and has the "right"
|
||||
byteorder */
|
||||
/* We know that the x86 can handle misalignment and has the same
|
||||
* byte order (LSB-first) as the 32-bit numbers we transmit. */
|
||||
#ifdef __i386__
|
||||
#define CAREFUL_ALIGNMENT 0
|
||||
#endif
|
||||
@@ -30,13 +31,12 @@
|
||||
#endif
|
||||
|
||||
#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
|
||||
#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
|
||||
#define UVAL(buf,pos) ((uint32)CVAL(buf,pos))
|
||||
#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
|
||||
|
||||
|
||||
#if CAREFUL_ALIGNMENT
|
||||
#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
|
||||
#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
|
||||
#define PVAL(buf,pos) (UVAL(buf,pos)|UVAL(buf,(pos)+1)<<8)
|
||||
#define IVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+2)<<16)
|
||||
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
|
||||
#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
|
||||
#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
|
||||
@@ -50,5 +50,3 @@
|
||||
#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
|
||||
#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
79
case_N.h
Normal file
79
case_N.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* End-of-run cleanup helper code used by cleanup.c.
|
||||
*
|
||||
* Copyright (C) 2006-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* This is included by cleanup.c multiple times, once for every segement in
|
||||
* the _exit_cleanup() code. This produces the next "case N:" statement in
|
||||
* sequence and increments the cleanup_step variable by 1. This ensures that
|
||||
* our case statements never get out of whack due to added/removed steps. */
|
||||
|
||||
#if !defined EXIT_CLEANUP_CASE_0
|
||||
#define EXIT_CLEANUP_CASE_0
|
||||
case 0:
|
||||
#elif !defined EXIT_CLEANUP_CASE_1
|
||||
#define EXIT_CLEANUP_CASE_1
|
||||
case 1:
|
||||
#elif !defined EXIT_CLEANUP_CASE_2
|
||||
#define EXIT_CLEANUP_CASE_2
|
||||
case 2:
|
||||
#elif !defined EXIT_CLEANUP_CASE_3
|
||||
#define EXIT_CLEANUP_CASE_3
|
||||
case 3:
|
||||
#elif !defined EXIT_CLEANUP_CASE_4
|
||||
#define EXIT_CLEANUP_CASE_4
|
||||
case 4:
|
||||
#elif !defined EXIT_CLEANUP_CASE_5
|
||||
#define EXIT_CLEANUP_CASE_5
|
||||
case 5:
|
||||
#elif !defined EXIT_CLEANUP_CASE_6
|
||||
#define EXIT_CLEANUP_CASE_6
|
||||
case 6:
|
||||
#elif !defined EXIT_CLEANUP_CASE_7
|
||||
#define EXIT_CLEANUP_CASE_7
|
||||
case 7:
|
||||
#elif !defined EXIT_CLEANUP_CASE_8
|
||||
#define EXIT_CLEANUP_CASE_8
|
||||
case 8:
|
||||
#elif !defined EXIT_CLEANUP_CASE_9
|
||||
#define EXIT_CLEANUP_CASE_9
|
||||
case 9:
|
||||
#elif !defined EXIT_CLEANUP_CASE_10
|
||||
#define EXIT_CLEANUP_CASE_10
|
||||
case 10:
|
||||
#elif !defined EXIT_CLEANUP_CASE_11
|
||||
#define EXIT_CLEANUP_CASE_11
|
||||
case 11:
|
||||
#elif !defined EXIT_CLEANUP_CASE_12
|
||||
#define EXIT_CLEANUP_CASE_12
|
||||
case 12:
|
||||
#elif !defined EXIT_CLEANUP_CASE_13
|
||||
#define EXIT_CLEANUP_CASE_13
|
||||
case 13:
|
||||
#elif !defined EXIT_CLEANUP_CASE_14
|
||||
#define EXIT_CLEANUP_CASE_14
|
||||
case 14:
|
||||
#elif !defined EXIT_CLEANUP_CASE_15
|
||||
#define EXIT_CLEANUP_CASE_15
|
||||
case 15:
|
||||
#elif !defined EXIT_CLEANUP_CASE_16
|
||||
#define EXIT_CLEANUP_CASE_16
|
||||
case 16:
|
||||
#else
|
||||
#error Need to add more case statements!
|
||||
#endif
|
||||
cleanup_step++;
|
||||
267
checksum.c
267
checksum.c
@@ -1,46 +1,46 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* Routines to support checksumming of bytes.
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
int csum_length=2; /* initial value */
|
||||
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
extern int checksum_seed;
|
||||
extern int protocol_version;
|
||||
|
||||
int csum_length = SHORT_SUM_LENGTH; /* initial value */
|
||||
|
||||
/*
|
||||
a simple 32 bit checksum that can be upadted from either end
|
||||
(inspired by Mark Adler's Adler-32 checksum)
|
||||
*/
|
||||
uint32 get_checksum1(char *buf1,int len)
|
||||
uint32 get_checksum1(char *buf1, int32 len)
|
||||
{
|
||||
int i;
|
||||
int32 i;
|
||||
uint32 s1, s2;
|
||||
schar *buf = (schar *)buf1;
|
||||
|
||||
s1 = s2 = 0;
|
||||
for (i = 0; i < (len-4); i+=4) {
|
||||
s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] +
|
||||
s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] +
|
||||
10*CHAR_OFFSET;
|
||||
s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
|
||||
s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
|
||||
}
|
||||
for (; i < len; i++) {
|
||||
s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
|
||||
@@ -49,99 +49,124 @@ uint32 get_checksum1(char *buf1,int len)
|
||||
}
|
||||
|
||||
|
||||
void get_checksum2(char *buf,int len,char *sum)
|
||||
void get_checksum2(char *buf, int32 len, char *sum)
|
||||
{
|
||||
int i;
|
||||
static char *buf1;
|
||||
static int len1;
|
||||
struct mdfour m;
|
||||
md_context m;
|
||||
|
||||
if (len > len1) {
|
||||
if (buf1) free(buf1);
|
||||
buf1 = new_array(char, len+4);
|
||||
len1 = len;
|
||||
if (!buf1) out_of_memory("get_checksum2");
|
||||
if (protocol_version >= 30) {
|
||||
uchar seedbuf[4];
|
||||
md5_begin(&m);
|
||||
md5_update(&m, (uchar *)buf, len);
|
||||
if (checksum_seed) {
|
||||
SIVAL(seedbuf, 0, checksum_seed);
|
||||
md5_update(&m, seedbuf, 4);
|
||||
}
|
||||
md5_result(&m, (uchar *)sum);
|
||||
} else {
|
||||
int32 i;
|
||||
static char *buf1;
|
||||
static int32 len1;
|
||||
|
||||
mdfour_begin(&m);
|
||||
|
||||
if (len > len1) {
|
||||
if (buf1)
|
||||
free(buf1);
|
||||
buf1 = new_array(char, len+4);
|
||||
len1 = len;
|
||||
if (!buf1)
|
||||
out_of_memory("get_checksum2");
|
||||
}
|
||||
|
||||
memcpy(buf1, buf, len);
|
||||
if (checksum_seed) {
|
||||
SIVAL(buf1,len,checksum_seed);
|
||||
len += 4;
|
||||
}
|
||||
|
||||
for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK)
|
||||
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
|
||||
|
||||
/*
|
||||
* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0 || protocol_version >= 27)
|
||||
mdfour_update(&m, (uchar *)(buf1+i), len-i);
|
||||
|
||||
mdfour_result(&m, (uchar *)sum);
|
||||
}
|
||||
|
||||
mdfour_begin(&m);
|
||||
|
||||
memcpy(buf1,buf,len);
|
||||
if (checksum_seed) {
|
||||
SIVAL(buf1,len,checksum_seed);
|
||||
len += 4;
|
||||
}
|
||||
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
|
||||
}
|
||||
/*
|
||||
* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0 || protocol_version >= 27) {
|
||||
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
|
||||
}
|
||||
|
||||
mdfour_result(&m, (uchar *)sum);
|
||||
}
|
||||
|
||||
|
||||
void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
void file_checksum(char *fname, char *sum, OFF_T size)
|
||||
{
|
||||
OFF_T i;
|
||||
struct map_struct *buf;
|
||||
OFF_T i, len = size;
|
||||
md_context m;
|
||||
int32 remainder;
|
||||
int fd;
|
||||
OFF_T len = size;
|
||||
char tmpchunk[CSUM_CHUNK];
|
||||
struct mdfour m;
|
||||
|
||||
memset(sum,0,MD4_SUM_LENGTH);
|
||||
|
||||
|
||||
memset(sum, 0, MAX_DIGEST_LEN);
|
||||
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) return;
|
||||
|
||||
buf = map_file(fd,size);
|
||||
|
||||
mdfour_begin(&m);
|
||||
if (fd == -1)
|
||||
return;
|
||||
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
|
||||
mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
|
||||
}
|
||||
buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
|
||||
|
||||
/*
|
||||
* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0) {
|
||||
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
|
||||
}
|
||||
if (len - i > 0 || protocol_version >= 27) {
|
||||
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
|
||||
}
|
||||
if (protocol_version >= 30) {
|
||||
md5_begin(&m);
|
||||
|
||||
mdfour_result(&m, (uchar *)sum);
|
||||
for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
md5_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
|
||||
CSUM_CHUNK);
|
||||
}
|
||||
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0)
|
||||
md5_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
md5_result(&m, (uchar *)sum);
|
||||
} else {
|
||||
mdfour_begin(&m);
|
||||
|
||||
for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
|
||||
CSUM_CHUNK);
|
||||
}
|
||||
|
||||
/* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes. */
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0 || protocol_version >= 27)
|
||||
mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
mdfour_result(&m, (uchar *)sum);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
unmap_file(buf);
|
||||
}
|
||||
|
||||
static int32 sumresidue;
|
||||
static md_context md;
|
||||
|
||||
static int sumresidue;
|
||||
static char sumrbuf[CSUM_CHUNK];
|
||||
static struct mdfour md;
|
||||
|
||||
void sum_init(void)
|
||||
void sum_init(int seed)
|
||||
{
|
||||
char s[4];
|
||||
mdfour_begin(&md);
|
||||
sumresidue=0;
|
||||
SIVAL(s,0,checksum_seed);
|
||||
sum_update(s,4);
|
||||
|
||||
if (protocol_version >= 30)
|
||||
md5_begin(&md);
|
||||
else {
|
||||
mdfour_begin(&md);
|
||||
sumresidue = 0;
|
||||
SIVAL(s, 0, seed);
|
||||
sum_update(s, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,41 +177,49 @@ void sum_init(void)
|
||||
* @todo Perhaps get rid of md and just pass in the address each time.
|
||||
* Very slightly clearer and slower.
|
||||
**/
|
||||
void sum_update(char *p, int len)
|
||||
void sum_update(const char *p, int32 len)
|
||||
{
|
||||
int i;
|
||||
if (protocol_version >= 30) {
|
||||
md5_update(&md, (uchar *)p, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len + sumresidue < CSUM_CHUNK) {
|
||||
memcpy(sumrbuf+sumresidue, p, len);
|
||||
memcpy(md.buffer + sumresidue, p, len);
|
||||
sumresidue += len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sumresidue) {
|
||||
i = MIN(CSUM_CHUNK-sumresidue,len);
|
||||
memcpy(sumrbuf+sumresidue,p,i);
|
||||
mdfour_update(&md, (uchar *)sumrbuf, (i+sumresidue));
|
||||
int32 i = CSUM_CHUNK - sumresidue;
|
||||
memcpy(md.buffer + sumresidue, p, i);
|
||||
mdfour_update(&md, (uchar *)md.buffer, CSUM_CHUNK);
|
||||
len -= i;
|
||||
p += i;
|
||||
}
|
||||
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
memcpy(sumrbuf,p+i,CSUM_CHUNK);
|
||||
mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
|
||||
while (len >= CSUM_CHUNK) {
|
||||
mdfour_update(&md, (uchar *)p, CSUM_CHUNK);
|
||||
len -= CSUM_CHUNK;
|
||||
p += CSUM_CHUNK;
|
||||
}
|
||||
|
||||
if (len - i > 0) {
|
||||
sumresidue = len-i;
|
||||
memcpy(sumrbuf,p+i,sumresidue);
|
||||
} else {
|
||||
sumresidue = 0;
|
||||
}
|
||||
sumresidue = len;
|
||||
if (sumresidue)
|
||||
memcpy(md.buffer, p, sumresidue);
|
||||
}
|
||||
|
||||
void sum_end(char *sum)
|
||||
int sum_end(char *sum)
|
||||
{
|
||||
if (sumresidue || protocol_version >= 27) {
|
||||
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
|
||||
if (protocol_version >= 30) {
|
||||
md5_result(&md, (uchar *)sum);
|
||||
return MD5_DIGEST_LEN;
|
||||
}
|
||||
|
||||
if (sumresidue || protocol_version >= 27)
|
||||
mdfour_update(&md, (uchar *)md.buffer, sumresidue);
|
||||
|
||||
mdfour_result(&md, (uchar *)sum);
|
||||
|
||||
return MD4_DIGEST_LEN;
|
||||
}
|
||||
|
||||
225
chmod.c
Normal file
225
chmod.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Implement the core of the --chmod option.
|
||||
*
|
||||
* Copyright (C) 2002 Scott Howard
|
||||
* Copyright (C) 2005-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern mode_t orig_umask;
|
||||
|
||||
#define FLAG_X_KEEP (1<<0)
|
||||
#define FLAG_DIRS_ONLY (1<<1)
|
||||
#define FLAG_FILES_ONLY (1<<2)
|
||||
|
||||
struct chmod_mode_struct {
|
||||
struct chmod_mode_struct *next;
|
||||
int ModeAND, ModeOR;
|
||||
char flags;
|
||||
};
|
||||
|
||||
#define CHMOD_ADD 1
|
||||
#define CHMOD_SUB 2
|
||||
#define CHMOD_EQ 3
|
||||
|
||||
#define STATE_ERROR 0
|
||||
#define STATE_1ST_HALF 1
|
||||
#define STATE_2ND_HALF 2
|
||||
|
||||
/* Parse a chmod-style argument, and break it down into one or more AND/OR
|
||||
* pairs in a linked list. We return a pointer to new items on succcess
|
||||
* (appending the items to the specified list), or NULL on error. */
|
||||
struct chmod_mode_struct *parse_chmod(const char *modestr,
|
||||
struct chmod_mode_struct **root_mode_ptr)
|
||||
{
|
||||
int state = STATE_1ST_HALF;
|
||||
int where = 0, what = 0, op = 0, topbits = 0, topoct = 0, flags = 0;
|
||||
struct chmod_mode_struct *first_mode = NULL, *curr_mode = NULL,
|
||||
*prev_mode = NULL;
|
||||
|
||||
while (state != STATE_ERROR) {
|
||||
if (!*modestr || *modestr == ',') {
|
||||
int bits;
|
||||
|
||||
if (!op) {
|
||||
state = STATE_ERROR;
|
||||
break;
|
||||
}
|
||||
prev_mode = curr_mode;
|
||||
curr_mode = new_array(struct chmod_mode_struct, 1);
|
||||
if (prev_mode)
|
||||
prev_mode->next = curr_mode;
|
||||
else
|
||||
first_mode = curr_mode;
|
||||
curr_mode->next = NULL;
|
||||
|
||||
if (where)
|
||||
bits = where * what;
|
||||
else {
|
||||
where = 0111;
|
||||
bits = (where * what) & ~orig_umask;
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case CHMOD_ADD:
|
||||
curr_mode->ModeAND = CHMOD_BITS;
|
||||
curr_mode->ModeOR = bits + topoct;
|
||||
break;
|
||||
case CHMOD_SUB:
|
||||
curr_mode->ModeAND = CHMOD_BITS - bits - topoct;
|
||||
curr_mode->ModeOR = 0;
|
||||
break;
|
||||
case CHMOD_EQ:
|
||||
curr_mode->ModeAND = CHMOD_BITS - (where * 7) - (topoct ? topbits : 0);
|
||||
curr_mode->ModeOR = bits + topoct;
|
||||
break;
|
||||
}
|
||||
|
||||
curr_mode->flags = flags;
|
||||
|
||||
if (!*modestr)
|
||||
break;
|
||||
modestr++;
|
||||
|
||||
state = STATE_1ST_HALF;
|
||||
where = what = op = topoct = topbits = flags = 0;
|
||||
}
|
||||
|
||||
if (state != STATE_2ND_HALF) {
|
||||
switch (*modestr) {
|
||||
case 'D':
|
||||
if (flags & FLAG_FILES_ONLY)
|
||||
state = STATE_ERROR;
|
||||
flags |= FLAG_DIRS_ONLY;
|
||||
break;
|
||||
case 'F':
|
||||
if (flags & FLAG_DIRS_ONLY)
|
||||
state = STATE_ERROR;
|
||||
flags |= FLAG_FILES_ONLY;
|
||||
break;
|
||||
case 'u':
|
||||
where |= 0100;
|
||||
topbits |= 04000;
|
||||
break;
|
||||
case 'g':
|
||||
where |= 0010;
|
||||
topbits |= 02000;
|
||||
break;
|
||||
case 'o':
|
||||
where |= 0001;
|
||||
break;
|
||||
case 'a':
|
||||
where |= 0111;
|
||||
break;
|
||||
case '+':
|
||||
op = CHMOD_ADD;
|
||||
state = STATE_2ND_HALF;
|
||||
break;
|
||||
case '-':
|
||||
op = CHMOD_SUB;
|
||||
state = STATE_2ND_HALF;
|
||||
break;
|
||||
case '=':
|
||||
op = CHMOD_EQ;
|
||||
state = STATE_2ND_HALF;
|
||||
break;
|
||||
default:
|
||||
state = STATE_ERROR;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (*modestr) {
|
||||
case 'r':
|
||||
what |= 4;
|
||||
break;
|
||||
case 'w':
|
||||
what |= 2;
|
||||
break;
|
||||
case 'X':
|
||||
flags |= FLAG_X_KEEP;
|
||||
/* FALL THROUGH */
|
||||
case 'x':
|
||||
what |= 1;
|
||||
break;
|
||||
case 's':
|
||||
if (topbits)
|
||||
topoct |= topbits;
|
||||
else
|
||||
topoct = 04000;
|
||||
break;
|
||||
case 't':
|
||||
topoct |= 01000;
|
||||
break;
|
||||
default:
|
||||
state = STATE_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
modestr++;
|
||||
}
|
||||
|
||||
if (state == STATE_ERROR) {
|
||||
free_chmod_mode(first_mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(curr_mode = *root_mode_ptr))
|
||||
*root_mode_ptr = first_mode;
|
||||
else {
|
||||
while (curr_mode->next)
|
||||
curr_mode = curr_mode->next;
|
||||
curr_mode->next = first_mode;
|
||||
}
|
||||
|
||||
return first_mode;
|
||||
}
|
||||
|
||||
|
||||
/* Takes an existing file permission and a list of AND/OR changes, and
|
||||
* create a new permissions. */
|
||||
int tweak_mode(int mode, struct chmod_mode_struct *chmod_modes)
|
||||
{
|
||||
int IsX = mode & 0111;
|
||||
int NonPerm = mode & ~CHMOD_BITS;
|
||||
|
||||
for ( ; chmod_modes; chmod_modes = chmod_modes->next) {
|
||||
if ((chmod_modes->flags & FLAG_DIRS_ONLY) && !S_ISDIR(NonPerm))
|
||||
continue;
|
||||
if ((chmod_modes->flags & FLAG_FILES_ONLY) && S_ISDIR(NonPerm))
|
||||
continue;
|
||||
mode &= chmod_modes->ModeAND;
|
||||
if ((chmod_modes->flags & FLAG_X_KEEP) && !IsX && !S_ISDIR(NonPerm))
|
||||
mode |= chmod_modes->ModeOR & ~0111;
|
||||
else
|
||||
mode |= chmod_modes->ModeOR;
|
||||
}
|
||||
|
||||
return mode | NonPerm;
|
||||
}
|
||||
|
||||
/* Free the linked list created by parse_chmod. */
|
||||
int free_chmod_mode(struct chmod_mode_struct *chmod_modes)
|
||||
{
|
||||
struct chmod_mode_struct *next;
|
||||
|
||||
while (chmod_modes) {
|
||||
next = chmod_modes->next;
|
||||
free(chmod_modes);
|
||||
chmod_modes = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
233
cleanup.c
233
cleanup.c
@@ -1,26 +1,39 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2002 by Martin Pool
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* End-of-run cleanup routines.
|
||||
*
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int io_error;
|
||||
extern int keep_partial;
|
||||
extern int log_got_error;
|
||||
extern char *partial_dir;
|
||||
extern char *logfile_name;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction sigact;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Close all open sockets and files, allowing a (somewhat) graceful
|
||||
* shutdown() of socket connections. This eliminates the abortive
|
||||
@@ -32,15 +45,13 @@ void close_all(void)
|
||||
int max_fd;
|
||||
int fd;
|
||||
int ret;
|
||||
struct stat st;
|
||||
STRUCT_STAT st;
|
||||
|
||||
max_fd = sysconf(_SC_OPEN_MAX) - 1;
|
||||
for (fd = max_fd; fd >= 0; fd--) {
|
||||
ret = fstat(fd,&st);
|
||||
if (fstat(fd,&st) == 0) {
|
||||
if (is_a_socket(fd)) {
|
||||
if ((ret = do_fstat(fd, &st)) == 0) {
|
||||
if (is_a_socket(fd))
|
||||
ret = shutdown(fd, 2);
|
||||
}
|
||||
ret = close(fd);
|
||||
}
|
||||
}
|
||||
@@ -65,15 +76,13 @@ void close_all(void)
|
||||
* --partial is selected. We need to ensure that the partial file is
|
||||
* kept if any real data has been transferred.
|
||||
**/
|
||||
int cleanup_got_literal=0;
|
||||
int cleanup_got_literal = 0;
|
||||
|
||||
static char *cleanup_fname;
|
||||
static char *cleanup_new_fname;
|
||||
static struct file_struct *cleanup_file;
|
||||
static int cleanup_fd1, cleanup_fd2;
|
||||
static struct map_struct *cleanup_buf;
|
||||
static int cleanup_fd_r, cleanup_fd_w;
|
||||
static pid_t cleanup_pid = 0;
|
||||
extern int io_error;
|
||||
|
||||
pid_t cleanup_child_pid = -1;
|
||||
|
||||
@@ -82,88 +91,136 @@ pid_t cleanup_child_pid = -1;
|
||||
*
|
||||
* @param code one of the RERR_* codes from errcode.h.
|
||||
**/
|
||||
void _exit_cleanup(int code, const char *file, int line)
|
||||
NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
{
|
||||
int ocode = code;
|
||||
extern int keep_partial;
|
||||
extern int log_got_error;
|
||||
static int inside_cleanup = 0;
|
||||
static int cleanup_step = 0;
|
||||
static int exit_code = 0;
|
||||
static int unmodified_code = 0;
|
||||
|
||||
if (inside_cleanup > 10) {
|
||||
/* prevent the occasional infinite recursion */
|
||||
return;
|
||||
}
|
||||
inside_cleanup++;
|
||||
SIGACTION(SIGUSR1, SIG_IGN);
|
||||
SIGACTION(SIGUSR2, SIG_IGN);
|
||||
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
signal(SIGUSR2, SIG_IGN);
|
||||
if (exit_code) /* Preserve first error code when recursing. */
|
||||
code = exit_code;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
|
||||
code, file, line);
|
||||
/* If this is the exit at the end of the run, the server side
|
||||
* should not attempt to output a message (see log.c). */
|
||||
if (am_server && code == 0)
|
||||
am_server = 2;
|
||||
|
||||
if (cleanup_child_pid != -1) {
|
||||
int status;
|
||||
if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
|
||||
status = WEXITSTATUS(status);
|
||||
if (status > code) code = status;
|
||||
/* Some of our actions might cause a recursive call back here, so we
|
||||
* keep track of where we are in the cleanup and never repeat a step. */
|
||||
switch (cleanup_step) {
|
||||
#include "case_N.h" /* case 0: cleanup_step++; */
|
||||
|
||||
exit_code = unmodified_code = code;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
|
||||
code, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
if (cleanup_got_literal && cleanup_fname && keep_partial) {
|
||||
char *fname = cleanup_fname;
|
||||
cleanup_fname = NULL;
|
||||
if (cleanup_buf) unmap_file(cleanup_buf);
|
||||
if (cleanup_fd1 != -1) close(cleanup_fd1);
|
||||
if (cleanup_fd2 != -1) close(cleanup_fd2);
|
||||
finish_transfer(cleanup_new_fname, fname, cleanup_file);
|
||||
}
|
||||
io_flush(FULL_FLUSH);
|
||||
if (cleanup_fname)
|
||||
do_unlink(cleanup_fname);
|
||||
if (code) {
|
||||
kill_all(SIGUSR1);
|
||||
}
|
||||
if (cleanup_pid && cleanup_pid == getpid()) {
|
||||
char *pidf = lp_pid_file();
|
||||
if (pidf && *pidf) {
|
||||
unlink(lp_pid_file());
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
|
||||
if (cleanup_child_pid != -1) {
|
||||
int status;
|
||||
int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
|
||||
if (pid == cleanup_child_pid) {
|
||||
status = WEXITSTATUS(status);
|
||||
if (status > code)
|
||||
code = exit_code = status;
|
||||
}
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
|
||||
if (cleanup_got_literal && cleanup_fname && cleanup_new_fname
|
||||
&& keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
|
||||
char *fname = cleanup_fname;
|
||||
cleanup_fname = NULL;
|
||||
if (cleanup_fd_r != -1)
|
||||
close(cleanup_fd_r);
|
||||
if (cleanup_fd_w != -1) {
|
||||
flush_write_file(cleanup_fd_w);
|
||||
close(cleanup_fd_w);
|
||||
}
|
||||
finish_transfer(cleanup_new_fname, fname, NULL, NULL,
|
||||
cleanup_file, 0, !partial_dir);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
|
||||
io_flush(FULL_FLUSH);
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
|
||||
if (cleanup_fname)
|
||||
do_unlink(cleanup_fname);
|
||||
if (code)
|
||||
kill_all(SIGUSR1);
|
||||
if (cleanup_pid && cleanup_pid == getpid()) {
|
||||
char *pidf = lp_pid_file();
|
||||
if (pidf && *pidf)
|
||||
unlink(lp_pid_file());
|
||||
}
|
||||
|
||||
if (code == 0) {
|
||||
if (io_error & IOERR_DEL_LIMIT)
|
||||
code = exit_code = RERR_DEL_LIMIT;
|
||||
if (io_error & IOERR_VANISHED)
|
||||
code = exit_code = RERR_VANISHED;
|
||||
if (io_error & IOERR_GENERAL || log_got_error)
|
||||
code = exit_code = RERR_PARTIAL;
|
||||
}
|
||||
|
||||
if (code || am_daemon || (logfile_name && (am_server || !verbose)))
|
||||
log_exit(code, file, line);
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,
|
||||
"_exit_cleanup(code=%d, file=%s, line=%d): "
|
||||
"about to call exit(%d)\n",
|
||||
unmodified_code, file, line, code);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
|
||||
if (am_server && code)
|
||||
msleep(100);
|
||||
close_all();
|
||||
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (code == 0) {
|
||||
if ((io_error & ~IOERR_VANISHED) || log_got_error)
|
||||
code = RERR_PARTIAL;
|
||||
else if (io_error)
|
||||
code = RERR_VANISHED;
|
||||
}
|
||||
|
||||
if (code) log_exit(code, file, line);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n",
|
||||
ocode, file, line, code);
|
||||
|
||||
close_all();
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void cleanup_disable(void)
|
||||
{
|
||||
cleanup_fname = NULL;
|
||||
cleanup_fname = cleanup_new_fname = NULL;
|
||||
cleanup_got_literal = 0;
|
||||
}
|
||||
|
||||
|
||||
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
|
||||
struct map_struct *buf, int fd1, int fd2)
|
||||
int fd_r, int fd_w)
|
||||
{
|
||||
cleanup_fname = fnametmp;
|
||||
cleanup_new_fname = fname;
|
||||
cleanup_new_fname = fname; /* can be NULL on a partial-dir failure */
|
||||
cleanup_file = file;
|
||||
cleanup_buf = buf;
|
||||
cleanup_fd1 = fd1;
|
||||
cleanup_fd2 = fd2;
|
||||
cleanup_fd_r = fd_r;
|
||||
cleanup_fd_w = fd_w;
|
||||
}
|
||||
|
||||
void cleanup_set_pid(pid_t pid)
|
||||
|
||||
136
clientname.c
136
clientname.c
@@ -1,40 +1,34 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file clientname.c
|
||||
*
|
||||
/*
|
||||
* Functions for looking up the remote name or addr of a socket.
|
||||
*
|
||||
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is now converted to use the new-style getaddrinfo()
|
||||
* interface, which supports IPv6 but is also supported on recent
|
||||
* IPv4-only machines. On systems that don't have that interface, we
|
||||
* emulate it using the KAME implementation.
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
static const char default_name[] = "UNKNOWN";
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
|
||||
|
||||
@@ -43,12 +37,11 @@ extern int am_server;
|
||||
**/
|
||||
char *client_addr(int fd)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t length = sizeof ss;
|
||||
char *ssh_client, *p;
|
||||
int len;
|
||||
static char addr_buf[100];
|
||||
static int initialised;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t length = sizeof ss;
|
||||
char *ssh_info, *p;
|
||||
|
||||
if (initialised)
|
||||
return addr_buf;
|
||||
@@ -56,15 +49,14 @@ char *client_addr(int fd)
|
||||
initialised = 1;
|
||||
|
||||
if (am_server) { /* daemon over --rsh mode */
|
||||
strcpy(addr_buf, "0.0.0.0");
|
||||
if ((ssh_client = getenv("SSH_CLIENT")) != NULL) {
|
||||
/* truncate SSH_CLIENT to just IP address */
|
||||
if ((p = strchr(ssh_client, ' ')) != NULL) {
|
||||
len = MIN((unsigned int) (p - ssh_client),
|
||||
sizeof addr_buf - 1);
|
||||
strncpy(addr_buf, ssh_client, len);
|
||||
*(addr_buf + len) = '\0';
|
||||
}
|
||||
strlcpy(addr_buf, "0.0.0.0", sizeof addr_buf);
|
||||
if ((ssh_info = getenv("SSH_CONNECTION")) != NULL
|
||||
|| (ssh_info = getenv("SSH_CLIENT")) != NULL
|
||||
|| (ssh_info = getenv("SSH2_CLIENT")) != NULL) {
|
||||
strlcpy(addr_buf, ssh_info, sizeof addr_buf);
|
||||
/* Truncate the value to just the IP address. */
|
||||
if ((p = strchr(addr_buf, ' ')) != NULL)
|
||||
*p = '\0';
|
||||
}
|
||||
} else {
|
||||
client_sockaddr(fd, &ss, &length);
|
||||
@@ -106,7 +98,7 @@ char *client_name(int fd)
|
||||
if (initialised)
|
||||
return name_buf;
|
||||
|
||||
strcpy(name_buf, default_name);
|
||||
strlcpy(name_buf, default_name, sizeof name_buf);
|
||||
initialised = 1;
|
||||
|
||||
memset(&ss, 0, sizeof ss);
|
||||
@@ -124,7 +116,7 @@ char *client_name(int fd)
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
|
||||
rprintf(FLOG, "malformed address %s: %s\n",
|
||||
addr, gai_strerror(err));
|
||||
return name_buf;
|
||||
}
|
||||
@@ -140,6 +132,8 @@ char *client_name(int fd)
|
||||
memcpy(&ss, answer->ai_addr, ss_len);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
freeaddrinfo(answer);
|
||||
} else {
|
||||
@@ -147,9 +141,9 @@ char *client_name(int fd)
|
||||
client_sockaddr(fd, &ss, &ss_len);
|
||||
}
|
||||
|
||||
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
|
||||
port_buf, sizeof port_buf))
|
||||
check_name(fd, &ss, name_buf);
|
||||
if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
|
||||
port_buf, sizeof port_buf) == 0)
|
||||
check_name(fd, &ss, name_buf, sizeof name_buf);
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
@@ -170,8 +164,7 @@ void client_sockaddr(int fd,
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
|
||||
/* FIXME: Can we really not continue? */
|
||||
rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
|
||||
fd, strerror(errno));
|
||||
rsyserr(FLOG, errno, "getpeername on fd%d failed", fd);
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
@@ -192,7 +185,7 @@ void client_sockaddr(int fd,
|
||||
memset(sin, 0, sizeof *sin);
|
||||
sin->sin_family = AF_INET;
|
||||
*ss_len = sizeof (struct sockaddr_in);
|
||||
#if HAVE_SOCKADDR_IN_LEN
|
||||
#ifdef HAVE_SOCKADDR_IN_LEN
|
||||
sin->sin_len = *ss_len;
|
||||
#endif
|
||||
sin->sin_port = sin6.sin6_port;
|
||||
@@ -214,21 +207,20 @@ void client_sockaddr(int fd,
|
||||
**/
|
||||
int lookup_name(int fd, const struct sockaddr_storage *ss,
|
||||
socklen_t ss_len,
|
||||
char *name_buf, size_t name_buf_len,
|
||||
char *port_buf, size_t port_buf_len)
|
||||
char *name_buf, size_t name_buf_size,
|
||||
char *port_buf, size_t port_buf_size)
|
||||
{
|
||||
int name_err;
|
||||
|
||||
/* reverse lookup */
|
||||
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
|
||||
name_buf, name_buf_len,
|
||||
port_buf, port_buf_len,
|
||||
name_buf, name_buf_size,
|
||||
port_buf, port_buf_size,
|
||||
NI_NAMEREQD | NI_NUMERICSERV);
|
||||
if (name_err != 0) {
|
||||
strcpy(name_buf, default_name);
|
||||
rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n",
|
||||
client_addr(fd),
|
||||
gai_strerror(name_err));
|
||||
strlcpy(name_buf, default_name, name_buf_size);
|
||||
rprintf(FLOG, "name lookup failed for %s: %s\n",
|
||||
client_addr(fd), gai_strerror(name_err));
|
||||
return name_err;
|
||||
}
|
||||
|
||||
@@ -249,8 +241,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
const char fn[] = "compare_addrinfo_sockaddr";
|
||||
|
||||
if (ai->ai_family != ss_family) {
|
||||
rprintf(FERROR,
|
||||
"%s: response family %d != %d\n",
|
||||
rprintf(FLOG, "%s: response family %d != %d\n",
|
||||
fn, ai->ai_family, ss_family);
|
||||
return 1;
|
||||
}
|
||||
@@ -274,8 +265,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
|
||||
|
||||
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
|
||||
rprintf(FERROR,
|
||||
"%s: too short sockaddr_in6; length=%d\n",
|
||||
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
|
||||
fn, ai->ai_addrlen);
|
||||
return 1;
|
||||
}
|
||||
@@ -309,7 +299,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
**/
|
||||
int check_name(int fd,
|
||||
const struct sockaddr_storage *ss,
|
||||
char *name_buf)
|
||||
char *name_buf, size_t name_buf_size)
|
||||
{
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int error;
|
||||
@@ -321,14 +311,12 @@ int check_name(int fd,
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(name_buf, NULL, &hints, &res0);
|
||||
if (error) {
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME ": forward name lookup for %s failed: %s\n",
|
||||
rprintf(FLOG, "forward name lookup for %s failed: %s\n",
|
||||
name_buf, gai_strerror(error));
|
||||
strcpy(name_buf, default_name);
|
||||
strlcpy(name_buf, default_name, name_buf_size);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* Given all these results, we expect that one of them will be
|
||||
* the same as ss. The comparison is a bit complicated. */
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
@@ -339,23 +327,17 @@ int check_name(int fd,
|
||||
if (!res0) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": no known address for \"%s\": "
|
||||
"spoofed address?\n",
|
||||
name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
rprintf(FLOG, "no known address for \"%s\": "
|
||||
"spoofed address?\n", name_buf);
|
||||
strlcpy(name_buf, default_name, name_buf_size);
|
||||
} else if (res == NULL) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": %s is not a known address for \"%s\": "
|
||||
"spoofed address?\n",
|
||||
client_addr(fd),
|
||||
name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
rprintf(FLOG, "%s is not a known address for \"%s\": "
|
||||
"spoofed address?\n", client_addr(fd), name_buf);
|
||||
strlcpy(name_buf, default_name, name_buf_size);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
860
clientserver.c
860
clientserver.c
File diff suppressed because it is too large
Load Diff
244
compat.c
244
compat.c
@@ -1,62 +1,136 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file compat.c
|
||||
*
|
||||
/*
|
||||
* Compatibility routines for older rsync protocol versions.
|
||||
**/
|
||||
*
|
||||
* Copyright (C) Andrew Tridgell 1996
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
int remote_protocol = 0;
|
||||
int file_extra_cnt = 0; /* count of file-list extras that everyone gets */
|
||||
int inc_recurse = 0;
|
||||
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
|
||||
extern int preserve_links;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_devices;
|
||||
extern int am_sender;
|
||||
extern int local_server;
|
||||
extern int inplace;
|
||||
extern int recurse;
|
||||
extern int use_qsort;
|
||||
extern int allow_inc_recurse;
|
||||
extern int append_mode;
|
||||
extern int fuzzy_basis;
|
||||
extern int read_batch;
|
||||
extern int delay_updates;
|
||||
extern int checksum_seed;
|
||||
extern int basis_dir_cnt;
|
||||
extern int prune_empty_dirs;
|
||||
extern int protocol_version;
|
||||
extern int protect_args;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_times;
|
||||
extern int always_checksum;
|
||||
extern int checksum_seed;
|
||||
extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int need_messages_from_generator;
|
||||
extern int delete_mode, delete_before, delete_during, delete_after;
|
||||
extern char *shell_cmd; /* contains VER.SUB string if client is a pre-release */
|
||||
extern char *partial_dir;
|
||||
extern char *dest_option;
|
||||
extern char *files_from;
|
||||
extern char *filesfrom_host;
|
||||
extern struct filter_list_struct filter_list;
|
||||
#ifdef ICONV_OPTION
|
||||
extern char *iconv_opt;
|
||||
extern iconv_t ic_send, ic_recv;
|
||||
#endif
|
||||
|
||||
extern int protocol_version;
|
||||
extern int verbose;
|
||||
/* These index values are for the file-list's extra-attribute array. */
|
||||
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx;
|
||||
#ifdef ICONV_OPTION
|
||||
int ic_ndx;
|
||||
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
int filesfrom_convert = 0;
|
||||
#endif
|
||||
|
||||
/* The server makes sure that if either side only supports a pre-release
|
||||
* version of a protocol, that both sides must speak a compatible version
|
||||
* of that protocol for it to be advertised as available. */
|
||||
static void check_sub_protocol(void)
|
||||
{
|
||||
char *dot;
|
||||
int their_protocol, their_sub;
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
|
||||
#else
|
||||
int our_sub = 0;
|
||||
#endif
|
||||
|
||||
if (!shell_cmd || !(dot = strchr(shell_cmd, '.'))
|
||||
|| !(their_protocol = atoi(shell_cmd))
|
||||
|| !(their_sub = atoi(dot+1))) {
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
if (our_sub)
|
||||
protocol_version--;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (their_protocol < protocol_version) {
|
||||
if (their_sub)
|
||||
protocol_version = their_protocol - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (their_protocol > protocol_version)
|
||||
their_sub = 0; /* 0 == final version of older protocol */
|
||||
if (their_sub != our_sub)
|
||||
protocol_version--;
|
||||
}
|
||||
|
||||
void setup_protocol(int f_out,int f_in)
|
||||
{
|
||||
if (am_sender)
|
||||
file_extra_cnt += PTR_EXTRA_CNT;
|
||||
else
|
||||
file_extra_cnt++;
|
||||
if (preserve_uid)
|
||||
uid_ndx = ++file_extra_cnt;
|
||||
if (preserve_gid)
|
||||
gid_ndx = ++file_extra_cnt;
|
||||
if (preserve_acls && !am_sender)
|
||||
acls_ndx = ++file_extra_cnt;
|
||||
if (preserve_xattrs)
|
||||
xattrs_ndx = ++file_extra_cnt;
|
||||
|
||||
if (remote_protocol == 0) {
|
||||
if (am_server) {
|
||||
remote_protocol = read_int(f_in);
|
||||
if (am_server && !local_server)
|
||||
check_sub_protocol();
|
||||
if (!read_batch)
|
||||
write_int(f_out, protocol_version);
|
||||
} else {
|
||||
write_int(f_out, protocol_version);
|
||||
remote_protocol = read_int(f_in);
|
||||
}
|
||||
remote_protocol = read_int(f_in);
|
||||
if (protocol_version > remote_protocol)
|
||||
protocol_version = remote_protocol;
|
||||
}
|
||||
if (read_batch && remote_protocol > protocol_version) {
|
||||
rprintf(FERROR, "The protocol version in the batch file is too new (%d > %d).\n",
|
||||
remote_protocol, protocol_version);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n",
|
||||
@@ -64,7 +138,7 @@ void setup_protocol(int f_out,int f_in)
|
||||
}
|
||||
if (remote_protocol < MIN_PROTOCOL_VERSION
|
||||
|| remote_protocol > MAX_PROTOCOL_VERSION) {
|
||||
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
|
||||
rprintf(FERROR,"protocol version mismatch -- is your shell clean?\n");
|
||||
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
@@ -83,6 +157,94 @@ void setup_protocol(int f_out,int f_in)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (protocol_version < 30) {
|
||||
if (append_mode == 1)
|
||||
append_mode = 2;
|
||||
if (preserve_acls && !local_server) {
|
||||
rprintf(FERROR,
|
||||
"--acls requires protocol 30 or higher"
|
||||
" (negotiated %d).\n",
|
||||
protocol_version);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (preserve_xattrs && !local_server) {
|
||||
rprintf(FERROR,
|
||||
"--xattrs requires protocol 30 or higher"
|
||||
" (negotiated %d).\n",
|
||||
protocol_version);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_mode && !(delete_before+delete_during+delete_after)) {
|
||||
if (protocol_version < 30)
|
||||
delete_before = 1;
|
||||
else
|
||||
delete_during = 1;
|
||||
}
|
||||
|
||||
if (protocol_version < 29) {
|
||||
if (fuzzy_basis) {
|
||||
rprintf(FERROR,
|
||||
"--fuzzy requires protocol 29 or higher"
|
||||
" (negotiated %d).\n",
|
||||
protocol_version);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (basis_dir_cnt && inplace) {
|
||||
rprintf(FERROR,
|
||||
"%s with --inplace requires protocol 29 or higher"
|
||||
" (negotiated %d).\n",
|
||||
dest_option, protocol_version);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (basis_dir_cnt > 1) {
|
||||
rprintf(FERROR,
|
||||
"Using more than one %s option requires protocol"
|
||||
" 29 or higher (negotiated %d).\n",
|
||||
dest_option, protocol_version);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (prune_empty_dirs) {
|
||||
rprintf(FERROR,
|
||||
"--prune-empty-dirs requires protocol 29 or higher"
|
||||
" (negotiated %d).\n",
|
||||
protocol_version);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
} else if (protocol_version >= 30) {
|
||||
if (recurse && allow_inc_recurse
|
||||
&& !delete_before && !delete_after && !delay_updates
|
||||
&& !use_qsort && !prune_empty_dirs)
|
||||
inc_recurse = 1;
|
||||
need_messages_from_generator = 1;
|
||||
}
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (iconv_opt && (!am_sender || inc_recurse))
|
||||
ic_ndx = ++file_extra_cnt;
|
||||
#endif
|
||||
|
||||
if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
|
||||
int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
|
||||
if (!am_sender || protocol_version >= 30)
|
||||
flags |= MATCHFLG_PERISHABLE;
|
||||
parse_rule(&filter_list, partial_dir, flags, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (protect_args && files_from) {
|
||||
if (am_sender)
|
||||
filesfrom_convert = filesfrom_host && ic_send != (iconv_t)-1;
|
||||
else
|
||||
filesfrom_convert = !filesfrom_host && ic_recv != (iconv_t)-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (am_server) {
|
||||
if (!checksum_seed)
|
||||
checksum_seed = time(NULL);
|
||||
|
||||
650
config.guess
vendored
650
config.guess
vendored
File diff suppressed because it is too large
Load Diff
206
config.sub
vendored
206
config.sub
vendored
@@ -1,9 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
|
||||
# Inc.
|
||||
|
||||
timestamp='2003-08-18'
|
||||
timestamp='2006-07-02'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@@ -21,14 +22,15 @@ timestamp='2003-08-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.
|
||||
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
#
|
||||
@@ -70,7 +72,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
@@ -83,11 +85,11 @@ Try \`$me --help' for more information."
|
||||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
--time-stamp | --time* | -t )
|
||||
echo "$timestamp" ; exit 0 ;;
|
||||
echo "$timestamp" ; exit ;;
|
||||
--version | -v )
|
||||
echo "$version" ; exit 0 ;;
|
||||
echo "$version" ; exit ;;
|
||||
--help | --h* | -h )
|
||||
echo "$usage"; exit 0 ;;
|
||||
echo "$usage"; exit ;;
|
||||
-- ) # Stop option processing
|
||||
shift; break ;;
|
||||
- ) # Use stdin as input.
|
||||
@@ -99,7 +101,7 @@ while test $# -gt 0 ; do
|
||||
*local*)
|
||||
# First pass through any local machine types.
|
||||
echo $1
|
||||
exit 0;;
|
||||
exit ;;
|
||||
|
||||
* )
|
||||
break ;;
|
||||
@@ -118,7 +120,9 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
@@ -144,7 +148,7 @@ case $os in
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis)
|
||||
-apple | -axis | -knuth | -cray)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
@@ -169,6 +173,10 @@ case $os in
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
-sco6)
|
||||
os=-sco5v6
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5)
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
@@ -185,6 +193,10 @@ case $os in
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5v6*)
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco*)
|
||||
os=-sco3.2v2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
@@ -229,14 +241,16 @@ case $basic_machine in
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| m32r | m68000 | m68k | m88k | mcore \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
@@ -245,6 +259,7 @@ case $basic_machine in
|
||||
| mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr4300 | mips64vr4300el \
|
||||
| mips64vr5000 | mips64vr5000el \
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
@@ -253,20 +268,23 @@ case $basic_machine in
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
| ns16k | ns32k \
|
||||
| openrisc | or32 \
|
||||
| or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| we32k \
|
||||
| x86 | xscale | xstormy16 | xtensa \
|
||||
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| z8k)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
@@ -277,6 +295,9 @@ case $basic_machine in
|
||||
;;
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||
;;
|
||||
ms1)
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
@@ -296,10 +317,10 @@ case $basic_machine in
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* \
|
||||
| bs2000-* \
|
||||
| avr-* | avr32-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | cydra-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
@@ -307,9 +328,9 @@ case $basic_machine in
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| m32r-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | mcore-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
@@ -318,6 +339,7 @@ case $basic_machine in
|
||||
| mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* \
|
||||
| mips64vr5000-* | mips64vr5000el-* \
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
@@ -325,24 +347,28 @@ case $basic_machine in
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
|
||||
| nios-* | nios2-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
||||
| xtensa-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| xstormy16-* | xtensa-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
;;
|
||||
@@ -362,6 +388,9 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
basic_machine=m68010-adobe
|
||||
os=-scout
|
||||
@@ -379,6 +408,9 @@ case $basic_machine in
|
||||
amd64)
|
||||
basic_machine=x86_64-pc
|
||||
;;
|
||||
amd64-*)
|
||||
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
amdahl)
|
||||
basic_machine=580-amdahl
|
||||
os=-sysv
|
||||
@@ -438,12 +470,27 @@ case $basic_machine in
|
||||
basic_machine=j90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
craynv)
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16c)
|
||||
basic_machine=cr16c-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
basic_machine=m68k-crds
|
||||
;;
|
||||
crisv32 | crisv32-* | etraxfs*)
|
||||
basic_machine=crisv32-axis
|
||||
;;
|
||||
cris | cris-* | etrax*)
|
||||
basic_machine=cris-axis
|
||||
;;
|
||||
crx)
|
||||
basic_machine=crx-unknown
|
||||
os=-elf
|
||||
;;
|
||||
da30 | da30-*)
|
||||
basic_machine=m68k-da30
|
||||
;;
|
||||
@@ -466,6 +513,10 @@ case $basic_machine in
|
||||
basic_machine=m88k-motorola
|
||||
os=-sysv3
|
||||
;;
|
||||
djgpp)
|
||||
basic_machine=i586-pc
|
||||
os=-msdosdjgpp
|
||||
;;
|
||||
dpx20 | dpx20-*)
|
||||
basic_machine=rs6000-bull
|
||||
os=-bosx
|
||||
@@ -644,10 +695,6 @@ case $basic_machine in
|
||||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
mmix*)
|
||||
basic_machine=mmix-knuth
|
||||
os=-mmixware
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
@@ -660,6 +707,9 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
;;
|
||||
ms1-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
@@ -728,10 +778,6 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
nv1)
|
||||
basic_machine=nv1-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
@@ -739,9 +785,12 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
or32 | or32-*)
|
||||
openrisc | openrisc-*)
|
||||
basic_machine=or32-unknown
|
||||
os=-coff
|
||||
;;
|
||||
os400)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-os400
|
||||
;;
|
||||
OSE68000 | ose68000)
|
||||
basic_machine=m68000-ericsson
|
||||
@@ -768,6 +817,12 @@ case $basic_machine in
|
||||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pc98)
|
||||
basic_machine=i386-pc
|
||||
;;
|
||||
pc98-*)
|
||||
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
@@ -824,6 +879,10 @@ case $basic_machine in
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rom68k)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
@@ -963,6 +1022,10 @@ case $basic_machine in
|
||||
tower | tower-32)
|
||||
basic_machine=m68k-ncr
|
||||
;;
|
||||
tpf)
|
||||
basic_machine=s390x-ibm
|
||||
os=-tpf
|
||||
;;
|
||||
udi29k)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
@@ -1006,6 +1069,10 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
xbox)
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
@@ -1036,6 +1103,9 @@ case $basic_machine in
|
||||
romp)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
mmix)
|
||||
basic_machine=mmix-knuth
|
||||
;;
|
||||
rs6000)
|
||||
basic_machine=rs6000-ibm
|
||||
;;
|
||||
@@ -1052,13 +1122,10 @@ case $basic_machine in
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparc | sparcv9 | sparcv9b)
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
@@ -1131,19 +1198,23 @@ case $os in
|
||||
| -aos* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -openbsd* | -solidbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1161,7 +1232,7 @@ case $os in
|
||||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
@@ -1182,6 +1253,9 @@ case $os in
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
os=-wince
|
||||
;;
|
||||
@@ -1203,6 +1277,9 @@ case $os in
|
||||
-atheos*)
|
||||
os=-atheos
|
||||
;;
|
||||
-syllable*)
|
||||
os=-syllable
|
||||
;;
|
||||
-386bsd)
|
||||
os=-bsd
|
||||
;;
|
||||
@@ -1225,6 +1302,9 @@ case $os in
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
os=-sysv3
|
||||
;;
|
||||
@@ -1261,6 +1341,9 @@ case $os in
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1283,6 +1366,9 @@ else
|
||||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
os=-riscix1.2
|
||||
;;
|
||||
@@ -1292,9 +1378,9 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
@@ -1338,9 +1424,15 @@ case $basic_machine in
|
||||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-haiku)
|
||||
os=-haiku
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
os=-proelf
|
||||
;;
|
||||
@@ -1473,9 +1565,15 @@ case $basic_machine in
|
||||
-mvs* | -opened*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-os400*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-ptx*)
|
||||
vendor=sequent
|
||||
;;
|
||||
-tpf*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-vxsim* | -vxworks* | -windiss*)
|
||||
vendor=wrs
|
||||
;;
|
||||
@@ -1500,7 +1598,7 @@ case $basic_machine in
|
||||
esac
|
||||
|
||||
echo $basic_machine$os
|
||||
exit 0
|
||||
exit
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
|
||||
551
configure.in
551
configure.in
@@ -3,9 +3,9 @@ dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT()
|
||||
AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.52)
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
RSYNC_VERSION=2.6.2
|
||||
RSYNC_VERSION=3.0.0pre2
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -26,8 +26,7 @@ AC_SUBST(SHELL)
|
||||
AC_DEFINE([_GNU_SOURCE], 1,
|
||||
[Define _GNU_SOURCE so that we get all necessary prototypes])
|
||||
|
||||
if test "x$ac_cv_prog_cc_stdc" = xno
|
||||
then
|
||||
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
|
||||
fi
|
||||
|
||||
@@ -38,12 +37,10 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([whether to include debugging symbols])
|
||||
AC_ARG_ENABLE(debug,
|
||||
AC_HELP_STRING([--enable-debug],
|
||||
[including debugging symbols and features (default yes)]),
|
||||
[], [])
|
||||
AC_HELP_STRING([--disable-debug],
|
||||
[disable debugging symbols and features]))
|
||||
|
||||
if test x"$enable_debug" = x"no"
|
||||
then
|
||||
if test x"$enable_debug" = x"no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
else
|
||||
@@ -54,25 +51,19 @@ else
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
AC_ARG_ENABLE(profile,
|
||||
AC_HELP_STRING([--enable-profile],
|
||||
[turn on CPU profiling (default no)],
|
||||
[], []))
|
||||
if test x"$enable_profile" = xyes
|
||||
then
|
||||
AC_HELP_STRING([--enable-profile],
|
||||
[turn on CPU profiling]))
|
||||
if test x"$enable_profile" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -pg"
|
||||
fi
|
||||
|
||||
|
||||
# Specifically, this turns on panic_action handling.
|
||||
AC_ARG_ENABLE(maintainer-mode,
|
||||
AC_HELP_STRING([--enable-maintainer-mode],
|
||||
[turn on extra debug features],
|
||||
[], []))
|
||||
if test x"$enable_maintainer_mode" = xyes
|
||||
then
|
||||
AC_HELP_STRING([--enable-maintainer-mode],
|
||||
[turn on extra debug features]))
|
||||
if test x"$enable_maintainer_mode" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
|
||||
fi
|
||||
|
||||
@@ -82,16 +73,15 @@ fi
|
||||
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
|
||||
|
||||
# If GCC, turn on warnings.
|
||||
if test "x$GCC" = "xyes"
|
||||
then
|
||||
if test x"$GCC" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -Wall -W"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(included-popt,
|
||||
[ --with-included-popt use bundled popt library, not from system])
|
||||
AC_HELP_STRING([--with-included-popt], [use bundled popt library, not from system]))
|
||||
|
||||
AC_ARG_WITH(rsync-path,
|
||||
[ --with-rsync-path=PATH set default --rsync-path to PATH (default: rsync)],
|
||||
AC_HELP_STRING([--with-rsync-path=PATH], [set default --rsync-path to PATH (default: rsync)]),
|
||||
[ RSYNC_PATH="$with_rsync_path" ],
|
||||
[ RSYNC_PATH="rsync" ])
|
||||
|
||||
@@ -122,18 +112,38 @@ AC_ARG_WITH(rsh,
|
||||
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
|
||||
|
||||
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
|
||||
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
|
||||
if test x$HAVE_REMSH = x1; then
|
||||
AC_DEFINE(HAVE_REMSH, 1, [Define to 1 if remote shell is remsh, not rsh])
|
||||
fi
|
||||
|
||||
if test x"$with_rsh" != x
|
||||
then
|
||||
if test x"$with_rsh" != x; then
|
||||
RSYNC_RSH="$with_rsh"
|
||||
else
|
||||
RSYNC_RSH="ssh"
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
|
||||
|
||||
# arrgh. libc in the current debian stable screws up the largefile
|
||||
AC_ARG_WITH(nobody-group,
|
||||
AC_HELP_STRING([--with-nobody-group=GROUP],
|
||||
[set the default unprivileged group (default nobody or nogroup)]),
|
||||
[ NOBODY_GROUP="$with_nobody_group" ])
|
||||
|
||||
if test x"$with_nobody_group" = x; then
|
||||
AC_MSG_CHECKING([the group for user "nobody"])
|
||||
if grep '^nobody:' /etc/group >/dev/null 2>&1; then
|
||||
NOBODY_GROUP=nobody
|
||||
elif grep '^nogroup:' /etc/group >/dev/null 2>&1; then
|
||||
NOBODY_GROUP=nogroup
|
||||
else
|
||||
NOBODY_GROUP=nobody # test for others?
|
||||
fi
|
||||
AC_MSG_RESULT($NOBODY_GROUP)
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(NOBODY_USER, "nobody", [unprivileged user--e.g. nobody])
|
||||
AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unprivileged user])
|
||||
|
||||
# arrgh. libc in some old debian version screwed up the largefile
|
||||
# stuff, getting byte range locking wrong
|
||||
AC_CACHE_CHECK([for broken largefile support],rsync_cv_HAVE_BROKEN_LARGEFILE,[
|
||||
AC_TRY_RUN([
|
||||
@@ -179,10 +189,9 @@ ipv6lib=none
|
||||
ipv6trylibc=yes
|
||||
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
AC_HELP_STRING([--disable-ipv6], [don't even try to use IPv6]))
|
||||
|
||||
if test "x$enable_ipv6" != xno
|
||||
then
|
||||
AC_HELP_STRING([--disable-ipv6],
|
||||
[don't even try to use IPv6]))
|
||||
if test x"$enable_ipv6" != x"no"; then
|
||||
AC_MSG_CHECKING([ipv6 stack type])
|
||||
for i in inria kame linux-glibc linux-inet6 toshiba v6d zeta; do
|
||||
case $i in
|
||||
@@ -271,11 +280,21 @@ yes
|
||||
AC_SEARCH_LIBS(getaddrinfo, inet6)
|
||||
fi
|
||||
|
||||
dnl Do you want to disable use of locale functions
|
||||
AC_ARG_ENABLE([locale],
|
||||
AC_HELP_STRING([--disable-locale],
|
||||
[disable locale features]))
|
||||
AH_TEMPLATE([CONFIG_LOCALE],
|
||||
[Undefine if you don't want locale features. By default this is defined.])
|
||||
if test x"$enable_locale" != x"no"; then
|
||||
AC_DEFINE(CONFIG_LOCALE)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to call shutdown on all sockets])
|
||||
case $host_os in
|
||||
*cygwin* ) AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(SHUTDOWN_ALL_SOCKETS, 1,
|
||||
[Define if sockets need to be shutdown])
|
||||
[Define to 1 if sockets need to be shutdown])
|
||||
;;
|
||||
* ) AC_MSG_RESULT(no);;
|
||||
esac
|
||||
@@ -287,15 +306,50 @@ AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
|
||||
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
|
||||
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
|
||||
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h \
|
||||
netdb.h malloc.h float.h)
|
||||
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h)
|
||||
AC_HEADER_MAJOR
|
||||
|
||||
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
|
||||
AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#ifdef MAJOR_IN_MKDEV
|
||||
#include <sys/mkdev.h>
|
||||
# if !defined makedev && (defined mkdev || defined _WIN32 || defined __WIN32__)
|
||||
# define makedev mkdev
|
||||
# endif
|
||||
#elif defined MAJOR_IN_SYSMACROS
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
dev_t dev = makedev(0, 5, 7);
|
||||
if (major(dev) != 5 || minor(dev) != 7)
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
],
|
||||
rsync_cv_MAKEDEV_TAKES_3_ARGS=yes,rsync_cv_MAKEDEV_TAKES_3_ARGS=no,rsync_cv_MAKEDEV_TAKES_3_ARGS=no)])
|
||||
if test x"$rsync_cv_MAKEDEV_TAKES_3_ARGS" = x"yes"; then
|
||||
AC_DEFINE(MAKEDEV_TAKES_3_ARGS, 1, [Define to 1 if makedev() takes 3 args])
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(long long)
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_CHECK_SIZEOF(int16_t)
|
||||
AC_CHECK_SIZEOF(uint16_t)
|
||||
AC_CHECK_SIZEOF(int32_t)
|
||||
AC_CHECK_SIZEOF(uint32_t)
|
||||
AC_CHECK_SIZEOF(int64_t)
|
||||
AC_CHECK_SIZEOF(off_t)
|
||||
AC_CHECK_SIZEOF(off64_t)
|
||||
AC_CHECK_SIZEOF(time_t)
|
||||
|
||||
AC_C_INLINE
|
||||
AC_C_LONG_DOUBLE
|
||||
|
||||
AC_TYPE_SIGNAL
|
||||
AC_TYPE_UID_T
|
||||
@@ -306,14 +360,13 @@ AC_TYPE_PID_T
|
||||
AC_TYPE_GETGROUPS
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
|
||||
AC_CHECK_TYPE([ino_t], [unsigned])
|
||||
TYPE_SOCKLEN_T
|
||||
|
||||
AC_CACHE_CHECK([for errno in errno.h],rsync_cv_errno, [
|
||||
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
|
||||
rsync_cv_errno=yes,rsync_cv_have_errno_decl=no)])
|
||||
if test x"$rsync_cv_errno" = x"yes"; then
|
||||
AC_DEFINE(HAVE_ERRNO_DECL, 1, [ ])
|
||||
AC_DEFINE(HAVE_ERRNO_DECL, 1, [Define to 1 if errno is declared in errno.h])
|
||||
fi
|
||||
|
||||
# The following test taken from the cvs sources
|
||||
@@ -348,11 +401,37 @@ if test x"$ac_cv_func_connect" = x"no"; then
|
||||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
|
||||
# ac_cv_func_connect=yes
|
||||
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
|
||||
AC_DEFINE(HAVE_CONNECT, 1, [ ])
|
||||
AC_DEFINE(HAVE_CONNECT, 1, [Define to 1 if you have the "connect" function])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB(resolv, inet_ntop)
|
||||
AC_SEARCH_LIBS(inet_ntop, resolv)
|
||||
|
||||
# Solaris and HP-UX weirdness:
|
||||
# Search for libiconv_open (not iconv_open) to discover if -liconv is needed!
|
||||
AC_SEARCH_LIBS(libiconv_open, iconv)
|
||||
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([$]{ac_t:-
|
||||
}[$]am_cv_proto_iconv)
|
||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
|
||||
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
|
||||
|
||||
@@ -383,7 +462,7 @@ if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
|
||||
#include <netdb.h>],[getaddrinfo(NULL, NULL, NULL, NULL);],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_GETADDRINFO, 1,
|
||||
[Define if you have the `getaddrinfo' function.])],
|
||||
[Define to 1 if you have the "getaddrinfo" function.])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_LIBOBJ(lib/getaddrinfo)])])
|
||||
AC_CHECK_FUNCS(getnameinfo, , [AC_LIBOBJ(lib/getnameinfo)])
|
||||
@@ -409,13 +488,22 @@ AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_UN_LEN, 1, [Do we have sockaddr_un.sun_len?]) ],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(struct sockaddr_storage)
|
||||
AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/socket.h>],
|
||||
[struct sockaddr_storage x;],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
|
||||
[Define if you have strct sockaddr_storage.] ),
|
||||
[Define to 1 if you have struct sockaddr_storage.] ),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
|
||||
@@ -427,6 +515,27 @@ AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(struct stat64)
|
||||
AC_TRY_COMPILE([#include <stdio.h>
|
||||
#if HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif
|
||||
],[struct stat64 st;],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_STRUCT_STAT64,1,[Define to 1 if you have struct stat64.]),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
|
||||
#
|
||||
AC_CHECK_FUNCS(strcasecmp)
|
||||
@@ -434,6 +543,11 @@ if test x"$ac_cv_func_strcasecmp" = x"no"; then
|
||||
AC_CHECK_LIB(resolv, strcasecmp)
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(aclsort)
|
||||
if test x"$ac_cv_func_aclsort" = x"no"; then
|
||||
AC_CHECK_LIB(sec, aclsort)
|
||||
fi
|
||||
|
||||
dnl At the moment we don't test for a broken memcmp(), because all we
|
||||
dnl need to do is test for equality, not comparison, and it seems that
|
||||
dnl every platform has a memcmp that can do at least that.
|
||||
@@ -441,10 +555,91 @@ dnl AC_FUNC_MEMCMP
|
||||
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_FUNC_ALLOCA
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \
|
||||
fchmod fstat strchr readlink link utime utimes strftime mtrace \
|
||||
memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk \
|
||||
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid)
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
|
||||
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
|
||||
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
|
||||
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
|
||||
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
|
||||
strerror putenv iconv_open locale_charset nl_langinfo getxattr \
|
||||
extattr_get_link sigaction sigprocmask)
|
||||
|
||||
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
|
||||
if test $ac_cv_func_getpgrp = yes; then
|
||||
AC_FUNC_GETPGRP
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(iconv,
|
||||
AC_HELP_STRING([--disable-iconv],
|
||||
[disable rsync's --iconv option]),
|
||||
[], [enable_iconv=$ac_cv_func_iconv_open])
|
||||
AH_TEMPLATE([ICONV_OPTION],
|
||||
[Define if you want the --iconv option. Specifing a value will set the
|
||||
default iconv setting (a NULL means no --iconv processing by default).])
|
||||
if test x"$enable_iconv" != x"no"; then
|
||||
if test x"$enable_iconv" = x"yes"; then
|
||||
AC_DEFINE(ICONV_OPTION, NULL)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED(ICONV_OPTION, "$enable_iconv")
|
||||
fi
|
||||
AC_DEFINE(UTF8_CHARSET, "UTF-8", [String to pass to iconv() for the UTF-8 charset.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether chown() modifies symlinks],rsync_cv_chown_modifies_symlink,[
|
||||
AC_TRY_RUN([
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
main() {
|
||||
char const *dangling_symlink = "conftest.dangle";
|
||||
unlink(dangling_symlink);
|
||||
if (symlink("conftest.no-such", dangling_symlink) < 0) abort();
|
||||
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(1);
|
||||
exit(0);
|
||||
}],
|
||||
rsync_cv_chown_modifies_symlink=yes,rsync_cv_chown_modifies_symlink=no,rsync_cv_chown_modifies_symlink=no)])
|
||||
if test $rsync_cv_chown_modifies_symlink = yes; then
|
||||
AC_DEFINE(CHOWN_MODIFIES_SYMLINK, 1, [Define to 1 if chown modifies symlinks.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_symlink,[
|
||||
AC_TRY_RUN([
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#define FILENAME "conftest.dangle"
|
||||
main() {
|
||||
unlink(FILENAME);
|
||||
if (symlink("conftest.no-such", FILENAME) < 0) abort();
|
||||
if (link(FILENAME, FILENAME "2") < 0) exit(1);
|
||||
exit(0);
|
||||
}],
|
||||
rsync_cv_can_hardlink_symlink=yes,rsync_cv_can_hardlink_symlink=no,rsync_cv_can_hardlink_symlink=no)])
|
||||
if test $rsync_cv_can_hardlink_symlink = yes; then
|
||||
AC_DEFINE(CAN_HARDLINK_SYMLINK, 1, [Define to 1 if link() can hard-link symlinks.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether link() can hard-link special files],rsync_cv_can_hardlink_special,[
|
||||
AC_TRY_RUN([
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#define FILENAME "conftest.fifi"
|
||||
main() {
|
||||
unlink(FILENAME);
|
||||
if (mkfifo(FILENAME, 0777) < 0) abort();
|
||||
if (link(FILENAME, FILENAME "2") < 0) exit(1);
|
||||
exit(0);
|
||||
}],
|
||||
rsync_cv_can_hardlink_special=yes,rsync_cv_can_hardlink_special=no,rsync_cv_can_hardlink_special=no)])
|
||||
if test $rsync_cv_can_hardlink_special = yes; then
|
||||
AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
|
||||
AC_TRY_RUN([
|
||||
@@ -457,17 +652,15 @@ main() {
|
||||
}],
|
||||
rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)])
|
||||
if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SOCKETPAIR, 1, [ ])
|
||||
AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define to 1 if you have the "socketpair" function])
|
||||
fi
|
||||
|
||||
if test x"$with_included_popt" != x"yes"
|
||||
then
|
||||
if test x"$with_included_popt" != x"yes"; then
|
||||
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to use included libpopt])
|
||||
if test x"$with_included_popt" = x"yes"
|
||||
then
|
||||
if test x"$with_included_popt" = x"yes"; then
|
||||
AC_MSG_RESULT($srcdir/popt)
|
||||
BUILD_POPT='$(popt_OBJS)'
|
||||
CFLAGS="$CFLAGS -I$srcdir/popt"
|
||||
@@ -481,39 +674,11 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for long long],rsync_cv_HAVE_LONGLONG,[
|
||||
AC_TRY_RUN([#include <stdio.h>
|
||||
main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }],
|
||||
rsync_cv_HAVE_LONGLONG=yes,rsync_cv_HAVE_LONGLONG=no,rsync_cv_HAVE_LONGLONG=cross)])
|
||||
if test x"$rsync_cv_HAVE_LONGLONG" = x"yes"; then
|
||||
AC_DEFINE(HAVE_LONGLONG, 1, [ ])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for off64_t],rsync_cv_HAVE_OFF64_T,[
|
||||
AC_TRY_RUN([#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }],
|
||||
rsync_cv_HAVE_OFF64_T=yes,rsync_cv_HAVE_OFF64_T=no,rsync_cv_HAVE_OFF64_T=cross)])
|
||||
if test x"$rsync_cv_HAVE_OFF64_T" = x"yes"; then
|
||||
AC_DEFINE(HAVE_OFF64_T, 1, [ ])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for short ino_t],rsync_cv_HAVE_SHORT_INO_T,[
|
||||
AC_TRY_RUN([#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
|
||||
rsync_cv_HAVE_SHORT_INO_T=yes,rsync_cv_HAVE_SHORT_INO_T=no,rsync_cv_HAVE_SHORT_INO_T=cross)])
|
||||
if test x"$rsync_cv_HAVE_SHORT_INO_T" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SHORT_INO_T, 1, [ ])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for unsigned char],rsync_cv_HAVE_UNSIGNED_CHAR,[
|
||||
AC_TRY_RUN([#include <stdio.h>
|
||||
main() { char c; c=250; exit((c > 0)?0:1); }],
|
||||
rsync_cv_HAVE_UNSIGNED_CHAR=yes,rsync_cv_HAVE_UNSIGNED_CHAR=no,rsync_cv_HAVE_UNSIGNED_CHAR=cross)])
|
||||
if test x"$rsync_cv_HAVE_UNSIGNED_CHAR" = x"yes"; then
|
||||
AC_DEFINE(HAVE_UNSIGNED_CHAR, 1, [ ])
|
||||
AC_CACHE_CHECK([for unsigned char],rsync_cv_SIGNED_CHAR_OK,[
|
||||
AC_TRY_COMPILE([],[signed char *s = ""],
|
||||
rsync_cv_SIGNED_CHAR_OK=yes,rsync_cv_SIGNED_CHAR_OK=no)])
|
||||
if test x"$rsync_cv_SIGNED_CHAR_OK" = x"yes"; then
|
||||
AC_DEFINE(SIGNED_CHAR_OK, 1, [Define to 1 if "signed char" is a valid type])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
|
||||
@@ -524,26 +689,25 @@ if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
|
||||
di->d_name[0] == 0) exit(0); exit(1);} ],
|
||||
rsync_cv_HAVE_BROKEN_READDIR=yes,rsync_cv_HAVE_BROKEN_READDIR=no,rsync_cv_HAVE_BROKEN_READDIR=cross)])
|
||||
if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
|
||||
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [ ])
|
||||
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [Define to 1 if readdir() is broken])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
|
||||
AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <utime.h>],
|
||||
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
|
||||
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no,rsync_cv_HAVE_UTIMBUF=cross)])
|
||||
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no)])
|
||||
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
|
||||
AC_DEFINE(HAVE_UTIMBUF, 1, [ ])
|
||||
AC_DEFINE(HAVE_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
|
||||
AC_TRY_RUN([
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}],
|
||||
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no,rsync_cv_HAVE_GETTIMEOFDAY_TZ=cross)])
|
||||
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
|
||||
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [ ])
|
||||
AC_TRY_COMPILE([#include <sys/time.h>
|
||||
#include <unistd.h>],
|
||||
[struct timeval tv; exit(gettimeofday(&tv, NULL));],
|
||||
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no)])
|
||||
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" != x"no"; then
|
||||
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [Define to 1 if gettimeofday() takes a time-zone arg])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
|
||||
@@ -568,7 +732,7 @@ main() { foo("hello"); }
|
||||
],
|
||||
rsync_cv_HAVE_C99_VSNPRINTF=yes,rsync_cv_HAVE_C99_VSNPRINTF=no,rsync_cv_HAVE_C99_VSNPRINTF=cross)])
|
||||
if test x"$rsync_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
|
||||
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [ ])
|
||||
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [Define to 1 if vsprintf has a C99-compatible return value])
|
||||
fi
|
||||
|
||||
|
||||
@@ -591,37 +755,46 @@ rsync_cv_HAVE_SECURE_MKSTEMP=yes,
|
||||
rsync_cv_HAVE_SECURE_MKSTEMP=no,
|
||||
rsync_cv_HAVE_SECURE_MKSTEMP=cross)])
|
||||
if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [ ])
|
||||
case $target_os in
|
||||
hpux*)
|
||||
dnl HP-UX has a broken mkstemp() implementation they refuse to fix,
|
||||
dnl so we noisily skip using it. See HP change request JAGaf34426
|
||||
dnl for details. (sbonds)
|
||||
AC_MSG_WARN(Skipping broken HP-UX mkstemp() -- using mktemp() instead)
|
||||
;;
|
||||
*)
|
||||
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [Define to 1 if mkstemp() is available and works right])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
|
||||
AC_CACHE_CHECK([if mknod creates FIFOs],rsync_cv_MKNOD_CREATES_FIFOS,[
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
main() { struct in_addr ip; ip.s_addr = 0x12345678;
|
||||
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
|
||||
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
|
||||
exit(0);}],
|
||||
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
|
||||
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
|
||||
AC_DEFINE(REPLACE_INET_NTOA, 1, [ ])
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
main() { int rc, ec; char *fn = "fifo-test";
|
||||
unlink(fn); rc = mknod(fn,S_IFIFO,0600); ec = errno; unlink(fn);
|
||||
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
|
||||
return 0;}],
|
||||
rsync_cv_MKNOD_CREATES_FIFOS=yes,rsync_cv_MKNOD_CREATES_FIFOS=no,rsync_cv_MKNOD_CREATES_FIFOS=cross)])
|
||||
if test x"$rsync_cv_MKNOD_CREATES_FIFOS" = x"yes"; then
|
||||
AC_DEFINE(MKNOD_CREATES_FIFOS, 1, [Define to 1 if mknod() can create FIFOs.])
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK([for broken inet_aton],rsync_cv_REPLACE_INET_ATON,[
|
||||
AC_CACHE_CHECK([if mknod creates sockets],rsync_cv_MKNOD_CREATES_SOCKETS,[
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
main() { struct in_addr ip;
|
||||
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
|
||||
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
|
||||
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then
|
||||
AC_DEFINE(REPLACE_INET_ATON, 1, [ ])
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
main() { int rc, ec; char *fn = "sock-test";
|
||||
unlink(fn); rc = mknod(fn,S_IFSOCK,0600); ec = errno; unlink(fn);
|
||||
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
|
||||
return 0;}],
|
||||
rsync_cv_MKNOD_CREATES_SOCKETS=yes,rsync_cv_MKNOD_CREATES_SOCKETS=no,rsync_cv_MKNOD_CREATES_SOCKETS=cross)])
|
||||
if test x"$rsync_cv_MKNOD_CREATES_SOCKETS" = x"yes"; then
|
||||
AC_DEFINE(MKNOD_CREATES_SOCKETS, 1, [Define to 1 if mknod() can create sockets.])
|
||||
fi
|
||||
|
||||
#
|
||||
@@ -655,24 +828,136 @@ AC_SUBST(OBJ_RESTORE)
|
||||
AC_SUBST(CC_SHOBJ_FLAG)
|
||||
AC_SUBST(BUILD_POPT)
|
||||
|
||||
AC_CHECK_HEADERS(sys/acl.h acl/libacl.h)
|
||||
AC_CHECK_FUNCS(_acl __acl _facl __facl)
|
||||
#################################################
|
||||
# check for ACL support
|
||||
|
||||
AC_MSG_CHECKING([whether to support ACLs])
|
||||
AC_ARG_ENABLE(acl-support,
|
||||
AC_HELP_STRING([--disable-acl-support],
|
||||
[disable ACL support]))
|
||||
|
||||
if test x"$enable_acl_support" = x"no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
case "$host_os" in
|
||||
*sysv5*)
|
||||
AC_MSG_RESULT(Using UnixWare ACLs)
|
||||
AC_DEFINE(HAVE_UNIXWARE_ACLS, 1, [true if you have UnixWare ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1, [Define to 1 to add support for ACLs])
|
||||
;;
|
||||
*solaris*|*cygwin*)
|
||||
AC_MSG_RESULT(Using solaris ACLs)
|
||||
AC_DEFINE(HAVE_SOLARIS_ACLS, 1, [true if you have solaris ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*hpux*)
|
||||
AC_MSG_RESULT(Using HPUX ACLs)
|
||||
AC_DEFINE(HAVE_HPUX_ACLS, 1, [true if you have HPUX ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*irix*)
|
||||
AC_MSG_RESULT(Using IRIX ACLs)
|
||||
AC_DEFINE(HAVE_IRIX_ACLS, 1, [true if you have IRIX ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*aix*)
|
||||
AC_MSG_RESULT(Using AIX ACLs)
|
||||
AC_DEFINE(HAVE_AIX_ACLS, 1, [true if you have AIX ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*osf*)
|
||||
AC_MSG_RESULT(Using Tru64 ACLs)
|
||||
AC_DEFINE(HAVE_TRU64_ACLS, 1, [true if you have Tru64 ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
LIBS="$LIBS -lpacl"
|
||||
;;
|
||||
darwin*)
|
||||
AC_MSG_RESULT(Using OS X ACLs)
|
||||
AC_DEFINE(HAVE_OSX_ACLS, 1, [true if you have Mac OS X ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT(running tests:)
|
||||
AC_CHECK_LIB(acl,acl_get_file)
|
||||
AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[
|
||||
AC_TRY_LINK([#include <sys/types.h>
|
||||
#include <sys/acl.h>],
|
||||
[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);],
|
||||
samba_cv_HAVE_POSIX_ACLS=yes,samba_cv_HAVE_POSIX_ACLS=no)])
|
||||
AC_MSG_CHECKING(ACL test results)
|
||||
if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
|
||||
AC_MSG_RESULT(Using posix ACLs)
|
||||
AC_DEFINE(HAVE_POSIX_ACLS, 1, [true if you have posix ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
|
||||
AC_TRY_LINK([#include <sys/types.h>
|
||||
#include <sys/acl.h>],
|
||||
[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);],
|
||||
samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)])
|
||||
if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
|
||||
AC_DEFINE(HAVE_ACL_GET_PERM_NP, 1, [true if you have acl_get_perm_np])
|
||||
fi
|
||||
else
|
||||
if test x"$enable_acl_support" = x"yes"; then
|
||||
AC_MSG_ERROR(Failed to find ACL support)
|
||||
else
|
||||
AC_MSG_RESULT(No ACL support found)
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(attr/xattr.h)
|
||||
AC_CHECK_HEADERS(sys/xattr.h)
|
||||
AC_CHECK_HEADERS(sys/extattr.h)
|
||||
|
||||
#################################################
|
||||
# check for extended attribute support
|
||||
AC_MSG_CHECKING(whether to support extended attributes)
|
||||
AC_ARG_ENABLE(xattr-support,
|
||||
AC_HELP_STRING([--disable-xattr-support],
|
||||
[disable extended attributes]),
|
||||
[], [case "$ac_cv_func_getxattr$ac_cv_func_extattr_get_link" in
|
||||
*yes*) enable_xattr_support=maybe ;;
|
||||
*) enable_xattr_support=no ;;
|
||||
esac])
|
||||
AH_TEMPLATE([SUPPORT_XATTRS],
|
||||
[Define to 1 to add support for extended attributes])
|
||||
if test x"$enable_xattr_support" = x"no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
case "$host_os" in
|
||||
*linux*)
|
||||
AC_MSG_RESULT(Using Linux xattrs)
|
||||
AC_DEFINE(HAVE_LINUX_XATTRS, 1, [True if you have Linux xattrs])
|
||||
AC_DEFINE(SUPPORT_XATTRS, 1)
|
||||
;;
|
||||
darwin*)
|
||||
AC_MSG_RESULT(Using OS X xattrs)
|
||||
AC_DEFINE(HAVE_OSX_XATTRS, 1, [True if you have Mac OS X xattrs])
|
||||
AC_DEFINE(SUPPORT_XATTRS, 1)
|
||||
;;
|
||||
freebsd*)
|
||||
AC_MSG_RESULT(Using FreeBSD extattrs)
|
||||
AC_DEFINE(HAVE_FREEBSD_XATTRS, 1, [True if you have FreeBSD xattrs])
|
||||
AC_DEFINE(SUPPORT_XATTRS, 1)
|
||||
;;
|
||||
*)
|
||||
if test x"$enable_xattr_support" = x"yes"; then
|
||||
AC_MSG_ERROR(Failed to find extended attribute support)
|
||||
else
|
||||
AC_MSG_RESULT(No extended attribute support found)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
if test x"$with_rsh" = x; then
|
||||
if test x"$HAVE_REMSH" = x1; then
|
||||
rmsh1='remsh:'
|
||||
rmsh2='=remsh'
|
||||
else
|
||||
rmsh1='rsh: '
|
||||
rmsh2='=rsh '
|
||||
fi
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ **********************************************************************])
|
||||
AC_MSG_RESULT([ * As of v2.6.0, the default remote shell is ssh instead of rsh!! *])
|
||||
AC_MSG_RESULT([ * To use previous default of $rmsh1 ./configure --with-rsh$rmsh2 *])
|
||||
AC_MSG_RESULT([ **********************************************************************])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
67
connection.c
67
connection.c
@@ -1,49 +1,46 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* Support the max connections option.
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* support the max connections option */
|
||||
#include "rsync.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
simple routine to do connection counting
|
||||
****************************************************************************/
|
||||
int claim_connection(char *fname,int max_connections)
|
||||
/* A simple routine to do connection counting. This returns 1 on success
|
||||
* and 0 on failure, with errno also being set if the open() failed (errno
|
||||
* will be 0 if the lock request failed). */
|
||||
int claim_connection(char *fname, int max_connections)
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (max_connections <= 0)
|
||||
if (max_connections == 0)
|
||||
return 1;
|
||||
|
||||
fd = open(fname,O_RDWR|O_CREAT, 0600);
|
||||
|
||||
if (fd == -1) {
|
||||
if ((fd = open(fname, O_RDWR|O_CREAT, 0600)) < 0)
|
||||
return 0;
|
||||
|
||||
/* Find a free spot. */
|
||||
for (i = 0; i < max_connections; i++) {
|
||||
if (lock_range(fd, i*4, 4))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* find a free spot */
|
||||
for (i=0;i<max_connections;i++) {
|
||||
if (lock_range(fd, i*4, 4)) return 1;
|
||||
}
|
||||
|
||||
/* only interested in open failures */
|
||||
errno = 0;
|
||||
|
||||
close(fd);
|
||||
|
||||
/* A lock failure needs to return an errno of 0. */
|
||||
errno = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
47
errcode.h
47
errcode.h
@@ -1,27 +1,26 @@
|
||||
/* -*- c-file-style: "linux"; -*-
|
||||
|
||||
Copyright (C) 1998-2000 by Andrew Tridgell
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* error codes returned by rsync. If you change these, please also update the
|
||||
* string mappings in log.c and the EXIT VALUES in rsync.yo
|
||||
* Error codes returned by rsync.
|
||||
*
|
||||
* Copyright (C) 1998-2000 Andrew Tridgell
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* If you change these, please also update the string mappings in log.c and
|
||||
* the EXIT VALUES in rsync.yo. */
|
||||
|
||||
#define RERR_OK 0
|
||||
#define RERR_SYNTAX 1 /* syntax or usage error */
|
||||
#define RERR_PROTOCOL 2 /* protocol incompatibility */
|
||||
@@ -34,12 +33,16 @@
|
||||
#define RERR_STREAMIO 12 /* error in rsync protocol data stream */
|
||||
#define RERR_MESSAGEIO 13 /* errors with program diagnostics */
|
||||
#define RERR_IPC 14 /* error in IPC code */
|
||||
#define RERR_CRASHED 15 /* sibling crashed */
|
||||
#define RERR_TERMINATED 16 /* sibling terminated abnormally */
|
||||
|
||||
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
|
||||
#define RERR_SIGNAL1 19 /* status returned when sent SIGUSR1 */
|
||||
#define RERR_SIGNAL 20 /* status returned when sent SIGINT, SIGTERM, SIGHUP */
|
||||
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
|
||||
#define RERR_MALLOC 22 /* error allocating core memory buffers */
|
||||
#define RERR_PARTIAL 23 /* partial transfer */
|
||||
#define RERR_VANISHED 24 /* file(s) vanished on sender side */
|
||||
#define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */
|
||||
|
||||
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
|
||||
|
||||
|
||||
241
fileio.c
241
fileio.c
@@ -1,70 +1,82 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
Copyright (C) 2002 by Martin Pool
|
||||
* File IO utilities used in rsync.
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
File IO utilities used in rsync
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
static char last_byte;
|
||||
static int last_sparse;
|
||||
#ifndef ENODATA
|
||||
#define ENODATA EAGAIN
|
||||
#endif
|
||||
|
||||
extern int sparse_files;
|
||||
|
||||
static char last_byte;
|
||||
static size_t sparse_seek = 0;
|
||||
|
||||
int sparse_end(int f)
|
||||
{
|
||||
if (last_sparse) {
|
||||
do_lseek(f,-1,SEEK_CUR);
|
||||
return (write(f,&last_byte,1) == 1 ? 0 : -1);
|
||||
}
|
||||
last_sparse = 0;
|
||||
return 0;
|
||||
int ret;
|
||||
|
||||
if (!sparse_seek)
|
||||
return 0;
|
||||
|
||||
do_lseek(f, sparse_seek-1, SEEK_CUR);
|
||||
sparse_seek = 0;
|
||||
|
||||
do {
|
||||
ret = write(f, "", 1);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
return ret <= 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static int write_sparse(int f,char *buf,size_t len)
|
||||
static int write_sparse(int f, char *buf, size_t len)
|
||||
{
|
||||
size_t l1=0, l2=0;
|
||||
size_t l1 = 0, l2 = 0;
|
||||
int ret;
|
||||
|
||||
for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
|
||||
for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}
|
||||
|
||||
/* XXX Riddle me this: why does this function SLOW DOWN when I
|
||||
* remove the following (unneeded) line?? Core Duo weirdness? */
|
||||
last_byte = buf[len-1];
|
||||
|
||||
if (l1 == len || l2 > 0)
|
||||
last_sparse=1;
|
||||
|
||||
if (l1 > 0) {
|
||||
do_lseek(f,l1,SEEK_CUR);
|
||||
}
|
||||
sparse_seek += l1;
|
||||
|
||||
if (l1 == len)
|
||||
return len;
|
||||
|
||||
ret = write(f, buf + l1, len - (l1+l2));
|
||||
if (ret == -1 || ret == 0)
|
||||
return ret;
|
||||
else if (ret != (int) (len - (l1+l2)))
|
||||
return (l1+ret);
|
||||
if (sparse_seek)
|
||||
do_lseek(f, sparse_seek, SEEK_CUR);
|
||||
sparse_seek = l2;
|
||||
|
||||
if (l2 > 0)
|
||||
do_lseek(f,l2,SEEK_CUR);
|
||||
while ((ret = write(f, buf + l1, len - (l1+l2))) <= 0) {
|
||||
if (ret < 0 && errno == EINTR)
|
||||
continue;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret != (int)(len - (l1+l2)))
|
||||
return l1+ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -91,6 +103,7 @@ int flush_write_file(int f)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* write_file does not allow incomplete writes. It loops internally
|
||||
* until len bytes are written or errno is set.
|
||||
@@ -101,14 +114,14 @@ int write_file(int f,char *buf,size_t len)
|
||||
|
||||
while (len > 0) {
|
||||
int r1;
|
||||
if (sparse_files) {
|
||||
if (sparse_files > 0) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
r1 = write_sparse(f, buf, len1);
|
||||
} else {
|
||||
if (!wf_writeBuf) {
|
||||
wf_writeBufSize = MAX_MAP_SIZE;
|
||||
wf_writeBufSize = WRITE_SIZE * 8;
|
||||
wf_writeBufCnt = 0;
|
||||
wf_writeBuf = new_array(char, MAX_MAP_SIZE);
|
||||
wf_writeBuf = new_array(char, wf_writeBufSize);
|
||||
if (!wf_writeBuf)
|
||||
out_of_memory("write_file");
|
||||
}
|
||||
@@ -125,7 +138,8 @@ int write_file(int f,char *buf,size_t len)
|
||||
}
|
||||
}
|
||||
if (r1 <= 0) {
|
||||
if (ret > 0) return ret;
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
return r1;
|
||||
}
|
||||
len -= r1;
|
||||
@@ -136,81 +150,71 @@ int write_file(int f,char *buf,size_t len)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* this provides functionality somewhat similar to mmap() but using
|
||||
read(). It gives sliding window access to a file. mmap() is not
|
||||
used because of the possibility of another program (such as a
|
||||
mailer) truncating the file thus giving us a SIGBUS */
|
||||
struct map_struct *map_file(int fd,OFF_T len)
|
||||
/* This provides functionality somewhat similar to mmap() but using read().
|
||||
* It gives sliding window access to a file. mmap() is not used because of
|
||||
* the possibility of another program (such as a mailer) truncating the
|
||||
* file thus giving us a SIGBUS. */
|
||||
struct map_struct *map_file(int fd, OFF_T len, int32 read_size,
|
||||
int32 blk_size)
|
||||
{
|
||||
struct map_struct *map;
|
||||
map = new(struct map_struct);
|
||||
if (!map) out_of_memory("map_file");
|
||||
|
||||
if (!(map = new0(struct map_struct)))
|
||||
out_of_memory("map_file");
|
||||
|
||||
if (blk_size && (read_size % blk_size))
|
||||
read_size += blk_size - (read_size % blk_size);
|
||||
|
||||
map->fd = fd;
|
||||
map->file_size = len;
|
||||
map->p = NULL;
|
||||
map->p_size = 0;
|
||||
map->p_offset = 0;
|
||||
map->p_fd_offset = 0;
|
||||
map->p_len = 0;
|
||||
map->status = 0;
|
||||
map->def_window_size = read_size;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
/* slide the read window in the file */
|
||||
char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
|
||||
{
|
||||
int nread;
|
||||
int32 nread;
|
||||
OFF_T window_start, read_start;
|
||||
int window_size, read_size, read_offset;
|
||||
int32 window_size, read_size, read_offset;
|
||||
|
||||
if (len == 0) {
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* can't go beyond the end of file */
|
||||
if (len > (map->file_size - offset)) {
|
||||
len = map->file_size - offset;
|
||||
if (len < 0) {
|
||||
rprintf(FERROR, "invalid len passed to map_ptr: %ld\n",
|
||||
(long)len);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
/* in most cases the region will already be available */
|
||||
if (offset >= map->p_offset &&
|
||||
offset+len <= map->p_offset+map->p_len) {
|
||||
return (map->p + (offset - map->p_offset));
|
||||
}
|
||||
|
||||
if (offset >= map->p_offset && offset+len <= map->p_offset+map->p_len)
|
||||
return map->p + (offset - map->p_offset);
|
||||
|
||||
/* nope, we are going to have to do a read. Work out our desired window */
|
||||
if (offset > 2*CHUNK_SIZE) {
|
||||
window_start = offset - 2*CHUNK_SIZE;
|
||||
window_start &= ~((OFF_T)(CHUNK_SIZE-1)); /* assumes power of 2 */
|
||||
} else {
|
||||
window_start = 0;
|
||||
}
|
||||
window_size = MAX_MAP_SIZE;
|
||||
if (window_start + window_size > map->file_size) {
|
||||
window_size = map->file_size - window_start;
|
||||
}
|
||||
if (offset + len > window_start + window_size) {
|
||||
window_size = (offset+len) - window_start;
|
||||
}
|
||||
window_start = offset;
|
||||
window_size = map->def_window_size;
|
||||
if (window_start + window_size > map->file_size)
|
||||
window_size = (int32)(map->file_size - window_start);
|
||||
if (len > window_size)
|
||||
window_size = len;
|
||||
|
||||
/* make sure we have allocated enough memory for the window */
|
||||
if (window_size > map->p_size) {
|
||||
map->p = realloc_array(map->p, char, window_size);
|
||||
if (!map->p) out_of_memory("map_ptr");
|
||||
if (!map->p)
|
||||
out_of_memory("map_ptr");
|
||||
map->p_size = window_size;
|
||||
}
|
||||
|
||||
/* now try to avoid re-reading any bytes by reusing any bytes from the previous
|
||||
buffer. */
|
||||
/* Now try to avoid re-reading any bytes by reusing any bytes
|
||||
* from the previous buffer. */
|
||||
if (window_start >= map->p_offset &&
|
||||
window_start < map->p_offset + map->p_len &&
|
||||
window_start + window_size >= map->p_offset + map->p_len) {
|
||||
read_start = map->p_offset + map->p_len;
|
||||
read_offset = read_start - window_start;
|
||||
read_offset = (int32)(read_start - window_start);
|
||||
read_size = window_size - read_offset;
|
||||
memmove(map->p, map->p + (map->p_len - read_offset), read_offset);
|
||||
} else {
|
||||
@@ -220,33 +224,39 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
}
|
||||
|
||||
if (read_size <= 0) {
|
||||
rprintf(FINFO,"Warning: unexpected read size of %d in map_ptr\n", read_size);
|
||||
} else {
|
||||
if (map->p_fd_offset != read_start) {
|
||||
if (do_lseek(map->fd,read_start,SEEK_SET) != read_start) {
|
||||
rprintf(FERROR,"lseek failed in map_ptr\n");
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
map->p_fd_offset = read_start;
|
||||
}
|
||||
|
||||
if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
|
||||
if (nread < 0) {
|
||||
nread = 0;
|
||||
if (!map->status)
|
||||
map->status = errno;
|
||||
}
|
||||
/* the best we can do is zero the buffer - the file
|
||||
has changed mid transfer! */
|
||||
memset(map->p+read_offset+nread, 0, read_size - nread);
|
||||
}
|
||||
map->p_fd_offset += nread;
|
||||
rprintf(FERROR, "invalid read_size of %ld in map_ptr\n",
|
||||
(long)read_size);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
if (map->p_fd_offset != read_start) {
|
||||
OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET);
|
||||
if (ret != read_start) {
|
||||
rsyserr(FERROR, errno, "lseek returned %.0f, not %.0f",
|
||||
(double)ret, (double)read_start);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
map->p_fd_offset = read_start;
|
||||
}
|
||||
map->p_offset = window_start;
|
||||
map->p_len = window_size;
|
||||
|
||||
return map->p + (offset - map->p_offset);
|
||||
while (read_size > 0) {
|
||||
nread = read(map->fd, map->p + read_offset, read_size);
|
||||
if (nread <= 0) {
|
||||
if (!map->status)
|
||||
map->status = nread ? errno : ENODATA;
|
||||
/* The best we can do is zero the buffer -- the file
|
||||
* has changed mid transfer! */
|
||||
memset(map->p + read_offset, 0, read_size);
|
||||
break;
|
||||
}
|
||||
map->p_fd_offset += nread;
|
||||
read_offset += nread;
|
||||
read_size -= nread;
|
||||
}
|
||||
|
||||
return map->p;
|
||||
}
|
||||
|
||||
|
||||
@@ -259,9 +269,8 @@ int unmap_file(struct map_struct *map)
|
||||
map->p = NULL;
|
||||
}
|
||||
ret = map->status;
|
||||
memset(map, 0, sizeof(*map));
|
||||
memset(map, 0, sizeof map[0]);
|
||||
free(map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
2356
generator.c
2356
generator.c
File diff suppressed because it is too large
Load Diff
23
getfsdev.c
Normal file
23
getfsdev.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "rsync.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
int ret;
|
||||
|
||||
while (--argc > 0) {
|
||||
#ifdef USE_STAT64_FUNCS
|
||||
ret = stat64(*++argv, &st);
|
||||
#else
|
||||
ret = stat(*++argv, &st);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Unable to stat `%s'\n", *argv);
|
||||
exit(1);
|
||||
}
|
||||
printf("%ld/%ld\n", (long)major(st.st_dev),
|
||||
(long)minor(st.st_dev));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
32
getgroups.c
32
getgroups.c
@@ -1,28 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2002 by Martin Pool
|
||||
*
|
||||
* Print out the gids of all groups for the current user. This is like
|
||||
* `id -G` on Linux, but it's too hard to find a portable equivalent.
|
||||
*
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file getgroups.c
|
||||
*
|
||||
* Print out the gids of all groups for the current user. This is
|
||||
* like `id -G` on Linux, but it's too hard to find a portable
|
||||
* equivalent.
|
||||
**/
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
@@ -63,6 +57,6 @@ main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
if (!gid_in_list)
|
||||
printf("%lu", (unsigned long)gid);
|
||||
printf("\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
145
hashtable.c
Normal file
145
hashtable.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Routines to provide a memory-efficient hashtable.
|
||||
*
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#define HASH_LOAD_LIMIT(size) ((size)*3/4)
|
||||
|
||||
struct hashtable *hashtable_create(int size, int key64)
|
||||
{
|
||||
struct hashtable *tbl;
|
||||
int node_size = key64 ? sizeof (struct ht_int64_node )
|
||||
: sizeof (struct ht_int32_node);
|
||||
|
||||
/* Pick a power of 2 that can hold the requested size. */
|
||||
if (size & (size-1) || size < 16) {
|
||||
int req = size;
|
||||
size = 16;
|
||||
while (size < req)
|
||||
size *= 2;
|
||||
}
|
||||
|
||||
if (!(tbl = new(struct hashtable))
|
||||
|| !(tbl->nodes = new_array0(char, size * node_size)))
|
||||
out_of_memory("hashtable_create");
|
||||
tbl->size = size;
|
||||
tbl->entries = 0;
|
||||
tbl->node_size = node_size;
|
||||
|
||||
return tbl;
|
||||
}
|
||||
|
||||
void hashtable_destroy(struct hashtable *tbl)
|
||||
{
|
||||
free(tbl->nodes);
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
/* This returns the node for the indicated key, either newly created or
|
||||
* already existing. Returns NULL if not allocating and not found. */
|
||||
void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
|
||||
{
|
||||
int key64 = (tbl->node_size > sizeof (struct ht_int32_node));
|
||||
struct ht_int32_node *node;
|
||||
uint32 ndx;
|
||||
|
||||
if (allocate_if_missing && tbl->entries > HASH_LOAD_LIMIT(tbl->size)) {
|
||||
void *old_nodes = tbl->nodes;
|
||||
int size = tbl->size * 2;
|
||||
int i;
|
||||
|
||||
if (!(tbl->nodes = new_array0(char, size * tbl->node_size)))
|
||||
out_of_memory("hashtable_node");
|
||||
tbl->size = size;
|
||||
tbl->entries = 0;
|
||||
|
||||
for (i = size / 2; i-- > 0; ) {
|
||||
struct ht_int32_node *move_node = HT_NODE(tbl, old_nodes, i);
|
||||
int64 move_key = HT_KEY(move_node, key64);
|
||||
if (move_key == 0)
|
||||
continue;
|
||||
node = hashtable_find(tbl, move_key, 1);
|
||||
node->data = move_node->data;
|
||||
}
|
||||
|
||||
free(old_nodes);
|
||||
}
|
||||
|
||||
if (!key64) {
|
||||
/* Based on Jenkins One-at-a-time hash. */
|
||||
uchar buf[4], *keyp = buf;
|
||||
int i;
|
||||
|
||||
SIVAL(buf, 0, key);
|
||||
for (ndx = 0, i = 0; i < 4; i++) {
|
||||
ndx += keyp[i];
|
||||
ndx += (ndx << 10);
|
||||
ndx ^= (ndx >> 6);
|
||||
}
|
||||
ndx += (ndx << 3);
|
||||
ndx ^= (ndx >> 11);
|
||||
ndx += (ndx << 15);
|
||||
} else {
|
||||
/* Based on Jenkins hashword() from lookup3.c. */
|
||||
uint32 a, b, c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + (8 << 2);
|
||||
|
||||
#define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k))))
|
||||
b += (uint32)(key >> 32);
|
||||
a += (uint32)key;
|
||||
c ^= b; c -= rot(b, 14);
|
||||
a ^= c; a -= rot(c, 11);
|
||||
b ^= a; b -= rot(a, 25);
|
||||
c ^= b; c -= rot(b, 16);
|
||||
a ^= c; a -= rot(c, 4);
|
||||
b ^= a; b -= rot(a, 14);
|
||||
c ^= b; c -= rot(b, 24);
|
||||
#undef rot
|
||||
ndx = c;
|
||||
}
|
||||
|
||||
/* If it already exists, return the node. If we're not
|
||||
* allocating, return NULL if the key is not found. */
|
||||
while (1) {
|
||||
int64 nkey;
|
||||
|
||||
ndx &= tbl->size - 1;
|
||||
node = HT_NODE(tbl, tbl->nodes, ndx);
|
||||
nkey = HT_KEY(node, key64);
|
||||
|
||||
if (nkey == key)
|
||||
return node;
|
||||
if (nkey == 0) {
|
||||
if (!allocate_if_missing)
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
ndx++;
|
||||
}
|
||||
|
||||
/* Take over this empty spot and then return the node. */
|
||||
if (key64)
|
||||
((struct ht_int64_node*)node)->key = key;
|
||||
else
|
||||
node->key = key;
|
||||
tbl->entries++;
|
||||
return node;
|
||||
}
|
||||
642
hlink.c
642
hlink.c
@@ -1,211 +1,479 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
* Routines to support hard-linking.
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int dry_run;
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int am_sender;
|
||||
extern int inc_recurse;
|
||||
extern int do_xfers;
|
||||
extern int link_dest;
|
||||
extern int preserve_acls;
|
||||
extern int make_backups;
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static int hlink_compare(struct file_struct **file1, struct file_struct **file2)
|
||||
{
|
||||
struct file_struct *f1 = *file1;
|
||||
struct file_struct *f2 = *file2;
|
||||
|
||||
if (f1->F_DEV != f2->F_DEV)
|
||||
return (int) (f1->F_DEV > f2->F_DEV ? 1 : -1);
|
||||
|
||||
if (f1->F_INODE != f2->F_INODE)
|
||||
return (int) (f1->F_INODE > f2->F_INODE ? 1 : -1);
|
||||
|
||||
return file_compare(file1, file2);
|
||||
}
|
||||
|
||||
static struct file_struct **hlink_list;
|
||||
static int hlink_count;
|
||||
|
||||
#define LINKED(p1,p2) ((p1)->F_DEV == (p2)->F_DEV \
|
||||
&& (p1)->F_INODE == (p2)->F_INODE)
|
||||
|
||||
/* Analyze the data in the hlink_list[], remove items that aren't multiply
|
||||
* linked, and replace the dev+inode data with the hlindex+next linked list. */
|
||||
static void link_idev_data(struct file_list *flist)
|
||||
{
|
||||
struct file_struct *head;
|
||||
int from, to, start;
|
||||
|
||||
alloc_pool_t hlink_pool;
|
||||
alloc_pool_t idev_pool = flist->hlink_pool;
|
||||
|
||||
hlink_pool = pool_create(128 * 1024, sizeof (struct hlink),
|
||||
out_of_memory, POOL_INTERN);
|
||||
|
||||
for (from = to = 0; from < hlink_count; from++) {
|
||||
start = from;
|
||||
head = hlink_list[start];
|
||||
while (from < hlink_count-1
|
||||
&& LINKED(hlink_list[from], hlink_list[from+1])) {
|
||||
pool_free(idev_pool, 0, hlink_list[from]->link_u.idev);
|
||||
hlink_list[from]->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
hlink_list[from]->F_HLINDEX = to;
|
||||
hlink_list[from]->F_NEXT = hlink_list[from+1];
|
||||
from++;
|
||||
}
|
||||
if (from > start) {
|
||||
pool_free(idev_pool, 0, hlink_list[from]->link_u.idev);
|
||||
hlink_list[from]->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
hlink_list[from]->F_HLINDEX = to;
|
||||
hlink_list[from]->F_NEXT = head;
|
||||
hlink_list[from]->flags |= FLAG_HLINK_EOL;
|
||||
hlink_list[to++] = head;
|
||||
} else {
|
||||
pool_free(idev_pool, 0, head->link_u.idev);
|
||||
head->link_u.idev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!to) {
|
||||
free(hlink_list);
|
||||
hlink_list = NULL;
|
||||
pool_destroy(hlink_pool);
|
||||
hlink_pool = NULL;
|
||||
} else {
|
||||
hlink_count = to;
|
||||
if (!(hlink_list = realloc_array(hlink_list,
|
||||
struct file_struct *, hlink_count)))
|
||||
out_of_memory("init_hard_links");
|
||||
}
|
||||
flist->hlink_pool = hlink_pool;
|
||||
pool_destroy(idev_pool);
|
||||
}
|
||||
extern int protocol_version;
|
||||
extern int remove_source_files;
|
||||
extern int stdout_format_has_i;
|
||||
extern int maybe_ATTRS_REPORT;
|
||||
extern char *basis_dir[];
|
||||
extern struct file_list *cur_flist;
|
||||
#ifdef ICONV_OPTION
|
||||
extern int ic_ndx;
|
||||
#endif
|
||||
|
||||
void init_hard_links(struct file_list *flist)
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
|
||||
/* Starting with protocol 30, we use a simple hashtable on the sending side
|
||||
* for hashing the st_dev and st_ino info. The receiving side gets told
|
||||
* (via flags and a "group index") which items are hard-linked together, so
|
||||
* we can avoid the pool of dev+inode data. For incremental recursion mode,
|
||||
* the receiver will use a ndx hash to remember old pathnames. */
|
||||
|
||||
static struct hashtable *dev_tbl;
|
||||
|
||||
static struct hashtable *prior_hlinks;
|
||||
|
||||
static struct file_list *hlink_flist;
|
||||
|
||||
void init_hard_links(void)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int i;
|
||||
if (am_sender || protocol_version < 30)
|
||||
dev_tbl = hashtable_create(16, SIZEOF_INT64 == 8);
|
||||
else if (inc_recurse)
|
||||
prior_hlinks = hashtable_create(1024, 0);
|
||||
}
|
||||
|
||||
if (flist->count < 2)
|
||||
return;
|
||||
struct ht_int64_node *idev_find(int64 dev, int64 ino)
|
||||
{
|
||||
static struct ht_int64_node *dev_node = NULL;
|
||||
struct hashtable *tbl;
|
||||
|
||||
if (hlink_list)
|
||||
free(hlink_list);
|
||||
|
||||
if (!(hlink_list = new_array(struct file_struct *, flist->count)))
|
||||
out_of_memory("init_hard_links");
|
||||
|
||||
hlink_count = 0;
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
if (flist->files[i]->link_u.idev)
|
||||
hlink_list[hlink_count++] = flist->files[i];
|
||||
}
|
||||
|
||||
qsort(hlink_list, hlink_count,
|
||||
sizeof hlink_list[0], (int (*)()) hlink_compare);
|
||||
|
||||
if (!hlink_count) {
|
||||
free(hlink_list);
|
||||
hlink_list = NULL;
|
||||
if (!dev_node || dev_node->key != dev) {
|
||||
/* We keep a separate hash table of inodes for every device. */
|
||||
dev_node = hashtable_find(dev_tbl, dev, 1);
|
||||
if (!(tbl = dev_node->data))
|
||||
tbl = dev_node->data = hashtable_create(512, SIZEOF_INT64 == 8);
|
||||
} else
|
||||
link_idev_data(flist);
|
||||
#endif
|
||||
tbl = dev_node->data;
|
||||
|
||||
return hashtable_find(tbl, ino, 1);
|
||||
}
|
||||
|
||||
int hard_link_check(struct file_struct *file, int skip)
|
||||
void idev_destroy(void)
|
||||
{
|
||||
if (!hlink_list || !file->link_u.links)
|
||||
return 0;
|
||||
if (skip && !(file->flags & FLAG_HLINK_EOL))
|
||||
hlink_list[file->F_HLINDEX] = file->F_NEXT;
|
||||
if (hlink_list[file->F_HLINDEX] != file) {
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "\"%s\" is a hard link\n",
|
||||
f_name(file));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static void hard_link_one(char *hlink1, char *hlink2)
|
||||
{
|
||||
if (do_link(hlink1, hlink2)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "link %s => %s failed: %s\n",
|
||||
hlink2, hlink1, strerror(errno));
|
||||
}
|
||||
}
|
||||
else if (verbose)
|
||||
rprintf(FINFO, "%s => %s\n", hlink2, hlink1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create any hard links in the global hlink_list. They were put
|
||||
* there by running init_hard_links on the filelist.
|
||||
**/
|
||||
void do_hard_links(void)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
struct file_struct *file, *first;
|
||||
char hlink1[MAXPATHLEN];
|
||||
char *hlink2;
|
||||
STRUCT_STAT st1, st2;
|
||||
int i;
|
||||
|
||||
if (!hlink_list)
|
||||
return;
|
||||
for (i = 0; i < dev_tbl->size; i++) {
|
||||
struct ht_int32_node *node = HT_NODE(dev_tbl, dev_tbl->nodes, i);
|
||||
if (node->data)
|
||||
hashtable_destroy(node->data);
|
||||
}
|
||||
|
||||
for (i = 0; i < hlink_count; i++) {
|
||||
first = file = hlink_list[i];
|
||||
if (link_stat(f_name_to(first, hlink1), &st1) != 0)
|
||||
hashtable_destroy(dev_tbl);
|
||||
}
|
||||
|
||||
static int hlink_compare_gnum(int *int1, int *int2)
|
||||
{
|
||||
struct file_struct *f1 = hlink_flist->sorted[*int1];
|
||||
struct file_struct *f2 = hlink_flist->sorted[*int2];
|
||||
int32 gnum1 = F_HL_GNUM(f1);
|
||||
int32 gnum2 = F_HL_GNUM(f2);
|
||||
|
||||
if (gnum1 != gnum2)
|
||||
return gnum1 > gnum2 ? 1 : -1;
|
||||
|
||||
return *int1 > *int2 ? 1 : -1;
|
||||
}
|
||||
|
||||
static void match_gnums(int32 *ndx_list, int ndx_count)
|
||||
{
|
||||
int32 from, prev;
|
||||
struct file_struct *file, *file_next;
|
||||
struct ht_int32_node *node = NULL;
|
||||
int32 gnum, gnum_next;
|
||||
|
||||
qsort(ndx_list, ndx_count, sizeof ndx_list[0],
|
||||
(int (*)()) hlink_compare_gnum);
|
||||
|
||||
for (from = 0; from < ndx_count; from++) {
|
||||
file = hlink_flist->sorted[ndx_list[from]];
|
||||
gnum = F_HL_GNUM(file);
|
||||
if (inc_recurse) {
|
||||
node = hashtable_find(prior_hlinks, gnum, 1);
|
||||
if (!node->data) {
|
||||
node->data = new_array0(char, 5);
|
||||
assert(gnum >= hlink_flist->ndx_start);
|
||||
file->flags |= FLAG_HLINK_FIRST;
|
||||
prev = -1;
|
||||
} else if (CVAL(node->data, 0) == 0) {
|
||||
struct file_list *flist;
|
||||
struct file_struct *fp;
|
||||
prev = IVAL(node->data, 1);
|
||||
flist = flist_for_ndx(prev);
|
||||
assert(flist != NULL);
|
||||
fp = flist->files[prev - flist->ndx_start];
|
||||
fp->flags &= ~FLAG_HLINK_LAST;
|
||||
} else
|
||||
prev = -1;
|
||||
} else {
|
||||
file->flags |= FLAG_HLINK_FIRST;
|
||||
prev = -1;
|
||||
}
|
||||
for ( ; from < ndx_count-1; file = file_next, gnum = gnum_next, from++) { /*SHARED ITERATOR*/
|
||||
file_next = hlink_flist->sorted[ndx_list[from+1]];
|
||||
gnum_next = F_HL_GNUM(file_next);
|
||||
if (gnum != gnum_next)
|
||||
break;
|
||||
F_HL_PREV(file) = prev;
|
||||
/* The linked list must use raw ndx values. */
|
||||
#ifdef ICONV_OPTION
|
||||
if (ic_ndx)
|
||||
prev = F_NDX(file);
|
||||
else
|
||||
#endif
|
||||
prev = ndx_list[from] + hlink_flist->ndx_start;
|
||||
}
|
||||
if (prev < 0 && !inc_recurse) {
|
||||
/* Disable hard-link bit and set DONE so that
|
||||
* HLINK_BUMP()-dependent values are unaffected. */
|
||||
file->flags &= ~(FLAG_HLINKED | FLAG_HLINK_FIRST);
|
||||
file->flags |= FLAG_HLINK_DONE;
|
||||
continue;
|
||||
while ((file = file->F_NEXT) != first) {
|
||||
hlink2 = f_name(file);
|
||||
if (link_stat(hlink2, &st2) == 0) {
|
||||
if (st2.st_dev == st1.st_dev
|
||||
&& st2.st_ino == st1.st_ino)
|
||||
continue;
|
||||
if (make_backups) {
|
||||
if (!make_backup(hlink2))
|
||||
continue;
|
||||
} else if (robust_unlink(hlink2)) {
|
||||
if (verbose > 0) {
|
||||
rprintf(FINFO,
|
||||
"unlink %s failed: %s\n",
|
||||
full_fname(hlink2),
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
file->flags |= FLAG_HLINK_LAST;
|
||||
F_HL_PREV(file) = prev;
|
||||
if (inc_recurse && CVAL(node->data, 0) == 0) {
|
||||
#ifdef ICONV_OPTION
|
||||
if (ic_ndx)
|
||||
prev = F_NDX(file);
|
||||
else
|
||||
#endif
|
||||
prev = ndx_list[from] + hlink_flist->ndx_start;
|
||||
SIVAL(node->data, 1, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Analyze the hard-links in the file-list by creating a list of all the
|
||||
* items that have hlink data, sorting them, and matching up identical
|
||||
* values into clusters. These will be a single linked list from last
|
||||
* to first when we're done. */
|
||||
void match_hard_links(struct file_list *flist)
|
||||
{
|
||||
int i, ndx_count = 0;
|
||||
int32 *ndx_list;
|
||||
|
||||
if (!(ndx_list = new_array(int32, flist->used)))
|
||||
out_of_memory("match_hard_links");
|
||||
|
||||
for (i = 0; i < flist->used; i++) {
|
||||
if (F_IS_HLINKED(flist->sorted[i]))
|
||||
ndx_list[ndx_count++] = i;
|
||||
}
|
||||
|
||||
hlink_flist = flist;
|
||||
|
||||
if (ndx_count)
|
||||
match_gnums(ndx_list, ndx_count);
|
||||
|
||||
free(ndx_list);
|
||||
if (protocol_version < 30)
|
||||
idev_destroy();
|
||||
}
|
||||
|
||||
static int maybe_hard_link(struct file_struct *file, int ndx,
|
||||
const char *fname, int statret, stat_x *sxp,
|
||||
const char *oldname, STRUCT_STAT *old_stp,
|
||||
const char *realname, int itemizing, enum logcode code)
|
||||
{
|
||||
if (statret == 0) {
|
||||
if (sxp->st.st_dev == old_stp->st_dev
|
||||
&& sxp->st.st_ino == old_stp->st_ino) {
|
||||
if (itemizing) {
|
||||
itemize(fname, file, ndx, statret, sxp,
|
||||
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
|
||||
0, "");
|
||||
}
|
||||
if (verbose > 1 && maybe_ATTRS_REPORT)
|
||||
rprintf(FCLIENT, "%s is uptodate\n", fname);
|
||||
file->flags |= FLAG_HLINK_DONE;
|
||||
return 0;
|
||||
}
|
||||
if (make_backups > 0) {
|
||||
if (!make_backup(fname))
|
||||
return -1;
|
||||
} else if (robust_unlink(fname)) {
|
||||
rsyserr(FERROR, errno, "unlink %s failed",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hard_link_one(file, fname, oldname, 0)) {
|
||||
if (itemizing) {
|
||||
itemize(fname, file, ndx, statret, sxp,
|
||||
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
|
||||
realname);
|
||||
}
|
||||
if (code != FNONE && verbose)
|
||||
rprintf(code, "%s => %s\n", fname, realname);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Figure out if a prior entry is still there or if we just have a
|
||||
* cached name for it. Never called with a FLAG_HLINK_FIRST entry. */
|
||||
static char *check_prior(int prev_ndx, int gnum, struct file_list **flist_p)
|
||||
{
|
||||
struct file_list *flist = flist_for_ndx(prev_ndx);
|
||||
struct ht_int32_node *node;
|
||||
|
||||
if (flist) {
|
||||
*flist_p = flist;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = hashtable_find(prior_hlinks, gnum, 0);
|
||||
assert(node != NULL && node->data);
|
||||
assert(CVAL(node->data, 0) != 0);
|
||||
return node->data;
|
||||
}
|
||||
|
||||
/* Only called if FLAG_HLINKED is set and FLAG_HLINK_FIRST is not. Returns:
|
||||
* 0 = process the file, 1 = skip the file, -1 = error occurred. */
|
||||
int hard_link_check(struct file_struct *file, int ndx, const char *fname,
|
||||
int statret, stat_x *sxp, int itemizing,
|
||||
enum logcode code)
|
||||
{
|
||||
STRUCT_STAT prev_st;
|
||||
char namebuf[MAXPATHLEN], altbuf[MAXPATHLEN];
|
||||
char *realname, *prev_name;
|
||||
struct file_list *flist;
|
||||
int gnum = inc_recurse ? F_HL_GNUM(file) : -1;
|
||||
int prev_ndx = F_HL_PREV(file);
|
||||
|
||||
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
|
||||
|
||||
if (!prev_name) {
|
||||
struct file_struct *prev_file = flist->files[prev_ndx - flist->ndx_start];
|
||||
|
||||
/* Is the previous link is not complete yet? */
|
||||
if (!(prev_file->flags & FLAG_HLINK_DONE)) {
|
||||
/* Is the previous link being transferred? */
|
||||
if (prev_file->flags & FLAG_FILE_SENT) {
|
||||
/* Add ourselves to the list of files that will be
|
||||
* updated when the transfer completes, and mark
|
||||
* ourself as waiting for the transfer. */
|
||||
F_HL_PREV(file) = F_HL_PREV(prev_file);
|
||||
F_HL_PREV(prev_file) = ndx;
|
||||
file->flags |= FLAG_FILE_SENT;
|
||||
cur_flist->in_progress++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* There is a finished file to link with! */
|
||||
if (!(prev_file->flags & FLAG_HLINK_FIRST)) {
|
||||
/* The previous previous is FIRST when prev is not. */
|
||||
prev_ndx = F_HL_PREV(prev_file);
|
||||
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
|
||||
/* Update our previous pointer to point to the FIRST. */
|
||||
F_HL_PREV(file) = prev_ndx;
|
||||
}
|
||||
|
||||
if (!prev_name) {
|
||||
int alt_dest;
|
||||
|
||||
prev_file = flist->files[prev_ndx - flist->ndx_start];
|
||||
/* F_HL_PREV() is alt_dest value when DONE && FIRST. */
|
||||
alt_dest = F_HL_PREV(prev_file);
|
||||
|
||||
if (alt_dest >= 0 && dry_run) {
|
||||
pathjoin(namebuf, MAXPATHLEN, basis_dir[alt_dest],
|
||||
f_name(prev_file, NULL));
|
||||
prev_name = namebuf;
|
||||
realname = f_name(prev_file, altbuf);
|
||||
} else {
|
||||
prev_name = f_name(prev_file, namebuf);
|
||||
realname = prev_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (link_stat(prev_name, &prev_st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
full_fname(prev_name));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (statret < 0 && basis_dir[0] != NULL) {
|
||||
/* If we match an alt-dest item, we don't output this as a change. */
|
||||
char cmpbuf[MAXPATHLEN];
|
||||
stat_x alt_sx;
|
||||
int j = 0;
|
||||
#ifdef SUPPORT_ACLS
|
||||
alt_sx.acc_acl = alt_sx.def_acl = NULL;
|
||||
#endif
|
||||
do {
|
||||
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
|
||||
if (link_stat(cmpbuf, &alt_sx.st, 0) < 0)
|
||||
continue;
|
||||
if (link_dest) {
|
||||
if (prev_st.st_dev != alt_sx.st.st_dev
|
||||
|| prev_st.st_ino != alt_sx.st.st_ino)
|
||||
continue;
|
||||
statret = 1;
|
||||
if (verbose < 2 || !stdout_format_has_i) {
|
||||
itemizing = 0;
|
||||
code = FNONE;
|
||||
if (verbose > 1 && maybe_ATTRS_REPORT)
|
||||
rprintf(FCLIENT, "%s is uptodate\n", fname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!unchanged_file(cmpbuf, file, &alt_sx.st))
|
||||
continue;
|
||||
statret = 1;
|
||||
if (unchanged_attrs(cmpbuf, file, &alt_sx))
|
||||
break;
|
||||
} while (basis_dir[++j] != NULL);
|
||||
if (statret == 1) {
|
||||
sxp->st = alt_sx.st;
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode)) {
|
||||
if (!ACL_READY(*sxp))
|
||||
get_acl(cmpbuf, sxp);
|
||||
else {
|
||||
sxp->acc_acl = alt_sx.acc_acl;
|
||||
sxp->def_acl = alt_sx.def_acl;
|
||||
}
|
||||
}
|
||||
hard_link_one(hlink1, hlink2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef SUPPORT_ACLS
|
||||
else if (preserve_acls)
|
||||
free_acl(&alt_sx);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (maybe_hard_link(file, ndx, fname, statret, sxp, prev_name, &prev_st,
|
||||
realname, itemizing, code) < 0)
|
||||
return -1;
|
||||
|
||||
if (remove_source_files == 1 && do_xfers)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hard_link_one(struct file_struct *file, const char *fname,
|
||||
const char *oldname, int terse)
|
||||
{
|
||||
if (do_link(oldname, fname) < 0) {
|
||||
enum logcode code;
|
||||
if (terse) {
|
||||
if (!verbose)
|
||||
return -1;
|
||||
code = FINFO;
|
||||
} else
|
||||
code = FERROR;
|
||||
rsyserr(code, errno, "link %s => %s failed",
|
||||
full_fname(fname), oldname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
file->flags |= FLAG_HLINK_DONE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
|
||||
STRUCT_STAT *stp, int itemizing, enum logcode code,
|
||||
int alt_dest)
|
||||
{
|
||||
stat_x prev_sx;
|
||||
STRUCT_STAT st;
|
||||
char alt_name[MAXPATHLEN], *prev_name;
|
||||
const char *our_name;
|
||||
struct file_list *flist;
|
||||
int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
|
||||
|
||||
if (stp == NULL && prev_ndx >= 0) {
|
||||
if (link_stat(fname, &st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
full_fname(fname));
|
||||
return;
|
||||
}
|
||||
stp = &st;
|
||||
}
|
||||
|
||||
/* FIRST combined with DONE means we were the first to get done. */
|
||||
file->flags |= FLAG_HLINK_FIRST | FLAG_HLINK_DONE;
|
||||
F_HL_PREV(file) = alt_dest;
|
||||
if (alt_dest >= 0 && dry_run) {
|
||||
pathjoin(alt_name, MAXPATHLEN, basis_dir[alt_dest],
|
||||
f_name(file, NULL));
|
||||
our_name = alt_name;
|
||||
} else
|
||||
our_name = fname;
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
prev_sx.acc_acl = prev_sx.def_acl = NULL;
|
||||
#endif
|
||||
|
||||
while ((ndx = prev_ndx) >= 0) {
|
||||
int val;
|
||||
flist = flist_for_ndx(ndx);
|
||||
assert(flist != NULL);
|
||||
file = flist->files[ndx - flist->ndx_start];
|
||||
file->flags = (file->flags & ~FLAG_HLINK_FIRST) | FLAG_HLINK_DONE;
|
||||
prev_ndx = F_HL_PREV(file);
|
||||
F_HL_PREV(file) = fin_ndx;
|
||||
prev_name = f_name(file, NULL);
|
||||
prev_statret = link_stat(prev_name, &prev_sx.st, 0);
|
||||
val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx,
|
||||
our_name, stp, fname, itemizing, code);
|
||||
flist->in_progress--;
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls)
|
||||
free_acl(&prev_sx);
|
||||
#endif
|
||||
if (val < 0)
|
||||
continue;
|
||||
if (remove_source_files == 1 && do_xfers)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
}
|
||||
|
||||
if (inc_recurse) {
|
||||
int gnum = F_HL_GNUM(file);
|
||||
struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
|
||||
assert(node != NULL && node->data != NULL);
|
||||
assert(CVAL(node->data, 0) == 0);
|
||||
free(node->data);
|
||||
if (!(node->data = strdup(our_name)))
|
||||
out_of_memory("finish_hard_link");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
100
ifuncs.h
Normal file
100
ifuncs.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* Inline functions for rsync.
|
||||
*
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
alloc_xbuf(xbuf *xb, size_t sz)
|
||||
{
|
||||
if (!(xb->buf = new_array(char, sz)))
|
||||
out_of_memory("alloc_xbuf");
|
||||
xb->size = sz;
|
||||
xb->len = xb->pos = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
realloc_xbuf(xbuf *xb, size_t sz)
|
||||
{
|
||||
char *bf = realloc_array(xb->buf, char, sz);
|
||||
if (!bf)
|
||||
out_of_memory("realloc_xbuf");
|
||||
xb->buf = bf;
|
||||
xb->size = sz;
|
||||
}
|
||||
|
||||
static inline int
|
||||
to_wire_mode(mode_t mode)
|
||||
{
|
||||
#ifdef SUPPORT_LINKS
|
||||
#if _S_IFLNK != 0120000
|
||||
if (S_ISLNK(mode))
|
||||
return (mode & ~(_S_IFMT)) | 0120000;
|
||||
#endif
|
||||
#endif
|
||||
return mode;
|
||||
}
|
||||
|
||||
static inline mode_t
|
||||
from_wire_mode(int mode)
|
||||
{
|
||||
#if _S_IFLNK != 0120000
|
||||
if ((mode & (_S_IFMT)) == 0120000)
|
||||
return (mode & ~(_S_IFMT)) | _S_IFLNK;
|
||||
#endif
|
||||
return mode;
|
||||
}
|
||||
|
||||
static inline int
|
||||
isDigit(const char *ptr)
|
||||
{
|
||||
return isdigit(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isPrint(const char *ptr)
|
||||
{
|
||||
return isprint(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isSpace(const char *ptr)
|
||||
{
|
||||
return isspace(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isLower(const char *ptr)
|
||||
{
|
||||
return islower(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isUpper(const char *ptr)
|
||||
{
|
||||
return isupper(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
toLower(const char *ptr)
|
||||
{
|
||||
return tolower(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
toUpper(const char *ptr)
|
||||
{
|
||||
return toupper(*(unsigned char *)ptr);
|
||||
}
|
||||
52
io.h
Normal file
52
io.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
extern int protocol_version;
|
||||
|
||||
static inline int32
|
||||
read_varint30(int f)
|
||||
{
|
||||
if (protocol_version < 30)
|
||||
return read_int(f);
|
||||
return read_varint(f);
|
||||
}
|
||||
|
||||
static inline int64
|
||||
read_varlong30(int f, uchar min_bytes)
|
||||
{
|
||||
if (protocol_version < 30)
|
||||
return read_longint(f);
|
||||
return read_varlong(f, min_bytes);
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_varint30(int f, int32 x)
|
||||
{
|
||||
if (protocol_version < 30)
|
||||
write_int(f, x);
|
||||
else
|
||||
write_varint(f, x);
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_varlong30(int f, int64 x, uchar min_bytes)
|
||||
{
|
||||
if (protocol_version < 30)
|
||||
write_longint(f, x);
|
||||
else
|
||||
write_varlong(f, x, min_bytes);
|
||||
}
|
||||
107
lib/compat.c
107
lib/compat.c
@@ -1,42 +1,34 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
Copyright (C) 2002 by Martin Pool
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file compat.c
|
||||
/*
|
||||
* Reimplementations of standard functions for platforms that don't have them.
|
||||
*
|
||||
* Reimplementations of standard functions for platforms that don't
|
||||
* have them.
|
||||
**/
|
||||
|
||||
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2004, 2005, 2006 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup(char *s)
|
||||
{
|
||||
int l = strlen(s) + 1;
|
||||
char *ret = (char *)malloc(l);
|
||||
if (ret)
|
||||
strcpy(ret,s);
|
||||
return ret;
|
||||
int len = strlen(s) + 1;
|
||||
char *ret = (char *)malloc(len);
|
||||
if (ret)
|
||||
memcpy(ret, s, len);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -86,7 +78,7 @@
|
||||
/**
|
||||
* Find the first ocurrence in @p s of any character in @p accept.
|
||||
*
|
||||
* Derived from glibc
|
||||
* Derived from glibc
|
||||
**/
|
||||
char *strpbrk(const char *s, const char *accept)
|
||||
{
|
||||
@@ -105,7 +97,7 @@
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/**
|
||||
* Like strncpy but does not 0 fill the buffer and always null
|
||||
* Like strncpy but does not 0 fill the buffer and always null
|
||||
* terminates.
|
||||
*
|
||||
* @param bufsize is the size of the destination buffer.
|
||||
@@ -128,7 +120,7 @@
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
/**
|
||||
* Like strncat() but does not 0 fill the buffer and always null
|
||||
* Like strncat() but does not 0 fill the buffer and always null
|
||||
* terminates.
|
||||
*
|
||||
* @param bufsize length of the buffer, which should be one more than
|
||||
@@ -150,53 +142,10 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REPLACE_INET_NTOA
|
||||
char *rep_inet_ntoa(struct in_addr ip)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)&ip.s_addr;
|
||||
static char buf[18];
|
||||
#if WORDS_BIGENDIAN
|
||||
snprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
|
||||
#else
|
||||
snprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REPLACE_INET_ATON
|
||||
int inet_aton(const char *cp, struct in_addr *inp)
|
||||
{
|
||||
unsigned int a1, a2, a3, a4;
|
||||
unsigned long ret;
|
||||
|
||||
if (strcmp(cp, "255.255.255.255") == 0) {
|
||||
inp->s_addr = (unsigned) -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf(cp, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) != 4 ||
|
||||
a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;
|
||||
|
||||
inp->s_addr = htonl(ret);
|
||||
|
||||
if (inp->s_addr == (unsigned) -1) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* some systems don't take the 2nd argument */
|
||||
int sys_gettimeofday(struct timeval *tv)
|
||||
{
|
||||
#if HAVE_GETTIMEOFDAY_TZ
|
||||
#ifdef HAVE_GETTIMEOFDAY_TZ
|
||||
return gettimeofday(tv, NULL);
|
||||
#else
|
||||
return gettimeofday(tv);
|
||||
|
||||
@@ -75,13 +75,14 @@ inet_ntop4(const unsigned char *src, char *dst, size_t size)
|
||||
{
|
||||
static const char *fmt = "%u.%u.%u.%u";
|
||||
char tmp[sizeof "255.255.255.255"];
|
||||
size_t len;
|
||||
|
||||
if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
|
||||
{
|
||||
len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]);
|
||||
if (len >= size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
memcpy(dst, tmp, len + 1);
|
||||
|
||||
return (dst);
|
||||
}
|
||||
@@ -106,7 +107,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
|
||||
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
|
||||
struct { int base, len; } best, cur;
|
||||
unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
|
||||
int i;
|
||||
int i, inc;
|
||||
|
||||
/*
|
||||
* Preprocess:
|
||||
@@ -157,13 +158,14 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
|
||||
/* Is this address an encapsulated IPv4? */
|
||||
if (i == 6 && best.base == 0 &&
|
||||
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
|
||||
if (!inet_ntop4(src+12, tp,
|
||||
sizeof tmp - (tp - tmp)))
|
||||
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
|
||||
return (NULL);
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += sprintf(tp, "%x", words[i]);
|
||||
inc = snprintf(tp, 5, "%x", words[i]);
|
||||
assert(inc < 5);
|
||||
tp += inc;
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) ==
|
||||
@@ -178,7 +180,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
memcpy(dst, tmp, tp - tmp);
|
||||
return (dst);
|
||||
}
|
||||
#endif /* AF_INET6 */
|
||||
|
||||
304
lib/md5.c
Normal file
304
lib/md5.c
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* RFC 1321 compliant MD5 implementation
|
||||
*
|
||||
* Copyright (C) 2001-2003 Christophe Devine
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
void md5_begin(md_context *ctx)
|
||||
{
|
||||
ctx->A = 0x67452301;
|
||||
ctx->B = 0xEFCDAB89;
|
||||
ctx->C = 0x98BADCFE;
|
||||
ctx->D = 0x10325476;
|
||||
|
||||
ctx->totalN = ctx->totalN2 = 0;
|
||||
}
|
||||
|
||||
static void md5_process(md_context *ctx, const uchar data[CSUM_CHUNK])
|
||||
{
|
||||
uint32 X[16], A, B, C, D;
|
||||
|
||||
A = ctx->A;
|
||||
B = ctx->B;
|
||||
C = ctx->C;
|
||||
D = ctx->D;
|
||||
|
||||
X[0] = IVAL(data, 0);
|
||||
X[1] = IVAL(data, 4);
|
||||
X[2] = IVAL(data, 8);
|
||||
X[3] = IVAL(data, 12);
|
||||
X[4] = IVAL(data, 16);
|
||||
X[5] = IVAL(data, 20);
|
||||
X[6] = IVAL(data, 24);
|
||||
X[7] = IVAL(data, 28);
|
||||
X[8] = IVAL(data, 32);
|
||||
X[9] = IVAL(data, 36);
|
||||
X[10] = IVAL(data, 40);
|
||||
X[11] = IVAL(data, 44);
|
||||
X[12] = IVAL(data, 48);
|
||||
X[13] = IVAL(data, 52);
|
||||
X[14] = IVAL(data, 56);
|
||||
X[15] = IVAL(data, 60);
|
||||
|
||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define P(a,b,c,d,k,s,t) a += F(b,c,d) + X[k] + t, a = S(a,s) + b
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
|
||||
P(A, B, C, D, 0, 7, 0xD76AA478);
|
||||
P(D, A, B, C, 1, 12, 0xE8C7B756);
|
||||
P(C, D, A, B, 2, 17, 0x242070DB);
|
||||
P(B, C, D, A, 3, 22, 0xC1BDCEEE);
|
||||
P(A, B, C, D, 4, 7, 0xF57C0FAF);
|
||||
P(D, A, B, C, 5, 12, 0x4787C62A);
|
||||
P(C, D, A, B, 6, 17, 0xA8304613);
|
||||
P(B, C, D, A, 7, 22, 0xFD469501);
|
||||
P(A, B, C, D, 8, 7, 0x698098D8);
|
||||
P(D, A, B, C, 9, 12, 0x8B44F7AF);
|
||||
P(C, D, A, B, 10, 17, 0xFFFF5BB1);
|
||||
P(B, C, D, A, 11, 22, 0x895CD7BE);
|
||||
P(A, B, C, D, 12, 7, 0x6B901122);
|
||||
P(D, A, B, C, 13, 12, 0xFD987193);
|
||||
P(C, D, A, B, 14, 17, 0xA679438E);
|
||||
P(B, C, D, A, 15, 22, 0x49B40821);
|
||||
|
||||
#undef F
|
||||
#define F(x,y,z) (y ^ (z & (x ^ y)))
|
||||
|
||||
P(A, B, C, D, 1, 5, 0xF61E2562);
|
||||
P(D, A, B, C, 6, 9, 0xC040B340);
|
||||
P(C, D, A, B, 11, 14, 0x265E5A51);
|
||||
P(B, C, D, A, 0, 20, 0xE9B6C7AA);
|
||||
P(A, B, C, D, 5, 5, 0xD62F105D);
|
||||
P(D, A, B, C, 10, 9, 0x02441453);
|
||||
P(C, D, A, B, 15, 14, 0xD8A1E681);
|
||||
P(B, C, D, A, 4, 20, 0xE7D3FBC8);
|
||||
P(A, B, C, D, 9, 5, 0x21E1CDE6);
|
||||
P(D, A, B, C, 14, 9, 0xC33707D6);
|
||||
P(C, D, A, B, 3, 14, 0xF4D50D87);
|
||||
P(B, C, D, A, 8, 20, 0x455A14ED);
|
||||
P(A, B, C, D, 13, 5, 0xA9E3E905);
|
||||
P(D, A, B, C, 2, 9, 0xFCEFA3F8);
|
||||
P(C, D, A, B, 7, 14, 0x676F02D9);
|
||||
P(B, C, D, A, 12, 20, 0x8D2A4C8A);
|
||||
|
||||
#undef F
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
|
||||
P(A, B, C, D, 5, 4, 0xFFFA3942);
|
||||
P(D, A, B, C, 8, 11, 0x8771F681);
|
||||
P(C, D, A, B, 11, 16, 0x6D9D6122);
|
||||
P(B, C, D, A, 14, 23, 0xFDE5380C);
|
||||
P(A, B, C, D, 1, 4, 0xA4BEEA44);
|
||||
P(D, A, B, C, 4, 11, 0x4BDECFA9);
|
||||
P(C, D, A, B, 7, 16, 0xF6BB4B60);
|
||||
P(B, C, D, A, 10, 23, 0xBEBFBC70);
|
||||
P(A, B, C, D, 13, 4, 0x289B7EC6);
|
||||
P(D, A, B, C, 0, 11, 0xEAA127FA);
|
||||
P(C, D, A, B, 3, 16, 0xD4EF3085);
|
||||
P(B, C, D, A, 6, 23, 0x04881D05);
|
||||
P(A, B, C, D, 9, 4, 0xD9D4D039);
|
||||
P(D, A, B, C, 12, 11, 0xE6DB99E5);
|
||||
P(C, D, A, B, 15, 16, 0x1FA27CF8);
|
||||
P(B, C, D, A, 2, 23, 0xC4AC5665);
|
||||
|
||||
#undef F
|
||||
#define F(x,y,z) (y ^ (x | ~z))
|
||||
|
||||
P(A, B, C, D, 0, 6, 0xF4292244);
|
||||
P(D, A, B, C, 7, 10, 0x432AFF97);
|
||||
P(C, D, A, B, 14, 15, 0xAB9423A7);
|
||||
P(B, C, D, A, 5, 21, 0xFC93A039);
|
||||
P(A, B, C, D, 12, 6, 0x655B59C3);
|
||||
P(D, A, B, C, 3, 10, 0x8F0CCC92);
|
||||
P(C, D, A, B, 10, 15, 0xFFEFF47D);
|
||||
P(B, C, D, A, 1, 21, 0x85845DD1);
|
||||
P(A, B, C, D, 8, 6, 0x6FA87E4F);
|
||||
P(D, A, B, C, 15, 10, 0xFE2CE6E0);
|
||||
P(C, D, A, B, 6, 15, 0xA3014314);
|
||||
P(B, C, D, A, 13, 21, 0x4E0811A1);
|
||||
P(A, B, C, D, 4, 6, 0xF7537E82);
|
||||
P(D, A, B, C, 11, 10, 0xBD3AF235);
|
||||
P(C, D, A, B, 2, 15, 0x2AD7D2BB);
|
||||
P(B, C, D, A, 9, 21, 0xEB86D391);
|
||||
|
||||
#undef F
|
||||
|
||||
ctx->A += A;
|
||||
ctx->B += B;
|
||||
ctx->C += C;
|
||||
ctx->D += D;
|
||||
}
|
||||
|
||||
void md5_update(md_context *ctx, const uchar *input, uint32 length)
|
||||
{
|
||||
uint32 left, fill;
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
left = ctx->totalN & 0x3F;
|
||||
fill = CSUM_CHUNK - left;
|
||||
|
||||
ctx->totalN += length;
|
||||
ctx->totalN &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->totalN < length)
|
||||
ctx->totalN2++;
|
||||
|
||||
if (left && length >= fill) {
|
||||
memcpy(ctx->buffer + left, input, fill);
|
||||
md5_process(ctx, ctx->buffer);
|
||||
length -= fill;
|
||||
input += fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while (length >= CSUM_CHUNK) {
|
||||
md5_process(ctx, input);
|
||||
length -= CSUM_CHUNK;
|
||||
input += CSUM_CHUNK;
|
||||
}
|
||||
|
||||
if (length)
|
||||
memcpy(ctx->buffer + left, input, length);
|
||||
}
|
||||
|
||||
static uchar md5_padding[CSUM_CHUNK] = { 0x80 };
|
||||
|
||||
void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN])
|
||||
{
|
||||
uint32 last, padn;
|
||||
uint32 high, low;
|
||||
uchar msglen[8];
|
||||
|
||||
high = (ctx->totalN >> 29)
|
||||
| (ctx->totalN2 << 3);
|
||||
low = (ctx->totalN << 3);
|
||||
|
||||
SIVAL(msglen, 0, low);
|
||||
SIVAL(msglen, 4, high);
|
||||
|
||||
last = ctx->totalN & 0x3F;
|
||||
padn = last < 56 ? 56 - last : 120 - last;
|
||||
|
||||
md5_update(ctx, md5_padding, padn);
|
||||
md5_update(ctx, msglen, 8);
|
||||
|
||||
SIVAL(digest, 0, ctx->A);
|
||||
SIVAL(digest, 4, ctx->B);
|
||||
SIVAL(digest, 8, ctx->C);
|
||||
SIVAL(digest, 12, ctx->D);
|
||||
}
|
||||
|
||||
void get_md5(uchar *out, const uchar *input, int n)
|
||||
{
|
||||
md_context ctx;
|
||||
md5_begin(&ctx);
|
||||
md5_update(&ctx, input, n);
|
||||
md5_result(&ctx, out);
|
||||
}
|
||||
|
||||
#ifdef TEST_MD5
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* those are the standard RFC 1321 test vectors
|
||||
*/
|
||||
|
||||
static struct {
|
||||
char *str, *md5;
|
||||
} tests[] = {
|
||||
{ "",
|
||||
"d41d8cd98f00b204e9800998ecf8427e" },
|
||||
{ "a",
|
||||
"0cc175b9c0f1b6a831c399e269772661" },
|
||||
{ "abc",
|
||||
"900150983cd24fb0d6963f7d28e17f72" },
|
||||
{ "message digest",
|
||||
"f96b697d7cb7938d525a2f31aaf161d0" },
|
||||
{ "abcdefghijklmnopqrstuvwxyz",
|
||||
"c3fcd3d76192e4007dfb496cca67e13b" },
|
||||
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"d174ab98d277d9f5a5611c2c9f419d9f" },
|
||||
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
"57edf4a22be3c955ac49da2e2107b67a" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *f;
|
||||
int i, j;
|
||||
char output[33];
|
||||
md_context ctx;
|
||||
uchar buf[1000];
|
||||
uchar md5sum[MD5_DIGEST_LEN];
|
||||
|
||||
if (argc < 2) {
|
||||
printf("\nMD5 Validation Tests:\n\n");
|
||||
|
||||
for (i = 0; tests[i].str; i++) {
|
||||
char *str = tests[i].str;
|
||||
char *chk = tests[i].md5;
|
||||
|
||||
printf(" Test %d ", i + 1);
|
||||
|
||||
get_md5(md5sum, str, strlen(str));
|
||||
|
||||
for (j = 0; j < MD5_DIGEST_LEN; j++)
|
||||
sprintf(output + j * 2, "%02x", md5sum[j]);
|
||||
|
||||
if (memcmp(output, chk, 32)) {
|
||||
printf("failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("passed.\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (--argc) {
|
||||
if (!(f = fopen(*++argv, "rb"))) {
|
||||
perror("fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
md5_begin(&ctx);
|
||||
|
||||
while ((i = fread(buf, 1, sizeof buf, f)) > 0)
|
||||
md5_update(&ctx, buf, i);
|
||||
|
||||
md5_result(&ctx, md5sum);
|
||||
|
||||
for (j = 0; j < MD5_DIGEST_LEN; j++)
|
||||
printf("%02x", md5sum[j]);
|
||||
|
||||
printf(" %s\n", *argv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
203
lib/mdfour.c
203
lib/mdfour.c
@@ -1,32 +1,32 @@
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
a implementation of MD4 designed for use in the SMB authentication protocol
|
||||
Copyright (C) Andrew Tridgell 1997-1998.
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
* Unix SMB/Netbios implementation.
|
||||
* Version 1.9.
|
||||
* An implementation of MD4 designed for use in the SMB authentication protocol.
|
||||
*
|
||||
* Copyright (C) 1997-1998 Andrew Tridgell
|
||||
* Copyright (C) 2005-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* NOTE: This code makes no attempt to be fast!
|
||||
*
|
||||
* It assumes that a int is at least 32 bits long. */
|
||||
|
||||
It assumes that a int is at least 32 bits long
|
||||
*/
|
||||
|
||||
static struct mdfour *m;
|
||||
static md_context *m;
|
||||
|
||||
#define MASK32 (0xffffffff)
|
||||
|
||||
@@ -48,32 +48,31 @@ static void mdfour64(uint32 *M)
|
||||
A = m->A; B = m->B; C = m->C; D = m->D;
|
||||
AA = A; BB = B; CC = C; DD = D;
|
||||
|
||||
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
|
||||
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
|
||||
ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
|
||||
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
|
||||
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
|
||||
ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
|
||||
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
|
||||
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
|
||||
ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
|
||||
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
|
||||
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
|
||||
ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
|
||||
|
||||
|
||||
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
|
||||
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
|
||||
ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
|
||||
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
|
||||
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
|
||||
ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
|
||||
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
|
||||
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
|
||||
ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
|
||||
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
|
||||
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
|
||||
ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
|
||||
|
||||
ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
|
||||
ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
|
||||
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
|
||||
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
|
||||
ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
|
||||
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
|
||||
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
|
||||
ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
|
||||
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
|
||||
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
|
||||
ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
|
||||
|
||||
A += AA; B += BB;
|
||||
@@ -85,16 +84,17 @@ static void mdfour64(uint32 *M)
|
||||
m->A = A; m->B = B; m->C = C; m->D = D;
|
||||
}
|
||||
|
||||
static void copy64(uint32 *M, unsigned char *in)
|
||||
static void copy64(uint32 *M, const uchar *in)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<16;i++)
|
||||
M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
|
||||
(in[i*4+1]<<8) | (in[i*4+0]<<0);
|
||||
for (i = 0; i < MD4_DIGEST_LEN; i++) {
|
||||
M[i] = (in[i*4+3] << 24) | (in[i*4+2] << 16)
|
||||
| (in[i*4+1] << 8) | (in[i*4+0] << 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy4(unsigned char *out,uint32 x)
|
||||
static void copy4(uchar *out,uint32 x)
|
||||
{
|
||||
out[0] = x&0xFF;
|
||||
out[1] = (x>>8)&0xFF;
|
||||
@@ -102,7 +102,7 @@ static void copy4(unsigned char *out,uint32 x)
|
||||
out[3] = (x>>24)&0xFF;
|
||||
}
|
||||
|
||||
void mdfour_begin(struct mdfour *md)
|
||||
void mdfour_begin(md_context *md)
|
||||
{
|
||||
md->A = 0x67452301;
|
||||
md->B = 0xefcdab89;
|
||||
@@ -112,27 +112,26 @@ void mdfour_begin(struct mdfour *md)
|
||||
md->totalN2 = 0;
|
||||
}
|
||||
|
||||
|
||||
static void mdfour_tail(unsigned char *in, uint32 n)
|
||||
static void mdfour_tail(const uchar *in, uint32 length)
|
||||
{
|
||||
unsigned char buf[128];
|
||||
uchar buf[128];
|
||||
uint32 M[16];
|
||||
extern int protocol_version;
|
||||
|
||||
/*
|
||||
* Count total number of bits, modulo 2^64
|
||||
*/
|
||||
m->totalN += n << 3;
|
||||
if (m->totalN < (n << 3)) {
|
||||
m->totalN += length << 3;
|
||||
if (m->totalN < (length << 3))
|
||||
m->totalN2++;
|
||||
}
|
||||
m->totalN2 += n >> 29;
|
||||
m->totalN2 += length >> 29;
|
||||
|
||||
memset(buf, 0, 128);
|
||||
if (n) memcpy(buf, in, n);
|
||||
buf[n] = 0x80;
|
||||
if (length)
|
||||
memcpy(buf, in, length);
|
||||
buf[length] = 0x80;
|
||||
|
||||
if (n <= 55) {
|
||||
if (length <= 55) {
|
||||
copy4(buf+56, m->totalN);
|
||||
/*
|
||||
* Prior to protocol version 27 only the number of bits
|
||||
@@ -140,9 +139,8 @@ static void mdfour_tail(unsigned char *in, uint32 n)
|
||||
* of bits modulo 2^64, which was fixed starting with
|
||||
* protocol version 27.
|
||||
*/
|
||||
if (protocol_version >= 27) {
|
||||
if (protocol_version >= 27)
|
||||
copy4(buf+60, m->totalN2);
|
||||
}
|
||||
copy64(M, buf);
|
||||
mdfour64(M);
|
||||
} else {
|
||||
@@ -153,9 +151,8 @@ static void mdfour_tail(unsigned char *in, uint32 n)
|
||||
* of bits modulo 2^64, which was fixed starting with
|
||||
* protocol version 27.
|
||||
*/
|
||||
if (protocol_version >= 27) {
|
||||
if (protocol_version >= 27)
|
||||
copy4(buf+124, m->totalN2);
|
||||
}
|
||||
copy64(M, buf);
|
||||
mdfour64(M);
|
||||
copy64(M, buf+64);
|
||||
@@ -163,54 +160,55 @@ static void mdfour_tail(unsigned char *in, uint32 n)
|
||||
}
|
||||
}
|
||||
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n)
|
||||
void mdfour_update(md_context *md, const uchar *in, uint32 length)
|
||||
{
|
||||
uint32 M[16];
|
||||
|
||||
m = md;
|
||||
|
||||
if (n == 0) mdfour_tail(in, n);
|
||||
if (length == 0)
|
||||
mdfour_tail(in, length);
|
||||
|
||||
while (n >= 64) {
|
||||
while (length >= 64) {
|
||||
copy64(M, in);
|
||||
mdfour64(M);
|
||||
in += 64;
|
||||
n -= 64;
|
||||
length -= 64;
|
||||
m->totalN += 64 << 3;
|
||||
if (m->totalN < 64 << 3) {
|
||||
if (m->totalN < 64 << 3)
|
||||
m->totalN2++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n) mdfour_tail(in, n);
|
||||
if (length)
|
||||
mdfour_tail(in, length);
|
||||
}
|
||||
|
||||
|
||||
void mdfour_result(struct mdfour *md, unsigned char *out)
|
||||
void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN])
|
||||
{
|
||||
m = md;
|
||||
|
||||
copy4(out, m->A);
|
||||
copy4(out+4, m->B);
|
||||
copy4(out+8, m->C);
|
||||
copy4(out+12, m->D);
|
||||
copy4(digest, m->A);
|
||||
copy4(digest+4, m->B);
|
||||
copy4(digest+8, m->C);
|
||||
copy4(digest+12, m->D);
|
||||
}
|
||||
|
||||
|
||||
void mdfour(unsigned char *out, unsigned char *in, int n)
|
||||
void mdfour(uchar digest[MD4_DIGEST_LEN], uchar *in, int length)
|
||||
{
|
||||
struct mdfour md;
|
||||
md_context md;
|
||||
mdfour_begin(&md);
|
||||
mdfour_update(&md, in, n);
|
||||
mdfour_result(&md, out);
|
||||
mdfour_update(&md, in, length);
|
||||
mdfour_result(&md, digest);
|
||||
}
|
||||
|
||||
#ifdef TEST_MDFOUR
|
||||
int protocol_version = 28;
|
||||
|
||||
static void file_checksum1(char *fname)
|
||||
{
|
||||
int fd, i;
|
||||
struct mdfour md;
|
||||
unsigned char buf[64*1024], sum[16];
|
||||
int fd, i, was_multiple_of_64 = 1;
|
||||
md_context md;
|
||||
uchar buf[64*1024], sum[MD4_DIGEST_LEN];
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) {
|
||||
@@ -221,63 +219,28 @@ static void file_checksum1(char *fname)
|
||||
mdfour_begin(&md);
|
||||
|
||||
while (1) {
|
||||
int n = read(fd, buf, sizeof(buf));
|
||||
if (n <= 0) break;
|
||||
int n = read(fd, buf, sizeof buf);
|
||||
if (n <= 0)
|
||||
break;
|
||||
was_multiple_of_64 = !(n % 64);
|
||||
mdfour_update(&md, buf, n);
|
||||
}
|
||||
if (was_multiple_of_64 && protocol_version >= 27)
|
||||
mdfour_update(&md, buf, 0);
|
||||
|
||||
close(fd);
|
||||
|
||||
mdfour_result(&md, sum);
|
||||
|
||||
for (i=0;i<16;i++)
|
||||
for (i = 0; i < MD4_DIGEST_LEN; i++)
|
||||
printf("%02X", sum[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include "../md4.h"
|
||||
|
||||
static void file_checksum2(char *fname)
|
||||
{
|
||||
int fd, i;
|
||||
MDstruct md;
|
||||
unsigned char buf[64], sum[16];
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) {
|
||||
perror("fname");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
MDbegin(&md);
|
||||
|
||||
while (1) {
|
||||
int n = read(fd, buf, sizeof(buf));
|
||||
if (n <= 0) break;
|
||||
MDupdate(&md, buf, n*8);
|
||||
}
|
||||
|
||||
if (!md.done) {
|
||||
MDupdate(&md, buf, 0);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
memcpy(sum, md.buffer, 16);
|
||||
|
||||
for (i=0;i<16;i++)
|
||||
printf("%02X", sum[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
file_checksum1(argv[1]);
|
||||
#if 0
|
||||
file_checksum2(argv[1]);
|
||||
#endif
|
||||
while (--argc)
|
||||
file_checksum1(*++argv);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
35
lib/mdfour.h
35
lib/mdfour.h
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
a implementation of MD4 designed for use in the SMB authentication protocol
|
||||
Copyright (C) Andrew Tridgell 1997-1998.
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
struct mdfour {
|
||||
uint32 A, B, C, D;
|
||||
uint32 totalN; /* bit count, lower 32 bits */
|
||||
uint32 totalN2; /* bit count, upper 32 bits */
|
||||
};
|
||||
|
||||
void mdfour_begin(struct mdfour *md);
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n);
|
||||
void mdfour_result(struct mdfour *md, unsigned char *out);
|
||||
void mdfour(unsigned char *out, unsigned char *in, int n);
|
||||
|
||||
|
||||
|
||||
|
||||
26
lib/mdigest.h
Normal file
26
lib/mdigest.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* The include file for both the MD4 and MD5 routines. */
|
||||
|
||||
#define MD4_DIGEST_LEN 16
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#define MAX_DIGEST_LEN MD5_DIGEST_LEN
|
||||
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
typedef struct {
|
||||
uint32 A, B, C, D;
|
||||
uint32 totalN; /* bit count, lower 32 bits */
|
||||
uint32 totalN2; /* bit count, upper 32 bits */
|
||||
uchar buffer[CSUM_CHUNK];
|
||||
} md_context;
|
||||
|
||||
void mdfour_begin(md_context *md);
|
||||
void mdfour_update(md_context *md, const uchar *in, uint32 length);
|
||||
void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN]);
|
||||
|
||||
void get_mdfour(uchar digest[MD4_DIGEST_LEN], const uchar *in, int length);
|
||||
|
||||
void md5_begin(md_context *ctx);
|
||||
void md5_update(md_context *ctx, const uchar *input, uint32 length);
|
||||
void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN]);
|
||||
|
||||
void get_md5(uchar digest[MD5_DIGEST_LEN], const uchar *input, int n);
|
||||
@@ -1,41 +1,39 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* A single utility routine.
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003, 2006 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/**
|
||||
* Produce a string representation of Unix mode bits like that used by
|
||||
* ls(1).
|
||||
*
|
||||
* @param buf buffer of at least 11 characters
|
||||
**/
|
||||
void permstring(char *perms,
|
||||
int mode)
|
||||
/* Produce a string representation of Unix mode bits like that used by ls(1).
|
||||
* The "buf" buffer must be at least 11 characters. */
|
||||
void permstring(char *perms, mode_t mode)
|
||||
{
|
||||
static const char *perm_map = "rwxrwxrwx";
|
||||
int i;
|
||||
|
||||
strcpy(perms, "----------");
|
||||
|
||||
for (i=0;i<9;i++) {
|
||||
if (mode & (1<<i)) perms[9-i] = perm_map[8-i];
|
||||
strlcpy(perms, "----------", 11);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (mode & (1 << i))
|
||||
perms[9-i] = perm_map[8-i];
|
||||
}
|
||||
|
||||
/* Handle setuid/sticky bits. You might think the indices are
|
||||
@@ -46,18 +44,22 @@ void permstring(char *perms,
|
||||
|
||||
if (mode & S_ISGID)
|
||||
perms[6] = (mode & S_IXGRP) ? 's' : 'S';
|
||||
|
||||
|
||||
#ifdef S_ISVTX
|
||||
if (mode & S_ISVTX)
|
||||
perms[9] = (mode & S_IXOTH) ? 't' : 'T';
|
||||
#endif
|
||||
|
||||
if (S_ISLNK(mode)) perms[0] = 'l';
|
||||
if (S_ISDIR(mode)) perms[0] = 'd';
|
||||
if (S_ISBLK(mode)) perms[0] = 'b';
|
||||
if (S_ISCHR(mode)) perms[0] = 'c';
|
||||
if (S_ISSOCK(mode)) perms[0] = 's';
|
||||
if (S_ISFIFO(mode)) perms[0] = 'p';
|
||||
}
|
||||
|
||||
|
||||
if (S_ISDIR(mode))
|
||||
perms[0] = 'd';
|
||||
else if (S_ISLNK(mode))
|
||||
perms[0] = 'l';
|
||||
else if (S_ISBLK(mode))
|
||||
perms[0] = 'b';
|
||||
else if (S_ISCHR(mode))
|
||||
perms[0] = 'c';
|
||||
else if (S_ISSOCK(mode))
|
||||
perms[0] = 's';
|
||||
else if (S_ISFIFO(mode))
|
||||
perms[0] = 'p';
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#define PERMSTRING_SIZE 11
|
||||
|
||||
void permstring(char *perms, int mode);
|
||||
void permstring(char *perms, mode_t mode);
|
||||
|
||||
169
lib/pool_alloc.3
169
lib/pool_alloc.3
@@ -28,7 +28,7 @@ See \fB\\$1\fP in \fB\\$2\fP for details.
|
||||
..
|
||||
.TH POOL_ALLOC 3
|
||||
.SH NAME
|
||||
pool_alloc, pool_free, pool_talloc, pool_tfree, pool_create, pool_destroy
|
||||
pool_alloc, pool_free, pool_free_old, pool_talloc, pool_tfree, pool_create, pool_destroy, pool_boundary
|
||||
\- Allocate and free memory in managed allocation pools.
|
||||
.SH SYNOPSIS
|
||||
.B #include "pool_alloc.h"
|
||||
@@ -39,42 +39,45 @@ pool_alloc, pool_free, pool_talloc, pool_tfree, pool_create, pool_destroy
|
||||
|
||||
\fBvoid *pool_alloc(struct alloc_pool *\fIpool\fB, size_t \fIsize\fB, char *\fImsg\fB);
|
||||
|
||||
\fBvoid pool_free(struct alloc_pool *\fIpool\fB, sise_t \fIsize\fB, void *\fIaddr\fB);
|
||||
\fBvoid pool_free(struct alloc_pool *\fIpool\fB, size_t \fIsize\fB, void *\fIaddr\fB);
|
||||
|
||||
\fBvoid pool_free_old(struct alloc_pool *\fIpool\fB, void *\fIaddr\fB);
|
||||
|
||||
\fBvoid *pool_talloc(struct alloc_pool *\fIpool\fB, \fItype\fB), int \fIcount\fB, char *\fImsg\fB);
|
||||
|
||||
\fBvoid pool_tfree(struct alloc_pool *\fIpool\fB, \fItype\fB, int \fIcount\fB, void *\fIaddr\fB);
|
||||
|
||||
\fBvoid pool_boundary(struct alloc_pool *\fIpool\fB, sise_t \fIsize\fB);
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
The pool allocation routines use
|
||||
.B malloc()
|
||||
for underlying memory management.
|
||||
What allocation pools do is cause
|
||||
memory within a given pool to be in large contigious blocks
|
||||
(called extents) that when freed will be reusable. Unlike
|
||||
.B malloc()
|
||||
What allocation pools do is cause memory within a given pool
|
||||
to be allocated in large contiguous blocks
|
||||
(called extents) that will be reusable when freed. Unlike
|
||||
.BR malloc() ,
|
||||
the allocations are not managed individually.
|
||||
Instead each extent tracks the total free memory within the
|
||||
Instead, each extent tracks the total free memory within the
|
||||
extent. Each extent can either be used to allocate memory
|
||||
or to manage the freeing of memory within that extent.
|
||||
When an extent has less free memory than a given
|
||||
allocation request or when the first request to free
|
||||
memory within that extent is received the extent ceases to
|
||||
be used for allocation.
|
||||
allocation request, the current extent ceases to be used
|
||||
for allocation. See also the
|
||||
.B pool_boundary()
|
||||
function.
|
||||
.P
|
||||
This form of memory management is suited to large numbers of small
|
||||
related allocations that are held for a while
|
||||
and then freed as a group.
|
||||
Because the
|
||||
underlying allocations are done in large contigious extents
|
||||
when an extent is freed it releases a large enough
|
||||
contigious block of memory to be useful to subsequent
|
||||
underlying allocations are done in large contiguous extents,
|
||||
when an extent is freed, it can release a large enough
|
||||
contiguous block of memory to allow the memory to be returned
|
||||
to the OS for use by whatever program needs it.
|
||||
You can allocate from one or more memory pools and/or
|
||||
.B malloc()
|
||||
and
|
||||
.B pool_alloc()
|
||||
calls even if allocations from other pools or from
|
||||
.B malloc()
|
||||
are made between allocations from a given pool.
|
||||
all at the same time without interfering with how pools work.
|
||||
.P
|
||||
.B pool_create()
|
||||
Creates an allocation pool for subsequent calls to the pool
|
||||
@@ -90,22 +93,32 @@ Specifying
|
||||
.B 0
|
||||
for
|
||||
.I quantum
|
||||
Will produce a quantum that should meet maximal allignment
|
||||
will produce a quantum that should meet maximal alignment
|
||||
on most platforms.
|
||||
If the
|
||||
If
|
||||
.B POOL_QALIGN
|
||||
.I flag
|
||||
is set allocations will be aligned to addresses that are a
|
||||
is set in the
|
||||
.IR flags ,
|
||||
allocations will be aligned to addresses that are a
|
||||
multiple of
|
||||
.IR quantum .
|
||||
If the
|
||||
If
|
||||
.B POOL_CLEAR
|
||||
.I flag
|
||||
is set all allocations from the pool will be zero filled.
|
||||
is set in the
|
||||
.IR flags ,
|
||||
all allocations from the pool will be initialized to zeros.
|
||||
You may specify a
|
||||
.B NULL
|
||||
for the
|
||||
.I bomb
|
||||
function pointer if you don't wish to use it. (See the
|
||||
.B pool_alloc()
|
||||
function for how it is used.)
|
||||
.P
|
||||
.B pool_destroy()
|
||||
destroys an allocation pool and frees all memory allocated
|
||||
in that pool.
|
||||
destroys an allocation
|
||||
.I pool
|
||||
and frees all its associated memory.
|
||||
.P
|
||||
.B pool_alloc()
|
||||
allocates
|
||||
@@ -115,57 +128,97 @@ bytes from the specified
|
||||
If
|
||||
.I size
|
||||
is
|
||||
.B 0
|
||||
.BR 0 ,
|
||||
.I quantum
|
||||
bytes will be freed.
|
||||
If the requested memory cannot be allocated
|
||||
.B pool_alloc()
|
||||
will call
|
||||
bytes will be allocated.
|
||||
If the pool has been created with
|
||||
.BR POOL_QALIGN ,
|
||||
every chunk of memory that is returned will be suitably aligned.
|
||||
You can use this with the default
|
||||
.I quantum
|
||||
size to ensure that all memory can store a variable of any type.
|
||||
If the requested memory cannot be allocated, the
|
||||
.I bomb()
|
||||
function, if defined, with
|
||||
function will be called with
|
||||
.I msg
|
||||
as it's sole argument and
|
||||
as its sole argument (if the function was defined at the time
|
||||
the pool was created), and then a
|
||||
.B NULL
|
||||
will be returned.
|
||||
address is returned (assuming that the bomb function didn't exit).
|
||||
.P
|
||||
.B pool_free()
|
||||
frees
|
||||
.I size
|
||||
bytes pointed to by
|
||||
bytes pointed to by an
|
||||
.I addr
|
||||
previously allocated in the specified
|
||||
that was previously allocated in the specified
|
||||
.IR pool .
|
||||
The memory freed within an extent will not be reusable until
|
||||
all of the memory in that extent has been freed but
|
||||
depending on the order in which the
|
||||
allocations are freed some extents may be released for reuse
|
||||
while others are still in use.
|
||||
If
|
||||
.I size
|
||||
is
|
||||
.B 0
|
||||
.BR 0 ,
|
||||
.I quantum
|
||||
bytes will be freed.
|
||||
The memory freed within an extent will not be reusable until
|
||||
all of the memory in that extent has been freed with one
|
||||
exception: the most recent pool allocation may be freed back
|
||||
into the pool prior to making any further allocations.
|
||||
If enough free calls are made to indicate that an extent has no
|
||||
remaining allocated objects (as computed by the total freed size for
|
||||
an extent), its memory will be completely freed back to the system.
|
||||
If
|
||||
.I addr
|
||||
is
|
||||
.B 0
|
||||
no memory will be freed but subsequent allocations will come
|
||||
.BR 0 ,
|
||||
no memory will be freed, but subsequent allocations will come
|
||||
from a new extent.
|
||||
.P
|
||||
.B pool_talloc()
|
||||
is a macro that take a
|
||||
.I type
|
||||
.B pool_free_old()
|
||||
takes a boundary
|
||||
.I addr
|
||||
value that was returned by
|
||||
.B pool_boundary()
|
||||
and frees up any extents in the
|
||||
.I pool
|
||||
that have data allocated from that point backward in time.
|
||||
NOTE: you must NOT mix calls to both
|
||||
.B pool_free
|
||||
and
|
||||
.B pool_free_old
|
||||
on the same pool!
|
||||
.P
|
||||
.B pool_boundary()
|
||||
asks for a boundary value that can be sent to
|
||||
.B pool_free_old()
|
||||
at a later time to free up all memory allocated prior to a particular
|
||||
moment in time.
|
||||
If the extent that holds the boundary point has allocations from after the
|
||||
boundary point, it will not be freed until a future
|
||||
.B pool_free_old()
|
||||
call encompasses the entirety of the extent's data.
|
||||
If
|
||||
.I len
|
||||
is non-zero, the call will also check if the active extent has at least
|
||||
that much free memory available in it, and if not, it will mark the
|
||||
extent as inactive, forcing a new extent to be used for future allocations.
|
||||
(You can specify -1 for
|
||||
.I len
|
||||
if you want to force a new extent to start.)
|
||||
.P
|
||||
.B pool_talloc()
|
||||
is a macro that takes a
|
||||
.I type
|
||||
and a
|
||||
.I count
|
||||
instead of
|
||||
.I size
|
||||
and will cast the return value to the correct type.
|
||||
instead of a
|
||||
.IR size .
|
||||
It casts the return value to the correct pointer type.
|
||||
.P
|
||||
.B pool_tfree
|
||||
is a macro to free memory previously allocated in the
|
||||
specified
|
||||
.IR pool .
|
||||
is a macro that calls
|
||||
.B pool_free
|
||||
on memory that was allocated by
|
||||
.BR pool_talloc() .
|
||||
.SH RETURN VALUE
|
||||
.B pool_create()
|
||||
returns a pointer to
|
||||
@@ -176,9 +229,6 @@ and
|
||||
.B pool_talloc()
|
||||
return pointers to the allocated memory,
|
||||
or NULL if the request fails.
|
||||
For each extent so long as no allocations are smaller than varaible
|
||||
allignment requirements this pointer will be suitably
|
||||
alligned for any kind of variable.
|
||||
The return type of
|
||||
.B pool_alloc()
|
||||
will normally require casting to the desired type but
|
||||
@@ -186,7 +236,12 @@ will normally require casting to the desired type but
|
||||
will returns a pointer of the requested
|
||||
.IR type .
|
||||
.P
|
||||
.B pool_boundary()
|
||||
returns a pointer that should only be used in a call to
|
||||
.BR pool_free_old() .
|
||||
.P
|
||||
.BR pool_free() ,
|
||||
.BR pool_free_old() ,
|
||||
.B pool_tfree()
|
||||
and
|
||||
.B pool_destroy()
|
||||
|
||||
280
lib/pool_alloc.c
280
lib/pool_alloc.c
@@ -6,21 +6,18 @@ struct alloc_pool
|
||||
{
|
||||
size_t size; /* extent size */
|
||||
size_t quantum; /* allocation quantum */
|
||||
struct pool_extent *live; /* current extent for
|
||||
* allocations */
|
||||
struct pool_extent *free; /* unfreed extent list */
|
||||
void (*bomb)();
|
||||
/* function to call if
|
||||
struct pool_extent *extents; /* top extent is "live" */
|
||||
void (*bomb)(); /* function to call if
|
||||
* malloc fails */
|
||||
int flags;
|
||||
|
||||
/* statistical data */
|
||||
unsigned long e_created; /* extents created */
|
||||
unsigned long e_freed; /* extents detroyed */
|
||||
uint64 n_allocated; /* calls to alloc */
|
||||
uint64 n_freed; /* calls to free */
|
||||
uint64 b_allocated; /* cum. bytes allocated */
|
||||
uint64 b_freed; /* cum. bytes freed */
|
||||
int64 n_allocated; /* calls to alloc */
|
||||
int64 n_freed; /* calls to free */
|
||||
int64 b_allocated; /* cum. bytes allocated */
|
||||
int64 b_freed; /* cum. bytes freed */
|
||||
};
|
||||
|
||||
struct pool_extent
|
||||
@@ -33,8 +30,8 @@ struct pool_extent
|
||||
};
|
||||
|
||||
struct align_test {
|
||||
void *foo;
|
||||
uint64 bar;
|
||||
void *foo;
|
||||
int64 bar;
|
||||
};
|
||||
|
||||
#define MINALIGN offsetof(struct align_test, bar)
|
||||
@@ -44,20 +41,18 @@ struct align_test {
|
||||
#define PTR_ADD(b,o) ( (void*) ((char*)(b) + (o)) )
|
||||
|
||||
alloc_pool_t
|
||||
pool_create(size_t size, size_t quantum,
|
||||
void (*bomb)(char *), int flags)
|
||||
pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags)
|
||||
{
|
||||
struct alloc_pool *pool;
|
||||
|
||||
if (!(pool = (struct alloc_pool*) malloc(sizeof (struct alloc_pool))))
|
||||
if (!(pool = new(struct alloc_pool)))
|
||||
return pool;
|
||||
memset(pool, 0, sizeof (struct alloc_pool));
|
||||
|
||||
pool->size = size /* round extent size to min alignment reqs */
|
||||
? (size + MINALIGN - 1) & ~(MINALIGN - 1)
|
||||
: POOL_DEF_EXTENT;
|
||||
if (pool->flags & POOL_INTERN)
|
||||
{
|
||||
if (flags & POOL_INTERN) {
|
||||
pool->size -= sizeof (struct pool_extent);
|
||||
flags |= POOL_APPEND;
|
||||
}
|
||||
@@ -77,15 +72,7 @@ pool_destroy(alloc_pool_t p)
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
if (pool->live)
|
||||
{
|
||||
cur = pool->live;
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
}
|
||||
for (cur = pool->free; cur; cur = next)
|
||||
{
|
||||
for (cur = pool->extents; cur; cur = next) {
|
||||
next = cur->next;
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
@@ -95,7 +82,7 @@ pool_destroy(alloc_pool_t p)
|
||||
}
|
||||
|
||||
void *
|
||||
pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
pool_alloc(alloc_pool_t p, size_t len, const char *bomb_msg)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
if (!pool)
|
||||
@@ -107,21 +94,15 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
len += pool->quantum - len % pool->quantum;
|
||||
|
||||
if (len > pool->size)
|
||||
goto bomb;
|
||||
goto bomb_out;
|
||||
|
||||
if (!pool->live || len > pool->live->free)
|
||||
{
|
||||
if (!pool->extents || len > pool->extents->free) {
|
||||
void *start;
|
||||
size_t free;
|
||||
size_t bound;
|
||||
size_t sqew;
|
||||
size_t skew;
|
||||
size_t asize;
|
||||
|
||||
if (pool->live)
|
||||
{
|
||||
pool->live->next = pool->free;
|
||||
pool->free = pool->live;
|
||||
}
|
||||
struct pool_extent *ext;
|
||||
|
||||
free = pool->size;
|
||||
bound = 0;
|
||||
@@ -130,30 +111,26 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
if (pool->flags & POOL_APPEND)
|
||||
asize += sizeof (struct pool_extent);
|
||||
|
||||
if (!(start = (void *) malloc(asize)))
|
||||
goto bomb;
|
||||
if (!(start = new_array(char, asize)))
|
||||
goto bomb_out;
|
||||
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(start, 0, pool->size);
|
||||
memset(start, 0, free);
|
||||
|
||||
if (pool->flags & POOL_APPEND)
|
||||
{
|
||||
pool->live = PTR_ADD(start, free);
|
||||
}
|
||||
else if (!(pool->live = (struct pool_extent *) malloc(sizeof (struct pool_extent))))
|
||||
{
|
||||
goto bomb;
|
||||
}
|
||||
ext = PTR_ADD(start, free);
|
||||
else if (!(ext = new(struct pool_extent)))
|
||||
goto bomb_out;
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum))
|
||||
{
|
||||
bound += sqew;
|
||||
free -= sqew;
|
||||
&& (skew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
|
||||
bound += skew;
|
||||
free -= skew;
|
||||
}
|
||||
pool->live->start = start;
|
||||
pool->live->free = free;
|
||||
pool->live->bound = bound;
|
||||
pool->live->next = NULL;
|
||||
ext->start = start;
|
||||
ext->free = free;
|
||||
ext->bound = bound;
|
||||
ext->next = pool->extents;
|
||||
pool->extents = ext;
|
||||
|
||||
pool->e_created++;
|
||||
}
|
||||
@@ -161,22 +138,24 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
pool->n_allocated++;
|
||||
pool->b_allocated += len;
|
||||
|
||||
pool->live->free -= len;
|
||||
pool->extents->free -= len;
|
||||
|
||||
return PTR_ADD(pool->live->start, pool->live->free);
|
||||
return PTR_ADD(pool->extents->start, pool->extents->free);
|
||||
|
||||
bomb:
|
||||
bomb_out:
|
||||
if (pool->bomb)
|
||||
(*pool->bomb)(bomb);
|
||||
(*pool->bomb)(bomb_msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function allows you to declare memory in the pool that you are done
|
||||
* using. If you free all the memory in a pool's extent, that extent will
|
||||
* be freed. */
|
||||
void
|
||||
pool_free(alloc_pool_t p, size_t len, void *addr)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
struct pool_extent *cur;
|
||||
struct pool_extent *prev;
|
||||
struct alloc_pool *pool = (struct alloc_pool *)p;
|
||||
struct pool_extent *cur, *prev;
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
@@ -186,46 +165,10 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
|
||||
else if (pool->quantum > 1 && len % pool->quantum)
|
||||
len += pool->quantum - len % pool->quantum;
|
||||
|
||||
if (!addr && pool->live)
|
||||
{
|
||||
pool->live->next = pool->free;
|
||||
pool->free = pool->live;
|
||||
pool->live = NULL;
|
||||
return;
|
||||
}
|
||||
pool->n_freed++;
|
||||
pool->b_freed += len;
|
||||
|
||||
cur = pool->live;
|
||||
if (cur
|
||||
&& addr >= cur->start
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
{
|
||||
if (addr == PTR_ADD(cur->start, cur->free))
|
||||
{
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(addr, 0, len);
|
||||
pool->b_freed += len;
|
||||
} else {
|
||||
cur->bound += len;
|
||||
}
|
||||
if (cur->free + cur->bound >= pool->size)
|
||||
{
|
||||
size_t sqew;
|
||||
|
||||
cur->free = pool->size;
|
||||
cur->bound = 0;
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum))
|
||||
{
|
||||
cur->bound += sqew;
|
||||
cur->free -= sqew;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next)
|
||||
{
|
||||
for (prev = NULL, cur = pool->extents; cur; prev = cur, cur = cur->next) {
|
||||
if (addr >= cur->start
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
break;
|
||||
@@ -233,32 +176,130 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
|
||||
if (!cur)
|
||||
return;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
prev->next = cur->next;
|
||||
cur->next = pool->free;
|
||||
pool->free = cur;
|
||||
if (!prev) {
|
||||
/* The "live" extent is kept ready for more allocations. */
|
||||
if (cur->free + cur->bound + len >= pool->size) {
|
||||
size_t skew;
|
||||
|
||||
if (pool->flags & POOL_CLEAR) {
|
||||
memset(PTR_ADD(cur->start, cur->free), 0,
|
||||
pool->size - cur->free);
|
||||
}
|
||||
cur->free = pool->size;
|
||||
cur->bound = 0;
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (skew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
|
||||
cur->bound += skew;
|
||||
cur->free -= skew;
|
||||
}
|
||||
} else if (addr == PTR_ADD(cur->start, cur->free)) {
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(addr, 0, len);
|
||||
cur->free += len;
|
||||
} else
|
||||
cur->bound += len;
|
||||
} else {
|
||||
cur->bound += len;
|
||||
|
||||
if (cur->free + cur->bound >= pool->size) {
|
||||
prev->next = cur->next;
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
pool->e_freed++;
|
||||
} else if (prev != pool->extents) {
|
||||
/* Move the extent to be the first non-live extent. */
|
||||
prev->next = cur->next;
|
||||
cur->next = pool->extents->next;
|
||||
pool->extents->next = cur;
|
||||
}
|
||||
}
|
||||
cur->bound += len;
|
||||
}
|
||||
|
||||
if (cur->free + cur->bound >= pool->size)
|
||||
{
|
||||
pool->free = cur->next;
|
||||
/* This allows you to declare that the given address marks the edge of some
|
||||
* pool memory that is no longer needed. Any extents that hold only data
|
||||
* older than the boundary address are freed. NOTE: You MUST NOT USE BOTH
|
||||
* pool_free() and pool_free_old() on the same pool!! */
|
||||
void
|
||||
pool_free_old(alloc_pool_t p, void *addr)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *)p;
|
||||
struct pool_extent *cur, *prev, *next;
|
||||
|
||||
if (!pool || !addr)
|
||||
return;
|
||||
|
||||
for (prev = NULL, cur = pool->extents; cur; prev = cur, cur = cur->next) {
|
||||
if (addr >= cur->start
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
break;
|
||||
}
|
||||
if (!cur)
|
||||
return;
|
||||
|
||||
if (addr == PTR_ADD(cur->start, cur->free)) {
|
||||
if (prev) {
|
||||
prev->next = NULL;
|
||||
next = cur;
|
||||
} else {
|
||||
size_t skew;
|
||||
|
||||
/* The most recent live extent can just be reset. */
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(addr, 0, pool->size - cur->free);
|
||||
cur->free = pool->size;
|
||||
cur->bound = 0;
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (skew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
|
||||
cur->bound += skew;
|
||||
cur->free -= skew;
|
||||
}
|
||||
next = cur->next;
|
||||
cur->next = NULL;
|
||||
}
|
||||
} else {
|
||||
next = cur->next;
|
||||
cur->next = NULL;
|
||||
}
|
||||
|
||||
while ((cur = next) != NULL) {
|
||||
next = cur->next;
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
pool->e_freed++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the current extent doesn't have "len" free space in it, mark it as full
|
||||
* so that the next alloc will start a new extent. If len is (size_t)-1, this
|
||||
* bump will always occur. The function returns a boundary address that can
|
||||
* be used with pool_free_old(), or a NULL if no memory is allocated. */
|
||||
void *
|
||||
pool_boundary(alloc_pool_t p, size_t len)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *)p;
|
||||
struct pool_extent *cur;
|
||||
|
||||
if (!pool || !pool->extents)
|
||||
return NULL;
|
||||
|
||||
cur = pool->extents;
|
||||
|
||||
if (cur->free < len) {
|
||||
cur->bound += cur->free;
|
||||
cur->free = 0;
|
||||
}
|
||||
|
||||
return PTR_ADD(cur->start, cur->free);
|
||||
}
|
||||
|
||||
#define FDPRINT(label, value) \
|
||||
snprintf(buf, BUFSIZ, label, value), \
|
||||
write(fd, buf, strlen(buf));
|
||||
snprintf(buf, sizeof buf, label, value), \
|
||||
write(fd, buf, strlen(buf))
|
||||
|
||||
#define FDEXTSTAT(ext) \
|
||||
snprintf(buf, BUFSIZ, " %12ld %5ld\n", \
|
||||
snprintf(buf, sizeof buf, " %12ld %5ld\n", \
|
||||
(long) ext->free, \
|
||||
(long) ext->bound), \
|
||||
write(fd, buf, strlen(buf))
|
||||
@@ -279,26 +320,17 @@ pool_stats(alloc_pool_t p, int fd, int summarize)
|
||||
FDPRINT(" Extents freed: %12ld\n", pool->e_freed);
|
||||
FDPRINT(" Alloc count: %12.0f\n", (double) pool->n_allocated);
|
||||
FDPRINT(" Free Count: %12.0f\n", (double) pool->n_freed);
|
||||
FDPRINT(" Alloc bytes: %12.0f\n", (double) pool->b_allocated);
|
||||
FDPRINT(" Free bytes: %12.0f\n", (double) pool->b_freed);
|
||||
FDPRINT(" Bytes allocated: %12.0f\n", (double) pool->b_allocated);
|
||||
FDPRINT(" Bytes freed: %12.0f\n", (double) pool->b_freed);
|
||||
|
||||
if (summarize)
|
||||
return;
|
||||
|
||||
if (!pool->live && !pool->free)
|
||||
if (!pool->extents)
|
||||
return;
|
||||
|
||||
write(fd, "\n", 1);
|
||||
|
||||
if (pool->live)
|
||||
{
|
||||
FDEXTSTAT(pool->live);
|
||||
}
|
||||
strcpy(buf, " FREE BOUND\n");
|
||||
write(fd, buf, strlen(buf));
|
||||
|
||||
for (cur = pool->free; cur; cur = cur->next)
|
||||
{
|
||||
for (cur = pool->extents; cur; cur = cur->next)
|
||||
FDEXTSTAT(cur);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
|
||||
typedef void *alloc_pool_t;
|
||||
|
||||
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(char *), int flags);
|
||||
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags);
|
||||
void pool_destroy(alloc_pool_t pool);
|
||||
void *pool_alloc(alloc_pool_t pool, size_t size, char *bomb);
|
||||
void *pool_alloc(alloc_pool_t pool, size_t size, const char *bomb_msg);
|
||||
void pool_free(alloc_pool_t pool, size_t size, void *addr);
|
||||
void pool_free_old(alloc_pool_t pool, void *addr);
|
||||
void *pool_boundary(alloc_pool_t pool, size_t size);
|
||||
|
||||
#define pool_talloc(pool, type, count, bomb) \
|
||||
((type *)pool_alloc(pool, sizeof(type) * count, bomb))
|
||||
#define pool_talloc(pool, type, count, bomb_msg) \
|
||||
((type *)pool_alloc(pool, sizeof(type) * count, bomb_msg))
|
||||
|
||||
#define pool_tfree(pool, type, count, addr) \
|
||||
(pool_free(pool, sizeof(type) * count, addr))
|
||||
|
||||
|
||||
209
lib/snprintf.c
209
lib/snprintf.c
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* NOTE: If you change this file, please merge it into rsync, samba, etc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright Patrick Powell 1995
|
||||
* This code is based on code written by Patrick Powell (papowell@astart.com)
|
||||
@@ -53,14 +57,57 @@
|
||||
* got rid of fcvt code (twas buggy and made testing harder)
|
||||
* added C99 semantics
|
||||
*
|
||||
* Paul Green (paulg@samba.org) April 9, 2003
|
||||
* fixed handling of %f when converting fractions with leading zeros.
|
||||
* (e.g., 0.025).
|
||||
* date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
|
||||
* actually print args for %g and %e
|
||||
*
|
||||
* date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
|
||||
* Since includes.h isn't included here, VA_COPY has to be defined here. I don't
|
||||
* see any include file that is guaranteed to be here, so I'm defining it
|
||||
* locally. Fixes AIX and Solaris builds.
|
||||
*
|
||||
* date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
|
||||
* put the ifdef for HAVE_VA_COPY in one place rather than in lots of
|
||||
* functions
|
||||
*
|
||||
* date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
|
||||
* Fix usage of va_list passed as an arg. Use __va_copy before using it
|
||||
* when it exists.
|
||||
*
|
||||
* date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
|
||||
* Fix incorrect zpadlen handling in fmtfp.
|
||||
* Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
|
||||
* few mods to make it easier to compile the tests.
|
||||
* addedd the "Ollie" test to the floating point ones.
|
||||
*
|
||||
* Martin Pool (mbp@samba.org) April 2003
|
||||
* Remove NO_CONFIG_H so that the test case can be built within a source
|
||||
* tree with less trouble.
|
||||
* Remove unnecessary SAFE_FREE() definition.
|
||||
*
|
||||
* Martin Pool (mbp@samba.org) May 2003
|
||||
* Put in a prototype for dummy_snprintf() to quiet compiler warnings.
|
||||
*
|
||||
* Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
|
||||
* if the C library has some snprintf functions already.
|
||||
**************************************************************/
|
||||
|
||||
#ifndef NO_CONFIG_H /* for some tests */
|
||||
#ifndef NO_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#else
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifdef TEST_SNPRINTF /* need math library headers for testing */
|
||||
|
||||
/* In test mode, we pretend that this system doesn't have any snprintf
|
||||
* functions, regardless of what config.h says. */
|
||||
# undef HAVE_SNPRINTF
|
||||
# undef HAVE_VSNPRINTF
|
||||
# undef HAVE_C99_VSNPRINTF
|
||||
# undef HAVE_ASPRINTF
|
||||
# undef HAVE_VASPRINTF
|
||||
# include <math.h>
|
||||
#endif /* TEST_SNPRINTF */
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
@@ -82,8 +129,9 @@
|
||||
/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
|
||||
#include <stdio.h>
|
||||
/* make the compiler happy with an empty file */
|
||||
void dummy_snprintf(void);
|
||||
void dummy_snprintf(void) {}
|
||||
#else
|
||||
#endif /* HAVE_SNPRINTF, etc */
|
||||
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
#define LDOUBLE long double
|
||||
@@ -91,21 +139,22 @@
|
||||
#define LDOUBLE double
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#if SIZEOF_LONG_LONG
|
||||
#define LLONG long long
|
||||
#else
|
||||
#define LLONG long
|
||||
#endif
|
||||
|
||||
static size_t dopr(char *buffer, size_t maxlen, const char *format,
|
||||
va_list args);
|
||||
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
|
||||
char *value, int flags, int min, int max);
|
||||
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
|
||||
long value, int base, int min, int max, int flags);
|
||||
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
|
||||
LDOUBLE fvalue, int min, int max, int flags);
|
||||
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
|
||||
#ifndef VA_COPY
|
||||
#if defined HAVE_VA_COPY || defined va_copy
|
||||
#define VA_COPY(dest, src) va_copy(dest, src)
|
||||
#else
|
||||
#ifdef HAVE___VA_COPY
|
||||
#define VA_COPY(dest, src) __va_copy(dest, src)
|
||||
#else
|
||||
#define VA_COPY(dest, src) (dest) = (src)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dopr(): poor man's version of doprintf
|
||||
@@ -141,7 +190,20 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
|
||||
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
|
||||
#endif
|
||||
|
||||
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
/* yes this really must be a ||. Don't muck with this (tridge) */
|
||||
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
|
||||
static size_t dopr(char *buffer, size_t maxlen, const char *format,
|
||||
va_list args_in);
|
||||
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
|
||||
char *value, int flags, int min, int max);
|
||||
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
|
||||
long value, int base, int min, int max, int flags);
|
||||
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
|
||||
LDOUBLE fvalue, int min, int max, int flags);
|
||||
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
|
||||
|
||||
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
|
||||
{
|
||||
char ch;
|
||||
LLONG value;
|
||||
@@ -153,6 +215,9 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
|
||||
int flags;
|
||||
int cflags;
|
||||
size_t currlen;
|
||||
va_list args;
|
||||
|
||||
VA_COPY(args, args_in);
|
||||
|
||||
state = DP_S_DEFAULT;
|
||||
currlen = flags = cflags = min = 0;
|
||||
@@ -322,6 +387,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
|
||||
fvalue = va_arg (args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
|
||||
break;
|
||||
case 'G':
|
||||
flags |= DP_F_UP;
|
||||
@@ -330,12 +396,14 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
|
||||
fvalue = va_arg (args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
|
||||
break;
|
||||
case 'c':
|
||||
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
|
||||
break;
|
||||
case 's':
|
||||
strvalue = va_arg (args, char *);
|
||||
if (!strvalue) strvalue = "(NULL)";
|
||||
if (max == -1) {
|
||||
max = strlen(strvalue);
|
||||
}
|
||||
@@ -564,28 +632,26 @@ static double my_modf(double x0, double *iptr)
|
||||
|
||||
for (i=0;i<100;i++) {
|
||||
l = (long)x;
|
||||
if (l <= (x+1) && l >= (x-1)) break;
|
||||
if (l <= (x+1) && l >= (x-1)) {
|
||||
if (i != 0) {
|
||||
double i2;
|
||||
double ret;
|
||||
|
||||
ret = my_modf(x0-l*f, &i2);
|
||||
(*iptr) = l*f + i2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
(*iptr) = l;
|
||||
return x - (*iptr);
|
||||
}
|
||||
x *= 0.1;
|
||||
f *= 10.0;
|
||||
}
|
||||
|
||||
if (i == 100) {
|
||||
/* yikes! the number is beyond what we can handle. What do we do? */
|
||||
(*iptr) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
double i2;
|
||||
double ret;
|
||||
|
||||
ret = my_modf(x0-l*f, &i2);
|
||||
(*iptr) = l*f + i2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
(*iptr) = l;
|
||||
return x - (*iptr);
|
||||
/* yikes! the number is beyond what we can handle. What do we do? */
|
||||
(*iptr) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -601,7 +667,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
int padlen = 0; /* amount to pad */
|
||||
int zpadlen = 0;
|
||||
int caps = 0;
|
||||
int index;
|
||||
int idx;
|
||||
double intpart;
|
||||
double fracpart;
|
||||
double temp;
|
||||
@@ -658,14 +724,13 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
|
||||
/* Convert integer part */
|
||||
do {
|
||||
temp = intpart;
|
||||
my_modf(intpart*0.1, &intpart);
|
||||
temp = temp*0.1;
|
||||
index = (int) ((temp -intpart +0.05)* 10.0);
|
||||
/* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
|
||||
/* printf ("%llf, %f, %x\n", temp, intpart, index); */
|
||||
temp = intpart*0.1;
|
||||
my_modf(temp, &intpart);
|
||||
idx = (int) ((temp -intpart +0.05)* 10.0);
|
||||
/* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
|
||||
/* printf ("%llf, %f, %x\n", temp, intpart, idx); */
|
||||
iconvert[iplace++] =
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[index];
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
|
||||
} while (intpart && (iplace < 311));
|
||||
if (iplace == 311) iplace--;
|
||||
iconvert[iplace] = 0;
|
||||
@@ -674,14 +739,13 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
if (fracpart)
|
||||
{
|
||||
do {
|
||||
temp = fracpart;
|
||||
my_modf(fracpart*0.1, &fracpart);
|
||||
temp = temp*0.1;
|
||||
index = (int) ((temp -fracpart +0.05)* 10.0);
|
||||
/* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
|
||||
/* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
|
||||
temp = fracpart*0.1;
|
||||
my_modf(temp, &fracpart);
|
||||
idx = (int) ((temp -fracpart +0.05)* 10.0);
|
||||
/* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
|
||||
/* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
|
||||
fconvert[fplace++] =
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[index];
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
|
||||
} while(fracpart && (fplace < 311));
|
||||
if (fplace == 311) fplace--;
|
||||
}
|
||||
@@ -729,14 +793,14 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
dopr_outch (buffer, currlen, maxlen, '.');
|
||||
|
||||
while (zpadlen > 0) {
|
||||
dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
}
|
||||
|
||||
while (fplace > 0)
|
||||
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
|
||||
}
|
||||
|
||||
|
||||
while (padlen < 0) {
|
||||
dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
++padlen;
|
||||
@@ -751,17 +815,21 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
(*currlen)++;
|
||||
}
|
||||
|
||||
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
#define vsnprintf rsync_vsnprintf
|
||||
int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
|
||||
int rsync_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
|
||||
{
|
||||
return dopr(str, count, fmt, args);
|
||||
}
|
||||
#define vsnprintf rsync_vsnprintf
|
||||
#endif
|
||||
|
||||
/* yes this really must be a ||. Don't muck with this (tridge)
|
||||
*
|
||||
* The logic for these two is that we need our own definition if the
|
||||
* OS *either* has no definition of *sprintf, or if it does have one
|
||||
* that doesn't work properly according to the autoconf test.
|
||||
*/
|
||||
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
#define snprintf rsync_snprintf
|
||||
int snprintf(char *str,size_t count,const char *fmt,...)
|
||||
int rsync_snprintf(char *str,size_t count,const char *fmt,...)
|
||||
{
|
||||
size_t ret;
|
||||
va_list ap;
|
||||
@@ -771,6 +839,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
#define snprintf rsync_snprintf
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -779,13 +848,19 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
int vasprintf(char **ptr, const char *format, va_list ap)
|
||||
{
|
||||
int ret;
|
||||
va_list ap2;
|
||||
|
||||
VA_COPY(ap2, ap);
|
||||
|
||||
ret = vsnprintf(NULL, 0, format, ap);
|
||||
ret = vsnprintf(NULL, 0, format, ap2);
|
||||
if (ret <= 0) return ret;
|
||||
|
||||
(*ptr) = (char *)malloc(ret+1);
|
||||
if (!*ptr) return -1;
|
||||
ret = vsnprintf(*ptr, ret+1, format, ap);
|
||||
|
||||
VA_COPY(ap2, ap);
|
||||
|
||||
ret = vsnprintf(*ptr, ret+1, format, ap2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -798,6 +873,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
*ptr = NULL;
|
||||
va_start(ap, format);
|
||||
ret = vasprintf(ptr, format, ap);
|
||||
va_end(ap);
|
||||
@@ -832,8 +908,9 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
"-16.16f",
|
||||
NULL
|
||||
};
|
||||
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
|
||||
0.9996, 1.996, 4.136, 0};
|
||||
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,
|
||||
0.9996, 1.996, 4.136, 5.030201, 0.00205,
|
||||
/* END LIST */ 0};
|
||||
char *int_fmt[] = {
|
||||
"%-1.5d",
|
||||
"%1.5d",
|
||||
@@ -928,8 +1005,10 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
{
|
||||
double v0 = 0.12345678901234567890123456789012345678901;
|
||||
for (x=0; x<100; x++) {
|
||||
snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x));
|
||||
sprintf(buf2, "%1.1f", v0*pow(10, x));
|
||||
double p = pow(10, x);
|
||||
double r = v0*p;
|
||||
snprintf(buf1, sizeof(buf1), "%1.1f", r);
|
||||
sprintf(buf2, "%1.1f", r);
|
||||
if (strcmp(buf1, buf2)) {
|
||||
printf("we seem to support %d digits\n", x-1);
|
||||
break;
|
||||
@@ -939,4 +1018,4 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* SNPRINTF_TEST */
|
||||
#endif /* TEST_SNPRINTF */
|
||||
|
||||
2771
lib/sysacls.c
Normal file
2771
lib/sysacls.c
Normal file
File diff suppressed because it is too large
Load Diff
304
lib/sysacls.h
Normal file
304
lib/sysacls.h
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Unix SMB/Netbios implementation.
|
||||
* Version 2.2.x
|
||||
* Portable SMB ACL interface
|
||||
* Copyright (C) Jeremy Allison 2000
|
||||
*
|
||||
* 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
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
|
||||
#ifdef HAVE_SYS_ACL_H
|
||||
#include <sys/acl.h>
|
||||
#endif
|
||||
#ifdef HAVE_ACL_LIBACL_H
|
||||
#include <acl/libacl.h>
|
||||
#endif
|
||||
|
||||
#define SMB_MALLOC(cnt) new_array(char, cnt)
|
||||
#define SMB_MALLOC_P(obj) new_array(obj, 1)
|
||||
#define SMB_MALLOC_ARRAY(obj, cnt) new_array(obj, cnt)
|
||||
#define SMB_REALLOC(mem, cnt) realloc_array(mem, char, cnt)
|
||||
#define slprintf snprintf
|
||||
|
||||
#if defined HAVE_POSIX_ACLS /*-----------------------------------------------*/
|
||||
|
||||
/* This is an identity mapping (just remove the SMB_). */
|
||||
|
||||
#define SMB_ACL_TAG_T acl_tag_t
|
||||
#define SMB_ACL_TYPE_T acl_type_t
|
||||
|
||||
/* Types of ACLs. */
|
||||
#define SMB_ACL_USER ACL_USER
|
||||
#define SMB_ACL_USER_OBJ ACL_USER_OBJ
|
||||
#define SMB_ACL_GROUP ACL_GROUP
|
||||
#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
|
||||
#define SMB_ACL_OTHER ACL_OTHER
|
||||
#define SMB_ACL_MASK ACL_MASK
|
||||
|
||||
#define SMB_ACL_T acl_t
|
||||
|
||||
#define SMB_ACL_ENTRY_T acl_entry_t
|
||||
|
||||
#define SMB_ACL_FIRST_ENTRY ACL_FIRST_ENTRY
|
||||
#define SMB_ACL_NEXT_ENTRY ACL_NEXT_ENTRY
|
||||
|
||||
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
|
||||
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
|
||||
|
||||
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
|
||||
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
|
||||
|
||||
#define SMB_ACL_NEED_SORT
|
||||
|
||||
#elif defined HAVE_TRU64_ACLS /*---------------------------------------------*/
|
||||
|
||||
/* This is for DEC/Compaq Tru64 UNIX */
|
||||
|
||||
#define SMB_ACL_TAG_T acl_tag_t
|
||||
#define SMB_ACL_TYPE_T acl_type_t
|
||||
|
||||
/* Types of ACLs. */
|
||||
#define SMB_ACL_USER ACL_USER
|
||||
#define SMB_ACL_USER_OBJ ACL_USER_OBJ
|
||||
#define SMB_ACL_GROUP ACL_GROUP
|
||||
#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
|
||||
#define SMB_ACL_OTHER ACL_OTHER
|
||||
#define SMB_ACL_MASK ACL_MASK
|
||||
|
||||
#define SMB_ACL_T acl_t
|
||||
|
||||
#define SMB_ACL_ENTRY_T acl_entry_t
|
||||
|
||||
#define SMB_ACL_FIRST_ENTRY 0
|
||||
#define SMB_ACL_NEXT_ENTRY 1
|
||||
|
||||
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
|
||||
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
|
||||
|
||||
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
|
||||
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
|
||||
|
||||
#define SMB_ACL_NEED_SORT
|
||||
|
||||
#elif defined HAVE_UNIXWARE_ACLS || defined HAVE_SOLARIS_ACLS /*-------------*/
|
||||
|
||||
/* Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
|
||||
* Modified by Toomas Soome <tsoome@ut.ee> for Solaris. */
|
||||
|
||||
/* SVR4.2 ES/MP ACLs */
|
||||
typedef int SMB_ACL_TAG_T;
|
||||
typedef int SMB_ACL_TYPE_T;
|
||||
|
||||
/* Types of ACLs. */
|
||||
#define SMB_ACL_USER USER
|
||||
#define SMB_ACL_USER_OBJ USER_OBJ
|
||||
#define SMB_ACL_GROUP GROUP
|
||||
#define SMB_ACL_GROUP_OBJ GROUP_OBJ
|
||||
#define SMB_ACL_OTHER OTHER_OBJ
|
||||
#define SMB_ACL_MASK CLASS_OBJ
|
||||
|
||||
typedef struct SMB_ACL_T {
|
||||
int size;
|
||||
int count;
|
||||
int next;
|
||||
struct acl acl[1];
|
||||
} *SMB_ACL_T;
|
||||
|
||||
typedef struct acl *SMB_ACL_ENTRY_T;
|
||||
|
||||
#define SMB_ACL_FIRST_ENTRY 0
|
||||
#define SMB_ACL_NEXT_ENTRY 1
|
||||
|
||||
#define SMB_ACL_TYPE_ACCESS 0
|
||||
#define SMB_ACL_TYPE_DEFAULT 1
|
||||
|
||||
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
|
||||
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
|
||||
|
||||
#define SMB_ACL_NEED_SORT
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#define SMB_ACL_LOSES_SPECIAL_MODE_BITS
|
||||
#endif
|
||||
|
||||
#elif defined HAVE_HPUX_ACLS /*----------------------------------------------*/
|
||||
|
||||
/* Based on the Solaris & UnixWare code. */
|
||||
|
||||
#undef GROUP
|
||||
#include <sys/aclv.h>
|
||||
|
||||
/* SVR4.2 ES/MP ACLs */
|
||||
typedef int SMB_ACL_TAG_T;
|
||||
typedef int SMB_ACL_TYPE_T;
|
||||
|
||||
/* Types of ACLs. */
|
||||
#define SMB_ACL_USER USER
|
||||
#define SMB_ACL_USER_OBJ USER_OBJ
|
||||
#define SMB_ACL_GROUP GROUP
|
||||
#define SMB_ACL_GROUP_OBJ GROUP_OBJ
|
||||
#define SMB_ACL_OTHER OTHER_OBJ
|
||||
#define SMB_ACL_MASK CLASS_OBJ
|
||||
|
||||
typedef struct SMB_ACL_T {
|
||||
int size;
|
||||
int count;
|
||||
int next;
|
||||
struct acl acl[1];
|
||||
} *SMB_ACL_T;
|
||||
|
||||
typedef struct acl *SMB_ACL_ENTRY_T;
|
||||
|
||||
#define SMB_ACL_FIRST_ENTRY 0
|
||||
#define SMB_ACL_NEXT_ENTRY 1
|
||||
|
||||
#define SMB_ACL_TYPE_ACCESS 0
|
||||
#define SMB_ACL_TYPE_DEFAULT 1
|
||||
|
||||
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
|
||||
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
|
||||
|
||||
#define SMB_ACL_NEED_SORT
|
||||
|
||||
#elif defined HAVE_IRIX_ACLS /*----------------------------------------------*/
|
||||
|
||||
/* IRIX ACLs */
|
||||
|
||||
#define SMB_ACL_TAG_T acl_tag_t
|
||||
#define SMB_ACL_TYPE_T acl_type_t
|
||||
|
||||
/* Types of ACLs. */
|
||||
#define SMB_ACL_USER ACL_USER
|
||||
#define SMB_ACL_USER_OBJ ACL_USER_OBJ
|
||||
#define SMB_ACL_GROUP ACL_GROUP
|
||||
#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
|
||||
#define SMB_ACL_OTHER ACL_OTHER_OBJ
|
||||
#define SMB_ACL_MASK ACL_MASK
|
||||
|
||||
typedef struct SMB_ACL_T {
|
||||
int next;
|
||||
BOOL freeaclp;
|
||||
struct acl *aclp;
|
||||
} *SMB_ACL_T;
|
||||
|
||||
#define SMB_ACL_ENTRY_T acl_entry_t
|
||||
|
||||
#define SMB_ACL_FIRST_ENTRY 0
|
||||
#define SMB_ACL_NEXT_ENTRY 1
|
||||
|
||||
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
|
||||
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
|
||||
|
||||
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
|
||||
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
|
||||
|
||||
#define SMB_ACL_NEED_SORT
|
||||
|
||||
#elif defined HAVE_AIX_ACLS /*-----------------------------------------------*/
|
||||
|
||||
/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
|
||||
|
||||
#include "/usr/include/acl.h"
|
||||
|
||||
struct acl_entry_link{
|
||||
struct acl_entry_link *prevp;
|
||||
struct new_acl_entry *entryp;
|
||||
struct acl_entry_link *nextp;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct new_acl_entry{
|
||||
unsigned short ace_len;
|
||||
unsigned short ace_type;
|
||||
unsigned int ace_access;
|
||||
struct ace_id ace_id[1];
|
||||
};
|
||||
|
||||
#define SMB_ACL_ENTRY_T struct new_acl_entry*
|
||||
#define SMB_ACL_T struct acl_entry_link*
|
||||
|
||||
#define SMB_ACL_TAG_T unsigned short
|
||||
#define SMB_ACL_TYPE_T int
|
||||
|
||||
/* Types of ACLs. */
|
||||
#define SMB_ACL_USER ACEID_USER
|
||||
#define SMB_ACL_USER_OBJ 3
|
||||
#define SMB_ACL_GROUP ACEID_GROUP
|
||||
#define SMB_ACL_GROUP_OBJ 4
|
||||
#define SMB_ACL_OTHER 5
|
||||
#define SMB_ACL_MASK 6
|
||||
|
||||
#define SMB_ACL_FIRST_ENTRY 1
|
||||
#define SMB_ACL_NEXT_ENTRY 2
|
||||
|
||||
#define SMB_ACL_TYPE_ACCESS 0
|
||||
#define SMB_ACL_TYPE_DEFAULT 1
|
||||
|
||||
#define SMB_ACL_VALID_NAME_BITS (4 | 2 | 1)
|
||||
#define SMB_ACL_VALID_OBJ_BITS (4 | 2 | 1)
|
||||
|
||||
#define SMB_ACL_NEED_SORT
|
||||
|
||||
#elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
|
||||
|
||||
/* Special handling for OS X ACLs */
|
||||
|
||||
#define SMB_ACL_TAG_T acl_tag_t
|
||||
#define SMB_ACL_TYPE_T acl_type_t
|
||||
|
||||
#define SMB_ACL_T acl_t
|
||||
|
||||
#define SMB_ACL_ENTRY_T acl_entry_t
|
||||
|
||||
#define SMB_ACL_USER 1
|
||||
#define SMB_ACL_GROUP 2
|
||||
|
||||
#define SMB_ACL_FIRST_ENTRY ACL_FIRST_ENTRY
|
||||
#define SMB_ACL_NEXT_ENTRY ACL_NEXT_ENTRY
|
||||
|
||||
#define SMB_ACL_TYPE_ACCESS ACL_TYPE_EXTENDED
|
||||
#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
|
||||
|
||||
#define SMB_ACL_VALID_NAME_BITS ((1<<25)-1)
|
||||
#define SMB_ACL_VALID_OBJ_BITS 0
|
||||
|
||||
/*#undef SMB_ACL_NEED_SORT*/
|
||||
|
||||
#else /*---------------------------------------------------------------------*/
|
||||
|
||||
/* Unknown platform. */
|
||||
|
||||
#error Cannot handle ACLs on this platform!
|
||||
|
||||
#endif
|
||||
|
||||
int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
|
||||
int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
|
||||
int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p);
|
||||
SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type);
|
||||
SMB_ACL_T sys_acl_get_fd(int fd);
|
||||
SMB_ACL_T sys_acl_init(int count);
|
||||
int sys_acl_create_entry(SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
|
||||
int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype, uint32 bits, id_t u_g_id);
|
||||
int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits);
|
||||
int sys_acl_valid(SMB_ACL_T theacl);
|
||||
int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
|
||||
int sys_acl_set_fd(int fd, SMB_ACL_T theacl);
|
||||
int sys_acl_delete_def_file(const char *name);
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl);
|
||||
int no_acl_syscall_error(int err);
|
||||
|
||||
#endif /* SUPPORT_ACLS */
|
||||
134
lib/sysxattrs.c
Normal file
134
lib/sysxattrs.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Extended attribute support for rsync.
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc.
|
||||
* Written by Jay Fenlason.
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "sysxattrs.h"
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
|
||||
#if defined HAVE_LINUX_XATTRS
|
||||
|
||||
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
|
||||
{
|
||||
return lgetxattr(path, name, value, size);
|
||||
}
|
||||
|
||||
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
|
||||
{
|
||||
return fgetxattr(filedes, name, value, size);
|
||||
}
|
||||
|
||||
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
|
||||
{
|
||||
return lsetxattr(path, name, value, size, 0);
|
||||
}
|
||||
|
||||
int sys_lremovexattr(const char *path, const char *name)
|
||||
{
|
||||
return lremovexattr(path, name);
|
||||
}
|
||||
|
||||
ssize_t sys_llistxattr(const char *path, char *list, size_t size)
|
||||
{
|
||||
return llistxattr(path, list, size);
|
||||
}
|
||||
|
||||
#elif HAVE_OSX_XATTRS
|
||||
|
||||
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
|
||||
{
|
||||
return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
|
||||
}
|
||||
|
||||
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
|
||||
{
|
||||
return fgetxattr(filedes, name, value, size, 0, 0);
|
||||
}
|
||||
|
||||
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
|
||||
{
|
||||
return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
|
||||
}
|
||||
|
||||
int sys_lremovexattr(const char *path, const char *name)
|
||||
{
|
||||
return removexattr(path, name, XATTR_NOFOLLOW);
|
||||
}
|
||||
|
||||
ssize_t sys_llistxattr(const char *path, char *list, size_t size)
|
||||
{
|
||||
return listxattr(path, list, size, XATTR_NOFOLLOW);
|
||||
}
|
||||
|
||||
#elif HAVE_FREEBSD_XATTRS
|
||||
|
||||
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
|
||||
{
|
||||
return extattr_get_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
|
||||
}
|
||||
|
||||
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
|
||||
{
|
||||
return extattr_get_fd(filedes, EXTATTR_NAMESPACE_USER, name, value, size);
|
||||
}
|
||||
|
||||
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
|
||||
{
|
||||
return extattr_set_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
|
||||
}
|
||||
|
||||
int sys_lremovexattr(const char *path, const char *name)
|
||||
{
|
||||
return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name);
|
||||
}
|
||||
|
||||
ssize_t sys_llistxattr(const char *path, char *list, size_t size)
|
||||
{
|
||||
unsigned char keylen;
|
||||
ssize_t off, len = extattr_list_link(path, EXTATTR_NAMESPACE_USER, list, size);
|
||||
|
||||
if (len <= 0 || (size_t)len > size)
|
||||
return len;
|
||||
|
||||
/* FreeBSD puts a single-byte length before each string, with no '\0'
|
||||
* terminator. We need to change this into a series of null-terminted
|
||||
* strings. Since the size is the same, we can simply transform the
|
||||
* output in place. */
|
||||
for (off = 0; off < len; off += keylen + 1) {
|
||||
keylen = ((unsigned char*)list)[off];
|
||||
if (off + keylen >= len) {
|
||||
/* Should be impossible, but kernel bugs happen! */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
memmove(list+off, list+off+1, keylen);
|
||||
list[off+keylen] = '\0';
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error You need to create xattr compatibility functions.
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SUPPORT_XATTRS */
|
||||
26
lib/sysxattrs.h
Normal file
26
lib/sysxattrs.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifdef SUPPORT_XATTRS
|
||||
|
||||
#if defined HAVE_ATTR_XATTR_H
|
||||
#include <attr/xattr.h>
|
||||
#elif defined HAVE_SYS_XATTR_H
|
||||
#include <sys/xattr.h>
|
||||
#elif defined HAVE_SYS_EXTATTR_H
|
||||
#include <sys/extattr.h>
|
||||
#endif
|
||||
|
||||
/* Linux 2.4 does not define this as a distinct errno value: */
|
||||
#ifndef ENOATTR
|
||||
#define ENOATTR ENODATA
|
||||
#endif
|
||||
|
||||
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size);
|
||||
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size);
|
||||
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size);
|
||||
int sys_lremovexattr(const char *path, const char *name);
|
||||
ssize_t sys_llistxattr(const char *path, char *list, size_t size);
|
||||
|
||||
#else
|
||||
|
||||
/* No xattrs available */
|
||||
|
||||
#endif
|
||||
315
lib/wildmatch.c
315
lib/wildmatch.c
@@ -57,173 +57,312 @@
|
||||
int wildmatch_iteration_count;
|
||||
#endif
|
||||
|
||||
static int domatch(const unsigned char *p, const unsigned char *text)
|
||||
static int force_lower_case = 0;
|
||||
|
||||
/* Match pattern "p" against the a virtually-joined string consisting
|
||||
* of "text" and any strings in array "a". */
|
||||
static int dowild(const uchar *p, const uchar *text, const uchar*const *a)
|
||||
{
|
||||
int matched, special;
|
||||
unsigned char ch, prev;
|
||||
uchar p_ch;
|
||||
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
wildmatch_iteration_count++;
|
||||
#endif
|
||||
|
||||
for ( ; (ch = *p) != '\0'; text++, p++) {
|
||||
if (*text == '\0' && ch != '*')
|
||||
return FALSE;
|
||||
switch (ch) {
|
||||
for ( ; (p_ch = *p) != '\0'; text++, p++) {
|
||||
int matched, special;
|
||||
uchar t_ch, prev_ch;
|
||||
while ((t_ch = *text) == '\0') {
|
||||
if (*a == NULL) {
|
||||
if (p_ch != '*')
|
||||
return ABORT_ALL;
|
||||
break;
|
||||
}
|
||||
text = *a++;
|
||||
}
|
||||
if (force_lower_case && ISUPPER(t_ch))
|
||||
t_ch = tolower(t_ch);
|
||||
switch (p_ch) {
|
||||
case '\\':
|
||||
/* Literal match with following character. Note that the test
|
||||
* in "default" handles the p[1] == '\0' failure case. */
|
||||
ch = *++p;
|
||||
p_ch = *++p;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (*text != ch)
|
||||
if (t_ch != p_ch)
|
||||
return FALSE;
|
||||
continue;
|
||||
case '?':
|
||||
/* Match anything but '/'. */
|
||||
if (*text == '/')
|
||||
if (t_ch == '/')
|
||||
return FALSE;
|
||||
continue;
|
||||
case '*':
|
||||
if (*++p == '*') {
|
||||
while (*++p == '*') {}
|
||||
special = TRUE;
|
||||
}
|
||||
else
|
||||
} else
|
||||
special = FALSE;
|
||||
if (*p == '\0') {
|
||||
/* Trailing "**" matches everything. Trailing "*" matches
|
||||
* only if there are no more slash characters. */
|
||||
return special? TRUE : strchr((char*)text, '/') == NULL;
|
||||
if (!special) {
|
||||
do {
|
||||
if (strchr((char*)text, '/') != NULL)
|
||||
return FALSE;
|
||||
} while ((text = *a++) != NULL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
for ( ; *text; text++) {
|
||||
if ((matched = domatch(p, text)) != FALSE) {
|
||||
while (1) {
|
||||
if (t_ch == '\0') {
|
||||
if ((text = *a++) == NULL)
|
||||
break;
|
||||
t_ch = *text;
|
||||
continue;
|
||||
}
|
||||
if ((matched = dowild(p, text, a)) != FALSE) {
|
||||
if (!special || matched != ABORT_TO_STARSTAR)
|
||||
return matched;
|
||||
}
|
||||
else if (!special && *text == '/')
|
||||
} else if (!special && t_ch == '/')
|
||||
return ABORT_TO_STARSTAR;
|
||||
t_ch = *++text;
|
||||
}
|
||||
return ABORT_ALL;
|
||||
case '[':
|
||||
ch = *++p;
|
||||
p_ch = *++p;
|
||||
#ifdef NEGATE_CLASS2
|
||||
if (ch == NEGATE_CLASS2)
|
||||
ch = NEGATE_CLASS;
|
||||
if (p_ch == NEGATE_CLASS2)
|
||||
p_ch = NEGATE_CLASS;
|
||||
#endif
|
||||
/* Assign literal TRUE/FALSE because of "matched" comparison. */
|
||||
special = ch == NEGATE_CLASS? TRUE : FALSE;
|
||||
special = p_ch == NEGATE_CLASS? TRUE : FALSE;
|
||||
if (special) {
|
||||
/* Inverted character class. */
|
||||
ch = *++p;
|
||||
p_ch = *++p;
|
||||
}
|
||||
prev = 0;
|
||||
prev_ch = 0;
|
||||
matched = FALSE;
|
||||
do {
|
||||
if (!ch)
|
||||
if (!p_ch)
|
||||
return ABORT_ALL;
|
||||
if (ch == '\\') {
|
||||
ch = *++p;
|
||||
if (!ch)
|
||||
if (p_ch == '\\') {
|
||||
p_ch = *++p;
|
||||
if (!p_ch)
|
||||
return ABORT_ALL;
|
||||
if (*text == ch)
|
||||
if (t_ch == p_ch)
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (ch == '-' && prev && p[1] && p[1] != ']') {
|
||||
ch = *++p;
|
||||
if (ch == '\\') {
|
||||
ch = *++p;
|
||||
if (!ch)
|
||||
} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
|
||||
p_ch = *++p;
|
||||
if (p_ch == '\\') {
|
||||
p_ch = *++p;
|
||||
if (!p_ch)
|
||||
return ABORT_ALL;
|
||||
}
|
||||
if (*text <= ch && *text >= prev)
|
||||
if (t_ch <= p_ch && t_ch >= prev_ch)
|
||||
matched = TRUE;
|
||||
ch = 0; /* This makes "prev" get set to 0. */
|
||||
}
|
||||
else if (ch == '[' && p[1] == ':') {
|
||||
const unsigned char *s = p += 2;
|
||||
p_ch = 0; /* This makes "prev_ch" get set to 0. */
|
||||
} else if (p_ch == '[' && p[1] == ':') {
|
||||
const uchar *s;
|
||||
int i;
|
||||
while ((ch = *p) && ch != ']') p++;
|
||||
if (!ch)
|
||||
for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {} /*SHARED ITERATOR*/
|
||||
if (!p_ch)
|
||||
return ABORT_ALL;
|
||||
i = p - s - 1;
|
||||
if (i < 0 || p[-1] != ':') {
|
||||
/* Didn't find ":]", so treat like a normal set. */
|
||||
p = s - 2;
|
||||
ch = '[';
|
||||
if (*text == ch)
|
||||
p_ch = '[';
|
||||
if (t_ch == p_ch)
|
||||
matched = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (CC_EQ(s,i, "alnum")) {
|
||||
if (ISALNUM(*text))
|
||||
if (ISALNUM(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "alpha")) {
|
||||
if (ISALPHA(*text))
|
||||
} else if (CC_EQ(s,i, "alpha")) {
|
||||
if (ISALPHA(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "blank")) {
|
||||
if (ISBLANK(*text))
|
||||
} else if (CC_EQ(s,i, "blank")) {
|
||||
if (ISBLANK(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "cntrl")) {
|
||||
if (ISCNTRL(*text))
|
||||
} else if (CC_EQ(s,i, "cntrl")) {
|
||||
if (ISCNTRL(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "digit")) {
|
||||
if (ISDIGIT(*text))
|
||||
} else if (CC_EQ(s,i, "digit")) {
|
||||
if (ISDIGIT(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "graph")) {
|
||||
if (ISGRAPH(*text))
|
||||
} else if (CC_EQ(s,i, "graph")) {
|
||||
if (ISGRAPH(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "lower")) {
|
||||
if (ISLOWER(*text))
|
||||
} else if (CC_EQ(s,i, "lower")) {
|
||||
if (ISLOWER(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "print")) {
|
||||
if (ISPRINT(*text))
|
||||
} else if (CC_EQ(s,i, "print")) {
|
||||
if (ISPRINT(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "punct")) {
|
||||
if (ISPUNCT(*text))
|
||||
} else if (CC_EQ(s,i, "punct")) {
|
||||
if (ISPUNCT(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "space")) {
|
||||
if (ISSPACE(*text))
|
||||
} else if (CC_EQ(s,i, "space")) {
|
||||
if (ISSPACE(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "upper")) {
|
||||
if (ISUPPER(*text))
|
||||
} else if (CC_EQ(s,i, "upper")) {
|
||||
if (ISUPPER(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "xdigit")) {
|
||||
if (ISXDIGIT(*text))
|
||||
} else if (CC_EQ(s,i, "xdigit")) {
|
||||
if (ISXDIGIT(t_ch))
|
||||
matched = TRUE;
|
||||
}
|
||||
else /* malformed [:class:] string */
|
||||
} else /* malformed [:class:] string */
|
||||
return ABORT_ALL;
|
||||
ch = 0; /* This makes "prev" get set to 0. */
|
||||
}
|
||||
else if (*text == ch)
|
||||
p_ch = 0; /* This makes "prev_ch" get set to 0. */
|
||||
} else if (t_ch == p_ch)
|
||||
matched = TRUE;
|
||||
} while (prev = ch, (ch = *++p) != ']');
|
||||
if (matched == special || *text == '/')
|
||||
} while (prev_ch = p_ch, (p_ch = *++p) != ']');
|
||||
if (matched == special || t_ch == '/')
|
||||
return FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return *text == '\0';
|
||||
do {
|
||||
if (*text)
|
||||
return FALSE;
|
||||
} while ((text = *a++) != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Find the pattern (p) in the text string (t). */
|
||||
int wildmatch(const char *p, const char *t)
|
||||
/* Match literal string "s" against the a virtually-joined string consisting
|
||||
* of "text" and any strings in array "a". */
|
||||
static int doliteral(const uchar *s, const uchar *text, const uchar*const *a)
|
||||
{
|
||||
for ( ; *s != '\0'; text++, s++) {
|
||||
while (*text == '\0') {
|
||||
if ((text = *a++) == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
if (*text != *s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do {
|
||||
if (*text)
|
||||
return FALSE;
|
||||
} while ((text = *a++) != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return the last "count" path elements from the concatenated string.
|
||||
* We return a string pointer to the start of the string, and update the
|
||||
* array pointer-pointer to point to any remaining string elements. */
|
||||
static const uchar *trailing_N_elements(const uchar*const **a_ptr, int count)
|
||||
{
|
||||
const uchar*const *a = *a_ptr;
|
||||
const uchar*const *first_a = a;
|
||||
|
||||
while (*a)
|
||||
a++;
|
||||
|
||||
while (a != first_a) {
|
||||
const uchar *s = *--a;
|
||||
s += strlen((char*)s);
|
||||
while (--s >= *a) {
|
||||
if (*s == '/' && !--count) {
|
||||
*a_ptr = a+1;
|
||||
return s+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
*a_ptr = a+1;
|
||||
return *a;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Match the "pattern" against the "text" string. */
|
||||
int wildmatch(const char *pattern, const char *text)
|
||||
{
|
||||
static const uchar *nomore[1]; /* A NULL pointer. */
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
wildmatch_iteration_count = 0;
|
||||
#endif
|
||||
return domatch((const unsigned char*)p, (const unsigned char*)t) == TRUE;
|
||||
return dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
|
||||
}
|
||||
|
||||
/* Match the "pattern" against the forced-to-lower-case "text" string. */
|
||||
int iwildmatch(const char *pattern, const char *text)
|
||||
{
|
||||
static const uchar *nomore[1]; /* A NULL pointer. */
|
||||
int ret;
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
wildmatch_iteration_count = 0;
|
||||
#endif
|
||||
force_lower_case = 1;
|
||||
ret = dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
|
||||
force_lower_case = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Match pattern "p" against the a virtually-joined string consisting
|
||||
* of all the pointers in array "texts" (which has a NULL pointer at the
|
||||
* end). The int "where" can be 0 (normal matching), > 0 (match only
|
||||
* the trailing N slash-separated filename components of "texts"), or < 0
|
||||
* (match the "pattern" at the start or after any slash in "texts"). */
|
||||
int wildmatch_array(const char *pattern, const char*const *texts, int where)
|
||||
{
|
||||
const uchar *p = (const uchar*)pattern;
|
||||
const uchar*const *a = (const uchar*const*)texts;
|
||||
const uchar *text;
|
||||
int matched;
|
||||
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
wildmatch_iteration_count = 0;
|
||||
#endif
|
||||
|
||||
if (where > 0)
|
||||
text = trailing_N_elements(&a, where);
|
||||
else
|
||||
text = *a++;
|
||||
if (!text)
|
||||
return FALSE;
|
||||
|
||||
if ((matched = dowild(p, text, a)) != TRUE && where < 0
|
||||
&& matched != ABORT_ALL) {
|
||||
while (1) {
|
||||
if (*text == '\0') {
|
||||
if ((text = (uchar*)*a++) == NULL)
|
||||
return FALSE;
|
||||
continue;
|
||||
}
|
||||
if (*text++ == '/' && (matched = dowild(p, text, a)) != FALSE
|
||||
&& matched != ABORT_TO_STARSTAR)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return matched == TRUE;
|
||||
}
|
||||
|
||||
/* Match literal string "s" against the a virtually-joined string consisting
|
||||
* of all the pointers in array "texts" (which has a NULL pointer at the
|
||||
* end). The int "where" can be 0 (normal matching), or > 0 (match
|
||||
* only the trailing N slash-separated filename components of "texts"). */
|
||||
int litmatch_array(const char *string, const char*const *texts, int where)
|
||||
{
|
||||
const uchar *s = (const uchar*)string;
|
||||
const uchar*const *a = (const uchar* const*)texts;
|
||||
const uchar *text;
|
||||
|
||||
if (where > 0)
|
||||
text = trailing_N_elements(&a, where);
|
||||
else
|
||||
text = *a++;
|
||||
if (!text)
|
||||
return FALSE;
|
||||
|
||||
return doliteral(s, text, a) == TRUE;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/* wildmatch.h */
|
||||
|
||||
int wildmatch(const char *p, const char *text);
|
||||
int wildmatch(const char *pattern, const char *text);
|
||||
int iwildmatch(const char *pattern, const char *text);
|
||||
int wildmatch_array(const char *pattern, const char*const *texts, int where);
|
||||
int litmatch_array(const char *string, const char*const *texts, int where);
|
||||
|
||||
378
loadparm.c
378
loadparm.c
@@ -1,26 +1,25 @@
|
||||
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
|
||||
and Karl Auer */
|
||||
|
||||
/* some fixes
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/*
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* some fixes
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Load parameters.
|
||||
@@ -51,12 +50,20 @@
|
||||
/* TODO: Parameter to set debug level on server. */
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
|
||||
#define strequal(a,b) (strcasecmp(a,b)==0)
|
||||
#define BOOLSTR(b) ((b) ? "Yes" : "No")
|
||||
typedef char pstring[1024];
|
||||
#define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
|
||||
|
||||
#ifndef LOG_DAEMON
|
||||
#define LOG_DAEMON 0
|
||||
#endif
|
||||
|
||||
#define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \
|
||||
" *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg"
|
||||
|
||||
/* the following are used by loadparm for option lists */
|
||||
typedef enum
|
||||
{
|
||||
@@ -98,89 +105,111 @@ struct parm_struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *bind_address;
|
||||
char *motd_file;
|
||||
char *log_file;
|
||||
char *pid_file;
|
||||
char *socket_options;
|
||||
int syslog_facility;
|
||||
int max_verbosity;
|
||||
|
||||
int rsync_port;
|
||||
} global;
|
||||
|
||||
static global Globals;
|
||||
|
||||
|
||||
/*
|
||||
* This structure describes a single service.
|
||||
* This structure describes a single service. Their order must match the
|
||||
* initializers below, which you can accomplish by keeping each sub-section
|
||||
* sorted. (e.g. in vim, just visually select each subsection and use !sort.)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
char *path;
|
||||
char *auth_users;
|
||||
char *comment;
|
||||
char *lock_file;
|
||||
BOOL read_only;
|
||||
BOOL list;
|
||||
BOOL use_chroot;
|
||||
BOOL transfer_logging;
|
||||
BOOL ignore_errors;
|
||||
char *uid;
|
||||
char *dont_compress;
|
||||
char *exclude;
|
||||
char *exclude_from;
|
||||
char *filter;
|
||||
char *gid;
|
||||
char *hosts_allow;
|
||||
char *hosts_deny;
|
||||
char *auth_users;
|
||||
char *secrets_file;
|
||||
BOOL strict_modes;
|
||||
char *exclude;
|
||||
char *exclude_from;
|
||||
char *include;
|
||||
char *include_from;
|
||||
char *incoming_chmod;
|
||||
char *lock_file;
|
||||
char *log_file;
|
||||
char *log_format;
|
||||
char *name;
|
||||
char *outgoing_chmod;
|
||||
char *path;
|
||||
char *postxfer_exec;
|
||||
char *prexfer_exec;
|
||||
char *refuse_options;
|
||||
char *dont_compress;
|
||||
int timeout;
|
||||
char *secrets_file;
|
||||
char *temp_dir;
|
||||
char *uid;
|
||||
|
||||
int max_connections;
|
||||
int max_verbosity;
|
||||
int syslog_facility;
|
||||
int timeout;
|
||||
|
||||
BOOL fake_super;
|
||||
BOOL ignore_errors;
|
||||
BOOL ignore_nonreadable;
|
||||
BOOL list;
|
||||
BOOL read_only;
|
||||
BOOL strict_modes;
|
||||
BOOL transfer_logging;
|
||||
BOOL use_chroot;
|
||||
BOOL write_only;
|
||||
} service;
|
||||
|
||||
|
||||
/* This is a default service used to prime a services structure */
|
||||
/* This is a default service used to prime a services structure. In order
|
||||
* to make these easy to keep sorted in the same way as the variables
|
||||
* above, use the variable name in the leading comment, including a
|
||||
* trailing ';' (to avoid a sorting problem with trailing digits). */
|
||||
static service sDefault =
|
||||
{
|
||||
NULL, /* name */
|
||||
NULL, /* path */
|
||||
NULL, /* comment */
|
||||
DEFAULT_LOCK_FILE, /* lock file */
|
||||
True, /* read only */
|
||||
True, /* list */
|
||||
True, /* use chroot */
|
||||
False, /* transfer logging */
|
||||
False, /* ignore errors */
|
||||
"nobody",/* uid */
|
||||
/* auth_users; */ NULL,
|
||||
/* comment; */ NULL,
|
||||
/* dont_compress; */ DEFAULT_DONT_COMPRESS,
|
||||
/* exclude; */ NULL,
|
||||
/* exclude_from; */ NULL,
|
||||
/* filter; */ NULL,
|
||||
/* gid; */ NOBODY_GROUP,
|
||||
/* hosts_allow; */ NULL,
|
||||
/* hosts_deny; */ NULL,
|
||||
/* include; */ NULL,
|
||||
/* include_from; */ NULL,
|
||||
/* incoming_chmod; */ NULL,
|
||||
/* lock_file; */ DEFAULT_LOCK_FILE,
|
||||
/* log_file; */ NULL,
|
||||
/* log_format; */ "%o %h [%a] %m (%u) %f %l",
|
||||
/* name; */ NULL,
|
||||
/* outgoing_chmod; */ NULL,
|
||||
/* path; */ NULL,
|
||||
/* postxfer_exec; */ NULL,
|
||||
/* prexfer_exec; */ NULL,
|
||||
/* refuse_options; */ NULL,
|
||||
/* secrets_file; */ NULL,
|
||||
/* temp_dir; */ NULL,
|
||||
/* uid; */ NOBODY_USER,
|
||||
|
||||
/* TODO: This causes problems on Debian, where it is called
|
||||
* "nogroup". Debian patch this in their version of the
|
||||
* package, but it would be nice to be consistent. Possibly
|
||||
* other systems are different again.
|
||||
*
|
||||
* What is the best behaviour? Perhaps always using (gid_t)
|
||||
* -2? */
|
||||
"nobody",/* gid */
|
||||
/* max_connections; */ 0,
|
||||
/* max_verbosity; */ 1,
|
||||
/* syslog_facility; */ LOG_DAEMON,
|
||||
/* timeout; */ 0,
|
||||
|
||||
NULL, /* hosts allow */
|
||||
NULL, /* hosts deny */
|
||||
NULL, /* auth users */
|
||||
NULL, /* secrets file */
|
||||
True, /* strict modes */
|
||||
NULL, /* exclude */
|
||||
NULL, /* exclude from */
|
||||
NULL, /* include */
|
||||
NULL, /* include from */
|
||||
"%o %h [%a] %m (%u) %f %l", /* log format */
|
||||
NULL, /* refuse options */
|
||||
"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz", /* dont compress */
|
||||
0, /* timeout */
|
||||
0, /* max connections */
|
||||
False /* ignore nonreadable */
|
||||
/* fake_super; */ False,
|
||||
/* ignore_errors; */ False,
|
||||
/* ignore_nonreadable; */ False,
|
||||
/* list; */ True,
|
||||
/* read_only; */ True,
|
||||
/* strict_modes; */ True,
|
||||
/* transfer_logging; */ False,
|
||||
/* use_chroot; */ True,
|
||||
/* write_only; */ False,
|
||||
};
|
||||
|
||||
|
||||
@@ -263,57 +292,65 @@ static struct enum_list enum_facilities[] = {
|
||||
/* note that we do not initialise the defaults union - it is not allowed in ANSI C */
|
||||
static struct parm_struct parm_table[] =
|
||||
{
|
||||
{"motd file", P_STRING, P_GLOBAL, &Globals.motd_file, NULL, 0},
|
||||
{"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
|
||||
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
|
||||
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
|
||||
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
|
||||
{"max verbosity", P_INTEGER, P_GLOBAL, &Globals.max_verbosity, NULL, 0},
|
||||
{"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
|
||||
{"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0},
|
||||
{"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0},
|
||||
{"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0},
|
||||
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
|
||||
|
||||
{"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
|
||||
{"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
|
||||
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
|
||||
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
|
||||
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
|
||||
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL, 0},
|
||||
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
|
||||
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
|
||||
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
|
||||
{"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable, NULL, 0},
|
||||
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
|
||||
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
|
||||
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
|
||||
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL, 0},
|
||||
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL, 0},
|
||||
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
|
||||
{"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes,NULL, 0},
|
||||
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
|
||||
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
|
||||
{"include", P_STRING, P_LOCAL, &sDefault.include, NULL, 0},
|
||||
{"include from", P_STRING, P_LOCAL, &sDefault.include_from,NULL, 0},
|
||||
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
|
||||
{"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors,NULL,0},
|
||||
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
|
||||
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options,NULL, 0},
|
||||
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress,NULL, 0},
|
||||
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
|
||||
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
|
||||
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
|
||||
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
|
||||
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
|
||||
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
|
||||
{"fake super", P_BOOL, P_LOCAL, &sDefault.fake_super, NULL,0},
|
||||
{"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
|
||||
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
|
||||
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
|
||||
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL,0},
|
||||
{"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors, NULL,0},
|
||||
{"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable,NULL,0},
|
||||
{"include from", P_STRING, P_LOCAL, &sDefault.include_from, NULL,0},
|
||||
{"include", P_STRING, P_LOCAL, &sDefault.include, NULL,0},
|
||||
{"incoming chmod", P_STRING, P_LOCAL, &sDefault.incoming_chmod, NULL,0},
|
||||
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL,0},
|
||||
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL,0},
|
||||
{"log file", P_STRING, P_LOCAL, &sDefault.log_file, NULL,0},
|
||||
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
|
||||
{"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
|
||||
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
|
||||
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
|
||||
{"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
|
||||
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
|
||||
#ifdef HAVE_PUTENV
|
||||
{"post-xfer exec", P_STRING, P_LOCAL, &sDefault.postxfer_exec, NULL,0},
|
||||
{"pre-xfer exec", P_STRING, P_LOCAL, &sDefault.prexfer_exec, NULL,0},
|
||||
#endif
|
||||
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL,0},
|
||||
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options, NULL,0},
|
||||
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file, NULL,0},
|
||||
{"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes, NULL,0},
|
||||
{"syslog facility", P_ENUM, P_LOCAL, &sDefault.syslog_facility,enum_facilities,0},
|
||||
{"temp dir", P_PATH, P_LOCAL, &sDefault.temp_dir, NULL,0},
|
||||
{"timeout", P_INTEGER,P_LOCAL, &sDefault.timeout, NULL,0},
|
||||
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging, NULL,0},
|
||||
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL,0},
|
||||
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL,0},
|
||||
{"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL,0},
|
||||
{NULL, P_BOOL, P_NONE, NULL, NULL,0}
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Initialise the global parameter structure.
|
||||
* Initialise the global parameter structure.
|
||||
***************************************************************************/
|
||||
static void init_globals(void)
|
||||
{
|
||||
memset(&Globals, 0, sizeof Globals);
|
||||
#ifdef LOG_DAEMON
|
||||
Globals.syslog_facility = LOG_DAEMON;
|
||||
#endif
|
||||
Globals.max_verbosity = 1;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Initialise the sDefault parameter structure.
|
||||
* Initialise the sDefault parameter structure.
|
||||
***************************************************************************/
|
||||
static void init_locals(void)
|
||||
{
|
||||
@@ -344,39 +381,52 @@ static void init_locals(void)
|
||||
int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
|
||||
|
||||
|
||||
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
|
||||
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
|
||||
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
|
||||
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
|
||||
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
|
||||
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
|
||||
FN_GLOBAL_INTEGER(lp_max_verbosity, &Globals.max_verbosity)
|
||||
|
||||
FN_LOCAL_STRING(lp_name, name)
|
||||
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
|
||||
|
||||
FN_LOCAL_STRING(lp_auth_users, auth_users)
|
||||
FN_LOCAL_STRING(lp_comment, comment)
|
||||
FN_LOCAL_STRING(lp_path, path)
|
||||
FN_LOCAL_STRING(lp_lock_file, lock_file)
|
||||
FN_LOCAL_BOOL(lp_read_only, read_only)
|
||||
FN_LOCAL_BOOL(lp_list, list)
|
||||
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
|
||||
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
|
||||
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
|
||||
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
|
||||
FN_LOCAL_STRING(lp_uid, uid)
|
||||
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
|
||||
FN_LOCAL_STRING(lp_exclude, exclude)
|
||||
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
|
||||
FN_LOCAL_STRING(lp_filter, filter)
|
||||
FN_LOCAL_STRING(lp_gid, gid)
|
||||
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
|
||||
FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
|
||||
FN_LOCAL_STRING(lp_auth_users, auth_users)
|
||||
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
|
||||
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
|
||||
FN_LOCAL_STRING(lp_exclude, exclude)
|
||||
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
|
||||
FN_LOCAL_STRING(lp_include, include)
|
||||
FN_LOCAL_STRING(lp_include_from, include_from)
|
||||
FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
|
||||
FN_LOCAL_STRING(lp_lock_file, lock_file)
|
||||
FN_LOCAL_STRING(lp_log_file, log_file)
|
||||
FN_LOCAL_STRING(lp_log_format, log_format)
|
||||
FN_LOCAL_STRING(lp_name, name)
|
||||
FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
|
||||
FN_LOCAL_STRING(lp_path, path)
|
||||
FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
|
||||
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
|
||||
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
|
||||
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
|
||||
FN_LOCAL_INTEGER(lp_timeout, timeout)
|
||||
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
|
||||
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
|
||||
FN_LOCAL_STRING(lp_temp_dir, temp_dir)
|
||||
FN_LOCAL_STRING(lp_uid, uid)
|
||||
|
||||
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
|
||||
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
|
||||
FN_LOCAL_INTEGER(lp_timeout, timeout)
|
||||
|
||||
FN_LOCAL_BOOL(lp_fake_super, fake_super)
|
||||
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
|
||||
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
|
||||
FN_LOCAL_BOOL(lp_list, list)
|
||||
FN_LOCAL_BOOL(lp_read_only, read_only)
|
||||
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
|
||||
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
|
||||
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
|
||||
FN_LOCAL_BOOL(lp_write_only, write_only)
|
||||
|
||||
/* local prototypes */
|
||||
static int strwicmp(char *psz1, char *psz2);
|
||||
@@ -389,7 +439,7 @@ static BOOL do_section(char *sectionname);
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
initialise a service to the defaults
|
||||
* initialise a service to the defaults
|
||||
***************************************************************************/
|
||||
static void init_service(service *pservice)
|
||||
{
|
||||
@@ -423,8 +473,8 @@ static void string_set(char **s, const char *v)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
add a new service to the services array initialising it with the given
|
||||
service
|
||||
* add a new service to the services array initialising it with the given
|
||||
* service
|
||||
***************************************************************************/
|
||||
static int add_a_service(service *pservice, char *name)
|
||||
{
|
||||
@@ -463,7 +513,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Do a case-insensitive, whitespace-ignoring string compare.
|
||||
* Do a case-insensitive, whitespace-ignoring string compare.
|
||||
***************************************************************************/
|
||||
static int strwicmp(char *psz1, char *psz2)
|
||||
{
|
||||
@@ -481,12 +531,11 @@ static int strwicmp(char *psz1, char *psz2)
|
||||
/* sync the strings on first non-whitespace */
|
||||
while (1)
|
||||
{
|
||||
while (isspace(* (unsigned char *) psz1))
|
||||
while (isSpace(psz1))
|
||||
psz1++;
|
||||
while (isspace(* (unsigned char *) psz2))
|
||||
while (isSpace(psz2))
|
||||
psz2++;
|
||||
if (toupper(* (unsigned char *) psz1) != toupper(* (unsigned char *) psz2)
|
||||
|| *psz1 == '\0' || *psz2 == '\0')
|
||||
if (toUpper(psz1) != toUpper(psz2) || *psz1 == '\0' || *psz2 == '\0')
|
||||
break;
|
||||
psz1++;
|
||||
psz2++;
|
||||
@@ -495,8 +544,8 @@ static int strwicmp(char *psz1, char *psz2)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Map a parameter's string representation to something we can use.
|
||||
Returns False if the parameter string is not recognised, else TRUE.
|
||||
* Map a parameter's string representation to something we can use.
|
||||
* Returns False if the parameter string is not recognised, else TRUE.
|
||||
***************************************************************************/
|
||||
static int map_parameter(char *parmname)
|
||||
{
|
||||
@@ -515,9 +564,9 @@ static int map_parameter(char *parmname)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Set a boolean variable from the text value stored in the passed string.
|
||||
Returns True in success, False if the passed string does not correctly
|
||||
represent a boolean.
|
||||
* Set a boolean variable from the text value stored in the passed string.
|
||||
* Returns True in success, False if the passed string does not correctly
|
||||
* represent a boolean.
|
||||
***************************************************************************/
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
{
|
||||
@@ -543,7 +592,7 @@ static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Find a service by name. Otherwise works like get_service.
|
||||
* Find a service by name. Otherwise works like get_service.
|
||||
***************************************************************************/
|
||||
static int getservicebyname(char *name, service *pserviceDest)
|
||||
{
|
||||
@@ -563,8 +612,7 @@ static int getservicebyname(char *name, service *pserviceDest)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Copy a service structure to another
|
||||
|
||||
* Copy a service structure to another
|
||||
***************************************************************************/
|
||||
static void copy_service(service *pserviceDest,
|
||||
service *pserviceSource)
|
||||
@@ -609,8 +657,8 @@ static void copy_service(service *pserviceDest,
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Process a parameter for a particular service number. If snum < 0
|
||||
then assume we are in the globals
|
||||
* Process a parameter for a particular service number. If snum < 0
|
||||
* then assume we are in the globals
|
||||
***************************************************************************/
|
||||
static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
{
|
||||
@@ -701,7 +749,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Process a parameter.
|
||||
* Process a parameter.
|
||||
***************************************************************************/
|
||||
static BOOL do_parameter(char *parmname, char *parmvalue)
|
||||
{
|
||||
@@ -709,9 +757,9 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Process a new section (service). At this stage all sections are services.
|
||||
Later we'll have special sections that permit server parameters to be set.
|
||||
Returns True on success, False on failure.
|
||||
* Process a new section (service). At this stage all sections are services.
|
||||
* Later we'll have special sections that permit server parameters to be set.
|
||||
* Returns True on success, False on failure.
|
||||
***************************************************************************/
|
||||
static BOOL do_section(char *sectionname)
|
||||
{
|
||||
@@ -756,14 +804,11 @@ static BOOL do_section(char *sectionname)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Load the services array from the services file. Return True on success,
|
||||
False on failure.
|
||||
* Load the services array from the services file. Return True on success,
|
||||
* False on failure.
|
||||
***************************************************************************/
|
||||
BOOL lp_load(char *pszFname, int globals_only)
|
||||
{
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int am_root;
|
||||
pstring n2;
|
||||
BOOL bRetval;
|
||||
|
||||
@@ -773,12 +818,7 @@ BOOL lp_load(char *pszFname, int globals_only)
|
||||
|
||||
init_globals();
|
||||
|
||||
if (pszFname)
|
||||
pstrcpy(n2,pszFname);
|
||||
else if (am_server && am_daemon && !am_root)
|
||||
pstrcpy(n2,RSYNCD_USERCONF);
|
||||
else
|
||||
pstrcpy(n2,RSYNCD_SYSCONF);
|
||||
pstrcpy(n2, pszFname);
|
||||
|
||||
/* We get sections first, so have to start 'behind' to make up */
|
||||
iServiceIndex = -1;
|
||||
@@ -789,7 +829,7 @@ BOOL lp_load(char *pszFname, int globals_only)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
return the max number of services
|
||||
* return the max number of services
|
||||
***************************************************************************/
|
||||
int lp_numservices(void)
|
||||
{
|
||||
@@ -797,17 +837,17 @@ int lp_numservices(void)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Return the number of the service with the given name, or -1 if it doesn't
|
||||
exist. Note that this is a DIFFERENT ANIMAL from the internal function
|
||||
getservicebyname()! This works ONLY if all services have been loaded, and
|
||||
does not copy the found service.
|
||||
* Return the number of the service with the given name, or -1 if it doesn't
|
||||
* exist. Note that this is a DIFFERENT ANIMAL from the internal function
|
||||
* getservicebyname()! This works ONLY if all services have been loaded, and
|
||||
* does not copy the found service.
|
||||
***************************************************************************/
|
||||
int lp_number(char *name)
|
||||
{
|
||||
int iService;
|
||||
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--)
|
||||
if (strequal(lp_name(iService), name))
|
||||
if (strcmp(lp_name(iService), name) == 0)
|
||||
break;
|
||||
|
||||
return (iService);
|
||||
|
||||
327
match.c
327
match.c
@@ -1,85 +1,68 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
* Block matching used by the file-transfer code.
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
extern int do_progress;
|
||||
extern int checksum_seed;
|
||||
extern int append_mode;
|
||||
|
||||
typedef unsigned short tag;
|
||||
|
||||
#define TABLESIZE (1<<16)
|
||||
#define NULL_TAG ((size_t)-1)
|
||||
int updating_basis_file;
|
||||
|
||||
static int false_alarms;
|
||||
static int tag_hits;
|
||||
static int hash_hits;
|
||||
static int matches;
|
||||
static int64 data_transfer;
|
||||
|
||||
static int total_false_alarms;
|
||||
static int total_tag_hits;
|
||||
static int total_hash_hits;
|
||||
static int total_matches;
|
||||
|
||||
extern struct stats stats;
|
||||
|
||||
struct target {
|
||||
tag t;
|
||||
size_t i;
|
||||
};
|
||||
#define TABLESIZE (1<<16)
|
||||
|
||||
static struct target *targets;
|
||||
|
||||
static size_t *tag_table;
|
||||
|
||||
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
|
||||
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
|
||||
|
||||
static int compare_targets(struct target *t1,struct target *t2)
|
||||
{
|
||||
return (int)t1->t - (int)t2->t;
|
||||
}
|
||||
static int32 *hash_table;
|
||||
|
||||
#define SUM2HASH2(s1,s2) (((s1) + (s2)) & 0xFFFF)
|
||||
#define SUM2HASH(sum) SUM2HASH2((sum)&0xFFFF,(sum)>>16)
|
||||
|
||||
static void build_hash_table(struct sum_struct *s)
|
||||
{
|
||||
size_t i;
|
||||
int32 i;
|
||||
|
||||
if (!tag_table)
|
||||
tag_table = new_array(size_t, TABLESIZE);
|
||||
|
||||
targets = new_array(struct target, s->count);
|
||||
if (!tag_table || !targets)
|
||||
out_of_memory("build_hash_table");
|
||||
|
||||
for (i = 0; i < s->count; i++) {
|
||||
targets[i].i = i;
|
||||
targets[i].t = gettag(s->sums[i].sum1);
|
||||
if (!hash_table) {
|
||||
hash_table = new_array(int32, TABLESIZE);
|
||||
if (!hash_table)
|
||||
out_of_memory("build_hash_table");
|
||||
}
|
||||
|
||||
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
|
||||
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
|
||||
|
||||
for (i = 0; i < TABLESIZE; i++)
|
||||
tag_table[i] = NULL_TAG;
|
||||
|
||||
for (i = s->count; i-- > 0; )
|
||||
tag_table[targets[i].t] = i;
|
||||
for (i = 0; i < s->count; i++) {
|
||||
uint32 t = SUM2HASH(s->sums[i].sum1);
|
||||
s->sums[i].chain = hash_table[t];
|
||||
hash_table[t] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,17 +81,20 @@ static OFF_T last_match;
|
||||
* @param i If >0, the number of a matched token. If 0, indicates we
|
||||
* have only literal data.
|
||||
**/
|
||||
static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
OFF_T offset,int i)
|
||||
static void matched(int f, struct sum_struct *s, struct map_struct *buf,
|
||||
OFF_T offset, int32 i)
|
||||
{
|
||||
OFF_T n = offset - last_match;
|
||||
OFF_T j;
|
||||
int32 n = (int32)(offset - last_match); /* max value: block_size (int32) */
|
||||
int32 j;
|
||||
|
||||
if (verbose > 2 && i >= 0)
|
||||
rprintf(FINFO,"match at %.0f last_match=%.0f j=%d len=%u n=%.0f\n",
|
||||
(double)offset,(double)last_match,i,s->sums[i].len,(double)n);
|
||||
if (verbose > 2 && i >= 0) {
|
||||
rprintf(FINFO,
|
||||
"match at %.0f last_match=%.0f j=%d len=%ld n=%ld\n",
|
||||
(double)offset, (double)last_match, i,
|
||||
(long)s->sums[i].len, (long)n);
|
||||
}
|
||||
|
||||
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
|
||||
send_token(f, i, buf, last_match, n, i < 0 ? 0 : s->sums[i].len);
|
||||
data_transfer += n;
|
||||
|
||||
if (i >= 0) {
|
||||
@@ -117,22 +103,17 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
}
|
||||
|
||||
for (j = 0; j < n; j += CHUNK_SIZE) {
|
||||
int n1 = MIN(CHUNK_SIZE,n-j);
|
||||
sum_update(map_ptr(buf,last_match+j,n1),n1);
|
||||
int32 n1 = MIN(CHUNK_SIZE, n - j);
|
||||
sum_update(map_ptr(buf, last_match + j, n1), n1);
|
||||
}
|
||||
|
||||
|
||||
if (i >= 0)
|
||||
last_match = offset + s->sums[i].len;
|
||||
else
|
||||
last_match = offset;
|
||||
|
||||
if (buf && do_progress) {
|
||||
if (buf && do_progress)
|
||||
show_progress(last_match, buf->file_size);
|
||||
|
||||
if (i == -1)
|
||||
end_progress(buf->file_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,22 +121,22 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
OFF_T offset, end;
|
||||
unsigned int k;
|
||||
size_t last_i;
|
||||
int32 k, want_i, backup;
|
||||
char sum2[SUM_LENGTH];
|
||||
uint32 s1, s2, sum;
|
||||
int more;
|
||||
schar *map;
|
||||
|
||||
/* last_i is used to encourage adjacent matches, allowing the RLL coding of the
|
||||
output to work more efficiently */
|
||||
last_i = (size_t)-1;
|
||||
/* want_i is used to encourage adjacent matches, allowing the RLL
|
||||
* coding of the output to work more efficiently. */
|
||||
want_i = 0;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"hash search b=%u len=%.0f\n",
|
||||
s->blength, (double)len);
|
||||
rprintf(FINFO, "hash search b=%ld len=%.0f\n",
|
||||
(long)s->blength, (double)len);
|
||||
}
|
||||
|
||||
k = MIN(len, s->blength);
|
||||
k = (int32)MIN(len, (OFF_T)s->blength);
|
||||
|
||||
map = (schar *)map_ptr(buf, 0, k);
|
||||
|
||||
@@ -163,45 +144,54 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
s1 = sum & 0xFFFF;
|
||||
s2 = sum >> 16;
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "sum=%.8x k=%u\n", sum, k);
|
||||
rprintf(FINFO, "sum=%.8x k=%ld\n", sum, (long)k);
|
||||
|
||||
offset = 0;
|
||||
|
||||
end = len + 1 - s->sums[s->count-1].len;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "hash search s->blength=%u len=%.0f count=%.0f\n",
|
||||
s->blength, (double)len, (double)s->count);
|
||||
rprintf(FINFO, "hash search s->blength=%ld len=%.0f count=%.0f\n",
|
||||
(long)s->blength, (double)len, (double)s->count);
|
||||
}
|
||||
|
||||
do {
|
||||
tag t = gettag2(s1,s2);
|
||||
int done_csum2 = 0;
|
||||
size_t j = tag_table[t];
|
||||
int32 i;
|
||||
|
||||
if (verbose > 4)
|
||||
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
|
||||
if (verbose > 4) {
|
||||
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
|
||||
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
|
||||
}
|
||||
|
||||
if (j == NULL_TAG)
|
||||
goto null_tag;
|
||||
i = hash_table[SUM2HASH2(s1,s2)];
|
||||
if (i < 0)
|
||||
goto null_hash;
|
||||
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
tag_hits++;
|
||||
for (; j < s->count && targets[j].t == t; j++) {
|
||||
unsigned int l;
|
||||
size_t i = targets[j].i;
|
||||
hash_hits++;
|
||||
do {
|
||||
int32 l;
|
||||
|
||||
if (sum != s->sums[i].sum1)
|
||||
continue;
|
||||
|
||||
/* also make sure the two blocks are the same length */
|
||||
l = MIN((OFF_T)s->blength, len-offset);
|
||||
l = (int32)MIN((OFF_T)s->blength, len-offset);
|
||||
if (l != s->sums[i].len)
|
||||
continue;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n",
|
||||
(double)offset,(double)j,(double)i,sum);
|
||||
/* in-place: ensure chunk's offset is either >= our
|
||||
* offset or that the data didn't move. */
|
||||
if (updating_basis_file && s->sums[i].offset < offset
|
||||
&& !(s->sums[i].flags & SUMFLG_SAME_OFFSET))
|
||||
continue;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"potential match at %.0f i=%ld sum=%08x\n",
|
||||
(double)offset, (long)i, sum);
|
||||
}
|
||||
|
||||
if (!done_csum2) {
|
||||
map = (schar *)map_ptr(buf,offset,l);
|
||||
@@ -214,44 +204,70 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we've found a match, but now check to see
|
||||
* if last_i can hint at a better match */
|
||||
for (j++; j < s->count && targets[j].t == t; j++) {
|
||||
size_t i2 = targets[j].i;
|
||||
if (i2 == last_i + 1) {
|
||||
if (sum != s->sums[i2].sum1)
|
||||
break;
|
||||
if (memcmp(sum2,s->sums[i2].sum2,s->s2length) != 0)
|
||||
break;
|
||||
/* we've found an adjacent match - the RLL coder
|
||||
* will be happy */
|
||||
i = i2;
|
||||
break;
|
||||
/* When updating in-place, the best possible match is
|
||||
* one with an identical offset, so we prefer that over
|
||||
* the following want_i optimization. */
|
||||
if (updating_basis_file) {
|
||||
int32 i2;
|
||||
for (i2 = i; i2 >= 0; i2 = s->sums[i2].chain) {
|
||||
if (s->sums[i2].offset != offset)
|
||||
continue;
|
||||
if (i2 != i) {
|
||||
if (sum != s->sums[i2].sum1)
|
||||
break;
|
||||
if (memcmp(sum2, s->sums[i2].sum2,
|
||||
s->s2length) != 0)
|
||||
break;
|
||||
i = i2;
|
||||
}
|
||||
/* This chunk was at the same offset on
|
||||
* both the sender and the receiver. */
|
||||
s->sums[i].flags |= SUMFLG_SAME_OFFSET;
|
||||
goto set_want_i;
|
||||
}
|
||||
}
|
||||
|
||||
last_i = i;
|
||||
/* we've found a match, but now check to see
|
||||
* if want_i can hint at a better match. */
|
||||
if (i != want_i && want_i < s->count
|
||||
&& (!updating_basis_file || s->sums[want_i].offset >= offset
|
||||
|| s->sums[want_i].flags & SUMFLG_SAME_OFFSET)
|
||||
&& sum == s->sums[want_i].sum1
|
||||
&& memcmp(sum2, s->sums[want_i].sum2, s->s2length) == 0) {
|
||||
/* we've found an adjacent match - the RLL coder
|
||||
* will be happy */
|
||||
i = want_i;
|
||||
}
|
||||
set_want_i:
|
||||
want_i = i + 1;
|
||||
|
||||
matched(f,s,buf,offset,i);
|
||||
offset += s->sums[i].len - 1;
|
||||
k = MIN(s->blength, len-offset);
|
||||
k = (int32)MIN((OFF_T)s->blength, len-offset);
|
||||
map = (schar *)map_ptr(buf, offset, k);
|
||||
sum = get_checksum1((char *)map, k);
|
||||
s1 = sum & 0xFFFF;
|
||||
s2 = sum >> 16;
|
||||
matches++;
|
||||
break;
|
||||
}
|
||||
} while ((i = s->sums[i].chain) >= 0);
|
||||
|
||||
null_hash:
|
||||
backup = (int32)(offset - last_match);
|
||||
/* We sometimes read 1 byte prior to last_match... */
|
||||
if (backup < 0)
|
||||
backup = 0;
|
||||
|
||||
null_tag:
|
||||
/* Trim off the first byte from the checksum */
|
||||
map = (schar *)map_ptr(buf, offset, k+1);
|
||||
more = offset + k < len;
|
||||
map = (schar *)map_ptr(buf, offset - backup, k + more + backup)
|
||||
+ backup;
|
||||
s1 -= map[0] + CHAR_OFFSET;
|
||||
s2 -= k * (map[0]+CHAR_OFFSET);
|
||||
|
||||
/* Add on the next byte (if there is one) to the checksum */
|
||||
if (k < (len-offset)) {
|
||||
s1 += (map[k]+CHAR_OFFSET);
|
||||
if (more) {
|
||||
s1 += map[k] + CHAR_OFFSET;
|
||||
s2 += s1;
|
||||
} else
|
||||
--k;
|
||||
@@ -262,15 +278,12 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
match. The 3 reads are caused by the
|
||||
running match, the checksum update and the
|
||||
literal send. */
|
||||
if (offset > last_match
|
||||
&& offset-last_match >= CHUNK_SIZE+s->blength
|
||||
&& end-offset > CHUNK_SIZE) {
|
||||
matched(f,s,buf,offset - s->blength, -2);
|
||||
}
|
||||
if (backup >= s->blength+CHUNK_SIZE && end-offset > CHUNK_SIZE)
|
||||
matched(f, s, buf, offset - s->blength, -2);
|
||||
} while (++offset < end);
|
||||
|
||||
matched(f,s,buf,len,-1);
|
||||
map_ptr(buf,len-1,1);
|
||||
matched(f, s, buf, len, -1);
|
||||
map_ptr(buf, len-1, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -290,55 +303,70 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
**/
|
||||
void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
char file_sum[MD4_SUM_LENGTH];
|
||||
extern int write_batch;
|
||||
char file_sum[MAX_DIGEST_LEN];
|
||||
int sum_len;
|
||||
|
||||
last_match = 0;
|
||||
false_alarms = 0;
|
||||
tag_hits = 0;
|
||||
hash_hits = 0;
|
||||
matches = 0;
|
||||
data_transfer = 0;
|
||||
|
||||
sum_init();
|
||||
sum_init(checksum_seed);
|
||||
|
||||
if (len > 0 && s->count>0) {
|
||||
if (append_mode > 0) {
|
||||
if (append_mode == 2) {
|
||||
OFF_T j = 0;
|
||||
for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) {
|
||||
if (buf && do_progress)
|
||||
show_progress(last_match, buf->file_size);
|
||||
sum_update(map_ptr(buf, last_match, CHUNK_SIZE),
|
||||
CHUNK_SIZE);
|
||||
last_match = j;
|
||||
}
|
||||
if (last_match < s->flength) {
|
||||
int32 n = (int32)(s->flength - last_match);
|
||||
if (buf && do_progress)
|
||||
show_progress(last_match, buf->file_size);
|
||||
sum_update(map_ptr(buf, last_match, n), n);
|
||||
}
|
||||
}
|
||||
last_match = s->flength;
|
||||
s->count = 0;
|
||||
}
|
||||
|
||||
if (len > 0 && s->count > 0) {
|
||||
build_hash_table(s);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"built hash table\n");
|
||||
|
||||
hash_search(f,s,buf,len);
|
||||
hash_search(f, s, buf, len);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"done hash search\n");
|
||||
} else {
|
||||
OFF_T j;
|
||||
/* by doing this in pieces we avoid too many seeks */
|
||||
for (j = 0; j < len-CHUNK_SIZE; j += CHUNK_SIZE) {
|
||||
int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j);
|
||||
matched(f,s,buf,j+n1,-2);
|
||||
}
|
||||
matched(f,s,buf,len,-1);
|
||||
for (j = last_match + CHUNK_SIZE; j < len; j += CHUNK_SIZE)
|
||||
matched(f, s, buf, j, -2);
|
||||
matched(f, s, buf, len, -1);
|
||||
}
|
||||
|
||||
sum_end(file_sum);
|
||||
sum_len = sum_end(file_sum);
|
||||
/* If we had a read error, send a bad checksum. */
|
||||
if (buf && buf->status != 0)
|
||||
file_sum[0]++;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f,file_sum,MD4_SUM_LENGTH);
|
||||
if (write_batch)
|
||||
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
|
||||
|
||||
if (targets) {
|
||||
free(targets);
|
||||
targets=NULL;
|
||||
}
|
||||
write_buf(f, file_sum, sum_len);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
|
||||
false_alarms, tag_hits, matches);
|
||||
rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
|
||||
false_alarms, hash_hits, matches);
|
||||
|
||||
total_tag_hits += tag_hits;
|
||||
total_hash_hits += hash_hits;
|
||||
total_false_alarms += false_alarms;
|
||||
total_matches += matches;
|
||||
stats.literal_data += data_transfer;
|
||||
@@ -350,8 +378,7 @@ void match_report(void)
|
||||
return;
|
||||
|
||||
rprintf(FINFO,
|
||||
"total: matches=%d tag_hits=%d false_alarms=%d data=%.0f\n",
|
||||
total_matches,total_tag_hits,
|
||||
total_false_alarms,
|
||||
"total: matches=%d hash_hits=%d false_alarms=%d data=%.0f\n",
|
||||
total_matches, total_hash_hits, total_false_alarms,
|
||||
(double)stats.literal_data);
|
||||
}
|
||||
|
||||
@@ -54,15 +54,14 @@ BEGIN {
|
||||
printf "int %s(void);\n", a[2]
|
||||
}
|
||||
|
||||
/^static|^extern/ || !/^[a-zA-Z]/ || /[;]/ {
|
||||
/^static|^extern/ || /[;]/ {
|
||||
next;
|
||||
}
|
||||
|
||||
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^const/ {
|
||||
!/^[A-Za-z][A-Za-z0-9_]* / {
|
||||
next;
|
||||
}
|
||||
|
||||
|
||||
/[(].*[)][ \t]*$/ {
|
||||
printf "%s;\n",$0;
|
||||
next;
|
||||
@@ -73,4 +72,3 @@ BEGIN {
|
||||
printf "%s\n",$0;
|
||||
next;
|
||||
}
|
||||
|
||||
|
||||
66
mkrounding.c
Normal file
66
mkrounding.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* A pre-compilation helper program to aid in the creation of rounding.h.
|
||||
*
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
struct test1 {
|
||||
union file_extras extras1[1];
|
||||
struct {
|
||||
# include "mkrounding.h"
|
||||
} file;
|
||||
};
|
||||
|
||||
struct test2 {
|
||||
union file_extras extras2[2];
|
||||
struct {
|
||||
# include "mkrounding.h"
|
||||
} file;
|
||||
};
|
||||
|
||||
struct test4 {
|
||||
union file_extras extras4[4];
|
||||
struct {
|
||||
# include "mkrounding.h"
|
||||
} file;
|
||||
};
|
||||
|
||||
#define SIZE_TEST(n) (sizeof (struct test ## n) == EXTRA_LEN * n + sizeof (struct file_struct))
|
||||
|
||||
int main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
{
|
||||
int cnt;
|
||||
if (SIZE_TEST(1))
|
||||
cnt = 0;
|
||||
else if (SIZE_TEST(2))
|
||||
cnt = 1;
|
||||
else if (SIZE_TEST(4))
|
||||
cnt = 3;
|
||||
else {
|
||||
fprintf(stderr, "Unable to determine required file_extras rounding!\n");
|
||||
cnt = 3;
|
||||
}
|
||||
if (cnt)
|
||||
fprintf(stderr, "Rounding file_extras in multiples of %d", cnt + 1);
|
||||
else
|
||||
fprintf(stderr, "No rounding needed for file_extras");
|
||||
fprintf(stderr, " (EXTRA_LEN=%d, FILE_STRUCT_LEN=%d)\n",
|
||||
(int)EXTRA_LEN, (int)FILE_STRUCT_LEN);
|
||||
printf("#define EXTRA_ROUNDING %d\n", cnt);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,24 +1,46 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Summary: A program for synchronizing files over a network.
|
||||
Name: rsync
|
||||
Version: 2.6.2
|
||||
Version: 3.0.0pre2
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-%{version}.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
Group: Applications/Internet
|
||||
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz
|
||||
URL: http://rsync.samba.org/
|
||||
|
||||
Prefix: %{_prefix}
|
||||
BuildRoot: /var/tmp/%{name}-root
|
||||
License: GPL
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
Rsync uses a reliable algorithm to bring remote and host files into
|
||||
sync very quickly. Rsync is fast because it just sends the differences
|
||||
in the files over the network instead of sending the complete
|
||||
files. Rsync is often used as a very powerful mirroring process or
|
||||
just as a more capable replacement for the rcp command. A technical
|
||||
report which describes the rsync algorithm is included in this
|
||||
package.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
%build
|
||||
%configure
|
||||
|
||||
make
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%makeinstall
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc COPYING README tech_report.tex
|
||||
%{_prefix}/bin/rsync
|
||||
%{_mandir}/man1/rsync.1*
|
||||
%{_mandir}/man5/rsyncd.conf.5*
|
||||
|
||||
%changelog
|
||||
* Thu Jan 30 2003 Horst von Brand <vonbrand@inf.utfsm.cl>
|
||||
@@ -64,30 +86,3 @@ to '%build', removed '%prefix'.
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr --mandir=%{_mandir}
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man{1,5}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) %{_mandir}/man1/rsync.1*
|
||||
%attr(-,root,root) %{_mandir}/man5/rsyncd.conf.5*
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
%attr(-,root,root) %doc doc/README-SGML doc/rsync.sgml
|
||||
|
||||
130
packaging/nightly-rsync
Executable file
130
packaging/nightly-rsync
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
|
||||
# copy of the /home/ftp/pub/rsync dir on samba.org. It also requires a
|
||||
# pristine CVS checkout of rsync (don't use your normal rsync build dir
|
||||
# unless you're 100% sure that there are not unchecked-in changes).
|
||||
#
|
||||
# If this is run with -ctu, it will make an updated "nightly" tar file in
|
||||
# the nightly dir. It will also remove any old tar files, regenerate the
|
||||
# HTML man pages in the nightly dir, and then rsync the changes to the
|
||||
# samba.org server.
|
||||
|
||||
use Getopt::Long;
|
||||
use Date::Format;
|
||||
|
||||
# Choose any dir where a pristine rsync has been checked out of CVS.
|
||||
our $unpacked = $ENV{HOME} . '/release/nightly';
|
||||
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
|
||||
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
|
||||
our $nightly_symlink = "$nightly/rsync-HEAD.tar.gz";
|
||||
|
||||
our($cvs_update, $make_tar, $upload, $help_opt);
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'cvs-update|c' => \$cvs_update,
|
||||
'make-tar|t' => \$make_tar,
|
||||
'upload|u' => \$upload,
|
||||
'help|h' => \$help_opt,
|
||||
) || $help_opt;
|
||||
|
||||
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
|
||||
our $ztoday = time2str('%d %b %Y', time);
|
||||
our $today = $ztoday;
|
||||
|
||||
chdir($unpacked) or die $!;
|
||||
|
||||
if ($cvs_update) {
|
||||
print "Updating from cvs...\n";
|
||||
system 'cvs -q up' and die $!;
|
||||
}
|
||||
|
||||
if ($make_tar) {
|
||||
print "Generating list of active CVS files...\n";
|
||||
my($dir, @files);
|
||||
open(CVS, '-|', 'cvs status 2>&1') or die $!;
|
||||
while (<CVS>) {
|
||||
if (/^cvs status: Examining (.*)/) {
|
||||
if ($1 eq '.') {
|
||||
$dir = '';
|
||||
} else {
|
||||
push(@files, $1);
|
||||
$dir = $1 . '/';
|
||||
}
|
||||
} elsif (/^File: (.*?)\s+Status: (.*)/ && $1 ne '.cvsignore') {
|
||||
push(@files, $dir . $1);
|
||||
if ($2 ne 'Up-to-date') {
|
||||
print "*** Not up-to-date: $dir$1\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
close CVS;
|
||||
|
||||
print "Creating $unpacked/$name.tar.gz\n";
|
||||
chdir('..') or die $!;
|
||||
rename($unpacked, $name) or die $!;
|
||||
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g-w -czf $nightly/$name.tar.gz $name") or die $!;
|
||||
foreach (@files) {
|
||||
print TAR "$name/$_\n";
|
||||
}
|
||||
close TAR;
|
||||
rename($name, $unpacked) or die $!;
|
||||
unlink($nightly_symlink);
|
||||
symlink("$name.tar.gz", $nightly_symlink);
|
||||
}
|
||||
|
||||
chdir($nightly) or die $!;
|
||||
|
||||
foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
|
||||
my $html_fn = $fn;
|
||||
$html_fn =~ s/\.yo/.html/;
|
||||
|
||||
open(IN, '<', "$unpacked/$fn") or die $!;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
|
||||
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
|
||||
#s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
|
||||
|
||||
open(OUT, '>', $fn) or die $!;
|
||||
print OUT $_;
|
||||
close OUT;
|
||||
|
||||
system "yodl2html -o $html_fn $fn";
|
||||
|
||||
unlink($fn);
|
||||
}
|
||||
|
||||
my $cnt = 0;
|
||||
open(PIPE, '-|', 'ls -1t rsync-HEAD-*') or die $!;
|
||||
while (<PIPE>) {
|
||||
chomp;
|
||||
next if $cnt++ < 10;
|
||||
unlink($_);
|
||||
}
|
||||
close PIPE;
|
||||
|
||||
system 'ls -ltr';
|
||||
|
||||
if ($upload) {
|
||||
my $opt = '';
|
||||
if (defined $ENV{RSYNC_PARTIAL_DIR}) {
|
||||
$opt = " -f 'R $ENV{RSYNC_PARTIAL_DIR}'";
|
||||
}
|
||||
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/nightly";
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: nightly-rsync [OPTIONS]
|
||||
|
||||
-c, --cvs-update update $unpacked via CVS.
|
||||
-t, --make-tar create a new tar file in $nightly
|
||||
-u, --upload upload the revised nightly dir to samba.org
|
||||
-h, --help display this help
|
||||
EOT
|
||||
}
|
||||
328
packaging/release-rsync
Executable file
328
packaging/release-rsync
Executable file
@@ -0,0 +1,328 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to
|
||||
# be a copy of the /home/ftp/pub/rsync dir on samba.org. If it is run
|
||||
# in test mode, it instead expects a dir named ~/tmp/samba-rsync-ftp
|
||||
# (e.g. copy ~/samba-rsync-ftp into ~/tmp and you can do a trial-run of
|
||||
# a release without affecting the files in the ~/samba-rsync-ftp dir).
|
||||
#
|
||||
# Run this as "release-rsync live" to affect ~/samba-rsync-ftp instead
|
||||
# of ~/tmp/samba-rsync-ftp.
|
||||
|
||||
use Date::Format;
|
||||
|
||||
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
|
||||
my $releasedir = $ENV{HOME} . '/release';
|
||||
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
|
||||
|
||||
my $ztoday = time2str('%d %b %Y', time);
|
||||
my $today = $ztoday;
|
||||
$today =~ s/^0//;
|
||||
|
||||
my $break = <<EOT;
|
||||
==========================================================================
|
||||
EOT
|
||||
my $note = <<EOT;
|
||||
== Note: type "-a u,n" if you want to auto-accept the U,N suggestions. ==
|
||||
EOT
|
||||
|
||||
my $live = shift;
|
||||
my $skipping = '';
|
||||
|
||||
print $break;
|
||||
if ($live) {
|
||||
print <<EOT;
|
||||
== This will release a new version of rsync onto an unsuspecting world. ==
|
||||
EOT
|
||||
} else {
|
||||
print <<EOT;
|
||||
== **** TESTMODE **** (Add "live" arg to avoid this.) ==
|
||||
EOT
|
||||
$dest =~ s#([^/]+$)#tmp/$1#;
|
||||
$skipping = ' ** SKIPPING **';
|
||||
}
|
||||
die "$dest does not exist\n" unless -d $dest;
|
||||
|
||||
print $break, "\nChecking out the latest rsync into $releasedir ...\n";
|
||||
|
||||
mkdir($releasedir, 0755) or die $! unless -d $releasedir;
|
||||
chdir($releasedir) or die $!;
|
||||
|
||||
system 'rm -rf rsync';
|
||||
|
||||
my(%dirs, @files);
|
||||
open(CVS, '-|', 'cvs checkout -P rsync') or die $!;
|
||||
while (<CVS>) {
|
||||
print $_;
|
||||
next if /\.(cvs)?ignore$/;
|
||||
if (m#^[UP] rsync/(.*)#) {
|
||||
my $fn = $1;
|
||||
my($dir) = $fn =~ m#^(.+)/#;
|
||||
push(@files, $dir) if defined($dir) && !$dirs{$1}++;
|
||||
push(@files, $fn);
|
||||
}
|
||||
}
|
||||
|
||||
chdir('rsync') or die $!;
|
||||
|
||||
my($version, $lastversion);
|
||||
open(IN, '<', 'configure.in') or die $!;
|
||||
while (<IN>) {
|
||||
if (/^RSYNC_VERSION=(.*)/) {
|
||||
$version = $lastversion = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
if ($lastversion =~ /cvs$/) {
|
||||
open(IN, '<', 'OLDNEWS') or die $!;
|
||||
$_ = <IN>;
|
||||
close IN;
|
||||
($lastversion) = /(\d+\.\d+\.\d+)/;
|
||||
}
|
||||
|
||||
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
|
||||
|
||||
print $break, "\nPlease enter the version number of this release: [$version] ";
|
||||
chomp($_ = <STDIN>);
|
||||
if ($_ eq '.') {
|
||||
$version =~ s/pre\d+//;
|
||||
} elsif ($_ ne '') {
|
||||
$version = $_;
|
||||
}
|
||||
$version =~ s/[-.]*pre[-.]*/pre/;
|
||||
|
||||
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
|
||||
|
||||
my $cvstag = "release-$version";
|
||||
$cvstag =~ s/[.]/-/g;
|
||||
$cvstag =~ s/pre/-pre/;
|
||||
|
||||
print "Enter the previous version to produce a patch against: [$lastversion] ";
|
||||
chomp($_ = <STDIN>);
|
||||
$lastversion = $_ if $_ ne '';
|
||||
$lastversion =~ s/[-.]*pre[-.]*/pre/;
|
||||
|
||||
my $release = 1;
|
||||
print "Please enter the RPM release number of this release: [$release] ";
|
||||
chomp($_ = <STDIN>);
|
||||
$release = $_ if $_ ne '';
|
||||
|
||||
my $diffdir;
|
||||
my $skipping2;
|
||||
if ($lastversion =~ /pre/) {
|
||||
if ($version !~ /pre/) {
|
||||
die "You should not diff a release version against a pre-release version.\n";
|
||||
}
|
||||
$diffdir = "$dest/old-previews";
|
||||
$skipping2 = ' ** SKIPPING **';
|
||||
} elsif ($version =~ /pre/) {
|
||||
$diffdir = $dest;
|
||||
$skipping2 = ' ** SKIPPING **';
|
||||
} else {
|
||||
$diffdir = "$dest/old-versions";
|
||||
$skipping2 = '';
|
||||
}
|
||||
|
||||
print "\n", $break, <<EOT;
|
||||
\$version is "$version"
|
||||
\$lastversion is "$lastversion"
|
||||
\$cvstag is "$cvstag"
|
||||
\$dest is "$dest"
|
||||
\$releasedir is "$releasedir"
|
||||
\$diffdir is "$diffdir"
|
||||
\$release is "$release"
|
||||
|
||||
About to:
|
||||
- make sure that SUBPROTOCOL_VERSION is 0$skipping2
|
||||
- tweak the version in configure.in, configure, and the spec files
|
||||
- make sure that configure, config.h.in, and proto.h are updated
|
||||
- tweak NEWS and OLDNEWS to update the release date$skipping2
|
||||
- tweak the date in the *.yo files and re-generate the man pages
|
||||
- make sure that the patches dir has been updated
|
||||
- page through the "cvs diff" output
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
my $f_opt = /f/ ? ' -f' : '';
|
||||
|
||||
print $break;
|
||||
system "./prepare-source && touch proto.h";
|
||||
|
||||
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
|
||||
glob('*.yo'), qw( configure.in configure ) );
|
||||
if ($version !~ /pre/) {
|
||||
push(@tweak_files, qw( rsync.h NEWS OLDNEWS ));
|
||||
}
|
||||
foreach my $fn (@tweak_files) {
|
||||
open(IN, '<', $fn) or die $!;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
if ($fn =~ /configure/) {
|
||||
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m;
|
||||
} elsif ($fn =~ /\.spec/) {
|
||||
s/^(Version:) .*/$1 $version/m;
|
||||
s/^(Release:) .*/$1 $release/m;
|
||||
} elsif ($fn =~ /\.yo/) {
|
||||
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
|
||||
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
|
||||
} elsif ($fn eq 'NEWS') {
|
||||
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
|
||||
or die "Couldn't update NEWS file with release date!\n";
|
||||
} elsif ($fn eq 'rsync.h') {
|
||||
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/;
|
||||
} elsif ($fn eq 'OLDNEWS') {
|
||||
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m
|
||||
or die "Couldn't update OLDNEWS file with release date!\n";
|
||||
} else {
|
||||
die "Unrecognized file in \@tweak_files: $fn\n";
|
||||
}
|
||||
open(OUT, '>', $fn) or die $!;
|
||||
print OUT $_;
|
||||
close OUT;
|
||||
}
|
||||
|
||||
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage rsync.1";
|
||||
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage rsyncd.conf.5";
|
||||
|
||||
mkdir('patches/tmp') or die $!;
|
||||
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";
|
||||
|
||||
print "\n", $break, $note, $break;
|
||||
system "patches/verify-patches -n -an$f_opt";
|
||||
|
||||
print $break;
|
||||
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
About to:
|
||||
- "cvs commit" all changes$skipping
|
||||
- "cvs tag" this release as $cvstag$skipping
|
||||
- change the diffs in the patches dir to include generated files
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
|
||||
if ($live) {
|
||||
system "cvs commit -m 'Preparing for release of $version'";
|
||||
system "cvs tag -F $cvstag .";
|
||||
}
|
||||
|
||||
if (!/skip/i) {
|
||||
print "\n", $break, $note, $break;
|
||||
system "patches/verify-patches -pun -an";
|
||||
}
|
||||
|
||||
my $tar_name = "rsync-$version.tar.gz";
|
||||
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
|
||||
my $tar_file = "$dest/$tar_name";
|
||||
my $diff_file = "$dest/$diff_name";
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
About to do the following in the samba-rsync-ftp dir:
|
||||
- move the old tar/diff files into the appropriate old-* dirs
|
||||
- hard-link the moved tar/diff files on samba.org$skipping
|
||||
- create release tar, "$tar_name"
|
||||
- create release diffs, "$diff_name"
|
||||
- update README, *NEWS, TODO, and cvs.log
|
||||
- update rsync*.html man pages
|
||||
- gpg-sign the release files$skipping
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
|
||||
chdir($releasedir) or die $!;
|
||||
|
||||
print $break;
|
||||
system "rm -rf rsync-$version";
|
||||
rename('rsync', "rsync-$version") or die $!;
|
||||
|
||||
# When creating a pre-release after a normal release, there's nothing to move.
|
||||
if ($diffdir ne $dest) {
|
||||
chdir($dest) or die $!;
|
||||
|
||||
print "Shuffling old files ...\n";
|
||||
|
||||
# We need to run this regardless of $lastversion's "pre"ness.
|
||||
my @moved_files;
|
||||
foreach my $fn (glob('rsync*pre*.tar.gz*'), glob('rsync*pre*-NEWS')) {
|
||||
link($fn, "old-previews/$fn") or die $!;
|
||||
push(@moved_files, $fn);
|
||||
}
|
||||
|
||||
if ($version !~ /pre/) {
|
||||
foreach my $fn (glob('rsync*.tar.gz*'), glob('rsync*-NEWS')) {
|
||||
next if $fn =~ /^rsync.*pre/;
|
||||
link($fn, "old-versions/$fn") or die $!;
|
||||
push(@moved_files, $fn);
|
||||
}
|
||||
|
||||
foreach my $fn (glob('rsync*pre*.diffs.gz*')) {
|
||||
unlink($fn);
|
||||
}
|
||||
|
||||
foreach my $fn (glob('rsync*.diffs.gz*')) {
|
||||
link($fn, "old-patches/$fn") or die $!;
|
||||
push(@moved_files, $fn);
|
||||
}
|
||||
}
|
||||
|
||||
# Optimize our future upload (in the absence of --detect-renamed) by
|
||||
# using rsync to hard-link the above files on samba.org.
|
||||
if ($live) {
|
||||
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
|
||||
}
|
||||
foreach (@moved_files) {
|
||||
unlink($_);
|
||||
}
|
||||
|
||||
chdir($releasedir) or die $!;
|
||||
}
|
||||
|
||||
print "Creating $tar_file ...\n";
|
||||
system "fakeroot tar czf $tar_file rsync-$version";
|
||||
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g+w -czf $tar_file rsync-$version") or die $!;
|
||||
foreach (@files) {
|
||||
print TAR "rsync-$version/$_\n";
|
||||
}
|
||||
close TAR;
|
||||
|
||||
print "Creating $diff_file ...\n";
|
||||
system "rm -rf rsync-$version rsync-$lastversion";
|
||||
system "tar xzf $tar_file; tar xzf $diffdir/rsync-$lastversion.tar.gz";
|
||||
## TWEAK THE VERSIONS AS DESIRED HERE ##
|
||||
#mkdir("rsync-$lastversion/support", 0755) or die $!;
|
||||
#rename("rsync-$lastversion/rsyncstats", "rsync-$lastversion/support/rsyncstats");
|
||||
#unlink("rsync-$lastversion/.ignore");
|
||||
## END ##
|
||||
system "diff -urN --exclude=patches rsync-$lastversion rsync-$version| gzip -9 >$diff_file";
|
||||
|
||||
print "Updating the other files in $dest ...\n";
|
||||
system "rsync -a rsync-$version/{README,NEWS,OLDNEWS,TODO} $dest";
|
||||
unlink("$dest/rsync-$version-NEWS");
|
||||
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
|
||||
system "rsync -a $cvsroot/CVSROOT/rsync.updates $dest/cvs.log";
|
||||
|
||||
system "yodl2html -o $dest/rsync.html rsync-$version/rsync.yo";
|
||||
system "yodl2html -o $dest/rsyncd.conf.html rsync-$version/rsyncd.conf.yo";
|
||||
|
||||
system "rm -rf rsync-*";
|
||||
|
||||
if ($live) {
|
||||
chdir($dest) or die $!;
|
||||
system "gpg -ba $tar_name; gpg -ba $diff_name";
|
||||
print $break, <<EOT;
|
||||
|
||||
All done. Remember to announce the release on *BOTH*
|
||||
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
|
||||
EOT
|
||||
} else {
|
||||
print $break, "All done.\n";
|
||||
}
|
||||
27
params.c
27
params.c
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
This modules is based on the params.c module from Samba, written by Karl Auer
|
||||
and much modifed by Christopher Hertel.
|
||||
/* This modules is based on the params.c module from Samba, written by Karl Auer
|
||||
and much modifed by Christopher Hertel. */
|
||||
|
||||
/*
|
||||
* 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 of the License, or
|
||||
* 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,
|
||||
@@ -12,11 +12,11 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* -------------------------------------------------------------------------- **
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------------------- **
|
||||
*
|
||||
* Module name: params
|
||||
*
|
||||
@@ -74,6 +74,7 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- **
|
||||
* Constants...
|
||||
@@ -164,7 +165,7 @@ static int Continuation( char *line, int pos )
|
||||
*/
|
||||
{
|
||||
pos--;
|
||||
while( (pos >= 0) && isspace(((unsigned char *)line)[pos]) )
|
||||
while( pos >= 0 && isSpace(line + pos) )
|
||||
pos--;
|
||||
|
||||
return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
|
||||
@@ -386,7 +387,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
c = 0;
|
||||
else
|
||||
{
|
||||
for( end = i; (end >= 0) && isspace(((unsigned char *) bufr)[end]); end-- )
|
||||
for( end = i; end >= 0 && isSpace(bufr + end); end-- )
|
||||
;
|
||||
c = getc( InFile );
|
||||
}
|
||||
@@ -491,8 +492,8 @@ static FILE *OpenConfFile( char *FileName )
|
||||
OpenedFile = fopen( FileName, "r" );
|
||||
if( NULL == OpenedFile )
|
||||
{
|
||||
rprintf(FERROR,"rsync: unable to open configuration file \"%s\": %s\n",
|
||||
FileName, strerror(errno));
|
||||
rsyserr(FERROR, errno, "unable to open configuration file \"%s\"",
|
||||
FileName);
|
||||
}
|
||||
|
||||
return( OpenedFile );
|
||||
|
||||
107
pipe.c
107
pipe.c
@@ -1,22 +1,23 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
/*
|
||||
* Routines used to setup various kinds of inter-process pipes.
|
||||
*
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
*
|
||||
* 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 of the License, or
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
@@ -24,15 +25,16 @@
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int blocking_io;
|
||||
extern int orig_umask;
|
||||
extern int read_batch;
|
||||
extern int filesfrom_fd;
|
||||
extern mode_t orig_umask;
|
||||
extern char *logfile_name;
|
||||
extern struct chmod_mode_struct *chmod_modes;
|
||||
|
||||
/**
|
||||
* Create a child connected to use on stdin/stdout.
|
||||
* Create a child connected to us via its stdin/stdout.
|
||||
*
|
||||
* This is derived from CVS code
|
||||
*
|
||||
* This is derived from CVS code
|
||||
*
|
||||
* Note that in the child STDIN is set to blocking and STDOUT
|
||||
* is set to non-blocking. This is necessary as rsh relies on stdin being blocking
|
||||
* and ssh relies on stdout being non-blocking
|
||||
@@ -46,20 +48,18 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
pid_t pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
|
||||
if (verbose >= 2) {
|
||||
print_child_argv(command);
|
||||
}
|
||||
|
||||
if (verbose >= 2)
|
||||
print_child_argv("opening connection using:", command);
|
||||
|
||||
if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
|
||||
rprintf(FERROR, "pipe: %s\n", strerror(errno));
|
||||
rsyserr(FERROR, errno, "pipe");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
rprintf(FERROR, "fork: %s\n", strerror(errno));
|
||||
rsyserr(FERROR, errno, "fork");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
@@ -68,8 +68,7 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
|
||||
rprintf(FERROR, "Failed to dup/close : %s\n",
|
||||
strerror(errno));
|
||||
rsyserr(FERROR, errno, "Failed to dup/close");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
if (to_child_pipe[0] != STDIN_FILENO)
|
||||
@@ -81,13 +80,12 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
if (blocking_io > 0)
|
||||
set_blocking(STDOUT_FILENO);
|
||||
execvp(command[0], command);
|
||||
rprintf(FERROR, "Failed to exec %s : %s\n",
|
||||
command[0], strerror(errno));
|
||||
rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
|
||||
rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
|
||||
rsyserr(FERROR, errno, "Failed to close");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
@@ -97,56 +95,75 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
return pid;
|
||||
}
|
||||
|
||||
pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
|
||||
/* This function forks a child which calls child_main(). First,
|
||||
* however, it has to establish communication paths to and from the
|
||||
* newborn child. It creates two socket pairs -- one for writing to
|
||||
* the child (from the parent) and one for reading from the child
|
||||
* (writing to the parent). Since that's four socket ends, each
|
||||
* process has to close the two ends it doesn't need. The remaining
|
||||
* two socket ends are retained for reading and writing. In the
|
||||
* child, the STDIN and STDOUT file descriptors refer to these
|
||||
* sockets. In the parent, the function arguments f_in and f_out are
|
||||
* set to refer to these sockets. */
|
||||
pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
|
||||
int (*child_main)(int, char*[]))
|
||||
{
|
||||
pid_t pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
|
||||
/* The parent process is always the sender for a local rsync. */
|
||||
assert(am_sender);
|
||||
|
||||
if (fd_pair(to_child_pipe) < 0 ||
|
||||
fd_pair(from_child_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe: %s\n",strerror(errno));
|
||||
rsyserr(FERROR, errno, "pipe");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
rprintf(FERROR,"fork: %s\n",strerror(errno));
|
||||
rsyserr(FERROR, errno, "fork");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
am_sender = read_batch ? 0 : !am_sender;
|
||||
am_server = 1;
|
||||
|
||||
if (!am_sender)
|
||||
filesfrom_fd = -1;
|
||||
am_sender = 0;
|
||||
am_server = 1;
|
||||
filesfrom_fd = -1;
|
||||
chmod_modes = NULL; /* Let the sending side handle this. */
|
||||
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
|
||||
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
|
||||
rsyserr(FERROR, errno, "Failed to dup/close");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
|
||||
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
|
||||
if (to_child_pipe[0] != STDIN_FILENO)
|
||||
close(to_child_pipe[0]);
|
||||
if (from_child_pipe[1] != STDOUT_FILENO)
|
||||
close(from_child_pipe[1]);
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
child_main(argc, argv);
|
||||
}
|
||||
|
||||
if (!am_sender)
|
||||
filesfrom_fd = -1;
|
||||
/* Let the client side handle this. */
|
||||
if (logfile_name) {
|
||||
logfile_name = NULL;
|
||||
logfile_close();
|
||||
}
|
||||
|
||||
if (close(from_child_pipe[1]) < 0 ||
|
||||
close(to_child_pipe[0]) < 0) {
|
||||
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
|
||||
rsyserr(FERROR, errno, "Failed to close");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
*f_in = from_child_pipe[0];
|
||||
*f_out = to_child_pipe[1];
|
||||
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
@@ -2,18 +2,20 @@
|
||||
* \file popt/findme.c
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#include "system.h"
|
||||
#include "findme.h"
|
||||
|
||||
const char * findProgramPath(const char * argv0) {
|
||||
const char * findProgramPath(const char * argv0)
|
||||
{
|
||||
char * path = getenv("PATH");
|
||||
char * pathbuf;
|
||||
char * start, * chptr;
|
||||
char * buf;
|
||||
size_t bufsize;
|
||||
|
||||
if (argv0 == NULL) return NULL; /* XXX can't happen */
|
||||
/* If there is a / in the argv[0], it has to be an absolute path */
|
||||
@@ -22,17 +24,20 @@ const char * findProgramPath(const char * argv0) {
|
||||
|
||||
if (path == NULL) return NULL;
|
||||
|
||||
start = pathbuf = alloca(strlen(path) + 1);
|
||||
buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
|
||||
bufsize = strlen(path) + 1;
|
||||
start = pathbuf = alloca(bufsize);
|
||||
if (pathbuf == NULL) return NULL; /* XXX can't happen */
|
||||
strlcpy(pathbuf, path, bufsize);
|
||||
bufsize += sizeof "/" - 1 + strlen(argv0);
|
||||
buf = malloc(bufsize);
|
||||
if (buf == NULL) return NULL; /* XXX can't happen */
|
||||
strcpy(pathbuf, path);
|
||||
|
||||
chptr = NULL;
|
||||
/*@-branchstate@*/
|
||||
do {
|
||||
if ((chptr = strchr(start, ':')))
|
||||
*chptr = '\0';
|
||||
sprintf(buf, "%s/%s", start, argv0);
|
||||
snprintf(buf, bufsize, "%s/%s", start, argv0);
|
||||
|
||||
if (!access(buf, X_OK))
|
||||
return buf;
|
||||
|
||||
207
popt/popt.c
207
popt/popt.c
@@ -2,7 +2,7 @@
|
||||
* \file popt/popt.c
|
||||
*/
|
||||
|
||||
/* (C) 19982000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist */
|
||||
|
||||
@@ -18,8 +18,18 @@
|
||||
#include "findme.h"
|
||||
#include "poptint.h"
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
static char * strerror(int errno) {
|
||||
#ifndef DBL_EPSILON
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#endif
|
||||
|
||||
#ifdef MYDEBUG
|
||||
/*@unchecked@*/
|
||||
int _popt_debug = 0;
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
|
||||
static char * strerror(int errno)
|
||||
{
|
||||
extern int sys_nerr;
|
||||
extern char * sys_errlist[];
|
||||
|
||||
@@ -31,7 +41,8 @@ static char * strerror(int errno) {
|
||||
#endif
|
||||
|
||||
#ifdef MYDEBUG
|
||||
/*@unused@*/ static void prtcon(const char *msg, poptContext con)
|
||||
/*@unused@*/
|
||||
static void prtcon(const char *msg, poptContext con)
|
||||
{
|
||||
if (msg) fprintf(stderr, "%s", msg);
|
||||
fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
|
||||
@@ -49,7 +60,7 @@ void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
|
||||
con->execPath = _free(con->execPath);
|
||||
con->execPath = xstrdup(path);
|
||||
con->execAbsolute = allowAbsolute;
|
||||
/*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
|
||||
/*@-nullstate@*/ /* LCL: con->execPath not NULL */
|
||||
return;
|
||||
/*@=nullstate@*/
|
||||
}
|
||||
@@ -62,17 +73,22 @@ static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
|
||||
for (; opt->longName || opt->shortName || opt->arg; opt++) {
|
||||
if (opt->arg == NULL) continue; /* XXX program error. */
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
|
||||
void * arg = opt->arg;
|
||||
/*@-branchstate@*/
|
||||
/* XXX sick hack to preserve pretense of ABI. */
|
||||
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
|
||||
/*@=branchstate@*/
|
||||
/* Recurse on included sub-tables. */
|
||||
invokeCallbacksPRE(con, opt->arg);
|
||||
invokeCallbacksPRE(con, arg);
|
||||
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
|
||||
(opt->argInfo & POPT_CBFLAG_PRE))
|
||||
{ /*@-castfcnptr@*/
|
||||
poptCallbackType cb = (poptCallbackType)opt->arg;
|
||||
/*@=castfcnptr@*/
|
||||
/* Perform callback. */
|
||||
/*@-moduncon -noeffectuncon @*/
|
||||
/*@-noeffectuncon @*/
|
||||
cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
|
||||
/*@=moduncon =noeffectuncon @*/
|
||||
/*@=noeffectuncon @*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,17 +101,22 @@ static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
|
||||
for (; opt->longName || opt->shortName || opt->arg; opt++) {
|
||||
if (opt->arg == NULL) continue; /* XXX program error. */
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
|
||||
void * arg = opt->arg;
|
||||
/*@-branchstate@*/
|
||||
/* XXX sick hack to preserve pretense of ABI. */
|
||||
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
|
||||
/*@=branchstate@*/
|
||||
/* Recurse on included sub-tables. */
|
||||
invokeCallbacksPOST(con, opt->arg);
|
||||
invokeCallbacksPOST(con, arg);
|
||||
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
|
||||
(opt->argInfo & POPT_CBFLAG_POST))
|
||||
{ /*@-castfcnptr@*/
|
||||
poptCallbackType cb = (poptCallbackType)opt->arg;
|
||||
/*@=castfcnptr@*/
|
||||
/* Perform callback. */
|
||||
/*@-moduncon -noeffectuncon @*/
|
||||
/*@-noeffectuncon @*/
|
||||
cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
|
||||
/*@=moduncon =noeffectuncon @*/
|
||||
/*@=noeffectuncon @*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,6 +133,11 @@ static void invokeCallbacksOPTION(poptContext con,
|
||||
if (opt != NULL)
|
||||
for (; opt->longName || opt->shortName || opt->arg; opt++) {
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
|
||||
void * arg = opt->arg;
|
||||
/*@-branchstate@*/
|
||||
/* XXX sick hack to preserve pretense of ABI. */
|
||||
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
|
||||
/*@=branchstate@*/
|
||||
/* Recurse on included sub-tables. */
|
||||
if (opt->arg != NULL) /* XXX program error */
|
||||
invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
|
||||
@@ -133,10 +159,10 @@ static void invokeCallbacksOPTION(poptContext con,
|
||||
const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
|
||||
/* Perform callback. */
|
||||
if (cb != NULL) { /* XXX program error */
|
||||
/*@-moduncon -noeffectuncon @*/
|
||||
/*@-noeffectuncon @*/
|
||||
cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
|
||||
con->os->nextArg, cbData);
|
||||
/*@=moduncon =noeffectuncon @*/
|
||||
/*@=noeffectuncon @*/
|
||||
}
|
||||
/* Terminate (unless explcitly continuing). */
|
||||
if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
|
||||
@@ -181,8 +207,12 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
|
||||
con->flags |= POPT_CONTEXT_POSIXMEHARDER;
|
||||
|
||||
if (name) {
|
||||
char * t = malloc(strlen(name) + 1);
|
||||
if (t) con->appName = strcpy(t, name);
|
||||
size_t bufsize = strlen(name) + 1;
|
||||
char * t = malloc(bufsize);
|
||||
if (t) {
|
||||
strlcpy(t, name, bufsize);
|
||||
con->appName = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*@-internalglobs@*/
|
||||
@@ -202,6 +232,7 @@ static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
|
||||
os->argb = PBM_FREE(os->argb);
|
||||
}
|
||||
|
||||
/*@-boundswrite@*/
|
||||
void poptResetContext(poptContext con)
|
||||
{
|
||||
int i;
|
||||
@@ -222,10 +253,11 @@ void poptResetContext(poptContext con)
|
||||
con->doExec = NULL;
|
||||
|
||||
if (con->finalArgv != NULL)
|
||||
for (i = 0; i < con->finalArgvCount; i++)
|
||||
for (i = 0; i < con->finalArgvCount; i++) {
|
||||
/*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
|
||||
con->finalArgv[i] = _free(con->finalArgv[i]);
|
||||
/*@=unqualifiedtrans@*/
|
||||
}
|
||||
|
||||
con->finalArgvCount = 0;
|
||||
con->arg_strip = PBM_FREE(con->arg_strip);
|
||||
@@ -233,8 +265,10 @@ void poptResetContext(poptContext con)
|
||||
return;
|
||||
/*@=nullstate@*/
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
/* Only one of longName, shortName should be set, not both. */
|
||||
/*@-boundswrite@*/
|
||||
static int handleExec(/*@special@*/ poptContext con,
|
||||
/*@null@*/ const char * longName, char shortName)
|
||||
/*@uses con->execs, con->numExecs, con->flags, con->doExec,
|
||||
@@ -277,12 +311,13 @@ static int handleExec(/*@special@*/ poptContext con,
|
||||
|
||||
i = con->finalArgvCount++;
|
||||
if (con->finalArgv != NULL) /* XXX can't happen */
|
||||
{ char *s = malloc((longName ? strlen(longName) : 0) + 3);
|
||||
{ size_t bufsize = (longName ? strlen(longName) : 0) + 3;
|
||||
char *s = malloc(bufsize);
|
||||
if (s != NULL) { /* XXX can't happen */
|
||||
if (longName)
|
||||
sprintf(s, "--%s", longName);
|
||||
snprintf(s, bufsize, "--%s", longName);
|
||||
else
|
||||
sprintf(s, "-%c", shortName);
|
||||
snprintf(s, bufsize, "-%c", shortName);
|
||||
con->finalArgv[i] = s;
|
||||
} else
|
||||
con->finalArgv[i] = NULL;
|
||||
@@ -292,11 +327,12 @@ static int handleExec(/*@special@*/ poptContext con,
|
||||
return 1;
|
||||
/*@=nullstate@*/
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
/* Only one of longName, shortName may be set at a time */
|
||||
static int handleAlias(/*@special@*/ poptContext con,
|
||||
/*@null@*/ const char * longName, char shortName,
|
||||
/*@keep@*/ /*@null@*/ const char * nextCharArg)
|
||||
/*@exposed@*/ /*@null@*/ const char * nextCharArg)
|
||||
/*@uses con->aliases, con->numAliases, con->optionStack, con->os,
|
||||
con->os->currAlias, con->os->currAlias->option.longName @*/
|
||||
/*@modifies con @*/
|
||||
@@ -330,8 +366,10 @@ static int handleAlias(/*@special@*/ poptContext con,
|
||||
if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
|
||||
return POPT_ERROR_OPTSTOODEEP;
|
||||
|
||||
/*@-boundsread@*/
|
||||
if (nextCharArg && *nextCharArg)
|
||||
con->os->nextCharArg = nextCharArg;
|
||||
/*@=boundsread@*/
|
||||
|
||||
con->os++;
|
||||
con->os->next = 0;
|
||||
@@ -346,13 +384,14 @@ static int handleAlias(/*@special@*/ poptContext con,
|
||||
return (rc ? rc : 1);
|
||||
}
|
||||
|
||||
/*@-bounds -boundswrite @*/
|
||||
static int execCommand(poptContext con)
|
||||
/*@*/
|
||||
/*@globals internalState @*/
|
||||
/*@modifies internalState @*/
|
||||
{
|
||||
poptItem item = con->doExec;
|
||||
const char ** argv;
|
||||
int argc = 0;
|
||||
int rc;
|
||||
|
||||
if (item == NULL) /*XXX can't happen*/
|
||||
return POPT_ERROR_NOARG;
|
||||
@@ -363,15 +402,15 @@ static int execCommand(poptContext con)
|
||||
|
||||
argv = malloc(sizeof(*argv) *
|
||||
(6 + item->argc + con->numLeftovers + con->finalArgvCount));
|
||||
if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */
|
||||
if (argv == NULL) return POPT_ERROR_MALLOC;
|
||||
|
||||
if (!strchr(item->argv[0], '/') && con->execPath) {
|
||||
char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
|
||||
sprintf(s, "%s/%s", con->execPath, item->argv[0]);
|
||||
if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
|
||||
size_t bufsize = strlen(con->execPath) + strlen(item->argv[0]) + sizeof "/";
|
||||
char *s = alloca(bufsize);
|
||||
snprintf(s, bufsize, "%s/%s", con->execPath, item->argv[0]);
|
||||
argv[argc] = s;
|
||||
} else {
|
||||
} else
|
||||
argv[argc] = findProgramPath(item->argv[0]);
|
||||
}
|
||||
if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
|
||||
|
||||
if (item->argc > 1) {
|
||||
@@ -386,16 +425,16 @@ static int execCommand(poptContext con)
|
||||
}
|
||||
|
||||
if (con->leftovers != NULL && con->numLeftovers > 0) {
|
||||
#if 0
|
||||
argv[argc++] = "--";
|
||||
#endif
|
||||
memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
|
||||
argc += con->numLeftovers;
|
||||
}
|
||||
|
||||
argv[argc] = NULL;
|
||||
|
||||
{
|
||||
#ifdef __hpux
|
||||
int rc = setresgid(getgid(), getgid(),-1);
|
||||
if (rc) return POPT_ERROR_ERRNO;
|
||||
rc = setresuid(getuid(), getuid(),-1);
|
||||
if (rc) return POPT_ERROR_ERRNO;
|
||||
#else
|
||||
@@ -405,19 +444,26 @@ static int execCommand(poptContext con)
|
||||
* XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
|
||||
*/
|
||||
#if defined(HAVE_SETUID)
|
||||
int rc = setgid(getgid());
|
||||
if (rc) return POPT_ERROR_ERRNO;
|
||||
rc = setuid(getuid());
|
||||
if (rc) return POPT_ERROR_ERRNO;
|
||||
#elif defined (HAVE_SETREUID)
|
||||
rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
|
||||
int rc = setregid(getgid(), getgid());
|
||||
if (rc) return POPT_ERROR_ERRNO;
|
||||
rc = setreuid(getuid(), getuid());
|
||||
if (rc) return POPT_ERROR_ERRNO;
|
||||
#else
|
||||
; /* Can't drop privileges */
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if (argv[0] == NULL)
|
||||
return POPT_ERROR_NOARG;
|
||||
#ifdef MYDEBUG
|
||||
|
||||
#ifdef MYDEBUG
|
||||
if (_popt_debug)
|
||||
{ const char ** avp;
|
||||
fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
|
||||
for (avp = argv; *avp; avp++)
|
||||
@@ -426,10 +472,13 @@ static int execCommand(poptContext con)
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = execvp(argv[0], (char *const *)argv);
|
||||
execvp(argv[0], (char *const *)argv);
|
||||
|
||||
return POPT_ERROR_ERRNO;
|
||||
}
|
||||
/*@=bounds =boundswrite @*/
|
||||
|
||||
/*@-boundswrite@*/
|
||||
/*@observer@*/ /*@null@*/ static const struct poptOption *
|
||||
findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
|
||||
char shortName,
|
||||
@@ -448,10 +497,15 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
|
||||
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
|
||||
const struct poptOption * opt2;
|
||||
void * arg = opt->arg;
|
||||
|
||||
/*@-branchstate@*/
|
||||
/* XXX sick hack to preserve pretense of ABI. */
|
||||
if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
|
||||
/*@=branchstate@*/
|
||||
/* Recurse on included sub-tables. */
|
||||
if (opt->arg == NULL) continue; /* XXX program error */
|
||||
opt2 = findOption(opt->arg, longName, shortName, callback,
|
||||
if (arg == NULL) continue; /* XXX program error */
|
||||
opt2 = findOption(arg, longName, shortName, callback,
|
||||
callbackData, singleDash);
|
||||
if (opt2 == NULL) continue;
|
||||
/* Sub-table data will be inheirited if no data yet. */
|
||||
@@ -496,6 +550,7 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
|
||||
|
||||
return opt;
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
static const char * findNextArg(/*@special@*/ poptContext con,
|
||||
unsigned argx, int delete_arg)
|
||||
@@ -534,6 +589,7 @@ static const char * findNextArg(/*@special@*/ poptContext con,
|
||||
return arg;
|
||||
}
|
||||
|
||||
/*@-boundswrite@*/
|
||||
static /*@only@*/ /*@null@*/ const char *
|
||||
expandNextArg(/*@special@*/ poptContext con, const char * s)
|
||||
/*@uses con->optionStack, con->os,
|
||||
@@ -541,7 +597,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
|
||||
/*@modifies con @*/
|
||||
{
|
||||
const char * a = NULL;
|
||||
size_t alen;
|
||||
size_t alen, pos;
|
||||
char *t, *te;
|
||||
size_t tn = strlen(s) + 1;
|
||||
char c;
|
||||
@@ -567,9 +623,9 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
|
||||
|
||||
alen = strlen(a);
|
||||
tn += alen;
|
||||
*te = '\0';
|
||||
pos = te - t;
|
||||
t = realloc(t, tn);
|
||||
te = t + strlen(t);
|
||||
te = t + pos;
|
||||
strncpy(te, a, alen); te += alen;
|
||||
continue;
|
||||
/*@notreached@*/ /*@switchbreak@*/ break;
|
||||
@@ -582,6 +638,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
|
||||
t = realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */
|
||||
return t;
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
static void poptStripArg(/*@special@*/ poptContext con, int which)
|
||||
/*@uses con->arg_strip, con->optionStack @*/
|
||||
@@ -599,26 +656,26 @@ static void poptStripArg(/*@special@*/ poptContext con, int which)
|
||||
/*@=compdef@*/
|
||||
}
|
||||
|
||||
static int poptSaveLong(const struct poptOption * opt, long aLong)
|
||||
/*@modifies opt->arg @*/
|
||||
int poptSaveLong(long * arg, int argInfo, long aLong)
|
||||
{
|
||||
if (opt->arg == NULL)
|
||||
/* XXX Check alignment, may fail on funky platforms. */
|
||||
if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
|
||||
return POPT_ERROR_NULLARG;
|
||||
|
||||
if (opt->argInfo & POPT_ARGFLAG_NOT)
|
||||
if (argInfo & POPT_ARGFLAG_NOT)
|
||||
aLong = ~aLong;
|
||||
switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
|
||||
switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
|
||||
case 0:
|
||||
*((long *) opt->arg) = aLong;
|
||||
*arg = aLong;
|
||||
break;
|
||||
case POPT_ARGFLAG_OR:
|
||||
*((long *) opt->arg) |= aLong;
|
||||
*arg |= aLong;
|
||||
break;
|
||||
case POPT_ARGFLAG_AND:
|
||||
*((long *) opt->arg) &= aLong;
|
||||
*arg &= aLong;
|
||||
break;
|
||||
case POPT_ARGFLAG_XOR:
|
||||
*((long *) opt->arg) ^= aLong;
|
||||
*arg ^= aLong;
|
||||
break;
|
||||
default:
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
@@ -627,26 +684,26 @@ static int poptSaveLong(const struct poptOption * opt, long aLong)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int poptSaveInt(const struct poptOption * opt, long aLong)
|
||||
/*@modifies opt->arg @*/
|
||||
int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
|
||||
{
|
||||
if (opt->arg == NULL)
|
||||
/* XXX Check alignment, may fail on funky platforms. */
|
||||
if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
|
||||
return POPT_ERROR_NULLARG;
|
||||
|
||||
if (opt->argInfo & POPT_ARGFLAG_NOT)
|
||||
if (argInfo & POPT_ARGFLAG_NOT)
|
||||
aLong = ~aLong;
|
||||
switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
|
||||
switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
|
||||
case 0:
|
||||
*((int *) opt->arg) = aLong;
|
||||
*arg = aLong;
|
||||
break;
|
||||
case POPT_ARGFLAG_OR:
|
||||
*((int *) opt->arg) |= aLong;
|
||||
*arg |= aLong;
|
||||
break;
|
||||
case POPT_ARGFLAG_AND:
|
||||
*((int *) opt->arg) &= aLong;
|
||||
*arg &= aLong;
|
||||
break;
|
||||
case POPT_ARGFLAG_XOR:
|
||||
*((int *) opt->arg) ^= aLong;
|
||||
*arg ^= aLong;
|
||||
break;
|
||||
default:
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
@@ -655,6 +712,7 @@ static int poptSaveInt(const struct poptOption * opt, long aLong)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*@-boundswrite@*/
|
||||
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
|
||||
int poptGetNextOpt(poptContext con)
|
||||
{
|
||||
@@ -714,8 +772,12 @@ int poptGetNextOpt(poptContext con)
|
||||
}
|
||||
|
||||
/* Make a copy we can hack at */
|
||||
localOptString = optString =
|
||||
strcpy(alloca(strlen(origOptString) + 1), origOptString);
|
||||
{ size_t bufsize = strlen(origOptString) + 1;
|
||||
localOptString = optString = alloca(bufsize);
|
||||
if (optString == NULL) /* XXX can't happen */
|
||||
return POPT_ERROR_BADOPT;
|
||||
strlcpy(optString, origOptString, bufsize);
|
||||
}
|
||||
|
||||
if (optString[0] == '\0')
|
||||
return POPT_ERROR_BADOPT;
|
||||
@@ -800,11 +862,11 @@ int poptGetNextOpt(poptContext con)
|
||||
|
||||
if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */
|
||||
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
|
||||
if (poptSaveInt(opt, 1L))
|
||||
if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
|
||||
if (opt->arg) {
|
||||
if (poptSaveInt(opt, (long)opt->val))
|
||||
if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
}
|
||||
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
|
||||
@@ -873,12 +935,12 @@ int poptGetNextOpt(poptContext con)
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
|
||||
if (aLong == LONG_MIN || aLong == LONG_MAX)
|
||||
return POPT_ERROR_OVERFLOW;
|
||||
if (poptSaveLong(opt, aLong))
|
||||
if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong))
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
} else {
|
||||
if (aLong > INT_MAX || aLong < INT_MIN)
|
||||
return POPT_ERROR_OVERFLOW;
|
||||
if (poptSaveInt(opt, aLong))
|
||||
if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong))
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
}
|
||||
} /*@switchbreak@*/ break;
|
||||
@@ -904,9 +966,6 @@ int poptGetNextOpt(poptContext con)
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
|
||||
*((double *) opt->arg) = aDouble;
|
||||
} else {
|
||||
#ifndef DBL_EPSILON
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#endif
|
||||
#define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
|
||||
if ((MY_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
|
||||
return POPT_ERROR_OVERFLOW;
|
||||
@@ -939,14 +998,15 @@ int poptGetNextOpt(poptContext con)
|
||||
}
|
||||
|
||||
if (con->finalArgv != NULL)
|
||||
{ char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
|
||||
{ ssize_t bufsize = (opt->longName ? strlen(opt->longName) : 0) + 3;
|
||||
char *s = malloc(bufsize);
|
||||
if (s != NULL) { /* XXX can't happen */
|
||||
if (opt->longName)
|
||||
sprintf(s, "%s%s",
|
||||
snprintf(s, bufsize, "%s%s",
|
||||
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
|
||||
opt->longName);
|
||||
else
|
||||
sprintf(s, "-%c", opt->shortName);
|
||||
snprintf(s, bufsize, "-%c", opt->shortName);
|
||||
con->finalArgv[con->finalArgvCount++] = s;
|
||||
} else
|
||||
con->finalArgv[con->finalArgvCount++] = NULL;
|
||||
@@ -967,6 +1027,7 @@ int poptGetNextOpt(poptContext con)
|
||||
|
||||
return (opt ? opt->val : -1); /* XXX can't happen */
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
const char * poptGetOptArg(poptContext con)
|
||||
{
|
||||
@@ -996,6 +1057,7 @@ const char * poptPeekArg(poptContext con)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*@-boundswrite@*/
|
||||
const char ** poptGetArgs(poptContext con)
|
||||
{
|
||||
if (con == NULL ||
|
||||
@@ -1009,6 +1071,7 @@ const char ** poptGetArgs(poptContext con)
|
||||
return (con->leftovers + con->nextLeftover);
|
||||
/*@=nullret =nullstate @*/
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
poptContext poptFreeContext(poptContext con)
|
||||
{
|
||||
@@ -1071,6 +1134,7 @@ int poptAddAlias(poptContext con, struct poptAlias alias,
|
||||
return poptAddItem(con, item, 0);
|
||||
}
|
||||
|
||||
/*@-boundswrite@*/
|
||||
/*@-mustmod@*/ /* LCL: con not modified? */
|
||||
int poptAddItem(poptContext con, poptItem newItem, int flags)
|
||||
{
|
||||
@@ -1115,6 +1179,7 @@ int poptAddItem(poptContext con, poptItem newItem, int flags)
|
||||
return 0;
|
||||
}
|
||||
/*@=mustmod@*/
|
||||
/*@=boundswrite@*/
|
||||
|
||||
const char * poptBadOption(poptContext con, int flags)
|
||||
{
|
||||
@@ -1128,7 +1193,7 @@ const char * poptBadOption(poptContext con, int flags)
|
||||
/*@=nullderef@*/
|
||||
}
|
||||
|
||||
const char *const poptStrerror(const int error)
|
||||
const char * poptStrerror(const int error)
|
||||
{
|
||||
switch (error) {
|
||||
case POPT_ERROR_NOARG:
|
||||
@@ -1184,6 +1249,7 @@ const char * poptGetInvocationName(poptContext con)
|
||||
return (con->os->argv ? con->os->argv[0] : "");
|
||||
}
|
||||
|
||||
/*@-boundswrite@*/
|
||||
int poptStrippedArgv(poptContext con, int argc, char ** argv)
|
||||
{
|
||||
int numargs = argc;
|
||||
@@ -1207,3 +1273,4 @@ int poptStrippedArgv(poptContext con, int argc, char ** argv)
|
||||
|
||||
return numargs;
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
216
popt/popt.h
216
popt/popt.h
@@ -112,33 +112,42 @@
|
||||
/** \ingroup popt
|
||||
*/
|
||||
struct poptOption {
|
||||
/*@observer@*/ /*@null@*/ const char * longName; /*!< may be NULL */
|
||||
char shortName; /*!< may be '\0' */
|
||||
/*@observer@*/ /*@null@*/
|
||||
const char * longName; /*!< may be NULL */
|
||||
char shortName; /*!< may be NUL */
|
||||
int argInfo;
|
||||
/*@shared@*/ /*@null@*/ void * arg; /*!< depends on argInfo */
|
||||
/*@shared@*/ /*@null@*/
|
||||
void * arg; /*!< depends on argInfo */
|
||||
int val; /*!< 0 means don't return, just update flag */
|
||||
/*@observer@*/ /*@null@*/ const char * descrip; /*!< description for autohelp -- may be NULL */
|
||||
/*@observer@*/ /*@null@*/ const char * argDescrip; /*!< argument description for autohelp */
|
||||
/*@observer@*/ /*@null@*/
|
||||
const char * descrip; /*!< description for autohelp -- may be NULL */
|
||||
/*@observer@*/ /*@null@*/
|
||||
const char * argDescrip; /*!< argument description for autohelp */
|
||||
};
|
||||
|
||||
/** \ingroup popt
|
||||
* A popt alias argument for poptAddAlias().
|
||||
*/
|
||||
struct poptAlias {
|
||||
/*@owned@*/ /*@null@*/ const char * longName; /*!< may be NULL */
|
||||
char shortName; /*!< may be '\0' */
|
||||
/*@owned@*/ /*@null@*/
|
||||
const char * longName; /*!< may be NULL */
|
||||
char shortName; /*!< may be NUL */
|
||||
int argc;
|
||||
/*@owned@*/ const char ** argv; /*!< must be free()able */
|
||||
/*@owned@*/
|
||||
const char ** argv; /*!< must be free()able */
|
||||
};
|
||||
|
||||
/** \ingroup popt
|
||||
* A popt alias or exec argument for poptAddItem().
|
||||
*/
|
||||
/*@-exporttype@*/
|
||||
typedef struct poptItem_s {
|
||||
struct poptOption option; /*!< alias/exec name(s) and description. */
|
||||
int argc; /*!< (alias) no. of args. */
|
||||
/*@owned@*/ const char ** argv; /*!< (alias) args, must be free()able. */
|
||||
/*@owned@*/
|
||||
const char ** argv; /*!< (alias) args, must be free()able. */
|
||||
} * poptItem;
|
||||
/*@=exporttype@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* \name Auto-generated help/usage
|
||||
@@ -148,16 +157,26 @@ typedef struct poptItem_s {
|
||||
/**
|
||||
* Empty table marker to enable displaying popt alias/exec options.
|
||||
*/
|
||||
/*@observer@*/ /*@checked@*/
|
||||
/*@-exportvar@*/
|
||||
/*@unchecked@*/ /*@observer@*/
|
||||
extern struct poptOption poptAliasOptions[];
|
||||
/*@=exportvar@*/
|
||||
#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
|
||||
0, "Options implemented via popt alias/exec:", NULL },
|
||||
|
||||
/**
|
||||
* Auto help table options.
|
||||
*/
|
||||
/*@observer@*/ /*@checked@*/
|
||||
/*@-exportvar@*/
|
||||
/*@unchecked@*/ /*@observer@*/
|
||||
extern struct poptOption poptHelpOptions[];
|
||||
/*@=exportvar@*/
|
||||
|
||||
/*@-exportvar@*/
|
||||
/*@unchecked@*/ /*@observer@*/
|
||||
extern struct poptOption * poptHelpOptionsI18N;
|
||||
/*@=exportvar@*/
|
||||
|
||||
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
|
||||
0, "Help options:", NULL },
|
||||
|
||||
@@ -166,19 +185,25 @@ extern struct poptOption poptHelpOptions[];
|
||||
|
||||
/** \ingroup popt
|
||||
*/
|
||||
/*@-exporttype@*/
|
||||
typedef /*@abstract@*/ struct poptContext_s * poptContext;
|
||||
/*@=exporttype@*/
|
||||
|
||||
/** \ingroup popt
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
/*@-typeuse@*/
|
||||
/*@-exporttype -typeuse@*/
|
||||
typedef struct poptOption * poptOption;
|
||||
/*@=typeuse@*/
|
||||
/*@=exporttype =typeuse@*/
|
||||
#endif
|
||||
|
||||
enum poptCallbackReason { POPT_CALLBACK_REASON_PRE,
|
||||
POPT_CALLBACK_REASON_POST,
|
||||
POPT_CALLBACK_REASON_OPTION };
|
||||
/*@-exportconst@*/
|
||||
enum poptCallbackReason {
|
||||
POPT_CALLBACK_REASON_PRE = 0,
|
||||
POPT_CALLBACK_REASON_POST = 1,
|
||||
POPT_CALLBACK_REASON_OPTION = 2
|
||||
};
|
||||
/*@=exportconst@*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -198,18 +223,20 @@ typedef void (*poptCallbackType) (poptContext con,
|
||||
/*@null@*/ const struct poptOption * opt,
|
||||
/*@null@*/ const char * arg,
|
||||
/*@null@*/ const void * data)
|
||||
/*@*/;
|
||||
/*@globals internalState @*/
|
||||
/*@modifies internalState @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Initialize popt context.
|
||||
* @param name
|
||||
* @param name context name (usually argv[0] program name)
|
||||
* @param argc no. of arguments
|
||||
* @param argv argument array
|
||||
* @param options address of popt option table
|
||||
* @param flags or'd POPT_CONTEXT_* bits
|
||||
* @return initialized popt context
|
||||
*/
|
||||
/*@only@*/ /*@null@*/ poptContext poptGetContext(
|
||||
/*@only@*/ /*@null@*/
|
||||
poptContext poptGetContext(
|
||||
/*@dependent@*/ /*@keep@*/ const char * name,
|
||||
int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
|
||||
/*@dependent@*/ /*@keep@*/ const struct poptOption * options,
|
||||
@@ -220,6 +247,7 @@ typedef void (*poptCallbackType) (poptContext con,
|
||||
* Reinitialize popt context.
|
||||
* @param con context
|
||||
*/
|
||||
/*@unused@*/
|
||||
void poptResetContext(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
@@ -229,57 +257,62 @@ void poptResetContext(/*@null@*/poptContext con)
|
||||
* @return next option val, -1 on last item, POPT_ERROR_* on error
|
||||
*/
|
||||
int poptGetNextOpt(/*@null@*/poptContext con)
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies con, fileSystem @*/;
|
||||
/*@globals fileSystem, internalState @*/
|
||||
/*@modifies con, fileSystem, internalState @*/;
|
||||
|
||||
/*@-redecl@*/
|
||||
/** \ingroup popt
|
||||
* Return next option argument (if any).
|
||||
* @param con context
|
||||
* @return option argument, NULL if no more options are available
|
||||
* @return option argument, NULL if no argument is available
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con)
|
||||
/*@observer@*/ /*@null@*/ /*@unused@*/
|
||||
const char * poptGetOptArg(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return current option's argument.
|
||||
* Return next argument.
|
||||
* @param con context
|
||||
* @return option argument, NULL if no more options are available
|
||||
* @return next argument, NULL if no argument is available
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con)
|
||||
/*@observer@*/ /*@null@*/ /*@unused@*/
|
||||
const char * poptGetArg(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Peek at current option's argument.
|
||||
* Peek at current argument.
|
||||
* @param con context
|
||||
* @return option argument
|
||||
* @return current argument, NULL if no argument is available
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con)
|
||||
/*@observer@*/ /*@null@*/ /*@unused@*/
|
||||
const char * poptPeekArg(/*@null@*/poptContext con)
|
||||
/*@*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return remaining arguments.
|
||||
* @param con context
|
||||
* @return argument array, terminated with NULL
|
||||
* @return argument array, NULL terminated
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con)
|
||||
/*@observer@*/ /*@null@*/
|
||||
const char ** poptGetArgs(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return the option which caused the most recent error.
|
||||
* @param con context
|
||||
* @param flags
|
||||
* @return offending option
|
||||
*/
|
||||
/*@observer@*/ const char * poptBadOption(/*@null@*/poptContext con, int flags)
|
||||
/*@observer@*/
|
||||
const char * poptBadOption(/*@null@*/poptContext con, int flags)
|
||||
/*@*/;
|
||||
/*@=redecl@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Destroy context.
|
||||
* @param con context
|
||||
* @return NULL always
|
||||
*/
|
||||
/*@null@*/ poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
|
||||
/*@null@*/
|
||||
poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
@@ -288,6 +321,7 @@ int poptGetNextOpt(/*@null@*/poptContext con)
|
||||
* @param argv argument array, NULL terminated
|
||||
* @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
|
||||
*/
|
||||
/*@unused@*/
|
||||
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
|
||||
/*@modifies con @*/;
|
||||
|
||||
@@ -307,7 +341,7 @@ int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
|
||||
/** \ingroup popt
|
||||
* Add alias/exec item to context.
|
||||
* @param con context
|
||||
* @param item alias/exec item to add
|
||||
* @param newItem alias/exec item to add
|
||||
* @param flags 0 for alias, 1 for exec
|
||||
* @return 0 on success
|
||||
*/
|
||||
@@ -321,9 +355,9 @@ int poptAddItem(poptContext con, poptItem newItem, int flags)
|
||||
* @return 0 on success, POPT_ERROR_ERRNO on failure
|
||||
*/
|
||||
int poptReadConfigFile(poptContext con, const char * fn)
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies fileSystem,
|
||||
con->execs, con->numExecs @*/;
|
||||
/*@globals errno, fileSystem, internalState @*/
|
||||
/*@modifies con->execs, con->numExecs,
|
||||
errno, fileSystem, internalState @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Read default configuration from /etc/popt and $HOME/.popt.
|
||||
@@ -331,10 +365,11 @@ int poptReadConfigFile(poptContext con, const char * fn)
|
||||
* @param useEnv (unused)
|
||||
* @return 0 on success, POPT_ERROR_ERRNO on failure
|
||||
*/
|
||||
/*@unused@*/
|
||||
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies fileSystem,
|
||||
con->execs, con->numExecs @*/;
|
||||
/*@globals fileSystem, internalState @*/
|
||||
/*@modifies con->execs, con->numExecs,
|
||||
fileSystem, internalState @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Duplicate an argument array.
|
||||
@@ -363,19 +398,70 @@ int poptDupArgv(int argc, /*@null@*/ const char **argv,
|
||||
* @retval argcPtr address of returned no. of arguments
|
||||
* @retval argvPtr address of returned argument array
|
||||
*/
|
||||
int poptParseArgvString(const unsigned char * s,
|
||||
int poptParseArgvString(const char * s,
|
||||
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
|
||||
/*@modifies *argcPtr, *argvPtr @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Parses an input configuration file and returns an string that is a
|
||||
* command line. For use with popt. You must free the return value when done.
|
||||
*
|
||||
* Given the file:
|
||||
\verbatim
|
||||
# this line is ignored
|
||||
# this one too
|
||||
aaa
|
||||
bbb
|
||||
ccc
|
||||
bla=bla
|
||||
|
||||
this_is = fdsafdas
|
||||
bad_line=
|
||||
reall bad line
|
||||
reall bad line = again
|
||||
5555= 55555
|
||||
test = with lots of spaces
|
||||
\endverbatim
|
||||
*
|
||||
* The result is:
|
||||
\verbatim
|
||||
--aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces"
|
||||
\endverbatim
|
||||
*
|
||||
* Passing this to poptParseArgvString() yields an argv of:
|
||||
\verbatim
|
||||
'--aaa'
|
||||
'--bbb'
|
||||
'--ccc'
|
||||
'--bla=bla'
|
||||
'--this_is=fdsafdas'
|
||||
'--5555=55555'
|
||||
'--test=with lots of spaces'
|
||||
\endverbatim
|
||||
*
|
||||
* @bug NULL is returned if file line is too long.
|
||||
* @bug Silently ignores invalid lines.
|
||||
*
|
||||
* @param fp file handle to read
|
||||
* @param *argstrp return string of options (malloc'd)
|
||||
* @param flags unused
|
||||
* @return 0 on success
|
||||
* @see poptParseArgvString
|
||||
*/
|
||||
/*@-fcnuse@*/
|
||||
int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, *argstrp, fileSystem @*/;
|
||||
/*@=fcnuse@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Return formatted error string for popt failure.
|
||||
* @param error popt error
|
||||
* @return error string
|
||||
*/
|
||||
/*@-redecl@*/
|
||||
/*@observer@*/ const char *const poptStrerror(const int error)
|
||||
/*@observer@*/
|
||||
const char * poptStrerror(const int error)
|
||||
/*@*/;
|
||||
/*@=redecl@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Limit search for executables.
|
||||
@@ -383,6 +469,7 @@ int poptParseArgvString(const unsigned char * s,
|
||||
* @param path single path to search for executables
|
||||
* @param allowAbsolute absolute paths only?
|
||||
*/
|
||||
/*@unused@*/
|
||||
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
|
||||
/*@modifies con @*/;
|
||||
|
||||
@@ -421,10 +508,11 @@ void poptSetOtherOptionHelp(poptContext con, const char * text)
|
||||
* @param con context
|
||||
* @return argv[0]
|
||||
*/
|
||||
/*@-redecl -fcnuse@*/
|
||||
/*@observer@*/ const char * poptGetInvocationName(poptContext con)
|
||||
/*@-fcnuse@*/
|
||||
/*@observer@*/
|
||||
const char * poptGetInvocationName(poptContext con)
|
||||
/*@*/;
|
||||
/*@=redecl =fcnuse@*/
|
||||
/*@=fcnuse@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Shuffle argv pointers to remove stripped args, returns new argc.
|
||||
@@ -438,6 +526,36 @@ int poptStrippedArgv(poptContext con, int argc, char ** argv)
|
||||
/*@modifies *argv @*/;
|
||||
/*@=fcnuse@*/
|
||||
|
||||
/**
|
||||
* Save a long, performing logical operation with value.
|
||||
* @warning Alignment check may be too strict on certain platorms.
|
||||
* @param arg integer pointer, aligned on int boundary.
|
||||
* @param argInfo logical operation (see POPT_ARGFLAG_*)
|
||||
* @param aLong value to use
|
||||
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
|
||||
*/
|
||||
/*@-incondefs@*/
|
||||
/*@unused@*/
|
||||
int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong)
|
||||
/*@modifies *arg @*/
|
||||
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
|
||||
/*@=incondefs@*/
|
||||
|
||||
/**
|
||||
* Save an integer, performing logical operation with value.
|
||||
* @warning Alignment check may be too strict on certain platorms.
|
||||
* @param arg integer pointer, aligned on int boundary.
|
||||
* @param argInfo logical operation (see POPT_ARGFLAG_*)
|
||||
* @param aLong value to use
|
||||
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
|
||||
*/
|
||||
/*@-incondefs@*/
|
||||
/*@unused@*/
|
||||
int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
|
||||
/*@modifies *arg @*/
|
||||
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
|
||||
/*@=incondefs@*/
|
||||
|
||||
/*@=type@*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -2,46 +2,48 @@
|
||||
* \file popt/poptconfig.c
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#include "system.h"
|
||||
#include "poptint.h"
|
||||
/*@access poptContext @*/
|
||||
|
||||
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
|
||||
static void configLine(poptContext con, unsigned char * line)
|
||||
static void configLine(poptContext con, char * line)
|
||||
/*@modifies con @*/
|
||||
{
|
||||
/*@-type@*/
|
||||
int nameLength = strlen(con->appName);
|
||||
/*@=type@*/
|
||||
size_t nameLength;
|
||||
const char * entryType;
|
||||
const char * opt;
|
||||
poptItem item = (poptItem) alloca(sizeof(*item));
|
||||
int i, j;
|
||||
|
||||
if (con->appName == NULL)
|
||||
return;
|
||||
nameLength = strlen(con->appName);
|
||||
|
||||
/*@-boundswrite@*/
|
||||
memset(item, 0, sizeof(*item));
|
||||
|
||||
/*@-type@*/
|
||||
if (strncmp(line, con->appName, nameLength)) return;
|
||||
/*@=type@*/
|
||||
|
||||
line += nameLength;
|
||||
if (*line == '\0' || !isspace(*line)) return;
|
||||
if (*line == '\0' || !isSpace(line)) return;
|
||||
|
||||
while (*line != '\0' && isspace(*line)) line++;
|
||||
while (*line != '\0' && isSpace(line)) line++;
|
||||
entryType = line;
|
||||
while (*line == '\0' || !isspace(*line)) line++;
|
||||
while (*line == '\0' || !isSpace(line)) line++;
|
||||
*line++ = '\0';
|
||||
|
||||
while (*line != '\0' && isspace(*line)) line++;
|
||||
while (*line != '\0' && isSpace(line)) line++;
|
||||
if (*line == '\0') return;
|
||||
opt = line;
|
||||
while (*line == '\0' || !isspace(*line)) line++;
|
||||
while (*line == '\0' || !isSpace(line)) line++;
|
||||
*line++ = '\0';
|
||||
|
||||
while (*line != '\0' && isspace(*line)) line++;
|
||||
while (*line != '\0' && isSpace(line)) line++;
|
||||
if (*line == '\0') return;
|
||||
|
||||
/*@-temptrans@*/ /* FIX: line alias is saved */
|
||||
@@ -80,6 +82,7 @@ static void configLine(poptContext con, unsigned char * line)
|
||||
item->argc = j;
|
||||
}
|
||||
/*@=modobserver@*/
|
||||
/*@=boundswrite@*/
|
||||
|
||||
/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
|
||||
if (!strcmp(entryType, "alias"))
|
||||
@@ -92,9 +95,9 @@ static void configLine(poptContext con, unsigned char * line)
|
||||
|
||||
int poptReadConfigFile(poptContext con, const char * fn)
|
||||
{
|
||||
const unsigned char * file, * chptr, * end;
|
||||
unsigned char * buf;
|
||||
/*@dependent@*/ unsigned char * dst;
|
||||
const char * file, * chptr, * end;
|
||||
char * buf;
|
||||
/*@dependent@*/ char * dst;
|
||||
int fd, rc;
|
||||
off_t fileLength;
|
||||
|
||||
@@ -106,9 +109,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
|
||||
if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
|
||||
rc = errno;
|
||||
(void) close(fd);
|
||||
/*@-mods@*/
|
||||
errno = rc;
|
||||
/*@=mods@*/
|
||||
return POPT_ERROR_ERRNO;
|
||||
}
|
||||
|
||||
@@ -116,14 +117,13 @@ int poptReadConfigFile(poptContext con, const char * fn)
|
||||
if (read(fd, (char *)file, fileLength) != fileLength) {
|
||||
rc = errno;
|
||||
(void) close(fd);
|
||||
/*@-mods@*/
|
||||
errno = rc;
|
||||
/*@=mods@*/
|
||||
return POPT_ERROR_ERRNO;
|
||||
}
|
||||
if (close(fd) == -1)
|
||||
return POPT_ERROR_ERRNO;
|
||||
|
||||
/*@-boundswrite@*/
|
||||
dst = buf = alloca(fileLength + 1);
|
||||
|
||||
chptr = file;
|
||||
@@ -134,7 +134,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
|
||||
case '\n':
|
||||
*dst = '\0';
|
||||
dst = buf;
|
||||
while (*dst && isspace(*dst)) dst++;
|
||||
while (*dst && isSpace(dst)) dst++;
|
||||
if (*dst && *dst != '#')
|
||||
configLine(con, dst);
|
||||
chptr++;
|
||||
@@ -155,6 +155,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
|
||||
}
|
||||
}
|
||||
/*@=infloops@*/
|
||||
/*@=boundswrite@*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -164,18 +165,16 @@ int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
|
||||
char * fn, * home;
|
||||
int rc;
|
||||
|
||||
/*@-type@*/
|
||||
if (!con->appName) return 0;
|
||||
/*@=type@*/
|
||||
if (con->appName == NULL) return 0;
|
||||
|
||||
rc = poptReadConfigFile(con, "/etc/popt");
|
||||
if (rc) return rc;
|
||||
if (getuid() != geteuid()) return 0;
|
||||
|
||||
if ((home = getenv("HOME"))) {
|
||||
fn = alloca(strlen(home) + 20);
|
||||
strcpy(fn, home);
|
||||
strcat(fn, "/.popt");
|
||||
size_t bufsize = strlen(home) + 20;
|
||||
fn = alloca(bufsize);
|
||||
if (fn == NULL) return 0;
|
||||
snprintf(fn, bufsize, "%s/.popt", home);
|
||||
rc = poptReadConfigFile(con, fn);
|
||||
if (rc) return rc;
|
||||
}
|
||||
|
||||
388
popt/popthelp.c
388
popt/popthelp.c
@@ -1,20 +1,31 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
|
||||
/*@-type@*/
|
||||
/** \ingroup popt
|
||||
* \file popt/popthelp.c
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/*#define POPT_WCHAR_HACK*/
|
||||
#ifdef POPT_WCHAR_HACK
|
||||
#include <wchar.h> /* for mbsrtowcs */
|
||||
/*@access mbstate_t @*/
|
||||
#endif
|
||||
#include "poptint.h"
|
||||
|
||||
/*@access poptContext@*/
|
||||
|
||||
/**
|
||||
* Display arguments.
|
||||
* @param con context
|
||||
* @param foo (unused)
|
||||
* @param key option(s)
|
||||
* @param arg (unused)
|
||||
* @param data (unused)
|
||||
*/
|
||||
static void displayArgs(poptContext con,
|
||||
/*@unused@*/ UNUSED(enum poptCallbackReason foo),
|
||||
@@ -49,6 +60,17 @@ struct poptOption poptAliasOptions[] = {
|
||||
/*@-castfcnptr@*/
|
||||
/*@observer@*/ /*@unchecked@*/
|
||||
struct poptOption poptHelpOptions[] = {
|
||||
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
|
||||
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
|
||||
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
|
||||
POPT_TABLEEND
|
||||
} ;
|
||||
|
||||
/*@observer@*/ /*@unchecked@*/
|
||||
static struct poptOption poptHelpOptions2[] = {
|
||||
/*@-readonlytrans@*/
|
||||
{ NULL, '\0', POPT_ARG_INTL_DOMAIN, PACKAGE, 0, NULL, NULL},
|
||||
/*@=readonlytrans@*/
|
||||
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
|
||||
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
|
||||
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
|
||||
@@ -58,12 +80,15 @@ struct poptOption poptHelpOptions[] = {
|
||||
#endif
|
||||
POPT_TABLEEND
|
||||
} ;
|
||||
|
||||
/*@observer@*/ /*@unchecked@*/
|
||||
struct poptOption * poptHelpOptionsI18N = poptHelpOptions2;
|
||||
/*@=castfcnptr@*/
|
||||
|
||||
/**
|
||||
* @param table option(s)
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ static const char *const
|
||||
/*@observer@*/ /*@null@*/ static const char *
|
||||
getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
|
||||
/*@*/
|
||||
{
|
||||
@@ -81,9 +106,9 @@ getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ static const char *const
|
||||
/*@observer@*/ /*@null@*/ static const char *
|
||||
getArgDescrip(const struct poptOption * opt,
|
||||
/*@-paramuse@*/ /* FIX: wazzup? */
|
||||
/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@=paramuse@*/
|
||||
/*@*/
|
||||
@@ -97,7 +122,11 @@ getArgDescrip(const struct poptOption * opt,
|
||||
|
||||
switch (opt->argInfo & POPT_ARG_MASK) {
|
||||
case POPT_ARG_NONE: return POPT_("NONE");
|
||||
#ifdef DYING
|
||||
case POPT_ARG_VAL: return POPT_("VAL");
|
||||
#else
|
||||
case POPT_ARG_VAL: return NULL;
|
||||
#endif
|
||||
case POPT_ARG_INT: return POPT_("INT");
|
||||
case POPT_ARG_LONG: return POPT_("LONG");
|
||||
case POPT_ARG_STRING: return POPT_("STRING");
|
||||
@@ -108,61 +137,65 @@ getArgDescrip(const struct poptOption * opt,
|
||||
}
|
||||
|
||||
/**
|
||||
* Display default value for an option.
|
||||
* @param lineLength display positions remaining
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
* @return
|
||||
*/
|
||||
static /*@only@*/ /*@null@*/ char *
|
||||
singleOptionDefaultValue(int lineLength,
|
||||
singleOptionDefaultValue(size_t lineLength,
|
||||
const struct poptOption * opt,
|
||||
/*@-paramuse@*/ /* FIX: i18n macros disable with lclint */
|
||||
/*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@=paramuse@*/
|
||||
/*@*/
|
||||
{
|
||||
const char * defstr = D_(translation_domain, "default");
|
||||
char * le = malloc(4*lineLength + 1);
|
||||
size_t limit, bufsize = 4*lineLength + 1;
|
||||
char * le = malloc(bufsize);
|
||||
char * l = le;
|
||||
|
||||
if (le == NULL) return NULL; /* XXX can't happen */
|
||||
*le = '\0';
|
||||
/*@-boundswrite@*/
|
||||
*le++ = '(';
|
||||
strcpy(le, defstr); le += strlen(le);
|
||||
le += strlcpy(le, defstr, bufsize - 3);
|
||||
*le++ = ':';
|
||||
*le++ = ' ';
|
||||
limit = bufsize - (le - l) - 1; /* -1 for closing paren */
|
||||
if (opt->arg) /* XXX programmer error */
|
||||
switch (opt->argInfo & POPT_ARG_MASK) {
|
||||
case POPT_ARG_VAL:
|
||||
case POPT_ARG_INT:
|
||||
{ long aLong = *((int *)opt->arg);
|
||||
sprintf(le, "%ld", aLong);
|
||||
le += strlen(le);
|
||||
le += snprintf(le, limit, "%ld", aLong);
|
||||
} break;
|
||||
case POPT_ARG_LONG:
|
||||
{ long aLong = *((long *)opt->arg);
|
||||
sprintf(le, "%ld", aLong);
|
||||
le += strlen(le);
|
||||
le += snprintf(le, limit, "%ld", aLong);
|
||||
} break;
|
||||
case POPT_ARG_FLOAT:
|
||||
{ double aDouble = *((float *)opt->arg);
|
||||
sprintf(le, "%g", aDouble);
|
||||
le += strlen(le);
|
||||
le += snprintf(le, limit, "%g", aDouble);
|
||||
} break;
|
||||
case POPT_ARG_DOUBLE:
|
||||
{ double aDouble = *((double *)opt->arg);
|
||||
sprintf(le, "%g", aDouble);
|
||||
le += strlen(le);
|
||||
le += snprintf(le, limit, "%g", aDouble);
|
||||
} break;
|
||||
case POPT_ARG_STRING:
|
||||
{ const char * s = *(const char **)opt->arg;
|
||||
if (s == NULL) {
|
||||
strcpy(le, "null"); le += strlen(le);
|
||||
le += strlcpy(le, "null", limit);
|
||||
} else {
|
||||
size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
|
||||
size_t len;
|
||||
limit -= 2; /* make room for quotes */
|
||||
*le++ = '"';
|
||||
strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);
|
||||
if (slen < strlen(s)) {
|
||||
strcpy(le, "..."); le += strlen(le);
|
||||
}
|
||||
len = strlcpy(le, s, limit);
|
||||
if (len >= limit) {
|
||||
le += limit - 3 - 1;
|
||||
*le++ = '.'; *le++ = '.'; *le++ = '.';
|
||||
} else
|
||||
le += len;
|
||||
*le++ = '"';
|
||||
}
|
||||
} break;
|
||||
@@ -174,50 +207,57 @@ singleOptionDefaultValue(int lineLength,
|
||||
}
|
||||
*le++ = ')';
|
||||
*le = '\0';
|
||||
/*@=boundswrite@*/
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display help text for an option.
|
||||
* @param fp output file handle
|
||||
* @param maxLeftCol largest argument display width
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static void singleOptionHelp(FILE * fp, int maxLeftCol,
|
||||
static void singleOptionHelp(FILE * fp, size_t maxLeftCol,
|
||||
const struct poptOption * opt,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
int indentLength = maxLeftCol + 5;
|
||||
int lineLength = 79 - indentLength;
|
||||
const unsigned char * help = D_(translation_domain, opt->descrip);
|
||||
size_t indentLength = maxLeftCol + 5;
|
||||
size_t lineLength = 79 - indentLength;
|
||||
const char * help = D_(translation_domain, opt->descrip);
|
||||
const char * argDescrip = getArgDescrip(opt, translation_domain);
|
||||
int helpLength;
|
||||
unsigned char * defs = NULL;
|
||||
unsigned char * left;
|
||||
int nb = maxLeftCol + 1;
|
||||
size_t helpLength;
|
||||
char * defs = NULL;
|
||||
char * left;
|
||||
size_t lelen, limit;
|
||||
size_t nb = maxLeftCol + 1;
|
||||
int displaypad = 0;
|
||||
|
||||
/* Make sure there's more than enough room in target buffer. */
|
||||
if (opt->longName) nb += strlen(opt->longName);
|
||||
if (argDescrip) nb += strlen(argDescrip);
|
||||
|
||||
/*@-boundswrite@*/
|
||||
left = malloc(nb);
|
||||
if (left == NULL) return; /* XXX can't happen */
|
||||
left[0] = '\0';
|
||||
left[maxLeftCol] = '\0';
|
||||
|
||||
if (opt->longName && opt->shortName)
|
||||
sprintf(left, "-%c, %s%s", opt->shortName,
|
||||
snprintf(left, nb, "-%c, %s%s", opt->shortName,
|
||||
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
|
||||
opt->longName);
|
||||
else if (opt->shortName != '\0')
|
||||
sprintf(left, "-%c", opt->shortName);
|
||||
snprintf(left, nb, "-%c", opt->shortName);
|
||||
else if (opt->longName)
|
||||
sprintf(left, "%s%s",
|
||||
snprintf(left, nb, "%s%s",
|
||||
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
|
||||
opt->longName);
|
||||
if (!*left) goto out;
|
||||
|
||||
if (argDescrip) {
|
||||
char * le = left + strlen(left);
|
||||
|
||||
@@ -229,16 +269,10 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
|
||||
if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) {
|
||||
defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
|
||||
if (defs) {
|
||||
char * t = malloc((help ? strlen(help) : 0) +
|
||||
strlen(defs) + sizeof(" "));
|
||||
size_t bufsize = (help ? strlen(help) : 0) + sizeof " " + strlen(defs);
|
||||
char * t = malloc(bufsize);
|
||||
if (t) {
|
||||
char * te = t;
|
||||
*te = '\0';
|
||||
if (help) {
|
||||
strcpy(te, help); te += strlen(te);
|
||||
}
|
||||
*te++ = ' ';
|
||||
strcpy(te, defs);
|
||||
snprintf(t, bufsize, "%s %s", help ? help : "", defs);
|
||||
defs = _free(defs);
|
||||
}
|
||||
defs = t;
|
||||
@@ -251,6 +285,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
|
||||
case POPT_ARG_NONE:
|
||||
break;
|
||||
case POPT_ARG_VAL:
|
||||
#ifdef NOTNOW /* XXX pug ugly nerdy output */
|
||||
{ long aLong = opt->val;
|
||||
int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
|
||||
int negate = (opt->argInfo & POPT_ARGFLAG_NOT);
|
||||
@@ -272,65 +307,94 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
|
||||
default:
|
||||
/*@innerbreak@*/ break;
|
||||
}
|
||||
*le++ = '=';
|
||||
*le++ = (opt->longName != NULL ? '=' : ' ');
|
||||
if (negate) *le++ = '~';
|
||||
/*@-formatconst@*/
|
||||
sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
|
||||
le += strlen(le);
|
||||
limit = nb - (le - left);
|
||||
lelen = snprintf(le, limit, (ops ? "0x%lx" : "%ld"), aLong);
|
||||
le += lelen >= limit ? limit - 1 : lelen;
|
||||
/*@=formatconst@*/
|
||||
*le++ = ']';
|
||||
} break;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case POPT_ARG_INT:
|
||||
case POPT_ARG_LONG:
|
||||
case POPT_ARG_FLOAT:
|
||||
case POPT_ARG_DOUBLE:
|
||||
case POPT_ARG_STRING:
|
||||
*le++ = '=';
|
||||
strcpy(le, argDescrip); le += strlen(le);
|
||||
*le++ = (opt->longName != NULL ? '=' : ' ');
|
||||
limit = nb - (le - left);
|
||||
lelen = strlcpy(le, argDescrip, limit);
|
||||
le += lelen >= limit ? limit - 1 : lelen;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
*le++ = '=';
|
||||
strcpy(le, argDescrip); le += strlen(le);
|
||||
limit = nb - (le - left);
|
||||
lelen = strlcpy(le, argDescrip, limit);
|
||||
if (lelen >= limit)
|
||||
lelen = limit - 1;
|
||||
le += lelen;
|
||||
|
||||
#ifdef POPT_WCHAR_HACK
|
||||
{ const char * scopy = argDescrip;
|
||||
mbstate_t t;
|
||||
size_t n;
|
||||
|
||||
memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */
|
||||
/* Determine number of characters. */
|
||||
n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
|
||||
|
||||
displaypad = (int) (lelen-n);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
|
||||
*le++ = ']';
|
||||
*le = '\0';
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
if (help)
|
||||
fprintf(fp," %-*s ", maxLeftCol, left);
|
||||
fprintf(fp," %-*s ", (int)maxLeftCol+displaypad, left);
|
||||
else {
|
||||
fprintf(fp," %s\n", left);
|
||||
goto out;
|
||||
}
|
||||
|
||||
left = _free(left);
|
||||
/*@-branchstate@*/
|
||||
if (defs) {
|
||||
help = defs; defs = NULL;
|
||||
help = defs;
|
||||
defs = NULL;
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
|
||||
helpLength = strlen(help);
|
||||
/*@-boundsread@*/
|
||||
while (helpLength > lineLength) {
|
||||
const unsigned char * ch;
|
||||
char format[10];
|
||||
const char * ch;
|
||||
char format[16];
|
||||
|
||||
ch = help + lineLength - 1;
|
||||
while (ch > help && !isspace(*ch)) ch--;
|
||||
while (ch > help && !isSpace(ch)) ch--;
|
||||
if (ch == help) break; /* give up */
|
||||
while (ch > (help + 1) && isspace(*ch)) ch--;
|
||||
while (ch > (help + 1) && isSpace(ch)) ch--;
|
||||
ch++;
|
||||
|
||||
sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
|
||||
snprintf(format, sizeof format, "%%.%ds\n%%%ds", (int) (ch - help), (int) indentLength);
|
||||
/*@-formatconst@*/
|
||||
fprintf(fp, format, help, " ");
|
||||
/*@=formatconst@*/
|
||||
help = ch;
|
||||
while (isspace(*help) && *help) help++;
|
||||
while (isSpace(help) && *help) help++;
|
||||
helpLength = strlen(help);
|
||||
}
|
||||
/*@=boundsread@*/
|
||||
|
||||
if (helpLength) fprintf(fp, "%s\n", help);
|
||||
|
||||
@@ -342,15 +406,17 @@ out:
|
||||
}
|
||||
|
||||
/**
|
||||
* Find display width for longest argument string.
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
* @return display width
|
||||
*/
|
||||
static int maxArgWidth(const struct poptOption * opt,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
static size_t maxArgWidth(const struct poptOption * opt,
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@*/
|
||||
{
|
||||
int max = 0;
|
||||
int len = 0;
|
||||
size_t max = 0;
|
||||
size_t len = 0;
|
||||
const char * s;
|
||||
|
||||
if (opt != NULL)
|
||||
@@ -370,8 +436,26 @@ static int maxArgWidth(const struct poptOption * opt,
|
||||
}
|
||||
|
||||
s = getArgDescrip(opt, translation_domain);
|
||||
|
||||
#ifdef POPT_WCHAR_HACK
|
||||
/* XXX Calculate no. of display characters. */
|
||||
if (s) {
|
||||
const char * scopy = s;
|
||||
mbstate_t t;
|
||||
size_t n;
|
||||
|
||||
/*@-boundswrite@*/
|
||||
memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */
|
||||
/*@=boundswrite@*/
|
||||
/* Determine number of characters. */
|
||||
n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
|
||||
len += sizeof("=")-1 + n;
|
||||
}
|
||||
#else
|
||||
if (s)
|
||||
len += sizeof("=")-1 + strlen(s);
|
||||
#endif
|
||||
|
||||
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
|
||||
if (len > max) max = len;
|
||||
}
|
||||
@@ -387,11 +471,12 @@ static int maxArgWidth(const struct poptOption * opt,
|
||||
* @param fp output file handle
|
||||
* @param items alias/exec array
|
||||
* @param nitems no. of alias/exec entries
|
||||
* @param left largest argument display width
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static void itemHelp(FILE * fp,
|
||||
/*@null@*/ poptItem items, int nitems, int left,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@null@*/ poptItem items, int nitems, size_t left,
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
@@ -409,13 +494,16 @@ static void itemHelp(FILE * fp,
|
||||
}
|
||||
|
||||
/**
|
||||
* Display help text for a table of options.
|
||||
* @param con context
|
||||
* @param fp output file handle
|
||||
* @param table option(s)
|
||||
* @param left largest argument display width
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static void singleTableHelp(poptContext con, FILE * fp,
|
||||
/*@null@*/ const struct poptOption * table, int left,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@null@*/ const struct poptOption * table, size_t left,
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
@@ -463,9 +551,11 @@ static int showHelpIntro(poptContext con, FILE * fp)
|
||||
|
||||
fprintf(fp, POPT_("Usage:"));
|
||||
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
|
||||
/*@-nullderef@*/ /* LCL: wazzup? */
|
||||
/*@-boundsread@*/
|
||||
/*@-nullderef -type@*/ /* LCL: wazzup? */
|
||||
fn = con->optionStack->argv[0];
|
||||
/*@=nullderef@*/
|
||||
/*@=nullderef =type@*/
|
||||
/*@=boundsread@*/
|
||||
if (fn == NULL) return len;
|
||||
if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
|
||||
fprintf(fp, " %s", fn);
|
||||
@@ -477,7 +567,7 @@ static int showHelpIntro(poptContext con, FILE * fp)
|
||||
|
||||
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
|
||||
{
|
||||
int leftColWidth;
|
||||
size_t leftColWidth;
|
||||
|
||||
(void) showHelpIntro(con, fp);
|
||||
if (con->otherHelp)
|
||||
@@ -490,47 +580,76 @@ void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
|
||||
}
|
||||
|
||||
/**
|
||||
* Display usage text for an option.
|
||||
* @param fp output file handle
|
||||
* @param cursor current display position
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static int singleOptionUsage(FILE * fp, int cursor,
|
||||
static size_t singleOptionUsage(FILE * fp, size_t cursor,
|
||||
const struct poptOption * opt,
|
||||
/*@null@*/ const char *translation_domain)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
int len = 3;
|
||||
size_t len = 4;
|
||||
char shortStr[2] = { '\0', '\0' };
|
||||
const char * item = shortStr;
|
||||
const char * argDescrip = getArgDescrip(opt, translation_domain);
|
||||
|
||||
if (opt->shortName!= '\0' ) {
|
||||
if (!(opt->argInfo & POPT_ARG_MASK))
|
||||
return cursor; /* we did these already */
|
||||
if (opt->shortName != '\0' && opt->longName != NULL) {
|
||||
len += 2;
|
||||
if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
|
||||
len += strlen(opt->longName);
|
||||
} else if (opt->shortName != '\0') {
|
||||
len++;
|
||||
shortStr[0] = opt->shortName;
|
||||
shortStr[1] = '\0';
|
||||
} else if (opt->longName) {
|
||||
len += 1 + strlen(opt->longName);
|
||||
len += strlen(opt->longName);
|
||||
if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
|
||||
item = opt->longName;
|
||||
}
|
||||
|
||||
if (len == 3) return cursor;
|
||||
if (len == 4) return cursor;
|
||||
|
||||
#ifdef POPT_WCHAR_HACK
|
||||
/* XXX Calculate no. of display characters. */
|
||||
if (argDescrip) {
|
||||
const char * scopy = argDescrip;
|
||||
mbstate_t t;
|
||||
size_t n;
|
||||
|
||||
/*@-boundswrite@*/
|
||||
memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */
|
||||
/*@=boundswrite@*/
|
||||
/* Determine number of characters. */
|
||||
n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
|
||||
len += sizeof("=")-1 + n;
|
||||
}
|
||||
#else
|
||||
if (argDescrip)
|
||||
len += strlen(argDescrip) + 1;
|
||||
len += sizeof("=")-1 + strlen(argDescrip);
|
||||
#endif
|
||||
|
||||
if ((cursor + len) > 79) {
|
||||
fprintf(fp, "\n ");
|
||||
cursor = 7;
|
||||
}
|
||||
|
||||
fprintf(fp, " [-%s%s%s%s]",
|
||||
((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
|
||||
item,
|
||||
(argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
|
||||
(argDescrip ? argDescrip : ""));
|
||||
if (opt->longName && opt->shortName) {
|
||||
fprintf(fp, " [-%c|-%s%s%s%s]",
|
||||
opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"),
|
||||
opt->longName,
|
||||
(argDescrip ? " " : ""),
|
||||
(argDescrip ? argDescrip : ""));
|
||||
} else {
|
||||
fprintf(fp, " [-%s%s%s%s]",
|
||||
((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
|
||||
item,
|
||||
(argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
|
||||
(argDescrip ? argDescrip : ""));
|
||||
}
|
||||
|
||||
return cursor + len + 1;
|
||||
}
|
||||
@@ -538,12 +657,14 @@ static int singleOptionUsage(FILE * fp, int cursor,
|
||||
/**
|
||||
* Display popt alias and exec usage.
|
||||
* @param fp output file handle
|
||||
* @param cursor current display position
|
||||
* @param item alias/exec array
|
||||
* @param nitems no. of ara/exec entries
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
static size_t itemUsage(FILE * fp, size_t cursor,
|
||||
/*@null@*/ poptItem item, int nitems,
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
@@ -567,15 +688,30 @@ static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of option tables already processed.
|
||||
*/
|
||||
typedef struct poptDone_s {
|
||||
int nopts;
|
||||
int maxopts;
|
||||
const void ** opts;
|
||||
} * poptDone;
|
||||
|
||||
/**
|
||||
* Display usage text for a table of options.
|
||||
* @param con context
|
||||
* @param fp output file handle
|
||||
* @param cursor current display position
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
* @param done tables already processed
|
||||
* @return
|
||||
*/
|
||||
static int singleTableUsage(poptContext con, FILE * fp,
|
||||
int cursor, const struct poptOption * opt,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
static size_t singleTableUsage(poptContext con, FILE * fp, size_t cursor,
|
||||
/*@null@*/ const struct poptOption * opt,
|
||||
/*@null@*/ UNUSED(const char * translation_domain),
|
||||
/*@null@*/ poptDone done)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
/*@modifies *fp, done, fileSystem @*/
|
||||
{
|
||||
/*@-branchstate@*/ /* FIX: W2DO? */
|
||||
if (opt != NULL)
|
||||
@@ -583,9 +719,26 @@ static int singleTableUsage(poptContext con, FILE * fp,
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
|
||||
translation_domain = (const char *)opt->arg;
|
||||
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
|
||||
if (opt->arg) /* XXX program error */
|
||||
if (done) {
|
||||
int i = 0;
|
||||
for (i = 0; i < done->nopts; i++) {
|
||||
/*@-boundsread@*/
|
||||
const void * that = done->opts[i];
|
||||
/*@=boundsread@*/
|
||||
if (that == NULL || that != opt->arg)
|
||||
/*@innercontinue@*/ continue;
|
||||
/*@innerbreak@*/ break;
|
||||
}
|
||||
/* Skip if this table has already been processed. */
|
||||
if (opt->arg == NULL || i < done->nopts)
|
||||
continue;
|
||||
/*@-boundswrite@*/
|
||||
if (done->nopts < done->maxopts)
|
||||
done->opts[done->nopts++] = (const void *) opt->arg;
|
||||
/*@=boundswrite@*/
|
||||
}
|
||||
cursor = singleTableUsage(con, fp, cursor, opt->arg,
|
||||
translation_domain);
|
||||
translation_domain, done);
|
||||
} else if ((opt->longName || opt->shortName) &&
|
||||
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
|
||||
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
|
||||
@@ -598,6 +751,7 @@ static int singleTableUsage(poptContext con, FILE * fp,
|
||||
|
||||
/**
|
||||
* Return concatenated short options for display.
|
||||
* @todo Sub-tables should be recursed.
|
||||
* @param opt option(s)
|
||||
* @param fp output file handle
|
||||
* @retval str concatenation of short options
|
||||
@@ -607,42 +761,51 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
|
||||
/*@null@*/ char * str)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *str, *fp, fileSystem @*/
|
||||
/*@requires maxRead(str) >= 0 @*/
|
||||
{
|
||||
char * s = alloca(300); /* larger then the ascii set */
|
||||
|
||||
s[0] = '\0';
|
||||
/*@-branchstate@*/ /* FIX: W2DO? */
|
||||
if (str == NULL) {
|
||||
memset(s, 0, sizeof(s));
|
||||
str = s;
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
/* bufsize larger then the ascii set, lazy alloca on top level call. */
|
||||
char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
|
||||
int len = 0;
|
||||
|
||||
/*@-boundswrite@*/
|
||||
if (opt != NULL)
|
||||
for (; (opt->longName || opt->shortName || opt->arg); opt++) {
|
||||
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
|
||||
str[strlen(str)] = opt->shortName;
|
||||
s[strlen(s)] = opt->shortName;
|
||||
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
|
||||
if (opt->arg) /* XXX program error */
|
||||
(void) showShortOptions(opt->arg, fp, str);
|
||||
len = showShortOptions(opt->arg, fp, s);
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
if (s != str || *s != '\0')
|
||||
return 0;
|
||||
|
||||
fprintf(fp, " [-%s]", s);
|
||||
return strlen(s) + 4;
|
||||
/* On return to top level, print the short options, return print length. */
|
||||
if (s == str && *s != '\0') {
|
||||
fprintf(fp, " [-%s]", s);
|
||||
len = strlen(s) + sizeof(" [-]")-1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
|
||||
{
|
||||
int cursor;
|
||||
poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done));
|
||||
size_t cursor;
|
||||
|
||||
done->nopts = 0;
|
||||
done->maxopts = 64;
|
||||
cursor = done->maxopts * sizeof(*done->opts);
|
||||
/*@-boundswrite@*/
|
||||
done->opts = memset(alloca(cursor), 0, cursor);
|
||||
/*@-keeptrans@*/
|
||||
done->opts[done->nopts++] = (const void *) con->options;
|
||||
/*@=keeptrans@*/
|
||||
/*@=boundswrite@*/
|
||||
|
||||
cursor = showHelpIntro(con, fp);
|
||||
cursor += showShortOptions(con->options, fp, NULL);
|
||||
(void) singleTableUsage(con, fp, cursor, con->options, NULL);
|
||||
(void) itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
|
||||
(void) itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
|
||||
cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done);
|
||||
cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
|
||||
cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
|
||||
|
||||
if (con->otherHelp) {
|
||||
cursor += strlen(con->otherHelp) + 1;
|
||||
@@ -658,4 +821,3 @@ void poptSetOtherOptionHelp(poptContext con, const char * text)
|
||||
con->otherHelp = _free(con->otherHelp);
|
||||
con->otherHelp = xstrdup(text);
|
||||
}
|
||||
/*@=type@*/
|
||||
|
||||
@@ -22,14 +22,24 @@ _free(/*@only@*/ /*@null@*/ const void * p)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
isSpace(const char *ptr)
|
||||
{
|
||||
return isspace(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
/* Bit mask macros. */
|
||||
/*@-exporttype -redef @*/
|
||||
typedef unsigned int __pbm_bits;
|
||||
/*@=exporttype =redef @*/
|
||||
#define __PBM_NBITS (8 * sizeof (__pbm_bits))
|
||||
#define __PBM_IX(d) ((d) / __PBM_NBITS)
|
||||
#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
|
||||
/*@-exporttype -redef @*/
|
||||
typedef struct {
|
||||
__pbm_bits bits[1];
|
||||
} pbm_set;
|
||||
/*@=exporttype =redef @*/
|
||||
#define __PBM_BITS(set) ((set)->bits)
|
||||
|
||||
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
|
||||
@@ -40,37 +50,53 @@ typedef struct {
|
||||
|
||||
struct optionStackEntry {
|
||||
int argc;
|
||||
/*@only@*/ /*@null@*/ const char ** argv;
|
||||
/*@only@*/ /*@null@*/ pbm_set * argb;
|
||||
/*@only@*/ /*@null@*/
|
||||
const char ** argv;
|
||||
/*@only@*/ /*@null@*/
|
||||
pbm_set * argb;
|
||||
int next;
|
||||
/*@only@*/ /*@null@*/ const char * nextArg;
|
||||
/*@keep@*/ /*@null@*/ const char * nextCharArg;
|
||||
/*@dependent@*/ /*@null@*/ poptItem currAlias;
|
||||
/*@only@*/ /*@null@*/
|
||||
const char * nextArg;
|
||||
/*@observer@*/ /*@null@*/
|
||||
const char * nextCharArg;
|
||||
/*@dependent@*/ /*@null@*/
|
||||
poptItem currAlias;
|
||||
int stuffed;
|
||||
};
|
||||
|
||||
struct poptContext_s {
|
||||
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
|
||||
/*@dependent@*/ struct optionStackEntry * os;
|
||||
/*@owned@*/ /*@null@*/ const char ** leftovers;
|
||||
/*@dependent@*/
|
||||
struct optionStackEntry * os;
|
||||
/*@owned@*/ /*@null@*/
|
||||
const char ** leftovers;
|
||||
int numLeftovers;
|
||||
int nextLeftover;
|
||||
/*@keep@*/ const struct poptOption * options;
|
||||
/*@keep@*/
|
||||
const struct poptOption * options;
|
||||
int restLeftover;
|
||||
/*@only@*/ /*@null@*/ const char * appName;
|
||||
/*@only@*/ /*@null@*/ poptItem aliases;
|
||||
/*@only@*/ /*@null@*/
|
||||
const char * appName;
|
||||
/*@only@*/ /*@null@*/
|
||||
poptItem aliases;
|
||||
int numAliases;
|
||||
int flags;
|
||||
/*@owned@*/ /*@null@*/ poptItem execs;
|
||||
/*@owned@*/ /*@null@*/
|
||||
poptItem execs;
|
||||
int numExecs;
|
||||
/*@only@*/ /*@null@*/ const char ** finalArgv;
|
||||
/*@only@*/ /*@null@*/
|
||||
const char ** finalArgv;
|
||||
int finalArgvCount;
|
||||
int finalArgvAlloced;
|
||||
/*@dependent@*/ /*@null@*/ poptItem doExec;
|
||||
/*@only@*/ const char * execPath;
|
||||
/*@dependent@*/ /*@null@*/
|
||||
poptItem doExec;
|
||||
/*@only@*/
|
||||
const char * execPath;
|
||||
int execAbsolute;
|
||||
/*@only@*/ const char * otherHelp;
|
||||
/*@null@*/ pbm_set * arg_strip;
|
||||
/*@only@*/ /*@relnull@*/
|
||||
const char * otherHelp;
|
||||
/*@null@*/
|
||||
pbm_set * arg_strip;
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
@@ -83,7 +109,7 @@ struct poptContext_s {
|
||||
#define _(foo) foo
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_DGETTEXT) && !defined(__LCLINT__)
|
||||
#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
|
||||
#define D_(dom, str) dgettext(dom, str)
|
||||
#define POPT_(foo) D_("popt", foo)
|
||||
#else
|
||||
|
||||
123
popt/poptparse.c
123
popt/poptparse.c
@@ -2,14 +2,17 @@
|
||||
* \file popt/poptparse.c
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "poptint.h"
|
||||
|
||||
#define POPT_ARGV_ARRAY_GROW_DELTA 5
|
||||
|
||||
/*@-boundswrite@*/
|
||||
int poptDupArgv(int argc, const char **argv,
|
||||
int * argcPtr, const char *** argvPtr)
|
||||
{
|
||||
@@ -35,7 +38,7 @@ int poptDupArgv(int argc, const char **argv,
|
||||
/*@-branchstate@*/
|
||||
for (i = 0; i < argc; i++) {
|
||||
argv2[i] = dst;
|
||||
dst += strlen(strcpy(dst, argv[i])) + 1;
|
||||
dst += strlcpy(dst, argv[i], nb) + 1;
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
argv2[argc] = NULL;
|
||||
@@ -50,11 +53,13 @@ int poptDupArgv(int argc, const char **argv,
|
||||
*argcPtr = argc;
|
||||
return 0;
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** argvPtr)
|
||||
/*@-bounds@*/
|
||||
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
|
||||
{
|
||||
const unsigned char * src;
|
||||
unsigned char quote = '\0';
|
||||
const char * src;
|
||||
char quote = '\0';
|
||||
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
|
||||
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
|
||||
int argc = 0;
|
||||
@@ -78,7 +83,7 @@ int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** a
|
||||
if (*src != quote) *buf++ = '\\';
|
||||
}
|
||||
*buf++ = *src;
|
||||
} else if (isspace(*src)) {
|
||||
} else if (isSpace(src)) {
|
||||
if (*argv[argc] != '\0') {
|
||||
buf++, argc++;
|
||||
if (argc == argvAlloced) {
|
||||
@@ -116,3 +121,109 @@ exit:
|
||||
if (argv) free(argv);
|
||||
return rc;
|
||||
}
|
||||
/*@=bounds@*/
|
||||
|
||||
/* still in the dev stage.
|
||||
* return values, perhaps 1== file erro
|
||||
* 2== line to long
|
||||
* 3== umm.... more?
|
||||
*/
|
||||
int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int flags))
|
||||
{
|
||||
char line[999];
|
||||
char * argstr;
|
||||
char * p;
|
||||
char * q;
|
||||
char * x;
|
||||
int t;
|
||||
int argvlen = 0;
|
||||
size_t maxlinelen = sizeof(line);
|
||||
size_t linelen;
|
||||
int maxargvlen = 480;
|
||||
int linenum = 0;
|
||||
|
||||
*argstrp = NULL;
|
||||
|
||||
/* | this_is = our_line
|
||||
* p q x
|
||||
*/
|
||||
|
||||
if (fp == NULL)
|
||||
return POPT_ERROR_NULLARG;
|
||||
|
||||
argstr = calloc(maxargvlen, sizeof(*argstr));
|
||||
if (argstr == NULL) return POPT_ERROR_MALLOC;
|
||||
|
||||
while (fgets(line, (int)maxlinelen, fp) != NULL) {
|
||||
linenum++;
|
||||
p = line;
|
||||
|
||||
/* loop until first non-space char or EOL */
|
||||
while( *p != '\0' && isSpace(p) )
|
||||
p++;
|
||||
|
||||
linelen = strlen(p);
|
||||
if (linelen >= maxlinelen-1)
|
||||
return POPT_ERROR_OVERFLOW; /* XXX line too long */
|
||||
|
||||
if (*p == '\0' || *p == '\n') continue; /* line is empty */
|
||||
if (*p == '#') continue; /* comment line */
|
||||
|
||||
q = p;
|
||||
|
||||
while (*q != '\0' && (!isSpace(q)) && *q != '=')
|
||||
q++;
|
||||
|
||||
if (isSpace(q)) {
|
||||
/* a space after the name, find next non space */
|
||||
*q++='\0';
|
||||
while( *q != '\0' && isSpace(q) ) q++;
|
||||
}
|
||||
if (*q == '\0') {
|
||||
/* single command line option (ie, no name=val, just name) */
|
||||
q[-1] = '\0'; /* kill off newline from fgets() call */
|
||||
argvlen += (t = q - p) + (sizeof(" --")-1);
|
||||
if (argvlen >= maxargvlen) {
|
||||
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
|
||||
argstr = realloc(argstr, maxargvlen);
|
||||
if (argstr == NULL) return POPT_ERROR_MALLOC;
|
||||
}
|
||||
strlcat(argstr, " --", maxargvlen);
|
||||
strlcat(argstr, p, maxargvlen);
|
||||
continue;
|
||||
}
|
||||
if (*q != '=')
|
||||
continue; /* XXX for now, silently ignore bogus line */
|
||||
|
||||
/* *q is an equal sign. */
|
||||
*q++ = '\0';
|
||||
|
||||
/* find next non-space letter of value */
|
||||
while (*q != '\0' && isSpace(q))
|
||||
q++;
|
||||
if (*q == '\0')
|
||||
continue; /* XXX silently ignore missing value */
|
||||
|
||||
/* now, loop and strip all ending whitespace */
|
||||
x = p + linelen;
|
||||
while (isSpace(--x))
|
||||
*x = 0; /* null out last char if space (including fgets() NL) */
|
||||
|
||||
/* rest of line accept */
|
||||
t = x - p;
|
||||
argvlen += t + (sizeof("' --='")-1);
|
||||
if (argvlen >= maxargvlen) {
|
||||
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
|
||||
argstr = realloc(argstr, maxargvlen);
|
||||
if (argstr == NULL) return POPT_ERROR_MALLOC;
|
||||
}
|
||||
strlcat(argstr, " --", maxargvlen);
|
||||
strlcat(argstr, p, maxargvlen);
|
||||
strlcat(argstr, "=\"", maxargvlen);
|
||||
strlcat(argstr, q, maxargvlen);
|
||||
strlcat(argstr, "\"", maxargvlen);
|
||||
}
|
||||
|
||||
*argstrp = argstr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,17 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined (__GLIBC__) && defined(__LCLINT__)
|
||||
/*@-declundef@*/
|
||||
/*@unchecked@*/
|
||||
extern __const __int32_t *__ctype_tolower;
|
||||
/*@unchecked@*/
|
||||
extern __const __int32_t *__ctype_toupper;
|
||||
/*@=declundef@*/
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
@@ -12,19 +22,32 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__GNUC__) || defined(APPLE)
|
||||
/* Apparently the OS X port of gcc gags on __attribute__.
|
||||
*
|
||||
* <http://www.opensource.apple.com/bugs/X/gcc/2512150.html> */
|
||||
#ifndef __GNUC__
|
||||
#define __attribute__(x)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __NeXT
|
||||
@@ -34,11 +57,12 @@
|
||||
#endif
|
||||
|
||||
#if defined(__LCLINT__)
|
||||
/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */
|
||||
/*@only@*/ void * alloca (size_t __size)
|
||||
/*@-declundef -incondefs @*/ /* LCL: missing annotation */
|
||||
/*@only@*/ /*@out@*/
|
||||
void * alloca (size_t __size)
|
||||
/*@ensures MaxSet(result) == (__size - 1) @*/
|
||||
/*@*/;
|
||||
/*@=declundef =incondefs =redecl@*/
|
||||
/*@=declundef =incondefs @*/
|
||||
#endif
|
||||
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
@@ -49,9 +73,9 @@
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# if HAVE_ALLOCA
|
||||
# ifdef HAVE_ALLOCA
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
char *alloca(size_t size);
|
||||
# endif
|
||||
# else
|
||||
# ifdef alloca
|
||||
@@ -65,18 +89,42 @@ char *alloca ();
|
||||
#define alloca __builtin_alloca
|
||||
#endif
|
||||
|
||||
/*@-redecl -redef@*/
|
||||
/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str)
|
||||
/*@*/;
|
||||
/*@=redecl =redef@*/
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char *d, const char *s, size_t bufsize);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
size_t strlcat(char *d, const char *s, size_t bufsize);
|
||||
#endif
|
||||
|
||||
#if HAVE_MCHECK_H && defined(__GNUC__)
|
||||
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)
|
||||
#define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str)))
|
||||
static inline char *
|
||||
xstrdup(const char *s)
|
||||
{
|
||||
size_t memsize = strlen(s) + 1;
|
||||
char *ptr = malloc(memsize);
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "virtual memory exhausted.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strlcpy(ptr, s, memsize);
|
||||
return ptr;
|
||||
}
|
||||
#else
|
||||
#define xstrdup(_str) strdup(_str)
|
||||
#endif /* HAVE_MCHECK_H && defined(__GNUC__) */
|
||||
|
||||
#if HAVE___SECURE_GETENV && !defined(__LCLINT__)
|
||||
#define getenv(_s) __secure_getenv(_s)
|
||||
#endif
|
||||
|
||||
#if !defined HAVE_SNPRINTF || !defined HAVE_C99_VSNPRINTF
|
||||
#define snprintf rsync_snprintf
|
||||
int snprintf(char *str,size_t count,const char *fmt,...);
|
||||
#endif
|
||||
|
||||
#define UNUSED(x) x __attribute__((__unused__))
|
||||
|
||||
#define PACKAGE "rsync"
|
||||
|
||||
#include "popt.h"
|
||||
|
||||
12
prepare-source
Executable file
12
prepare-source
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
# Use autoconf, autoheader, yodl, etc. to ready the generated files in the
|
||||
# release. This is typically used after applying a diff from the "patches"
|
||||
# directory in a CVS-checked-out version.
|
||||
#
|
||||
# NOTE: if you use a diff from the "patches" directory of a *release tar*
|
||||
# (as opposed to from CVS), this is not needed (but doesn't hurt anything).
|
||||
dir=`dirname $0`
|
||||
if test x"$dir" != x -a x"$dir" != x.; then
|
||||
cd "$dir"
|
||||
fi
|
||||
make -f prepare-source.mak
|
||||
25
prepare-source.mak
Normal file
25
prepare-source.mak
Normal file
@@ -0,0 +1,25 @@
|
||||
gen: configure config.h.in proto.h man
|
||||
|
||||
configure: configure.in aclocal.m4
|
||||
autoconf
|
||||
|
||||
config.h.in: configure.in aclocal.m4
|
||||
autoheader && touch config.h.in
|
||||
|
||||
proto.h: *.c lib/compat.c
|
||||
cat *.c lib/compat.c | awk -f mkproto.awk >proto.h.new
|
||||
if diff proto.h proto.h.new >/dev/null; then \
|
||||
rm proto.h.new; \
|
||||
else \
|
||||
mv proto.h.new proto.h; \
|
||||
fi
|
||||
|
||||
man: rsync.1 rsyncd.conf.5
|
||||
|
||||
rsync.1: rsync.yo
|
||||
yodl2man -o rsync.1 rsync.yo
|
||||
-./tweak_manpage rsync.1
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.yo
|
||||
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
|
||||
-./tweak_manpage rsyncd.conf.5
|
||||
75
progress.c
75
progress.c
@@ -1,12 +1,14 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
/*
|
||||
* Routines to output progress information during a file transfer.
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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 of the License, or
|
||||
* 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,
|
||||
@@ -14,9 +16,8 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
@@ -26,6 +27,12 @@ extern int am_server;
|
||||
|
||||
#define PROGRESS_HISTORY_SECS 5
|
||||
|
||||
#ifdef GETPGRP_VOID
|
||||
#define GETPGRP_ARG
|
||||
#else
|
||||
#define GETPGRP_ARG 0
|
||||
#endif
|
||||
|
||||
struct progress_history {
|
||||
struct timeval time;
|
||||
OFF_T ofs;
|
||||
@@ -52,26 +59,26 @@ static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
|
||||
static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
|
||||
int is_last)
|
||||
{
|
||||
char eol[256];
|
||||
char rembuf[64], eol[128];
|
||||
const char *units;
|
||||
int pct = ofs == size ? 100 : (int) (100.0 * ofs / size);
|
||||
unsigned long diff;
|
||||
double rate, remain;
|
||||
int remain_h, remain_m, remain_s;
|
||||
|
||||
if (is_last) {
|
||||
/* Compute stats based on the starting info. */
|
||||
diff = msdiff(&ph_start.time, now);
|
||||
if (!diff)
|
||||
if (!ph_start.time.tv_sec
|
||||
|| !(diff = msdiff(&ph_start.time, now)))
|
||||
diff = 1;
|
||||
rate = (double) (ofs - ph_start.ofs) * 1000.0 / diff / 1024.0;
|
||||
/* Switch to total time taken for our last update. */
|
||||
remain = (double) diff / 1000.0;
|
||||
} else {
|
||||
/* Compute stats based on recent progress. */
|
||||
diff = msdiff(&ph_list[oldest_hpos].time, now);
|
||||
rate = diff ? (double) (ofs - ph_list[oldest_hpos].ofs) * 1000.0
|
||||
/ diff / 1024.0 : 0;
|
||||
if (!(diff = msdiff(&ph_list[oldest_hpos].time, now)))
|
||||
diff = 1;
|
||||
rate = (double) (ofs - ph_list[oldest_hpos].ofs) * 1000.0
|
||||
/ diff / 1024.0;
|
||||
remain = rate ? (double) (size - ofs) / rate / 1000.0 : 0.0;
|
||||
}
|
||||
|
||||
@@ -85,21 +92,24 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
|
||||
units = "kB/s";
|
||||
}
|
||||
|
||||
remain_s = (int) remain % 60;
|
||||
remain_m = (int) (remain / 60.0) % 60;
|
||||
remain_h = (int) (remain / 3600.0);
|
||||
if (remain < 0)
|
||||
strlcpy(rembuf, " ??:??:??", sizeof rembuf);
|
||||
else {
|
||||
snprintf(rembuf, sizeof rembuf, "%4d:%02d:%02d",
|
||||
(int) (remain / 3600.0),
|
||||
(int) (remain / 60.0) % 60,
|
||||
(int) remain % 60);
|
||||
}
|
||||
|
||||
if (is_last) {
|
||||
snprintf(eol, sizeof eol, " (%d, %.1f%% of %d)\n",
|
||||
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
|
||||
stats.num_transferred_files,
|
||||
(float)((stats.current_file_index+1) * 100)
|
||||
/ stats.num_files,
|
||||
stats.num_files - stats.current_file_index - 1,
|
||||
stats.num_files);
|
||||
} else
|
||||
strcpy(eol, "\r");
|
||||
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
|
||||
(double) ofs, pct, rate, units,
|
||||
remain_h, remain_m, remain_s, eol);
|
||||
strlcpy(eol, "\r", sizeof eol);
|
||||
rprintf(FCLIENT, "%12s %3d%% %7.2f%s %s%s",
|
||||
human_num(ofs), pct, rate, units, rembuf, eol);
|
||||
}
|
||||
|
||||
void end_progress(OFF_T size)
|
||||
@@ -115,10 +125,19 @@ void end_progress(OFF_T size)
|
||||
void show_progress(OFF_T ofs, OFF_T size)
|
||||
{
|
||||
struct timeval now;
|
||||
#if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
|
||||
static pid_t pgrp = -1;
|
||||
pid_t tc_pgrp;
|
||||
#endif
|
||||
|
||||
if (am_server)
|
||||
return;
|
||||
|
||||
#if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
|
||||
if (pgrp == -1)
|
||||
pgrp = getpgrp(GETPGRP_ARG);
|
||||
#endif
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
if (!ph_start.time.tv_sec) {
|
||||
@@ -150,5 +169,11 @@ void show_progress(OFF_T ofs, OFF_T size)
|
||||
ph_list[newest_hpos].ofs = ofs;
|
||||
}
|
||||
|
||||
#if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
|
||||
tc_pgrp = tcgetpgrp(STDOUT_FILENO);
|
||||
if (tc_pgrp != pgrp && tc_pgrp != -1)
|
||||
return;
|
||||
#endif
|
||||
|
||||
rprint_progress(ofs, size, &now, False);
|
||||
}
|
||||
|
||||
817
receiver.c
817
receiver.c
@@ -1,132 +1,66 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* Routines only used by the receiving process.
|
||||
*
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
extern int delete_after;
|
||||
extern int max_delete;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int dry_run;
|
||||
extern int do_xfers;
|
||||
extern int am_server;
|
||||
extern int do_progress;
|
||||
extern int inc_recurse;
|
||||
extern int log_before_transfer;
|
||||
extern int stdout_format_has_i;
|
||||
extern int logfile_format_has_i;
|
||||
extern int csum_length;
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
extern int batch_gen_fd;
|
||||
extern int protocol_version;
|
||||
extern int relative_paths;
|
||||
extern int preserve_hard_links;
|
||||
extern int preserve_perms;
|
||||
extern int cvs_exclude;
|
||||
extern int io_error;
|
||||
extern char *tmpdir;
|
||||
extern char *compare_dest;
|
||||
extern int preserve_xattrs;
|
||||
extern int basis_dir_cnt;
|
||||
extern int make_backups;
|
||||
extern int do_progress;
|
||||
extern char *backup_dir;
|
||||
extern char *backup_suffix;
|
||||
extern int backup_suffix_len;
|
||||
extern int cleanup_got_literal;
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
extern int orig_umask;
|
||||
|
||||
static void delete_one(char *fn, int is_dir)
|
||||
{
|
||||
if (!is_dir) {
|
||||
if (robust_unlink(fn) != 0) {
|
||||
rprintf(FERROR, "delete_one: unlink %s failed: %s\n",
|
||||
full_fname(fn), strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO, "deleting %s\n", fn);
|
||||
}
|
||||
} else {
|
||||
if (do_rmdir(fn) != 0) {
|
||||
if (errno != ENOTEMPTY && errno != EEXIST) {
|
||||
rprintf(FERROR, "delete_one: rmdir %s failed: %s\n",
|
||||
full_fname(fn), strerror(errno));
|
||||
}
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO, "deleting directory %s\n", fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int is_backup_file(char *fn)
|
||||
{
|
||||
int k = strlen(fn) - backup_suffix_len;
|
||||
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
|
||||
}
|
||||
|
||||
|
||||
/* This deletes any files on the receiving side that are not present
|
||||
* on the sending side. */
|
||||
void delete_files(struct file_list *flist)
|
||||
{
|
||||
struct file_list *local_file_list;
|
||||
int i, j;
|
||||
char *argv[1], fbuf[MAXPATHLEN];
|
||||
static int deletion_count;
|
||||
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
|
||||
if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
|
||||
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < flist->count; j++) {
|
||||
if (!(flist->files[j]->flags & FLAG_TOP_DIR)
|
||||
|| !S_ISDIR(flist->files[j]->mode))
|
||||
continue;
|
||||
|
||||
argv[0] = f_name_to(flist->files[j], fbuf);
|
||||
|
||||
if (!(local_file_list = send_file_list(-1, 1, argv)))
|
||||
continue;
|
||||
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "deleting in %s\n", fbuf);
|
||||
|
||||
for (i = local_file_list->count-1; i >= 0; i--) {
|
||||
if (max_delete && deletion_count > max_delete)
|
||||
break;
|
||||
if (!local_file_list->files[i]->basename)
|
||||
continue;
|
||||
if (flist_find(flist,local_file_list->files[i]) < 0) {
|
||||
char *f = f_name(local_file_list->files[i]);
|
||||
if (make_backups && (backup_dir || !is_backup_file(f))) {
|
||||
(void) make_backup(f);
|
||||
if (verbose)
|
||||
rprintf(FINFO, "deleting %s\n", f);
|
||||
} else {
|
||||
int mode = local_file_list->files[i]->mode;
|
||||
delete_one(f, S_ISDIR(mode) != 0);
|
||||
}
|
||||
deletion_count++;
|
||||
}
|
||||
}
|
||||
flist_free(local_file_list);
|
||||
}
|
||||
}
|
||||
extern int remove_source_files;
|
||||
extern int append_mode;
|
||||
extern int sparse_files;
|
||||
extern int keep_partial;
|
||||
extern int checksum_seed;
|
||||
extern int inplace;
|
||||
extern int delay_updates;
|
||||
extern mode_t orig_umask;
|
||||
extern struct stats stats;
|
||||
extern char *tmpdir;
|
||||
extern char *partial_dir;
|
||||
extern char *basis_dir[];
|
||||
extern struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
|
||||
static struct bitbag *delayed_bits = NULL;
|
||||
static int phase = 0, redoing = 0;
|
||||
/* We're either updating the basis file or an identical copy: */
|
||||
static int updating_basis;
|
||||
|
||||
/*
|
||||
* get_tmpname() - create a tmp filename for a given filename
|
||||
@@ -149,17 +83,15 @@ void delete_files(struct file_list *flist)
|
||||
* As long as it's unique, rsync will work.
|
||||
*/
|
||||
|
||||
static int get_tmpname(char *fnametmp, char *fname)
|
||||
int get_tmpname(char *fnametmp, char *fname)
|
||||
{
|
||||
int maxname, added, length = 0;
|
||||
char *f;
|
||||
int length = 0;
|
||||
int maxname;
|
||||
|
||||
if (tmpdir) {
|
||||
/* Note: this can't overflow, so the return value is safe */
|
||||
length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
|
||||
fnametmp[length++] = '/';
|
||||
fnametmp[length] = '\0'; /* always NULL terminated */
|
||||
}
|
||||
|
||||
if ((f = strrchr(fname, '/')) != NULL) {
|
||||
@@ -172,8 +104,9 @@ static int get_tmpname(char *fnametmp, char *fname)
|
||||
} else
|
||||
f = fname;
|
||||
fnametmp[length++] = '.';
|
||||
fnametmp[length] = '\0'; /* always NULL terminated */
|
||||
|
||||
/* The maxname value is bufsize, and includes space for the '\0'.
|
||||
* (Note that NAME_MAX get -8 for the leading '.' above.) */
|
||||
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
|
||||
|
||||
if (maxname < 1) {
|
||||
@@ -182,29 +115,70 @@ static int get_tmpname(char *fnametmp, char *fname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
strlcpy(fnametmp + length, f, maxname);
|
||||
strcat(fnametmp + length, ".XXXXXX");
|
||||
added = strlcpy(fnametmp + length, f, maxname);
|
||||
if (added >= maxname)
|
||||
added = maxname - 1;
|
||||
memcpy(fnametmp + length + added, ".XXXXXX", 8);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
|
||||
OFF_T total_size)
|
||||
static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
const char *fname, int fd, OFF_T total_size)
|
||||
{
|
||||
int i;
|
||||
static char file_sum1[MAX_DIGEST_LEN];
|
||||
static char file_sum2[MAX_DIGEST_LEN];
|
||||
struct map_struct *mapbuf;
|
||||
struct sum_struct sum;
|
||||
unsigned int len;
|
||||
int32 len, sum_len;
|
||||
OFF_T offset = 0;
|
||||
OFF_T offset2;
|
||||
char *data;
|
||||
static char file_sum1[MD4_SUM_LENGTH];
|
||||
static char file_sum2[MD4_SUM_LENGTH];
|
||||
char *map=NULL;
|
||||
int32 i;
|
||||
char *map = NULL;
|
||||
|
||||
read_sum_head(f_in, &sum);
|
||||
|
||||
sum_init();
|
||||
if (fd_r >= 0 && size_r > 0) {
|
||||
int32 read_size = MAX(sum.blength * 2, 16*1024);
|
||||
mapbuf = map_file(fd_r, size_r, read_size, sum.blength);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "recv mapped %s of size %.0f\n",
|
||||
fname_r, (double)size_r);
|
||||
}
|
||||
} else
|
||||
mapbuf = NULL;
|
||||
|
||||
sum_init(checksum_seed);
|
||||
|
||||
if (append_mode > 0) {
|
||||
OFF_T j;
|
||||
sum.flength = (OFF_T)sum.count * sum.blength;
|
||||
if (sum.remainder)
|
||||
sum.flength -= sum.blength - sum.remainder;
|
||||
if (append_mode == 2) {
|
||||
for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
|
||||
if (do_progress)
|
||||
show_progress(offset, total_size);
|
||||
sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
|
||||
CHUNK_SIZE);
|
||||
offset = j;
|
||||
}
|
||||
if (offset < sum.flength) {
|
||||
int32 len = (int32)(sum.flength - offset);
|
||||
if (do_progress)
|
||||
show_progress(offset, total_size);
|
||||
sum_update(map_ptr(mapbuf, offset, len), len);
|
||||
}
|
||||
}
|
||||
offset = sum.flength;
|
||||
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
|
||||
rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
|
||||
full_fname(fname), (double)j, (double)offset);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
}
|
||||
|
||||
while ((i = recv_token(f_in, &data)) != 0) {
|
||||
if (do_progress)
|
||||
@@ -219,161 +193,377 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
|
||||
stats.literal_data += i;
|
||||
cleanup_got_literal = 1;
|
||||
|
||||
sum_update(data,i);
|
||||
sum_update(data, i);
|
||||
|
||||
if (fd != -1 && write_file(fd,data,i) != i) {
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
if (fd != -1 && write_file(fd,data,i) != i)
|
||||
goto report_write_error;
|
||||
offset += i;
|
||||
continue;
|
||||
}
|
||||
|
||||
i = -(i+1);
|
||||
offset2 = i*(OFF_T)sum.blength;
|
||||
offset2 = i * (OFF_T)sum.blength;
|
||||
len = sum.blength;
|
||||
if (i == (int) sum.count-1 && sum.remainder != 0)
|
||||
if (i == (int)sum.count-1 && sum.remainder != 0)
|
||||
len = sum.remainder;
|
||||
|
||||
stats.matched_data += len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
|
||||
i,len,(double)offset2,(double)offset);
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"chunk[%d] of size %ld at %.0f offset=%.0f\n",
|
||||
i, (long)len, (double)offset2, (double)offset);
|
||||
}
|
||||
|
||||
if (mapbuf) {
|
||||
map = map_ptr(mapbuf,offset2,len);
|
||||
|
||||
see_token(map, len);
|
||||
sum_update(map,len);
|
||||
sum_update(map, len);
|
||||
}
|
||||
|
||||
if (fd != -1 && write_file(fd,map,len) != (int) len) {
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
if (updating_basis) {
|
||||
if (offset == offset2 && fd != -1) {
|
||||
OFF_T pos;
|
||||
if (flush_write_file(fd) < 0)
|
||||
goto report_write_error;
|
||||
offset += len;
|
||||
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
|
||||
rsyserr(FERROR, errno,
|
||||
"lseek of %s returned %.0f, not %.0f",
|
||||
full_fname(fname),
|
||||
(double)pos, (double)offset);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (fd != -1 && map && write_file(fd, map, len) != (int)len)
|
||||
goto report_write_error;
|
||||
offset += len;
|
||||
}
|
||||
|
||||
flush_write_file(fd);
|
||||
if (flush_write_file(fd) < 0)
|
||||
goto report_write_error;
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
if (inplace && fd != -1)
|
||||
ftruncate(fd, offset);
|
||||
#endif
|
||||
|
||||
if (do_progress)
|
||||
end_progress(total_size);
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
report_write_error:
|
||||
rsyserr(FERROR, errno, "write failed on %s",
|
||||
full_fname(fname));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
sum_end(file_sum1);
|
||||
sum_len = sum_end(file_sum1);
|
||||
|
||||
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
|
||||
if (verbose > 2) {
|
||||
if (mapbuf)
|
||||
unmap_file(mapbuf);
|
||||
|
||||
read_buf(f_in, file_sum2, sum_len);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"got file_sum\n");
|
||||
}
|
||||
if (fd != -1 && memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
|
||||
if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void discard_receive_data(int f_in, OFF_T length)
|
||||
{
|
||||
receive_data(f_in, NULL, -1, 0, NULL, -1, length);
|
||||
}
|
||||
|
||||
static void handle_delayed_updates(char *local_name)
|
||||
{
|
||||
char *fname, *partialptr;
|
||||
int ndx;
|
||||
|
||||
for (ndx = -1; (ndx = bitbag_next_bit(delayed_bits, ndx)) >= 0; ) {
|
||||
struct file_struct *file = cur_flist->files[ndx];
|
||||
fname = local_name ? local_name : f_name(file, NULL);
|
||||
if ((partialptr = partial_dir_fname(fname)) != NULL) {
|
||||
if (make_backups > 0 && !make_backup(fname))
|
||||
continue;
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "renaming %s to %s\n",
|
||||
partialptr, fname);
|
||||
}
|
||||
/* We don't use robust_rename() here because the
|
||||
* partial-dir must be on the same drive. */
|
||||
if (do_rename(partialptr, fname) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"rename failed for %s (from %s)",
|
||||
full_fname(fname), partialptr);
|
||||
} else {
|
||||
if (remove_source_files
|
||||
|| (preserve_hard_links && F_IS_HLINKED(file)))
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
|
||||
{
|
||||
while (next_gen_ndx < desired_ndx) {
|
||||
if (next_gen_ndx >= 0) {
|
||||
rprintf(FINFO,
|
||||
"(No batched update for%s \"%s\")\n",
|
||||
redoing ? " resend of" : "",
|
||||
f_name(cur_flist->files[next_gen_ndx], NULL));
|
||||
}
|
||||
next_gen_ndx = read_int(fd);
|
||||
if (next_gen_ndx == -1) {
|
||||
if (inc_recurse)
|
||||
next_gen_ndx = first_flist->prev->used + first_flist->prev->ndx_start;
|
||||
else
|
||||
next_gen_ndx = cur_flist->used;
|
||||
}
|
||||
}
|
||||
return next_gen_ndx;
|
||||
}
|
||||
|
||||
/**
|
||||
* main routine for receiver process.
|
||||
*
|
||||
* Receiver process runs on the same host as the generator process. */
|
||||
int recv_files(int f_in,struct file_list *flist,char *local_name)
|
||||
int recv_files(int f_in, char *local_name)
|
||||
{
|
||||
int next_gen_ndx = -1;
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
int iflags, xlen;
|
||||
char *fname, fbuf[MAXPATHLEN];
|
||||
char template[MAXPATHLEN];
|
||||
char xname[MAXPATHLEN];
|
||||
char fnametmp[MAXPATHLEN];
|
||||
char *fnamecmp;
|
||||
char *fnamecmp, *partialptr;
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
struct map_struct *mapbuf;
|
||||
int i;
|
||||
uchar fnamecmp_type;
|
||||
struct file_struct *file;
|
||||
int phase=0;
|
||||
int recv_ok;
|
||||
struct stats initial_stats;
|
||||
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
|
||||
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
|
||||
int max_phase = protocol_version >= 29 ? 2 : 1;
|
||||
int dflt_perms = (ACCESSPERMS & ~orig_umask);
|
||||
#ifdef SUPPORT_ACLS
|
||||
const char *parent_dirname = "";
|
||||
#endif
|
||||
int ndx, recv_ok;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
|
||||
|
||||
if (flist->hlink_pool) {
|
||||
pool_destroy(flist->hlink_pool);
|
||||
flist->hlink_pool = NULL;
|
||||
}
|
||||
if (delay_updates)
|
||||
delayed_bits = bitbag_create(cur_flist->used + 1);
|
||||
|
||||
updating_basis = inplace;
|
||||
|
||||
while (1) {
|
||||
cleanup_disable();
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase == 0) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files phase=%d\n",phase);
|
||||
send_msg(MSG_DONE, "", 0);
|
||||
continue;
|
||||
/* This call also sets cur_flist. */
|
||||
ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
|
||||
xname, &xlen);
|
||||
if (ndx == NDX_DONE) {
|
||||
if (inc_recurse && first_flist) {
|
||||
flist_free(first_flist);
|
||||
if (first_flist)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
if (read_batch && cur_flist) {
|
||||
int high = inc_recurse
|
||||
? first_flist->prev->used + first_flist->prev->ndx_start
|
||||
: cur_flist->used;
|
||||
get_next_gen_ndx(batch_gen_fd, next_gen_ndx, high);
|
||||
next_gen_ndx = -1;
|
||||
}
|
||||
if (++phase > max_phase)
|
||||
break;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "recv_files phase=%d\n", phase);
|
||||
if (phase == 2 && delay_updates)
|
||||
handle_delayed_updates(local_name);
|
||||
send_msg(MSG_DONE, "", 0, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
|
||||
i, flist->count);
|
||||
if (ndx - cur_flist->ndx_start >= 0)
|
||||
file = cur_flist->files[ndx - cur_flist->ndx_start];
|
||||
else
|
||||
file = dir_flist->files[cur_flist->parent_ndx];
|
||||
fname = local_name ? local_name : f_name(file, fbuf);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "recv_files(%s)\n", fname);
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (iflags & ITEM_REPORT_XATTR && !dry_run)
|
||||
recv_xattr_request(file, f_in);
|
||||
#endif
|
||||
|
||||
if (!(iflags & ITEM_TRANSFER)) {
|
||||
maybe_log_item(file, iflags, itemizing, xname);
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
|
||||
set_file_attrs(fname, file, NULL, fname, 0);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if (phase == 2) {
|
||||
rprintf(FERROR,
|
||||
"got transfer request in phase 2 [%s]\n",
|
||||
who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
if (file->flags & FLAG_FILE_SENT) {
|
||||
if (csum_length == SHORT_SUM_LENGTH) {
|
||||
if (keep_partial && !partial_dir)
|
||||
make_backups = -make_backups; /* prevents double backup */
|
||||
if (append_mode)
|
||||
sparse_files = -sparse_files;
|
||||
append_mode = -append_mode;
|
||||
csum_length = SUM_LENGTH;
|
||||
redoing = 1;
|
||||
}
|
||||
} else {
|
||||
if (csum_length != SHORT_SUM_LENGTH) {
|
||||
if (keep_partial && !partial_dir)
|
||||
make_backups = -make_backups;
|
||||
if (append_mode)
|
||||
sparse_files = -sparse_files;
|
||||
append_mode = -append_mode;
|
||||
csum_length = SHORT_SUM_LENGTH;
|
||||
redoing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
stats.current_file_index = i;
|
||||
stats.current_file_index = ndx;
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
stats.total_transferred_size += F_LENGTH(file);
|
||||
cleanup_got_literal = 0;
|
||||
|
||||
if (local_name)
|
||||
fname = local_name;
|
||||
else
|
||||
fname = f_name_to(file, fbuf);
|
||||
if (server_filter_list.head
|
||||
&& check_filter(&server_filter_list, fname, 0) < 0) {
|
||||
rprintf(FERROR, "attempt to hack rsync failed.\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
}
|
||||
if (!do_xfers) { /* log the transfer */
|
||||
log_item(FCLIENT, file, &stats, iflags, NULL);
|
||||
if (read_batch)
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
continue;
|
||||
}
|
||||
if (write_batch < 0) {
|
||||
log_item(FINFO, file, &stats, iflags, NULL);
|
||||
if (!am_server)
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (read_batch) {
|
||||
next_gen_ndx = get_next_gen_ndx(batch_gen_fd, next_gen_ndx, ndx);
|
||||
if (ndx < next_gen_ndx) {
|
||||
rprintf(FINFO,
|
||||
"(Skipping batched update for \"%s\")\n",
|
||||
fname);
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
next_gen_ndx = -1;
|
||||
}
|
||||
|
||||
partialptr = partial_dir ? partial_dir_fname(fname) : fname;
|
||||
|
||||
if (protocol_version >= 29) {
|
||||
switch (fnamecmp_type) {
|
||||
case FNAMECMP_FNAME:
|
||||
fnamecmp = fname;
|
||||
break;
|
||||
case FNAMECMP_PARTIAL_DIR:
|
||||
fnamecmp = partialptr;
|
||||
break;
|
||||
case FNAMECMP_BACKUP:
|
||||
fnamecmp = get_backup_name(fname);
|
||||
break;
|
||||
case FNAMECMP_FUZZY:
|
||||
updating_basis = 0;
|
||||
if (file->dirname) {
|
||||
pathjoin(fnamecmpbuf, MAXPATHLEN,
|
||||
file->dirname, xname);
|
||||
fnamecmp = fnamecmpbuf;
|
||||
} else
|
||||
fnamecmp = xname;
|
||||
break;
|
||||
default:
|
||||
updating_basis = 0;
|
||||
if (fnamecmp_type >= basis_dir_cnt) {
|
||||
rprintf(FERROR,
|
||||
"invalid basis_dir index: %d.\n",
|
||||
fnamecmp_type);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
|
||||
basis_dir[fnamecmp_type], fname);
|
||||
fnamecmp = fnamecmpbuf;
|
||||
break;
|
||||
}
|
||||
if (!fnamecmp || (server_filter_list.head
|
||||
&& check_filter(&server_filter_list, fname, 0) < 0))
|
||||
fnamecmp = fname;
|
||||
} else {
|
||||
/* Reminder: --inplace && --partial-dir are never
|
||||
* enabled at the same time. */
|
||||
if (inplace && make_backups > 0) {
|
||||
if (!(fnamecmp = get_backup_name(fname)))
|
||||
fnamecmp = fname;
|
||||
} else if (partial_dir && partialptr)
|
||||
fnamecmp = partialptr;
|
||||
else
|
||||
fnamecmp = fname;
|
||||
}
|
||||
|
||||
initial_stats = stats;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files(%s)\n",fname);
|
||||
|
||||
fnamecmp = fname;
|
||||
|
||||
/* open the file */
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
|
||||
if (fd1 == -1 && compare_dest != NULL) {
|
||||
/* try the file at compare_dest instead */
|
||||
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
|
||||
compare_dest, fname);
|
||||
fnamecmp = fnamecmpbuf;
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
if (fd1 == -1 && protocol_version < 29) {
|
||||
if (fnamecmp != fname) {
|
||||
fnamecmp = fname;
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
}
|
||||
|
||||
if (fd1 == -1 && basis_dir[0]) {
|
||||
/* pre-29 allowed only one alternate basis */
|
||||
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
|
||||
basis_dir[0], fname);
|
||||
fnamecmp = fnamecmpbuf;
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
|
||||
rprintf(FERROR, "fstat %s failed: %s\n",
|
||||
full_fname(fnamecmp), strerror(errno));
|
||||
receive_data(f_in,NULL,-1,NULL,file->length);
|
||||
if (fd1 == -1) {
|
||||
st.st_mode = 0;
|
||||
st.st_size = 0;
|
||||
} else if (do_fstat(fd1,&st) != 0) {
|
||||
rsyserr(FERROR, errno, "fstat %s failed",
|
||||
full_fname(fnamecmp));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -385,109 +575,174 @@ int recv_files(int f_in,struct file_list *flist,char *local_name)
|
||||
*/
|
||||
rprintf(FERROR,"recv_files: %s is a directory\n",
|
||||
full_fname(fnamecmp));
|
||||
receive_data(f_in, NULL, -1, NULL, file->length);
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
|
||||
close(fd1);
|
||||
fd1 = -1;
|
||||
mapbuf = NULL;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !preserve_perms) {
|
||||
/* if the file exists already and we aren't preserving
|
||||
* permissions then act as though the remote end sent
|
||||
* us the file permissions we already have */
|
||||
file->mode = st.st_mode;
|
||||
/* If we're not preserving permissions, change the file-list's
|
||||
* mode based on the local permissions and some heuristics. */
|
||||
if (!preserve_perms) {
|
||||
int exists = fd1 != -1;
|
||||
#ifdef SUPPORT_ACLS
|
||||
const char *dn = file->dirname ? file->dirname : ".";
|
||||
if (parent_dirname != dn
|
||||
&& strcmp(parent_dirname, dn) != 0) {
|
||||
dflt_perms = default_perms_for_dir(dn);
|
||||
parent_dirname = dn;
|
||||
}
|
||||
#endif
|
||||
file->mode = dest_mode(file->mode, st.st_mode,
|
||||
dflt_perms, exists);
|
||||
}
|
||||
|
||||
if (fd1 != -1 && st.st_size > 0) {
|
||||
mapbuf = map_file(fd1,st.st_size);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
|
||||
} else
|
||||
mapbuf = NULL;
|
||||
/* We now check to see if we are writing the file "inplace" */
|
||||
if (inplace) {
|
||||
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
|
||||
if (fd2 == -1) {
|
||||
rsyserr(FERROR, errno, "open %s failed",
|
||||
full_fname(fname));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!get_tmpname(fnametmp,fname)) {
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!get_tmpname(fnametmp,fname)) {
|
||||
if (mapbuf) unmap_file(mapbuf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
strlcpy(template, fnametmp, sizeof template);
|
||||
|
||||
/* we initially set the perms without the
|
||||
* setuid/setgid bits to ensure that there is no race
|
||||
* condition. They are then correctly updated after
|
||||
* the lchown. Thanks to snabb@epipe.fi for pointing
|
||||
* this out. We also set it initially without group
|
||||
* access because of a similar race condition. */
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
|
||||
/* in most cases parent directories will already exist
|
||||
* because their information should have been previously
|
||||
* transferred, but that may not be the case with -R */
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
create_directory_path(fnametmp, orig_umask) == 0) {
|
||||
strlcpy(fnametmp, template, sizeof fnametmp);
|
||||
/* we initially set the perms without the
|
||||
* setuid/setgid bits to ensure that there is no race
|
||||
* condition. They are then correctly updated after
|
||||
* the lchown. Thanks to snabb@epipe.fi for pointing
|
||||
* this out. We also set it initially without group
|
||||
* access because of a similar race condition. */
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR, "mkstemp %s failed: %s\n",
|
||||
full_fname(fnametmp), strerror(errno));
|
||||
receive_data(f_in,mapbuf,-1,NULL,file->length);
|
||||
if (mapbuf) unmap_file(mapbuf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
|
||||
/* in most cases parent directories will already exist
|
||||
* because their information should have been previously
|
||||
* transferred, but that may not be the case with -R */
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT
|
||||
&& create_directory_path(fnametmp) == 0) {
|
||||
/* Get back to name with XXXXXX in it. */
|
||||
get_tmpname(fnametmp, fname);
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rsyserr(FERROR, errno, "mkstemp %s failed",
|
||||
full_fname(fnametmp));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
|
||||
}
|
||||
|
||||
cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
|
||||
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
/* log the transfer */
|
||||
if (log_before_transfer)
|
||||
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
|
||||
else if (!am_server && verbose && do_progress)
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
}
|
||||
|
||||
/* recv file data */
|
||||
recv_ok = receive_data(f_in,mapbuf,fd2,fname,file->length);
|
||||
recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
|
||||
fname, fd2, F_LENGTH(file));
|
||||
|
||||
log_recv(file, &initial_stats);
|
||||
log_item(log_code, file, &initial_stats, iflags, NULL);
|
||||
|
||||
if (mapbuf) unmap_file(mapbuf);
|
||||
if (fd1 != -1) {
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
}
|
||||
if (close(fd2) < 0) {
|
||||
rprintf(FERROR, "close failed on %s: %s\n",
|
||||
full_fname(fnametmp), strerror(errno));
|
||||
rsyserr(FERROR, errno, "close failed on %s",
|
||||
full_fname(fnametmp));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
|
||||
|
||||
finish_transfer(fname, fnametmp, file);
|
||||
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
|
||||
char *temp_copy_name;
|
||||
if (partialptr == fname)
|
||||
partialptr = temp_copy_name = NULL;
|
||||
else if (*partial_dir == '/')
|
||||
temp_copy_name = NULL;
|
||||
else
|
||||
temp_copy_name = partialptr;
|
||||
finish_transfer(fname, fnametmp, fnamecmp,
|
||||
temp_copy_name, file, recv_ok, 1);
|
||||
if (fnamecmp == partialptr) {
|
||||
do_unlink(partialptr);
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
}
|
||||
} else if (keep_partial && partialptr
|
||||
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
|
||||
finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
|
||||
file, recv_ok, !partial_dir);
|
||||
if (delay_updates && recv_ok) {
|
||||
bitbag_set_bit(delayed_bits, ndx);
|
||||
recv_ok = -1;
|
||||
}
|
||||
} else {
|
||||
partialptr = NULL;
|
||||
do_unlink(fnametmp);
|
||||
}
|
||||
|
||||
cleanup_disable();
|
||||
|
||||
if (!recv_ok) {
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
char buf[4];
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
|
||||
SIVAL(buf, 0, i);
|
||||
send_msg(MSG_REDO, buf, 4);
|
||||
if (recv_ok > 0) {
|
||||
if (remove_source_files || inc_recurse
|
||||
|| (preserve_hard_links && F_IS_HLINKED(file)))
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
} else if (!recv_ok) {
|
||||
enum logcode msgtype = redoing || read_batch ? FERROR : FINFO;
|
||||
if (msgtype == FERROR || verbose) {
|
||||
char *errstr, *redostr, *keptstr;
|
||||
if (!(keep_partial && partialptr) && !inplace)
|
||||
keptstr = "discarded";
|
||||
else if (partial_dir)
|
||||
keptstr = "put into partial-dir";
|
||||
else
|
||||
keptstr = "retained";
|
||||
if (msgtype == FERROR) {
|
||||
errstr = "ERROR";
|
||||
redostr = "";
|
||||
} else {
|
||||
errstr = "WARNING";
|
||||
redostr = " (will try again)";
|
||||
}
|
||||
rprintf(msgtype,
|
||||
"%s: %s failed verification -- update %s%s.\n",
|
||||
errstr, fname, keptstr, redostr);
|
||||
}
|
||||
if (!redoing) {
|
||||
send_msg_int(MSG_REDO, ndx);
|
||||
file->flags |= FLAG_FILE_SENT;
|
||||
} else if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
}
|
||||
}
|
||||
if (make_backups < 0)
|
||||
make_backups = -make_backups;
|
||||
|
||||
if (delete_after && recurse && delete_mode && !local_name
|
||||
&& flist->count > 0)
|
||||
delete_files(flist);
|
||||
if (phase == 2 && delay_updates) /* for protocol_version < 29 */
|
||||
handle_delayed_updates(local_name);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files finished\n");
|
||||
|
||||
652
rsync.c
652
rsync.c
@@ -1,39 +1,305 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* this file contains code used by more than one part of the rsync
|
||||
process */
|
||||
* Routines common to more than one of the rsync processes.
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
|
||||
#include <libcharset.h>
|
||||
#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_executability;
|
||||
extern int preserve_times;
|
||||
extern int am_root;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_perms;
|
||||
extern int am_starting_up;
|
||||
extern int allow_8bit_chars;
|
||||
extern int protocol_version;
|
||||
extern int uid_ndx;
|
||||
extern int gid_ndx;
|
||||
extern int inc_recurse;
|
||||
extern int inplace;
|
||||
extern int flist_eof;
|
||||
extern int keep_dirlinks;
|
||||
extern int make_backups;
|
||||
extern struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
extern struct chmod_mode_struct *daemon_chmod_modes;
|
||||
#ifdef ICONV_OPTION
|
||||
extern char *iconv_opt;
|
||||
#endif
|
||||
|
||||
#ifdef ICONV_CONST
|
||||
iconv_t ic_chck = (iconv_t)-1;
|
||||
# ifdef ICONV_OPTION
|
||||
iconv_t ic_send = (iconv_t)-1, ic_recv = (iconv_t)-1;
|
||||
# endif
|
||||
|
||||
static const char *default_charset(void)
|
||||
{
|
||||
# if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
|
||||
return locale_charset();
|
||||
# elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
|
||||
return nl_langinfo(CODESET);
|
||||
# else
|
||||
return ""; /* Works with (at the very least) gnu iconv... */
|
||||
# endif
|
||||
}
|
||||
|
||||
void setup_iconv(void)
|
||||
{
|
||||
const char *defset = default_charset();
|
||||
# ifdef ICONV_OPTION
|
||||
const char *charset;
|
||||
char *cp;
|
||||
# endif
|
||||
|
||||
if (!am_server && !allow_8bit_chars) {
|
||||
|
||||
/* It's OK if this fails... */
|
||||
ic_chck = iconv_open(defset, defset);
|
||||
|
||||
if (verbose > 3) {
|
||||
if (ic_chck == (iconv_t)-1) {
|
||||
rprintf(FINFO,
|
||||
"note: iconv_open(\"%s\", \"%s\") failed (%d)"
|
||||
" -- using isprint() instead of iconv().\n",
|
||||
defset, defset, errno);
|
||||
} else {
|
||||
rprintf(FINFO,
|
||||
"note: iconv_open(\"%s\", \"%s\") succeeded.\n",
|
||||
defset, defset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef ICONV_OPTION
|
||||
if (!iconv_opt)
|
||||
return;
|
||||
|
||||
if ((cp = strchr(iconv_opt, ',')) != NULL) {
|
||||
if (am_server) /* A local transfer needs this. */
|
||||
iconv_opt = cp + 1;
|
||||
else
|
||||
*cp = '\0';
|
||||
}
|
||||
|
||||
if (!*iconv_opt || (*iconv_opt == '.' && iconv_opt[1] == '\0'))
|
||||
charset = defset;
|
||||
else
|
||||
charset = iconv_opt;
|
||||
|
||||
if ((ic_send = iconv_open(UTF8_CHARSET, charset)) == (iconv_t)-1) {
|
||||
rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
|
||||
UTF8_CHARSET, charset);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if ((ic_recv = iconv_open(charset, UTF8_CHARSET)) == (iconv_t)-1) {
|
||||
rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
|
||||
charset, UTF8_CHARSET);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "%s charset: %s\n",
|
||||
am_server ? "server" : "client",
|
||||
*charset ? charset : "[LOCALE]");
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef ICONV_OPTION
|
||||
|
||||
/* This function converts the characters in the "in" xbuf into characters
|
||||
* in the "out" xbuf. The "len" of the "in" xbuf is used starting from its
|
||||
* "pos". The "size" of the "out" xbuf restricts how many characters can be
|
||||
* stored, starting at its "pos+len" position. Note that the last byte of
|
||||
* the buffer is never used, which reserves space for a terminating '\0'.
|
||||
* We return a 0 on success or a -1 on error. An error also sets errno to
|
||||
* E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0.
|
||||
* The "in" xbuf is altered to update "pos" and "len". The "out" xbuf has
|
||||
* data appended, and its "len" incremented. If ICB_EXPAND_OUT is set in
|
||||
* "flags", the "out" xbuf will also be allocated if empty, and expanded if
|
||||
* too small (so E2BIG will not be returned). If ICB_INCLUDE_BAD is set in
|
||||
* "flags", any badly-encoded chars are included verbatim in the "out" xbuf,
|
||||
* so EILSEQ will not be returned. Likewise for ICB_INCLUDE_INCOMPLETE with
|
||||
* respect to an incomplete multi-byte char at the end, which ensures that
|
||||
* EINVAL is not returned. Anytime "in.pos" is 0 we will reset the iconv()
|
||||
* state prior to processing the characters. */
|
||||
int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
|
||||
{
|
||||
ICONV_CONST char *ibuf;
|
||||
size_t icnt, ocnt;
|
||||
char *obuf;
|
||||
|
||||
if (!out->size && flags & ICB_EXPAND_OUT)
|
||||
alloc_xbuf(out, 1024);
|
||||
|
||||
if (!in->pos)
|
||||
iconv(ic, NULL, 0, NULL, 0);
|
||||
|
||||
ibuf = in->buf + in->pos;
|
||||
icnt = in->len;
|
||||
|
||||
obuf = out->buf + (out->pos + out->len);
|
||||
ocnt = out->size - (out->pos + out->len) - 1;
|
||||
|
||||
while (icnt) {
|
||||
while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EINVAL) {
|
||||
if (!(flags & ICB_INCLUDE_INCOMPLETE))
|
||||
goto finish;
|
||||
} else if (errno == EILSEQ) {
|
||||
if (!(flags & ICB_INCLUDE_BAD))
|
||||
goto finish;
|
||||
} else {
|
||||
size_t opos = obuf - out->buf;
|
||||
if (!(flags & ICB_EXPAND_OUT)) {
|
||||
errno = E2BIG;
|
||||
goto finish;
|
||||
}
|
||||
realloc_xbuf(out, out->size + 1024);
|
||||
obuf = out->buf + opos;
|
||||
ocnt += 1024;
|
||||
continue;
|
||||
}
|
||||
*obuf++ = *ibuf++;
|
||||
ocnt--, icnt--;
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
finish:
|
||||
in->len = icnt;
|
||||
in->pos = ibuf - in->buf;
|
||||
out->len = obuf - out->buf - out->pos;
|
||||
|
||||
return errno ? -1 : 0;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
|
||||
char *buf, int *len_ptr)
|
||||
{
|
||||
int len, iflags = 0;
|
||||
struct file_list *flist;
|
||||
uchar fnamecmp_type = FNAMECMP_FNAME;
|
||||
int ndx;
|
||||
|
||||
read_loop:
|
||||
while (1) {
|
||||
ndx = read_ndx(f_in);
|
||||
|
||||
if (ndx >= 0)
|
||||
break;
|
||||
if (ndx == NDX_DONE)
|
||||
return ndx;
|
||||
if (!inc_recurse || am_sender)
|
||||
goto invalid_ndx;
|
||||
if (ndx == NDX_FLIST_EOF) {
|
||||
flist_eof = 1;
|
||||
send_msg(MSG_FLIST_EOF, "", 0, 0);
|
||||
continue;
|
||||
}
|
||||
ndx = NDX_FLIST_OFFSET - ndx;
|
||||
if (ndx < 0 || ndx >= dir_flist->used) {
|
||||
ndx = NDX_FLIST_OFFSET - ndx;
|
||||
rprintf(FERROR,
|
||||
"[%s] Invalid dir index: %d (%d - %d)\n",
|
||||
who_am_i(), ndx, NDX_FLIST_OFFSET,
|
||||
NDX_FLIST_OFFSET - dir_flist->used + 1);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
/* Send everything read from f_in to msg_fd_out. */
|
||||
send_msg_int(MSG_FLIST, ndx);
|
||||
start_flist_forward(f_in);
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "[%s] receiving flist for dir %d\n",
|
||||
who_am_i(), ndx);
|
||||
}
|
||||
flist = recv_file_list(f_in);
|
||||
flist->parent_ndx = ndx;
|
||||
stop_flist_forward();
|
||||
}
|
||||
|
||||
iflags = protocol_version >= 29 ? read_shortint(f_in)
|
||||
: ITEM_TRANSFER | ITEM_MISSING_DATA;
|
||||
|
||||
/* Honor the old-style keep-alive indicator. */
|
||||
if (protocol_version < 30
|
||||
&& ndx == cur_flist->used && iflags == ITEM_IS_NEW) {
|
||||
if (am_sender)
|
||||
maybe_send_keepalive();
|
||||
goto read_loop;
|
||||
}
|
||||
|
||||
if (!(flist = flist_for_ndx(ndx))) {
|
||||
invalid_ndx:
|
||||
rprintf(FERROR,
|
||||
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
|
||||
ndx, first_flist->ndx_start - 1, first_flist->prev->ndx_end,
|
||||
iflags, who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
cur_flist = flist;
|
||||
|
||||
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
|
||||
fnamecmp_type = read_byte(f_in);
|
||||
*type_ptr = fnamecmp_type;
|
||||
|
||||
if (iflags & ITEM_XNAME_FOLLOWS) {
|
||||
if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
} else {
|
||||
*buf = '\0';
|
||||
len = -1;
|
||||
}
|
||||
*len_ptr = len;
|
||||
|
||||
if (iflags & ITEM_TRANSFER) {
|
||||
int i = ndx - cur_flist->ndx_start;
|
||||
if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {
|
||||
rprintf(FERROR,
|
||||
"received request to transfer non-regular file: %d [%s]\n",
|
||||
ndx, who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
|
||||
*iflag_ptr = iflags;
|
||||
return ndx;
|
||||
}
|
||||
|
||||
/*
|
||||
free a sums struct
|
||||
@@ -44,174 +310,185 @@ void free_sums(struct sum_struct *s)
|
||||
free(s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* delete a file or directory. If force_delete is set then delete
|
||||
* recursively
|
||||
*/
|
||||
int delete_file(char *fname)
|
||||
/* This is only called when we aren't preserving permissions. Figure out what
|
||||
* the permissions should be and return them merged back into the mode. */
|
||||
mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
|
||||
int exists)
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *di;
|
||||
char buf[MAXPATHLEN];
|
||||
extern int force_delete;
|
||||
STRUCT_STAT st;
|
||||
int ret;
|
||||
extern int recurse;
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
ret = do_lstat(fname, &st);
|
||||
#else
|
||||
ret = do_stat(fname, &st);
|
||||
#endif
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (robust_unlink(fname) == 0 || errno == ENOENT)
|
||||
return 0;
|
||||
rprintf(FERROR, "delete_file: unlink %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_rmdir(fname) == 0 || errno == ENOENT)
|
||||
return 0;
|
||||
if (!force_delete || !recurse
|
||||
|| (errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now we do a recsursive delete on the directory ... */
|
||||
if (!(d = opendir(fname))) {
|
||||
rprintf(FERROR, "delete_file: opendir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
|
||||
char *dname = d_name(di);
|
||||
if (dname[0] == '.' && (dname[1] == '\0'
|
||||
|| (dname[1] == '.' && dname[2] == '\0')))
|
||||
continue;
|
||||
pathjoin(buf, sizeof buf, fname, dname);
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO, "deleting %s\n", buf);
|
||||
if (delete_file(buf) != 0) {
|
||||
closedir(d);
|
||||
return -1;
|
||||
int new_mode;
|
||||
/* If the file already exists, we'll return the local permissions,
|
||||
* possibly tweaked by the --executability option. */
|
||||
if (exists) {
|
||||
new_mode = (flist_mode & ~CHMOD_BITS) | (stat_mode & CHMOD_BITS);
|
||||
if (preserve_executability && S_ISREG(flist_mode)) {
|
||||
/* If the source file is executable, grant execute
|
||||
* rights to everyone who can read, but ONLY if the
|
||||
* file isn't already executable. */
|
||||
if (!(flist_mode & 0111))
|
||||
new_mode &= ~0111;
|
||||
else if (!(stat_mode & 0111))
|
||||
new_mode |= (new_mode & 0444) >> 2;
|
||||
}
|
||||
} else {
|
||||
/* Apply destination default permissions and turn
|
||||
* off special permissions. */
|
||||
new_mode = flist_mode & (~CHMOD_BITS | dflt_perms);
|
||||
}
|
||||
if (errno) {
|
||||
rprintf(FERROR, "delete_file: readdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (do_rmdir(fname) != 0) {
|
||||
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return new_mode;
|
||||
}
|
||||
|
||||
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
int report)
|
||||
int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
const char *fnamecmp, int flags)
|
||||
{
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
stat_x sx2;
|
||||
int change_uid, change_gid;
|
||||
mode_t new_mode = file->mode;
|
||||
int inherit;
|
||||
|
||||
if (dry_run) return 0;
|
||||
|
||||
if (!st) {
|
||||
if (link_stat(fname,&st2) != 0) {
|
||||
rprintf(FERROR, "stat %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
if (!sxp) {
|
||||
if (dry_run)
|
||||
return 1;
|
||||
if (link_stat(fname, &sx2.st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
full_fname(fname));
|
||||
return 0;
|
||||
}
|
||||
st = &st2;
|
||||
#ifdef SUPPORT_ACLS
|
||||
sx2.acc_acl = sx2.def_acl = NULL;
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
sx2.xattr = NULL;
|
||||
#endif
|
||||
sxp = &sx2;
|
||||
inherit = !preserve_perms;
|
||||
} else
|
||||
inherit = !preserve_perms && file->flags & FLAG_DIR_CREATED;
|
||||
|
||||
if (inherit && S_ISDIR(new_mode) && sxp->st.st_mode & S_ISGID) {
|
||||
/* We just created this directory and its setgid
|
||||
* bit is on, so make sure it stays on. */
|
||||
new_mode |= S_ISGID;
|
||||
}
|
||||
|
||||
if (preserve_times && !S_ISLNK(st->st_mode) &&
|
||||
cmp_modtime(st->st_mtime, file->modtime) != 0) {
|
||||
/* don't complain about not setting times on directories
|
||||
* because some filesystems can't do it */
|
||||
if (set_modtime(fname,file->modtime) != 0 &&
|
||||
!S_ISDIR(st->st_mode)) {
|
||||
rprintf(FERROR, "failed to set times on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return 0;
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
|
||||
get_acl(fname, sxp);
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && fnamecmp)
|
||||
set_xattr(fname, file, fnamecmp, sxp);
|
||||
if (am_root < 0)
|
||||
set_stat_xattr(fname, file);
|
||||
#endif
|
||||
|
||||
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
|
||||
flags |= ATTRS_SKIP_MTIME;
|
||||
if (!(flags & ATTRS_SKIP_MTIME)
|
||||
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
|
||||
int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno, "failed to set times on %s",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
updated = 1;
|
||||
if (ret == 0) /* ret == 1 if symlink could not be set */
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
|
||||
change_gid = preserve_gid && file->gid != GID_NONE
|
||||
&& st->st_gid != file->gid;
|
||||
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
|
||||
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
|
||||
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
|
||||
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
|
||||
if (S_ISLNK(sxp->st.st_mode))
|
||||
;
|
||||
else
|
||||
#endif
|
||||
if (change_uid || change_gid) {
|
||||
if (verbose > 2) {
|
||||
if (change_uid) {
|
||||
rprintf(FINFO,
|
||||
"set uid of %s from %ld to %ld\n",
|
||||
fname, (long)st->st_uid, (long)file->uid);
|
||||
"set uid of %s from %u to %u\n",
|
||||
fname, (unsigned)sxp->st.st_uid, F_OWNER(file));
|
||||
}
|
||||
if (change_gid) {
|
||||
rprintf(FINFO,
|
||||
"set gid of %s from %ld to %ld\n",
|
||||
fname, (long)st->st_gid, (long)file->gid);
|
||||
"set gid of %s from %u to %u\n",
|
||||
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
|
||||
}
|
||||
}
|
||||
if (do_lchown(fname,
|
||||
change_uid ? file->uid : st->st_uid,
|
||||
change_gid ? file->gid : st->st_gid) != 0) {
|
||||
if (am_root < 0) {
|
||||
;
|
||||
} else if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
* unless have the privilege */
|
||||
rprintf(FERROR, "%s %s failed: %s\n",
|
||||
rsyserr(FERROR, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname), strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
} else
|
||||
/* a lchown had been done - we have to re-stat if the
|
||||
* destination had the setuid or setgid bits set due
|
||||
* to the side effect of the chown call */
|
||||
if (st->st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, st);
|
||||
* destination had the setuid or setgid bits set due
|
||||
* to the side effect of the chown call */
|
||||
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, &sxp->st,
|
||||
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
if (daemon_chmod_modes && !S_ISLNK(new_mode))
|
||||
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
/* It's OK to call set_acl() now, even for a dir, as the generator
|
||||
* will enable owner-writability using chmod, if necessary.
|
||||
*
|
||||
* If set_acl() changes permission bits in the process of setting
|
||||
* an access ACL, it changes sxp->st.st_mode so we know whether we
|
||||
* need to chmod(). */
|
||||
if (preserve_acls && !S_ISLNK(new_mode) && set_acl(fname, file, sxp) == 0)
|
||||
updated = 1;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHMOD
|
||||
if (!S_ISLNK(st->st_mode)) {
|
||||
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
|
||||
updated = 1;
|
||||
if (do_chmod(fname,(file->mode & CHMOD_BITS)) != 0) {
|
||||
rprintf(FERROR, "failed to set permissions on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
|
||||
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to set permissions on %s",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
if (ret == 0) /* ret == 1 if symlink could not be set */
|
||||
updated = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (verbose > 1 && report) {
|
||||
if (verbose > 1 && flags & ATTRS_REPORT) {
|
||||
if (updated)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
rprintf(FCLIENT, "%s\n", fname);
|
||||
else
|
||||
rprintf(FINFO,"%s is uptodate\n",fname);
|
||||
rprintf(FCLIENT, "%s is uptodate\n", fname);
|
||||
}
|
||||
cleanup:
|
||||
if (sxp == &sx2) {
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls)
|
||||
free_acl(&sx2);
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs)
|
||||
free_xattr(&sx2);
|
||||
#endif
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
||||
void sig_int(void)
|
||||
RETSIGTYPE sig_int(UNUSED(int val))
|
||||
{
|
||||
/* KLUGE: if the user hits Ctrl-C while ssh is prompting
|
||||
* for a password, then our cleanup's sending of a SIGUSR1
|
||||
@@ -225,29 +502,86 @@ void sig_int(void)
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
|
||||
/* finish off a file transfer, renaming the file and setting the permissions
|
||||
and ownership */
|
||||
void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
|
||||
/* Finish off a file transfer: renaming the file and setting the file's
|
||||
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
|
||||
* NULL and the robust_rename() call is forced to copy the temp file, we
|
||||
* stage the file into the partial-dir and then rename it into place. */
|
||||
void finish_transfer(const char *fname, const char *fnametmp,
|
||||
const char *fnamecmp, const char *partialptr,
|
||||
struct file_struct *file, int ok_to_set_time,
|
||||
int overwriting_basis)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (make_backups && !make_backup(fname))
|
||||
if (inplace) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "finishing %s\n", fname);
|
||||
fnametmp = fname;
|
||||
goto do_set_file_attrs;
|
||||
}
|
||||
|
||||
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
|
||||
return;
|
||||
|
||||
/* Change permissions before putting the file into place. */
|
||||
set_file_attrs(fnametmp, file, NULL, fnamecmp,
|
||||
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
|
||||
|
||||
/* move tmp file over real file */
|
||||
ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
|
||||
ret = robust_rename(fnametmp, fname, partialptr,
|
||||
file->mode & INITACCESSPERMS);
|
||||
if (ret < 0) {
|
||||
rprintf(FERROR, "%s %s -> \"%s\": %s\n",
|
||||
ret == -2 ? "copy" : "rename",
|
||||
full_fname(fnametmp), fname, strerror(errno));
|
||||
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
|
||||
ret == -2 ? "copy" : "rename",
|
||||
full_fname(fnametmp), fname);
|
||||
do_unlink(fnametmp);
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
return;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* The file was moved into place (not copied), so it's done. */
|
||||
return;
|
||||
}
|
||||
/* The file was copied, so tweak the perms of the copied file. If it
|
||||
* was copied to partialptr, move it into its final destination. */
|
||||
fnametmp = partialptr ? partialptr : fname;
|
||||
|
||||
do_set_file_attrs:
|
||||
set_file_attrs(fnametmp, file, NULL, fnamecmp,
|
||||
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
|
||||
|
||||
if (partialptr) {
|
||||
if (do_rename(fnametmp, fname) < 0) {
|
||||
rsyserr(FERROR, errno, "rename %s -> \"%s\"",
|
||||
full_fname(fnametmp), fname);
|
||||
} else
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
}
|
||||
}
|
||||
|
||||
struct file_list *flist_for_ndx(int ndx)
|
||||
{
|
||||
struct file_list *flist = cur_flist;
|
||||
|
||||
if (!flist && !(flist = first_flist))
|
||||
return NULL;
|
||||
|
||||
while (ndx < flist->ndx_start-1) {
|
||||
if (flist == first_flist)
|
||||
return NULL;
|
||||
flist = flist->prev;
|
||||
}
|
||||
while (ndx > flist->ndx_end) {
|
||||
if (!(flist = flist->next))
|
||||
return NULL;
|
||||
}
|
||||
return flist;
|
||||
}
|
||||
|
||||
const char *who_am_i(void)
|
||||
{
|
||||
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
|
||||
if (am_starting_up)
|
||||
return am_server ? "server" : "client";
|
||||
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
|
||||
}
|
||||
|
||||
489
rsyncd.conf.yo
489
rsyncd.conf.yo
@@ -1,6 +1,6 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(30 Apr 2004)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync server)
|
||||
manpage(rsyncd.conf)(5)(11 Oct 2007)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
|
||||
manpagesynopsis()
|
||||
|
||||
rsyncd.conf
|
||||
@@ -8,27 +8,27 @@ rsyncd.conf
|
||||
manpagedescription()
|
||||
|
||||
The rsyncd.conf file is the runtime configuration file for rsync when
|
||||
run as an rsync server.
|
||||
run as an rsync daemon.
|
||||
|
||||
The rsyncd.conf file controls authentication, access, logging and
|
||||
available modules.
|
||||
|
||||
manpagesection(FILE FORMAT)
|
||||
|
||||
The file consists of modules and parameters. A module begins with the
|
||||
The file consists of modules and parameters. A module begins with the
|
||||
name of the module in square brackets and continues until the next
|
||||
module begins. Modules contain parameters of the form 'name = value'.
|
||||
module begins. Modules contain parameters of the form "name = value".
|
||||
|
||||
The file is line-based - that is, each newline-terminated line represents
|
||||
The file is line-based -- that is, each newline-terminated line represents
|
||||
either a comment, a module name or a parameter.
|
||||
|
||||
Only the first equals sign in a parameter is significant. Whitespace before
|
||||
Only the first equals sign in a parameter is significant. Whitespace before
|
||||
or after the first equals sign is discarded. Leading, trailing and internal
|
||||
whitespace in module and parameter names is irrelevant. Leading and
|
||||
trailing whitespace in a parameter value is discarded. Internal whitespace
|
||||
within a parameter value is retained verbatim.
|
||||
|
||||
Any line beginning with a hash (#) is ignored, as are lines containing
|
||||
Any line beginning with a hash (#) is ignored, as are lines containing
|
||||
only whitespace.
|
||||
|
||||
Any line ending in a \ is "continued" on the next line in the
|
||||
@@ -37,12 +37,12 @@ customary UNIX fashion.
|
||||
The values following the equals sign in parameters are all either a string
|
||||
(no quotes needed) or a boolean, which may be given as yes/no, 0/1 or
|
||||
true/false. Case is not significant in boolean values, but is preserved
|
||||
in string values.
|
||||
in string values.
|
||||
|
||||
manpagesection(LAUNCHING THE RSYNC DAEMON)
|
||||
|
||||
The rsync daemon is launched by specifying the --daemon option to
|
||||
rsync.
|
||||
The rsync daemon is launched by specifying the bf(--daemon) option to
|
||||
rsync.
|
||||
|
||||
The daemon must run with root privileges if you wish to use chroot, to
|
||||
bind to a port numbered under 1024 (as is the default 873), or to set
|
||||
@@ -51,31 +51,28 @@ write the appropriate data, log, and lock files.
|
||||
|
||||
You can launch it either via inetd, as a stand-alone daemon, or from
|
||||
an rsync client via a remote shell. If run as a stand-alone daemon then
|
||||
just run the command "rsync --daemon" from a suitable startup script.
|
||||
If run from an rsync client via a remote shell (by specifying both the
|
||||
"-e/--rsh" option and server mode with "::" or "rsync://"), the --daemon
|
||||
option is automatically passed to the remote side.
|
||||
just run the command "bf(rsync --daemon)" from a suitable startup script.
|
||||
|
||||
When run via inetd you should add a line like this to /etc/services:
|
||||
|
||||
quote(rsync 873/tcp)
|
||||
verb( rsync 873/tcp)
|
||||
|
||||
and a single line something like this to /etc/inetd.conf:
|
||||
|
||||
quote(rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
|
||||
|
||||
verb( rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
|
||||
|
||||
Replace "/usr/bin/rsync" with the path to where you have rsync installed on
|
||||
your system. You will then need to send inetd a HUP signal to tell it to
|
||||
reread its config file.
|
||||
|
||||
Note that you should not send the rsync server a HUP signal to force
|
||||
Note that you should bf(not) send the rsync daemon a HUP signal to force
|
||||
it to reread the tt(rsyncd.conf) file. The file is re-read on each client
|
||||
connection.
|
||||
connection.
|
||||
|
||||
manpagesection(GLOBAL OPTIONS)
|
||||
|
||||
The first parameters in the file (before a [module] header) are the
|
||||
global parameters.
|
||||
global parameters.
|
||||
|
||||
You may also include any module parameters in the global part of the
|
||||
config file in which case the supplied value will override the
|
||||
@@ -87,28 +84,25 @@ dit(bf(motd file)) The "motd file" option allows you to specify a
|
||||
usually contains site information and any legal notices. The default
|
||||
is no motd file.
|
||||
|
||||
dit(bf(log file)) The "log file" option tells the rsync daemon to log
|
||||
messages to that file rather than using syslog. This is particularly
|
||||
useful on systems (such as AIX) where syslog() doesn't work for
|
||||
chrooted programs.
|
||||
|
||||
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
|
||||
its process ID to that file.
|
||||
its process ID to that file. If the file already exists, the rsync
|
||||
daemon will abort rather than overwrite the file.
|
||||
|
||||
dit(bf(syslog facility)) The "syslog facility" option allows you to
|
||||
specify the syslog facility name to use when logging messages from the
|
||||
rsync server. You may use any standard syslog facility name which is
|
||||
defined on your system. Common names are auth, authpriv, cron, daemon,
|
||||
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
|
||||
local1, local2, local3, local4, local5, local6 and local7. The default
|
||||
is daemon.
|
||||
dit(bf(port)) You can override the default port the daemon will listen on
|
||||
by specifying this value (defaults to 873). This is ignored if the daemon
|
||||
is being run by inetd, and is superseded by the bf(--port) command-line option.
|
||||
|
||||
dit(bf(address)) You can override the default IP address the daemon
|
||||
will listen on by specifying this value. This is ignored if the daemon is
|
||||
being run by inetd, and is superseded by the bf(--address) command-line option.
|
||||
|
||||
dit(bf(socket options)) This option can provide endless fun for people
|
||||
who like to tune their systems to the utmost degree. You can set all
|
||||
sorts of socket options which may make transfers faster (or
|
||||
slower!). Read the man page for the setsockopt() system call for
|
||||
slower!). Read the man page for the code(setsockopt()) system call for
|
||||
details on some of the options you may be able to set. By default no
|
||||
special socket options are set.
|
||||
special socket options are set. These settings are superseded by the
|
||||
bf(--sockopts) command-line option.
|
||||
|
||||
enddit()
|
||||
|
||||
@@ -126,59 +120,98 @@ dit(bf(comment)) The "comment" option specifies a description string
|
||||
that is displayed next to the module name when clients obtain a list
|
||||
of available modules. The default is no comment.
|
||||
|
||||
dit(bf(path)) The "path" option specifies the directory in the servers
|
||||
dit(bf(path)) The "path" option specifies the directory in the daemon's
|
||||
filesystem to make available in this module. You must specify this option
|
||||
for each module in tt(rsyncd.conf).
|
||||
|
||||
dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
|
||||
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
|
||||
to the "path" before starting the file transfer with the client. This has
|
||||
the advantage of extra protection against possible implementation security
|
||||
holes, but it has the disadvantages of requiring super-user privileges,
|
||||
of not being able to follow symbolic links outside of the new root path
|
||||
when reading, and of complicating the preservation of usernames and groups
|
||||
holes, but it has the disadvantages of requiring super-user privileges,
|
||||
of not being able to follow symbolic links that are either absolute or outside
|
||||
of the new root path, and of complicating the preservation of usernames and groups
|
||||
(see below). When "use chroot" is false, for security reasons,
|
||||
symlinks may only be relative paths pointing to other files within the root
|
||||
path, and leading slashes are removed from most absolute paths (options
|
||||
such as --backup-dir, --compare-dest, etc. interpret an absolute path as
|
||||
such as bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
|
||||
rooted in the module's "path" dir, just as if chroot was specified).
|
||||
The default for "use chroot" is true.
|
||||
|
||||
In order to preserve usernames and groupnames, rsync needs to be able to
|
||||
use the standard library functions for looking up names and IDs (i.e.
|
||||
getpwuid(), getgrgid(), getpwname(), and getgrnam()). This means a
|
||||
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a
|
||||
process in the chroot namespace will need to have access to the resources
|
||||
used by these library functions (traditionally /etc/passwd and
|
||||
/etc/group). If these resources are not available, rsync will only be
|
||||
able to copy the IDs, just as if the --numeric-ids option had been
|
||||
able to copy the IDs, just as if the bf(--numeric-ids) option had been
|
||||
specified.
|
||||
|
||||
Note that you are free to setup user/group information in the chroot area
|
||||
differently from your normal system. For example, you could abbreviate
|
||||
the list of users and groups. Also, you can protect this information
|
||||
from being downloaded by adding an exclude rule to the rsync.conf file
|
||||
(e.g. "exclude = /etc/"). To protect it from being changed by an upload
|
||||
(if the module is not read only), be sure to set the permissions (or
|
||||
owner) on the files and/or parent directories so that they cannot be
|
||||
written by the daemon.
|
||||
the list of users and groups. Also, you can protect this information from
|
||||
being downloaded/uploaded by adding an exclude rule to the rsyncd.conf file
|
||||
(e.g. "bf(exclude = /etc/**)"). Note that having the exclusion affect uploads
|
||||
is a relatively new feature in rsync, so make sure your daemon is
|
||||
at least 2.6.3 to effect this. Also note that it is safest to exclude a
|
||||
directory and all its contents combining the rule "/some/dir/" with the
|
||||
rule "/some/dir/**" just to be sure that rsync will not allow deeper
|
||||
access to some of the excluded files inside the directory (rsync tries to
|
||||
do this automatically, but you might as well specify both to be extra
|
||||
sure).
|
||||
|
||||
dit(bf(max connections)) The "max connections" option allows you to
|
||||
specify the maximum number of simultaneous connections you will allow.
|
||||
Any clients connecting when the maximum has been reached will receive a
|
||||
message telling them to try later. The default is 0 which means no limit.
|
||||
message telling them to try later. The default is 0, which means no limit.
|
||||
A negative value disables the module.
|
||||
See also the "lock file" option.
|
||||
|
||||
dit(bf(log file)) When the "log file" option is set to a non-empty
|
||||
string, the rsync daemon will log messages to the indicated file rather
|
||||
than using syslog. This is particularly useful on systems (such as AIX)
|
||||
where code(syslog()) doesn't work for chrooted programs. The file is
|
||||
opened before code(chroot()) is called, allowing it to be placed outside
|
||||
the transfer. If this value is set on a per-module basis instead of
|
||||
globally, the global log will still contain any authorization failures
|
||||
or config-file error messages.
|
||||
|
||||
If the daemon fails to open to specified file, it will fall back to
|
||||
using syslog and output an error about the failure. (Note that the
|
||||
failure to open the specified log file used to be a fatal error.)
|
||||
|
||||
dit(bf(syslog facility)) The "syslog facility" option allows you to
|
||||
specify the syslog facility name to use when logging messages from the
|
||||
rsync daemon. You may use any standard syslog facility name which is
|
||||
defined on your system. Common names are auth, authpriv, cron, daemon,
|
||||
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
|
||||
local1, local2, local3, local4, local5, local6 and local7. The default
|
||||
is daemon. This setting has no effect if the "log file" setting is a
|
||||
non-empty string (either set in the per-modules settings, or inherited
|
||||
from the global settings).
|
||||
|
||||
dit(bf(max verbosity)) The "max verbosity" option allows you to control
|
||||
the maximum amount of verbose information that you'll allow the daemon to
|
||||
generate (since the information goes into the log file). The default is 1,
|
||||
which allows the client to request one level of verbosity.
|
||||
|
||||
dit(bf(lock file)) The "lock file" option specifies the file to use to
|
||||
support the "max connections" option. The rsync server uses record
|
||||
support the "max connections" option. The rsync daemon uses record
|
||||
locking on this file to ensure that the max connections limit is not
|
||||
exceeded for the modules sharing the lock file.
|
||||
exceeded for the modules sharing the lock file.
|
||||
The default is tt(/var/run/rsyncd.lock).
|
||||
|
||||
dit(bf(read only)) The "read only" option determines whether clients
|
||||
will be able to upload files or not. If "read only" is true then any
|
||||
attempted uploads will fail. If "read only" is false then uploads will
|
||||
be possible if file permissions on the server allow them. The default
|
||||
be possible if file permissions on the daemon side allow them. The default
|
||||
is for all modules to be read only.
|
||||
|
||||
dit(bf(write only)) The "write only" option determines whether clients
|
||||
will be able to download files or not. If "write only" is true then any
|
||||
attempted downloads will fail. If "write only" is false then downloads
|
||||
will be possible if file permissions on the daemon side allow them. The
|
||||
default is for this option to be disabled.
|
||||
|
||||
dit(bf(list)) The "list" option determines if this module should be
|
||||
listed when the client asks for a listing of available modules. By
|
||||
setting this to false you can create hidden modules. The default is
|
||||
@@ -195,61 +228,89 @@ file transfers to and from that module should take place as when the daemon
|
||||
was run as root. This complements the "uid" option. The default is gid -2,
|
||||
which is normally the group "nobody".
|
||||
|
||||
dit(bf(exclude)) The "exclude" option allows you to specify a space
|
||||
separated list of patterns to add to the exclude list.
|
||||
This is only superficially equivalent
|
||||
to the client specifying these patterns with the --exclude option.
|
||||
Only one "exclude" option may be specified, but
|
||||
you can use "-" and "+" before patterns to specify exclude/include.
|
||||
dit(bf(fake super)) Setting "fake super = yes" for a module causes the
|
||||
daemon side to behave as if the bf(--fake-user) command-line option had
|
||||
been specified. This allows the full attributes of a file to be stored
|
||||
without having to have the daemon actually running as root.
|
||||
|
||||
dit(bf(filter)) The "filter" option allows you to specify a space-separated
|
||||
list of filter rules that the daemon will not allow to be read or written.
|
||||
This is only superficially equivalent to the client specifying these
|
||||
patterns with the bf(--filter) option. Only one "filter" option may be
|
||||
specified, but it may contain as many rules as you like, including
|
||||
merge-file rules. Note that per-directory merge-file rules do not provide
|
||||
as much protection as global rules, but they can be used to make bf(--delete)
|
||||
work better when a client downloads the daemon's files (if the per-dir
|
||||
merge files are included in the transfer).
|
||||
|
||||
dit(bf(exclude)) The "exclude" option allows you to specify a
|
||||
space-separated list of patterns that the daemon will not allow to be read
|
||||
or written. This is only superficially equivalent to the client
|
||||
specifying these patterns with the bf(--exclude) option. Only one "exclude"
|
||||
option may be specified, but you can use "-" and "+" before patterns to
|
||||
specify exclude/include.
|
||||
|
||||
Because this exclude list is not passed to the client it only applies on
|
||||
the server: that is, it excludes files received by a client when receiving
|
||||
from a server and files deleted on a server when sending to a server, but
|
||||
it doesn't exclude files sent from a client when sending to a server or
|
||||
files deleted on a client when receiving from a server.
|
||||
|
||||
Note that this option is not designed with strong security in
|
||||
mind, it is quite possible that a client may find a way to bypass this
|
||||
exclude list. If you want to absolutely ensure that certain files
|
||||
cannot be accessed then use the uid/gid options in combination with
|
||||
file permissions.
|
||||
the daemon: that is, it excludes files received by a client when receiving
|
||||
from a daemon and files deleted on a daemon when sending to a daemon, but
|
||||
it doesn't exclude files from being deleted on a client when receiving
|
||||
from a daemon.
|
||||
|
||||
dit(bf(exclude from)) The "exclude from" option specifies a filename
|
||||
on the server that contains exclude patterns, one per line.
|
||||
on the daemon that contains exclude patterns, one per line.
|
||||
This is only superficially equivalent
|
||||
to the client specifying the --exclude-from option with an equivalent file.
|
||||
to the client specifying the bf(--exclude-from) option with an equivalent file.
|
||||
See the "exclude" option above.
|
||||
|
||||
dit(bf(include)) The "include" option allows you to specify a space
|
||||
separated list of patterns which rsync should not exclude. This is
|
||||
only superficially equivalent to the client specifying these patterns
|
||||
with the --include option because it applies only on the server.
|
||||
This is useful as it
|
||||
allows you to build up quite complex exclude/include rules. Only one
|
||||
"include" option may be specified, but you can use "+" and "-" before
|
||||
patterns to switch include/exclude. See the "exclude" option above.
|
||||
dit(bf(include)) The "include" option allows you to specify a
|
||||
space-separated list of patterns which rsync should not exclude. This is
|
||||
only superficially equivalent to the client specifying these patterns with
|
||||
the bf(--include) option because it applies only on the daemon. This is
|
||||
useful as it allows you to build up quite complex exclude/include rules.
|
||||
Only one "include" option may be specified, but you can use "+" and "-"
|
||||
before patterns to switch include/exclude. See the "exclude" option
|
||||
above.
|
||||
|
||||
dit(bf(include from)) The "include from" option specifies a filename
|
||||
on the server that contains include patterns, one per line. This is
|
||||
on the daemon that contains include patterns, one per line. This is
|
||||
only superficially equivalent to the client specifying the
|
||||
--include-from option with a equivalent file.
|
||||
bf(--include-from) option with a equivalent file.
|
||||
See the "exclude" option above.
|
||||
|
||||
dit(bf(incoming chmod)) This option allows you to specify a set of
|
||||
comma-separated chmod strings that will affect the permissions of all
|
||||
incoming files (files that are being received by the daemon). These
|
||||
changes happen after all other permission calculations, and this will
|
||||
even override destination-default and/or existing permissions when the
|
||||
client does not specify bf(--perms).
|
||||
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
|
||||
manpage for information on the format of this string.
|
||||
|
||||
dit(bf(outgoing chmod)) This option allows you to specify a set of
|
||||
comma-separated chmod strings that will affect the permissions of all
|
||||
outgoing files (files that are being sent out from the daemon). These
|
||||
changes happen first, making the sent permissions appear to be different
|
||||
than those stored in the filesystem itself. For instance, you could
|
||||
disable group write permissions on the server while having it appear to
|
||||
be on to the clients.
|
||||
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
|
||||
manpage for information on the format of this string.
|
||||
|
||||
dit(bf(auth users)) The "auth users" option specifies a comma and
|
||||
space separated list of usernames that will be allowed to connect to
|
||||
space-separated list of usernames that will be allowed to connect to
|
||||
this module. The usernames do not need to exist on the local
|
||||
system. The usernames may also contain shell wildcard characters. If
|
||||
"auth users" is set then the client will be challenged to supply a
|
||||
username and password to connect to the module. A challenge response
|
||||
authentication protocol is used for this exchange. The plain text
|
||||
usernames are passwords are stored in the file specified by the
|
||||
usernames and passwords are stored in the file specified by the
|
||||
"secrets file" option. The default is for all users to be able to
|
||||
connect without a password (this is called "anonymous rsync").
|
||||
|
||||
See also the bf(CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL
|
||||
PROGRAM) section in rsync(1) for information on how handle an
|
||||
See also the "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
|
||||
PROGRAM" section in bf(rsync)(1) for information on how handle an
|
||||
rsyncd.conf-level username that differs from the remote-shell-level
|
||||
username when using a remote shell to connect to an rsync server.
|
||||
username when using a remote shell to connect to an rsync daemon.
|
||||
|
||||
dit(bf(secrets file)) The "secrets file" option specifies the name of
|
||||
a file that contains the username:password pairs used for
|
||||
@@ -259,13 +320,13 @@ username:password pairs separated by a single colon. Any line starting
|
||||
with a hash (#) is considered a comment and is skipped. The passwords
|
||||
can contain any characters but be warned that many operating systems
|
||||
limit the length of passwords that can be typed at the client end, so
|
||||
you may find that passwords longer than 8 characters don't work.
|
||||
you may find that passwords longer than 8 characters don't work.
|
||||
|
||||
There is no default for the "secrets file" option, you must choose a name
|
||||
(such as tt(/etc/rsyncd.secrets)). The file must normally not be readable
|
||||
by "other"; see "strict modes".
|
||||
|
||||
dit(bf(strict modes)) The "strict modes" option determines whether or not
|
||||
dit(bf(strict modes)) The "strict modes" option determines whether or not
|
||||
the permissions on the secrets file will be checked. If "strict modes" is
|
||||
true, then the secrets file must not be readable by any user ID other
|
||||
than the one that the rsync daemon is running under. If "strict modes" is
|
||||
@@ -279,40 +340,38 @@ connection is rejected.
|
||||
|
||||
Each pattern can be in one of five forms:
|
||||
|
||||
itemize(
|
||||
quote(itemization(
|
||||
it() a dotted decimal IPv4 address of the form a.b.c.d, or an IPv6 address
|
||||
of the form a:b:c::d:e:f. In this case the incoming machine's IP address
|
||||
must match exactly.
|
||||
|
||||
it() an address/mask in the form ipaddr/n where ipaddr is the IP address
|
||||
and n is the number of one bits in the netmask. All IP addresses which
|
||||
match the masked IP address will be allowed in.
|
||||
|
||||
it() an address/mask in the form ipaddr/maskaddr where ipaddr is the
|
||||
IP address and maskaddr is the netmask in dotted decimal notation for IPv4,
|
||||
or similar for IPv6, e.g. ffff:ffff:ffff:ffff:: instead of /64. All IP
|
||||
addresses which match the masked IP address will be allowed in.
|
||||
|
||||
it() a hostname. The hostname as determined by a reverse lookup will
|
||||
be matched (case insensitive) against the pattern. Only an exact
|
||||
match is allowed in.
|
||||
|
||||
it() a hostname pattern using wildcards. These are matched using the
|
||||
same rules as normal unix filename matching. If the pattern matches
|
||||
then the client is allowed in.
|
||||
)
|
||||
))
|
||||
|
||||
Note IPv6 link-local addresses can have a scope in the address specification:
|
||||
|
||||
quote(fe80::1%link1)
|
||||
quote(fe80::%link1/64)
|
||||
quote(fe80::%link1/ffff:ffff:ffff:ffff::)
|
||||
quote(
|
||||
tt( fe80::1%link1)nl()
|
||||
tt( fe80::%link1/64)nl()
|
||||
tt( fe80::%link1/ffff:ffff:ffff:ffff::)nl()
|
||||
)
|
||||
|
||||
You can also combine "hosts allow" with a separate "hosts deny"
|
||||
option. If both options are specified then the "hosts allow" option s
|
||||
checked first and a match results in the client being able to
|
||||
connect. The "hosts deny" option is then checked and a match means
|
||||
that the host is rejected. If the host does not match either the
|
||||
that the host is rejected. If the host does not match either the
|
||||
"hosts allow" or the "hosts deny" patterns then it is allowed to
|
||||
connect.
|
||||
|
||||
@@ -326,92 +385,160 @@ rejected. See the "hosts allow" option for more information.
|
||||
The default is no "hosts deny" option, which means all hosts can connect.
|
||||
|
||||
dit(bf(ignore errors)) The "ignore errors" option tells rsyncd to
|
||||
ignore I/O errors on the server when deciding whether to run the delete
|
||||
phase of the transfer. Normally rsync skips the --delete step if any
|
||||
I/O errors have occurred in order to prevent disasterous deletion due
|
||||
ignore I/O errors on the daemon when deciding whether to run the delete
|
||||
phase of the transfer. Normally rsync skips the bf(--delete) step if any
|
||||
I/O errors have occurred in order to prevent disastrous deletion due
|
||||
to a temporary resource shortage or other I/O error. In some cases this
|
||||
test is counter productive so you can use this option to turn off this
|
||||
behaviour.
|
||||
behavior.
|
||||
|
||||
dit(bf(ignore nonreadable)) This tells the rsync server to completely
|
||||
dit(bf(ignore nonreadable)) This tells the rsync daemon to completely
|
||||
ignore files that are not readable by the user. This is useful for
|
||||
public archives that may have some non-readable files among the
|
||||
directories, and the sysadmin doesn't want those files to be seen at all.
|
||||
|
||||
dit(bf(transfer logging)) The "transfer logging" option enables per-file
|
||||
dit(bf(transfer logging)) The "transfer logging" option enables per-file
|
||||
logging of downloads and uploads in a format somewhat similar to that
|
||||
used by ftp daemons. If you want to customize the log formats look at
|
||||
the log format option.
|
||||
used by ftp daemons. The daemon always logs the transfer at the end, so
|
||||
if a transfer is aborted, no mention will be made in the log file.
|
||||
|
||||
If you want to customize the log lines, see the "log format" option.
|
||||
|
||||
dit(bf(log format)) The "log format" option allows you to specify the
|
||||
format used for logging file transfers when transfer logging is
|
||||
enabled. The format is a text string containing embedded single
|
||||
character escape sequences prefixed with a percent (%) character.
|
||||
|
||||
The prefixes that are understood are:
|
||||
|
||||
itemize(
|
||||
it() %h for the remote host name
|
||||
it() %a for the remote IP address
|
||||
it() %l for the length of the file in bytes
|
||||
it() %p for the process ID of this rsync session
|
||||
it() %o for the operation, which is either "send" or "recv"
|
||||
it() %f for the filename
|
||||
it() %P for the module path
|
||||
it() %m for the module name
|
||||
it() %t for the current date time
|
||||
it() %u for the authenticated username (or the null string)
|
||||
it() %b for the number of bytes actually transferred
|
||||
it() %c when sending files this gives the number of checksum bytes
|
||||
received for this file
|
||||
)
|
||||
format used for logging file transfers when transfer logging is enabled.
|
||||
The format is a text string containing embedded single-character escape
|
||||
sequences prefixed with a percent (%) character. An optional numeric
|
||||
field width may also be specified between the percent and the escape
|
||||
letter (e.g. "bf(%-50n %8l %07p)").
|
||||
|
||||
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
|
||||
is always added to the beginning when using the "log file" option.
|
||||
is always prefixed when using the "log file" option.
|
||||
(A perl script that will summarize this default log format is included
|
||||
in the rsync source code distribution in the "support" subdirectory:
|
||||
rsyncstats.)
|
||||
|
||||
A perl script called rsyncstats to summarize this format is included
|
||||
in the rsync source code distribution.
|
||||
The single-character escapes that are understood are as follows:
|
||||
|
||||
quote(itemization(
|
||||
it() %a the remote IP address
|
||||
it() %b the number of bytes actually transferred
|
||||
it() %B the permission bits of the file (e.g. rwxrwxrwt)
|
||||
it() %c the checksum bytes received for this file (only when sending)
|
||||
it() %f the filename (long form on sender; no trailing "/")
|
||||
it() %G the gid of the file (decimal) or "DEFAULT"
|
||||
it() %h the remote host name
|
||||
it() %i an itemized list of what is being updated
|
||||
it() %l the length of the file in bytes
|
||||
it() %L the string " -> SYMLINK", " => HARDLINK", or "" (where bf(SYMLINK) or bf(HARDLINK) is a filename)
|
||||
it() %m the module name
|
||||
it() %M the last-modified time of the file
|
||||
it() %n the filename (short form; trailing "/" on dir)
|
||||
it() %o the operation, which is "send", "recv", or "del." (the latter includes the trailing period)
|
||||
it() %p the process ID of this rsync session
|
||||
it() %P the module path
|
||||
it() %t the current date time
|
||||
it() %u the authenticated username or an empty string
|
||||
it() %U the uid of the file (decimal)
|
||||
))
|
||||
|
||||
For a list of what the characters mean that are output by "%i", see the
|
||||
bf(--itemize-changes) option in the rsync manpage.
|
||||
|
||||
Note that some of the logged output changes when talking with older
|
||||
rsync versions. For instance, deleted files were only output as verbose
|
||||
messages prior to rsync 2.6.4.
|
||||
|
||||
dit(bf(timeout)) The "timeout" option allows you to override the
|
||||
clients choice for I/O timeout for this module. Using this option you
|
||||
can ensure that rsync won't wait on a dead client forever. The timeout
|
||||
is specified in seconds. A value of zero means no timeout and is the
|
||||
default. A good choice for anonymous rsync servers may be 600 (giving
|
||||
default. A good choice for anonymous rsync daemons may be 600 (giving
|
||||
a 10 minute timeout).
|
||||
|
||||
dit(bf(refuse options)) The "refuse options" option allows you to
|
||||
specify a space separated list of rsync command line options that will
|
||||
be refused by your rsync server. The full names of the options must be
|
||||
used (i.e., you must use "checksum" not "c" to disable checksumming).
|
||||
When an option is refused, the server prints an error message and exits.
|
||||
To prevent all compression, you can use "dont compress = *" (see below)
|
||||
specify a space-separated list of rsync command line options that will
|
||||
be refused by your rsync daemon.
|
||||
You may specify the full option name, its one-letter abbreviation, or a
|
||||
wild-card string that matches multiple options.
|
||||
For example, this would refuse bf(--checksum) (bf(-c)) and all the various
|
||||
delete options:
|
||||
|
||||
quote(tt( refuse options = c delete))
|
||||
|
||||
The reason the above refuses all delete options is that the options imply
|
||||
bf(--delete), and implied options are refused just like explicit options.
|
||||
As an additional safety feature, the refusal of "delete" also refuses
|
||||
bf(remove-sent-files) when the daemon is the sender; if you want the latter
|
||||
without the former, instead refuse "delete-*" -- that refuses all the
|
||||
delete modes without affecting bf(--remove-sent-files).
|
||||
|
||||
When an option is refused, the daemon prints an error message and exits.
|
||||
To prevent all compression when serving files,
|
||||
you can use "dont compress = *" (see below)
|
||||
instead of "refuse options = compress" to avoid returning an error to a
|
||||
client that requests compression.
|
||||
|
||||
dit(bf(dont compress)) The "dont compress" option allows you to select
|
||||
filenames based on wildcard patterns that should not be compressed
|
||||
during transfer. Compression is expensive in terms of CPU usage so it
|
||||
when pulling files from the daemon (no analogous option exists to
|
||||
govern the pushing of files to a daemon).
|
||||
Compression is expensive in terms of CPU usage, so it
|
||||
is usually good to not try to compress files that won't compress well,
|
||||
such as already compressed files.
|
||||
such as already compressed files.
|
||||
|
||||
The "dont compress" option takes a space separated list of
|
||||
The "dont compress" option takes a space-separated list of
|
||||
case-insensitive wildcard patterns. Any source filename matching one
|
||||
of the patterns will not be compressed during transfer.
|
||||
|
||||
The default setting is verb(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
|
||||
See the bf(--skip-compress) option in the bf(rsync)(1) manpage for the list
|
||||
of file suffixes that are not compressed by default. Specifying a value
|
||||
for the bf(dont compress) option changes the default when the daemon is
|
||||
the sender.
|
||||
|
||||
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
|
||||
before and/or after the transfer. If the bf(pre-xfer exec) command fails, the
|
||||
transfer is aborted before it begins.
|
||||
|
||||
The following environment variables will be set, though some are
|
||||
specific to the pre-xfer or the post-xfer environment:
|
||||
|
||||
quote(itemization(
|
||||
it() bf(RSYNC_MODULE_NAME): The name of the module being accessed.
|
||||
it() bf(RSYNC_MODULE_PATH): The path configured for the module.
|
||||
it() bf(RSYNC_HOST_ADDR): The accessing host's IP address.
|
||||
it() bf(RSYNC_HOST_NAME): The accessing host's name.
|
||||
it() bf(RSYNC_USER_NAME): The accessing user's name (empty if no user).
|
||||
it() bf(RSYNC_PID): A unique number for this transfer.
|
||||
it() bf(RSYNC_REQUEST): (pre-xfer only) The module/path info specified
|
||||
by the user (note that the user can specify multiple source files,
|
||||
so the request can be something like "mod/path1 mod/path2", etc.).
|
||||
it() bf(RSYNC_ARG#): (pre-xfer only) The pre-request arguments are set
|
||||
in these numbered values. RSYNC_ARG0 is always "rsyncd", and the last
|
||||
value contains a single period.
|
||||
it() bf(RSYNC_EXIT_STATUS): (post-xfer only) the server side's exit value.
|
||||
This will be 0 for a successful run, a positive value for an error that the
|
||||
server generated, or a -1 if rsync failed to exit properly. Note that an
|
||||
error that occurs on the client side does not currently get sent to the
|
||||
server side, so this is not the final exit status for the whole transfer.
|
||||
it() bf(RSYNC_RAW_STATUS): (post-xfer only) the raw exit value from code(waitpid()).
|
||||
))
|
||||
|
||||
Even though the commands can be associated with a particular module, they
|
||||
are run using the permissions of the user that started the daemon (not the
|
||||
module's uid/gid setting) without any chroot restrictions.
|
||||
|
||||
enddit()
|
||||
|
||||
manpagesection(AUTHENTICATION STRENGTH)
|
||||
|
||||
The authentication protocol used in rsync is a 128 bit MD4 based
|
||||
challenge response system. Although I believe that no one has ever
|
||||
demonstrated a brute-force break of this sort of system you should
|
||||
realize that this is not a "military strength" authentication system.
|
||||
It should be good enough for most purposes but if you want really top
|
||||
quality security then I recommend that you run rsync over ssh.
|
||||
challenge response system. This is fairly weak protection, though (with
|
||||
at least one brute-force hash-finding algorithm publicly available), so
|
||||
if you want really top-quality security, then I recommend that you run
|
||||
rsync over ssh. (Yes, a future version of rsync will switch over to a
|
||||
stronger hashing method.)
|
||||
|
||||
Also note that the rsync server protocol does not currently provide any
|
||||
Also note that the rsync daemon protocol does not currently provide any
|
||||
encryption of the data that is transferred over the connection. Only
|
||||
authentication is provided. Use ssh as the transport if you want
|
||||
encryption.
|
||||
@@ -419,32 +546,6 @@ encryption.
|
||||
Future versions of rsync may support SSL for better authentication and
|
||||
encryption, but that is still being investigated.
|
||||
|
||||
manpagesection(RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
|
||||
|
||||
If rsync is run with both the --daemon and --rsh (-e) options, it will
|
||||
spawn an rsync daemon using a remote shell connection. Several
|
||||
configuration options will not be available unless the remote user is
|
||||
root (e.g. chroot, setuid/setgid, etc.). There is no need to configure
|
||||
inetd or the services map to include the rsync server port if you run an
|
||||
rsync server only via a remote shell program.
|
||||
|
||||
ADVANCED: To run an rsync server out of a single-use ssh key, use the
|
||||
"command=em(COMMAND)" syntax in the remote user's authorized_keys entry,
|
||||
where command would be
|
||||
|
||||
quote(rsync --server --daemon .)
|
||||
|
||||
NOTE: rsync's argument parsing expects the trailing ".", so make sure
|
||||
that it's there. If you want to use an rsyncd.conf(5)-style
|
||||
configuration file other than the default, you can added a
|
||||
--config option to the em(command):
|
||||
|
||||
quote(rsync --server --daemon --config=em(file) .)
|
||||
|
||||
Note that the "--server" here is the internal option that rsync uses to
|
||||
run the remote version of rsync that it communicates with, and thus you
|
||||
should not be using the --server option under normal circumstances.
|
||||
|
||||
manpagesection(EXAMPLES)
|
||||
|
||||
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
|
||||
@@ -456,17 +557,17 @@ verb(
|
||||
comment = ftp export area
|
||||
)
|
||||
|
||||
|
||||
A more sophisticated example would be:
|
||||
|
||||
uid = nobody nl()
|
||||
gid = nobody nl()
|
||||
use chroot = no nl()
|
||||
max connections = 4 nl()
|
||||
syslog facility = local5 nl()
|
||||
verb(
|
||||
uid = nobody
|
||||
gid = nobody
|
||||
use chroot = no
|
||||
max connections = 4
|
||||
syslog facility = local5
|
||||
pid file = /var/run/rsyncd.pid
|
||||
|
||||
verb([ftp]
|
||||
[ftp]
|
||||
path = /var/ftp/pub
|
||||
comment = whole ftp area (approx 6.1 GB)
|
||||
|
||||
@@ -477,7 +578,7 @@ verb([ftp]
|
||||
[rsyncftp]
|
||||
path = /var/ftp/pub/rsync
|
||||
comment = rsync ftp area (approx 6 MB)
|
||||
|
||||
|
||||
[sambawww]
|
||||
path = /public_html/samba
|
||||
comment = Samba WWW pages (approx 240 MB)
|
||||
@@ -491,8 +592,10 @@ verb([ftp]
|
||||
|
||||
The /etc/rsyncd.secrets file would look something like this:
|
||||
|
||||
tridge:mypass nl()
|
||||
susan:herpass
|
||||
quote(
|
||||
tt(tridge:mypass)nl()
|
||||
tt(susan:herpass)nl()
|
||||
)
|
||||
|
||||
manpagefiles()
|
||||
|
||||
@@ -500,21 +603,18 @@ manpagefiles()
|
||||
|
||||
manpageseealso()
|
||||
|
||||
rsync(1)
|
||||
bf(rsync)(1)
|
||||
|
||||
manpagediagnostics()
|
||||
|
||||
manpagebugs()
|
||||
|
||||
The rsync server does not send all types of error messages to the
|
||||
client. this means a client may be mystified as to why a transfer
|
||||
failed. The error will have been logged by syslog on the server.
|
||||
|
||||
Please report bugs! The rsync bug tracking system is online at
|
||||
url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
This man page is current for version 2.x of rsync.
|
||||
|
||||
This man page is current for version 3.0.0pre2 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
@@ -535,12 +635,13 @@ Gailly and Mark Adler.
|
||||
manpagesection(THANKS)
|
||||
|
||||
Thanks to Warren Stanley for his original idea and patch for the rsync
|
||||
server. Thanks to Karsten Thygesen for his many suggestions and
|
||||
documentation!
|
||||
daemon. Thanks to Karsten Thygesen for his many suggestions and
|
||||
documentation!
|
||||
|
||||
manpageauthor()
|
||||
|
||||
rsync was written by Andrew Tridgell and Paul Mackerras. They may be
|
||||
contacted via email at tridge@samba.org and
|
||||
Paul.Mackerras@cs.anu.edu.au
|
||||
rsync was written by Andrew Tridgell and Paul Mackerras.
|
||||
Many people have later contributed to it.
|
||||
|
||||
Mailing lists for support and development are available at
|
||||
url(http://lists.samba.org)(lists.samba.org)
|
||||
|
||||
106
runtests.sh
106
runtests.sh
@@ -1,6 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
# Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version
|
||||
@@ -13,8 +14,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# rsync top-level test script -- this invokes all the other more
|
||||
# detailed tests in order. This script can either be called by `make
|
||||
@@ -49,8 +49,8 @@
|
||||
|
||||
# This script must be invoked from the build directory.
|
||||
|
||||
# A scratch directory, 'testtmp', is created in the build directory to
|
||||
# hold working files.
|
||||
# A scratch directory, 'testtmp', is used in the build directory to
|
||||
# hold per-test subdirectories.
|
||||
|
||||
# This script also uses the $loglevel environment variable. 1 is the
|
||||
# default value, and 10 the most verbose. You can set this from the
|
||||
@@ -85,7 +85,7 @@
|
||||
# they're explicitly given on the command line.
|
||||
|
||||
# Also, we can't count on 'cp -a' or 'mkdir -p', although they're
|
||||
# pretty handy.
|
||||
# pretty handy (see function makepath for the latter).
|
||||
|
||||
# I think some of the GNU documentation suggests that we shouldn't
|
||||
# rely on shell functions. However, the Bash manual seems to say that
|
||||
@@ -100,6 +100,8 @@
|
||||
# You cannot do "export VAR=VALUE" all on one line; the export must be
|
||||
# separate from the assignment. (SCO SysV)
|
||||
|
||||
# Don't rely on grep -q, as that doesn't work everywhere -- just redirect
|
||||
# stdout to /dev/null to keep it quiet.
|
||||
|
||||
|
||||
# STILL TO DO:
|
||||
@@ -124,72 +126,110 @@ set -e
|
||||
. "./shconfig"
|
||||
|
||||
RUNSHFLAGS='-e'
|
||||
export RUNSHFLAGS
|
||||
|
||||
# for Solaris
|
||||
PATH="/usr/xpg4/bin/:$PATH"
|
||||
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin/:$PATH"
|
||||
|
||||
if [ -n "$loglevel" ] && [ "$loglevel" -gt 8 ]
|
||||
then
|
||||
if set -x
|
||||
then
|
||||
if [ "x$loglevel" != x ] && [ "$loglevel" -gt 8 ]; then
|
||||
if set -x; then
|
||||
# If it doesn't work the first time, don't keep trying.
|
||||
RUNSHFLAGS="$RUNSHFLAGS -x"
|
||||
fi
|
||||
fi
|
||||
|
||||
POSIXLY_CORRECT=1
|
||||
if test x"$TOOLDIR" = x; then
|
||||
TOOLDIR=`pwd`
|
||||
fi
|
||||
srcdir=`dirname $0`
|
||||
if test x"$srcdir" = x -o x"$srcdir" = x.; then
|
||||
srcdir="$TOOLDIR"
|
||||
fi
|
||||
if test x"$rsync_bin" = x; then
|
||||
rsync_bin="$TOOLDIR/rsync"
|
||||
fi
|
||||
|
||||
# This allows the user to specify extra rsync options -- use carefully!
|
||||
RSYNC="$rsync_bin $*"
|
||||
#RSYNC="valgrind $rsync_bin $*"
|
||||
|
||||
export POSIXLY_CORRECT TOOLDIR srcdir RSYNC
|
||||
|
||||
echo "============================================================"
|
||||
echo "$0 running in `pwd`"
|
||||
echo " rsync_bin=$rsync_bin"
|
||||
echo "$0 running in $TOOLDIR"
|
||||
echo " rsync_bin=$RSYNC"
|
||||
echo " srcdir=$srcdir"
|
||||
|
||||
testuser=`id -un || whoami || echo UNKNOWN`
|
||||
if [ -f /usr/bin/whoami ]; then
|
||||
testuser=`/usr/bin/whoami`
|
||||
elif [ -f /usr/ucb/whoami ]; then
|
||||
testuser=`/usr/ucb/whoami`
|
||||
elif [ -f /bin/whoami ]; then
|
||||
testuser=`/bin/whoami`
|
||||
else
|
||||
testuser=`id -un 2>/dev/null || echo ${LOGNAME:-${USERNAME:-${USER:-'UNKNOWN'}}}`
|
||||
fi
|
||||
|
||||
echo " testuser=$testuser"
|
||||
echo " os=`uname -a`"
|
||||
|
||||
# It must be "yes", not just nonnull
|
||||
if test "x$preserve_scratch" = xyes
|
||||
then
|
||||
if [ "x$preserve_scratch" = xyes ]; then
|
||||
echo " preserve_scratch=yes"
|
||||
else
|
||||
echo " preserve_scratch=no"
|
||||
fi
|
||||
|
||||
# Check if setacl/setfacl is around and if it supports the -k or -s option.
|
||||
if setacl -k u::7,g::5,o:5 testsuite 2>/dev/null; then
|
||||
setfacl_nodef='setacl -k'
|
||||
elif setfacl --help 2>&1 | grep ' -k,\|\[-[a-z]*k' >/dev/null; then
|
||||
setfacl_nodef='setfacl -k'
|
||||
elif setfacl -s u::7,g::5,o:5 testsuite 2>/dev/null; then
|
||||
setfacl_nodef='setfacl -s u::7,g::5,o:5'
|
||||
else
|
||||
# The "true" command runs successfully, but does nothing.
|
||||
setfacl_nodef=true
|
||||
fi
|
||||
|
||||
if test ! -f $rsync_bin
|
||||
then
|
||||
export setfacl_nodef
|
||||
|
||||
if [ ! -f "$rsync_bin" ]; then
|
||||
echo "rsync_bin $rsync_bin is not a file" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if test ! -d $srcdir
|
||||
then
|
||||
if [ ! -d "$srcdir" ]; then
|
||||
echo "srcdir $srcdir is not a directory" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
RSYNC="$rsync_bin"
|
||||
|
||||
export rsync_bin RSYNC
|
||||
|
||||
skipped=0
|
||||
missing=0
|
||||
passed=0
|
||||
failed=0
|
||||
|
||||
# Prefix for scratch directory. We create separate directories for
|
||||
# each test case, so that they can be left behind in case of failure
|
||||
# to aid investigation.
|
||||
scratchbase="`pwd`"/testtmp
|
||||
# Directory that holds the other test subdirs. We create separate dirs
|
||||
# inside for each test case, so that they can be left behind in case of
|
||||
# failure to aid investigation. We don't remove the testtmp subdir at
|
||||
# the end so that it can be configured as a symlink to a filesystem that
|
||||
# has ACLs and xattr support enabled (if desired).
|
||||
scratchbase="$TOOLDIR"/testtmp
|
||||
echo " scratchbase=$scratchbase"
|
||||
[ -d "$scratchbase" ] || mkdir "$scratchbase"
|
||||
|
||||
suitedir="$srcdir/testsuite"
|
||||
|
||||
export scratchdir suitedir
|
||||
|
||||
prep_scratch() {
|
||||
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
|
||||
[ -d "$scratchdir" ] && chmod -R u+rwX "$scratchdir" && rm -rf "$scratchdir"
|
||||
mkdir "$scratchdir"
|
||||
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
|
||||
$setfacl_nodef "$scratchdir" || true
|
||||
chmod g-s "$scratchdir"
|
||||
ln -s "$srcdir" "$scratchdir/src"
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -198,15 +238,14 @@ maybe_discard_scratch() {
|
||||
return 0
|
||||
}
|
||||
|
||||
if [ "x$whichtests" = x ]
|
||||
then
|
||||
if [ "x$whichtests" = x ]; then
|
||||
whichtests="*.test"
|
||||
fi
|
||||
|
||||
for testscript in $suitedir/$whichtests
|
||||
do
|
||||
testbase=`echo $testscript | sed 's!.*/!!' | sed -e 's/.test\$//'`
|
||||
scratchdir="$scratchbase.$testbase"
|
||||
testbase=`echo $testscript | sed -e 's!.*/!!' -e 's/.test\$//'`
|
||||
scratchdir="$scratchbase/$testbase"
|
||||
|
||||
prep_scratch
|
||||
|
||||
@@ -250,8 +289,7 @@ do
|
||||
*)
|
||||
echo "FAIL $testbase"
|
||||
failed=`expr $failed + 1`
|
||||
if [ "x$nopersist" = "xyes" ]
|
||||
then
|
||||
if [ "x$nopersist" = xyes ]; then
|
||||
exit 1
|
||||
fi
|
||||
esac
|
||||
|
||||
483
sender.c
483
sender.c
@@ -1,33 +1,50 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
* Routines only used by the sending process.
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int io_error;
|
||||
extern int dry_run;
|
||||
extern int do_xfers;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int inc_recurse;
|
||||
extern int log_before_transfer;
|
||||
extern int stdout_format_has_i;
|
||||
extern int logfile_format_has_i;
|
||||
extern int csum_length;
|
||||
extern int append_mode;
|
||||
extern int io_error;
|
||||
extern int allowed_lull;
|
||||
extern int preserve_xattrs;
|
||||
extern int protocol_version;
|
||||
|
||||
extern int remove_source_files;
|
||||
extern int updating_basis_file;
|
||||
extern int make_backups;
|
||||
extern int do_progress;
|
||||
extern int inplace;
|
||||
extern int batch_fd;
|
||||
extern int write_batch;
|
||||
extern struct stats stats;
|
||||
extern struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
|
||||
/**
|
||||
* @file
|
||||
@@ -36,22 +53,6 @@ extern int protocol_version;
|
||||
* and transmits them to the receiver. The sender process runs on the
|
||||
* machine holding the source files.
|
||||
**/
|
||||
void read_sum_head(int f, struct sum_struct *sum)
|
||||
{
|
||||
sum->count = read_int(f);
|
||||
sum->blength = read_int(f);
|
||||
if (protocol_version < 27) {
|
||||
sum->s2length = csum_length;
|
||||
} else {
|
||||
sum->s2length = read_int(f);
|
||||
if (sum->s2length > MD4_SUM_LENGTH) {
|
||||
rprintf(FERROR, "Invalid checksum length %ld\n",
|
||||
(long)sum->s2length);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
sum->remainder = read_int(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the checksums for a buffer
|
||||
@@ -59,44 +60,57 @@ void read_sum_head(int f, struct sum_struct *sum)
|
||||
static struct sum_struct *receive_sums(int f)
|
||||
{
|
||||
struct sum_struct *s;
|
||||
int i;
|
||||
int32 i;
|
||||
int lull_mod = allowed_lull * 5;
|
||||
OFF_T offset = 0;
|
||||
|
||||
s = new(struct sum_struct);
|
||||
if (!s) out_of_memory("receive_sums");
|
||||
if (!(s = new(struct sum_struct)))
|
||||
out_of_memory("receive_sums");
|
||||
|
||||
read_sum_head(f, s);
|
||||
|
||||
s->sums = NULL;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "count=%ld n=%u rem=%u\n",
|
||||
(long)s->count, s->blength, s->remainder);
|
||||
rprintf(FINFO, "count=%.0f n=%ld rem=%ld\n",
|
||||
(double)s->count, (long)s->blength, (long)s->remainder);
|
||||
}
|
||||
|
||||
if (append_mode > 0) {
|
||||
s->flength = (OFF_T)s->count * s->blength;
|
||||
if (s->remainder)
|
||||
s->flength -= s->blength - s->remainder;
|
||||
return s;
|
||||
}
|
||||
|
||||
if (s->count == 0)
|
||||
return(s);
|
||||
|
||||
s->sums = new_array(struct sum_buf, s->count);
|
||||
if (!s->sums) out_of_memory("receive_sums");
|
||||
if (!(s->sums = new_array(struct sum_buf, s->count)))
|
||||
out_of_memory("receive_sums");
|
||||
|
||||
for (i = 0; i < (int) s->count; i++) {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
s->sums[i].sum1 = read_int(f);
|
||||
read_buf(f, s->sums[i].sum2, s->s2length);
|
||||
|
||||
s->sums[i].offset = offset;
|
||||
s->sums[i].i = i;
|
||||
s->sums[i].flags = 0;
|
||||
|
||||
if (i == (int) s->count-1 && s->remainder != 0) {
|
||||
if (i == s->count-1 && s->remainder != 0)
|
||||
s->sums[i].len = s->remainder;
|
||||
} else {
|
||||
else
|
||||
s->sums[i].len = s->blength;
|
||||
}
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
i, s->sums[i].len, (double)s->sums[i].offset, s->sums[i].sum1);
|
||||
if (allowed_lull && !(i % lull_mod))
|
||||
maybe_send_keepalive();
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
i, s->sums[i].len, (double)s->sums[i].offset,
|
||||
s->sums[i].sum1);
|
||||
}
|
||||
}
|
||||
|
||||
s->flength = offset;
|
||||
@@ -104,220 +118,259 @@ static struct sum_struct *receive_sums(int f)
|
||||
return s;
|
||||
}
|
||||
|
||||
void successful_send(int ndx)
|
||||
{
|
||||
char fname[MAXPATHLEN];
|
||||
struct file_struct *file;
|
||||
struct file_list *flist;
|
||||
|
||||
if (!remove_source_files)
|
||||
return;
|
||||
|
||||
void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
if (!(flist = flist_for_ndx(ndx))) {
|
||||
rprintf(FERROR,
|
||||
"INTERNAL ERROR: unable to find flist for item %d\n",
|
||||
ndx);
|
||||
return;
|
||||
}
|
||||
|
||||
file = flist->files[ndx - flist->ndx_start];
|
||||
if (!push_pathname(F_PATHNAME(file), -1))
|
||||
return;
|
||||
f_name(file, fname);
|
||||
|
||||
if (do_unlink(fname) == 0) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "sender removed %s\n", fname);
|
||||
} else
|
||||
rsyserr(FERROR, errno, "sender failed to remove %s", fname);
|
||||
}
|
||||
|
||||
static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
|
||||
const char *fname, struct file_struct *file,
|
||||
uchar fnamecmp_type, char *buf, int len)
|
||||
{
|
||||
write_ndx(f_out, ndx);
|
||||
if (protocol_version < 29)
|
||||
return;
|
||||
write_shortint(f_out, iflags);
|
||||
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
|
||||
write_byte(f_out, fnamecmp_type);
|
||||
if (iflags & ITEM_XNAME_FOLLOWS)
|
||||
write_vstring(f_out, buf, len);
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
|
||||
send_xattr_request(fname, file, f_out);
|
||||
#endif
|
||||
}
|
||||
|
||||
void send_files(int f_in, int f_out)
|
||||
{
|
||||
int fd = -1;
|
||||
struct sum_struct *s;
|
||||
struct map_struct *buf = NULL;
|
||||
struct map_struct *mbuf = NULL;
|
||||
STRUCT_STAT st;
|
||||
char fname[MAXPATHLEN];
|
||||
int i;
|
||||
char fname[MAXPATHLEN], xname[MAXPATHLEN];
|
||||
const char *path, *slash;
|
||||
uchar fnamecmp_type;
|
||||
int iflags, xlen;
|
||||
struct file_struct *file;
|
||||
int phase = 0;
|
||||
extern struct stats stats;
|
||||
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
|
||||
struct stats initial_stats;
|
||||
extern int write_batch;
|
||||
extern int read_batch;
|
||||
int checksums_match;
|
||||
int buff_len;
|
||||
char buff[CHUNK_SIZE];
|
||||
int j;
|
||||
int done;
|
||||
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
|
||||
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
|
||||
int f_xfer = write_batch < 0 ? batch_fd : f_out;
|
||||
int ndx, j;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files starting\n");
|
||||
|
||||
while (1) {
|
||||
unsigned int offset;
|
||||
if (inc_recurse)
|
||||
send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase == 0) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out, -1);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files phase=%d\n", phase);
|
||||
continue;
|
||||
/* This call also sets cur_flist. */
|
||||
ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
|
||||
xname, &xlen);
|
||||
if (ndx == NDX_DONE) {
|
||||
if (inc_recurse && first_flist) {
|
||||
flist_free(first_flist);
|
||||
if (first_flist) {
|
||||
write_ndx(f_out, NDX_DONE);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (++phase > max_phase)
|
||||
break;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files phase=%d\n", phase);
|
||||
write_ndx(f_out, NDX_DONE);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR, "Invalid file index %d (count=%d)\n",
|
||||
i, flist->count);
|
||||
if (inc_recurse)
|
||||
send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
|
||||
|
||||
if (ndx - cur_flist->ndx_start >= 0)
|
||||
file = cur_flist->files[ndx - cur_flist->ndx_start];
|
||||
else
|
||||
file = dir_flist->files[cur_flist->parent_ndx];
|
||||
if (F_PATHNAME(file)) {
|
||||
path = F_PATHNAME(file);
|
||||
slash = "/";
|
||||
} else {
|
||||
path = slash = "";
|
||||
}
|
||||
if (!push_pathname(F_PATHNAME(file), -1))
|
||||
continue;
|
||||
f_name(file, fname);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR)
|
||||
recv_xattr_request(file, f_in);
|
||||
#endif
|
||||
|
||||
if (!(iflags & ITEM_TRANSFER)) {
|
||||
maybe_log_item(file, iflags, itemizing, xname);
|
||||
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
|
||||
fnamecmp_type, xname, xlen);
|
||||
continue;
|
||||
}
|
||||
if (phase == 2) {
|
||||
rprintf(FERROR,
|
||||
"got transfer request in phase 2 [%s]\n",
|
||||
who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
|
||||
stats.current_file_index = i;
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
if (file->basedir) {
|
||||
/* N.B. We're sure that this fits, so offset is OK. */
|
||||
offset = strlcpy(fname, file->basedir, sizeof fname);
|
||||
if (!offset || fname[offset-1] != '/')
|
||||
fname[offset++] = '/';
|
||||
} else
|
||||
offset = 0;
|
||||
f_name_to(file, fname + offset);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname+offset);
|
||||
if (file->flags & FLAG_FILE_SENT) {
|
||||
if (csum_length == SHORT_SUM_LENGTH) {
|
||||
/* For inplace: redo phase turns off the backup
|
||||
* flag so that we do a regular inplace send. */
|
||||
make_backups = -make_backups;
|
||||
append_mode = -append_mode;
|
||||
csum_length = SUM_LENGTH;
|
||||
}
|
||||
write_int(f_out, i);
|
||||
} else {
|
||||
if (csum_length != SHORT_SUM_LENGTH) {
|
||||
make_backups = -make_backups;
|
||||
append_mode = -append_mode;
|
||||
csum_length = SHORT_SUM_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
updating_basis_file = inplace && (protocol_version >= 29
|
||||
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
|
||||
|
||||
stats.current_file_index = ndx;
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += F_LENGTH(file);
|
||||
|
||||
if (!do_xfers) { /* log the transfer */
|
||||
log_item(FCLIENT, file, &stats, iflags, NULL);
|
||||
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
|
||||
fnamecmp_type, xname, xlen);
|
||||
continue;
|
||||
}
|
||||
|
||||
initial_stats = stats;
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (!s) {
|
||||
if (!(s = receive_sums(f_in))) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "receive_sums failed\n");
|
||||
return;
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (write_batch)
|
||||
write_batch_csum_info(&i, s);
|
||||
|
||||
if (!read_batch) {
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
enum logcode c = am_daemon
|
||||
&& protocol_version < 28 ? FERROR
|
||||
: FINFO;
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(c, "file has vanished: %s\n",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "send_files failed to open %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
}
|
||||
free_sums(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* map the local file */
|
||||
if (do_fstat(fd, &st) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "fstat failed: %s\n", strerror(errno));
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd, st.st_size);
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
enum logcode c = am_daemon
|
||||
&& protocol_version < 28 ? FERROR
|
||||
: FINFO;
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(c, "file has vanished: %s\n",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
buf = NULL;
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno,
|
||||
"send_files failed to open %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
|
||||
fname, (double)st.st_size);
|
||||
|
||||
write_int(f_out, i);
|
||||
|
||||
if (write_batch)
|
||||
write_batch_delta_file((char *)&i, sizeof i);
|
||||
|
||||
write_sum_head(f_out, s);
|
||||
free_sums(s);
|
||||
if (protocol_version >= 30)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose > 2 && !read_batch)
|
||||
rprintf(FINFO, "calling match_sums %s\n", fname);
|
||||
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname+offset);
|
||||
/* map the local file */
|
||||
if (do_fstat(fd, &st) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "fstat failed");
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (st.st_size) {
|
||||
int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE);
|
||||
mbuf = map_file(fd, st.st_size, read_size, s->blength);
|
||||
} else
|
||||
mbuf = NULL;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "send_files mapped %s%s%s of size %.0f\n",
|
||||
path,slash,fname, (double)st.st_size);
|
||||
}
|
||||
|
||||
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
|
||||
fnamecmp_type, xname, xlen);
|
||||
write_sum_head(f_xfer, s);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "calling match_sums %s%s%s\n", path,slash,fname);
|
||||
|
||||
if (log_before_transfer)
|
||||
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
|
||||
else if (!am_server && verbose && do_progress)
|
||||
rprintf(FCLIENT, "%s\n", fname);
|
||||
|
||||
set_compression(fname);
|
||||
|
||||
if (read_batch) {
|
||||
/* read checksums originally computed on sender side */
|
||||
read_batch_csum_info(i, s, &checksums_match);
|
||||
if (checksums_match) {
|
||||
read_batch_delta_file((char*)&j, sizeof (int));
|
||||
if (j != i) { /* if flist index entries don't match*/
|
||||
rprintf(FINFO, "index mismatch in send_files\n");
|
||||
rprintf(FINFO, "read index = %d flist ndx = %d\n", j, i);
|
||||
close_batch_delta_file();
|
||||
close_batch_csums_file();
|
||||
exit_cleanup(1);
|
||||
} else {
|
||||
write_int(f_out, j);
|
||||
write_sum_head(f_out, s);
|
||||
done = 0;
|
||||
while (!done) {
|
||||
read_batch_delta_file((char*)&buff_len, sizeof (int));
|
||||
write_int(f_out, buff_len);
|
||||
if (buff_len == 0) {
|
||||
done = 1;
|
||||
} else {
|
||||
if (buff_len > 0) {
|
||||
read_batch_delta_file(buff, buff_len);
|
||||
write_buf(f_out, buff, buff_len);
|
||||
}
|
||||
}
|
||||
} /* end while */
|
||||
read_batch_delta_file( buff, MD4_SUM_LENGTH);
|
||||
write_buf(f_out, buff, MD4_SUM_LENGTH);
|
||||
match_sums(f_xfer, s, mbuf, st.st_size);
|
||||
if (do_progress)
|
||||
end_progress(st.st_size);
|
||||
|
||||
} /* j=i */
|
||||
} else { /* not checksum match */
|
||||
rprintf (FINFO, "readbatch & checksums don't match\n");
|
||||
rprintf (FINFO, "filename=%s is being skipped\n", fname);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
match_sums(f_out, s, buf, st.st_size);
|
||||
log_send(file, &initial_stats);
|
||||
}
|
||||
log_item(log_code, file, &initial_stats, iflags, NULL);
|
||||
|
||||
if (!read_batch) {
|
||||
if (buf) {
|
||||
j = unmap_file(buf);
|
||||
if (j) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR,
|
||||
"read errors mapping %s: (%d) %s\n",
|
||||
full_fname(fname), j, strerror(j));
|
||||
}
|
||||
if (mbuf) {
|
||||
j = unmap_file(mbuf);
|
||||
if (j) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, j,
|
||||
"read errors mapping %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
free_sums(s);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "sender finished %s\n", fname);
|
||||
rprintf(FINFO, "sender finished %s%s%s\n", path,slash,fname);
|
||||
|
||||
/* Flag that we actually sent this entry. */
|
||||
file->flags |= FLAG_FILE_SENT;
|
||||
}
|
||||
if (make_backups < 0)
|
||||
make_backups = -make_backups;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send files finished\n");
|
||||
|
||||
match_report();
|
||||
|
||||
write_int(f_out, -1);
|
||||
if (write_batch || read_batch) {
|
||||
close_batch_csums_file();
|
||||
close_batch_delta_file();
|
||||
}
|
||||
|
||||
write_ndx(f_out, NDX_DONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
321
socket.c
321
socket.c
@@ -1,38 +1,41 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file socket.c
|
||||
*
|
||||
/*
|
||||
* Socket functions used in rsync.
|
||||
*
|
||||
* This file is now converted to use the new-style getaddrinfo()
|
||||
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* This file is now converted to use the new-style getaddrinfo()
|
||||
* interface, which supports IPv6 but is also supported on recent
|
||||
* IPv4-only machines. On systems that don't have that interface, we
|
||||
* emulate it using the KAME implementation.
|
||||
**/
|
||||
* emulate it using the KAME implementation. */
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction sigact;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Establish a proxy connection on an open socket to a web proxy by
|
||||
@@ -52,13 +55,13 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
proxy_user, ":", proxy_pass, NULL);
|
||||
len = strlen(buffer);
|
||||
|
||||
if ((len*8 + 5) / 6 >= (int)sizeof authbuf) {
|
||||
if ((len*8 + 5) / 6 >= (int)sizeof authbuf - 3) {
|
||||
rprintf(FERROR,
|
||||
"authentication information is too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
base64_encode(buffer, len, authbuf);
|
||||
base64_encode(buffer, len, authbuf, 1);
|
||||
authhdr = "\r\nProxy-Authorization: Basic ";
|
||||
} else {
|
||||
*authbuf = '\0';
|
||||
@@ -69,15 +72,13 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
host, port, authhdr, authbuf);
|
||||
len = strlen(buffer);
|
||||
if (write(fd, buffer, len) != len) {
|
||||
rprintf(FERROR, "failed to write to proxy: %s\n",
|
||||
strerror(errno));
|
||||
rsyserr(FERROR, errno, "failed to write to proxy");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
|
||||
if (read(fd, cp, 1) != 1) {
|
||||
rprintf(FERROR, "failed to read from proxy: %s\n",
|
||||
strerror(errno));
|
||||
rsyserr(FERROR, errno, "failed to read from proxy");
|
||||
return -1;
|
||||
}
|
||||
if (*cp == '\n')
|
||||
@@ -90,15 +91,15 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
if (*cp == '\r')
|
||||
*cp = '\0';
|
||||
if (strncmp(buffer, "HTTP/", 5) != 0) {
|
||||
rprintf(FERROR, "bad response from proxy - %s\n",
|
||||
rprintf(FERROR, "bad response from proxy -- %s\n",
|
||||
buffer);
|
||||
return -1;
|
||||
}
|
||||
for (cp = &buffer[5]; isdigit(*(uchar*)cp) || *cp == '.'; cp++) {}
|
||||
for (cp = &buffer[5]; isDigit(cp) || *cp == '.'; cp++) {}
|
||||
while (*cp == ' ')
|
||||
cp++;
|
||||
if (*cp != '2') {
|
||||
rprintf(FERROR, "bad response from proxy - %s\n",
|
||||
rprintf(FERROR, "bad response from proxy -- %s\n",
|
||||
buffer);
|
||||
return -1;
|
||||
}
|
||||
@@ -106,8 +107,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
while (1) {
|
||||
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
|
||||
if (read(fd, cp, 1) != 1) {
|
||||
rprintf(FERROR, "failed to read from proxy: %s\n",
|
||||
strerror(errno));
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to read from proxy");
|
||||
return -1;
|
||||
}
|
||||
if (*cp == '\n')
|
||||
@@ -127,7 +128,7 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
* if this fails.
|
||||
**/
|
||||
int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
const char *bind_address)
|
||||
const char *bind_addr)
|
||||
{
|
||||
int error;
|
||||
struct addrinfo bhints, *bres_all, *r;
|
||||
@@ -136,9 +137,9 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
bhints.ai_family = ai_family;
|
||||
bhints.ai_socktype = ai_socktype;
|
||||
bhints.ai_flags = AI_PASSIVE;
|
||||
if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
|
||||
if ((error = getaddrinfo(bind_addr, NULL, &bhints, &bres_all))) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
|
||||
bind_address, gai_strerror(error));
|
||||
bind_addr, gai_strerror(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -172,12 +173,12 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
* reachable, perhaps because we can't e.g. route ipv6 to that network
|
||||
* but we can get ip4 packets through.
|
||||
*
|
||||
* @param bind_address Local address to use. Normally NULL to bind
|
||||
* @param bind_addr Local address to use. Normally NULL to bind
|
||||
* the wildcard address.
|
||||
*
|
||||
* @param af_hint Address family, e.g. AF_INET or AF_INET6.
|
||||
**/
|
||||
int open_socket_out(char *host, int port, const char *bind_address,
|
||||
int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
int type = SOCK_STREAM;
|
||||
@@ -198,7 +199,7 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
strlcpy(buffer, h, sizeof buffer);
|
||||
|
||||
/* Is the USER:PASS@ prefix present? */
|
||||
if ((cp = strchr(buffer, '@')) != NULL) {
|
||||
if ((cp = strrchr(buffer, '@')) != NULL) {
|
||||
*cp++ = '\0';
|
||||
/* The remainder is the HOST:PORT part. */
|
||||
h = cp;
|
||||
@@ -253,9 +254,9 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
if (s < 0)
|
||||
continue;
|
||||
|
||||
if (bind_address
|
||||
if (bind_addr
|
||||
&& try_bind_local(s, res->ai_family, type,
|
||||
bind_address) == -1) {
|
||||
bind_addr) == -1) {
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
@@ -276,8 +277,7 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
if (s < 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
|
||||
h, strerror(errno));
|
||||
rsyserr(FERROR, errno, "failed to connect to %s", h);
|
||||
return -1;
|
||||
}
|
||||
return s;
|
||||
@@ -294,13 +294,49 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
*
|
||||
* This is based on the Samba LIBSMB_PROG feature.
|
||||
*
|
||||
* @param bind_address Local address to use. Normally NULL to get the stack default.
|
||||
* @param bind_addr Local address to use. Normally NULL to get the stack default.
|
||||
**/
|
||||
int open_socket_out_wrapped(char *host, int port, const char *bind_address,
|
||||
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
char *prog = getenv("RSYNC_CONNECT_PROG");
|
||||
|
||||
if (prog && strchr(prog, '%')) {
|
||||
int hlen = strlen(host);
|
||||
int len = strlen(prog) + 1;
|
||||
char *f, *t;
|
||||
for (f = prog; *f; f++) {
|
||||
if (*f != '%')
|
||||
continue;
|
||||
/* Compute more than enough room. */
|
||||
if (f[1] == '%')
|
||||
f++;
|
||||
else
|
||||
len += hlen;
|
||||
}
|
||||
f = prog;
|
||||
if (!(prog = new_array(char, len)))
|
||||
out_of_memory("open_socket_out_wrapped");
|
||||
for (t = prog; *f; f++) {
|
||||
if (*f == '%') {
|
||||
switch (*++f) {
|
||||
case '%':
|
||||
/* Just skips the extra '%'. */
|
||||
break;
|
||||
case 'H':
|
||||
memcpy(t, host, hlen);
|
||||
t += hlen;
|
||||
continue;
|
||||
default:
|
||||
f--; /* pass % through */
|
||||
break;
|
||||
}
|
||||
}
|
||||
*t++ = *f;
|
||||
}
|
||||
*t = '\0';
|
||||
}
|
||||
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
|
||||
prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
|
||||
@@ -308,36 +344,31 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_address,
|
||||
}
|
||||
if (prog)
|
||||
return sock_exec(prog);
|
||||
return open_socket_out(host, port, bind_address, af_hint);
|
||||
return open_socket_out(host, port, bind_addr, af_hint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Open a socket of the specified type, port and address for incoming data
|
||||
* Open one or more sockets for incoming data using the specified type,
|
||||
* port, and address.
|
||||
*
|
||||
* Try to be better about handling the results of getaddrinfo(): when
|
||||
* opening an inbound socket, we might get several address results,
|
||||
* e.g. for the machine's ipv4 and ipv6 name.
|
||||
* The getaddrinfo() call may return several address results, e.g. for
|
||||
* the machine's IPv4 and IPv6 name.
|
||||
*
|
||||
* If binding a wildcard, then any one of them should do. If an address
|
||||
* was specified but it's insufficiently specific then that's not our
|
||||
* fault.
|
||||
* We return an array of file-descriptors to the sockets, with a trailing
|
||||
* -1 value to indicate the end of the list.
|
||||
*
|
||||
* However, some of the advertized addresses may not work because e.g. we
|
||||
* don't have IPv6 support in the kernel. In that case go on and try all
|
||||
* addresses until one succeeds.
|
||||
*
|
||||
* @param bind_address Local address to bind, or NULL to allow it to
|
||||
* @param bind_addr Local address to bind, or NULL to allow it to
|
||||
* default.
|
||||
**/
|
||||
static int *open_socket_in(int type, int port, const char *bind_address,
|
||||
static int *open_socket_in(int type, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
int one=1;
|
||||
int s, *sp, *socks, maxs;
|
||||
int one = 1;
|
||||
int s, *socks, maxs, i, ecnt;
|
||||
struct addrinfo hints, *all_ai, *resp;
|
||||
char portbuf[10];
|
||||
char portbuf[10], **errmsgs;
|
||||
int error;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
@@ -345,31 +376,35 @@ static int *open_socket_in(int type, int port, const char *bind_address,
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
snprintf(portbuf, sizeof portbuf, "%d", port);
|
||||
error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
|
||||
error = getaddrinfo(bind_addr, portbuf, &hints, &all_ai);
|
||||
if (error) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
|
||||
bind_address, gai_strerror(error));
|
||||
bind_addr, gai_strerror(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Count max number of sockets we might open. */
|
||||
for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
|
||||
|
||||
socks = new_array(int, maxs + 1);
|
||||
if (!socks) {
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME "couldn't allocate memory for sockets");
|
||||
return NULL;
|
||||
}
|
||||
errmsgs = new_array(char *, maxs);
|
||||
if (!socks || !errmsgs)
|
||||
out_of_memory("open_socket_in");
|
||||
|
||||
/* We may not be able to create the socket, if for example the
|
||||
* machine knows about IPv6 in the C library, but not in the
|
||||
* kernel. */
|
||||
sp = socks + 1; /* Leave room for count at start of array. */
|
||||
for (resp = all_ai; resp; resp = resp->ai_next) {
|
||||
for (resp = all_ai, i = ecnt = 0; resp; resp = resp->ai_next) {
|
||||
s = socket(resp->ai_family, resp->ai_socktype,
|
||||
resp->ai_protocol);
|
||||
|
||||
if (s == -1) {
|
||||
int r = asprintf(&errmsgs[ecnt++],
|
||||
"socket(%d,%d,%d) failed: %s\n",
|
||||
(int)resp->ai_family, (int)resp->ai_socktype,
|
||||
(int)resp->ai_protocol, strerror(errno));
|
||||
if (r < 0)
|
||||
out_of_memory("open_socket_in");
|
||||
/* See if there's another address that will work... */
|
||||
continue;
|
||||
}
|
||||
@@ -379,29 +414,47 @@ static int *open_socket_in(int type, int port, const char *bind_address,
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
if (resp->ai_family == AF_INET6) {
|
||||
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(char *)&one, sizeof one);
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(char *)&one, sizeof one) < 0
|
||||
&& default_af_hint != AF_INET6) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now we've got a socket - we need to bind it. */
|
||||
if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
|
||||
/* Nope, try another */
|
||||
int r = asprintf(&errmsgs[ecnt++],
|
||||
"bind() failed: %s (address-family %d)\n",
|
||||
strerror(errno), (int)resp->ai_family);
|
||||
if (r < 0)
|
||||
out_of_memory("open_socket_in");
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
*sp++ = s;
|
||||
socks[i++] = s;
|
||||
}
|
||||
*socks = sp - socks - 1; /* Save count. */
|
||||
socks[i] = -1;
|
||||
|
||||
if (all_ai)
|
||||
freeaddrinfo(all_ai);
|
||||
|
||||
if (*socks == 0) {
|
||||
/* Only output the socket()/bind() messages if we were totally
|
||||
* unsuccessful, or if the daemon is being run with -vv. */
|
||||
for (s = 0; s < ecnt; s++) {
|
||||
if (!i || verbose > 1)
|
||||
rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]), 0);
|
||||
free(errmsgs[s]);
|
||||
}
|
||||
free(errmsgs);
|
||||
|
||||
if (!i) {
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME ": open inbound socket on port %d failed: "
|
||||
"%s\n", port, strerror(errno));
|
||||
"unable to bind any inbound sockets on port %d\n",
|
||||
port);
|
||||
free(socks);
|
||||
return NULL;
|
||||
}
|
||||
@@ -439,16 +492,20 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
|
||||
#ifdef WNOHANG
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0) {}
|
||||
#endif
|
||||
#ifndef HAVE_SIGACTION
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void start_accept_loop(int port, int (*fn)(int, int))
|
||||
{
|
||||
fd_set deffds;
|
||||
int *sp, maxfd, i, j;
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
int *sp, maxfd, i;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigact.sa_flags = SA_NOCLDSTOP;
|
||||
#endif
|
||||
|
||||
/* open an incoming socket */
|
||||
sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
|
||||
@@ -457,12 +514,15 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
|
||||
/* ready to listen */
|
||||
FD_ZERO(&deffds);
|
||||
maxfd = -1;
|
||||
for (i = 1; i <= *sp; i++) {
|
||||
if (listen(sp[i], 5) == -1) {
|
||||
for (j = 1; j <= i; j++)
|
||||
close(sp[j]);
|
||||
free(sp);
|
||||
for (i = 0, maxfd = -1; sp[i] >= 0; i++) {
|
||||
if (listen(sp[i], 5) < 0) {
|
||||
rsyserr(FERROR, errno, "listen() on socket failed");
|
||||
#ifdef INET6
|
||||
if (errno == EADDRINUSE && i > 0) {
|
||||
rprintf(FINFO,
|
||||
"Try using --ipv4 or --ipv6 to avoid this listen() error.\n");
|
||||
}
|
||||
#endif
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
FD_SET(sp[i], &deffds);
|
||||
@@ -470,7 +530,6 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
maxfd = sp[i];
|
||||
}
|
||||
|
||||
|
||||
/* now accept incoming connections - forking a new process
|
||||
* for each incoming connection */
|
||||
while (1) {
|
||||
@@ -483,7 +542,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
/* close log file before the potentially very long select so
|
||||
* file can be trimmed by another process instead of growing
|
||||
* forever */
|
||||
log_close();
|
||||
logfile_close();
|
||||
|
||||
#ifdef FD_COPY
|
||||
FD_COPY(&deffds, &fds);
|
||||
@@ -494,8 +553,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
|
||||
continue;
|
||||
|
||||
fd = -1;
|
||||
for (i = 1; i <= *sp; i++) {
|
||||
for (i = 0, fd = -1; sp[i] >= 0; i++) {
|
||||
if (FD_ISSET(sp[i], &fds)) {
|
||||
fd = accept(sp[i], (struct sockaddr *)&addr,
|
||||
&addrlen);
|
||||
@@ -506,22 +564,21 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
SIGACTION(SIGCHLD, sigchld_handler);
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
int ret;
|
||||
close(sp[i]);
|
||||
/* open log file in child before possibly giving
|
||||
* up privileges */
|
||||
log_open();
|
||||
for (i = 0; sp[i] >= 0; i++)
|
||||
close(sp[i]);
|
||||
/* Re-open log file in child before possibly giving
|
||||
* up privileges (see logfile_close() above). */
|
||||
logfile_reopen();
|
||||
ret = fn(fd, fd);
|
||||
close_all();
|
||||
_exit(ret);
|
||||
} else if (pid < 0) {
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME
|
||||
": could not create child server process: %s\n",
|
||||
strerror(errno));
|
||||
rsyserr(FERROR, errno,
|
||||
"could not create child server process");
|
||||
close(fd);
|
||||
/* This might have happened because we're
|
||||
* overloaded. Sleep briefly before trying to
|
||||
@@ -532,7 +589,6 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
free(sp);
|
||||
}
|
||||
|
||||
|
||||
@@ -627,7 +683,7 @@ void set_socket_options(int fd, char *options)
|
||||
|
||||
case OPT_ON:
|
||||
if (got_value)
|
||||
rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
|
||||
rprintf(FERROR,"syntax error -- %s does not take a value\n",tok);
|
||||
|
||||
{
|
||||
int on = socket_options[i].value;
|
||||
@@ -638,45 +694,15 @@ void set_socket_options(int fd, char *options)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
|
||||
strerror(errno));
|
||||
if (ret != 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to set socket option %s", tok);
|
||||
}
|
||||
}
|
||||
|
||||
free(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Become a daemon, discarding the controlling terminal
|
||||
**/
|
||||
void become_daemon(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (fork()) {
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/* detach from the terminal */
|
||||
#ifdef HAVE_SETSID
|
||||
setsid();
|
||||
#else
|
||||
#ifdef TIOCNOTTY
|
||||
i = open("/dev/tty", O_RDWR);
|
||||
if (i >= 0) {
|
||||
ioctl(i, (int)TIOCNOTTY, (char *)0);
|
||||
close(i);
|
||||
}
|
||||
#endif /* TIOCNOTTY */
|
||||
#endif
|
||||
/* make sure that stdin, stdout an stderr don't stuff things
|
||||
* up (library functions, for example) */
|
||||
for (i = 0; i < 3; i++) {
|
||||
close(i);
|
||||
open("/dev/null", O_RDWR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is like socketpair but uses tcp. It is used by the Samba
|
||||
@@ -703,7 +729,7 @@ static int socketpair_tcp(int fd[2])
|
||||
goto failed;
|
||||
|
||||
memset(&sock2, 0, sizeof sock2);
|
||||
#if HAVE_SOCKADDR_IN_LEN
|
||||
#ifdef HAVE_SOCKADDR_IN_LEN
|
||||
sock2.sin_len = sizeof sock2;
|
||||
#endif
|
||||
sock2.sin_family = PF_INET;
|
||||
@@ -733,14 +759,16 @@ static int socketpair_tcp(int fd[2])
|
||||
goto failed;
|
||||
|
||||
close(listener);
|
||||
listener = -1;
|
||||
|
||||
set_blocking(fd[1]);
|
||||
|
||||
if (connect_done == 0) {
|
||||
if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0
|
||||
&& errno != EISCONN)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
set_blocking(fd[1]);
|
||||
|
||||
/* all OK! */
|
||||
return 0;
|
||||
|
||||
@@ -770,8 +798,7 @@ int sock_exec(const char *prog)
|
||||
int fd[2];
|
||||
|
||||
if (socketpair_tcp(fd) != 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": socketpair_tcp failed (%s)\n",
|
||||
strerror(errno));
|
||||
rsyserr(FERROR, errno, "socketpair_tcp failed");
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 2)
|
||||
|
||||
6
support/Makefile
Normal file
6
support/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
all: savetransfer
|
||||
|
||||
savetransfer: savetransfer.o
|
||||
|
||||
clean:
|
||||
rm -f *.o savetransfer
|
||||
90
support/atomic-rsync
Executable file
90
support/atomic-rsync
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This script lets you update a hierarchy of files in an atomic way by
|
||||
# first creating a new hierarchy using rsync's --link-dest option, and
|
||||
# then swapping the hierarchy into place. **See the usage message for
|
||||
# more details and some important caveats!**
|
||||
|
||||
use strict;
|
||||
use Cwd 'abs_path';
|
||||
|
||||
my $RSYNC_PROG = '/usr/bin/rsync';
|
||||
my $RM_PROG = '/bin/rm';
|
||||
|
||||
my $dest_dir = $ARGV[-1];
|
||||
usage(1) if $dest_dir eq '' || $dest_dir =~ /^--/;
|
||||
|
||||
if (!-d $dest_dir) {
|
||||
print STDERR "$dest_dir is not a directory.\n\n";
|
||||
usage(1);
|
||||
}
|
||||
|
||||
if (@_ = grep(/^--(link|compare)-dest/, @ARGV)) {
|
||||
$_ = join(' or ', @_);
|
||||
print STDERR "You may not use $_ as an rsync option.\n\n";
|
||||
usage(1);
|
||||
}
|
||||
|
||||
$dest_dir = abs_path($dest_dir);
|
||||
if ($dest_dir eq '/') {
|
||||
print STDERR 'You must not use "/" as the destination directory.', "\n\n";
|
||||
usage(1);
|
||||
}
|
||||
|
||||
my $old_dir = "$dest_dir~old~";
|
||||
my $new_dir = $ARGV[-1] = "$dest_dir~new~";
|
||||
|
||||
system($RM_PROG, '-rf', $old_dir) if -d $old_dir;
|
||||
|
||||
if (system($RSYNC_PROG, "--link-dest=$dest_dir", @ARGV)) {
|
||||
if ($? == -1) {
|
||||
print "failed to execute $RSYNC_PROG: $!\n";
|
||||
} elsif ($? & 127) {
|
||||
printf "child died with signal %d, %s coredump\n",
|
||||
($? & 127), ($? & 128) ? 'with' : 'without';
|
||||
} else {
|
||||
printf "child exited with value %d\n", $? >> 8;
|
||||
}
|
||||
exit $?;
|
||||
}
|
||||
|
||||
rename($dest_dir, $old_dir) or die "Unable to rename $new_dir to $old_dir: $!";
|
||||
rename($new_dir, $dest_dir) or die "Unable to rename $new_dir to $dest_dir: $!";
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
sub usage
|
||||
{
|
||||
my($ret) = @_;
|
||||
my $fh = $ret ? *STDERR : *STDOUT;
|
||||
print $fh <<EOT;
|
||||
Usage: atomic-rsync [RSYNC-OPTIONS] HOST:/SOURCE/DIR/ /DEST/DIR/
|
||||
atomic-rsync [RSYNC-OPTIONS] HOST::MOD/DIR/ /DEST/DIR/
|
||||
|
||||
This script lets you update a hierarchy of files in an atomic way by first
|
||||
creating a new hierarchy (using hard-links to leverage the existing files),
|
||||
and then swapping the new hierarchy into place. You must be pulling files
|
||||
to a local directory, and that directory must already exist. For example:
|
||||
|
||||
atomic-rsync -av host:/remote/files/ /local/files/
|
||||
|
||||
This would make the transfer to the directory /local/files~new~ and then
|
||||
swap out /local/files at the end of the transfer by renaming it to
|
||||
/local/files~old~ and putting the new directory into its place. The
|
||||
/local/files~old~ directory will be preserved until the next update, at
|
||||
which point it will be deleted.
|
||||
|
||||
Do NOT specify this command:
|
||||
|
||||
atomic-rsync -av host:/remote/files /local/
|
||||
|
||||
... UNLESS you want the entire /local dir to be swapped out!
|
||||
|
||||
See the "rsync" command for its list of options. You may not use the
|
||||
--link-dest or --compare-dest options (since this script uses --link-dest
|
||||
to make the transfer efficient). Also, the destination directory cannot
|
||||
be "/".
|
||||
EOT
|
||||
exit $ret;
|
||||
}
|
||||
64
support/cull_options
Executable file
64
support/cull_options
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/perl
|
||||
# This script outputs some perl code that parses all possible options
|
||||
# that the code in options.c might send to the server. This perl code
|
||||
# is included in the rrsync script.
|
||||
use strict;
|
||||
|
||||
our(%short_no_arg, %short_with_num, %long_opt);
|
||||
our $last_long_opt;
|
||||
|
||||
open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
|
||||
|
||||
while (<IN>) {
|
||||
if (/\Qargstr[x++]\E = '(.)'/) {
|
||||
$short_no_arg{$1} = 1;
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {
|
||||
$short_with_num{$1} = 1;
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
|
||||
$last_long_opt = $1;
|
||||
$long_opt{$1} = 0;
|
||||
} elsif (defined($last_long_opt)
|
||||
&& /\Qargs[ac++]\E = ([^["\s]+);/ && $1 ne 'dest_option') {
|
||||
$long_opt{$last_long_opt} = 2;
|
||||
undef $last_long_opt;
|
||||
} elsif (/dest_option = "--([^"]+)"/) {
|
||||
$long_opt{$1} = 2;
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qasprintf(\E[^,]+, "--([^"=]+)=/ || /\Qargs[ac++]\E = "--([^"=]+)=/) {
|
||||
$long_opt{$1} = 1;
|
||||
undef $last_long_opt;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
my $short_no_arg = join('', sort keys %short_no_arg);
|
||||
my $short_with_num = join('', sort keys %short_with_num);
|
||||
|
||||
print <<EOT;
|
||||
|
||||
# These options are the only options that rsync might send to the server,
|
||||
# and only in the option format that the stock rsync produces.
|
||||
|
||||
# To disable a short-named option, add its letter to this string:
|
||||
our \$short_disabled = 's';
|
||||
|
||||
our \$short_no_arg = '$short_no_arg'; # DO NOT REMOVE ANY
|
||||
our \$short_with_num = '$short_with_num'; # DO NOT REMOVE ANY
|
||||
|
||||
# To disable a long-named option, change its value to a -1. The values mean:
|
||||
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
|
||||
# check the arg when receiving; and 3 = always check the arg.
|
||||
our \%long_opt = (
|
||||
EOT
|
||||
|
||||
foreach my $opt (sort keys %long_opt) {
|
||||
my $val = $long_opt{$opt};
|
||||
$val = 1 if $opt =~ /^(max-|min-)/;
|
||||
$val = 3 if $opt eq 'files-from';
|
||||
$val = '$ro ? -1 : ' . $val if $opt =~ /^remove-/;
|
||||
print " '$opt' => $val,\n";
|
||||
}
|
||||
|
||||
print ");\n\n";
|
||||
42
support/cvs2includes
Executable file
42
support/cvs2includes
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This script finds all CVS/Entries files in the current directory and below
|
||||
# and creates a local .cvsinclude file with non-inherited rules including each
|
||||
# checked-in file. Then, use this option whenever using --cvs-exclude (-C):
|
||||
#
|
||||
# -f ': .cvsinclude'
|
||||
#
|
||||
# That ensures that all checked-in files/dirs are included in the transfer.
|
||||
# (You could alternately put ": .cvsinclude" into an .rsync-filter file and
|
||||
# use the -F option, which is easier to type.)
|
||||
#
|
||||
# The downside is that you need to remember to re-run cvs2includes whenever
|
||||
# you add a new file to the project.
|
||||
use strict;
|
||||
|
||||
open(FIND, 'find . -name CVS -type d |') or die $!;
|
||||
while (<FIND>) {
|
||||
chomp;
|
||||
s#^\./##;
|
||||
|
||||
my $entries = "$_/Entries";
|
||||
s/CVS$/.cvsinclude/;
|
||||
my $filter = $_;
|
||||
|
||||
open(ENTRIES, $entries) or die "Unable to open $entries: $!\n";
|
||||
my @includes;
|
||||
while (<ENTRIES>) {
|
||||
push(@includes, $1) if m#/(.+?)/#;
|
||||
}
|
||||
close ENTRIES;
|
||||
if (@includes) {
|
||||
open(FILTER, ">$filter") or die "Unable to write $filter: $!\n";
|
||||
print FILTER map "+ /$_\n", @includes;
|
||||
close FILTER;
|
||||
print "Updated $filter\n";
|
||||
} elsif (-f $filter) {
|
||||
unlink($filter);
|
||||
print "Removed $filter\n";
|
||||
}
|
||||
}
|
||||
close FIND;
|
||||
173
support/file-attr-restore
Executable file
173
support/file-attr-restore
Executable file
@@ -0,0 +1,173 @@
|
||||
#!/usr/bin/perl
|
||||
# This script will parse the output of "find ARG [ARG...] -ls" and
|
||||
# apply (at your discretion) the permissions, owner, and group info
|
||||
# it reads onto any existing files and dirs (it doesn't try to affect
|
||||
# symlinks). Run this with --help (-h) for a usage summary.
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
our($p_opt, $o_opt, $g_opt, $map_file, $dry_run, $verbosity, $help_opt);
|
||||
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'all|a' => sub { $p_opt = $o_opt = $g_opt = 1 },
|
||||
'perms|p' => \$p_opt,
|
||||
'owner|o' => \$o_opt,
|
||||
'groups|g' => \$g_opt,
|
||||
'map|m=s' => \$map_file,
|
||||
'dry-run|n' => \$dry_run,
|
||||
'help|h' => \$help_opt,
|
||||
'verbose|v+' => \$verbosity,
|
||||
) || $help_opt;
|
||||
|
||||
our(%uid_hash, %gid_hash);
|
||||
|
||||
$" = ', '; # How to join arrays referenced in double-quotes.
|
||||
|
||||
&parse_map_file($map_file) if defined $map_file;
|
||||
|
||||
my $detail_line = qr{
|
||||
^ \s* \d+ \s+ # ignore inode
|
||||
\d+ \s+ # ignore size
|
||||
([-bcdlps]) # 1. File type
|
||||
( [-r][-w][-xsS] # 2. user-permissions
|
||||
[-r][-w][-xsS] # group-permissions
|
||||
[-r][-w][-xtT] ) \s+ # other-permissions
|
||||
\d+ \s+ # ignore number of links
|
||||
(\S+) \s+ # 3. owner
|
||||
(\S+) \s+ # 4. group
|
||||
(?: \d+ \s+ )? # ignore size (when present)
|
||||
\w+ \s+ \d+ \s+ # ignore month and date
|
||||
\d+ (?: : \d+ )? \s+ # ignore time or year
|
||||
([^\r\n]+) $ # 5. name
|
||||
}x;
|
||||
|
||||
while (<>) {
|
||||
my($type, $perms, $owner, $group, $name) = /$detail_line/;
|
||||
die "Invalid input line $.:\n$_" unless defined $name;
|
||||
die "A filename is not properly escaped:\n$_" unless $name =~ /^[^"\\]*(\\(\d\d\d|\D)[^"\\]*)*$/;
|
||||
my $fn = $name;
|
||||
$fn =~ s/\\(\d+|.)/ eval "\"\\$1\"" /eg;
|
||||
if ($type eq '-') {
|
||||
undef $type unless -f $fn;
|
||||
} elsif ($type eq 'd') {
|
||||
undef $type unless -d $fn;
|
||||
} elsif ($type eq 'b') {
|
||||
undef $type unless -b $fn;
|
||||
} elsif ($type eq 'c') {
|
||||
undef $type unless -c $fn;
|
||||
} elsif ($type eq 'p') {
|
||||
undef $type unless -p $fn;
|
||||
} elsif ($type eq 's') {
|
||||
undef $type unless -S $fn;
|
||||
} else {
|
||||
if ($verbosity) {
|
||||
if ($type eq 'l') {
|
||||
$name =~ s/ -> .*//;
|
||||
$type = 'symlink';
|
||||
} else {
|
||||
$type = "type '$type'";
|
||||
}
|
||||
print "Skipping $name ($type ignored)\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
if (!defined $type) {
|
||||
my $reason = -e _ ? "types don't match" : 'missing';
|
||||
print "Skipping $name ($reason)\n";
|
||||
next;
|
||||
}
|
||||
my($cur_mode, $cur_uid, $cur_gid) = (stat(_))[2,4,5];
|
||||
$cur_mode &= 07777;
|
||||
my $highs = join('', $perms =~ /..(.)..(.)..(.)/);
|
||||
$highs =~ tr/-rwxSTst/00001111/;
|
||||
$perms =~ tr/-STrwxst/00011111/;
|
||||
my $mode = $p_opt ? oct('0b' . $highs . $perms) : $cur_mode;
|
||||
my $uid = $o_opt ? $uid_hash{$owner} : $cur_uid;
|
||||
if (!defined $uid) {
|
||||
if ($owner =~ /^\d+$/) {
|
||||
$uid = $owner;
|
||||
} else {
|
||||
$uid = getpwnam($owner);
|
||||
}
|
||||
$uid_hash{$owner} = $uid;
|
||||
}
|
||||
my $gid = $g_opt ? $gid_hash{$group} : $cur_gid;
|
||||
if (!defined $gid) {
|
||||
if ($group =~ /^\d+$/) {
|
||||
$gid = $group;
|
||||
} else {
|
||||
$gid = getgrnam($group);
|
||||
}
|
||||
$gid_hash{$group} = $gid;
|
||||
}
|
||||
|
||||
my @changes;
|
||||
if ($mode != $cur_mode) {
|
||||
push(@changes, 'permissions');
|
||||
if (!$dry_run && !chmod($mode, $fn)) {
|
||||
warn "chmod($mode, \"$name\") failed: $!\n";
|
||||
}
|
||||
}
|
||||
if ($uid != $cur_uid || $gid != $cur_gid) {
|
||||
push(@changes, 'owner') if $uid != $cur_uid;
|
||||
push(@changes, 'group') if $gid != $cur_gid;
|
||||
if (!$dry_run) {
|
||||
if (!chown($uid, $gid, $fn)) {
|
||||
warn "chown($uid, $gid, \"$name\") failed: $!\n";
|
||||
}
|
||||
if (($mode & 06000) && !chmod($mode, $fn)) {
|
||||
warn "post-chown chmod($mode, \"$name\") failed: $!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (@changes) {
|
||||
print "$name: changed @changes\n";
|
||||
} elsif ($verbosity) {
|
||||
print "$name: OK\n";
|
||||
}
|
||||
}
|
||||
exit;
|
||||
|
||||
sub parse_map_file
|
||||
{
|
||||
my($fn) = @_;
|
||||
open(IN, $fn) or die "Unable to open $fn: $!\n";
|
||||
while (<IN>) {
|
||||
if (/^user\s+(\S+)\s+(\S+)/) {
|
||||
$uid_hash{$1} = $2;
|
||||
} elsif (/^group\s+(\S+)\s+(\S+)/) {
|
||||
$gid_hash{$1} = $2;
|
||||
} else {
|
||||
die "Invalid line #$. in mapfile `$fn':\n$_";
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: file-attr-restore [OPTIONS] FILE [FILE...]
|
||||
-a, --all Restore all the attributes (-pog)
|
||||
-p, --perms Restore the permissions
|
||||
-o, --owner Restore the ownership
|
||||
-g, --groups Restore the group
|
||||
-m, --map=FILE Read user/group mappings from FILE
|
||||
-n, --dry-run Don't actually make the changes
|
||||
-v, --verbose Increase verbosity
|
||||
-h, --help Show this help text
|
||||
|
||||
The FILE arg(s) should have been created by running the "find"
|
||||
program with "-ls" as the output specifier.
|
||||
|
||||
The input file for the --map option must be in this format:
|
||||
|
||||
user FROM TO
|
||||
group FROM TO
|
||||
|
||||
The "FROM" should be an user/group mentioned in the input, and the TO
|
||||
should be either a uid/gid number, or a local user/group name.
|
||||
EOT
|
||||
}
|
||||
27
support/files-to-excludes
Executable file
27
support/files-to-excludes
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/perl
|
||||
# This script takes an input of filenames and outputs a set of
|
||||
# include/exclude directives that can be used by rsync to copy
|
||||
# just the indicated files using an --exclude-from=FILE option.
|
||||
use strict;
|
||||
|
||||
my %hash;
|
||||
|
||||
while (<>) {
|
||||
chomp;
|
||||
s#^/+##;
|
||||
my $path = '/';
|
||||
while (m#([^/]+/)/*#g) {
|
||||
$path .= $1;
|
||||
print "+ $path\n" unless $hash{$path}++;
|
||||
}
|
||||
if (m#([^/]+)$#) {
|
||||
print "+ $path$1\n";
|
||||
} else {
|
||||
delete $hash{$path};
|
||||
}
|
||||
}
|
||||
|
||||
foreach (sort keys %hash) {
|
||||
print "- $_*\n";
|
||||
}
|
||||
print "- /*\n";
|
||||
34
support/logfilter
Executable file
34
support/logfilter
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/perl
|
||||
# Filter the rsync daemon log messages by module name. The log file can be
|
||||
# in either syslog format or rsync's own log-file format. Note that the
|
||||
# MODULE_NAME parameter is used in a regular-expression match in order to
|
||||
# allow regex wildcards to be used. You can also limit the output by
|
||||
# directory hierarchy in a module. Examples:
|
||||
#
|
||||
# logfilter foo /var/log/rsyncd.log # output lines for module foo
|
||||
# logfilter foo/dir /var/log/syslog # limit lines to those in dir of foo
|
||||
|
||||
use strict;
|
||||
|
||||
my $match = shift;
|
||||
die "Usage: logfilter MODULE_NAME [LOGFILE ...]\n" unless defined $match;
|
||||
|
||||
my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd';
|
||||
my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d ';
|
||||
|
||||
my %pids;
|
||||
|
||||
while (<>) {
|
||||
my($pid,$msg) = /^(?:$syslog_prefix|$rsyncd_prefix)\[(\d+)\]:? (.*)/o;
|
||||
next unless defined $pid;
|
||||
my($mod_spec) = $msg =~ /^rsync (?:on|to) (\S+) from /;
|
||||
if (defined $mod_spec) {
|
||||
if ($mod_spec =~ /^$match(\/\S*)?$/o) {
|
||||
$pids{$pid} = 1;
|
||||
} else {
|
||||
delete $pids{$pid};
|
||||
}
|
||||
}
|
||||
next unless $pids{$pid};
|
||||
print $_;
|
||||
}
|
||||
23
support/lsh
Executable file
23
support/lsh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
# This script can be used as a "remote shell" command that is only
|
||||
# capable of pretending to connect to "localhost". This is useful
|
||||
# for testing or for running a local copy where the sender and the
|
||||
# receiver needs to use different options (e.g. --fake-super). If
|
||||
# we get a -l USER option, we try to use "sudo -u USER" to run the
|
||||
# command.
|
||||
|
||||
prefix=''
|
||||
|
||||
cd # Default path is home dir, just like ssh.
|
||||
|
||||
while : ; do
|
||||
case "$1" in
|
||||
-l) shift ; prefix="sudo -u $1"; shift ;;
|
||||
-l*) prefix=`echo $1 | sed 's/-l/sudo -u /'`; shift ;;
|
||||
-*) shift ;;
|
||||
localhost) shift; break ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
eval $prefix "${@}"
|
||||
44
support/mnt-excl
Executable file
44
support/mnt-excl
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/perl -w
|
||||
# This script takes a command-line arg of a source directory
|
||||
# that will be passed to rsync, and generates a set of excludes
|
||||
# that will exclude all mount points from the list. This is
|
||||
# useful if you have "bind" mounts since the --one-file-system
|
||||
# option won't notice the transition to a different spot on
|
||||
# the same disk. For example:
|
||||
#
|
||||
# mnt-excl /dir | rsync --exclude-from=- ... /dir /dest/
|
||||
# mnt-excl /dir/ | rsync --exclude-from=- ... /dir/ /dest/
|
||||
# ssh host mnt-excl /dir | rsync --exclude-from=- ... host:/dir /dest/
|
||||
#
|
||||
# Imagine that /dir/foo is a mount point: the first invocation of
|
||||
# mnt-excl would have output /dir/foo, while the second would have
|
||||
# output /foo (which are the properly anchored excludes).
|
||||
#
|
||||
# NOTE: This script expects /proc/mounts to exist, but could be
|
||||
# easily adapted to read /etc/mtab or similar.
|
||||
#
|
||||
# ADDENDUM: The addition of the --filter option (which has support for
|
||||
# absolute-anchored excludes) has made this script less useful than it
|
||||
# was. Beginning with 2.6.4, you can achieve the effect of this script
|
||||
# through this command:
|
||||
#
|
||||
# awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/
|
||||
|
||||
use strict;
|
||||
use Cwd 'abs_path';
|
||||
|
||||
my $file = '/proc/mounts';
|
||||
my $dir = shift || '/';
|
||||
$dir = abs_path($dir);
|
||||
$dir =~ s#([^/]*)$##;
|
||||
my $trailing = $1;
|
||||
$trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
|
||||
$trailing .= '/' if $trailing ne '';
|
||||
|
||||
open(IN, $file) or die "Unable to open $file: $!\n";
|
||||
while (<IN>) {
|
||||
$_ = (split)[1];
|
||||
next unless s#^\Q$dir$trailing\E##o && $_ ne '';
|
||||
print "- /$trailing$_\n";
|
||||
}
|
||||
close IN;
|
||||
209
support/rrsync
Normal file
209
support/rrsync
Normal file
@@ -0,0 +1,209 @@
|
||||
#!/usr/bin/perl
|
||||
# Name: /usr/local/bin/rrsync (should also have a symlink in /usr/bin)
|
||||
# Purpose: Restricts rsync to subdirectory declared in .ssh/authorized_keys
|
||||
# Author: Joe Smith <js-cgi@inwap.com> 30-Sep-2004
|
||||
# Modified by: Wayne Davison <wayned@samba.org>
|
||||
use strict;
|
||||
|
||||
use Socket;
|
||||
use Cwd 'abs_path';
|
||||
use File::Glob ':glob';
|
||||
|
||||
# You may configure these values to your liking. See also the section
|
||||
# of options if you want to disable any options that rsync accepts.
|
||||
use constant RSYNC => '/usr/bin/rsync';
|
||||
use constant LOGFILE => 'rrsync.log';
|
||||
|
||||
my $Usage = <<EOM;
|
||||
Use 'command="$0 [-ro] SUBDIR"'
|
||||
in front of lines in $ENV{HOME}/.ssh/authorized_keys
|
||||
EOM
|
||||
|
||||
our $ro = (@ARGV && $ARGV[0] eq '-ro') ? shift : ''; # -ro = Read-Only
|
||||
our $subdir = shift;
|
||||
die "$0: No subdirectory specified\n$Usage" unless defined $subdir;
|
||||
$subdir = abs_path($subdir);
|
||||
die "$0: Restricted directory does not exist!\n" if $subdir ne '/' && !-d $subdir;
|
||||
|
||||
# The client uses "rsync -av -e ssh src/ server:dir/", and sshd on the server
|
||||
# executes this program when .ssh/authorized_keys has 'command="..."'.
|
||||
# For example:
|
||||
# command="rrsync logs/client" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAzGhEeNlPr...
|
||||
# command="rrsync -ro results" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAmkHG1WCjC...
|
||||
#
|
||||
# Format of the envrionment variables set by sshd:
|
||||
# SSH_ORIGINAL_COMMAND=rsync --server -vlogDtpr --partial . ARG # push
|
||||
# SSH_ORIGINAL_COMMAND=rsync --server --sender -vlogDtpr --partial . ARGS # pull
|
||||
# SSH_CONNECTION=client_addr client_port server_port
|
||||
|
||||
my $command = $ENV{SSH_ORIGINAL_COMMAND};
|
||||
die "$0: Not invoked via sshd\n$Usage" unless defined $command;
|
||||
die "$0: SSH_ORIGINAL_COMMAND='$command' is not rsync\n" unless $command =~ s/^rsync\s+//;
|
||||
our $am_sender = $command =~ /^--server\s+--sender\s/; # Restrictive on purpose!
|
||||
die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
|
||||
|
||||
### START of options data produced by the cull_options script. ###
|
||||
|
||||
# These options are the only options that rsync might send to the server,
|
||||
# and only in the option format that the stock rsync produces.
|
||||
|
||||
# To disable a short-named option, add its letter to this string:
|
||||
our $short_disabled = 's';
|
||||
|
||||
our $short_no_arg = 'ACDEHIKLORSWXbcdgklmnoprstuvxz'; # DO NOT REMOVE ANY
|
||||
our $short_with_num = 'B'; # DO NOT REMOVE ANY
|
||||
|
||||
# To disable a long-named option, change its value to a -1. The values mean:
|
||||
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
|
||||
# check the arg when receiving; and 3 = always check the arg.
|
||||
our %long_opt = (
|
||||
'append' => 0,
|
||||
'backup-dir' => 2,
|
||||
'bwlimit' => 1,
|
||||
'checksum-seed' => 1,
|
||||
'compare-dest' => 2,
|
||||
'compress-level' => 1,
|
||||
'copy-dest' => 2,
|
||||
'copy-unsafe-links' => 0,
|
||||
'daemon' => 0,
|
||||
'delay-updates' => 0,
|
||||
'delete' => 0,
|
||||
'delete-after' => 0,
|
||||
'delete-before' => 0,
|
||||
'delete-delay' => 0,
|
||||
'delete-during' => 0,
|
||||
'delete-excluded' => 0,
|
||||
'existing' => 0,
|
||||
'files-from' => 3,
|
||||
'force' => 0,
|
||||
'from0' => 0,
|
||||
'fuzzy' => 0,
|
||||
'iconv' => 1,
|
||||
'ignore-errors' => 0,
|
||||
'ignore-existing' => 0,
|
||||
'inplace' => 0,
|
||||
'link-dest' => 2,
|
||||
'list-only' => 0,
|
||||
'log-format' => 1,
|
||||
'max-delete' => 1,
|
||||
'max-size' => 1,
|
||||
'min-size' => 1,
|
||||
'modify-window' => 1,
|
||||
'no-i-r' => 0,
|
||||
'no-implied-dirs' => 0,
|
||||
'no-r' => 0,
|
||||
'no-relative' => 0,
|
||||
'no-specials' => 0,
|
||||
'numeric-ids' => 0,
|
||||
'only-write-batch' => 1,
|
||||
'partial' => 0,
|
||||
'partial-dir' => 2,
|
||||
'remove-sent-files' => $ro ? -1 : 0,
|
||||
'remove-source-files' => $ro ? -1 : 0,
|
||||
'safe-links' => 0,
|
||||
'sender' => 0,
|
||||
'server' => 0,
|
||||
'size-only' => 0,
|
||||
'skip-compress' => 1,
|
||||
'specials' => 0,
|
||||
'suffix' => 1,
|
||||
'super' => 0,
|
||||
'temp-dir' => 2,
|
||||
'timeout' => 1,
|
||||
);
|
||||
|
||||
### END of options data produced by the cull_options script. ###
|
||||
|
||||
if ($short_disabled ne '') {
|
||||
$short_no_arg =~ s/[$short_disabled]//go;
|
||||
$short_with_num =~ s/[$short_disabled]//go;
|
||||
}
|
||||
$short_no_arg = "[$short_no_arg]" if length($short_no_arg) > 1;
|
||||
$short_with_num = "[$short_with_num]" if length($short_with_num) > 1;
|
||||
|
||||
my $write_log = -f LOGFILE && open(LOG, '>>', LOGFILE);
|
||||
|
||||
chdir($subdir) or die "$0: Unable to chdir to restricted dir: $!\n";
|
||||
|
||||
my(@opts, @args);
|
||||
my $in_options = 1;
|
||||
my $last_opt = '';
|
||||
my $check_type;
|
||||
while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
|
||||
$_ = $1;
|
||||
if ($check_type) {
|
||||
push(@opts, check_arg($last_opt, $_, $check_type));
|
||||
$check_type = 0;
|
||||
} elsif ($in_options) {
|
||||
push(@opts, $_);
|
||||
if ($_ eq '.') {
|
||||
$in_options = 0;
|
||||
} else {
|
||||
next if /^-$short_no_arg+(e\d+\.\d+)?$/o || /^-$short_with_num\d+$/o;
|
||||
|
||||
my($opt,$arg) = /^--([^=]+)(?:=(.*))?$/;
|
||||
my $disabled;
|
||||
if (defined $opt) {
|
||||
my $ct = $long_opt{$opt};
|
||||
last unless defined $ct;
|
||||
next if $ct == 0;
|
||||
if ($ct > 0) {
|
||||
if (!defined $arg) {
|
||||
$check_type = $ct;
|
||||
$last_opt = $opt;
|
||||
next;
|
||||
}
|
||||
$arg = check_arg($opt, $arg, $ct);
|
||||
$opts[-1] =~ s/=.*/=$arg/;
|
||||
next;
|
||||
}
|
||||
$disabled = 1;
|
||||
$opt = "--$opt";
|
||||
} elsif ($short_disabled ne '') {
|
||||
$disabled = /^-$short_no_arg*([$short_disabled])/o;
|
||||
$opt = "-$1";
|
||||
}
|
||||
|
||||
last unless $disabled; # Generate generic failure
|
||||
die "$0: option $opt has been disabled on this server.\n";
|
||||
}
|
||||
} else {
|
||||
if ($subdir ne '/') {
|
||||
# Validate args to ensure they don't try to leave our restricted dir.
|
||||
s#//+#/#g;
|
||||
s#^/##;
|
||||
s#^$#.#;
|
||||
die "Do not use .. in any path!\n" if m#(^|/)\\?\.\\?\.(\\?/|$)#;
|
||||
}
|
||||
push(@args, bsd_glob($_, GLOB_LIMIT|GLOB_NOCHECK|GLOB_BRACE|GLOB_QUOTE));
|
||||
}
|
||||
}
|
||||
die "$0: invalid rsync-command syntax or options\n" if $in_options;
|
||||
|
||||
@args = ( '.' ) if !@args;
|
||||
|
||||
if ($write_log) {
|
||||
my ($mm,$hh) = (localtime)[1,2];
|
||||
my $host = $ENV{SSH_CONNECTION} || 'unknown';
|
||||
$host =~ s/ .*//; # Keep only the client's IP addr
|
||||
$host =~ s/^::ffff://;
|
||||
$host = gethostbyaddr(inet_aton($host),AF_INET) || $host;
|
||||
printf LOG "%02d:%02d %-13s [%s]\n", $hh, $mm, $host, "@opts @args";
|
||||
close LOG;
|
||||
}
|
||||
|
||||
# Note: This assumes that the rsync protocol will not be maliciously hijacked.
|
||||
exec(RSYNC, @opts, @args) or die "exec(rsync @opts @args) failed: $? $!";
|
||||
|
||||
sub check_arg
|
||||
{
|
||||
my($opt, $arg, $type) = @_;
|
||||
$arg =~ s/\\(.)/$1/g;
|
||||
if ($subdir ne '/' && ($type == 3 || ($type == 2 && !$am_sender))) {
|
||||
$arg =~ s#//#/#g;
|
||||
die "Do not use .. in --$opt; anchor the path at the root of your restricted dir.\n"
|
||||
if $arg =~ m#(^|/)\.\.(/|$)#;
|
||||
$arg =~ s#^/#$subdir/#;
|
||||
}
|
||||
$arg;
|
||||
}
|
||||
@@ -1,72 +1,80 @@
|
||||
#! /usr/bin/perl
|
||||
# ---------------------------------------------------------------------------
|
||||
#
|
||||
# USAGE: rsyncstats <options>
|
||||
#
|
||||
# OPTIONS:
|
||||
# -f <filename> Use <filename> for the log file
|
||||
# -h include report on hourly traffic
|
||||
# -d include report on domain traffic
|
||||
# -t report on total traffic by section
|
||||
# -D <domain> report only on traffic from <domain>
|
||||
# -l <depth> Depth of path detail for sections
|
||||
# -s <section> Section to report on, For example: -s /pub will report
|
||||
# only on paths under /pub
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This script parses the default logfile format produced by rsync when running
|
||||
# as a daemon with transfer logging enabled. It is derived from the xferstats
|
||||
# script that comes with wuftpd
|
||||
# as a daemon with transfer logging enabled. It also parses a slightly tweaked
|
||||
# version of the default format where %o has been replaced with %i.
|
||||
#
|
||||
# This script is derived from the xferstats script that comes with wuftpd. See
|
||||
# the usage message at the bottom for the options it takes.
|
||||
#
|
||||
# Andrew Tridgell, October 1998
|
||||
# rsync-bugs@samba.org
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# edit the next line to customize for your default log file
|
||||
$usage_file = "/var/adm/rsyncd.log";
|
||||
use Getopt::Long;
|
||||
|
||||
# You may wish to edit the next line to customize for your default log file.
|
||||
$usage_file = "/var/log/rsyncd.log";
|
||||
|
||||
# Edit the following lines for default report settings.
|
||||
# Entries defined here will be over-ridden by the command line.
|
||||
|
||||
$opt_h = 1;
|
||||
$opt_d = 0;
|
||||
$opt_t = 1;
|
||||
$opt_l = 2;
|
||||
$hourly_report = 0;
|
||||
$domain_report = 0;
|
||||
$total_report = 0;
|
||||
$depth_limit = 9999;
|
||||
$only_section = '';
|
||||
|
||||
require 'getopts.pl';
|
||||
&Getopts('f:rahdD:l:s:');
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'hourly-report|h' => \$hourly_report,
|
||||
'domain-report|d' => \$domain_report,
|
||||
'domain|D:s' => \$only_domain,
|
||||
'total-report|t' => \$total_report,
|
||||
'depth-limit|l:i' => \$depth_limit,
|
||||
'real|r' => \$real,
|
||||
'anon|a' => \$anon,
|
||||
'section|s:s' => \$only_section,
|
||||
'file|f:s' => \$usage_file,
|
||||
);
|
||||
|
||||
if ($opt_r) { $real = 1;}
|
||||
if ($opt_a) { $anon = 1;}
|
||||
if ($real == 0 && $anon == 0) { $anon = 1; }
|
||||
if ($opt_f) {$usage_file = $opt_f;}
|
||||
$anon = 1 if !$real && !$anon;
|
||||
|
||||
open (LOG,$usage_file) || die "Error opening usage log file: $usage_file\n";
|
||||
open(LOG, $usage_file) || die "Error opening usage log file: $usage_file\n";
|
||||
|
||||
if ($opt_D) {print "Transfer Totals include the '$opt_D' domain only.\n";
|
||||
print "All other domains are filtered out for this report.\n\n";}
|
||||
if ($only_domain) {
|
||||
print "Transfer Totals include the '$only_domain' domain only.\n";
|
||||
print "All other domains are filtered out for this report.\n\n";
|
||||
}
|
||||
|
||||
if ($opt_s) {print "Transfer Totals include the '$opt_s' section only.\n";
|
||||
print "All other sections are filtered out for this report.\n\n";}
|
||||
if ($only_section) {
|
||||
print "Transfer Totals include the '$only_section' section only.\n";
|
||||
print "All other sections are filtered out for this report.\n\n";
|
||||
}
|
||||
|
||||
line: while (<LOG>) {
|
||||
|
||||
@line = split;
|
||||
my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd';
|
||||
my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d ';
|
||||
|
||||
$day = $line[0];
|
||||
$time = $line[1];
|
||||
$pid = $line[2];
|
||||
$op = $line[3];
|
||||
$host = $line[4];
|
||||
$ip = $line[5];
|
||||
$module = $line[6];
|
||||
$user = $line[7];
|
||||
$file = $line[8];
|
||||
$bytes = $line[9];
|
||||
next unless ($day,$time,$op,$host,$module,$file,$bytes)
|
||||
= m{^
|
||||
( \w\w\w\s+\d+ | \d+/\d\d/\d\d ) \s+ # day
|
||||
(\d\d:\d\d:\d\d) \s+ # time
|
||||
[^[]* \[\d+\]:? \s+ # pid (ignored)
|
||||
(send|recv|[<>]f\S+) \s+ # op (%o or %i)
|
||||
(\S+) \s+ # host
|
||||
\[\d+\.\d+\.\d+\.\d+\] \s+ # IP (ignored)
|
||||
(\S+) \s+ # module
|
||||
\(\S*\) \s+ # user (ignored)
|
||||
(.*) \s+ # file name
|
||||
(\d+) # file length in bytes
|
||||
$ }x;
|
||||
|
||||
next if ($#line != 9);
|
||||
|
||||
next if ($op != "send" && $op != "recv");
|
||||
# TODO actually divide the data by into send/recv categories
|
||||
if ($op =~ /^>/) {
|
||||
$op = 'send';
|
||||
} elsif ($op =~ /^</) {
|
||||
$op = 'recv';
|
||||
}
|
||||
|
||||
$daytime = $day;
|
||||
$hour = substr($time,0,2);
|
||||
@@ -78,11 +86,13 @@ line: while (<LOG>) {
|
||||
@path = split(/\//, $file);
|
||||
|
||||
$pathkey = "";
|
||||
for ($i=0; $i <= $#path && $i <= $opt_l;$i++) {
|
||||
for ($i=0; $i <= $#path && $i <= $depth_limit; $i++) {
|
||||
$pathkey = $pathkey . "/" . $path[$i];
|
||||
}
|
||||
|
||||
next if (substr($pathkey,0,length("$opt_s")) ne "$opt_s");
|
||||
if ($only_section ne '') {
|
||||
next unless (substr($pathkey,0,length($only_section)) eq $only_section);
|
||||
}
|
||||
|
||||
$host =~ tr/A-Z/a-z/;
|
||||
|
||||
@@ -92,12 +102,12 @@ line: while (<LOG>) {
|
||||
if ( int($address[0]) > 0 || $#address < 2 )
|
||||
{ $domain = "unresolved"; }
|
||||
|
||||
if ($opt_D) {
|
||||
next unless (substr($domain,0,length("$opt_D")) eq "$opt_D");
|
||||
if ($only_domain ne '') {
|
||||
next unless (substr($domain,0,length($only_domain)) eq $only_domain);
|
||||
}
|
||||
|
||||
|
||||
# printf ("c=%d day=%s bytes=%d file=%s path=%s\n",
|
||||
# printf("c=%d day=%s bytes=%d file=%s path=%s\n",
|
||||
# $#line, $daytime, $bytes, $file, $pathkey);
|
||||
|
||||
$xferfiles++; # total files sent
|
||||
@@ -117,20 +127,20 @@ line: while (<LOG>) {
|
||||
}
|
||||
close LOG;
|
||||
|
||||
@syslist = keys(systemfiles);
|
||||
@dates = sort datecompare keys(xferbytes);
|
||||
#@syslist = keys %systemfiles;
|
||||
@dates = sort datecompare keys %xferbytes;
|
||||
|
||||
if ($xferfiles == 0) {die "There was no data to process.\n";}
|
||||
|
||||
|
||||
print "TOTALS FOR SUMMARY PERIOD ", $dates[0], " TO ", $dates[$#dates], "\n\n";
|
||||
printf ("Files Transmitted During Summary Period %12.0f\n", $xferfiles);
|
||||
printf ("Bytes Transmitted During Summary Period %12.0f\n", $xferbytes);
|
||||
printf ("Systems Using Archives %12.0f\n\n", $#syslist+1);
|
||||
printf("Files Transmitted During Summary Period %12.0f\n", $xferfiles);
|
||||
printf("Bytes Transmitted During Summary Period %12.0f\n", $xferbytes);
|
||||
#printf("Systems Using Archives %12.0f\n\n", $#syslist+1);
|
||||
|
||||
printf ("Average Files Transmitted Daily %12.0f\n",
|
||||
printf("Average Files Transmitted Daily %12.0f\n",
|
||||
$xferfiles / ($#dates + 1));
|
||||
printf ("Average Bytes Transmitted Daily %12.0f\n",
|
||||
printf("Average Bytes Transmitted Daily %12.0f\n",
|
||||
$xferbytes / ($#dates + 1));
|
||||
|
||||
format top1 =
|
||||
@@ -150,7 +160,7 @@ $date, $nfiles, $nbytes/(1024*1024), $pctfiles, $pctbytes
|
||||
$^ = top1;
|
||||
$~ = line1;
|
||||
|
||||
foreach $date ( sort datecompare keys(xferbytes) ) {
|
||||
foreach $date (sort datecompare keys %xferbytes) {
|
||||
|
||||
$nfiles = $xferfiles{$date};
|
||||
$nbytes = $xferbytes{$date};
|
||||
@@ -159,7 +169,7 @@ foreach $date ( sort datecompare keys(xferbytes) ) {
|
||||
write;
|
||||
}
|
||||
|
||||
if ($opt_t) {
|
||||
if ($total_report) {
|
||||
format top2 =
|
||||
|
||||
Total Transfers from each Archive Section (By bytes)
|
||||
@@ -179,7 +189,7 @@ $- = 0;
|
||||
$^ = top2;
|
||||
$~ = line2;
|
||||
|
||||
foreach $section ( sort bytecompare keys(groupfiles) ) {
|
||||
foreach $section (sort bytecompare keys %groupfiles) {
|
||||
|
||||
$files = $groupfiles{$section};
|
||||
$bytes = $groupbytes{$section};
|
||||
@@ -193,7 +203,7 @@ if ( $xferfiles < 1 ) { $xferfiles = 1; }
|
||||
if ( $xferbytes < 1 ) { $xferbytes = 1; }
|
||||
}
|
||||
|
||||
if ($opt_d) {
|
||||
if ($domain_report) {
|
||||
format top3 =
|
||||
|
||||
Total Transfer Amount By Domain
|
||||
@@ -212,7 +222,7 @@ $- = 0;
|
||||
$^ = top3;
|
||||
$~ = line3;
|
||||
|
||||
foreach $domain ( sort domnamcompare keys(domainfiles) ) {
|
||||
foreach $domain (sort domnamcompare keys %domainfiles) {
|
||||
|
||||
if ( $domainsecs{$domain} < 1 ) { $domainsecs{$domain} = 1; }
|
||||
|
||||
@@ -226,7 +236,7 @@ foreach $domain ( sort domnamcompare keys(domainfiles) ) {
|
||||
|
||||
}
|
||||
|
||||
if ($opt_h) {
|
||||
if ($hourly_report) {
|
||||
|
||||
format top8 =
|
||||
|
||||
@@ -248,7 +258,7 @@ $- = 0;
|
||||
$^ = top8;
|
||||
$~ = line8;
|
||||
|
||||
foreach $hour ( sort keys(xfertbytes) ) {
|
||||
foreach $hour (sort keys %xfertbytes) {
|
||||
|
||||
$nfiles = $xfertfiles{$hour};
|
||||
$nbytes = $xfertbytes{$hour};
|
||||
@@ -284,3 +294,19 @@ sub faccompare {
|
||||
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
USAGE: rsyncstats [options]
|
||||
|
||||
OPTIONS:
|
||||
-f FILENAME Use FILENAME for the log file.
|
||||
-h Include report on hourly traffic.
|
||||
-d Include report on domain traffic.
|
||||
-t Report on total traffic by section.
|
||||
-D DOMAIN Report only on traffic from DOMAIN.
|
||||
-l DEPTH Set DEPTH of path detail for sections.
|
||||
-s SECTION Set SECTION to report on. For example, "-s /pub"
|
||||
will report only on paths under "/pub".
|
||||
EOT
|
||||
}
|
||||
|
||||
175
support/savetransfer.c
Normal file
175
support/savetransfer.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/* This program can record the stream of data flowing to or from a program.
|
||||
* This allows it to be used to check that rsync's data that is flowing
|
||||
* through a remote shell is not being corrupted (for example).
|
||||
*
|
||||
* Usage: savetransfer [-i|-o] OUTPUT_FILE PROGRAM [ARGS...]
|
||||
* -i Save the input going to PROGRAM to the OUTPUT_FILE
|
||||
* -o Save the output coming from PROGRAM to the OUTPUT_FILE
|
||||
*
|
||||
* If you want to capture the flow of data for an rsync command, use one of
|
||||
* the following commands (the resulting files should be identical):
|
||||
*
|
||||
* rsync -av --rsh="savetransfer -i /tmp/to.server ssh"
|
||||
* --rsync-path="savetransfer -i /tmp/from.client rsync" SOURCE DEST
|
||||
*
|
||||
* rsync -av --rsh="savetransfer -o /tmp/from.server ssh"
|
||||
* --rsync-path="savetransfer -o /tmp/to.client rsync" SOURCE DEST
|
||||
*
|
||||
* Note that this program aborts after 30 seconds of inactivity, so you'll need
|
||||
* to change it if that is not enough dead time for your transfer. Also, some
|
||||
* of the above commands will not notice that the transfer is done (if we're
|
||||
* saving the input to a PROGRAM and the PROGRAM goes away: we won't notice
|
||||
* that it's gone unless more data comes in) -- when this happens it will delay
|
||||
* at the end of the transfer until the timeout period expires.
|
||||
*/
|
||||
|
||||
#include "../rsync.h"
|
||||
|
||||
#define TIMEOUT_SECONDS 30
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction sigact;
|
||||
#endif
|
||||
|
||||
void run_program(char **command);
|
||||
|
||||
char buf[4096];
|
||||
int save_data_from_program = 0;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fd_file, len;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
|
||||
argv++;
|
||||
if (--argc && argv[0][0] == '-') {
|
||||
if (argv[0][1] == 'o')
|
||||
save_data_from_program = 1;
|
||||
else if (argv[0][1] == 'i')
|
||||
save_data_from_program = 0;
|
||||
else {
|
||||
fprintf(stderr, "Unknown option: %s\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: savetransfer [-i|-o] OUTPUT_FILE PROGRAM [ARGS...]\n");
|
||||
fprintf(stderr, "-i Save the input going to PROGRAM to the OUTPUT_FILE\n");
|
||||
fprintf(stderr, "-o Save the output coming from PROGRAM to the OUTPUT_FILE\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((fd_file = open(*argv, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0644)) < 0) {
|
||||
fprintf(stderr, "Unable to write to `%s': %s\n", *argv, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
set_blocking(fd_file);
|
||||
|
||||
SIGACTION(SIGPIPE, SIG_IGN);
|
||||
|
||||
run_program(argv + 1);
|
||||
|
||||
#if defined HAVE_SETMODE && O_BINARY
|
||||
setmode(STDIN_FILENO, O_BINARY);
|
||||
setmode(STDOUT_FILENO, O_BINARY);
|
||||
#endif
|
||||
set_nonblocking(STDIN_FILENO);
|
||||
set_blocking(STDOUT_FILENO);
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
tv.tv_sec = TIMEOUT_SECONDS;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(STDIN_FILENO+1, &fds, NULL, NULL, &tv))
|
||||
break;
|
||||
if (!FD_ISSET(STDIN_FILENO, &fds))
|
||||
break;
|
||||
if ((len = read(STDIN_FILENO, buf, sizeof buf)) <= 0)
|
||||
break;
|
||||
if (write(STDOUT_FILENO, buf, len) != len) {
|
||||
fprintf(stderr, "Failed to write data to stdout: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (write(fd_file, buf, len) != len) {
|
||||
fprintf(stderr, "Failed to write data to fd_file: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
run_program(char **command)
|
||||
{
|
||||
int pipe_fds[2], ret;
|
||||
pid_t pid;
|
||||
|
||||
if (pipe(pipe_fds) < 0) {
|
||||
fprintf(stderr, "pipe failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
fprintf(stderr, "fork failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
if (save_data_from_program)
|
||||
ret = dup2(pipe_fds[1], STDOUT_FILENO);
|
||||
else
|
||||
ret = dup2(pipe_fds[0], STDIN_FILENO);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to dup (in child): %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
close(pipe_fds[0]);
|
||||
close(pipe_fds[1]);
|
||||
set_blocking(STDIN_FILENO);
|
||||
set_blocking(STDOUT_FILENO);
|
||||
execvp(command[0], command);
|
||||
fprintf(stderr, "Failed to exec %s: %s\n", command[0], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (save_data_from_program)
|
||||
ret = dup2(pipe_fds[0], STDIN_FILENO);
|
||||
else
|
||||
ret = dup2(pipe_fds[1], STDOUT_FILENO);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to dup (in parent): %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
close(pipe_fds[0]);
|
||||
close(pipe_fds[1]);
|
||||
}
|
||||
|
||||
void
|
||||
set_nonblocking(int fd)
|
||||
{
|
||||
int val;
|
||||
|
||||
if ((val = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return;
|
||||
if (!(val & NONBLOCK_FLAG)) {
|
||||
val |= NONBLOCK_FLAG;
|
||||
fcntl(fd, F_SETFL, val);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_blocking(int fd)
|
||||
{
|
||||
int val;
|
||||
|
||||
if ((val = fcntl(fd, F_GETFL, 0)) < 0)
|
||||
return;
|
||||
if (val & NONBLOCK_FLAG) {
|
||||
val &= ~NONBLOCK_FLAG;
|
||||
fcntl(fd, F_SETFL, val);
|
||||
}
|
||||
}
|
||||
173
syscall.c
173
syscall.c
@@ -1,32 +1,33 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
Copyright (C) 2002 by Martin Pool
|
||||
|
||||
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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file syscall.c
|
||||
*
|
||||
/*
|
||||
* Syscall wrappers to ensure that nothing gets done in dry_run mode
|
||||
* and to handle system peculiarities.
|
||||
**/
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
*
|
||||
* 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, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
extern int dry_run;
|
||||
extern int am_root;
|
||||
extern int read_only;
|
||||
extern int list_only;
|
||||
extern int preserve_perms;
|
||||
@@ -41,22 +42,22 @@ extern int preserve_perms;
|
||||
|
||||
#define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
|
||||
|
||||
int do_unlink(char *fname)
|
||||
int do_unlink(const char *fname)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
return unlink(fname);
|
||||
}
|
||||
|
||||
int do_symlink(char *fname1, char *fname2)
|
||||
int do_symlink(const char *fname1, const char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
return symlink(fname1, fname2);
|
||||
}
|
||||
|
||||
#if HAVE_LINK
|
||||
int do_link(char *fname1, char *fname2)
|
||||
#ifdef HAVE_LINK
|
||||
int do_link(const char *fname1, const char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
@@ -68,26 +69,70 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
#ifndef HAVE_LCHOWN
|
||||
#define lchown chown
|
||||
#endif
|
||||
return lchown(path, owner, group);
|
||||
}
|
||||
|
||||
#if HAVE_MKNOD
|
||||
int do_mknod(char *pathname, mode_t mode, dev_t dev)
|
||||
int do_mknod(const char *pathname, mode_t mode, dev_t dev)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
return mknod(pathname, mode, dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
int do_rmdir(char *pathname)
|
||||
/* For --fake-super, we create a normal file with mode 0600. */
|
||||
if (am_root < 0) {
|
||||
int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
|
||||
if (fd < 0 || close(fd) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
|
||||
if (S_ISFIFO(mode))
|
||||
return mkfifo(pathname, mode);
|
||||
#endif
|
||||
#if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
|
||||
if (S_ISSOCK(mode)) {
|
||||
int sock;
|
||||
struct sockaddr_un saddr;
|
||||
#ifdef HAVE_SOCKADDR_UN_LEN
|
||||
unsigned int len =
|
||||
#endif
|
||||
strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
|
||||
#ifdef HAVE_SOCKADDR_UN_LEN
|
||||
saddr.sun_len = len >= sizeof saddr.sun_path
|
||||
? sizeof saddr.sun_path : len + 1;
|
||||
#endif
|
||||
saddr.sun_family = AF_UNIX;
|
||||
|
||||
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
|
||||
|| (unlink(pathname) < 0 && errno != ENOENT)
|
||||
|| (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
|
||||
return -1;
|
||||
close(sock);
|
||||
#ifdef HAVE_CHMOD
|
||||
return do_chmod(pathname, mode);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_MKNOD
|
||||
return mknod(pathname, mode, dev);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int do_rmdir(const char *pathname)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
return rmdir(pathname);
|
||||
}
|
||||
|
||||
int do_open(char *pathname, int flags, mode_t mode)
|
||||
int do_open(const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
if (flags != O_RDONLY) {
|
||||
RETURN_ERROR_IF(dry_run, 0);
|
||||
@@ -97,37 +142,43 @@ int do_open(char *pathname, int flags, mode_t mode)
|
||||
return open(pathname, flags | O_BINARY, mode);
|
||||
}
|
||||
|
||||
#if HAVE_CHMOD
|
||||
#ifdef HAVE_CHMOD
|
||||
int do_chmod(const char *path, mode_t mode)
|
||||
{
|
||||
int code;
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
code = chmod(path, mode);
|
||||
if (S_ISLNK(mode)) {
|
||||
#ifdef HAVE_LCHMOD
|
||||
code = lchmod(path, mode & CHMOD_BITS);
|
||||
#else
|
||||
code = 1;
|
||||
#endif
|
||||
} else
|
||||
code = chmod(path, mode & CHMOD_BITS);
|
||||
if (code != 0 && preserve_perms)
|
||||
return code;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int do_rename(char *fname1, char *fname2)
|
||||
int do_rename(const char *fname1, const char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
return rename(fname1, fname2);
|
||||
}
|
||||
|
||||
|
||||
void trim_trailing_slashes(char *name)
|
||||
{
|
||||
int l;
|
||||
/* Some BSD systems cannot make a directory if the name
|
||||
* contains a trailing slash.
|
||||
* <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
|
||||
|
||||
|
||||
/* Don't change empty string; and also we can't improve on
|
||||
* "/" */
|
||||
|
||||
|
||||
l = strlen(name);
|
||||
while (l > 1) {
|
||||
if (name[--l] != '/')
|
||||
@@ -136,23 +187,21 @@ void trim_trailing_slashes(char *name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int do_mkdir(char *fname, mode_t mode)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
trim_trailing_slashes(fname);
|
||||
trim_trailing_slashes(fname);
|
||||
return mkdir(fname, mode);
|
||||
}
|
||||
|
||||
|
||||
/* like mkstemp but forces permissions */
|
||||
int do_mkstemp(char *template, mode_t perms)
|
||||
{
|
||||
RETURN_ERROR_IF(dry_run, 0);
|
||||
RETURN_ERROR_IF(read_only, EROFS);
|
||||
|
||||
#if defined(HAVE_SECURE_MKSTEMP) && defined(HAVE_FCHMOD)
|
||||
#if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
|
||||
{
|
||||
int fd = mkstemp(template);
|
||||
if (fd == -1)
|
||||
@@ -164,6 +213,9 @@ int do_mkstemp(char *template, mode_t perms)
|
||||
errno = errno_save;
|
||||
return -1;
|
||||
}
|
||||
#if defined HAVE_SETMODE && O_BINARY
|
||||
setmode(fd, O_BINARY);
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
#else
|
||||
@@ -175,27 +227,29 @@ int do_mkstemp(char *template, mode_t perms)
|
||||
|
||||
int do_stat(const char *fname, STRUCT_STAT *st)
|
||||
{
|
||||
#if HAVE_OFF64_T
|
||||
#ifdef USE_STAT64_FUNCS
|
||||
return stat64(fname, st);
|
||||
#else
|
||||
return stat(fname, st);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
int do_lstat(const char *fname, STRUCT_STAT *st)
|
||||
{
|
||||
#if HAVE_OFF64_T
|
||||
#ifdef SUPPORT_LINKS
|
||||
# ifdef USE_STAT64_FUNCS
|
||||
return lstat64(fname, st);
|
||||
#else
|
||||
# else
|
||||
return lstat(fname, st);
|
||||
# endif
|
||||
#else
|
||||
return do_stat(fname, st);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int do_fstat(int fd, STRUCT_STAT *st)
|
||||
{
|
||||
#if HAVE_OFF64_T
|
||||
#ifdef USE_STAT64_FUNCS
|
||||
return fstat64(fd, st);
|
||||
#else
|
||||
return fstat(fd, st);
|
||||
@@ -204,28 +258,21 @@ int do_fstat(int fd, STRUCT_STAT *st)
|
||||
|
||||
OFF_T do_lseek(int fd, OFF_T offset, int whence)
|
||||
{
|
||||
#if HAVE_OFF64_T
|
||||
#ifdef HAVE_LSEEK64
|
||||
#if !SIZEOF_OFF64_T
|
||||
OFF_T lseek64();
|
||||
#else
|
||||
off64_t lseek64();
|
||||
#endif
|
||||
return lseek64(fd, offset, whence);
|
||||
#else
|
||||
return lseek(fd, offset, whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_MMAP
|
||||
void *do_mmap(void *start, int len, int prot, int flags, int fd, OFF_T offset)
|
||||
{
|
||||
#if HAVE_OFF64_T
|
||||
return mmap64(start, len, prot, flags, fd, offset);
|
||||
#else
|
||||
return mmap(start, len, prot, flags, fd, offset);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
char *d_name(struct dirent *di)
|
||||
{
|
||||
#if HAVE_BROKEN_READDIR
|
||||
#ifdef HAVE_BROKEN_READDIR
|
||||
return (di->d_name - 2);
|
||||
#else
|
||||
return di->d_name;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user