mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 07:15:35 -04:00
Compare commits
3729 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
d8195637d4 | ||
|
|
c8d771a0fb | ||
|
|
9130776c4e | ||
|
|
9eac94a4dd | ||
|
|
6e06d2f31a | ||
|
|
6a6d21136a | ||
|
|
f28bd83346 | ||
|
|
96fb478eae | ||
|
|
8752b3fcd8 | ||
|
|
55ffed7e42 | ||
|
|
e00df64bae | ||
|
|
080ddf58ae | ||
|
|
4ce48a5bfd | ||
|
|
20bf7f847f | ||
|
|
b66d00853b | ||
|
|
8b602edda4 | ||
|
|
9f27cd8ca6 | ||
|
|
b084f9e092 | ||
|
|
4220e1098e | ||
|
|
c30468169a | ||
|
|
c0d9e8c76b | ||
|
|
90a973fe8a | ||
|
|
7f0feb4dd6 | ||
|
|
33a5432ea6 | ||
|
|
968ff560d2 | ||
|
|
cd59be1d5e | ||
|
|
8b2869c0d2 | ||
|
|
82a51ea53d | ||
|
|
20af605eba | ||
|
|
a6536635e3 | ||
|
|
adddd075eb | ||
|
|
a0c823b22b | ||
|
|
9fdb334e85 | ||
|
|
f89e890b87 | ||
|
|
1c666c3fcb | ||
|
|
2a383be0f1 | ||
|
|
ac1d2d3384 | ||
|
|
acfcfa7053 | ||
|
|
8ef81dd452 | ||
|
|
67340e9523 | ||
|
|
a7ceddae34 | ||
|
|
24e1569f8b | ||
|
|
de31639fff | ||
|
|
8b46340924 | ||
|
|
d008bcb5cd | ||
|
|
0484b5b0b7 | ||
|
|
f01b6368a5 | ||
|
|
40d38dc0be | ||
|
|
33a2361cc2 | ||
|
|
4124540d61 | ||
|
|
5f38126817 | ||
|
|
b05b3c9b48 | ||
|
|
a03a9f4efe | ||
|
|
3e55030372 | ||
|
|
273c0420d0 | ||
|
|
5774786fa5 | ||
|
|
1a9ec1fd1c | ||
|
|
b2aa573b1c | ||
|
|
63d0331991 | ||
|
|
bf6dcd1713 | ||
|
|
495723bb26 | ||
|
|
911cb0662c | ||
|
|
5387514eaf | ||
|
|
61414c83ce | ||
|
|
43a9d0e7c2 | ||
|
|
df5cd107a5 | ||
|
|
abca4eba67 | ||
|
|
96d3590a08 | ||
|
|
8429aa9e0e | ||
|
|
79d4053048 | ||
|
|
753b6b4692 | ||
|
|
f8f726449b | ||
|
|
357406ecb2 | ||
|
|
3915fd7583 | ||
|
|
9c5e91f848 | ||
|
|
af107f6c08 | ||
|
|
a3dbb20a0e | ||
|
|
a3779426b6 | ||
|
|
2f5ca63d92 | ||
|
|
0e1d98ae92 | ||
|
|
04575bcab5 | ||
|
|
71b291d71b | ||
|
|
decba3ae73 | ||
|
|
f8ed564c9f | ||
|
|
47ba39bef6 | ||
|
|
71f7051489 | ||
|
|
3c3791e8be | ||
|
|
c39d6514ab | ||
|
|
1cb6f3bf4d | ||
|
|
f09dc86ab6 | ||
|
|
f26ac1e8cb | ||
|
|
84a3efa0ab | ||
|
|
00ed4b5bf3 | ||
|
|
e2e053bbd7 | ||
|
|
f8b33ab379 | ||
|
|
5df1fcf245 | ||
|
|
b1ad6a3260 | ||
|
|
6442ccc606 | ||
|
|
b21813060c | ||
|
|
706c75307a | ||
|
|
2b284ee33d | ||
|
|
4cfa6156e3 | ||
|
|
c1e7217fcb | ||
|
|
4b2f6a7c37 | ||
|
|
a8726d2a06 | ||
|
|
b5ebe6d9c7 | ||
|
|
ef383c0d32 | ||
|
|
8dcf93356e | ||
|
|
ce5f2732e4 | ||
|
|
3e89da86df | ||
|
|
f5450e791d | ||
|
|
cb984e620e | ||
|
|
be92ac6c36 | ||
|
|
5dc6e9c9ca | ||
|
|
0b79c324ca | ||
|
|
f39b6638f6 | ||
|
|
a4b6f30579 | ||
|
|
7be73df4e7 | ||
|
|
14b61c63f0 | ||
|
|
75a64762c2 | ||
|
|
028fdddb49 | ||
|
|
f86b0f2e7b | ||
|
|
285fba0759 | ||
|
|
92b9eb978e | ||
|
|
1e82e2cea6 | ||
|
|
a7ed6ca618 | ||
|
|
b4b90120ff | ||
|
|
16f72adc49 | ||
|
|
3d06165389 | ||
|
|
fd4893155d | ||
|
|
67e78a8231 | ||
|
|
6b320e4045 | ||
|
|
7e5cb90983 | ||
|
|
8120a98f47 | ||
|
|
8f3f8eec08 | ||
|
|
386b93dc60 | ||
|
|
b3bc31102c | ||
|
|
0f1aa0d3e5 | ||
|
|
7a08ae31d2 | ||
|
|
304f127f56 | ||
|
|
c338460d66 | ||
|
|
48d704af52 | ||
|
|
ac7aa92290 | ||
|
|
0042f81894 | ||
|
|
2c836acb37 | ||
|
|
a1d8f29a3d | ||
|
|
a174e1ed0f | ||
|
|
530adb7625 | ||
|
|
cd3fe9fb03 | ||
|
|
a8edfd53d1 | ||
|
|
dbb665180c | ||
|
|
9d78ed31a7 | ||
|
|
89afe532d7 | ||
|
|
c67d13866b | ||
|
|
3b98b08c4d | ||
|
|
9c15534511 | ||
|
|
55afbb522c | ||
|
|
27ed20f7a0 | ||
|
|
f567e9b3d7 | ||
|
|
40ae4f93a0 | ||
|
|
7a27e9b599 | ||
|
|
62c9e6b3a5 | ||
|
|
cfeed4da95 | ||
|
|
4068d8617d | ||
|
|
421c2a2448 | ||
|
|
d1e7726460 | ||
|
|
0596df00b3 | ||
|
|
417c99f637 | ||
|
|
de0e225076 | ||
|
|
e0391f8149 | ||
|
|
7de2483fbd | ||
|
|
65d6212d03 | ||
|
|
4d4df3cd2b | ||
|
|
62125b10c9 | ||
|
|
81c3a3a86e | ||
|
|
61d35e1844 | ||
|
|
15f85b1f63 | ||
|
|
5bf63a11f4 | ||
|
|
97a67bdfa9 | ||
|
|
aa0b9ca174 | ||
|
|
b96efc2f67 | ||
|
|
be20dc3448 | ||
|
|
cb869c26d9 | ||
|
|
7cf8e8d05d | ||
|
|
54fd3e5020 | ||
|
|
3e4916822d | ||
|
|
7efdcf3218 | ||
|
|
9935066b70 | ||
|
|
6c2e5b56e4 | ||
|
|
2289bf64cc | ||
|
|
b1bf649cba | ||
|
|
8ee6eb7134 | ||
|
|
f98c60bfa8 | ||
|
|
a5c1113971 | ||
|
|
736f46d1d9 | ||
|
|
a8f7e4b835 | ||
|
|
9352b0649b | ||
|
|
a85906c756 | ||
|
|
8aa81e06e6 | ||
|
|
1f9ae80a3e | ||
|
|
71020fc3aa | ||
|
|
7b74bba15e | ||
|
|
e5fbaa713a | ||
|
|
6609a9f17e | ||
|
|
5204e853e1 | ||
|
|
01363a24e2 | ||
|
|
d49def4832 | ||
|
|
4836c3eece | ||
|
|
9f7b8c3b8f | ||
|
|
ade7292aee | ||
|
|
dbd8811b85 | ||
|
|
05118158f4 | ||
|
|
1df395f7c2 | ||
|
|
5fdf2e7063 | ||
|
|
6fe05820ff | ||
|
|
670d8abf80 | ||
|
|
b2bffbb2ca | ||
|
|
13a6d667d2 | ||
|
|
1be77f8336 | ||
|
|
187e9c24f1 | ||
|
|
eddeaf76f8 | ||
|
|
33e9d10d2a | ||
|
|
46f7dc3bf6 | ||
|
|
555b0e20f7 | ||
|
|
a57dfe710d | ||
|
|
53adbd7a3d | ||
|
|
17f033b725 | ||
|
|
cefed3e8dc | ||
|
|
84fa865c0c | ||
|
|
f05f993eb7 | ||
|
|
e90cdb8adf | ||
|
|
4250941710 | ||
|
|
a2687b64a2 | ||
|
|
c284f34a49 | ||
|
|
5f5be796b0 | ||
|
|
5cb374364b | ||
|
|
f15256e156 | ||
|
|
ce37eb2d83 | ||
|
|
0d6e308b51 | ||
|
|
b1dab2363a | ||
|
|
bd6abc4939 | ||
|
|
96eeda0324 | ||
|
|
4c4266d9c9 | ||
|
|
54e87b4b06 | ||
|
|
44e9e221f3 | ||
|
|
61dec11ae0 | ||
|
|
5009de7d2d | ||
|
|
67f3feebcb | ||
|
|
b22260749f | ||
|
|
06d76beb28 | ||
|
|
7af4227ac2 | ||
|
|
9312b7325e | ||
|
|
c6edb381f5 | ||
|
|
a1d55ad095 | ||
|
|
a289addd96 | ||
|
|
13c5b46361 | ||
|
|
f3af206d8d | ||
|
|
df0054ab13 | ||
|
|
0d162bd17c | ||
|
|
e1add89334 | ||
|
|
22d49dc429 | ||
|
|
1aa4caf318 | ||
|
|
306ffb8c71 | ||
|
|
0a98201164 | ||
|
|
e0870f1d7a | ||
|
|
1923b1fce4 | ||
|
|
5dc4003e63 | ||
|
|
37c817eb81 | ||
|
|
284d628a7c | ||
|
|
ff3184ca1e | ||
|
|
12865a9762 | ||
|
|
ea847c6232 | ||
|
|
b695f2423d | ||
|
|
c3e5e5851b | ||
|
|
4337c8f856 | ||
|
|
4c7e46079d | ||
|
|
72a6e63136 | ||
|
|
37101856a6 | ||
|
|
65fc84b32e | ||
|
|
45e08edb08 | ||
|
|
05b7bab8e1 | ||
|
|
904817552d | ||
|
|
6e195fe975 | ||
|
|
3eaf615f40 | ||
|
|
6156e72f85 | ||
|
|
73a4bdfd77 | ||
|
|
4844449a5d | ||
|
|
ae289aec1e | ||
|
|
9e4c32ea54 | ||
|
|
a5f9cff256 | ||
|
|
d01d15e096 | ||
|
|
a53426441b | ||
|
|
5d1966948e | ||
|
|
f673ea84b2 | ||
|
|
64f21c31bf | ||
|
|
520cf41711 | ||
|
|
d38fc30563 | ||
|
|
6dff599288 | ||
|
|
f746dda0a0 | ||
|
|
91a1e147ae | ||
|
|
40da904230 | ||
|
|
34fada3012 | ||
|
|
f91e01d9a5 | ||
|
|
3048b0a8ea | ||
|
|
d99b4ccf93 | ||
|
|
58811a0a38 | ||
|
|
cb290916be | ||
|
|
a2b0471f1d | ||
|
|
bb18e7550c | ||
|
|
db2b5cb75f | ||
|
|
fa8c787d8b | ||
|
|
ec40899bb9 | ||
|
|
b5accabaa7 | ||
|
|
4e308a9526 | ||
|
|
4d88810810 | ||
|
|
f321922214 | ||
|
|
cab13afe8d | ||
|
|
72fc7ec59b | ||
|
|
58743a87b8 | ||
|
|
54bf456e85 | ||
|
|
a24639bb36 | ||
|
|
3fef53645d | ||
|
|
882e689312 | ||
|
|
b0a93231cf | ||
|
|
0c819b76d6 | ||
|
|
ce58b1b479 | ||
|
|
a16d8f2b25 | ||
|
|
59187666b9 | ||
|
|
808c57c343 | ||
|
|
4af8fe4e78 | ||
|
|
4034cb3f71 | ||
|
|
6fc048f438 | ||
|
|
5d2a707139 | ||
|
|
81d2b0ef9d | ||
|
|
248ed45fc6 | ||
|
|
893c4cc056 | ||
|
|
a7725e6df9 | ||
|
|
368ad70e05 | ||
|
|
b7cee9498b | ||
|
|
72d45525d2 | ||
|
|
1fb8ec4b0d | ||
|
|
beb9368481 | ||
|
|
981555bddb | ||
|
|
9c7527085c | ||
|
|
eddd5d129e | ||
|
|
26f76b7912 | ||
|
|
32eda0961e | ||
|
|
66964002df | ||
|
|
57469f6c31 | ||
|
|
13c7bcbb2b | ||
|
|
d48c806560 | ||
|
|
ad1a09a509 | ||
|
|
d6631cf3a5 | ||
|
|
5a8543b8b8 | ||
|
|
19119cbd35 | ||
|
|
442743b83c | ||
|
|
419896af47 | ||
|
|
0569a1339d | ||
|
|
f1e3656ee2 | ||
|
|
a644fc3cc4 | ||
|
|
d17e1dd2da | ||
|
|
b9b15fb165 | ||
|
|
ef732c3b54 | ||
|
|
baa4212ae1 | ||
|
|
0be976ec0a | ||
|
|
f7f10340d6 | ||
|
|
68f9910d94 | ||
|
|
fb6e0ea120 | ||
|
|
97feb557ed | ||
|
|
dc8293ff73 | ||
|
|
785db4ced0 | ||
|
|
5562deb169 | ||
|
|
983b1ed321 | ||
|
|
548abf96ce | ||
|
|
f8ebdf9265 | ||
|
|
aa23c22004 | ||
|
|
1d5cda2265 | ||
|
|
fe70ad26d3 | ||
|
|
0a00748901 | ||
|
|
03979352b4 | ||
|
|
cb7fb45e42 | ||
|
|
92cc9dd7c2 | ||
|
|
88a7fb3edd | ||
|
|
728d092201 | ||
|
|
80707c983c | ||
|
|
5911fee567 | ||
|
|
a09f6f55da | ||
|
|
caf5cc9152 | ||
|
|
58422e8393 | ||
|
|
e8d3168e3a | ||
|
|
7b1a0c19b8 | ||
|
|
536492752b | ||
|
|
7c4f063b13 | ||
|
|
1a62c49d31 | ||
|
|
fea4db62bd | ||
|
|
4499c0eebd | ||
|
|
0c42946536 | ||
|
|
ab264c9e79 | ||
|
|
dd7fb70f6e | ||
|
|
30f337c9ef | ||
|
|
9d35271938 | ||
|
|
bbfb1d016b | ||
|
|
c4b4df4fb4 | ||
|
|
a6d89d18bf | ||
|
|
75bc860093 | ||
|
|
02a279a75f | ||
|
|
584c7bf76d | ||
|
|
c4cd2ca6bf | ||
|
|
1ef00d2072 | ||
|
|
4dd4c72790 | ||
|
|
6aae748ea7 | ||
|
|
aa953c3201 | ||
|
|
3f55bd5dad | ||
|
|
279b1c1ebb | ||
|
|
fa45cda1aa | ||
|
|
11dc274054 | ||
|
|
e7bef92205 | ||
|
|
4a1991d7c5 | ||
|
|
13aefa1365 | ||
|
|
addf0c4a1c | ||
|
|
25bfc8cea1 | ||
|
|
dfd5ba6ab7 | ||
|
|
393ba2214d | ||
|
|
f358487f8e | ||
|
|
a18381aca6 | ||
|
|
f6e54812b7 | ||
|
|
31e7451aa5 | ||
|
|
0e36d9da42 | ||
|
|
da9d12f5d9 | ||
|
|
a60e2dca6b | ||
|
|
86c4601e12 | ||
|
|
173f5bf8cf | ||
|
|
823edc686f | ||
|
|
a3a841073e | ||
|
|
57385128c3 | ||
|
|
2990e06f29 | ||
|
|
2ef2e822d1 | ||
|
|
b7736c797c | ||
|
|
9b9c8aaf4d | ||
|
|
b0fd253afc | ||
|
|
e028b9ff53 | ||
|
|
9c07d25345 | ||
|
|
7352b8736b | ||
|
|
5b540e86a4 | ||
|
|
6744b62ddd | ||
|
|
e90b8acec3 | ||
|
|
925c517f19 | ||
|
|
cc964a518c | ||
|
|
3309507dd3 | ||
|
|
5e7dbaca50 | ||
|
|
76c2194714 | ||
|
|
968c8030cf | ||
|
|
446e239e2c | ||
|
|
e7bc9b64a3 | ||
|
|
8018edd3aa | ||
|
|
64c3523a6f | ||
|
|
310c9f30f0 | ||
|
|
5c1b7bfd2a | ||
|
|
faf11086d8 | ||
|
|
52fa4d7893 | ||
|
|
de0551020b | ||
|
|
c1456d83a7 | ||
|
|
1cbbaea957 | ||
|
|
f6aeaa74d1 | ||
|
|
6839140eb5 | ||
|
|
915dd20705 | ||
|
|
c53217a2b8 | ||
|
|
b2ac00eb16 | ||
|
|
45ddbf6204 | ||
|
|
276877cf77 | ||
|
|
6b45fcf160 | ||
|
|
49c24eccd4 | ||
|
|
0d7d3763f2 | ||
|
|
241dc65eee | ||
|
|
860bdd4571 | ||
|
|
55bf051bbc | ||
|
|
423dba8ea1 | ||
|
|
517c7b4dee | ||
|
|
18ced14631 | ||
|
|
ce67256218 | ||
|
|
9e83fa99fe | ||
|
|
256a9e376c | ||
|
|
ef5075e092 | ||
|
|
65653a6596 | ||
|
|
d5a0b48379 | ||
|
|
314a74d731 | ||
|
|
90e22f4b51 | ||
|
|
ab304c268c | ||
|
|
16a3fec02d | ||
|
|
abb0b532f8 | ||
|
|
43cd760fc1 | ||
|
|
9af87151ec | ||
|
|
8dd99390f5 | ||
|
|
e636af6b23 | ||
|
|
e3217f1448 | ||
|
|
66b711633f | ||
|
|
f40f2fc8ce | ||
|
|
e6f9e388cf | ||
|
|
3c1e2ad956 | ||
|
|
e6d2799170 | ||
|
|
2cfbf4bc0e | ||
|
|
f7731f1fc2 | ||
|
|
7d3f8ae2df | ||
|
|
a60fdd63f4 | ||
|
|
3a7dec59bc | ||
|
|
880ae34190 | ||
|
|
d00daf1f3f | ||
|
|
17fadf7d40 | ||
|
|
06c28400fa | ||
|
|
6e35c72fdb | ||
|
|
e2d22fee53 | ||
|
|
1bca1de6cc | ||
|
|
e0ed4e4087 | ||
|
|
4a7319be12 | ||
|
|
55d5937dd6 | ||
|
|
63596e1c4a | ||
|
|
603e6b05c7 | ||
|
|
dfad66a838 | ||
|
|
58cadc8608 | ||
|
|
b11b50bcd0 | ||
|
|
a73de5f3ba | ||
|
|
84c3645cea | ||
|
|
2a88a8cd30 | ||
|
|
8a97fc2e1b | ||
|
|
7a2fd68b96 | ||
|
|
6a7cc46cb2 | ||
|
|
aa6dc37ccb | ||
|
|
ea42541fe0 | ||
|
|
b7b2741f3a | ||
|
|
eb61be192d | ||
|
|
9b9114e8cd | ||
|
|
857e38bb45 | ||
|
|
4ea812445d | ||
|
|
e80a765412 | ||
|
|
15089022d4 | ||
|
|
f69204adad | ||
|
|
459a83c9cc | ||
|
|
6464bdbe13 | ||
|
|
4f3e9a0fba | ||
|
|
8a9709dee5 | ||
|
|
daa598df11 | ||
|
|
d04e9c51b4 | ||
|
|
d89a3a313a | ||
|
|
350e4e4dec | ||
|
|
c95dcb3935 | ||
|
|
1e4f48d6c4 | ||
|
|
fb55e28d83 | ||
|
|
067669dac7 | ||
|
|
24c906d3f7 | ||
|
|
14820f635d | ||
|
|
59192f5650 | ||
|
|
365346ca30 | ||
|
|
d01350a881 | ||
|
|
38b02c13d0 | ||
|
|
b017ec4e13 | ||
|
|
2c873122b3 | ||
|
|
6969ebcfcf | ||
|
|
1dbb94cadf | ||
|
|
8a78bb963d | ||
|
|
6931c13800 | ||
|
|
e6e3f12ffc | ||
|
|
e2559dbedc | ||
|
|
1f3d6cdd86 | ||
|
|
4a7ee79d4d | ||
|
|
0c2ef5f42d | ||
|
|
ca20c7fd62 | ||
|
|
191e40da17 | ||
|
|
80ddadb7e8 | ||
|
|
31f3b68a97 | ||
|
|
d594399c6a | ||
|
|
d74a2e3ed5 | ||
|
|
d175d7e13e | ||
|
|
daa8ce838b | ||
|
|
b19fd07c02 | ||
|
|
47d6a60c2f | ||
|
|
980821ebab | ||
|
|
592f4696dc | ||
|
|
8a7846f97e | ||
|
|
87f18b6289 | ||
|
|
28063ba5b2 | ||
|
|
fe332038c6 | ||
|
|
3c0b1ebf78 | ||
|
|
f2fe4903c9 | ||
|
|
3151cbae89 | ||
|
|
3c30b99059 | ||
|
|
a7735ba085 | ||
|
|
d811b68901 | ||
|
|
1c8162a921 | ||
|
|
16417f8b9d | ||
|
|
b49d381d05 | ||
|
|
7da9a16d10 | ||
|
|
32f60a6e7b | ||
|
|
b7db090661 | ||
|
|
136c5c5ec3 | ||
|
|
85b80fbc73 | ||
|
|
16859cdbdc | ||
|
|
fc96552d26 | ||
|
|
15bb997d0a | ||
|
|
b6b42c892c | ||
|
|
5bb920003e | ||
|
|
37ff0e344d | ||
|
|
97d53f8c75 | ||
|
|
f2ac84c36d | ||
|
|
c21eeef5bc | ||
|
|
e11c425119 | ||
|
|
84229c7ac9 | ||
|
|
c9a59880f0 | ||
|
|
9a17dddbc5 | ||
|
|
277d99e8c9 | ||
|
|
2a1874cc82 | ||
|
|
d5c973ccb7 | ||
|
|
37f3ce61bb | ||
|
|
076f60eed0 | ||
|
|
20b2e9cef7 | ||
|
|
e37d8229f5 | ||
|
|
710faea9a4 | ||
|
|
70a6051cf1 | ||
|
|
7a1f46b6ac | ||
|
|
7ca9250db0 | ||
|
|
af7086c63f | ||
|
|
8808589277 | ||
|
|
6cd5096063 | ||
|
|
677cd34acd | ||
|
|
08c5385e65 | ||
|
|
d7bf70f196 | ||
|
|
6f3cff41dd | ||
|
|
5de45bcadc | ||
|
|
446ee5b110 | ||
|
|
d3e6fd3910 | ||
|
|
6813fa7eac | ||
|
|
0f5a04e3ff | ||
|
|
8801138b47 | ||
|
|
2473391971 | ||
|
|
7d6879328a | ||
|
|
900454132e | ||
|
|
92b8abfe80 | ||
|
|
52e628a861 | ||
|
|
4791825d49 | ||
|
|
d542c20c5f | ||
|
|
4762db4fc9 | ||
|
|
8645af1d8c | ||
|
|
429f98283f | ||
|
|
5be7fa93fc | ||
|
|
837cbad97f | ||
|
|
af1d91c562 | ||
|
|
908f5a9f9f | ||
|
|
9b74643315 | ||
|
|
986066873e | ||
|
|
9533e15a79 | ||
|
|
8dc74608a3 | ||
|
|
3e85237e5f | ||
|
|
9d0523ef4c | ||
|
|
4a7144ee7e | ||
|
|
c120ff37f5 | ||
|
|
83fd337d8e | ||
|
|
707c1a3085 | ||
|
|
8294b00c11 | ||
|
|
da2bcdd1c2 | ||
|
|
093acc5dad | ||
|
|
fd73b94d31 | ||
|
|
38499c1a49 | ||
|
|
170381c052 | ||
|
|
8113a033dd | ||
|
|
87cc45e136 | ||
|
|
f6b8d591f7 | ||
|
|
d31c09c872 | ||
|
|
337a1a86a7 | ||
|
|
b7dc46c0f6 | ||
|
|
ff57065957 | ||
|
|
0406a3a7a4 | ||
|
|
bc3b5b2558 | ||
|
|
d1cce1dd92 | ||
|
|
7bb7058e8d | ||
|
|
727fa3688f | ||
|
|
577ab12ce5 | ||
|
|
0f2ac85576 | ||
|
|
fab1f8898e | ||
|
|
f63d68be97 | ||
|
|
58665d23b4 | ||
|
|
195bd906a2 | ||
|
|
fc1ae6582f | ||
|
|
fc0257c9fd | ||
|
|
91c4da3fda | ||
|
|
990ff150ef | ||
|
|
e72b18a9bd | ||
|
|
bc63ae3f13 | ||
|
|
6e12886393 | ||
|
|
b5ca91ae4b | ||
|
|
89855e78ab | ||
|
|
e106de49c8 | ||
|
|
afbcc8f216 | ||
|
|
f177b7cca2 | ||
|
|
ea5164d181 | ||
|
|
ccdff3ebbf | ||
|
|
24d0fcde7f | ||
|
|
56014c8c0a | ||
|
|
7c2a9e766c | ||
|
|
bb24028f51 | ||
|
|
52d3e10613 | ||
|
|
67863f46e3 | ||
|
|
9c28e52628 | ||
|
|
1b2f167546 | ||
|
|
702d0c4529 | ||
|
|
51106bafc6 | ||
|
|
42d4edc067 | ||
|
|
fbc0bc4d53 | ||
|
|
1b2db7aecb | ||
|
|
1ce29566e7 | ||
|
|
3742bf3ac3 | ||
|
|
18d6b679af | ||
|
|
dbda5fbf06 | ||
|
|
2154309a54 | ||
|
|
afb6e9450d | ||
|
|
dfa3248380 | ||
|
|
2cda256088 | ||
|
|
d9c7edf63f | ||
|
|
a151343943 | ||
|
|
85ed0aa396 | ||
|
|
3019f95f37 | ||
|
|
5702bc12b3 | ||
|
|
b0d791bb35 | ||
|
|
3903928ca0 | ||
|
|
827c37f631 | ||
|
|
b45b059a3d | ||
|
|
f39281ae56 | ||
|
|
e2bea9eb8d | ||
|
|
931a979904 | ||
|
|
3fccfafd30 | ||
|
|
7a6fd4c1c7 | ||
|
|
8395d24616 | ||
|
|
7d085960eb | ||
|
|
3884317181 | ||
|
|
089a2435f8 | ||
|
|
8ed16deb24 | ||
|
|
a577af9067 | ||
|
|
59af13651b | ||
|
|
787568f371 | ||
|
|
f0019fc506 | ||
|
|
9f639210ca | ||
|
|
deec574421 | ||
|
|
04657e42d5 | ||
|
|
1b88775534 | ||
|
|
7f6537557d | ||
|
|
518233ca79 | ||
|
|
bc72130d71 | ||
|
|
855decd3a7 | ||
|
|
0090cbdba6 | ||
|
|
73ff720972 | ||
|
|
c561e1378d | ||
|
|
aa2c47d835 | ||
|
|
536b84680b | ||
|
|
7508b795bf | ||
|
|
76ee1d18bf | ||
|
|
379bc86547 | ||
|
|
066696644f | ||
|
|
755bcd3722 | ||
|
|
1985aa9666 | ||
|
|
f4663a36da | ||
|
|
521e6fdcfc | ||
|
|
61ab574e38 | ||
|
|
660cb6a085 | ||
|
|
4274208833 | ||
|
|
34db05b421 | ||
|
|
1657be22a3 | ||
|
|
3636b9ffaa | ||
|
|
e3cd264571 | ||
|
|
69555b0943 | ||
|
|
522c05cf9a | ||
|
|
f0b4fdaf5e | ||
|
|
ac6ce98375 | ||
|
|
1b3cadaa39 | ||
|
|
61ca7d596c | ||
|
|
688d573295 | ||
|
|
ec6e0bf0c0 | ||
|
|
184dede92f | ||
|
|
d2cc0323fb | ||
|
|
3a1eefd331 | ||
|
|
824f1c7944 | ||
|
|
7bc8218d81 | ||
|
|
a405cda63c | ||
|
|
7afa3a4a48 | ||
|
|
c80b3d8c3f | ||
|
|
ef6122c622 | ||
|
|
75fb17b891 | ||
|
|
2abbf2498f | ||
|
|
b91b50c01f | ||
|
|
06891710f2 | ||
|
|
b765ec32b9 | ||
|
|
a70d070cc5 | ||
|
|
1f1fbe187e | ||
|
|
fc63847406 | ||
|
|
f58677d123 | ||
|
|
7ab1538861 | ||
|
|
7ad0f94de9 | ||
|
|
8af534a52c | ||
|
|
7447419266 | ||
|
|
5216de37a4 | ||
|
|
ccc0d1eb1d | ||
|
|
7fc0890881 | ||
|
|
b17f1d76c0 | ||
|
|
451b5fc969 | ||
|
|
1e678fcab1 | ||
|
|
48bcc6ee2b | ||
|
|
32734c7c3c | ||
|
|
aaf375d0a5 | ||
|
|
9680f811f6 | ||
|
|
bda41fa509 | ||
|
|
7ea84b6890 | ||
|
|
cc234d944a | ||
|
|
ac84096d1f | ||
|
|
a1cc591b29 | ||
|
|
da0405080e | ||
|
|
0c0a3e2dd3 | ||
|
|
ad301e487c | ||
|
|
b5ae4aba38 | ||
|
|
8d2aad49e3 | ||
|
|
bc2b4963a0 | ||
|
|
ee7118a816 | ||
|
|
95dd949c09 | ||
|
|
9326552e66 | ||
|
|
1e34e4b7cd | ||
|
|
06464f55e2 | ||
|
|
1b85e3f1a0 | ||
|
|
eac9dc63e3 | ||
|
|
30e8c8e1e4 | ||
|
|
d53d7795ee | ||
|
|
59c95e4243 | ||
|
|
f8a94f0de8 | ||
|
|
3b5f6214a6 | ||
|
|
542ad675b9 | ||
|
|
1e736b8ff7 | ||
|
|
a6d8c3f336 | ||
|
|
bb4aa89c10 | ||
|
|
09021eabb5 | ||
|
|
8d69d57113 | ||
|
|
eaa4c150ab | ||
|
|
a125c82ad2 | ||
|
|
93eff16a6a | ||
|
|
d2d9fe184d | ||
|
|
2d4ca358db | ||
|
|
39993af514 | ||
|
|
bef4934045 | ||
|
|
1312d9fc47 | ||
|
|
75aeac44e8 | ||
|
|
68f40ebba9 | ||
|
|
973007daac | ||
|
|
8060514230 | ||
|
|
b1a2f37a6e | ||
|
|
7c66b86028 | ||
|
|
cc248aae9b | ||
|
|
ca23c51aeb | ||
|
|
fca9a9b0f0 | ||
|
|
1ea15dbe05 | ||
|
|
8e34cd41f0 | ||
|
|
9ef1cc7cdf | ||
|
|
411acbbc2a | ||
|
|
32e83406c4 | ||
|
|
7e28fca126 | ||
|
|
e4ffb53900 | ||
|
|
7c2d381c28 | ||
|
|
bde47ca7c5 | ||
|
|
ea7f8108b0 | ||
|
|
98393ae2e2 | ||
|
|
759ac87019 | ||
|
|
a1e0e45e01 | ||
|
|
54170a084d | ||
|
|
1bbf83c07d | ||
|
|
ccd2b499ed | ||
|
|
1de50993a7 | ||
|
|
786c36876b | ||
|
|
8bd1a73e14 | ||
|
|
c7d692c3c3 | ||
|
|
f9b9e2f067 | ||
|
|
dafe63ca98 | ||
|
|
f49a7b227f | ||
|
|
f5e4eadb74 | ||
|
|
717eb9b883 | ||
|
|
5ba268efa8 | ||
|
|
25ff30e804 | ||
|
|
bdae761ee1 | ||
|
|
5af50297be | ||
|
|
32f761755e | ||
|
|
c4fea82ff9 | ||
|
|
6ded1170ac | ||
|
|
991f90f296 | ||
|
|
c979dad54a | ||
|
|
136ac7ecec | ||
|
|
3e8369b6dc | ||
|
|
a7dc44d27d | ||
|
|
07a874fd9b | ||
|
|
e35080cede | ||
|
|
ce8149b6fe | ||
|
|
a86179f429 | ||
|
|
56cf38ac98 | ||
|
|
b0f451eb3b | ||
|
|
d0829892c6 | ||
|
|
fdf88d7574 | ||
|
|
595f2d4d97 | ||
|
|
cae95647a4 | ||
|
|
a254fd9798 | ||
|
|
805edf9d7d | ||
|
|
eca2adb4b3 | ||
|
|
4eea7793ea | ||
|
|
67684d038d | ||
|
|
98b332edea | ||
|
|
e681e82066 | ||
|
|
08571358b1 | ||
|
|
8901a07fdb | ||
|
|
880da0072e | ||
|
|
a83600cc82 | ||
|
|
dd0628f85f | ||
|
|
e66dfd1879 | ||
|
|
bf2daeaf2d | ||
|
|
bd0ad74f4b | ||
|
|
79f671cc7c | ||
|
|
0f9c48b1d2 | ||
|
|
538ba24fd7 | ||
|
|
d37d8d7b69 | ||
|
|
f4a0483ab8 | ||
|
|
f5f95a38c4 | ||
|
|
3e7053ac59 | ||
|
|
420ef2c419 | ||
|
|
9fb3f7a9ab | ||
|
|
734a94a20c | ||
|
|
b44be3e944 | ||
|
|
fc0302cf07 | ||
|
|
4fdc39dde8 | ||
|
|
9a933bc2ce | ||
|
|
524dc9afd6 | ||
|
|
e4d709cbf8 | ||
|
|
48c1586cd1 | ||
|
|
7bd0cf5b8f | ||
|
|
fcb69e5cdc | ||
|
|
96557d23a3 | ||
|
|
4e5db0ad4a | ||
|
|
c81a32f071 | ||
|
|
6f2623fd69 | ||
|
|
b4235b3165 | ||
|
|
d25c0e42c7 | ||
|
|
0ecfbf27c3 | ||
|
|
fb4c98c2c8 | ||
|
|
cd8e38b13f | ||
|
|
b35d0d8e9a | ||
|
|
c948e309f2 | ||
|
|
d1f83bcc81 | ||
|
|
e0fde757fd | ||
|
|
25d34a5c80 | ||
|
|
610364e3a6 | ||
|
|
036e70b024 | ||
|
|
ac13ad106a | ||
|
|
bd9e9eccbd | ||
|
|
8ff9d697c9 | ||
|
|
62b68c8046 | ||
|
|
e4724e5c1c | ||
|
|
559e727bf7 | ||
|
|
126642b633 | ||
|
|
cca4e06786 | ||
|
|
2f1faea89b | ||
|
|
3d90ec146f | ||
|
|
1bc209b441 | ||
|
|
1433e6da69 | ||
|
|
f8f4c862e8 | ||
|
|
226df8e717 | ||
|
|
6c92af2067 | ||
|
|
54c7298ce4 | ||
|
|
642a979a27 | ||
|
|
e733c93423 | ||
|
|
ffdb58a51a | ||
|
|
c053133207 | ||
|
|
9098bbf3b3 | ||
|
|
68618b8810 | ||
|
|
e553d27f41 | ||
|
|
d092924c63 | ||
|
|
34027489e0 | ||
|
|
d1239eae92 | ||
|
|
331050969b | ||
|
|
259c3e72b0 | ||
|
|
8f7a38336d | ||
|
|
999dfffc9b | ||
|
|
527a51cec5 | ||
|
|
20c15aead5 | ||
|
|
fb859e5674 | ||
|
|
4f2dcb1714 | ||
|
|
64e74631e0 | ||
|
|
fba31efb74 | ||
|
|
435f1ed70d | ||
|
|
94f34ca10a | ||
|
|
b0633744fa | ||
|
|
c127e8aaec | ||
|
|
bf4e725d5d | ||
|
|
663717f465 | ||
|
|
12b159ac41 | ||
|
|
9299c8f0b4 | ||
|
|
dfef3f1099 | ||
|
|
fa3690f488 | ||
|
|
4acbfa2ade | ||
|
|
ef86d74736 | ||
|
|
118f39d45b | ||
|
|
77867907ed | ||
|
|
98c1b32565 | ||
|
|
7a176e87d5 | ||
|
|
79c9d8a180 | ||
|
|
7d8219327b | ||
|
|
4ac4bdbb38 | ||
|
|
f494f2864c | ||
|
|
017f22b47f | ||
|
|
dec41b556b | ||
|
|
be2961da2c | ||
|
|
914cc65c9d | ||
|
|
6479c2ed3f | ||
|
|
c1a04ecbfd | ||
|
|
69b06c50c4 | ||
|
|
6aaf8d8c10 | ||
|
|
4cf64834ed | ||
|
|
b8709f5046 | ||
|
|
24448f741f | ||
|
|
76533c52dc | ||
|
|
3ff984d7a7 | ||
|
|
7a52790b50 | ||
|
|
7b329a2d79 | ||
|
|
599dc93c64 | ||
|
|
8b54f00466 | ||
|
|
8469faef03 | ||
|
|
bceec82f35 | ||
|
|
ed521de525 | ||
|
|
d157de203a | ||
|
|
1bfbf40bd5 | ||
|
|
6d19c6742c | ||
|
|
a628b06977 | ||
|
|
6b2d24de2c | ||
|
|
e23d790fa7 | ||
|
|
2a5904a580 | ||
|
|
4610ac79c2 | ||
|
|
142f5be922 | ||
|
|
b17dd0c435 | ||
|
|
3669201179 | ||
|
|
a5c48193c7 | ||
|
|
4366275bab | ||
|
|
c579310a00 | ||
|
|
96553aa7ef | ||
|
|
2094283b80 | ||
|
|
4c631ac621 | ||
|
|
d96d3893dd | ||
|
|
b73b51a9e4 | ||
|
|
3c1edccb7b | ||
|
|
b23c290630 | ||
|
|
c7b562becf | ||
|
|
5648a81936 | ||
|
|
daa3d0e2da | ||
|
|
c9a66d41fe | ||
|
|
0ee1bd82c5 | ||
|
|
53e1f937bc | ||
|
|
604f343c49 | ||
|
|
e9c4c3018b | ||
|
|
db1babe6a9 | ||
|
|
f1abcc7a4c | ||
|
|
97e1254a2d | ||
|
|
89b0a3d963 | ||
|
|
3a79260d3a | ||
|
|
43a4dc1053 | ||
|
|
e53fe9a278 | ||
|
|
f5a95bb50b | ||
|
|
0e23e41d48 | ||
|
|
ac69049ec2 | ||
|
|
b2a2dd1154 | ||
|
|
31837783c0 | ||
|
|
d40fb72395 | ||
|
|
1c548d5e59 | ||
|
|
be59d0ec23 | ||
|
|
0bc467516a | ||
|
|
844f11f284 | ||
|
|
1cf1e7b3b4 | ||
|
|
18b72cc829 | ||
|
|
271f87e5d4 | ||
|
|
2e6c7f4549 | ||
|
|
6819304740 | ||
|
|
a795ab99c7 | ||
|
|
567e56313a | ||
|
|
9e95e92bdf | ||
|
|
be60c7b9d1 | ||
|
|
7d81641065 | ||
|
|
17d8573ef0 | ||
|
|
e2dd78f744 | ||
|
|
06b91d8eb9 | ||
|
|
9ec5422c37 | ||
|
|
1935e11c3c | ||
|
|
ec14031abd | ||
|
|
024a9bafbd | ||
|
|
27741d9fd9 | ||
|
|
e3bdb76326 | ||
|
|
9369576459 | ||
|
|
8a405c6ca1 | ||
|
|
94ad1c6477 | ||
|
|
6f039cc2ac | ||
|
|
6216ca2c70 | ||
|
|
c6e27b608e | ||
|
|
f76584a57c | ||
|
|
7bea78ced6 | ||
|
|
1264288cb5 | ||
|
|
0f0ea7f779 | ||
|
|
0b4af330ce | ||
|
|
6dd41b67fb | ||
|
|
1521eefb62 | ||
|
|
a036a0e818 | ||
|
|
7583ded808 | ||
|
|
78818f4465 | ||
|
|
7a49cb5667 | ||
|
|
23212669ac | ||
|
|
3ce0f9a653 | ||
|
|
d834adc14f | ||
|
|
b84ba8967a | ||
|
|
79845f2834 | ||
|
|
78ece130a4 | ||
|
|
bd37c66630 | ||
|
|
371d1c36b3 | ||
|
|
d0f821ad3d | ||
|
|
ded8347d6b | ||
|
|
c4a5c57dc3 | ||
|
|
404e813c52 | ||
|
|
90d0a8db38 | ||
|
|
956ff9ff72 | ||
|
|
1eca49c6ed | ||
|
|
34758d5c15 | ||
|
|
befbfe6115 | ||
|
|
900748fca1 | ||
|
|
87ee248169 | ||
|
|
bb7c4fa361 | ||
|
|
c613d37048 | ||
|
|
d52a22e4db | ||
|
|
6dfb45bcdf | ||
|
|
145794936f | ||
|
|
301c680fd7 | ||
|
|
d27cbec598 | ||
|
|
f5be54d6ab | ||
|
|
1e19f7ba5f | ||
|
|
db719fb0d7 | ||
|
|
b0d4f4c10e | ||
|
|
238d23d775 | ||
|
|
c019068f06 | ||
|
|
715d1f4504 | ||
|
|
4f092bee9f | ||
|
|
1bbd10fe07 | ||
|
|
088aac8597 | ||
|
|
81c652d5d2 | ||
|
|
d7761c1480 | ||
|
|
93689aa51a | ||
|
|
46e6ad492a | ||
|
|
97efa5c36c | ||
|
|
0b1ffe2755 | ||
|
|
8c35542d1f | ||
|
|
0e9480317d | ||
|
|
b695d088cf | ||
|
|
81dc5750ca | ||
|
|
d82434cf27 | ||
|
|
cd6058f3d4 | ||
|
|
9be3ba223c | ||
|
|
a261989cda | ||
|
|
7b5c3eb05e | ||
|
|
0feec72eee | ||
|
|
be8bd99aa4 | ||
|
|
355b8bcd73 | ||
|
|
d58e4c273c | ||
|
|
a217ad3095 | ||
|
|
3d6feada8a | ||
|
|
5f78da2025 | ||
|
|
a05e4fa512 | ||
|
|
2119a4c462 | ||
|
|
1d5a1da9f8 | ||
|
|
2e7d19945c | ||
|
|
5d2c5c4c73 | ||
|
|
8694312695 | ||
|
|
d9d6bc5278 | ||
|
|
ebed4c3af0 | ||
|
|
172875cf15 | ||
|
|
4d26e9e4f4 | ||
|
|
8f4455f296 | ||
|
|
2e1d43deb2 | ||
|
|
6780f72000 | ||
|
|
39e01d2d4b | ||
|
|
f75502950b | ||
|
|
974f27e7e9 | ||
|
|
af32f69eb0 | ||
|
|
0cd2f40764 | ||
|
|
0d95824995 | ||
|
|
bbc09ffba9 | ||
|
|
a4677968cf | ||
|
|
03b1cddc31 | ||
|
|
9c2dd04993 | ||
|
|
a84a93fafe | ||
|
|
5fdcc397b1 | ||
|
|
5664871e5f | ||
|
|
55d9e0fada | ||
|
|
929e3011c6 | ||
|
|
07d70ff560 | ||
|
|
58c2960960 | ||
|
|
00d943d513 | ||
|
|
71c780da06 | ||
|
|
3b18cba889 | ||
|
|
2974e20550 | ||
|
|
430d841a2c | ||
|
|
31ec50d7da | ||
|
|
5ad0e46f08 | ||
|
|
1b5814e338 | ||
|
|
255810c0d6 | ||
|
|
5d2640376e | ||
|
|
d02984bbb7 | ||
|
|
0f9555207a | ||
|
|
885448d74c | ||
|
|
b14545b3ff | ||
|
|
9a5a86734f | ||
|
|
d1d1505045 | ||
|
|
144ce1dc21 | ||
|
|
aa126974ba | ||
|
|
707de53457 | ||
|
|
10f83cf43d | ||
|
|
59ee743c5f | ||
|
|
d54765c442 | ||
|
|
91262d5d3e | ||
|
|
1c09c743b1 | ||
|
|
06ce139fcc | ||
|
|
fae5bb3183 | ||
|
|
6fe25398d6 | ||
|
|
909ce14fc4 | ||
|
|
935b920120 | ||
|
|
b31427cd4a | ||
|
|
e2e3379d79 | ||
|
|
6b1ef85dd8 | ||
|
|
92325ada0c | ||
|
|
1707e0f9e2 | ||
|
|
7ff701e816 | ||
|
|
2e3c141795 | ||
|
|
76f79ba748 | ||
|
|
9dd891bb28 | ||
|
|
99f106d1cf | ||
|
|
3816cae745 | ||
|
|
759c0627e1 | ||
|
|
e03dfae507 | ||
|
|
c7677b892a | ||
|
|
da7b63972d | ||
|
|
499957d9ba | ||
|
|
582250008b | ||
|
|
a9b31409d5 | ||
|
|
98355b8086 | ||
|
|
70ed474b38 | ||
|
|
4775934364 | ||
|
|
25f2cb3d6b | ||
|
|
154f9a3aca | ||
|
|
b9df3bf20c | ||
|
|
6abd193fe3 | ||
|
|
362099a512 | ||
|
|
fdfc3dc9f3 | ||
|
|
4937459225 | ||
|
|
be2f866b4c | ||
|
|
f08aacf7d6 | ||
|
|
4fa6112efe | ||
|
|
1623ba6889 | ||
|
|
766526c791 | ||
|
|
5c15e29f2b | ||
|
|
0413e1605f | ||
|
|
0e5a1f8352 | ||
|
|
e5a2b8544d | ||
|
|
736a6a291c | ||
|
|
6e69cff118 | ||
|
|
cf72f20426 | ||
|
|
d479210cee | ||
|
|
b781537597 | ||
|
|
ea1438dad8 | ||
|
|
d2e9d069b4 | ||
|
|
58379559cc | ||
|
|
b3e6c81565 | ||
|
|
a6a3c3df45 | ||
|
|
6e3d4c4045 | ||
|
|
ca60b701ee | ||
|
|
e24c0b98d7 | ||
|
|
f389ac80a9 | ||
|
|
50f2f002d9 | ||
|
|
9ec7528475 | ||
|
|
a8e2a43a09 | ||
|
|
eb06fa95e4 | ||
|
|
1db8b61de7 | ||
|
|
38c66db8d6 | ||
|
|
f8be7d4219 | ||
|
|
13e29995f5 | ||
|
|
7c583c7316 | ||
|
|
9fecec5e85 | ||
|
|
9e696bd468 | ||
|
|
6ab6d4bfc1 | ||
|
|
cb1bcc7ebb | ||
|
|
19ba7d6318 | ||
|
|
7753ca1f49 | ||
|
|
d52a796c39 | ||
|
|
60514d457c | ||
|
|
5bc00efe42 | ||
|
|
c45f3133bc | ||
|
|
fb47591de0 | ||
|
|
514d129c49 | ||
|
|
db843fc12d | ||
|
|
63787382d8 | ||
|
|
85d4d142d8 | ||
|
|
3cd2af41e4 | ||
|
|
b214eda4f0 | ||
|
|
0771727d41 | ||
|
|
a5d74a1876 | ||
|
|
23bf32f767 | ||
|
|
87a819edee | ||
|
|
27a1234874 | ||
|
|
51f289d1e6 | ||
|
|
d0d6dc61e8 | ||
|
|
d91c8c50d2 | ||
|
|
e20a4f84d6 | ||
|
|
bbd6f4ba8e | ||
|
|
2a951cd2f9 | ||
|
|
a538066d5a | ||
|
|
c10b0bdd50 | ||
|
|
431efc8979 | ||
|
|
2d6dbe290c | ||
|
|
c33e3e3967 | ||
|
|
71b3374bd5 | ||
|
|
de343e3cce | ||
|
|
384958ed3d | ||
|
|
1cd5beeb06 | ||
|
|
4c70e359d0 | ||
|
|
f9c3005bff | ||
|
|
9147074d8b | ||
|
|
7007bddaef | ||
|
|
2f8dc29182 | ||
|
|
6066594bbe | ||
|
|
40c0289176 | ||
|
|
acf1af0cd9 | ||
|
|
62791bdfa2 | ||
|
|
47f1218d69 | ||
|
|
1179355dab | ||
|
|
3d807132e4 | ||
|
|
42d0b4c280 | ||
|
|
d313ae7d23 | ||
|
|
28a69e25ea | ||
|
|
ad911a7ac3 | ||
|
|
5575de140d | ||
|
|
a5ce1eb1af | ||
|
|
76a78cd8bc | ||
|
|
0b25efc12a | ||
|
|
64cae087b6 | ||
|
|
b7cc59c503 | ||
|
|
7eb8d18a99 | ||
|
|
e7bf3e5e87 | ||
|
|
5aafd07b37 | ||
|
|
053f3a831d | ||
|
|
a2d2e5c047 | ||
|
|
dd3a922035 | ||
|
|
0e916c6038 | ||
|
|
87fcb63975 | ||
|
|
68b2cc5538 | ||
|
|
4dcf3697ff | ||
|
|
ea77525546 | ||
|
|
17d5a07ec2 | ||
|
|
3966b9c609 | ||
|
|
1c47fbd96b | ||
|
|
1691bdcafc | ||
|
|
6a5ef41fb3 | ||
|
|
09b6f4b00d | ||
|
|
7067b0aa28 | ||
|
|
112e731150 | ||
|
|
1336e41460 | ||
|
|
7c1b7890d3 | ||
|
|
dd0700b025 | ||
|
|
04d8e8b25f | ||
|
|
3723efcb1d | ||
|
|
054b40b6fa | ||
|
|
6773a7798f | ||
|
|
2d4c8e5945 | ||
|
|
087173c887 | ||
|
|
57835c00ad | ||
|
|
4ed886ae6e | ||
|
|
740819ef7b | ||
|
|
829230689e | ||
|
|
77ba4cc2f9 | ||
|
|
e94989fe4d | ||
|
|
c11b88061f | ||
|
|
647c5433f8 | ||
|
|
8f694072a5 | ||
|
|
9a689986c6 | ||
|
|
3174b31d96 | ||
|
|
4eb61975b7 | ||
|
|
76e26e1042 | ||
|
|
9069dfd005 | ||
|
|
2be5d2daad | ||
|
|
22cd0063e5 | ||
|
|
3d2e458a4d | ||
|
|
a57568d716 | ||
|
|
61f543cade | ||
|
|
b8771f9615 | ||
|
|
d5d4b28220 | ||
|
|
a037edaccd | ||
|
|
356bbb8351 | ||
|
|
1f0fa9318a | ||
|
|
15c1707887 | ||
|
|
9dec7aa9c1 | ||
|
|
bc3d7454e0 | ||
|
|
56901bc7c3 | ||
|
|
5c7f570b16 | ||
|
|
4f6e5fe323 | ||
|
|
7d682ffea7 | ||
|
|
cef40af209 | ||
|
|
a358449ab1 | ||
|
|
8ef6b72514 | ||
|
|
620bbabc61 | ||
|
|
7ef6aa6405 | ||
|
|
7ad1d4fd66 | ||
|
|
bf5c2bf604 | ||
|
|
b8fe70a516 | ||
|
|
06963d0fca | ||
|
|
b964901f7d | ||
|
|
b52c1d9d3a | ||
|
|
a24e12e6dd | ||
|
|
3c6cd53b23 | ||
|
|
4f69fe59c7 | ||
|
|
d2e02b7d96 | ||
|
|
a57873b710 | ||
|
|
30ce7e8a64 | ||
|
|
f0af1e5ec6 | ||
|
|
f7ca98bdc4 | ||
|
|
7df0935a51 | ||
|
|
f22ee86517 | ||
|
|
8f98c608b9 | ||
|
|
32c58f06e0 | ||
|
|
040f7b6595 | ||
|
|
d2476f0db3 | ||
|
|
952cf8f4f3 | ||
|
|
a138e47560 | ||
|
|
7d6916547f | ||
|
|
6cd7888e46 | ||
|
|
1d54358e52 | ||
|
|
4c80c473ed | ||
|
|
571a4b2654 | ||
|
|
501972bf72 | ||
|
|
99cdaff70d | ||
|
|
c36b5017b8 | ||
|
|
a4cf6bec19 | ||
|
|
0154b302ce | ||
|
|
ec99e9da81 | ||
|
|
e052b21f32 | ||
|
|
b2f0246498 | ||
|
|
c1659c79ef | ||
|
|
4a7cb3e8a8 | ||
|
|
0de40240bb | ||
|
|
d79c77caca | ||
|
|
2b106d0b3a | ||
|
|
8fef024528 | ||
|
|
6963e540db | ||
|
|
3ef526f5fa | ||
|
|
eecd22ff7b | ||
|
|
add7e8fb6b | ||
|
|
f6e09367a7 | ||
|
|
3aae15ecfb | ||
|
|
f5ad6eb18d | ||
|
|
7f1b717ac7 | ||
|
|
55bdb41632 | ||
|
|
7c06e407ec | ||
|
|
c13ad7ec47 | ||
|
|
d2094cc33d | ||
|
|
c3469aed19 | ||
|
|
232ce2b2c8 | ||
|
|
882582b307 | ||
|
|
ebaa0489b4 | ||
|
|
1a1c244dc3 | ||
|
|
320989b05d | ||
|
|
9d682a8dc1 | ||
|
|
37c3cf430d | ||
|
|
751411c40d | ||
|
|
6a46226b3a | ||
|
|
42e66aa24c | ||
|
|
5cb1f5c795 | ||
|
|
12b9c8409e | ||
|
|
e8ca590142 | ||
|
|
863dff5179 | ||
|
|
3fedd74ba2 | ||
|
|
78ffe4787f | ||
|
|
a4b4af889b | ||
|
|
d286ee98b9 | ||
|
|
42be591878 | ||
|
|
3a4c683f04 | ||
|
|
e7d29902a6 | ||
|
|
64bd756832 | ||
|
|
8642efd0d6 | ||
|
|
063393d62d | ||
|
|
7a55d06e0d | ||
|
|
6f82f7a6f6 | ||
|
|
33d213bb37 | ||
|
|
a426e396c4 | ||
|
|
fafeb69cb6 | ||
|
|
b9277bdb6a | ||
|
|
b53713d322 | ||
|
|
2f22174f21 | ||
|
|
d820215b35 | ||
|
|
ea4a03762a | ||
|
|
46ef7d1dc8 | ||
|
|
e340a8203e | ||
|
|
3459d319d1 | ||
|
|
09ec75a629 | ||
|
|
4df7868d39 | ||
|
|
bc888e05da | ||
|
|
26c7f120e6 | ||
|
|
5b7be6ee4a | ||
|
|
951351a537 | ||
|
|
0b21c485ec | ||
|
|
068a7221ce | ||
|
|
a4772a4dbc | ||
|
|
2ee91aedb1 | ||
|
|
d95447229b | ||
|
|
40ec33b604 | ||
|
|
35e3b2d555 | ||
|
|
aa9c2df9d9 | ||
|
|
f472cdf017 | ||
|
|
1dc587af1b | ||
|
|
aeb6292d0d | ||
|
|
7d91d5a619 | ||
|
|
7169bb4aa9 | ||
|
|
2db52650fc | ||
|
|
c1f62a573a | ||
|
|
08a740ff43 | ||
|
|
b67381d0dc | ||
|
|
07e9500818 | ||
|
|
c77cf82206 | ||
|
|
f8014b864e | ||
|
|
d58911fb37 | ||
|
|
b335d74565 | ||
|
|
3405fe45f4 | ||
|
|
095efec1d6 | ||
|
|
7ca6e85649 | ||
|
|
74be4fc399 | ||
|
|
3b4b1984ef | ||
|
|
6902ed178b | ||
|
|
fab9a9c547 | ||
|
|
376acbfad5 | ||
|
|
12458878c2 | ||
|
|
546434f867 | ||
|
|
ac2a1a449d | ||
|
|
e1bd49d6f3 | ||
|
|
ab94af5c6f | ||
|
|
c88ca682ef | ||
|
|
fc990e81cb | ||
|
|
e2ba16ccea | ||
|
|
76d4988d06 | ||
|
|
25ea348bd1 | ||
|
|
8ca5756339 | ||
|
|
029c171330 | ||
|
|
8f04bb36e7 | ||
|
|
b7334b4c31 | ||
|
|
a7f8404ecd | ||
|
|
6c65e14634 | ||
|
|
ddd491d45e | ||
|
|
5d78a10232 | ||
|
|
4d66e00afa | ||
|
|
531d06b824 | ||
|
|
c6a7f2f48a | ||
|
|
d4e4cbe105 | ||
|
|
41bd28fee3 | ||
|
|
a1a440c23e | ||
|
|
089e73f8d6 | ||
|
|
2c5548d25e | ||
|
|
65c2a918d4 | ||
|
|
8950ac03f8 | ||
|
|
26ef00bd3c | ||
|
|
efe3037cf5 | ||
|
|
f62c17e378 | ||
|
|
0f62178580 | ||
|
|
81c99202d3 | ||
|
|
3473b5b4d8 | ||
|
|
ba35824322 | ||
|
|
6afe7f23b0 | ||
|
|
19b27a485e | ||
|
|
ff81e809f4 | ||
|
|
fd2dd2aa23 | ||
|
|
82ed910630 | ||
|
|
90ba34e27c | ||
|
|
8ee3d639b2 | ||
|
|
0c5a792ac7 | ||
|
|
2af27ad9aa | ||
|
|
3b2b534567 | ||
|
|
3fa64fd008 | ||
|
|
b557c4c7eb | ||
|
|
0882faa2b2 | ||
|
|
3cd5eb3b3b | ||
|
|
4ff3d9d6b4 | ||
|
|
26c08b6c21 | ||
|
|
4db4149283 | ||
|
|
1ac15cd8ad | ||
|
|
b348deae3d | ||
|
|
18c71e96f8 | ||
|
|
f0f5767f15 | ||
|
|
15b7b73d7d | ||
|
|
e420b9d854 | ||
|
|
2855f61f4a | ||
|
|
2d1ebe9c72 | ||
|
|
c485a357cc | ||
|
|
5013576705 | ||
|
|
8886f8d0e6 | ||
|
|
fcb6d28d0b | ||
|
|
62402cb14b | ||
|
|
305ab1331b | ||
|
|
8212336aaa | ||
|
|
3e3dcd624f | ||
|
|
b30b3bb899 | ||
|
|
55b64e4b5e | ||
|
|
e411463442 | ||
|
|
660c6fbdaa | ||
|
|
ce6c7c6318 | ||
|
|
fa994de488 | ||
|
|
2348926995 | ||
|
|
735a816e54 | ||
|
|
a1b1b1da46 | ||
|
|
c3563c46ed | ||
|
|
0c80cd8ee9 | ||
|
|
b79f79e3aa | ||
|
|
af642a61b3 | ||
|
|
ef1aa91039 | ||
|
|
1960e2280c | ||
|
|
7c1b4daa6f | ||
|
|
7a24c346b0 | ||
|
|
64c2cf8fea | ||
|
|
81d538ce23 | ||
|
|
e327acece4 | ||
|
|
4e40377ac2 | ||
|
|
eeb1568fd5 | ||
|
|
0ba481368c | ||
|
|
38bf526fc5 | ||
|
|
bc363ea983 | ||
|
|
84f69dad19 | ||
|
|
4a13b9d57a | ||
|
|
a039749b4c | ||
|
|
15b84e142a | ||
|
|
45a8354004 | ||
|
|
c32d024071 | ||
|
|
205c27ac67 | ||
|
|
f5c2081302 | ||
|
|
e6c64e7933 | ||
|
|
a036580649 | ||
|
|
796d484b44 | ||
|
|
1f52f4c407 | ||
|
|
d567322fbc | ||
|
|
3ff1e677a1 | ||
|
|
ef325f0cf4 | ||
|
|
3d8810c928 | ||
|
|
d153974ee2 | ||
|
|
5b56cc19fb | ||
|
|
c48b22c858 | ||
|
|
65d0a49f5c | ||
|
|
6a48ca56eb | ||
|
|
a20aa42ac4 | ||
|
|
e92ee12893 | ||
|
|
5c66303ad6 | ||
|
|
27e3e9c906 | ||
|
|
f0b36a48c8 | ||
|
|
25cf88936f | ||
|
|
ae682c3e11 | ||
|
|
99994aef3e | ||
|
|
78043d1969 | ||
|
|
43e46b4cf6 | ||
|
|
9ec16c83be | ||
|
|
a24c687094 | ||
|
|
60cb2f9016 | ||
|
|
ac1a0994b6 | ||
|
|
f2cbf44ba5 | ||
|
|
dab552237e | ||
|
|
2201ba580e | ||
|
|
b7c33e3bde | ||
|
|
82980a2384 | ||
|
|
b6a30afc98 | ||
|
|
ed91f3e418 | ||
|
|
60c8d7bc7f | ||
|
|
5783c065ba | ||
|
|
adc19c987b | ||
|
|
3d38277706 | ||
|
|
64c704f0b9 | ||
|
|
69c6522734 | ||
|
|
0f8f98c8ff | ||
|
|
e384bfbdcb | ||
|
|
08e5094d7f | ||
|
|
4b3977bf00 | ||
|
|
c80ccabb0c | ||
|
|
ef5d23ebcd | ||
|
|
27b9a19be0 | ||
|
|
14175f1e77 | ||
|
|
269833af78 | ||
|
|
fca3ef06cd | ||
|
|
07a14ef8b2 | ||
|
|
21cde2888c | ||
|
|
4a7481889c | ||
|
|
0adb99b9dc | ||
|
|
36349ea0be | ||
|
|
ec3f7d1b61 | ||
|
|
f0359dd00d | ||
|
|
ef55c686bc | ||
|
|
5f7ce2041c | ||
|
|
328fcf113a | ||
|
|
24c857f1de | ||
|
|
a784e10d00 | ||
|
|
7eb6bf0397 | ||
|
|
49d6fdc036 | ||
|
|
8b35435f7c | ||
|
|
8ada751890 | ||
|
|
1a52e84874 | ||
|
|
53c5cbed23 | ||
|
|
4a81463880 | ||
|
|
09b7f5dbb1 | ||
|
|
6d7b6081ac | ||
|
|
31b7d79afe | ||
|
|
b2999e457f | ||
|
|
0f3203c312 | ||
|
|
a2edb26cd6 | ||
|
|
9bec528606 | ||
|
|
2f0e3b30a9 | ||
|
|
ff41a59f58 | ||
|
|
08f15335b5 | ||
|
|
bd36966bed | ||
|
|
f76933b149 | ||
|
|
378a074c82 | ||
|
|
c36cd31713 | ||
|
|
5e12ce1186 | ||
|
|
166aa72332 | ||
|
|
f9f6184f38 | ||
|
|
f625af9400 | ||
|
|
fc7952e7f3 | ||
|
|
cbce490e13 | ||
|
|
74a7f81d57 | ||
|
|
5b5591d8a8 | ||
|
|
c55f70218c | ||
|
|
6957ae33a9 | ||
|
|
8a5d6bba09 | ||
|
|
1d2c275fff | ||
|
|
d0fd26aa16 | ||
|
|
e20c5e9521 | ||
|
|
66203a982b | ||
|
|
b315601ce0 | ||
|
|
5f808dfbd7 | ||
|
|
0b73ca12fa | ||
|
|
03e2d0e329 | ||
|
|
182517e692 | ||
|
|
554e0a8dd0 | ||
|
|
b0f3f5784c | ||
|
|
3060d4aa1d | ||
|
|
1347d5126a | ||
|
|
5d1e1dcf4b | ||
|
|
74f5442401 | ||
|
|
c08bb0fb73 | ||
|
|
e30f065766 | ||
|
|
9dce9b45b3 | ||
|
|
60be6acf46 | ||
|
|
a5827a28d2 | ||
|
|
dcc875e41e | ||
|
|
128cf58433 | ||
|
|
7e0ca8e2f0 | ||
|
|
d79d1c69f7 | ||
|
|
a7d068abff | ||
|
|
7f931a0002 | ||
|
|
07b7c86c06 | ||
|
|
1f5c6343e6 | ||
|
|
290b615a16 | ||
|
|
57df171bc0 | ||
|
|
f08baea3dd | ||
|
|
2fb139c11b | ||
|
|
3420c8e6e0 | ||
|
|
b17bc22bb3 | ||
|
|
3adffb52e6 | ||
|
|
4df9f36841 | ||
|
|
5c9730a46c | ||
|
|
d9fcc198cf | ||
|
|
c831379436 | ||
|
|
d73ee7b70e | ||
|
|
cda2ae84b3 | ||
|
|
e7d6e0aa0c | ||
|
|
8c9fd200f9 | ||
|
|
79f118d859 | ||
|
|
7b10f91d8f | ||
|
|
3d19b4c83e | ||
|
|
79452d4693 | ||
|
|
cb13abfed0 | ||
|
|
0503f06089 | ||
|
|
f855a7d01a | ||
|
|
4c3b4b2557 | ||
|
|
79b5aa09a0 | ||
|
|
9bd6597666 | ||
|
|
6fe076b3d7 | ||
|
|
cec8aa7724 | ||
|
|
4c36a13ef2 | ||
|
|
24986abd07 | ||
|
|
8dfac376b5 | ||
|
|
e78733d975 | ||
|
|
dffba35e01 | ||
|
|
bd4ed7f719 | ||
|
|
752eaba41f | ||
|
|
ad517ce5b3 | ||
|
|
1f8413449d |
34
.cvsignore
34
.cvsignore
@@ -1,21 +1,25 @@
|
||||
.ignore
|
||||
.cvsignore
|
||||
ID
|
||||
Makefile
|
||||
a
|
||||
b
|
||||
autom4te*.cache
|
||||
confdefs.h
|
||||
config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
dist.tar.gz
|
||||
conftest.c
|
||||
conftest.log
|
||||
dox
|
||||
getgroups
|
||||
gmon.out
|
||||
rsync
|
||||
rsync-*
|
||||
rsync.aux
|
||||
rsync.dvi
|
||||
rsync.log
|
||||
tech_report.aux
|
||||
tech_report.dvi
|
||||
tech_report.log
|
||||
tech_report.ps
|
||||
test
|
||||
|
||||
shconfig
|
||||
testdir
|
||||
tests-dont-exist
|
||||
testtmp
|
||||
testtmp.*
|
||||
tls
|
||||
trimslash
|
||||
t_unsafe
|
||||
wildtest
|
||||
getfsdev
|
||||
.rsync-filter
|
||||
|
||||
11
COPYING
11
COPYING
@@ -2,7 +2,7 @@
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -291,7 +291,7 @@ convey 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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -305,14 +305,15 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
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.
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
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:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision 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.
|
||||
|
||||
187
Doxyfile
Normal file
187
Doxyfile
Normal file
@@ -0,0 +1,187 @@
|
||||
# Doxyfile 1.2.15
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# General configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = rsync
|
||||
PROJECT_NUMBER = HEAD
|
||||
OUTPUT_DIRECTORY = dox
|
||||
OUTPUT_LANGUAGE = English
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = NO
|
||||
STRIP_FROM_PATH = *source
|
||||
INTERNAL_DOCS = YES
|
||||
STRIP_CODE_COMMENTS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
SHORT_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = YES
|
||||
VERBATIM_HEADERS = YES
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
INHERIT_DOCS = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 8
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
ALIASES =
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
SHOW_USED_FILES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = NO
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = .
|
||||
FILE_PATTERNS = *.c \
|
||||
*.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = proto.h \
|
||||
zlib \
|
||||
popt
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 3
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 3
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = NO
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
HAVE_DOT = YES
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
TEMPLATE_RELATIONS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
||||
CGI_NAME = search.cgi
|
||||
CGI_URL =
|
||||
DOC_URL =
|
||||
DOC_ABSPATH =
|
||||
BIN_ABSPATH = /usr/local/bin/
|
||||
EXT_DOC_PATHS =
|
||||
63
INSTALL
Normal file
63
INSTALL
Normal file
@@ -0,0 +1,63 @@
|
||||
To build and install rsync:
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
# make install
|
||||
|
||||
You may set the installation directory and other parameters by options
|
||||
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.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.
|
||||
|
||||
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
|
||||
---------
|
||||
|
||||
Under packaging you will find .spec files for several distributions.
|
||||
The .spec file in packaging/lsb can be used for Linux systems that
|
||||
adhere to the Linux Standards Base (e.g., RedHat and others).
|
||||
|
||||
HP-UX NOTES
|
||||
-----------
|
||||
|
||||
The HP-UX 10.10 "bundled" C compiler seems not to be able to cope with
|
||||
ANSI C. You may see this error message in config.log if ./configure
|
||||
fails:
|
||||
|
||||
(Bundled) cc: "configure", line 2162: error 1705: Function prototypes are an ANSI feature.
|
||||
|
||||
Install gcc or HP's "ANSI/C Compiler".
|
||||
|
||||
MAC OSX NOTES
|
||||
-------------
|
||||
|
||||
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 started to support
|
||||
IPv6 in 10.2 (Jaguar). If your build fails, try again after running
|
||||
configure with --disable-ipv6.
|
||||
|
||||
IBM AIX NOTES
|
||||
-------------
|
||||
|
||||
IBM AIX has a largefile problem with mkstemp. See IBM PR-51921.
|
||||
The workaround is to append the below to config.h
|
||||
#ifdef _LARGE_FILES
|
||||
#undef HAVE_SECURE_MKSTEMP
|
||||
#endif
|
||||
162
Makefile.in
162
Makefile.in
@@ -9,65 +9,113 @@ mandir=@mandir@
|
||||
LIBS=@LIBS@
|
||||
CC=@CC@
|
||||
CFLAGS=@CFLAGS@
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
EXEEXT=@EXEEXT@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
|
||||
INSTALLCMD=@INSTALL@
|
||||
INSTALLMAN=@INSTALL@
|
||||
|
||||
srcdir=@srcdir@
|
||||
VPATH=$(srcdir)
|
||||
SHELL=/bin/sh
|
||||
|
||||
VERSION=@VERSION@
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o
|
||||
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
|
||||
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.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/inffast.o zlib/inflate.o zlib/inftrees.o \
|
||||
zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.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 chmod.o
|
||||
OBJS3=progress.o pipe.o
|
||||
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
|
||||
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ)
|
||||
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/compat.o lib/snprintf.o lib/permstring.o
|
||||
|
||||
# Programs we must have to run the test cases
|
||||
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
|
||||
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
|
||||
|
||||
# Objects for CHECK_PROGS to clean
|
||||
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:
|
||||
@OBJ_SAVE@
|
||||
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< @CC_SHOBJ_FLAG@
|
||||
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
|
||||
@OBJ_RESTORE@
|
||||
|
||||
all: rsync
|
||||
|
||||
man: rsync.1 rsyncd.conf.5
|
||||
all: rsync$(EXEEXT)
|
||||
|
||||
install: all
|
||||
-mkdir -p ${bindir}
|
||||
${INSTALLCMD} -m 755 rsync ${bindir}
|
||||
-mkdir -p ${mandir}/man1
|
||||
-mkdir -p ${mandir}/man5
|
||||
${INSTALLCMD} -m 644 $(srcdir)/rsync.1 ${mandir}/man1
|
||||
${INSTALLCMD} -m 644 $(srcdir)/rsyncd.conf.5 ${mandir}/man5
|
||||
-mkdir -p ${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) INSTALLCMD='$(INSTALLCMD) -s' install
|
||||
$(MAKE) INSTALL_STRIP='-s' install
|
||||
|
||||
rsync: $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
|
||||
rsync$(EXEEXT): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
rsync.1: rsync.yo
|
||||
yodl2man -o rsync.1 rsync.yo
|
||||
$(OBJS): $(HEADERS)
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.yo
|
||||
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
|
||||
tls$(EXEEXT): $(TLS_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
|
||||
|
||||
getgroups$(EXEEXT): getgroups.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getgroups.o $(LIBS)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
gen:
|
||||
$(MAKE) -C $(srcdir) -f prepare-source.mak gen
|
||||
|
||||
man:
|
||||
$(MAKE) -C $(srcdir) -f prepare-source.mak man
|
||||
|
||||
proto:
|
||||
cat *.c | awk -f mkproto.awk > proto.h
|
||||
$(MAKE) -C $(srcdir) -f prepare-source.mak proto.h
|
||||
|
||||
clean:
|
||||
rm -f *~ $(OBJS) rsync
|
||||
clean: cleantests
|
||||
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS)
|
||||
|
||||
cleantests:
|
||||
rm -rf ./testtmp*
|
||||
|
||||
# We try to delete built files from both the source and build
|
||||
# directories, just in case somebody previously configured things in
|
||||
# the source directory.
|
||||
distclean: clean
|
||||
rm -f config.h config.cache config.status Makefile
|
||||
rm -f Makefile config.h config.status
|
||||
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
|
||||
|
||||
rm -f config.cache config.log
|
||||
rm -f $(srcdir)/config.cache $(srcdir)/config.log
|
||||
|
||||
rm -f shconfig $(srcdir)/shconfig
|
||||
|
||||
# this target is really just for my use. It only works on a limited
|
||||
# range of machines and is used to produce a list of potentially
|
||||
@@ -75,4 +123,60 @@ distclean: clean
|
||||
finddead:
|
||||
nm *.o */*.o |grep 'U ' | awk '{print $$2}' | sort -u > nmused.txt
|
||||
nm *.o */*.o |grep 'T ' | awk '{print $$3}' | sort -u > nmfns.txt
|
||||
comm -13 nmused.txt nmfns.txt
|
||||
comm -13 nmused.txt nmfns.txt
|
||||
|
||||
# 'check' is the GNU name, 'test' is the name for everybody else :-)
|
||||
.PHONY: check test
|
||||
|
||||
test: check
|
||||
|
||||
|
||||
# There seems to be no standard way to specify some variables as
|
||||
# exported from a Makefile apart from listing them like this.
|
||||
|
||||
# This depends on building rsync; if we need any helper programs it
|
||||
# should depend on them too.
|
||||
|
||||
# We try to run the scripts with POSIX mode on, in the hope that will
|
||||
# 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
|
||||
|
||||
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
|
||||
wildtest$(EXEEXT): wildtest.o lib/compat.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o @BUILD_POPT@ $(LIBS)
|
||||
|
||||
# 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)
|
||||
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
|
||||
|
||||
# Run the SPLINT (Secure Programming Lint) tool. <www.splint.org>
|
||||
.PHONY: splint
|
||||
splint:
|
||||
splint +unixlib +gnuextensions -weak rsync.c
|
||||
|
||||
|
||||
rsync.dvi: doc/rsync.texinfo
|
||||
texi2dvi -o $@ $<
|
||||
|
||||
rsync.ps: rsync.dvi
|
||||
dvips -ta4 -o $@ $<
|
||||
|
||||
rsync.pdf: doc/rsync.texinfo
|
||||
texi2dvi -o $@ --pdf $<
|
||||
|
||||
|
||||
doxygen:
|
||||
cd $(srcdir) && rm dox/html/* && doxygen
|
||||
|
||||
# for maintainers only
|
||||
doxygen-upload:
|
||||
rsync -avzv $(srcdir)/dox/html/ --delete \
|
||||
samba.org:/home/httpd/html/rsync/doxygen/head/
|
||||
|
||||
320
NEWS
Normal file
320
NEWS
Normal file
@@ -0,0 +1,320 @@
|
||||
NEWS for rsync 2.6.7 (11 Mar 2006)
|
||||
|
||||
Protocol: 29 (unchanged)
|
||||
Changes since 2.6.6:
|
||||
|
||||
OUTPUT CHANGES:
|
||||
|
||||
- The letter 'D' in the itemized output was being used for both devices
|
||||
(character or block) as well as other special files (such as fifos and
|
||||
named sockets). This has changed to separate non-device special files
|
||||
under the 'S' designation (e.g. "cS+++++++ path/fifo"). See also the
|
||||
"--specials" option, below.
|
||||
|
||||
- The way rsync escapes unreadable characters has changed. First, rsync
|
||||
now has support for recognizing valid multibyte character sequences in
|
||||
your current locale, allowing it to escape fewer characters than before
|
||||
for a locale such as UTF-8. Second, it now uses an escape idiom of
|
||||
"\#123", which is the literal string "\#" followed by exactly 3 octal
|
||||
digits. Rsync no longer doubles a backslash character in a filename
|
||||
(e.g. it used to output "foo\\bar" when copying "foo\bar") -- now it only
|
||||
escapes a backslash that is followed by a hash-sign and 3 digits (0-9)
|
||||
(e.g. it will output "foo\#134#789" when copying "foo\#789"). See also
|
||||
the --8-bit-output (-8) option, mentioned below.
|
||||
|
||||
Script writers: the local rsync is the one that outputs escaped names,
|
||||
so if you need to support unescaping of filenames for older rsyncs, I'd
|
||||
suggest that you parse the output of "rsync --version" and only use the
|
||||
old unescaping rules for 2.6.5 and 2.6.6.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Fixed a really old bug that caused --checksum (-c) to checksum all the
|
||||
files encountered during the delete scan (ouch).
|
||||
|
||||
- Fixed a potential hang in a remote generator: when the receiver gets a
|
||||
read-error on the socket, it now signals the generator about this so that
|
||||
the generator does not try to send any of the terminating error messages
|
||||
to the client (avoiding a potential hang in some setups).
|
||||
|
||||
- Made hard-links work with symlinks and devices again.
|
||||
|
||||
- If the sender gets an early EOF reading a source file, we propagate this
|
||||
error to the receiver so that it can discard the file and try requesting
|
||||
it again (which is the existing behavior for other kinds of read errors).
|
||||
|
||||
- If a device-file/special-file changes permissions, rsync now updates the
|
||||
permissions without recreating the file.
|
||||
|
||||
- If the user specifies a remote-host for both the source and destination,
|
||||
we now output a syntax error rather than trying to open the destination
|
||||
hostspec as a filename.
|
||||
|
||||
- When --inplace creates a new destination file, rsync now creates it with
|
||||
permissions 0600 instead of 0000 -- this makes restarting possible when
|
||||
the transfer gets interrupted in the middle of sending a new file.
|
||||
|
||||
- Reject the combination of --inplace and --sparse since the sparse-output
|
||||
algorithm doesn't work when overwriting existing data.
|
||||
|
||||
- Fixed the directory name in the error that is output when pop_dir()
|
||||
fails.
|
||||
|
||||
- Really fixed the parsing of a "!" entry in .cvsignore files this time.
|
||||
|
||||
- If the generator gets a stat() error on a file, output it (this used to
|
||||
require at least -vv for the error to be seen).
|
||||
|
||||
- If waitpid() fails or the child rsync didn't exit cleanly, we now handle
|
||||
the exit status properly and generate a better error.
|
||||
|
||||
- Fixed some glitches in the double-verbose output when using --copy-dest,
|
||||
--link-dest, or --compare-dest. Also improved how the verbose output
|
||||
handles hard-links (within the transfer) that had an up-to-date alternate
|
||||
"dest" file, and copied files (via --copy-dest).
|
||||
|
||||
- Fixed the matching of the dont-compress items (e.g. *.gz) against files
|
||||
that have a path component containing a slash.
|
||||
|
||||
- If code reading a filter/exclude file an EINTR error, rsync now clears
|
||||
the error flag on the file handle so it can keep on reading.
|
||||
|
||||
- If --relative is active, the sending side cleans up trailing "/" or "/."
|
||||
suffixes to avoid triggering a bug in older rsync versions. Also, we now
|
||||
reject a ".." dir if it would be sent as a relative dir.
|
||||
|
||||
- If a non-directory is in the way of a directory and rsync is run with
|
||||
--dry-run and --delete, rsync no longer complains about not being able
|
||||
to opendir() the not-yet present directory.
|
||||
|
||||
- When --list-only is used and a non-existent local destination dir was
|
||||
also specified as a destination, rsync no longer generates a warning
|
||||
about being unable to create the missing directory.
|
||||
|
||||
- Fixed some problems with --relative --no-implied-dirs when the
|
||||
destination directory did not yet exist: we can now create a symlink or
|
||||
device when it is the first thing in the missing dir, and --fuzzy no
|
||||
longer complains about being unable to open the missing dir.
|
||||
|
||||
- Fixed a bug where the --copy-links option would not affect implied
|
||||
directories without --copy-unsafe-links (see --relative).
|
||||
|
||||
- Got rid of the need for --force to be used in some circumstances with
|
||||
--delete-after (making it consistent with --delete-before/-during).
|
||||
|
||||
- Rsync now ignores the SIGXFSZ signal, just in case your OS sends this
|
||||
when a file is too large (rsync handles the write error).
|
||||
|
||||
- Fixed a bug in the Proxy-Authorization header's base64-encoded value: it
|
||||
was not properly padded with trailing '=' chars. This only affects a
|
||||
user that need to use a password-authenticated proxy for an outgoing
|
||||
daemon-rsync connection.
|
||||
|
||||
- If we're transferring an empty directory to a new name, rsync no longer
|
||||
forces S_IWUSR if it wasn't already set, nor does it accidentally leave
|
||||
it set.
|
||||
|
||||
- Fixed a bug in the debug output (-vvvvv) that could mention the wrong
|
||||
checksum for the current file offset.
|
||||
|
||||
- Rsync no longer allows a single directory to be copied over a non-
|
||||
directory destination arg.
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Added the --append option that makes rsync append data onto files that
|
||||
are longer on the source than the destination (this includes new files).
|
||||
|
||||
- Added the --min-size=SIZE option to exclude small files from the
|
||||
transfer.
|
||||
|
||||
- Added the --compress-level option to allow you to set how aggressive
|
||||
rsync's compression should be (this option implies --compress).
|
||||
|
||||
- Enhanced the parsing of the SIZE value for --min-size and --max-size to
|
||||
allow easy entry of multiples of 1000 (instead of just multiples of 1024)
|
||||
and off-by-one values too (e.g. --max-size=8mb-1).
|
||||
|
||||
- Added the --8-bit-output (-8) option, which tells rsync to avoid escaping
|
||||
high-bit characters that it thinks are unreadable in the current locale.
|
||||
|
||||
- The new option --human-readable (-h) changes the output of --progress,
|
||||
--stats, and the end-of-run summary to be easier to read. If repeated,
|
||||
the units become powers of 1024 instead of powers of 1000. (The old
|
||||
meaning of -h, as a shorthand for --help, still works as long as you
|
||||
just use it on its own, as in "rsync -h".)
|
||||
|
||||
- If lutimes() and/or lchmod() are around, use them to allow the
|
||||
preservation of attributes on symlinks.
|
||||
|
||||
- The --link-dest option now affects symlinks and devices (when possible).
|
||||
|
||||
- Added two config items to the rsyncd.conf parsing: "pre-xfer exec" and
|
||||
"post-xfer exec". These allow a command to be specified on a per-module
|
||||
basis that will be run before and/or after a daemon-mode transfer. (See
|
||||
the man page for a list of the environment variables that are set with
|
||||
information about the transfer.)
|
||||
|
||||
- When using the --relative option, you can now insert a dot dir in
|
||||
the source path to indicate where the replication of the source dirs
|
||||
should start. For example, if you specify a source path of
|
||||
rsync://host/module/foo/bar/./baz/dir with -R, rsync will now only
|
||||
replicate the "baz/dir" part of the source path (note: a trailing
|
||||
dot dir is unaffected unless it also has a trailing slash).
|
||||
|
||||
- Added some new --no-FOO options that make it easier to override unwanted
|
||||
implied or default options. For example, "-a --no-o" (aka "--archive
|
||||
--no-owner") can be used to turn off the preservation of file ownership
|
||||
that is implied by -a.
|
||||
|
||||
- Added the --chmod=MODE option that allows the destination permissions to
|
||||
be changed from the source permissions. E.g. --chmod=g+w,o-rwx
|
||||
|
||||
- Added the "incoming chmod" and "outgoing chmod" daemon options that allow
|
||||
a module to specify what permissions changes should be applied to all
|
||||
files copied to and from the daemon.
|
||||
|
||||
- Allow the --temp-dir option to be specified when starting a daemon, which
|
||||
sets the default temporary directory for incoming files.
|
||||
|
||||
- If --delete is combined with --dirs without --recursive, rsync will now
|
||||
delete in any directory whose content is being synchronized.
|
||||
|
||||
- If --backup is combined with --delete without --backup-dir (and without
|
||||
--delete-excluded), we add a "protect" filter-rule to ensure that files
|
||||
with the backup suffix are not deleted.
|
||||
|
||||
- The file-count stats that are output by --progress were improved to
|
||||
better indicate what the numbers mean. For instance, the output:
|
||||
"(xfer#5, to-check=8383/9999)" indicates that this was the fifth file
|
||||
to be transferred, and we still need to check 8383 more files out of
|
||||
a total of 9999.
|
||||
|
||||
- The include/exclude code now allows a dir/*** directive (with 3 trailing
|
||||
stars) to match both the dir itself as well as all the content below the
|
||||
dir (dir/** would not match the dir).
|
||||
|
||||
- Added the --prune-empty-dirs (-m) option that makes the receiving rsync
|
||||
discard empty chains of directories from the file-list. This makes it
|
||||
easier to selectively copy files from a source hierarchy and end up with
|
||||
just the directories needed to hold the resulting files.
|
||||
|
||||
- If the --itemize-changes (-i) option is repeated, rsync now includes
|
||||
unchanged files in the itemized output (similar to -vv, but without all
|
||||
the other verbose messages that can get in the way). Of course, the
|
||||
client must be version 2.6.7 for this to work, but the remote rsync only
|
||||
needs to be 2.6.7 if you're pushing files.
|
||||
|
||||
- Added the --specials option to tell rsync to copy non-device special
|
||||
files (which rsync now attempts even as a normal user). The --devices
|
||||
option now requests the copying of just devices (character and block).
|
||||
The -D option still requests both (e.g. --devices and --specials), -a
|
||||
still implies -D, and non-root users still get a silent downgrade that
|
||||
omits device copying.
|
||||
|
||||
- Added the --super option to make the receiver always attempt super-user
|
||||
activities. This is useful for systems that allow things such as devices
|
||||
to be created or ownership to be set without being UID 0, and is also
|
||||
useful for someone who wants to ensure that errors will be output if the
|
||||
receiving rsync isn't being run as root.
|
||||
|
||||
- Added the --sockopts option for those few who want to customize the TCP
|
||||
options used to contact a daemon rsync.
|
||||
|
||||
- Added a way for the --temp-dir option to be combined with a partial-dir
|
||||
setting that lets rsync avoid non-atomic updates (for those times when
|
||||
--temp-dir is not being used because space is tight).
|
||||
|
||||
- A new support script, files-to-excludes, will transform a list of files
|
||||
into a set of include/exclude directives that will copy those files.
|
||||
|
||||
- A new option, --executability (-E) can be used to preserve just the
|
||||
execute bit on files, for those times when using the --perms option is
|
||||
not desired.
|
||||
|
||||
- The daemon now logs each connection and also each module-list request
|
||||
that it receives.
|
||||
|
||||
- New log-format options: %M (modtime), %U (uid), %G (gid), and %B
|
||||
(permission bits, e.g. "rwxr-xrwt").
|
||||
|
||||
- The --dry-run option no longer forces the enabling of --verbose.
|
||||
|
||||
- The --remove-sent-files option now does a better job of incrementally
|
||||
removing the sent files on the sending side (older versions tended to
|
||||
clump up all the removals at the end).
|
||||
|
||||
- A daemon now supersedes its minimal SIGCHLD handler with the standard
|
||||
PID-remembering version after forking. This ensures that the generator
|
||||
can get the child-exit status from the receiver.
|
||||
|
||||
- Use of the --bwlimit option no longer interferes with the remote rsync
|
||||
sending error messages about invalid/refused options.
|
||||
|
||||
- Rsync no longer returns a usage error when used with one local source arg
|
||||
and no destination: this now implies the --list-only option, just like
|
||||
the comparable situation with a remote source arg.
|
||||
|
||||
- Added the --copy-dirlinks option, a more limited version of --copy-links.
|
||||
|
||||
- Various documentation improvements, including: a better synopsis, some
|
||||
improved examples, a better discussion of the presence and absence of
|
||||
--perms (including how it interacts with the new --executability and
|
||||
--chmod options), an extended discussion of --temp-dir, an improved
|
||||
discussion of --partial-dir, a better description of rsync's pattern
|
||||
matching characters, an improved --no-implied-dirs section, and the
|
||||
documenting of what the --stats option outputs.
|
||||
|
||||
- Various new and updated diffs in the patches dir, including: acls.diff,
|
||||
xattrs.diff, atimes.diff, detect-renamed.diff, and slp.diff.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- We now use sigaction() and sigprocmask() if possible, and fall back on
|
||||
signal() if not. Using sigprocmask() ensures that rsync enables all the
|
||||
signals that it needs, just in case it was started in a masked state.
|
||||
|
||||
- Some buffer sizes were expanded a bit, particularly on systems where
|
||||
MAXPATHLEN is overly small (e.g. cygwin).
|
||||
|
||||
- If io_printf() tries to format more data than fits in the buffer, exit
|
||||
with an error instead of transmitting a truncated buffer.
|
||||
|
||||
- If a va_copy macro is defined, lib/snprintf.c will use it when defining
|
||||
the VA_COPY macro.
|
||||
|
||||
- Reduced the amount of stack memory needed for each level of directory
|
||||
recursion by nearly MAXPATHLEN bytes.
|
||||
|
||||
- The wildmatch function was extended to allow an array of strings to be
|
||||
supplied as the string to match. This allows the exclude code to do less
|
||||
string copying.
|
||||
|
||||
- Got rid of the safe_fname() function (and all the myriad calls) and
|
||||
replaced it with a new function in the log.c code that filters all the
|
||||
output going to the terminal.
|
||||
|
||||
- Unified the f_name() and the f_name_to() functions.
|
||||
|
||||
- Improved the hash-table code the sender uses to handle checksums to make
|
||||
it use slightly less memory and run just a little faster.
|
||||
|
||||
DEVELOPER RELATED:
|
||||
|
||||
- The diffs in the patches dir now require "patch -p1 <DIFF" instead of
|
||||
the previous -p0. Also, the version included in the release tar now
|
||||
affect generated files (e.g. configure, rsync.1, proto.h, etc.), so
|
||||
it is no longer necessary to run autoconf and/or yodl unless you're
|
||||
applying a patch that was checked out from CVS.
|
||||
|
||||
- Several diffs in the patches dir now use the proper --enable-FOO
|
||||
configure option instead of --with-FOO to turn on the inclusion of
|
||||
the newly patched feature.
|
||||
|
||||
- There is a new script, "prepare-source" than can be used to update the
|
||||
various generated files (proto.h, configure, etc.) even before configure
|
||||
has created the Makefile (this is mainly useful when patching the source
|
||||
with a patch that doesn't affect generated files).
|
||||
|
||||
- The testsuite now sets HOME so that it won't be affected by a file such
|
||||
as ~/.popt.
|
||||
120
README
120
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
|
||||
@@ -18,83 +18,25 @@ this package.
|
||||
USAGE
|
||||
-----
|
||||
|
||||
Basically you use rsync just like rcp, but rsync has many additional options.
|
||||
Basically you use rsync just like rcp, but rsync has many additional
|
||||
options. To get a complete list of supported options type
|
||||
|
||||
Here is a brief description of rsync usage:
|
||||
|
||||
Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
|
||||
or rsync [OPTION]... [USER@]HOST:SRC DEST
|
||||
or rsync [OPTION]... SRC [SRC]... DEST
|
||||
or rsync [OPTION]... [USER@]HOST::SRC [DEST]
|
||||
or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
|
||||
or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
|
||||
SRC on single-colon remote HOST will be expanded by remote shell
|
||||
SRC on server remote HOST may contain shell wildcards or multiple
|
||||
sources separated by space as long as they have same top-level
|
||||
|
||||
Options
|
||||
-v, --verbose increase verbosity
|
||||
-q, --quiet decrease verbosity
|
||||
-c, --checksum always checksum
|
||||
-a, --archive archive mode
|
||||
-r, --recursive recurse into directories
|
||||
-R, --relative use relative path names
|
||||
-b, --backup make backups (default ~ suffix)
|
||||
--suffix=SUFFIX override backup suffix
|
||||
-u, --update update only (don't overwrite newer files)
|
||||
-l, --links preserve soft links
|
||||
-L, --copy-links treat soft links like regular files
|
||||
--copy-unsafe-links copy links outside the source tree
|
||||
--safe-links ignore links outside the destination tree
|
||||
-H, --hard-links preserve hard links
|
||||
-p, --perms preserve permissions
|
||||
-o, --owner preserve owner (root only)
|
||||
-g, --group preserve group
|
||||
-D, --devices preserve devices (root only)
|
||||
-t, --times preserve times
|
||||
-S, --sparse handle sparse files efficiently
|
||||
-n, --dry-run show what would have been transferred
|
||||
-W, --whole-file copy whole files, no incremental checks
|
||||
-x, --one-file-system don't cross filesystem boundaries
|
||||
-B, --block-size=SIZE checksum blocking size (default 700)
|
||||
-e, --rsh=COMMAND specify rsh replacement
|
||||
--rsync-path=PATH specify path to rsync on the remote machine
|
||||
-C, --cvs-exclude auto ignore files in the same way CVS does
|
||||
--delete delete files that don't exist on the sending side
|
||||
--delete-excluded also delete excluded files on the receiving side
|
||||
--partial keep partially transferred files
|
||||
--force force deletion of directories even if not empty
|
||||
--numeric-ids don't map uid/gid values by user/group name
|
||||
--timeout=TIME set IO timeout in seconds
|
||||
-I, --ignore-times don't exclude files that match length and time
|
||||
--size-only only use file size when determining if a file should be transferred
|
||||
-T --temp-dir=DIR create temporary files in directory DIR
|
||||
--compare-dest=DIR also compare destination files relative to DIR
|
||||
-z, --compress compress file data
|
||||
--exclude=PATTERN exclude files matching PATTERN
|
||||
--exclude-from=FILE exclude patterns listed in FILE
|
||||
--include=PATTERN don't exclude files matching PATTERN
|
||||
--include-from=FILE don't exclude patterns listed in FILE
|
||||
--version print version number
|
||||
--daemon run as a rsync daemon
|
||||
--config=FILE specify alternate rsyncd.conf file
|
||||
--port=PORT specify alternate rsyncd port number
|
||||
--stats give some file transfer stats
|
||||
--progress show progress during transfer
|
||||
--log-format=FORMAT log file transfers using specified format
|
||||
--password-file=FILE get password from FILE
|
||||
-h, --help show this help screen
|
||||
rsync --help
|
||||
|
||||
and see the manual for more information.
|
||||
|
||||
|
||||
SETUP
|
||||
-----
|
||||
|
||||
Rsync uses rsh or ssh for communication. It does not need to be setuid
|
||||
and requires no special privileges for installation. It does not
|
||||
require a inetd entry or a daemon. You must, however, have a working
|
||||
rsh or ssh system. Using ssh is recommended for its security
|
||||
features.
|
||||
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 ssh or rsh system. Using ssh is
|
||||
recommended for its security features.
|
||||
|
||||
Alternatively, rsync can run in `daemon' mode, listening on a socket.
|
||||
This is generally used for public file distribution, although
|
||||
authentication and access control are available.
|
||||
|
||||
To install rsync, first run the "configure" script. This will create a
|
||||
Makefile and config.h appropriate for your system. Then type
|
||||
@@ -125,8 +67,7 @@ There is a mailing list for the discussion of rsync and its
|
||||
applications. It is open to anyone to join. I will announce new
|
||||
versions on this list.
|
||||
|
||||
To join the mailing list send mail to listproc@samba.org with
|
||||
no subject and a body of "subscribe rsync Your Name".
|
||||
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
|
||||
|
||||
@@ -135,15 +76,21 @@ BUG REPORTS
|
||||
-----------
|
||||
|
||||
If you have web access then please look at
|
||||
http://rsync.samba.org/rsync/
|
||||
|
||||
This will give you access to the bug tracking system used by the
|
||||
developers of rsync and will allow you to look at other bug reports or
|
||||
submit a new bug report.
|
||||
http://rsync.samba.org/
|
||||
|
||||
If you don't have web access then mail bug reports to
|
||||
rsync-bugs@samba.org or (if you think it will be of interest to lots
|
||||
of people) send it to 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
|
||||
internet for the error message you've received, or looking in the
|
||||
mailing list archives at
|
||||
|
||||
http://mail-archive.com/rsync@lists.samba.org/
|
||||
|
||||
To send a bug report, follow the instructions on the bug-tracking
|
||||
page of the web site.
|
||||
|
||||
If you don't have web access, email your bug report to
|
||||
rsync@lists.samba.org.
|
||||
|
||||
|
||||
CVS TREE
|
||||
@@ -153,10 +100,10 @@ If you want to get the very latest version of rsync direct from the
|
||||
source code repository then you can use anonymous cvs. You will need a
|
||||
recent version of cvs then use the following commands:
|
||||
|
||||
cvs -d :pserver:cvs@cvs.samba.org:/cvsroot login
|
||||
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot login
|
||||
Password: cvs
|
||||
|
||||
cvs -d :pserver:cvs@cvs.samba.org:/cvsroot co rsync
|
||||
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot co rsync
|
||||
|
||||
Look at the cvs documentation for more details.
|
||||
|
||||
@@ -164,11 +111,12 @@ Look at the cvs documentation for more details.
|
||||
COPYRIGHT
|
||||
---------
|
||||
|
||||
Rsync was written by Andrew Tridgell and Paul Mackerras, and is
|
||||
available under the Gnu Public License.
|
||||
rsync was originally written by Andrew Tridgell and has been improved
|
||||
by many developers around the world. rsync may be used, modified and
|
||||
redistributed only under the terms of the GNU General Public License,
|
||||
found in the file COPYING in this distribution, or at
|
||||
|
||||
tridge@samba.org
|
||||
paulus@cs.anu.edu.au
|
||||
http://www.fsf.org/licenses/gpl.html
|
||||
|
||||
|
||||
AVAILABILITY
|
||||
|
||||
554
TODO
Normal file
554
TODO
Normal file
@@ -0,0 +1,554 @@
|
||||
-*- indented-text -*-
|
||||
|
||||
FEATURES ------------------------------------------------------------
|
||||
Use chroot only if supported
|
||||
Allow supplementary groups in rsyncd.conf 2002/04/09
|
||||
Handling IPv6 on old machines
|
||||
Other IPv6 stuff
|
||||
Add ACL support 2001/12/02
|
||||
proxy authentication 2002/01/23
|
||||
SOCKS 2002/01/23
|
||||
FAT support
|
||||
--diff david.e.sewell 2002/03/15
|
||||
Add daemon --no-fork option
|
||||
Create more granular verbosity 2003/05/15
|
||||
|
||||
DOCUMENTATION --------------------------------------------------------
|
||||
Keep list of open issues and todos on the web site
|
||||
Perhaps redo manual as SGML
|
||||
|
||||
LOGGING --------------------------------------------------------------
|
||||
Memory accounting
|
||||
Improve error messages
|
||||
Better statistics Rasmus 2002/03/08
|
||||
Perhaps flush stdout like syslog
|
||||
Log child death on signal
|
||||
verbose output David Stein 2001/12/20
|
||||
internationalization
|
||||
|
||||
DEVELOPMENT --------------------------------------------------------
|
||||
Handling duplicate names
|
||||
Use generic zlib 2002/02/25
|
||||
TDB 2002/03/12
|
||||
Splint 2002/03/12
|
||||
|
||||
PERFORMANCE ----------------------------------------------------------
|
||||
Traverse just one directory at a time
|
||||
Allow skipping MD4 file_sum 2002/04/08
|
||||
Accelerate MD4
|
||||
|
||||
TESTING --------------------------------------------------------------
|
||||
Torture test
|
||||
Cross-test versions 2001/08/22
|
||||
Test on kernel source
|
||||
Test large files
|
||||
Create mutator program for testing
|
||||
Create configure option to enable dangerous tests
|
||||
Create pipe program for testing
|
||||
Create test makefile target for some tests
|
||||
|
||||
RELATED PROJECTS -----------------------------------------------------
|
||||
rsyncsh
|
||||
http://rsync.samba.org/rsync-and-debian/
|
||||
rsyncable gzip patch
|
||||
rsyncsplit as alternative to real integration with gzip?
|
||||
reverse rsync over HTTP Range
|
||||
|
||||
|
||||
|
||||
FEATURES ------------------------------------------------------------
|
||||
|
||||
|
||||
Use chroot only if supported
|
||||
|
||||
If the platform doesn't support it, then don't even try.
|
||||
|
||||
If running as non-root, then don't fail, just give a warning.
|
||||
(There was a thread about this a while ago?)
|
||||
|
||||
http://lists.samba.org/pipermail/rsync/2001-August/thread.html
|
||||
http://lists.samba.org/pipermail/rsync/2001-September/thread.html
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Allow supplementary groups in rsyncd.conf 2002/04/09
|
||||
|
||||
Perhaps allow supplementary groups to be specified in rsyncd.conf;
|
||||
then make the first one the primary gid and all the rest be
|
||||
supplementary gids.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Handling IPv6 on old machines
|
||||
|
||||
The KAME IPv6 patch is nice in theory but has proved a bit of a
|
||||
nightmare in practice. The basic idea of their patch is that rsync
|
||||
is rewritten to use the new getaddrinfo()/getnameinfo() interface,
|
||||
rather than gethostbyname()/gethostbyaddr() as in rsync 2.4.6.
|
||||
Systems that don't have the new interface are handled by providing
|
||||
our own implementation in lib/, which is selectively linked in.
|
||||
|
||||
The problem with this is that it is really hard to get right on
|
||||
platforms that have a half-working implementation, so redefining
|
||||
these functions clashes with system headers, and leaving them out
|
||||
breaks. This affects at least OSF/1, RedHat 5, and Cobalt, which
|
||||
are moderately improtant.
|
||||
|
||||
Perhaps the simplest solution would be to have two different files
|
||||
implementing the same interface, and choose either the new or the
|
||||
old API. This is probably necessary for systems that e.g. have
|
||||
IPv6, but gethostbyaddr() can't handle it. The Linux manpage claims
|
||||
this is currently the case.
|
||||
|
||||
In fact, our internal sockets interface (things like
|
||||
open_socket_out(), etc) is much narrower than the getaddrinfo()
|
||||
interface, and so probably simpler to get right. In addition, the
|
||||
old code is known to work well on old machines.
|
||||
|
||||
We could drop the rather large lib/getaddrinfo files.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Other IPv6 stuff
|
||||
|
||||
Implement suggestions from http://www.kame.net/newsletter/19980604/
|
||||
and ftp://ftp.iij.ad.jp/pub/RFC/rfc2553.txt
|
||||
|
||||
If a host has multiple addresses, then listen try to connect to all
|
||||
in order until we get through. (getaddrinfo may return multiple
|
||||
addresses.) This is kind of implemented already.
|
||||
|
||||
Possibly also when starting as a server we may need to listen on
|
||||
multiple passive addresses. This might be a bit harder, because we
|
||||
may need to select on all of them. Hm.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
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.
|
||||
NOTE: there is a patch that implements this in the "patches" subdir.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
proxy authentication 2002/01/23
|
||||
|
||||
Allow RSYNC_PROXY to be http://user:pass@proxy.foo:3128/, and do
|
||||
HTTP Basic Proxy-Authentication.
|
||||
|
||||
Multiple schemes are possible, up to and including the insanity that
|
||||
is NTLM, but Basic probably covers most cases.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
SOCKS 2002/01/23
|
||||
|
||||
Add --with-socks, and then perhaps a command-line option to put them
|
||||
on or off. This might be more reliable than LD_PRELOAD hacks.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
FAT support
|
||||
|
||||
rsync to a FAT partition on a Unix machine doesn't work very well at
|
||||
the moment. I think we get errors about invalid filenames and
|
||||
perhaps also trying to do atomic renames.
|
||||
|
||||
I guess the code to do this is currently #ifdef'd on Windows;
|
||||
perhaps we ought to intelligently fall back to it on Unix too.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
--diff david.e.sewell 2002/03/15
|
||||
|
||||
Allow people to specify the diff command. (Might want to use wdiff,
|
||||
gnudiff, etc.)
|
||||
|
||||
Just diff the temporary file with the destination file, and delete
|
||||
the tmp file rather than moving it into place.
|
||||
|
||||
Interaction with --partial.
|
||||
|
||||
Security interactions with daemon mode?
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
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
|
||||
parent exits.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Create more granular verbosity 2003/05/15
|
||||
|
||||
Control output with the --report option.
|
||||
|
||||
The option takes as a single argument (no whitespace) a
|
||||
comma delimited lists of keywords.
|
||||
|
||||
This would separate debugging from "logging" as well as
|
||||
fine grained selection of statistical reporting and what
|
||||
actions are logged.
|
||||
|
||||
http://lists.samba.org/archive/rsync/2003-May/006059.html
|
||||
|
||||
-- --
|
||||
|
||||
DOCUMENTATION --------------------------------------------------------
|
||||
|
||||
|
||||
Keep list of open issues and todos on the web site
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Perhaps redo manual as SGML
|
||||
|
||||
The man page is getting rather large, and there is more information
|
||||
that ought to be added.
|
||||
|
||||
TexInfo source is probably a dying format.
|
||||
|
||||
Linuxdoc looks like the most likely contender. I know DocBook is
|
||||
favoured by some people, but it's so bloody verbose, even with emacs
|
||||
support.
|
||||
|
||||
-- --
|
||||
|
||||
LOGGING --------------------------------------------------------------
|
||||
|
||||
|
||||
Memory accounting
|
||||
|
||||
At exit, show how much memory was used for the file list, etc.
|
||||
|
||||
Also we do a wierd exponential-growth allocation in flist.c. I'm
|
||||
not sure this makes sense with modern mallocs. At any rate it will
|
||||
make us allocate a huge amount of memory for large file lists.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Improve error messages
|
||||
|
||||
If we hang or get SIGINT, then explain where we were up to. Perhaps
|
||||
have a static buffer that contains the current function name, or
|
||||
some kind of description of what we were trying to do. This is a
|
||||
little easier on people than needing to run strace/truss.
|
||||
|
||||
"The dungeon collapses! You are killed." Rather than "unexpected
|
||||
eof" give a message that is more detailed if possible and also more
|
||||
helpful.
|
||||
|
||||
If we get an error writing to a socket, then we should perhaps
|
||||
continue trying to read to see if an error message comes across
|
||||
explaining why the socket is closed. I'm not sure if this would
|
||||
work, but it would certainly make our messages more helpful.
|
||||
|
||||
What happens if a directory is missing -x attributes. Do we lose
|
||||
our load? (Debian #28416) Probably fixed now, but a test case would
|
||||
be good.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Better statistics Rasmus 2002/03/08
|
||||
|
||||
<Rasmus>
|
||||
hey, how about an rsync option that just gives you the
|
||||
summary without the list of files? And perhaps gives
|
||||
more information like the number of new files, number
|
||||
of changed, deleted, etc. ?
|
||||
|
||||
<mbp>
|
||||
nice idea there is --stats but at the moment it's very
|
||||
tridge-oriented rather than user-friendly it would be
|
||||
nice to improve it that would also work well with
|
||||
--dryrun
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Perhaps flush stdout like syslog
|
||||
|
||||
Perhaps flush stdout after each filename, so that people trying to
|
||||
monitor progress in a log file can do so more easily. See
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48108
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Log child death on signal
|
||||
|
||||
If a child of the rsync daemon dies with a signal, we should notice
|
||||
that when we reap it and log a message.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
verbose output David Stein 2001/12/20
|
||||
|
||||
At end of transfer, show how many files were or were not transferred
|
||||
correctly.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
internationalization
|
||||
|
||||
Change to using gettext(). Probably need to ship this for platforms
|
||||
that don't have it.
|
||||
|
||||
Solicit translations.
|
||||
|
||||
Does anyone care? Before we bother modifying the code, we ought to
|
||||
get the manual translated first, because that's possibly more useful
|
||||
and at any rate demonstrates desire.
|
||||
|
||||
-- --
|
||||
|
||||
DEVELOPMENT --------------------------------------------------------
|
||||
|
||||
Handling duplicate names
|
||||
|
||||
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).
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Use generic zlib 2002/02/25
|
||||
|
||||
Perhaps don't use our own zlib.
|
||||
|
||||
Advantages:
|
||||
|
||||
- will automatically be up to date with bugfixes in zlib
|
||||
|
||||
- can leave it out for small rsync on e.g. recovery disks
|
||||
|
||||
- can use a shared library
|
||||
|
||||
- avoids people breaking rsync by trying to do this themselves and
|
||||
messing up
|
||||
|
||||
Should we ship zlib for systems that don't have it, or require
|
||||
people to install it separately?
|
||||
|
||||
Apparently this will make us incompatible with versions of rsync
|
||||
that use the patched version of rsync. Probably the simplest way to
|
||||
do this is to just disable gzip (with a warning) when talking to old
|
||||
versions.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
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
|
||||
annotations as necessary. Keep track of the number of warnings
|
||||
found initially, and see how many of them are real bugs, or real
|
||||
security bugs. Knowing the percentage of likely hits would be
|
||||
really interesting for other projects.
|
||||
|
||||
-- --
|
||||
|
||||
PERFORMANCE ----------------------------------------------------------
|
||||
|
||||
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
|
||||
send the file checksum. If we're doing a local transfer, then
|
||||
calculating MD4 checksums uses 90% of CPU and is unlikely to be
|
||||
useful.
|
||||
|
||||
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).
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Accelerate MD4
|
||||
|
||||
Perhaps borrow an assembler MD4 from someone?
|
||||
|
||||
Make sure we call MD4 with properly-sized blocks whenever possible
|
||||
to avoid copying into the residue region?
|
||||
|
||||
-- --
|
||||
|
||||
TESTING --------------------------------------------------------------
|
||||
|
||||
Torture test
|
||||
|
||||
Something that just keeps running rsync continuously over a data set
|
||||
likely to generate problems.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Cross-test versions 2001/08/22
|
||||
|
||||
Part of the regression suite should be making sure that we
|
||||
don't break backwards compatibility: old clients vs new
|
||||
servers and so on. Ideally we would test both up and down
|
||||
from the current release to all old versions.
|
||||
|
||||
Run current rsync versions against significant past releases.
|
||||
|
||||
We might need to omit broken old versions, or versions in which
|
||||
particular functionality is broken
|
||||
|
||||
It might be sufficient to test downloads from well-known public
|
||||
rsync servers running different versions of rsync. This will give
|
||||
some testing and also be the most common case for having different
|
||||
versions and not being able to upgrade.
|
||||
|
||||
The new --protocol option may help in this.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Test on kernel source
|
||||
|
||||
Download all versions of kernel; unpack, sync between them. Also
|
||||
sync between uncompressed tarballs. Compare directories after
|
||||
transfer.
|
||||
|
||||
Use local mode; ssh; daemon; --whole-file and --no-whole-file.
|
||||
|
||||
Use awk to pull out the 'speedup' number for each transfer. Make
|
||||
sure it is >= x.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Test large files
|
||||
|
||||
Sparse and non-sparse
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Create mutator program for testing
|
||||
|
||||
Insert bytes, delete bytes, swap blocks, ...
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Create configure option to enable dangerous tests
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Create pipe program for testing
|
||||
|
||||
Create pipe program that makes slow/jerky connections for
|
||||
testing Versions of read() and write() that corrupt the
|
||||
stream, or abruptly fail
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
Create test makefile target for some tests
|
||||
|
||||
Separate makefile target to run rough tests -- or perhaps
|
||||
just run them every time?
|
||||
|
||||
-- --
|
||||
|
||||
RELATED PROJECTS -----------------------------------------------------
|
||||
|
||||
rsyncsh
|
||||
|
||||
Write a small emulation of interactive ftp as a Pythonn program
|
||||
that calls rsync. Commands such as "cd", "ls", "ls *.c" etc map
|
||||
fairly directly into rsync commands: it just needs to remember the
|
||||
current host, directory and so on. We can probably even do
|
||||
completion of remote filenames.
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
http://rsync.samba.org/rsync-and-debian/
|
||||
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
rsyncable gzip patch
|
||||
|
||||
Exhaustive, tortuous testing
|
||||
|
||||
Cleanups?
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
rsyncsplit as alternative to real integration with gzip?
|
||||
|
||||
-- --
|
||||
|
||||
|
||||
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/
|
||||
|
||||
-- --
|
||||
|
||||
247
access.c
247
access.c
@@ -26,57 +26,192 @@
|
||||
|
||||
static int match_hostname(char *host, char *tok)
|
||||
{
|
||||
if (!host || !*host) return 0;
|
||||
return (fnmatch(tok, host, 0) == 0);
|
||||
if (!host || !*host)
|
||||
return 0;
|
||||
return wildmatch(tok, host);
|
||||
}
|
||||
|
||||
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])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void make_mask(char *mask, int plen, int addrlen)
|
||||
{
|
||||
int w, b;
|
||||
|
||||
w = plen >> 3;
|
||||
b = plen & 0x7;
|
||||
|
||||
if (w)
|
||||
memset(mask, 0xff, w);
|
||||
if (w < addrlen)
|
||||
mask[w] = 0xff & (0xff<<(8-b));
|
||||
if (w+1 < addrlen)
|
||||
memset(mask+w+1, 0, addrlen-w-1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int match_address(char *addr, char *tok)
|
||||
{
|
||||
char *p;
|
||||
unsigned long a, t, mask = (unsigned long)~0;
|
||||
struct addrinfo hints, *resa, *rest;
|
||||
int gai;
|
||||
int ret = 0;
|
||||
int addrlen = 0;
|
||||
#ifdef HAVE_STRTOL
|
||||
long int bits;
|
||||
#else
|
||||
int bits;
|
||||
#endif
|
||||
char mask[16];
|
||||
char *a = NULL, *t = NULL;
|
||||
unsigned int len;
|
||||
|
||||
if (!addr || !*addr) return 0;
|
||||
|
||||
if (!isdigit(tok[0])) return 0;
|
||||
if (!addr || !*addr)
|
||||
return 0;
|
||||
|
||||
p = strchr(tok,'/');
|
||||
if (p) *p = 0;
|
||||
|
||||
a = inet_addr(addr);
|
||||
t = inet_addr(tok);
|
||||
|
||||
if (p) {
|
||||
*p = '/';
|
||||
}
|
||||
*p = '\0';
|
||||
len = p - tok;
|
||||
} else
|
||||
len = strlen(tok);
|
||||
|
||||
if (t == INADDR_NONE) {
|
||||
rprintf(FERROR,"malformed address %s\n", tok);
|
||||
/* Fail quietly if tok is a hostname (not an address) */
|
||||
if (strspn(tok, ".0123456789") != len
|
||||
#ifdef INET6
|
||||
&& strchr(tok, ':') == NULL
|
||||
#endif
|
||||
) {
|
||||
if (p)
|
||||
*p = '/';
|
||||
return 0;
|
||||
}
|
||||
|
||||
a = ntohl(a);
|
||||
t = ntohl(t);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
#ifdef AI_NUMERICHOST
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
#endif
|
||||
|
||||
if (p) {
|
||||
if (strchr(p+1,'.')) {
|
||||
mask = inet_addr(p+1);
|
||||
if (mask == INADDR_NONE) {
|
||||
rprintf(FERROR,"malformed mask in %s\n", tok);
|
||||
return 0;
|
||||
}
|
||||
mask = ntohl(mask);
|
||||
} else {
|
||||
int bits = atoi(p+1);
|
||||
if (bits <= 0 || bits > 32) {
|
||||
rprintf(FERROR,"malformed mask in %s\n", tok);
|
||||
return 0;
|
||||
}
|
||||
mask &= (mask << (32-bits));
|
||||
}
|
||||
if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
|
||||
if (p)
|
||||
*p = '/';
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((a&mask) == (t&mask));
|
||||
gai = getaddrinfo(tok, NULL, &hints, &rest);
|
||||
if (p)
|
||||
*p++ = '/';
|
||||
if (gai != 0) {
|
||||
rprintf(FLOG, "error matching address %s: %s\n",
|
||||
tok, gai_strerror(gai));
|
||||
freeaddrinfo(resa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rest->ai_family != resa->ai_family) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch(resa->ai_family) {
|
||||
case PF_INET:
|
||||
a = (char *)&((struct sockaddr_in *)resa->ai_addr)->sin_addr;
|
||||
t = (char *)&((struct sockaddr_in *)rest->ai_addr)->sin_addr;
|
||||
addrlen = 4;
|
||||
|
||||
break;
|
||||
|
||||
#ifdef INET6
|
||||
case PF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6a, *sin6t;
|
||||
|
||||
sin6a = (struct sockaddr_in6 *)resa->ai_addr;
|
||||
sin6t = (struct sockaddr_in6 *)rest->ai_addr;
|
||||
|
||||
a = (char *)&sin6a->sin6_addr;
|
||||
t = (char *)&sin6t->sin6_addr;
|
||||
|
||||
addrlen = 16;
|
||||
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
if (sin6t->sin6_scope_id &&
|
||||
sin6a->sin6_scope_id != sin6t->sin6_scope_id) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
rprintf(FLOG, "unknown family %u\n", rest->ai_family);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bits = -1;
|
||||
if (p) {
|
||||
if (inet_pton(resa->ai_addr->sa_family, p, mask) <= 0) {
|
||||
#ifdef HAVE_STRTOL
|
||||
char *ep = NULL;
|
||||
#else
|
||||
unsigned char *pp;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRTOL
|
||||
bits = strtol(p, &ep, 10);
|
||||
if (!*p || *ep) {
|
||||
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(FLOG, "malformed mask in %s\n", tok);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
bits = atoi(p);
|
||||
#endif
|
||||
if (bits == 0) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
if (bits < 0 || bits > (addrlen << 3)) {
|
||||
rprintf(FLOG, "malformed mask in %s\n", tok);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bits = 128;
|
||||
}
|
||||
|
||||
if (bits >= 0)
|
||||
make_mask(mask, bits, addrlen);
|
||||
|
||||
ret = match_binary(a, t, mask, addrlen);
|
||||
|
||||
out:
|
||||
freeaddrinfo(resa);
|
||||
freeaddrinfo(rest);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int access_match(char *list, char *addr, char *host)
|
||||
@@ -84,12 +219,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;
|
||||
@@ -102,29 +239,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;
|
||||
}
|
||||
|
||||
12
acconfig.h
12
acconfig.h
@@ -1,12 +0,0 @@
|
||||
#undef HAVE_BROKEN_READDIR
|
||||
#undef HAVE_ERRNO_DECL
|
||||
#undef HAVE_LONGLONG
|
||||
#undef HAVE_OFF64_T
|
||||
#undef HAVE_REMSH
|
||||
#undef HAVE_UNSIGNED_CHAR
|
||||
#undef HAVE_UTIMBUF
|
||||
#undef ino_t
|
||||
#undef HAVE_CONNECT
|
||||
#undef HAVE_SHORT_INO_T
|
||||
#undef HAVE_GETOPT_LONG
|
||||
#undef REPLACE_INET_NTOA
|
||||
48
aclocal.m4
vendored
48
aclocal.m4
vendored
@@ -21,3 +21,51 @@ AC_DEFUN(AC_VALIDATE_CACHE_SYSTEM_TYPE, [
|
||||
ac_cv_build_system_type="$build"
|
||||
ac_cv_target_system_type="$target"
|
||||
])
|
||||
|
||||
dnl Check for socklen_t: historically on BSD it is an int, and in
|
||||
dnl POSIX 1g it is a type of its own, but some platforms use different
|
||||
dnl types for the argument to getsockopt, getpeername, etc. So we
|
||||
dnl have to test to find something that will work.
|
||||
|
||||
dnl This is no good, because passing the wrong pointer on C compilers is
|
||||
dnl likely to only generate a warning, not an error. We don't call this at
|
||||
dnl the moment.
|
||||
|
||||
AC_DEFUN([TYPE_SOCKLEN_T],
|
||||
[
|
||||
AC_CHECK_TYPE([socklen_t], ,[
|
||||
AC_MSG_CHECKING([for socklen_t equivalent])
|
||||
AC_CACHE_VAL([rsync_cv_socklen_t_equiv],
|
||||
[
|
||||
# Systems have either "struct sockaddr *" or
|
||||
# "void *" as the second argument to getpeername
|
||||
rsync_cv_socklen_t_equiv=
|
||||
for arg2 in "struct sockaddr" void; do
|
||||
for t in int size_t unsigned long "unsigned long"; do
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int getpeername (int, $arg2 *, $t *);
|
||||
],[
|
||||
$t len;
|
||||
getpeername(0,0,&len);
|
||||
],[
|
||||
rsync_cv_socklen_t_equiv="$t"
|
||||
break
|
||||
])
|
||||
done
|
||||
done
|
||||
|
||||
if test "x$rsync_cv_socklen_t_equiv" = x; then
|
||||
AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
|
||||
fi
|
||||
])
|
||||
AC_MSG_RESULT($rsync_cv_socklen_t_equiv)
|
||||
AC_DEFINE_UNQUOTED(socklen_t, $rsync_cv_socklen_t_equiv,
|
||||
[type to use in place of socklen_t if not defined])],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/socket.h>])
|
||||
])
|
||||
|
||||
|
||||
|
||||
300
authenticate.c
300
authenticate.c
@@ -1,16 +1,17 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
|
||||
/* -*- 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.
|
||||
@@ -19,20 +20,20 @@
|
||||
/* support rsync authentication */
|
||||
#include "rsync.h"
|
||||
|
||||
extern char *password_file;
|
||||
|
||||
/***************************************************************************
|
||||
encode a buffer using base64 - simple and slow algorithm. null terminates
|
||||
the result.
|
||||
***************************************************************************/
|
||||
static void base64_encode(char *buf, int len, char *out)
|
||||
void base64_encode(char *buf, int len, char *out, int pad)
|
||||
{
|
||||
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
int bit_offset, byte_offset, idx, i;
|
||||
unsigned char *d = (unsigned char *)buf;
|
||||
int bytes = (len*8 + 5)/6;
|
||||
|
||||
memset(out, 0, bytes+1);
|
||||
|
||||
for (i=0;i<bytes;i++) {
|
||||
for (i = 0; i < bytes; i++) {
|
||||
byte_offset = (i*6)/8;
|
||||
bit_offset = (i*6)%8;
|
||||
if (bit_offset < 3) {
|
||||
@@ -45,242 +46,271 @@ static 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 */
|
||||
/* Generate a challenge buffer and return it base64-encoded. */
|
||||
static void gen_challenge(char *addr, char *challenge)
|
||||
{
|
||||
char input[32];
|
||||
char md4_out[MD4_SUM_LENGTH];
|
||||
struct timeval tv;
|
||||
|
||||
memset(input, 0, sizeof(input));
|
||||
memset(input, 0, sizeof input);
|
||||
|
||||
strlcpy((char *)input, addr, 17);
|
||||
gettimeofday(&tv, NULL);
|
||||
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);
|
||||
sum_end(md4_out);
|
||||
|
||||
base64_encode(md4_out, MD4_SUM_LENGTH, challenge, 0);
|
||||
}
|
||||
|
||||
|
||||
/* return the secret for a user from the sercret file. maximum length
|
||||
is len. null terminate it */
|
||||
/* 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, char *user, char *secret, int len)
|
||||
{
|
||||
char *fname = lp_secrets_file(module);
|
||||
int fd, found=0;
|
||||
char line[MAXPATHLEN];
|
||||
char *p, *pass=NULL;
|
||||
STRUCT_STAT st;
|
||||
int ok = 1;
|
||||
extern int am_root;
|
||||
int fd, ok = 1;
|
||||
char ch, *p;
|
||||
|
||||
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) {
|
||||
rprintf(FERROR,"stat(%s) : %s\n", fname, strerror(errno));
|
||||
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 (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. */
|
||||
p = secret;
|
||||
while (len > 0) {
|
||||
if (read(fd, p, 1) != 1 || *p == '\n')
|
||||
break;
|
||||
if (*p == '\r')
|
||||
continue;
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
*p = '\0';
|
||||
close(fd);
|
||||
|
||||
strlcpy(secret, pass, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *getpassf(char *filename)
|
||||
{
|
||||
char buffer[100];
|
||||
int len=0;
|
||||
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;
|
||||
char *envpw = getenv("RSYNC_PASSWORD");
|
||||
|
||||
if (!filename) return NULL;
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
if ( (fd=open(filename,O_RDONLY)) == -1) {
|
||||
rprintf(FERROR,"could not open password file \"%s\"\n",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) {
|
||||
rprintf(FERROR,"stat(%s) : %s\n", filename, strerror(errno));
|
||||
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 ( (len=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 */
|
||||
/* Generate an MD4 hash created from the combination of the password
|
||||
* and the challenge string and return it base64-encoded. */
|
||||
static void generate_hash(char *in, char *challenge, char *out)
|
||||
{
|
||||
char buf[16];
|
||||
char buf[MD4_SUM_LENGTH];
|
||||
|
||||
sum_init();
|
||||
sum_init(0);
|
||||
sum_update(in, strlen(in));
|
||||
sum_update(challenge, strlen(challenge));
|
||||
sum_end(buf);
|
||||
|
||||
base64_encode(buf, 16, out);
|
||||
base64_encode(buf, MD4_SUM_LENGTH, 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 fd, 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, char *host, char *addr,
|
||||
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[MD4_SUM_LENGTH*2];
|
||||
char line[BIGPATHBUFLEN];
|
||||
char secret[512];
|
||||
char pass2[MD4_SUM_LENGTH*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(fd,"%s%s\n", leader, b64_challenge);
|
||||
io_printf(f_out, "%s%s\n", leader, challenge);
|
||||
|
||||
if (!read_line(fd, line, sizeof(line)-1)) {
|
||||
if (!read_line(f_in, line, sizeof line - 1)
|
||||
|| (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 (strcmp(tok, user) == 0) 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)
|
||||
{
|
||||
char *pass;
|
||||
char pass2[30];
|
||||
extern char *password_file;
|
||||
char pass2[MD4_SUM_LENGTH*2];
|
||||
|
||||
if (!user || !*user) return;
|
||||
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.
|
||||
*
|
||||
* Andrew Klein says that getpassphrase() is present
|
||||
* on Solaris and reads up to 256 characters.
|
||||
*
|
||||
* OpenBSD has a readpassphrase() that might be more suitable.
|
||||
*/
|
||||
pass = getpass("Password: ");
|
||||
}
|
||||
|
||||
if (!pass || !*pass) {
|
||||
if (!pass)
|
||||
pass = "";
|
||||
}
|
||||
|
||||
generate_hash(pass, challenge, pass2);
|
||||
io_printf(fd, "%s %s\n", user, pass2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
279
backup.c
Normal file
279
backup.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
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 */
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
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_specials;
|
||||
extern int preserve_links;
|
||||
extern int safe_symlinks;
|
||||
|
||||
/* make a complete pathname for backup file */
|
||||
char *get_backup_name(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)
|
||||
{
|
||||
int rename_errno;
|
||||
char *fnamebak = get_backup_name(fname);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Create a directory given an absolute path, perms based upon another directory
|
||||
path
|
||||
****************************************************************************/
|
||||
static int make_bak_dir(char *fullpath)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
char *rel = fullpath + backup_dir_len;
|
||||
char *end = rel + strlen(rel);
|
||||
char *p = end;
|
||||
|
||||
while (strncmp(fullpath, "./", 2) == 0)
|
||||
fullpath += 2;
|
||||
|
||||
/* Try to find an existing dir, starting from the deepest dir. */
|
||||
while (1) {
|
||||
if (--p == fullpath) {
|
||||
p += strlen(p);
|
||||
goto failure;
|
||||
}
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
if (mkdir_defmode(fullpath) == 0)
|
||||
break;
|
||||
if (errno != ENOENT) {
|
||||
rsyserr(FERROR, errno,
|
||||
"make_bak_dir mkdir %s failed",
|
||||
full_fname(fullpath));
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make all the dirs that we didn't find on the way here. */
|
||||
while (1) {
|
||||
if (p >= rel) {
|
||||
/* Try to transfer the directory settings of the
|
||||
* actual dir that the files are coming from. */
|
||||
if (do_stat(rel, &st) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"make_bak_dir stat %s failed",
|
||||
full_fname(rel));
|
||||
} else {
|
||||
do_lchown(fullpath, st.st_uid, st.st_gid);
|
||||
do_chmod(fullpath, st.st_mode);
|
||||
}
|
||||
}
|
||||
*p = '/';
|
||||
p += strlen(p);
|
||||
if (p == end)
|
||||
break;
|
||||
if (mkdir_defmode(fullpath) < 0) {
|
||||
rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
|
||||
full_fname(fullpath));
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
while (p != end) {
|
||||
*p = '/';
|
||||
p += strlen(p);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* robustly move a file, creating new directory structures if necessary */
|
||||
static int robust_move(char *src, char *dst)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
struct file_struct *file;
|
||||
char *buf;
|
||||
int kept = 0;
|
||||
int ret_code;
|
||||
|
||||
/* return if no file to keep */
|
||||
if (do_lstat(fname, &st) < 0)
|
||||
return 1;
|
||||
|
||||
if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
|
||||
return 1; /* the file could have disappeared */
|
||||
|
||||
if (!(buf = get_backup_name(fname)))
|
||||
return 0;
|
||||
|
||||
/* Check to see if this is a device file, or link */
|
||||
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|
||||
|| (preserve_specials && IS_SPECIAL(file->mode))) {
|
||||
do_unlink(buf);
|
||||
if (do_mknod(buf, file->mode, file->u.rdev) < 0
|
||||
&& (errno != ENOENT || make_bak_dir(buf) < 0
|
||||
|| do_mknod(buf, file->mode, file->u.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);
|
||||
}
|
||||
|
||||
if (!kept && S_ISDIR(file->mode)) {
|
||||
/* make an empty directory */
|
||||
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);
|
||||
}
|
||||
kept = 1;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
if (!kept && preserve_links && S_ISLNK(file->mode)) {
|
||||
if (safe_symlinks && unsafe_symlink(file->u.link, buf)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
|
||||
full_fname(buf), file->u.link);
|
||||
}
|
||||
kept = 1;
|
||||
} else {
|
||||
do_unlink(buf);
|
||||
if (do_symlink(file->u.link, buf) < 0
|
||||
&& (errno != ENOENT || make_bak_dir(buf) < 0
|
||||
|| do_symlink(file->u.link, buf) < 0)) {
|
||||
rsyserr(FERROR, errno, "link %s -> \"%s\"",
|
||||
full_fname(buf),
|
||||
file->u.link);
|
||||
}
|
||||
do_unlink(fname);
|
||||
kept = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!kept && !S_ISREG(file->mode)) {
|
||||
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
|
||||
fname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* move to keep tree if a file */
|
||||
if (!kept) {
|
||||
if (robust_move(fname, buf) != 0) {
|
||||
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
|
||||
full_fname(fname), buf);
|
||||
} else if (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_file_attrs(buf, file, NULL, 0);
|
||||
free(file);
|
||||
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "backed up %s to %s\n",
|
||||
fname, buf);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* main backup switch routine */
|
||||
int make_backup(char *fname)
|
||||
{
|
||||
if (backup_dir)
|
||||
return keep_backup(fname);
|
||||
return make_simple_backup(fname);
|
||||
}
|
||||
216
batch.c
Normal file
216
batch.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Weiss 1/1999
|
||||
Batch utilities for rsync.
|
||||
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "zlib/zlib.h"
|
||||
#include <time.h>
|
||||
|
||||
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 char *batch_name;
|
||||
|
||||
extern struct filter_list_struct filter_list;
|
||||
|
||||
static int tweaked_compress_level;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
int i, flags;
|
||||
|
||||
#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
|
||||
|
||||
/* 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;
|
||||
}
|
||||
write_int(fd, flags);
|
||||
}
|
||||
|
||||
void read_stream_flags(int fd)
|
||||
{
|
||||
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_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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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
|
||||
write_arg(fd, p);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
140
checksum.c
140
checksum.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
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.
|
||||
@@ -23,24 +23,24 @@ int csum_length=2; /* initial value */
|
||||
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
int checksum_seed = 0;
|
||||
extern int remote_version;
|
||||
extern int checksum_seed;
|
||||
extern int protocol_version;
|
||||
|
||||
/*
|
||||
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,35 +49,43 @@ 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;
|
||||
int32 i;
|
||||
static char *buf1;
|
||||
static int len1;
|
||||
static int32 len1;
|
||||
struct mdfour m;
|
||||
|
||||
if (len > len1) {
|
||||
if (buf1) free(buf1);
|
||||
buf1 = (char *)malloc(len+4);
|
||||
if (buf1)
|
||||
free(buf1);
|
||||
buf1 = new_array(char, len+4);
|
||||
len1 = len;
|
||||
if (!buf1) out_of_memory("get_checksum2");
|
||||
if (!buf1)
|
||||
out_of_memory("get_checksum2");
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
if (len - i > 0) {
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
@@ -88,27 +96,29 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
struct map_struct *buf;
|
||||
int fd;
|
||||
OFF_T len = size;
|
||||
char tmpchunk[CSUM_CHUNK];
|
||||
struct mdfour m;
|
||||
|
||||
memset(sum,0,csum_length);
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) return;
|
||||
|
||||
buf = map_file(fd,size);
|
||||
|
||||
|
||||
memset(sum,0,MD4_SUM_LENGTH);
|
||||
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1)
|
||||
return;
|
||||
|
||||
buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
|
||||
|
||||
mdfour_begin(&m);
|
||||
|
||||
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);
|
||||
mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
|
||||
CSUM_CHUNK);
|
||||
}
|
||||
|
||||
if (len - i > 0) {
|
||||
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
|
||||
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
|
||||
}
|
||||
/* 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 *)map_ptr(buf, i, len-i), len-i);
|
||||
|
||||
mdfour_result(&m, (uchar *)sum);
|
||||
|
||||
@@ -117,64 +127,58 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
}
|
||||
|
||||
|
||||
void checksum_init(void)
|
||||
{
|
||||
if (remote_version >= 14)
|
||||
csum_length = 2; /* adaptive */
|
||||
else
|
||||
csum_length = SUM_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sumresidue;
|
||||
static int32 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);
|
||||
sumresidue = 0;
|
||||
SIVAL(s, 0, seed);
|
||||
sum_update(s, 4);
|
||||
}
|
||||
|
||||
void sum_update(char *p,int len)
|
||||
/**
|
||||
* Feed data into an MD4 accumulator, md. The results may be
|
||||
* retrieved using sum_end(). md is used for different purposes at
|
||||
* different points during execution.
|
||||
*
|
||||
* @todo Perhaps get rid of md and just pass in the address each time.
|
||||
* Very slightly clearer and slower.
|
||||
**/
|
||||
void sum_update(char *p, int32 len)
|
||||
{
|
||||
int i;
|
||||
if (len + sumresidue < CSUM_CHUNK) {
|
||||
memcpy(sumrbuf+sumresidue, p, len);
|
||||
memcpy(sumrbuf + 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(sumrbuf + sumresidue, p, i);
|
||||
mdfour_update(&md, (uchar *)sumrbuf, 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(sumrbuf, p, sumresidue);
|
||||
}
|
||||
|
||||
void sum_end(char *sum)
|
||||
{
|
||||
if (sumresidue) {
|
||||
if (sumresidue || protocol_version >= 27)
|
||||
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
|
||||
}
|
||||
|
||||
mdfour_result(&md, (uchar *)sum);
|
||||
}
|
||||
|
||||
205
chmod.c
Normal file
205
chmod.c
Normal file
@@ -0,0 +1,205 @@
|
||||
#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;
|
||||
}
|
||||
173
cleanup.c
173
cleanup.c
@@ -1,17 +1,19 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
/* -*- 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.
|
||||
@@ -19,47 +21,143 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* handling the cleanup when a transfer is interrupted is tricky when
|
||||
--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;
|
||||
extern int io_error;
|
||||
extern int keep_partial;
|
||||
extern int log_got_error;
|
||||
extern char *partial_dir;
|
||||
|
||||
#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
|
||||
* TCP RST sent by a Winsock-based system when the close() occurs.
|
||||
**/
|
||||
void close_all(void)
|
||||
{
|
||||
#ifdef SHUTDOWN_ALL_SOCKETS
|
||||
int max_fd;
|
||||
int fd;
|
||||
int ret;
|
||||
STRUCT_STAT st;
|
||||
|
||||
max_fd = sysconf(_SC_OPEN_MAX) - 1;
|
||||
for (fd = max_fd; fd >= 0; fd--) {
|
||||
if ((ret = do_fstat(fd, &st)) == 0) {
|
||||
if (is_a_socket(fd))
|
||||
ret = shutdown(fd, 2);
|
||||
ret = close(fd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @file cleanup.c
|
||||
*
|
||||
* Code for handling interrupted transfers. Depending on the @c
|
||||
* --partial option, we may either delete the temporary file, or go
|
||||
* ahead and overwrite the destination. This second behaviour only
|
||||
* occurs if we've sent literal data and therefore hopefully made
|
||||
* progress on the transfer.
|
||||
**/
|
||||
|
||||
/**
|
||||
* Set to True once literal data has been sent across the link for the
|
||||
* current file. (????)
|
||||
*
|
||||
* Handling the cleanup when a transfer is interrupted is tricky when
|
||||
* --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;
|
||||
|
||||
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_pid = 0;
|
||||
static int cleanup_fd_r, cleanup_fd_w;
|
||||
static pid_t cleanup_pid = 0;
|
||||
|
||||
pid_t cleanup_child_pid = -1;
|
||||
|
||||
/**
|
||||
* Eventually calls exit(), passing @p code, therefore does not return.
|
||||
*
|
||||
* @param code one of the RERR_* codes from errcode.h.
|
||||
**/
|
||||
void _exit_cleanup(int code, const char *file, int line)
|
||||
{
|
||||
extern int keep_partial;
|
||||
int ocode = code;
|
||||
static int inside_cleanup = 0;
|
||||
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
if (inside_cleanup > 10) {
|
||||
/* prevent the occasional infinite recursion */
|
||||
return;
|
||||
}
|
||||
inside_cleanup++;
|
||||
|
||||
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);
|
||||
SIGACTION(SIGUSR1, SIG_IGN);
|
||||
SIGACTION(SIGUSR2, SIG_IGN);
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
|
||||
code, file, line);
|
||||
}
|
||||
io_flush();
|
||||
if (cleanup_fname)
|
||||
do_unlink(cleanup_fname);
|
||||
if (code) {
|
||||
kill_all(SIGUSR1);
|
||||
}
|
||||
if ((cleanup_pid != 0) && (cleanup_pid == (int) getpid())) {
|
||||
char *pidf = lp_pid_file();
|
||||
if (pidf && *pidf) {
|
||||
unlink(lp_pid_file());
|
||||
|
||||
if (cleanup_child_pid != -1) {
|
||||
int status;
|
||||
if (wait_process(cleanup_child_pid, &status, WNOHANG)
|
||||
== cleanup_child_pid) {
|
||||
status = WEXITSTATUS(status);
|
||||
if (status > code)
|
||||
code = status;
|
||||
}
|
||||
}
|
||||
|
||||
if (code) log_exit(code, file, line);
|
||||
if (cleanup_got_literal && cleanup_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,
|
||||
cleanup_file, 0, !partial_dir);
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
if (code == 0) {
|
||||
if (io_error & IOERR_DEL_LIMIT)
|
||||
code = RERR_DEL_LIMIT;
|
||||
if (io_error & IOERR_VANISHED)
|
||||
code = RERR_VANISHED;
|
||||
if (io_error & IOERR_GENERAL || log_got_error)
|
||||
code = RERR_PARTIAL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -71,17 +169,16 @@ void cleanup_disable(void)
|
||||
|
||||
|
||||
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_fname = fname ? fnametmp : NULL;
|
||||
cleanup_new_fname = fname;
|
||||
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(int pid)
|
||||
void cleanup_set_pid(pid_t pid)
|
||||
{
|
||||
cleanup_pid = pid;
|
||||
}
|
||||
|
||||
346
clientname.c
Normal file
346
clientname.c
Normal file
@@ -0,0 +1,346 @@
|
||||
/* -*- 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.
|
||||
*
|
||||
* 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_server;
|
||||
|
||||
|
||||
/**
|
||||
* Return the IP addr of the client as a string
|
||||
**/
|
||||
char *client_addr(int fd)
|
||||
{
|
||||
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;
|
||||
|
||||
initialised = 1;
|
||||
|
||||
if (am_server) { /* daemon over --rsh mode */
|
||||
strcpy(addr_buf, "0.0.0.0");
|
||||
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);
|
||||
getnameinfo((struct sockaddr *)&ss, length,
|
||||
addr_buf, sizeof addr_buf, NULL, 0, NI_NUMERICHOST);
|
||||
}
|
||||
|
||||
return addr_buf;
|
||||
}
|
||||
|
||||
|
||||
static int get_sockaddr_family(const struct sockaddr_storage *ss)
|
||||
{
|
||||
return ((struct sockaddr *) ss)->sa_family;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the DNS name of the client.
|
||||
*
|
||||
* The name is statically cached so that repeated lookups are quick,
|
||||
* so there is a limit of one lookup per customer.
|
||||
*
|
||||
* If anything goes wrong, including the name->addr->name check, then
|
||||
* we just use "UNKNOWN", so you can use that value in hosts allow
|
||||
* lines.
|
||||
*
|
||||
* After translation from sockaddr to name we do a forward lookup to
|
||||
* make sure nobody is spoofing PTR records.
|
||||
**/
|
||||
char *client_name(int fd)
|
||||
{
|
||||
static char name_buf[100];
|
||||
static char port_buf[100];
|
||||
static int initialised;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t ss_len;
|
||||
|
||||
if (initialised)
|
||||
return name_buf;
|
||||
|
||||
strcpy(name_buf, default_name);
|
||||
initialised = 1;
|
||||
|
||||
memset(&ss, 0, sizeof ss);
|
||||
|
||||
if (am_server) { /* daemon over --rsh mode */
|
||||
char *addr = client_addr(fd);
|
||||
struct addrinfo hint, *answer;
|
||||
int err;
|
||||
|
||||
memset(&hint, 0, sizeof hint);
|
||||
|
||||
#ifdef AI_NUMERICHOST
|
||||
hint.ai_flags = AI_NUMERICHOST;
|
||||
#endif
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
|
||||
rprintf(FLOG, "malformed address %s: %s\n",
|
||||
addr, gai_strerror(err));
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
switch (answer->ai_family) {
|
||||
case AF_INET:
|
||||
ss_len = sizeof (struct sockaddr_in);
|
||||
memcpy(&ss, answer->ai_addr, ss_len);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
ss_len = sizeof (struct sockaddr_in6);
|
||||
memcpy(&ss, answer->ai_addr, ss_len);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
freeaddrinfo(answer);
|
||||
} else {
|
||||
ss_len = sizeof ss;
|
||||
client_sockaddr(fd, &ss, &ss_len);
|
||||
}
|
||||
|
||||
if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
|
||||
port_buf, sizeof port_buf) == 0)
|
||||
check_name(fd, &ss, name_buf);
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the sockaddr for the client.
|
||||
*
|
||||
* If it comes in as an ipv4 address mapped into IPv6 format then we
|
||||
* convert it back to a regular IPv4.
|
||||
**/
|
||||
void client_sockaddr(int fd,
|
||||
struct sockaddr_storage *ss,
|
||||
socklen_t *ss_len)
|
||||
{
|
||||
memset(ss, 0, sizeof *ss);
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
|
||||
/* FIXME: Can we really not continue? */
|
||||
rsyserr(FLOG, errno, "getpeername on fd%d failed", fd);
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (get_sockaddr_family(ss) == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
|
||||
/* OK, so ss is in the IPv6 family, but it is really
|
||||
* an IPv4 address: something like
|
||||
* "::ffff:10.130.1.2". If we use it as-is, then the
|
||||
* reverse lookup might fail or perhaps something else
|
||||
* bad might happen. So instead we convert it to an
|
||||
* equivalent address in the IPv4 address family. */
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
memcpy(&sin6, ss, sizeof sin6);
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
memset(sin, 0, sizeof *sin);
|
||||
sin->sin_family = AF_INET;
|
||||
*ss_len = sizeof (struct sockaddr_in);
|
||||
#ifdef HAVE_SOCKADDR_IN_LEN
|
||||
sin->sin_len = *ss_len;
|
||||
#endif
|
||||
sin->sin_port = sin6.sin6_port;
|
||||
|
||||
/* There is a macro to extract the mapped part
|
||||
* (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
|
||||
* to be present in the Linux headers. */
|
||||
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
|
||||
sizeof sin->sin_addr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look up a name from @p ss into @p name_buf.
|
||||
*
|
||||
* @param fd file descriptor for client socket.
|
||||
**/
|
||||
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)
|
||||
{
|
||||
int name_err;
|
||||
|
||||
/* reverse lookup */
|
||||
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
|
||||
name_buf, name_buf_len,
|
||||
port_buf, port_buf_len,
|
||||
NI_NAMEREQD | NI_NUMERICSERV);
|
||||
if (name_err != 0) {
|
||||
strcpy(name_buf, default_name);
|
||||
rprintf(FLOG, "name lookup failed for %s: %s\n",
|
||||
client_addr(fd), gai_strerror(name_err));
|
||||
return name_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compare an addrinfo from the resolver to a sockinfo.
|
||||
*
|
||||
* Like strcmp, returns 0 for identical.
|
||||
**/
|
||||
int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
const struct sockaddr_storage *ss)
|
||||
{
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
const char fn[] = "compare_addrinfo_sockaddr";
|
||||
|
||||
if (ai->ai_family != ss_family) {
|
||||
rprintf(FLOG, "%s: response family %d != %d\n",
|
||||
fn, ai->ai_family, ss_family);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The comparison method depends on the particular AF. */
|
||||
if (ss_family == AF_INET) {
|
||||
const struct sockaddr_in *sin1, *sin2;
|
||||
|
||||
sin1 = (const struct sockaddr_in *) ss;
|
||||
sin2 = (const struct sockaddr_in *) ai->ai_addr;
|
||||
|
||||
return memcmp(&sin1->sin_addr, &sin2->sin_addr,
|
||||
sizeof sin1->sin_addr);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sin1, *sin2;
|
||||
|
||||
sin1 = (const struct sockaddr_in6 *) ss;
|
||||
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
|
||||
|
||||
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
|
||||
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
|
||||
fn, ai->ai_addrlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
|
||||
sizeof sin1->sin6_addr))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
if (sin1->sin6_scope_id != sin2->sin6_scope_id)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
/* don't know */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do a forward lookup on @p name_buf and make sure it corresponds to
|
||||
* @p ss -- otherwise we may be being spoofed. If we suspect we are,
|
||||
* then we don't abort the connection but just emit a warning, and
|
||||
* change @p name_buf to be "UNKNOWN".
|
||||
*
|
||||
* We don't do anything with the service when checking the name,
|
||||
* because it doesn't seem that it could be spoofed in any way, and
|
||||
* getaddrinfo on random service names seems to cause problems on AIX.
|
||||
**/
|
||||
int check_name(int fd,
|
||||
const struct sockaddr_storage *ss,
|
||||
char *name_buf)
|
||||
{
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int error;
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = ss_family;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(name_buf, NULL, &hints, &res0);
|
||||
if (error) {
|
||||
rprintf(FLOG, "forward name lookup for %s failed: %s\n",
|
||||
name_buf, gai_strerror(error));
|
||||
strcpy(name_buf, default_name);
|
||||
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) {
|
||||
if (!compare_addrinfo_sockaddr(res, ss))
|
||||
break; /* OK, identical */
|
||||
}
|
||||
|
||||
if (!res0) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FLOG, "no known address for \"%s\": "
|
||||
"spoofed address?\n", name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
} else if (res == NULL) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FLOG, "%s is not a known address for \"%s\": "
|
||||
"spoofed address?\n", client_addr(fd), name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return 0;
|
||||
}
|
||||
912
clientserver.c
912
clientserver.c
File diff suppressed because it is too large
Load Diff
129
compat.c
129
compat.c
@@ -17,59 +17,106 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* compatability routines for older rsync protocol versions */
|
||||
/**
|
||||
* @file compat.c
|
||||
*
|
||||
* Compatibility routines for older rsync protocol versions.
|
||||
**/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int am_server;
|
||||
int remote_protocol = 0;
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int preserve_links;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_times;
|
||||
extern int always_checksum;
|
||||
extern int checksum_seed;
|
||||
|
||||
|
||||
extern int remote_version;
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
extern int inplace;
|
||||
extern int fuzzy_basis;
|
||||
extern int read_batch;
|
||||
extern int checksum_seed;
|
||||
extern int basis_dir_cnt;
|
||||
extern int prune_empty_dirs;
|
||||
extern int protocol_version;
|
||||
extern char *dest_option;
|
||||
|
||||
void setup_protocol(int f_out,int f_in)
|
||||
{
|
||||
if (remote_version == 0) {
|
||||
if (am_server) {
|
||||
remote_version = read_int(f_in);
|
||||
write_int(f_out,PROTOCOL_VERSION);
|
||||
} else {
|
||||
write_int(f_out,PROTOCOL_VERSION);
|
||||
remote_version = read_int(f_in);
|
||||
}
|
||||
if (remote_protocol == 0) {
|
||||
if (!read_batch)
|
||||
write_int(f_out, protocol_version);
|
||||
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 (remote_version < MIN_PROTOCOL_VERSION ||
|
||||
remote_version > MAX_PROTOCOL_VERSION) {
|
||||
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n",
|
||||
am_server? "Server" : "Client", remote_protocol, protocol_version);
|
||||
}
|
||||
if (remote_protocol < MIN_PROTOCOL_VERSION
|
||||
|| remote_protocol > MAX_PROTOCOL_VERSION) {
|
||||
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);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "local_version=%d remote_version=%d\n",
|
||||
PROTOCOL_VERSION, remote_version);
|
||||
|
||||
if (remote_version >= 12) {
|
||||
if (am_server) {
|
||||
checksum_seed = time(NULL);
|
||||
write_int(f_out,checksum_seed);
|
||||
} else {
|
||||
checksum_seed = read_int(f_in);
|
||||
}
|
||||
if (remote_protocol < OLD_PROTOCOL_VERSION) {
|
||||
rprintf(FINFO,"%s is very old version of rsync, upgrade recommended.\n",
|
||||
am_server? "Client" : "Server");
|
||||
}
|
||||
if (protocol_version < MIN_PROTOCOL_VERSION) {
|
||||
rprintf(FERROR, "--protocol must be at least %d on the %s.\n",
|
||||
MIN_PROTOCOL_VERSION, am_server? "Server" : "Client");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (protocol_version > PROTOCOL_VERSION) {
|
||||
rprintf(FERROR, "--protocol must be no more than %d on the %s.\n",
|
||||
PROTOCOL_VERSION, am_server? "Server" : "Client");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
checksum_init();
|
||||
}
|
||||
|
||||
if (am_server) {
|
||||
if (!checksum_seed)
|
||||
checksum_seed = time(NULL);
|
||||
write_int(f_out, checksum_seed);
|
||||
} else {
|
||||
checksum_seed = read_int(f_in);
|
||||
}
|
||||
}
|
||||
|
||||
1119
config.guess
vendored
1119
config.guess
vendored
File diff suppressed because it is too large
Load Diff
764
config.sub
vendored
764
config.sub
vendored
File diff suppressed because it is too large
Load Diff
757
configure.in
757
configure.in
@@ -1,35 +1,316 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(byteorder.h)
|
||||
|
||||
AC_INIT()
|
||||
AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
# compile with optimisation and without debugging by default
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
RSYNC_VERSION=2.6.7
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
AC_VALIDATE_CACHE_SYSTEM_TYPE
|
||||
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
|
||||
|
||||
LDFLAGS=${LDFLAGS-""}
|
||||
|
||||
AC_CANONICAL_TARGET([])
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_EGREP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_CC_STDC
|
||||
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" = x"no"; then
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
|
||||
fi
|
||||
|
||||
# We must decide this before testing the compiler.
|
||||
|
||||
# Please allow this to default to yes, so that your users have more
|
||||
# chance of getting a useful stack trace if problems occur.
|
||||
|
||||
AC_MSG_CHECKING([whether to include debugging symbols])
|
||||
AC_ARG_ENABLE(debug,
|
||||
AC_HELP_STRING([--disable-debug],
|
||||
[turn off debugging symbols and features]))
|
||||
|
||||
if test x"$enable_debug" = x"no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
# leave CFLAGS alone; AC_PROG_CC will try to include -g if it can
|
||||
dnl AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
|
||||
dnl CFLAGS=${CFLAGS-"-g"}
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(profile,
|
||||
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" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
|
||||
fi
|
||||
|
||||
|
||||
# This is needed for our included version of popt. Kind of silly, but
|
||||
# I don't want our version too far out of sync.
|
||||
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
|
||||
|
||||
# If GCC, turn on warnings.
|
||||
if test x"$GCC" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -Wall -W"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(included-popt,
|
||||
AC_HELP_STRING([--with-included-popt], [use bundled popt library, not from system]))
|
||||
|
||||
AC_ARG_WITH(rsync-path,
|
||||
AC_HELP_STRING([--with-rsync-path=PATH], [set default --rsync-path to PATH (default: rsync)]),
|
||||
[ RSYNC_PATH="$with_rsync_path" ],
|
||||
[ RSYNC_PATH="rsync" ])
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [location of rsync on remote machine])
|
||||
|
||||
AC_ARG_WITH(rsyncd-conf,
|
||||
AC_HELP_STRING([--with-rsyncd-conf=PATH], [set configuration file for rsync server to PATH (default: /etc/rsyncd.conf)]),
|
||||
[ if test ! -z "$with_rsyncd_conf" ; then
|
||||
case $with_rsyncd_conf in
|
||||
yes|no)
|
||||
RSYNCD_SYSCONF="/etc/rsyncd.conf"
|
||||
;;
|
||||
/*)
|
||||
RSYNCD_SYSCONF="$with_rsyncd_conf"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-rsyncd-conf=PATH)
|
||||
;;
|
||||
esac
|
||||
else
|
||||
RSYNCD_SYSCONF="/etc/rsyncd.conf"
|
||||
fi ],
|
||||
[ RSYNCD_SYSCONF="/etc/rsyncd.conf" ])
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNCD_SYSCONF, "$RSYNCD_SYSCONF", [location of configuration file for rsync server])
|
||||
|
||||
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)
|
||||
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
|
||||
RSYNC_RSH="$with_rsh"
|
||||
else
|
||||
RSYNC_RSH="ssh"
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
|
||||
|
||||
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)
|
||||
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([
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct flock lock;
|
||||
int status;
|
||||
char tpl[32] = "/tmp/locktest.XXXXXX";
|
||||
int fd = mkstemp(tpl);
|
||||
if (fd < 0) {
|
||||
strcpy(tpl, "conftest.dat");
|
||||
fd = open(tpl, O_CREAT|O_RDWR, 0600);
|
||||
}
|
||||
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 1;
|
||||
lock.l_pid = 0;
|
||||
fcntl(fd,F_SETLK,&lock);
|
||||
if (fork() == 0) {
|
||||
lock.l_start = 1;
|
||||
_exit(fcntl(fd,F_SETLK,&lock) == 0);
|
||||
}
|
||||
wait(&status);
|
||||
unlink(tpl);
|
||||
exit(WEXITSTATUS(status));
|
||||
}
|
||||
],
|
||||
rsync_cv_HAVE_BROKEN_LARGEFILE=yes,rsync_cv_HAVE_BROKEN_LARGEFILE=no,rsync_cv_HAVE_BROKEN_LARGEFILE=cross)])
|
||||
if test x"$rsync_cv_HAVE_BROKEN_LARGEFILE" != x"yes"; then
|
||||
AC_SYS_LARGEFILE
|
||||
fi
|
||||
|
||||
ipv6type=unknown
|
||||
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" != 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
|
||||
inria)
|
||||
# http://www.kame.net/
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <netinet/in.h>
|
||||
#ifdef IPV6_INRIA_VERSION
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])
|
||||
])
|
||||
;;
|
||||
kame)
|
||||
# http://www.kame.net/
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <netinet/in.h>
|
||||
#ifdef __KAME__
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
linux-glibc)
|
||||
# http://www.v6.linux.or.jp/
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <features.h>
|
||||
#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
linux-inet6)
|
||||
# http://www.v6.linux.or.jp/
|
||||
if test -d /usr/inet6 -o -f /usr/inet6/lib/libinet6.a; then
|
||||
ipv6type=$i
|
||||
ipv6lib=inet6
|
||||
ipv6libdir=/usr/inet6/lib
|
||||
ipv6trylibc=yes;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])
|
||||
CFLAGS="-I/usr/inet6/include $CFLAGS"
|
||||
fi
|
||||
;;
|
||||
toshiba)
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <sys/param.h>
|
||||
#ifdef _TOSHIBA_INET6
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
ipv6lib=inet6;
|
||||
ipv6libdir=/usr/local/v6/lib;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
v6d)
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include </usr/local/v6/include/sys/v6config.h>
|
||||
#ifdef __V6D__
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
ipv6lib=v6;
|
||||
ipv6libdir=/usr/local/v6/lib;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
zeta)
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <sys/param.h>
|
||||
#ifdef _ZETA_MINAMI_INET6
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
ipv6lib=inet6;
|
||||
ipv6libdir=/usr/local/v6/lib;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
esac
|
||||
if test "$ipv6type" != "unknown"; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
AC_MSG_RESULT($ipv6type)
|
||||
|
||||
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],
|
||||
[turn off 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 to 1 if sockets need to be shutdown])
|
||||
;;
|
||||
* ) AC_MSG_RESULT(no);;
|
||||
esac
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_TIME
|
||||
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)
|
||||
AC_CHECK_HEADERS(compat.h sys/param.h ctype.h sys/wait.h sys/ioctl.h)
|
||||
AC_CHECK_HEADERS(sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h)
|
||||
AC_CHECK_HEADERS(glob.h)
|
||||
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 locale.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h)
|
||||
AC_HEADER_MAJOR
|
||||
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(long long)
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_CHECK_SIZEOF(off_t)
|
||||
AC_CHECK_SIZEOF(off64_t)
|
||||
|
||||
AC_C_INLINE
|
||||
AC_C_LONG_DOUBLE
|
||||
|
||||
AC_TYPE_SIGNAL
|
||||
AC_TYPE_UID_T
|
||||
@@ -38,119 +319,21 @@ AC_TYPE_OFF_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_GETGROUPS
|
||||
AC_STRUCT_ST_RDEV
|
||||
AC_CHECK_TYPE(ino_t,unsigned)
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
|
||||
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)
|
||||
fi
|
||||
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod)
|
||||
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
|
||||
AC_CHECK_FUNCS(memmove lchown vsnprintf snprintf setsid glob strpbrk)
|
||||
AC_CHECK_FUNCS(strlcat strlcpy)
|
||||
|
||||
AC_CACHE_CHECK([for working fnmatch],rsync_cv_HAVE_FNMATCH,[
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
main() { exit(fnmatch("*.o", "x.o", FNM_PATHNAME) == 0? 0: 1); }],
|
||||
rsync_cv_HAVE_FNMATCH=yes,rsync_cv_HAVE_FNMATCH=no,rsync_cv_HAVE_FNMATCH=cross)])
|
||||
if test x"$rsync_cv_HAVE_FNMATCH" = x"yes"; then
|
||||
AC_DEFINE(HAVE_FNMATCH)
|
||||
fi
|
||||
|
||||
# sometimes getopt_long cannot parse same arguments twice
|
||||
# e.g. on certain versions of CygWin32
|
||||
AC_CACHE_CHECK([for working getopt_long],rsync_cv_HAVE_GETOPT_LONG,[
|
||||
AC_TRY_RUN([#include <getopt.h>
|
||||
main() {
|
||||
int i, x = 0; char *argv[] = { "x", "--xx" };
|
||||
struct option o[] = {{"xx", 0, 0, 1}, {0,0,0,0}};
|
||||
getopt_long(2, argv, "x", o, &i) == 1 ? x++ : 0; optind = 0;
|
||||
getopt_long(2, argv, "x", o, &i) == 1 ? x++ : 0;
|
||||
exit(x == 2 ? 0 : 1);
|
||||
}], rsync_cv_HAVE_GETOPT_LONG=yes,rsync_cv_HAVE_GETOPT_LONG=no,
|
||||
rsync_cv_HAVE_GETOPT_LONG=cross)])
|
||||
if test x"$rsync_cv_HAVE_GETOPT_LONG" = x"yes"; then
|
||||
AC_DEFINE(HAVE_GETOPT_LONG)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
|
||||
AC_TRY_RUN([#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
|
||||
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)
|
||||
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)])
|
||||
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
|
||||
AC_DEFINE(HAVE_UTIMBUF)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
|
||||
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(0); }
|
||||
exit(1);}],
|
||||
rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=cross)])
|
||||
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
|
||||
AC_DEFINE(REPLACE_INET_NTOA)
|
||||
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
|
||||
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
|
||||
# These need checks to be before checks for any other functions that
|
||||
# might be in the same libraries.
|
||||
# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has
|
||||
# libsocket.so which has a bad implementation of gethostbyname (it
|
||||
# only looks in /etc/hosts), so we only look for -lsocket if we need
|
||||
@@ -175,15 +358,123 @@ if test x"$ac_cv_func_connect" = x"no"; then
|
||||
esac
|
||||
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
|
||||
dnl has been cached.
|
||||
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
|
||||
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
|
||||
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)
|
||||
AC_DEFINE(HAVE_CONNECT, 1, [Define to 1 if you have the "connect" function])
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
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)
|
||||
|
||||
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
|
||||
|
||||
AC_CHECK_FUNCS(inet_ntop, , [AC_LIBOBJ(lib/inet_ntop)])
|
||||
AC_CHECK_FUNCS(inet_pton, , [AC_LIBOBJ(lib/inet_pton)])
|
||||
|
||||
# Irix 6.5 has getaddrinfo but not the corresponding defines, so use
|
||||
# builtin getaddrinfo if one of the defines don't exist
|
||||
AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
|
||||
rsync_cv_HAVE_GETADDR_DEFINES,[
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#ifdef AI_PASSIVE
|
||||
yes
|
||||
#endif],
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=yes,
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=no)])
|
||||
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
|
||||
# Tru64 UNIX has getaddrinfo() but has it renamed in libc as
|
||||
# something else so we must include <netdb.h> to get the
|
||||
# redefinition.
|
||||
AC_CHECK_FUNCS(getaddrinfo, ,
|
||||
[AC_MSG_CHECKING([for getaddrinfo by including <netdb.h>])
|
||||
AC_TRY_LINK([#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>],[getaddrinfo(NULL, NULL, NULL, NULL);],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_GETADDRINFO, 1,
|
||||
[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)])
|
||||
else
|
||||
AC_LIBOBJ(lib/getaddrinfo)
|
||||
AC_LIBOBJ(lib/getnameinfo)
|
||||
fi
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_LEN, 1, [Do we have sockaddr.sa_len?]) ],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
])
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_IN_LEN, 1, [Do we have sockaddr_in.sin_len?]) ],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#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 to 1 if you have struct sockaddr_storage.] ),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID, 1, [Do we have sockaddr_in6.sin6_scope_id?]) ],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#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)
|
||||
@@ -191,6 +482,231 @@ if test x"$ac_cv_func_strcasecmp" = x"no"; then
|
||||
AC_CHECK_LIB(resolv, strcasecmp)
|
||||
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.
|
||||
dnl AC_FUNC_MEMCMP
|
||||
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_FUNC_ALLOCA
|
||||
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 \
|
||||
sigaction sigprocmask)
|
||||
|
||||
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
|
||||
if test $ac_cv_func_getpgrp = yes; then
|
||||
AC_FUNC_GETPGRP
|
||||
fi
|
||||
|
||||
# Determine whether chown follows symlinks (it should).
|
||||
AC_CACHE_CHECK([whether chown() dereferences symlinks],rsync_cv_chown_follows_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(0);
|
||||
exit(1);
|
||||
}],
|
||||
rsync_cv_chown_follows_symlink=yes,rsync_cv_chown_follows_symlink=no,rsync_cv_chown_follows_symlink=yes)])
|
||||
if test $rsync_cv_chown_follows_symlink = no; then
|
||||
AC_DEFINE(CHOWN_MODIFIES_SYMLINK, 1, [Define to 1 if chown modifies symlinks.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
|
||||
AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
main() {
|
||||
int fd[2];
|
||||
exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1);
|
||||
}],
|
||||
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, [Define to 1 if you have the "socketpair" function])
|
||||
fi
|
||||
|
||||
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
|
||||
AC_MSG_RESULT($srcdir/popt)
|
||||
BUILD_POPT='$(popt_OBJS)'
|
||||
CFLAGS="$CFLAGS -I$srcdir/popt"
|
||||
if test x"$ALLOCA" != x
|
||||
then
|
||||
# this can be removed when/if we add an included alloca.c;
|
||||
# see autoconf documentation on AC_FUNC_ALLOCA
|
||||
AC_MSG_WARN([included libpopt will use malloc, not alloca (which wastes a small amount of memory)])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
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,[
|
||||
AC_TRY_RUN([#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
|
||||
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, [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)])
|
||||
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
|
||||
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_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,[
|
||||
AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
void foo(const char *format, ...) {
|
||||
va_list ap;
|
||||
int len;
|
||||
char buf[5];
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(0, 0, format, ap);
|
||||
va_end(ap);
|
||||
if (len != 5) exit(1);
|
||||
|
||||
if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
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, [Define to 1 if vsprintf has a C99-compatible return value])
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK([for secure mkstemp],rsync_cv_HAVE_SECURE_MKSTEMP,[
|
||||
AC_TRY_RUN([#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
main() {
|
||||
struct stat st;
|
||||
char tpl[20]="/tmp/test.XXXXXX";
|
||||
int fd = mkstemp(tpl);
|
||||
if (fd == -1) exit(1);
|
||||
unlink(tpl);
|
||||
if (fstat(fd, &st) != 0) exit(1);
|
||||
if ((st.st_mode & 0777) != 0600) exit(1);
|
||||
exit(0);
|
||||
}],
|
||||
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
|
||||
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_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, [Define to 1 if inet_ntoa() needs to be replaced])
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK([for broken inet_aton],rsync_cv_REPLACE_INET_ATON,[
|
||||
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, [Define to 1 if inet_aton() needs to be replaced])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([if mknod creates FIFOs],rsync_cv_MKNOD_CREATES_FIFOS,[
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#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([if mknod creates sockets],rsync_cv_MKNOD_CREATES_SOCKETS,[
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#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
|
||||
|
||||
#
|
||||
# The following test was mostly taken from the tcl/tk plus patches
|
||||
#
|
||||
@@ -220,6 +736,11 @@ fi
|
||||
AC_SUBST(OBJ_SAVE)
|
||||
AC_SUBST(OBJ_RESTORE)
|
||||
AC_SUBST(CC_SHOBJ_FLAG)
|
||||
AC_SUBST(BUILD_POPT)
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_OUTPUT(Makefile lib/dummy zlib/dummy)
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
82
csprotocol.txt
Normal file
82
csprotocol.txt
Normal file
@@ -0,0 +1,82 @@
|
||||
This is kind of informal and may be wrong, but it helped me. It's
|
||||
basically a summary of clientserver.c and authenticate.c.
|
||||
|
||||
-- Martin Pool <mbp@samba.org>
|
||||
|
||||
$Id$
|
||||
|
||||
|
||||
|
||||
|
||||
This is the protocol used for rsync --daemon; i.e. connections to port
|
||||
873 rather than invocations over a remote shell.
|
||||
|
||||
When the server accepts a connection, it prints a greeting
|
||||
|
||||
@RSYNCD: <version>
|
||||
|
||||
where <version> is the numeric version; currently 24. It follows this
|
||||
with a free text message-of-the-day. It expects to see a similar
|
||||
greeting back from the client.
|
||||
|
||||
The server is now in the connected state. The client can either send
|
||||
the command
|
||||
|
||||
#list
|
||||
|
||||
to get a listing of modules, or the name of a module. After this, the
|
||||
connection is now bound to a particular module. Access per host for
|
||||
this module is now checked, as is per-module connection limits.
|
||||
|
||||
If authentication is required to use this module, the server will say
|
||||
|
||||
@RSYNCD: AUTHREQD <challenge>
|
||||
|
||||
where <challenge> is a random string of base64 characters. The client
|
||||
must respond with
|
||||
|
||||
<user> <response>
|
||||
|
||||
where <user> is the username they claim to be, and <response> is the
|
||||
base64 form of the MD4 hash of challenge+password.
|
||||
|
||||
At this point the server applies all remaining constraints before
|
||||
handing control to the client, including switching uid/gid, setting up
|
||||
include and exclude lists, moving to the root of the module, and doing
|
||||
chroot.
|
||||
|
||||
If the login is acceptable, then the server will respond with
|
||||
|
||||
@RSYNCD: OK
|
||||
|
||||
The client now writes some rsync options, as if it were remotely
|
||||
executing the command. The server parses these arguments as if it had
|
||||
just been invoked with them, but they're added to the existing state.
|
||||
So if the client specifies a list of files to be included or excluded,
|
||||
they'll defer to existing limits specified in the server
|
||||
configuration.
|
||||
|
||||
At this point the client and server both switch to using a
|
||||
multiplexing layer across the socket. The main point of this is to
|
||||
allow the server to asynchronously pass errors back, while still
|
||||
allowing streamed and pipelined data.
|
||||
|
||||
Unfortunately, the multiplex protocol is not used at every stage. We
|
||||
start up in plain socket mode and then change over by calling
|
||||
io_start_buffering. Of course both the client and the server have to
|
||||
do this at the same point.
|
||||
|
||||
The server then talks to the client as normal across the socket,
|
||||
passing checksums, file lists and so on. For documentation of that,
|
||||
stay tuned (or write it yourself!).
|
||||
|
||||
|
||||
|
||||
------------
|
||||
Protocol version changes
|
||||
|
||||
25 (2001-08-20, 2.4.7pre2)
|
||||
|
||||
Send an explicit "@RSYNC EXIT" command at the end of the
|
||||
module listing. We never intentionally end the transmission
|
||||
by just closing the socket anymore.
|
||||
2
doc/.cvsignore
Normal file
2
doc/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
rsync.pdf
|
||||
rsync.ps
|
||||
20
doc/README-SGML
Normal file
20
doc/README-SGML
Normal file
@@ -0,0 +1,20 @@
|
||||
Handling the rsync SGML documentation
|
||||
|
||||
rsync documentation is now primarily in Docbook format. Docbook is an
|
||||
SGML/XML documentation format that is becoming standard on free
|
||||
operating systems. It's also used for Samba documentation.
|
||||
|
||||
The SGML files are source code that can be translated into various
|
||||
useful output formats, primarily PDF, HTML, Postscript and plain text.
|
||||
|
||||
To do this transformation on Debian, you should install the
|
||||
docbook-utils package. Having done that, you can say
|
||||
|
||||
docbook2pdf rsync.sgml
|
||||
|
||||
and so on.
|
||||
|
||||
On other systems you probably need James Clark's "sp" and "JadeTeX"
|
||||
packages. Work it out for yourself and send a note to the mailing
|
||||
list.
|
||||
|
||||
42
doc/profile.txt
Normal file
42
doc/profile.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
Notes on rsync profiling
|
||||
|
||||
strlcpy is hot:
|
||||
|
||||
0.00 0.00 1/7735635 push_dir [68]
|
||||
0.00 0.00 1/7735635 pop_dir [71]
|
||||
0.00 0.00 1/7735635 send_file_list [15]
|
||||
0.01 0.00 18857/7735635 send_files [4]
|
||||
0.04 0.00 129260/7735635 send_file_entry [18]
|
||||
0.04 0.00 129260/7735635 make_file [20]
|
||||
0.04 0.00 141666/7735635 send_directory <cycle 1> [36]
|
||||
2.29 0.00 7316589/7735635 f_name [13]
|
||||
[14] 11.7 2.42 0.00 7735635 strlcpy [14]
|
||||
|
||||
|
||||
Here's the top few functions:
|
||||
|
||||
46.23 9.57 9.57 13160929 0.00 0.00 mdfour64
|
||||
14.78 12.63 3.06 13160929 0.00 0.00 copy64
|
||||
11.69 15.05 2.42 7735635 0.00 0.00 strlcpy
|
||||
10.05 17.13 2.08 41438 0.05 0.38 sum_update
|
||||
4.11 17.98 0.85 13159996 0.00 0.00 mdfour_update
|
||||
1.50 18.29 0.31 file_compare
|
||||
1.45 18.59 0.30 129261 0.00 0.01 send_file_entry
|
||||
1.23 18.84 0.26 2557585 0.00 0.00 f_name
|
||||
1.11 19.07 0.23 1483750 0.00 0.00 u_strcmp
|
||||
1.11 19.30 0.23 118129 0.00 0.00 writefd_unbuffered
|
||||
0.92 19.50 0.19 1085011 0.00 0.00 writefd
|
||||
0.43 19.59 0.09 156987 0.00 0.00 read_timeout
|
||||
0.43 19.68 0.09 129261 0.00 0.00 clean_fname
|
||||
0.39 19.75 0.08 32887 0.00 0.38 matched
|
||||
0.34 19.82 0.07 1 70.00 16293.92 send_files
|
||||
0.29 19.89 0.06 129260 0.00 0.00 make_file
|
||||
0.29 19.95 0.06 75430 0.00 0.00 read_unbuffered
|
||||
|
||||
|
||||
|
||||
mdfour could perhaps be made faster:
|
||||
|
||||
/* NOTE: This code makes no attempt to be fast! */
|
||||
|
||||
There might be an optimized version somewhere that we can borrow.
|
||||
351
doc/rsync.sgml
Normal file
351
doc/rsync.sgml
Normal file
@@ -0,0 +1,351 @@
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
<book id="rsync">
|
||||
<bookinfo>
|
||||
<title>rsync</title>
|
||||
<copyright>
|
||||
<year>1996 -- 2002</year>
|
||||
<holder>Martin Pool</holder>
|
||||
<holder>Andrew Tridgell</holder>
|
||||
</copyright>
|
||||
<author>
|
||||
<firstname>Martin</firstname>
|
||||
<surname>Pool</surname>
|
||||
</author>
|
||||
</bookinfo>
|
||||
|
||||
<chapter>
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>rsync is a flexible program for efficiently copying files or
|
||||
directory trees.
|
||||
|
||||
<para>rsync has many options to select which files will be copied
|
||||
and how they are to be transferred. It may be used as an
|
||||
alternative to ftp, http, scp or rcp.
|
||||
|
||||
<para>The rsync remote-update protocol allows rsync to transfer just
|
||||
the differences between two sets of files across the network link,
|
||||
using an efficient checksum-search algorithm described in the
|
||||
technical report that accompanies this package.</para>
|
||||
|
||||
<para>Some of the additional features of rsync are:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>support for copying links, devices, owners, groups and
|
||||
permissions
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
exclude and exclude-from options similar to GNU tar
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
a CVS exclude mode for ignoring the same files that CVS would ignore
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
can use any transparent remote shell, including rsh or ssh
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
does not require root privileges
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
pipelining of file transfers to minimize latency costs
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
support for anonymous or authenticated rsync servers (ideal for
|
||||
mirroring)
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</chapter>
|
||||
|
||||
|
||||
|
||||
<chapter>
|
||||
<title>Using rsync</title>
|
||||
<section>
|
||||
<title>
|
||||
Introductory example
|
||||
</title>
|
||||
|
||||
<para>
|
||||
Probably the most common case of rsync usage is to copy files
|
||||
to or from a remote machine using
|
||||
<application>ssh</application> as a network transport. In
|
||||
this situation rsync is a good alternative to
|
||||
<application>scp</application>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The most commonly used arguments for rsync are
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<listitem>
|
||||
<para>Be verbose. Primarily, display the name of each file as it is copied.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-a</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Reproduce the structure and attributes of the origin files as exactly
|
||||
as possible: this includes copying subdirectories, symlinks, special
|
||||
files, ownership and permissions. (@xref{Attributes to
|
||||
copy}.)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
|
||||
|
||||
<para><option>-v </option>
|
||||
|
||||
<para><option>-z</option>
|
||||
Compress network traffic, using a modified version of the
|
||||
@command{zlib} library.</para>
|
||||
|
||||
<para><option>-P</option>
|
||||
Display a progress indicator while files are transferred. This should
|
||||
normally be ommitted if rsync is not run on a terminal.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<title>Local and remote</title>
|
||||
|
||||
<para>There are six different ways of using rsync. They
|
||||
are:</para>
|
||||
|
||||
|
||||
|
||||
<!-- one of (CALLOUTLIST GLOSSLIST ITEMIZEDLIST ORDEREDLIST SEGMENTEDLIST SIMPLELIST VARIABLELIST CAUTION IMPORTANT NOTE TIP WARNING LITERALLAYOUT PROGRAMLISTING PROGRAMLISTINGCO SCREEN SCREENCO SCREENSHOT SYNOPSIS CMDSYNOPSIS FUNCSYNOPSIS CLASSSYNOPSIS FIELDSYNOPSIS CONSTRUCTORSYNOPSIS DESTRUCTORSYNOPSIS METHODSYNOPSIS FORMALPARA PARA SIMPARA ADDRESS BLOCKQUOTE GRAPHIC GRAPHICCO MEDIAOBJECT MEDIAOBJECTCO INFORMALEQUATION INFORMALEXAMPLE INFORMALFIGURE INFORMALTABLE EQUATION EXAMPLE FIGURE TABLE MSGSET PROCEDURE SIDEBAR QANDASET ANCHOR BRIDGEHEAD REMARK HIGHLIGHTS ABSTRACT AUTHORBLURB EPIGRAPH INDEXTERM REFENTRY SECTION) -->
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
for copying local files. This is invoked when neither
|
||||
source nor destination path contains a @code{:} separator
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
for copying from the local machine to a remote machine using
|
||||
a remote shell program as the transport (such as rsh or
|
||||
ssh). This is invoked when the destination path contains a
|
||||
single @code{:} separator.
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
for copying from a remote machine to the local machine
|
||||
using a remote shell program. This is invoked when the source
|
||||
contains a @code{:} separator.
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
for copying from a remote rsync server to the local
|
||||
machine. This is invoked when the source path contains a @code{::}
|
||||
separator or a @code{rsync://} URL.
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
for copying from the local machine to a remote rsync
|
||||
server. This is invoked when the destination path contains a @code{::}
|
||||
separator.
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
for listing files on a remote machine. This is done the
|
||||
same way as rsync transfers except that you leave off the
|
||||
local destination.
|
||||
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
<para>
|
||||
Note that in all cases (other than listing) at least one of the source
|
||||
and destination paths must be local.
|
||||
|
||||
<para>
|
||||
Any one invocation of rsync makes a copy in a single direction. rsync
|
||||
currently has no equivalent of @command{ftp}'s interactive mode.
|
||||
|
||||
@cindex @sc{nfs}
|
||||
@cindex network filesystems
|
||||
@cindex remote filesystems
|
||||
|
||||
<para>
|
||||
rsync's network protocol is generally faster at copying files than
|
||||
network filesystems such as @sc{nfs} or @sc{cifs}. It is better to
|
||||
run rsync on the file server either as a daemon or over ssh than
|
||||
running rsync giving the network directory.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
|
||||
|
||||
<chapter>
|
||||
<title>Frequently asked questions</title>
|
||||
|
||||
|
||||
<!-- one of (CALLOUTLIST GLOSSLIST ITEMIZEDLIST ORDEREDLIST SEGMENTEDLIST SIMPLELIST VARIABLELIST CAUTION IMPORTANT NOTE TIP WARNING LITERALLAYOUT PROGRAMLISTING PROGRAMLISTINGCO SCREEN SCREENCO SCREENSHOT SYNOPSIS CMDSYNOPSIS FUNCSYNOPSIS CLASSSYNOPSIS FIELDSYNOPSIS CONSTRUCTORSYNOPSIS DESTRUCTORSYNOPSIS METHODSYNOPSIS FORMALPARA PARA SIMPARA ADDRESS BLOCKQUOTE GRAPHIC GRAPHICCO MEDIAOBJECT MEDIAOBJECTCO INFORMALEQUATION INFORMALEXAMPLE INFORMALFIGURE INFORMALTABLE EQUATION EXAMPLE FIGURE TABLE MSGSET PROCEDURE SIDEBAR QANDASET ANCHOR BRIDGEHEAD REMARK HIGHLIGHTS ABSTRACT AUTHORBLURB EPIGRAPH INDEXTERM SECTION SIMPLESECT REFENTRY SECT1) -->
|
||||
<qandaset>
|
||||
<!-- one of (QANDADIV QANDAENTRY) -->
|
||||
|
||||
<qandaentry>
|
||||
<question>
|
||||
<!-- one of (CALLOUTLIST GLOSSLIST ITEMIZEDLIST ORDEREDLIST
|
||||
SEGMENTEDLIST SIMPLELIST VARIABLELIST CAUTION IMPORTANT NOTE
|
||||
TIP WARNING LITERALLAYOUT PROGRAMLISTING PROGRAMLISTINGCO
|
||||
SCREEN SCREENCO SCREENSHOT SYNOPSIS CMDSYNOPSIS FUNCSYNOPSIS
|
||||
CLASSSYNOPSIS FIELDSYNOPSIS CONSTRUCTORSYNOPSIS
|
||||
DESTRUCTORSYNOPSIS METHODSYNOPSIS FORMALPARA PARA SIMPARA
|
||||
ADDRESS BLOCKQUOTE GRAPHIC GRAPHICCO MEDIAOBJECT
|
||||
MEDIAOBJECTCO INFORMALEQUATION INFORMALEXAMPLE
|
||||
INFORMALFIGURE INFORMALTABLE EQUATION EXAMPLE FIGURE TABLE
|
||||
PROCEDURE ANCHOR BRIDGEHEAD REMARK HIGHLIGHTS INDEXTERM) -->
|
||||
<para>Are there mailing lists for rsync?
|
||||
</question>
|
||||
|
||||
<answer>
|
||||
<para>Yes, and you can subscribe and unsubscribe through a
|
||||
web interface at
|
||||
<ulink
|
||||
url="http://lists.samba.org/">http://lists.samba.org/</ulink>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you are having trouble with the mailing list, please
|
||||
send mail to the administrator
|
||||
|
||||
<email>rsync-admin@lists.samba.org</email>
|
||||
|
||||
not to the list itself.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The mailing list archives are searchable. Use
|
||||
<ulink url="http://google.com/">Google</ulink> and prepend
|
||||
the search with <userinput>site:lists.samba.org
|
||||
rsync</userinput>, plus relevant keywords.
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
|
||||
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>
|
||||
Why is rsync so much bigger when I build it with
|
||||
<command>gcc</command>?
|
||||
</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
On gcc, rsync builds by default with debug symbols
|
||||
included. If you strip both executables, they should end
|
||||
up about the same size. (Use <command>make
|
||||
install-strip</command>.)
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
|
||||
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Is rsync useful for a single large file like an ISO image?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
Yes, but note the following:
|
||||
|
||||
<para>
|
||||
Background: A common use of rsync is to update a file (or set of files) in one location from a more
|
||||
correct or up-to-date copy in another location, taking advantage of portions of the files that are
|
||||
identical to speed up the process. (Note that rsync will transfer a file in its entirety if no copy
|
||||
exists at the destination.)
|
||||
|
||||
<para>
|
||||
(This discussion is written in terms of updating a local copy of a file from a correct file in a
|
||||
remote location, although rsync can work in either direction.)
|
||||
|
||||
<para>
|
||||
The file to be updated (the local file) must be in a destination directory that has enough space for
|
||||
two copies of the file. (In addition, keep an extra copy of the file to be updated in a different
|
||||
location for safety -- see the discussion (below) about rsync's behavior when the rsync process is
|
||||
interrupted before completion.)
|
||||
|
||||
<para>
|
||||
The local file must have the same name as the remote file being sync'd to (I think?). If you are
|
||||
trying to upgrade an iso from, for example, beta1 to beta2, rename the local file to the same name
|
||||
as the beta2 file. *(This is a useful thing to do -- only the changed portions will be
|
||||
transmitted.)*
|
||||
|
||||
<para>
|
||||
The extra copy of the local file kept in a different location is because of rsync's behavior if
|
||||
interrupted before completion:
|
||||
|
||||
<para>
|
||||
* If you specify the --partial option and rsync is interrupted, rsync will save the partially
|
||||
rsync'd file and throw away the original local copy. (The partially rsync'd file is correct but
|
||||
truncated.) If rsync is restarted, it will not have a local copy of the file to check for duplicate
|
||||
blocks beyond the section of the file that has already been rsync'd, thus the remainder of the rsync
|
||||
process will be a "pure transfer" of the file rather than taking advantage of the rsync algorithm.
|
||||
|
||||
<para>
|
||||
* If you don't specify the --partial option and rsync is interrupted, rsync will throw away the
|
||||
partially rsync'd file, and, when rsync is restarted starts the rsync process over from the
|
||||
beginning.
|
||||
|
||||
<para>
|
||||
Which of these is most desirable depends on the degree of commonality between the local and remote
|
||||
copies of the file *and how much progress was made before the interruption*.
|
||||
|
||||
<para>
|
||||
The ideal approach after an interruption would be to create a new file by taking the original file
|
||||
and deleting a portion equal in size to the portion already rsync'd and then appending *the
|
||||
remaining* portion to the portion of the file that has already been rsync'd. (There has been some
|
||||
discussion about creating an option to do this automatically.)
|
||||
|
||||
The --compare-dest option is useful when transferring multiple files, but is of no benefit in
|
||||
transferring a single file. (AFAIK)
|
||||
|
||||
*Other potentially useful information can be found at:
|
||||
-[3]http://twiki.org/cgi-bin/view/Wikilearn/RsyncingALargeFile
|
||||
|
||||
This answer, formatted with "real" bullets, can be found at:
|
||||
-[4]http://twiki.org/cgi-bin/view/Wikilearn/RsyncingALargeFileFAQ*
|
||||
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
</qandaset>
|
||||
</chapter>
|
||||
|
||||
|
||||
<appendix>
|
||||
<title>Other Resources</title>
|
||||
|
||||
<para><ulink url="http://www.ccp14.ac.uk/ccp14admin/rsync/"></ulink></para>
|
||||
</appendix>
|
||||
</book>
|
||||
52
errcode.h
52
errcode.h
@@ -1,18 +1,64 @@
|
||||
/* error codes returned by rsync */
|
||||
/* -*- 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
|
||||
*/
|
||||
|
||||
#define RERR_OK 0
|
||||
#define RERR_SYNTAX 1 /* syntax or usage error */
|
||||
#define RERR_PROTOCOL 2 /* protocol incompatibility */
|
||||
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
|
||||
#define RERR_UNSUPPORTED 4 /* requested action not supported */
|
||||
#define RERR_UNSUPPORTED 4 /* requested action not supported */
|
||||
#define RERR_STARTCLIENT 5 /* error starting client-server protocol */
|
||||
|
||||
#define RERR_SOCKETIO 10 /* error in socket IO */
|
||||
#define RERR_FILEIO 11 /* error in file IO */
|
||||
#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 */
|
||||
|
||||
/* Although it doesn't seem to be specified anywhere,
|
||||
* ssh and the shell seem to return these values:
|
||||
*
|
||||
* 124 if the command exited with status 255
|
||||
* 125 if the command is killed by a signal
|
||||
* 126 if the command cannot be run
|
||||
* 127 if the command is not found
|
||||
*
|
||||
* and we could use this to give a better explanation if the remote
|
||||
* command is not found.
|
||||
*/
|
||||
#define RERR_CMD_FAILED 124
|
||||
#define RERR_CMD_KILLED 125
|
||||
#define RERR_CMD_RUN 126
|
||||
#define RERR_CMD_NOTFOUND 127
|
||||
|
||||
237
fileio.c
237
fileio.c
@@ -1,29 +1,35 @@
|
||||
/*
|
||||
/*
|
||||
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 IO utilities used in rsync
|
||||
File IO utilities used in rsync
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
#ifndef ENODATA
|
||||
#define ENODATA EAGAIN
|
||||
#endif
|
||||
|
||||
extern int sparse_files;
|
||||
|
||||
static char last_byte;
|
||||
static int last_sparse;
|
||||
extern int sparse_files;
|
||||
|
||||
int sparse_end(int f)
|
||||
{
|
||||
@@ -36,13 +42,13 @@ int sparse_end(int f)
|
||||
}
|
||||
|
||||
|
||||
static int write_sparse(int f,char *buf,int len)
|
||||
static int write_sparse(int f,char *buf,size_t len)
|
||||
{
|
||||
int 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++) ;
|
||||
for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
|
||||
for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}
|
||||
|
||||
last_byte = buf[len-1];
|
||||
|
||||
@@ -50,38 +56,83 @@ static int write_sparse(int f,char *buf,int len)
|
||||
last_sparse=1;
|
||||
|
||||
if (l1 > 0) {
|
||||
do_lseek(f,l1,SEEK_CUR);
|
||||
do_lseek(f,l1,SEEK_CUR);
|
||||
}
|
||||
|
||||
if (l1 == len)
|
||||
if (l1 == len)
|
||||
return len;
|
||||
|
||||
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
|
||||
if (ret == -1 || ret == 0) return ret;
|
||||
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 (l2 > 0)
|
||||
do_lseek(f,l2,SEEK_CUR);
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static char *wf_writeBuf;
|
||||
static size_t wf_writeBufSize;
|
||||
static size_t wf_writeBufCnt;
|
||||
|
||||
int write_file(int f,char *buf,int len)
|
||||
int flush_write_file(int f)
|
||||
{
|
||||
int ret = 0;
|
||||
char *bp = wf_writeBuf;
|
||||
|
||||
while (wf_writeBufCnt > 0) {
|
||||
if ((ret = write(f, bp, wf_writeBufCnt)) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return ret;
|
||||
}
|
||||
wf_writeBufCnt -= ret;
|
||||
bp += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* write_file does not allow incomplete writes. It loops internally
|
||||
* until len bytes are written or errno is set.
|
||||
*/
|
||||
int write_file(int f,char *buf,size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!sparse_files) {
|
||||
return write(f,buf,len);
|
||||
}
|
||||
|
||||
while (len>0) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
int r1 = write_sparse(f, buf, len1);
|
||||
while (len > 0) {
|
||||
int r1;
|
||||
if (sparse_files) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
r1 = write_sparse(f, buf, len1);
|
||||
} else {
|
||||
if (!wf_writeBuf) {
|
||||
wf_writeBufSize = WRITE_SIZE * 8;
|
||||
wf_writeBufCnt = 0;
|
||||
wf_writeBuf = new_array(char, wf_writeBufSize);
|
||||
if (!wf_writeBuf)
|
||||
out_of_memory("write_file");
|
||||
}
|
||||
r1 = MIN(len, wf_writeBufSize - wf_writeBufCnt);
|
||||
if (r1) {
|
||||
memcpy(wf_writeBuf + wf_writeBufCnt, buf, r1);
|
||||
wf_writeBufCnt += r1;
|
||||
}
|
||||
if (wf_writeBufCnt == wf_writeBufSize) {
|
||||
if (flush_write_file(f) < 0)
|
||||
return -1;
|
||||
if (!r1 && len)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (r1 <= 0) {
|
||||
if (ret > 0) return ret;
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
return r1;
|
||||
}
|
||||
len -= r1;
|
||||
@@ -92,75 +143,67 @@ int write_file(int f,char *buf,int 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 = (struct map_struct *)malloc(sizeof(*map));
|
||||
if (!map) out_of_memory("map_file");
|
||||
|
||||
if (!(map = new(struct map_struct)))
|
||||
out_of_memory("map_file");
|
||||
|
||||
if (blk_size && (read_size % blk_size))
|
||||
read_size += blk_size - (read_size % blk_size);
|
||||
|
||||
memset(map, 0, sizeof map[0]);
|
||||
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->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_start = offset;
|
||||
window_size = map->def_window_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;
|
||||
}
|
||||
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 = (char *)Realloc(map->p, window_size);
|
||||
if (!map->p) out_of_memory("map_ptr");
|
||||
map->p = realloc_array(map->p, char, window_size);
|
||||
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) {
|
||||
@@ -175,39 +218,53 @@ 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;
|
||||
/* 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_fd_offset += read_size;
|
||||
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;
|
||||
}
|
||||
read_offset += nread;
|
||||
read_size -= nread;
|
||||
}
|
||||
|
||||
return map->p;
|
||||
}
|
||||
|
||||
|
||||
void unmap_file(struct map_struct *map)
|
||||
int unmap_file(struct map_struct *map)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (map->p) {
|
||||
free(map->p);
|
||||
map->p = NULL;
|
||||
}
|
||||
memset(map, 0, sizeof(*map));
|
||||
ret = map->status;
|
||||
memset(map, 0, sizeof map[0]);
|
||||
free(map);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
1642
generator.c
1642
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;
|
||||
}
|
||||
68
getgroups.c
Normal file
68
getgroups.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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 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.
|
||||
**/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
int
|
||||
main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
{
|
||||
int n, i;
|
||||
gid_t *list;
|
||||
gid_t gid = MY_GID();
|
||||
int gid_in_list = 0;
|
||||
|
||||
#ifdef HAVE_GETGROUPS
|
||||
if ((n = getgroups(0, NULL)) < 0) {
|
||||
perror("getgroups");
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
n = 0;
|
||||
#endif
|
||||
|
||||
list = (gid_t*)malloc(sizeof (gid_t) * (n + 1));
|
||||
if (!list) {
|
||||
fprintf(stderr, "out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETGROUPS
|
||||
if (n > 0)
|
||||
n = getgroups(n, list);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
printf("%lu ", (unsigned long)list[i]);
|
||||
if (list[i] == gid)
|
||||
gid_in_list = 1;
|
||||
}
|
||||
/* The default gid might not be in the list on some systems. */
|
||||
if (!gid_in_list)
|
||||
printf("%lu", (unsigned long)gid);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
348
hlink.c
348
hlink.c
@@ -1,17 +1,18 @@
|
||||
/*
|
||||
/*
|
||||
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.
|
||||
@@ -19,138 +20,271 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int dry_run;
|
||||
extern int verbose;
|
||||
extern int link_dest;
|
||||
extern int make_backups;
|
||||
extern int log_format_has_i;
|
||||
extern char *basis_dir[];
|
||||
extern struct file_list *the_file_list;
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static int hlink_compare(struct file_struct *f1,struct file_struct *f2)
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
|
||||
#define SKIPPED_LINK (-1)
|
||||
#define FINISHED_LINK (-2)
|
||||
|
||||
#define FPTR(i) (the_file_list->files[i])
|
||||
#define LINKED(p1,p2) (FPTR(p1)->F_DEV == FPTR(p2)->F_DEV \
|
||||
&& FPTR(p1)->F_INODE == FPTR(p2)->F_INODE)
|
||||
|
||||
static int hlink_compare(int *int1, int *int2)
|
||||
{
|
||||
if (!S_ISREG(f1->mode) && !S_ISREG(f2->mode)) return 0;
|
||||
if (!S_ISREG(f1->mode)) return -1;
|
||||
if (!S_ISREG(f2->mode)) return 1;
|
||||
struct file_struct *f1 = FPTR(*int1);
|
||||
struct file_struct *f2 = FPTR(*int2);
|
||||
|
||||
if (f1->dev != f2->dev)
|
||||
return (int)(f1->dev>f2->dev?1:-1);
|
||||
if (f1->F_DEV != f2->F_DEV)
|
||||
return (int) (f1->F_DEV > f2->F_DEV ? 1 : -1);
|
||||
|
||||
if (f1->inode != f2->inode)
|
||||
return (int)(f1->inode>f2->inode?1:-1);
|
||||
if (f1->F_INODE != f2->F_INODE)
|
||||
return (int) (f1->F_INODE > f2->F_INODE ? 1 : -1);
|
||||
|
||||
return file_compare(&f1,&f2);
|
||||
return f_name_cmp(f1, f2);
|
||||
}
|
||||
|
||||
|
||||
static struct file_struct *hlink_list;
|
||||
static int *hlink_list;
|
||||
static int hlink_count;
|
||||
|
||||
/* 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(void)
|
||||
{
|
||||
int cur, from, to, start;
|
||||
|
||||
alloc_pool_t hlink_pool;
|
||||
alloc_pool_t idev_pool = the_file_list->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;
|
||||
while (1) {
|
||||
cur = hlink_list[from];
|
||||
if (from == hlink_count-1
|
||||
|| !LINKED(cur, hlink_list[from+1]))
|
||||
break;
|
||||
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
|
||||
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
FPTR(cur)->F_HLINDEX = to;
|
||||
FPTR(cur)->F_NEXT = hlink_list[++from];
|
||||
}
|
||||
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
|
||||
if (from > start) {
|
||||
int head = hlink_list[start];
|
||||
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
FPTR(head)->flags |= FLAG_HLINK_TOL;
|
||||
FPTR(cur)->F_HLINDEX = to;
|
||||
FPTR(cur)->F_NEXT = head;
|
||||
FPTR(cur)->flags |= FLAG_HLINK_EOL;
|
||||
hlink_list[to++] = head;
|
||||
} else
|
||||
FPTR(cur)->link_u.links = NULL;
|
||||
}
|
||||
|
||||
if (!to) {
|
||||
free(hlink_list);
|
||||
hlink_list = NULL;
|
||||
pool_destroy(hlink_pool);
|
||||
hlink_pool = NULL;
|
||||
} else {
|
||||
hlink_count = to;
|
||||
hlink_list = realloc_array(hlink_list, int, hlink_count);
|
||||
if (!hlink_list)
|
||||
out_of_memory("init_hard_links");
|
||||
}
|
||||
the_file_list->hlink_pool = hlink_pool;
|
||||
pool_destroy(idev_pool);
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_hard_links(struct file_list *flist)
|
||||
void init_hard_links(void)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
int i;
|
||||
if (flist->count < 2) return;
|
||||
|
||||
if (hlink_list) free(hlink_list);
|
||||
|
||||
if (!(hlink_list =
|
||||
(struct file_struct *)malloc(sizeof(hlink_list[0])*flist->count)))
|
||||
if (hlink_list)
|
||||
free(hlink_list);
|
||||
|
||||
if (!(hlink_list = new_array(int, the_file_list->count)))
|
||||
out_of_memory("init_hard_links");
|
||||
|
||||
for (i = 0; i < flist->count; i++)
|
||||
memcpy(&hlink_list[i], flist->files[i], sizeof(hlink_list[0]));
|
||||
hlink_count = 0;
|
||||
for (i = 0; i < the_file_list->count; i++) {
|
||||
if (FPTR(i)->link_u.idev)
|
||||
hlink_list[hlink_count++] = i;
|
||||
}
|
||||
|
||||
qsort(hlink_list,flist->count,
|
||||
sizeof(hlink_list[0]),
|
||||
(int (*)())hlink_compare);
|
||||
qsort(hlink_list, hlink_count,
|
||||
sizeof hlink_list[0], (int (*)()) hlink_compare);
|
||||
|
||||
hlink_count=flist->count;
|
||||
if (!hlink_count) {
|
||||
free(hlink_list);
|
||||
hlink_list = NULL;
|
||||
} else
|
||||
link_idev_data();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check if a file should be skipped because it is the same as an
|
||||
earlier hard link */
|
||||
int check_hard_link(struct file_struct *file)
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
static int maybe_hard_link(struct file_struct *file, int ndx,
|
||||
char *fname, int statret, STRUCT_STAT *st,
|
||||
char *toname, STRUCT_STAT *to_st,
|
||||
int itemizing, enum logcode code)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int low=0,high=hlink_count-1;
|
||||
int ret=0;
|
||||
|
||||
if (!hlink_list || !S_ISREG(file->mode)) return 0;
|
||||
|
||||
while (low != high) {
|
||||
int mid = (low+high)/2;
|
||||
ret = hlink_compare(&hlink_list[mid],file);
|
||||
if (ret == 0) {
|
||||
low = mid;
|
||||
break;
|
||||
}
|
||||
if (ret > 0)
|
||||
high=mid;
|
||||
else
|
||||
low=mid+1;
|
||||
}
|
||||
|
||||
if (hlink_compare(&hlink_list[low],file) != 0) return 0;
|
||||
|
||||
if (low > 0 &&
|
||||
S_ISREG(hlink_list[low-1].mode) &&
|
||||
file->dev == hlink_list[low-1].dev &&
|
||||
file->inode == hlink_list[low-1].inode)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static void hard_link_one(int i)
|
||||
{
|
||||
STRUCT_STAT st1,st2;
|
||||
|
||||
if (link_stat(f_name(&hlink_list[i-1]),&st1) != 0) return;
|
||||
|
||||
if (link_stat(f_name(&hlink_list[i]),&st2) != 0) {
|
||||
if (do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"link %s => %s : %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i-1]),strerror(errno));
|
||||
return;
|
||||
if (statret == 0) {
|
||||
if (st->st_dev == to_st->st_dev
|
||||
&& st->st_ino == to_st->st_ino) {
|
||||
if (itemizing) {
|
||||
itemize(file, ndx, statret, st,
|
||||
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
|
||||
0, "");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (st2.st_dev == st1.st_dev && st2.st_ino == st1.st_ino) return;
|
||||
|
||||
if (robust_unlink(f_name(&hlink_list[i])) != 0 ||
|
||||
do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"link %s => %s : %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i-1]),strerror(errno));
|
||||
return;
|
||||
if (make_backups) {
|
||||
if (!make_backup(fname))
|
||||
return -1;
|
||||
} else if (robust_unlink(fname)) {
|
||||
rsyserr(FERROR, errno, "unlink %s failed",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"%s => %s\n",
|
||||
f_name(&hlink_list[i]),f_name(&hlink_list[i-1]));
|
||||
return hard_link_one(file, ndx, fname, statret, st, toname,
|
||||
0, itemizing, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* create any hard links in the flist */
|
||||
void do_hard_links(struct file_list *flist)
|
||||
int hard_link_check(struct file_struct *file, int ndx, char *fname,
|
||||
int statret, STRUCT_STAT *st, int itemizing,
|
||||
enum logcode code, int skip)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int i;
|
||||
|
||||
if (!hlink_list) return;
|
||||
|
||||
for (i=1;i<hlink_count;i++) {
|
||||
if (S_ISREG(hlink_list[i].mode) &&
|
||||
S_ISREG(hlink_list[i-1].mode) &&
|
||||
hlink_list[i].basename && hlink_list[i-1].basename &&
|
||||
hlink_list[i].dev == hlink_list[i-1].dev &&
|
||||
hlink_list[i].inode == hlink_list[i-1].inode) {
|
||||
hard_link_one(i);
|
||||
}
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
int head;
|
||||
if (skip && !(file->flags & FLAG_HLINK_EOL))
|
||||
head = hlink_list[file->F_HLINDEX] = file->F_NEXT;
|
||||
else
|
||||
head = hlink_list[file->F_HLINDEX];
|
||||
if (ndx != head) {
|
||||
struct file_struct *head_file = FPTR(head);
|
||||
if (!log_format_has_i && verbose > 1) {
|
||||
rprintf(FINFO, "\"%s\" is a hard link\n",
|
||||
f_name(file, NULL));
|
||||
}
|
||||
if (head_file->F_HLINDEX == FINISHED_LINK) {
|
||||
STRUCT_STAT st2, st3;
|
||||
char *toname = f_name(head_file, NULL);
|
||||
if (link_stat(toname, &st2, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
full_fname(toname));
|
||||
return -1;
|
||||
}
|
||||
if (statret < 0 && basis_dir[0] != NULL) {
|
||||
char cmpbuf[MAXPATHLEN];
|
||||
int j = 0;
|
||||
do {
|
||||
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
|
||||
if (link_stat(cmpbuf, &st3, 0) < 0)
|
||||
continue;
|
||||
if (link_dest) {
|
||||
if (st2.st_dev != st3.st_dev
|
||||
|| st2.st_ino != st3.st_ino)
|
||||
continue;
|
||||
statret = 1;
|
||||
st = &st3;
|
||||
if (verbose < 2 || !log_format_has_i)
|
||||
itemizing = code = 0;
|
||||
break;
|
||||
}
|
||||
if (!unchanged_file(cmpbuf, file, &st3))
|
||||
continue;
|
||||
statret = 1;
|
||||
st = &st3;
|
||||
if (unchanged_attrs(file, &st3))
|
||||
break;
|
||||
} while (basis_dir[++j] != NULL);
|
||||
}
|
||||
maybe_hard_link(file, ndx, fname, statret, st,
|
||||
toname, &st2, itemizing, code);
|
||||
file->F_HLINDEX = FINISHED_LINK;
|
||||
} else
|
||||
file->F_HLINDEX = SKIPPED_LINK;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
int hard_link_one(struct file_struct *file, int ndx, char *fname,
|
||||
int statret, STRUCT_STAT *st, char *toname, int terse,
|
||||
int itemizing, enum logcode code)
|
||||
{
|
||||
if (do_link(toname, fname)) {
|
||||
if (terse) {
|
||||
if (!verbose)
|
||||
return -1;
|
||||
code = FINFO;
|
||||
} else
|
||||
code = FERROR;
|
||||
rsyserr(code, errno, "link %s => %s failed",
|
||||
full_fname(fname), toname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (itemizing) {
|
||||
itemize(file, ndx, statret, st,
|
||||
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
|
||||
terse ? "" : toname);
|
||||
}
|
||||
if (code && verbose && !terse)
|
||||
rprintf(code, "%s => %s\n", fname, toname);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void hard_link_cluster(struct file_struct *file, int master, int itemizing,
|
||||
enum logcode code)
|
||||
{
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
char hlink1[MAXPATHLEN];
|
||||
char *hlink2;
|
||||
STRUCT_STAT st1, st2;
|
||||
int statret, ndx = master;
|
||||
|
||||
file->F_HLINDEX = FINISHED_LINK;
|
||||
if (link_stat(f_name(file, hlink1), &st1, 0) < 0)
|
||||
return;
|
||||
if (!(file->flags & FLAG_HLINK_TOL)) {
|
||||
while (!(file->flags & FLAG_HLINK_EOL)) {
|
||||
ndx = file->F_NEXT;
|
||||
file = FPTR(ndx);
|
||||
}
|
||||
}
|
||||
do {
|
||||
ndx = file->F_NEXT;
|
||||
file = FPTR(ndx);
|
||||
if (file->F_HLINDEX != SKIPPED_LINK)
|
||||
continue;
|
||||
hlink2 = f_name(file, NULL);
|
||||
statret = link_stat(hlink2, &st2, 0);
|
||||
maybe_hard_link(file, ndx, hlink2, statret, &st2,
|
||||
hlink1, &st1, itemizing, code);
|
||||
file->F_HLINDEX = FINISHED_LINK;
|
||||
} while (!(file->flags & FLAG_HLINK_EOL));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ else
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
|
||||
@@ -1,49 +1 @@
|
||||
.cvsignore
|
||||
Makefile
|
||||
a
|
||||
b
|
||||
config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
dist.tar.gz
|
||||
dummy
|
||||
rsync
|
||||
rsync-0.1
|
||||
rsync-0.1
|
||||
rsync-0.1
|
||||
rsync-0.1.tar.gz
|
||||
rsync-0.2
|
||||
rsync-0.2
|
||||
rsync-0.2.tar.gz
|
||||
rsync-0.3
|
||||
rsync-0.3
|
||||
rsync-0.3.tar.gz
|
||||
rsync-0.4
|
||||
rsync-0.4
|
||||
rsync-0.4.tar.gz
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5.tar.gz
|
||||
rsync-0.6
|
||||
rsync-0.7
|
||||
rsync-0.7
|
||||
rsync-0.8
|
||||
rsync-0.8
|
||||
rsync-0.8
|
||||
rsync-0.8
|
||||
rsync-ERSION
|
||||
rsync.aux
|
||||
rsync.dvi
|
||||
rsync.log
|
||||
tech_report.aux
|
||||
tech_report.dvi
|
||||
tech_report.log
|
||||
tech_report.ps
|
||||
test
|
||||
|
||||
125
lib/compat.c
125
lib/compat.c
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
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
|
||||
@@ -16,11 +17,15 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
compatibility functions - replacing functions for platforms that don't
|
||||
have them.
|
||||
/**
|
||||
* @file compat.c
|
||||
*
|
||||
* Reimplementations of standard functions for platforms that don't
|
||||
* have them.
|
||||
**/
|
||||
|
||||
|
||||
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
|
||||
@@ -78,9 +83,11 @@
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRPBRK
|
||||
/* Find the first ocurrence in S of any character in ACCEPT.
|
||||
derived from glibc
|
||||
*/
|
||||
/**
|
||||
* Find the first ocurrence in @p s of any character in @p accept.
|
||||
*
|
||||
* Derived from glibc
|
||||
**/
|
||||
char *strpbrk(const char *s, const char *accept)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
@@ -95,53 +102,103 @@
|
||||
}
|
||||
#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
|
||||
slprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
|
||||
#else
|
||||
slprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/* like strncpy but does not 0 fill the buffer and always null
|
||||
terminates. bufsize is the size of the destination buffer */
|
||||
/**
|
||||
* Like strncpy but does not 0 fill the buffer and always null
|
||||
* terminates.
|
||||
*
|
||||
* @param bufsize is the size of the destination buffer.
|
||||
*
|
||||
* @return index of the terminating byte.
|
||||
**/
|
||||
size_t strlcpy(char *d, const char *s, size_t bufsize)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
size_t ret = len;
|
||||
if (len >= bufsize) len = bufsize-1;
|
||||
memcpy(d, s, len);
|
||||
d[len] = 0;
|
||||
if (bufsize > 0) {
|
||||
if (len >= bufsize)
|
||||
len = bufsize-1;
|
||||
memcpy(d, s, len);
|
||||
d[len] = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
/* like strncat but does not 0 fill the buffer and always null
|
||||
terminates. bufsize is the length of the buffer, which should
|
||||
be one more than the maximum resulting string length */
|
||||
/**
|
||||
* 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
|
||||
* the maximum resulting string length.
|
||||
**/
|
||||
size_t strlcat(char *d, const char *s, size_t bufsize)
|
||||
{
|
||||
size_t len1 = strlen(d);
|
||||
size_t len2 = strlen(s);
|
||||
size_t ret = len1 + len2;
|
||||
|
||||
if (len1+len2 >= bufsize) {
|
||||
len2 = bufsize - (len1+1);
|
||||
}
|
||||
if (len2 > 0) {
|
||||
if (len1 < bufsize - 1) {
|
||||
if (len2 >= bufsize - len1)
|
||||
len2 = bufsize - len1 - 1;
|
||||
memcpy(d+len1, s, len2);
|
||||
d[len1+len2] = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#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];
|
||||
#ifdef 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)
|
||||
{
|
||||
#ifdef HAVE_GETTIMEOFDAY_TZ
|
||||
return gettimeofday(tv, NULL);
|
||||
#else
|
||||
return gettimeofday(tv);
|
||||
#endif
|
||||
}
|
||||
|
||||
204
lib/fnmatch.c
204
lib/fnmatch.c
@@ -1,204 +0,0 @@
|
||||
#include "../rsync.h"
|
||||
#ifndef HAVE_FNMATCH
|
||||
|
||||
/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#if defined (STDC_HEADERS) || !defined (isascii)
|
||||
#define ISASCII(c) 1
|
||||
#else
|
||||
#define ISASCII(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#define ISUPPER(c) (ISASCII (c) && isupper (c))
|
||||
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, nonzero if not. */
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
const char *pattern;
|
||||
const char *string;
|
||||
int flags;
|
||||
{
|
||||
register const char *p = pattern, *n = string;
|
||||
register char c;
|
||||
|
||||
/* Note that this evalutes C many times. */
|
||||
#define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
c = FOLD (c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_FILE_NAME) && *n == '/')
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
{
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (FOLD (*n) != c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
|
||||
if (((flags & FNM_FILE_NAME) && *n == '/') ||
|
||||
(c == '?' && *n == '\0'))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (c == '\0')
|
||||
return 0;
|
||||
|
||||
{
|
||||
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
|
||||
c1 = FOLD (c1);
|
||||
for (--p; *n != '\0'; ++n)
|
||||
if ((c == '[' || FOLD (*n) == c1) &&
|
||||
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
|
||||
return 0;
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
case '[':
|
||||
{
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
register int not;
|
||||
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
not = (*p == '!' || *p == '^');
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
register char cstart = c, cend = c;
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
cstart = cend = *p++;
|
||||
|
||||
cstart = cend = FOLD (cstart);
|
||||
|
||||
if (c == '\0')
|
||||
/* [ (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
|
||||
if ((flags & FNM_FILE_NAME) && c == '/')
|
||||
/* [/] can never match. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (c == '-' && *p != ']')
|
||||
{
|
||||
cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return FNM_NOMATCH;
|
||||
cend = FOLD (cend);
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
|
||||
goto matched;
|
||||
|
||||
if (c == ']')
|
||||
break;
|
||||
}
|
||||
if (!not)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
matched:;
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
while (c != ']')
|
||||
{
|
||||
if (c == '\0')
|
||||
/* [... (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
if (not)
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c != FOLD (*n))
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
if (*n == '\0')
|
||||
return 0;
|
||||
|
||||
if ((flags & FNM_LEADING_DIR) && *n == '/')
|
||||
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
|
||||
return 0;
|
||||
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
#else /* HAVE_FNMATCH */
|
||||
void fnmatch_dummy(void) {}
|
||||
#endif
|
||||
@@ -1,69 +0,0 @@
|
||||
/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
|
||||
#undef __P
|
||||
#define __P(protos) protos
|
||||
#else /* Not C++ or ANSI C. */
|
||||
#undef __P
|
||||
#define __P(protos) ()
|
||||
/* We can get away without defining `const' here only because in this file
|
||||
it is used only inside the prototype for `fnmatch', which is elided in
|
||||
non-ANSI C where `const' is problematical. */
|
||||
#endif /* C++ or ANSI C. */
|
||||
|
||||
|
||||
/* We #undef these before defining them because some losing systems
|
||||
(HP-UX A.08.07 for example) define these in <unistd.h>. */
|
||||
#undef FNM_PATHNAME
|
||||
#undef FNM_NOESCAPE
|
||||
#undef FNM_PERIOD
|
||||
|
||||
/* Bits set in the FLAGS argument to `fnmatch'. */
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
|
||||
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
|
||||
|
||||
#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
|
||||
#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#endif
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch __P ((const char *__pattern, const char *__string,
|
||||
int __flags));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* fnmatch.h */
|
||||
751
lib/getopt.c
751
lib/getopt.c
@@ -1,751 +0,0 @@
|
||||
#include "../rsync.h"
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
|
||||
/* Getopt for GNU.
|
||||
NOTE: getopt is now part of the C library, so if you don't know what
|
||||
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
|
||||
before changing it!
|
||||
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
|
||||
Ditto for AIX 3.2 and <stdlib.h>. */
|
||||
#ifndef _NO_PROTO
|
||||
#define _NO_PROTO
|
||||
#endif
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
|
||||
|
||||
/* This is for other GNU distributions with internationalized messages.
|
||||
The GNU C Library itself does not yet support such messages. */
|
||||
#if HAVE_LIBINTL_H
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(msgid) (msgid)
|
||||
#endif
|
||||
|
||||
/* This version of `getopt' appears to the caller like standard Unix `getopt'
|
||||
but it behaves differently for the user, since it allows the user
|
||||
to intersperse the options with the other arguments.
|
||||
|
||||
As `getopt' works, it permutes the elements of ARGV so that,
|
||||
when it is done, all the options precede everything else. Thus
|
||||
all application programs are extended to handle flexible argument order.
|
||||
|
||||
Setting the environment variable POSIXLY_CORRECT disables permutation.
|
||||
Then the behavior is completely standard.
|
||||
|
||||
GNU application programs can use a third alternative mode in which
|
||||
they can distinguish the relative order of options and other arguments. */
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
char *optarg = NULL;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
/* XXX 1003.2 says this must be 1 before any call. */
|
||||
int optind = 0;
|
||||
|
||||
/* The next char to be scanned in the option-element
|
||||
in which the last option character we returned was found.
|
||||
This allows us to pick up the scan where we left off.
|
||||
|
||||
If this is zero, or a null string, it means resume the scan
|
||||
by advancing to the next ARGV-element. */
|
||||
|
||||
static char *nextchar;
|
||||
|
||||
/* Callers store zero here to inhibit the error message
|
||||
for unrecognized options. */
|
||||
|
||||
int opterr = 1;
|
||||
|
||||
/* Set to an option character which was unrecognized.
|
||||
This must be initialized on some systems to avoid linking in the
|
||||
system's own getopt implementation. */
|
||||
|
||||
int optopt = '?';
|
||||
|
||||
/* Describe how to deal with options that follow non-option ARGV-elements.
|
||||
|
||||
If the caller did not specify anything,
|
||||
the default is REQUIRE_ORDER if the environment variable
|
||||
POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
||||
|
||||
REQUIRE_ORDER means don't recognize them as options;
|
||||
stop option processing when the first non-option is seen.
|
||||
This is what Unix does.
|
||||
This mode of operation is selected by either setting the environment
|
||||
variable POSIXLY_CORRECT, or using `+' as the first character
|
||||
of the list of option characters.
|
||||
|
||||
PERMUTE is the default. We permute the contents of ARGV as we scan,
|
||||
so that eventually all the non-options are at the end. This allows options
|
||||
to be given in any order, even with programs that were not written to
|
||||
expect this.
|
||||
|
||||
RETURN_IN_ORDER is an option available to programs that were written
|
||||
to expect options and other ARGV-elements in any order and that care about
|
||||
the ordering of the two. We describe each non-option ARGV-element
|
||||
as if it were the argument of an option with character code 1.
|
||||
Using `-' as the first character of the list of option characters
|
||||
selects this mode of operation.
|
||||
|
||||
The special argument `--' forces an end of option-scanning regardless
|
||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
|
||||
|
||||
static enum
|
||||
{
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||
} ordering;
|
||||
|
||||
/* Value of POSIXLY_CORRECT environment variable. */
|
||||
static char *posixly_correct;
|
||||
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* We want to avoid inclusion of string.h with non-GNU libraries
|
||||
because there are many ways it can cause trouble.
|
||||
On some systems, it contains special magic macros that don't work
|
||||
in GCC. */
|
||||
#include <string.h>
|
||||
#define my_index strchr
|
||||
#else
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
char *getenv ();
|
||||
|
||||
static char *
|
||||
my_index (str, chr)
|
||||
const char *str;
|
||||
int chr;
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
if (*str == chr)
|
||||
return (char *) str;
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If using GCC, we can safely declare strlen this way.
|
||||
If not using GCC, it is ok not to declare it. */
|
||||
#ifdef __GNUC__
|
||||
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
|
||||
That was relevant to code that was here before. */
|
||||
#if !defined (__STDC__) || !__STDC__
|
||||
/* gcc with -traditional declares the built-in strlen to return int,
|
||||
and has done so at least since version 2.4.5. -- rms. */
|
||||
extern int strlen (const char *);
|
||||
#endif /* not __STDC__ */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* not __GNU_LIBRARY__ */
|
||||
|
||||
/* Handle permutation of arguments. */
|
||||
|
||||
/* Describe the part of ARGV that contains non-options that have
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first of them;
|
||||
`last_nonopt' is the index after the last of them. */
|
||||
|
||||
static int first_nonopt;
|
||||
static int last_nonopt;
|
||||
|
||||
/* Exchange two adjacent subsequences of ARGV.
|
||||
One subsequence is elements [first_nonopt,last_nonopt)
|
||||
which contains all the non-options that have been skipped so far.
|
||||
The other is elements [last_nonopt,optind), which contains all
|
||||
the options processed since those non-options were skipped.
|
||||
|
||||
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
||||
the new indices of the non-options in ARGV after they are moved. */
|
||||
|
||||
static void
|
||||
exchange (argv)
|
||||
char **argv;
|
||||
{
|
||||
int bottom = first_nonopt;
|
||||
int middle = last_nonopt;
|
||||
int top = optind;
|
||||
char *tem;
|
||||
|
||||
/* Exchange the shorter segment with the far end of the longer segment.
|
||||
That puts the shorter segment into the right place.
|
||||
It leaves the longer segment in the right place overall,
|
||||
but it consists of two parts that need to be swapped next. */
|
||||
|
||||
while (top > middle && middle > bottom)
|
||||
{
|
||||
if (top - middle > middle - bottom)
|
||||
{
|
||||
/* Bottom segment is the short one. */
|
||||
int len = middle - bottom;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the top part of the top segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
||||
argv[top - (middle - bottom) + i] = tem;
|
||||
}
|
||||
/* Exclude the moved bottom segment from further swapping. */
|
||||
top -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Top segment is the short one. */
|
||||
int len = top - middle;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the bottom part of the bottom segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[middle + i];
|
||||
argv[middle + i] = tem;
|
||||
}
|
||||
/* Exclude the moved top segment from further swapping. */
|
||||
bottom += len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update records for the slots the non-options now occupy. */
|
||||
|
||||
first_nonopt += (optind - last_nonopt);
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* Initialize the internal data when the first call is made. */
|
||||
|
||||
static const char *
|
||||
_getopt_initialize (optstring)
|
||||
const char *optstring;
|
||||
{
|
||||
/* Start processing options with ARGV-element 1 (since ARGV-element 0
|
||||
is the program name); the sequence of previously skipped
|
||||
non-option ARGV-elements is empty. */
|
||||
|
||||
first_nonopt = last_nonopt = optind = 1;
|
||||
|
||||
nextchar = NULL;
|
||||
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT");
|
||||
|
||||
/* Determine how to handle the ordering of options and nonoptions. */
|
||||
|
||||
if (optstring[0] == '-')
|
||||
{
|
||||
ordering = RETURN_IN_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (optstring[0] == '+')
|
||||
{
|
||||
ordering = REQUIRE_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (posixly_correct != NULL)
|
||||
ordering = REQUIRE_ORDER;
|
||||
else
|
||||
ordering = PERMUTE;
|
||||
|
||||
return optstring;
|
||||
}
|
||||
|
||||
/* Scan elements of ARGV (whose length is ARGC) for option characters
|
||||
given in OPTSTRING.
|
||||
|
||||
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
||||
then it is an option element. The characters of this element
|
||||
(aside from the initial '-') are option characters. If `getopt'
|
||||
is called repeatedly, it returns successively each of the option characters
|
||||
from each of the option elements.
|
||||
|
||||
If `getopt' finds another option character, it returns that character,
|
||||
updating `optind' and `nextchar' so that the next call to `getopt' can
|
||||
resume the scan with the following option character or ARGV-element.
|
||||
|
||||
If there are no more option characters, `getopt' returns `EOF'.
|
||||
Then `optind' is the index in ARGV of the first ARGV-element
|
||||
that is not an option. (The ARGV-elements have been permuted
|
||||
so that those that are not options now come last.)
|
||||
|
||||
OPTSTRING is a string containing the legitimate option characters.
|
||||
If an option character is seen that is not listed in OPTSTRING,
|
||||
return '?' after printing an error message. If you set `opterr' to
|
||||
zero, the error message is suppressed but we still return '?'.
|
||||
|
||||
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
||||
so the following text in the same ARGV-element, or the text of the following
|
||||
ARGV-element, is returned in `optarg'. Two colons mean an option that
|
||||
wants an optional arg; if there is text in the current ARGV-element,
|
||||
it is returned in `optarg', otherwise `optarg' is set to zero.
|
||||
|
||||
If OPTSTRING starts with `-' or `+', it requests different methods of
|
||||
handling the non-option ARGV-elements.
|
||||
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
|
||||
|
||||
Long-named options begin with `--' instead of `-'.
|
||||
Their names may be abbreviated as long as the abbreviation is unique
|
||||
or is an exact match for some defined option. If they have an
|
||||
argument, it follows the option name in the same ARGV-element, separated
|
||||
from the option name by a `=', or else the in next ARGV-element.
|
||||
When `getopt' finds a long-named option, it returns 0 if that option's
|
||||
`flag' field is nonzero, the value of the option's `val' field
|
||||
if the `flag' field is zero.
|
||||
|
||||
The elements of ARGV aren't really const, because we permute them.
|
||||
But we pretend they're const in the prototype to be compatible
|
||||
with other systems.
|
||||
|
||||
LONGOPTS is a vector of `struct option' terminated by an
|
||||
element containing a name which is zero.
|
||||
|
||||
LONGIND returns the index in LONGOPT of the long-named option found.
|
||||
It is only valid when a long-named option has been found by the most
|
||||
recent call.
|
||||
|
||||
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
|
||||
long-named options. */
|
||||
|
||||
int
|
||||
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
const struct option *longopts;
|
||||
int *longind;
|
||||
int long_only;
|
||||
{
|
||||
optarg = NULL;
|
||||
|
||||
if (optind == 0)
|
||||
optstring = _getopt_initialize (optstring);
|
||||
|
||||
if (nextchar == NULL || *nextchar == '\0')
|
||||
{
|
||||
/* Advance to the next ARGV-element. */
|
||||
|
||||
if (ordering == PERMUTE)
|
||||
{
|
||||
/* If we have just processed some options following some non-options,
|
||||
exchange them so that the options come first. */
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (last_nonopt != optind)
|
||||
first_nonopt = optind;
|
||||
|
||||
/* Skip any additional non-options
|
||||
and extend the range of non-options previously skipped. */
|
||||
|
||||
while (optind < argc
|
||||
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
optind++;
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* The special ARGV-element `--' means premature end of options.
|
||||
Skip it like a null option,
|
||||
then exchange with previous non-options as if it were an option,
|
||||
then skip everything else like a non-option. */
|
||||
|
||||
if (optind != argc && !strcmp (argv[optind], "--"))
|
||||
{
|
||||
optind++;
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (first_nonopt == last_nonopt)
|
||||
first_nonopt = optind;
|
||||
last_nonopt = argc;
|
||||
|
||||
optind = argc;
|
||||
}
|
||||
|
||||
/* If we have done all the ARGV-elements, stop the scan
|
||||
and back over any non-options that we skipped and permuted. */
|
||||
|
||||
if (optind == argc)
|
||||
{
|
||||
/* Set the next-arg-index to point at the non-options
|
||||
that we previously skipped, so the caller will digest them. */
|
||||
if (first_nonopt != last_nonopt)
|
||||
optind = first_nonopt;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* If we have come to a non-option and did not permute it,
|
||||
either stop the scan or describe it to the caller and pass it by. */
|
||||
|
||||
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
{
|
||||
if (ordering == REQUIRE_ORDER)
|
||||
return EOF;
|
||||
optarg = argv[optind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have found another option-ARGV-element.
|
||||
Skip the initial punctuation. */
|
||||
|
||||
nextchar = (argv[optind] + 1
|
||||
+ (longopts != NULL && argv[optind][1] == '-'));
|
||||
}
|
||||
|
||||
/* Decode the current option-ARGV-element. */
|
||||
|
||||
/* Check whether the ARGV-element is a long option.
|
||||
|
||||
If long_only and the ARGV-element has the form "-f", where f is
|
||||
a valid short option, don't consider it an abbreviated form of
|
||||
a long option that starts with f. Otherwise there would be no
|
||||
way to give the -f short option.
|
||||
|
||||
On the other hand, if there's a long option "fubar" and
|
||||
the ARGV-element is "-fu", do consider that an abbreviation of
|
||||
the long option, just like "--fu", and not "-f" with arg "u".
|
||||
|
||||
This distinction seems to be the most useful approach. */
|
||||
|
||||
if (longopts != NULL
|
||||
&& (argv[optind][1] == '-'
|
||||
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
|
||||
{
|
||||
char *nameend;
|
||||
const struct option *p;
|
||||
const struct option *pfound = NULL;
|
||||
int exact = 0;
|
||||
int ambig = 0;
|
||||
int indfound;
|
||||
int option_index;
|
||||
|
||||
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
|
||||
/* Do nothing. */ ;
|
||||
|
||||
/* Test all long options for either exact match
|
||||
or abbreviated matches. */
|
||||
for (p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
||||
{
|
||||
if (nameend - nextchar == strlen (p->name))
|
||||
{
|
||||
/* Exact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
exact = 1;
|
||||
break;
|
||||
}
|
||||
else if (pfound == NULL)
|
||||
{
|
||||
/* First nonexact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
}
|
||||
else
|
||||
/* Second or later nonexact match found. */
|
||||
ambig = 1;
|
||||
}
|
||||
|
||||
if (ambig && !exact)
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr, gettext ("%s: option `%s' is ambiguous\n"),
|
||||
argv[0], argv[optind]);
|
||||
nextchar += strlen (nextchar);
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
|
||||
if (pfound != NULL)
|
||||
{
|
||||
option_index = indfound;
|
||||
optind++;
|
||||
if (*nameend)
|
||||
{
|
||||
/* Don't test has_arg with >, because some C compilers don't
|
||||
allow it to be used on enums. */
|
||||
if (pfound->has_arg)
|
||||
optarg = nameend + 1;
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
if (argv[optind - 1][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr,
|
||||
gettext ("%s: option `--%s' doesn't allow an argument\n"),
|
||||
argv[0], pfound->name);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr,
|
||||
gettext ("%s: option `%c%s' doesn't allow an argument\n"),
|
||||
argv[0], argv[optind - 1][0], pfound->name);
|
||||
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
else if (pfound->has_arg == 1)
|
||||
{
|
||||
if (optind < argc)
|
||||
optarg = argv[optind++];
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr,
|
||||
gettext ("%s: option `%s' requires an argument\n"),
|
||||
argv[0], argv[optind - 1]);
|
||||
nextchar += strlen (nextchar);
|
||||
return optstring[0] == ':' ? ':' : '?';
|
||||
}
|
||||
}
|
||||
nextchar += strlen (nextchar);
|
||||
if (longind != NULL)
|
||||
*longind = option_index;
|
||||
if (pfound->flag)
|
||||
{
|
||||
*(pfound->flag) = pfound->val;
|
||||
return 0;
|
||||
}
|
||||
return pfound->val;
|
||||
}
|
||||
|
||||
/* Can't find it as a long option. If this is not getopt_long_only,
|
||||
or the option starts with '--' or is not a valid short
|
||||
option, then it's an error.
|
||||
Otherwise interpret it as a short option. */
|
||||
if (!long_only || argv[optind][1] == '-'
|
||||
|| my_index (optstring, *nextchar) == NULL)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr, gettext ("%s: unrecognized option `--%s'\n"),
|
||||
argv[0], nextchar);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr, gettext ("%s: unrecognized option `%c%s'\n"),
|
||||
argv[0], argv[optind][0], nextchar);
|
||||
}
|
||||
nextchar = (char *) "";
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at and handle the next short option-character. */
|
||||
|
||||
{
|
||||
char c = *nextchar++;
|
||||
char *temp = my_index (optstring, c);
|
||||
|
||||
/* Increment `optind' when we start to process its last character. */
|
||||
if (*nextchar == '\0')
|
||||
++optind;
|
||||
|
||||
if (temp == NULL || c == ':')
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (posixly_correct)
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr, gettext ("%s: illegal option -- %c\n"),
|
||||
argv[0], c);
|
||||
else
|
||||
fprintf (stderr, gettext ("%s: invalid option -- %c\n"),
|
||||
argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
return '?';
|
||||
}
|
||||
if (temp[1] == ':')
|
||||
{
|
||||
if (temp[2] == ':')
|
||||
{
|
||||
/* This is an option that accepts an argument optionally. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
optind++;
|
||||
}
|
||||
else
|
||||
optarg = NULL;
|
||||
nextchar = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an option that requires an argument. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
/* If we end this ARGV-element by taking the rest as an arg,
|
||||
we must advance to the next element now. */
|
||||
optind++;
|
||||
}
|
||||
else if (optind == argc)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr,
|
||||
gettext ("%s: option requires an argument -- %c\n"),
|
||||
argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
if (optstring[0] == ':')
|
||||
c = ':';
|
||||
else
|
||||
c = '?';
|
||||
}
|
||||
else
|
||||
/* We already incremented `optind' once;
|
||||
increment it again when taking next ARGV-elt as argument. */
|
||||
optarg = argv[optind++];
|
||||
nextchar = NULL;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getopt (argc, argv, optstring)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
{
|
||||
return _getopt_internal (argc, argv, optstring,
|
||||
(const struct option *) 0,
|
||||
(int *) 0,
|
||||
0);
|
||||
}
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/* Compile with -DTEST to make an executable for use in testing
|
||||
the above definition of `getopt'. */
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
|
||||
c = getopt (argc, argv, "abc:d:0123456789");
|
||||
if (c == EOF)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
||||
#else /* HAVE_GETOPT_LONG */
|
||||
void getopt_dummy(void) {}
|
||||
#endif
|
||||
129
lib/getopt.h
129
lib/getopt.h
@@ -1,129 +0,0 @@
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
#define _GETOPT_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
#if defined (__STDC__) && __STDC__
|
||||
const char *name;
|
||||
#else
|
||||
char *name;
|
||||
#endif
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
#if defined (__STDC__) && __STDC__
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* Many other libraries have conflicting prototypes for getopt, with
|
||||
differences in the consts, in stdlib.h. To avoid compilation
|
||||
errors, only prototype getopt for the GNU C library. */
|
||||
extern int getopt (int argc, char *const *argv, const char *shortopts);
|
||||
#else /* not __GNU_LIBRARY__ */
|
||||
extern int getopt ();
|
||||
#endif /* __GNU_LIBRARY__ */
|
||||
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
extern int getopt_long_only (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
|
||||
/* Internal only. Users should not call this directly. */
|
||||
extern int _getopt_internal (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind,
|
||||
int long_only);
|
||||
#else /* not __STDC__ */
|
||||
extern int getopt ();
|
||||
extern int getopt_long ();
|
||||
extern int getopt_long_only ();
|
||||
|
||||
extern int _getopt_internal ();
|
||||
#endif /* __STDC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GETOPT_H */
|
||||
184
lib/inet_ntop.c
Normal file
184
lib/inet_ntop.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 1996-2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#define NS_INT16SZ 2
|
||||
#define NS_IN6ADDRSZ 16
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static const char *inet_ntop4(const unsigned char *src, char *dst,
|
||||
size_t size);
|
||||
|
||||
#ifdef AF_INET6
|
||||
static const char *inet_ntop6(const unsigned char *src, char *dst,
|
||||
size_t size);
|
||||
#endif
|
||||
|
||||
/* char *
|
||||
* isc_net_ntop(af, src, dst, size)
|
||||
* convert a network format address to presentation format.
|
||||
* return:
|
||||
* pointer to presentation format address (`dst'), or NULL (see errno).
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
const char *
|
||||
inet_ntop(int af, const void *src, char *dst, size_t size)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_ntop4(src, dst, size));
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
return (inet_ntop6(src, dst, size));
|
||||
#endif
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* inet_ntop4(src, dst, size)
|
||||
* format an IPv4 address
|
||||
* return:
|
||||
* `dst' (as a const)
|
||||
* notes:
|
||||
* (1) uses no statics
|
||||
* (2) takes a unsigned char* not an in_addr as input
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static const char *
|
||||
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"];
|
||||
|
||||
if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
|
||||
{
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
|
||||
return (dst);
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* isc_inet_ntop6(src, dst, size)
|
||||
* convert IPv6 binary address into presentation (printable) format
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
#ifdef AF_INET6
|
||||
static const char *
|
||||
inet_ntop6(const unsigned char *src, char *dst, size_t size)
|
||||
{
|
||||
/*
|
||||
* Note that int32_t and int16_t need only be "at least" large enough
|
||||
* to contain a value of the specified size. On some systems, like
|
||||
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||
* Keep this in mind if you think this function should have been coded
|
||||
* to use pointer overlays. All the world's not a VAX.
|
||||
*/
|
||||
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;
|
||||
|
||||
/*
|
||||
* Preprocess:
|
||||
* Copy the input (bytewise) array into a wordwise array.
|
||||
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||
*/
|
||||
memset(words, '\0', sizeof words);
|
||||
for (i = 0; i < NS_IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
cur.base = -1;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
cur.base = i, cur.len = 1;
|
||||
else
|
||||
cur.len++;
|
||||
} else {
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
cur.base = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
}
|
||||
if (best.base != -1 && best.len < 2)
|
||||
best.base = -1;
|
||||
|
||||
/*
|
||||
* Format the result.
|
||||
*/
|
||||
tp = tmp;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
/* Are we inside the best run of 0x00's? */
|
||||
if (best.base != -1 && i >= best.base &&
|
||||
i < (best.base + best.len)) {
|
||||
if (i == best.base)
|
||||
*tp++ = ':';
|
||||
continue;
|
||||
}
|
||||
/* Are we following an initial run of 0x00s or any real hex? */
|
||||
if (i != 0)
|
||||
*tp++ = ':';
|
||||
/* 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)))
|
||||
return (NULL);
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += sprintf(tp, "%x", words[i]);
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) ==
|
||||
(NS_IN6ADDRSZ / NS_INT16SZ))
|
||||
*tp++ = ':';
|
||||
*tp++ = '\0';
|
||||
|
||||
/*
|
||||
* Check for overflow, copy, and we're done.
|
||||
*/
|
||||
if ((size_t)(tp - tmp) > size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
#endif /* AF_INET6 */
|
||||
212
lib/inet_pton.c
Normal file
212
lib/inet_pton.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 1996-2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#define NS_INT16SZ 2
|
||||
#define NS_INADDRSZ 4
|
||||
#define NS_IN6ADDRSZ 16
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static int inet_pton4(const char *src, unsigned char *dst);
|
||||
#ifdef INET6
|
||||
static int inet_pton6(const char *src, unsigned char *dst);
|
||||
#endif
|
||||
|
||||
/* int
|
||||
* inet_pton(af, src, dst)
|
||||
* convert from presentation format (which usually means ASCII printable)
|
||||
* to network format (which is usually some kind of binary format).
|
||||
* return:
|
||||
* 1 if the address was valid for the specified address family
|
||||
* 0 if the address wasn't valid (`dst' is untouched in this case)
|
||||
* -1 if some other error occurred (`dst' is untouched in this case, too)
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
int
|
||||
inet_pton(int af,
|
||||
const char *src,
|
||||
void *dst)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_pton4(src, dst));
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
return (inet_pton6(src, dst));
|
||||
#endif
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton4(src, dst)
|
||||
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||
* return:
|
||||
* 1 if `src' is a valid dotted quad, else 0.
|
||||
* notice:
|
||||
* does not touch `dst' unless it's returning 1.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(src, dst)
|
||||
const char *src;
|
||||
unsigned char *dst;
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
unsigned char tmp[NS_INADDRSZ], *tp;
|
||||
|
||||
saw_digit = 0;
|
||||
octets = 0;
|
||||
*(tp = tmp) = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr(digits, ch)) != NULL) {
|
||||
unsigned int new = *tp * 10 + (pch - digits);
|
||||
|
||||
if (new > 255)
|
||||
return (0);
|
||||
*tp = new;
|
||||
if (! saw_digit) {
|
||||
if (++octets > 4)
|
||||
return (0);
|
||||
saw_digit = 1;
|
||||
}
|
||||
} else if (ch == '.' && saw_digit) {
|
||||
if (octets == 4)
|
||||
return (0);
|
||||
*++tp = 0;
|
||||
saw_digit = 0;
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
if (octets < 4)
|
||||
return (0);
|
||||
memcpy(dst, tmp, NS_INADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton6(src, dst)
|
||||
* convert presentation level address to network order binary form.
|
||||
* return:
|
||||
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
|
||||
* notice:
|
||||
* (1) does not touch `dst' unless it's returning 1.
|
||||
* (2) :: in a full address is silently ignored.
|
||||
* credit:
|
||||
* inspired by Mark Andrews.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
#ifdef INET6
|
||||
static int
|
||||
inet_pton6(src, dst)
|
||||
const char *src;
|
||||
unsigned char *dst;
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *xdigits, *curtok;
|
||||
int ch, saw_xdigit;
|
||||
unsigned int val;
|
||||
|
||||
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
|
||||
endp = tp + NS_IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
return (0);
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
return (0);
|
||||
colonp = tp;
|
||||
continue;
|
||||
}
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (unsigned char) (val >> 8) & 0xff;
|
||||
*tp++ = (unsigned char) val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
|
||||
inet_pton4(curtok, tp) > 0) {
|
||||
tp += NS_INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (unsigned char) (val >> 8) & 0xff;
|
||||
*tp++ = (unsigned char) val & 0xff;
|
||||
}
|
||||
if (colonp != NULL) {
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[- i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
if (tp != endp)
|
||||
return (0);
|
||||
memcpy(dst, tmp, NS_IN6ADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
97
lib/mdfour.c
97
lib/mdfour.c
@@ -28,30 +28,23 @@
|
||||
|
||||
static struct mdfour *m;
|
||||
|
||||
#define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z)))
|
||||
#define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)))
|
||||
#define H(X,Y,Z) ((X)^(Y)^(Z))
|
||||
#ifdef LARGE_INT32
|
||||
#define lshift(x,s) ((((x)<<(s))&0xFFFFFFFF) | (((x)>>(32-(s)))&0xFFFFFFFF))
|
||||
#else
|
||||
#define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s))))
|
||||
#endif
|
||||
#define MASK32 (0xffffffff)
|
||||
|
||||
#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
|
||||
#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s)
|
||||
#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s)
|
||||
#define F(X,Y,Z) ((((X)&(Y)) | ((~(X))&(Z))))
|
||||
#define G(X,Y,Z) ((((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))))
|
||||
#define H(X,Y,Z) (((X)^(Y)^(Z)))
|
||||
#define lshift(x,s) (((((x)<<(s))&MASK32) | (((x)>>(32-(s)))&MASK32)))
|
||||
|
||||
#define ROUND1(a,b,c,d,k,s) a = lshift((a + F(b,c,d) + M[k])&MASK32, s)
|
||||
#define ROUND2(a,b,c,d,k,s) a = lshift((a + G(b,c,d) + M[k] + 0x5A827999)&MASK32,s)
|
||||
#define ROUND3(a,b,c,d,k,s) a = lshift((a + H(b,c,d) + M[k] + 0x6ED9EBA1)&MASK32,s)
|
||||
|
||||
/* this applies md4 to 64 byte chunks */
|
||||
static void mdfour64(uint32 *M)
|
||||
{
|
||||
int j;
|
||||
uint32 AA, BB, CC, DD;
|
||||
uint32 X[16];
|
||||
uint32 A,B,C,D;
|
||||
|
||||
for (j=0;j<16;j++)
|
||||
X[j] = M[j];
|
||||
|
||||
A = m->A; B = m->B; C = m->C; D = m->D;
|
||||
AA = A; BB = B; CC = C; DD = D;
|
||||
|
||||
@@ -64,6 +57,7 @@ static void mdfour64(uint32 *M)
|
||||
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(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);
|
||||
@@ -82,15 +76,11 @@ static void mdfour64(uint32 *M)
|
||||
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; C += CC; D += DD;
|
||||
A += AA; B += BB;
|
||||
C += CC; D += DD;
|
||||
|
||||
#ifdef LARGE_INT32
|
||||
A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
|
||||
C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
|
||||
#endif
|
||||
|
||||
for (j=0;j<16;j++)
|
||||
X[j] = 0;
|
||||
A &= MASK32; B &= MASK32;
|
||||
C &= MASK32; D &= MASK32;
|
||||
|
||||
m->A = A; m->B = B; m->C = C; m->D = D;
|
||||
}
|
||||
@@ -119,29 +109,53 @@ void mdfour_begin(struct mdfour *md)
|
||||
md->C = 0x98badcfe;
|
||||
md->D = 0x10325476;
|
||||
md->totalN = 0;
|
||||
md->totalN2 = 0;
|
||||
}
|
||||
|
||||
|
||||
static void mdfour_tail(unsigned char *in, int n)
|
||||
static void mdfour_tail(unsigned char *in, uint32 n)
|
||||
{
|
||||
unsigned char buf[128];
|
||||
uint32 M[16];
|
||||
uint32 b;
|
||||
extern int protocol_version;
|
||||
|
||||
m->totalN += n;
|
||||
|
||||
b = m->totalN * 8;
|
||||
/*
|
||||
* Count total number of bits, modulo 2^64
|
||||
*/
|
||||
m->totalN += n << 3;
|
||||
if (m->totalN < (n << 3)) {
|
||||
m->totalN2++;
|
||||
}
|
||||
m->totalN2 += n >> 29;
|
||||
|
||||
memset(buf, 0, 128);
|
||||
if (n) memcpy(buf, in, n);
|
||||
buf[n] = 0x80;
|
||||
|
||||
if (n <= 55) {
|
||||
copy4(buf+56, b);
|
||||
copy4(buf+56, m->totalN);
|
||||
/*
|
||||
* Prior to protocol version 27 only the number of bits
|
||||
* modulo 2^32 was included. MD4 requires the number
|
||||
* of bits modulo 2^64, which was fixed starting with
|
||||
* protocol version 27.
|
||||
*/
|
||||
if (protocol_version >= 27) {
|
||||
copy4(buf+60, m->totalN2);
|
||||
}
|
||||
copy64(M, buf);
|
||||
mdfour64(M);
|
||||
} else {
|
||||
copy4(buf+120, b);
|
||||
copy4(buf+120, m->totalN);
|
||||
/*
|
||||
* Prior to protocol version 27 only the number of bits
|
||||
* modulo 2^32 was included. MD4 requires the number
|
||||
* of bits modulo 2^64, which was fixed starting with
|
||||
* protocol version 27.
|
||||
*/
|
||||
if (protocol_version >= 27) {
|
||||
copy4(buf+124, m->totalN2);
|
||||
}
|
||||
copy64(M, buf);
|
||||
mdfour64(M);
|
||||
copy64(M, buf+64);
|
||||
@@ -149,20 +163,23 @@ static void mdfour_tail(unsigned char *in, int n)
|
||||
}
|
||||
}
|
||||
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, int n)
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n)
|
||||
{
|
||||
uint32 M[16];
|
||||
|
||||
if (n == 0) mdfour_tail(in, n);
|
||||
|
||||
m = md;
|
||||
|
||||
if (n == 0) mdfour_tail(in, n);
|
||||
|
||||
while (n >= 64) {
|
||||
copy64(M, in);
|
||||
mdfour64(M);
|
||||
in += 64;
|
||||
n -= 64;
|
||||
m->totalN += 64;
|
||||
m->totalN += 64 << 3;
|
||||
if (m->totalN < 64 << 3) {
|
||||
m->totalN2++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n) mdfour_tail(in, n);
|
||||
@@ -189,9 +206,11 @@ void mdfour(unsigned char *out, unsigned char *in, int n)
|
||||
}
|
||||
|
||||
#ifdef TEST_MDFOUR
|
||||
int protocol_version = 28;
|
||||
|
||||
static void file_checksum1(char *fname)
|
||||
{
|
||||
int fd, i;
|
||||
int fd, i, was_multiple_of_64 = 1;
|
||||
struct mdfour md;
|
||||
unsigned char buf[64*1024], sum[16];
|
||||
|
||||
@@ -205,9 +224,13 @@ static void file_checksum1(char *fname)
|
||||
|
||||
while (1) {
|
||||
int n = read(fd, buf, sizeof(buf));
|
||||
if (n <= 0) break;
|
||||
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);
|
||||
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
|
||||
struct mdfour {
|
||||
uint32 A, B, C, D;
|
||||
uint32 totalN;
|
||||
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, int n);
|
||||
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);
|
||||
|
||||
|
||||
62
lib/permstring.c
Normal file
62
lib/permstring.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#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, 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];
|
||||
}
|
||||
|
||||
/* Handle setuid/sticky bits. You might think the indices are
|
||||
* off by one, but remember there's a type char at the
|
||||
* start. */
|
||||
if (mode & S_ISUID)
|
||||
perms[3] = (mode & S_IXUSR) ? 's' : 'S';
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
|
||||
3
lib/permstring.h
Normal file
3
lib/permstring.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#define PERMSTRING_SIZE 11
|
||||
|
||||
void permstring(char *perms, mode_t mode);
|
||||
199
lib/pool_alloc.3
Normal file
199
lib/pool_alloc.3
Normal file
@@ -0,0 +1,199 @@
|
||||
.ds d \-\^\-
|
||||
.ds o \fR[\fP
|
||||
.ds c \fR]\fP
|
||||
.ds | \fR|\fP
|
||||
.de D
|
||||
\\.B \*d\\$1
|
||||
..
|
||||
.de DI
|
||||
\\.BI \*d\\$1 \\$2
|
||||
..
|
||||
.de DR
|
||||
\\.BR \*d\\$1 \\$2
|
||||
..
|
||||
.de Di
|
||||
\\.BI \*d\\$1 " \\$2"
|
||||
..
|
||||
.de Db
|
||||
\\.B \*d\\$1 " \\$2"
|
||||
..
|
||||
.de Df
|
||||
\\.B \*d\*ono\*c\\$1
|
||||
..
|
||||
.de See
|
||||
See \fB\\$1\fP for details.
|
||||
..
|
||||
.de SeeIn
|
||||
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
|
||||
\- Allocate and free memory in managed allocation pools.
|
||||
.SH SYNOPSIS
|
||||
.B #include "pool_alloc.h"
|
||||
|
||||
\fBstruct alloc_pool *pool_create(size_t \fIsize\fB, size_t \fIquantum\fB, void (*\fIbomb\fB)(char *), int \fIflags\fB);
|
||||
|
||||
\fBvoid pool_destroy(struct alloc_pool *\fIpool\fB);
|
||||
|
||||
\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_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);
|
||||
.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()
|
||||
the allocations are not managed individually.
|
||||
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.
|
||||
.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
|
||||
.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.
|
||||
.P
|
||||
.B pool_create()
|
||||
Creates an allocation pool for subsequent calls to the pool
|
||||
allocation functions.
|
||||
When an extent is created for allocations it will be
|
||||
.I size
|
||||
bytes.
|
||||
Allocations from the pool have their sizes rounded up to a
|
||||
multiple of
|
||||
.I quantum
|
||||
bytes in length.
|
||||
Specifying
|
||||
.B 0
|
||||
for
|
||||
.I quantum
|
||||
Will produce a quantum that should meet maximal allignment
|
||||
on most platforms.
|
||||
If the
|
||||
.B POOL_QALIGN
|
||||
.I flag
|
||||
is set allocations will be aligned to addresses that are a
|
||||
multiple of
|
||||
.IR quantum .
|
||||
If the
|
||||
.B POOL_CLEAR
|
||||
.I flag
|
||||
is set all allocations from the pool will be zero filled.
|
||||
.P
|
||||
.B pool_destroy()
|
||||
destroys an allocation pool and frees all memory allocated
|
||||
in that pool.
|
||||
.P
|
||||
.B pool_alloc()
|
||||
allocates
|
||||
.I size
|
||||
bytes from the specified
|
||||
.IR pool .
|
||||
If
|
||||
.I size
|
||||
is
|
||||
.B 0
|
||||
.I quantum
|
||||
bytes will be freed.
|
||||
If the requested memory cannot be allocated
|
||||
.B pool_alloc()
|
||||
will call
|
||||
.I bomb()
|
||||
function, if defined, with
|
||||
.I msg
|
||||
as it's sole argument and
|
||||
.B NULL
|
||||
will be returned.
|
||||
.P
|
||||
.B pool_free()
|
||||
frees
|
||||
.I size
|
||||
bytes pointed to by
|
||||
.I addr
|
||||
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
|
||||
.I quantum
|
||||
bytes will be freed.
|
||||
If
|
||||
.I addr
|
||||
is
|
||||
.B 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
|
||||
and
|
||||
.I count
|
||||
instead of
|
||||
.I size
|
||||
and will cast the return value to the correct type.
|
||||
.P
|
||||
.B pool_tfree
|
||||
is a macro to free memory previously allocated in the
|
||||
specified
|
||||
.IR pool .
|
||||
.SH RETURN VALUE
|
||||
.B pool_create()
|
||||
returns a pointer to
|
||||
.BR "struct alloc_pool" .
|
||||
.P
|
||||
.B pool_alloc()
|
||||
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
|
||||
.B pool_talloc()
|
||||
will returns a pointer of the requested
|
||||
.IR type .
|
||||
.P
|
||||
.BR pool_free() ,
|
||||
.B pool_tfree()
|
||||
and
|
||||
.B pool_destroy()
|
||||
return no value.
|
||||
.SH SEE ALSO
|
||||
.nf
|
||||
malloc(3)
|
||||
.SH AUTHOR
|
||||
pool_alloc was created by J.W. Schultz of Pegasystems Technologies.
|
||||
.SH BUGS AND ISSUES
|
||||
280
lib/pool_alloc.c
Normal file
280
lib/pool_alloc.c
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "rsync.h"
|
||||
|
||||
#define POOL_DEF_EXTENT (32 * 1024)
|
||||
|
||||
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
|
||||
* malloc fails */
|
||||
int flags;
|
||||
|
||||
/* statistical data */
|
||||
unsigned long e_created; /* extents created */
|
||||
unsigned long e_freed; /* extents detroyed */
|
||||
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
|
||||
{
|
||||
void *start; /* starting address */
|
||||
size_t free; /* free bytecount */
|
||||
size_t bound; /* bytes bound by padding,
|
||||
* overhead and freed */
|
||||
struct pool_extent *next;
|
||||
};
|
||||
|
||||
struct align_test {
|
||||
void *foo;
|
||||
int64 bar;
|
||||
};
|
||||
|
||||
#define MINALIGN offsetof(struct align_test, bar)
|
||||
|
||||
/* Temporarily cast a void* var into a char* var when adding an offset (to
|
||||
* keep some compilers from complaining about the pointer arithmetic). */
|
||||
#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)
|
||||
{
|
||||
struct alloc_pool *pool;
|
||||
|
||||
if (!(pool = (struct alloc_pool*) malloc(sizeof (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) {
|
||||
pool->size -= sizeof (struct pool_extent);
|
||||
flags |= POOL_APPEND;
|
||||
}
|
||||
pool->quantum = quantum ? quantum : MINALIGN;
|
||||
pool->bomb = bomb;
|
||||
pool->flags = flags;
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
void
|
||||
pool_destroy(alloc_pool_t p)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
struct pool_extent *cur, *next;
|
||||
|
||||
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) {
|
||||
next = cur->next;
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
}
|
||||
free(pool);
|
||||
}
|
||||
|
||||
void *
|
||||
pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
if (!len)
|
||||
len = pool->quantum;
|
||||
else if (pool->quantum > 1 && len % pool->quantum)
|
||||
len += pool->quantum - len % pool->quantum;
|
||||
|
||||
if (len > pool->size)
|
||||
goto bomb;
|
||||
|
||||
if (!pool->live || len > pool->live->free) {
|
||||
void *start;
|
||||
size_t free;
|
||||
size_t bound;
|
||||
size_t sqew;
|
||||
size_t asize;
|
||||
|
||||
if (pool->live) {
|
||||
pool->live->next = pool->free;
|
||||
pool->free = pool->live;
|
||||
}
|
||||
|
||||
free = pool->size;
|
||||
bound = 0;
|
||||
|
||||
asize = pool->size;
|
||||
if (pool->flags & POOL_APPEND)
|
||||
asize += sizeof (struct pool_extent);
|
||||
|
||||
if (!(start = (void *) malloc(asize)))
|
||||
goto bomb;
|
||||
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(start, 0, pool->size);
|
||||
|
||||
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;
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
|
||||
bound += sqew;
|
||||
free -= sqew;
|
||||
}
|
||||
pool->live->start = start;
|
||||
pool->live->free = free;
|
||||
pool->live->bound = bound;
|
||||
pool->live->next = NULL;
|
||||
|
||||
pool->e_created++;
|
||||
}
|
||||
|
||||
pool->n_allocated++;
|
||||
pool->b_allocated += len;
|
||||
|
||||
pool->live->free -= len;
|
||||
|
||||
return PTR_ADD(pool->live->start, pool->live->free);
|
||||
|
||||
bomb:
|
||||
if (pool->bomb)
|
||||
(*pool->bomb)(bomb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
if (!len)
|
||||
len = pool->quantum;
|
||||
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) {
|
||||
if (addr >= cur->start
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
break;
|
||||
}
|
||||
if (!cur)
|
||||
return;
|
||||
|
||||
if (prev) {
|
||||
prev->next = cur->next;
|
||||
cur->next = pool->free;
|
||||
pool->free = cur;
|
||||
}
|
||||
cur->bound += len;
|
||||
|
||||
if (cur->free + cur->bound >= pool->size) {
|
||||
pool->free = cur->next;
|
||||
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
pool->e_freed++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#define FDPRINT(label, value) \
|
||||
snprintf(buf, sizeof buf, label, value), \
|
||||
write(fd, buf, strlen(buf))
|
||||
|
||||
#define FDEXTSTAT(ext) \
|
||||
snprintf(buf, sizeof buf, " %12ld %5ld\n", \
|
||||
(long) ext->free, \
|
||||
(long) ext->bound), \
|
||||
write(fd, buf, strlen(buf))
|
||||
|
||||
void
|
||||
pool_stats(alloc_pool_t p, int fd, int summarize)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
struct pool_extent *cur;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
FDPRINT(" Extent size: %12ld\n", (long) pool->size);
|
||||
FDPRINT(" Alloc quantum: %12ld\n", (long) pool->quantum);
|
||||
FDPRINT(" Extents created: %12ld\n", pool->e_created);
|
||||
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);
|
||||
|
||||
if (summarize)
|
||||
return;
|
||||
|
||||
if (!pool->live && !pool->free)
|
||||
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)
|
||||
FDEXTSTAT(cur);
|
||||
}
|
||||
20
lib/pool_alloc.h
Normal file
20
lib/pool_alloc.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#define POOL_CLEAR (1<<0) /* zero fill allocations */
|
||||
#define POOL_QALIGN (1<<1) /* align data to quanta */
|
||||
#define POOL_INTERN (1<<2) /* Allocate extent structures */
|
||||
#define POOL_APPEND (1<<3) /* or appended to extent data */
|
||||
|
||||
typedef void *alloc_pool_t;
|
||||
|
||||
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(char *), int flags);
|
||||
void pool_destroy(alloc_pool_t pool);
|
||||
void *pool_alloc(alloc_pool_t pool, size_t size, char *bomb);
|
||||
void pool_free(alloc_pool_t pool, size_t size, void *addr);
|
||||
|
||||
#define pool_talloc(pool, type, count, bomb) \
|
||||
((type *)pool_alloc(pool, sizeof(type) * count, bomb))
|
||||
|
||||
#define pool_tfree(pool, type, count, addr) \
|
||||
(pool_free(pool, sizeof(type) * count, addr))
|
||||
|
||||
1493
lib/snprintf.c
1493
lib/snprintf.c
File diff suppressed because it is too large
Load Diff
368
lib/wildmatch.c
Normal file
368
lib/wildmatch.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
** Do shell-style pattern matching for ?, \, [], and * characters.
|
||||
** It is 8bit clean.
|
||||
**
|
||||
** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
|
||||
** Rich $alz is now <rsalz@bbn.com>.
|
||||
**
|
||||
** Modified by Wayne Davison to special-case '/' matching, to make '**'
|
||||
** work differently than '*', and to fix the character-class code.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* What character marks an inverted character class? */
|
||||
#define NEGATE_CLASS '!'
|
||||
#define NEGATE_CLASS2 '^'
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#define ABORT_ALL -1
|
||||
#define ABORT_TO_STARSTAR -2
|
||||
|
||||
#define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \
|
||||
&& *(class) == *(litmatch) \
|
||||
&& strncmp((char*)class, litmatch, len) == 0)
|
||||
|
||||
#if defined STDC_HEADERS || !defined isascii
|
||||
# define ISASCII(c) 1
|
||||
#else
|
||||
# define ISASCII(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#ifdef isblank
|
||||
# define ISBLANK(c) (ISASCII(c) && isblank(c))
|
||||
#else
|
||||
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
|
||||
#endif
|
||||
|
||||
#ifdef isgraph
|
||||
# define ISGRAPH(c) (ISASCII(c) && isgraph(c))
|
||||
#else
|
||||
# define ISGRAPH(c) (ISASCII(c) && isprint(c) && !isspace(c))
|
||||
#endif
|
||||
|
||||
#define ISPRINT(c) (ISASCII(c) && isprint(c))
|
||||
#define ISDIGIT(c) (ISASCII(c) && isdigit(c))
|
||||
#define ISALNUM(c) (ISASCII(c) && isalnum(c))
|
||||
#define ISALPHA(c) (ISASCII(c) && isalpha(c))
|
||||
#define ISCNTRL(c) (ISASCII(c) && iscntrl(c))
|
||||
#define ISLOWER(c) (ISASCII(c) && islower(c))
|
||||
#define ISPUNCT(c) (ISASCII(c) && ispunct(c))
|
||||
#define ISSPACE(c) (ISASCII(c) && isspace(c))
|
||||
#define ISUPPER(c) (ISASCII(c) && isupper(c))
|
||||
#define ISXDIGIT(c) (ISASCII(c) && isxdigit(c))
|
||||
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
int wildmatch_iteration_count;
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
uchar p_ch;
|
||||
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
wildmatch_iteration_count++;
|
||||
#endif
|
||||
|
||||
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. */
|
||||
p_ch = *++p;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (t_ch != p_ch)
|
||||
return FALSE;
|
||||
continue;
|
||||
case '?':
|
||||
/* Match anything but '/'. */
|
||||
if (t_ch == '/')
|
||||
return FALSE;
|
||||
continue;
|
||||
case '*':
|
||||
if (*++p == '*') {
|
||||
while (*++p == '*') {}
|
||||
special = TRUE;
|
||||
} else
|
||||
special = FALSE;
|
||||
if (*p == '\0') {
|
||||
/* Trailing "**" matches everything. Trailing "*" matches
|
||||
* only if there are no more slash characters. */
|
||||
if (!special) {
|
||||
do {
|
||||
if (strchr((char*)text, '/') != NULL)
|
||||
return FALSE;
|
||||
} while ((text = *a++) != NULL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
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 && t_ch == '/')
|
||||
return ABORT_TO_STARSTAR;
|
||||
t_ch = *++text;
|
||||
}
|
||||
return ABORT_ALL;
|
||||
case '[':
|
||||
p_ch = *++p;
|
||||
#ifdef NEGATE_CLASS2
|
||||
if (p_ch == NEGATE_CLASS2)
|
||||
p_ch = NEGATE_CLASS;
|
||||
#endif
|
||||
/* Assign literal TRUE/FALSE because of "matched" comparison. */
|
||||
special = p_ch == NEGATE_CLASS? TRUE : FALSE;
|
||||
if (special) {
|
||||
/* Inverted character class. */
|
||||
p_ch = *++p;
|
||||
}
|
||||
prev_ch = 0;
|
||||
matched = FALSE;
|
||||
do {
|
||||
if (!p_ch)
|
||||
return ABORT_ALL;
|
||||
if (p_ch == '\\') {
|
||||
p_ch = *++p;
|
||||
if (!p_ch)
|
||||
return ABORT_ALL;
|
||||
if (t_ch == p_ch)
|
||||
matched = TRUE;
|
||||
} 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 (t_ch <= p_ch && t_ch >= prev_ch)
|
||||
matched = TRUE;
|
||||
p_ch = 0; /* This makes "prev_ch" get set to 0. */
|
||||
} else if (p_ch == '[' && p[1] == ':') {
|
||||
const uchar *s;
|
||||
int i;
|
||||
for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {}
|
||||
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;
|
||||
p_ch = '[';
|
||||
if (t_ch == p_ch)
|
||||
matched = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (CC_EQ(s,i, "alnum")) {
|
||||
if (ISALNUM(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "alpha")) {
|
||||
if (ISALPHA(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "blank")) {
|
||||
if (ISBLANK(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "cntrl")) {
|
||||
if (ISCNTRL(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "digit")) {
|
||||
if (ISDIGIT(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "graph")) {
|
||||
if (ISGRAPH(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "lower")) {
|
||||
if (ISLOWER(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "print")) {
|
||||
if (ISPRINT(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "punct")) {
|
||||
if (ISPUNCT(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "space")) {
|
||||
if (ISSPACE(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "upper")) {
|
||||
if (ISUPPER(t_ch))
|
||||
matched = TRUE;
|
||||
} else if (CC_EQ(s,i, "xdigit")) {
|
||||
if (ISXDIGIT(t_ch))
|
||||
matched = TRUE;
|
||||
} else /* malformed [:class:] string */
|
||||
return ABORT_ALL;
|
||||
p_ch = 0; /* This makes "prev_ch" get set to 0. */
|
||||
} else if (t_ch == p_ch)
|
||||
matched = TRUE;
|
||||
} while (prev_ch = p_ch, (p_ch = *++p) != ']');
|
||||
if (matched == special || t_ch == '/')
|
||||
return FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
if (*text)
|
||||
return FALSE;
|
||||
} while ((text = *a++) != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* 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 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;
|
||||
}
|
||||
6
lib/wildmatch.h
Normal file
6
lib/wildmatch.h
Normal file
@@ -0,0 +1,6 @@
|
||||
/* wildmatch.h */
|
||||
|
||||
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);
|
||||
364
loadparm.c
364
loadparm.c
@@ -1,17 +1,22 @@
|
||||
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
|
||||
and Karl Auer */
|
||||
|
||||
/*
|
||||
/* some fixes
|
||||
*
|
||||
* 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.
|
||||
@@ -31,7 +36,7 @@
|
||||
* 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
|
||||
* 4) If it's a global then initialise it in init_globals. If a local
|
||||
* (ie. service) parameter then initialise it in the sDefault structure
|
||||
*
|
||||
*
|
||||
*
|
||||
* Notes:
|
||||
* The configuration file is processed sequentially for speed. It is NOT
|
||||
@@ -43,6 +48,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* TODO: Parameter to set debug level on server. */
|
||||
|
||||
#include "rsync.h"
|
||||
#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
|
||||
#define strequal(a,b) (strcasecmp(a,b)==0)
|
||||
@@ -54,7 +61,7 @@ typedef char pstring[1024];
|
||||
typedef enum
|
||||
{
|
||||
P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
|
||||
P_STRING,P_GSTRING,P_ENUM,P_SEP
|
||||
P_PATH,P_STRING,P_GSTRING,P_ENUM,P_SEP
|
||||
} parm_type;
|
||||
|
||||
typedef enum
|
||||
@@ -77,8 +84,6 @@ struct parm_struct
|
||||
unsigned flags;
|
||||
};
|
||||
|
||||
static BOOL bLoaded = False;
|
||||
|
||||
#ifndef GLOBAL_NAME
|
||||
#define GLOBAL_NAME "global"
|
||||
#endif
|
||||
@@ -88,81 +93,112 @@ static BOOL bLoaded = False;
|
||||
#define iSERVICE(i) (*pSERVICE(i))
|
||||
#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
|
||||
|
||||
/*
|
||||
/*
|
||||
* This structure describes global (ie., server-wide) parameters.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *motd_file;
|
||||
char *bind_address;
|
||||
char *log_file;
|
||||
char *motd_file;
|
||||
char *pid_file;
|
||||
int syslog_facility;
|
||||
char *socket_options;
|
||||
|
||||
int rsync_port;
|
||||
int syslog_facility;
|
||||
} 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;
|
||||
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_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 timeout;
|
||||
|
||||
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 */
|
||||
static service sDefault =
|
||||
/* 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 */
|
||||
"nobody",/* uid */
|
||||
"nobody",/* gid */
|
||||
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", /* dont compress */
|
||||
0, /* timeout */
|
||||
0 /* max connections */
|
||||
/* auth_users; */ NULL,
|
||||
/* comment; */ NULL,
|
||||
/* dont_compress; */ "*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",
|
||||
/* 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_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,
|
||||
|
||||
/* max_connections; */ 0,
|
||||
/* max_verbosity; */ 1,
|
||||
/* timeout; */ 0,
|
||||
|
||||
/* ignore_errors; */ False,
|
||||
/* ignore_nonreadable; */ False,
|
||||
/* list; */ True,
|
||||
/* read_only; */ True,
|
||||
/* strict_modes; */ True,
|
||||
/* transfer_logging; */ False,
|
||||
/* use_chroot; */ True,
|
||||
/* write_only; */ False,
|
||||
};
|
||||
|
||||
|
||||
@@ -204,7 +240,7 @@ static struct enum_list enum_facilities[] = {
|
||||
{ LOG_NEWS, "news" },
|
||||
#endif
|
||||
#ifdef LOG_AUTH
|
||||
{ LOG_AUTH, "security" },
|
||||
{ LOG_AUTH, "security" },
|
||||
#endif
|
||||
#ifdef LOG_SYSLOG
|
||||
{ LOG_SYSLOG, "syslog" },
|
||||
@@ -245,37 +281,51 @@ 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},
|
||||
{"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
|
||||
{"log file", P_STRING, P_GLOBAL,&Globals.log_file, 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},
|
||||
{"syslog facility", P_ENUM, P_GLOBAL,&Globals.syslog_facility,enum_facilities,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_STRING, 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},
|
||||
{"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},
|
||||
{"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},
|
||||
{"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 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},
|
||||
{"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}
|
||||
};
|
||||
|
||||
|
||||
@@ -284,7 +334,7 @@ Initialise the global parameter structure.
|
||||
***************************************************************************/
|
||||
static void init_globals(void)
|
||||
{
|
||||
memset(&Globals, 0, sizeof(Globals));
|
||||
memset(&Globals, 0, sizeof Globals);
|
||||
#ifdef LOG_DAEMON
|
||||
Globals.syslog_facility = LOG_DAEMON;
|
||||
#endif
|
||||
@@ -299,8 +349,8 @@ static void init_locals(void)
|
||||
|
||||
|
||||
/*
|
||||
In this section all the functions that are used to access the
|
||||
parameters from the rest of the program are defined
|
||||
In this section all the functions that are used to access the
|
||||
parameters from the rest of the program are defined
|
||||
*/
|
||||
|
||||
#define FN_GLOBAL_STRING(fn_name,ptr) \
|
||||
@@ -322,44 +372,58 @@ static void init_locals(void)
|
||||
int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
|
||||
|
||||
|
||||
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
|
||||
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
|
||||
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
|
||||
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
|
||||
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
|
||||
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
|
||||
|
||||
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
|
||||
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
|
||||
|
||||
FN_LOCAL_STRING(lp_name, name)
|
||||
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_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_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_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_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 );
|
||||
static int map_parameter( char *parmname);
|
||||
static BOOL set_boolean( BOOL *pb, char *parmvalue );
|
||||
static int strwicmp(char *psz1, char *psz2);
|
||||
static int map_parameter(char *parmname);
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue);
|
||||
static int getservicebyname(char *name, service *pserviceDest);
|
||||
static void copy_service( service *pserviceDest,
|
||||
service *pserviceSource);
|
||||
static void copy_service(service *pserviceDest, service *pserviceSource);
|
||||
static BOOL do_parameter(char *parmname, char *parmvalue);
|
||||
static BOOL do_section(char *sectionname);
|
||||
|
||||
@@ -373,19 +437,33 @@ static void init_service(service *pservice)
|
||||
copy_service(pservice,&sDefault);
|
||||
}
|
||||
|
||||
static void string_set(char **s, char *v)
|
||||
|
||||
/**
|
||||
* Assign a copy of @p v to @p *s. Handles NULL strings. @p *v must
|
||||
* be initialized when this is called, either to NULL or a malloc'd
|
||||
* string.
|
||||
*
|
||||
* @fixme There is a small leak here in that sometimes the existing
|
||||
* value will be dynamically allocated, and the old copy is lost.
|
||||
* However, we can't always deallocate the old value, because in the
|
||||
* case of sDefault, it points to a static string. It would be nice
|
||||
* to have either all-strdup'd values, or to never need to free
|
||||
* memory.
|
||||
**/
|
||||
static void string_set(char **s, const char *v)
|
||||
{
|
||||
if (!v) {
|
||||
*s = NULL;
|
||||
return;
|
||||
}
|
||||
*s = strdup(v);
|
||||
if (!*s) exit_cleanup(RERR_MALLOC);
|
||||
if (!*s)
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
add a new service to the services array initialising it with the given
|
||||
add a new service to the services array initialising it with the given
|
||||
service
|
||||
***************************************************************************/
|
||||
static int add_a_service(service *pservice, char *name)
|
||||
@@ -397,7 +475,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
tservice = *pservice;
|
||||
|
||||
/* it might already exist */
|
||||
if (name)
|
||||
if (name)
|
||||
{
|
||||
i = getservicebyname(name,NULL);
|
||||
if (i >= 0)
|
||||
@@ -406,10 +484,10 @@ static int add_a_service(service *pservice, char *name)
|
||||
|
||||
i = iNumServices;
|
||||
|
||||
ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
|
||||
ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
|
||||
|
||||
if (ServicePtrs)
|
||||
pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
|
||||
pSERVICE(iNumServices) = new(service);
|
||||
|
||||
if (!ServicePtrs || !pSERVICE(iNumServices))
|
||||
return(-1);
|
||||
@@ -419,7 +497,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
init_service(pSERVICE(i));
|
||||
copy_service(pSERVICE(i),&tservice);
|
||||
if (name)
|
||||
string_set(&iSERVICE(i).name,name);
|
||||
string_set(&iSERVICE(i).name,name);
|
||||
|
||||
return(i);
|
||||
}
|
||||
@@ -443,11 +521,12 @@ static int strwicmp(char *psz1, char *psz2)
|
||||
/* sync the strings on first non-whitespace */
|
||||
while (1)
|
||||
{
|
||||
while (isspace(*psz1))
|
||||
while (isspace(* (unsigned char *) psz1))
|
||||
psz1++;
|
||||
while (isspace(*psz2))
|
||||
while (isspace(* (unsigned char *) psz2))
|
||||
psz2++;
|
||||
if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
|
||||
if (toupper(* (unsigned char *) psz1) != toupper(* (unsigned char *) psz2)
|
||||
|| *psz1 == '\0' || *psz2 == '\0')
|
||||
break;
|
||||
psz1++;
|
||||
psz2++;
|
||||
@@ -456,7 +535,7 @@ static int strwicmp(char *psz1, char *psz2)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Map a parameter's string representation to something we can use.
|
||||
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)
|
||||
@@ -466,7 +545,7 @@ static int map_parameter(char *parmname)
|
||||
if (*parmname == '-')
|
||||
return(-1);
|
||||
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
|
||||
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
|
||||
return(iIndex);
|
||||
|
||||
@@ -477,7 +556,7 @@ 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
|
||||
Returns True in success, False if the passed string does not correctly
|
||||
represent a boolean.
|
||||
***************************************************************************/
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
@@ -511,7 +590,7 @@ static int getservicebyname(char *name, service *pserviceDest)
|
||||
int iService;
|
||||
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--)
|
||||
if (strwicmp(iSERVICE(iService).name, name) == 0)
|
||||
if (strwicmp(iSERVICE(iService).name, name) == 0)
|
||||
{
|
||||
if (pserviceDest != NULL)
|
||||
copy_service(pserviceDest, pSERVICE(iService));
|
||||
@@ -527,7 +606,7 @@ static int getservicebyname(char *name, service *pserviceDest)
|
||||
Copy a service structure to another
|
||||
|
||||
***************************************************************************/
|
||||
static void copy_service(service *pserviceDest,
|
||||
static void copy_service(service *pserviceDest,
|
||||
service *pserviceSource)
|
||||
{
|
||||
int i;
|
||||
@@ -535,9 +614,9 @@ static void copy_service(service *pserviceDest,
|
||||
for (i=0;parm_table[i].label;i++)
|
||||
if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
|
||||
void *def_ptr = parm_table[i].ptr;
|
||||
void *src_ptr =
|
||||
void *src_ptr =
|
||||
((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
|
||||
void *dest_ptr =
|
||||
void *dest_ptr =
|
||||
((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
|
||||
|
||||
switch (parm_table[i].type)
|
||||
@@ -557,6 +636,7 @@ static void copy_service(service *pserviceDest,
|
||||
*(char *)dest_ptr = *(char *)src_ptr;
|
||||
break;
|
||||
|
||||
case P_PATH:
|
||||
case P_STRING:
|
||||
string_set(dest_ptr,*(char **)src_ptr);
|
||||
break;
|
||||
@@ -577,6 +657,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
int parmnum, i;
|
||||
void *parm_ptr=NULL; /* where we are going to store the result */
|
||||
void *def_ptr=NULL;
|
||||
char *cp;
|
||||
|
||||
parmnum = map_parameter(parmname);
|
||||
|
||||
@@ -623,6 +704,15 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
sscanf(parmvalue,"%o",(int *)parm_ptr);
|
||||
break;
|
||||
|
||||
case P_PATH:
|
||||
string_set(parm_ptr,parmvalue);
|
||||
if ((cp = *(char**)parm_ptr) != NULL) {
|
||||
int len = strlen(cp);
|
||||
while (len > 1 && cp[len-1] == '/') len--;
|
||||
cp[len] = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
case P_STRING:
|
||||
string_set(parm_ptr,parmvalue);
|
||||
break;
|
||||
@@ -674,7 +764,7 @@ static BOOL do_section(char *sectionname)
|
||||
init_locals();
|
||||
|
||||
/* if we've just struck a global section, note the fact. */
|
||||
bInGlobalSection = isglobal;
|
||||
bInGlobalSection = isglobal;
|
||||
|
||||
/* check for multiple global sections */
|
||||
if (bInGlobalSection)
|
||||
@@ -706,27 +796,33 @@ static BOOL do_section(char *sectionname)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Load the services array from the services file. Return True on success,
|
||||
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;
|
||||
|
||||
|
||||
bRetval = False;
|
||||
|
||||
bInGlobalSection = True;
|
||||
|
||||
|
||||
init_globals();
|
||||
|
||||
pstrcpy(n2,pszFname);
|
||||
if (pszFname)
|
||||
pstrcpy(n2,pszFname);
|
||||
else if (am_server && am_daemon && !am_root)
|
||||
pstrcpy(n2,RSYNCD_USERCONF);
|
||||
else
|
||||
pstrcpy(n2,RSYNCD_SYSCONF);
|
||||
|
||||
/* We get sections first, so have to start 'behind' to make up */
|
||||
iServiceIndex = -1;
|
||||
bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
|
||||
|
||||
bLoaded = True;
|
||||
|
||||
return (bRetval);
|
||||
}
|
||||
@@ -751,7 +847,7 @@ 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);
|
||||
|
||||
850
log.c
850
log.c
@@ -1,35 +1,116 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
|
||||
/* -*- c-file-style: "linux"; -*-
|
||||
|
||||
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2000-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.
|
||||
*/
|
||||
|
||||
/*
|
||||
logging and utility functions
|
||||
|
||||
Logging and utility functions.
|
||||
tridge, May 1998
|
||||
|
||||
Mapping to human-readable messages added by Martin Pool
|
||||
<mbp@samba.org>, Oct 2000.
|
||||
*/
|
||||
#include "rsync.h"
|
||||
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int local_server;
|
||||
extern int quiet;
|
||||
extern int module_id;
|
||||
extern int msg_fd_out;
|
||||
extern int allow_8bit_chars;
|
||||
extern int protocol_version;
|
||||
extern int preserve_times;
|
||||
extern int log_format_has_i;
|
||||
extern int log_format_has_o_or_i;
|
||||
extern int daemon_log_format_has_o_or_i;
|
||||
extern mode_t orig_umask;
|
||||
extern char *auth_user;
|
||||
extern char *log_format;
|
||||
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
|
||||
extern iconv_t ic_chck;
|
||||
#endif
|
||||
|
||||
static int log_initialised;
|
||||
static int logfile_was_closed;
|
||||
static char *logfname;
|
||||
static FILE *logfile;
|
||||
struct stats stats;
|
||||
|
||||
int log_got_error = 0;
|
||||
|
||||
struct {
|
||||
int code;
|
||||
char const *name;
|
||||
} const rerr_names[] = {
|
||||
{ RERR_SYNTAX , "syntax or usage error" },
|
||||
{ RERR_PROTOCOL , "protocol incompatibility" },
|
||||
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
|
||||
{ RERR_UNSUPPORTED, "requested action not supported" },
|
||||
{ RERR_STARTCLIENT, "error starting client-server protocol" },
|
||||
{ RERR_SOCKETIO , "error in socket IO" },
|
||||
{ RERR_FILEIO , "error in file IO" },
|
||||
{ RERR_STREAMIO , "error in rsync protocol data stream" },
|
||||
{ RERR_MESSAGEIO , "errors with program diagnostics" },
|
||||
{ RERR_IPC , "error in IPC code" },
|
||||
{ RERR_CRASHED , "sibling process crashed" },
|
||||
{ RERR_TERMINATED , "sibling process terminated abnormally" },
|
||||
{ RERR_SIGNAL1 , "received SIGUSR1" },
|
||||
{ RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
|
||||
{ RERR_WAITCHILD , "waitpid() failed" },
|
||||
{ RERR_MALLOC , "error allocating core memory buffers" },
|
||||
{ RERR_PARTIAL , "some files could not be transferred" },
|
||||
{ RERR_VANISHED , "some files vanished before they could be transferred" },
|
||||
{ RERR_TIMEOUT , "timeout in data send/receive" },
|
||||
{ RERR_CMD_FAILED , "remote shell failed" },
|
||||
{ RERR_CMD_KILLED , "remote shell killed" },
|
||||
{ RERR_CMD_RUN , "remote command could not be run" },
|
||||
{ RERR_CMD_NOTFOUND,"remote command not found" },
|
||||
{ RERR_DEL_LIMIT , "the --max-delete limit stopped deletions" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Map from rsync error code to name, or return NULL.
|
||||
*/
|
||||
static char const *rerr_name(int code)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; rerr_names[i].name; i++) {
|
||||
if (rerr_names[i].code == code)
|
||||
return rerr_names[i].name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void logit(int priority, char *buf)
|
||||
{
|
||||
if (logfile_was_closed)
|
||||
logfile_reopen();
|
||||
if (logfile) {
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
timestring(time(NULL)), (int)getpid(), buf);
|
||||
fflush(logfile);
|
||||
} else {
|
||||
@@ -37,31 +118,14 @@ static void logit(int priority, char *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void log_open(void)
|
||||
static void syslog_init()
|
||||
{
|
||||
static int initialised;
|
||||
static int been_here = 0;
|
||||
int options = LOG_PID;
|
||||
time_t t;
|
||||
char *logf;
|
||||
|
||||
if (initialised) return;
|
||||
initialised = 1;
|
||||
|
||||
/* this looks pointless, but it is needed in order for the
|
||||
C library on some systems to fetch the timezone info
|
||||
before the chroot */
|
||||
t = time(NULL);
|
||||
localtime(&t);
|
||||
|
||||
/* optionally use a log file instead of syslog */
|
||||
logf = lp_log_file();
|
||||
if (logf && *logf) {
|
||||
extern int orig_umask;
|
||||
int old_umask = umask(022 | orig_umask);
|
||||
logfile = fopen(logf, "a");
|
||||
umask(old_umask);
|
||||
if (been_here)
|
||||
return;
|
||||
}
|
||||
been_here = 1;
|
||||
|
||||
#ifdef LOG_NDELAY
|
||||
options |= LOG_NDELAY;
|
||||
@@ -74,256 +138,642 @@ void log_open(void)
|
||||
#endif
|
||||
|
||||
#ifndef LOG_NDELAY
|
||||
logit(LOG_INFO,"rsyncd started\n");
|
||||
logit(LOG_INFO, "rsyncd started\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
|
||||
void rprintf(int fd, const char *format, ...)
|
||||
static void logfile_open(void)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
FILE *f=NULL;
|
||||
extern int am_daemon;
|
||||
extern int quiet;
|
||||
/* recursion can happen with certain fatal conditions */
|
||||
|
||||
if (quiet != 0 && fd == FINFO) return;
|
||||
|
||||
va_start(ap, format);
|
||||
len = vslprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
buf[len] = 0;
|
||||
|
||||
if (fd == FLOG) {
|
||||
if (am_daemon) logit(LOG_INFO, buf);
|
||||
return;
|
||||
mode_t old_umask = umask(022 | orig_umask);
|
||||
logfile = fopen(logfname, "a");
|
||||
umask(old_umask);
|
||||
if (!logfile) {
|
||||
int fopen_errno = errno;
|
||||
/* Rsync falls back to using syslog on failure. */
|
||||
syslog_init();
|
||||
rsyserr(FERROR, fopen_errno,
|
||||
"failed to open log-file %s", logfname);
|
||||
rprintf(FINFO, "Ignoring \"log file\" setting.\n");
|
||||
}
|
||||
|
||||
if (am_daemon) {
|
||||
static int depth;
|
||||
int priority = LOG_INFO;
|
||||
if (fd == FERROR) priority = LOG_WARNING;
|
||||
|
||||
if (depth) return;
|
||||
|
||||
depth++;
|
||||
|
||||
log_open();
|
||||
if (!io_multiplex_write(fd, buf, strlen(buf))) {
|
||||
logit(priority, buf);
|
||||
}
|
||||
|
||||
depth--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
|
||||
if (fd == FINFO) {
|
||||
extern int am_server;
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
|
||||
}
|
||||
|
||||
void rflush(int fd)
|
||||
void log_init(void)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
if (log_initialised)
|
||||
return;
|
||||
log_initialised = 1;
|
||||
|
||||
/* this looks pointless, but it is needed in order for the
|
||||
* C library on some systems to fetch the timezone info
|
||||
* before the chroot */
|
||||
t = time(NULL);
|
||||
localtime(&t);
|
||||
|
||||
/* optionally use a log file instead of syslog */
|
||||
logfname = lp_log_file();
|
||||
if (logfname && *logfname)
|
||||
logfile_open();
|
||||
else
|
||||
syslog_init();
|
||||
}
|
||||
|
||||
void logfile_close(void)
|
||||
{
|
||||
if (logfile) {
|
||||
logfile_was_closed = 1;
|
||||
fclose(logfile);
|
||||
logfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void logfile_reopen(void)
|
||||
{
|
||||
if (logfile_was_closed) {
|
||||
logfile_was_closed = 0;
|
||||
logfile_open();
|
||||
}
|
||||
}
|
||||
|
||||
static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
|
||||
{
|
||||
const char *s, *end = buf + len;
|
||||
for (s = buf; s < end; s++) {
|
||||
if ((s < end - 4
|
||||
&& *s == '\\' && s[1] == '#'
|
||||
&& isdigit(*(uchar*)(s+2))
|
||||
&& isdigit(*(uchar*)(s+3))
|
||||
&& isdigit(*(uchar*)(s+4)))
|
||||
|| (*s != '\t'
|
||||
&& ((use_isprint && !isprint(*(uchar*)s))
|
||||
|| *(uchar*)s < ' '))) {
|
||||
if (s != buf && fwrite(buf, s - buf, 1, f) != 1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
fprintf(f, "\\#%03o", *(uchar*)s);
|
||||
buf = s + 1;
|
||||
}
|
||||
}
|
||||
if (buf != end && fwrite(buf, end - buf, 1, f) != 1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
|
||||
/* this is the underlying (unformatted) rsync debugging function. Call
|
||||
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
|
||||
* certain fatal conditions. */
|
||||
void rwrite(enum logcode code, char *buf, int len)
|
||||
{
|
||||
int trailing_CR_or_NL;
|
||||
FILE *f = NULL;
|
||||
|
||||
if (len < 0)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
if (quiet && code == FINFO)
|
||||
return;
|
||||
|
||||
if (am_server && msg_fd_out >= 0) {
|
||||
/* Pass the message to our sibling. */
|
||||
send_msg((enum msgcode)code, buf, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
|
||||
code = FERROR;
|
||||
|
||||
if (code == FCLIENT)
|
||||
code = FINFO;
|
||||
else if (am_daemon) {
|
||||
static int in_block;
|
||||
char msg[2048];
|
||||
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
|
||||
|
||||
if (in_block)
|
||||
return;
|
||||
in_block = 1;
|
||||
if (!log_initialised)
|
||||
log_init();
|
||||
strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));
|
||||
logit(priority, msg);
|
||||
in_block = 0;
|
||||
|
||||
if (code == FLOG || !am_server)
|
||||
return;
|
||||
} else if (code == FLOG)
|
||||
return;
|
||||
|
||||
if (am_server) {
|
||||
/* Pass the message to the non-server side. */
|
||||
if (io_multiplex_write((enum msgcode)code, buf, len))
|
||||
return;
|
||||
if (am_daemon) {
|
||||
/* TODO: can we send the error to the user somehow? */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case FERROR:
|
||||
log_got_error = 1;
|
||||
f = stderr;
|
||||
goto pre_scan;
|
||||
case FINFO:
|
||||
f = am_server ? stderr : stdout;
|
||||
pre_scan:
|
||||
while (len > 1 && *buf == '\n') {
|
||||
fputc(*buf, f);
|
||||
buf++;
|
||||
len--;
|
||||
}
|
||||
break;
|
||||
case FNAME:
|
||||
f = am_server ? stderr : stdout;
|
||||
break;
|
||||
default:
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
|
||||
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
|
||||
? buf[--len] : 0;
|
||||
|
||||
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
|
||||
if (ic_chck != (iconv_t)-1) {
|
||||
char convbuf[1024];
|
||||
char *in_buf = buf, *out_buf = convbuf;
|
||||
size_t in_cnt = len, out_cnt = sizeof convbuf - 1;
|
||||
|
||||
iconv(ic_chck, NULL, 0, NULL, 0);
|
||||
while (iconv(ic_chck, &in_buf,&in_cnt,
|
||||
&out_buf,&out_cnt) == (size_t)-1) {
|
||||
if (out_buf != convbuf) {
|
||||
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
|
||||
out_buf = convbuf;
|
||||
out_cnt = sizeof convbuf - 1;
|
||||
}
|
||||
if (errno == E2BIG)
|
||||
continue;
|
||||
fprintf(f, "\\#%03o", *(uchar*)in_buf++);
|
||||
in_cnt--;
|
||||
}
|
||||
if (out_buf != convbuf)
|
||||
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
|
||||
} else
|
||||
#endif
|
||||
filtered_fwrite(f, buf, len, !allow_8bit_chars);
|
||||
|
||||
if (trailing_CR_or_NL) {
|
||||
fputc(trailing_CR_or_NL, f);
|
||||
fflush(f);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR or
|
||||
* FLOG. */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[BIGPATHBUFLEN];
|
||||
size_t len;
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(buf, sizeof buf, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Deal with buffer overruns. Instead of panicking, just
|
||||
* truncate the resulting string. (Note that configure ensures
|
||||
* that we have a vsnprintf() that doesn't ever return -1.) */
|
||||
if (len > sizeof buf - 1) {
|
||||
static const char ellipsis[] = "[...]";
|
||||
|
||||
/* Reset length, and zero-terminate the end of our buffer */
|
||||
len = sizeof buf - 1;
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Copy the ellipsis to the end of the string, but give
|
||||
* us one extra character:
|
||||
*
|
||||
* v--- null byte at buf[sizeof buf - 1]
|
||||
* abcdefghij0
|
||||
* -> abcd[...]00 <-- now two null bytes at end
|
||||
*
|
||||
* If the input format string has a trailing newline,
|
||||
* we copy it into that extra null; if it doesn't, well,
|
||||
* all we lose is one byte. */
|
||||
memcpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);
|
||||
if (format[strlen(format)-1] == '\n') {
|
||||
buf[len-1] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
|
||||
/* This is like rprintf, but it also tries to print some
|
||||
* representation of the error code. Normally errcode = errno.
|
||||
*
|
||||
* Unlike rprintf, this always adds a newline and there should not be
|
||||
* one in the format string.
|
||||
*
|
||||
* Note that since strerror might involve dynamically loading a
|
||||
* message catalog we need to call it once before chroot-ing. */
|
||||
void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[BIGPATHBUFLEN];
|
||||
size_t len;
|
||||
|
||||
strcpy(buf, RSYNC_NAME ": ");
|
||||
len = (sizeof RSYNC_NAME ": ") - 1;
|
||||
|
||||
va_start(ap, format);
|
||||
len += vsnprintf(buf + len, sizeof buf - len, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < sizeof buf) {
|
||||
len += snprintf(buf + len, sizeof buf - len,
|
||||
": %s (%d)\n", strerror(errcode), errcode);
|
||||
}
|
||||
if (len >= sizeof buf)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
|
||||
void rflush(enum logcode code)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
extern int am_daemon;
|
||||
|
||||
|
||||
if (am_daemon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd == FLOG) {
|
||||
if (code == FLOG) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd == FERROR) {
|
||||
if (code == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd == FINFO) {
|
||||
extern int am_server;
|
||||
if (am_server)
|
||||
if (code == FINFO) {
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(RERR_MESSAGEIO);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* a generic logging routine for send/recv, with parameter
|
||||
substitiution */
|
||||
static void log_formatted(int fd,
|
||||
char *format, char *op, struct file_struct *file,
|
||||
struct stats *initial_stats)
|
||||
* substitiution */
|
||||
static void log_formatted(enum logcode code, char *format, char *op,
|
||||
struct file_struct *file, struct stats *initial_stats,
|
||||
int iflags, char *hlink)
|
||||
{
|
||||
extern int module_id;
|
||||
extern char *auth_user;
|
||||
char buf[1024];
|
||||
char buf2[1024];
|
||||
char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
|
||||
char *p, *s, *n;
|
||||
int l;
|
||||
extern struct stats stats;
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
size_t len, total;
|
||||
int64 b;
|
||||
|
||||
strlcpy(buf, format, sizeof(buf));
|
||||
|
||||
for (s=&buf[0];
|
||||
s && (p=strchr(s,'%')); ) {
|
||||
n = NULL;
|
||||
s = p + 1;
|
||||
*fmt = '%';
|
||||
|
||||
switch (p[1]) {
|
||||
case 'h': if (am_daemon) n = client_name(0); break;
|
||||
case 'a': if (am_daemon) n = client_addr(0); break;
|
||||
case 'l':
|
||||
slprintf(buf2,sizeof(buf2),"%.0f",
|
||||
(double)file->length);
|
||||
/* We expand % codes one by one in place in buf. We don't
|
||||
* copy in the terminating null of the inserted strings, but
|
||||
* rather keep going until we reach the null of the format. */
|
||||
total = strlcpy(buf, format, sizeof buf);
|
||||
if (total > MAXPATHLEN) {
|
||||
rprintf(FERROR, "log-format string is WAY too long!\n");
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
buf[total++] = '\n';
|
||||
buf[total] = '\0';
|
||||
|
||||
for (p = buf; (p = strchr(p, '%')) != NULL; ) {
|
||||
s = p++;
|
||||
n = fmt + 1;
|
||||
if (*p == '-')
|
||||
*n++ = *p++;
|
||||
while (isdigit(*(uchar*)p) && n - fmt < (int)(sizeof fmt) - 8)
|
||||
*n++ = *p++;
|
||||
if (!*p)
|
||||
break;
|
||||
*n = '\0';
|
||||
n = NULL;
|
||||
|
||||
switch (*p) {
|
||||
case 'h':
|
||||
if (am_daemon)
|
||||
n = client_name(0);
|
||||
break;
|
||||
case 'a':
|
||||
if (am_daemon)
|
||||
n = client_addr(0);
|
||||
break;
|
||||
case 'l':
|
||||
strlcat(fmt, ".0f", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt,
|
||||
(double)file->length);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'p':
|
||||
slprintf(buf2,sizeof(buf2),"%d",
|
||||
(int)getpid());
|
||||
case 'U':
|
||||
strlcat(fmt, "ld", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt,
|
||||
(long)file->uid);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'o': n = op; break;
|
||||
case 'f':
|
||||
slprintf(buf2, sizeof(buf2), "%s/%s",
|
||||
file->basedir?file->basedir:"",
|
||||
f_name(file));
|
||||
clean_fname(buf2);
|
||||
n = buf2;
|
||||
if (*n == '/') n++;
|
||||
case 'G':
|
||||
if (file->gid == GID_NONE)
|
||||
n = "DEFAULT";
|
||||
else {
|
||||
strlcat(fmt, "ld", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt,
|
||||
(long)file->gid);
|
||||
n = buf2;
|
||||
}
|
||||
break;
|
||||
case 'm': n = lp_name(module_id); break;
|
||||
case 't': n = timestring(time(NULL)); break;
|
||||
case 'P': n = lp_path(module_id); break;
|
||||
case 'u': n = auth_user; break;
|
||||
case 'b':
|
||||
case 'p':
|
||||
strlcat(fmt, "ld", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt,
|
||||
(long)getpid());
|
||||
n = buf2;
|
||||
break;
|
||||
case 'M':
|
||||
n = timestring(file->modtime);
|
||||
{
|
||||
char *cp = n;
|
||||
while ((cp = strchr(cp, ' ')) != NULL)
|
||||
*cp = '-';
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
n = buf2 + MAXPATHLEN - PERMSTRING_SIZE;
|
||||
permstring(n - 1, file->mode); /* skip the type char */
|
||||
break;
|
||||
case 'o':
|
||||
n = op;
|
||||
break;
|
||||
case 'f':
|
||||
n = f_name(file, NULL);
|
||||
if (am_sender && file->dir.root) {
|
||||
pathjoin(buf2, sizeof buf2,
|
||||
file->dir.root, n);
|
||||
clean_fname(buf2, 0);
|
||||
if (fmt[1])
|
||||
strlcpy(n, buf2, MAXPATHLEN);
|
||||
else
|
||||
n = buf2;
|
||||
} else
|
||||
clean_fname(n, 0);
|
||||
if (*n == '/')
|
||||
n++;
|
||||
break;
|
||||
case 'n':
|
||||
n = f_name(file, NULL);
|
||||
if (S_ISDIR(file->mode))
|
||||
strlcat(n, "/", MAXPATHLEN);
|
||||
break;
|
||||
case 'L':
|
||||
if (hlink && *hlink) {
|
||||
n = hlink;
|
||||
strcpy(buf2, " => ");
|
||||
} else if (S_ISLNK(file->mode) && file->u.link) {
|
||||
n = file->u.link;
|
||||
strcpy(buf2, " -> ");
|
||||
} else {
|
||||
n = "";
|
||||
if (!fmt[1])
|
||||
break;
|
||||
strcpy(buf2, " ");
|
||||
}
|
||||
strlcat(fmt, "s", sizeof fmt);
|
||||
snprintf(buf2 + 4, sizeof buf2 - 4, fmt, n);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'm':
|
||||
n = lp_name(module_id);
|
||||
break;
|
||||
case 't':
|
||||
n = timestring(time(NULL));
|
||||
break;
|
||||
case 'P':
|
||||
n = lp_path(module_id);
|
||||
break;
|
||||
case 'u':
|
||||
n = auth_user;
|
||||
break;
|
||||
case 'b':
|
||||
if (am_sender) {
|
||||
b = stats.total_written -
|
||||
b = stats.total_written -
|
||||
initial_stats->total_written;
|
||||
} else {
|
||||
b = stats.total_read -
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
strlcat(fmt, ".0f", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt, (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'c':
|
||||
case 'c':
|
||||
if (!am_sender) {
|
||||
b = stats.total_written -
|
||||
b = stats.total_written -
|
||||
initial_stats->total_written;
|
||||
} else {
|
||||
b = stats.total_read -
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
strlcat(fmt, ".0f", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt, (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'i':
|
||||
if (iflags & ITEM_DELETED) {
|
||||
n = "*deleting";
|
||||
break;
|
||||
}
|
||||
n = buf2 + MAXPATHLEN - 32;
|
||||
n[0] = iflags & ITEM_LOCAL_CHANGE
|
||||
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
|
||||
: !(iflags & ITEM_TRANSFER) ? '.'
|
||||
: !local_server && *op == 's' ? '<' : '>';
|
||||
n[1] = S_ISDIR(file->mode) ? 'd'
|
||||
: IS_SPECIAL(file->mode) ? 'S'
|
||||
: IS_DEVICE(file->mode) ? 'D'
|
||||
: S_ISLNK(file->mode) ? 'L' : 'f';
|
||||
n[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
|
||||
n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
|
||||
n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
|
||||
: !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
|
||||
n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
|
||||
n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
|
||||
n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
|
||||
n[8] = '.';
|
||||
n[9] = '\0';
|
||||
|
||||
if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
|
||||
char ch = iflags & ITEM_IS_NEW ? '+' : '?';
|
||||
int i;
|
||||
for (i = 2; n[i]; i++)
|
||||
n[i] = ch;
|
||||
} else if (n[0] == '.' || n[0] == 'h'
|
||||
|| (n[0] == 'c' && n[1] == 'f')) {
|
||||
int i;
|
||||
for (i = 2; n[i]; i++) {
|
||||
if (n[i] != '.')
|
||||
break;
|
||||
}
|
||||
if (!n[i]) {
|
||||
for (i = 2; n[i]; i++)
|
||||
n[i] = ' ';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!n) continue;
|
||||
/* "n" is the string to be inserted in place of this % code. */
|
||||
if (!n)
|
||||
continue;
|
||||
if (n != buf2 && fmt[1]) {
|
||||
strlcat(fmt, "s", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt, n);
|
||||
n = buf2;
|
||||
}
|
||||
len = strlen(n);
|
||||
|
||||
l = strlen(n);
|
||||
/* Subtract the length of the escape from the string's size. */
|
||||
total -= p - s + 1;
|
||||
|
||||
if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
|
||||
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
|
||||
if (len + total >= (size_t)sizeof buf) {
|
||||
rprintf(FERROR,
|
||||
"buffer overflow expanding %%%c -- exiting\n",
|
||||
p[0]);
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
|
||||
if (l != 2) {
|
||||
memmove(s+(l-1), s+1, strlen(s+1)+1);
|
||||
}
|
||||
memcpy(p, n, l);
|
||||
/* Shuffle the rest of the string along to make space for n */
|
||||
if (len != (size_t)(p - s + 1))
|
||||
memmove(s + len, p + 1, total - (s - buf) + 1);
|
||||
total += len;
|
||||
|
||||
s = p+l;
|
||||
/* Insert the contents of string "n", but NOT its null. */
|
||||
if (len)
|
||||
memcpy(s, n, len);
|
||||
|
||||
/* Skip over inserted string; continue looking */
|
||||
p = s + len;
|
||||
}
|
||||
|
||||
rprintf(fd,"%s\n", buf);
|
||||
rwrite(code, buf, total);
|
||||
}
|
||||
|
||||
/* log the outgoing transfer of a file */
|
||||
void log_send(struct file_struct *file, struct stats *initial_stats)
|
||||
/* Return 1 if the format escape is in the log-format string (e.g. look for
|
||||
* the 'b' in the "%9b" format escape). */
|
||||
int log_format_has(const char *format, char esc)
|
||||
{
|
||||
extern int module_id;
|
||||
extern int am_server;
|
||||
extern char *log_format;
|
||||
const char *p;
|
||||
|
||||
if (!format)
|
||||
return 0;
|
||||
|
||||
for (p = format; (p = strchr(p, '%')) != NULL; ) {
|
||||
if (*++p == '-')
|
||||
p++;
|
||||
while (isdigit(*(uchar*)p))
|
||||
p++;
|
||||
if (!*p)
|
||||
break;
|
||||
if (*p == esc)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* log the transfer of a file */
|
||||
void log_item(struct file_struct *file, struct stats *initial_stats,
|
||||
int iflags, char *hlink)
|
||||
{
|
||||
char *s_or_r = am_sender ? "send" : "recv";
|
||||
|
||||
if (lp_transfer_logging(module_id)) {
|
||||
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
|
||||
log_formatted(FLOG, lp_log_format(module_id), s_or_r,
|
||||
file, initial_stats, iflags, hlink);
|
||||
} else if (log_format && !am_server) {
|
||||
log_formatted(FINFO, log_format, "send", file, initial_stats);
|
||||
log_formatted(FNAME, log_format, s_or_r,
|
||||
file, initial_stats, iflags, hlink);
|
||||
}
|
||||
}
|
||||
|
||||
/* log the incoming transfer of a file */
|
||||
void log_recv(struct file_struct *file, struct stats *initial_stats)
|
||||
void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
|
||||
char *buf)
|
||||
{
|
||||
extern int module_id;
|
||||
extern int am_server;
|
||||
extern char *log_format;
|
||||
|
||||
if (lp_transfer_logging(module_id)) {
|
||||
log_formatted(FLOG, lp_log_format(module_id), "recv", file, initial_stats);
|
||||
} else if (log_format && !am_server) {
|
||||
log_formatted(FINFO, log_format, "recv", file, initial_stats);
|
||||
}
|
||||
int significant_flags = iflags & SIGNIFICANT_ITEM_FLAGS;
|
||||
int see_item = itemizing && (significant_flags || *buf
|
||||
|| log_format_has_i > 1 || (verbose > 1 && log_format_has_i));
|
||||
int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
|
||||
if (am_server) {
|
||||
if (am_daemon && !dry_run && see_item)
|
||||
log_item(file, &stats, iflags, buf);
|
||||
} else if (see_item || local_change || *buf
|
||||
|| (S_ISDIR(file->mode) && significant_flags))
|
||||
log_item(file, &stats, iflags, buf);
|
||||
}
|
||||
|
||||
/* called when the transfer is interrupted for some reason */
|
||||
void log_delete(char *fname, int mode)
|
||||
{
|
||||
static struct file_struct file;
|
||||
int len = strlen(fname);
|
||||
char *fmt;
|
||||
|
||||
file.mode = mode;
|
||||
file.basename = fname;
|
||||
|
||||
if (!verbose && !log_format)
|
||||
;
|
||||
else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
|
||||
if (S_ISDIR(mode))
|
||||
len++; /* directories include trailing null */
|
||||
send_msg(MSG_DELETED, fname, len);
|
||||
} else {
|
||||
fmt = log_format_has_o_or_i ? log_format : "deleting %n";
|
||||
log_formatted(FCLIENT, fmt, "del.", &file, &stats,
|
||||
ITEM_DELETED, NULL);
|
||||
}
|
||||
|
||||
if (!am_daemon || dry_run || !lp_transfer_logging(module_id))
|
||||
return;
|
||||
|
||||
fmt = daemon_log_format_has_o_or_i ? lp_log_format(module_id) : "deleting %n";
|
||||
log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the transfer is interrupted for some reason.
|
||||
*
|
||||
* Code is one of the RERR_* codes from errcode.h, or terminating
|
||||
* successfully.
|
||||
*/
|
||||
void log_exit(int code, const char *file, int line)
|
||||
{
|
||||
if (code == 0) {
|
||||
extern struct stats stats;
|
||||
rprintf(FLOG,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
|
||||
rprintf(FLOG,"sent %.0f bytes received %.0f bytes total size %.0f\n",
|
||||
(double)stats.total_written,
|
||||
(double)stats.total_read,
|
||||
(double)stats.total_size);
|
||||
} else {
|
||||
rprintf(FLOG,"transfer interrupted (code %d) at %s(%d)\n",
|
||||
code, file, line);
|
||||
const char *name;
|
||||
|
||||
name = rerr_name(code);
|
||||
if (!name)
|
||||
name = "unexplained error";
|
||||
|
||||
/* VANISHED is not an error, only a warning */
|
||||
if (code == RERR_VANISHED) {
|
||||
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s]\n",
|
||||
name, code, file, line, who_am_i());
|
||||
} else {
|
||||
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s]\n",
|
||||
name, code, file, line, who_am_i());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* log the incoming transfer of a file for interactive use, this
|
||||
will be called at the end where the client was run
|
||||
|
||||
it i called when a file starts to be transferred
|
||||
*/
|
||||
void log_transfer(struct file_struct *file, const char *fname)
|
||||
{
|
||||
extern int verbose;
|
||||
|
||||
if (!verbose) return;
|
||||
|
||||
rprintf(FINFO,"%s\n", fname);
|
||||
}
|
||||
|
||||
|
||||
406
match.c
406
match.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
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.
|
||||
@@ -19,226 +19,256 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
extern int do_progress;
|
||||
extern int checksum_seed;
|
||||
extern int append_mode;
|
||||
|
||||
extern int remote_version;
|
||||
|
||||
typedef unsigned short tag;
|
||||
|
||||
#define TABLESIZE (1<<16)
|
||||
#define NULL_TAG (-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;
|
||||
int i;
|
||||
};
|
||||
#define TABLESIZE (1<<16)
|
||||
|
||||
static struct target *targets;
|
||||
|
||||
static int *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)
|
||||
{
|
||||
int i;
|
||||
int32 i;
|
||||
|
||||
if (!tag_table)
|
||||
tag_table = (int *)malloc(sizeof(tag_table[0])*TABLESIZE);
|
||||
if (!hash_table) {
|
||||
hash_table = new_array(int32, TABLESIZE);
|
||||
if (!hash_table)
|
||||
out_of_memory("build_hash_table");
|
||||
}
|
||||
|
||||
targets = (struct target *)malloc(sizeof(targets[0])*s->count);
|
||||
if (!tag_table || !targets)
|
||||
out_of_memory("build_hash_table");
|
||||
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
|
||||
|
||||
for (i=0;i<s->count;i++) {
|
||||
targets[i].i = i;
|
||||
targets[i].t = gettag(s->sums[i].sum1);
|
||||
}
|
||||
|
||||
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
|
||||
|
||||
for (i=0;i<TABLESIZE;i++)
|
||||
tag_table[i] = NULL_TAG;
|
||||
|
||||
for (i=s->count-1;i>=0;i--) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static OFF_T last_match;
|
||||
|
||||
|
||||
static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
OFF_T offset,int i)
|
||||
/**
|
||||
* Transmit a literal and/or match token.
|
||||
*
|
||||
* This delightfully-named function is called either when we find a
|
||||
* match and need to transmit all the unmatched data leading up to it,
|
||||
* or when we get bored of accumulating literal data and just need to
|
||||
* transmit it. As a result of this second case, it is called even if
|
||||
* we have not matched at all!
|
||||
*
|
||||
* @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, int32 i)
|
||||
{
|
||||
OFF_T n = offset - last_match;
|
||||
OFF_T j;
|
||||
int32 n = offset - last_match; /* max value: block_size (int32) */
|
||||
int32 j;
|
||||
|
||||
if (verbose > 2 && i >= 0)
|
||||
rprintf(FINFO,"match at %d last_match=%d j=%d len=%d n=%d\n",
|
||||
(int)offset,(int)last_match,i,(int)s->sums[i].len,(int)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) {
|
||||
stats.matched_data += s->sums[i].len;
|
||||
n += s->sums[i].len;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (j = 0; j < n; j += CHUNK_SIZE) {
|
||||
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)
|
||||
if (buf && do_progress)
|
||||
show_progress(last_match, buf->file_size);
|
||||
|
||||
if (i == -1) end_progress();
|
||||
}
|
||||
|
||||
|
||||
static void hash_search(int f,struct sum_struct *s,
|
||||
struct map_struct *buf,OFF_T len)
|
||||
struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
OFF_T offset;
|
||||
int j,k, last_i;
|
||||
int end;
|
||||
OFF_T offset, end, backup;
|
||||
int32 k, want_i;
|
||||
char sum2[SUM_LENGTH];
|
||||
uint32 s1, s2, sum;
|
||||
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 = -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=%d len=%d\n",s->n,(int)len);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "hash search b=%ld len=%.0f\n",
|
||||
(long)s->blength, (double)len);
|
||||
}
|
||||
|
||||
k = (int32)MIN(len, (OFF_T)s->blength);
|
||||
|
||||
map = (schar *)map_ptr(buf, 0, k);
|
||||
|
||||
k = MIN(len, s->n);
|
||||
|
||||
map = (schar *)map_ptr(buf,0,k);
|
||||
|
||||
sum = get_checksum1((char *)map, k);
|
||||
s1 = sum & 0xFFFF;
|
||||
s2 = sum >> 16;
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "sum=%.8x k=%d\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->n=%d len=%d count=%d\n",
|
||||
s->n,(int)len,s->count);
|
||||
|
||||
|
||||
if (verbose > 3) {
|
||||
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;
|
||||
|
||||
j = tag_table[t];
|
||||
if (verbose > 4)
|
||||
rprintf(FINFO,"offset=%d sum=%08x\n",(int)offset,sum);
|
||||
|
||||
if (j == NULL_TAG) {
|
||||
goto null_tag;
|
||||
int32 i;
|
||||
|
||||
if (verbose > 4) {
|
||||
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
|
||||
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
|
||||
}
|
||||
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
tag_hits++;
|
||||
for (; j<s->count && targets[j].t == t; j++) {
|
||||
int l, i = targets[j].i;
|
||||
|
||||
if (sum != s->sums[i].sum1) continue;
|
||||
|
||||
/* also make sure the two blocks are the same length */
|
||||
l = MIN(s->n,len-offset);
|
||||
if (l != s->sums[i].len) continue;
|
||||
i = hash_table[SUM2HASH2(s1,s2)];
|
||||
if (i < 0)
|
||||
goto null_hash;
|
||||
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
hash_hits++;
|
||||
do {
|
||||
int32 l;
|
||||
|
||||
if (sum != s->sums[i].sum1)
|
||||
continue;
|
||||
|
||||
/* also make sure the two blocks are the same length */
|
||||
l = (int32)MIN((OFF_T)s->blength, len-offset);
|
||||
if (l != s->sums[i].len)
|
||||
continue;
|
||||
|
||||
/* 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 (verbose > 3)
|
||||
rprintf(FINFO,"potential match at %d target=%d %d sum=%08x\n",
|
||||
(int)offset,j,i,sum);
|
||||
|
||||
if (!done_csum2) {
|
||||
map = (schar *)map_ptr(buf,offset,l);
|
||||
get_checksum2((char *)map,l,sum2);
|
||||
done_csum2 = 1;
|
||||
}
|
||||
|
||||
if (memcmp(sum2,s->sums[i].sum2,csum_length) != 0) {
|
||||
|
||||
if (memcmp(sum2,s->sums[i].sum2,s->s2length) != 0) {
|
||||
false_alarms++;
|
||||
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++) {
|
||||
int i2 = targets[j].i;
|
||||
if (i2 == last_i + 1) {
|
||||
if (sum != s->sums[i2].sum1) break;
|
||||
if (memcmp(sum2,s->sums[i2].sum2,csum_length) != 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((len-offset), s->n);
|
||||
map = (schar *)map_ptr(buf,offset,k);
|
||||
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;
|
||||
}
|
||||
|
||||
null_tag:
|
||||
} while ((i = s->sums[i].chain) >= 0);
|
||||
|
||||
null_hash:
|
||||
backup = offset - last_match;
|
||||
/* We sometimes read 1 byte prior to last_match... */
|
||||
if (backup < 0)
|
||||
backup = 0;
|
||||
|
||||
/* 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 {
|
||||
} else
|
||||
--k;
|
||||
}
|
||||
|
||||
/* By matching early we avoid re-reading the
|
||||
data 3 times in the case where a token
|
||||
@@ -246,67 +276,92 @@ 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 >= CHUNK_SIZE+s->n &&
|
||||
(end-offset > CHUNK_SIZE)) {
|
||||
matched(f,s,buf,offset - s->n, -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);
|
||||
}
|
||||
|
||||
|
||||
void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
|
||||
/**
|
||||
* Scan through a origin file, looking for sections that match
|
||||
* checksums from the generator, and transmit either literal or token
|
||||
* data.
|
||||
*
|
||||
* Also calculates the MD4 checksum of the whole file, using the md
|
||||
* accumulator. This is transmitted with the file as protection
|
||||
* against corruption on the wire.
|
||||
*
|
||||
* @param s Checksums received from the generator. If <tt>s->count ==
|
||||
* 0</tt>, then there are actually no checksums for this file.
|
||||
*
|
||||
* @param len Length of the file to send.
|
||||
**/
|
||||
void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
char file_sum[MD4_SUM_LENGTH];
|
||||
|
||||
last_match = 0;
|
||||
false_alarms = 0;
|
||||
tag_hits = 0;
|
||||
matches=0;
|
||||
data_transfer=0;
|
||||
hash_hits = 0;
|
||||
matches = 0;
|
||||
data_transfer = 0;
|
||||
|
||||
sum_init();
|
||||
sum_init(checksum_seed);
|
||||
|
||||
if (len > 0 && s->count>0) {
|
||||
if (append_mode) {
|
||||
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 len = s->flength - last_match;
|
||||
if (buf && do_progress)
|
||||
show_progress(last_match, buf->file_size);
|
||||
sum_update(map_ptr(buf, last_match, len), len);
|
||||
last_match = s->flength;
|
||||
}
|
||||
s->count = 0;
|
||||
}
|
||||
|
||||
if (len > 0 && s->count > 0) {
|
||||
build_hash_table(s);
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"built hash table\n");
|
||||
|
||||
|
||||
hash_search(f,s,buf,len);
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
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);
|
||||
/* If we had a read error, send a bad checksum. */
|
||||
if (buf && buf->status != 0)
|
||||
file_sum[0]++;
|
||||
|
||||
if (remote_version >= 14) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f,file_sum,MD4_SUM_LENGTH);
|
||||
}
|
||||
|
||||
if (targets) {
|
||||
free(targets);
|
||||
targets=NULL;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
|
||||
false_alarms, tag_hits, matches);
|
||||
|
||||
total_tag_hits += tag_hits;
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f,file_sum,MD4_SUM_LENGTH);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
|
||||
false_alarms, hash_hits, matches);
|
||||
|
||||
total_hash_hits += hash_hits;
|
||||
total_false_alarms += false_alarms;
|
||||
total_matches += matches;
|
||||
stats.literal_data += data_transfer;
|
||||
@@ -318,8 +373,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);
|
||||
}
|
||||
|
||||
263
md4.c
263
md4.c
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
This code is from rfc1186.
|
||||
|
||||
It has been modified to use the SIVAL() macro to make it
|
||||
byte order and length independent, so we don't need the LOWBYTEFIRST define
|
||||
*/
|
||||
|
||||
/*
|
||||
** ********************************************************************
|
||||
** md4.c -- Implementation of MD4 Message Digest Algorithm **
|
||||
** Updated: 2/16/90 by Ronald L. Rivest **
|
||||
** (C) 1990 RSA Data Security, Inc. **
|
||||
** ********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
** To use MD4:
|
||||
** -- Include md4.h in your program
|
||||
** -- Declare an MDstruct MD to hold the state of the digest
|
||||
** computation.
|
||||
** -- Initialize MD using MDbegin(&MD)
|
||||
** -- For each full block (64 bytes) X you wish to process, call
|
||||
** MDupdate(&MD,X,512)
|
||||
** (512 is the number of bits in a full block.)
|
||||
** -- For the last block (less than 64 bytes) you wish to process,
|
||||
** MDupdate(&MD,X,n)
|
||||
** where n is the number of bits in the partial block. A partial
|
||||
** block terminates the computation, so every MD computation
|
||||
** should terminate by processing a partial block, even if it
|
||||
** has n = 0.
|
||||
** -- The message digest is available in MD.buffer[0] ...
|
||||
** MD.buffer[3]. (Least-significant byte of each word
|
||||
** should be output first.)
|
||||
** -- You can print out the digest using MDprint(&MD)
|
||||
*/
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/* Compile-time includes
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* Compile-time declarations of MD4 "magic constants".
|
||||
*/
|
||||
#define I0 0x67452301 /* Initial values for MD buffer */
|
||||
#define I1 0xefcdab89
|
||||
#define I2 0x98badcfe
|
||||
#define I3 0x10325476
|
||||
#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
|
||||
#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
|
||||
/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
|
||||
** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
|
||||
** Table 2, page 660.
|
||||
*/
|
||||
|
||||
#define fs1 3 /* round 1 shift amounts */
|
||||
#define fs2 7
|
||||
#define fs3 11
|
||||
#define fs4 19
|
||||
#define gs1 3 /* round 2 shift amounts */
|
||||
#define gs2 5
|
||||
#define gs3 9
|
||||
#define gs4 13
|
||||
#define hs1 3 /* round 3 shift amounts */
|
||||
#define hs2 9
|
||||
#define hs3 11
|
||||
#define hs4 15
|
||||
|
||||
/* Compile-time macro declarations for MD4.
|
||||
** Note: The "rot" operator uses the variable "tmp".
|
||||
** It assumes tmp is declared as unsigned int, so that the >>
|
||||
** operator will shift in zeros rather than extending the sign bit.
|
||||
*/
|
||||
#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
|
||||
#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
|
||||
#define h(X,Y,Z) (X^Y^Z)
|
||||
#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
|
||||
#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
|
||||
#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
|
||||
#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
|
||||
|
||||
/* MDbegin(MDp)
|
||||
** Initialize message digest buffer MDp.
|
||||
** This is a user-callable routine.
|
||||
*/
|
||||
void
|
||||
MDbegin(MDp)
|
||||
MDptr MDp;
|
||||
{ int i;
|
||||
MDp->buffer[0] = I0;
|
||||
MDp->buffer[1] = I1;
|
||||
MDp->buffer[2] = I2;
|
||||
MDp->buffer[3] = I3;
|
||||
for (i=0;i<8;i++) MDp->count[i] = 0;
|
||||
MDp->done = 0;
|
||||
}
|
||||
|
||||
/* MDreverse(X)
|
||||
** Reverse the byte-ordering of every int in X.
|
||||
** Assumes X is an array of 16 ints.
|
||||
** The macro revx reverses the byte-ordering of the next word of X.
|
||||
*/
|
||||
static void MDreverse(X)
|
||||
unsigned int32 *X;
|
||||
{ register unsigned int32 t;
|
||||
register unsigned int i;
|
||||
|
||||
for(i = 0; i < 16; i++) {
|
||||
t = X[i];
|
||||
SIVAL(X,i*4,t);
|
||||
}
|
||||
}
|
||||
|
||||
/* MDblock(MDp,X)
|
||||
** Update message digest buffer MDp->buffer using 16-word data block X.
|
||||
** Assumes all 16 words of X are full of data.
|
||||
** Does not update MDp->count.
|
||||
** This routine is not user-callable.
|
||||
*/
|
||||
static void
|
||||
MDblock(MDp,X)
|
||||
MDptr MDp;
|
||||
unsigned int32 *X;
|
||||
{
|
||||
register unsigned int32 tmp, A, B, C, D;
|
||||
MDreverse(X);
|
||||
A = MDp->buffer[0];
|
||||
B = MDp->buffer[1];
|
||||
C = MDp->buffer[2];
|
||||
D = MDp->buffer[3];
|
||||
/* Update the message digest buffer */
|
||||
ff(A , B , C , D , 0 , fs1); /* Round 1 */
|
||||
ff(D , A , B , C , 1 , fs2);
|
||||
ff(C , D , A , B , 2 , fs3);
|
||||
ff(B , C , D , A , 3 , fs4);
|
||||
ff(A , B , C , D , 4 , fs1);
|
||||
ff(D , A , B , C , 5 , fs2);
|
||||
ff(C , D , A , B , 6 , fs3);
|
||||
ff(B , C , D , A , 7 , fs4);
|
||||
ff(A , B , C , D , 8 , fs1);
|
||||
ff(D , A , B , C , 9 , fs2);
|
||||
ff(C , D , A , B , 10 , fs3);
|
||||
ff(B , C , D , A , 11 , fs4);
|
||||
ff(A , B , C , D , 12 , fs1);
|
||||
ff(D , A , B , C , 13 , fs2);
|
||||
ff(C , D , A , B , 14 , fs3);
|
||||
ff(B , C , D , A , 15 , fs4);
|
||||
gg(A , B , C , D , 0 , gs1); /* Round 2 */
|
||||
gg(D , A , B , C , 4 , gs2);
|
||||
gg(C , D , A , B , 8 , gs3);
|
||||
gg(B , C , D , A , 12 , gs4);
|
||||
gg(A , B , C , D , 1 , gs1);
|
||||
gg(D , A , B , C , 5 , gs2);
|
||||
gg(C , D , A , B , 9 , gs3);
|
||||
gg(B , C , D , A , 13 , gs4);
|
||||
gg(A , B , C , D , 2 , gs1);
|
||||
gg(D , A , B , C , 6 , gs2);
|
||||
gg(C , D , A , B , 10 , gs3);
|
||||
gg(B , C , D , A , 14 , gs4);
|
||||
gg(A , B , C , D , 3 , gs1);
|
||||
gg(D , A , B , C , 7 , gs2);
|
||||
gg(C , D , A , B , 11 , gs3);
|
||||
gg(B , C , D , A , 15 , gs4);
|
||||
hh(A , B , C , D , 0 , hs1); /* Round 3 */
|
||||
hh(D , A , B , C , 8 , hs2);
|
||||
hh(C , D , A , B , 4 , hs3);
|
||||
hh(B , C , D , A , 12 , hs4);
|
||||
hh(A , B , C , D , 2 , hs1);
|
||||
hh(D , A , B , C , 10 , hs2);
|
||||
hh(C , D , A , B , 6 , hs3);
|
||||
hh(B , C , D , A , 14 , hs4);
|
||||
hh(A , B , C , D , 1 , hs1);
|
||||
hh(D , A , B , C , 9 , hs2);
|
||||
hh(C , D , A , B , 5 , hs3);
|
||||
hh(B , C , D , A , 13 , hs4);
|
||||
hh(A , B , C , D , 3 , hs1);
|
||||
hh(D , A , B , C , 11 , hs2);
|
||||
hh(C , D , A , B , 7 , hs3);
|
||||
hh(B , C , D , A , 15 , hs4);
|
||||
MDp->buffer[0] += A;
|
||||
MDp->buffer[1] += B;
|
||||
MDp->buffer[2] += C;
|
||||
MDp->buffer[3] += D;
|
||||
}
|
||||
|
||||
/* MDupdate(MDp,X,count)
|
||||
** Input: MDp -- an MDptr
|
||||
** X -- a pointer to an array of unsigned characters.
|
||||
** count -- the number of bits of X to use.
|
||||
** (if not a multiple of 8, uses high bits of last byte.)
|
||||
** Update MDp using the number of bits of X given by count.
|
||||
** This is the basic input routine for an MD4 user.
|
||||
** The routine completes the MD computation when count < 512, so
|
||||
** every MD computation should end with one call to MDupdate with a
|
||||
** count less than 512. A call with count 0 will be ignored if the
|
||||
** MD has already been terminated (done != 0), so an extra call with
|
||||
** count 0 can be given as a "courtesy close" to force termination
|
||||
** if desired.
|
||||
*/
|
||||
void
|
||||
MDupdate(MDp,X,count)
|
||||
MDptr MDp;
|
||||
unsigned char *X;
|
||||
unsigned int count;
|
||||
{ unsigned int32 i, tmp, bit, byte, mask;
|
||||
unsigned char XX[64];
|
||||
unsigned char *p;
|
||||
/* return with no error if this is a courtesy close with count
|
||||
** zero and MDp->done is true.
|
||||
*/
|
||||
if (count == 0 && MDp->done) return;
|
||||
/* check to see if MD is already done and report error */
|
||||
if (MDp->done)
|
||||
{ rprintf(FERROR,"\nError: MDupdate MD already done."); return; }
|
||||
/* Add count to MDp->count */
|
||||
tmp = count;
|
||||
p = MDp->count;
|
||||
while (tmp)
|
||||
{ tmp += *p;
|
||||
*p++ = tmp;
|
||||
tmp = tmp >> 8;
|
||||
}
|
||||
/* Process data */
|
||||
if (count == 512)
|
||||
{ /* Full block of data to handle */
|
||||
MDblock(MDp,(unsigned int32 *)X);
|
||||
}
|
||||
else if (count > 512) /* Check for count too large */
|
||||
{ rprintf(FERROR,"\nError: MDupdate called with illegal count value %d."
|
||||
,count);
|
||||
return;
|
||||
}
|
||||
else /* partial block -- must be last block so finish up */
|
||||
{ /* Find out how many bytes and residual bits there are */
|
||||
byte = count >> 3;
|
||||
bit = count & 7;
|
||||
/* Copy X into XX since we need to modify it */
|
||||
for (i=0;i<=byte;i++) XX[i] = X[i];
|
||||
for (i=byte+1;i<64;i++) XX[i] = 0;
|
||||
/* Add padding '1' bit and low-order zeros in last byte */
|
||||
mask = 1 << (7 - bit);
|
||||
XX[byte] = (XX[byte] | mask) & ~( mask - 1);
|
||||
/* If room for bit count, finish up with this block */
|
||||
if (byte <= 55)
|
||||
{ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
|
||||
MDblock(MDp,(unsigned int32 *)XX);
|
||||
}
|
||||
else /* need to do two blocks to finish up */
|
||||
{ MDblock(MDp,(unsigned int32 *)XX);
|
||||
for (i=0;i<56;i++) XX[i] = 0;
|
||||
for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
|
||||
MDblock(MDp,(unsigned int32 *)XX);
|
||||
}
|
||||
/* Set flag saying we're done with MD computation */
|
||||
MDp->done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** End of md4.c
|
||||
*/
|
||||
49
md4.h
49
md4.h
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
This code is from rfc1186.
|
||||
*/
|
||||
|
||||
/*
|
||||
** ********************************************************************
|
||||
** md4.h -- Header file for implementation of **
|
||||
** MD4 Message Digest Algorithm **
|
||||
** Updated: 2/13/90 by Ronald L. Rivest **
|
||||
** (C) 1990 RSA Data Security, Inc. **
|
||||
** ********************************************************************
|
||||
*/
|
||||
|
||||
/* MDstruct is the data structure for a message digest computation.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int32 buffer[4]; /* Holds 4-word result of MD computation */
|
||||
unsigned char count[8]; /* Number of bits processed so far */
|
||||
unsigned int done; /* Nonzero means MD computation finished */
|
||||
} MDstruct, *MDptr;
|
||||
|
||||
/* MDbegin(MD)
|
||||
|
||||
|
||||
|
||||
** Input: MD -- an MDptr
|
||||
** Initialize the MDstruct prepatory to doing a message digest
|
||||
** computation.
|
||||
*/
|
||||
extern void MDbegin();
|
||||
|
||||
/* MDupdate(MD,X,count)
|
||||
** Input: MD -- an MDptr
|
||||
** X -- a pointer to an array of unsigned characters.
|
||||
** count -- the number of bits of X to use (an unsigned int).
|
||||
** Updates MD using the first "count" bits of X.
|
||||
** The array pointed to by X is not modified.
|
||||
** If count is not a multiple of 8, MDupdate uses high bits of
|
||||
** last byte.
|
||||
** This is the basic input routine for a user.
|
||||
** The routine terminates the MD computation when count < 512, so
|
||||
** every MD computation should end with one call to MDupdate with a
|
||||
** count less than 512. Zero is OK for a count.
|
||||
*/
|
||||
extern void MDupdate();
|
||||
|
||||
/*
|
||||
** End of md4.h
|
||||
*/
|
||||
@@ -58,7 +58,7 @@ BEGIN {
|
||||
next;
|
||||
}
|
||||
|
||||
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ {
|
||||
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^uchar|^short|^struct|^BOOL|^void|^time|^const|^RETSIGTYPE/ {
|
||||
next;
|
||||
}
|
||||
|
||||
|
||||
88
packaging/lsb/rsync.spec
Normal file
88
packaging/lsb/rsync.spec
Normal file
@@ -0,0 +1,88 @@
|
||||
Summary: A program for synchronizing files over a network.
|
||||
Name: rsync
|
||||
Version: 2.6.7
|
||||
Release: 1
|
||||
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 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.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%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>
|
||||
Fixed "Sept" date in %changelog here
|
||||
Use %{_mandir} to point to manpages
|
||||
Support for compressed manpages (* at end catches them in %files)
|
||||
Add doc/README-SGML and doc/rsync.sgml to %doc
|
||||
|
||||
* Mon Sep 11 2000 John H Terpstra <jht@turbolinux.com>
|
||||
Changed target paths to be Linux Standards Base compliant
|
||||
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
116
packaging/nightly-rsync
Executable file
116
packaging/nightly-rsync
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/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($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 $!;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
system "find . -name 'rsync-HEAD-*' -daystart -mtime +14 | xargs rm -f";
|
||||
system 'ls -ltr';
|
||||
|
||||
if ($upload) {
|
||||
$ENV{RSYNC_PARTIAL_DIR} = ''; # The rsync on samba.org is OLD.
|
||||
system "rsync -aviHP --delete . 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
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.3.0
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.3.0.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for 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
|
||||
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.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS=$RPM_OPT_FLAGS
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
@@ -1,79 +0,0 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: PVERSION
|
||||
Release: PRELEASE
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-PVERSION.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for 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
|
||||
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.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS=$RPM_OPT_FLAGS
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
317
packaging/release-rsync
Executable file
317
packaging/release-rsync
Executable file
@@ -0,0 +1,317 @@
|
||||
#!/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;
|
||||
|
||||
$lastversion =~ s/(\d+)cvs$/ $1 - 1 /e;
|
||||
$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 configure, config.h.in, and proto.h are updated
|
||||
- tweak the version in configure.in, configure, and the spec files
|
||||
- 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( 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;
|
||||
} else {
|
||||
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*$/$1 ($today)\n/m;
|
||||
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m;
|
||||
}
|
||||
open(OUT, '>', $fn) or die $!;
|
||||
print OUT $_;
|
||||
close OUT;
|
||||
}
|
||||
|
||||
system "yodl2man -o rsync.1 rsync.yo";
|
||||
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo";
|
||||
#system "perl -pi -e \"s/\\\\\\'/\\\\&'/g\" rsync.1 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_file = "$dest/rsync-$version.tar.gz";
|
||||
my $diff_file = "$dest/rsync-$lastversion-$version.diffs.gz";
|
||||
|
||||
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 moved tar/diff files to old files on samba.org$skipping
|
||||
- create release tar, "$tar_file"
|
||||
- create release diffs, "$diff_file"
|
||||
- update README, *NEWS, TODO, and cvs.log
|
||||
- update rsync*.html man pages
|
||||
|
||||
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')) {
|
||||
my $new_fn = "old-previews/$fn";
|
||||
rename($fn, $new_fn) or die $!;
|
||||
push(@moved_files, $new_fn);
|
||||
}
|
||||
|
||||
if ($version !~ /pre/) {
|
||||
foreach my $fn (glob('rsync*.tar.gz*'), glob('rsync*-NEWS')) {
|
||||
next if $fn =~ /^rsync.*pre/;
|
||||
my $new_fn = "old-versions/$fn";
|
||||
rename($fn, $new_fn) or die $!;
|
||||
push(@moved_files, $new_fn);
|
||||
}
|
||||
|
||||
foreach my $fn (glob('rsync*.diffs.gz*')) {
|
||||
next if $fn =~ /^rsync.*pre/;
|
||||
my $new_fn = "old-patches/$fn";
|
||||
rename($fn, $new_fn) or die $!;
|
||||
push(@moved_files, $new_fn);
|
||||
}
|
||||
}
|
||||
|
||||
# Optimize our future upload (in the absence of --detect-renamed) by
|
||||
# hard-linking the above moved files on the remote server.
|
||||
if ($live) {
|
||||
my $remote_cmd = '';
|
||||
foreach (@moved_files) {
|
||||
my($path, $fn) = m#(.*)/([^/]+)$#;
|
||||
$remote_cmd .= "ln -f /home/ftp/pub/rsync/{$fn,$path};";
|
||||
}
|
||||
system "ssh samba.org '$remote_cmd'";
|
||||
}
|
||||
foreach (glob("rsync*pre*.diffs.gz*")) {
|
||||
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 rsync-$version.tar.gz";
|
||||
system "gpg -ba rsync-$lastversion-$version.diffs.gz";
|
||||
}
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
All done. Remember to announce the release on *BOTH*
|
||||
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
|
||||
EOT
|
||||
94
packaging/solaris/build_pkg.sh
Normal file
94
packaging/solaris/build_pkg.sh
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
# Shell script for building Solaris package of rsync
|
||||
# Author: Jens Apel <jens.apel@web.de>
|
||||
# License: GPL
|
||||
#
|
||||
# BASEDIR is /usr/local and should be the same as the
|
||||
# --prefix parameter of configure
|
||||
#
|
||||
# this script should be copied under
|
||||
# packaging/solaris/5.8/build_pkg.sh
|
||||
|
||||
# Definitions start here
|
||||
# you can edit this, if you like
|
||||
|
||||
# The Package name under which rsync will b installed
|
||||
PKGNAME=SMBrsync
|
||||
|
||||
# Extract common info requires for the 'info' part of the package.
|
||||
# This should be made generic and generated by the configure script
|
||||
# but for now it is hard coded
|
||||
BASEDIR=/usr/local
|
||||
VERSION="2.5.5"
|
||||
ARCH=`uname -p`
|
||||
NAME=rsync
|
||||
|
||||
# Definitions end here
|
||||
# Please do not edit below this line or you know what you do.
|
||||
|
||||
## Start by faking root install
|
||||
echo "Creating install directory (fake $BASEDIR)..."
|
||||
START=`pwd`
|
||||
FAKE_ROOT=$START/${PKGNAME}
|
||||
mkdir $FAKE_ROOT
|
||||
|
||||
# copy the binary and the man page to their places
|
||||
mkdir $FAKE_ROOT/bin
|
||||
mkdir -p $FAKE_ROOT/doc/rsync
|
||||
mkdir -p $FAKE_ROOT/man/man1
|
||||
mkdir -p $FAKE_ROOT/man/man5
|
||||
|
||||
cp ../../../rsync $FAKE_ROOT/bin/rsync
|
||||
cp ../../../rsync.1 $FAKE_ROOT/man/man1/rsync.1
|
||||
cp ../../../rsyncd.conf.5 $FAKE_ROOT/man/man5/rsyncd.conf.5
|
||||
cp ../../../README $FAKE_ROOT/doc/rsync/README
|
||||
cp ../../../COPYING $FAKE_ROOT/doc/rsync/COPYING
|
||||
cp ../../../tech_report.pdf $FAKE_ROOT/doc/rsync/tech_report.pdf
|
||||
cp ../../../COPYING $FAKE_ROOT/COPYING
|
||||
|
||||
## Build info file
|
||||
echo "Building pkginfo file..."
|
||||
cat > $FAKE_ROOT/pkginfo << EOF_INFO
|
||||
PKG=$PKGNAME
|
||||
NAME=$NAME
|
||||
DESC="Program for efficient remote updates of files."
|
||||
VENDOR="Samba Team URL: http://samba.anu.edu.au/rsync/"
|
||||
BASEDIR=$BASEDIR
|
||||
ARCH=$ARCH
|
||||
VERSION=$VERSION
|
||||
CATEGORY=application
|
||||
CLASSES=none
|
||||
EOF_INFO
|
||||
|
||||
## Build prototype file
|
||||
cat > $FAKE_ROOT/prototype << EOFPROTO
|
||||
i copyright=COPYING
|
||||
i pkginfo=pkginfo
|
||||
d none bin 0755 bin bin
|
||||
f none bin/rsync 0755 bin bin
|
||||
d none doc 0755 bin bin
|
||||
d none doc/$NAME 0755 bin bin
|
||||
f none doc/$NAME/README 0644 bin bin
|
||||
f none doc/$NAME/COPYING 0644 bin bin
|
||||
f none doc/$NAME/tech_report.pdf 0644 bin bin
|
||||
d none man 0755 bin bin
|
||||
d none man/man1 0755 bin bin
|
||||
f none man/man1/rsync.1 0644 bin bin
|
||||
d none man/man5 0755 bin bin
|
||||
f none man/man5/rsyncd.conf.5 0644 bin bin
|
||||
EOFPROTO
|
||||
|
||||
## And now build the package.
|
||||
OUTPUTFILE=$PKGNAME-$VERSION-sol8-$ARCH-local.pkg
|
||||
echo "Building package.."
|
||||
echo FAKE_ROOT = $FAKE_ROOT
|
||||
cd $FAKE_ROOT
|
||||
pkgmk -d . -r . -f ./prototype -o
|
||||
pkgtrans -os . $OUTPUTFILE $PKGNAME
|
||||
|
||||
mv $OUTPUTFILE ..
|
||||
cd ..
|
||||
|
||||
# Comment this out if you want to see, which file structure has been created
|
||||
rm -rf $FAKE_ROOT
|
||||
|
||||
16
params.c
16
params.c
@@ -164,7 +164,7 @@ static int Continuation( char *line, int pos )
|
||||
*/
|
||||
{
|
||||
pos--;
|
||||
while( (pos >= 0) && isspace(line[pos]) )
|
||||
while( (pos >= 0) && isspace(((unsigned char *)line)[pos]) )
|
||||
pos--;
|
||||
|
||||
return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
|
||||
@@ -207,7 +207,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
|
||||
if( i > (bSize - 2) )
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = Realloc( bufr, bSize );
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func);
|
||||
@@ -301,7 +301,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
if( i > (bSize - 2) ) /* Ensure there's space for next char. */
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = Realloc( bufr, bSize );
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
|
||||
@@ -366,7 +366,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
if( i > (bSize - 2) ) /* Make sure there's enough room. */
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = Realloc( bufr, bSize );
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
|
||||
@@ -386,7 +386,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
c = 0;
|
||||
else
|
||||
{
|
||||
for( end = i; (end >= 0) && isspace(bufr[end]); end-- )
|
||||
for( end = i; (end >= 0) && isspace(((unsigned char *) bufr)[end]); end-- )
|
||||
;
|
||||
c = getc( InFile );
|
||||
}
|
||||
@@ -491,8 +491,8 @@ static FILE *OpenConfFile( char *FileName )
|
||||
OpenedFile = fopen( FileName, "r" );
|
||||
if( NULL == OpenedFile )
|
||||
{
|
||||
rprintf(FERROR,"%s Unable to open configuration file \"%s\":\n\t%s\n",
|
||||
func, FileName, strerror(errno));
|
||||
rsyserr(FERROR, errno, "rsync: unable to open configuration file \"%s\"",
|
||||
FileName);
|
||||
}
|
||||
|
||||
return( OpenedFile );
|
||||
@@ -530,7 +530,7 @@ BOOL pm_process( char *FileName,
|
||||
else /* If we don't have a buffer */
|
||||
{ /* allocate one, then parse, */
|
||||
bSize = BUFR_INC; /* then free. */
|
||||
bufr = (char *)malloc( bSize );
|
||||
bufr = new_array( char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR,"%s memory allocation failure.\n", func);
|
||||
|
||||
159
pipe.c
Normal file
159
pipe.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* -*- 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>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int blocking_io;
|
||||
extern int filesfrom_fd;
|
||||
extern mode_t orig_umask;
|
||||
extern struct chmod_mode_struct *chmod_modes;
|
||||
|
||||
/**
|
||||
* Create a child connected to us via its stdin/stdout.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* If blocking_io is set then use blocking io on both fds. That can be
|
||||
* used to cope with badly broken rsh implementations like the one on
|
||||
* Solaris.
|
||||
**/
|
||||
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 (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
|
||||
rsyserr(FERROR, errno, "pipe");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
rsyserr(FERROR, errno, "fork");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
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) {
|
||||
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]);
|
||||
umask(orig_umask);
|
||||
set_blocking(STDIN_FILENO);
|
||||
if (blocking_io > 0)
|
||||
set_blocking(STDOUT_FILENO);
|
||||
execvp(command[0], command);
|
||||
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) {
|
||||
rsyserr(FERROR, errno, "Failed to close");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
*f_in = from_child_pipe[0];
|
||||
*f_out = to_child_pipe[1];
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
rsyserr(FERROR, errno, "pipe");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
rsyserr(FERROR, errno, "fork");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
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) {
|
||||
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]);
|
||||
child_main(argc, argv);
|
||||
}
|
||||
|
||||
if (close(from_child_pipe[1]) < 0 ||
|
||||
close(to_child_pipe[0]) < 0) {
|
||||
rsyserr(FERROR, errno, "Failed to close");
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
|
||||
*f_in = from_child_pipe[0];
|
||||
*f_out = to_child_pipe[1];
|
||||
|
||||
return pid;
|
||||
}
|
||||
7
popt/.cvsignore
Normal file
7
popt/.cvsignore
Normal file
@@ -0,0 +1,7 @@
|
||||
ID
|
||||
Makefile
|
||||
config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
dummy
|
||||
46
popt/CHANGES
Normal file
46
popt/CHANGES
Normal file
@@ -0,0 +1,46 @@
|
||||
1.5 -> 1.6
|
||||
- add ability to perform callbacks for every, not just first, match.
|
||||
|
||||
1.3 -> 1.5
|
||||
- heavy dose of const's
|
||||
- poptParseArgvString() now NULL terminates the list
|
||||
|
||||
1.2.3 -> 1.3
|
||||
- added support for single -
|
||||
- misc bug fixes
|
||||
- portability improvements
|
||||
|
||||
1.2.2 -> 1.2.3
|
||||
- fixed memset() in help message generation (Dale Hawkins)
|
||||
- added extern "C" stuff to popt.h for C++ compilers (Dale Hawkins)
|
||||
- const'ified poptParseArgvString (Jeff Garzik)
|
||||
|
||||
1.2.1 -> 1.2.2
|
||||
- fixed bug in chaind alias happens which seems to have only
|
||||
affected --triggers in rpm
|
||||
- added POPT_ARG_VAL
|
||||
- popt.3 installed by default
|
||||
|
||||
1.2 -> 1.2.1
|
||||
- added POPT_ARG_INTL_DOMAIN (Elliot Lee)
|
||||
- updated Makefile's to be more GNUish (Elliot Lee)
|
||||
|
||||
1.1 -> 1.2
|
||||
- added popt.3 man page (Robert Lynch)
|
||||
- don't use mmap anymore (its lack of portability isn't worth the
|
||||
trouble)
|
||||
- added test script
|
||||
- added support for exec
|
||||
- removed support for *_POPT_ALIASES env variable -- it was a bad
|
||||
idea
|
||||
- reorganized into multiple source files
|
||||
- added automatic help generation, POPT_AUTOHELP
|
||||
- added table callbacks
|
||||
- added table inclusion
|
||||
- updated man page for new features
|
||||
- added test scripts
|
||||
|
||||
1.0 -> 1.1
|
||||
- moved to autoconf (Fred Fish)
|
||||
- added STRERROR replacement (Norbert Warmuth)
|
||||
- added const keywords (Bruce Perens)
|
||||
22
popt/COPYING
Normal file
22
popt/COPYING
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 1998 Red Hat Software
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of the X Consortium shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the X Consortium.
|
||||
18
popt/README
Normal file
18
popt/README
Normal file
@@ -0,0 +1,18 @@
|
||||
This is the popt command line option parsing library. While it is similiar
|
||||
to getopt(3), it contains a number of enhancements, including:
|
||||
|
||||
1) popt is fully reentrant
|
||||
2) popt can parse arbitrary argv[] style arrays while
|
||||
getopt(2) makes this quite difficult
|
||||
3) popt allows users to alias command line arguments
|
||||
4) popt provides convience functions for parsing strings
|
||||
into argv[] style arrays
|
||||
|
||||
popt is used by rpm, the Red Hat install program, and many other Red Hat
|
||||
utilities, all of which provide excellent examples of how to use popt.
|
||||
Complete documentation on popt is available in popt.ps (included in this
|
||||
tarball), which is excerpted with permission from the book "Linux
|
||||
Application Development" by Michael K. Johnson and Erik Troan (availble
|
||||
from Addison Wesley in May, 1998).
|
||||
|
||||
Comments on popt should be addressed to ewt@redhat.com.
|
||||
4
popt/README.rsync
Normal file
4
popt/README.rsync
Normal file
@@ -0,0 +1,4 @@
|
||||
This is a perfectly ordinary copy of libpopt. It is only used on platforms
|
||||
that do not have a sufficiently up-to-date copy of their own. If you build
|
||||
rsync on a platform which has popt, this directory should not be used. (You
|
||||
can control that using the --with-included-popt configure flag.)
|
||||
0
popt/dummy.in
Normal file
0
popt/dummy.in
Normal file
50
popt/findme.c
Normal file
50
popt/findme.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/** \ingroup popt
|
||||
* \file popt/findme.c
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 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) {
|
||||
char * path = getenv("PATH");
|
||||
char * pathbuf;
|
||||
char * start, * chptr;
|
||||
char * buf;
|
||||
|
||||
if (argv0 == NULL) return NULL; /* XXX can't happen */
|
||||
/* If there is a / in the argv[0], it has to be an absolute path */
|
||||
if (strchr(argv0, '/'))
|
||||
return xstrdup(argv0);
|
||||
|
||||
if (path == NULL) return NULL;
|
||||
|
||||
start = pathbuf = alloca(strlen(path) + 1);
|
||||
buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
|
||||
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);
|
||||
|
||||
if (!access(buf, X_OK))
|
||||
return buf;
|
||||
|
||||
if (chptr)
|
||||
start = chptr + 1;
|
||||
else
|
||||
start = NULL;
|
||||
} while (start && *start);
|
||||
/*@=branchstate@*/
|
||||
|
||||
free(buf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
20
popt/findme.h
Normal file
20
popt/findme.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/** \ingroup popt
|
||||
* \file popt/findme.h
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#ifndef H_FINDME
|
||||
#define H_FINDME
|
||||
|
||||
/**
|
||||
* Return absolute path to executable by searching PATH.
|
||||
* @param argv0 name of executable
|
||||
* @return (malloc'd) absolute path to executable (or NULL)
|
||||
*/
|
||||
/*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0)
|
||||
/*@*/;
|
||||
|
||||
#endif
|
||||
1209
popt/popt.c
Normal file
1209
popt/popt.c
Normal file
File diff suppressed because it is too large
Load Diff
446
popt/popt.h
Normal file
446
popt/popt.h
Normal file
@@ -0,0 +1,446 @@
|
||||
/** \file popt/popt.h
|
||||
* \ingroup popt
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#ifndef H_POPT
|
||||
#define H_POPT
|
||||
|
||||
#include <stdio.h> /* for FILE * */
|
||||
|
||||
#define POPT_OPTION_DEPTH 10
|
||||
|
||||
/** \ingroup popt
|
||||
* \name Arg type identifiers
|
||||
*/
|
||||
/*@{*/
|
||||
#define POPT_ARG_NONE 0 /*!< no arg */
|
||||
#define POPT_ARG_STRING 1 /*!< arg will be saved as string */
|
||||
#define POPT_ARG_INT 2 /*!< arg will be converted to int */
|
||||
#define POPT_ARG_LONG 3 /*!< arg will be converted to long */
|
||||
#define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */
|
||||
#define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be
|
||||
set first in table; arg points
|
||||
to callback, descrip points to
|
||||
callback data to pass */
|
||||
#define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain
|
||||
for this table and any
|
||||
included tables; arg points
|
||||
to the domain string */
|
||||
#define POPT_ARG_VAL 7 /*!< arg should take value val */
|
||||
#define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */
|
||||
#define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */
|
||||
|
||||
#define POPT_ARG_MASK 0x0000FFFF
|
||||
/*@}*/
|
||||
|
||||
/** \ingroup popt
|
||||
* \name Arg modifiers
|
||||
*/
|
||||
/*@{*/
|
||||
#define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */
|
||||
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */
|
||||
#define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */
|
||||
#define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */
|
||||
|
||||
#define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */
|
||||
#define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */
|
||||
#define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */
|
||||
#define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */
|
||||
#define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */
|
||||
#define POPT_ARGFLAG_NOT 0x01000000 /*!< arg will be negated */
|
||||
#define POPT_ARGFLAG_LOGICALOPS \
|
||||
(POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR)
|
||||
|
||||
#define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR)
|
||||
/*!< set arg bit(s) */
|
||||
#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND)
|
||||
/*!< clear arg bit(s) */
|
||||
|
||||
#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 /*!< show default value in --help */
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** \ingroup popt
|
||||
* \name Callback modifiers
|
||||
*/
|
||||
/*@{*/
|
||||
#define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */
|
||||
#define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */
|
||||
#define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line,
|
||||
not the subtable */
|
||||
#define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */
|
||||
#define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */
|
||||
/*@}*/
|
||||
|
||||
/** \ingroup popt
|
||||
* \name Error return values
|
||||
*/
|
||||
/*@{*/
|
||||
#define POPT_ERROR_NOARG -10 /*!< missing argument */
|
||||
#define POPT_ERROR_BADOPT -11 /*!< unknown option */
|
||||
#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
|
||||
#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
|
||||
#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */
|
||||
#define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */
|
||||
#define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */
|
||||
#define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */
|
||||
#define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */
|
||||
#define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */
|
||||
/*@}*/
|
||||
|
||||
/** \ingroup popt
|
||||
* \name poptBadOption() flags
|
||||
*/
|
||||
/*@{*/
|
||||
#define POPT_BADOPTION_NOALIAS (1 << 0) /*!< don't go into an alias */
|
||||
/*@}*/
|
||||
|
||||
/** \ingroup popt
|
||||
* \name poptGetContext() flags
|
||||
*/
|
||||
/*@{*/
|
||||
#define POPT_CONTEXT_NO_EXEC (1 << 0) /*!< ignore exec expansions */
|
||||
#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /*!< pay attention to argv[0] */
|
||||
#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /*!< options can't follow args */
|
||||
#define POPT_CONTEXT_ARG_OPTS (1 << 4) /*!< return args as options with value 0 */
|
||||
/*@}*/
|
||||
|
||||
/** \ingroup popt
|
||||
*/
|
||||
struct poptOption {
|
||||
/*@observer@*/ /*@null@*/ const char * longName; /*!< may be NULL */
|
||||
char shortName; /*!< may be '\0' */
|
||||
int 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 */
|
||||
};
|
||||
|
||||
/** \ingroup popt
|
||||
* A popt alias argument for poptAddAlias().
|
||||
*/
|
||||
struct poptAlias {
|
||||
/*@owned@*/ /*@null@*/ const char * longName; /*!< may be NULL */
|
||||
char shortName; /*!< may be '\0' */
|
||||
int argc;
|
||||
/*@owned@*/ const char ** argv; /*!< must be free()able */
|
||||
};
|
||||
|
||||
/** \ingroup popt
|
||||
* A popt alias or exec argument for poptAddItem().
|
||||
*/
|
||||
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. */
|
||||
} * poptItem;
|
||||
|
||||
/** \ingroup popt
|
||||
* \name Auto-generated help/usage
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* Empty table marker to enable displaying popt alias/exec options.
|
||||
*/
|
||||
/*@observer@*/ /*@checked@*/
|
||||
extern struct poptOption poptAliasOptions[];
|
||||
#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
|
||||
0, "Options implemented via popt alias/exec:", NULL },
|
||||
|
||||
/**
|
||||
* Auto help table options.
|
||||
*/
|
||||
/*@observer@*/ /*@checked@*/
|
||||
extern struct poptOption poptHelpOptions[];
|
||||
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
|
||||
0, "Help options:", NULL },
|
||||
|
||||
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
|
||||
/*@}*/
|
||||
|
||||
/** \ingroup popt
|
||||
*/
|
||||
typedef /*@abstract@*/ struct poptContext_s * poptContext;
|
||||
|
||||
/** \ingroup popt
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
/*@-typeuse@*/
|
||||
typedef struct poptOption * poptOption;
|
||||
/*@=typeuse@*/
|
||||
#endif
|
||||
|
||||
enum poptCallbackReason { POPT_CALLBACK_REASON_PRE,
|
||||
POPT_CALLBACK_REASON_POST,
|
||||
POPT_CALLBACK_REASON_OPTION };
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*@-type@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Table callback prototype.
|
||||
* @param con context
|
||||
* @param reason reason for callback
|
||||
* @param opt option that triggered callback
|
||||
* @param arg @todo Document.
|
||||
* @param data @todo Document.
|
||||
*/
|
||||
typedef void (*poptCallbackType) (poptContext con,
|
||||
enum poptCallbackReason reason,
|
||||
/*@null@*/ const struct poptOption * opt,
|
||||
/*@null@*/ const char * arg,
|
||||
/*@null@*/ const void * data)
|
||||
/*@*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Initialize popt context.
|
||||
* @param 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(
|
||||
/*@dependent@*/ /*@keep@*/ const char * name,
|
||||
int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
|
||||
/*@dependent@*/ /*@keep@*/ const struct poptOption * options,
|
||||
int flags)
|
||||
/*@*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Reinitialize popt context.
|
||||
* @param con context
|
||||
*/
|
||||
void poptResetContext(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return value of next option found.
|
||||
* @param con context
|
||||
* @return next option val, -1 on last item, POPT_ERROR_* on error
|
||||
*/
|
||||
int poptGetNextOpt(/*@null@*/poptContext con)
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies con, fileSystem @*/;
|
||||
|
||||
/*@-redecl@*/
|
||||
/** \ingroup popt
|
||||
* Return next option argument (if any).
|
||||
* @param con context
|
||||
* @return option argument, NULL if no more options are available
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return current option's argument.
|
||||
* @param con context
|
||||
* @return option argument, NULL if no more options are available
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Peek at current option's argument.
|
||||
* @param con context
|
||||
* @return option argument
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con)
|
||||
/*@*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return remaining arguments.
|
||||
* @param con context
|
||||
* @return argument array, terminated with NULL
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return the option which caused the most recent error.
|
||||
* @param con context
|
||||
* @return offending option
|
||||
*/
|
||||
/*@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)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Add arguments to context.
|
||||
* @param con context
|
||||
* @param argv argument array, NULL terminated
|
||||
* @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
|
||||
*/
|
||||
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Add alias to context.
|
||||
* @todo Pass alias by reference, not value.
|
||||
* @deprecated Use poptAddItem instead.
|
||||
* @param con context
|
||||
* @param alias alias to add
|
||||
* @param flags (unused)
|
||||
* @return 0 on success
|
||||
*/
|
||||
/*@unused@*/
|
||||
int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Add alias/exec item to context.
|
||||
* @param con context
|
||||
* @param item alias/exec item to add
|
||||
* @param flags 0 for alias, 1 for exec
|
||||
* @return 0 on success
|
||||
*/
|
||||
int poptAddItem(poptContext con, poptItem newItem, int flags)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Read configuration file.
|
||||
* @param con context
|
||||
* @param fn file name to read
|
||||
* @return 0 on success, POPT_ERROR_ERRNO on failure
|
||||
*/
|
||||
int poptReadConfigFile(poptContext con, const char * fn)
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies fileSystem,
|
||||
con->execs, con->numExecs @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Read default configuration from /etc/popt and $HOME/.popt.
|
||||
* @param con context
|
||||
* @param useEnv (unused)
|
||||
* @return 0 on success, POPT_ERROR_ERRNO on failure
|
||||
*/
|
||||
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies fileSystem,
|
||||
con->execs, con->numExecs @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Duplicate an argument array.
|
||||
* @note: The argument array is malloc'd as a single area, so only argv must
|
||||
* be free'd.
|
||||
*
|
||||
* @param argc no. of arguments
|
||||
* @param argv argument array
|
||||
* @retval argcPtr address of returned no. of arguments
|
||||
* @retval argvPtr address of returned argument array
|
||||
* @return 0 on success, POPT_ERROR_NOARG on failure
|
||||
*/
|
||||
int poptDupArgv(int argc, /*@null@*/ const char **argv,
|
||||
/*@null@*/ /*@out@*/ int * argcPtr,
|
||||
/*@null@*/ /*@out@*/ const char *** argvPtr)
|
||||
/*@modifies *argcPtr, *argvPtr @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Parse a string into an argument array.
|
||||
* The parse allows ', ", and \ quoting, but ' is treated the same as " and
|
||||
* both may include \ quotes.
|
||||
* @note: The argument array is malloc'd as a single area, so only argv must
|
||||
* be free'd.
|
||||
*
|
||||
* @param s string to parse
|
||||
* @retval argcPtr address of returned no. of arguments
|
||||
* @retval argvPtr address of returned argument array
|
||||
*/
|
||||
int poptParseArgvString(const unsigned char * s,
|
||||
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
|
||||
/*@modifies *argcPtr, *argvPtr @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Return formatted error string for popt failure.
|
||||
* @param error popt error
|
||||
* @return error string
|
||||
*/
|
||||
/*@-redecl@*/
|
||||
/*@observer@*/ const char * poptStrerror(const int error)
|
||||
/*@*/;
|
||||
/*@=redecl@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Limit search for executables.
|
||||
* @param con context
|
||||
* @param path single path to search for executables
|
||||
* @param allowAbsolute absolute paths only?
|
||||
*/
|
||||
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
|
||||
/*@modifies con @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Print detailed description of options.
|
||||
* @param con context
|
||||
* @param fp ouput file handle
|
||||
* @param flags (unused)
|
||||
*/
|
||||
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Print terse description of options.
|
||||
* @param con context
|
||||
* @param fp ouput file handle
|
||||
* @param flags (unused)
|
||||
*/
|
||||
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/;
|
||||
|
||||
/** \ingroup popt
|
||||
* Provide text to replace default "[OPTION...]" in help/usage output.
|
||||
* @param con context
|
||||
* @param text replacement text
|
||||
*/
|
||||
/*@-fcnuse@*/
|
||||
void poptSetOtherOptionHelp(poptContext con, const char * text)
|
||||
/*@modifies con @*/;
|
||||
/*@=fcnuse@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Return argv[0] from context.
|
||||
* @param con context
|
||||
* @return argv[0]
|
||||
*/
|
||||
/*@-redecl -fcnuse@*/
|
||||
/*@observer@*/ const char * poptGetInvocationName(poptContext con)
|
||||
/*@*/;
|
||||
/*@=redecl =fcnuse@*/
|
||||
|
||||
/** \ingroup popt
|
||||
* Shuffle argv pointers to remove stripped args, returns new argc.
|
||||
* @param con context
|
||||
* @param argc no. of args
|
||||
* @param argv arg vector
|
||||
* @return new argc
|
||||
*/
|
||||
/*@-fcnuse@*/
|
||||
int poptStrippedArgv(poptContext con, int argc, char ** argv)
|
||||
/*@modifies *argv @*/;
|
||||
/*@=fcnuse@*/
|
||||
|
||||
/*@=type@*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
184
popt/poptconfig.c
Normal file
184
popt/poptconfig.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/** \ingroup popt
|
||||
* \file popt/poptconfig.c
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 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"
|
||||
|
||||
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
|
||||
static void configLine(poptContext con, unsigned char * line)
|
||||
/*@modifies con @*/
|
||||
{
|
||||
/*@-type@*/
|
||||
int nameLength = strlen(con->appName);
|
||||
/*@=type@*/
|
||||
const char * entryType;
|
||||
const char * opt;
|
||||
poptItem item = (poptItem) alloca(sizeof(*item));
|
||||
int i, j;
|
||||
|
||||
memset(item, 0, sizeof(*item));
|
||||
|
||||
/*@-type@*/
|
||||
if (strncmp(line, con->appName, nameLength)) return;
|
||||
/*@=type@*/
|
||||
|
||||
line += nameLength;
|
||||
if (*line == '\0' || !isspace(*line)) return;
|
||||
|
||||
while (*line != '\0' && isspace(*line)) line++;
|
||||
entryType = line;
|
||||
while (*line == '\0' || !isspace(*line)) line++;
|
||||
*line++ = '\0';
|
||||
|
||||
while (*line != '\0' && isspace(*line)) line++;
|
||||
if (*line == '\0') return;
|
||||
opt = line;
|
||||
while (*line == '\0' || !isspace(*line)) line++;
|
||||
*line++ = '\0';
|
||||
|
||||
while (*line != '\0' && isspace(*line)) line++;
|
||||
if (*line == '\0') return;
|
||||
|
||||
/*@-temptrans@*/ /* FIX: line alias is saved */
|
||||
if (opt[0] == '-' && opt[1] == '-')
|
||||
item->option.longName = opt + 2;
|
||||
else if (opt[0] == '-' && opt[2] == '\0')
|
||||
item->option.shortName = opt[1];
|
||||
/*@=temptrans@*/
|
||||
|
||||
if (poptParseArgvString(line, &item->argc, &item->argv)) return;
|
||||
|
||||
/*@-modobserver@*/
|
||||
item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
|
||||
for (i = 0, j = 0; i < item->argc; i++, j++) {
|
||||
const char * f;
|
||||
if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
|
||||
f = item->argv[i] + sizeof("--POPTdesc=");
|
||||
if (f[0] == '$' && f[1] == '"') f++;
|
||||
item->option.descrip = f;
|
||||
item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
|
||||
j--;
|
||||
} else
|
||||
if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
|
||||
f = item->argv[i] + sizeof("--POPTargs=");
|
||||
if (f[0] == '$' && f[1] == '"') f++;
|
||||
item->option.argDescrip = f;
|
||||
item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
|
||||
item->option.argInfo |= POPT_ARG_STRING;
|
||||
j--;
|
||||
} else
|
||||
if (j != i)
|
||||
item->argv[j] = item->argv[i];
|
||||
}
|
||||
if (j != i) {
|
||||
item->argv[j] = NULL;
|
||||
item->argc = j;
|
||||
}
|
||||
/*@=modobserver@*/
|
||||
|
||||
/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
|
||||
if (!strcmp(entryType, "alias"))
|
||||
(void) poptAddItem(con, item, 0);
|
||||
else if (!strcmp(entryType, "exec"))
|
||||
(void) poptAddItem(con, item, 1);
|
||||
/*@=nullstate@*/
|
||||
}
|
||||
/*@=compmempass@*/
|
||||
|
||||
int poptReadConfigFile(poptContext con, const char * fn)
|
||||
{
|
||||
const unsigned char * file, * chptr, * end;
|
||||
unsigned char * buf;
|
||||
/*@dependent@*/ unsigned char * dst;
|
||||
int fd, rc;
|
||||
off_t fileLength;
|
||||
|
||||
fd = open(fn, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
|
||||
|
||||
fileLength = lseek(fd, 0, SEEK_END);
|
||||
if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
|
||||
rc = errno;
|
||||
(void) close(fd);
|
||||
/*@-mods@*/
|
||||
errno = rc;
|
||||
/*@=mods@*/
|
||||
return POPT_ERROR_ERRNO;
|
||||
}
|
||||
|
||||
file = alloca(fileLength + 1);
|
||||
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;
|
||||
|
||||
dst = buf = alloca(fileLength + 1);
|
||||
|
||||
chptr = file;
|
||||
end = (file + fileLength);
|
||||
/*@-infloops@*/ /* LCL: can't detect chptr++ */
|
||||
while (chptr < end) {
|
||||
switch (*chptr) {
|
||||
case '\n':
|
||||
*dst = '\0';
|
||||
dst = buf;
|
||||
while (*dst && isspace(*dst)) dst++;
|
||||
if (*dst && *dst != '#')
|
||||
configLine(con, dst);
|
||||
chptr++;
|
||||
/*@switchbreak@*/ break;
|
||||
case '\\':
|
||||
*dst++ = *chptr++;
|
||||
if (chptr < end) {
|
||||
if (*chptr == '\n')
|
||||
dst--, chptr++;
|
||||
/* \ at the end of a line does not insert a \n */
|
||||
else
|
||||
*dst++ = *chptr++;
|
||||
}
|
||||
/*@switchbreak@*/ break;
|
||||
default:
|
||||
*dst++ = *chptr++;
|
||||
/*@switchbreak@*/ break;
|
||||
}
|
||||
}
|
||||
/*@=infloops@*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
|
||||
{
|
||||
char * fn, * home;
|
||||
int rc;
|
||||
|
||||
/*@-type@*/
|
||||
if (!con->appName) return 0;
|
||||
/*@=type@*/
|
||||
|
||||
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");
|
||||
rc = poptReadConfigFile(con, fn);
|
||||
if (rc) return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
661
popt/popthelp.c
Normal file
661
popt/popthelp.c
Normal file
@@ -0,0 +1,661 @@
|
||||
/* -*- 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
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#include "system.h"
|
||||
#include "poptint.h"
|
||||
|
||||
/**
|
||||
* @param con context
|
||||
* @param key option(s)
|
||||
*/
|
||||
static void displayArgs(poptContext con,
|
||||
/*@unused@*/ UNUSED(enum poptCallbackReason foo),
|
||||
struct poptOption * key,
|
||||
/*@unused@*/ UNUSED(const char * arg), /*@unused@*/ UNUSED(void * data))
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies fileSystem@*/
|
||||
{
|
||||
if (key->shortName == '?')
|
||||
poptPrintHelp(con, stdout, 0);
|
||||
else
|
||||
poptPrintUsage(con, stdout, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef NOTYET
|
||||
/*@unchecked@*/
|
||||
static int show_option_defaults = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Empty table marker to enable displaying popt alias/exec options.
|
||||
*/
|
||||
/*@observer@*/ /*@unchecked@*/
|
||||
struct poptOption poptAliasOptions[] = {
|
||||
POPT_TABLEEND
|
||||
};
|
||||
|
||||
/**
|
||||
* Auto help table options.
|
||||
*/
|
||||
/*@-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 },
|
||||
#ifdef NOTYET
|
||||
{ "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0,
|
||||
N_("Display option defaults in message"), NULL },
|
||||
#endif
|
||||
POPT_TABLEEND
|
||||
} ;
|
||||
/*@=castfcnptr@*/
|
||||
|
||||
/**
|
||||
* @param table option(s)
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ static const char *
|
||||
getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
|
||||
/*@*/
|
||||
{
|
||||
const struct poptOption *opt;
|
||||
|
||||
if (table != NULL)
|
||||
for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
|
||||
if (opt->argInfo == POPT_ARG_INTL_DOMAIN)
|
||||
return opt->arg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
/*@observer@*/ /*@null@*/ static const char *
|
||||
getArgDescrip(const struct poptOption * opt,
|
||||
/*@-paramuse@*/ /* FIX: wazzup? */
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@=paramuse@*/
|
||||
/*@*/
|
||||
{
|
||||
if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
|
||||
|
||||
if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
|
||||
if (opt->argDescrip) return POPT_(opt->argDescrip);
|
||||
|
||||
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
|
||||
|
||||
switch (opt->argInfo & POPT_ARG_MASK) {
|
||||
case POPT_ARG_NONE: return POPT_("NONE");
|
||||
case POPT_ARG_VAL: return POPT_("VAL");
|
||||
case POPT_ARG_INT: return POPT_("INT");
|
||||
case POPT_ARG_LONG: return POPT_("LONG");
|
||||
case POPT_ARG_STRING: return POPT_("STRING");
|
||||
case POPT_ARG_FLOAT: return POPT_("FLOAT");
|
||||
case POPT_ARG_DOUBLE: return POPT_("DOUBLE");
|
||||
default: return POPT_("ARG");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static /*@only@*/ /*@null@*/ char *
|
||||
singleOptionDefaultValue(int lineLength,
|
||||
const struct poptOption * opt,
|
||||
/*@-paramuse@*/ /* FIX: i18n macros disable with lclint */
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@=paramuse@*/
|
||||
/*@*/
|
||||
{
|
||||
const char * defstr = D_(translation_domain, "default");
|
||||
char * le = malloc(4*lineLength + 1);
|
||||
char * l = le;
|
||||
|
||||
if (le == NULL) return NULL; /* XXX can't happen */
|
||||
*le = '\0';
|
||||
*le++ = '(';
|
||||
strcpy(le, defstr); le += strlen(le);
|
||||
*le++ = ':';
|
||||
*le++ = ' ';
|
||||
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);
|
||||
} break;
|
||||
case POPT_ARG_LONG:
|
||||
{ long aLong = *((long *)opt->arg);
|
||||
sprintf(le, "%ld", aLong);
|
||||
le += strlen(le);
|
||||
} break;
|
||||
case POPT_ARG_FLOAT:
|
||||
{ double aDouble = *((float *)opt->arg);
|
||||
sprintf(le, "%g", aDouble);
|
||||
le += strlen(le);
|
||||
} break;
|
||||
case POPT_ARG_DOUBLE:
|
||||
{ double aDouble = *((double *)opt->arg);
|
||||
sprintf(le, "%g", aDouble);
|
||||
le += strlen(le);
|
||||
} break;
|
||||
case POPT_ARG_STRING:
|
||||
{ const char * s = *(const char **)opt->arg;
|
||||
if (s == NULL) {
|
||||
strcpy(le, "null"); le += strlen(le);
|
||||
} else {
|
||||
size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
|
||||
*le++ = '"';
|
||||
strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);
|
||||
if (slen < strlen(s)) {
|
||||
strcpy(le, "..."); le += strlen(le);
|
||||
}
|
||||
*le++ = '"';
|
||||
}
|
||||
} break;
|
||||
case POPT_ARG_NONE:
|
||||
default:
|
||||
l = _free(l);
|
||||
return NULL;
|
||||
/*@notreached@*/ break;
|
||||
}
|
||||
*le++ = ')';
|
||||
*le = '\0';
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fp output file handle
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static void singleOptionHelp(FILE * fp, int maxLeftCol,
|
||||
const struct poptOption * opt,
|
||||
/*@null@*/ 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);
|
||||
const char * argDescrip = getArgDescrip(opt, translation_domain);
|
||||
int helpLength;
|
||||
unsigned char * defs = NULL;
|
||||
unsigned char * left;
|
||||
int nb = maxLeftCol + 1;
|
||||
|
||||
/* Make sure there's more than enough room in target buffer. */
|
||||
if (opt->longName) nb += strlen(opt->longName);
|
||||
if (argDescrip) nb += strlen(argDescrip);
|
||||
|
||||
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,
|
||||
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
|
||||
opt->longName);
|
||||
else if (opt->shortName != '\0')
|
||||
sprintf(left, "-%c", opt->shortName);
|
||||
else if (opt->longName)
|
||||
sprintf(left, "%s%s",
|
||||
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
|
||||
opt->longName);
|
||||
if (!*left) goto out;
|
||||
if (argDescrip) {
|
||||
char * le = left + strlen(left);
|
||||
|
||||
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
|
||||
*le++ = '[';
|
||||
|
||||
/* Choose type of output */
|
||||
/*@-branchstate@*/
|
||||
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(" "));
|
||||
if (t) {
|
||||
char * te = t;
|
||||
*te = '\0';
|
||||
if (help) {
|
||||
strcpy(te, help); te += strlen(te);
|
||||
}
|
||||
*te++ = ' ';
|
||||
strcpy(te, defs);
|
||||
defs = _free(defs);
|
||||
}
|
||||
defs = t;
|
||||
}
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
|
||||
if (opt->argDescrip == NULL) {
|
||||
switch (opt->argInfo & POPT_ARG_MASK) {
|
||||
case POPT_ARG_NONE:
|
||||
break;
|
||||
case POPT_ARG_VAL:
|
||||
{ long aLong = opt->val;
|
||||
int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
|
||||
int negate = (opt->argInfo & POPT_ARGFLAG_NOT);
|
||||
|
||||
/* Don't bother displaying typical values */
|
||||
if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
|
||||
break;
|
||||
*le++ = '[';
|
||||
switch (ops) {
|
||||
case POPT_ARGFLAG_OR:
|
||||
*le++ = '|';
|
||||
/*@innerbreak@*/ break;
|
||||
case POPT_ARGFLAG_AND:
|
||||
*le++ = '&';
|
||||
/*@innerbreak@*/ break;
|
||||
case POPT_ARGFLAG_XOR:
|
||||
*le++ = '^';
|
||||
/*@innerbreak@*/ break;
|
||||
default:
|
||||
/*@innerbreak@*/ break;
|
||||
}
|
||||
*le++ = '=';
|
||||
if (negate) *le++ = '~';
|
||||
/*@-formatconst@*/
|
||||
sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
|
||||
le += strlen(le);
|
||||
/*@=formatconst@*/
|
||||
*le++ = ']';
|
||||
} 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);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*le++ = '=';
|
||||
strcpy(le, argDescrip); le += strlen(le);
|
||||
}
|
||||
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
|
||||
*le++ = ']';
|
||||
*le = '\0';
|
||||
}
|
||||
|
||||
if (help)
|
||||
fprintf(fp," %-*s ", maxLeftCol, left);
|
||||
else {
|
||||
fprintf(fp," %s\n", left);
|
||||
goto out;
|
||||
}
|
||||
|
||||
left = _free(left);
|
||||
if (defs) {
|
||||
help = defs; defs = NULL;
|
||||
}
|
||||
|
||||
helpLength = strlen(help);
|
||||
while (helpLength > lineLength) {
|
||||
const unsigned char * ch;
|
||||
char format[10];
|
||||
|
||||
ch = help + lineLength - 1;
|
||||
while (ch > help && !isspace(*ch)) ch--;
|
||||
if (ch == help) break; /* give up */
|
||||
while (ch > (help + 1) && isspace(*ch)) ch--;
|
||||
ch++;
|
||||
|
||||
sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
|
||||
/*@-formatconst@*/
|
||||
fprintf(fp, format, help, " ");
|
||||
/*@=formatconst@*/
|
||||
help = ch;
|
||||
while (isspace(*help) && *help) help++;
|
||||
helpLength = strlen(help);
|
||||
}
|
||||
|
||||
if (helpLength) fprintf(fp, "%s\n", help);
|
||||
|
||||
out:
|
||||
/*@-dependenttrans@*/
|
||||
defs = _free(defs);
|
||||
/*@=dependenttrans@*/
|
||||
left = _free(left);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static int maxArgWidth(const struct poptOption * opt,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@*/
|
||||
{
|
||||
int max = 0;
|
||||
int len = 0;
|
||||
const char * s;
|
||||
|
||||
if (opt != NULL)
|
||||
while (opt->longName || opt->shortName || opt->arg) {
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
|
||||
if (opt->arg) /* XXX program error */
|
||||
len = maxArgWidth(opt->arg, translation_domain);
|
||||
if (len > max) max = len;
|
||||
} else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
|
||||
len = sizeof(" ")-1;
|
||||
if (opt->shortName != '\0') len += sizeof("-X")-1;
|
||||
if (opt->shortName != '\0' && opt->longName) len += sizeof(", ")-1;
|
||||
if (opt->longName) {
|
||||
len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH)
|
||||
? sizeof("-")-1 : sizeof("--")-1);
|
||||
len += strlen(opt->longName);
|
||||
}
|
||||
|
||||
s = getArgDescrip(opt, translation_domain);
|
||||
if (s)
|
||||
len += sizeof("=")-1 + strlen(s);
|
||||
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
|
||||
if (len > max) max = len;
|
||||
}
|
||||
|
||||
opt++;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display popt alias and exec help.
|
||||
* @param fp output file handle
|
||||
* @param items alias/exec array
|
||||
* @param nitems no. of alias/exec entries
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static void itemHelp(FILE * fp,
|
||||
/*@null@*/ poptItem items, int nitems, int left,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
poptItem item;
|
||||
int i;
|
||||
|
||||
if (items != NULL)
|
||||
for (i = 0, item = items; i < nitems; i++, item++) {
|
||||
const struct poptOption * opt;
|
||||
opt = &item->option;
|
||||
if ((opt->longName || opt->shortName) &&
|
||||
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
|
||||
singleOptionHelp(fp, left, opt, translation_domain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fp output file handle
|
||||
* @param table option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static void singleTableHelp(poptContext con, FILE * fp,
|
||||
/*@null@*/ const struct poptOption * table, int left,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
const struct poptOption * opt;
|
||||
const char *sub_transdom;
|
||||
|
||||
if (table == poptAliasOptions) {
|
||||
itemHelp(fp, con->aliases, con->numAliases, left, NULL);
|
||||
itemHelp(fp, con->execs, con->numExecs, left, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (table != NULL)
|
||||
for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
|
||||
if ((opt->longName || opt->shortName) &&
|
||||
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
|
||||
singleOptionHelp(fp, left, opt, translation_domain);
|
||||
}
|
||||
|
||||
if (table != NULL)
|
||||
for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
|
||||
if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE)
|
||||
continue;
|
||||
sub_transdom = getTableTranslationDomain(opt->arg);
|
||||
if (sub_transdom == NULL)
|
||||
sub_transdom = translation_domain;
|
||||
|
||||
if (opt->descrip)
|
||||
fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
|
||||
|
||||
singleTableHelp(con, fp, opt->arg, left, sub_transdom);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param con context
|
||||
* @param fp output file handle
|
||||
*/
|
||||
static int showHelpIntro(poptContext con, FILE * fp)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
int len = 6;
|
||||
const char * fn;
|
||||
|
||||
fprintf(fp, POPT_("Usage:"));
|
||||
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
|
||||
/*@-nullderef@*/ /* LCL: wazzup? */
|
||||
fn = con->optionStack->argv[0];
|
||||
/*@=nullderef@*/
|
||||
if (fn == NULL) return len;
|
||||
if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
|
||||
fprintf(fp, " %s", fn);
|
||||
len += strlen(fn) + 1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
|
||||
{
|
||||
int leftColWidth;
|
||||
|
||||
(void) showHelpIntro(con, fp);
|
||||
if (con->otherHelp)
|
||||
fprintf(fp, " %s\n", con->otherHelp);
|
||||
else
|
||||
fprintf(fp, " %s\n", POPT_("[OPTION...]"));
|
||||
|
||||
leftColWidth = maxArgWidth(con->options, NULL);
|
||||
singleTableHelp(con, fp, con->options, leftColWidth, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fp output file handle
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static int singleOptionUsage(FILE * fp, int cursor,
|
||||
const struct poptOption * opt,
|
||||
/*@null@*/ const char *translation_domain)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
int len = 3;
|
||||
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 */
|
||||
len++;
|
||||
shortStr[0] = opt->shortName;
|
||||
shortStr[1] = '\0';
|
||||
} else if (opt->longName) {
|
||||
len += 1 + strlen(opt->longName);
|
||||
item = opt->longName;
|
||||
}
|
||||
|
||||
if (len == 3) return cursor;
|
||||
|
||||
if (argDescrip)
|
||||
len += strlen(argDescrip) + 1;
|
||||
|
||||
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 : ""));
|
||||
|
||||
return cursor + len + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display popt alias and exec usage.
|
||||
* @param fp output file handle
|
||||
* @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)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
int i;
|
||||
|
||||
/*@-branchstate@*/ /* FIX: W2DO? */
|
||||
if (item != NULL)
|
||||
for (i = 0; i < nitems; i++, item++) {
|
||||
const struct poptOption * opt;
|
||||
opt = &item->option;
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
|
||||
translation_domain = (const char *)opt->arg;
|
||||
} else if ((opt->longName || opt->shortName) &&
|
||||
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
|
||||
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
|
||||
}
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fp output file handle
|
||||
* @param opt option(s)
|
||||
* @param translation_domain translation domain
|
||||
*/
|
||||
static int singleTableUsage(poptContext con, FILE * fp,
|
||||
int cursor, const struct poptOption * opt,
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *fp, fileSystem @*/
|
||||
{
|
||||
/*@-branchstate@*/ /* FIX: W2DO? */
|
||||
if (opt != NULL)
|
||||
for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
|
||||
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 */
|
||||
cursor = singleTableUsage(con, fp, cursor, opt->arg,
|
||||
translation_domain);
|
||||
} else if ((opt->longName || opt->shortName) &&
|
||||
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
|
||||
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
|
||||
}
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return concatenated short options for display.
|
||||
* @param opt option(s)
|
||||
* @param fp output file handle
|
||||
* @retval str concatenation of short options
|
||||
* @return length of display string
|
||||
*/
|
||||
static int showShortOptions(const struct poptOption * opt, FILE * fp,
|
||||
/*@null@*/ char * str)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies *str, *fp, fileSystem @*/
|
||||
{
|
||||
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@*/
|
||||
|
||||
if (opt != NULL)
|
||||
for (; (opt->longName || opt->shortName || opt->arg); opt++) {
|
||||
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
|
||||
str[strlen(str)] = 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);
|
||||
}
|
||||
|
||||
if (s != str || *s != '\0')
|
||||
return 0;
|
||||
|
||||
fprintf(fp, " [-%s]", s);
|
||||
return strlen(s) + 4;
|
||||
}
|
||||
|
||||
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
|
||||
{
|
||||
int cursor;
|
||||
|
||||
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);
|
||||
|
||||
if (con->otherHelp) {
|
||||
cursor += strlen(con->otherHelp) + 1;
|
||||
if (cursor > 79) fprintf(fp, "\n ");
|
||||
fprintf(fp, " %s", con->otherHelp);
|
||||
}
|
||||
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
void poptSetOtherOptionHelp(poptContext con, const char * text)
|
||||
{
|
||||
con->otherHelp = _free(con->otherHelp);
|
||||
con->otherHelp = xstrdup(text);
|
||||
}
|
||||
/*@=type@*/
|
||||
96
popt/poptint.h
Normal file
96
popt/poptint.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/** \ingroup popt
|
||||
* \file popt/poptint.h
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
|
||||
file accompanying popt source distributions, available from
|
||||
ftp://ftp.rpm.org/pub/rpm/dist. */
|
||||
|
||||
#ifndef H_POPTINT
|
||||
#define H_POPTINT
|
||||
|
||||
/**
|
||||
* Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
|
||||
* @param p memory to free
|
||||
* @retval NULL always
|
||||
*/
|
||||
/*@unused@*/ static inline /*@null@*/ void *
|
||||
_free(/*@only@*/ /*@null@*/ const void * p)
|
||||
/*@modifies p @*/
|
||||
{
|
||||
if (p != NULL) free((void *)p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Bit mask macros. */
|
||||
typedef unsigned int __pbm_bits;
|
||||
#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))
|
||||
typedef struct {
|
||||
__pbm_bits bits[1];
|
||||
} pbm_set;
|
||||
#define __PBM_BITS(set) ((set)->bits)
|
||||
|
||||
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
|
||||
#define PBM_FREE(s) _free(s);
|
||||
#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d))
|
||||
#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d))
|
||||
#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
|
||||
|
||||
struct optionStackEntry {
|
||||
int argc;
|
||||
/*@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;
|
||||
int stuffed;
|
||||
};
|
||||
|
||||
struct poptContext_s {
|
||||
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
|
||||
/*@dependent@*/ struct optionStackEntry * os;
|
||||
/*@owned@*/ /*@null@*/ const char ** leftovers;
|
||||
int numLeftovers;
|
||||
int nextLeftover;
|
||||
/*@keep@*/ const struct poptOption * options;
|
||||
int restLeftover;
|
||||
/*@only@*/ /*@null@*/ const char * appName;
|
||||
/*@only@*/ /*@null@*/ poptItem aliases;
|
||||
int numAliases;
|
||||
int flags;
|
||||
/*@owned@*/ /*@null@*/ poptItem execs;
|
||||
int numExecs;
|
||||
/*@only@*/ /*@null@*/ const char ** finalArgv;
|
||||
int finalArgvCount;
|
||||
int finalArgvAlloced;
|
||||
/*@dependent@*/ /*@null@*/ poptItem doExec;
|
||||
/*@only@*/ const char * execPath;
|
||||
int execAbsolute;
|
||||
/*@only@*/ const char * otherHelp;
|
||||
/*@null@*/ pbm_set * arg_strip;
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
#include <libintl.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
|
||||
#define _(foo) gettext(foo)
|
||||
#else
|
||||
#define _(foo) foo
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_DGETTEXT) && !defined(__LCLINT__)
|
||||
#define D_(dom, str) dgettext(dom, str)
|
||||
#define POPT_(foo) D_("popt", foo)
|
||||
#else
|
||||
#define D_(dom, str) str
|
||||
#define POPT_(foo) foo
|
||||
#endif
|
||||
|
||||
#define N_(foo) foo
|
||||
|
||||
#endif
|
||||
118
popt/poptparse.c
Normal file
118
popt/poptparse.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/** \ingroup popt
|
||||
* \file popt/poptparse.c
|
||||
*/
|
||||
|
||||
/* (C) 1998-2000 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_ARGV_ARRAY_GROW_DELTA 5
|
||||
|
||||
int poptDupArgv(int argc, const char **argv,
|
||||
int * argcPtr, const char *** argvPtr)
|
||||
{
|
||||
size_t nb = (argc + 1) * sizeof(*argv);
|
||||
const char ** argv2;
|
||||
char * dst;
|
||||
int i;
|
||||
|
||||
if (argc <= 0 || argv == NULL) /* XXX can't happen */
|
||||
return POPT_ERROR_NOARG;
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (argv[i] == NULL)
|
||||
return POPT_ERROR_NOARG;
|
||||
nb += strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
dst = malloc(nb);
|
||||
if (dst == NULL) /* XXX can't happen */
|
||||
return POPT_ERROR_MALLOC;
|
||||
argv2 = (void *) dst;
|
||||
dst += (argc + 1) * sizeof(*argv);
|
||||
|
||||
/*@-branchstate@*/
|
||||
for (i = 0; i < argc; i++) {
|
||||
argv2[i] = dst;
|
||||
dst += strlen(strcpy(dst, argv[i])) + 1;
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
argv2[argc] = NULL;
|
||||
|
||||
if (argvPtr) {
|
||||
*argvPtr = argv2;
|
||||
} else {
|
||||
free(argv2);
|
||||
argv2 = NULL;
|
||||
}
|
||||
if (argcPtr)
|
||||
*argcPtr = argc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** argvPtr)
|
||||
{
|
||||
const unsigned char * src;
|
||||
unsigned char quote = '\0';
|
||||
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
|
||||
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
|
||||
int argc = 0;
|
||||
int buflen = strlen(s) + 1;
|
||||
char * buf = memset(alloca(buflen), 0, buflen);
|
||||
int rc = POPT_ERROR_MALLOC;
|
||||
|
||||
if (argv == NULL) return rc;
|
||||
argv[argc] = buf;
|
||||
|
||||
for (src = s; *src != '\0'; src++) {
|
||||
if (quote == *src) {
|
||||
quote = '\0';
|
||||
} else if (quote != '\0') {
|
||||
if (*src == '\\') {
|
||||
src++;
|
||||
if (!*src) {
|
||||
rc = POPT_ERROR_BADQUOTE;
|
||||
goto exit;
|
||||
}
|
||||
if (*src != quote) *buf++ = '\\';
|
||||
}
|
||||
*buf++ = *src;
|
||||
} else if (isspace(*src)) {
|
||||
if (*argv[argc] != '\0') {
|
||||
buf++, argc++;
|
||||
if (argc == argvAlloced) {
|
||||
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
|
||||
argv = realloc(argv, sizeof(*argv) * argvAlloced);
|
||||
if (argv == NULL) goto exit;
|
||||
}
|
||||
argv[argc] = buf;
|
||||
}
|
||||
} else switch (*src) {
|
||||
case '"':
|
||||
case '\'':
|
||||
quote = *src;
|
||||
/*@switchbreak@*/ break;
|
||||
case '\\':
|
||||
src++;
|
||||
if (!*src) {
|
||||
rc = POPT_ERROR_BADQUOTE;
|
||||
goto exit;
|
||||
}
|
||||
/*@fallthrough@*/
|
||||
default:
|
||||
*buf++ = *src;
|
||||
/*@switchbreak@*/ break;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(argv[argc])) {
|
||||
argc++, buf++;
|
||||
}
|
||||
|
||||
rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
|
||||
|
||||
exit:
|
||||
if (argv) free(argv);
|
||||
return rc;
|
||||
}
|
||||
82
popt/system.h
Normal file
82
popt/system.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if HAVE_MCHECK_H
|
||||
#include <mcheck.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 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> */
|
||||
#define __attribute__(x)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __NeXT
|
||||
/* access macros are not declared in non posix mode in unistd.h -
|
||||
don't try to use posix on NeXTstep 3.3 ! */
|
||||
#include <libc.h>
|
||||
#endif
|
||||
|
||||
#if defined(__LCLINT__)
|
||||
/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */
|
||||
/*@only@*/ void * alloca (size_t __size)
|
||||
/*@ensures MaxSet(result) == (__size - 1) @*/
|
||||
/*@*/;
|
||||
/*@=declundef =incondefs =redecl@*/
|
||||
#endif
|
||||
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
#ifndef __GNUC__
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# if HAVE_ALLOCA
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
# endif
|
||||
# else
|
||||
# ifdef alloca
|
||||
# undef alloca
|
||||
# endif
|
||||
# define alloca(sz) malloc(sz) /* Kludge this for now */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(__GNUC__) && defined(__STRICT_ANSI__)
|
||||
#define alloca __builtin_alloca
|
||||
#endif
|
||||
|
||||
/*@-redecl -redef@*/
|
||||
/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str)
|
||||
/*@*/;
|
||||
/*@=redecl =redef@*/
|
||||
|
||||
#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)))
|
||||
#else
|
||||
#define xstrdup(_str) strdup(_str)
|
||||
#endif /* HAVE_MCHECK_H && defined(__GNUC__) */
|
||||
|
||||
#define UNUSED(x) x __attribute__((__unused__))
|
||||
|
||||
#include "popt.h"
|
||||
13
prepare-source
Executable file
13
prepare-source
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
# Use autoconf, autoheader, yodl, etc. to ready the generated files
|
||||
# in the release. This is typically used after applying a diff from
|
||||
# "patches" directory in CVS.
|
||||
#
|
||||
# NOTE: if you use a diff from the "patches" directory in a release
|
||||
# tar, this is not needed (but doesn't hurt anything).
|
||||
dir=`dirname $0`
|
||||
if test x"$dir" = x -o x"$dir" = x.; then
|
||||
make -f prepare-source.mak
|
||||
else
|
||||
make -C "$dir" -f prepare-source.mak
|
||||
fi
|
||||
23
prepare-source.mak
Normal file
23
prepare-source.mak
Normal file
@@ -0,0 +1,23 @@
|
||||
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
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.yo
|
||||
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
|
||||
175
progress.c
Normal file
175
progress.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/* -*- 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>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern struct stats stats;
|
||||
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;
|
||||
};
|
||||
|
||||
static struct progress_history ph_start;
|
||||
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
|
||||
static int newest_hpos, oldest_hpos;
|
||||
|
||||
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
|
||||
{
|
||||
return (t2->tv_sec - t1->tv_sec) * 1000L
|
||||
+ (t2->tv_usec - t1->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ofs Current position in file
|
||||
* @param size Total size of file
|
||||
* @param is_last True if this is the last time progress will be
|
||||
* printed for this file, so we should output a newline. (Not
|
||||
* necessarily the same as all bytes being received.)
|
||||
**/
|
||||
static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
|
||||
int is_last)
|
||||
{
|
||||
char eol[256];
|
||||
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. */
|
||||
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. */
|
||||
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;
|
||||
}
|
||||
|
||||
if (rate > 1024*1024) {
|
||||
rate /= 1024.0 * 1024.0;
|
||||
units = "GB/s";
|
||||
} else if (rate > 1024) {
|
||||
rate /= 1024.0;
|
||||
units = "MB/s";
|
||||
} else {
|
||||
units = "kB/s";
|
||||
}
|
||||
|
||||
remain_s = (int) remain % 60;
|
||||
remain_m = (int) (remain / 60.0) % 60;
|
||||
remain_h = (int) (remain / 3600.0);
|
||||
|
||||
if (is_last) {
|
||||
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
|
||||
stats.num_transferred_files,
|
||||
stats.num_files - stats.current_file_index - 1,
|
||||
stats.num_files);
|
||||
} else
|
||||
strcpy(eol, "\r");
|
||||
rprintf(FINFO, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
|
||||
human_num(ofs), pct, rate, units,
|
||||
remain_h, remain_m, remain_s, eol);
|
||||
}
|
||||
|
||||
void end_progress(OFF_T size)
|
||||
{
|
||||
if (!am_server) {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
rprint_progress(size, size, &now, True);
|
||||
}
|
||||
memset(&ph_start, 0, sizeof ph_start);
|
||||
}
|
||||
|
||||
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) {
|
||||
int i;
|
||||
|
||||
/* Try to guess the real starting time when the sender started
|
||||
* to send us data by using the time we last received some data
|
||||
* in the last file (if it was recent enough). */
|
||||
if (msdiff(&ph_list[newest_hpos].time, &now) <= 1500) {
|
||||
ph_start.time = ph_list[newest_hpos].time;
|
||||
ph_start.ofs = 0;
|
||||
} else {
|
||||
ph_start.time.tv_sec = now.tv_sec;
|
||||
ph_start.time.tv_usec = now.tv_usec;
|
||||
ph_start.ofs = ofs;
|
||||
}
|
||||
|
||||
for (i = 0; i < PROGRESS_HISTORY_SECS; i++)
|
||||
ph_list[i] = ph_start;
|
||||
}
|
||||
else {
|
||||
if (msdiff(&ph_list[newest_hpos].time, &now) < 1000)
|
||||
return;
|
||||
|
||||
newest_hpos = oldest_hpos;
|
||||
oldest_hpos = (oldest_hpos + 1) % PROGRESS_HISTORY_SECS;
|
||||
ph_list[newest_hpos].time.tv_sec = now.tv_sec;
|
||||
ph_list[newest_hpos].time.tv_usec = now.tv_usec;
|
||||
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);
|
||||
}
|
||||
908
receiver.c
908
receiver.c
File diff suppressed because it is too large
Load Diff
427
rsync.c
427
rsync.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
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.
|
||||
@@ -21,17 +21,74 @@
|
||||
process */
|
||||
|
||||
#include "rsync.h"
|
||||
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#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 daemon_log_format_has_i;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_executability;
|
||||
extern int preserve_times;
|
||||
extern int omit_dir_times;
|
||||
extern int am_root;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int am_starting_up;
|
||||
extern int allow_8bit_chars;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_perms;
|
||||
extern int inplace;
|
||||
extern int keep_dirlinks;
|
||||
extern int make_backups;
|
||||
extern char *backup_suffix;
|
||||
extern mode_t orig_umask;
|
||||
extern struct stats stats;
|
||||
extern struct chmod_mode_struct *daemon_chmod_modes;
|
||||
|
||||
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
|
||||
iconv_t ic_chck = (iconv_t)-1;
|
||||
|
||||
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()
|
||||
{
|
||||
if (!am_server && !allow_8bit_chars) {
|
||||
const char *defset = default_charset();
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
free a sums struct
|
||||
@@ -42,245 +99,209 @@ void free_sums(struct sum_struct *s)
|
||||
free(s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* delete a file or directory. If force_delet 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 cur_mode, int exists)
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *di;
|
||||
char buf[MAXPATHLEN];
|
||||
extern int force_delete;
|
||||
STRUCT_STAT st;
|
||||
int ret;
|
||||
extern int recurse;
|
||||
|
||||
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
ret = do_lstat(fname, &st);
|
||||
#else
|
||||
ret = do_stat(fname, &st);
|
||||
#endif
|
||||
if (ret) {
|
||||
rprintf(FERROR,"stat(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
rprintf(FERROR,"unlink(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
|
||||
if (!force_delete || !recurse ||
|
||||
(errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
rprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now we do a recsursive delete on the directory ... */
|
||||
d = opendir(fname);
|
||||
if (!d) {
|
||||
rprintf(FERROR,"opendir(%s): %s\n",
|
||||
fname,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (di=readdir(d); di; di=readdir(d)) {
|
||||
char *dname = d_name(di);
|
||||
if (strcmp(dname,".")==0 ||
|
||||
strcmp(dname,"..")==0)
|
||||
continue;
|
||||
slprintf(buf, sizeof(buf), "%s/%s", fname, dname);
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"deleting %s\n", buf);
|
||||
if (delete_file(buf) != 0) {
|
||||
closedir(d);
|
||||
return -1;
|
||||
/* If the file already exists, we'll return the local permissions,
|
||||
* possibly tweaked by the --executability option. */
|
||||
if (exists) {
|
||||
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))
|
||||
cur_mode &= ~0111;
|
||||
else if (!(cur_mode & 0111))
|
||||
cur_mode |= (cur_mode & 0444) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (do_rmdir(fname) != 0) {
|
||||
rprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else
|
||||
cur_mode = flist_mode & ACCESSPERMS & ~orig_umask;
|
||||
if (daemon_chmod_modes && !S_ISLNK(flist_mode))
|
||||
cur_mode = tweak_mode(cur_mode, daemon_chmod_modes);
|
||||
return (flist_mode & ~CHMOD_BITS) | (cur_mode & CHMOD_BITS);
|
||||
}
|
||||
|
||||
static int is_in_group(gid_t gid)
|
||||
{
|
||||
#ifdef GETGROUPS_T
|
||||
static gid_t last_in = (gid_t) -2, last_out;
|
||||
static int ngroups = -2;
|
||||
static GETGROUPS_T *gidset;
|
||||
int n;
|
||||
|
||||
if (gid == last_in)
|
||||
return last_out;
|
||||
if (ngroups < -1) {
|
||||
/* treat failure (-1) as if not member of any group */
|
||||
ngroups = getgroups(0, 0);
|
||||
if (ngroups > 0) {
|
||||
gidset = (GETGROUPS_T *) malloc(ngroups * sizeof(GETGROUPS_T));
|
||||
ngroups = getgroups(ngroups, gidset);
|
||||
}
|
||||
}
|
||||
|
||||
last_in = gid;
|
||||
last_out = 0;
|
||||
for (n = 0; n < ngroups; n++) {
|
||||
if (gidset[n] == gid) {
|
||||
last_out = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return last_out;
|
||||
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
int report)
|
||||
int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
|
||||
int flags)
|
||||
{
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
int change_uid, change_gid;
|
||||
extern int am_daemon;
|
||||
|
||||
if (dry_run) return 0;
|
||||
|
||||
if (!st) {
|
||||
if (link_stat(fname,&st2) != 0) {
|
||||
rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
|
||||
if (dry_run)
|
||||
return 1;
|
||||
if (link_stat(fname, &st2, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
full_fname(fname));
|
||||
return 0;
|
||||
}
|
||||
st = &st2;
|
||||
}
|
||||
|
||||
if (preserve_times && !S_ISLNK(st->st_mode) &&
|
||||
st->st_mtime != file->modtime) {
|
||||
/* 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",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
} else {
|
||||
updated = 1;
|
||||
if (!preserve_perms && S_ISDIR(file->mode)
|
||||
&& st->st_mode & S_ISGID) {
|
||||
/* We just created this directory and its setgid
|
||||
* bit is on, so make sure it stays on. */
|
||||
file->mode |= S_ISGID;
|
||||
}
|
||||
}
|
||||
|
||||
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
|
||||
change_gid = !am_daemon && preserve_gid && file->gid != (gid_t) -1 && \
|
||||
st->st_gid != file->gid;
|
||||
if (change_gid && !am_root) {
|
||||
/* enforce bsd-style group semantics: non-root can only
|
||||
change to groups that the user is a member of */
|
||||
change_gid = is_in_group(file->gid);
|
||||
}
|
||||
if (change_uid || change_gid) {
|
||||
if (do_lchown(fname,
|
||||
change_uid?file->uid:st->st_uid,
|
||||
change_gid?file->gid:st->st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
unless have the privilege */
|
||||
rprintf(FERROR,"chown %s : %s\n", fname,strerror(errno));
|
||||
if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
|
||||
flags |= ATTRS_SKIP_MTIME;
|
||||
if (!(flags & ATTRS_SKIP_MTIME)
|
||||
&& cmp_time(st->st_mtime, file->modtime) != 0) {
|
||||
int ret = set_modtime(fname, file->modtime, st->st_mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno, "failed to set times on %s",
|
||||
full_fname(fname));
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
|
||||
if (S_ISLNK(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);
|
||||
}
|
||||
if (change_gid) {
|
||||
rprintf(FINFO,
|
||||
"set gid of %s from %ld to %ld\n",
|
||||
fname,
|
||||
(long)st->st_gid, (long)file->gid);
|
||||
}
|
||||
}
|
||||
if (do_lchown(fname,
|
||||
change_uid ? file->uid : st->st_uid,
|
||||
change_gid ? file->gid : st->st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
* unless have the privilege */
|
||||
rsyserr(FERROR, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname));
|
||||
return 0;
|
||||
}
|
||||
/* 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,
|
||||
keep_dirlinks && S_ISDIR(st->st_mode));
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHMOD
|
||||
if (!S_ISLNK(st->st_mode)) {
|
||||
int file_mode;
|
||||
if (preserve_perms)
|
||||
file_mode = file->mode;
|
||||
else
|
||||
file_mode = file->mode & ACCESSPERMS;
|
||||
if (st->st_mode != file->mode) {
|
||||
updated = 1;
|
||||
if (do_chmod(fname,file_mode) != 0) {
|
||||
rprintf(FERROR,"failed to set permissions on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
|
||||
int ret = do_chmod(fname, file->mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to set permissions on %s",
|
||||
full_fname(fname));
|
||||
return 0;
|
||||
}
|
||||
if (ret == 0) /* ret == 1 if symlink could not be set */
|
||||
updated = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (verbose > 1 && report) {
|
||||
|
||||
if (verbose > 1 && flags & ATTRS_REPORT) {
|
||||
enum logcode code = daemon_log_format_has_i || dry_run
|
||||
? FCLIENT : FINFO;
|
||||
if (updated)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
rprintf(code, "%s\n", fname);
|
||||
else
|
||||
rprintf(FINFO,"%s is uptodate\n",fname);
|
||||
rprintf(code, "%s is uptodate\n", fname);
|
||||
}
|
||||
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
|
||||
* signal to all our children may kill ssh before it has a
|
||||
* chance to restore the tty settings (i.e. turn echo back
|
||||
* on). By sleeping for a short time, ssh gets a bigger
|
||||
* chance to do the right thing. If child processes are
|
||||
* not ssh waiting for a password, then this tiny delay
|
||||
* shouldn't hurt anything. */
|
||||
msleep(400);
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
int make_backup(char *fname)
|
||||
/* 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(char *fname, char *fnametmp, char *partialptr,
|
||||
struct file_struct *file, int ok_to_set_time,
|
||||
int overwriting_basis)
|
||||
{
|
||||
char fnamebak[MAXPATHLEN];
|
||||
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
|
||||
rprintf(FERROR,"backup filename too long\n");
|
||||
return 0;
|
||||
int ret;
|
||||
|
||||
if (inplace) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "finishing %s\n", fname);
|
||||
fnametmp = fname;
|
||||
goto do_set_file_attrs;
|
||||
}
|
||||
|
||||
slprintf(fnamebak,sizeof(fnamebak),"%s%s",fname,backup_suffix);
|
||||
if (do_rename(fname,fnamebak) != 0) {
|
||||
/* cygwin (at least version b19) reports EINVAL */
|
||||
if (errno != ENOENT && errno != EINVAL) {
|
||||
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
} else if (verbose > 1) {
|
||||
rprintf(FINFO,"backed up %s to %s\n",fname,fnamebak);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
if (make_backups && !make_backup(fname))
|
||||
if (make_backups && overwriting_basis && !make_backup(fname))
|
||||
return;
|
||||
|
||||
/* Change permissions before putting the file into place. */
|
||||
set_file_attrs(fnametmp, file, NULL,
|
||||
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
|
||||
|
||||
/* move tmp file over real file */
|
||||
if (robust_rename(fnametmp,fname) != 0) {
|
||||
if (errno == EXDEV) {
|
||||
/* rename failed on cross-filesystem link.
|
||||
Copy the file instead. */
|
||||
if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
|
||||
rprintf(FERROR,"copy %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
} else {
|
||||
rprintf(FERROR,"rename %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
}
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
|
||||
ret = robust_rename(fnametmp, fname, partialptr,
|
||||
file->mode & INITACCESSPERMS);
|
||||
if (ret < 0) {
|
||||
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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *who_am_i(void)
|
||||
{
|
||||
if (am_starting_up)
|
||||
return am_server ? "server" : "client";
|
||||
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
|
||||
}
|
||||
|
||||
682
rsync.h
682
rsync.h
@@ -1,30 +1,34 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
/*
|
||||
Copyright (C) by Andrew Tridgell 1996, 2000
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#define False 0
|
||||
#define True 1
|
||||
|
||||
#define BLOCK_SIZE 700
|
||||
#define RSYNC_RSH_ENV "RSYNC_RSH"
|
||||
#define RSYNC_RSH_IO_ENV "RSYNC_RSH_IO"
|
||||
|
||||
#define RSYNC_NAME "rsync"
|
||||
#define RSYNCD_CONF "/etc/rsyncd.conf"
|
||||
/* RSYNCD_SYSCONF is now set in config.h */
|
||||
#define RSYNCD_USERCONF "rsyncd.conf"
|
||||
|
||||
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
|
||||
#define URL_PREFIX "rsync://"
|
||||
@@ -35,21 +39,55 @@
|
||||
incompatible with older versions :-( */
|
||||
#define CHAR_OFFSET 0
|
||||
|
||||
/* These flags are only used during the flist transfer. */
|
||||
|
||||
#define FLAG_DELETE (1<<0)
|
||||
#define SAME_MODE (1<<1)
|
||||
#define SAME_RDEV (1<<2)
|
||||
#define SAME_UID (1<<3)
|
||||
#define SAME_GID (1<<4)
|
||||
#define SAME_DIR (1<<5)
|
||||
#define SAME_NAME SAME_DIR
|
||||
#define LONG_NAME (1<<6)
|
||||
#define SAME_TIME (1<<7)
|
||||
#define XMIT_TOP_DIR (1<<0)
|
||||
#define XMIT_SAME_MODE (1<<1)
|
||||
#define XMIT_EXTENDED_FLAGS (1<<2)
|
||||
#define XMIT_SAME_RDEV_pre28 XMIT_EXTENDED_FLAGS /* Only in protocols < 28 */
|
||||
#define XMIT_SAME_UID (1<<3)
|
||||
#define XMIT_SAME_GID (1<<4)
|
||||
#define XMIT_SAME_NAME (1<<5)
|
||||
#define XMIT_LONG_NAME (1<<6)
|
||||
#define XMIT_SAME_TIME (1<<7)
|
||||
#define XMIT_SAME_RDEV_MAJOR (1<<8)
|
||||
#define XMIT_HAS_IDEV_DATA (1<<9)
|
||||
#define XMIT_SAME_DEV (1<<10)
|
||||
#define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
|
||||
|
||||
/* These flags are used in the live flist data. */
|
||||
|
||||
#define FLAG_TOP_DIR (1<<0)
|
||||
#define FLAG_SENT (1<<1) /* sender */
|
||||
#define FLAG_HLINK_EOL (1<<1) /* receiver/generator */
|
||||
#define FLAG_MOUNT_POINT (1<<2) /* sender/generator */
|
||||
#define FLAG_DEL_HERE (1<<3) /* receiver/generator */
|
||||
#define FLAG_HLINK_TOL (1<<4) /* receiver/generator */
|
||||
#define FLAG_NO_FUZZY (1<<5) /* generator */
|
||||
|
||||
/* update this if you make incompatible changes */
|
||||
#define PROTOCOL_VERSION 20
|
||||
#define MIN_PROTOCOL_VERSION 11
|
||||
#define MAX_PROTOCOL_VERSION 30
|
||||
#define PROTOCOL_VERSION 29
|
||||
|
||||
/* We refuse to interoperate with versions that are not in this range.
|
||||
* Note that we assume we'll work with later versions: the onus is on
|
||||
* people writing them to make sure that they don't send us anything
|
||||
* we won't understand.
|
||||
*
|
||||
* Interoperation with old but supported protocol versions
|
||||
* should cause a warning to be printed. At a future date
|
||||
* the old protocol will become the minimum and
|
||||
* compatibility code removed.
|
||||
*
|
||||
* There are two possible explanations for the limit at
|
||||
* MAX_PROTOCOL_VERSION: either to allow new major-rev versions that
|
||||
* do not interoperate with us, and (more likely) so that we can
|
||||
* detect an attempt to connect rsync to a non-rsync server, which is
|
||||
* unlikely to begin by sending a byte between MIN_PROTOCL_VERSION and
|
||||
* MAX_PROTOCOL_VERSION. */
|
||||
|
||||
#define MIN_PROTOCOL_VERSION 20
|
||||
#define OLD_PROTOCOL_VERSION 25
|
||||
#define MAX_PROTOCOL_VERSION 40
|
||||
|
||||
#define RSYNC_PORT 873
|
||||
|
||||
@@ -58,59 +96,128 @@
|
||||
#define CHUNK_SIZE (32*1024)
|
||||
#define MAX_MAP_SIZE (256*1024)
|
||||
#define IO_BUFFER_SIZE (4092)
|
||||
#define MAX_READ_BUFFER (1024*1024)
|
||||
#define MAX_BLOCK_SIZE ((int32)1 << 29)
|
||||
|
||||
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
|
||||
#define IOERR_VANISHED (1<<1)
|
||||
#define IOERR_DEL_LIMIT (1<<2)
|
||||
|
||||
#define MAX_ARGS 1000
|
||||
#define MAX_BASIS_DIRS 20
|
||||
#define MAX_SERVER_ARGS (MAX_BASIS_DIRS*2 + 100)
|
||||
|
||||
#define MPLEX_BASE 7
|
||||
#define FERROR 1
|
||||
#define FINFO 2
|
||||
#define FLOG 3
|
||||
|
||||
#define NO_FILTERS 0
|
||||
#define SERVER_FILTERS 1
|
||||
#define ALL_FILTERS 2
|
||||
|
||||
#define XFLG_FATAL_ERRORS (1<<0)
|
||||
#define XFLG_OLD_PREFIXES (1<<1)
|
||||
#define XFLG_ANCHORED2ABS (1<<2)
|
||||
#define XFLG_ABS_IF_SLASH (1<<3)
|
||||
|
||||
#define ATTRS_REPORT (1<<0)
|
||||
#define ATTRS_SKIP_MTIME (1<<1)
|
||||
|
||||
#define FULL_FLUSH 1
|
||||
#define NORMAL_FLUSH 0
|
||||
|
||||
#define PDIR_CREATE 1
|
||||
#define PDIR_DELETE 0
|
||||
|
||||
/* Note: 0x00 - 0x7F are used for basis_dir[] indexes! */
|
||||
#define FNAMECMP_BASIS_DIR_LOW 0x00 /* Must remain 0! */
|
||||
#define FNAMECMP_BASIS_DIR_HIGH 0x7F
|
||||
#define FNAMECMP_FNAME 0x80
|
||||
#define FNAMECMP_PARTIAL_DIR 0x81
|
||||
#define FNAMECMP_BACKUP 0x82
|
||||
#define FNAMECMP_FUZZY 0x83
|
||||
|
||||
/* For use by the itemize_changes code */
|
||||
#define ITEM_REPORT_CHECKSUM (1<<1)
|
||||
#define ITEM_REPORT_SIZE (1<<2)
|
||||
#define ITEM_REPORT_TIME (1<<3)
|
||||
#define ITEM_REPORT_PERMS (1<<4)
|
||||
#define ITEM_REPORT_OWNER (1<<5)
|
||||
#define ITEM_REPORT_GROUP (1<<6)
|
||||
#define ITEM_REPORT_XATTRS (1<<7)
|
||||
#define ITEM_BASIS_TYPE_FOLLOWS (1<<11)
|
||||
#define ITEM_XNAME_FOLLOWS (1<<12)
|
||||
#define ITEM_IS_NEW (1<<13)
|
||||
#define ITEM_LOCAL_CHANGE (1<<14)
|
||||
#define ITEM_TRANSFER (1<<15)
|
||||
/* These are outside the range of the transmitted flags. */
|
||||
#define ITEM_MISSING_DATA (1<<16) /* used by log_formatted() */
|
||||
#define ITEM_DELETED (1<<17) /* used by log_formatted() */
|
||||
|
||||
#define SIGNIFICANT_ITEM_FLAGS (~(\
|
||||
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
|
||||
|
||||
|
||||
/* Log-message categories. Only FERROR and FINFO get sent over the socket.
|
||||
* FLOG and FCLIENT are only used on the daemon side for custom logging,
|
||||
* while FNAME is only used on the client side. */
|
||||
enum logcode { FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FNAME=5, FSOCKERR=6 };
|
||||
|
||||
/* Messages types that are sent over the message channel. The logcode
|
||||
* values must all be present here with identical numbers. */
|
||||
enum msgcode {
|
||||
MSG_DATA=0, /* raw data on the multiplexed stream */
|
||||
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
|
||||
MSG_LOG=FLOG, MSG_SOCKERR=FSOCKERR, /* sibling logging */
|
||||
MSG_REDO=9, /* reprocess indicated flist index */
|
||||
MSG_SUCCESS=100,/* successfully updated indicated flist index */
|
||||
MSG_DELETED=101,/* successfully deleted a file on receiving side */
|
||||
MSG_DONE=86 /* current phase is done */
|
||||
};
|
||||
|
||||
#include "errcode.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_REMSH
|
||||
#define RSYNC_RSH "remsh"
|
||||
#else
|
||||
#define RSYNC_RSH "rsh"
|
||||
#endif
|
||||
/* The default RSYNC_RSH is always set in config.h. */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
#include <getopt.h>
|
||||
#else
|
||||
#include "lib/getopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.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
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#if defined HAVE_MALLOC_H && (defined HAVE_MALLINFO || !defined HAVE_STDLIB_H)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -130,8 +237,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
@@ -167,12 +272,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FNMATCH
|
||||
#include <fnmatch.h>
|
||||
#else
|
||||
#include "lib/fnmatch.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
@@ -188,25 +287,41 @@
|
||||
#include <syslog.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
#ifdef HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# ifdef HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# ifdef HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# ifdef HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "lib/pool_alloc.h"
|
||||
|
||||
#define BOOL int
|
||||
|
||||
@@ -214,56 +329,117 @@
|
||||
#define uchar unsigned char
|
||||
#endif
|
||||
|
||||
#if HAVE_UNSIGNED_CHAR
|
||||
#ifdef SIGNED_CHAR_OK
|
||||
#define schar signed char
|
||||
#else
|
||||
#define schar char
|
||||
#endif
|
||||
|
||||
/* Find a variable that is either exactly 32-bits or longer.
|
||||
* If some code depends on 32-bit truncation, it will need to
|
||||
* take special action in a "#if SIZEOF_INT32 > 4" section. */
|
||||
#ifndef int32
|
||||
#if (SIZEOF_INT == 4)
|
||||
#define int32 int
|
||||
#elif (SIZEOF_LONG == 4)
|
||||
#define int32 long
|
||||
#elif (SIZEOF_SHORT == 4)
|
||||
#define int32 short
|
||||
#if SIZEOF_INT == 4
|
||||
# define int32 int
|
||||
# define SIZEOF_INT32 4
|
||||
#elif SIZEOF_LONG == 4
|
||||
# define int32 long
|
||||
# define SIZEOF_INT32 4
|
||||
#elif SIZEOF_SHORT == 4
|
||||
# define int32 short
|
||||
# define SIZEOF_INT32 4
|
||||
#elif SIZEOF_INT > 4
|
||||
# define int32 int
|
||||
# define SIZEOF_INT32 SIZEOF_INT
|
||||
#elif SIZEOF_LONG > 4
|
||||
# define int32 long
|
||||
# define SIZEOF_INT32 SIZEOF_LONG
|
||||
#else
|
||||
/* I hope this works */
|
||||
#define int32 int
|
||||
#define LARGE_INT32
|
||||
# error Could not find a 32-bit integer variable
|
||||
#endif
|
||||
#else
|
||||
# define SIZEOF_INT32 4
|
||||
#endif
|
||||
|
||||
#ifndef uint32
|
||||
#define uint32 unsigned int32
|
||||
#endif
|
||||
|
||||
#if HAVE_OFF64_T
|
||||
#define OFF_T off64_t
|
||||
#define STRUCT_STAT struct stat64
|
||||
#else
|
||||
#if SIZEOF_OFF_T == 8 || !SIZEOF_OFF64_T || !defined HAVE_STRUCT_STAT64
|
||||
#define OFF_T off_t
|
||||
#define STRUCT_STAT struct stat
|
||||
#else
|
||||
#define OFF_T off64_t
|
||||
#define STRUCT_STAT struct stat64
|
||||
#define USE_STAT64_FUNCS 1
|
||||
#endif
|
||||
|
||||
#if HAVE_OFF64_T
|
||||
#define int64 off64_t
|
||||
#elif (SIZEOF_LONG == 8)
|
||||
#define int64 long
|
||||
#elif (SIZEOF_INT == 8)
|
||||
#define int64 int
|
||||
#elif HAVE_LONGLONG
|
||||
#define int64 long long
|
||||
/* CAVEAT: on some systems, int64 will really be a 32-bit integer IFF
|
||||
* that's the maximum size the file system can handle and there is no
|
||||
* 64-bit type available. The rsync source must therefore take steps
|
||||
* to ensure that any code that really requires a 64-bit integer has
|
||||
* it (e.g. the checksum code uses two 32-bit integers for its 64-bit
|
||||
* counter). */
|
||||
#if SIZEOF_OFF64_T == 8
|
||||
# define int64 off64_t
|
||||
# define SIZEOF_INT64 8
|
||||
#elif SIZEOF_LONG == 8
|
||||
# define int64 long
|
||||
# define SIZEOF_INT64 8
|
||||
#elif SIZEOF_INT == 8
|
||||
# define int64 int
|
||||
# define SIZEOF_INT64 8
|
||||
#elif SIZEOF_LONG_LONG == 8
|
||||
# define int64 long long
|
||||
# define SIZEOF_INT64 8
|
||||
#elif SIZEOF_OFF_T == 8
|
||||
# define int64 off_t
|
||||
# define SIZEOF_INT64 8
|
||||
#elif SIZEOF_INT > 8
|
||||
# define int64 int
|
||||
# define SIZEOF_INT64 SIZEOF_INT
|
||||
#elif SIZEOF_LONG > 8
|
||||
# define int64 long
|
||||
# define SIZEOF_INT64 SIZEOF_LONG
|
||||
#elif SIZEOF_LONG_LONG > 8
|
||||
# define int64 long long
|
||||
# define SIZEOF_INT64 SIZEOF_LONG_LONG
|
||||
#else
|
||||
#define int64 off_t
|
||||
#define NO_INT64
|
||||
/* As long as it gets... */
|
||||
# define int64 off_t
|
||||
# define SIZEOF_INT64 SIZEOF_OFF_T
|
||||
#endif
|
||||
|
||||
#if HAVE_SHORT_INO_T
|
||||
#define INO_T uint32
|
||||
#else
|
||||
#define INO_T ino_t
|
||||
#endif
|
||||
/* Starting from protocol version 26, we always use 64-bit
|
||||
* ino_t and dev_t internally, even if this platform does not
|
||||
* allow files to have 64-bit inums. That's because the
|
||||
* receiver needs to find duplicate (dev,ino) tuples to detect
|
||||
* hardlinks, and it might have files coming from a platform
|
||||
* that has 64-bit inums.
|
||||
*
|
||||
* The only exception is if we're on a platform with no 64-bit type at
|
||||
* all.
|
||||
*
|
||||
* Because we use read_longint() to get these off the wire, if you
|
||||
* transfer devices or hardlinks with dev or inum > 2**32 to a machine
|
||||
* with no 64-bit types then you will get an overflow error. Probably
|
||||
* not many people have that combination of machines, and you can
|
||||
* avoid it by not preserving hardlinks or not transferring device
|
||||
* nodes. It's not clear that any other behaviour is better.
|
||||
*
|
||||
* Note that if you transfer devices from a 64-bit-devt machine (say,
|
||||
* Solaris) to a 32-bit-devt machine (say, Linux-2.2/x86) then the
|
||||
* device numbers will be truncated. But it's a kind of silly thing
|
||||
* to do anyhow.
|
||||
*
|
||||
* FIXME: I don't think the code in flist.c has ever worked on a system
|
||||
* where dev_t is a struct.
|
||||
*/
|
||||
|
||||
struct idev {
|
||||
int64 inode;
|
||||
int64 dev;
|
||||
};
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@@ -280,69 +456,174 @@
|
||||
/* the length of the md4 checksum */
|
||||
#define MD4_SUM_LENGTH 16
|
||||
#define SUM_LENGTH 16
|
||||
#define SHORT_SUM_LENGTH 2
|
||||
#define BLOCKSUM_BIAS 10
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
/* We want a roomy line buffer that can hold more than MAXPATHLEN,
|
||||
* and significantly more than an overly short MAXPATHLEN. */
|
||||
#if MAXPATHLEN < 4096
|
||||
#define BIGPATHBUFLEN (4096+1024)
|
||||
#else
|
||||
#define BIGPATHBUFLEN (MAXPATHLEN+1024)
|
||||
#endif
|
||||
|
||||
#ifndef NAME_MAX
|
||||
#define NAME_MAX 255
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
#ifndef IN_LOOPBACKNET
|
||||
#define IN_LOOPBACKNET 127
|
||||
#endif
|
||||
|
||||
#define GID_NONE ((gid_t)-1)
|
||||
|
||||
#define HL_CHECK_MASTER 0
|
||||
#define HL_SKIP 1
|
||||
|
||||
struct hlink {
|
||||
int next;
|
||||
int hlindex;
|
||||
};
|
||||
|
||||
#define F_DEV link_u.idev->dev
|
||||
#define F_INODE link_u.idev->inode
|
||||
|
||||
#define F_HLINDEX link_u.links->hlindex
|
||||
#define F_NEXT link_u.links->next
|
||||
|
||||
struct file_struct {
|
||||
unsigned flags;
|
||||
time_t modtime;
|
||||
union {
|
||||
dev_t rdev; /* The device number, if this is a device */
|
||||
char *sum; /* Only a normal file can have a checksum */
|
||||
char *link; /* Points to symlink string, if a symlink */
|
||||
} u;
|
||||
OFF_T length;
|
||||
mode_t mode;
|
||||
INO_T inode;
|
||||
dev_t dev;
|
||||
dev_t rdev;
|
||||
char *basename; /* The current item's name (AKA filename) */
|
||||
char *dirname; /* The directory info inside the transfer */
|
||||
union {
|
||||
char *root; /* Sender-side dir info outside transfer */
|
||||
int depth; /* Receiver-side directory depth info */
|
||||
} dir;
|
||||
union {
|
||||
struct idev *idev;
|
||||
struct hlink *links;
|
||||
} link_u;
|
||||
time_t modtime;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
char *basename;
|
||||
char *dirname;
|
||||
char *basedir;
|
||||
char *link;
|
||||
char *sum;
|
||||
mode_t mode;
|
||||
uchar flags; /* this item MUST remain last */
|
||||
};
|
||||
|
||||
/*
|
||||
* Start the flist array at FLIST_START entries and grow it
|
||||
* by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
|
||||
*/
|
||||
#define FLIST_START (32 * 1024)
|
||||
#define FLIST_LINEAR (FLIST_START * 512)
|
||||
|
||||
/*
|
||||
* Extent size for allocation pools A minimum size of 128KB
|
||||
* is needed to mmap them so that freeing will release the
|
||||
* space to the OS.
|
||||
*
|
||||
* Larger sizes reduce leftover fragments and speed free calls
|
||||
* (when they happen) Smaller sizes increase the chance of
|
||||
* freed allocations freeing whole extents.
|
||||
*/
|
||||
#define FILE_EXTENT (256 * 1024)
|
||||
#define HLINK_EXTENT (128 * 1024)
|
||||
|
||||
#define WITH_HLINK 1
|
||||
#define WITHOUT_HLINK 0
|
||||
|
||||
struct file_list {
|
||||
struct file_struct **files;
|
||||
alloc_pool_t file_pool;
|
||||
alloc_pool_t hlink_pool;
|
||||
int count;
|
||||
int malloced;
|
||||
struct file_struct **files;
|
||||
int low, high;
|
||||
};
|
||||
|
||||
#define SUMFLG_SAME_OFFSET (1<<0)
|
||||
|
||||
struct sum_buf {
|
||||
OFF_T offset; /* offset in file of this chunk */
|
||||
int len; /* length of chunk of file */
|
||||
int i; /* index of this chunk */
|
||||
uint32 sum1; /* simple checksum */
|
||||
char sum2[SUM_LENGTH]; /* checksum */
|
||||
OFF_T offset; /**< offset in file of this chunk */
|
||||
int32 len; /**< length of chunk of file */
|
||||
uint32 sum1; /**< simple checksum */
|
||||
int32 chain; /**< next hash-table collision */
|
||||
short flags; /**< flag bits */
|
||||
char sum2[SUM_LENGTH]; /**< checksum */
|
||||
};
|
||||
|
||||
struct sum_struct {
|
||||
OFF_T flength; /* total file length */
|
||||
int count; /* how many chunks */
|
||||
int remainder; /* flength % block_length */
|
||||
int n; /* block_length */
|
||||
struct sum_buf *sums; /* points to info for each chunk */
|
||||
OFF_T flength; /**< total file length */
|
||||
struct sum_buf *sums; /**< points to info for each chunk */
|
||||
int32 count; /**< how many chunks */
|
||||
int32 blength; /**< block_length */
|
||||
int32 remainder; /**< flength % block_length */
|
||||
int s2length; /**< sum2_length */
|
||||
};
|
||||
|
||||
struct map_struct {
|
||||
char *p;
|
||||
int fd,p_size,p_len;
|
||||
OFF_T file_size, p_offset, p_fd_offset;
|
||||
OFF_T file_size; /* File size (from stat) */
|
||||
OFF_T p_offset; /* Window start */
|
||||
OFF_T p_fd_offset; /* offset of cursor in fd ala lseek */
|
||||
char *p; /* Window pointer */
|
||||
int32 p_size; /* Largest window size we allocated */
|
||||
int32 p_len; /* Latest (rounded) window size */
|
||||
int32 def_window_size; /* Default window size */
|
||||
int fd; /* File Descriptor */
|
||||
int status; /* first errno from read errors */
|
||||
};
|
||||
|
||||
struct exclude_struct {
|
||||
char *orig;
|
||||
#define MATCHFLG_WILD (1<<0) /* pattern has '*', '[', and/or '?' */
|
||||
#define MATCHFLG_WILD2 (1<<1) /* pattern has '**' */
|
||||
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with "**" */
|
||||
#define MATCHFLG_WILD3_SUFFIX (1<<3) /* pattern ends with "***" */
|
||||
#define MATCHFLG_ABS_PATH (1<<4) /* path-match on absolute path */
|
||||
#define MATCHFLG_INCLUDE (1<<5) /* this is an include, not an exclude */
|
||||
#define MATCHFLG_DIRECTORY (1<<6) /* this matches only directories */
|
||||
#define MATCHFLG_WORD_SPLIT (1<<7) /* split rules on whitespace */
|
||||
#define MATCHFLG_NO_INHERIT (1<<8) /* don't inherit these rules */
|
||||
#define MATCHFLG_NO_PREFIXES (1<<9) /* parse no prefixes from patterns */
|
||||
#define MATCHFLG_MERGE_FILE (1<<10)/* specifies a file to merge */
|
||||
#define MATCHFLG_PERDIR_MERGE (1<<11)/* merge-file is searched per-dir */
|
||||
#define MATCHFLG_EXCLUDE_SELF (1<<12)/* merge-file name should be excluded */
|
||||
#define MATCHFLG_FINISH_SETUP (1<<13)/* per-dir merge file needs setup */
|
||||
#define MATCHFLG_NEGATE (1<<14)/* rule matches when pattern does not */
|
||||
#define MATCHFLG_CVS_IGNORE (1<<15)/* rule was -C or :C */
|
||||
#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
|
||||
#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
|
||||
#define MATCHFLG_CLEAR_LIST (1<<18)/* this item is the "!" token */
|
||||
|
||||
#define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
|
||||
| MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
|
||||
| MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE)
|
||||
|
||||
struct filter_struct {
|
||||
struct filter_struct *next;
|
||||
char *pattern;
|
||||
int regular_exp;
|
||||
int fnmatch_flags;
|
||||
int include;
|
||||
int directory;
|
||||
int local;
|
||||
uint32 match_flags;
|
||||
union {
|
||||
int slash_cnt;
|
||||
struct filter_list_struct *mergelist;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct filter_list_struct {
|
||||
struct filter_struct *head;
|
||||
struct filter_struct *tail;
|
||||
char *debug_type;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
@@ -352,27 +633,54 @@ struct stats {
|
||||
int64 total_read;
|
||||
int64 literal_data;
|
||||
int64 matched_data;
|
||||
int64 flist_buildtime;
|
||||
int64 flist_xfertime;
|
||||
int flist_size;
|
||||
int num_files;
|
||||
int num_transferred_files;
|
||||
int current_file_index;
|
||||
};
|
||||
|
||||
|
||||
/* we need this function because of the silly way in which duplicate
|
||||
entries are handled in the file lists - we can't change this
|
||||
without breaking existing versions */
|
||||
static inline int flist_up(struct file_list *flist, int i)
|
||||
{
|
||||
while (!flist->files[i]->basename) i++;
|
||||
return i;
|
||||
}
|
||||
struct chmod_mode_struct;
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "version.h"
|
||||
#include "proto.h"
|
||||
#include "lib/mdfour.h"
|
||||
#include "lib/wildmatch.h"
|
||||
#include "lib/permstring.h"
|
||||
#include "lib/addrinfo.h"
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
#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> */
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#define UNUSED(x) x __attribute__((__unused__))
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
/* We have replacement versions of these if they're missing. */
|
||||
#ifndef HAVE_ASPRINTF
|
||||
int asprintf(char **ptr, const char *format, ...);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VASPRINTF
|
||||
int vasprintf(char **ptr, const char *format, va_list ap);
|
||||
#endif
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
#if !defined HAVE_SNPRINTF || !defined HAVE_C99_VSNPRINTF
|
||||
#define snprintf rsync_snprintf
|
||||
int snprintf(char *str,size_t count,const char *fmt,...);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
extern char *sys_errlist[];
|
||||
#define strerror(i) sys_errlist[i]
|
||||
#endif
|
||||
@@ -386,14 +694,19 @@ extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#define SUPPORT_LINKS HAVE_READLINK
|
||||
#define SUPPORT_HARD_LINKS HAVE_LINK
|
||||
|
||||
#ifndef HAVE_LCHOWN
|
||||
#define lchown chown
|
||||
#ifdef HAVE_READLINK
|
||||
#define SUPPORT_LINKS 1
|
||||
#endif
|
||||
#ifdef HAVE_LINK
|
||||
#define SUPPORT_HARD_LINKS 1
|
||||
#endif
|
||||
|
||||
#define SIGNAL_CAST (RETSIGTYPE (*)())
|
||||
#ifdef HAVE_SIGACTION
|
||||
#define SIGACTION(n,h) sigact.sa_handler=(h), sigaction((n),&sigact,NULL)
|
||||
#define signal(n,h) we_need_to_call_SIGACTION_not_signal(n,h)
|
||||
#else
|
||||
#define SIGACTION(n,h) signal(n,h)
|
||||
#endif
|
||||
|
||||
#ifndef EWOULDBLOCK
|
||||
#define EWOULDBLOCK EAGAIN
|
||||
@@ -411,10 +724,24 @@ extern int errno;
|
||||
#define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
#ifndef S_IRUSR
|
||||
#define S_IRUSR 0400
|
||||
#endif
|
||||
|
||||
#ifndef S_IWUSR
|
||||
#define S_IWUSR 0200
|
||||
#endif
|
||||
|
||||
#ifndef ACCESSPERMS
|
||||
#define ACCESSPERMS 0777
|
||||
#endif
|
||||
|
||||
#ifndef S_ISVTX
|
||||
#define S_ISVTX 0
|
||||
#endif
|
||||
|
||||
#define CHMOD_BITS (S_ISUID | S_ISGID | S_ISVTX | ACCESSPERMS)
|
||||
|
||||
#ifndef _S_IFMT
|
||||
#define _S_IFMT 0170000
|
||||
#endif
|
||||
@@ -459,12 +786,26 @@ extern int errno;
|
||||
#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
|
||||
#endif
|
||||
|
||||
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
|
||||
#ifndef ACCESSPERMS
|
||||
#define ACCESSPERMS 0777
|
||||
/* work out what fcntl flag to use for non-blocking */
|
||||
#ifdef O_NONBLOCK
|
||||
# define NONBLOCK_FLAG O_NONBLOCK
|
||||
#elif defined SYSV
|
||||
# define NONBLOCK_FLAG O_NDELAY
|
||||
#else
|
||||
# define NONBLOCK_FLAG FNDELAY
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_LOOPBACK
|
||||
#define INADDR_LOOPBACK 0x7f000001
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
|
||||
|
||||
/* Initial mask on permissions given to temporary files. Mask off setuid
|
||||
bits and group access because of potential race-condition security
|
||||
holes, and mask other access because mode 707 is bizarre */
|
||||
@@ -473,17 +814,30 @@ extern int errno;
|
||||
/* handler for null strings in printf format */
|
||||
#define NS(s) ((s)?(s):"<NULL>")
|
||||
|
||||
/* Convenient wrappers for malloc and realloc. Use them. */
|
||||
#define new(type) ((type *)malloc(sizeof(type)))
|
||||
#define new_array(type, num) ((type *)_new_array(sizeof(type), (num)))
|
||||
#define realloc_array(ptr, type, num) ((type *)_realloc_array((ptr), sizeof(type), (num)))
|
||||
|
||||
/* use magic gcc attributes to catch format errors */
|
||||
void rprintf(int , const char *, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
void rprintf(enum logcode , const char *, ...)
|
||||
__attribute__((format (printf, 2, 3)))
|
||||
;
|
||||
|
||||
/* This is just like rprintf, but it also tries to print some
|
||||
* representation of the error code. Normally errcode = errno. */
|
||||
void rsyserr(enum logcode, int, const char *, ...)
|
||||
__attribute__((format (printf, 3, 4)))
|
||||
;
|
||||
|
||||
#ifdef REPLACE_INET_NTOA
|
||||
#define inet_ntoa rep_inet_ntoa
|
||||
#endif
|
||||
|
||||
/* Make sure that the O_BINARY flag is defined. */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char *d, const char *s, size_t bufsize);
|
||||
@@ -493,4 +847,34 @@ size_t strlcpy(char *d, const char *s, size_t bufsize);
|
||||
size_t strlcat(char *d, const char *s, size_t bufsize);
|
||||
#endif
|
||||
|
||||
#ifndef WEXITSTATUS
|
||||
#define WEXITSTATUS(stat) ((int)(((stat)>>8)&0xFF))
|
||||
#endif
|
||||
|
||||
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
|
||||
|
||||
#ifdef HAVE_GETEUID
|
||||
#define MY_UID() geteuid()
|
||||
#else
|
||||
#define MY_UID() getuid()
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETEGID
|
||||
#define MY_GID() getegid()
|
||||
#else
|
||||
#define MY_GID() getgid()
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
int inet_pton(int af, const char *src, void *dst);
|
||||
#endif
|
||||
|
||||
#ifdef MAINTAINER_MODE
|
||||
const char *get_panic_action(void);
|
||||
#endif
|
||||
|
||||
469
rsync3.txt
Normal file
469
rsync3.txt
Normal file
@@ -0,0 +1,469 @@
|
||||
-*- indented-text -*-
|
||||
|
||||
Notes towards a new version of rsync
|
||||
Martin Pool <mbp@samba.org>, September 2001.
|
||||
|
||||
|
||||
Good things about the current implementation:
|
||||
|
||||
- Widely known and adopted.
|
||||
|
||||
- Fast/efficient, especially for moderately small sets of files over
|
||||
slow links (transoceanic or modem.)
|
||||
|
||||
- Fairly reliable.
|
||||
|
||||
- The choice of runnning over a plain TCP socket or tunneling over
|
||||
ssh.
|
||||
|
||||
- rsync operations are idempotent: you can always run the same
|
||||
command twice to make sure it worked properly without any fear.
|
||||
(Are there any exceptions?)
|
||||
|
||||
- Small changes to files cause small deltas.
|
||||
|
||||
- There is a way to evolve the protocol to some extent.
|
||||
|
||||
- rdiff and rsync --write-batch allow generation of standalone patch
|
||||
sets. rsync+ is pretty cheesy, though. xdelta seems cleaner.
|
||||
|
||||
- Process triangle is creative, but seems to provoke OS bugs.
|
||||
|
||||
- "Morning-after property": you don't need to know anything on the
|
||||
local machine about the state of the remote machine, or about
|
||||
transfers that have been done in the past.
|
||||
|
||||
- You can easily push or pull simply by switching the order of
|
||||
files.
|
||||
|
||||
- The "modules" system has some neat features compared to
|
||||
e.g. Apache's per-directory configuration. In particular, because
|
||||
you can set a userid and chroot directory, there is strong
|
||||
protection between different modules. I haven't seen any calls
|
||||
for a more flexible system.
|
||||
|
||||
|
||||
Bad things about the current implementation:
|
||||
|
||||
- Persistent and hard-to-diagnose hang bugs remain
|
||||
|
||||
- Protocol is sketchily documented, tied to this implementation, and
|
||||
hard to modify/extend
|
||||
|
||||
- Both the program and the protocol assume a single non-interactive
|
||||
one-way transfer
|
||||
|
||||
- A list of all files are held in memory for the entire transfer,
|
||||
which cripples scalability to large file trees
|
||||
|
||||
- Opening a new socket for every operation causes problems,
|
||||
especially when running over SSH with password authentication.
|
||||
|
||||
- Renamed files are not handled: the old file is removed, and the
|
||||
new file created from scratch.
|
||||
|
||||
- The versioning approach assumes that future versions of the
|
||||
program know about all previous versions, and will do the right
|
||||
thing.
|
||||
|
||||
- People always get confused about ':' vs '::'
|
||||
|
||||
- Error messages can be cryptic.
|
||||
|
||||
- Default behaviour is not intuitive: in too many cases rsync will
|
||||
happily do nothing. Perhaps -a should be the default?
|
||||
|
||||
- People get confused by trailing slashes, though it's hard to think
|
||||
of another reasonable way to make this necessary distinction
|
||||
between a directory and its contents.
|
||||
|
||||
|
||||
Protocol philosophy:
|
||||
|
||||
*The* big difference between protocols like HTTP, FTP, and NFS is
|
||||
that their fundamental operations are "read this file", "delete
|
||||
this file", and "make this directory", whereas rsync is "make this
|
||||
directory like this one".
|
||||
|
||||
|
||||
Questionable features:
|
||||
|
||||
These are neat, but not necessarily clean or worth preserving.
|
||||
|
||||
- The remote rsync can be wrapped by some other program, such as in
|
||||
tridge's rsync-mail scripts. The general feature of sending and
|
||||
retrieving mail over rsync is good, but this is perhaps not the
|
||||
right way to implement it.
|
||||
|
||||
|
||||
Desirable features:
|
||||
|
||||
These don't really require architectural changes; they're just
|
||||
something to keep in mind.
|
||||
|
||||
- Synchronize ACLs and extended attributes
|
||||
|
||||
- Anonymous servers should be efficient
|
||||
|
||||
- Code should be portable to non-UNIX systems
|
||||
|
||||
- Should be possible to document the protocol in RFC form
|
||||
|
||||
- --dry-run option
|
||||
|
||||
- IPv6 support. Pretty straightforward.
|
||||
|
||||
- Allow the basis and destination files to be different. For
|
||||
example, you could use this when you have a CD-ROM and want to
|
||||
download an updated image onto a hard drive.
|
||||
|
||||
- Efficiently interrupt and restart a transfer. We can write a
|
||||
checkpoint file that says where we're up to in the filesystem.
|
||||
Alternatively, as long as transfers are idempotent, we can just
|
||||
restart the whole thing. [NFSv4]
|
||||
|
||||
- Scripting support.
|
||||
|
||||
- Propagate atimes and do not modify them. This is very ugly on
|
||||
Unix. It might be better to try to add O_NOATIME to kernels, and
|
||||
call that.
|
||||
|
||||
- Unicode. Probably just use UTF-8 for everything.
|
||||
|
||||
- Open authentication system. Can we use PAM? Is SASL an adequate
|
||||
mapping of PAM to the network, or useful in some other way?
|
||||
|
||||
- Resume interrupted transfers without the --partial flag. We need
|
||||
to leave the temporary file behind, and then know to use it. This
|
||||
leaves a risk of large temporary files accumulating, which is not
|
||||
good. Perhaps it should be off by default.
|
||||
|
||||
- tcpwrappers support. Should be trivial; can already be done
|
||||
through tcpd or inetd.
|
||||
|
||||
- Socks support built in. It's not clear this is any better than
|
||||
just linking against the socks library, though.
|
||||
|
||||
- When run over SSH, invoke with predictable command-line arguments,
|
||||
so that people can restrict what commands sshd will run. (Is this
|
||||
really required?)
|
||||
|
||||
- Comparison mode: give a list of which files are new, gone, or
|
||||
different. Set return code depending on whether anything has
|
||||
changed.
|
||||
|
||||
- Internationalized messages (gettext?)
|
||||
|
||||
- Optionally use real regexps rather than globs?
|
||||
|
||||
- Show overall progress. Pretty hard to do, especially if we insist
|
||||
on not scanning the directory tree up front.
|
||||
|
||||
|
||||
Regression testing:
|
||||
|
||||
- Support automatic testing.
|
||||
|
||||
- Have hard internal timeouts against hangs.
|
||||
|
||||
- Be deterministic.
|
||||
|
||||
- Measure performance.
|
||||
|
||||
|
||||
Hard links:
|
||||
|
||||
At the moment, we can recreate hard links, but it's a bit
|
||||
inefficient: it depends on holding a list of all files in the tree.
|
||||
Every time we see a file with a linkcount >1, we need to search for
|
||||
another known name that has the same (fsid,inum) tuple. We could do
|
||||
that more efficiently by keeping a list of only files with
|
||||
linkcount>1, and removing files from that list as all their names
|
||||
become known.
|
||||
|
||||
|
||||
Command-line options:
|
||||
|
||||
We have rather a lot at the moment. We might get more if the tool
|
||||
becomes more flexible. Do we need a .rc or configuration file?
|
||||
That wouldn't really fit with its pattern of use: cp and tar don't
|
||||
have them, though ssh does.
|
||||
|
||||
|
||||
Scripting issues:
|
||||
|
||||
- Perhaps support multiple scripting languages: candidates include
|
||||
Perl, Python, Tcl, Scheme (guile?), sh, ...
|
||||
|
||||
- Simply running a subprocess and looking at its stdout/exit code
|
||||
might be sufficient, though it could also be pretty slow if it's
|
||||
called often.
|
||||
|
||||
- There are security issues about running remote code, at least if
|
||||
it's not running in the users own account. So we can either
|
||||
disallow it, or use some kind of sandbox system.
|
||||
|
||||
- Python is a good language, but the syntax is not so good for
|
||||
giving small fragments on the command line.
|
||||
|
||||
- Tcl is broken Lisp.
|
||||
|
||||
- Lots of sysadmins know Perl, though Perl can give some bizarre or
|
||||
confusing errors. The built in stat operators and regexps might
|
||||
be useful.
|
||||
|
||||
- Sadly probably not enough people know Scheme.
|
||||
|
||||
- sh is hard to embed.
|
||||
|
||||
|
||||
Scripting hooks:
|
||||
|
||||
- Whether to transfer a file
|
||||
|
||||
- What basis file to use
|
||||
|
||||
- Logging
|
||||
|
||||
- Whether to allow transfers (for public servers)
|
||||
|
||||
- Authentication
|
||||
|
||||
- Locking
|
||||
|
||||
- Cache
|
||||
|
||||
- Generating backup path/name.
|
||||
|
||||
- Post-processing of backups, e.g. to do compression.
|
||||
|
||||
- After transfer, before replacement: so that we can spit out a diff
|
||||
of what was changed, or kick off some kind of reconciliation
|
||||
process.
|
||||
|
||||
|
||||
VFS:
|
||||
|
||||
Rather than talking straight to the filesystem, rsyncd talks through
|
||||
an internal API. Samba has one. Is it useful?
|
||||
|
||||
- Could be a tidy way to implement cached signatures.
|
||||
|
||||
- Keep files compressed on disk?
|
||||
|
||||
|
||||
Interactive interface:
|
||||
|
||||
- Something like ncFTP, or integration into GNOME-vfs. Probably
|
||||
hold a single socket connection open.
|
||||
|
||||
- Can either call us as a separate process, or as a library.
|
||||
|
||||
- The standalone process needs to produce output in a form easily
|
||||
digestible by a calling program, like the --emacs feature some
|
||||
have. Same goes for output: rpm outputs a series of hash symbols,
|
||||
which are easier for a GUI to handle than "\r30% complete"
|
||||
strings.
|
||||
|
||||
- Yow! emacs support. (You could probably build that already, of
|
||||
course.) I'd like to be able to write a simple script on a remote
|
||||
machine that rsyncs it to my workstation, edits it there, then
|
||||
pushes it back up.
|
||||
|
||||
|
||||
Pie-in-the-sky features:
|
||||
|
||||
These might have a severe impact on the protocol, and are not
|
||||
clearly in our core requirements. It looks like in many of them
|
||||
having scripting hooks will allow us
|
||||
|
||||
- Transport over UDP multicast. The hard part is handling multiple
|
||||
destinations which have different basis files. We can look at
|
||||
multicast-TFTP for inspiration.
|
||||
|
||||
- Conflict resolution. Possibly general scripting support will be
|
||||
sufficient.
|
||||
|
||||
- Integrate with locking. It's hard to see a good general solution,
|
||||
because Unix systems have several locking mechanisms, and grabbing
|
||||
the lock from programs that don't expect it could cause deadlocks,
|
||||
timeouts, or other problems. Scripting support might help.
|
||||
|
||||
- Replicate in place, rather than to a temporary file. This is
|
||||
dangerous in the case of interruption, and it also means that the
|
||||
delta can't refer to blocks that have already been overwritten.
|
||||
On the other hand we could semi-trivially do this at first by
|
||||
simply generating a delta with no copy instructions.
|
||||
|
||||
- Replicate block devices. Most of the difficulties here are to do
|
||||
with replication in place, though on some systems we will also
|
||||
have to do I/O on block boundaries.
|
||||
|
||||
- Peer to peer features. Flavour of the year. Can we think about
|
||||
ways for clients to smoothly and voluntarily become servers for
|
||||
content they receive?
|
||||
|
||||
- Imagine a situation where the destination has a much faster link
|
||||
to the cloud than the source. In this case, Mojo Nation downloads
|
||||
interleaved blocks from several slower servers. The general
|
||||
situation might be a way for a master rsync process to farm out
|
||||
tasks to several subjobs. In this particular case they'd need
|
||||
different sockets. This might be related to multicast.
|
||||
|
||||
|
||||
Unlikely features:
|
||||
|
||||
- Allow remote source and destination. If this can be cleanly
|
||||
designed into the protocol, perhaps with the remote machine acting
|
||||
as a kind of echo, then it's good. It's uncommon enough that we
|
||||
don't want to shape the whole protocol around it, though.
|
||||
|
||||
In fact, in a triangle of machines there are two possibilities:
|
||||
all traffic passes from remote1 to remote2 through local, or local
|
||||
just sets up the transfer and then remote1 talks to remote2. FTP
|
||||
supports the second but it's not clearly good. There are some
|
||||
security problems with being able to instruct one machine to open
|
||||
a connection to another.
|
||||
|
||||
|
||||
In favour of evolving the protocol:
|
||||
|
||||
- Keeping compatibility with existing rsync servers will help with
|
||||
adoption and testing.
|
||||
|
||||
- We should at the very least be able to fall back to the new
|
||||
protocol.
|
||||
|
||||
- Error handling is not so good.
|
||||
|
||||
|
||||
In favour of using a new protocol:
|
||||
|
||||
- Maintaining compatibility might soak up development time that
|
||||
would better go into improving a new protocol.
|
||||
|
||||
- If we start from scratch, it can be documented as we go, and we
|
||||
can avoid design decisions that make the protocol complex or
|
||||
implementation-bound.
|
||||
|
||||
|
||||
Error handling:
|
||||
|
||||
- Errors should come back reliably, and be clearly associated with
|
||||
the particular file that caused the problem.
|
||||
|
||||
- Some errors ought to cause the whole transfer to abort; some are
|
||||
just warnings. If any errors have occurred, then rsync ought to
|
||||
return an error.
|
||||
|
||||
|
||||
Concurrency:
|
||||
|
||||
- We want to keep the CPU, filesystem, and network as full as
|
||||
possible as much of the time as possible.
|
||||
|
||||
- We can do nonblocking network IO, but not so for disk.
|
||||
|
||||
- It makes sense to on the destination be generating signatures and
|
||||
applying patches at the same time.
|
||||
|
||||
- Can structure this with nonblocking, threads, separate processes,
|
||||
etc.
|
||||
|
||||
|
||||
Uses:
|
||||
|
||||
- Mirroring software distributions:
|
||||
|
||||
- Synchronizing laptop and desktop
|
||||
|
||||
- NFS filesystem migration/replication. See
|
||||
http://www.ietf.org/proceedings/00jul/00july-133.htm#P24510_1276764
|
||||
|
||||
- Sync with PDA
|
||||
|
||||
- Network backup systems
|
||||
|
||||
- CVS filemover
|
||||
|
||||
|
||||
Conflict resolution:
|
||||
|
||||
- Requires application-specific knowledge. We want to provide
|
||||
policy, rather than mechanism.
|
||||
|
||||
- Possibly allowing two-way migration across a single connection
|
||||
would be useful.
|
||||
|
||||
|
||||
Moved files: <http://rsync.samba.org/cgi-bin/rsync.fom?file=44>
|
||||
|
||||
- There's no trivial way to detect renamed files, especially if they
|
||||
move between directories.
|
||||
|
||||
- If we had a picture of the remote directory from last time on
|
||||
either machine, then the inode numbers might give us a hint about
|
||||
files which may have been renamed.
|
||||
|
||||
- Files that are renamed and not modified can be detected by
|
||||
examining the directory listing, looking for files with the same
|
||||
size/date as the origin.
|
||||
|
||||
|
||||
Filesystem migration:
|
||||
|
||||
NFSv4 probably wants to migrate file locks, but that's not really
|
||||
our problem.
|
||||
|
||||
|
||||
Atomic updates:
|
||||
|
||||
The NFSv4 working group wants atomic migration. Most of the
|
||||
responsibility for this lies on the NFS server or OS.
|
||||
|
||||
If migrating a whole tree, then we could do a nearly-atomic rename
|
||||
at the end. This ties in to having separate basis and destination
|
||||
files.
|
||||
|
||||
There's no way in Unix to replace a whole set of files atomically.
|
||||
However, if we get them all onto the destination machine and then do
|
||||
the updates quickly it would greatly reduce the window.
|
||||
|
||||
|
||||
Scalability:
|
||||
|
||||
We should aim to work well on machines in use in a year or two.
|
||||
That probably means transfers of many millions of files in one
|
||||
batch, and gigabytes or terabytes of data.
|
||||
|
||||
For argument's sake: at the low end, we want to sync ten files for a
|
||||
total of 10kb across a 1kB/s link. At the high end, we want to sync
|
||||
1e9 files for 1TB of data across a 1GB/s link.
|
||||
|
||||
On the whole CPU usage is not normally a limiting factor, if only
|
||||
because running over SSH burns a lot of cycles on encryption.
|
||||
|
||||
Perhaps have resource throttling without relying on rlimit.
|
||||
|
||||
|
||||
Streaming:
|
||||
|
||||
A big attraction of rsync is that there are few round-trip delays:
|
||||
basically only one to get started, and then everything is
|
||||
pipelined. This is a problem with FTP, and NFS (at least up to
|
||||
v3). NFSv4 can pipeline operations, but building on that is
|
||||
probably a bit complicated.
|
||||
|
||||
|
||||
Related work:
|
||||
|
||||
- mirror.pl http://freshmeat.net/project/mirror/
|
||||
|
||||
- ProFTPd
|
||||
|
||||
- Apache
|
||||
|
||||
- http://freshmeat.net/search/?site=Freshmeat&q=mirror§ion=projects
|
||||
|
||||
- BitTorrent -- p2p mirroring
|
||||
http://bitconjurer.org/BitTorrent/
|
||||
468
rsyncd.conf.yo
468
rsyncd.conf.yo
@@ -1,6 +1,6 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(12 Feb 1999)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync server)
|
||||
manpage(rsyncd.conf)(5)(11 Mar 2006)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
|
||||
manpagesynopsis()
|
||||
|
||||
rsyncd.conf
|
||||
@@ -8,9 +8,7 @@ rsyncd.conf
|
||||
manpagedescription()
|
||||
|
||||
The rsyncd.conf file is the runtime configuration file for rsync when
|
||||
run with the --daemon option. When run in this way rsync becomes a
|
||||
rsync server listening on TCP port 873. Connections from rsync clients
|
||||
are accepted for either anonymous or authenticated rsync sessions.
|
||||
run as an rsync daemon.
|
||||
|
||||
The rsyncd.conf file controls authentication, access, logging and
|
||||
available modules.
|
||||
@@ -21,7 +19,7 @@ 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'.
|
||||
|
||||
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
|
||||
@@ -43,26 +41,32 @@ in string values.
|
||||
|
||||
manpagesection(LAUNCHING THE RSYNC DAEMON)
|
||||
|
||||
The rsync daemon is launched by specifying the --daemon option to
|
||||
rsync. The daemon must run with root privileges.
|
||||
The rsync daemon is launched by specifying the bf(--daemon) option to
|
||||
rsync.
|
||||
|
||||
You can launch it either via inetd or as a stand-alone daemon. If run
|
||||
as a daemon then just run the command "rsync --daemon" from a suitable
|
||||
startup script.
|
||||
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
|
||||
file ownership. Otherwise, it must just have permission to read and
|
||||
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 "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)
|
||||
|
||||
You will then need to send inetd a HUP signal to tell it to reread its
|
||||
config file.
|
||||
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
|
||||
it to reread the tt(/etc/rsyncd.conf). The file is re-read on each client
|
||||
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.
|
||||
|
||||
manpagesection(GLOBAL OPTIONS)
|
||||
@@ -83,25 +87,37 @@ 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.
|
||||
chrooted programs. 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 a failure to open the specified log file used to be a fatal
|
||||
error.)
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
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()
|
||||
|
||||
@@ -119,92 +135,169 @@ 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(/etc/rsyncd.conf).
|
||||
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 and
|
||||
of not being able to follow symbolic links outside of the new root path.
|
||||
The default is to use chroot.
|
||||
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 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
|
||||
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 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/uploaded by adding an exclude rule to the rsyncd.conf file
|
||||
(e.g. "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
|
||||
to this module of your rsync server. 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.
|
||||
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.
|
||||
See also the "lock file" option.
|
||||
|
||||
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. The default is tt(/var/run/rsyncd.lock).
|
||||
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
|
||||
for modules to be listable.
|
||||
|
||||
dit(bf(uid)) The "uid" option specifies the user name or user id that
|
||||
dit(bf(uid)) The "uid" option specifies the user name or user ID that
|
||||
file transfers to and from that module should take place as when the daemon
|
||||
was run as root. In combination with the "gid" option this determines what
|
||||
file permissions are available. The default is the user "nobody".
|
||||
file permissions are available. The default is uid -2, which is normally
|
||||
the user "nobody".
|
||||
|
||||
dit(bf(gid)) The "gid" option specifies the group name or group id that
|
||||
dit(bf(gid)) The "gid" option specifies the group name or group ID that
|
||||
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 the
|
||||
group "nobody".
|
||||
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 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(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).
|
||||
|
||||
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.
|
||||
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 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. This is
|
||||
equivalent to the client specifying the --exclude-from option with a
|
||||
equivalent file. See also the note about security for the exclude
|
||||
option above.
|
||||
on the daemon that contains exclude patterns, one per line.
|
||||
This is only superficially equivalent
|
||||
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
|
||||
equivalent to the client specifying these patterns with the --include
|
||||
option. 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 section of exclude patterns in the rsync man page for information
|
||||
on the syntax of this option.
|
||||
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
|
||||
equivalent to the client specifying the --include-from option with a
|
||||
equivalent file.
|
||||
on the daemon that contains include patterns, one per line. This is
|
||||
only superficially equivalent to the client specifying the
|
||||
bf(--include-from) option with a equivalent file.
|
||||
See the "exclude" option above.
|
||||
|
||||
dit(bf(auth users)) The "auth users" option specifies a comma
|
||||
and 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. 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
|
||||
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
|
||||
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 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 "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
|
||||
PROGRAM" section in 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 daemon.
|
||||
|
||||
dit(bf(secrets file)) The "secrets file" option specifies the name of
|
||||
a file that contains the username:password pairs used for
|
||||
authenticating this module. This file is only consulted if the "auth
|
||||
@@ -216,11 +309,12 @@ 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.
|
||||
|
||||
There is no default for the "secrets file" option, you must choose a name
|
||||
(such as tt(/etc/rsyncd.secrets)).
|
||||
(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
|
||||
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
|
||||
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
|
||||
false, the check is not performed. The default is true. This option
|
||||
was added to accommodate rsync running on the Windows operating system.
|
||||
@@ -232,25 +326,31 @@ connection is rejected.
|
||||
|
||||
Each pattern can be in one of five forms:
|
||||
|
||||
itemize(
|
||||
it() a dotted decimal IP address. In this case the incoming machines
|
||||
IP address must match exactly.
|
||||
|
||||
it() a address/mask in the form a.b.c.d/n were n is the number of
|
||||
one bits in in the netmask. All IP addresses which match the masked
|
||||
IP address will be allowed in.
|
||||
|
||||
it() a address/mask in the form a.b.c.d/e.f.g.h where e.f.g.h is a
|
||||
netmask in dotted decimal notation. All IP addresses which match the masked
|
||||
IP address will be allowed in.
|
||||
|
||||
quote(itemize(
|
||||
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(
|
||||
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"
|
||||
@@ -270,52 +370,95 @@ 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 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
|
||||
behavior.
|
||||
|
||||
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
|
||||
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. "%-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(itemize(
|
||||
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 IO timeout for this module. Using this option you
|
||||
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.
|
||||
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, you can use "dont compress = *" (see below)
|
||||
instead of "refuse options = compress" to avoid returning an error to a
|
||||
client that requests compression.
|
||||
@@ -326,25 +469,54 @@ during transfer. 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.
|
||||
|
||||
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)
|
||||
The default setting is tt(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
|
||||
|
||||
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(itemize(
|
||||
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_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) rsync's exit value. This will be 0 for a
|
||||
successful run, a positive value for an error that rsync returned
|
||||
(e.g. 23=partial xfer), or a -1 if rsync failed to exit properly.
|
||||
it() bf(RSYNC_RAW_STATUS): (post-xfer only) the raw exit value from 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
|
||||
encryption of the data that is transferred over the link. Only
|
||||
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.
|
||||
|
||||
@@ -362,17 +534,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()
|
||||
pid file = /etc/rsyncd.pid
|
||||
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)
|
||||
|
||||
@@ -397,12 +569,14 @@ 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()
|
||||
|
||||
/etc/rsyncd.conf
|
||||
/etc/rsyncd.conf or rsyncd.conf
|
||||
|
||||
manpageseealso()
|
||||
|
||||
@@ -412,15 +586,12 @@ 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.0 of rsync
|
||||
|
||||
This man page is current for version 2.6.7 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
@@ -441,12 +612,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
|
||||
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)
|
||||
|
||||
26
rsyncsh.txt
Normal file
26
rsyncsh.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
rsyncsh
|
||||
Copyright (C) 2001 by Martin Pool
|
||||
|
||||
This is a quick hack to build an interactive shell around rsync, the
|
||||
same way we have the ftp, lftp and ncftp programs for the FTP
|
||||
protocol. The key application for this is connecting to a public
|
||||
rsync server, such as rsync.kernel.org, change down through and list
|
||||
directories, and finally pull down the file you want.
|
||||
|
||||
rsync is somewhat ill-at-ease as an interactive operation, since every
|
||||
network connection is used to carry out exactly one operation. rsync
|
||||
kind of "forks across the network" passing the options and filenames
|
||||
to operate upon, and the connection is closed when the transfer is
|
||||
complete. (This might be fixed in the future, either by adapting the
|
||||
current protocol to allow chained operations over a single socket, or
|
||||
by writing a new protocol that better supports interactive use.)
|
||||
|
||||
So, rsyncsh runs a new rsync command and opens a new socket for every
|
||||
(network-based) command you type.
|
||||
|
||||
This has two consequences. Firstly, there is more command latency
|
||||
than is really desirable. More seriously, if the connection cannot be
|
||||
done automatically, because for example it uses SSH with a password,
|
||||
then you will need to enter the password every time. We might even
|
||||
fix this in the future, though, by having a way to automatically feed
|
||||
the password to SSH if it's entered once.
|
||||
289
runtests.sh
Executable file
289
runtests.sh
Executable file
@@ -0,0 +1,289 @@
|
||||
#! /bin/sh
|
||||
|
||||
# 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 version
|
||||
# 2 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
# rsync top-level test script -- this invokes all the other more
|
||||
# detailed tests in order. This script can either be called by `make
|
||||
# check' or `make installcheck'. `check' runs against the copies of
|
||||
# the program and other files in the build directory, and
|
||||
# `installcheck' against the installed copy of the program.
|
||||
|
||||
# In either case we need to also be able to find the source directory,
|
||||
# since we read test scripts and possibly other information from
|
||||
# there.
|
||||
|
||||
# Whenever possible, informational messages are written to stdout and
|
||||
# error messages to stderr. They're separated out by the build farm
|
||||
# display scripts.
|
||||
|
||||
# According to the GNU autoconf manual, the only valid place to set up
|
||||
# directory locations is through Make, since users are allowed to (try
|
||||
# to) change their mind on the Make command line. So, Make has to
|
||||
# pass in all the values we need.
|
||||
|
||||
# For other configured settings we read ./config.sh, which tells us
|
||||
# about shell commands on this machine and similar things.
|
||||
|
||||
# rsync_bin gives the location of the rsync binary. This is either
|
||||
# builddir/rsync if we're testing an uninstalled copy, or
|
||||
# install_prefix/bin/rsync if we're testing an installed copy. On the
|
||||
# build farm rsync will be installed, but into a scratch /usr.
|
||||
|
||||
# srcdir gives the location of the source tree, which lets us find the
|
||||
# build scripts. At the moment we assume we are invoked from the
|
||||
# source directory.
|
||||
|
||||
# This script must be invoked from the build directory.
|
||||
|
||||
# A scratch directory, 'testtmp', is created in the build directory to
|
||||
# hold working files.
|
||||
|
||||
# This script also uses the $loglevel environment variable. 1 is the
|
||||
# default value, and 10 the most verbose. You can set this from the
|
||||
# Make command line. It's also set by the build farm to give more
|
||||
# detail for failing builds.
|
||||
|
||||
|
||||
# NOTES FOR TEST CASES:
|
||||
|
||||
# Each test case runs in its own shell.
|
||||
|
||||
# Exit codes from tests:
|
||||
|
||||
# 1 tests failed
|
||||
# 2 error in starting tests
|
||||
# 77 this test skipped (random value unlikely to happen by chance, same as
|
||||
# automake)
|
||||
|
||||
# HOWEVER, the overall exit code to the farm is different: we return
|
||||
# the *number of tests that failed*, so that it will show up nicely in
|
||||
# the overall summary.
|
||||
|
||||
# rsync.fns contains some general setup functions and definitions.
|
||||
|
||||
|
||||
# NOTES ON PORTABILITY:
|
||||
|
||||
# Both this script and the Makefile have to be pretty conservative
|
||||
# about which Unix features they use.
|
||||
|
||||
# We cannot count on Make exporting variables to commands, unless
|
||||
# they're explicitly given on the command line.
|
||||
|
||||
# Also, we can't count on 'cp -a' or 'mkdir -p', although they're
|
||||
# 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
|
||||
# they're in POSIX 1003.2, and since the build farm relies on them
|
||||
# they're probably working on most machines we really care about.
|
||||
|
||||
# You cannot use "function foo {" syntax, but must instead say "foo()
|
||||
# {", or it breaks on FreeBSD.
|
||||
|
||||
# BSD machines tend not to have "head" or "seq".
|
||||
|
||||
# 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:
|
||||
|
||||
# We need a good protection against tests that hang indefinitely.
|
||||
# Perhaps some combination of starting them in the background, wait,
|
||||
# and kill?
|
||||
|
||||
# Perhaps we need a common way to cleanup tests. At the moment just
|
||||
# clobbering the directory when we're done should be enough.
|
||||
|
||||
# If any of the targets fail, then (GNU?) Make returns 2, instead of
|
||||
# the return code from the failing command. This is fine, but it
|
||||
# means that the build farm just shows "2" for failed tests, not the
|
||||
# number of tests that actually failed. For more details we might
|
||||
# need to grovel through the log files to find a line saying how many
|
||||
# failed.
|
||||
|
||||
|
||||
set -e
|
||||
|
||||
. "./shconfig"
|
||||
|
||||
RUNSHFLAGS='-e'
|
||||
export RUNSHFLAGS
|
||||
|
||||
# for Solaris
|
||||
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin/:$PATH"
|
||||
|
||||
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
|
||||
|
||||
echo "============================================================"
|
||||
echo "$0 running in `pwd`"
|
||||
echo " rsync_bin=$rsync_bin"
|
||||
echo " srcdir=$srcdir"
|
||||
|
||||
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 [ "x$preserve_scratch" = xyes ]; then
|
||||
echo " preserve_scratch=yes"
|
||||
else
|
||||
echo " preserve_scratch=no"
|
||||
fi
|
||||
|
||||
# We'll use setfacl if it's around and it supports the -k option.
|
||||
if setfacl --help 2>/dev/null | grep ' -k,' >/dev/null; then
|
||||
setfacl=setfacl
|
||||
else
|
||||
setfacl=true
|
||||
fi
|
||||
|
||||
if [ ! -f "$rsync_bin" ]; then
|
||||
echo "rsync_bin $rsync_bin is not a file" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -d "$srcdir" ]; then
|
||||
echo "srcdir $srcdir is not a directory" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
RSYNC="$rsync_bin"
|
||||
#RSYNC="valgrind --tool=addrcheck $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
|
||||
echo " scratchbase=$scratchbase"
|
||||
|
||||
suitedir="$srcdir/testsuite"
|
||||
|
||||
export scratchdir suitedir
|
||||
|
||||
prep_scratch() {
|
||||
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
|
||||
mkdir "$scratchdir"
|
||||
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
|
||||
$setfacl -k "$scratchdir"
|
||||
chmod g-s "$scratchdir"
|
||||
return 0
|
||||
}
|
||||
|
||||
maybe_discard_scratch() {
|
||||
[ x"$preserve_scratch" != xyes ] && [ -d "$scratchdir" ] && rm -rf "$scratchdir"
|
||||
return 0
|
||||
}
|
||||
|
||||
if [ "x$whichtests" = x ]; then
|
||||
whichtests="*.test"
|
||||
fi
|
||||
|
||||
for testscript in $suitedir/$whichtests
|
||||
do
|
||||
testbase=`echo $testscript | sed -e 's!.*/!!' -e 's/.test\$//'`
|
||||
scratchdir="$scratchbase.$testbase"
|
||||
|
||||
prep_scratch
|
||||
|
||||
set +e
|
||||
sh $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
|
||||
result=$?
|
||||
set -e
|
||||
|
||||
if [ "x$always_log" = xyes -o \( $result != 0 -a $result != 77 -a $result != 78 \) ]
|
||||
then
|
||||
echo "----- $testbase log follows"
|
||||
cat "$scratchdir/test.log"
|
||||
echo "----- $testbase log ends"
|
||||
if [ -f "$scratchdir/rsyncd.log" ]; then
|
||||
echo "----- $testbase rsyncd.log follows"
|
||||
cat "$scratchdir/rsyncd.log"
|
||||
echo "----- $testbase rsyncd.log ends"
|
||||
fi
|
||||
fi
|
||||
|
||||
case $result in
|
||||
0)
|
||||
echo "PASS $testbase"
|
||||
passed=`expr $passed + 1`
|
||||
maybe_discard_scratch
|
||||
;;
|
||||
77)
|
||||
# backticks will fill the whole file onto one line, which is a feature
|
||||
whyskipped=`cat "$scratchdir/whyskipped"`
|
||||
echo "SKIP $testbase ($whyskipped)"
|
||||
skipped=`expr $skipped + 1`
|
||||
maybe_discard_scratch
|
||||
;;
|
||||
78)
|
||||
# It failed, but we expected that. don't dump out error logs,
|
||||
# because most users won't want to see them. But do leave
|
||||
# the working directory around.
|
||||
echo "XFAIL $testbase"
|
||||
failed=`expr $failed + 1`
|
||||
;;
|
||||
*)
|
||||
echo "FAIL $testbase"
|
||||
failed=`expr $failed + 1`
|
||||
if [ "x$nopersist" = xyes ]; then
|
||||
exit 1
|
||||
fi
|
||||
esac
|
||||
done
|
||||
|
||||
echo '------------------------------------------------------------'
|
||||
echo "----- overall results:"
|
||||
echo " $passed passed"
|
||||
[ "$failed" -gt 0 ] && echo " $failed failed"
|
||||
[ "$skipped" -gt 0 ] && echo " $skipped skipped"
|
||||
[ "$missing" -gt 0 ] && echo " $missing missing"
|
||||
echo '------------------------------------------------------------'
|
||||
|
||||
# OK, so expr exits with 0 if the result is neither null nor zero; and
|
||||
# 1 if the expression is null or zero. This is the opposite of what
|
||||
# we want, and if we just call expr then this script will always fail,
|
||||
# because -e is set.
|
||||
|
||||
result=`expr $failed + $missing || true`
|
||||
echo "overall result is $result"
|
||||
exit $result
|
||||
421
sender.c
421
sender.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
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.
|
||||
@@ -20,58 +20,94 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int remote_version;
|
||||
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 log_before_transfer;
|
||||
extern int log_format_has_i;
|
||||
extern int daemon_log_format_has_i;
|
||||
extern int csum_length;
|
||||
extern int append_mode;
|
||||
extern int io_error;
|
||||
extern int allowed_lull;
|
||||
extern int protocol_version;
|
||||
extern int remove_sent_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 *the_file_list;
|
||||
extern char *log_format;
|
||||
|
||||
|
||||
/*
|
||||
receive the checksums for a buffer
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* The sender gets checksums from the generator, calculates deltas,
|
||||
* and transmits them to the receiver. The sender process runs on the
|
||||
* machine holding the source files.
|
||||
**/
|
||||
|
||||
/**
|
||||
* Receive the checksums for a buffer
|
||||
**/
|
||||
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 = (struct sum_struct *)malloc(sizeof(*s));
|
||||
if (!s) out_of_memory("receive_sums");
|
||||
if (!(s = new(struct sum_struct)))
|
||||
out_of_memory("receive_sums");
|
||||
|
||||
read_sum_head(f, s);
|
||||
|
||||
s->count = read_int(f);
|
||||
s->n = read_int(f);
|
||||
s->remainder = read_int(f);
|
||||
s->sums = NULL;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"count=%d n=%d rem=%d\n",
|
||||
s->count,s->n,s->remainder);
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "count=%.0f n=%ld rem=%ld\n",
|
||||
(double)s->count, (long)s->blength, (long)s->remainder);
|
||||
}
|
||||
|
||||
if (s->count == 0)
|
||||
if (append_mode) {
|
||||
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 = (struct sum_buf *)malloc(sizeof(s->sums[0])*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<s->count;i++) {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
s->sums[i].sum1 = read_int(f);
|
||||
read_buf(f,s->sums[i].sum2,csum_length);
|
||||
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 == s->count-1 && s->remainder != 0) {
|
||||
if (i == s->count-1 && s->remainder != 0)
|
||||
s->sums[i].len = s->remainder;
|
||||
} else {
|
||||
s->sums[i].len = s->n;
|
||||
}
|
||||
else
|
||||
s->sums[i].len = s->blength;
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] len=%d offset=%d sum1=%08x\n",
|
||||
i,s->sums[i].len,(int)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;
|
||||
@@ -79,152 +115,269 @@ static struct sum_struct *receive_sums(int f)
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
{
|
||||
int fd;
|
||||
struct sum_struct *s;
|
||||
struct map_struct *buf;
|
||||
STRUCT_STAT st;
|
||||
char fname[MAXPATHLEN];
|
||||
int i;
|
||||
void successful_send(int ndx)
|
||||
{
|
||||
char fname[MAXPATHLEN];
|
||||
struct file_struct *file;
|
||||
int phase = 0;
|
||||
extern struct stats stats;
|
||||
unsigned int offset;
|
||||
|
||||
if (ndx < 0 || ndx >= the_file_list->count)
|
||||
return;
|
||||
|
||||
file = the_file_list->files[ndx];
|
||||
/* The generator might tell us about symlinks we didn't send. */
|
||||
if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
|
||||
return;
|
||||
if (file->dir.root) {
|
||||
offset = stringjoin(fname, sizeof fname,
|
||||
file->dir.root, "/", NULL);
|
||||
} else
|
||||
offset = 0;
|
||||
f_name(file, fname + offset);
|
||||
if (remove_sent_files && do_unlink(fname) == 0 && verbose > 1)
|
||||
rprintf(FINFO, "sender removed %s\n", fname + offset);
|
||||
}
|
||||
|
||||
static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
|
||||
uchar fnamecmp_type, char *buf, int len)
|
||||
{
|
||||
write_int(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);
|
||||
}
|
||||
|
||||
/* This is also used by receive.c with f_out = -1. */
|
||||
int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
|
||||
char *buf, int *len_ptr)
|
||||
{
|
||||
int len;
|
||||
uchar fnamecmp_type = FNAMECMP_FNAME;
|
||||
int iflags = protocol_version >= 29 ? read_shortint(f_in)
|
||||
: ITEM_TRANSFER | ITEM_MISSING_DATA;
|
||||
|
||||
/* Handle the new keep-alive (no-op) packet. */
|
||||
if (ndx == the_file_list->count && iflags == ITEM_IS_NEW)
|
||||
;
|
||||
else if (ndx < 0 || ndx >= the_file_list->count) {
|
||||
rprintf(FERROR, "Invalid file index: %d (count=%d) [%s]\n",
|
||||
ndx, the_file_list->count, who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
} else if (iflags == ITEM_IS_NEW) {
|
||||
rprintf(FERROR, "Invalid itemized flag word: %x [%s]\n",
|
||||
iflags, who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!S_ISREG(the_file_list->files[ndx]->mode)) {
|
||||
rprintf(FERROR,
|
||||
"received request to transfer non-regular file: %d [%s]\n",
|
||||
ndx, who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
} else if (f_out >= 0) {
|
||||
write_ndx_and_attrs(f_out, ndx, iflags,
|
||||
fnamecmp_type, buf, len);
|
||||
}
|
||||
|
||||
return iflags;
|
||||
}
|
||||
|
||||
void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
{
|
||||
int fd = -1;
|
||||
struct sum_struct *s;
|
||||
struct map_struct *mbuf = NULL;
|
||||
STRUCT_STAT st;
|
||||
char *fname2, fname[MAXPATHLEN];
|
||||
char xname[MAXPATHLEN];
|
||||
uchar fnamecmp_type;
|
||||
int iflags, xlen;
|
||||
struct file_struct *file;
|
||||
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
|
||||
struct stats initial_stats;
|
||||
int save_make_backups = make_backups;
|
||||
int itemizing = am_daemon ? daemon_log_format_has_i
|
||||
: !am_server && log_format_has_i;
|
||||
int f_xfer = write_batch < 0 ? batch_fd : f_out;
|
||||
int i, j;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files starting\n");
|
||||
|
||||
setup_readbuffer(f_in);
|
||||
rprintf(FINFO, "send_files starting\n");
|
||||
|
||||
while (1) {
|
||||
int offset=0;
|
||||
unsigned int offset;
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out,-1);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files phase=%d\n",phase);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
if (++phase > max_phase)
|
||||
break;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files phase=%d\n", phase);
|
||||
write_int(f_out, -1);
|
||||
/* For inplace: redo phase turns off the backup
|
||||
* flag so that we do a regular inplace send. */
|
||||
make_backups = 0;
|
||||
append_mode = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
|
||||
i, flist->count);
|
||||
iflags = read_item_attrs(f_in, f_out, i, &fnamecmp_type,
|
||||
xname, &xlen);
|
||||
if (iflags == ITEM_IS_NEW) /* no-op packet */
|
||||
continue;
|
||||
|
||||
file = flist->files[i];
|
||||
if (file->dir.root) {
|
||||
/* N.B. We're sure that this fits, so offset is OK. */
|
||||
offset = strlcpy(fname, file->dir.root, sizeof fname);
|
||||
if (!offset || fname[offset-1] != '/')
|
||||
fname[offset++] = '/';
|
||||
} else
|
||||
offset = 0;
|
||||
fname2 = f_name(file, fname + offset);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
|
||||
|
||||
if (!(iflags & ITEM_TRANSFER)) {
|
||||
maybe_log_item(file, iflags, itemizing, xname);
|
||||
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];
|
||||
updating_basis_file = inplace && (protocol_version >= 29
|
||||
? fnamecmp_type == FNAMECMP_FNAME : !make_backups);
|
||||
|
||||
stats.current_file_index = i;
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
fname[0] = 0;
|
||||
if (file->basedir) {
|
||||
strlcpy(fname,file->basedir,MAXPATHLEN);
|
||||
if (strlen(fname) == MAXPATHLEN-1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR, "send_files failed on long-named directory %s\n",
|
||||
fname);
|
||||
return;
|
||||
}
|
||||
strlcat(fname,"/",MAXPATHLEN);
|
||||
offset = strlen(file->basedir)+1;
|
||||
}
|
||||
strlcat(fname,f_name(file),MAXPATHLEN);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname+offset);
|
||||
}
|
||||
write_int(f_out,i);
|
||||
if (!do_xfers) { /* log the transfer */
|
||||
if (!am_server && log_format)
|
||||
log_item(file, &stats, iflags, NULL);
|
||||
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
|
||||
xname, xlen);
|
||||
continue;
|
||||
}
|
||||
|
||||
initial_stats = stats;
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (!s) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"receive_sums failed\n");
|
||||
if (!(s = receive_sums(f_in))) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "receive_sums failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"send_files failed to open %s: %s\n",
|
||||
fname,strerror(errno));
|
||||
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;
|
||||
rsyserr(FERROR, errno,
|
||||
"send_files failed to open %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
free_sums(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* map the local file */
|
||||
if (do_fstat(fd,&st) != 0) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"fstat failed : %s\n",strerror(errno));
|
||||
if (do_fstat(fd, &st) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "fstat failed");
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd,st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files mapped %s of size %d\n",
|
||||
fname,(int)st.st_size);
|
||||
|
||||
write_int(f_out,i);
|
||||
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"calling match_sums %s\n",fname);
|
||||
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname+offset);
|
||||
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 of size %.0f\n",
|
||||
fname, (double)st.st_size);
|
||||
}
|
||||
|
||||
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
|
||||
xname, xlen);
|
||||
write_sum_head(f_xfer, s);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "calling match_sums %s\n", fname);
|
||||
|
||||
if (log_before_transfer)
|
||||
log_item(file, &initial_stats, iflags, NULL);
|
||||
else if (!am_server && verbose && do_progress)
|
||||
rprintf(FINFO, "%s\n", fname2);
|
||||
|
||||
set_compression(fname);
|
||||
|
||||
match_sums(f_out,s,buf,st.st_size);
|
||||
|
||||
log_send(file, &initial_stats);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
match_sums(f_xfer, s, mbuf, st.st_size);
|
||||
if (do_progress)
|
||||
end_progress(st.st_size);
|
||||
|
||||
if (!log_before_transfer)
|
||||
log_item(file, &initial_stats, iflags, NULL);
|
||||
|
||||
if (mbuf) {
|
||||
j = unmap_file(mbuf);
|
||||
if (j) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, j,
|
||||
"read errors mapping %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
|
||||
free_sums(s);
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sender finished %s\n",fname);
|
||||
rprintf(FINFO, "sender finished %s\n", fname);
|
||||
|
||||
/* Flag that we actually sent this entry. */
|
||||
file->flags |= FLAG_SENT;
|
||||
}
|
||||
make_backups = save_make_backups;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send files finished\n");
|
||||
rprintf(FINFO, "send files finished\n");
|
||||
|
||||
match_report();
|
||||
|
||||
write_int(f_out,-1);
|
||||
write_int(f_out, -1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user