mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 15:25:30 -04:00
Compare commits
449 Commits
v3.2.0pre3
...
v3.2.4pre1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e44bbd313 | ||
|
|
4adfdaaf12 | ||
|
|
4a7ba3cfaf | ||
|
|
ffbca80ca2 | ||
|
|
c11467af36 | ||
|
|
13cfe6406f | ||
|
|
8e77ece0ee | ||
|
|
ffec7fe109 | ||
|
|
e07f8fb863 | ||
|
|
8cf9dbb742 | ||
|
|
3008e7c226 | ||
|
|
a2b630c0bb | ||
|
|
5b1baa7a2e | ||
|
|
7f8cf771b7 | ||
|
|
b00e99c529 | ||
|
|
a76e32f949 | ||
|
|
512acd125e | ||
|
|
72adf49ba8 | ||
|
|
73ceea6ad2 | ||
|
|
39c3ae0ea3 | ||
|
|
ed19ea05fe | ||
|
|
dc1b9febf1 | ||
|
|
d9015da151 | ||
|
|
1f0e62f139 | ||
|
|
7d830ff52f | ||
|
|
8f383e8987 | ||
|
|
ca538965d8 | ||
|
|
e4669b81ae | ||
|
|
1b9308b727 | ||
|
|
80c64dc3b3 | ||
|
|
be3d6c0fbb | ||
|
|
7956070f2b | ||
|
|
d0f34b5a76 | ||
|
|
84498104bf | ||
|
|
378a0a634f | ||
|
|
ac08fa74f3 | ||
|
|
d5d4ae51ee | ||
|
|
0f87eafa2f | ||
|
|
3af00277ee | ||
|
|
b774dbc1c0 | ||
|
|
296352ecb0 | ||
|
|
11a9b62322 | ||
|
|
452ef78517 | ||
|
|
0d1b48893a | ||
|
|
ec8a05f653 | ||
|
|
78b5bc6629 | ||
|
|
f41cdc75a1 | ||
|
|
c8e7c4b352 | ||
|
|
bff084c10a | ||
|
|
16c8b05f11 | ||
|
|
15dd2058fd | ||
|
|
c27180c044 | ||
|
|
050fdd4126 | ||
|
|
ae1f002999 | ||
|
|
3911c23866 | ||
|
|
3814dbb0f4 | ||
|
|
82f023d7e3 | ||
|
|
ec57c57baf | ||
|
|
354fa581c1 | ||
|
|
d881814a35 | ||
|
|
ad048d78ac | ||
|
|
109dbc0b75 | ||
|
|
745ecf2825 | ||
|
|
265785b7b9 | ||
|
|
97f4d48a07 | ||
|
|
3cc7f0ba43 | ||
|
|
dde4695136 | ||
|
|
3337930292 | ||
|
|
44cc148907 | ||
|
|
b2e16facd4 | ||
|
|
4fd662fea9 | ||
|
|
12c058698b | ||
|
|
33095916ec | ||
|
|
5818cf8596 | ||
|
|
1fa0bd1e87 | ||
|
|
592c6bc3e5 | ||
|
|
efc81c93a9 | ||
|
|
35d4f6737a | ||
|
|
291a042b3e | ||
|
|
9dad3721a9 | ||
|
|
dbb1c2d10c | ||
|
|
e8e34ed6fb | ||
|
|
c529782a8d | ||
|
|
2dfd48492e | ||
|
|
a6bdf313f2 | ||
|
|
915685e01b | ||
|
|
05540220a9 | ||
|
|
75158e1086 | ||
|
|
676537cf29 | ||
|
|
d857fd42ac | ||
|
|
5856b71eb7 | ||
|
|
57adb2973a | ||
|
|
ead44adcd3 | ||
|
|
d3085f7add | ||
|
|
1da64c37e8 | ||
|
|
ef36b097bf | ||
|
|
ec3833c96e | ||
|
|
25dfc2c41d | ||
|
|
d5b7889d40 | ||
|
|
74561d70b5 | ||
|
|
83f7372369 | ||
|
|
8c3de35b0b | ||
|
|
ec1d5d564c | ||
|
|
26befd9c6c | ||
|
|
a28c4558c5 | ||
|
|
ed6a0dc7c2 | ||
|
|
9dd62525f3 | ||
|
|
ada588a7a8 | ||
|
|
286e164ed6 | ||
|
|
85b8dc8aba | ||
|
|
0748800118 | ||
|
|
b7fab6f285 | ||
|
|
9fc7deab0d | ||
|
|
b115bc8a5d | ||
|
|
cd018c7a4c | ||
|
|
9fce0eb5ab | ||
|
|
33e94849b1 | ||
|
|
8f1511184a | ||
|
|
acca9d43d3 | ||
|
|
58f464f4da | ||
|
|
7eb59a9152 | ||
|
|
740ed11aa8 | ||
|
|
d2a97a7ab4 | ||
|
|
15bc7ded39 | ||
|
|
f0810068a6 | ||
|
|
7aa2f36317 | ||
|
|
9cd85b8496 | ||
|
|
f8dcd7d452 | ||
|
|
69530b406e | ||
|
|
122b0fdc4f | ||
|
|
b990d97d35 | ||
|
|
fd6839b746 | ||
|
|
a79d9b22b1 | ||
|
|
2613c9d98a | ||
|
|
27aff880a9 | ||
|
|
7b53e67d64 | ||
|
|
da956469a1 | ||
|
|
9c59632d8b | ||
|
|
d1f458d383 | ||
|
|
a35a900ac0 | ||
|
|
f4c3969b63 | ||
|
|
ee75e51f2f | ||
|
|
9f9240b661 | ||
|
|
48885309c7 | ||
|
|
203b3d0143 | ||
|
|
25526eb3fe | ||
|
|
c3f7414c45 | ||
|
|
4c4fce5107 | ||
|
|
6816b31378 | ||
|
|
e94bad1c15 | ||
|
|
617d726a3d | ||
|
|
020eda887f | ||
|
|
b5f8021a12 | ||
|
|
7b6947576a | ||
|
|
9375a8c4c2 | ||
|
|
7f5c4084c7 | ||
|
|
6c89f00d1b | ||
|
|
dee0993286 | ||
|
|
47351c2b16 | ||
|
|
16b7670614 | ||
|
|
72b2a81f90 | ||
|
|
d73c26d2b7 | ||
|
|
e83bbeb673 | ||
|
|
b6aa9c5cfe | ||
|
|
dfe3b77cb5 | ||
|
|
cbe3b2bfe5 | ||
|
|
b1ae7fc941 | ||
|
|
8695bcc2b1 | ||
|
|
4ae6f708b1 | ||
|
|
14c4656fb8 | ||
|
|
13cec31f7f | ||
|
|
5db7e4b1ee | ||
|
|
54693fa992 | ||
|
|
3f83bcb4af | ||
|
|
e1e546d67e | ||
|
|
3714084f48 | ||
|
|
eb2c3a5e18 | ||
|
|
f6967eca58 | ||
|
|
8455bf66c2 | ||
|
|
00e59e01e3 | ||
|
|
91eaffe13f | ||
|
|
2066024981 | ||
|
|
d274b2096f | ||
|
|
0327a2526b | ||
|
|
f43412f1d5 | ||
|
|
b9010ec617 | ||
|
|
21ecc833ea | ||
|
|
f9bb8f76ee | ||
|
|
a5a9f268fe | ||
|
|
0a255771f4 | ||
|
|
e07d79ad50 | ||
|
|
2f74eb7584 | ||
|
|
39741c7d50 | ||
|
|
3f016888fd | ||
|
|
e5a012c959 | ||
|
|
c3cf174e5e | ||
|
|
a0a7c9f2e3 | ||
|
|
a8f61ba937 | ||
|
|
842d6edfdc | ||
|
|
92a8855ff3 | ||
|
|
def96fd7c4 | ||
|
|
f624a73bbc | ||
|
|
93a373f6ba | ||
|
|
01742c07e6 | ||
|
|
e00662f263 | ||
|
|
491ddb08a4 | ||
|
|
918cb39fed | ||
|
|
1369fe43e1 | ||
|
|
150f3416ac | ||
|
|
d8941be8cb | ||
|
|
592059c8fd | ||
|
|
37f4a23f60 | ||
|
|
27be94c889 | ||
|
|
974f49e22a | ||
|
|
9f7506ac1b | ||
|
|
8779d6c8bb | ||
|
|
96be713fd2 | ||
|
|
13d8fc9542 | ||
|
|
f74473b151 | ||
|
|
5eda68f11b | ||
|
|
f635207347 | ||
|
|
64f7e893f3 | ||
|
|
31556ec7a8 | ||
|
|
9ad3f4385f | ||
|
|
e9899dbdb4 | ||
|
|
18cffa8aa9 | ||
|
|
7e07a32504 | ||
|
|
be11a496bb | ||
|
|
c6f5f0b505 | ||
|
|
f553da1730 | ||
|
|
40753bcbf7 | ||
|
|
33df361d52 | ||
|
|
f4db970718 | ||
|
|
ab3928898f | ||
|
|
13f274fd02 | ||
|
|
b51fe50e7f | ||
|
|
1829a2ee0d | ||
|
|
65370a0f56 | ||
|
|
23213099e9 | ||
|
|
25e08110d5 | ||
|
|
95f683039d | ||
|
|
129d7195ff | ||
|
|
044339d6b4 | ||
|
|
4c4fc7462a | ||
|
|
22cb57ee20 | ||
|
|
4c0be4da13 | ||
|
|
4549855126 | ||
|
|
284c28c773 | ||
|
|
d2406ae372 | ||
|
|
1e9c34972a | ||
|
|
116bd19324 | ||
|
|
883de22c29 | ||
|
|
18f500a7a4 | ||
|
|
d14b0ca4db | ||
|
|
4156e7d464 | ||
|
|
9e48da65c1 | ||
|
|
2cdf9416ee | ||
|
|
cd0c83e485 | ||
|
|
0e814e956c | ||
|
|
f47e5a7732 | ||
|
|
91fff802b9 | ||
|
|
3c8ac20d63 | ||
|
|
38a521defd | ||
|
|
2f13049600 | ||
|
|
af531cf787 | ||
|
|
d495e343c0 | ||
|
|
de7e4d00ab | ||
|
|
374cc1be74 | ||
|
|
8b25488fe9 | ||
|
|
4f5742baa0 | ||
|
|
2b416de4ca | ||
|
|
1f41b7dca1 | ||
|
|
486e7852db | ||
|
|
a68a92793c | ||
|
|
a84e8aced7 | ||
|
|
3bc2d9aeaa | ||
|
|
6214c26bd3 | ||
|
|
da7a350667 | ||
|
|
66ca4fc97b | ||
|
|
7d63f8b249 | ||
|
|
bb1365dd77 | ||
|
|
bcc273d460 | ||
|
|
a6da3c67f8 | ||
|
|
ab110fc8fb | ||
|
|
7265d96116 | ||
|
|
560b63b051 | ||
|
|
0eb82a7c90 | ||
|
|
f92a5182fc | ||
|
|
fb6fabc116 | ||
|
|
c3269275a8 | ||
|
|
7e47855d47 | ||
|
|
d2d6ad481a | ||
|
|
5dcb49c7dd | ||
|
|
19d8550cf4 | ||
|
|
7610f76aea | ||
|
|
59cb358fda | ||
|
|
bb16db1747 | ||
|
|
d6f0342a34 | ||
|
|
6f6e5b51cc | ||
|
|
28de25a664 | ||
|
|
052b34dceb | ||
|
|
748b5c5d53 | ||
|
|
e1e4ffe057 | ||
|
|
1b53b2ff4b | ||
|
|
da45cecfc8 | ||
|
|
87b5d233e9 | ||
|
|
194cee671d | ||
|
|
b7c5520add | ||
|
|
2bee307592 | ||
|
|
85e62c330d | ||
|
|
0add026a5d | ||
|
|
f4184849c4 | ||
|
|
565cde84a7 | ||
|
|
f0e670b4c6 | ||
|
|
ef8951779d | ||
|
|
e285f8f9d2 | ||
|
|
cb383673f6 | ||
|
|
0768d620a5 | ||
|
|
d640d78f91 | ||
|
|
544b3d8b3b | ||
|
|
ce12142c45 | ||
|
|
c83a81ca38 | ||
|
|
d88db22ae8 | ||
|
|
a1cc50ba96 | ||
|
|
feb2fff894 | ||
|
|
7d30490ef4 | ||
|
|
317beebef8 | ||
|
|
7a413c9722 | ||
|
|
5be7363297 | ||
|
|
646784f0e5 | ||
|
|
18ed3f0279 | ||
|
|
00dd50a00c | ||
|
|
7039d14616 | ||
|
|
ec3c9f2f5a | ||
|
|
3b4f5fb891 | ||
|
|
76064b1bf2 | ||
|
|
8df766917e | ||
|
|
299430a6c1 | ||
|
|
dcbe005a6a | ||
|
|
af57b55bdb | ||
|
|
967e6426b9 | ||
|
|
61971acbe1 | ||
|
|
5bd0b6cf71 | ||
|
|
0eec25f75b | ||
|
|
3a6f06003c | ||
|
|
f805d1a7f7 | ||
|
|
ab29ee9c44 | ||
|
|
d07c2992d1 | ||
|
|
b1a8b09c21 | ||
|
|
fe2ef556d9 | ||
|
|
11eb67eec9 | ||
|
|
39a083b16b | ||
|
|
202b7b18af | ||
|
|
20934382e3 | ||
|
|
1bdf68b905 | ||
|
|
89827e49bc | ||
|
|
f157ff3b3a | ||
|
|
d15cfef935 | ||
|
|
28f9c960d5 | ||
|
|
323c42d51e | ||
|
|
d1fdf9ff8d | ||
|
|
e93f40d8b4 | ||
|
|
4df1b1d4fe | ||
|
|
1af58f6b77 | ||
|
|
a8fc8fc2d2 | ||
|
|
b8b7f1f3d0 | ||
|
|
622a116917 | ||
|
|
b51b0b3236 | ||
|
|
8cb1c99563 | ||
|
|
597a751466 | ||
|
|
5a9e4ae5e7 | ||
|
|
3094552311 | ||
|
|
e4c9ff5873 | ||
|
|
9b13bcf185 | ||
|
|
8f6d6bcb08 | ||
|
|
300fd3055a | ||
|
|
f6df3708c2 | ||
|
|
785cb938ec | ||
|
|
246d117df0 | ||
|
|
3f776f582b | ||
|
|
d8d2d71663 | ||
|
|
6a9adabfbb | ||
|
|
2564f25114 | ||
|
|
7fb08531e0 | ||
|
|
9dba0bb7fb | ||
|
|
87bca719c3 | ||
|
|
f3439944ea | ||
|
|
a7c1690d62 | ||
|
|
662fedd74b | ||
|
|
128139c66a | ||
|
|
2b439c1fc8 | ||
|
|
e16b22751a | ||
|
|
7587e20cf4 | ||
|
|
2e1b46db39 | ||
|
|
f4e6fe54c9 | ||
|
|
f86ceb5539 | ||
|
|
dfa34b4792 | ||
|
|
e9e9fd0cca | ||
|
|
7e95ba8787 | ||
|
|
66fd34ed84 | ||
|
|
f8c6f9f4f3 | ||
|
|
e6cfebb578 | ||
|
|
5d2379d93f | ||
|
|
6884ccbd2f | ||
|
|
bad97961dc | ||
|
|
b0ab07cdac | ||
|
|
68c4583693 | ||
|
|
6b237b0fe9 | ||
|
|
b37a136314 | ||
|
|
c9c8c64506 | ||
|
|
c5d502dc5f | ||
|
|
1629b803cb | ||
|
|
29c7a4558a | ||
|
|
b7dc2ca25c | ||
|
|
f525f2c818 | ||
|
|
1b5819efbd | ||
|
|
a56a0bc7d6 | ||
|
|
bd7bd5ff0c | ||
|
|
f9aece899f | ||
|
|
63508f1518 | ||
|
|
9ac22062af | ||
|
|
73faaab26d | ||
|
|
9467c1f9b9 | ||
|
|
04653dabc8 | ||
|
|
19617f7b4a | ||
|
|
b218de2702 | ||
|
|
d4764934c3 | ||
|
|
c225330aaf | ||
|
|
3c56896d21 | ||
|
|
deb8353d2c | ||
|
|
73053f26bc | ||
|
|
0c13e1b3f8 | ||
|
|
9da38f2f99 | ||
|
|
a93ffb1ae9 | ||
|
|
e08f600378 | ||
|
|
e406845542 | ||
|
|
a93eb4cf38 | ||
|
|
7fd24bef0f | ||
|
|
1a9a184145 | ||
|
|
4965ccf283 | ||
|
|
c6f89cbf9c | ||
|
|
2921779c1f | ||
|
|
cbed522ef4 | ||
|
|
4f539ccf21 | ||
|
|
b5e539fc5a | ||
|
|
88c18ef648 | ||
|
|
7dc9431f60 | ||
|
|
07a3e1f939 | ||
|
|
93223719c9 |
23
.cirrus.yml
Normal file
23
.cirrus.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
freebsd_task:
|
||||
name: FreeBSD
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-2
|
||||
env:
|
||||
PATH: /usr/local/bin:$PATH
|
||||
prep_script:
|
||||
- dd if=/dev/zero of=/tmp/zpool bs=1M count=1024
|
||||
- zpool create -m `pwd`/testtmp zpool /tmp/zpool
|
||||
- pkg install -y bash autotools m4 xxhash zstd liblz4 wget
|
||||
- wget -O git-version.h https://gist.githubusercontent.com/WayneD/c11243fa374fc64d4e42f2855c8e3827/raw/rsync-git-version.h
|
||||
configure_script:
|
||||
- CPPFLAGS=-I/usr/local/include/ LDFLAGS=-L/usr/local/lib/ ./configure --disable-md2man
|
||||
make_script:
|
||||
- make
|
||||
install_script:
|
||||
- make install
|
||||
info_script:
|
||||
- rsync --version
|
||||
test_script:
|
||||
- RSYNC_EXPECT_SKIPPED=acls-default,acls,crtimes,protected-regular make check
|
||||
ssl_file_list_script:
|
||||
- rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
126
.github/workflows/build.yml
vendored
Normal file
126
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore: [ .cirrus.yml ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths-ignore: [ .cirrus.yml ]
|
||||
schedule:
|
||||
- cron: '42 8 * * *'
|
||||
|
||||
jobs:
|
||||
|
||||
ubuntu-build:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: prep
|
||||
run: |
|
||||
sudo apt-get install acl libacl1-dev attr libattr1-dev liblz4-dev libzstd-dev libxxhash-dev python3-cmarkgfm openssl wget
|
||||
wget -O git-version.h https://gist.githubusercontent.com/WayneD/c11243fa374fc64d4e42f2855c8e3827/raw/rsync-git-version.h
|
||||
echo "/usr/local/bin" >>$GITHUB_PATH
|
||||
- name: configure
|
||||
run: ./configure --with-rrsync
|
||||
- name: make
|
||||
run: make
|
||||
- name: install
|
||||
run: sudo make install
|
||||
- name: info
|
||||
run: rsync --version
|
||||
- name: check
|
||||
run: sudo RSYNC_EXPECT_SKIPPED=crtimes make check
|
||||
- name: check30
|
||||
run: sudo RSYNC_EXPECT_SKIPPED=crtimes make check30
|
||||
- name: check29
|
||||
run: sudo RSYNC_EXPECT_SKIPPED=crtimes make check29
|
||||
- name: ssl file list
|
||||
run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
|
||||
- name: save artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ubuntu-bin
|
||||
path: |
|
||||
rsync
|
||||
rsync-ssl
|
||||
rsync.1
|
||||
rsync-ssl.1
|
||||
rsyncd.conf.5
|
||||
rrsync.1
|
||||
rrsync
|
||||
|
||||
macos-build:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: prep
|
||||
run: |
|
||||
brew install automake openssl xxhash zstd lz4 wget
|
||||
sudo pip3 install commonmark
|
||||
wget -O git-version.h https://gist.githubusercontent.com/WayneD/c11243fa374fc64d4e42f2855c8e3827/raw/rsync-git-version.h
|
||||
echo "/usr/local/bin" >>$GITHUB_PATH
|
||||
- name: configure
|
||||
run: CPPFLAGS=-I/usr/local/opt/openssl/include/ LDFLAGS=-L/usr/local/opt/openssl/lib/ ./configure --with-rrsync
|
||||
- name: make
|
||||
run: make
|
||||
- name: install
|
||||
run: sudo make install
|
||||
- name: info
|
||||
run: rsync --version
|
||||
- name: check
|
||||
run: sudo RSYNC_EXPECT_SKIPPED=acls-default,chmod-temp-dir,chown-fake,devices-fake,dir-sgid,protected-regular,xattrs-hlink,xattrs make check
|
||||
- name: ssl file list
|
||||
run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
|
||||
- name: save artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: macos-bin
|
||||
path: |
|
||||
rsync
|
||||
rsync-ssl
|
||||
rsync.1
|
||||
rsync-ssl.1
|
||||
rsyncd.conf.5
|
||||
rrsync.1
|
||||
rrsync
|
||||
|
||||
cygwin-build:
|
||||
runs-on: windows-latest
|
||||
if: (github.event_name == 'schedule' || contains(github.event.head_commit.message, '[buildall]'))
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: crazy-max/ghaction-chocolatey@v1.2.2
|
||||
with:
|
||||
args: install -y --no-progress cygwin cyg-get
|
||||
- name: prep
|
||||
run: |
|
||||
cyg-get make autoconf automake gcc-core attr libattr-devel python38 python38-pip libzstd-devel liblz4-devel libssl-devel libxxhash0 libxxhash-devel
|
||||
curl.exe -o git-version.h https://gist.githubusercontent.com/WayneD/c11243fa374fc64d4e42f2855c8e3827/raw/rsync-git-version.h
|
||||
echo "C:/tools/cygwin/bin" >>$Env:GITHUB_PATH
|
||||
- name: commonmark
|
||||
run: bash -c 'python3 -mpip install --user commonmark'
|
||||
- name: configure
|
||||
run: bash -c './configure --with-rrsync'
|
||||
- name: make
|
||||
run: bash -c 'make'
|
||||
- name: install
|
||||
run: bash -c 'make install'
|
||||
- name: info
|
||||
run: bash -c '/usr/local/bin/rsync --version'
|
||||
- name: check
|
||||
run: bash -c 'RSYNC_EXPECT_SKIPPED=acls-default,acls,chown,devices,dir-sgid,protected-regular make check'
|
||||
- name: ssl file list
|
||||
run: bash -c 'PATH="/usr/local/bin:$PATH" rsync-ssl --no-motd download.samba.org::rsyncftp/ || true'
|
||||
- name: save artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: cygwin-bin
|
||||
path: |
|
||||
rsync.exe
|
||||
rsync-ssl
|
||||
rsync.1
|
||||
rsync-ssl.1
|
||||
rsyncd.conf.5
|
||||
rrsync.1
|
||||
rrsync
|
||||
31
.github/workflows/ccpp.yml
vendored
31
.github/workflows/ccpp.yml
vendored
@@ -1,31 +0,0 @@
|
||||
name: C CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: prepare-packages
|
||||
run: sudo apt-get install fakeroot acl libacl1-dev attr libattr1-dev liblz4-dev libzstd-dev libxxhash-dev python3-cmarkgfm
|
||||
- name: prepare-source
|
||||
run: ./prepare-source
|
||||
- name: configure
|
||||
run: ./configure --with-included-popt --with-included-zlib --enable-simd
|
||||
- name: make
|
||||
run: make
|
||||
- name: version-summary
|
||||
run: ./rsync --version
|
||||
- name: make check
|
||||
run: make check
|
||||
- name: make check30
|
||||
run: make check30
|
||||
- name: make check29
|
||||
run: make check29
|
||||
15
.gitignore
vendored
15
.gitignore
vendored
@@ -15,20 +15,26 @@ config.status
|
||||
aclocal.m4
|
||||
/proto.h
|
||||
/proto.h-tstamp
|
||||
/rsync*.1
|
||||
/rsync*.5
|
||||
/rsync*.[15]
|
||||
/rrsync*.1
|
||||
/rsync*.html
|
||||
/rrsync*.html
|
||||
/help-rsync*.h
|
||||
/default-cvsignore.h
|
||||
/default-dont-compress.h
|
||||
/daemon-parm.h
|
||||
/.md2man-works
|
||||
/autom4te*.cache
|
||||
/confdefs.h
|
||||
/conftest*
|
||||
/dox
|
||||
/getgroups
|
||||
/gists
|
||||
/gmon.out
|
||||
/rsync
|
||||
/stunnel-rsyncd.conf
|
||||
/shconfig
|
||||
/git-version.h
|
||||
/testdir
|
||||
/tests-dont-exist
|
||||
/testtmp
|
||||
@@ -46,5 +52,8 @@ aclocal.m4
|
||||
/testsuite/devices-fake.test
|
||||
/testsuite/xattrs-hlink.test
|
||||
/patches
|
||||
/SaVeDiR
|
||||
/patches.gen
|
||||
/build
|
||||
/auto-build-save
|
||||
.deps
|
||||
/*.exe
|
||||
|
||||
26
COPYING
26
COPYING
@@ -1,7 +1,16 @@
|
||||
REGARDING OPENSSL AND XXHASH
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to dynamically link rsync with the OpenSSL and xxhash
|
||||
libraries when those libraries are being distributed in compliance
|
||||
with their license terms, and to distribute a dynamically linked
|
||||
combination of rsync and these libraries. This is also considered
|
||||
to be covered under the GPL's System Libraries exception.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -645,7 +654,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -664,20 +673,11 @@ might be different; for a GUI interface, you would use an "about box".
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
REGARDING OPENSSL AND XXHASH
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to dynamically link rsync with the OpenSSL and xxhash
|
||||
libraries when those libraries are being distributed in compliance
|
||||
with their license terms, and to distribute a dynamically linked
|
||||
combination of rsync and these libraries. This is also considered
|
||||
to be covered under the GPL's System Libraries exception.
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
||||
226
INSTALL.md
226
INSTALL.md
@@ -1,13 +1,172 @@
|
||||
To build and install rsync:
|
||||
# How to build and install rsync
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
# make install
|
||||
When building rsync, you'll want to install various libraries in order to get
|
||||
all the features enabled. The configure script will alert you when the
|
||||
newest libraries are missing and tell you the appropriate `--disable-LIB`
|
||||
option to use if you want to just skip that feature. What follows are various
|
||||
support libraries that you may want to install to build rsync with the maximum
|
||||
features (the impatient can skip down to the package summary):
|
||||
|
||||
You may set the installation directory and other parameters by options
|
||||
to ./configure. To see them, use:
|
||||
## The basic setup
|
||||
|
||||
$ ./configure --help
|
||||
You need to have a C compiler installed and optionally a C++ compiler in order
|
||||
to try to build some hardware-accelerated checksum routines. Rsync also needs
|
||||
a modern awk, which might be provided via gawk or nawk on some OSes.
|
||||
|
||||
## Autoconf & man pages
|
||||
|
||||
If you're installing from the git repo (instead of a release tar file) you'll
|
||||
also need the GNU autotools (autoconf & automake) and your choice of 2 python3
|
||||
markdown libraries: cmarkgfm or commonmark (needed to generate the man pages).
|
||||
If your OS doesn't provide a python3-cmarkgfm or python3-commonmark package,
|
||||
you can run the following to install the commonmark python library for your
|
||||
build user (after installing python3's pip package):
|
||||
|
||||
> python3 -mpip install --user commonmark
|
||||
|
||||
You can test if you've got it fixed by running (from the rsync checkout):
|
||||
|
||||
> ./md2man --test rsync-ssl.1.md
|
||||
|
||||
Alternately, you can avoid generating the man pages by fetching the very latest
|
||||
versions (that match the latest git source) from the [generated-files][6] dir.
|
||||
One way to do that is to run:
|
||||
|
||||
> ./prepare-source fetchgen
|
||||
|
||||
[6]: https://download.samba.org/pub/rsync/generated-files/
|
||||
|
||||
## ACL support
|
||||
|
||||
To support copying ACL file information, make sure you have an acl
|
||||
development library installed. It also helps to have the helper programs
|
||||
installed to manipulate ACLs and to run the rsync testsuite.
|
||||
|
||||
## Xattr support
|
||||
|
||||
To support copying xattr file information, make sure you have an attr
|
||||
development library installed. It also helps to have the helper programs
|
||||
installed to manipulate xattrs and to run the rsync testsuite.
|
||||
|
||||
## xxhash
|
||||
|
||||
The [xxHash library][1] provides extremely fast checksum functions that can
|
||||
make the "rsync algorithm" run much more quickly, especially when matching
|
||||
blocks in large files. Installing this development library adds xxhash
|
||||
checksums as the default checksum algorithm. You'll need at least v0.8.0
|
||||
if you want rsync to include the full range of its checksum algorithms.
|
||||
|
||||
[1]: https://cyan4973.github.io/xxHash/
|
||||
|
||||
## zstd
|
||||
|
||||
The [zstd library][2] compression algorithm that uses less CPU than
|
||||
the default zlib algorithm at the same compression level. Note that you
|
||||
need at least version 1.4, so you might need to skip the zstd compression if
|
||||
you can only install a 1.3 release. Installing this development library
|
||||
adds zstd compression as the default compression algorithm.
|
||||
|
||||
[2]: http://facebook.github.io/zstd/
|
||||
|
||||
## lz4
|
||||
|
||||
The [lz4 library][3] compression algorithm that uses very little CPU, though
|
||||
it also has the smallest compression ratio of other algorithms. Installing
|
||||
this development library adds lz4 compression as an available compression
|
||||
algorithm.
|
||||
|
||||
[3]: https://lz4.github.io/lz4/
|
||||
|
||||
## openssl crypto
|
||||
|
||||
The [openssl crypto library][4] provides some hardware accelerated checksum
|
||||
algorithms for MD4 and MD5. Installing this development library makes rsync
|
||||
use the (potentially) faster checksum routines when computing MD4 & MD5
|
||||
checksums.
|
||||
|
||||
[4]: https://www.openssl.org/docs/man1.0.2/man3/crypto.html
|
||||
|
||||
## Package summary
|
||||
|
||||
To help you get the libraries installed, here are some package install commands
|
||||
for various OSes. The commands are split up to correspond with the above
|
||||
items, but feel free to combine the package names into a single install, if you
|
||||
like.
|
||||
|
||||
- For Debian and Ubuntu (Debian Buster users may want to briefly(?) enable
|
||||
buster-backports to update zstd from 1.3 to 1.4):
|
||||
|
||||
> sudo apt install -y gcc g++ gawk autoconf automake python3-cmarkgfm
|
||||
> sudo apt install -y acl libacl1-dev
|
||||
> sudo apt install -y attr libattr1-dev
|
||||
> sudo apt install -y libxxhash-dev
|
||||
> sudo apt install -y libzstd-dev
|
||||
> sudo apt install -y liblz4-dev
|
||||
> sudo apt install -y libssl-dev
|
||||
|
||||
- For CentOS (use EPEL for python3-pip):
|
||||
|
||||
> sudo yum -y install epel-release
|
||||
> sudo yum -y install gcc g++ gawk autoconf automake python3-pip
|
||||
> sudo yum -y install acl libacl-devel
|
||||
> sudo yum -y install attr libattr-devel
|
||||
> sudo yum -y install xxhash-devel
|
||||
> sudo yum -y install libzstd-devel
|
||||
> sudo yum -y install lz4-devel
|
||||
> sudo yum -y install openssl-devel
|
||||
> python3 -mpip install --user commonmark
|
||||
|
||||
- For Fedora 33:
|
||||
|
||||
> sudo dnf -y install acl libacl-devel
|
||||
> sudo dnf -y install attr libattr-devel
|
||||
> sudo dnf -y install xxhash-devel
|
||||
> sudo dnf -y install libzstd-devel
|
||||
> sudo dnf -y install lz4-devel
|
||||
> sudo dnf -y install openssl-devel
|
||||
|
||||
- For FreeBSD (this assumes that the python3 version is 3.7):
|
||||
|
||||
> sudo pkg install -y autotools python3 py37-CommonMark
|
||||
> sudo pkg install -y xxhash
|
||||
> sudo pkg install -y zstd
|
||||
> sudo pkg install -y liblz4
|
||||
|
||||
- For macOS:
|
||||
|
||||
> brew install automake
|
||||
> brew install xxhash
|
||||
> brew install zstd
|
||||
> brew install lz4
|
||||
> brew install openssl
|
||||
|
||||
- For Cygwin (with all cygwin programs stopped, run the appropriate setup program from a cmd shell):
|
||||
|
||||
> setup-x86_64 --quiet-mode -P make,gawk,autoconf,automake,gcc-core,python38,python38-pip
|
||||
> setup-x86_64 --quiet-mode -P attr,libattr-devel
|
||||
> setup-x86_64 --quiet-mode -P libzstd-devel
|
||||
> setup-x86_64 --quiet-mode -P liblz4-devel
|
||||
> setup-x86_64 --quiet-mode -P libssl-devel
|
||||
|
||||
Sometimes cygwin has commonmark packaged and sometimes it doesn't. Now that
|
||||
its python38 has stabilized, you could install python38-commonmark. Or just
|
||||
avoid the issue by running this from a bash shell as your build user:
|
||||
|
||||
> python3 -mpip install --user commonmark
|
||||
|
||||
## Build and install
|
||||
|
||||
After installing the various libraries, you need to configure, build, and
|
||||
install the source:
|
||||
|
||||
> ./configure
|
||||
> make
|
||||
> sudo make install
|
||||
|
||||
The default install path is /usr/local/bin, but you can set the installation
|
||||
directory and other parameters using 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
|
||||
@@ -19,56 +178,65 @@ 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 a recent release 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.
|
||||
the `--with-included-popt` option is passed to ./configure.
|
||||
|
||||
If you configure using --enable-maintainer-mode, then rsync will try
|
||||
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.
|
||||
|
||||
MAKE COMPATIBILITY
|
||||
------------------
|
||||
If you want to automatically use a separate "build" directory based on
|
||||
the current git branch name, start with a pristine git checkout and run
|
||||
"mkdir auto-build-save" before you run the first ./configure command.
|
||||
That will cause a fresh build dir to spring into existence along with a
|
||||
special Makefile symlink that allows you to run "make" and "./configure"
|
||||
from the source dir (the "build" dir gets auto switched based on branch).
|
||||
This is helpful when using the branch-from-patch and patch-update scripts
|
||||
to maintain the official rsync patches. If you ever need to build from
|
||||
a "detached head" git position then you'll need to manually chdir into
|
||||
the build dir to run make. I also like to create 2 more symlinks in the
|
||||
source dir: `ln -s build/rsync . ; ln -s build/testtmp .`
|
||||
|
||||
## Make compatibility
|
||||
|
||||
Note that Makefile.in has a rule that uses a wildcard in a prerequisite. If
|
||||
your make has a problem with this rule, you will see an error like this:
|
||||
|
||||
Don't know how to make ./*.c
|
||||
|
||||
You can change the "proto.h-tstamp" target in Makefile.in to list all the *.c
|
||||
You can change the "proto.h-tstamp" target in Makefile.in to list all the \*.c
|
||||
filenames explicitly in order to avoid this issue.
|
||||
|
||||
RPM NOTES
|
||||
---------
|
||||
## 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
|
||||
-----------
|
||||
## 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.
|
||||
(Bundled) cc: "configure", line 2162: error 1705: Function prototypes are an ANSI feature.
|
||||
|
||||
Install gcc or HP's "ANSI/C Compiler".
|
||||
|
||||
MAC OSX NOTES
|
||||
-------------
|
||||
## Mac OS X notes
|
||||
|
||||
Some versions of Mac OS X (Darwin) seem to have an IPv6 stack, but do
|
||||
not completely implement the "New Sockets" API.
|
||||
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.
|
||||
[This site][5] 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
|
||||
-------------
|
||||
[5]: http://www.ipv6.org/impl/mac.html
|
||||
|
||||
## 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
|
||||
The workaround is to append the following to config.h:
|
||||
|
||||
> #ifdef _LARGE_FILES
|
||||
> #undef HAVE_SECURE_MKSTEMP
|
||||
> #endif
|
||||
|
||||
142
Makefile.in
142
Makefile.in
@@ -1,5 +1,4 @@
|
||||
# Makefile for rsync. This is processed by configure to produce the final
|
||||
# Makefile
|
||||
# The Makefile for rsync (configure creates it from Makefile.in).
|
||||
|
||||
prefix=@prefix@
|
||||
datarootdir=@datarootdir@
|
||||
@@ -7,9 +6,11 @@ exec_prefix=@exec_prefix@
|
||||
bindir=@bindir@
|
||||
libdir=@libdir@/rsync
|
||||
mandir=@mandir@
|
||||
with_rrsync=@with_rrsync@
|
||||
|
||||
LIBS=@LIBS@
|
||||
CC=@CC@
|
||||
AWK=@AWK@
|
||||
CFLAGS=@CFLAGS@
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
CXX=@CXX@
|
||||
@@ -26,32 +27,31 @@ MKDIR_P=@MKDIR_P@
|
||||
VPATH=$(srcdir)
|
||||
SHELL=/bin/sh
|
||||
|
||||
VERSION=@RSYNC_VERSION@
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
SIMD_x86_64=simd-checksum-x86_64.o lib/md5-asm-x86_64.o
|
||||
SIMD_x86_64=simd-checksum-x86_64.o simd-checksum-avx2.o
|
||||
ASM_x86_64=lib/md5-asm-x86_64.o
|
||||
|
||||
GENFILES=configure.sh aclocal.m4 config.h.in proto.h proto.h-tstamp rsync.1 rsync.1.html \
|
||||
GENFILES=configure.sh aclocal.m4 config.h.in rsync.1 rsync.1.html \
|
||||
rsync-ssl.1 rsync-ssl.1.html rsyncd.conf.5 rsyncd.conf.5.html
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h itypes.h inums.h \
|
||||
lib/pool_alloc.h
|
||||
lib/pool_alloc.h lib/mdigest.h lib/md-defines.h
|
||||
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
|
||||
lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o @LIBOBJS@
|
||||
zlib_OBJS=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
|
||||
zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o
|
||||
OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
|
||||
util.o util2.o main.o checksum.o match.o syscall.o log.o backup.o delete.o
|
||||
util1.o util2.o main.o checksum.o match.o syscall.o log.o backup.o delete.o
|
||||
OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
|
||||
fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
|
||||
OBJS3=progress.o pipe.o
|
||||
usage.o fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
|
||||
OBJS3=progress.o pipe.o @ASM@ @SIMD@
|
||||
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
|
||||
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
|
||||
popt/popthelp.o popt/poptparse.o
|
||||
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) @SIMD@ $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@
|
||||
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@
|
||||
|
||||
TLS_OBJ = tls.o syscall.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
|
||||
TLS_OBJ = tls.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
|
||||
|
||||
# Programs we must have to run the test cases
|
||||
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
|
||||
@@ -68,28 +68,32 @@ CHECK_OBJS=tls.o testrun.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.
|
||||
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
|
||||
@OBJ_RESTORE@
|
||||
|
||||
all: Makefile rsync$(EXEEXT) stunnel-rsyncd.conf @MAKE_RRSYNC@ @MAKE_MAN@
|
||||
.PHONY: all
|
||||
all: Makefile rsync$(EXEEXT) stunnel-rsyncd.conf @MAKE_MAN@
|
||||
|
||||
.PHONY: install
|
||||
install: all
|
||||
-${MKDIR_P} ${DESTDIR}${bindir}
|
||||
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
|
||||
${INSTALLCMD} -m 755 rsync-ssl ${DESTDIR}${bindir}
|
||||
-${MKDIR_P} ${DESTDIR}${mandir}/man1
|
||||
-${MKDIR_P} ${DESTDIR}${mandir}/man5
|
||||
if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
|
||||
if test -f rsync-ssl.1; then ${INSTALLMAN} -m 644 rsync-ssl.1 ${DESTDIR}${mandir}/man1; fi
|
||||
if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
|
||||
-$(MKDIR_P) $(DESTDIR)$(bindir)
|
||||
$(INSTALLCMD) $(INSTALL_STRIP) -m 755 rsync$(EXEEXT) $(DESTDIR)$(bindir)
|
||||
$(INSTALLCMD) -m 755 $(srcdir)/rsync-ssl $(DESTDIR)$(bindir)
|
||||
-$(MKDIR_P) $(DESTDIR)$(mandir)/man1
|
||||
-$(MKDIR_P) $(DESTDIR)$(mandir)/man5
|
||||
if test -f rsync.1; then $(INSTALLMAN) -m 644 rsync.1 $(DESTDIR)$(mandir)/man1; fi
|
||||
if test -f rsync-ssl.1; then $(INSTALLMAN) -m 644 rsync-ssl.1 $(DESTDIR)$(mandir)/man1; fi
|
||||
if test -f rsyncd.conf.5; then $(INSTALLMAN) -m 644 rsyncd.conf.5 $(DESTDIR)$(mandir)/man5; fi
|
||||
if test "$(with_rrsync)" = yes; then \
|
||||
$(INSTALLCMD) -m 755 rrsync $(DESTDIR)$(bindir); \
|
||||
if test -f rrsync.1; then $(INSTALLMAN) -m 644 rrsync.1 $(DESTDIR)$(mandir)/man1; fi; \
|
||||
fi
|
||||
|
||||
install-ssl-daemon: stunnel-rsyncd.conf
|
||||
-${MKDIR_P} ${DESTDIR}/etc/stunnel
|
||||
${INSTALLCMD} -m 644 stunnel-rsyncd.conf ${DESTDIR}/etc/stunnel/rsyncd.conf
|
||||
-$(MKDIR_P) $(DESTDIR)/etc/stunnel
|
||||
$(INSTALLCMD) -m 644 stunnel-rsyncd.conf $(DESTDIR)/etc/stunnel/rsyncd.conf
|
||||
@if ! ls /etc/rsync-ssl/certs/server.* >/dev/null 2>/dev/null; then \
|
||||
echo "Note that you'll need to install the certificate used by /etc/stunnel/rsyncd.conf"; \
|
||||
fi
|
||||
|
||||
install-all: install install-ssl-client install-ssl-daemon
|
||||
install-all: install install-ssl-daemon
|
||||
|
||||
install-strip:
|
||||
$(MAKE) INSTALL_STRIP='-s' install
|
||||
@@ -97,14 +101,25 @@ install-strip:
|
||||
rsync$(EXEEXT): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
rrsync: support/rrsync
|
||||
cp -p $(srcdir)/support/rrsync rrsync
|
||||
|
||||
$(OBJS): $(HEADERS)
|
||||
$(CHECK_OBJS): $(HEADERS)
|
||||
options.o: latest-year.h help-rsync.h help-rsyncd.h
|
||||
tls.o xattrs.o: lib/sysxattrs.h
|
||||
usage.o: version.h latest-year.h help-rsync.h help-rsyncd.h git-version.h default-cvsignore.h
|
||||
loadparm.o: default-dont-compress.h daemon-parm.h
|
||||
|
||||
flist.o: rounding.h
|
||||
|
||||
default-cvsignore.h default-dont-compress.h: rsync.1.md define-from-md.awk
|
||||
$(AWK) -f $(srcdir)/define-from-md.awk -v hfile=$@ $(srcdir)/rsync.1.md
|
||||
|
||||
help-rsync.h help-rsyncd.h: rsync.1.md help-from-md.awk
|
||||
awk -f $(srcdir)/help-from-md.awk -v helpfile=$@ $(srcdir)/rsync.1.md
|
||||
$(AWK) -f $(srcdir)/help-from-md.awk -v hfile=$@ $(srcdir)/rsync.1.md
|
||||
|
||||
daemon-parm.h: daemon-parm.txt daemon-parm.awk
|
||||
$(AWK) -f $(srcdir)/daemon-parm.awk $(srcdir)/daemon-parm.txt
|
||||
|
||||
rounding.h: rounding.c rsync.h proto.h
|
||||
@for r in 0 1 3; do \
|
||||
@@ -124,11 +139,20 @@ rounding.h: rounding.c rsync.h proto.h
|
||||
fi
|
||||
@rm -f rounding.out
|
||||
|
||||
simd-checksum-x86_64.o: simd-checksum-x86_64.cpp
|
||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $(srcdir)/simd-checksum-x86_64.cpp
|
||||
git-version.h: ALWAYS_RUN
|
||||
$(srcdir)/mkgitver
|
||||
|
||||
lib/md5-asm-x86_64.o: lib/md5-asm-x86_64.s
|
||||
$(CC) -c -o $@ $(srcdir)/lib/md5-asm-x86_64.s
|
||||
.PHONY: ALWAYS_RUN
|
||||
ALWAYS_RUN:
|
||||
|
||||
simd-checksum-x86_64.o: simd-checksum-x86_64.cpp
|
||||
@$(srcdir)/cmd-or-msg disable-simd $(CXX) -I. $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $(srcdir)/simd-checksum-x86_64.cpp
|
||||
|
||||
simd-checksum-avx2.o: simd-checksum-avx2.S
|
||||
@$(srcdir)/cmd-or-msg disable-asm $(CC) $(CFLAGS) --include=$(srcdir)/rsync.h -DAVX2_ASM -I. @NOEXECSTACK@ -c -o $@ $(srcdir)/simd-checksum-avx2.S
|
||||
|
||||
lib/md5-asm-x86_64.o: lib/md5-asm-x86_64.S config.h lib/md-defines.h
|
||||
@$(srcdir)/cmd-or-msg disable-asm $(CC) -I. @NOEXECSTACK@ -c -o $@ $(srcdir)/lib/md5-asm-x86_64.S
|
||||
|
||||
tls$(EXEEXT): $(TLS_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
|
||||
@@ -142,11 +166,11 @@ getgroups$(EXEEXT): getgroups.o
|
||||
getfsdev$(EXEEXT): getfsdev.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
|
||||
|
||||
TRIMSLASH_OBJ = trimslash.o syscall.o t_stub.o lib/compat.o lib/snprintf.o
|
||||
TRIMSLASH_OBJ = trimslash.o syscall.o util2.o t_stub.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 util2.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
|
||||
T_UNSAFE_OBJ = t_unsafe.o syscall.o util1.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
|
||||
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
|
||||
|
||||
@@ -154,11 +178,15 @@ t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
|
||||
conf: configure.sh config.h.in
|
||||
|
||||
.PHONY: gen
|
||||
gen: conf proto.h man
|
||||
gen: conf proto.h man git-version.h
|
||||
|
||||
.PHONY: gensend
|
||||
gensend: gen
|
||||
rsync -aic $(GENFILES) $${SAMBA_HOST-samba.org}:/home/ftp/pub/rsync/generated-files/
|
||||
if ! diff git-version.h $(srcdir)/gists/rsync-git-version.h >/dev/null; then \
|
||||
./rsync -ai git-version.h $(srcdir)/gists/rsync-git-version.h && \
|
||||
(cd $(srcdir)/gists && git commit --allow-empty-message -m '' rsync-git-version.h && git push) ; \
|
||||
fi
|
||||
rsync -aic $(GENFILES) git-version.h $${SAMBA_HOST-samba.org}:/home/ftp/pub/rsync/generated-files/ || true
|
||||
|
||||
aclocal.m4: $(srcdir)/m4/*.m4
|
||||
aclocal -I $(srcdir)/m4
|
||||
@@ -180,7 +208,7 @@ configure.sh config.h.in: configure.ac aclocal.m4
|
||||
else \
|
||||
echo "config.h.in has CHANGED."; \
|
||||
fi
|
||||
@if test -f configure.sh.old -o -f config.h.in.old; then \
|
||||
@if test -f configure.sh.old || test -f config.h.in.old; then \
|
||||
if test "$(MAKECMDGOALS)" = reconfigure; then \
|
||||
echo 'Continuing with "make reconfigure".'; \
|
||||
else \
|
||||
@@ -195,6 +223,10 @@ reconfigure: configure.sh
|
||||
./config.status --recheck
|
||||
./config.status
|
||||
|
||||
.PHONY: restatus
|
||||
restatus:
|
||||
./config.status
|
||||
|
||||
Makefile: Makefile.in config.status configure.sh config.h.in
|
||||
@if test -f Makefile; then cp -p Makefile Makefile.old; else touch Makefile.old; fi
|
||||
@./config.status
|
||||
@@ -219,25 +251,29 @@ proto: proto.h-tstamp
|
||||
proto.h: proto.h-tstamp
|
||||
@if test -f proto.h; then :; else cp -p $(srcdir)/proto.h .; fi
|
||||
|
||||
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c config.h
|
||||
awk -f $(srcdir)/mkproto.awk $(srcdir)/*.c $(srcdir)/lib/compat.c
|
||||
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c daemon-parm.h
|
||||
$(AWK) -f $(srcdir)/mkproto.awk $(srcdir)/*.c $(srcdir)/lib/compat.c daemon-parm.h
|
||||
|
||||
.PHONY: man
|
||||
man: rsync.1 rsync-ssl.1 rsyncd.conf.5
|
||||
man: rsync.1 rsync-ssl.1 rsyncd.conf.5 @MAKE_RRSYNC_1@
|
||||
|
||||
rsync.1: rsync.1.md md2man NEWS.md Makefile
|
||||
@$(srcdir)/maybe-make-man $(srcdir) rsync.1.md
|
||||
rsync.1: rsync.1.md md-convert version.h Makefile
|
||||
@$(srcdir)/maybe-make-man rsync.1.md
|
||||
|
||||
rsync-ssl.1: rsync-ssl.1.md md2man NEWS.md Makefile
|
||||
@$(srcdir)/maybe-make-man $(srcdir) rsync-ssl.1.md
|
||||
rsync-ssl.1: rsync-ssl.1.md md-convert version.h Makefile
|
||||
@$(srcdir)/maybe-make-man rsync-ssl.1.md
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.5.md md2man NEWS.md Makefile
|
||||
@$(srcdir)/maybe-make-man $(srcdir) rsyncd.conf.5.md
|
||||
rsyncd.conf.5: rsyncd.conf.5.md md-convert version.h Makefile
|
||||
@$(srcdir)/maybe-make-man rsyncd.conf.5.md
|
||||
|
||||
rrsync.1: support/rrsync.1.md md-convert Makefile
|
||||
@$(srcdir)/maybe-make-man support/rrsync.1.md
|
||||
|
||||
.PHONY: clean
|
||||
clean: cleantests
|
||||
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
rounding rounding.h *.old rsync*.1 rsync*.5 rsync*.html
|
||||
git-version.h rounding rounding.h *.old rsync*.1 rsync*.5 rsync*.html \
|
||||
daemon-parm.h help-*.h default-*.h proto.h proto.h-tstamp
|
||||
|
||||
.PHONY: cleantests
|
||||
cleantests:
|
||||
@@ -248,16 +284,11 @@ cleantests:
|
||||
# the source directory.
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
rm -f Makefile config.h config.status
|
||||
rm -f stunnel-rsyncd.conf
|
||||
rm -f lib/dummy popt/dummy zlib/dummy
|
||||
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
|
||||
rm -f $(srcdir)/lib/dummy $(srcdir)/popt/dummy $(srcdir)/zlib/dummy
|
||||
rm -f config.cache config.log
|
||||
rm -f $(srcdir)/config.cache $(srcdir)/config.log
|
||||
rm -f shconfig $(srcdir)/shconfig
|
||||
rm -f $(GENFILES)
|
||||
rm -rf autom4te.cache
|
||||
for dir in $(srcdir) . ; do \
|
||||
(cd "$$dir" && rm -rf Makefile config.h config.status stunnel-rsyncd.conf \
|
||||
lib/dummy popt/dummy zlib/dummy config.cache config.log shconfig \
|
||||
$(GENFILES) autom4te.cache) ; \
|
||||
done
|
||||
|
||||
# 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
|
||||
@@ -267,6 +298,7 @@ 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
|
||||
@rm nmused.txt nmfns.txt
|
||||
|
||||
# 'check' is the GNU name, 'test' is the name for everybody else :-)
|
||||
.PHONY: test
|
||||
|
||||
3863
OLDNEWS.md
3863
OLDNEWS.md
File diff suppressed because it is too large
Load Diff
73
README.md
73
README.md
@@ -23,8 +23,18 @@ options. To get a complete list of supported options type:
|
||||
|
||||
rsync --help
|
||||
|
||||
See the manpage for more detailed information.
|
||||
See the [manpage][0] for more detailed information.
|
||||
|
||||
[0]: https://download.samba.org/pub/rsync/rsync.1
|
||||
|
||||
BUILDING AND INSTALLING
|
||||
-----------------------
|
||||
|
||||
If you need to build rsync yourself, check out the [INSTALL][1] page for
|
||||
information on what libraries and packages you can use to get the maximum
|
||||
features in your build.
|
||||
|
||||
[1]: https://github.com/WayneD/rsync/blob/master/INSTALL.md
|
||||
|
||||
SETUP
|
||||
-----
|
||||
@@ -63,9 +73,9 @@ connect to an rsync daemon.
|
||||
WEB SITE
|
||||
--------
|
||||
|
||||
The main rsync web site is here:
|
||||
For more information, visit the [main rsync web site][2].
|
||||
|
||||
> http://rsync.samba.org/
|
||||
[2]: https://rsync.samba.org/
|
||||
|
||||
You'll find a FAQ list, downloads, resources, HTML versions of the
|
||||
manpages, etc.
|
||||
@@ -77,25 +87,25 @@ MAILING LISTS
|
||||
There is a mailing list for the discussion of rsync and its applications
|
||||
that is open to anyone to join. New releases are announced on this
|
||||
list, and there is also an announcement-only mailing list for those that
|
||||
want official announcements. See the mailing-list page for full
|
||||
details:
|
||||
want official announcements. See the [mailing-list page][3] for full
|
||||
details.
|
||||
|
||||
> http://rsync.samba.org/lists.html
|
||||
[3]: https://rsync.samba.org/lists.html
|
||||
|
||||
|
||||
BUG REPORTS
|
||||
-----------
|
||||
|
||||
To visit this web page for full the details on bug reporting:
|
||||
The [bug-tracking web page][4] has full details on bug reporting.
|
||||
|
||||
> http://rsync.samba.org/bugzilla.html
|
||||
[4]: https://rsync.samba.org/bug-tracking.html
|
||||
|
||||
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:
|
||||
That page contains links to the current bug list, and information on how to
|
||||
do a good job when reporting a bug. You might also like to try searching
|
||||
the Internet for the error message you've received, or looking in the
|
||||
[mailing list archives][5].
|
||||
|
||||
> http://mail-archive.com/rsync@lists.samba.org/
|
||||
[5]: https://mail-archive.com/rsync@lists.samba.org/
|
||||
|
||||
To send a bug report, follow the instructions on the bug-tracking
|
||||
page of the web site.
|
||||
@@ -108,42 +118,27 @@ GIT REPOSITORY
|
||||
|
||||
If you want to get the very latest version of rsync direct from the
|
||||
source code repository, then you will need to use git. The git repo
|
||||
is hosted on github and on samba's site. Feel free to access it here:
|
||||
is hosted [on GitHub][6] and [on Samba's site][7].
|
||||
|
||||
> https://github.com/WayneD/rsync
|
||||
[6]: https://github.com/WayneD/rsync
|
||||
[7]: https://git.samba.org/?p=rsync.git;a=summary
|
||||
|
||||
or clone it from its samba repo:
|
||||
See [the download page][8] for full details on all the ways to grab the
|
||||
source.
|
||||
|
||||
> git clone git://git.samba.org/rsync.git
|
||||
|
||||
See the download page for full details on all the ways to grab the
|
||||
source:
|
||||
|
||||
> http://rsync.samba.org/download.html
|
||||
[8]: https://rsync.samba.org/download.html
|
||||
|
||||
|
||||
COPYRIGHT
|
||||
---------
|
||||
|
||||
Rsync was originally written by Andrew Tridgell and is currently
|
||||
maintained by Wayne Davison. It has been improved by many developers
|
||||
maintained by Wayne Davison. It has been improved by many developers
|
||||
from 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:
|
||||
the GNU General Public License, found in the file [COPYING][9] in this
|
||||
distribution, or at [the Free Software Foundation][10].
|
||||
|
||||
> http://www.fsf.org/licenses/gpl.html
|
||||
|
||||
|
||||
AVAILABILITY
|
||||
------------
|
||||
|
||||
The main web site for rsync is http://rsync.samba.org/
|
||||
|
||||
The main ftp site is ftp://rsync.samba.org/pub/rsync/
|
||||
|
||||
This is also available as rsync://download.samba.org/rsyncftp/ if you
|
||||
connect via ssl. Use the `rsync-ssl` script if you have it, otherwise
|
||||
connect to the rsync server via a normal rsync command and it will
|
||||
output some instructions for how to connect.
|
||||
[9]: https://github.com/WayneD/rsync/blob/master/COPYING
|
||||
[10]: https://www.fsf.org/licenses/gpl.html
|
||||
|
||||
12
SECURITY.md
Normal file
12
SECURITY.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the current release of the software is actively supported. If you need
|
||||
help backporting fixes into an older release, feel free to ask.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Email your vulnerability information to rsync's maintainer:
|
||||
|
||||
Wayne Davison <wayne@opencoder.net>
|
||||
12
TODO
12
TODO
@@ -49,7 +49,7 @@ Create test makefile target for some tests
|
||||
|
||||
RELATED PROJECTS -----------------------------------------------------
|
||||
rsyncsh
|
||||
http://rsync.samba.org/rsync-and-debian/
|
||||
https://rsync.samba.org/rsync-and-debian/
|
||||
rsyncable gzip patch
|
||||
rsyncsplit as alternative to real integration with gzip?
|
||||
reverse rsync over HTTP Range
|
||||
@@ -66,8 +66,8 @@ Use chroot only if supported
|
||||
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
|
||||
https://lists.samba.org/pipermail/rsync/2001-August/thread.html
|
||||
https://lists.samba.org/pipermail/rsync/2001-September/thread.html
|
||||
|
||||
-- --
|
||||
|
||||
@@ -204,7 +204,7 @@ Create more granular verbosity 2003/05/15
|
||||
fine grained selection of statistical reporting and what
|
||||
actions are logged.
|
||||
|
||||
http://lists.samba.org/archive/rsync/2003-May/006059.html
|
||||
https://lists.samba.org/archive/rsync/2003-May/006059.html
|
||||
|
||||
-- --
|
||||
|
||||
@@ -287,7 +287,7 @@ 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
|
||||
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48108
|
||||
|
||||
-- --
|
||||
|
||||
@@ -495,7 +495,7 @@ rsyncsh
|
||||
-- --
|
||||
|
||||
|
||||
http://rsync.samba.org/rsync-and-debian/
|
||||
https://rsync.samba.org/rsync-and-debian/
|
||||
|
||||
|
||||
-- --
|
||||
|
||||
20
access.c
20
access.c
@@ -2,7 +2,7 @@
|
||||
* Routines to authenticate access to a daemon (hosts allow/deny).
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2004-2020 Wayne Davison
|
||||
* Copyright (C) 2004-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,10 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
#ifdef HAVE_NETGROUP_H
|
||||
#include <netgroup.h>
|
||||
#endif
|
||||
|
||||
static int allow_forward_dns;
|
||||
|
||||
@@ -33,6 +37,11 @@ static int match_hostname(const char **host_ptr, const char *addr, const char *t
|
||||
if (!host || !*host)
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_INNETGR
|
||||
if (*tok == '@' && tok[1])
|
||||
return innetgr(tok + 1, host, NULL, NULL);
|
||||
#endif
|
||||
|
||||
/* First check if the reverse-DNS-determined hostname matches. */
|
||||
if (iwildmatch(tok, host))
|
||||
return 1;
|
||||
@@ -52,10 +61,8 @@ static int match_hostname(const char **host_ptr, const char *addr, const char *t
|
||||
if (strcmp(addr, inet_ntoa(*(struct in_addr*)(hp->h_addr_list[i]))) == 0) {
|
||||
/* If reverse lookups are off, we'll use the conf-specified
|
||||
* hostname in preference to UNDETERMINED. */
|
||||
if (host == undetermined_hostname) {
|
||||
if (!(*host_ptr = strdup(tok)))
|
||||
*host_ptr = undetermined_hostname;
|
||||
}
|
||||
if (host == undetermined_hostname)
|
||||
*host_ptr = strdup(tok);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -241,9 +248,6 @@ static int access_match(const char *list, const char *addr, const char **host_pt
|
||||
char *tok;
|
||||
char *list2 = strdup(list);
|
||||
|
||||
if (!list2)
|
||||
out_of_memory("access_match");
|
||||
|
||||
strlower(list2);
|
||||
|
||||
for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
|
||||
|
||||
19
acls.c
19
acls.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2006-2020 Wayne Davison
|
||||
* Copyright (C) 2006-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -168,8 +168,6 @@ static rsync_acl *create_racl(void)
|
||||
{
|
||||
rsync_acl *racl = new(rsync_acl);
|
||||
|
||||
if (!racl)
|
||||
out_of_memory("create_racl");
|
||||
*racl = empty_rsync_acl;
|
||||
|
||||
return racl;
|
||||
@@ -335,8 +333,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
|
||||
qsort(temp_ida_list.items, temp_ida_list.count, sizeof (id_access), id_access_sorter);
|
||||
}
|
||||
#endif
|
||||
if (!(racl->names.idas = new_array(id_access, temp_ida_list.count)))
|
||||
out_of_memory("unpack_smb_acl");
|
||||
racl->names.idas = new_array(id_access, temp_ida_list.count);
|
||||
memcpy(racl->names.idas, temp_ida_list.items, temp_ida_list.count * sizeof (id_access));
|
||||
} else
|
||||
racl->names.idas = NULL;
|
||||
@@ -505,9 +502,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
|
||||
|
||||
if (cnt) {
|
||||
char *bp = buf + 4*4;
|
||||
id_access *ida;
|
||||
if (!(ida = racl->names.idas = new_array(id_access, cnt)))
|
||||
out_of_memory("get_rsync_acl");
|
||||
id_access *ida = racl->names.idas = new_array(id_access, cnt);
|
||||
racl->names.count = cnt;
|
||||
for ( ; cnt--; ida++, bp += 4+4) {
|
||||
ida->id = IVAL(bp, 0);
|
||||
@@ -703,12 +698,7 @@ static uchar recv_ida_entries(int f, ida_entries *ent)
|
||||
uchar computed_mask_bits = 0;
|
||||
int i, count = read_varint(f);
|
||||
|
||||
if (count) {
|
||||
if (!(ent->idas = new_array(id_access, count)))
|
||||
out_of_memory("recv_ida_entries");
|
||||
} else
|
||||
ent->idas = NULL;
|
||||
|
||||
ent->idas = count ? new_array(id_access, count) : NULL;
|
||||
ent->count = count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
@@ -773,6 +763,7 @@ static int recv_rsync_acl(int f, item_list *racl_list, SMB_ACL_TYPE_T type, mode
|
||||
#ifdef HAVE_OSX_ACLS
|
||||
/* If we received a superfluous mask, throw it away. */
|
||||
duo_item->racl.mask_obj = NO_ENTRY;
|
||||
(void)mode;
|
||||
#else
|
||||
if (duo_item->racl.names.count && duo_item->racl.mask_obj == NO_ENTRY) {
|
||||
/* Mask must be non-empty with lists. */
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "rsync.h"
|
||||
#include "itypes.h"
|
||||
#include "ifuncs.h"
|
||||
|
||||
extern int read_only;
|
||||
extern char *password_file;
|
||||
@@ -118,7 +119,7 @@ static const char *check_secret(int module, const char *user, const char *group,
|
||||
if ((st.st_mode & 06) != 0) {
|
||||
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
|
||||
ok = 0;
|
||||
} else if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
} else if (MY_UID() == ROOT_UID && st.st_uid != ROOT_UID) {
|
||||
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
|
||||
ok = 0;
|
||||
}
|
||||
@@ -195,7 +196,7 @@ static const char *getpassf(const char *filename)
|
||||
rprintf(FERROR, "ERROR: password file must not be other-accessible\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
if (MY_UID() == ROOT_UID && st.st_uid != ROOT_UID) {
|
||||
rprintf(FERROR, "ERROR: password file must be owned by root when running as root\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
@@ -226,7 +227,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
|
||||
char *users = lp_auth_users(module);
|
||||
char challenge[MAX_DIGEST_LEN*2];
|
||||
char line[BIGPATHBUFLEN];
|
||||
char **auth_uid_groups = NULL;
|
||||
const char **auth_uid_groups = NULL;
|
||||
int auth_uid_groups_cnt = -1;
|
||||
const char *err = NULL;
|
||||
int group_match = -1;
|
||||
@@ -250,8 +251,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
|
||||
}
|
||||
*pass++ = '\0';
|
||||
|
||||
if (!(users = strdup(users)))
|
||||
out_of_memory("auth_server");
|
||||
users = strdup(users);
|
||||
|
||||
for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
|
||||
char *opts;
|
||||
@@ -287,8 +287,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
|
||||
else {
|
||||
gid_t *gid_array = gid_list.items;
|
||||
auth_uid_groups_cnt = gid_list.count;
|
||||
if ((auth_uid_groups = new_array(char *, auth_uid_groups_cnt)) == NULL)
|
||||
out_of_memory("auth_server");
|
||||
auth_uid_groups = new_array(const char *, auth_uid_groups_cnt);
|
||||
for (j = 0; j < auth_uid_groups_cnt; j++)
|
||||
auth_uid_groups[j] = gid_to_group(gid_array[j]);
|
||||
}
|
||||
@@ -314,7 +313,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
|
||||
else if (opt_ch == 'd')
|
||||
err = "denied by rule";
|
||||
else {
|
||||
char *group = group_match >= 0 ? auth_uid_groups[group_match] : NULL;
|
||||
const char *group = group_match >= 0 ? auth_uid_groups[group_match] : NULL;
|
||||
err = check_secret(module, line, group, challenge, pass);
|
||||
}
|
||||
|
||||
@@ -325,7 +324,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
|
||||
int j;
|
||||
for (j = 0; j < auth_uid_groups_cnt; j++) {
|
||||
if (auth_uid_groups[j])
|
||||
free(auth_uid_groups[j]);
|
||||
free((char*)auth_uid_groups[j]);
|
||||
}
|
||||
free(auth_uid_groups);
|
||||
}
|
||||
|
||||
5
backup.c
5
backup.c
@@ -2,7 +2,7 @@
|
||||
* Backup handling code.
|
||||
*
|
||||
* Copyright (C) 1999 Andrew Tridgell
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -304,7 +304,8 @@ int make_backup(const char *fname, BOOL prefer_rename)
|
||||
#endif
|
||||
|
||||
if (!ret && !S_ISREG(file->mode)) {
|
||||
rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
|
||||
if (INFO_GTE(NONREG, 1))
|
||||
rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
|
||||
unmake_file(file);
|
||||
#ifdef SUPPORT_ACLS
|
||||
uncache_tmp_acls();
|
||||
|
||||
11
batch.c
11
batch.c
@@ -38,13 +38,10 @@ extern int do_compression;
|
||||
extern int inplace;
|
||||
extern int append_mode;
|
||||
extern int write_batch;
|
||||
extern int xfersum_type;
|
||||
extern int protocol_version;
|
||||
extern int raw_argc, cooked_argc;
|
||||
extern char **raw_argv, **cooked_argv;
|
||||
extern char *batch_name;
|
||||
extern const char *checksum_choice;
|
||||
extern const char *compress_choice;
|
||||
#ifdef ICONV_OPTION
|
||||
extern char *iconv_opt;
|
||||
#endif
|
||||
@@ -269,14 +266,6 @@ void write_batch_shell_file(void)
|
||||
err |= write_opt("--exclude-from", "-");
|
||||
}
|
||||
|
||||
/* We need to make sure that any protocol-based or negotiated choices get accurately
|
||||
* reflected in the options we save AND that we avoid any need for --read-batch to
|
||||
* do a string-based negotiation (since we don't write them into the file). */
|
||||
if (do_compression)
|
||||
err |= write_opt("--compress-choice", compress_choice);
|
||||
if (strchr(checksum_choice, ',') || xfersum_type != parse_csum_name(NULL, -1))
|
||||
err |= write_opt("--checksum-choice", checksum_choice);
|
||||
|
||||
/* Elide the filename args from the option list, but scan for them in reverse. */
|
||||
for (i = raw_argc-1, j = cooked_argc-1; i > 0 && j >= 0; i--) {
|
||||
if (strcmp(raw_argv[i], cooked_argv[j]) == 0) {
|
||||
|
||||
109
checksum.c
109
checksum.c
@@ -27,8 +27,12 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#ifdef SUPPORT_XXHASH
|
||||
#include "xxhash.h"
|
||||
#include <xxhash.h>
|
||||
# if XXH_VERSION_NUMBER >= 800
|
||||
# define SUPPORT_XXH3 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern int am_server;
|
||||
@@ -40,6 +44,10 @@ extern const char *checksum_choice;
|
||||
|
||||
struct name_num_obj valid_checksums = {
|
||||
"checksum", NULL, NULL, 0, 0, {
|
||||
#ifdef SUPPORT_XXH3
|
||||
{ CSUM_XXH3_128, "xxh128", NULL },
|
||||
{ CSUM_XXH3_64, "xxh3", NULL },
|
||||
#endif
|
||||
#ifdef SUPPORT_XXHASH
|
||||
{ CSUM_XXH64, "xxh64", NULL },
|
||||
{ CSUM_XXH64, "xxhash", NULL },
|
||||
@@ -85,7 +93,7 @@ static const char *checksum_name(int num)
|
||||
{
|
||||
struct name_num_item *nni = get_nni_by_num(&valid_checksums, num);
|
||||
|
||||
return nni ? nni->name : num < CSUM_MD4 ? "MD4" : "UNKNOWN";
|
||||
return nni ? nni->name : num < CSUM_MD4 ? "md4" : "UNKNOWN";
|
||||
}
|
||||
|
||||
void parse_checksum_choice(int final_call)
|
||||
@@ -99,6 +107,8 @@ void parse_checksum_choice(int final_call)
|
||||
checksum_type = parse_csum_name(cp+1, -1);
|
||||
} else
|
||||
xfersum_type = checksum_type = parse_csum_name(checksum_choice, -1);
|
||||
if (am_server && checksum_choice)
|
||||
validate_choice_vs_env(NSTR_CHECKSUM, xfersum_type, checksum_type);
|
||||
}
|
||||
|
||||
if (xfersum_type == CSUM_NONE)
|
||||
@@ -133,10 +143,11 @@ int csum_len_for_type(int cst, BOOL flist_csum)
|
||||
return MD4_DIGEST_LEN;
|
||||
case CSUM_MD5:
|
||||
return MD5_DIGEST_LEN;
|
||||
#ifdef SUPPORT_XXHASH
|
||||
case CSUM_XXH64:
|
||||
case CSUM_XXH3_64:
|
||||
return 64/8;
|
||||
#endif
|
||||
case CSUM_XXH3_128:
|
||||
return 128/8;
|
||||
default: /* paranoia to prevent missing case values */
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
@@ -158,10 +169,10 @@ int canonical_checksum(int csum_type)
|
||||
case CSUM_MD4:
|
||||
case CSUM_MD5:
|
||||
return -1;
|
||||
#ifdef SUPPORT_XXHASH
|
||||
case CSUM_XXH64:
|
||||
case CSUM_XXH3_64:
|
||||
case CSUM_XXH3_128:
|
||||
return 1;
|
||||
#endif
|
||||
default: /* paranoia to prevent missing case values */
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
@@ -198,6 +209,17 @@ void get_checksum2(char *buf, int32 len, char *sum)
|
||||
case CSUM_XXH64:
|
||||
SIVAL64(sum, 0, XXH64(buf, len, checksum_seed));
|
||||
break;
|
||||
#endif
|
||||
#ifdef SUPPORT_XXH3
|
||||
case CSUM_XXH3_64:
|
||||
SIVAL64(sum, 0, XXH3_64bits_withSeed(buf, len, checksum_seed));
|
||||
break;
|
||||
case CSUM_XXH3_128: {
|
||||
XXH128_hash_t digest = XXH3_128bits_withSeed(buf, len, checksum_seed);
|
||||
SIVAL64(sum, 0, digest.low64);
|
||||
SIVAL64(sum, 8, digest.high64);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD5: {
|
||||
MD5_CTX m5;
|
||||
@@ -249,8 +271,6 @@ void get_checksum2(char *buf, int32 len, char *sum)
|
||||
free(buf1);
|
||||
buf1 = new_array(char, len+4);
|
||||
len1 = len;
|
||||
if (!buf1)
|
||||
out_of_memory("get_checksum2");
|
||||
}
|
||||
|
||||
memcpy(buf1, buf, len);
|
||||
@@ -313,6 +333,45 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
|
||||
SIVAL64(sum, 0, XXH64_digest(state));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef SUPPORT_XXH3
|
||||
case CSUM_XXH3_64: {
|
||||
static XXH3_state_t* state = NULL;
|
||||
if (!state && !(state = XXH3_createState()))
|
||||
out_of_memory("file_checksum");
|
||||
|
||||
XXH3_64bits_reset(state);
|
||||
|
||||
for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
|
||||
XXH3_64bits_update(state, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
|
||||
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0)
|
||||
XXH3_64bits_update(state, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
SIVAL64(sum, 0, XXH3_64bits_digest(state));
|
||||
break;
|
||||
}
|
||||
case CSUM_XXH3_128: {
|
||||
XXH128_hash_t digest;
|
||||
static XXH3_state_t* state = NULL;
|
||||
if (!state && !(state = XXH3_createState()))
|
||||
out_of_memory("file_checksum");
|
||||
|
||||
XXH3_128bits_reset(state);
|
||||
|
||||
for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
|
||||
XXH3_128bits_update(state, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
|
||||
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0)
|
||||
XXH3_128bits_update(state, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
digest = XXH3_128bits_digest(state);
|
||||
SIVAL64(sum, 0, digest.low64);
|
||||
SIVAL64(sum, 8, digest.high64);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD5: {
|
||||
MD5_CTX m5;
|
||||
@@ -389,6 +448,9 @@ static union {
|
||||
#ifdef SUPPORT_XXHASH
|
||||
static XXH64_state_t* xxh64_state;
|
||||
#endif
|
||||
#ifdef SUPPORT_XXH3
|
||||
static XXH3_state_t* xxh3_state;
|
||||
#endif
|
||||
static int cursum_type;
|
||||
|
||||
void sum_init(int csum_type, int seed)
|
||||
@@ -406,6 +468,18 @@ void sum_init(int csum_type, int seed)
|
||||
out_of_memory("sum_init");
|
||||
XXH64_reset(xxh64_state, 0);
|
||||
break;
|
||||
#endif
|
||||
#ifdef SUPPORT_XXH3
|
||||
case CSUM_XXH3_64:
|
||||
if (!xxh3_state && !(xxh3_state = XXH3_createState()))
|
||||
out_of_memory("sum_init");
|
||||
XXH3_64bits_reset(xxh3_state);
|
||||
break;
|
||||
case CSUM_XXH3_128:
|
||||
if (!xxh3_state && !(xxh3_state = XXH3_createState()))
|
||||
out_of_memory("sum_init");
|
||||
XXH3_128bits_reset(xxh3_state);
|
||||
break;
|
||||
#endif
|
||||
case CSUM_MD5:
|
||||
MD5_Init(&ctx.m5);
|
||||
@@ -448,6 +522,14 @@ void sum_update(const char *p, int32 len)
|
||||
case CSUM_XXH64:
|
||||
XXH64_update(xxh64_state, p, len);
|
||||
break;
|
||||
#endif
|
||||
#ifdef SUPPORT_XXH3
|
||||
case CSUM_XXH3_64:
|
||||
XXH3_64bits_update(xxh3_state, p, len);
|
||||
break;
|
||||
case CSUM_XXH3_128:
|
||||
XXH3_128bits_update(xxh3_state, p, len);
|
||||
break;
|
||||
#endif
|
||||
case CSUM_MD5:
|
||||
MD5_Update(&ctx.m5, (uchar *)p, len);
|
||||
@@ -502,6 +584,17 @@ int sum_end(char *sum)
|
||||
case CSUM_XXH64:
|
||||
SIVAL64(sum, 0, XXH64_digest(xxh64_state));
|
||||
break;
|
||||
#endif
|
||||
#ifdef SUPPORT_XXH3
|
||||
case CSUM_XXH3_64:
|
||||
SIVAL64(sum, 0, XXH3_64bits_digest(xxh3_state));
|
||||
break;
|
||||
case CSUM_XXH3_128: {
|
||||
XXH128_hash_t digest = XXH3_128bits_digest(xxh3_state);
|
||||
SIVAL64(sum, 0, digest.low64);
|
||||
SIVAL64(sum, 8, digest.high64);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD5:
|
||||
MD5_Final((uchar *)sum, &ctx.m5);
|
||||
|
||||
@@ -137,7 +137,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
if (DEBUG_GTE(EXIT, 2)) {
|
||||
rprintf(FINFO,
|
||||
"[%s] _exit_cleanup(code=%d, file=%s, line=%d): entered\n",
|
||||
who_am_i(), code, file, line);
|
||||
who_am_i(), code, src_file(file), line);
|
||||
}
|
||||
|
||||
#include "case_N.h"
|
||||
@@ -221,8 +221,9 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
/* If line < 0, this exit is after a MSG_ERROR_EXIT event, so
|
||||
* we don't want to output a duplicate error. */
|
||||
if ((exit_code && line > 0)
|
||||
|| am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1))))
|
||||
|| am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1)))) {
|
||||
log_exit(exit_code, exit_file, exit_line);
|
||||
}
|
||||
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
|
||||
36
clientname.c
36
clientname.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2020 Wayne Davison
|
||||
* Copyright (C) 2002-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -49,7 +49,7 @@ static char ipaddr_buf[100];
|
||||
|
||||
static void client_sockaddr(int fd, struct sockaddr_storage *ss, socklen_t *ss_len);
|
||||
static int check_name(const char *ipaddr, const struct sockaddr_storage *ss, char *name_buf, size_t name_buf_size);
|
||||
static int valid_ipaddr(const char *s);
|
||||
static int valid_ipaddr(const char *s, int allow_scope);
|
||||
|
||||
/* Return the IP addr of the client as a string. */
|
||||
char *client_addr(int fd)
|
||||
@@ -73,7 +73,7 @@ char *client_addr(int fd)
|
||||
if ((p = strchr(ipaddr_buf, ' ')) != NULL)
|
||||
*p = '\0';
|
||||
}
|
||||
if (valid_ipaddr(ipaddr_buf))
|
||||
if (valid_ipaddr(ipaddr_buf, True))
|
||||
return ipaddr_buf;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ char *client_name(const char *ipaddr)
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
NOISY_DEATH("Unknown ai_family value");
|
||||
}
|
||||
freeaddrinfo(answer);
|
||||
|
||||
@@ -156,7 +156,7 @@ char *client_name(const char *ipaddr)
|
||||
}
|
||||
|
||||
|
||||
/* Try to read an proxy protocol header (V1 or V2). Returns 1 on success or 0 on failure. */
|
||||
/* Try to read a proxy protocol header (V1 or V2). Returns 1 on success or 0 on failure. */
|
||||
int read_proxy_protocol_header(int fd)
|
||||
{
|
||||
union {
|
||||
@@ -213,12 +213,14 @@ int read_proxy_protocol_header(int fd)
|
||||
if (size != sizeof hdr.v2.addr.ip4)
|
||||
return 0;
|
||||
inet_ntop(AF_INET, hdr.v2.addr.ip4.src_addr, ipaddr_buf, sizeof ipaddr_buf);
|
||||
return valid_ipaddr(ipaddr_buf);
|
||||
return valid_ipaddr(ipaddr_buf, False);
|
||||
#ifdef INET6
|
||||
case PROXY_FAM_TCPv6:
|
||||
if (size != sizeof hdr.v2.addr.ip6)
|
||||
return 0;
|
||||
inet_ntop(AF_INET6, hdr.v2.addr.ip6.src_addr, ipaddr_buf, sizeof ipaddr_buf);
|
||||
return valid_ipaddr(ipaddr_buf);
|
||||
return valid_ipaddr(ipaddr_buf, False);
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -274,7 +276,7 @@ int read_proxy_protocol_header(int fd)
|
||||
if ((sp = strchr(p, ' ')) == NULL)
|
||||
return 0;
|
||||
*sp = '\0';
|
||||
if (!valid_ipaddr(p))
|
||||
if (!valid_ipaddr(p, False))
|
||||
return 0;
|
||||
strlcpy(ipaddr_buf, p, sizeof ipaddr_buf); /* It will always fit when valid. */
|
||||
|
||||
@@ -282,7 +284,7 @@ int read_proxy_protocol_header(int fd)
|
||||
if ((sp = strchr(p, ' ')) == NULL)
|
||||
return 0;
|
||||
*sp = '\0';
|
||||
if (!valid_ipaddr(p))
|
||||
if (!valid_ipaddr(p, False))
|
||||
return 0;
|
||||
/* Ignore destination address. */
|
||||
|
||||
@@ -464,7 +466,7 @@ static int check_name(const char *ipaddr, const struct sockaddr_storage *ss, cha
|
||||
}
|
||||
|
||||
/* Returns 1 for a valid IPv4 or IPv6 addr, or 0 for a bad one. */
|
||||
static int valid_ipaddr(const char *s)
|
||||
static int valid_ipaddr(const char *s, int allow_scope)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -481,7 +483,12 @@ static int valid_ipaddr(const char *s)
|
||||
|
||||
for (count = 0; count < 8; count++) {
|
||||
if (!*s)
|
||||
return saw_double_colon && count < 7;
|
||||
return saw_double_colon;
|
||||
if (allow_scope && *s == '%') {
|
||||
if (saw_double_colon)
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strchr(s, ':') == NULL && strchr(s, '.') != NULL) {
|
||||
if ((!saw_double_colon && count != 6) || (saw_double_colon && count > 6))
|
||||
@@ -507,8 +514,11 @@ static int valid_ipaddr(const char *s)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ipv4_at_end)
|
||||
return !*s;
|
||||
if (!ipv4_at_end) {
|
||||
if (allow_scope && *s == '%')
|
||||
for (s++; isAlNum(s); s++) { }
|
||||
return !*s && s[-1] != '%';
|
||||
}
|
||||
}
|
||||
|
||||
/* IPv4 */
|
||||
|
||||
307
clientserver.c
307
clientserver.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2020 Wayne Davison
|
||||
* Copyright (C) 2002-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "rsync.h"
|
||||
#include "itypes.h"
|
||||
#include "ifuncs.h"
|
||||
|
||||
extern int quiet;
|
||||
extern int dry_run;
|
||||
@@ -36,8 +37,8 @@ extern int protect_args;
|
||||
extern int ignore_errors;
|
||||
extern int preserve_xattrs;
|
||||
extern int kluge_around_eof;
|
||||
extern int daemon_over_rsh;
|
||||
extern int munge_symlinks;
|
||||
extern int open_noatime;
|
||||
extern int sanitize_paths;
|
||||
extern int numeric_ids;
|
||||
extern int filesfrom_fd;
|
||||
@@ -54,6 +55,7 @@ extern char *config_file;
|
||||
extern char *logfile_format;
|
||||
extern char *files_from;
|
||||
extern char *tmpdir;
|
||||
extern char *early_input_file;
|
||||
extern struct chmod_mode_struct *chmod_modes;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
#ifdef ICONV_OPTION
|
||||
@@ -67,8 +69,14 @@ char *auth_user;
|
||||
int read_only = 0;
|
||||
int module_id = -1;
|
||||
int pid_file_fd = -1;
|
||||
int early_input_len = 0;
|
||||
char *early_input = NULL;
|
||||
pid_t namecvt_pid = 0;
|
||||
struct chmod_mode_struct *daemon_chmod_modes;
|
||||
|
||||
#define EARLY_INPUT_CMD "#early_input="
|
||||
#define EARLY_INPUT_CMDLEN (sizeof EARLY_INPUT_CMD - 1)
|
||||
|
||||
/* module_dirlen is the length of the module_dir string when in daemon
|
||||
* mode and module_dir is not "/"; otherwise 0. (Note that a chroot-
|
||||
* enabled module can have a non-"/" module_dir these days.) */
|
||||
@@ -78,6 +86,7 @@ unsigned int module_dirlen = 0;
|
||||
char *full_module_path;
|
||||
|
||||
static int rl_nulls = 0;
|
||||
static int namecvt_fd_req = -1, namecvt_fd_ans = -1;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction sigact;
|
||||
@@ -144,14 +153,12 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int
|
||||
#else
|
||||
int our_sub = 0;
|
||||
#endif
|
||||
char *motd;
|
||||
|
||||
io_printf(f_out, "@RSYNCD: %d.%d\n", protocol_version, our_sub);
|
||||
|
||||
if (!am_client) {
|
||||
motd = lp_motd_file();
|
||||
char *motd = lp_motd_file();
|
||||
if (motd && *motd) {
|
||||
FILE *f = fopen(motd,"r");
|
||||
FILE *f = fopen(motd, "r");
|
||||
while (f && !feof(f)) {
|
||||
int len = fread(buf, 1, bufsiz - 1, f);
|
||||
if (len > 0)
|
||||
@@ -231,8 +238,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
else
|
||||
modlen = p - *argv;
|
||||
|
||||
if (!(modname = new_array(char, modlen+1+1))) /* room for '/' & '\0' */
|
||||
out_of_memory("start_inband_exchange");
|
||||
modname = new_array(char, modlen+1+1); /* room for '/' & '\0' */
|
||||
strlcpy(modname, *argv, modlen + 1);
|
||||
modname[modlen] = '/';
|
||||
modname[modlen+1] = '\0';
|
||||
@@ -245,10 +251,36 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
if (exchange_protocols(f_in, f_out, line, sizeof line, 1) < 0)
|
||||
return -1;
|
||||
|
||||
/* set daemon_over_rsh to false since we need to build the
|
||||
* true set of args passed through the rsh/ssh connection;
|
||||
* this is a no-op for direct-socket-connection mode */
|
||||
daemon_over_rsh = 0;
|
||||
if (early_input_file) {
|
||||
STRUCT_STAT st;
|
||||
FILE *f = fopen(early_input_file, "rb");
|
||||
if (!f || do_fstat(fileno(f), &st) < 0) {
|
||||
rsyserr(FERROR, errno, "failed to open %s", early_input_file);
|
||||
return -1;
|
||||
}
|
||||
early_input_len = st.st_size;
|
||||
if (early_input_len > (int)sizeof line) {
|
||||
rprintf(FERROR, "%s is > %d bytes.\n", early_input_file, (int)sizeof line);
|
||||
return -1;
|
||||
}
|
||||
if (early_input_len > 0) {
|
||||
io_printf(f_out, EARLY_INPUT_CMD "%d\n", early_input_len);
|
||||
while (early_input_len > 0) {
|
||||
int len;
|
||||
if (feof(f)) {
|
||||
rprintf(FERROR, "Early EOF in %s\n", early_input_file);
|
||||
return -1;
|
||||
}
|
||||
len = fread(line, 1, early_input_len, f);
|
||||
if (len > 0) {
|
||||
write_buf(f_out, line, len);
|
||||
early_input_len -= len;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
server_options(sargs, &sargc);
|
||||
|
||||
if (sargc >= MAX_ARGS - 2)
|
||||
@@ -348,7 +380,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PUTENV
|
||||
#if defined HAVE_SETENV || defined HAVE_PUTENV
|
||||
static int read_arg_from_pipe(int fd, char *buf, int limit)
|
||||
{
|
||||
char *bp = buf, *eob = buf + limit - 1;
|
||||
@@ -373,31 +405,65 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
|
||||
|
||||
static void set_env_str(const char *var, const char *str)
|
||||
{
|
||||
#ifdef HAVE_SETENV
|
||||
if (setenv(var, str, 1) < 0)
|
||||
out_of_memory("set_env_str");
|
||||
#else
|
||||
#ifdef HAVE_PUTENV
|
||||
char *mem;
|
||||
if (asprintf(&mem, "%s=%s", var, str) < 0)
|
||||
out_of_memory("set_env_str");
|
||||
putenv(mem);
|
||||
#else
|
||||
(void)var;
|
||||
(void)str;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined HAVE_SETENV || defined HAVE_PUTENV
|
||||
|
||||
static void set_envN_str(const char *var, int num, const char *str)
|
||||
{
|
||||
#ifdef HAVE_SETENV
|
||||
char buf[128];
|
||||
(void)snprintf(buf, sizeof buf, "%s%d", var, num);
|
||||
if (setenv(buf, str, 1) < 0)
|
||||
out_of_memory("set_env_str");
|
||||
#else
|
||||
#ifdef HAVE_PUTENV
|
||||
char *mem;
|
||||
if (asprintf(&mem, "%s%d=%s", var, num, str) < 0)
|
||||
out_of_memory("set_envN_str");
|
||||
putenv(mem);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_env_num(const char *var, long num)
|
||||
{
|
||||
#ifdef HAVE_SETENV
|
||||
char val[64];
|
||||
(void)snprintf(val, sizeof val, "%ld", num);
|
||||
if (setenv(var, val, 1) < 0)
|
||||
out_of_memory("set_env_str");
|
||||
#else
|
||||
#ifdef HAVE_PUTENV
|
||||
char *mem;
|
||||
if (asprintf(&mem, "%s=%ld", var, num) < 0)
|
||||
out_of_memory("set_env_num");
|
||||
putenv(mem);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Used for both early exec & pre-xfer exec */
|
||||
/* Used for "early exec", "pre-xfer exec", and the "name converter" script. */
|
||||
static pid_t start_pre_exec(const char *cmd, int *arg_fd_ptr, int *error_fd_ptr)
|
||||
{
|
||||
int arg_fds[2], error_fds[2], arg_fd, error_fd;
|
||||
int arg_fds[2], error_fds[2], arg_fd;
|
||||
pid_t pid;
|
||||
|
||||
if ((error_fd_ptr && pipe(error_fds) < 0) || (arg_fd_ptr && pipe(arg_fds) < 0) || (pid = fork()) < 0)
|
||||
if ((error_fd_ptr && pipe(error_fds) < 0) || pipe(arg_fds) < 0 || (pid = fork()) < 0)
|
||||
return (pid_t)-1;
|
||||
|
||||
if (pid == 0) {
|
||||
@@ -406,38 +472,34 @@ static pid_t start_pre_exec(const char *cmd, int *arg_fd_ptr, int *error_fd_ptr)
|
||||
|
||||
if (error_fd_ptr) {
|
||||
close(error_fds[0]);
|
||||
error_fd = error_fds[1];
|
||||
set_blocking(error_fd);
|
||||
set_blocking(error_fds[1]);
|
||||
}
|
||||
|
||||
if (arg_fd_ptr) {
|
||||
close(arg_fds[1]);
|
||||
arg_fd = arg_fds[0];
|
||||
set_blocking(arg_fd);
|
||||
close(arg_fds[1]);
|
||||
arg_fd = arg_fds[0];
|
||||
set_blocking(arg_fd);
|
||||
|
||||
len = read_arg_from_pipe(arg_fd, buf, BIGPATHBUFLEN);
|
||||
if (len <= 0)
|
||||
_exit(1);
|
||||
set_env_str("RSYNC_REQUEST", buf);
|
||||
|
||||
for (j = 0; ; j++) {
|
||||
len = read_arg_from_pipe(arg_fd, buf, BIGPATHBUFLEN);
|
||||
if (len <= 0)
|
||||
if (len <= 0) {
|
||||
if (!len)
|
||||
break;
|
||||
_exit(1);
|
||||
set_env_str("RSYNC_REQUEST", buf);
|
||||
|
||||
for (j = 0; ; j++) {
|
||||
char *p;
|
||||
len = read_arg_from_pipe(arg_fd, buf, BIGPATHBUFLEN);
|
||||
if (len <= 0) {
|
||||
if (!len)
|
||||
break;
|
||||
_exit(1);
|
||||
}
|
||||
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) >= 0)
|
||||
putenv(p);
|
||||
}
|
||||
close(arg_fd);
|
||||
set_envN_str("RSYNC_ARG", j, buf);
|
||||
}
|
||||
|
||||
dup2(arg_fd, STDIN_FILENO);
|
||||
close(arg_fd);
|
||||
|
||||
if (error_fd_ptr) {
|
||||
close(STDIN_FILENO);
|
||||
dup2(error_fd, STDOUT_FILENO);
|
||||
close(error_fd);
|
||||
dup2(error_fds[1], STDOUT_FILENO);
|
||||
close(error_fds[1]);
|
||||
}
|
||||
|
||||
status = shell_exec(cmd);
|
||||
@@ -449,20 +511,20 @@ static pid_t start_pre_exec(const char *cmd, int *arg_fd_ptr, int *error_fd_ptr)
|
||||
|
||||
if (error_fd_ptr) {
|
||||
close(error_fds[1]);
|
||||
error_fd = *error_fd_ptr = error_fds[0];
|
||||
set_blocking(error_fd);
|
||||
*error_fd_ptr = error_fds[0];
|
||||
set_blocking(error_fds[0]);
|
||||
}
|
||||
|
||||
if (arg_fd_ptr) {
|
||||
close(arg_fds[0]);
|
||||
arg_fd = *arg_fd_ptr = arg_fds[1];
|
||||
set_blocking(arg_fd);
|
||||
}
|
||||
close(arg_fds[0]);
|
||||
arg_fd = *arg_fd_ptr = arg_fds[1];
|
||||
set_blocking(arg_fd);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
static void write_pre_exec_args(int write_fd, char *request, char **early_argv, char **argv)
|
||||
#endif
|
||||
|
||||
static void write_pre_exec_args(int write_fd, char *request, char **early_argv, char **argv, int exec_type)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
@@ -475,11 +537,17 @@ static void write_pre_exec_args(int write_fd, char *request, char **early_argv,
|
||||
write_buf(write_fd, *early_argv, strlen(*early_argv)+1);
|
||||
j = 1; /* Skip arg0 name in argv. */
|
||||
}
|
||||
for ( ; argv[j]; j++)
|
||||
write_buf(write_fd, argv[j], strlen(argv[j])+1);
|
||||
if (argv) {
|
||||
for ( ; argv[j]; j++)
|
||||
write_buf(write_fd, argv[j], strlen(argv[j])+1);
|
||||
}
|
||||
write_byte(write_fd, 0);
|
||||
|
||||
close(write_fd);
|
||||
if (exec_type == 1 && early_input_len)
|
||||
write_buf(write_fd, early_input, early_input_len);
|
||||
|
||||
if (exec_type != 2) /* the name converter needs this left open */
|
||||
close(write_fd);
|
||||
}
|
||||
|
||||
static char *finish_pre_exec(const char *desc, pid_t pid, int read_fd)
|
||||
@@ -661,17 +729,17 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
|
||||
module_id = i;
|
||||
|
||||
if (lp_transfer_logging(i) && !logfile_format)
|
||||
logfile_format = lp_log_format(i);
|
||||
if (lp_transfer_logging(module_id) && !logfile_format)
|
||||
logfile_format = lp_log_format(module_id);
|
||||
if (log_format_has(logfile_format, 'i'))
|
||||
logfile_format_has_i = 1;
|
||||
if (logfile_format_has_i || log_format_has(logfile_format, 'o'))
|
||||
logfile_format_has_o_or_i = 1;
|
||||
|
||||
uid = MY_UID();
|
||||
am_root = (uid == 0);
|
||||
am_root = (uid == ROOT_UID);
|
||||
|
||||
p = *lp_uid(i) ? lp_uid(i) : am_root ? NOBODY_USER : NULL;
|
||||
p = *lp_uid(module_id) ? lp_uid(module_id) : am_root ? NOBODY_USER : NULL;
|
||||
if (p) {
|
||||
if (!user_to_uid(p, &uid, True)) {
|
||||
rprintf(FLOG, "Invalid uid %s\n", p);
|
||||
@@ -682,7 +750,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
} else
|
||||
set_uid = 0;
|
||||
|
||||
p = *lp_gid(i) ? conf_strtok(lp_gid(i)) : NULL;
|
||||
p = *lp_gid(module_id) ? conf_strtok(lp_gid(module_id)) : NULL;
|
||||
if (p) {
|
||||
/* The "*" gid must be the first item in the list. */
|
||||
if (strcmp(p, "*") == 0) {
|
||||
@@ -715,7 +783,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
return -1;
|
||||
}
|
||||
|
||||
module_dir = lp_path(i);
|
||||
module_dir = lp_path(module_id);
|
||||
if (*module_dir == '\0') {
|
||||
rprintf(FLOG, "No path specified for module %s\n", name);
|
||||
io_printf(f_out, "@ERROR: no path setting.\n");
|
||||
@@ -752,38 +820,39 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
} else
|
||||
set_filter_dir(module_dir, module_dirlen);
|
||||
|
||||
p = lp_filter(i);
|
||||
p = lp_filter(module_id);
|
||||
parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3);
|
||||
|
||||
p = lp_include_from(i);
|
||||
p = lp_include_from(module_id);
|
||||
parse_filter_file(&daemon_filter_list, p, rule_template(FILTRULE_INCLUDE),
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
|
||||
|
||||
p = lp_include(i);
|
||||
p = lp_include(module_id);
|
||||
parse_filter_str(&daemon_filter_list, p,
|
||||
rule_template(FILTRULE_INCLUDE | FILTRULE_WORD_SPLIT),
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
|
||||
|
||||
p = lp_exclude_from(i);
|
||||
p = lp_exclude_from(module_id);
|
||||
parse_filter_file(&daemon_filter_list, p, rule_template(0),
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
|
||||
|
||||
p = lp_exclude(i);
|
||||
p = lp_exclude(module_id);
|
||||
parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
|
||||
|
||||
log_init(1);
|
||||
|
||||
#ifdef HAVE_PUTENV
|
||||
if ((*lp_early_exec(i) || *lp_prexfer_exec(i) || *lp_postxfer_exec(i))
|
||||
#if defined HAVE_SETENV || defined HAVE_PUTENV
|
||||
if ((*lp_early_exec(module_id) || *lp_prexfer_exec(module_id)
|
||||
|| *lp_postxfer_exec(module_id) || *lp_name_converter(module_id))
|
||||
&& !getenv("RSYNC_NO_XFER_EXEC")) {
|
||||
set_env_num("RSYNC_PID", (long)getpid());
|
||||
|
||||
/* For post-xfer exec, fork a new process to run the rsync
|
||||
* daemon while this process waits for the exit status and
|
||||
* runs the indicated command at that point. */
|
||||
if (*lp_postxfer_exec(i)) {
|
||||
if (*lp_postxfer_exec(module_id)) {
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
rsyserr(FLOG, errno, "fork failed");
|
||||
@@ -803,7 +872,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
else
|
||||
status = -1;
|
||||
set_env_num("RSYNC_EXIT_STATUS", status);
|
||||
if (shell_exec(lp_postxfer_exec(i)) < 0)
|
||||
if (shell_exec(lp_postxfer_exec(module_id)) < 0)
|
||||
status = -1;
|
||||
_exit(status);
|
||||
}
|
||||
@@ -811,13 +880,15 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
|
||||
/* For early exec, fork a child process to run the indicated
|
||||
* command and wait for it to exit. */
|
||||
if (*lp_early_exec(i)) {
|
||||
pid_t pid = start_pre_exec(lp_early_exec(i), NULL, NULL);
|
||||
if (*lp_early_exec(module_id)) {
|
||||
int arg_fd;
|
||||
pid_t pid = start_pre_exec(lp_early_exec(module_id), &arg_fd, NULL);
|
||||
if (pid == (pid_t)-1) {
|
||||
rsyserr(FLOG, errno, "early exec preparation failed");
|
||||
io_printf(f_out, "@ERROR: early exec preparation failed\n");
|
||||
return -1;
|
||||
}
|
||||
write_pre_exec_args(arg_fd, NULL, NULL, NULL, 1);
|
||||
if (finish_pre_exec("early exec", pid, -1) != NULL) {
|
||||
rsyserr(FLOG, errno, "early exec failed");
|
||||
io_printf(f_out, "@ERROR: early exec failed\n");
|
||||
@@ -828,17 +899,31 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
/* For pre-xfer exec, fork a child process to run the indicated
|
||||
* command, though it first waits for the parent process to
|
||||
* send us the user's request via a pipe. */
|
||||
if (*lp_prexfer_exec(i)) {
|
||||
pre_exec_pid = start_pre_exec(lp_prexfer_exec(i), &pre_exec_arg_fd, &pre_exec_error_fd);
|
||||
if (*lp_prexfer_exec(module_id)) {
|
||||
pre_exec_pid = start_pre_exec(lp_prexfer_exec(module_id), &pre_exec_arg_fd, &pre_exec_error_fd);
|
||||
if (pre_exec_pid == (pid_t)-1) {
|
||||
rsyserr(FLOG, errno, "pre-xfer exec preparation failed");
|
||||
io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (*lp_name_converter(module_id)) {
|
||||
namecvt_pid = start_pre_exec(lp_name_converter(module_id), &namecvt_fd_req, &namecvt_fd_ans);
|
||||
if (namecvt_pid == (pid_t)-1) {
|
||||
rsyserr(FLOG, errno, "name-converter exec preparation failed");
|
||||
io_printf(f_out, "@ERROR: name-converter exec preparation failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (early_input) {
|
||||
free(early_input);
|
||||
early_input = NULL;
|
||||
}
|
||||
|
||||
if (use_chroot) {
|
||||
/*
|
||||
* XXX: The 'use chroot' flag is a fairly reliable
|
||||
@@ -865,7 +950,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
if (module_dirlen || (!use_chroot && !*lp_daemon_chroot()))
|
||||
sanitize_paths = 1;
|
||||
|
||||
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
|
||||
if ((munge_symlinks = lp_munge_symlinks(module_id)) < 0)
|
||||
munge_symlinks = !use_chroot || module_dirlen;
|
||||
if (munge_symlinks) {
|
||||
STRUCT_STAT st;
|
||||
@@ -917,11 +1002,11 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
}
|
||||
|
||||
our_uid = MY_UID();
|
||||
am_root = (our_uid == 0);
|
||||
am_root = (our_uid == ROOT_UID);
|
||||
}
|
||||
|
||||
if (lp_temp_dir(i) && *lp_temp_dir(i)) {
|
||||
tmpdir = lp_temp_dir(i);
|
||||
if (lp_temp_dir(module_id) && *lp_temp_dir(module_id)) {
|
||||
tmpdir = lp_temp_dir(module_id);
|
||||
if (strlen(tmpdir) >= MAXPATHLEN - 10) {
|
||||
rprintf(FLOG,
|
||||
"the 'temp dir' value for %s is WAY too long -- ignoring.\n",
|
||||
@@ -948,15 +1033,23 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
} else
|
||||
orig_early_argv = NULL;
|
||||
|
||||
/* The default is to use the user's setting unless the module sets True or False. */
|
||||
if (lp_open_noatime(module_id) >= 0)
|
||||
open_noatime = lp_open_noatime(module_id);
|
||||
|
||||
munge_symlinks = save_munge_symlinks; /* The client mustn't control this. */
|
||||
|
||||
if (am_daemon > 0)
|
||||
msgs2stderr = 0; /* A non-rsh-run daemon doesn't have stderr for msgs. */
|
||||
|
||||
if (pre_exec_pid) {
|
||||
write_pre_exec_args(pre_exec_arg_fd, request, orig_early_argv, orig_argv);
|
||||
write_pre_exec_args(pre_exec_arg_fd, request, orig_early_argv, orig_argv, 0);
|
||||
err_msg = finish_pre_exec("pre-xfer exec", pre_exec_pid, pre_exec_error_fd);
|
||||
}
|
||||
|
||||
if (namecvt_pid)
|
||||
write_pre_exec_args(namecvt_fd_req, request, orig_early_argv, orig_argv, 2);
|
||||
|
||||
if (orig_early_argv)
|
||||
free(orig_early_argv);
|
||||
|
||||
@@ -967,7 +1060,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
if (write_batch < 0)
|
||||
dry_run = 1;
|
||||
|
||||
if (lp_fake_super(i)) {
|
||||
if (lp_fake_super(module_id)) {
|
||||
if (preserve_xattrs > 1)
|
||||
preserve_xattrs = 1;
|
||||
am_root = -1;
|
||||
@@ -992,7 +1085,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
|
||||
#ifndef DEBUG
|
||||
/* don't allow the logs to be flooded too fast */
|
||||
limit_output_verbosity(lp_max_verbosity(i));
|
||||
limit_output_verbosity(lp_max_verbosity(module_id));
|
||||
#endif
|
||||
|
||||
if (protocol_version < 23 && (protocol_version == 22 || am_sender))
|
||||
@@ -1053,20 +1146,21 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
#endif
|
||||
|
||||
if (!numeric_ids
|
||||
&& (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
|
||||
&& (use_chroot ? lp_numeric_ids(module_id) != False && !*lp_name_converter(module_id)
|
||||
: lp_numeric_ids(module_id) == True))
|
||||
numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
|
||||
|
||||
if (lp_timeout(i) && (!io_timeout || lp_timeout(i) < io_timeout))
|
||||
set_io_timeout(lp_timeout(i));
|
||||
if (lp_timeout(module_id) && (!io_timeout || lp_timeout(module_id) < io_timeout))
|
||||
set_io_timeout(lp_timeout(module_id));
|
||||
|
||||
/* If we have some incoming/outgoing chmod changes, append them to
|
||||
* any user-specified changes (making our changes have priority).
|
||||
* We also get a pointer to just our changes so that a receiver
|
||||
* process can use them separately if --perms wasn't specified. */
|
||||
if (am_sender)
|
||||
p = lp_outgoing_chmod(i);
|
||||
p = lp_outgoing_chmod(module_id);
|
||||
else
|
||||
p = lp_incoming_chmod(i);
|
||||
p = lp_incoming_chmod(module_id);
|
||||
if (*p && !(daemon_chmod_modes = parse_chmod(p, &chmod_modes))) {
|
||||
rprintf(FLOG, "Invalid \"%sing chmod\" directive: %s\n",
|
||||
am_sender ? "outgo" : "incom", p);
|
||||
@@ -1077,6 +1171,38 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL namecvt_call(const char *cmd, const char **name_p, id_t *id_p)
|
||||
{
|
||||
char buf[1024];
|
||||
int got, len;
|
||||
|
||||
if (*name_p)
|
||||
len = snprintf(buf, sizeof buf, "%s %s\n", cmd, *name_p);
|
||||
else
|
||||
len = snprintf(buf, sizeof buf, "%s %ld\n", cmd, (long)*id_p);
|
||||
if (len >= (int)sizeof buf) {
|
||||
rprintf(FERROR, "namecvt_call() request was too large.\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
while ((got = write(namecvt_fd_req, buf, len)) != len) {
|
||||
if (got < 0 && errno == EINTR)
|
||||
continue;
|
||||
rprintf(FERROR, "Connection to name-converter failed.\n");
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
if (!read_line_old(namecvt_fd_ans, buf, sizeof buf, 0))
|
||||
return False;
|
||||
|
||||
if (*name_p)
|
||||
*id_p = (id_t)atol(buf);
|
||||
else
|
||||
*name_p = strdup(buf);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* send a list of available modules to the client. Don't list those
|
||||
with "list = False". */
|
||||
static void send_listing(int fd)
|
||||
@@ -1166,7 +1292,7 @@ int start_daemon(int f_in, int f_out)
|
||||
return -1;
|
||||
}
|
||||
our_uid = MY_UID();
|
||||
am_root = (our_uid == 0);
|
||||
am_root = (our_uid == ROOT_UID);
|
||||
}
|
||||
|
||||
addr = client_addr(f_in);
|
||||
@@ -1185,6 +1311,19 @@ int start_daemon(int f_in, int f_out)
|
||||
if (!read_line_old(f_in, line, sizeof line, 0))
|
||||
return -1;
|
||||
|
||||
if (strncmp(line, EARLY_INPUT_CMD, EARLY_INPUT_CMDLEN) == 0) {
|
||||
early_input_len = strtol(line + EARLY_INPUT_CMDLEN, NULL, 10);
|
||||
if (early_input_len <= 0 || early_input_len > BIGPATHBUFLEN) {
|
||||
io_printf(f_out, "@ERROR: invalid early_input length\n");
|
||||
return -1;
|
||||
}
|
||||
early_input = new_array(char, early_input_len);
|
||||
read_buf(f_in, early_input, early_input_len);
|
||||
|
||||
if (!read_line_old(f_in, line, sizeof line, 0))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!*line || strcmp(line, "#list") == 0) {
|
||||
rprintf(FLOG, "module-list request from %s (%s)\n",
|
||||
host, addr);
|
||||
@@ -1346,7 +1485,7 @@ int daemon_main(void)
|
||||
log_init(0);
|
||||
|
||||
rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
|
||||
RSYNC_VERSION, rsync_port);
|
||||
rsync_version(), rsync_port);
|
||||
/* TODO: If listening on a particular address, then show that
|
||||
* address too. In fact, why not just do getnameinfo on the
|
||||
* local address??? */
|
||||
|
||||
11
cmd-or-msg
Executable file
11
cmd-or-msg
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
srcdir=`dirname $0`
|
||||
opt="$1"
|
||||
shift
|
||||
|
||||
echo "$*"
|
||||
if ! "${@}"; then
|
||||
echo "If you can't fix the issue, re-run $srcdir/configure with --$opt."
|
||||
exit 1
|
||||
fi
|
||||
231
compat.c
231
compat.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) Andrew Tridgell 1996
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2004-2020 Wayne Davison
|
||||
* Copyright (C) 2004-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,6 +20,8 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "itypes.h"
|
||||
#include "ifuncs.h"
|
||||
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
@@ -42,6 +44,7 @@ extern int protect_args;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_atimes;
|
||||
extern int preserve_crtimes;
|
||||
extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int xfer_flags_as_varint;
|
||||
@@ -49,6 +52,8 @@ extern int need_messages_from_generator;
|
||||
extern int delete_mode, delete_before, delete_during, delete_after;
|
||||
extern int do_compression;
|
||||
extern int do_compression_level;
|
||||
extern int saw_stderr_opt;
|
||||
extern int msgs2stderr;
|
||||
extern char *shell_cmd;
|
||||
extern char *partial_dir;
|
||||
extern char *files_from;
|
||||
@@ -72,9 +77,10 @@ int want_xattr_optim = 0;
|
||||
int proper_seed_order = 0;
|
||||
int inplace_partial = 0;
|
||||
int do_negotiated_strings = 0;
|
||||
int xmit_id0_names = 0;
|
||||
|
||||
/* These index values are for the file-list's extra-attribute array. */
|
||||
int pathname_ndx, depth_ndx, atimes_ndx, uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
|
||||
int pathname_ndx, depth_ndx, atimes_ndx, crtimes_ndx, uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
|
||||
|
||||
int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
|
||||
int sender_symlink_iconv = 0; /* sender should convert symlink content */
|
||||
@@ -108,6 +114,7 @@ struct name_num_obj valid_compressions = {
|
||||
#define CF_CHKSUM_SEED_FIX (1<<5)
|
||||
#define CF_INPLACE_PARTIAL_DIR (1<<6)
|
||||
#define CF_VARINT_FLIST_FLAGS (1<<7)
|
||||
#define CF_ID0_NAMES (1<<8)
|
||||
|
||||
static const char *client_info;
|
||||
|
||||
@@ -149,7 +156,13 @@ static void check_sub_protocol(void)
|
||||
|
||||
void set_allow_inc_recurse(void)
|
||||
{
|
||||
client_info = shell_cmd ? shell_cmd : "";
|
||||
if (!local_server)
|
||||
client_info = shell_cmd ? shell_cmd : "";
|
||||
else if (am_server) {
|
||||
char buf[64];
|
||||
maybe_add_e_option(buf, sizeof buf);
|
||||
client_info = *buf ? strdup(buf+1) : ""; /* The +1 skips the leading "e". */
|
||||
}
|
||||
|
||||
if (!recurse || use_qsort)
|
||||
allow_inc_recurse = 0;
|
||||
@@ -157,8 +170,7 @@ void set_allow_inc_recurse(void)
|
||||
&& (delete_before || delete_after
|
||||
|| delay_updates || prune_empty_dirs))
|
||||
allow_inc_recurse = 0;
|
||||
else if (am_server && !local_server
|
||||
&& (strchr(client_info, 'i') == NULL))
|
||||
else if (am_server && strchr(client_info, 'i') == NULL)
|
||||
allow_inc_recurse = 0;
|
||||
}
|
||||
|
||||
@@ -173,6 +185,8 @@ void parse_compress_choice(int final_call)
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
do_compression = nni->num;
|
||||
if (am_server)
|
||||
validate_choice_vs_env(NSTR_COMPRESS, do_compression, -1);
|
||||
} else if (do_compression)
|
||||
do_compression = CPRES_ZLIB;
|
||||
else
|
||||
@@ -241,8 +255,7 @@ static void init_nno_saw(struct name_num_obj *nno, int val)
|
||||
}
|
||||
|
||||
if (!nno->saw) {
|
||||
if (!(nno->saw = new_array0(uchar, nno->saw_len)))
|
||||
out_of_memory("init_nno_saw");
|
||||
nno->saw = new_array0(uchar, nno->saw_len);
|
||||
|
||||
/* We'll take this opportunity to make sure that the main_name values are set right. */
|
||||
for (cnt = 1, nni = nno->list; nni->name; nni++, cnt++) {
|
||||
@@ -261,10 +274,14 @@ static void init_nno_saw(struct name_num_obj *nno, int val)
|
||||
static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf, int tobuf_len)
|
||||
{
|
||||
char *to = tobuf, *tok = NULL;
|
||||
int cnt = 0;
|
||||
int saw_tok = 0, cnt = 0;
|
||||
|
||||
while (1) {
|
||||
if (*from == ' ' || !*from) {
|
||||
int at_space = isSpace(from);
|
||||
char ch = *from++;
|
||||
if (ch == '&')
|
||||
ch = '\0';
|
||||
if (!ch || at_space) {
|
||||
if (tok) {
|
||||
struct name_num_item *nni = get_nni_by_name(nno, tok, to - tok);
|
||||
if (nni && !nno->saw[nni->num]) {
|
||||
@@ -278,9 +295,10 @@ static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf
|
||||
}
|
||||
} else
|
||||
to = tok - (tok != tobuf);
|
||||
saw_tok = 1;
|
||||
tok = NULL;
|
||||
}
|
||||
if (!*from++)
|
||||
if (!ch)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
@@ -293,13 +311,19 @@ static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf
|
||||
to = tok - (tok != tobuf);
|
||||
break;
|
||||
}
|
||||
*to++ = *from++;
|
||||
*to++ = ch;
|
||||
}
|
||||
*to = '\0';
|
||||
|
||||
if (saw_tok && to == tobuf)
|
||||
return strlcpy(tobuf, "INVALID", MAX_NSTR_STRLEN);
|
||||
|
||||
return to - tobuf;
|
||||
}
|
||||
|
||||
/* This routine is always called with a tmpbuf of MAX_NSTR_STRLEN length, but the
|
||||
* buffer may be pre-populated with a "len" length string to use OR a len of -1
|
||||
* to tell us to read a string from the fd. */
|
||||
static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf, int len)
|
||||
{
|
||||
struct name_num_item *ret = NULL;
|
||||
@@ -315,17 +339,26 @@ static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf,
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
struct name_num_item *nni;
|
||||
int best = nno->saw_len; /* We want best == 1 from the client list, so start with a big number. */
|
||||
char *tok;
|
||||
if (am_server)
|
||||
init_nno_saw(nno, 1); /* Since we're parsing client names, anything we parse first is #1. */
|
||||
for (tok = strtok(tmpbuf, " \t"); tok; tok = strtok(NULL, " \t")) {
|
||||
struct name_num_item *nni = get_nni_by_name(nno, tok, -1);
|
||||
char *space, *tok = tmpbuf;
|
||||
while (tok) {
|
||||
while (*tok == ' ') tok++; /* Should be unneeded... */
|
||||
if (!*tok)
|
||||
break;
|
||||
if ((space = strchr(tok, ' ')) != NULL)
|
||||
*space = '\0';
|
||||
nni = get_nni_by_name(nno, tok, -1);
|
||||
if (space) {
|
||||
*space = ' ';
|
||||
tok = space + 1;
|
||||
} else
|
||||
tok = NULL;
|
||||
if (!nni || !nno->saw[nni->num] || best <= nno->saw[nni->num])
|
||||
continue;
|
||||
ret = nni;
|
||||
best = nno->saw[nni->num];
|
||||
if (best == 1)
|
||||
if (best == 1 || am_server) /* The server side stops at the first acceptable client choice */
|
||||
break;
|
||||
}
|
||||
if (ret) {
|
||||
@@ -337,15 +370,84 @@ static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf,
|
||||
}
|
||||
}
|
||||
|
||||
if (!am_server)
|
||||
rprintf(FERROR, "Failed to negotiate a common %s\n", nno->type);
|
||||
if (!am_server || !do_negotiated_strings) {
|
||||
char *cp = tmpbuf;
|
||||
int j;
|
||||
rprintf(FERROR, "Failed to negotiate a %s choice.\n", nno->type);
|
||||
rprintf(FERROR, "%s list: %s\n", am_server ? "Client" : "Server", tmpbuf);
|
||||
/* Recreate our original list from the saw values. This can't overflow our huge
|
||||
* buffer because we don't have enough valid entries to get anywhere close. */
|
||||
for (j = 1, *cp = '\0'; j <= nno->saw_len; j++) {
|
||||
struct name_num_item *nni;
|
||||
for (nni = nno->list; nni->name; nni++) {
|
||||
if (nno->saw[nni->num] == j) {
|
||||
*cp++ = ' ';
|
||||
cp += strlcpy(cp, nni->name, MAX_NSTR_STRLEN - (cp - tmpbuf));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!*tmpbuf)
|
||||
strlcpy(cp, " INVALID", MAX_NSTR_STRLEN);
|
||||
rprintf(FERROR, "%s list:%s\n", am_server ? "Server" : "Client", tmpbuf);
|
||||
}
|
||||
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
static const char *getenv_nstr(int ntype)
|
||||
{
|
||||
const char *env_str = getenv(ntype == NSTR_COMPRESS ? "RSYNC_COMPRESS_LIST" : "RSYNC_CHECKSUM_LIST");
|
||||
|
||||
/* When writing a batch file, we always negotiate an old-style choice. */
|
||||
if (write_batch)
|
||||
env_str = ntype == NSTR_COMPRESS ? "zlib" : protocol_version >= 30 ? "md5" : "md4";
|
||||
|
||||
if (am_server && env_str) {
|
||||
char *cp = strchr(env_str, '&');
|
||||
if (cp)
|
||||
env_str = cp + 1;
|
||||
}
|
||||
|
||||
return env_str;
|
||||
}
|
||||
|
||||
void validate_choice_vs_env(int ntype, int num1, int num2)
|
||||
{
|
||||
struct name_num_obj *nno = ntype == NSTR_COMPRESS ? &valid_compressions : &valid_checksums;
|
||||
const char *list_str = getenv_nstr(ntype);
|
||||
char tmpbuf[MAX_NSTR_STRLEN];
|
||||
|
||||
if (!list_str)
|
||||
return;
|
||||
|
||||
while (isSpace(list_str)) list_str++;
|
||||
|
||||
if (!*list_str)
|
||||
return;
|
||||
|
||||
init_nno_saw(nno, 0);
|
||||
parse_nni_str(nno, list_str, tmpbuf, MAX_NSTR_STRLEN);
|
||||
|
||||
if (ntype == NSTR_CHECKSUM) /* If "md4" is in the env list, all the old MD4 choices are OK too. */
|
||||
nno->saw[CSUM_MD4_ARCHAIC] = nno->saw[CSUM_MD4_BUSTED] = nno->saw[CSUM_MD4_OLD] = nno->saw[CSUM_MD4];
|
||||
|
||||
if (!nno->saw[num1] || (num2 >= 0 && !nno->saw[num2])) {
|
||||
rprintf(FERROR, "Your --%s-choice value (%s) was refused by the server.\n",
|
||||
ntype == NSTR_COMPRESS ? "compress" : "checksum",
|
||||
ntype == NSTR_COMPRESS ? compress_choice : checksum_choice);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
free(nno->saw);
|
||||
nno->saw = NULL;
|
||||
}
|
||||
|
||||
/* The saw buffer is initialized and used to store ordinal values from 1 to N
|
||||
* for the order of the args in the array. If dup_markup == '\0', duplicates
|
||||
* are removed otherwise the char is prefixed to the duplicate term and, if it
|
||||
* is an opening paren/bracket/brace, the matching closing char is suffixed. */
|
||||
* is an opening paren/bracket/brace, the matching closing char is suffixed.
|
||||
* "none" is removed on the client side unless dup_markup != '\0'. */
|
||||
int get_default_nno_list(struct name_num_obj *nno, char *to_buf, int to_buf_len, char dup_markup)
|
||||
{
|
||||
struct name_num_item *nni;
|
||||
@@ -367,6 +469,8 @@ int get_default_nno_list(struct name_num_obj *nno, char *to_buf, int to_buf_len,
|
||||
continue;
|
||||
delim = dup_markup;
|
||||
}
|
||||
if (nni->num == 0 && !am_server && !dup_markup)
|
||||
continue;
|
||||
if (len)
|
||||
to_buf[len++]= ' ';
|
||||
if (delim) {
|
||||
@@ -386,25 +490,15 @@ int get_default_nno_list(struct name_num_obj *nno, char *to_buf, int to_buf_len,
|
||||
return len;
|
||||
}
|
||||
|
||||
static void send_negotiate_str(int f_out, struct name_num_obj *nno, const char *env_name)
|
||||
static void send_negotiate_str(int f_out, struct name_num_obj *nno, int ntype)
|
||||
{
|
||||
char tmpbuf[MAX_NSTR_STRLEN];
|
||||
const char *list_str = getenv(env_name);
|
||||
int len, fail_if_empty = list_str && strstr(list_str, "FAIL");
|
||||
const char *list_str = getenv_nstr(ntype);
|
||||
int len;
|
||||
|
||||
if (!do_negotiated_strings) {
|
||||
if (!am_server && fail_if_empty) {
|
||||
rprintf(FERROR, "Remote rsync is too old for %s negotiation\n", nno->type);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (list_str && *list_str && (!am_server || local_server)) {
|
||||
if (list_str && *list_str) {
|
||||
init_nno_saw(nno, 0);
|
||||
len = parse_nni_str(nno, list_str, tmpbuf, MAX_NSTR_STRLEN);
|
||||
if (fail_if_empty && !len)
|
||||
len = strlcpy(tmpbuf, "FAIL", MAX_NSTR_STRLEN);
|
||||
list_str = tmpbuf;
|
||||
} else
|
||||
list_str = NULL;
|
||||
@@ -419,15 +513,10 @@ static void send_negotiate_str(int f_out, struct name_num_obj *nno, const char *
|
||||
rprintf(FINFO, "Client %s list (on client): %s\n", nno->type, tmpbuf);
|
||||
}
|
||||
|
||||
if (local_server) {
|
||||
/* A local server doesn't bother to send/recv the strings, it just constructs
|
||||
* and parses the same string on both sides. */
|
||||
recv_negotiate_str(-1, nno, tmpbuf, len);
|
||||
} else {
|
||||
/* Each side sends their list of valid names to the other side and then both sides
|
||||
* pick the first name in the client's list that is also in the server's list. */
|
||||
/* Each side sends their list of valid names to the other side and then both sides
|
||||
* pick the first name in the client's list that is also in the server's list. */
|
||||
if (do_negotiated_strings)
|
||||
write_vstring(f_out, tmpbuf, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void negotiate_the_strings(int f_in, int f_out)
|
||||
@@ -435,20 +524,35 @@ static void negotiate_the_strings(int f_in, int f_out)
|
||||
/* We send all the negotiation strings before we start to read them to help avoid a slow startup. */
|
||||
|
||||
if (!checksum_choice)
|
||||
send_negotiate_str(f_out, &valid_checksums, "RSYNC_CHECKSUM_LIST");
|
||||
send_negotiate_str(f_out, &valid_checksums, NSTR_CHECKSUM);
|
||||
|
||||
if (do_compression && !compress_choice)
|
||||
send_negotiate_str(f_out, &valid_compressions, "RSYNC_COMPRESS_LIST");
|
||||
send_negotiate_str(f_out, &valid_compressions, NSTR_COMPRESS);
|
||||
|
||||
if (valid_checksums.saw) {
|
||||
char tmpbuf[MAX_NSTR_STRLEN];
|
||||
recv_negotiate_str(f_in, &valid_checksums, tmpbuf, -1);
|
||||
int len;
|
||||
if (do_negotiated_strings)
|
||||
len = -1;
|
||||
else
|
||||
len = strlcpy(tmpbuf, protocol_version >= 30 ? "md5" : "md4", MAX_NSTR_STRLEN);
|
||||
recv_negotiate_str(f_in, &valid_checksums, tmpbuf, len);
|
||||
}
|
||||
|
||||
if (valid_compressions.saw) {
|
||||
char tmpbuf[MAX_NSTR_STRLEN];
|
||||
recv_negotiate_str(f_in, &valid_compressions, tmpbuf, -1);
|
||||
int len;
|
||||
if (do_negotiated_strings)
|
||||
len = -1;
|
||||
else
|
||||
len = strlcpy(tmpbuf, "zlib", MAX_NSTR_STRLEN);
|
||||
recv_negotiate_str(f_in, &valid_compressions, tmpbuf, len);
|
||||
}
|
||||
|
||||
/* If the other side is too old to negotiate, the above steps just made sure that
|
||||
* the env didn't disallow the old algorithm. Mark things as non-negotiated. */
|
||||
if (!do_negotiated_strings)
|
||||
valid_checksums.negotiated_name = valid_compressions.negotiated_name = NULL;
|
||||
}
|
||||
|
||||
void setup_protocol(int f_out,int f_in)
|
||||
@@ -460,7 +564,9 @@ void setup_protocol(int f_out,int f_in)
|
||||
* aligned for direct int64-pointer memory access. */
|
||||
if (preserve_atimes)
|
||||
atimes_ndx = (file_extra_cnt += EXTRA64_CNT);
|
||||
if (am_sender) /* This is most likely in the in64 union as well. */
|
||||
if (preserve_crtimes)
|
||||
crtimes_ndx = (file_extra_cnt += EXTRA64_CNT);
|
||||
if (am_sender) /* This is most likely in the file_extras64 union as well. */
|
||||
pathname_ndx = (file_extra_cnt += PTR_EXTRA_CNT);
|
||||
else
|
||||
depth_ndx = ++file_extra_cnt;
|
||||
@@ -518,6 +624,9 @@ void setup_protocol(int f_out,int f_in)
|
||||
if (read_batch)
|
||||
check_batch_flags();
|
||||
|
||||
if (!saw_stderr_opt && protocol_version <= 28 && am_server)
|
||||
msgs2stderr = 0; /* The client side may not have stderr setup for us. */
|
||||
|
||||
#ifndef SUPPORT_PREALLOCATION
|
||||
if (preallocate_files && !am_sender) {
|
||||
rprintf(FERROR, "preallocation is not supported on this %s\n",
|
||||
@@ -593,19 +702,19 @@ void setup_protocol(int f_out,int f_in)
|
||||
#ifdef ICONV_OPTION
|
||||
compat_flags |= CF_SYMLINK_ICONV;
|
||||
#endif
|
||||
if (local_server || strchr(client_info, 'f') != NULL)
|
||||
if (strchr(client_info, 'f') != NULL)
|
||||
compat_flags |= CF_SAFE_FLIST;
|
||||
if (local_server || strchr(client_info, 'x') != NULL)
|
||||
if (strchr(client_info, 'x') != NULL)
|
||||
compat_flags |= CF_AVOID_XATTR_OPTIM;
|
||||
if (local_server || strchr(client_info, 'C') != NULL)
|
||||
if (strchr(client_info, 'C') != NULL)
|
||||
compat_flags |= CF_CHKSUM_SEED_FIX;
|
||||
if (local_server || strchr(client_info, 'I') != NULL)
|
||||
if (strchr(client_info, 'I') != NULL)
|
||||
compat_flags |= CF_INPLACE_PARTIAL_DIR;
|
||||
if (local_server || strchr(client_info, 'v') != NULL) {
|
||||
if (!write_batch || protocol_version >= 30) {
|
||||
do_negotiated_strings = 1;
|
||||
compat_flags |= CF_VARINT_FLIST_FLAGS;
|
||||
}
|
||||
if (strchr(client_info, 'u') != NULL)
|
||||
compat_flags |= CF_ID0_NAMES;
|
||||
if (strchr(client_info, 'v') != NULL) {
|
||||
do_negotiated_strings = 1;
|
||||
compat_flags |= CF_VARINT_FLIST_FLAGS;
|
||||
}
|
||||
if (strchr(client_info, 'V') != NULL) { /* Support a pre-release 'V' that got superseded */
|
||||
if (!write_batch)
|
||||
@@ -623,6 +732,11 @@ void setup_protocol(int f_out,int f_in)
|
||||
want_xattr_optim = protocol_version >= 31 && !(compat_flags & CF_AVOID_XATTR_OPTIM);
|
||||
proper_seed_order = compat_flags & CF_CHKSUM_SEED_FIX ? 1 : 0;
|
||||
xfer_flags_as_varint = compat_flags & CF_VARINT_FLIST_FLAGS ? 1 : 0;
|
||||
xmit_id0_names = compat_flags & CF_ID0_NAMES ? 1 : 0;
|
||||
if (!xfer_flags_as_varint && preserve_crtimes) {
|
||||
fprintf(stderr, "Both rsync versions must be at least 3.2.0 for --crtimes.\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (am_sender) {
|
||||
receiver_symlink_times = am_server
|
||||
? strchr(client_info, 'L') != NULL
|
||||
@@ -634,7 +748,7 @@ void setup_protocol(int f_out,int f_in)
|
||||
#endif
|
||||
#ifdef ICONV_OPTION
|
||||
sender_symlink_iconv = iconv_opt && (am_server
|
||||
? local_server || strchr(client_info, 's') != NULL
|
||||
? strchr(client_info, 's') != NULL
|
||||
: !!(compat_flags & CF_SYMLINK_ICONV));
|
||||
#endif
|
||||
if (inc_recurse && !allow_inc_recurse) {
|
||||
@@ -654,6 +768,9 @@ void setup_protocol(int f_out,int f_in)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (read_batch)
|
||||
do_negotiated_strings = 0;
|
||||
|
||||
if (need_unsorted_flist && (!am_sender || inc_recurse))
|
||||
unsort_ndx = ++file_extra_cnt;
|
||||
|
||||
|
||||
28
configure
vendored
28
configure
vendored
@@ -4,24 +4,24 @@
|
||||
# then transfer control to the configure.sh script to do the real work.
|
||||
|
||||
dir=`dirname $0`
|
||||
realconfigure="$dir/configure.sh"
|
||||
if test x"$dir" = x; then
|
||||
dir=.
|
||||
fi
|
||||
|
||||
if test ! -f "$realconfigure"; then
|
||||
if test -f "$HOME/build_farm/build_test.fns"; then
|
||||
# Test the included popt
|
||||
set -- --with-included-popt "${@}"
|
||||
# Allow the build farm to grab latest files via rsync.
|
||||
actions='build fetch'
|
||||
else
|
||||
actions='build'
|
||||
if test "$dir" = '.'; then
|
||||
branch=`packaging/prep-auto-dir` || exit 1
|
||||
if test x"$branch" != x; then
|
||||
cd build || exit 1
|
||||
dir=..
|
||||
fi
|
||||
if "$dir/prepare-source" $actions; then
|
||||
:
|
||||
else
|
||||
fi
|
||||
|
||||
if test ! -f configure.sh; then
|
||||
if ! "$dir/prepare-source" build; then
|
||||
echo 'Failed to build configure.sh and/or config.h.in -- giving up.' >&2
|
||||
rm -f "$realconfigure"
|
||||
rm -f configure.sh
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "$realconfigure" "${@}"
|
||||
exec ./configure.sh --srcdir="$dir" "${@}"
|
||||
|
||||
566
configure.ac
566
configure.ac
@@ -1,16 +1,30 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT([rsync],[3.2.0pre3],[http://rsync.samba.org/bugzilla.html])
|
||||
AC_INIT([rsync],[ ],[https://rsync.samba.org/bug-tracking.html])
|
||||
|
||||
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 compat.h sys/param.h ctype.h sys/wait.h sys/stat.h \
|
||||
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h grp.h \
|
||||
sys/un.h sys/attr.h arpa/inet.h arpa/nameser.h locale.h sys/types.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h mcheck.h \
|
||||
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h dl.h \
|
||||
popt.h popt/popt.h linux/falloc.h netinet/in_systm.h netgroup.h \
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h sys/file.h)
|
||||
AC_CHECK_HEADERS([netinet/ip.h], [], [], [[#include <netinet/in.h>]])
|
||||
AC_HEADER_MAJOR_FIXED
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
AC_SUBST(RSYNC_VERSION, $PACKAGE_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $PACKAGE_VERSION])
|
||||
PACKAGE_VERSION=`sed 's/.*"\(.*\)".*/\1/' <$srcdir/version.h`
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$PACKAGE_VERSION"], [rsync release version])
|
||||
AC_MSG_NOTICE([Configuring rsync $PACKAGE_VERSION])
|
||||
|
||||
LDFLAGS=${LDFLAGS-""}
|
||||
|
||||
@@ -27,7 +41,7 @@ AC_CONFIG_LIBOBJ_DIR([lib])
|
||||
|
||||
AC_MSG_CHECKING([whether to include debugging symbols])
|
||||
AC_ARG_ENABLE(debug,
|
||||
AS_HELP_STRING([--disable-debug],[disable debugging symbols and features]))
|
||||
AS_HELP_STRING([--disable-debug],[disable to omit debugging symbols and features]))
|
||||
|
||||
if test x"$enable_debug" = x"no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -42,6 +56,7 @@ dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXX
|
||||
AC_PROG_AWK
|
||||
AC_PROG_EGREP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MKDIR_P
|
||||
@@ -57,8 +72,13 @@ if test x"$ac_cv_prog_cc_stdc" = x"no"; then
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you do not seem to have one])
|
||||
fi
|
||||
|
||||
no_lib=''
|
||||
err_msg=''
|
||||
nl='
|
||||
'
|
||||
|
||||
AC_ARG_ENABLE(profile,
|
||||
AS_HELP_STRING([--enable-profile],[turn on CPU profiling]))
|
||||
AS_HELP_STRING([--enable-profile],[enable to turn on CPU profiling]))
|
||||
if test x"$enable_profile" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -pg"
|
||||
fi
|
||||
@@ -68,7 +88,7 @@ if test x"$ac_cv_path_PYTHON3" = x; then
|
||||
AC_MSG_RESULT(no - python3 not found)
|
||||
md2man_works=no
|
||||
else
|
||||
md2man_out=`"$srcdir/md2man" --test "$srcdir/rsync.1.md" 2>&1`
|
||||
md2man_out=`"$srcdir/md2man" --test "$srcdir/rsync-ssl.1.md" 2>&1`
|
||||
if test $? = 0; then
|
||||
AC_MSG_RESULT(yes)
|
||||
md2man_works=yes
|
||||
@@ -81,26 +101,27 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([if we require man-page building])
|
||||
AC_ARG_ENABLE([md2man],
|
||||
AS_HELP_STRING([--disable-md2man],[disable md2man for man page creation]))
|
||||
AS_HELP_STRING([--disable-md2man],[disable to omit man page creation]))
|
||||
if test x"$enable_md2man" != x"no"; then
|
||||
if test -f "$srcdir/rsync.1"; then
|
||||
AC_MSG_RESULT(optional)
|
||||
else
|
||||
AC_MSG_RESULT(required)
|
||||
if test x"$md2man_works" = x"no"; then
|
||||
AC_MSG_ERROR(You need python3 and the cmarkgfm OR commonmark python3 lib in order to build man pages.
|
||||
You can specify --disable-md2man if you want to skip building them.)
|
||||
err_msg="$err_msg$nl- You need python3 and either the cmarkgfm OR commonmark python3 lib in order"
|
||||
err_msg="$err_msg$nl to build man pages based on the git source (man pages are included in the"
|
||||
err_msg="$err_msg$nl official release tar files)."
|
||||
no_lib="$no_lib md2man"
|
||||
fi
|
||||
fi
|
||||
MAKE_MAN=man
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
MAKE_MAN=''
|
||||
fi
|
||||
|
||||
# Specifically, this turns on panic_action handling.
|
||||
AC_ARG_ENABLE(maintainer-mode,
|
||||
AS_HELP_STRING([--enable-maintainer-mode],[turn on extra debug features]))
|
||||
AS_HELP_STRING([--enable-maintainer-mode],[enable to turn on extra debug features]))
|
||||
if test x"$enable_maintainer_mode" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
|
||||
fi
|
||||
@@ -114,6 +135,16 @@ if test x"$GCC" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -Wall -W"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(rrsync,
|
||||
AS_HELP_STRING([--with-rrsync],[also install the rrsync script and its man page]))
|
||||
if test x"$with_rrsync" != x"yes"; then
|
||||
with_rrsync=no
|
||||
else
|
||||
MAKE_RRSYNC='rrsync'
|
||||
MAKE_RRSYNC_1='rrsync.1'
|
||||
fi
|
||||
AC_SUBST(with_rrsync)
|
||||
|
||||
AC_ARG_WITH(included-popt,
|
||||
AS_HELP_STRING([--with-included-popt],[use bundled popt library, not from system]))
|
||||
|
||||
@@ -173,6 +204,11 @@ AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
|
||||
AC_PATH_PROG(SHELL_PATH, sh, /bin/sh, [/usr/xpg4/bin$PATH_SEPARATOR$PATH])
|
||||
AC_PATH_PROG(FAKEROOT_PATH, fakeroot, /usr/bin/fakeroot, [/usr/xpg4/bin$PATH_SEPARATOR$PATH])
|
||||
|
||||
AC_ARG_WITH(nobody-user,
|
||||
AS_HELP_STRING([--with-nobody-user=USER],[set the default unprivileged user (default nobody)]),
|
||||
[ NOBODY_USER="$with_nobody_user" ],
|
||||
[ NOBODY_USER="nobody" ])
|
||||
|
||||
AC_ARG_WITH(nobody-group,
|
||||
AS_HELP_STRING([--with-nobody-group=GROUP],[set the default unprivileged group (default nobody or nogroup)]),
|
||||
[ NOBODY_GROUP="$with_nobody_group" ])
|
||||
@@ -189,7 +225,7 @@ if test x"$with_nobody_group" = x; then
|
||||
AC_MSG_RESULT($NOBODY_GROUP)
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(NOBODY_USER, "nobody", [unprivileged user--e.g. nobody])
|
||||
AC_DEFINE_UNQUOTED(NOBODY_USER, "$NOBODY_USER", [unprivileged user--e.g. nobody])
|
||||
AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unprivileged user])
|
||||
|
||||
# SIMD optimizations
|
||||
@@ -197,35 +233,127 @@ SIMD=
|
||||
|
||||
AC_MSG_CHECKING([whether to enable SIMD optimizations])
|
||||
AC_ARG_ENABLE(simd,
|
||||
AS_HELP_STRING([--enable-simd],[enable SIMD optimizations (requires g++)]))
|
||||
AS_HELP_STRING([--enable-simd],[enable/disable to control SIMD optimizations (requires c++)]))
|
||||
|
||||
if test x"$enable_simd" = x"yes"; then
|
||||
# For x86-64 SIMD, g++ is also required
|
||||
if test x"$build_cpu" = x"x86_64"; then
|
||||
if test x"$CXX" = x"g++"; then
|
||||
# AC_MSG_RESULT() called below
|
||||
SIMD="$SIMD x86_64"
|
||||
# Clag is crashing with -g -O2, so we'll get rid of -g for now.
|
||||
CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-g //'`
|
||||
m4_define(SIMD_X86_64_TEST, [[#include <stdio.h>
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <immintrin.h>
|
||||
__attribute__ ((target("default"))) int test_ssse3(int x) { return x; }
|
||||
__attribute__ ((target("default"))) int test_sse2(int x) { return x; }
|
||||
__attribute__ ((target("default"))) int test_avx2(int x) { return x; }
|
||||
__attribute__ ((target("ssse3"))) int test_ssse3(int x) { return x; }
|
||||
__attribute__ ((target("sse2"))) int test_sse2(int x) { return x; }
|
||||
__attribute__ ((target("avx2"))) int test_avx2(int x) { return x; }
|
||||
typedef long long __m128i_u __attribute__((__vector_size__(16), __may_alias__, __aligned__(1)));
|
||||
typedef long long __m256i_u __attribute__((__vector_size__(32), __may_alias__, __aligned__(1)));
|
||||
__attribute__ ((target("default"))) void more_testing(char* buf, int len) { }
|
||||
__attribute__ ((target("ssse3"))) void more_testing(char* buf, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (len-32); i+=32) {
|
||||
__m128i in8_1, in8_2;
|
||||
in8_1 = _mm_lddqu_si128((__m128i_u*)&buf[i]);
|
||||
in8_2 = _mm_lddqu_si128((__m128i_u*)&buf[i + 16]);
|
||||
}
|
||||
}
|
||||
]])
|
||||
|
||||
if test x"$enable_simd" = x""; then
|
||||
case "$host_os" in
|
||||
*linux*) ;;
|
||||
*) enable_simd=no ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x"$enable_simd" != x"no"; then
|
||||
# For x86-64 SIMD, g++ >=5 or clang++ >=7 is required
|
||||
if test x"$host_cpu" = x"x86_64" || test x"$host_cpu" = x"amd64"; then
|
||||
AC_LANG(C++)
|
||||
if test x"$host" = x"$build"; then
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([SIMD_X86_64_TEST],[[if (test_ssse3(42) != 42 || test_sse2(42) != 42 || test_avx2(42) != 42) exit(1);]])],
|
||||
[CXX_OK=yes],[CXX_OK=no])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR(Failed to find g++ for SIMD speedups.
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([SIMD_X86_64_TEST])],[CXX_OK=yes],[CXX_OK=no])
|
||||
fi
|
||||
AC_LANG(C)
|
||||
if test x"$CXX_OK" = x"yes"; then
|
||||
# AC_MSG_RESULT() is called below.
|
||||
SIMD="$host_cpu"
|
||||
elif test x"$enable_simd" = x"yes"; then
|
||||
AC_MSG_RESULT(error)
|
||||
AC_MSG_ERROR(The SIMD compilation test failed.
|
||||
Omit --enable-simd to continue without it.)
|
||||
fi
|
||||
elif test x"$enable_simd" = x"yes"; then
|
||||
AC_MSG_RESULT(unavailable)
|
||||
AC_MSG_ERROR(The SIMD optimizations are currently x86_64|amd64 only.
|
||||
Omit --enable-simd to continue without it.)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x"$SIMD" != x""; then
|
||||
SIMD=`echo "$SIMD" | sed -e 's/^ *//'`
|
||||
AC_MSG_RESULT([yes ($SIMD)])
|
||||
AC_DEFINE(HAVE_SIMD, 1, [Define to 1 to enable SIMD optimizations])
|
||||
SIMD=`echo "$SIMD" | sed -e 's/[[^ ]]\+/$(SIMD_&)/g'`
|
||||
# We only use g++ for its target attribute dispatching, disable unneeded bulky features
|
||||
SIMD='$(SIMD_'"$SIMD)"
|
||||
# We only use c++ for its target attribute dispatching, disable unneeded bulky features
|
||||
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-rtti"
|
||||
# Apple often has "g++" as a symlink for clang. Try to find out the truth.
|
||||
CXX_VERSION=`$CXX --version 2>/dev/null | head -n 2`
|
||||
case "$CXX_VERSION" in
|
||||
*clang*) CXXFLAGS="$CXXFLAGS -fno-slp-vectorize" ;; # avoid a performance hit
|
||||
esac
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_SUBST(SIMD)
|
||||
|
||||
AC_MSG_CHECKING([if assembler accepts noexecstack])
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wa,--noexecstack"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[return 0;]])],
|
||||
[ NOEXECSTACK='-Wa,--noexecstack' ; AC_MSG_RESULT(yes) ],
|
||||
[ NOEXECSTACK='' ; AC_MSG_RESULT(no) ])
|
||||
CFLAGS="$OLD_CFLAGS"
|
||||
AC_SUBST(NOEXECSTACK)
|
||||
|
||||
ASM=
|
||||
|
||||
AC_MSG_CHECKING([whether to enable ASM optimizations])
|
||||
AC_ARG_ENABLE(asm,
|
||||
AS_HELP_STRING([--enable-asm],[enable/disable to control ASM optimizations]))
|
||||
|
||||
if test x"$enable_asm" = x""; then
|
||||
case "$host_os" in
|
||||
*linux*) ;;
|
||||
*) enable_asm=no ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x"$enable_asm" != x"no"; then
|
||||
if test x"$host_cpu" = x"x86_64" || test x"$host_cpu" = x"amd64"; then
|
||||
ASM="$host_cpu"
|
||||
elif test x"$enable_asm" = x"yes"; then
|
||||
AC_MSG_RESULT(unavailable)
|
||||
AC_MSG_ERROR(The ASM optimizations are currently x86_64|amd64 only.
|
||||
Omit --enable-asm to continue without it.)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x"$ASM" != x""; then
|
||||
AC_MSG_RESULT([yes ($ASM)])
|
||||
AC_DEFINE(HAVE_ASM, 1, [Define to 1 to enable ASM optimizations])
|
||||
ASM='$(ASM_'"$ASM)"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_SUBST(ASM)
|
||||
|
||||
# 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,[
|
||||
@@ -233,7 +361,9 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/wait.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@@ -269,123 +399,39 @@ if test x"$rsync_cv_HAVE_BROKEN_LARGEFILE" != x"yes"; then
|
||||
AC_SYS_LARGEFILE
|
||||
fi
|
||||
|
||||
ipv6type=unknown
|
||||
ipv6lib=none
|
||||
ipv6trylibc=yes
|
||||
|
||||
AC_MSG_CHECKING([whether to enable ipv6])
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
AS_HELP_STRING([--disable-ipv6],[turn off IPv6 support]))
|
||||
if test x"$enable_ipv6" != x"no"; then
|
||||
AC_MSG_CHECKING([ipv6 stack type])
|
||||
for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta cygwin; 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
|
||||
;;
|
||||
solaris)
|
||||
# http://www.sun.com
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <netinet/ip6.h>
|
||||
#ifdef __sun
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
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])])
|
||||
;;
|
||||
cygwin)
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <netinet/in.h>
|
||||
#ifdef _CYGWIN_IN6_H
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
esac
|
||||
if test "$ipv6type" != "unknown"; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
AC_MSG_RESULT($ipv6type)
|
||||
AS_HELP_STRING([--disable-ipv6],[disable to omit ipv6 support]),
|
||||
[ case "$enableval" in
|
||||
no)
|
||||
AC_MSG_RESULT(no)
|
||||
;;
|
||||
*) AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])
|
||||
;;
|
||||
esac ],
|
||||
|
||||
AC_SEARCH_LIBS(getaddrinfo, inet6)
|
||||
fi
|
||||
AC_TRY_RUN([ /* AF_INET6 avalable check */
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
main()
|
||||
{
|
||||
if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
|
||||
exit(1);
|
||||
else
|
||||
exit(0);
|
||||
}
|
||||
],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6]),
|
||||
AC_MSG_RESULT(no),
|
||||
AC_MSG_RESULT(no)
|
||||
))
|
||||
|
||||
dnl Do you want to disable use of locale functions
|
||||
AC_ARG_ENABLE([locale],
|
||||
AS_HELP_STRING([--disable-locale],[disable locale features]))
|
||||
AS_HELP_STRING([--disable-locale],[disable to omit locale features]))
|
||||
AH_TEMPLATE([CONFIG_LOCALE],
|
||||
[Undefine if you do not want locale features. By default this is defined.])
|
||||
if test x"$enable_locale" != x"no"; then
|
||||
@@ -401,23 +447,9 @@ case $host_os in
|
||||
* ) 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 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 sys/attr.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 \
|
||||
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h \
|
||||
popt.h popt/popt.h linux/falloc.h netinet/in_systm.h netinet/ip.h \
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h)
|
||||
AC_HEADER_MAJOR_FIXED
|
||||
|
||||
AC_MSG_CHECKING([whether to enable use of openssl crypto library])
|
||||
AC_ARG_ENABLE([openssl],
|
||||
AS_HELP_STRING([--disable-openssl],[disable openssl crypto library]))
|
||||
AS_HELP_STRING([--disable-openssl],[disable to omit openssl crypto library]))
|
||||
AH_TEMPLATE([USE_OPENSSL],
|
||||
[Undefine if you do not want to use openssl crypto library. By default this is defined.])
|
||||
if test x"$enable_openssl" != x"no"; then
|
||||
@@ -425,12 +457,12 @@ if test x"$enable_openssl" != x"no"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_SEARCH_LIBS(MD5_Init, crypto,
|
||||
[AC_DEFINE(USE_OPENSSL)],
|
||||
[AC_MSG_ERROR(Failed to find MD5_Init function in openssl crypto lib.
|
||||
Use --disable-openssl to continue without openssl crypto lib support.)])
|
||||
[err_msg="$err_msg$nl- Failed to find MD5_Init function in openssl crypto lib.";
|
||||
no_lib="$no_lib openssl"])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR(Failed to find openssl/md4.h and openssl/md5.h for openssl crypto lib support.
|
||||
Use --disable-openssl to continue without it.)
|
||||
err_msg="$err_msg$nl- Failed to find openssl/md4.h and openssl/md5.h for openssl crypto lib support."
|
||||
no_lib="$no_lib openssl"
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -438,7 +470,7 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([whether to enable xxhash checksum support])
|
||||
AC_ARG_ENABLE([xxhash],
|
||||
AS_HELP_STRING([--disable-xxhash],[disable xxhash checksums]))
|
||||
AS_HELP_STRING([--disable-xxhash],[disable to omit xxhash checksums]))
|
||||
AH_TEMPLATE([SUPPORT_XXHASH],
|
||||
[Undefine if you do not want xxhash checksums. By default this is defined.])
|
||||
if test x"$enable_xxhash" != x"no"; then
|
||||
@@ -446,12 +478,12 @@ if test x"$enable_xxhash" != x"no"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_SEARCH_LIBS(XXH64_createState, xxhash,
|
||||
[AC_DEFINE(SUPPORT_XXHASH)],
|
||||
[AC_MSG_ERROR(Failed to find XXH64_createState function in xxhash lib.
|
||||
Use --disable-xxhash to continue without xxhash checksums.)])
|
||||
[err_msg="$err_msg$nl- Failed to find XXH64_createState function in xxhash lib.";
|
||||
no_lib="$no_lib xxhash"])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR(Failed to find xxhash.h for xxhash checksum support.
|
||||
Use --disable-xxhash to continue without it.)
|
||||
err_msg="$err_msg$nl- Failed to find xxhash.h for xxhash checksum support.";
|
||||
no_lib="$no_lib xxhash"
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -459,7 +491,7 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([whether to enable zstd compression])
|
||||
AC_ARG_ENABLE([zstd],
|
||||
AC_HELP_STRING([--disable-zstd], [disable zstd compression]))
|
||||
AC_HELP_STRING([--disable-zstd], [disable to omit zstd compression]))
|
||||
AH_TEMPLATE([SUPPORT_ZSTD],
|
||||
[Undefine if you do not want zstd compression. By default this is defined.])
|
||||
if test x"$enable_zstd" != x"no"; then
|
||||
@@ -467,12 +499,12 @@ if test x"$enable_zstd" != x"no"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_SEARCH_LIBS(ZSTD_minCLevel, zstd,
|
||||
[AC_DEFINE(SUPPORT_ZSTD)],
|
||||
[AC_MSG_ERROR(Failed to find ZSTD_minCLevel function in zstd lib.
|
||||
Use --disable-zstd to continue without zstd compression.)])
|
||||
[err_msg="$err_msg$nl- Failed to find ZSTD_minCLevel function in zstd lib.";
|
||||
no_lib="$no_lib zstd"])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR(Failed to find zstd.h for zstd compression support.
|
||||
Use --disable-zstd to continue without it.)
|
||||
err_msg="$err_msg$nl- Failed to find zstd.h for zstd compression support.";
|
||||
no_lib="$no_lib zstd"
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -480,7 +512,7 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([whether to enable LZ4 compression])
|
||||
AC_ARG_ENABLE([lz4],
|
||||
AC_HELP_STRING([--disable-lz4], [disable LZ4 compression]))
|
||||
AC_HELP_STRING([--disable-lz4], [disable to omit LZ4 compression]))
|
||||
AH_TEMPLATE([SUPPORT_LZ4],
|
||||
[Undefine if you do not want LZ4 compression. By default this is defined.])
|
||||
if test x"$enable_lz4" != x"no"; then
|
||||
@@ -488,20 +520,39 @@ if test x"$enable_lz4" != x"no"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_SEARCH_LIBS(LZ4_compress_default, lz4,
|
||||
[AC_DEFINE(SUPPORT_LZ4)],
|
||||
[AC_MSG_ERROR(Failed to find LZ4_compress_default function in lz4 lib.
|
||||
Use --disable-lz4 to continue without lz4 compression.)])
|
||||
[err_msg="$err_msg$nl- Failed to find LZ4_compress_default function in lz4 lib.";
|
||||
no_lib="$no_lib lz4"])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR(Failed to find lz4.h for lz4 compression support.
|
||||
Use --disable-lz4 to continue without it.)
|
||||
err_msg="$err_msg$nl- Failed to find lz4.h for lz4 compression support."
|
||||
no_lib="$no_lib lz4"
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
if test x"$no_lib" != x; then
|
||||
echo ""
|
||||
echo "Configure found the following issues:"
|
||||
echo "$err_msg"
|
||||
echo ""
|
||||
echo "See the INSTALL file for hints on how to install the missing libraries and/or"
|
||||
echo "how to generate (or fetch) man pages:"
|
||||
echo " https://github.com/WayneD/rsync/blob/master/INSTALL.md"
|
||||
echo ""
|
||||
echo "To disable one or more features, the relevant configure options are:"
|
||||
for lib in $no_lib; do
|
||||
echo " --disable-$lib"
|
||||
done
|
||||
echo ""
|
||||
AC_MSG_ERROR(Aborting configure run)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef MAJOR_IN_MKDEV
|
||||
#include <sys/mkdev.h>
|
||||
# if !defined makedev && (defined mkdev || defined _WIN32 || defined __WIN32__)
|
||||
@@ -617,7 +668,9 @@ AC_SEARCH_LIBS(libiconv_open, iconv)
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
@@ -630,7 +683,7 @@ size_t iconv();
|
||||
#endif
|
||||
]], [[]])],[am_cv_proto_iconv_arg1=""],[am_cv_proto_iconv_arg1="const"])
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed 's/( /(/'`
|
||||
AC_MSG_RESULT([$]{ac_t:-
|
||||
}[$]am_cv_proto_iconv)
|
||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
||||
@@ -641,31 +694,47 @@ dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
|
||||
AC_REPLACE_FUNCS([inet_ntop inet_pton])
|
||||
|
||||
AC_HAVE_TYPE([struct addrinfo], [#include <netdb.h>])
|
||||
AC_HAVE_TYPE([struct sockaddr_storage], [#include <sys/types.h>
|
||||
#include <sys/socket.h>])
|
||||
AC_HAVE_TYPE([struct sockaddr_storage], [
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif])
|
||||
|
||||
# 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],
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef AI_PASSIVE
|
||||
yes
|
||||
#endif],
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=yes,
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=no)])
|
||||
AS_IF([test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes" -a x"$ac_cv_type_struct_addrinfo" = x"yes"],[
|
||||
AS_IF([test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes" && test x"$ac_cv_type_struct_addrinfo" = x"yes"],[
|
||||
# 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_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>]], [[getaddrinfo(NULL, NULL, NULL, NULL);]])],[AC_MSG_RESULT([yes])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#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 and required types.])],[AC_MSG_RESULT([no])
|
||||
AC_LIBOBJ([getaddrinfo])])])
|
||||
@@ -675,16 +744,24 @@ AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_LEN, 1, [Do we have sockaddr.sa_len?]) ],
|
||||
[],
|
||||
[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_IN_LEN, 1, [Do we have sockaddr_in.sin_len?]) ],
|
||||
[],
|
||||
[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
@@ -692,8 +769,12 @@ AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_UN_LEN, 1, [Do we have sockaddr_un.sun_len?]) ],
|
||||
[],
|
||||
[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
@@ -701,8 +782,12 @@ 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?]) ],
|
||||
[],
|
||||
[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
@@ -742,15 +827,16 @@ dnl AC_FUNC_MEMCMP
|
||||
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_FUNC_ALLOCA
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd chown chmod lchmod mknod mkfifo \
|
||||
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
|
||||
chflags getattrlist \
|
||||
chflags getattrlist mktime innetgr linkat \
|
||||
memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
|
||||
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
|
||||
strlcat strlcpy strtol mallinfo mallinfo2 getgroups setgroups geteuid getegid \
|
||||
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
|
||||
seteuid strerror putenv iconv_open locale_charset nl_langinfo getxattr \
|
||||
extattr_get_link sigaction sigprocmask setattrlist getgrouplist \
|
||||
initgroups utimensat posix_fallocate attropen setvbuf nanosleep usleep)
|
||||
initgroups utimensat posix_fallocate attropen setvbuf nanosleep usleep \
|
||||
setenv unsetenv)
|
||||
|
||||
dnl cygwin iconv.h defines iconv_open as libiconv_open
|
||||
if test x"$ac_cv_func_iconv_open" != x"yes"; then
|
||||
@@ -761,7 +847,9 @@ dnl Preallocation stuff (also fallocate, posix_fallocate function tests above):
|
||||
|
||||
AC_CACHE_CHECK([for useable fallocate],rsync_cv_have_fallocate,[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h>
|
||||
#include <sys/types.h>]], [[fallocate(0, 0, 0, 0);]])],[rsync_cv_have_fallocate=yes],[rsync_cv_have_fallocate=no])])
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif]], [[fallocate(0, 0, 0, 0);]])],[rsync_cv_have_fallocate=yes],[rsync_cv_have_fallocate=no])])
|
||||
if test x"$rsync_cv_have_fallocate" = x"yes"; then
|
||||
AC_DEFINE(HAVE_FALLOCATE, 1, [Define to 1 if you have the fallocate function and it compiles and links without error])
|
||||
fi
|
||||
@@ -798,8 +886,12 @@ AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
|
||||
|
||||
AC_CACHE_CHECK([for SYS_fallocate],rsync_cv_have_sys_fallocate,[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/syscall.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>]], [[syscall(SYS_fallocate, 0, 0, (loff_t)0, (loff_t)0);]])],[rsync_cv_have_sys_fallocate=yes],[rsync_cv_have_sys_fallocate=no])])
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif]], [[syscall(SYS_fallocate, 0, 0, (loff_t)0, (loff_t)0);]])],[rsync_cv_have_sys_fallocate=yes],[rsync_cv_have_sys_fallocate=no])])
|
||||
if test x"$rsync_cv_have_sys_fallocate" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SYS_FALLOCATE, 1, [Define to 1 if you have the SYS_fallocate syscall number])
|
||||
fi
|
||||
@@ -826,7 +918,7 @@ if test $ac_cv_func_getpgrp = yes; then
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(iconv-open,
|
||||
AS_HELP_STRING([--disable-iconv-open],[disable all use of iconv_open() function]),
|
||||
AS_HELP_STRING([--disable-iconv-open],[disable to avoid all use of iconv_open()]),
|
||||
[], [enable_iconv_open=$ac_cv_func_iconv_open])
|
||||
|
||||
if test x"$enable_iconv_open" != x"no"; then
|
||||
@@ -834,7 +926,7 @@ if test x"$enable_iconv_open" != x"no"; then
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(iconv,
|
||||
AS_HELP_STRING([--disable-iconv],[disable rsync's --iconv option]),
|
||||
AS_HELP_STRING([--disable-iconv],[disable to omit the --iconv option]),
|
||||
[], [enable_iconv=$enable_iconv_open])
|
||||
AH_TEMPLATE([ICONV_OPTION],
|
||||
[Define if you want the --iconv option. Specifying a value will set the
|
||||
@@ -868,6 +960,11 @@ fi
|
||||
|
||||
AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_symlink,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#elif defined HAVE_SYS_FCNTL_H
|
||||
# include <sys/fcntl.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
@@ -878,7 +975,11 @@ int main(void) {
|
||||
unlink(FILENAME);
|
||||
if (symlink("conftest.no-such", FILENAME) < 0) abort();
|
||||
unlink(FILENAME "2");
|
||||
#ifdef HAVE_LINKAT
|
||||
if (linkat(AT_FDCWD, FILENAME, AT_FDCWD, FILENAME "2", 0) < 0) return 1;
|
||||
#else
|
||||
if (link(FILENAME, FILENAME "2") < 0) return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}]])],[rsync_cv_can_hardlink_symlink=yes],[rsync_cv_can_hardlink_symlink=no],[rsync_cv_can_hardlink_symlink=no])])
|
||||
if test $rsync_cv_can_hardlink_symlink = yes; then
|
||||
@@ -909,8 +1010,12 @@ fi
|
||||
|
||||
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
int fd[2];
|
||||
@@ -935,6 +1040,21 @@ elif test x"$ac_cv_header_popt_h" != x"yes"; then
|
||||
with_included_popt=yes
|
||||
fi
|
||||
|
||||
if test x"$GCC" = x"yes"; then
|
||||
if test x"$with_included_popt" != x"yes"; then
|
||||
# Turn pedantic warnings into errors to ensure an array-init overflow is an error.
|
||||
CFLAGS="$CFLAGS -pedantic-errors"
|
||||
else
|
||||
# Our internal popt code cannot be compiled with pedantic warnings as errors, so try to
|
||||
# turn off pedantic warnings (which will not lose the error for array-init overflow).
|
||||
# Older gcc versions don't understand -Wno-pedantic, so check if --help=warnings lists
|
||||
# -Wpedantic and use that as a flag.
|
||||
case `$CC --help=warnings 2>/dev/null | grep Wpedantic` in
|
||||
*-Wpedantic*) CFLAGS="$CFLAGS -pedantic-errors -Wno-pedantic" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to use included libpopt])
|
||||
if test x"$with_included_popt" = x"yes"; then
|
||||
AC_MSG_RESULT($srcdir/popt)
|
||||
@@ -977,7 +1097,10 @@ if test x"$rsync_cv_SIGNED_CHAR_OK" = x"yes"; then
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <sys/types.h>
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <dirent.h>
|
||||
int main(void) { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
|
||||
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
|
||||
@@ -987,7 +1110,10 @@ if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_STRUCT_UTIMBUF,[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <utime.h>]], [[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; return utime("foo.c",&tbuf);]])],[rsync_cv_HAVE_STRUCT_UTIMBUF=yes],[rsync_cv_HAVE_STRUCT_UTIMBUF=no])])
|
||||
if test x"$rsync_cv_HAVE_STRUCT_UTIMBUF" = x"yes"; then
|
||||
AC_DEFINE(HAVE_STRUCT_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
|
||||
@@ -995,17 +1121,23 @@ fi
|
||||
|
||||
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/time.h>
|
||||
#include <unistd.h>]], [[struct timeval tv; return gettimeofday(&tv, NULL);]])],[rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes],[rsync_cv_HAVE_GETTIMEOFDAY_TZ=no])])
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif]], [[struct timeval tv; return 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_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
void foo(const char *format, ...) {
|
||||
va_list ap;
|
||||
@@ -1028,9 +1160,13 @@ fi
|
||||
|
||||
AC_CACHE_CHECK([for secure mkstemp],rsync_cv_HAVE_SECURE_MKSTEMP,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
int main(void) {
|
||||
struct stat st;
|
||||
char tpl[20]="/tmp/test.XXXXXX";
|
||||
@@ -1119,6 +1255,8 @@ AC_SUBST(OBJ_RESTORE)
|
||||
AC_SUBST(CC_SHOBJ_FLAG)
|
||||
AC_SUBST(BUILD_POPT)
|
||||
AC_SUBST(BUILD_ZLIB)
|
||||
AC_SUBST(MAKE_RRSYNC)
|
||||
AC_SUBST(MAKE_RRSYNC_1)
|
||||
AC_SUBST(MAKE_MAN)
|
||||
|
||||
AC_CHECK_FUNCS(_acl __acl _facl __facl)
|
||||
@@ -1127,7 +1265,7 @@ AC_CHECK_FUNCS(_acl __acl _facl __facl)
|
||||
|
||||
AC_MSG_CHECKING([whether to support ACLs])
|
||||
AC_ARG_ENABLE(acl-support,
|
||||
AS_HELP_STRING([--disable-acl-support],[disable ACL support]))
|
||||
AS_HELP_STRING([--disable-acl-support],[disable to omit ACL support]))
|
||||
|
||||
if test x"$enable_acl_support" = x"no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -1143,11 +1281,6 @@ else
|
||||
AC_DEFINE(HAVE_SOLARIS_ACLS, 1, [true if you have solaris ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*hpux*)
|
||||
AC_MSG_RESULT(Using HPUX ACLs)
|
||||
AC_DEFINE(HAVE_HPUX_ACLS, 1, [true if you have HPUX ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*irix*)
|
||||
AC_MSG_RESULT(Using IRIX ACLs)
|
||||
AC_DEFINE(HAVE_IRIX_ACLS, 1, [true if you have IRIX ACLs])
|
||||
@@ -1169,20 +1302,35 @@ else
|
||||
AC_DEFINE(HAVE_OSX_ACLS, 1, [true if you have Mac OS X ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*hpux*|*nsk*)
|
||||
AC_MSG_RESULT(Using HPUX ACLs)
|
||||
AC_DEFINE(HAVE_HPUX_ACLS, 1, [true if you have HPUX ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT(running tests:)
|
||||
AC_CHECK_LIB(acl,acl_get_file)
|
||||
AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
||||
#include <sys/acl.h>]], [[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);]])],[samba_cv_HAVE_POSIX_ACLS=yes],[samba_cv_HAVE_POSIX_ACLS=no])])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ACL_H
|
||||
#include <sys/acl.h>
|
||||
#endif]], [[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);]])],[samba_cv_HAVE_POSIX_ACLS=yes],[samba_cv_HAVE_POSIX_ACLS=no])])
|
||||
AC_MSG_CHECKING(ACL test results)
|
||||
if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
|
||||
AC_MSG_RESULT(Using posix ACLs)
|
||||
AC_DEFINE(HAVE_POSIX_ACLS, 1, [true if you have posix ACLs])
|
||||
AC_DEFINE(SUPPORT_ACLS, 1)
|
||||
AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
||||
#include <sys/acl.h>]], [[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);]])],[samba_cv_HAVE_ACL_GET_PERM_NP=yes],[samba_cv_HAVE_ACL_GET_PERM_NP=no])])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ACL_H
|
||||
#include <sys/acl.h>
|
||||
#endif]], [[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);]])],[samba_cv_HAVE_ACL_GET_PERM_NP=yes],[samba_cv_HAVE_ACL_GET_PERM_NP=no])])
|
||||
if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
|
||||
AC_DEFINE(HAVE_ACL_GET_PERM_NP, 1, [true if you have acl_get_perm_np])
|
||||
fi
|
||||
@@ -1201,7 +1349,7 @@ fi
|
||||
# check for extended attribute support
|
||||
AC_MSG_CHECKING(whether to support extended attributes)
|
||||
AC_ARG_ENABLE(xattr-support,
|
||||
AS_HELP_STRING([--disable-xattr-support],[disable extended attributes]),
|
||||
AS_HELP_STRING([--disable-xattr-support],[disable to omit extended attributes]),
|
||||
[], [case "$ac_cv_func_getxattr$ac_cv_func_extattr_get_link$ac_cv_func_attropen" in
|
||||
*yes*) enable_xattr_support=maybe ;;
|
||||
*) enable_xattr_support=no ;;
|
||||
@@ -1212,7 +1360,7 @@ if test x"$enable_xattr_support" = x"no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
case "$host_os" in
|
||||
*linux*|*netbsd*)
|
||||
*linux*|*netbsd*|*cygwin*)
|
||||
AC_MSG_RESULT(Using Linux xattrs)
|
||||
AC_DEFINE(HAVE_LINUX_XATTRS, 1, [True if you have Linux xattrs (or equivalent)])
|
||||
AC_DEFINE(SUPPORT_XATTRS, 1)
|
||||
@@ -1247,7 +1395,7 @@ else
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"$enable_iconv" = x"no"; then
|
||||
if test x"$enable_acl_support" = x"no" || test x"$enable_xattr_support" = x"no" || test x"$enable_iconv" = x"no"; then
|
||||
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wno-unused-parameter"
|
||||
@@ -1268,5 +1416,5 @@ AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT([ rsync $PACKAGE_VERSION configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
114
daemon-parm.awk
Executable file
114
daemon-parm.awk
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/awk -f
|
||||
|
||||
# The caller must pass arg: daemon-parm.txt
|
||||
# The resulting code is output into daemon-parm.h
|
||||
|
||||
BEGIN {
|
||||
heading = "/* DO NOT EDIT THIS FILE! It is auto-generated from a list of values in " ARGV[1] "! */\n\n"
|
||||
sect = psect = defines = accessors = prior_ptype = ""
|
||||
parms = "\nstatic struct parm_struct parm_table[] = {"
|
||||
comment_fmt = "\n/********** %s **********/\n"
|
||||
tdstruct = "typedef struct {"
|
||||
}
|
||||
|
||||
/^\s*$/ { next }
|
||||
/^#/ { next }
|
||||
|
||||
/^Globals:/ {
|
||||
if (defines != "") {
|
||||
print "The Globals section must come first!"
|
||||
defines = ""
|
||||
exit
|
||||
}
|
||||
defines = tdstruct
|
||||
values = "\nstatic const all_vars Defaults = {\n { /* Globals: */\n"
|
||||
exps = exp_values = sprintf(comment_fmt, "EXP")
|
||||
sect = "GLOBAL"
|
||||
psect = ", P_GLOBAL, &Vars.g."
|
||||
next
|
||||
}
|
||||
|
||||
/^Locals:/ {
|
||||
if (sect == "") {
|
||||
print "The Locals section must come after the Globals!"
|
||||
exit
|
||||
}
|
||||
defines = defines exps "} global_vars;\n\n" tdstruct
|
||||
values = values exp_values "\n }, { /* Locals: */\n"
|
||||
exps = exp_values = sprintf(comment_fmt, "EXP")
|
||||
sect = "LOCAL"
|
||||
psect = ", P_LOCAL, &Vars.l."
|
||||
next
|
||||
}
|
||||
|
||||
/^(STRING|CHAR|PATH|INTEGER|ENUM|OCTAL|BOOL|BOOLREV|BOOL3)[ \t]/ {
|
||||
ptype = $1
|
||||
name = $2
|
||||
$1 = $2 = ""
|
||||
sub(/^[ \t]+/, "")
|
||||
|
||||
if (ptype != prior_ptype) {
|
||||
comment = sprintf(comment_fmt, ptype)
|
||||
defines = defines comment
|
||||
values = values comment
|
||||
parms = parms "\n"
|
||||
accessors = accessors "\n"
|
||||
prior_ptype = ptype
|
||||
}
|
||||
|
||||
if (ptype == "STRING" || ptype == "PATH") {
|
||||
atype = "STRING"
|
||||
vtype = "char*"
|
||||
} else if (ptype ~ /BOOL/) {
|
||||
atype = vtype = "BOOL"
|
||||
} else if (ptype == "CHAR") {
|
||||
atype = "CHAR"
|
||||
vtype = "char"
|
||||
} else {
|
||||
atype = "INTEGER"
|
||||
vtype = "int"
|
||||
}
|
||||
|
||||
# The name might be var_name|public_name
|
||||
pubname = name
|
||||
sub(/\|.*/, "", name)
|
||||
sub(/.*\|/, "", pubname)
|
||||
gsub(/_/, " ", pubname)
|
||||
gsub(/-/, "", name)
|
||||
|
||||
if (ptype == "ENUM")
|
||||
enum = "enum_" name
|
||||
else
|
||||
enum = "NULL"
|
||||
|
||||
defines = defines "\t" vtype " " name ";\n"
|
||||
values = values "\t" $0 ", /* " name " */\n"
|
||||
parms = parms " {\"" pubname "\", P_" ptype psect name ", " enum ", 0},\n"
|
||||
accessors = accessors "FN_" sect "_" atype "(lp_" name ", " name ")\n"
|
||||
|
||||
if (vtype == "char*") {
|
||||
exps = exps "\tBOOL " name "_EXP;\n"
|
||||
exp_values = exp_values "\tFalse, /* " name "_EXP */\n"
|
||||
}
|
||||
|
||||
next
|
||||
}
|
||||
|
||||
/./ {
|
||||
print "Extraneous line:" $0
|
||||
defines = ""
|
||||
exit
|
||||
}
|
||||
|
||||
END {
|
||||
if (sect != "" && defines != "") {
|
||||
defines = defines exps "} local_vars;\n\n"
|
||||
defines = defines tdstruct "\n\tglobal_vars g;\n\tlocal_vars l;\n} all_vars;\n"
|
||||
values = values exp_values "\n }\n};\n\nstatic all_vars Vars;\n"
|
||||
parms = parms "\n {NULL, P_BOOL, P_NONE, NULL, NULL, 0}\n};\n"
|
||||
print heading defines values parms accessors > "daemon-parm.h"
|
||||
} else {
|
||||
print "Failed to parse the data in " ARGV[1]
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
68
daemon-parm.txt
Normal file
68
daemon-parm.txt
Normal file
@@ -0,0 +1,68 @@
|
||||
Globals: ================================================================
|
||||
|
||||
STRING bind_address|address NULL
|
||||
STRING daemon_chroot NULL
|
||||
STRING daemon_gid NULL
|
||||
STRING daemon_uid NULL
|
||||
STRING motd_file NULL
|
||||
STRING pid_file NULL
|
||||
STRING socket_options NULL
|
||||
|
||||
INTEGER listen_backlog 5
|
||||
INTEGER rsync_port|port 0
|
||||
|
||||
BOOL proxy_protocol False
|
||||
|
||||
Locals: =================================================================
|
||||
|
||||
STRING auth_users NULL
|
||||
STRING charset NULL
|
||||
STRING comment NULL
|
||||
STRING dont_compress DEFAULT_DONT_COMPRESS
|
||||
STRING early_exec NULL
|
||||
STRING exclude NULL
|
||||
STRING exclude_from NULL
|
||||
STRING filter NULL
|
||||
STRING gid NULL
|
||||
STRING hosts_allow NULL
|
||||
STRING hosts_deny NULL
|
||||
STRING include NULL
|
||||
STRING include_from NULL
|
||||
STRING incoming_chmod NULL
|
||||
STRING lock_file DEFAULT_LOCK_FILE
|
||||
STRING log_file NULL
|
||||
STRING log_format "%o %h [%a] %m (%u) %f %l"
|
||||
STRING name NULL
|
||||
STRING name_converter NULL
|
||||
STRING outgoing_chmod NULL
|
||||
STRING post-xfer_exec NULL
|
||||
STRING pre-xfer_exec NULL
|
||||
STRING refuse_options NULL
|
||||
STRING secrets_file NULL
|
||||
STRING syslog_tag "rsyncd"
|
||||
STRING uid NULL
|
||||
|
||||
PATH path NULL
|
||||
PATH temp_dir NULL
|
||||
|
||||
INTEGER max_connections 0
|
||||
INTEGER max_verbosity 1
|
||||
INTEGER timeout 0
|
||||
|
||||
ENUM syslog_facility LOG_DAEMON
|
||||
|
||||
BOOL fake_super False
|
||||
BOOL forward_lookup True
|
||||
BOOL ignore_errors False
|
||||
BOOL ignore_nonreadable False
|
||||
BOOL list True
|
||||
BOOL read_only True
|
||||
BOOL reverse_lookup True
|
||||
BOOL strict_modes True
|
||||
BOOL transfer_logging False
|
||||
BOOL use_chroot True
|
||||
BOOL write_only False
|
||||
|
||||
BOOL3 munge_symlinks Unset
|
||||
BOOL3 numeric_ids Unset
|
||||
BOOL3 open_noatime Unset
|
||||
41
define-from-md.awk
Executable file
41
define-from-md.awk
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/awk -f
|
||||
|
||||
# The caller must pass args: -v hfile=NAME rsync.1.md
|
||||
|
||||
BEGIN {
|
||||
heading = "/* DO NOT EDIT THIS FILE! It is auto-generated from a list of values in " ARGV[1] "! */"
|
||||
if (hfile ~ /compress/) {
|
||||
define = "#define DEFAULT_DONT_COMPRESS"
|
||||
prefix = "*."
|
||||
} else {
|
||||
define = "#define DEFAULT_CVSIGNORE"
|
||||
prefix = ""
|
||||
}
|
||||
value_list = ""
|
||||
}
|
||||
|
||||
/^ > [^ ]+$/ {
|
||||
gsub(/`/, "")
|
||||
if (value_list != "") value_list = value_list " "
|
||||
value_list = value_list prefix $2
|
||||
next
|
||||
}
|
||||
|
||||
value_list ~ /\.gz / && hfile ~ /compress/ {
|
||||
exit
|
||||
}
|
||||
|
||||
value_list ~ /SCCS / && hfile ~ /cvsignore/ {
|
||||
exit
|
||||
}
|
||||
|
||||
value_list = ""
|
||||
|
||||
END {
|
||||
if (value_list != "")
|
||||
print heading "\n\n" define " \"" value_list "\"" > hfile
|
||||
else {
|
||||
print "Failed to find a value list in " ARGV[1] " for " hfile
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
33
exclude.c
33
exclude.c
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
@@ -199,8 +200,7 @@ static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_
|
||||
} else
|
||||
suf_len = 0;
|
||||
|
||||
if (!(rule->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))
|
||||
out_of_memory("add_rule");
|
||||
rule->pattern = new_array(char, pre_len + pat_len + suf_len + 1);
|
||||
if (pre_len) {
|
||||
memcpy(rule->pattern, dirbuf + module_dirlen, pre_len);
|
||||
for (cp = rule->pattern; cp < rule->pattern + pre_len; cp++) {
|
||||
@@ -261,19 +261,14 @@ static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_
|
||||
}
|
||||
}
|
||||
|
||||
if (!(lp = new_array0(filter_rule_list, 1)))
|
||||
out_of_memory("add_rule");
|
||||
lp = new_array0(filter_rule_list, 1);
|
||||
if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0)
|
||||
out_of_memory("add_rule");
|
||||
rule->u.mergelist = lp;
|
||||
|
||||
if (mergelist_cnt == mergelist_size) {
|
||||
mergelist_size += 5;
|
||||
mergelist_parents = realloc_array(mergelist_parents,
|
||||
filter_rule *,
|
||||
mergelist_size);
|
||||
if (!mergelist_parents)
|
||||
out_of_memory("add_rule");
|
||||
mergelist_parents = realloc_array(mergelist_parents, filter_rule *, mergelist_size);
|
||||
}
|
||||
if (DEBUG_GTE(FILTER, 2)) {
|
||||
rprintf(FINFO, "[%s] activating mergelist #%d%s\n",
|
||||
@@ -497,8 +492,6 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
|
||||
push = (struct local_filter_state *)new_array(char,
|
||||
sizeof (struct local_filter_state)
|
||||
+ (mergelist_cnt-1) * sizeof (filter_rule_list));
|
||||
if (!push)
|
||||
out_of_memory("push_local_filters");
|
||||
|
||||
push->mergelist_cnt = mergelist_cnt;
|
||||
for (i = 0; i < mergelist_cnt; i++) {
|
||||
@@ -821,8 +814,7 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
|
||||
if (!*s)
|
||||
return NULL;
|
||||
|
||||
if (!(rule = new0(filter_rule)))
|
||||
out_of_memory("parse_rule_tok");
|
||||
rule = new0(filter_rule);
|
||||
|
||||
/* Inherit from the template. Don't inherit FILTRULES_SIDES; we check
|
||||
* that later. */
|
||||
@@ -1051,16 +1043,6 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
|
||||
return rule;
|
||||
}
|
||||
|
||||
static char default_cvsignore[] =
|
||||
/* These default ignored items come from the CVS manual. */
|
||||
"RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"
|
||||
" .make.state .nse_depinfo *~ #* .#* ,* _$* *$"
|
||||
" *.old *.bak *.BAK *.orig *.rej .del-*"
|
||||
" *.a *.olb *.o *.obj *.so *.exe"
|
||||
" *.Z *.elc *.ln core"
|
||||
/* The rest we added to suit ourself. */
|
||||
" .svn/ .git/ .hg/ .bzr/";
|
||||
|
||||
static void get_cvs_excludes(uint32 rflags)
|
||||
{
|
||||
static int initialized = 0;
|
||||
@@ -1070,7 +1052,7 @@ static void get_cvs_excludes(uint32 rflags)
|
||||
return;
|
||||
initialized = 1;
|
||||
|
||||
parse_filter_str(&cvs_filter_list, default_cvsignore,
|
||||
parse_filter_str(&cvs_filter_list, default_cvsignore(),
|
||||
rule_template(rflags | (protocol_version >= 30 ? FILTRULE_PERISHABLE : 0)),
|
||||
0);
|
||||
|
||||
@@ -1134,8 +1116,7 @@ void parse_filter_str(filter_rule_list *listp, const char *rulestr,
|
||||
const char *name;
|
||||
filter_rule *excl_self;
|
||||
|
||||
if (!(excl_self = new0(filter_rule)))
|
||||
out_of_memory("parse_filter_str");
|
||||
excl_self = new0(filter_rule);
|
||||
/* Find the beginning of the basename and add an exclude for it. */
|
||||
for (name = pat + pat_len; name > pat && name[-1] != '/'; name--) {}
|
||||
add_rule(listp, name, (pat + pat_len) - name, excl_self, 0);
|
||||
|
||||
7
fileio.c
7
fileio.c
@@ -157,8 +157,6 @@ int write_file(int f, int use_seek, OFF_T offset, const char *buf, int len)
|
||||
wf_writeBufSize = WRITE_SIZE * 8;
|
||||
wf_writeBufCnt = 0;
|
||||
wf_writeBuf = new_array(char, wf_writeBufSize);
|
||||
if (!wf_writeBuf)
|
||||
out_of_memory("write_file");
|
||||
}
|
||||
r1 = (int)MIN((size_t)len, wf_writeBufSize - wf_writeBufCnt);
|
||||
if (r1) {
|
||||
@@ -217,8 +215,7 @@ struct map_struct *map_file(int fd, OFF_T len, int32 read_size, int32 blk_size)
|
||||
{
|
||||
struct map_struct *map;
|
||||
|
||||
if (!(map = new0(struct map_struct)))
|
||||
out_of_memory("map_file");
|
||||
map = new0(struct map_struct);
|
||||
|
||||
if (blk_size && (read_size % blk_size))
|
||||
read_size += blk_size - (read_size % blk_size);
|
||||
@@ -261,8 +258,6 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
|
||||
/* make sure we have allocated enough memory for the window */
|
||||
if (window_size > map->p_size) {
|
||||
map->p = realloc_array(map->p, char, window_size);
|
||||
if (!map->p)
|
||||
out_of_memory("map_ptr");
|
||||
map->p_size = window_size;
|
||||
}
|
||||
|
||||
|
||||
151
flist.c
151
flist.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2020 Wayne Davison
|
||||
* Copyright (C) 2002-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -56,6 +56,7 @@ extern int delete_during;
|
||||
extern int missing_args;
|
||||
extern int eol_nulls;
|
||||
extern int atimes_ndx;
|
||||
extern int crtimes_ndx;
|
||||
extern int relative_paths;
|
||||
extern int implied_dirs;
|
||||
extern int ignore_perishable;
|
||||
@@ -133,6 +134,7 @@ static char empty_sum[MAX_DIGEST_LEN];
|
||||
static int flist_count_offset; /* for --delete --progress */
|
||||
static int show_filelist_progress;
|
||||
|
||||
static struct file_list *flist_new(int flags, const char *msg);
|
||||
static void flist_sort_and_clean(struct file_list *flist, int strip_root);
|
||||
static void output_flist(struct file_list *flist);
|
||||
|
||||
@@ -293,6 +295,8 @@ static void flist_expand(struct file_list *flist, int extra)
|
||||
flist->malloced = FLIST_START;
|
||||
else if (flist->malloced >= FLIST_LINEAR)
|
||||
flist->malloced += FLIST_LINEAR;
|
||||
else if (flist->malloced < FLIST_START_LARGE/16)
|
||||
flist->malloced *= 4;
|
||||
else
|
||||
flist->malloced *= 2;
|
||||
|
||||
@@ -301,10 +305,9 @@ static void flist_expand(struct file_list *flist, int extra)
|
||||
if (flist->malloced < flist->used + extra)
|
||||
flist->malloced = flist->used + extra;
|
||||
|
||||
new_ptr = realloc_array(flist->files, struct file_struct *,
|
||||
flist->malloced);
|
||||
new_ptr = realloc_array(flist->files, struct file_struct *, flist->malloced);
|
||||
|
||||
if (DEBUG_GTE(FLIST, 1) && flist->malloced != FLIST_START) {
|
||||
if (DEBUG_GTE(FLIST, 1) && flist->files) {
|
||||
rprintf(FCLIENT, "[%s] expand file_list pointer array to %s bytes, did%s move\n",
|
||||
who_am_i(),
|
||||
big_num(sizeof flist->files[0] * flist->malloced),
|
||||
@@ -312,9 +315,6 @@ static void flist_expand(struct file_list *flist, int extra)
|
||||
}
|
||||
|
||||
flist->files = new_ptr;
|
||||
|
||||
if (!flist->files)
|
||||
out_of_memory("flist_expand");
|
||||
}
|
||||
|
||||
static void flist_done_allocating(struct file_list *flist)
|
||||
@@ -381,6 +381,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
int ndx, int first_ndx)
|
||||
{
|
||||
static time_t modtime, atime;
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
static time_t crtime;
|
||||
#endif
|
||||
static mode_t mode;
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
static int64 dev;
|
||||
@@ -447,7 +450,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
if (protocol_version < 28)
|
||||
xflags |= XMIT_SAME_RDEV_pre28;
|
||||
else {
|
||||
rdev = MAKEDEV(major(rdev), 0);
|
||||
rdev = MAKEDEV(rdev_major, 0);
|
||||
xflags |= XMIT_SAME_RDEV_MAJOR;
|
||||
if (protocol_version < 30)
|
||||
xflags |= XMIT_RDEV_MINOR_8_pre30;
|
||||
@@ -486,6 +489,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
else
|
||||
atime = F_ATIME(file);
|
||||
}
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx) {
|
||||
crtime = F_CRTIME(file);
|
||||
if (crtime == modtime)
|
||||
xflags |= XMIT_CRTIME_EQ_MTIME;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (tmp_dev != -1) {
|
||||
@@ -573,6 +583,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
}
|
||||
if (xflags & XMIT_MOD_NSEC)
|
||||
write_varint(f, F_MOD_NSEC(file));
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME))
|
||||
write_varlong(f, crtime, 4);
|
||||
#endif
|
||||
if (!(xflags & XMIT_SAME_MODE))
|
||||
write_int(f, to_wire_mode(mode));
|
||||
if (atimes_ndx && !S_ISDIR(mode) && !(xflags & XMIT_SAME_ATIME))
|
||||
@@ -665,6 +679,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags)
|
||||
{
|
||||
static int64 modtime, atime;
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
static time_t crtime;
|
||||
#endif
|
||||
static mode_t mode;
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
static int64 dev;
|
||||
@@ -684,7 +701,9 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
int extra_len = file_extra_cnt * EXTRA_LEN;
|
||||
int first_hlink_ndx = -1;
|
||||
int64 file_length;
|
||||
#ifdef CAN_SET_NSEC
|
||||
uint32 modtime_nsec;
|
||||
#endif
|
||||
const char *basename;
|
||||
struct file_struct *file;
|
||||
alloc_pool_t *pool;
|
||||
@@ -771,17 +790,24 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
|
||||
file_length = F_LENGTH(first);
|
||||
modtime = first->modtime;
|
||||
#ifdef CAN_SET_NSEC
|
||||
modtime_nsec = F_MOD_NSEC_or_0(first);
|
||||
#endif
|
||||
mode = first->mode;
|
||||
if (atimes_ndx && !S_ISDIR(mode))
|
||||
atime = F_ATIME(first);
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx)
|
||||
crtime = F_CRTIME(first);
|
||||
#endif
|
||||
if (preserve_uid)
|
||||
uid = F_OWNER(first);
|
||||
if (preserve_gid)
|
||||
gid = F_GROUP(first);
|
||||
if (preserve_devices && IS_DEVICE(mode)) {
|
||||
uint32 *devp = F_RDEV_P(first);
|
||||
rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
|
||||
rdev_major = DEV_MAJOR(devp);
|
||||
rdev = MAKEDEV(rdev_major, DEV_MINOR(devp));
|
||||
extra_len += DEV_EXTRA_CNT * EXTRA_LEN;
|
||||
}
|
||||
if (preserve_links && S_ISLNK(mode))
|
||||
@@ -808,9 +834,28 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
modtime = read_int(f);
|
||||
}
|
||||
if (xflags & XMIT_MOD_NSEC)
|
||||
#ifndef CAN_SET_NSEC
|
||||
(void)read_varint(f);
|
||||
#else
|
||||
modtime_nsec = read_varint(f);
|
||||
else
|
||||
modtime_nsec = 0;
|
||||
#endif
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx) {
|
||||
if (xflags & XMIT_CRTIME_EQ_MTIME)
|
||||
crtime = modtime;
|
||||
else
|
||||
crtime = read_varlong(f, 4);
|
||||
#if SIZEOF_TIME_T < SIZEOF_INT64
|
||||
if (!am_generator && (int64)(time_t)crtime != crtime) {
|
||||
rprintf(FERROR_XFER,
|
||||
"Create time value of %s truncated on receiver.\n",
|
||||
lastname);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (!(xflags & XMIT_SAME_MODE))
|
||||
mode = from_wire_mode(read_int(f));
|
||||
if (atimes_ndx && !S_ISDIR(mode) && !(xflags & XMIT_SAME_ATIME)) {
|
||||
@@ -992,6 +1037,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
}
|
||||
if (atimes_ndx && !S_ISDIR(mode))
|
||||
F_ATIME(file) = atime;
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx)
|
||||
F_CRTIME(file) = crtime;
|
||||
#endif
|
||||
if (unsort_ndx)
|
||||
F_NDX(file) = flist->used + flist->ndx_start;
|
||||
|
||||
@@ -1335,10 +1384,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
+ linkname_len;
|
||||
if (pool)
|
||||
bp = pool_alloc(pool, alloc_len, "make_file");
|
||||
else {
|
||||
if (!(bp = new_array(char, alloc_len)))
|
||||
out_of_memory("make_file");
|
||||
}
|
||||
else
|
||||
bp = new_array(char, alloc_len);
|
||||
|
||||
memset(bp, 0, extra_len + FILE_STRUCT_LEN);
|
||||
bp += extra_len;
|
||||
@@ -1391,6 +1438,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
file->flags |= FLAG_OWNED_BY_US;
|
||||
if (atimes_ndx && !S_ISDIR(file->mode))
|
||||
F_ATIME(file) = st.st_atime;
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx)
|
||||
F_CRTIME(file) = get_create_time(fname, &st);
|
||||
#endif
|
||||
|
||||
if (basename != thisname)
|
||||
file->dirname = lastdir;
|
||||
@@ -1661,8 +1712,7 @@ static void fsort(struct file_struct **fp, size_t num)
|
||||
if (use_qsort)
|
||||
qsort(fp, num, PTR_SIZE, file_compare);
|
||||
else {
|
||||
struct file_struct **tmp = new_array(struct file_struct *,
|
||||
(num+1) / 2);
|
||||
struct file_struct **tmp = new_array(struct file_struct *, (num+1) / 2);
|
||||
fsort_tmp(fp, num, tmp);
|
||||
free(tmp);
|
||||
}
|
||||
@@ -1895,13 +1945,11 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
|
||||
len = strlen(limit+1);
|
||||
memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list);
|
||||
if (!relname_list) {
|
||||
if (!(relname_list = new0(item_list)))
|
||||
out_of_memory("send_implied_dirs");
|
||||
relname_list = new0(item_list);
|
||||
memcpy(F_DIR_RELNAMES_P(lastpath_struct), &relname_list, sizeof relname_list);
|
||||
}
|
||||
rnpp = EXPAND_ITEM_LIST(relname_list, relnamecache *, 32);
|
||||
if (!(*rnpp = (relnamecache*)new_array(char, sizeof (relnamecache) + len)))
|
||||
out_of_memory("send_implied_dirs");
|
||||
*rnpp = (relnamecache*)new_array(char, RELNAMECACHE_LEN + len + 1);
|
||||
(*rnpp)->name_type = name_type;
|
||||
strlcpy((*rnpp)->fname, limit+1, len + 1);
|
||||
|
||||
@@ -2059,10 +2107,8 @@ void send_extra_file_list(int f, int at_least)
|
||||
}
|
||||
|
||||
if (need_unsorted_flist) {
|
||||
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
|
||||
out_of_memory("send_extra_file_list");
|
||||
memcpy(flist->sorted, flist->files,
|
||||
flist->used * sizeof (struct file_struct*));
|
||||
flist->sorted = new_array(struct file_struct *, flist->used);
|
||||
memcpy(flist->sorted, flist->files, flist->used * PTR_SIZE);
|
||||
} else
|
||||
flist->sorted = flist->files;
|
||||
|
||||
@@ -2142,8 +2188,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
flist = cur_flist = flist_new(0, "send_file_list");
|
||||
flist_expand(flist, FLIST_START_LARGE);
|
||||
if (inc_recurse) {
|
||||
dir_flist = flist_new(FLIST_TEMP, "send_file_list");
|
||||
flist_expand(dir_flist, FLIST_START_LARGE);
|
||||
flags |= FLAG_DIVERT_DIRS;
|
||||
} else
|
||||
dir_flist = cur_flist;
|
||||
@@ -2414,10 +2462,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
* recursion mode, the sender marks duplicate dirs so that it can
|
||||
* send them together in a single file-list. */
|
||||
if (need_unsorted_flist) {
|
||||
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
|
||||
out_of_memory("send_file_list");
|
||||
memcpy(flist->sorted, flist->files,
|
||||
flist->used * sizeof (struct file_struct*));
|
||||
flist->sorted = new_array(struct file_struct *, flist->used);
|
||||
memcpy(flist->sorted, flist->files, flist->used * PTR_SIZE);
|
||||
} else
|
||||
flist->sorted = flist->files;
|
||||
flist_sort_and_clean(flist, 0);
|
||||
@@ -2425,7 +2471,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
file_old_total += flist->used;
|
||||
|
||||
if (numeric_ids <= 0 && !inc_recurse)
|
||||
send_id_list(f);
|
||||
send_id_lists(f);
|
||||
|
||||
/* send the io_error flag */
|
||||
if (protocol_version < 30)
|
||||
@@ -2499,10 +2545,13 @@ struct file_list *recv_file_list(int f, int dir_ndx)
|
||||
#endif
|
||||
|
||||
flist = flist_new(0, "recv_file_list");
|
||||
flist_expand(flist, FLIST_START_LARGE);
|
||||
|
||||
if (inc_recurse) {
|
||||
if (flist->ndx_start == 1)
|
||||
if (flist->ndx_start == 1) {
|
||||
dir_flist = flist_new(FLIST_TEMP, "recv_file_list");
|
||||
flist_expand(dir_flist, FLIST_START_LARGE);
|
||||
}
|
||||
dstart = dir_flist->used;
|
||||
} else {
|
||||
dir_flist = flist;
|
||||
@@ -2597,10 +2646,8 @@ struct file_list *recv_file_list(int f, int dir_ndx)
|
||||
* order and for calling flist_find()). We keep the "files"
|
||||
* list unsorted for our exchange of index numbers with the
|
||||
* other side (since their names may not sort the same). */
|
||||
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
|
||||
out_of_memory("recv_file_list");
|
||||
memcpy(flist->sorted, flist->files,
|
||||
flist->used * sizeof (struct file_struct*));
|
||||
flist->sorted = new_array(struct file_struct *, flist->used);
|
||||
memcpy(flist->sorted, flist->files, flist->used * PTR_SIZE);
|
||||
if (inc_recurse && dir_flist->used > dstart) {
|
||||
static int dir_flist_malloced = 0;
|
||||
if (dir_flist_malloced < dir_flist->malloced) {
|
||||
@@ -2610,7 +2657,7 @@ struct file_list *recv_file_list(int f, int dir_ndx)
|
||||
dir_flist_malloced = dir_flist->malloced;
|
||||
}
|
||||
memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
|
||||
(dir_flist->used - dstart) * sizeof (struct file_struct*));
|
||||
(dir_flist->used - dstart) * PTR_SIZE);
|
||||
fsort(dir_flist->sorted + dstart, dir_flist->used - dstart);
|
||||
}
|
||||
} else {
|
||||
@@ -2742,28 +2789,28 @@ int flist_find(struct file_list *flist, struct file_struct *f)
|
||||
* 1=match directories, 0=match non-directories, or -1=match either. */
|
||||
int flist_find_name(struct file_list *flist, const char *fname, int want_dir_match)
|
||||
{
|
||||
struct { /* We have to create a temporary file_struct for the search. */
|
||||
struct file_struct f;
|
||||
char name_space[MAXPATHLEN];
|
||||
} t;
|
||||
static struct file_struct *f;
|
||||
char fbuf[MAXPATHLEN];
|
||||
const char *slash = strrchr(fname, '/');
|
||||
const char *basename = slash ? slash+1 : fname;
|
||||
|
||||
memset(&t.f, 0, FILE_STRUCT_LEN);
|
||||
memcpy((void *)t.f.basename, basename, strlen(basename)+1);
|
||||
if (!f)
|
||||
f = (struct file_struct*)new_array(char, FILE_STRUCT_LEN + MAXPATHLEN + 1);
|
||||
|
||||
memset(f, 0, FILE_STRUCT_LEN);
|
||||
memcpy((void*)f->basename, basename, strlen(basename)+1);
|
||||
|
||||
if (slash) {
|
||||
strlcpy(fbuf, fname, slash - fname + 1);
|
||||
t.f.dirname = fbuf;
|
||||
f->dirname = fbuf;
|
||||
} else
|
||||
t.f.dirname = NULL;
|
||||
f->dirname = NULL;
|
||||
|
||||
t.f.mode = want_dir_match > 0 ? S_IFDIR : S_IFREG;
|
||||
f->mode = want_dir_match > 0 ? S_IFDIR : S_IFREG;
|
||||
|
||||
if (want_dir_match < 0)
|
||||
return flist_find_ignore_dirness(flist, &t.f);
|
||||
return flist_find(flist, &t.f);
|
||||
return flist_find_ignore_dirness(flist, f);
|
||||
return flist_find(flist, f);
|
||||
}
|
||||
|
||||
/* Search for an identically-named item in the file list. Differs from
|
||||
@@ -2804,26 +2851,20 @@ void clear_file(struct file_struct *file)
|
||||
}
|
||||
|
||||
/* Allocate a new file list. */
|
||||
struct file_list *flist_new(int flags, char *msg)
|
||||
static struct file_list *flist_new(int flags, const char *msg)
|
||||
{
|
||||
struct file_list *flist;
|
||||
|
||||
if (!(flist = new0(struct file_list)))
|
||||
out_of_memory(msg);
|
||||
flist = new0(struct file_list);
|
||||
|
||||
if (flags & FLIST_TEMP) {
|
||||
if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0,
|
||||
out_of_memory,
|
||||
POOL_INTERN)))
|
||||
if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0, _out_of_memory, POOL_INTERN)))
|
||||
out_of_memory(msg);
|
||||
} else {
|
||||
/* This is a doubly linked list with prev looping back to
|
||||
* the end of the list, but the last next pointer is NULL. */
|
||||
if (!first_flist) {
|
||||
flist->file_pool = pool_create(NORMAL_EXTENT, 0,
|
||||
out_of_memory,
|
||||
POOL_INTERN);
|
||||
if (!flist->file_pool)
|
||||
if (!(flist->file_pool = pool_create(NORMAL_EXTENT, 0, _out_of_memory, POOL_INTERN)))
|
||||
out_of_memory(msg);
|
||||
|
||||
flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0;
|
||||
|
||||
349
generator.c
349
generator.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -44,7 +44,9 @@ extern int preserve_specials;
|
||||
extern int preserve_hard_links;
|
||||
extern int preserve_executability;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_times;
|
||||
extern int preserve_mtimes;
|
||||
extern int omit_dir_times;
|
||||
extern int omit_link_times;
|
||||
extern int delete_mode;
|
||||
extern int delete_before;
|
||||
extern int delete_during;
|
||||
@@ -84,7 +86,7 @@ extern int list_only;
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
extern int safe_symlinks;
|
||||
extern long block_size; /* "long" because popt can't set an int32. */
|
||||
extern int32 block_size;
|
||||
extern int unsort_ndx;
|
||||
extern int max_delete;
|
||||
extern int force_delete;
|
||||
@@ -112,10 +114,6 @@ static int need_retouch_dir_times;
|
||||
static int need_retouch_dir_perms;
|
||||
static const char *solo_file = NULL;
|
||||
|
||||
enum nonregtype {
|
||||
TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK
|
||||
};
|
||||
|
||||
/* Forward declarations. */
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
static void handle_skipped_hlink(struct file_struct *file, int itemizing,
|
||||
@@ -186,7 +184,8 @@ static int remember_delete(struct file_struct *file, const char *fname, int flag
|
||||
static int read_delay_line(char *buf, int *flags_p)
|
||||
{
|
||||
static int read_pos = 0;
|
||||
int j, len, mode;
|
||||
unsigned int mode;
|
||||
int j, len;
|
||||
char *bp, *past_space;
|
||||
|
||||
while (1) {
|
||||
@@ -270,7 +269,7 @@ static void do_delayed_deletions(char *delbuf)
|
||||
* MAXPATHLEN buffer with the name of the directory in it (the functions we
|
||||
* call will append names onto the end, but the old dir value will be restored
|
||||
* on exit). */
|
||||
static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
|
||||
static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t fs_dev)
|
||||
{
|
||||
static int already_warned = 0;
|
||||
static struct hashtable *dev_tbl;
|
||||
@@ -305,12 +304,12 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
|
||||
if (!dev_tbl)
|
||||
dev_tbl = hashtable_create(16, HT_KEY64);
|
||||
if (file->flags & FLAG_TOP_DIR) {
|
||||
hashtable_find(dev_tbl, *fs_dev+1, "");
|
||||
filesystem_dev = *fs_dev;
|
||||
} else if (filesystem_dev != *fs_dev) {
|
||||
if (!hashtable_find(dev_tbl, *fs_dev+1, NULL))
|
||||
hashtable_find(dev_tbl, fs_dev+1, "");
|
||||
filesystem_dev = fs_dev;
|
||||
} else if (filesystem_dev != fs_dev) {
|
||||
if (!hashtable_find(dev_tbl, fs_dev+1, NULL))
|
||||
return;
|
||||
filesystem_dev = *fs_dev; /* it's a prior top-dir dev */
|
||||
filesystem_dev = fs_dev; /* it's a prior top-dir dev */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,9 +378,9 @@ static void do_delete_pass(void)
|
||||
|| !S_ISDIR(st.st_mode))
|
||||
continue;
|
||||
|
||||
delete_in_dir(fbuf, file, &st.st_dev);
|
||||
delete_in_dir(fbuf, file, st.st_dev);
|
||||
}
|
||||
delete_in_dir(NULL, NULL, &dev_zero);
|
||||
delete_in_dir(NULL, NULL, dev_zero);
|
||||
|
||||
if (INFO_GTE(FLIST, 2) && !am_server)
|
||||
rprintf(FINFO, " \r");
|
||||
@@ -396,6 +395,19 @@ static inline int mtime_differs(STRUCT_STAT *stp, struct file_struct *file)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int any_time_differs(stat_x *sxp, struct file_struct *file, UNUSED(const char *fname))
|
||||
{
|
||||
int differs = mtime_differs(&sxp->st, file);
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (!differs && crtimes_ndx) {
|
||||
if (sxp->crtime == 0)
|
||||
sxp->crtime = get_create_time(fname, &sxp->st);
|
||||
differs = !same_time(sxp->crtime, 0, F_CRTIME(file), 0);
|
||||
}
|
||||
#endif
|
||||
return differs;
|
||||
}
|
||||
|
||||
static inline int perms_differ(struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
if (preserve_perms)
|
||||
@@ -450,7 +462,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
if (S_ISLNK(file->mode)) {
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
if (preserve_times & PRESERVE_LINK_TIMES && mtime_differs(&sxp->st, file))
|
||||
if (preserve_mtimes && !omit_link_times && any_time_differs(sxp, file, fname))
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef CAN_CHMOD_SYMLINK
|
||||
@@ -470,7 +482,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
|
||||
return 0;
|
||||
#endif
|
||||
} else {
|
||||
if (preserve_times && mtime_differs(&sxp->st, file))
|
||||
if (preserve_mtimes && any_time_differs(sxp, file, fname))
|
||||
return 0;
|
||||
if (perms_differ(file, sxp))
|
||||
return 0;
|
||||
@@ -494,9 +506,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
|
||||
const char *xname)
|
||||
{
|
||||
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
|
||||
int keep_time = !preserve_times ? 0
|
||||
: S_ISDIR(file->mode) ? preserve_times & PRESERVE_DIR_TIMES
|
||||
: S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
|
||||
int keep_time = !preserve_mtimes ? 0
|
||||
: S_ISDIR(file->mode) ? !omit_dir_times
|
||||
: S_ISLNK(file->mode) ? !omit_link_times
|
||||
: 1;
|
||||
|
||||
if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
|
||||
@@ -512,6 +524,14 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
|
||||
if (atimes_ndx && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
|
||||
&& !same_time(F_ATIME(file), 0, sxp->st.st_atime, 0))
|
||||
iflags |= ITEM_REPORT_ATIME;
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx) {
|
||||
if (sxp->crtime == 0)
|
||||
sxp->crtime = get_create_time(fnamecmp, &sxp->st);
|
||||
if (!same_time(sxp->crtime, 0, F_CRTIME(file), 0))
|
||||
iflags |= ITEM_REPORT_CRTIME;
|
||||
}
|
||||
#endif
|
||||
#if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
|
||||
if (S_ISLNK(file->mode)) {
|
||||
;
|
||||
@@ -578,30 +598,77 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Perform our quick-check heuristic for determining if a file is unchanged. */
|
||||
int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
|
||||
static enum filetype get_file_type(mode_t mode)
|
||||
{
|
||||
if (st->st_size != F_LENGTH(file))
|
||||
return 0;
|
||||
|
||||
/* if always checksum is set then we use the checksum instead
|
||||
of the file time to determine whether to sync */
|
||||
if (always_checksum > 0 && S_ISREG(st->st_mode)) {
|
||||
char sum[MAX_DIGEST_LEN];
|
||||
file_checksum(fn, st, sum);
|
||||
return memcmp(sum, F_SUM(file), flist_csum_len) == 0;
|
||||
}
|
||||
|
||||
if (size_only > 0)
|
||||
return 1;
|
||||
|
||||
if (ignore_times)
|
||||
return 0;
|
||||
|
||||
return !mtime_differs(st, file);
|
||||
if (S_ISREG(mode))
|
||||
return FT_REG;
|
||||
if (S_ISLNK(mode))
|
||||
return FT_SYMLINK;
|
||||
if (S_ISDIR(mode))
|
||||
return FT_DIR;
|
||||
if (IS_SPECIAL(mode))
|
||||
return FT_SPECIAL;
|
||||
if (IS_DEVICE(mode))
|
||||
return FT_DEVICE;
|
||||
return FT_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Perform our quick-check heuristic for determining if a file is unchanged. */
|
||||
int quick_check_ok(enum filetype ftype, const char *fn, struct file_struct *file, STRUCT_STAT *st)
|
||||
{
|
||||
switch (ftype) {
|
||||
case FT_REG:
|
||||
if (st->st_size != F_LENGTH(file))
|
||||
return 0;
|
||||
|
||||
/* If always_checksum is set then we use the checksum instead
|
||||
* of the file mtime to determine whether to sync. */
|
||||
if (always_checksum > 0) {
|
||||
char sum[MAX_DIGEST_LEN];
|
||||
file_checksum(fn, st, sum);
|
||||
return memcmp(sum, F_SUM(file), flist_csum_len) == 0;
|
||||
}
|
||||
|
||||
if (size_only > 0)
|
||||
return 1;
|
||||
|
||||
if (ignore_times)
|
||||
return 0;
|
||||
|
||||
if (mtime_differs(st, file))
|
||||
return 0;
|
||||
break;
|
||||
case FT_DIR:
|
||||
break;
|
||||
case FT_SYMLINK: {
|
||||
#ifdef SUPPORT_LINKS
|
||||
char lnk[MAXPATHLEN];
|
||||
int len = do_readlink(fn, lnk, MAXPATHLEN-1);
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
lnk[len] = '\0';
|
||||
if (strcmp(lnk, F_SYMLINK(file)) != 0)
|
||||
return 0;
|
||||
break;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
case FT_SPECIAL:
|
||||
if (!BITS_EQUAL(file->mode, st->st_mode, _S_IFMT))
|
||||
return 0;
|
||||
break;
|
||||
case FT_DEVICE: {
|
||||
uint32 *devp = F_RDEV_P(file);
|
||||
if (st->st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
case FT_UNSUPPORTED:
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* set (initialize) the size entries in the per-file sum_struct
|
||||
@@ -886,7 +953,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
|
||||
best_match = j;
|
||||
match_level = 1;
|
||||
}
|
||||
if (!unchanged_file(cmpbuf, file, &sxp->st))
|
||||
if (!quick_check_ok(FT_REG, cmpbuf, file, &sxp->st))
|
||||
continue;
|
||||
if (match_level == 1) {
|
||||
best_match = j;
|
||||
@@ -985,29 +1052,14 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
|
||||
{
|
||||
int best_match = -1;
|
||||
int match_level = 0;
|
||||
enum nonregtype type;
|
||||
uint32 *devp;
|
||||
#ifdef SUPPORT_LINKS
|
||||
char lnk[MAXPATHLEN];
|
||||
int len;
|
||||
#endif
|
||||
enum filetype ftype = get_file_type(file->mode);
|
||||
int j = 0;
|
||||
|
||||
#ifndef SUPPORT_LINKS
|
||||
if (S_ISLNK(file->mode))
|
||||
if (ftype == FT_SYMLINK)
|
||||
return -1;
|
||||
#endif
|
||||
if (S_ISDIR(file->mode)) {
|
||||
type = TYPE_DIR;
|
||||
} else if (IS_SPECIAL(file->mode))
|
||||
type = TYPE_SPECIAL;
|
||||
else if (IS_DEVICE(file->mode))
|
||||
type = TYPE_DEVICE;
|
||||
#ifdef SUPPORT_LINKS
|
||||
else if (S_ISLNK(file->mode))
|
||||
type = TYPE_SYMLINK;
|
||||
#endif
|
||||
else {
|
||||
if (ftype == FT_REG || ftype == FT_UNSUPPORTED) {
|
||||
rprintf(FERROR,
|
||||
"internal: try_dests_non() called with invalid mode (%o)\n",
|
||||
(int)file->mode);
|
||||
@@ -1018,53 +1070,14 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
|
||||
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
|
||||
if (link_stat(cmpbuf, &sxp->st, 0) < 0)
|
||||
continue;
|
||||
switch (type) {
|
||||
case TYPE_DIR:
|
||||
if (!S_ISDIR(sxp->st.st_mode))
|
||||
continue;
|
||||
break;
|
||||
case TYPE_SPECIAL:
|
||||
if (!IS_SPECIAL(sxp->st.st_mode))
|
||||
continue;
|
||||
break;
|
||||
case TYPE_DEVICE:
|
||||
if (!IS_DEVICE(sxp->st.st_mode))
|
||||
continue;
|
||||
break;
|
||||
case TYPE_SYMLINK:
|
||||
#ifdef SUPPORT_LINKS
|
||||
if (!S_ISLNK(sxp->st.st_mode))
|
||||
continue;
|
||||
break;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
if (ftype != get_file_type(sxp->st.st_mode))
|
||||
continue;
|
||||
if (match_level < 1) {
|
||||
match_level = 1;
|
||||
best_match = j;
|
||||
}
|
||||
switch (type) {
|
||||
case TYPE_DIR:
|
||||
case TYPE_SPECIAL:
|
||||
break;
|
||||
case TYPE_DEVICE:
|
||||
devp = F_RDEV_P(file);
|
||||
if (sxp->st.st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))
|
||||
continue;
|
||||
break;
|
||||
case TYPE_SYMLINK:
|
||||
#ifdef SUPPORT_LINKS
|
||||
if ((len = do_readlink(cmpbuf, lnk, MAXPATHLEN-1)) <= 0)
|
||||
continue;
|
||||
lnk[len] = '\0';
|
||||
if (strcmp(lnk, F_SYMLINK(file)) != 0)
|
||||
continue;
|
||||
break;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
if (!quick_check_ok(ftype, cmpbuf, file, &sxp->st))
|
||||
continue;
|
||||
if (match_level < 2) {
|
||||
match_level = 2;
|
||||
best_match = j;
|
||||
@@ -1109,14 +1122,14 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
|
||||
match_level = 2;
|
||||
if (itemizing && stdout_format_has_i
|
||||
&& (INFO_GTE(NAME, 2) || stdout_format_has_i > 1)) {
|
||||
int chg = alt_dest_type == COMPARE_DEST && type != TYPE_DIR ? 0
|
||||
int chg = alt_dest_type == COMPARE_DEST && ftype != FT_DIR ? 0
|
||||
: ITEM_LOCAL_CHANGE + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0);
|
||||
char *lp = match_level == 3 ? "" : NULL;
|
||||
itemize(cmpbuf, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp);
|
||||
}
|
||||
if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT) {
|
||||
rprintf(FCLIENT, "%s%s is uptodate\n",
|
||||
fname, type == TYPE_DIR ? "/" : "");
|
||||
fname, ftype == FT_DIR ? "/" : "");
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
@@ -1131,6 +1144,7 @@ static void list_file_entry(struct file_struct *f)
|
||||
int size_width = human_readable ? 14 : 11;
|
||||
int mtime_width = 1 + strlen(mtime_str);
|
||||
int atime_width = atimes_ndx ? mtime_width : 0;
|
||||
int crtime_width = crtimes_ndx ? mtime_width : 0;
|
||||
|
||||
if (!F_IS_ACTIVE(f)) {
|
||||
/* this can happen if duplicate names were removed */
|
||||
@@ -1141,10 +1155,11 @@ static void list_file_entry(struct file_struct *f)
|
||||
|
||||
if (missing_args == 2 && f->mode == 0) {
|
||||
rprintf(FINFO, "%-*s %s\n",
|
||||
10 + 1 + size_width + mtime_width + atime_width, "*missing",
|
||||
10 + 1 + size_width + mtime_width + atime_width + crtime_width, "*missing",
|
||||
f_name(f, NULL));
|
||||
} else {
|
||||
const char *atime_str = atimes_ndx && !S_ISDIR(f->mode) ? timestring(F_ATIME(f)) : "";
|
||||
const char *crtime_str = crtimes_ndx ? timestring(F_CRTIME(f)) : "";
|
||||
const char *arrow, *lnk;
|
||||
|
||||
permstring(permbuf, f->mode);
|
||||
@@ -1157,9 +1172,9 @@ static void list_file_entry(struct file_struct *f)
|
||||
#endif
|
||||
arrow = lnk = "";
|
||||
|
||||
rprintf(FINFO, "%s %*s %s%*s %s%s%s\n",
|
||||
rprintf(FINFO, "%s %*s %s%*s%*s %s%s%s\n",
|
||||
permbuf, size_width, human_num(F_LENGTH(f)),
|
||||
timestring(f->modtime), atime_width, atime_str,
|
||||
timestring(f->modtime), atime_width, atime_str, crtime_width, crtime_str,
|
||||
f_name(f, NULL), arrow, lnk);
|
||||
}
|
||||
}
|
||||
@@ -1208,7 +1223,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
uchar fnamecmp_type;
|
||||
int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0;
|
||||
int is_dir = !S_ISDIR(file->mode) ? 0
|
||||
enum filetype stype, ftype = get_file_type(file->mode);
|
||||
int is_dir = ftype != FT_DIR ? 0
|
||||
: inc_recurse && ndx != cur_flist->ndx_start - 1 ? -1
|
||||
: 1;
|
||||
|
||||
@@ -1277,20 +1293,25 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
* this function was asked to process in the file list. */
|
||||
if (!inc_recurse
|
||||
&& (*dn != '.' || dn[1]) /* Avoid an issue with --relative and the "." dir. */
|
||||
&& (!prior_dir_file || strcmp(dn, f_name(prior_dir_file, NULL)) != 0)
|
||||
&& flist_find_name(cur_flist, dn, 1) < 0) {
|
||||
&& (!prior_dir_file || strcmp(dn, f_name(prior_dir_file, NULL)) != 0)) {
|
||||
int ok = 0, j = flist_find_name(cur_flist, dn, -1);
|
||||
if (j >= 0) {
|
||||
struct file_struct *f = cur_flist->sorted[j];
|
||||
if (S_ISDIR(f->mode) || (missing_args == 2 && !file->mode && !f->mode))
|
||||
ok = 1;
|
||||
}
|
||||
/* The --delete-missing-args option can actually put invalid entries into
|
||||
* the file list, so if that option was specified, we'll just complain about
|
||||
* it and allow it. */
|
||||
if (missing_args == 2 && file->mode == 0)
|
||||
if (!ok && missing_args == 2 && file->mode == 0 && j < 0)
|
||||
rprintf(FERROR, "WARNING: parent dir is absent in the file list: %s\n", dn);
|
||||
else {
|
||||
else if (!ok) {
|
||||
rprintf(FERROR, "ABORTING due to invalid path from sender: %s/%s\n",
|
||||
dn, file->basename);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
if (relative_paths && !implied_dirs
|
||||
if (relative_paths && !implied_dirs && file->mode != 0
|
||||
&& do_stat(dn, &sx.st) < 0) {
|
||||
if (dry_run)
|
||||
goto parent_is_dry_missing;
|
||||
@@ -1351,10 +1372,27 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
&& !am_root && sx.st.st_uid == our_uid)
|
||||
del_opts |= DEL_NO_UID_WRITE;
|
||||
|
||||
if (statret == 0)
|
||||
stype = get_file_type(sx.st.st_mode);
|
||||
else
|
||||
stype = FT_UNSUPPORTED;
|
||||
|
||||
if (ignore_existing > 0 && statret == 0
|
||||
&& (!is_dir || !S_ISDIR(sx.st.st_mode))) {
|
||||
if (INFO_GTE(SKIP, 1) && is_dir >= 0)
|
||||
rprintf(FINFO, "%s exists\n", fname);
|
||||
&& (!is_dir || stype != FT_DIR)) {
|
||||
if (INFO_GTE(SKIP, 1) && is_dir >= 0) {
|
||||
const char *suf = "";
|
||||
if (INFO_GTE(SKIP, 2)) {
|
||||
if (ftype != stype)
|
||||
suf = " (type change)";
|
||||
else if (!quick_check_ok(ftype, fname, file, &sx.st))
|
||||
suf = always_checksum ? " (sum change)" : " (file change)";
|
||||
else if (!unchanged_attrs(fname, file, &sx))
|
||||
suf = " (attr change)";
|
||||
else
|
||||
suf = " (uptodate)";
|
||||
}
|
||||
rprintf(FINFO, "%s exists%s\n", fname, suf);
|
||||
}
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (F_IS_HLINKED(file))
|
||||
handle_skipped_hlink(file, itemizing, code, f_out);
|
||||
@@ -1375,7 +1413,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
} else
|
||||
added_perms = 0;
|
||||
if (is_dir < 0) {
|
||||
if (!(preserve_times & PRESERVE_DIR_TIMES))
|
||||
if (!preserve_mtimes || omit_dir_times)
|
||||
goto cleanup;
|
||||
/* In inc_recurse mode we want to make sure any missing
|
||||
* directories get created while we're still processing
|
||||
@@ -1383,7 +1421,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
* dir's mtime right away). We will handle the dir in
|
||||
* full later (right before we handle its contents). */
|
||||
if (statret == 0
|
||||
&& (S_ISDIR(sx.st.st_mode)
|
||||
&& (stype == FT_DIR
|
||||
|| delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
|
||||
goto cleanup; /* Any errors get reported later. */
|
||||
if (do_mkdir(fname, (file->mode|added_perms) & 0700) == 0)
|
||||
@@ -1395,7 +1433,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
* file of that name and it is *not* a directory, then
|
||||
* we need to delete it. If it doesn't exist, then
|
||||
* (perhaps recursively) create it. */
|
||||
if (statret == 0 && !S_ISDIR(sx.st.st_mode)) {
|
||||
if (statret == 0 && stype != FT_DIR) {
|
||||
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0)
|
||||
goto skipping_dir_contents;
|
||||
statret = -1;
|
||||
@@ -1479,7 +1517,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
else if (delete_during && f_out != -1 && !phase
|
||||
&& !(file->flags & FLAG_MISSING_DIR)) {
|
||||
if (file->flags & FLAG_CONTENT_DIR)
|
||||
delete_in_dir(fname, file, &real_sx.st.st_dev);
|
||||
delete_in_dir(fname, file, real_sx.st.st_dev);
|
||||
else
|
||||
change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
|
||||
}
|
||||
@@ -1490,7 +1528,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
/* If we're not preserving permissions, change the file-list's
|
||||
* mode based on the local permissions and some heuristics. */
|
||||
if (!preserve_perms) {
|
||||
int exists = statret == 0 && !S_ISDIR(sx.st.st_mode);
|
||||
int exists = statret == 0 && stype != FT_DIR;
|
||||
file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms, exists);
|
||||
}
|
||||
|
||||
@@ -1500,7 +1538,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
#endif
|
||||
|
||||
if (preserve_links && S_ISLNK(file->mode)) {
|
||||
if (preserve_links && ftype == FT_SYMLINK) {
|
||||
#ifdef SUPPORT_LINKS
|
||||
const char *sl = F_SYMLINK(file);
|
||||
if (safe_symlinks && unsafe_symlink(sl, fname)) {
|
||||
@@ -1517,12 +1555,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
if (statret == 0) {
|
||||
char lnk[MAXPATHLEN];
|
||||
int len;
|
||||
|
||||
if (S_ISLNK(sx.st.st_mode)
|
||||
&& (len = do_readlink(fname, lnk, MAXPATHLEN-1)) > 0
|
||||
&& strncmp(lnk, sl, len) == 0 && sl[len] == '\0') {
|
||||
if (stype == FT_SYMLINK && quick_check_ok(stype, fname, file, &sx.st)) {
|
||||
/* The link is pointing to the right place. */
|
||||
set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
|
||||
if (itemizing)
|
||||
@@ -1555,7 +1588,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
if (atomic_create(file, fname, sl, NULL, MAKEDEV(0, 0), &sx, statret == 0 ? DEL_FOR_SYMLINK : 0)) {
|
||||
set_file_attrs(fname, file, NULL, NULL, 0);
|
||||
if (itemizing) {
|
||||
if (statret == 0 && !S_ISLNK(sx.st.st_mode))
|
||||
if (statret == 0 && stype != FT_SYMLINK)
|
||||
statret = -1;
|
||||
itemize(fnamecmp, file, ndx, statret, &sx,
|
||||
ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL);
|
||||
@@ -1576,28 +1609,22 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|
||||
|| (preserve_specials && IS_SPECIAL(file->mode))) {
|
||||
if ((am_root && preserve_devices && ftype == FT_DEVICE)
|
||||
|| (preserve_specials && ftype == FT_SPECIAL)) {
|
||||
dev_t rdev;
|
||||
int del_for_flag = 0;
|
||||
if (IS_DEVICE(file->mode)) {
|
||||
int del_for_flag;
|
||||
if (ftype == FT_DEVICE) {
|
||||
uint32 *devp = F_RDEV_P(file);
|
||||
rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
|
||||
} else
|
||||
del_for_flag = DEL_FOR_DEVICE;
|
||||
} else {
|
||||
rdev = 0;
|
||||
del_for_flag = DEL_FOR_SPECIAL;
|
||||
}
|
||||
if (statret == 0) {
|
||||
if (IS_DEVICE(file->mode)) {
|
||||
if (!IS_DEVICE(sx.st.st_mode))
|
||||
statret = -1;
|
||||
del_for_flag = DEL_FOR_DEVICE;
|
||||
} else {
|
||||
if (!IS_SPECIAL(sx.st.st_mode))
|
||||
statret = -1;
|
||||
del_for_flag = DEL_FOR_SPECIAL;
|
||||
}
|
||||
if (statret == 0
|
||||
&& BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT)
|
||||
&& (IS_SPECIAL(sx.st.st_mode) || sx.st.st_rdev == rdev)) {
|
||||
if (ftype != stype)
|
||||
statret = -1;
|
||||
else if (quick_check_ok(ftype, fname, file, &sx.st)) {
|
||||
/* The device or special file is identical. */
|
||||
set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
|
||||
if (itemizing)
|
||||
@@ -1650,10 +1677,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!S_ISREG(file->mode)) {
|
||||
if (solo_file)
|
||||
fname = f_name(file, NULL);
|
||||
rprintf(FINFO, "skipping non-regular file \"%s\"\n", fname);
|
||||
if (ftype != FT_REG) {
|
||||
if (INFO_GTE(NONREG, 1)) {
|
||||
if (solo_file)
|
||||
fname = f_name(file, NULL);
|
||||
rprintf(FINFO, "skipping non-regular file \"%s\"\n", fname);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1674,7 +1703,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (update_only > 0 && statret == 0 && file->modtime - sx.st.st_mtime <= modify_window) {
|
||||
if (update_only > 0 && statret == 0 && file->modtime - sx.st.st_mtime < modify_window) {
|
||||
if (INFO_GTE(SKIP, 1))
|
||||
rprintf(FINFO, "%s is newer\n", fname);
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
@@ -1686,7 +1715,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
|
||||
fnamecmp_type = FNAMECMP_FNAME;
|
||||
|
||||
if (statret == 0 && !(S_ISREG(sx.st.st_mode) || (write_devices && IS_DEVICE(sx.st.st_mode)))) {
|
||||
if (statret == 0 && !(stype == FT_REG || (write_devices && stype == FT_DEVICE))) {
|
||||
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_FILE) != 0)
|
||||
goto cleanup;
|
||||
statret = -1;
|
||||
@@ -1720,7 +1749,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
partialptr = NULL;
|
||||
|
||||
if (statret != 0 && fuzzy_basis) {
|
||||
if (need_fuzzy_dirlist && S_ISREG(file->mode)) {
|
||||
if (need_fuzzy_dirlist) {
|
||||
const char *dn = file->dirname ? file->dirname : ".";
|
||||
int i;
|
||||
strlcpy(fnamecmpbuf, dn, sizeof fnamecmpbuf);
|
||||
@@ -1768,7 +1797,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
;
|
||||
else if (fnamecmp_type >= FNAMECMP_FUZZY)
|
||||
;
|
||||
else if (unchanged_file(fnamecmp, file, &sx.st)) {
|
||||
else if (quick_check_ok(FT_REG, fnamecmp, file, &sx.st)) {
|
||||
if (partialptr) {
|
||||
do_unlink(partialptr);
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
@@ -2213,7 +2242,7 @@ void generate_files(int f_out, const char *local_name)
|
||||
}
|
||||
solo_file = local_name;
|
||||
dir_tweaking = !(list_only || solo_file || dry_run);
|
||||
need_retouch_dir_times = preserve_times & PRESERVE_DIR_TIMES;
|
||||
need_retouch_dir_times = preserve_mtimes && !omit_dir_times;
|
||||
loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
|
||||
symlink_timeset_failed_flags = ITEM_REPORT_TIME
|
||||
| (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
|
||||
@@ -2227,8 +2256,6 @@ void generate_files(int f_out, const char *local_name)
|
||||
if (delete_during == 2) {
|
||||
deldelay_size = BIGPATHBUFLEN * 4;
|
||||
deldelay_buf = new_array(char, deldelay_size);
|
||||
if (!deldelay_buf)
|
||||
out_of_memory("delete-delay");
|
||||
}
|
||||
info_levels[INFO_FLIST] = info_levels[INFO_PROGRESS] = 0;
|
||||
|
||||
@@ -2268,7 +2295,7 @@ void generate_files(int f_out, const char *local_name)
|
||||
dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
|
||||
} else
|
||||
dirdev = MAKEDEV(0, 0);
|
||||
delete_in_dir(fbuf, fp, &dirdev);
|
||||
delete_in_dir(fbuf, fp, dirdev);
|
||||
} else
|
||||
change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp));
|
||||
}
|
||||
@@ -2315,7 +2342,7 @@ void generate_files(int f_out, const char *local_name)
|
||||
} while ((cur_flist = cur_flist->next) != NULL);
|
||||
|
||||
if (delete_during)
|
||||
delete_in_dir(NULL, NULL, &dev_zero);
|
||||
delete_in_dir(NULL, NULL, dev_zero);
|
||||
phase++;
|
||||
if (DEBUG_GTE(GENR, 1))
|
||||
rprintf(FINFO, "generate_files phase=%d\n", phase);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* `id -G` on Linux, but it's too hard to find a portable equivalent.
|
||||
*
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2019 Wayne Davison
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
@@ -20,8 +20,7 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
int
|
||||
main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
int main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
{
|
||||
int n, i;
|
||||
gid_t *list;
|
||||
|
||||
@@ -35,9 +35,8 @@ struct hashtable *hashtable_create(int size, int key64)
|
||||
size *= 2;
|
||||
}
|
||||
|
||||
if (!(tbl = new(struct hashtable))
|
||||
|| !(tbl->nodes = new_array0(char, size * node_size)))
|
||||
out_of_memory("hashtable_create");
|
||||
tbl = new(struct hashtable);
|
||||
tbl->nodes = new_array0(char, size * node_size);
|
||||
tbl->size = size;
|
||||
tbl->entries = 0;
|
||||
tbl->node_size = node_size;
|
||||
@@ -94,8 +93,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, void *data_when_new)
|
||||
int size = tbl->size * 2;
|
||||
int i;
|
||||
|
||||
if (!(tbl->nodes = new_array0(char, size * tbl->node_size)))
|
||||
out_of_memory("hashtable_node");
|
||||
tbl->nodes = new_array0(char, size * tbl->node_size);
|
||||
tbl->size = size;
|
||||
tbl->entries = 0;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/awk -f
|
||||
|
||||
# The caller must set -v helpfile=help-NAME.h and pass arg NAME.NUM.md
|
||||
# The caller must pass args: -v hfile=help-NAME.h NAME.NUM.md
|
||||
|
||||
BEGIN {
|
||||
heading = "/* DO NOT EDIT THIS FILE! It is auto-generated from the option list in " ARGV[1] "! */"
|
||||
findcomment = helpfile
|
||||
findcomment = hfile
|
||||
sub("\\.", "\\.", findcomment)
|
||||
findcomment = "\\[comment\\].*" findcomment
|
||||
backtick_cnt = 0
|
||||
@@ -32,9 +32,9 @@ $0 ~ findcomment {
|
||||
|
||||
END {
|
||||
if (foundcomment && backtick_cnt > 1)
|
||||
print heading "\n" prints > helpfile
|
||||
print heading "\n" prints > hfile
|
||||
else {
|
||||
print "Failed to find " helpfile " section in " ARGV[1]
|
||||
print "Failed to find " hfile " section in " ARGV[1]
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
11
hlink.c
11
hlink.c
@@ -125,8 +125,7 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
|
||||
if (inc_recurse) {
|
||||
node = hashtable_find(prior_hlinks, gnum, data_when_new);
|
||||
if (node->data == data_when_new) {
|
||||
if (!(node->data = new_array0(char, 5)))
|
||||
out_of_memory("match_gnums");
|
||||
node->data = new_array0(char, 5);
|
||||
assert(gnum >= hlink_flist->ndx_start);
|
||||
file->flags |= FLAG_HLINK_FIRST;
|
||||
prev = -1;
|
||||
@@ -190,8 +189,7 @@ void match_hard_links(struct file_list *flist)
|
||||
int i, ndx_count = 0;
|
||||
int32 *ndx_list;
|
||||
|
||||
if (!(ndx_list = new_array(int32, flist->used)))
|
||||
out_of_memory("match_hard_links");
|
||||
ndx_list = new_array(int32, flist->used);
|
||||
|
||||
for (i = 0; i < flist->used; i++) {
|
||||
if (F_IS_HLINKED(flist->sorted[i]))
|
||||
@@ -408,7 +406,7 @@ int hard_link_check(struct file_struct *file, int ndx, char *fname,
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!unchanged_file(cmpbuf, file, &alt_sx.st))
|
||||
if (!quick_check_ok(FT_REG, cmpbuf, file, &alt_sx.st))
|
||||
continue;
|
||||
statret = 1;
|
||||
if (unchanged_attrs(cmpbuf, file, &alt_sx))
|
||||
@@ -541,8 +539,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
free(node->data);
|
||||
if (!(node->data = strdup(our_name)))
|
||||
out_of_memory("finish_hard_link");
|
||||
node->data = strdup(our_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
ifuncs.h
16
ifuncs.h
@@ -1,6 +1,6 @@
|
||||
/* Inline functions for rsync.
|
||||
*
|
||||
* Copyright (C) 2007-2019 Wayne Davison
|
||||
* Copyright (C) 2007-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,8 +19,7 @@
|
||||
static inline void
|
||||
alloc_xbuf(xbuf *xb, size_t sz)
|
||||
{
|
||||
if (!(xb->buf = new_array(char, sz)))
|
||||
out_of_memory("alloc_xbuf");
|
||||
xb->buf = new_array(char, sz);
|
||||
xb->size = sz;
|
||||
xb->len = xb->pos = 0;
|
||||
}
|
||||
@@ -29,8 +28,6 @@ static inline void
|
||||
realloc_xbuf(xbuf *xb, size_t sz)
|
||||
{
|
||||
char *bf = realloc_array(xb->buf, char, sz);
|
||||
if (!bf)
|
||||
out_of_memory("realloc_xbuf");
|
||||
xb->buf = bf;
|
||||
xb->size = sz;
|
||||
}
|
||||
@@ -78,6 +75,7 @@ d_name(struct dirent *di)
|
||||
static inline void
|
||||
init_stat_x(stat_x *sx_p)
|
||||
{
|
||||
sx_p->crtime = 0;
|
||||
#ifdef SUPPORT_ACLS
|
||||
sx_p->acc_acl = sx_p->def_acl = NULL;
|
||||
#endif
|
||||
@@ -104,3 +102,11 @@ free_stat_x(stat_x *sx_p)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline char *my_strdup(const char *str, const char *file, int line)
|
||||
{
|
||||
int len = strlen(str)+1;
|
||||
char *buf = my_alloc(NULL, len, 1, file, line);
|
||||
memcpy(buf, str, len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ else
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
if [ -f $src ] || [ -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
|
||||
171
io.c
171
io.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2001 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -54,12 +54,14 @@ extern int read_batch;
|
||||
extern int compat_flags;
|
||||
extern int protect_args;
|
||||
extern int checksum_seed;
|
||||
extern int daemon_connection;
|
||||
extern int protocol_version;
|
||||
extern int remove_source_files;
|
||||
extern int preserve_hard_links;
|
||||
extern BOOL extra_flist_sending_enabled;
|
||||
extern BOOL flush_ok_after_signal;
|
||||
extern struct stats stats;
|
||||
extern time_t stop_at_utime;
|
||||
extern struct file_list *cur_flist;
|
||||
#ifdef ICONV_OPTION
|
||||
extern int filesfrom_convert;
|
||||
@@ -262,15 +264,18 @@ static size_t safe_read(int fd, char *buf, size_t len)
|
||||
rprintf(FINFO, "select exception on fd %d\n", fd); */
|
||||
|
||||
if (FD_ISSET(fd, &r_fds)) {
|
||||
int n = read(fd, buf + got, len - got);
|
||||
if (DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] safe_read(%d)=%ld\n", who_am_i(), fd, (long)n);
|
||||
ssize_t n = read(fd, buf + got, len - got);
|
||||
if (DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] safe_read(%d)=%" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), fd, (SIZE_T_FMT_CAST)n);
|
||||
}
|
||||
if (n == 0)
|
||||
break;
|
||||
if (n < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
rsyserr(FERROR, errno, "safe_read failed to read %ld bytes", (long)len);
|
||||
rsyserr(FERROR, errno, "safe_read failed to read %" SIZE_T_FMT_MOD "d bytes",
|
||||
(SIZE_T_FMT_CAST)len);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
if ((got += (size_t)n) == len)
|
||||
@@ -302,7 +307,7 @@ static const char *what_fd_is(int fd)
|
||||
* is not used on the socket except very early in the transfer. */
|
||||
static void safe_write(int fd, const char *buf, size_t len)
|
||||
{
|
||||
int n;
|
||||
ssize_t n;
|
||||
|
||||
assert(fd != iobuf.out_fd);
|
||||
|
||||
@@ -313,8 +318,8 @@ static void safe_write(int fd, const char *buf, size_t len)
|
||||
if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) {
|
||||
write_failed:
|
||||
rsyserr(FERROR, errno,
|
||||
"safe_write failed to write %ld bytes to %s",
|
||||
(long)len, what_fd_is(fd));
|
||||
"safe_write failed to write %" SIZE_T_FMT_MOD "d bytes to %s",
|
||||
(SIZE_T_FMT_CAST)len, what_fd_is(fd));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
} else {
|
||||
@@ -360,7 +365,7 @@ static void safe_write(int fd, const char *buf, size_t len)
|
||||
* a chunk of data and put it into the output buffer. */
|
||||
static void forward_filesfrom_data(void)
|
||||
{
|
||||
int len;
|
||||
ssize_t len;
|
||||
|
||||
len = read(ff_forward_fd, ff_xb.buf + ff_xb.len, ff_xb.size - ff_xb.len);
|
||||
if (len <= 0) {
|
||||
@@ -375,8 +380,10 @@ static void forward_filesfrom_data(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] files-from read=%ld\n", who_am_i(), (long)len);
|
||||
if (DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] files-from read=%" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)len);
|
||||
}
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
len += ff_xb.len;
|
||||
@@ -463,7 +470,7 @@ void reduce_iobuf_size(xbuf *out, size_t new_size)
|
||||
{
|
||||
if (new_size < out->size) {
|
||||
/* Avoid weird buffer interactions by only outputting this to stderr. */
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 4)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 4)) {
|
||||
const char *name = out == &iobuf.out ? "iobuf.out"
|
||||
: out == &iobuf.msg ? "iobuf.msg"
|
||||
: NULL;
|
||||
@@ -481,7 +488,7 @@ void restore_iobuf_size(xbuf *out)
|
||||
if (IOBUF_WAS_REDUCED(out->size)) {
|
||||
size_t new_size = IOBUF_RESTORE_SIZE(out->size);
|
||||
/* Avoid weird buffer interactions by only outputting this to stderr. */
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 4)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 4)) {
|
||||
const char *name = out == &iobuf.out ? "iobuf.out"
|
||||
: out == &iobuf.msg ? "iobuf.msg"
|
||||
: NULL;
|
||||
@@ -560,52 +567,59 @@ static char *perform_io(size_t needed, int flags)
|
||||
case PIO_NEED_INPUT:
|
||||
/* We never resize the circular input buffer. */
|
||||
if (iobuf.in.size < needed) {
|
||||
rprintf(FERROR, "need to read %ld bytes, iobuf.in.buf is only %ld bytes.\n",
|
||||
(long)needed, (long)iobuf.in.size);
|
||||
rprintf(FERROR, "need to read %" SIZE_T_FMT_MOD "d bytes,"
|
||||
" iobuf.in.buf is only %" SIZE_T_FMT_MOD "d bytes.\n",
|
||||
(SIZE_T_FMT_CAST)needed, (SIZE_T_FMT_CAST)iobuf.in.size);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, %sinput)\n",
|
||||
who_am_i(), (long)needed, flags & PIO_CONSUME_INPUT ? "consume&" : "");
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%" SIZE_T_FMT_MOD "d, %sinput)\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)needed, flags & PIO_CONSUME_INPUT ? "consume&" : "");
|
||||
}
|
||||
break;
|
||||
|
||||
case PIO_NEED_OUTROOM:
|
||||
/* We never resize the circular output buffer. */
|
||||
if (iobuf.out.size - iobuf.out_empty_len < needed) {
|
||||
fprintf(stderr, "need to write %ld bytes, iobuf.out.buf is only %ld bytes.\n",
|
||||
(long)needed, (long)(iobuf.out.size - iobuf.out_empty_len));
|
||||
fprintf(stderr, "need to write %" SIZE_T_FMT_MOD "d bytes,"
|
||||
" iobuf.out.buf is only %" SIZE_T_FMT_MOD "d bytes.\n",
|
||||
(SIZE_T_FMT_CAST)needed, (SIZE_T_FMT_CAST)(iobuf.out.size - iobuf.out_empty_len));
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, outroom) needs to flush %ld\n",
|
||||
who_am_i(), (long)needed,
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%" SIZE_T_FMT_MOD "d,"
|
||||
" outroom) needs to flush %" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)needed,
|
||||
iobuf.out.len + needed > iobuf.out.size
|
||||
? (long)(iobuf.out.len + needed - iobuf.out.size) : 0L);
|
||||
? (SIZE_T_FMT_CAST)(iobuf.out.len + needed - iobuf.out.size) : (SIZE_T_FMT_CAST)0);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIO_NEED_MSGROOM:
|
||||
/* We never resize the circular message buffer. */
|
||||
if (iobuf.msg.size < needed) {
|
||||
fprintf(stderr, "need to write %ld bytes, iobuf.msg.buf is only %ld bytes.\n",
|
||||
(long)needed, (long)iobuf.msg.size);
|
||||
fprintf(stderr, "need to write %" SIZE_T_FMT_MOD "d bytes,"
|
||||
" iobuf.msg.buf is only %" SIZE_T_FMT_MOD "d bytes.\n",
|
||||
(SIZE_T_FMT_CAST)needed, (SIZE_T_FMT_CAST)iobuf.msg.size);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, msgroom) needs to flush %ld\n",
|
||||
who_am_i(), (long)needed,
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%" SIZE_T_FMT_MOD "d,"
|
||||
" msgroom) needs to flush %" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)needed,
|
||||
iobuf.msg.len + needed > iobuf.msg.size
|
||||
? (long)(iobuf.msg.len + needed - iobuf.msg.size) : 0L);
|
||||
? (SIZE_T_FMT_CAST)(iobuf.msg.len + needed - iobuf.msg.size) : (SIZE_T_FMT_CAST)0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3))
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, %d)\n", who_am_i(), (long)needed, flags);
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%" SIZE_T_FMT_MOD "d, %d)\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)needed, flags);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -662,9 +676,9 @@ static char *perform_io(size_t needed, int flags)
|
||||
SIVAL(iobuf.out.buf + iobuf.raw_data_header_pos, 0,
|
||||
((MPLEX_BASE + (int)MSG_DATA)<<24) + iobuf.out.len - 4);
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 1)) {
|
||||
rprintf(FINFO, "[%s] send_msg(%d, %ld)\n",
|
||||
who_am_i(), (int)MSG_DATA, (long)iobuf.out.len - 4);
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 1)) {
|
||||
rprintf(FINFO, "[%s] send_msg(%d, %" SIZE_T_FMT_MOD "d)\n",
|
||||
who_am_i(), (int)MSG_DATA, (SIZE_T_FMT_CAST)iobuf.out.len - 4);
|
||||
}
|
||||
|
||||
/* reserve room for the next MSG_DATA header */
|
||||
@@ -755,7 +769,7 @@ static char *perform_io(size_t needed, int flags)
|
||||
|
||||
if (iobuf.in_fd >= 0 && FD_ISSET(iobuf.in_fd, &r_fds)) {
|
||||
size_t len, pos = iobuf.in.pos + iobuf.in.len;
|
||||
int n;
|
||||
ssize_t n;
|
||||
if (pos >= iobuf.in.size) {
|
||||
pos -= iobuf.in.size;
|
||||
len = iobuf.in.size - iobuf.in.len;
|
||||
@@ -782,12 +796,14 @@ static char *perform_io(size_t needed, int flags)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
}
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] recv=%ld\n", who_am_i(), (long)n);
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] recv=%" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)n);
|
||||
}
|
||||
|
||||
if (io_timeout) {
|
||||
last_io_in = time(NULL);
|
||||
if (flags & PIO_NEED_INPUT)
|
||||
if (io_timeout && flags & PIO_NEED_INPUT)
|
||||
maybe_send_keepalive(last_io_in, 0);
|
||||
}
|
||||
stats.total_read += n;
|
||||
@@ -795,9 +811,14 @@ static char *perform_io(size_t needed, int flags)
|
||||
iobuf.in.len += n;
|
||||
}
|
||||
|
||||
if (stop_at_utime && time(NULL) >= stop_at_utime) {
|
||||
rprintf(FERROR, "stopping at requested limit\n");
|
||||
exit_cleanup(RERR_TIMEOUT);
|
||||
}
|
||||
|
||||
if (out && FD_ISSET(iobuf.out_fd, &w_fds)) {
|
||||
size_t len = iobuf.raw_flushing_ends_before ? iobuf.raw_flushing_ends_before - out->pos : out->len;
|
||||
int n;
|
||||
ssize_t n;
|
||||
|
||||
if (bwlimit_writemax && len > bwlimit_writemax)
|
||||
len = bwlimit_writemax;
|
||||
@@ -817,9 +838,9 @@ static char *perform_io(size_t needed, int flags)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
}
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] %s sent=%ld\n",
|
||||
who_am_i(), out == &iobuf.out ? "out" : "msg", (long)n);
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] %s sent=%" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), out == &iobuf.out ? "out" : "msg", (SIZE_T_FMT_CAST)n);
|
||||
}
|
||||
|
||||
if (io_timeout)
|
||||
@@ -912,7 +933,11 @@ void noop_io_until_death(void)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
if (!iobuf.in.buf || !iobuf.out.buf || iobuf.in_fd < 0 || iobuf.out_fd < 0 || kluge_around_eof || msgs2stderr)
|
||||
if (!iobuf.in.buf || !iobuf.out.buf || iobuf.in_fd < 0 || iobuf.out_fd < 0 || kluge_around_eof)
|
||||
return;
|
||||
|
||||
/* If we're talking to a daemon over a socket, don't short-circuit this logic */
|
||||
if (msgs2stderr && daemon_connection >= 0)
|
||||
return;
|
||||
|
||||
kluge_around_eof = 2;
|
||||
@@ -930,13 +955,15 @@ int send_msg(enum msgcode code, const char *buf, size_t len, int convert)
|
||||
{
|
||||
char *hdr;
|
||||
size_t needed, pos;
|
||||
BOOL want_debug = DEBUG_GTE(IO, 1) && convert >= 0 && (msgs2stderr || code != MSG_INFO);
|
||||
BOOL want_debug = DEBUG_GTE(IO, 1) && convert >= 0 && (msgs2stderr == 1 || code != MSG_INFO);
|
||||
|
||||
if (!OUT_MULTIPLEXED)
|
||||
return 0;
|
||||
|
||||
if (want_debug)
|
||||
rprintf(FINFO, "[%s] send_msg(%d, %ld)\n", who_am_i(), (int)code, (long)len);
|
||||
if (want_debug) {
|
||||
rprintf(FINFO, "[%s] send_msg(%d, %" SIZE_T_FMT_MOD "d)\n",
|
||||
who_am_i(), (int)code, (SIZE_T_FMT_CAST)len);
|
||||
}
|
||||
|
||||
/* When checking for enough free space for this message, we need to
|
||||
* make sure that there is space for the 4-byte header, plus we'll
|
||||
@@ -952,9 +979,9 @@ int send_msg(enum msgcode code, const char *buf, size_t len, int convert)
|
||||
#endif
|
||||
needed = len + 4 + 3;
|
||||
if (iobuf.msg.len + needed > iobuf.msg.size) {
|
||||
if (!am_receiver)
|
||||
if (am_sender)
|
||||
perform_io(needed, PIO_NEED_MSGROOM);
|
||||
else { /* We allow the receiver to increase their iobuf.msg size to avoid a deadlock. */
|
||||
else { /* We sometimes allow the iobuf.msg size to increase to avoid a deadlock. */
|
||||
size_t old_size = iobuf.msg.size;
|
||||
restore_iobuf_size(&iobuf.msg);
|
||||
realloc_xbuf(&iobuf.msg, iobuf.msg.size * 2);
|
||||
@@ -1011,8 +1038,10 @@ int send_msg(enum msgcode code, const char *buf, size_t len, int convert)
|
||||
|
||||
SIVAL(hdr, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
if (want_debug && convert > 0)
|
||||
rprintf(FINFO, "[%s] converted msg len=%ld\n", who_am_i(), (long)len);
|
||||
if (want_debug && convert > 0) {
|
||||
rprintf(FINFO, "[%s] converted msg len=%" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)len);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1239,8 +1268,7 @@ void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
rl_flags |= (protect_args && ic_recv != (iconv_t)-1 ? RL_CONVERT : 0);
|
||||
#endif
|
||||
|
||||
if (!(argv = new_array(char *, maxargs)))
|
||||
out_of_memory("read_args");
|
||||
argv = new_array(char *, maxargs);
|
||||
if (mod_name && !protect_args)
|
||||
argv[argc++] = "rsyncd";
|
||||
|
||||
@@ -1253,8 +1281,7 @@ void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
|
||||
if (argc == maxargs-1) {
|
||||
maxargs += MAX_ARGS;
|
||||
if (!(argv = realloc_array(argv, char *, maxargs)))
|
||||
out_of_memory("read_args");
|
||||
argv = realloc_array(argv, char *, maxargs);
|
||||
}
|
||||
|
||||
if (dot_pos) {
|
||||
@@ -1262,8 +1289,7 @@ void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
int len = strlen(buf);
|
||||
if (request_len)
|
||||
request_p[0][request_len++] = ' ';
|
||||
if (!(*request_p = realloc_array(*request_p, char, request_len + len + 1)))
|
||||
out_of_memory("read_args");
|
||||
*request_p = realloc_array(*request_p, char, request_len + len + 1);
|
||||
memcpy(*request_p + request_len, buf, len + 1);
|
||||
request_len += len;
|
||||
}
|
||||
@@ -1272,8 +1298,7 @@ void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
else
|
||||
glob_expand(buf, &argv, &argc, &maxargs);
|
||||
} else {
|
||||
if (!(p = strdup(buf)))
|
||||
out_of_memory("read_args");
|
||||
p = strdup(buf);
|
||||
argv[argc++] = p;
|
||||
if (*p == '.' && p[1] == '\0')
|
||||
dot_pos = argc;
|
||||
@@ -1289,7 +1314,7 @@ void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
|
||||
BOOL io_start_buffering_out(int f_out)
|
||||
{
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] io_start_buffering_out(%d)\n", who_am_i(), f_out);
|
||||
|
||||
if (iobuf.out.buf) {
|
||||
@@ -1308,7 +1333,7 @@ BOOL io_start_buffering_out(int f_out)
|
||||
|
||||
BOOL io_start_buffering_in(int f_in)
|
||||
{
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] io_start_buffering_in(%d)\n", who_am_i(), f_in);
|
||||
|
||||
if (iobuf.in.buf) {
|
||||
@@ -1327,7 +1352,7 @@ BOOL io_start_buffering_in(int f_in)
|
||||
|
||||
void io_end_buffering_in(BOOL free_buffers)
|
||||
{
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] io_end_buffering_in(IOBUF_%s_BUFS)\n",
|
||||
who_am_i(), free_buffers ? "FREE" : "KEEP");
|
||||
}
|
||||
@@ -1342,7 +1367,7 @@ void io_end_buffering_in(BOOL free_buffers)
|
||||
|
||||
void io_end_buffering_out(BOOL free_buffers)
|
||||
{
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] io_end_buffering_out(IOBUF_%s_BUFS)\n",
|
||||
who_am_i(), free_buffers ? "FREE" : "KEEP");
|
||||
}
|
||||
@@ -1430,8 +1455,10 @@ static void read_a_msg(void)
|
||||
msg_bytes = tag & 0xFFFFFF;
|
||||
tag = (tag >> 24) - MPLEX_BASE;
|
||||
|
||||
if (DEBUG_GTE(IO, 1) && msgs2stderr)
|
||||
rprintf(FINFO, "[%s] got msg=%d, len=%ld\n", who_am_i(), (int)tag, (long)msg_bytes);
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 1)) {
|
||||
rprintf(FINFO, "[%s] got msg=%d, len=%" SIZE_T_FMT_MOD "d\n",
|
||||
who_am_i(), (int)tag, (SIZE_T_FMT_CAST)msg_bytes);
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
case MSG_DATA:
|
||||
@@ -1607,8 +1634,10 @@ static void read_a_msg(void)
|
||||
else
|
||||
goto invalid_msg;
|
||||
iobuf.in_multiplexed = 1;
|
||||
if (DEBUG_GTE(EXIT, 3))
|
||||
rprintf(FINFO, "[%s] got MSG_ERROR_EXIT with %ld bytes\n", who_am_i(), (long)msg_bytes);
|
||||
if (DEBUG_GTE(EXIT, 3)) {
|
||||
rprintf(FINFO, "[%s] got MSG_ERROR_EXIT with %" SIZE_T_FMT_MOD "d bytes\n",
|
||||
who_am_i(), (SIZE_T_FMT_CAST)msg_bytes);
|
||||
}
|
||||
if (msg_bytes == 0) {
|
||||
if (!am_sender && !am_generator) {
|
||||
if (DEBUG_GTE(EXIT, 3)) {
|
||||
@@ -2302,7 +2331,7 @@ void io_start_multiplex_out(int fd)
|
||||
{
|
||||
io_flush(FULL_FLUSH);
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] io_start_multiplex_out(%d)\n", who_am_i(), fd);
|
||||
|
||||
if (!iobuf.msg.buf)
|
||||
@@ -2319,7 +2348,7 @@ void io_start_multiplex_out(int fd)
|
||||
/* Setup for multiplexing a MSG_* stream with the data stream. */
|
||||
void io_start_multiplex_in(int fd)
|
||||
{
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] io_start_multiplex_in(%d)\n", who_am_i(), fd);
|
||||
|
||||
iobuf.in_multiplexed = 1; /* See also IN_MULTIPLEXED */
|
||||
@@ -2330,7 +2359,7 @@ int io_end_multiplex_in(int mode)
|
||||
{
|
||||
int ret = iobuf.in_multiplexed ? iobuf.in_fd : -1;
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] io_end_multiplex_in(mode=%d)\n", who_am_i(), mode);
|
||||
|
||||
iobuf.in_multiplexed = 0;
|
||||
@@ -2348,7 +2377,7 @@ int io_end_multiplex_out(int mode)
|
||||
{
|
||||
int ret = iobuf.out_empty_len ? iobuf.out_fd : -1;
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] io_end_multiplex_out(mode=%d)\n", who_am_i(), mode);
|
||||
|
||||
if (mode != MPLX_TO_BUFFERED)
|
||||
|
||||
8
itypes.h
8
itypes.h
@@ -1,6 +1,6 @@
|
||||
/* Inline functions for rsync.
|
||||
*
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -40,6 +40,12 @@ isSpace(const char *ptr)
|
||||
return isspace(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isAlNum(const char *ptr)
|
||||
{
|
||||
return isalnum(*(unsigned char *)ptr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isLower(const char *ptr)
|
||||
{
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define LATEST_YEAR "2020"
|
||||
#define LATEST_YEAR "2022"
|
||||
|
||||
85
lib/compat.c
85
lib/compat.c
@@ -24,16 +24,24 @@
|
||||
|
||||
static char number_separator;
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup(char *s)
|
||||
char get_number_separator(void)
|
||||
{
|
||||
int len = strlen(s) + 1;
|
||||
char *ret = (char *)malloc(len);
|
||||
if (ret)
|
||||
memcpy(ret, s, len);
|
||||
return ret;
|
||||
if (!number_separator) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof buf, "%f", 3.14);
|
||||
if (strchr(buf, '.') != NULL)
|
||||
number_separator = ',';
|
||||
else
|
||||
number_separator = '.';
|
||||
}
|
||||
|
||||
return number_separator;
|
||||
}
|
||||
|
||||
char get_decimal_point(void)
|
||||
{
|
||||
return get_number_separator() == ',' ? '.' : ',';
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETCWD
|
||||
char *getcwd(char *buf, int size)
|
||||
@@ -155,30 +163,6 @@ int sys_gettimeofday(struct timeval *tv)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define HUMANIFY(mult) \
|
||||
do { \
|
||||
if (num >= mult || num <= -mult) { \
|
||||
double dnum = (double)num / mult; \
|
||||
char units; \
|
||||
if (num < 0) \
|
||||
dnum = -dnum; \
|
||||
if (dnum < mult) \
|
||||
units = 'K'; \
|
||||
else if ((dnum /= mult) < mult) \
|
||||
units = 'M'; \
|
||||
else if ((dnum /= mult) < mult) \
|
||||
units = 'G'; \
|
||||
else { \
|
||||
dnum /= mult; \
|
||||
units = 'T'; \
|
||||
} \
|
||||
if (num < 0) \
|
||||
dnum = -dnum; \
|
||||
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); \
|
||||
return bufs[n]; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Return the int64 number as a string. If the human_flag arg is non-zero,
|
||||
* we may output the number in K, M, G, or T units. If we don't add a unit
|
||||
* suffix, we will append the fract string, if it is non-NULL. We can
|
||||
@@ -190,22 +174,35 @@ char *do_big_num(int64 num, int human_flag, const char *fract)
|
||||
char *s;
|
||||
int len, negated;
|
||||
|
||||
if (human_flag && !number_separator) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof buf, "%f", 3.14);
|
||||
if (strchr(buf, '.') != NULL)
|
||||
number_separator = ',';
|
||||
else
|
||||
number_separator = '.';
|
||||
}
|
||||
if (human_flag && !number_separator)
|
||||
(void)get_number_separator();
|
||||
|
||||
n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
|
||||
|
||||
if (human_flag > 1) {
|
||||
if (human_flag == 2)
|
||||
HUMANIFY(1000);
|
||||
else
|
||||
HUMANIFY(1024);
|
||||
int mult = human_flag == 2 ? 1000 : 1024;
|
||||
if (num >= mult || num <= -mult) {
|
||||
double dnum = (double)num / mult;
|
||||
char units;
|
||||
if (num < 0)
|
||||
dnum = -dnum;
|
||||
if (dnum < mult)
|
||||
units = 'K';
|
||||
else if ((dnum /= mult) < mult)
|
||||
units = 'M';
|
||||
else if ((dnum /= mult) < mult)
|
||||
units = 'G';
|
||||
else if ((dnum /= mult) < mult)
|
||||
units = 'T';
|
||||
else {
|
||||
dnum /= mult;
|
||||
units = 'P';
|
||||
}
|
||||
if (num < 0)
|
||||
dnum = -dnum;
|
||||
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units);
|
||||
return bufs[n];
|
||||
}
|
||||
}
|
||||
|
||||
s = bufs[n] + sizeof bufs[0] - 1;
|
||||
|
||||
17
lib/md-defines.h
Normal file
17
lib/md-defines.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* Keep this simple so both C and ASM can use it */
|
||||
|
||||
#define MD4_DIGEST_LEN 16
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#define MAX_DIGEST_LEN MD5_DIGEST_LEN
|
||||
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
#define CSUM_NONE 0
|
||||
#define CSUM_MD4_ARCHAIC 1
|
||||
#define CSUM_MD4_BUSTED 2
|
||||
#define CSUM_MD4_OLD 3
|
||||
#define CSUM_MD4 4
|
||||
#define CSUM_MD5 5
|
||||
#define CSUM_XXH64 6
|
||||
#define CSUM_XXH3_64 7
|
||||
#define CSUM_XXH3_128 8
|
||||
@@ -24,11 +24,19 @@
|
||||
* show any significant difference in performance, though.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "md-defines.h"
|
||||
|
||||
#if !defined USE_OPENSSL && CSUM_CHUNK == 64
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define md5_process_asm _md5_process_asm
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 16
|
||||
|
||||
.globl md5_process_asm
|
||||
.type md5_process_asm,@function
|
||||
md5_process_asm:
|
||||
push %rbp
|
||||
push %rbx
|
||||
@@ -689,5 +697,5 @@ md5_process_asm:
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
.L_md5_process_asm_end:
|
||||
.size md5_process_asm,.L_md5_process_asm_end-md5_process_asm
|
||||
|
||||
#endif /* !USE_OPENSSL ... */
|
||||
@@ -148,7 +148,7 @@ static void md5_process(md_context *ctx, const uchar data[CSUM_CHUNK])
|
||||
ctx->D += D;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SIMD) && (CSUM_CHUNK == 64)
|
||||
#if defined HAVE_ASM && CSUM_CHUNK == 64
|
||||
extern void md5_process_asm(md_context *ctx, const void *data, size_t num);
|
||||
#endif
|
||||
|
||||
@@ -176,7 +176,7 @@ void md5_update(md_context *ctx, const uchar *input, uint32 length)
|
||||
left = 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SIMD) && (CSUM_CHUNK == 64)
|
||||
#if defined HAVE_ASM && CSUM_CHUNK == 64
|
||||
if (length >= CSUM_CHUNK) {
|
||||
uint32 chunks = length / CSUM_CHUNK;
|
||||
md5_process_asm(ctx, input, chunks);
|
||||
|
||||
@@ -4,20 +4,7 @@
|
||||
#include "openssl/md4.h"
|
||||
#include "openssl/md5.h"
|
||||
#endif
|
||||
|
||||
#define MD4_DIGEST_LEN 16
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#define MAX_DIGEST_LEN MD5_DIGEST_LEN
|
||||
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
#define CSUM_NONE 0
|
||||
#define CSUM_MD4_ARCHAIC 1
|
||||
#define CSUM_MD4_BUSTED 2
|
||||
#define CSUM_MD4_OLD 3
|
||||
#define CSUM_MD4 4
|
||||
#define CSUM_MD5 5
|
||||
#define CSUM_XXH64 6
|
||||
#include "md-defines.h"
|
||||
|
||||
typedef struct {
|
||||
uint32 A, B, C, D;
|
||||
|
||||
@@ -33,7 +33,7 @@ pool_alloc, pool_free, pool_free_old, pool_talloc, pool_tfree, pool_create, pool
|
||||
.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);
|
||||
\fBstruct alloc_pool *pool_create(size_t \fIsize\fB, size_t \fIquantum\fB, void (*\fIbomb\fB)(char*,char*,int), int \fIflags\fB);
|
||||
|
||||
\fBvoid pool_destroy(struct alloc_pool *\fIpool\fB);
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@ struct alloc_pool
|
||||
size_t size; /* extent size */
|
||||
size_t quantum; /* allocation quantum */
|
||||
struct pool_extent *extents; /* top extent is "live" */
|
||||
void (*bomb)(); /* function to call if
|
||||
* malloc fails */
|
||||
void (*bomb)(); /* called if malloc fails */
|
||||
int flags;
|
||||
|
||||
/* statistical data */
|
||||
@@ -45,13 +44,13 @@ struct align_test {
|
||||
#define PTR_ADD(b,o) ( (void*) ((char*)(b) + (o)) )
|
||||
|
||||
alloc_pool_t
|
||||
pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags)
|
||||
pool_create(size_t size, size_t quantum, void (*bomb)(const char*, const char*, int), int flags)
|
||||
{
|
||||
struct alloc_pool *pool;
|
||||
|
||||
if ((MINALIGN & (MINALIGN - 1)) != 0) {
|
||||
if ((MINALIGN & (MINALIGN - 1)) != (0)) {
|
||||
if (bomb)
|
||||
(*bomb)("Compiler error: MINALIGN is not a power of 2\n");
|
||||
(*bomb)("Compiler error: MINALIGN is not a power of 2", __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -169,7 +168,7 @@ pool_alloc(alloc_pool_t p, size_t len, const char *bomb_msg)
|
||||
|
||||
bomb_out:
|
||||
if (pool->bomb)
|
||||
(*pool->bomb)(bomb_msg);
|
||||
(*pool->bomb)(bomb_msg, __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
typedef void *alloc_pool_t;
|
||||
|
||||
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags);
|
||||
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(const char*, const char*, int), int flags);
|
||||
void pool_destroy(alloc_pool_t pool);
|
||||
void *pool_alloc(alloc_pool_t pool, size_t size, const char *bomb_msg);
|
||||
void pool_free(alloc_pool_t pool, size_t size, void *addr);
|
||||
|
||||
632
lib/sysacls.c
632
lib/sysacls.c
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
* Version 2.2.x
|
||||
* Portable SMB ACL interface
|
||||
* Copyright (C) Jeremy Allison 2000
|
||||
* Copyright (C) 2007-2019 Wayne Davison
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -139,7 +139,9 @@ typedef struct acl *SMB_ACL_ENTRY_T;
|
||||
|
||||
/* Based on the Solaris & UnixWare code. */
|
||||
|
||||
#ifndef __TANDEM
|
||||
#undef GROUP
|
||||
#endif
|
||||
#include <sys/aclv.h>
|
||||
|
||||
/* SVR4.2 ES/MP ACLs */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Extended attribute support for rsync.
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc.
|
||||
* Copyright (C) 2003-2019 Wayne Davison
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Written by Jay Fenlason.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -67,7 +67,7 @@ ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t si
|
||||
u_int32_t offset = len;
|
||||
size_t data_retrieved = len;
|
||||
while (data_retrieved < size) {
|
||||
len = getxattr(path, name, value + offset, size - data_retrieved, offset, XATTR_NOFOLLOW);
|
||||
len = getxattr(path, name, (char*)value + offset, size - data_retrieved, offset, XATTR_NOFOLLOW);
|
||||
if (len <= 0)
|
||||
break;
|
||||
data_retrieved += len;
|
||||
@@ -167,7 +167,7 @@ static ssize_t read_xattr(int attrfd, void *buf, size_t buflen)
|
||||
} else {
|
||||
size_t bufpos;
|
||||
for (bufpos = 0; bufpos < sb.st_size; ) {
|
||||
ssize_t cnt = read(attrfd, buf + bufpos, sb.st_size - bufpos);
|
||||
ssize_t cnt = read(attrfd, (char*)buf + bufpos, sb.st_size - bufpos);
|
||||
if (cnt <= 0) {
|
||||
if (cnt < 0 && errno == EINTR)
|
||||
continue;
|
||||
@@ -218,7 +218,7 @@ int sys_lsetxattr(const char *path, const char *name, const void *value, size_t
|
||||
return -1;
|
||||
|
||||
for (bufpos = 0; bufpos < size; ) {
|
||||
ssize_t cnt = write(attrfd, value+bufpos, size);
|
||||
ssize_t cnt = write(attrfd, (char*)value + bufpos, size);
|
||||
if (cnt <= 0) {
|
||||
if (cnt < 0 && errno == EINTR)
|
||||
continue;
|
||||
@@ -274,7 +274,8 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
|
||||
&& (dp->d_name[10] == 'o' || dp->d_name[10] == 'w'))
|
||||
continue;
|
||||
|
||||
if ((ret += len+1) > size) {
|
||||
ret += len + 1;
|
||||
if ((size_t)ret > size) {
|
||||
if (size == 0)
|
||||
continue;
|
||||
ret = -1;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifdef SUPPORT_XATTRS
|
||||
|
||||
#if defined HAVE_ATTR_XATTR_H
|
||||
#include <attr/xattr.h>
|
||||
#elif defined HAVE_SYS_XATTR_H
|
||||
#if defined HAVE_SYS_XATTR_H
|
||||
#include <sys/xattr.h>
|
||||
#elif defined HAVE_ATTR_XATTR_H
|
||||
#include <attr/xattr.h>
|
||||
#elif defined HAVE_SYS_EXTATTR_H
|
||||
#include <sys/extattr.h>
|
||||
#endif
|
||||
|
||||
461
loadparm.c
461
loadparm.c
@@ -42,24 +42,20 @@
|
||||
|
||||
#include "rsync.h"
|
||||
#include "itypes.h"
|
||||
#include "ifuncs.h"
|
||||
#include "default-dont-compress.h"
|
||||
|
||||
extern item_list dparam_list;
|
||||
|
||||
#define strequal(a, b) (strcasecmp(a, b)==0)
|
||||
#define BOOLSTR(b) ((b) ? "Yes" : "No")
|
||||
|
||||
#ifndef LOG_DAEMON
|
||||
#define LOG_DAEMON 0
|
||||
#endif
|
||||
|
||||
#define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \
|
||||
" *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg *.png" \
|
||||
" *.lzo *.rzip *.lzma *.rar *.ace *.gpg *.xz *.txz *.lz *.tlz" \
|
||||
" *.ogv *.web[mp] *.squashfs"
|
||||
|
||||
/* the following are used by loadparm for option lists */
|
||||
typedef enum {
|
||||
P_BOOL, P_BOOLREV, P_CHAR, P_INTEGER,
|
||||
P_BOOL, P_BOOLREV, P_BOOL3, P_CHAR, P_INTEGER,
|
||||
P_OCTAL, P_PATH, P_STRING, P_ENUM
|
||||
} parm_type;
|
||||
|
||||
@@ -90,234 +86,6 @@ struct parm_struct {
|
||||
#define LP_SNUM_OK(i) ((i) >= 0 && (i) < (int)section_list.count)
|
||||
#define SECTION_PTR(s, p) (((char*)(s)) + (ptrdiff_t)(((char*)(p))-(char*)&Vars.l))
|
||||
|
||||
/* This structure describes global (ie., server-wide) parameters. */
|
||||
typedef struct {
|
||||
char *bind_address;
|
||||
char *daemon_chroot;
|
||||
char *daemon_gid;
|
||||
char *daemon_uid;
|
||||
char *motd_file;
|
||||
char *pid_file;
|
||||
char *socket_options;
|
||||
|
||||
/* Each _EXP var tracks if the associated char* var has been expanded yet or not. */
|
||||
BOOL bind_address_EXP;
|
||||
BOOL daemon_chroot_EXP;
|
||||
BOOL daemon_gid_EXP;
|
||||
BOOL daemon_uid_EXP;
|
||||
BOOL motd_file_EXP;
|
||||
BOOL pid_file_EXP;
|
||||
BOOL socket_options_EXP;
|
||||
|
||||
int listen_backlog;
|
||||
int rsync_port;
|
||||
|
||||
BOOL proxy_protocol;
|
||||
} global_vars;
|
||||
|
||||
/* This structure describes a single section. 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.)
|
||||
* NOTE: the char* variables MUST all remain at the start of the struct! */
|
||||
typedef struct {
|
||||
char *auth_users;
|
||||
char *charset;
|
||||
char *comment;
|
||||
char *dont_compress;
|
||||
char *early_exec;
|
||||
char *exclude;
|
||||
char *exclude_from;
|
||||
char *filter;
|
||||
char *gid;
|
||||
char *hosts_allow;
|
||||
char *hosts_deny;
|
||||
char *include;
|
||||
char *include_from;
|
||||
char *incoming_chmod;
|
||||
char *lock_file;
|
||||
char *log_file;
|
||||
char *log_format;
|
||||
char *name;
|
||||
char *outgoing_chmod;
|
||||
char *path;
|
||||
char *postxfer_exec;
|
||||
char *prexfer_exec;
|
||||
char *refuse_options;
|
||||
char *secrets_file;
|
||||
char *syslog_tag;
|
||||
char *temp_dir;
|
||||
char *uid;
|
||||
|
||||
/* Each _EXP var tracks if the associated char* var has been expanded yet or not. */
|
||||
BOOL auth_users_EXP;
|
||||
BOOL charset_EXP;
|
||||
BOOL comment_EXP;
|
||||
BOOL dont_compress_EXP;
|
||||
BOOL early_exec_EXP;
|
||||
BOOL exclude_EXP;
|
||||
BOOL exclude_from_EXP;
|
||||
BOOL filter_EXP;
|
||||
BOOL gid_EXP;
|
||||
BOOL hosts_allow_EXP;
|
||||
BOOL hosts_deny_EXP;
|
||||
BOOL include_EXP;
|
||||
BOOL include_from_EXP;
|
||||
BOOL incoming_chmod_EXP;
|
||||
BOOL lock_file_EXP;
|
||||
BOOL log_file_EXP;
|
||||
BOOL log_format_EXP;
|
||||
BOOL name_EXP;
|
||||
BOOL outgoing_chmod_EXP;
|
||||
BOOL path_EXP;
|
||||
BOOL postxfer_exec_EXP;
|
||||
BOOL prexfer_exec_EXP;
|
||||
BOOL refuse_options_EXP;
|
||||
BOOL secrets_file_EXP;
|
||||
BOOL syslog_tag_EXP;
|
||||
BOOL temp_dir_EXP;
|
||||
BOOL uid_EXP;
|
||||
|
||||
int max_connections;
|
||||
int max_verbosity;
|
||||
int syslog_facility;
|
||||
int timeout;
|
||||
|
||||
BOOL fake_super;
|
||||
BOOL forward_lookup;
|
||||
BOOL ignore_errors;
|
||||
BOOL ignore_nonreadable;
|
||||
BOOL list;
|
||||
BOOL munge_symlinks;
|
||||
BOOL numeric_ids;
|
||||
BOOL read_only;
|
||||
BOOL reverse_lookup;
|
||||
BOOL strict_modes;
|
||||
BOOL transfer_logging;
|
||||
BOOL use_chroot;
|
||||
BOOL write_only;
|
||||
} local_vars;
|
||||
|
||||
/* This structure describes the global variables (g) as well as the globally
|
||||
* specified values of the local variables (l), which are used when modules
|
||||
* don't specify their own values. */
|
||||
typedef struct {
|
||||
global_vars g;
|
||||
local_vars l;
|
||||
} all_vars;
|
||||
|
||||
/* The application defaults for all the variables. "Defaults" is
|
||||
* used to re-initialize "Vars" before each config-file read.
|
||||
*
|
||||
* In order to keep these sorted in the same way as the structure
|
||||
* above, use the variable name in the leading comment, including a
|
||||
* trailing ';' (to avoid a sorting problem with trailing digits). */
|
||||
static const all_vars Defaults = {
|
||||
/* ==== global_vars ==== */
|
||||
{
|
||||
/* bind_address; */ NULL,
|
||||
/* daemon_chroot; */ NULL,
|
||||
/* daemon_gid; */ NULL,
|
||||
/* daemon_uid; */ NULL,
|
||||
/* motd_file; */ NULL,
|
||||
/* pid_file; */ NULL,
|
||||
/* socket_options; */ NULL,
|
||||
|
||||
/* bind_address_EXP; */ False,
|
||||
/* daemon_chroot_EXP; */ False,
|
||||
/* daemon_gid_EXP; */ False,
|
||||
/* daemon_uid_EXP; */ False,
|
||||
/* motd_file_EXP; */ False,
|
||||
/* pid_file_EXP; */ False,
|
||||
/* socket_options_EXP; */ False,
|
||||
|
||||
/* listen_backlog; */ 5,
|
||||
/* rsync_port; */ 0,
|
||||
|
||||
/* proxy_protocol; */ False,
|
||||
},
|
||||
|
||||
/* ==== local_vars ==== */
|
||||
{
|
||||
/* auth_users; */ NULL,
|
||||
/* charset; */ NULL,
|
||||
/* comment; */ NULL,
|
||||
/* dont_compress; */ DEFAULT_DONT_COMPRESS,
|
||||
/* early_exec; */ NULL,
|
||||
/* exclude; */ NULL,
|
||||
/* exclude_from; */ NULL,
|
||||
/* filter; */ NULL,
|
||||
/* gid; */ NULL,
|
||||
/* hosts_allow; */ NULL,
|
||||
/* hosts_deny; */ NULL,
|
||||
/* include; */ NULL,
|
||||
/* include_from; */ NULL,
|
||||
/* incoming_chmod; */ NULL,
|
||||
/* lock_file; */ DEFAULT_LOCK_FILE,
|
||||
/* log_file; */ NULL,
|
||||
/* log_format; */ "%o %h [%a] %m (%u) %f %l",
|
||||
/* name; */ NULL,
|
||||
/* outgoing_chmod; */ NULL,
|
||||
/* path; */ NULL,
|
||||
/* postxfer_exec; */ NULL,
|
||||
/* prexfer_exec; */ NULL,
|
||||
/* refuse_options; */ NULL,
|
||||
/* secrets_file; */ NULL,
|
||||
/* syslog_tag; */ "rsyncd",
|
||||
/* temp_dir; */ NULL,
|
||||
/* uid; */ NULL,
|
||||
|
||||
/* auth_users_EXP; */ False,
|
||||
/* charset_EXP; */ False,
|
||||
/* comment_EXP; */ False,
|
||||
/* dont_compress_EXP; */ False,
|
||||
/* early_exec_EXP; */ False,
|
||||
/* exclude_EXP; */ False,
|
||||
/* exclude_from_EXP; */ False,
|
||||
/* filter_EXP; */ False,
|
||||
/* gid_EXP; */ False,
|
||||
/* hosts_allow_EXP; */ False,
|
||||
/* hosts_deny_EXP; */ False,
|
||||
/* include_EXP; */ False,
|
||||
/* include_from_EXP; */ False,
|
||||
/* incoming_chmod_EXP; */ False,
|
||||
/* lock_file_EXP; */ False,
|
||||
/* log_file_EXP; */ False,
|
||||
/* log_format_EXP; */ False,
|
||||
/* name_EXP; */ False,
|
||||
/* outgoing_chmod_EXP; */ False,
|
||||
/* path_EXP; */ False,
|
||||
/* postxfer_exec_EXP; */ False,
|
||||
/* prexfer_exec_EXP; */ False,
|
||||
/* refuse_options_EXP; */ False,
|
||||
/* secrets_file_EXP; */ False,
|
||||
/* syslog_tag_EXP; */ False,
|
||||
/* temp_dir_EXP; */ False,
|
||||
/* uid_EXP; */ False,
|
||||
|
||||
/* max_connections; */ 0,
|
||||
/* max_verbosity; */ 1,
|
||||
/* syslog_facility; */ LOG_DAEMON,
|
||||
/* timeout; */ 0,
|
||||
|
||||
/* fake_super; */ False,
|
||||
/* forward_lookup; */ True,
|
||||
/* ignore_errors; */ False,
|
||||
/* ignore_nonreadable; */ False,
|
||||
/* list; */ True,
|
||||
/* munge_symlinks; */ (BOOL)-1,
|
||||
/* numeric_ids; */ (BOOL)-1,
|
||||
/* read_only; */ True,
|
||||
/* reverse_lookup; */ True,
|
||||
/* strict_modes; */ True,
|
||||
/* transfer_logging; */ False,
|
||||
/* use_chroot; */ True,
|
||||
/* write_only; */ False,
|
||||
}
|
||||
};
|
||||
|
||||
/* The currently configured values for all the variables. */
|
||||
static all_vars Vars;
|
||||
|
||||
/* Stack of "Vars" values used by the &include directive. */
|
||||
static item_list Vars_stack = EMPTY_ITEM_LIST;
|
||||
|
||||
@@ -327,9 +95,7 @@ static item_list section_list = EMPTY_ITEM_LIST;
|
||||
static int iSectionIndex = -1;
|
||||
static BOOL bInGlobalSection = True;
|
||||
|
||||
#define NUMPARAMETERS (sizeof (parm_table) / sizeof (struct parm_struct))
|
||||
|
||||
static struct enum_list enum_facilities[] = {
|
||||
static struct enum_list enum_syslog_facility[] = {
|
||||
#ifdef LOG_AUTH
|
||||
{ LOG_AUTH, "auth" },
|
||||
#endif
|
||||
@@ -396,96 +162,27 @@ static struct enum_list enum_facilities[] = {
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
static struct parm_struct parm_table[] =
|
||||
{
|
||||
{"address", P_STRING, P_GLOBAL,&Vars.g.bind_address, NULL,0},
|
||||
{"daemon chroot", P_STRING, P_GLOBAL,&Vars.g.daemon_chroot, NULL,0},
|
||||
{"daemon gid", P_STRING, P_GLOBAL,&Vars.g.daemon_gid, NULL,0},
|
||||
{"daemon uid", P_STRING, P_GLOBAL,&Vars.g.daemon_uid, NULL,0},
|
||||
{"listen backlog", P_INTEGER,P_GLOBAL,&Vars.g.listen_backlog, NULL,0},
|
||||
{"motd file", P_STRING, P_GLOBAL,&Vars.g.motd_file, NULL,0},
|
||||
{"pid file", P_STRING, P_GLOBAL,&Vars.g.pid_file, NULL,0},
|
||||
{"port", P_INTEGER,P_GLOBAL,&Vars.g.rsync_port, NULL,0},
|
||||
{"proxy protocol", P_BOOL, P_LOCAL, &Vars.g.proxy_protocol, NULL,0},
|
||||
{"socket options", P_STRING, P_GLOBAL,&Vars.g.socket_options, NULL,0},
|
||||
|
||||
{"auth users", P_STRING, P_LOCAL, &Vars.l.auth_users, NULL,0},
|
||||
{"charset", P_STRING, P_LOCAL, &Vars.l.charset, NULL,0},
|
||||
{"comment", P_STRING, P_LOCAL, &Vars.l.comment, NULL,0},
|
||||
{"dont compress", P_STRING, P_LOCAL, &Vars.l.dont_compress, NULL,0},
|
||||
{"early exec", P_STRING, P_LOCAL, &Vars.l.early_exec, NULL,0},
|
||||
{"exclude from", P_STRING, P_LOCAL, &Vars.l.exclude_from, NULL,0},
|
||||
{"exclude", P_STRING, P_LOCAL, &Vars.l.exclude, NULL,0},
|
||||
{"fake super", P_BOOL, P_LOCAL, &Vars.l.fake_super, NULL,0},
|
||||
{"filter", P_STRING, P_LOCAL, &Vars.l.filter, NULL,0},
|
||||
{"forward lookup", P_BOOL, P_LOCAL, &Vars.l.forward_lookup, NULL,0},
|
||||
{"gid", P_STRING, P_LOCAL, &Vars.l.gid, NULL,0},
|
||||
{"hosts allow", P_STRING, P_LOCAL, &Vars.l.hosts_allow, NULL,0},
|
||||
{"hosts deny", P_STRING, P_LOCAL, &Vars.l.hosts_deny, NULL,0},
|
||||
{"ignore errors", P_BOOL, P_LOCAL, &Vars.l.ignore_errors, NULL,0},
|
||||
{"ignore nonreadable",P_BOOL, P_LOCAL, &Vars.l.ignore_nonreadable, NULL,0},
|
||||
{"include from", P_STRING, P_LOCAL, &Vars.l.include_from, NULL,0},
|
||||
{"include", P_STRING, P_LOCAL, &Vars.l.include, NULL,0},
|
||||
{"incoming chmod", P_STRING, P_LOCAL, &Vars.l.incoming_chmod, NULL,0},
|
||||
{"list", P_BOOL, P_LOCAL, &Vars.l.list, NULL,0},
|
||||
{"lock file", P_STRING, P_LOCAL, &Vars.l.lock_file, NULL,0},
|
||||
{"log file", P_STRING, P_LOCAL, &Vars.l.log_file, NULL,0},
|
||||
{"log format", P_STRING, P_LOCAL, &Vars.l.log_format, NULL,0},
|
||||
{"max connections", P_INTEGER,P_LOCAL, &Vars.l.max_connections, NULL,0},
|
||||
{"max verbosity", P_INTEGER,P_LOCAL, &Vars.l.max_verbosity, NULL,0},
|
||||
{"munge symlinks", P_BOOL, P_LOCAL, &Vars.l.munge_symlinks, NULL,0},
|
||||
{"name", P_STRING, P_LOCAL, &Vars.l.name, NULL,0},
|
||||
{"numeric ids", P_BOOL, P_LOCAL, &Vars.l.numeric_ids, NULL,0},
|
||||
{"outgoing chmod", P_STRING, P_LOCAL, &Vars.l.outgoing_chmod, NULL,0},
|
||||
{"path", P_PATH, P_LOCAL, &Vars.l.path, NULL,0},
|
||||
#ifdef HAVE_PUTENV
|
||||
{"post-xfer exec", P_STRING, P_LOCAL, &Vars.l.postxfer_exec, NULL,0},
|
||||
{"pre-xfer exec", P_STRING, P_LOCAL, &Vars.l.prexfer_exec, NULL,0},
|
||||
#endif
|
||||
{"read only", P_BOOL, P_LOCAL, &Vars.l.read_only, NULL,0},
|
||||
{"refuse options", P_STRING, P_LOCAL, &Vars.l.refuse_options, NULL,0},
|
||||
{"reverse lookup", P_BOOL, P_LOCAL, &Vars.l.reverse_lookup, NULL,0},
|
||||
{"secrets file", P_STRING, P_LOCAL, &Vars.l.secrets_file, NULL,0},
|
||||
{"strict modes", P_BOOL, P_LOCAL, &Vars.l.strict_modes, NULL,0},
|
||||
{"syslog facility", P_ENUM, P_LOCAL, &Vars.l.syslog_facility, enum_facilities,0},
|
||||
{"syslog tag", P_STRING, P_LOCAL, &Vars.l.syslog_tag, NULL,0},
|
||||
{"temp dir", P_PATH, P_LOCAL, &Vars.l.temp_dir, NULL,0},
|
||||
{"timeout", P_INTEGER,P_LOCAL, &Vars.l.timeout, NULL,0},
|
||||
{"transfer logging", P_BOOL, P_LOCAL, &Vars.l.transfer_logging, NULL,0},
|
||||
{"uid", P_STRING, P_LOCAL, &Vars.l.uid, NULL,0},
|
||||
{"use chroot", P_BOOL, P_LOCAL, &Vars.l.use_chroot, NULL,0},
|
||||
{"write only", P_BOOL, P_LOCAL, &Vars.l.write_only, NULL,0},
|
||||
{NULL, P_BOOL, P_NONE, NULL, NULL,0}
|
||||
};
|
||||
|
||||
/* Initialise the Default all_vars structure. */
|
||||
void reset_daemon_vars(void)
|
||||
{
|
||||
memcpy(&Vars, &Defaults, sizeof Vars);
|
||||
}
|
||||
|
||||
/* Expand %VAR% references. Any unknown vars or unrecognized
|
||||
* syntax leaves the raw chars unchanged. */
|
||||
static char *expand_vars(char *str)
|
||||
static char *expand_vars(const char *str)
|
||||
{
|
||||
char *buf, *t, *f;
|
||||
char *buf, *t;
|
||||
const char *f;
|
||||
int bufsize;
|
||||
|
||||
if (!str || !strchr(str, '%'))
|
||||
return str;
|
||||
return (char *)str; /* TODO change return value to const char* at some point. */
|
||||
|
||||
bufsize = strlen(str) + 2048;
|
||||
if ((buf = new_array(char, bufsize+1)) == NULL) /* +1 for trailing '\0' */
|
||||
out_of_memory("expand_vars");
|
||||
buf = new_array(char, bufsize+1); /* +1 for trailing '\0' */
|
||||
|
||||
for (t = buf, f = str; bufsize && *f; ) {
|
||||
if (*f == '%' && *++f != '%') {
|
||||
char *percent = strchr(f, '%');
|
||||
if (percent) {
|
||||
if (*f == '%' && isUpper(f+1)) {
|
||||
char *percent = strchr(f+1, '%');
|
||||
if (percent && percent - f < bufsize) {
|
||||
char *val;
|
||||
*percent = '\0';
|
||||
val = getenv(f);
|
||||
*percent = '%';
|
||||
strlcpy(t, f+1, percent - f);
|
||||
val = getenv(t);
|
||||
if (val) {
|
||||
int len = strlcpy(t, val, bufsize+1);
|
||||
if (len > bufsize)
|
||||
@@ -496,7 +193,6 @@ static char *expand_vars(char *str)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
f--;
|
||||
}
|
||||
*t++ = *f++;
|
||||
bufsize--;
|
||||
@@ -514,6 +210,8 @@ static char *expand_vars(char *str)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Each "char* foo" has an associated "BOOL foo_EXP" that tracks if the string has been expanded yet or not. */
|
||||
|
||||
/* NOTE: use this function and all the FN_{GLOBAL,LOCAL} ones WITHOUT a trailing semicolon! */
|
||||
#define RETURN_EXPANDED(val) {if (!val ## _EXP) {val = expand_vars(val); val ## _EXP = True;} return val ? val : "";}
|
||||
|
||||
@@ -538,65 +236,24 @@ static char *expand_vars(char *str)
|
||||
#define FN_LOCAL_INTEGER(fn_name, val) \
|
||||
int fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : Vars.l.val;}
|
||||
|
||||
FN_GLOBAL_STRING(lp_bind_address, bind_address)
|
||||
FN_GLOBAL_STRING(lp_daemon_chroot, daemon_chroot)
|
||||
FN_GLOBAL_STRING(lp_daemon_gid, daemon_gid)
|
||||
FN_GLOBAL_STRING(lp_daemon_uid, daemon_uid)
|
||||
FN_GLOBAL_STRING(lp_motd_file, motd_file)
|
||||
FN_GLOBAL_STRING(lp_pid_file, pid_file)
|
||||
FN_GLOBAL_STRING(lp_socket_options, socket_options)
|
||||
/* The following include file contains:
|
||||
*
|
||||
* typedef global_vars - describes global (ie., server-wide) parameters.
|
||||
* typedef local_vars - describes a single section.
|
||||
* typedef all_vars - a combination of global_vars & local_vars.
|
||||
* all_vars Defaults - the default values for all the variables.
|
||||
* all_vars Vars - the currently configured values for all the variables.
|
||||
* struct parm_struct parm_table - the strings & variables for the parser.
|
||||
* FN_{LOCAL,GLOBAL}_{TYPE}() definition for all the lp_var_name() accessors.
|
||||
*/
|
||||
|
||||
FN_GLOBAL_INTEGER(lp_listen_backlog, listen_backlog)
|
||||
FN_GLOBAL_INTEGER(lp_rsync_port, rsync_port)
|
||||
#include "daemon-parm.h"
|
||||
|
||||
FN_GLOBAL_BOOL(lp_proxy_protocol, proxy_protocol)
|
||||
|
||||
FN_LOCAL_STRING(lp_auth_users, auth_users)
|
||||
FN_LOCAL_STRING(lp_charset, charset)
|
||||
FN_LOCAL_STRING(lp_comment, comment)
|
||||
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
|
||||
FN_LOCAL_STRING(lp_early_exec, early_exec)
|
||||
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_include, include)
|
||||
FN_LOCAL_STRING(lp_include_from, include_from)
|
||||
FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
|
||||
FN_LOCAL_STRING(lp_lock_file, lock_file)
|
||||
FN_LOCAL_STRING(lp_log_file, log_file)
|
||||
FN_LOCAL_STRING(lp_log_format, log_format)
|
||||
FN_LOCAL_STRING(lp_name, name)
|
||||
FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
|
||||
FN_LOCAL_STRING(lp_path, path)
|
||||
FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
|
||||
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
|
||||
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
|
||||
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
|
||||
FN_LOCAL_STRING(lp_syslog_tag, syslog_tag)
|
||||
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_syslog_facility, syslog_facility)
|
||||
FN_LOCAL_INTEGER(lp_timeout, timeout)
|
||||
|
||||
FN_LOCAL_BOOL(lp_fake_super, fake_super)
|
||||
FN_LOCAL_BOOL(lp_forward_lookup, forward_lookup)
|
||||
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_munge_symlinks, munge_symlinks)
|
||||
FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids)
|
||||
FN_LOCAL_BOOL(lp_read_only, read_only)
|
||||
FN_LOCAL_BOOL(lp_reverse_lookup, reverse_lookup)
|
||||
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)
|
||||
/* Initialise the Default all_vars structure. */
|
||||
void reset_daemon_vars(void)
|
||||
{
|
||||
memcpy(&Vars, &Defaults, sizeof Vars);
|
||||
}
|
||||
|
||||
/* Assign a copy of v to *s. Handles NULL strings. We don't worry
|
||||
* about overwriting a malloc'd string because the long-running
|
||||
@@ -605,10 +262,7 @@ FN_LOCAL_BOOL(lp_write_only, write_only)
|
||||
* the start, so any lost memory is inconsequential. */
|
||||
static inline void string_set(char **s, const char *v)
|
||||
{
|
||||
if (!v)
|
||||
*s = NULL;
|
||||
else if (!(*s = strdup(v)))
|
||||
out_of_memory("string_set");
|
||||
*s = v ? strdup(v) : NULL;
|
||||
}
|
||||
|
||||
/* Copy local_vars into a new section. No need to strdup since we don't free. */
|
||||
@@ -624,19 +278,14 @@ static void init_section(local_vars *psection)
|
||||
copy_section(psection, &Vars.l);
|
||||
}
|
||||
|
||||
/* Do a case-insensitive, whitespace-ignoring string compare. */
|
||||
static int strwicmp(char *psz1, char *psz2)
|
||||
/* Do a case-insensitive, whitespace-ignoring string equality check. */
|
||||
static int strwiEQ(char *psz1, char *psz2)
|
||||
{
|
||||
/* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
|
||||
/* appropriate value. */
|
||||
/* If one or both strings are NULL, we return equality right away. */
|
||||
if (psz1 == psz2)
|
||||
return 0;
|
||||
|
||||
if (psz1 == NULL)
|
||||
return -1;
|
||||
|
||||
if (psz2 == NULL)
|
||||
return 1;
|
||||
if (psz1 == NULL || psz2 == NULL)
|
||||
return 0;
|
||||
|
||||
/* sync the strings on first non-whitespace */
|
||||
while (1) {
|
||||
@@ -644,12 +293,14 @@ static int strwicmp(char *psz1, char *psz2)
|
||||
psz1++;
|
||||
while (isSpace(psz2))
|
||||
psz2++;
|
||||
if (toUpper(psz1) != toUpper(psz2) || *psz1 == '\0' || *psz2 == '\0')
|
||||
if (*psz1 == '\0' || *psz2 == '\0')
|
||||
break;
|
||||
if (toUpper(psz1) != toUpper(psz2))
|
||||
break;
|
||||
psz1++;
|
||||
psz2++;
|
||||
}
|
||||
return *psz1 - *psz2;
|
||||
return *psz1 == *psz2;
|
||||
}
|
||||
|
||||
/* Find a section by name. Otherwise works like get_section. */
|
||||
@@ -658,7 +309,7 @@ static int getsectionbyname(char *name)
|
||||
int i;
|
||||
|
||||
for (i = section_list.count - 1; i >= 0; i--) {
|
||||
if (strwicmp(iSECTION(i).name, name) == 0)
|
||||
if (strwiEQ(iSECTION(i).name, name))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -698,7 +349,7 @@ static int map_parameter(char *parmname)
|
||||
return -1;
|
||||
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++) {
|
||||
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
|
||||
if (strwiEQ(parm_table[iIndex].label, parmname))
|
||||
return iIndex;
|
||||
}
|
||||
|
||||
@@ -709,16 +360,14 @@ static int map_parameter(char *parmname)
|
||||
/* Set a boolean variable from the text value stored in the passed string.
|
||||
* Returns True in success, False if the passed string does not correctly
|
||||
* represent a boolean. */
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue, int allow_unset)
|
||||
{
|
||||
if (strwicmp(parmvalue, "yes") == 0
|
||||
|| strwicmp(parmvalue, "true") == 0
|
||||
|| strwicmp(parmvalue, "1") == 0)
|
||||
if (strwiEQ(parmvalue, "yes") || strwiEQ(parmvalue, "true") || strwiEQ(parmvalue, "1"))
|
||||
*pb = True;
|
||||
else if (strwicmp(parmvalue, "no") == 0
|
||||
|| strwicmp(parmvalue, "False") == 0
|
||||
|| strwicmp(parmvalue, "0") == 0)
|
||||
else if (strwiEQ(parmvalue, "no") || strwiEQ(parmvalue, "false") || strwiEQ(parmvalue, "0"))
|
||||
*pb = False;
|
||||
else if (allow_unset && (strwiEQ(parmvalue, "unset") || strwiEQ(parmvalue, "-1")))
|
||||
*pb = Unset;
|
||||
else {
|
||||
rprintf(FLOG, "Badly formed boolean in configuration file: \"%s\".\n", parmvalue);
|
||||
return False;
|
||||
@@ -767,11 +416,15 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
|
||||
|
||||
switch (parm_table[parmnum].type) {
|
||||
case P_BOOL:
|
||||
set_boolean(parm_ptr, parmvalue);
|
||||
set_boolean(parm_ptr, parmvalue, False);
|
||||
break;
|
||||
|
||||
case P_BOOL3:
|
||||
set_boolean(parm_ptr, parmvalue, True);
|
||||
break;
|
||||
|
||||
case P_BOOLREV:
|
||||
set_boolean(parm_ptr, parmvalue);
|
||||
set_boolean(parm_ptr, parmvalue, False);
|
||||
*(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
|
||||
break;
|
||||
|
||||
@@ -784,7 +437,7 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
|
||||
break;
|
||||
|
||||
case P_OCTAL:
|
||||
sscanf(parmvalue, "%o", (int *)parm_ptr);
|
||||
sscanf(parmvalue, "%o", (unsigned int *)parm_ptr);
|
||||
break;
|
||||
|
||||
case P_PATH:
|
||||
@@ -841,7 +494,7 @@ static BOOL do_section(char *sectionname)
|
||||
return True;
|
||||
}
|
||||
|
||||
isglobal = strwicmp(sectionname, GLOBAL_NAME) == 0;
|
||||
isglobal = strwiEQ(sectionname, GLOBAL_NAME);
|
||||
|
||||
/* At the end of the global section, add any --dparam items. */
|
||||
if (bInGlobalSection && !isglobal) {
|
||||
|
||||
57
log.c
57
log.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,7 +34,7 @@ extern int module_id;
|
||||
extern int allow_8bit_chars;
|
||||
extern int protocol_version;
|
||||
extern int always_checksum;
|
||||
extern int preserve_times;
|
||||
extern int preserve_mtimes;
|
||||
extern int msgs2stderr;
|
||||
extern int xfersum_type;
|
||||
extern int checksum_type;
|
||||
@@ -251,7 +251,7 @@ static void filtered_fwrite(FILE *f, const char *in_buf, int in_len, int use_isp
|
||||
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
{
|
||||
char trailing_CR_or_NL;
|
||||
FILE *f = msgs2stderr ? stderr : stdout;
|
||||
FILE *f = msgs2stderr == 1 ? stderr : stdout;
|
||||
#ifdef ICONV_OPTION
|
||||
iconv_t ic = is_utf8 && ic_recv != (iconv_t)-1 ? ic_recv : ic_chck;
|
||||
#else
|
||||
@@ -263,7 +263,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
if (len < 0)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
if (msgs2stderr) {
|
||||
if (msgs2stderr == 1) {
|
||||
/* A normal daemon can get msgs2stderr set if the socket is busted, so we
|
||||
* change the message destination into an FLOG message in order to try to
|
||||
* get some info about an abnormal-exit into the log file. An rsh daemon
|
||||
@@ -327,7 +327,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
|
||||
if (am_server && !msgs2stderr) {
|
||||
if (am_server && msgs2stderr != 1 && (msgs2stderr != 2 || f != stderr)) {
|
||||
enum msgcode msg = (enum msgcode)code;
|
||||
if (protocol_version < 30) {
|
||||
if (msg == MSG_ERROR)
|
||||
@@ -350,8 +350,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
output_needs_newline = 0;
|
||||
}
|
||||
|
||||
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
|
||||
? buf[--len] : 0;
|
||||
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r') ? buf[--len] : '\0';
|
||||
|
||||
if (len && buf[0] == '\r') {
|
||||
fputc('\r', f);
|
||||
@@ -372,7 +371,12 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
iconvbufs(ic, &inbuf, &outbuf, inbuf.pos ? 0 : ICB_INIT);
|
||||
ierrno = errno;
|
||||
if (outbuf.len) {
|
||||
filtered_fwrite(f, convbuf, outbuf.len, 0, 0);
|
||||
char trailing = inbuf.len ? '\0' : trailing_CR_or_NL;
|
||||
filtered_fwrite(f, convbuf, outbuf.len, 0, trailing);
|
||||
if (trailing) {
|
||||
trailing_CR_or_NL = '\0';
|
||||
fflush(f);
|
||||
}
|
||||
outbuf.len = 0;
|
||||
}
|
||||
/* Log one byte of illegal/incomplete sequence and continue with
|
||||
@@ -702,7 +706,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
|
||||
c[1] = 'L';
|
||||
c[3] = '.';
|
||||
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
|
||||
: !preserve_times || !receiver_symlink_times
|
||||
: !preserve_mtimes || !receiver_symlink_times
|
||||
|| (iflags & ITEM_REPORT_TIMEFAIL) ? 'T' : 't';
|
||||
} else {
|
||||
c[1] = S_ISDIR(file->mode) ? 'd'
|
||||
@@ -710,14 +714,15 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
|
||||
: IS_DEVICE(file->mode) ? 'D' : 'f';
|
||||
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
|
||||
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
|
||||
: !preserve_times ? 'T' : 't';
|
||||
: !preserve_mtimes ? 'T' : 't';
|
||||
}
|
||||
c[2] = !(iflags & ITEM_REPORT_CHANGE) ? '.' : 'c';
|
||||
c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
|
||||
c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
|
||||
c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
|
||||
c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.'
|
||||
: S_ISLNK(file->mode) ? 'U' : 'u';
|
||||
c[8] = !(iflags & (ITEM_REPORT_ATIME|ITEM_REPORT_CRTIME)) ? '.'
|
||||
: BITS_SET(iflags, ITEM_REPORT_ATIME|ITEM_REPORT_CRTIME) ? 'b'
|
||||
: iflags & ITEM_REPORT_ATIME ? 'u' : 'n';
|
||||
c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
|
||||
c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
|
||||
c[11] = '\0';
|
||||
@@ -833,14 +838,24 @@ void maybe_log_item(struct file_struct *file, int iflags, int itemizing, const c
|
||||
|
||||
void log_delete(const char *fname, int mode)
|
||||
{
|
||||
static struct {
|
||||
union file_extras ex[4]; /* just in case... */
|
||||
struct file_struct file;
|
||||
} x; /* Zero-initialized due to static declaration. */
|
||||
static struct file_struct *file = NULL;
|
||||
int len = strlen(fname);
|
||||
const char *fmt;
|
||||
|
||||
x.file.mode = mode;
|
||||
if (!file) {
|
||||
int extra_len = (file_extra_cnt + 2) * EXTRA_LEN;
|
||||
char *bp;
|
||||
#if EXTRA_ROUNDING > 0
|
||||
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
|
||||
extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
|
||||
#endif
|
||||
|
||||
bp = new_array0(char, FILE_STRUCT_LEN + extra_len + 1);
|
||||
bp += extra_len;
|
||||
file = (struct file_struct *)bp;
|
||||
}
|
||||
|
||||
file->mode = mode;
|
||||
|
||||
if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
|
||||
if (S_ISDIR(mode))
|
||||
@@ -850,14 +865,14 @@ void log_delete(const char *fname, int mode)
|
||||
;
|
||||
else {
|
||||
fmt = stdout_format_has_o_or_i ? stdout_format : "deleting %n";
|
||||
log_formatted(FCLIENT, fmt, "del.", &x.file, fname, ITEM_DELETED, NULL);
|
||||
log_formatted(FCLIENT, fmt, "del.", file, fname, ITEM_DELETED, NULL);
|
||||
}
|
||||
|
||||
if (!logfile_name || dry_run || !logfile_format)
|
||||
return;
|
||||
|
||||
fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
|
||||
log_formatted(FLOG, fmt, "del.", &x.file, fname, ITEM_DELETED, NULL);
|
||||
log_formatted(FLOG, fmt, "del.", file, fname, ITEM_DELETED, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -886,10 +901,10 @@ void log_exit(int code, const char *file, int line)
|
||||
/* VANISHED is not an error, only a warning */
|
||||
if (code == RERR_VANISHED) {
|
||||
rprintf(FWARNING, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
name, code, file, line, who_am_i(), RSYNC_VERSION);
|
||||
name, code, src_file(file), line, who_am_i(), rsync_version());
|
||||
} else {
|
||||
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
name, code, file, line, who_am_i(), RSYNC_VERSION);
|
||||
name, code, src_file(file), line, who_am_i(), rsync_version());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
203
main.c
203
main.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -22,11 +22,15 @@
|
||||
|
||||
#include "rsync.h"
|
||||
#include "inums.h"
|
||||
#include "ifuncs.h"
|
||||
#include "io.h"
|
||||
#if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#include <popt.h>
|
||||
#ifdef __TANDEM
|
||||
#include <floss.h(floss_execlp)>
|
||||
#endif
|
||||
|
||||
extern int dry_run;
|
||||
extern int list_only;
|
||||
@@ -53,6 +57,7 @@ extern int copy_unsafe_links;
|
||||
extern int keep_dirlinks;
|
||||
extern int preserve_hard_links;
|
||||
extern int protocol_version;
|
||||
extern int mkpath_dest_arg;
|
||||
extern int file_total;
|
||||
extern int recurse;
|
||||
extern int xfer_dirs;
|
||||
@@ -82,6 +87,7 @@ extern BOOL shutting_down;
|
||||
extern int backup_dir_len;
|
||||
extern int basis_dir_cnt;
|
||||
extern int default_af_hint;
|
||||
extern int stdout_format_has_i;
|
||||
extern struct stats stats;
|
||||
extern char *stdout_format;
|
||||
extern char *logfile_format;
|
||||
@@ -92,6 +98,7 @@ extern char *shell_cmd;
|
||||
extern char *password_file;
|
||||
extern char *backup_dir;
|
||||
extern char *copy_as;
|
||||
extern char *tmpdir;
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
extern char backup_dir_buf[MAXPATHLEN];
|
||||
extern char *basis_dir[MAX_BASIS_DIRS+1];
|
||||
@@ -103,7 +110,7 @@ gid_t our_gid;
|
||||
int am_receiver = 0; /* Only set to 1 after the receiver/generator fork. */
|
||||
int am_generator = 0; /* Only set to 1 after the receiver/generator fork. */
|
||||
int local_server = 0;
|
||||
int daemon_over_rsh = 0;
|
||||
int daemon_connection = 0; /* 0 = no daemon, 1 = daemon via remote shell, -1 = daemon via socket */
|
||||
mode_t orig_umask = 0;
|
||||
int batch_gen_fd = -1;
|
||||
int sender_keeps_checksum = 0;
|
||||
@@ -298,7 +305,7 @@ static void become_copy_as_user()
|
||||
|
||||
our_uid = MY_UID();
|
||||
our_gid = MY_GID();
|
||||
am_root = (our_uid == 0);
|
||||
am_root = (our_uid == ROOT_UID);
|
||||
|
||||
if (gname)
|
||||
gname[-1] = ':';
|
||||
@@ -460,38 +467,33 @@ static void output_summary(void)
|
||||
**/
|
||||
static void show_malloc_stats(void)
|
||||
{
|
||||
#ifdef HAVE_MALLINFO
|
||||
struct mallinfo mi;
|
||||
|
||||
mi = mallinfo();
|
||||
#ifdef MEM_ALLOC_INFO
|
||||
struct MEM_ALLOC_INFO mi = MEM_ALLOC_INFO(); /* mallinfo or mallinfo2 */
|
||||
|
||||
rprintf(FCLIENT, "\n");
|
||||
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
|
||||
(int)getpid(), am_server ? "server " : "",
|
||||
am_daemon ? "daemon " : "", who_am_i());
|
||||
rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n",
|
||||
(long)mi.arena);
|
||||
rprintf(FINFO, " ordblks: %10ld (chunks not in use)\n",
|
||||
(long)mi.ordblks);
|
||||
rprintf(FINFO, " smblks: %10ld\n",
|
||||
(long)mi.smblks);
|
||||
rprintf(FINFO, " hblks: %10ld (chunks from mmap)\n",
|
||||
(long)mi.hblks);
|
||||
rprintf(FINFO, " hblkhd: %10ld (bytes from mmap)\n",
|
||||
(long)mi.hblkhd);
|
||||
rprintf(FINFO, " allmem: %10ld (bytes from sbrk + mmap)\n",
|
||||
(long)mi.arena + mi.hblkhd);
|
||||
rprintf(FINFO, " usmblks: %10ld\n",
|
||||
(long)mi.usmblks);
|
||||
rprintf(FINFO, " fsmblks: %10ld\n",
|
||||
(long)mi.fsmblks);
|
||||
rprintf(FINFO, " uordblks: %10ld (bytes used)\n",
|
||||
(long)mi.uordblks);
|
||||
rprintf(FINFO, " fordblks: %10ld (bytes free)\n",
|
||||
(long)mi.fordblks);
|
||||
rprintf(FINFO, " keepcost: %10ld (bytes in releasable chunk)\n",
|
||||
(long)mi.keepcost);
|
||||
#endif /* HAVE_MALLINFO */
|
||||
|
||||
#define PRINT_ALLOC_NUM(title, descr, num) \
|
||||
rprintf(FINFO, " %-11s%10" SIZE_T_FMT_MOD "d (" descr ")\n", \
|
||||
title ":", (SIZE_T_FMT_CAST)(num));
|
||||
|
||||
PRINT_ALLOC_NUM("arena", "bytes from sbrk", mi.arena);
|
||||
PRINT_ALLOC_NUM("ordblks", "chunks not in use", mi.ordblks);
|
||||
PRINT_ALLOC_NUM("smblks", "free fastbin blocks", mi.smblks);
|
||||
PRINT_ALLOC_NUM("hblks", "chunks from mmap", mi.hblks);
|
||||
PRINT_ALLOC_NUM("hblkhd", "bytes from mmap", mi.hblkhd);
|
||||
PRINT_ALLOC_NUM("allmem", "bytes from sbrk + mmap", mi.arena + mi.hblkhd);
|
||||
PRINT_ALLOC_NUM("usmblks", "always 0", mi.usmblks);
|
||||
PRINT_ALLOC_NUM("fsmblks", "bytes in freed fastbin blocks", mi.fsmblks);
|
||||
PRINT_ALLOC_NUM("uordblks", "bytes used", mi.uordblks);
|
||||
PRINT_ALLOC_NUM("fordblks", "bytes free", mi.fordblks);
|
||||
PRINT_ALLOC_NUM("keepcost", "bytes in releasable chunk", mi.keepcost);
|
||||
|
||||
#undef PRINT_ALLOC_NUM
|
||||
|
||||
#endif /* MEM_ALLOC_INFO */
|
||||
}
|
||||
|
||||
|
||||
@@ -512,8 +514,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
if (!cmd)
|
||||
cmd = RSYNC_RSH;
|
||||
cmd = need_to_free = strdup(cmd);
|
||||
if (!cmd)
|
||||
goto oom;
|
||||
|
||||
for (t = f = cmd; *f; f++) {
|
||||
if (*f == ' ')
|
||||
@@ -563,12 +563,12 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
#ifdef HAVE_REMSH
|
||||
/* remsh (on HPUX) takes the arguments the other way around */
|
||||
args[argc++] = machine;
|
||||
if (user && !(daemon_over_rsh && dash_l_set)) {
|
||||
if (user && !(daemon_connection && dash_l_set)) {
|
||||
args[argc++] = "-l";
|
||||
args[argc++] = user;
|
||||
}
|
||||
#else
|
||||
if (user && !(daemon_over_rsh && dash_l_set)) {
|
||||
if (user && !(daemon_connection && dash_l_set)) {
|
||||
args[argc++] = "-l";
|
||||
args[argc++] = user;
|
||||
}
|
||||
@@ -588,7 +588,11 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
if (blocking_io < 0 && (strcmp(t, "rsh") == 0 || strcmp(t, "remsh") == 0))
|
||||
blocking_io = 1;
|
||||
|
||||
server_options(args, &argc);
|
||||
if (daemon_connection > 0) {
|
||||
args[argc++] = "--server";
|
||||
args[argc++] = "--daemon";
|
||||
} else
|
||||
server_options(args, &argc);
|
||||
|
||||
if (argc >= MAX_ARGS - 2)
|
||||
goto arg_overflow;
|
||||
@@ -596,7 +600,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
|
||||
args[argc++] = ".";
|
||||
|
||||
if (!daemon_over_rsh) {
|
||||
if (!daemon_connection) {
|
||||
while (remote_argc > 0) {
|
||||
if (argc >= MAX_ARGS - 1) {
|
||||
arg_overflow:
|
||||
@@ -649,7 +653,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
if (protect_args && !daemon_over_rsh)
|
||||
if (protect_args && !daemon_connection)
|
||||
send_protected_args(*f_out_p, args);
|
||||
}
|
||||
|
||||
@@ -657,10 +661,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
free(need_to_free);
|
||||
|
||||
return pid;
|
||||
|
||||
oom:
|
||||
out_of_memory("do_cmd");
|
||||
return 0; /* not reached */
|
||||
}
|
||||
|
||||
/* The receiving side operates in one of two modes:
|
||||
@@ -679,7 +679,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
int statret;
|
||||
int statret, trailing_slash;
|
||||
char *cp;
|
||||
|
||||
if (DEBUG_GTE(RECV, 1)) {
|
||||
@@ -712,7 +712,29 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
}
|
||||
|
||||
/* See what currently exists at the destination. */
|
||||
if ((statret = do_stat(dest_path, &st)) == 0) {
|
||||
statret = do_stat(dest_path, &st);
|
||||
cp = strrchr(dest_path, '/');
|
||||
trailing_slash = cp && !cp[1];
|
||||
|
||||
if (mkpath_dest_arg && statret < 0 && (cp || file_total > 1)) {
|
||||
int save_errno = errno;
|
||||
int ret = make_path(dest_path, file_total > 1 && !trailing_slash ? 0 : MKP_DROP_NAME);
|
||||
if (ret < 0)
|
||||
goto mkdir_error;
|
||||
if (ret && (INFO_GTE(NAME, 1) || stdout_format_has_i)) {
|
||||
if (file_total == 1 || trailing_slash)
|
||||
*cp = '\0';
|
||||
rprintf(FINFO, "created %d director%s for %s\n", ret, ret == 1 ? "y" : "ies", dest_path);
|
||||
if (file_total == 1 || trailing_slash)
|
||||
*cp = '/';
|
||||
}
|
||||
if (ret)
|
||||
statret = do_stat(dest_path, &st);
|
||||
else
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
if (statret == 0) {
|
||||
/* If the destination is a dir, enter it and use mode 1. */
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (!change_dir(dest_path, CD_NORMAL)) {
|
||||
@@ -742,15 +764,12 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
|
||||
cp = strrchr(dest_path, '/');
|
||||
|
||||
/* If we need a destination directory because the transfer is not
|
||||
* of a single non-directory or the user has requested one via a
|
||||
* destination path ending in a slash, create one and use mode 1. */
|
||||
if (file_total > 1 || (cp && !cp[1])) {
|
||||
/* Lop off the final slash (if any). */
|
||||
if (cp && !cp[1])
|
||||
*cp = '\0';
|
||||
if (file_total > 1 || trailing_slash) {
|
||||
if (trailing_slash)
|
||||
*cp = '\0'; /* Lop off the final slash (if any). */
|
||||
|
||||
if (statret == 0) {
|
||||
rprintf(FERROR, "ERROR: destination path is not a directory\n");
|
||||
@@ -758,6 +777,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
}
|
||||
|
||||
if (do_mkdir(dest_path, ACCESSPERMS) != 0) {
|
||||
mkdir_error:
|
||||
rsyserr(FERROR, errno, "mkdir %s failed",
|
||||
full_fname(dest_path));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
@@ -767,7 +787,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
&& strcmp(flist->files[flist->low]->basename, ".") == 0)
|
||||
flist->files[0]->flags |= FLAG_DIR_CREATED;
|
||||
|
||||
if (INFO_GTE(NAME, 1))
|
||||
if (INFO_GTE(NAME, 1) || stdout_format_has_i)
|
||||
rprintf(FINFO, "created directory %s\n", dest_path);
|
||||
|
||||
if (dry_run) {
|
||||
@@ -824,8 +844,6 @@ static void check_alt_basis_dirs(void)
|
||||
if (dry_run > 1 && *bdir != '/') {
|
||||
int len = curr_dir_len + 1 + bd_len + 1;
|
||||
char *new = new_array(char, len);
|
||||
if (!new)
|
||||
out_of_memory("check_alt_basis_dirs");
|
||||
if (slash && strncmp(bdir, "../", 3) == 0) {
|
||||
/* We want to remove only one leading "../" prefix for
|
||||
* the directory we couldn't create in dry-run mode:
|
||||
@@ -984,6 +1002,23 @@ static int do_recv(int f_in, int f_out, char *local_name)
|
||||
backup_dir_buf[backup_dir_len-1] = '/';
|
||||
}
|
||||
|
||||
if (tmpdir) {
|
||||
STRUCT_STAT st;
|
||||
int ret = do_stat(tmpdir, &st);
|
||||
if (ret < 0 || !S_ISDIR(st.st_mode)) {
|
||||
if (ret == 0) {
|
||||
rprintf(FERROR, "The temp-dir is not a directory: %s\n", tmpdir);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (errno == ENOENT) {
|
||||
rprintf(FERROR, "The temp-dir does not exist: %s\n", tmpdir);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
rprintf(FERROR, "Failed to stat temp-dir %s: %s\n", tmpdir, strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
}
|
||||
|
||||
io_flush(FULL_FLUSH);
|
||||
|
||||
if ((pid = do_fork()) == -1) {
|
||||
@@ -1090,7 +1125,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
|
||||
char *local_name = NULL;
|
||||
int negated_levels;
|
||||
|
||||
if (filesfrom_fd >= 0 && !msgs2stderr && protocol_version < 31) {
|
||||
if (filesfrom_fd >= 0 && msgs2stderr != 1 && protocol_version < 31) {
|
||||
/* We can't mix messages with files-from data on the socket,
|
||||
* so temporarily turn off info/debug messages. */
|
||||
negate_output_levels();
|
||||
@@ -1339,19 +1374,12 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
return MAX(exit_code, exit_code2);
|
||||
}
|
||||
|
||||
static int copy_argv(char *argv[])
|
||||
static void dup_argv(char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; argv[i]; i++) {
|
||||
if (!(argv[i] = strdup(argv[i]))) {
|
||||
rprintf (FERROR, "out of memory at %s(%d)\n",
|
||||
__FILE__, __LINE__);
|
||||
return RERR_MALLOC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
for (i = 0; argv[i]; i++)
|
||||
argv[i] = strdup(argv[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1372,8 +1400,7 @@ static int start_client(int argc, char *argv[])
|
||||
|
||||
/* Don't clobber argv[] so that ps(1) can still show the right
|
||||
* command line. */
|
||||
if ((ret = copy_argv(argv)) != 0)
|
||||
return ret;
|
||||
dup_argv(argv);
|
||||
|
||||
if (!read_batch) { /* for read_batch, NO source is specified */
|
||||
char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
|
||||
@@ -1401,7 +1428,7 @@ static int start_client(int argc, char *argv[])
|
||||
}
|
||||
am_sender = 0;
|
||||
if (rsync_port)
|
||||
daemon_over_rsh = shell_cmd ? 1 : -1;
|
||||
daemon_connection = shell_cmd ? 1 : -1;
|
||||
} else { /* source is local, check dest arg */
|
||||
am_sender = 1;
|
||||
|
||||
@@ -1433,7 +1460,7 @@ static int start_client(int argc, char *argv[])
|
||||
} else { /* hostspec was found, so dest is remote */
|
||||
argv[argc] = path;
|
||||
if (rsync_port)
|
||||
daemon_over_rsh = shell_cmd ? 1 : -1;
|
||||
daemon_connection = shell_cmd ? 1 : -1;
|
||||
}
|
||||
}
|
||||
} else { /* read_batch */
|
||||
@@ -1454,8 +1481,15 @@ static int start_client(int argc, char *argv[])
|
||||
char *dummy_host;
|
||||
int dummy_port = rsync_port;
|
||||
int i;
|
||||
if (!argv[0][0])
|
||||
goto invalid_empty;
|
||||
/* For local source, extra source args must not have hostspec. */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!argv[i][0]) {
|
||||
invalid_empty:
|
||||
rprintf(FERROR, "Empty source arg specified.\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (check_for_hostspec(argv[i], &dummy_host, &dummy_port)) {
|
||||
rprintf(FERROR, "Unexpected remote arg: %s\n", argv[i]);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -1496,10 +1530,10 @@ static int start_client(int argc, char *argv[])
|
||||
else
|
||||
env_port = rsync_port;
|
||||
|
||||
if (daemon_over_rsh < 0)
|
||||
if (daemon_connection < 0)
|
||||
return start_socket_client(shell_machine, remote_argc, remote_argv, argc, argv);
|
||||
|
||||
if (password_file && !daemon_over_rsh) {
|
||||
if (password_file && !daemon_connection) {
|
||||
rprintf(FERROR, "The --password-file option may only be "
|
||||
"used when accessing an rsync daemon.\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -1527,15 +1561,17 @@ static int start_client(int argc, char *argv[])
|
||||
}
|
||||
|
||||
#ifdef HAVE_PUTENV
|
||||
if (daemon_over_rsh)
|
||||
if (daemon_connection)
|
||||
set_env_num("RSYNC_PORT", env_port);
|
||||
#else
|
||||
(void)env_port;
|
||||
#endif
|
||||
|
||||
pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc, &f_in, &f_out);
|
||||
|
||||
/* if we're running an rsync server on the remote host over a
|
||||
* remote shell command, we need to do the RSYNCD protocol first */
|
||||
if (daemon_over_rsh) {
|
||||
if (daemon_connection) {
|
||||
int tmpret;
|
||||
tmpret = start_inband_exchange(f_in, f_out, shell_user, remote_argc, remote_argv);
|
||||
if (tmpret < 0)
|
||||
@@ -1567,11 +1603,13 @@ static void sigusr2_handler(UNUSED(int val))
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
#if defined SIGINFO || defined SIGVTALRM
|
||||
static void siginfo_handler(UNUSED(int val))
|
||||
{
|
||||
if (!am_server && !INFO_GTE(PROGRESS, 1))
|
||||
want_progress_now = True;
|
||||
}
|
||||
#endif
|
||||
|
||||
void remember_children(UNUSED(int val))
|
||||
{
|
||||
@@ -1599,7 +1637,6 @@ void remember_children(UNUSED(int val))
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This routine catches signals and tries to send them to gdb.
|
||||
*
|
||||
@@ -1623,7 +1660,6 @@ const char *get_panic_action(void)
|
||||
return "xterm -display :0 -T Panic -n Panic -e gdb /proc/%d/exe %d";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
|
||||
*
|
||||
@@ -1647,6 +1683,22 @@ static void rsync_panic_handler(UNUSED(int whatsig))
|
||||
}
|
||||
#endif
|
||||
|
||||
static void unset_env_var(const char *var)
|
||||
{
|
||||
#ifdef HAVE_UNSETENV
|
||||
unsetenv(var);
|
||||
#else
|
||||
#ifdef HAVE_PUTENV
|
||||
char *mem;
|
||||
if (asprintf(&mem, "%s=", var) < 0)
|
||||
out_of_memory("unset_env_var");
|
||||
putenv(mem);
|
||||
#else
|
||||
(void)var;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
@@ -1682,7 +1734,9 @@ int main(int argc,char *argv[])
|
||||
starttime = time(NULL);
|
||||
our_uid = MY_UID();
|
||||
our_gid = MY_GID();
|
||||
am_root = our_uid == 0;
|
||||
am_root = our_uid == ROOT_UID;
|
||||
|
||||
unset_env_var("DISPLAY");
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
@@ -1702,6 +1756,7 @@ int main(int argc,char *argv[])
|
||||
|
||||
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
|
||||
setlocale(LC_CTYPE, "");
|
||||
setlocale(LC_NUMERIC, "");
|
||||
#endif
|
||||
|
||||
if (!parse_arguments(&argc, (const char ***) &argv)) {
|
||||
|
||||
2
match.c
2
match.c
@@ -65,8 +65,6 @@ static void build_hash_table(struct sum_struct *s)
|
||||
if (hash_table)
|
||||
free(hash_table);
|
||||
hash_table = new_array(int32, tablesize);
|
||||
if (!hash_table)
|
||||
out_of_memory("build_hash_table");
|
||||
alloc_size = tablesize;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ x"$2" = x ]; then
|
||||
echo "Usage: $0 SRC_DIR NAME.NUM.md" 1>&2
|
||||
if [ $# != 1 ]; then
|
||||
echo "Usage: $0 NAME.NUM.md" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
srcdir="$1"
|
||||
inname="$2"
|
||||
inname="$1"
|
||||
srcdir=`dirname "$0"`
|
||||
flagfile="$srcdir/.md2man-works"
|
||||
|
||||
if [ ! -d "$srcdir" ]; then
|
||||
echo "The specified SRC_DIR is not a directory: $srcdir" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$flagfile" ]; then
|
||||
# We test our smallest manpage just to see if the python setup works.
|
||||
if "$srcdir/md2man" --test "$srcdir/rsync-ssl.1.md" >/dev/null 2>&1; then
|
||||
if "$srcdir/md-convert" --test "$srcdir/rsync-ssl.1.md" >/dev/null 2>&1; then
|
||||
touch $flagfile
|
||||
else
|
||||
outname=`echo "$inname" | sed 's/\.md$//'`
|
||||
@@ -37,4 +32,4 @@ if [ ! -f "$flagfile" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
"$srcdir/md2man" "$srcdir/$inname"
|
||||
"$srcdir/md-convert" "$srcdir/$inname"
|
||||
|
||||
476
md-convert
Executable file
476
md-convert
Executable file
@@ -0,0 +1,476 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This script transforms markdown files into html and (optionally) nroff. The
|
||||
# output files are written into the current directory named for the input file
|
||||
# without the .md suffix and either the .html suffix or no suffix.
|
||||
#
|
||||
# If the input .md file has a section number at the end of the name (e.g.,
|
||||
# rsync.1.md) a nroff file is also output (PROJ.NUM.md -> PROJ.NUM).
|
||||
#
|
||||
# The markdown input format has one extra extension: if a numbered list starts
|
||||
# at 0, it is turned into a description list. The dl's dt tag is taken from the
|
||||
# contents of the first tag inside the li, which is usually a p, code, or
|
||||
# strong tag.
|
||||
#
|
||||
# The cmarkgfm or commonmark lib is used to transforms the input file into
|
||||
# html. Then, the html.parser is used as a state machine that lets us tweak
|
||||
# the html and (optionally) output nroff data based on the html tags.
|
||||
#
|
||||
# If the string @USE_GFM_PARSER@ exists in the file, the string is removed and
|
||||
# a github-flavored-markup parser is used to parse the file.
|
||||
#
|
||||
# The man-page .md files also get the vars @VERSION@, @BINDIR@, and @LIBDIR@
|
||||
# substituted. Some of these values depend on the Makefile $(prefix) (see the
|
||||
# generated Makefile). If the maintainer wants to build files for /usr/local
|
||||
# while creating release-ready man-page files for /usr, use the environment to
|
||||
# set RSYNC_OVERRIDE_PREFIX=/usr.
|
||||
|
||||
# Copyright (C) 2020 - 2021 Wayne Davison
|
||||
#
|
||||
# This program is freely redistributable.
|
||||
|
||||
import os, sys, re, argparse, subprocess, time
|
||||
from html.parser import HTMLParser
|
||||
|
||||
CONSUMES_TXT = set('h1 h2 p li pre'.split())
|
||||
|
||||
HTML_START = """\
|
||||
<html><head>
|
||||
<title>%s</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto&family=Roboto+Mono&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
max-width: 50em;
|
||||
margin: auto;
|
||||
}
|
||||
body, b, strong, u {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
code {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-weight: bold;
|
||||
white-space: pre;
|
||||
}
|
||||
pre code {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
}
|
||||
blockquote pre code {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
dd p:first-of-type {
|
||||
margin-block-start: 0em;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
"""
|
||||
|
||||
TABLE_STYLE = """\
|
||||
table {
|
||||
border-color: grey;
|
||||
border-spacing: 0;
|
||||
}
|
||||
tr {
|
||||
border-top: 1px solid grey;
|
||||
}
|
||||
tr:nth-child(2n) {
|
||||
background-color: #f6f8fa;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #dfe2e5;
|
||||
text-align: center;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
"""
|
||||
|
||||
MAN_HTML_END = """\
|
||||
<div style="float: right"><p><i>%s</i></p></div>
|
||||
"""
|
||||
|
||||
HTML_END = """\
|
||||
</body></html>
|
||||
"""
|
||||
|
||||
MAN_START = r"""
|
||||
.TH "%s" "%s" "%s" "%s" "User Commands"
|
||||
.\" prefix=%s
|
||||
""".lstrip()
|
||||
|
||||
MAN_END = """\
|
||||
"""
|
||||
|
||||
NORM_FONT = ('\1', r"\fP")
|
||||
BOLD_FONT = ('\2', r"\fB")
|
||||
UNDR_FONT = ('\3', r"\fI")
|
||||
NBR_DASH = ('\4', r"\-")
|
||||
NBR_SPACE = ('\xa0', r"\ ")
|
||||
|
||||
md_parser = None
|
||||
env_subs = { }
|
||||
|
||||
def main():
|
||||
for mdfn in args.mdfiles:
|
||||
parse_md_file(mdfn)
|
||||
|
||||
if args.test:
|
||||
print("The test was successful.")
|
||||
|
||||
|
||||
def parse_md_file(mdfn):
|
||||
fi = re.match(r'^(?P<fn>(?P<srcdir>.+/)?(?P<name>(?P<prog>[^/]+?)(\.(?P<sect>\d+))?)\.md)$', mdfn)
|
||||
if not fi:
|
||||
die('Failed to parse a md input file name:', mdfn)
|
||||
fi = argparse.Namespace(**fi.groupdict())
|
||||
fi.want_manpage = not not fi.sect
|
||||
if fi.want_manpage:
|
||||
fi.title = fi.prog + '(' + fi.sect + ') man page'
|
||||
else:
|
||||
fi.title = fi.prog
|
||||
|
||||
if fi.want_manpage:
|
||||
if not env_subs:
|
||||
find_man_substitutions()
|
||||
prog_ver = 'rsync ' + env_subs['VERSION']
|
||||
if fi.prog != 'rsync':
|
||||
prog_ver = fi.prog + ' from ' + prog_ver
|
||||
fi.man_headings = (fi.prog, fi.sect, env_subs['date'], prog_ver, env_subs['prefix'])
|
||||
|
||||
with open(mdfn, 'r', encoding='utf-8') as fh:
|
||||
txt = fh.read()
|
||||
|
||||
use_gfm_parser = '@USE_GFM_PARSER@' in txt
|
||||
if use_gfm_parser:
|
||||
txt = txt.replace('@USE_GFM_PARSER@', '')
|
||||
|
||||
if fi.want_manpage:
|
||||
txt = (txt.replace('@VERSION@', env_subs['VERSION'])
|
||||
.replace('@BINDIR@', env_subs['bindir'])
|
||||
.replace('@LIBDIR@', env_subs['libdir']))
|
||||
|
||||
if use_gfm_parser:
|
||||
if not gfm_parser:
|
||||
die('Input file requires cmarkgfm parser:', mdfn)
|
||||
fi.html_in = gfm_parser(txt)
|
||||
else:
|
||||
fi.html_in = md_parser(txt)
|
||||
txt = None
|
||||
|
||||
TransformHtml(fi)
|
||||
|
||||
if args.test:
|
||||
return
|
||||
|
||||
output_list = [ (fi.name + '.html', fi.html_out) ]
|
||||
if fi.want_manpage:
|
||||
output_list += [ (fi.name, fi.man_out) ]
|
||||
for fn, txt in output_list:
|
||||
if os.path.lexists(fn):
|
||||
os.unlink(fn)
|
||||
print("Wrote:", fn)
|
||||
with open(fn, 'w', encoding='utf-8') as fh:
|
||||
fh.write(txt)
|
||||
|
||||
|
||||
def find_man_substitutions():
|
||||
srcdir = os.path.dirname(sys.argv[0]) + '/'
|
||||
mtime = 0
|
||||
|
||||
git_dir = srcdir + '.git'
|
||||
if os.path.lexists(git_dir):
|
||||
mtime = int(subprocess.check_output(['git', '--git-dir', git_dir, 'log', '-1', '--format=%at']))
|
||||
|
||||
# Allow "prefix" to be overridden via the environment:
|
||||
env_subs['prefix'] = os.environ.get('RSYNC_OVERRIDE_PREFIX', None)
|
||||
|
||||
if args.test:
|
||||
env_subs['VERSION'] = '1.0.0'
|
||||
env_subs['bindir'] = '/usr/bin'
|
||||
env_subs['libdir'] = '/usr/lib/rsync'
|
||||
else:
|
||||
for fn in (srcdir + 'version.h', 'Makefile'):
|
||||
try:
|
||||
st = os.lstat(fn)
|
||||
except OSError:
|
||||
die('Failed to find', srcdir + fn)
|
||||
if not mtime:
|
||||
mtime = st.st_mtime
|
||||
|
||||
with open(srcdir + 'version.h', 'r', encoding='utf-8') as fh:
|
||||
txt = fh.read()
|
||||
m = re.search(r'"(.+?)"', txt)
|
||||
env_subs['VERSION'] = m.group(1)
|
||||
|
||||
with open('Makefile', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
m = re.match(r'^(\w+)=(.+)', line)
|
||||
if not m:
|
||||
continue
|
||||
var, val = (m.group(1), m.group(2))
|
||||
if var == 'prefix' and env_subs[var] is not None:
|
||||
continue
|
||||
while re.search(r'\$\{', val):
|
||||
val = re.sub(r'\$\{(\w+)\}', lambda m: env_subs[m.group(1)], val)
|
||||
env_subs[var] = val
|
||||
if var == 'srcdir':
|
||||
break
|
||||
|
||||
env_subs['date'] = time.strftime('%d %b %Y', time.localtime(mtime))
|
||||
|
||||
|
||||
def html_via_commonmark(txt):
|
||||
return commonmark.HtmlRenderer().render(commonmark.Parser().parse(txt))
|
||||
|
||||
|
||||
class TransformHtml(HTMLParser):
|
||||
def __init__(self, fi):
|
||||
HTMLParser.__init__(self, convert_charrefs=True)
|
||||
|
||||
st = self.state = argparse.Namespace(
|
||||
list_state = [ ],
|
||||
p_macro = ".P\n",
|
||||
at_first_tag_in_li = False,
|
||||
at_first_tag_in_dd = False,
|
||||
dt_from = None,
|
||||
in_pre = False,
|
||||
in_code = False,
|
||||
html_out = [ HTML_START % fi.title ],
|
||||
man_out = [ ],
|
||||
txt = '',
|
||||
want_manpage = fi.want_manpage,
|
||||
)
|
||||
|
||||
if st.want_manpage:
|
||||
st.man_out.append(MAN_START % fi.man_headings)
|
||||
|
||||
if '</table>' in fi.html_in:
|
||||
st.html_out[0] = st.html_out[0].replace('</style>', TABLE_STYLE + '</style>')
|
||||
|
||||
self.feed(fi.html_in)
|
||||
fi.html_in = None
|
||||
|
||||
if st.want_manpage:
|
||||
st.html_out.append(MAN_HTML_END % env_subs['date'])
|
||||
st.html_out.append(HTML_END)
|
||||
st.man_out.append(MAN_END)
|
||||
|
||||
fi.html_out = ''.join(st.html_out)
|
||||
st.html_out = None
|
||||
|
||||
fi.man_out = ''.join(st.man_out)
|
||||
st.man_out = None
|
||||
|
||||
|
||||
def handle_starttag(self, tag, attrs_list):
|
||||
st = self.state
|
||||
if args.debug:
|
||||
self.output_debug('START', (tag, attrs_list))
|
||||
if st.at_first_tag_in_li:
|
||||
if st.list_state[-1] == 'dl':
|
||||
st.dt_from = tag
|
||||
if tag == 'p':
|
||||
tag = 'dt'
|
||||
else:
|
||||
st.html_out.append('<dt>')
|
||||
elif tag == 'p':
|
||||
st.at_first_tag_in_dd = True # Kluge to suppress a .P at the start of an li.
|
||||
st.at_first_tag_in_li = False
|
||||
if tag == 'p':
|
||||
if not st.at_first_tag_in_dd:
|
||||
st.man_out.append(st.p_macro)
|
||||
elif tag == 'li':
|
||||
st.at_first_tag_in_li = True
|
||||
lstate = st.list_state[-1]
|
||||
if lstate == 'dl':
|
||||
return
|
||||
if lstate == 'o':
|
||||
st.man_out.append(".IP o\n")
|
||||
else:
|
||||
st.man_out.append(".IP " + str(lstate) + ".\n")
|
||||
st.list_state[-1] += 1
|
||||
elif tag == 'blockquote':
|
||||
st.man_out.append(".RS 4\n")
|
||||
elif tag == 'pre':
|
||||
st.in_pre = True
|
||||
st.man_out.append(st.p_macro + ".nf\n")
|
||||
elif tag == 'code' and not st.in_pre:
|
||||
st.in_code = True
|
||||
st.txt += BOLD_FONT[0]
|
||||
elif tag == 'strong' or tag == 'b':
|
||||
st.txt += BOLD_FONT[0]
|
||||
elif tag == 'em' or tag == 'i':
|
||||
if st.want_manpage:
|
||||
tag = 'u' # Change it into underline to be more like the man page
|
||||
st.txt += UNDR_FONT[0]
|
||||
elif tag == 'ol':
|
||||
start = 1
|
||||
for var, val in attrs_list:
|
||||
if var == 'start':
|
||||
start = int(val) # We only support integers.
|
||||
break
|
||||
if st.list_state:
|
||||
st.man_out.append(".RS\n")
|
||||
if start == 0:
|
||||
tag = 'dl'
|
||||
attrs_list = [ ]
|
||||
st.list_state.append('dl')
|
||||
else:
|
||||
st.list_state.append(start)
|
||||
st.man_out.append(st.p_macro)
|
||||
st.p_macro = ".IP\n"
|
||||
elif tag == 'ul':
|
||||
st.man_out.append(st.p_macro)
|
||||
if st.list_state:
|
||||
st.man_out.append(".RS\n")
|
||||
st.p_macro = ".IP\n"
|
||||
st.list_state.append('o')
|
||||
elif tag == 'hr':
|
||||
st.man_out.append(".l\n")
|
||||
st.html_out.append("<hr />")
|
||||
return
|
||||
st.html_out.append('<' + tag + ''.join(' ' + var + '="' + htmlify(val) + '"' for var, val in attrs_list) + '>')
|
||||
st.at_first_tag_in_dd = False
|
||||
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
st = self.state
|
||||
if args.debug:
|
||||
self.output_debug('END', (tag,))
|
||||
if tag in CONSUMES_TXT or st.dt_from == tag:
|
||||
txt = st.txt.strip()
|
||||
st.txt = ''
|
||||
else:
|
||||
txt = None
|
||||
add_to_txt = None
|
||||
if tag == 'h1':
|
||||
st.man_out.append(st.p_macro + '.SH "' + manify(txt) + '"\n')
|
||||
elif tag == 'h2':
|
||||
st.man_out.append(st.p_macro + '.SS "' + manify(txt) + '"\n')
|
||||
elif tag == 'p':
|
||||
if st.dt_from == 'p':
|
||||
tag = 'dt'
|
||||
st.man_out.append('.IP "' + manify(txt) + '"\n')
|
||||
st.dt_from = None
|
||||
elif txt != '':
|
||||
st.man_out.append(manify(txt) + "\n")
|
||||
elif tag == 'li':
|
||||
if st.list_state[-1] == 'dl':
|
||||
if st.at_first_tag_in_li:
|
||||
die("Invalid 0. -> td translation")
|
||||
tag = 'dd'
|
||||
if txt != '':
|
||||
st.man_out.append(manify(txt) + "\n")
|
||||
st.at_first_tag_in_li = False
|
||||
elif tag == 'blockquote':
|
||||
st.man_out.append(".RE\n")
|
||||
elif tag == 'pre':
|
||||
st.in_pre = False
|
||||
st.man_out.append(manify(txt) + "\n.fi\n")
|
||||
elif (tag == 'code' and not st.in_pre):
|
||||
st.in_code = False
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'strong' or tag == 'b':
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'em' or tag == 'i':
|
||||
if st.want_manpage:
|
||||
tag = 'u' # Change it into underline to be more like the man page
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'ol' or tag == 'ul':
|
||||
if st.list_state.pop() == 'dl':
|
||||
tag = 'dl'
|
||||
if st.list_state:
|
||||
st.man_out.append(".RE\n")
|
||||
else:
|
||||
st.p_macro = ".P\n"
|
||||
st.at_first_tag_in_dd = False
|
||||
elif tag == 'hr':
|
||||
return
|
||||
st.html_out.append('</' + tag + '>')
|
||||
if add_to_txt:
|
||||
if txt is None:
|
||||
st.txt += add_to_txt
|
||||
else:
|
||||
txt += add_to_txt
|
||||
if st.dt_from == tag:
|
||||
st.man_out.append('.IP "' + manify(txt) + '"\n')
|
||||
st.html_out.append('</dt><dd>')
|
||||
st.at_first_tag_in_dd = True
|
||||
st.dt_from = None
|
||||
elif tag == 'dt':
|
||||
st.html_out.append('<dd>')
|
||||
st.at_first_tag_in_dd = True
|
||||
|
||||
|
||||
def handle_data(self, txt):
|
||||
st = self.state
|
||||
if args.debug:
|
||||
self.output_debug('DATA', (txt,))
|
||||
if st.in_pre:
|
||||
html = htmlify(txt)
|
||||
else:
|
||||
txt = re.sub(r'\s--(\s)', NBR_SPACE[0] + r'--\1', txt).replace('--', NBR_DASH[0]*2)
|
||||
txt = re.sub(r'(^|\W)-', r'\1' + NBR_DASH[0], txt)
|
||||
html = htmlify(txt)
|
||||
if st.in_code:
|
||||
txt = re.sub(r'\s', NBR_SPACE[0], txt)
|
||||
html = html.replace(NBR_DASH[0], '-').replace(NBR_SPACE[0], ' ') # <code> is non-breaking in CSS
|
||||
st.html_out.append(html.replace(NBR_SPACE[0], ' ').replace(NBR_DASH[0], '-⁠'))
|
||||
st.txt += txt
|
||||
|
||||
|
||||
def output_debug(self, event, extra):
|
||||
import pprint
|
||||
st = self.state
|
||||
if args.debug < 2:
|
||||
st = argparse.Namespace(**vars(st))
|
||||
if len(st.html_out) > 2:
|
||||
st.html_out = ['...'] + st.html_out[-2:]
|
||||
if len(st.man_out) > 2:
|
||||
st.man_out = ['...'] + st.man_out[-2:]
|
||||
print(event, extra)
|
||||
pprint.PrettyPrinter(indent=2).pprint(vars(st))
|
||||
|
||||
|
||||
def manify(txt):
|
||||
return re.sub(r"^(['.])", r'\&\1', txt.replace('\\', '\\\\')
|
||||
.replace(NBR_SPACE[0], NBR_SPACE[1])
|
||||
.replace(NBR_DASH[0], NBR_DASH[1])
|
||||
.replace(NORM_FONT[0], NORM_FONT[1])
|
||||
.replace(BOLD_FONT[0], BOLD_FONT[1])
|
||||
.replace(UNDR_FONT[0], UNDR_FONT[1]), flags=re.M)
|
||||
|
||||
|
||||
def htmlify(txt):
|
||||
return txt.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def warn(*msg):
|
||||
print(*msg, file=sys.stderr)
|
||||
|
||||
|
||||
def die(*msg):
|
||||
warn(*msg)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Output html and (optionally) nroff for markdown pages.", add_help=False)
|
||||
parser.add_argument('--test', action='store_true', help="Just test the parsing without outputting any files.")
|
||||
parser.add_argument('--debug', '-D', action='count', default=0, help='Output copious info on the html parsing. Repeat for even more.')
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument("mdfiles", nargs='+', help="The source .md files to convert.")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
import cmarkgfm
|
||||
md_parser = cmarkgfm.markdown_to_html
|
||||
gfm_parser = cmarkgfm.github_flavored_markdown_to_html
|
||||
except:
|
||||
try:
|
||||
import commonmark
|
||||
md_parser = html_via_commonmark
|
||||
except:
|
||||
die("Failed to find cmarkgfm or commonmark for python3.")
|
||||
gfm_parser = None
|
||||
|
||||
main()
|
||||
374
md2man
374
md2man
@@ -1,374 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This script takes a manpage written in markdown and turns it into an html web
|
||||
# page and a nroff man page. The input file must have the name of the program
|
||||
# and the section in this format: NAME.NUM.md. The output files are written
|
||||
# into the current directory named NAME.NUM.html and NAME.NUM. The input
|
||||
# format has one extra extension: if a numbered list starts at 0, it is turned
|
||||
# into a description list. The dl's dt tag is taken from the contents of the
|
||||
# first tag inside the li, which is usually a p, code, or strong tag. The
|
||||
# cmarkgfm or commonmark lib is used to transforms the input file into html.
|
||||
# The html.parser is used as a state machine that both tweaks the html and
|
||||
# outputs the nroff data based on the html tags.
|
||||
#
|
||||
# Copyright (C) 2020 Wayne Davison
|
||||
#
|
||||
# This program is freely redistributable.
|
||||
|
||||
import sys, os, re, argparse, subprocess, time
|
||||
from html.parser import HTMLParser
|
||||
|
||||
CONSUMES_TXT = set('h1 h2 p li pre'.split())
|
||||
|
||||
HTML_START = """\
|
||||
<html><head>
|
||||
<title>%s</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto&family=Roboto+Mono&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
max-width: 50em;
|
||||
margin: auto;
|
||||
}
|
||||
body, b, strong, u {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
code {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre code {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
}
|
||||
blockquote pre code {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
dd p:first-of-type {
|
||||
margin-block-start: 0em;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
"""
|
||||
|
||||
HTML_END = """\
|
||||
<div style="float: right"><p><i>%s</i></p></div>
|
||||
</body></html>
|
||||
"""
|
||||
|
||||
MAN_START = r"""
|
||||
.TH "%s" "%s" "%s" "%s" "User Commands"
|
||||
""".lstrip()
|
||||
|
||||
MAN_END = """\
|
||||
"""
|
||||
|
||||
NORM_FONT = ('\1', r"\fP")
|
||||
BOLD_FONT = ('\2', r"\fB")
|
||||
ULIN_FONT = ('\3', r"\fI")
|
||||
|
||||
md_parser = None
|
||||
|
||||
def main():
|
||||
fi = re.match(r'^(?P<fn>(?P<srcdir>.+/)?(?P<name>(?P<prog>[^/]+)\.(?P<sect>\d+))\.md)$', args.mdfile)
|
||||
if not fi:
|
||||
die('Failed to parse NAME.NUM.md out of input file:', args.mdfile)
|
||||
fi = argparse.Namespace(**fi.groupdict())
|
||||
|
||||
if not fi.srcdir:
|
||||
fi.srcdir = './'
|
||||
|
||||
fi.title = fi.prog + '(' + fi.sect + ') man page'
|
||||
fi.mtime = 0
|
||||
|
||||
if os.path.lexists(fi.srcdir + '.git'):
|
||||
fi.mtime = int(subprocess.check_output('git log -1 --format=%at'.split()))
|
||||
|
||||
env_subs = { 'prefix': os.environ.get('RSYNC_OVERRIDE_PREFIX', None) }
|
||||
|
||||
if args.test:
|
||||
env_subs['VERSION'] = '1.0.0'
|
||||
env_subs['libdir'] = '/usr'
|
||||
else:
|
||||
for fn in 'NEWS.md Makefile'.split():
|
||||
try:
|
||||
st = os.lstat(fi.srcdir + fn)
|
||||
except:
|
||||
die('Failed to find', fi.srcdir + fn)
|
||||
if not fi.mtime:
|
||||
fi.mtime = st.st_mtime
|
||||
|
||||
with open(fi.srcdir + 'Makefile', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
m = re.match(r'^(\w+)=(.+)', line)
|
||||
if not m:
|
||||
continue
|
||||
var, val = (m[1], m[2])
|
||||
if var == 'prefix' and env_subs[var] is not None:
|
||||
continue
|
||||
while re.search(r'\$\{', val):
|
||||
val = re.sub(r'\$\{(\w+)\}', lambda m: env_subs[m[1]], val)
|
||||
env_subs[var] = val
|
||||
if var == 'VERSION':
|
||||
break
|
||||
|
||||
with open(fi.fn, 'r', encoding='utf-8') as fh:
|
||||
txt = fh.read()
|
||||
|
||||
txt = re.sub(r'@VERSION@', env_subs['VERSION'], txt)
|
||||
txt = re.sub(r'@LIBDIR@', env_subs['libdir'], txt)
|
||||
|
||||
fi.html_in = md_parser(txt)
|
||||
txt = None
|
||||
|
||||
fi.date = time.strftime('%d %b %Y', time.localtime(fi.mtime))
|
||||
fi.man_headings = (fi.prog, fi.sect, fi.date, fi.prog + ' ' + env_subs['VERSION'])
|
||||
|
||||
HtmlToManPage(fi)
|
||||
|
||||
if args.test:
|
||||
print("The test was successful.")
|
||||
return
|
||||
|
||||
for fn, txt in ((fi.name + '.html', fi.html_out), (fi.name, fi.man_out)):
|
||||
print("Wrote:", fn)
|
||||
with open(fn, 'w', encoding='utf-8') as fh:
|
||||
fh.write(txt)
|
||||
|
||||
|
||||
def html_via_cmarkgfm(txt):
|
||||
return cmarkgfm.markdown_to_html(txt)
|
||||
|
||||
|
||||
def html_via_commonmark(txt):
|
||||
return commonmark.HtmlRenderer().render(commonmark.Parser().parse(txt))
|
||||
|
||||
|
||||
class HtmlToManPage(HTMLParser):
|
||||
def __init__(self, fi):
|
||||
HTMLParser.__init__(self, convert_charrefs=True)
|
||||
|
||||
st = self.state = argparse.Namespace(
|
||||
list_state = [ ],
|
||||
p_macro = ".P\n",
|
||||
at_first_tag_in_li = False,
|
||||
at_first_tag_in_dd = False,
|
||||
dt_from = None,
|
||||
in_pre = False,
|
||||
in_code = False,
|
||||
html_out = [ HTML_START % fi.title ],
|
||||
man_out = [ MAN_START % fi.man_headings ],
|
||||
txt = '',
|
||||
)
|
||||
|
||||
self.feed(fi.html_in)
|
||||
fi.html_in = None
|
||||
|
||||
st.html_out.append(HTML_END % fi.date)
|
||||
st.man_out.append(MAN_END)
|
||||
|
||||
fi.html_out = ''.join(st.html_out)
|
||||
st.html_out = None
|
||||
|
||||
fi.man_out = ''.join(st.man_out)
|
||||
st.man_out = None
|
||||
|
||||
|
||||
def handle_starttag(self, tag, attrs_list):
|
||||
st = self.state
|
||||
if args.debug:
|
||||
self.output_debug('START', (tag, attrs_list))
|
||||
if st.at_first_tag_in_li:
|
||||
if st.list_state[-1] == 'dl':
|
||||
st.dt_from = tag
|
||||
if tag == 'p':
|
||||
tag = 'dt'
|
||||
else:
|
||||
st.html_out.append('<dt>')
|
||||
elif tag == 'p':
|
||||
st.at_first_tag_in_dd = True # Kluge to suppress a .P at the start of an li.
|
||||
st.at_first_tag_in_li = False
|
||||
if tag == 'p':
|
||||
if not st.at_first_tag_in_dd:
|
||||
st.man_out.append(st.p_macro)
|
||||
elif tag == 'li':
|
||||
st.at_first_tag_in_li = True
|
||||
lstate = st.list_state[-1]
|
||||
if lstate == 'dl':
|
||||
return
|
||||
if lstate == 'o':
|
||||
st.man_out.append(".IP o\n")
|
||||
else:
|
||||
st.man_out.append(".IP " + str(lstate) + ".\n")
|
||||
st.list_state[-1] += 1
|
||||
elif tag == 'blockquote':
|
||||
st.man_out.append(".RS 4\n")
|
||||
elif tag == 'pre':
|
||||
st.in_pre = True
|
||||
st.man_out.append(st.p_macro + ".nf\n")
|
||||
elif tag == 'code' and not st.in_pre:
|
||||
st.in_code = True
|
||||
st.txt += BOLD_FONT[0]
|
||||
elif tag == 'strong' or tag == 'b':
|
||||
st.txt += BOLD_FONT[0]
|
||||
elif tag == 'em' or tag == 'i':
|
||||
tag = 'u' # Change it into underline to be more like the man page
|
||||
st.txt += ULIN_FONT[0]
|
||||
elif tag == 'ol':
|
||||
start = 1
|
||||
for var, val in attrs_list:
|
||||
if var == 'start':
|
||||
start = int(val) # We only support integers.
|
||||
break
|
||||
if st.list_state:
|
||||
st.man_out.append(".RS\n")
|
||||
if start == 0:
|
||||
tag = 'dl'
|
||||
attrs_list = [ ]
|
||||
st.list_state.append('dl')
|
||||
else:
|
||||
st.list_state.append(start)
|
||||
st.man_out.append(st.p_macro)
|
||||
st.p_macro = ".IP\n"
|
||||
elif tag == 'ul':
|
||||
st.man_out.append(st.p_macro)
|
||||
if st.list_state:
|
||||
st.man_out.append(".RS\n")
|
||||
st.p_macro = ".IP\n"
|
||||
st.list_state.append('o')
|
||||
st.html_out.append('<' + tag + ''.join(' ' + var + '="' + htmlify(val) + '"' for var, val in attrs_list) + '>')
|
||||
st.at_first_tag_in_dd = False
|
||||
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
st = self.state
|
||||
if args.debug:
|
||||
self.output_debug('END', (tag,))
|
||||
if tag in CONSUMES_TXT or st.dt_from == tag:
|
||||
txt = st.txt.strip()
|
||||
st.txt = ''
|
||||
else:
|
||||
txt = None
|
||||
add_to_txt = None
|
||||
if tag == 'h1':
|
||||
st.man_out.append(st.p_macro + '.SH "' + manify(txt) + '"\n')
|
||||
elif tag == 'h2':
|
||||
st.man_out.append(st.p_macro + '.SS "' + manify(txt) + '"\n')
|
||||
elif tag == 'p':
|
||||
if st.dt_from == 'p':
|
||||
tag = 'dt'
|
||||
st.man_out.append('.IP "' + manify(txt) + '"\n')
|
||||
st.dt_from = None
|
||||
elif txt != '':
|
||||
st.man_out.append(manify(txt) + "\n")
|
||||
elif tag == 'li':
|
||||
if st.list_state[-1] == 'dl':
|
||||
if st.at_first_tag_in_li:
|
||||
die("Invalid 0. -> td translation")
|
||||
tag = 'dd'
|
||||
if txt != '':
|
||||
st.man_out.append(manify(txt) + "\n")
|
||||
st.at_first_tag_in_li = False
|
||||
elif tag == 'blockquote':
|
||||
st.man_out.append(".RE\n")
|
||||
elif tag == 'pre':
|
||||
st.in_pre = False
|
||||
st.man_out.append(manify(txt) + "\n.fi\n")
|
||||
elif (tag == 'code' and not st.in_pre):
|
||||
st.in_code = False
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'strong' or tag == 'b':
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'em' or tag == 'i':
|
||||
tag = 'u' # Change it into underline to be more like the man page
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'ol' or tag == 'ul':
|
||||
if st.list_state.pop() == 'dl':
|
||||
tag = 'dl'
|
||||
if st.list_state:
|
||||
st.man_out.append(".RE\n")
|
||||
else:
|
||||
st.p_macro = ".P\n"
|
||||
st.at_first_tag_in_dd = False
|
||||
st.html_out.append('</' + tag + '>')
|
||||
if add_to_txt:
|
||||
if txt is None:
|
||||
st.txt += add_to_txt
|
||||
else:
|
||||
txt += add_to_txt
|
||||
if st.dt_from == tag:
|
||||
st.man_out.append('.IP "' + manify(txt) + '"\n')
|
||||
st.html_out.append('</dt><dd>')
|
||||
st.at_first_tag_in_dd = True
|
||||
st.dt_from = None
|
||||
elif tag == 'dt':
|
||||
st.html_out.append('<dd>')
|
||||
st.at_first_tag_in_dd = True
|
||||
|
||||
|
||||
def handle_data(self, data):
|
||||
st = self.state
|
||||
if args.debug:
|
||||
self.output_debug('DATA', (data,))
|
||||
if st.in_code:
|
||||
data = re.sub(r'\s', '\xa0', data) # nbsp in non-pre code
|
||||
data = re.sub(r'\s--\s', '\xa0-- ', data)
|
||||
st.html_out.append(htmlify(data))
|
||||
st.txt += data
|
||||
|
||||
|
||||
def output_debug(self, event, extra):
|
||||
import pprint
|
||||
st = self.state
|
||||
if args.debug < 2:
|
||||
st = argparse.Namespace(**vars(st))
|
||||
if len(st.html_out) > 2:
|
||||
st.html_out = ['...'] + st.html_out[-2:]
|
||||
if len(st.man_out) > 2:
|
||||
st.man_out = ['...'] + st.man_out[-2:]
|
||||
print(event, extra)
|
||||
pprint.PrettyPrinter(indent=2).pprint(vars(st))
|
||||
|
||||
|
||||
def manify(txt):
|
||||
return re.sub(r"^(['.])", r'\&\1', txt.replace('\\', '\\\\')
|
||||
.replace("\xa0", r'\ ') # non-breaking space
|
||||
.replace('--', r'\-\-') # non-breaking double dash
|
||||
.replace(NORM_FONT[0], NORM_FONT[1])
|
||||
.replace(BOLD_FONT[0], BOLD_FONT[1])
|
||||
.replace(ULIN_FONT[0], ULIN_FONT[1]), flags=re.M)
|
||||
|
||||
|
||||
def htmlify(txt):
|
||||
return re.sub(r'(\W)-', r'\1‑',
|
||||
txt.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
.replace('--', '‑‑').replace("\xa0-", ' ‑').replace("\xa0", ' '))
|
||||
|
||||
|
||||
def warn(*msg):
|
||||
print(*msg, file=sys.stderr)
|
||||
|
||||
|
||||
def die(*msg):
|
||||
warn(*msg)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Transform a NAME.NUM.md markdown file into a NAME.NUM.html web page & a NAME.NUM man page.', add_help=False)
|
||||
parser.add_argument('--test', action='store_true', help='Test if we can parse the input w/o updating any files.')
|
||||
parser.add_argument('--debug', '-D', action='count', default=0, help='Output copious info on the html parsing. Repeat for even more.')
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument('mdfile', help="The NAME.NUM.md file to parse.")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
import cmarkgfm
|
||||
md_parser = html_via_cmarkgfm
|
||||
except:
|
||||
try:
|
||||
import commonmark
|
||||
md_parser = html_via_commonmark
|
||||
except:
|
||||
die("Failed to find cmarkgfm or commonmark for python3.")
|
||||
|
||||
main()
|
||||
20
mkgitver
Executable file
20
mkgitver
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
srcdir=`dirname $0`
|
||||
gitver=`git describe --abbrev=8 2>/dev/null`
|
||||
|
||||
if [ ! -f git-version.h ]; then
|
||||
touch git-version.h
|
||||
fi
|
||||
|
||||
case "$gitver" in
|
||||
*.*)
|
||||
echo "#define RSYNC_GITVER \"$gitver\"" >git-version.h.new
|
||||
if ! diff git-version.h.new git-version.h >/dev/null; then
|
||||
echo "Updating git-version.h"
|
||||
mv git-version.h.new git-version.h
|
||||
else
|
||||
rm git-version.h.new
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
BEGIN {
|
||||
while ((getline i < "proto.h") > 0) old_protos = old_protos ? old_protos "\n" i : i
|
||||
close("proto.h")
|
||||
protos = "/* This file is automatically generated with \"make proto\". DO NOT EDIT */\n"
|
||||
}
|
||||
|
||||
@@ -35,5 +36,5 @@ inheader {
|
||||
|
||||
END {
|
||||
if (old_protos != protos) print protos > "proto.h"
|
||||
printf "" > "proto.h-tstamp"
|
||||
system("touch proto.h-tstamp")
|
||||
}
|
||||
|
||||
12
packaging/auto-Makefile
Normal file
12
packaging/auto-Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
TARGETS := all install install-ssl-daemon install-all install-strip conf gen gensend reconfigure restatus \
|
||||
proto man clean cleantests distclean test check check29 check30 installcheck splint \
|
||||
doxygen doxygen-upload finddead rrsync
|
||||
|
||||
.PHONY: $(TARGETS) auto-prep
|
||||
|
||||
$(TARGETS): auto-prep
|
||||
make -C build $@
|
||||
|
||||
auto-prep:
|
||||
@if test x`packaging/prep-auto-dir` = x; then echo "auto-build-save is not setup"; exit 1; fi
|
||||
@echo 'Build branch: '`readlink build/.branch | tr % /`
|
||||
@@ -171,4 +171,4 @@ if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
# vim: sw=4 et ft=python
|
||||
|
||||
@@ -1,85 +1,143 @@
|
||||
#!/usr/bin/env perl
|
||||
# This script outputs some perl code that parses all possible options
|
||||
# that the code in options.c might send to the server. This perl code
|
||||
# is included in the rrsync script.
|
||||
use strict;
|
||||
#!/usr/bin/env python3
|
||||
# This script outputs either perl or python code that parses all possible options
|
||||
# that the code in options.c might send to the server. The resulting code is then
|
||||
# included in the rrsync script.
|
||||
|
||||
our %short_no_arg;
|
||||
our %short_with_num = ( '@' => 1 );
|
||||
our %long_opt = ( # These include some extra long-args that BackupPC uses:
|
||||
'block-size' => 1,
|
||||
'daemon' => -1,
|
||||
'debug' => 1,
|
||||
'fake-super' => 0,
|
||||
'fuzzy' => 0,
|
||||
'group' => 0,
|
||||
'hard-links' => 0,
|
||||
'ignore-times' => 0,
|
||||
'info' => 1,
|
||||
'links' => 0,
|
||||
'log-file' => 3,
|
||||
'one-file-system' => 0,
|
||||
'owner' => 0,
|
||||
'perms' => 0,
|
||||
'recursive' => 0,
|
||||
'times' => 0,
|
||||
'write-devices' => -1,
|
||||
);
|
||||
our $last_long_opt;
|
||||
import re, argparse
|
||||
|
||||
open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
|
||||
short_no_arg = { }
|
||||
short_with_num = { '@': 1 };
|
||||
long_opts = { # These include some extra long-args that BackupPC uses:
|
||||
'block-size': 1,
|
||||
'daemon': -1,
|
||||
'debug': 1,
|
||||
'fake-super': 0,
|
||||
'fuzzy': 0,
|
||||
'group': 0,
|
||||
'hard-links': 0,
|
||||
'ignore-times': 0,
|
||||
'info': 1,
|
||||
'links': 0,
|
||||
'log-file': 3,
|
||||
'munge-links': 0,
|
||||
'no-munge-links': -1,
|
||||
'one-file-system': 0,
|
||||
'owner': 0,
|
||||
'perms': 0,
|
||||
'recursive': 0,
|
||||
'stderr': 1,
|
||||
'times': 0,
|
||||
'write-devices': -1,
|
||||
}
|
||||
|
||||
while (<IN>) {
|
||||
if (/\Qargstr[x++]\E = '([^.ie])'/) {
|
||||
$short_no_arg{$1} = 1;
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {
|
||||
$short_with_num{$1} = 1;
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
|
||||
$last_long_opt = $1;
|
||||
$long_opt{$1} = 0 unless exists $long_opt{$1};
|
||||
} elsif (defined($last_long_opt)
|
||||
&& /\Qargs[ac++]\E = ([^["\s]+);/) {
|
||||
$long_opt{$last_long_opt} = 2;
|
||||
undef $last_long_opt;
|
||||
} elsif (/return "--([^"]+-dest)";/) {
|
||||
$long_opt{$1} = 2;
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qasprintf(\E[^,]+, "--([^"=]+)=/ || /\Qargs[ac++]\E = "--([^"=]+)=/ || /fmt = .*: "--([^"=]+)=/) {
|
||||
$long_opt{$1} = 1;
|
||||
undef $last_long_opt;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
def main():
|
||||
last_long_opt = None
|
||||
|
||||
my $short_no_arg = join('', sort keys %short_no_arg);
|
||||
my $short_with_num = join('', sort keys %short_with_num);
|
||||
with open('../options.c') as fh:
|
||||
for line in fh:
|
||||
m = re.search(r"argstr\[x\+\+\] = '([^.ie])'", line)
|
||||
if m:
|
||||
short_no_arg[m.group(1)] = 1
|
||||
last_long_opt = None
|
||||
continue
|
||||
|
||||
print <<EOT;
|
||||
m = re.search(r'asprintf\([^,]+, "-([a-zA-Z0-9])\%l?[ud]"', line)
|
||||
if m:
|
||||
short_with_num[m.group(1)] = 1
|
||||
last_long_opt = None
|
||||
continue
|
||||
|
||||
# These options are the only options that rsync might send to the server,
|
||||
# and only in the option format that the stock rsync produces.
|
||||
m = re.search(r'args\[ac\+\+\] = "--([^"=]+)"', line)
|
||||
if m:
|
||||
last_long_opt = m.group(1)
|
||||
if last_long_opt not in long_opts:
|
||||
long_opts[last_long_opt] = 0
|
||||
else:
|
||||
last_long_opt = None
|
||||
continue
|
||||
|
||||
if last_long_opt:
|
||||
m = re.search(r'args\[ac\+\+\] = ([^["\s]+);', line)
|
||||
if m:
|
||||
long_opts[last_long_opt] = 2
|
||||
last_long_opt = None
|
||||
continue
|
||||
|
||||
m = re.search(r'return "--([^"]+-dest)";', line)
|
||||
if m:
|
||||
long_opts[m.group(1)] = 2
|
||||
last_long_opt = None
|
||||
continue
|
||||
|
||||
m = re.search(r'asprintf\([^,]+, "--([^"=]+)=', line)
|
||||
if not m:
|
||||
m = re.search(r'args\[ac\+\+\] = "--([^"=]+)=', line)
|
||||
if not m:
|
||||
m = re.search(r'fmt = .*: "--([^"=]+)=', line)
|
||||
if m:
|
||||
long_opts[m.group(1)] = 1
|
||||
last_long_opt = None
|
||||
|
||||
long_opts['files-from'] = 3
|
||||
|
||||
txt = """\
|
||||
### START of options data produced by the cull_options script. ###
|
||||
|
||||
# To disable a short-named option, add its letter to this string:
|
||||
our \$short_disabled = 's';
|
||||
|
||||
our \$short_no_arg = '$short_no_arg'; # DO NOT REMOVE ANY
|
||||
our \$short_with_num = '$short_with_num'; # DO NOT REMOVE ANY
|
||||
"""
|
||||
|
||||
txt += str_assign('short_disabled', 's') + "\n"
|
||||
txt += '# These are also disabled when the restricted dir is not "/":\n'
|
||||
txt += str_assign('short_disabled_subdir', 'KLk') + "\n"
|
||||
txt += '# These are all possible short options that we will accept (when not disabled above):\n'
|
||||
txt += str_assign('short_no_arg', ''.join(sorted(short_no_arg)), 'DO NOT REMOVE ANY')
|
||||
txt += str_assign('short_with_num', ''.join(sorted(short_with_num)), 'DO NOT REMOVE ANY')
|
||||
|
||||
txt += """
|
||||
# To disable a long-named option, change its value to a -1. The values mean:
|
||||
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
|
||||
# check the arg when receiving; and 3 = always check the arg.
|
||||
our \%long_opt = (
|
||||
EOT
|
||||
"""
|
||||
|
||||
foreach my $opt (sort keys %long_opt) {
|
||||
my $val = $long_opt{$opt};
|
||||
$val = 1 if $opt =~ /^(max-|min-)/;
|
||||
$val = 3 if $opt eq 'files-from';
|
||||
$val = q"$only eq 'r' ? -1 : " . $val if $opt =~ /^(remove-|log-file)/;
|
||||
$val = q"$only eq 'w' ? -1 : " . $val if $opt eq 'sender';
|
||||
print " '$opt' => $val,\n";
|
||||
}
|
||||
print(txt, end='')
|
||||
|
||||
print ");\n\n";
|
||||
if args.python:
|
||||
print("long_opts = {")
|
||||
sep = ':'
|
||||
else:
|
||||
print("our %long_opt = (")
|
||||
sep = ' =>'
|
||||
|
||||
for opt in sorted(long_opts):
|
||||
if opt.startswith(('min-', 'max-')):
|
||||
val = 1
|
||||
else:
|
||||
val = long_opts[opt]
|
||||
print(' ', repr(opt) + sep, str(val) + ',')
|
||||
|
||||
if args.python:
|
||||
print("}")
|
||||
else:
|
||||
print(");")
|
||||
print("\n### END of options data produced by the cull_options script. ###")
|
||||
|
||||
|
||||
def str_assign(name, val, comment=None):
|
||||
comment = ' # ' + comment if comment else ''
|
||||
if args.python:
|
||||
return name + ' = ' + repr(val) + comment + "\n"
|
||||
return 'our $' + name + ' = ' + repr(val) + ';' + comment + "\n"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Output culled rsync options for rrsync.", add_help=False)
|
||||
out_group = parser.add_mutually_exclusive_group()
|
||||
out_group.add_argument('--perl', action='store_true', help="Output perl code.")
|
||||
out_group.add_argument('--python', action='store_true', help="Output python code (the default).")
|
||||
parser.add_argument('--help', '-h', action='help', help="Output this help message and exit.")
|
||||
args = parser.parse_args()
|
||||
if not args.perl:
|
||||
args.python = True
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.2.0
|
||||
%define fullversion %{version}pre3
|
||||
Release: 0.1.pre3
|
||||
Version: 3.2.4
|
||||
%define fullversion %{version}pre1
|
||||
Release: 0.1.pre1
|
||||
%define srcdir src-previews
|
||||
Group: Applications/Internet
|
||||
License: GPL
|
||||
Source0: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz
|
||||
#Source1: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-patches-%{fullversion}.tar.gz
|
||||
URL: http://rsync.samba.org/
|
||||
Source0: https://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz
|
||||
#Source1: https://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-patches-%{fullversion}.tar.gz
|
||||
URL: https://rsync.samba.org/
|
||||
|
||||
Prefix: %{_prefix}
|
||||
BuildRoot: /var/tmp/%{name}-root
|
||||
@@ -66,7 +66,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc COPYING NEWS.md OLDNEWS.md README.md support/ tech_report.tex
|
||||
%doc COPYING NEWS.md README.md support/ tech_report.tex
|
||||
%config(noreplace) /etc/xinetd.d/rsync
|
||||
%{_prefix}/bin/rsync
|
||||
%{_prefix}/bin/rsync-ssl
|
||||
@@ -79,8 +79,8 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%dir /etc/rsync-ssl/certs
|
||||
|
||||
%changelog
|
||||
* Wed Jun 17 2020 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.2.0pre3.
|
||||
* Sun Jan 02 2022 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.2.4pre1.
|
||||
|
||||
* Fri Mar 21 2008 Wayne Davison <wayne@opencoder.net>
|
||||
Added installation of /etc/xinetd.d/rsync file and some commented-out
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2020 Wayne Davison
|
||||
#
|
||||
# This program is freely redistributable.
|
||||
|
||||
import os, re, argparse
|
||||
|
||||
HTML_START = """\
|
||||
<html><head>
|
||||
<title>%s</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto&family=Roboto+Mono&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
max-width: 50em;
|
||||
margin: auto;
|
||||
}
|
||||
body, b, strong, u {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
code {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre code {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
}
|
||||
blockquote pre code {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
dd p:first-of-type {
|
||||
margin-block-start: 0em;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
"""
|
||||
|
||||
HTML_END = """\
|
||||
</body></html>
|
||||
"""
|
||||
|
||||
md_parser = None
|
||||
|
||||
def main():
|
||||
for mdfn in args.mdfiles:
|
||||
if not mdfn.endswith('.md'):
|
||||
print('Ignoring non-md input file:', mdfn)
|
||||
continue
|
||||
title = re.sub(r'.*/', '', mdfn).replace('.md', '')
|
||||
htfn = mdfn.replace('.md', '.html')
|
||||
|
||||
print("Parsing", mdfn, '->', htfn)
|
||||
|
||||
with open(mdfn, 'r', encoding='utf-8') as fh:
|
||||
txt = fh.read()
|
||||
|
||||
txt = re.sub(r'\s--\s', '\xa0-- ', txt)
|
||||
|
||||
html = md_parser(txt)
|
||||
|
||||
html = re.sub(r'(<code>)([\s\S]*?)(</code>)', lambda m: m[1] + re.sub(r'\s', '\xa0', m[2]) + m[3], html)
|
||||
html = html.replace('--', '‑‑').replace("\xa0-", ' ‑').replace("\xa0", ' ')
|
||||
html = re.sub(r'(\W)-', r'\1‑', html)
|
||||
|
||||
if os.path.lexists(htfn):
|
||||
os.unlink(htfn)
|
||||
|
||||
with open(htfn, 'w', encoding='utf-8') as fh:
|
||||
fh.write(HTML_START % title)
|
||||
fh.write(html)
|
||||
fh.write(HTML_END)
|
||||
|
||||
|
||||
def html_via_cmarkgfm(txt):
|
||||
return cmarkgfm.markdown_to_html(txt)
|
||||
|
||||
|
||||
def html_via_commonmark(txt):
|
||||
return commonmark.HtmlRenderer().render(commonmark.Parser().parse(txt))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Output html for md pages.', add_help=False)
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument("mdfiles", nargs='+', help="The .md files to turn into .html files.")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
import cmarkgfm
|
||||
md_parser = html_via_cmarkgfm
|
||||
except:
|
||||
try:
|
||||
import commonmark
|
||||
md_parser = html_via_commonmark
|
||||
except:
|
||||
die("Failed to find cmarkgfm or commonmark for python3.")
|
||||
|
||||
main()
|
||||
@@ -1,106 +0,0 @@
|
||||
#!/usr/bin/env -S python3 -B
|
||||
|
||||
# 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
|
||||
# git checkout of rsync (feel free to use your normal rsync build dir as
|
||||
# long as it doesn't have any uncommitted changes).
|
||||
#
|
||||
# If this is run with -tu, 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.
|
||||
|
||||
import os, sys, re, argparse, glob
|
||||
from datetime import datetime, timezone
|
||||
from getpass import getpass
|
||||
|
||||
sys.path = ['packaging'] + sys.path
|
||||
|
||||
from pkglib import *
|
||||
|
||||
# Where the local copy of /home/ftp/pub/rsync/dev/nightly should be updated.
|
||||
dest = os.environ['HOME'] + '/samba-rsync-ftp/dev/nightly'
|
||||
samba_host = os.environ['SAMBA_HOST']
|
||||
nightly_symlink = f"{dest}/rsync-HEAD.tar.gz"
|
||||
|
||||
def main():
|
||||
now = datetime.now(timezone.utc)
|
||||
name = now.strftime('rsync-HEAD-%Y%m%d-%H%MGMT')
|
||||
ztoday = now.strftime('%d %b %Y')
|
||||
today = ztoday.lstrip('0')
|
||||
gen_target = 'gensend' if args.upload else 'gen'
|
||||
|
||||
if not os.path.isdir(dest):
|
||||
die("$dest does not exist")
|
||||
if not os.path.isdir('.git'):
|
||||
die("There is no .git dir in the current directory.")
|
||||
if not os.path.exists('rsyncd.conf.5.md'):
|
||||
die("There is no rsync checkout in the current directory.")
|
||||
|
||||
mandate_gensend_hook()
|
||||
|
||||
if args.make_tar:
|
||||
check_git_state('master')
|
||||
cmd_chk(['touch', 'NEWS.md'])
|
||||
cmd_chk(['make', gen_target])
|
||||
cmd_chk(['rsync', '-a', *glob.glob('*.[1-9].html'), dest])
|
||||
|
||||
gen_files = get_gen_files()
|
||||
|
||||
confversion = get_configure_version()
|
||||
|
||||
# All version values are strings!
|
||||
last_version, last_protocol_version = get_OLDNEWS_version_info()
|
||||
protocol_version, subprotocol_version = get_protocol_versions()
|
||||
|
||||
if 'dev' in confversion or 'pre' in confversion:
|
||||
if last_protocol_version != protocol_version:
|
||||
if subprotocol_version == '0':
|
||||
die("SUBPROTOCOL_VERSION must not be 0 for a non-final release with a changed PROTOCOL_VERSION.")
|
||||
elif subprotocol_version != '0':
|
||||
die("SUBPROTOCOL_VERSION must be 0 when the PROTOCOL_VERSION hasn't changed from the last release.")
|
||||
elif subprotocol_version != '0':
|
||||
die("SUBPROTOCOL_VERSION must be 0 for a final release.")
|
||||
|
||||
name_slash = name + '/'
|
||||
tar_name = f"{name}.tar.gz"
|
||||
|
||||
print('Creating', tar_name)
|
||||
|
||||
cmd_chk(['rsync', '-a', *gen_files, name_slash])
|
||||
cmd_chk(f"git archive --format=tar --prefix={name}/ HEAD | tar xf -")
|
||||
cmd_chk(['support/git-set-file-times', '--quiet', '--prefix', name_slash])
|
||||
cmd_chk(['fakeroot', 'tar', 'czf', os.path.join(dest, tar_name), name])
|
||||
cmd_chk(['rm', '-rf', name])
|
||||
|
||||
if os.path.lexists(nightly_symlink):
|
||||
os.unlink(nightly_symlink)
|
||||
os.symlink(tar_name, nightly_symlink)
|
||||
|
||||
os.chdir(dest)
|
||||
|
||||
tar_files = list(reversed(sorted(glob.glob('rsync-HEAD-*'))))
|
||||
if len(tar_files) > 10:
|
||||
for fn in tar_files[10:]:
|
||||
print('Removing', fn)
|
||||
os.unlink(fn)
|
||||
|
||||
cmd_run('ls -ltr'.split())
|
||||
|
||||
if args.upload:
|
||||
cmd = 'rsync -aivHP --delete-after'.split()
|
||||
partial_dir = os.environ.get('RSYNC_PARTIAL_DIR', None)
|
||||
if partial_dir:
|
||||
cmd.append('-fR ' + partial_dir)
|
||||
cmd_chk([*cmd, '.', f"{samba_host}:/home/ftp/pub/rsync/dev/nightly"])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='A helper script for "nightly" tar files.', add_help=False)
|
||||
parser.add_argument('--make-tar', '-t', action='store_true', help=f"Create a new tar file in {dest}.")
|
||||
parser.add_argument('--upload', '-u', action='store_true', help="Upload the revised nightly dir to {samba_host}.")
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
@@ -13,9 +13,9 @@ sys.path = ['packaging'] + sys.path
|
||||
from pkglib import *
|
||||
|
||||
MAKE_GEN_CMDS = [
|
||||
'make -f prepare-source.mak conf'.split(),
|
||||
'./config.status'.split(),
|
||||
'make gen'.split(),
|
||||
'./prepare-source'.split(),
|
||||
'cd build && if test -f config.status ; then ./config.status ; else ../configure ; fi',
|
||||
'make -C build gen'.split(),
|
||||
]
|
||||
TMP_DIR = "patches.gen"
|
||||
|
||||
@@ -33,6 +33,9 @@ def main():
|
||||
|
||||
master_commit = latest_git_hash(args.base_branch)
|
||||
|
||||
if cmd_txt_chk(['packaging/prep-auto-dir']).out == '':
|
||||
die('You must setup an auto-build-save dir to use this script.')
|
||||
|
||||
if args.gen:
|
||||
if os.path.lexists(TMP_DIR):
|
||||
die(f'"{TMP_DIR}" must not exist in the current directory.')
|
||||
@@ -42,7 +45,7 @@ def main():
|
||||
cmd_chk(cmd)
|
||||
cmd_chk(['rsync', '-a', *gen_files, f'{TMP_DIR}/master/'])
|
||||
|
||||
last_touch = time.time()
|
||||
last_touch = int(time.time())
|
||||
|
||||
# Start by finding all patches so that we can load all possible parents.
|
||||
patches = sorted(list(get_patch_branches(args.base_branch)))
|
||||
@@ -91,9 +94,10 @@ def main():
|
||||
if args.gen:
|
||||
shutil.rmtree(TMP_DIR)
|
||||
|
||||
while last_touch >= time.time():
|
||||
while last_touch >= int(time.time()):
|
||||
time.sleep(1)
|
||||
cmd_chk(['git', 'checkout', starting_branch])
|
||||
cmd_chk(['packaging/prep-auto-dir'], discard='output')
|
||||
|
||||
|
||||
def update_patch(patch):
|
||||
@@ -113,31 +117,39 @@ def update_patch(patch):
|
||||
|
||||
print(f"======== {patch} ========")
|
||||
|
||||
while args.gen and last_touch >= time.time():
|
||||
while args.gen and last_touch >= int(time.time()):
|
||||
time.sleep(1)
|
||||
s = cmd_run(f"git checkout patch/{args.base_branch}/{patch}".split())
|
||||
|
||||
branch = f"patch/{args.base_branch}/{patch}"
|
||||
s = cmd_run(['git', 'checkout', branch])
|
||||
if s.returncode != 0:
|
||||
return 0
|
||||
|
||||
s = cmd_run(['git', 'merge', based_on])
|
||||
ok = s.returncode == 0
|
||||
if not ok or args.shell:
|
||||
m = re.search(r'([^/]+)$', parent)
|
||||
parent_dir = m[1]
|
||||
if not ok:
|
||||
print(f'"git merge {based_on}" incomplete -- please fix.')
|
||||
os.environ['PS1'] = f"[{parent_dir}] {patch}: "
|
||||
while True:
|
||||
s = cmd_run([os.environ.get('SHELL', '/bin/sh')])
|
||||
if s.returncode != 0:
|
||||
ans = input("Abort? [n/y] ")
|
||||
if re.match(r'^y', ans, flags=re.I):
|
||||
return 0
|
||||
continue
|
||||
cur_branch, is_clean, status_txt = check_git_status(0)
|
||||
if is_clean:
|
||||
break
|
||||
print(status_txt, end='')
|
||||
skip_shell = False
|
||||
if not ok or args.cmd or args.make or args.shell:
|
||||
cmd_chk(['packaging/prep-auto-dir'], discard='output')
|
||||
if not ok:
|
||||
print(f'"git merge {based_on}" incomplete -- please fix.')
|
||||
if not run_a_shell(parent, patch):
|
||||
return 0
|
||||
if not args.make and not args.cmd:
|
||||
skip_shell = True
|
||||
if args.make:
|
||||
if cmd_run(['packaging/smart-make']).returncode != 0:
|
||||
if not run_a_shell(parent, patch):
|
||||
return 0
|
||||
if not args.cmd:
|
||||
skip_shell = True
|
||||
if args.cmd:
|
||||
if cmd_run(args.cmd).returncode != 0:
|
||||
if not run_a_shell(parent, patch):
|
||||
return 0
|
||||
skip_shell = True
|
||||
if args.shell and not skip_shell:
|
||||
if not run_a_shell(parent, patch):
|
||||
return 0
|
||||
|
||||
with open(f"{args.patches_dir}/{patch}.diff", 'w', encoding='utf-8') as fh:
|
||||
fh.write(description[patch])
|
||||
@@ -150,7 +162,7 @@ def update_patch(patch):
|
||||
cmd_chk(['rsync', '-a', *gen_files, f"{TMP_DIR}/{patch}/"])
|
||||
else:
|
||||
gen_files = [ ]
|
||||
last_touch = time.time()
|
||||
last_touch = int(time.time())
|
||||
|
||||
proc = cmd_pipe(['git', 'diff', based_on])
|
||||
skipping = False
|
||||
@@ -185,16 +197,38 @@ def update_patch(patch):
|
||||
line = plus_re.sub(r'+++ b/\1', line)
|
||||
fh.write(line)
|
||||
proc.communicate()
|
||||
for fn in gen_files:
|
||||
os.unlink(fn)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
def run_a_shell(parent, patch):
|
||||
m = re.search(r'([^/]+)$', parent)
|
||||
parent_dir = m[1]
|
||||
os.environ['PS1'] = f"[{parent_dir}] {patch}: "
|
||||
|
||||
while True:
|
||||
s = cmd_run([os.environ.get('SHELL', '/bin/sh')])
|
||||
if s.returncode != 0:
|
||||
ans = input("Abort? [n/y] ")
|
||||
if re.match(r'^y', ans, flags=re.I):
|
||||
return False
|
||||
continue
|
||||
cur_branch, is_clean, status_txt = check_git_status(0)
|
||||
if is_clean:
|
||||
break
|
||||
print(status_txt, end='')
|
||||
|
||||
cmd_run('rm -f build/*.o build/*/*.o')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Turn a git branch back into a diff files in the patches dir.", add_help=False)
|
||||
parser.add_argument('--branch', '-b', dest='base_branch', metavar='BASE_BRANCH', default='master', help="The branch the patch is based on. Default: master.")
|
||||
parser.add_argument('--skip-check', action='store_true', help="Skip the check that ensures starting with a clean branch.")
|
||||
parser.add_argument('--make', '-m', action='store_true', help="Run the smart-make script in every patch branch.")
|
||||
parser.add_argument('--cmd', '-c', help="Run a command in every patch branch.")
|
||||
parser.add_argument('--shell', '-s', action='store_true', help="Launch a shell for every patch/BASE/* branch updated, not just when a conflict occurs.")
|
||||
parser.add_argument('--gen', metavar='DIR', nargs='?', const='', help='Include generated files. Optional DIR value overrides the default of using the "patches" dir.')
|
||||
parser.add_argument('--patches-dir', '-p', metavar='DIR', default='patches', help="Override the location of the rsync-patches dir. Default: patches.")
|
||||
@@ -207,4 +241,4 @@ if __name__ == '__main__':
|
||||
args.patches_dir = args.gen
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
# vim: sw=4 et ft=python
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import os, sys, re, subprocess
|
||||
import os, sys, re, subprocess, argparse
|
||||
|
||||
# This python3 library provides a few helpful routines that are
|
||||
# used by the latest packaging scripts.
|
||||
@@ -23,27 +23,32 @@ def set_default_encoding(enc):
|
||||
|
||||
|
||||
# Set shell=True if the cmd is a string; sets a default encoding unless raw=True was specified.
|
||||
def _tweak_opts(cmd, opts, **maybe_set):
|
||||
# This sets any maybe_set value that isn't already set AND creates a copy of opts for us.
|
||||
opts = {**maybe_set, **opts}
|
||||
def _tweak_opts(cmd, opts, **maybe_set_args):
|
||||
def _maybe_set(o, **msa): # Only set a value if the user didn't already set it.
|
||||
for var, val in msa.items():
|
||||
if var not in o:
|
||||
o[var] = val
|
||||
|
||||
opts = opts.copy()
|
||||
_maybe_set(opts, **maybe_set_args)
|
||||
|
||||
if type(cmd) == str:
|
||||
opts = {'shell': True, **opts}
|
||||
_maybe_set(opts, shell=True)
|
||||
|
||||
want_raw = opts.pop('raw', False)
|
||||
if default_encoding and not want_raw:
|
||||
opts = {'encoding': default_encoding, **opts}
|
||||
_maybe_set(opts, encoding=default_encoding)
|
||||
|
||||
capture = opts.pop('capture', None)
|
||||
if capture:
|
||||
if capture == 'stdout':
|
||||
opts = {'stdout': subprocess.PIPE, **opts}
|
||||
_maybe_set(opts, stdout=subprocess.PIPE)
|
||||
elif capture == 'stderr':
|
||||
opts = {'stderr': subprocess.PIPE, **opts}
|
||||
_maybe_set(opts, stderr=subprocess.PIPE)
|
||||
elif capture == 'output':
|
||||
opts = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, **opts}
|
||||
_maybe_set(opts, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
elif capture == 'combined':
|
||||
opts = {'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT, **opts}
|
||||
_maybe_set(opts, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
|
||||
discard = opts.pop('discard', None)
|
||||
if discard:
|
||||
@@ -66,30 +71,26 @@ def cmd_chk(cmd, **opts):
|
||||
return subprocess.run(cmd, **_tweak_opts(cmd, opts, check=True))
|
||||
|
||||
|
||||
# Capture stdout in a string and return the (output, return_code) tuple.
|
||||
# Use capture='combined' opt to get both stdout and stderr together.
|
||||
def cmd_txt_status(cmd, **opts):
|
||||
# Capture stdout in a string and return an object with out, err, and rc (return code).
|
||||
# It defaults to capture='stdout' (so err is empty) but can be overridden using
|
||||
# capture='combined' or capture='output' (the latter populates the err value).
|
||||
def cmd_txt(cmd, **opts):
|
||||
input = opts.pop('input', None)
|
||||
if input is not None:
|
||||
opts['stdin'] = subprocess.PIPE
|
||||
proc = subprocess.Popen(cmd, **_tweak_opts(cmd, opts, capture='stdout'))
|
||||
out = proc.communicate(input=input)[0]
|
||||
return (out, proc.returncode)
|
||||
out, err = proc.communicate(input=input)
|
||||
return argparse.Namespace(out=out, err=err, rc=proc.returncode)
|
||||
|
||||
|
||||
# Like cmd_txt_status() but just return the output.
|
||||
def cmd_txt(cmd, **opts):
|
||||
return cmd_txt_status(cmd, **opts)[0]
|
||||
|
||||
|
||||
# Capture stdout in a string and return the output if the command has a 0 return code.
|
||||
# Otherwise it throws an exception that indicates the return code and the output.
|
||||
# Just like calling cmd_txt() except that it raises an error if the command has a non-0 return code.
|
||||
# The raised error includes the cmd, the return code, and the captured output.
|
||||
def cmd_txt_chk(cmd, **opts):
|
||||
out, rc = cmd_txt_status(cmd, **opts)
|
||||
if rc != 0:
|
||||
cmd_err = f'Command "{cmd}" returned non-zero exit status "{rc}" and output:\n{out}'
|
||||
ct = cmd_txt(cmd, **opts)
|
||||
if ct.rc != 0:
|
||||
cmd_err = f'Command "{cmd}" returned non-0 exit status "{ct.rc}" and output:\n{ct.out}{ct.err}'
|
||||
raise Exception(cmd_err)
|
||||
return out
|
||||
return ct
|
||||
|
||||
|
||||
# Starts a piped-output command of stdout (by default) and leaves it up to you to read
|
||||
@@ -102,7 +103,7 @@ def cmd_pipe(cmd, **opts):
|
||||
# arg fatal_unless_clean can be used to make that non-fatal. Returns a
|
||||
# tuple of the current branch, the is_clean flag, and the status text.
|
||||
def check_git_status(fatal_unless_clean=True, subdir='.'):
|
||||
status_txt = cmd_txt_chk(f"cd '{subdir}' && git status")
|
||||
status_txt = cmd_txt_chk(f"cd '{subdir}' && git status").out
|
||||
is_clean = re.search(r'\nnothing to commit.+working (directory|tree) clean', status_txt) != None
|
||||
|
||||
if not is_clean and fatal_unless_clean:
|
||||
@@ -149,7 +150,7 @@ def check_git_state(master_branch, fatal_unless_clean=True, check_extra_dir=None
|
||||
|
||||
# Return the git hash of the most recent commit.
|
||||
def latest_git_hash(branch):
|
||||
out = cmd_txt_chk(['git', 'log', '-1', '--no-color', branch])
|
||||
out = cmd_txt_chk(['git', 'log', '-1', '--no-color', branch]).out
|
||||
m = re.search(r'^commit (\S+)', out, flags=re.M)
|
||||
if not m:
|
||||
die(f"Unable to determine commit hash for master branch: {branch}")
|
||||
@@ -175,51 +176,56 @@ def mandate_gensend_hook():
|
||||
print('Creating hook file:', hook)
|
||||
cmd_chk(['./rsync', '-a', 'packaging/pre-push', hook])
|
||||
else:
|
||||
out, rc = cmd_txt_status(['fgrep', 'make gensend', hook], discard='output')
|
||||
if rc:
|
||||
ct = cmd_txt(['fgrep', 'make gensend', hook], discard='output')
|
||||
if ct.rc:
|
||||
die('Please add a "make gensend" into your', hook, 'script.')
|
||||
|
||||
|
||||
# Snag the GENFILES values out of the Makefile.in file and return them as a list.
|
||||
def get_gen_files():
|
||||
def get_gen_files(want_dir_plus_list=False):
|
||||
cont_re = re.compile(r'\\\n')
|
||||
|
||||
extras = [ ]
|
||||
gen_files = [ ]
|
||||
|
||||
auto_dir = os.path.join('auto-build-save', cmd_txt('git rev-parse --abbrev-ref HEAD').out.strip().replace('/', '%'))
|
||||
|
||||
with open('Makefile.in', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
if not extras:
|
||||
if not gen_files:
|
||||
chk = re.sub(r'^GENFILES=', '', line)
|
||||
if line == chk:
|
||||
continue
|
||||
line = chk
|
||||
m = re.search(r'\\$', line)
|
||||
line = re.sub(r'^\s+|\s*\\\n?$|\s+$', '', line)
|
||||
extras += line.split()
|
||||
gen_files += line.split()
|
||||
if not m:
|
||||
break
|
||||
|
||||
return extras
|
||||
if want_dir_plus_list:
|
||||
return (auto_dir, gen_files)
|
||||
|
||||
return [ os.path.join(auto_dir, fn) for fn in gen_files ]
|
||||
|
||||
|
||||
def get_configure_version():
|
||||
with open('configure.ac', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
m = re.match(r'^AC_INIT\(\[rsync\],\s*\[(\d.+?)\]', line)
|
||||
if m:
|
||||
return m[1]
|
||||
die("Unable to find AC_INIT with version in configure.ac")
|
||||
def get_rsync_version():
|
||||
with open('version.h', 'r', encoding='utf-8') as fh:
|
||||
txt = fh.read()
|
||||
m = re.match(r'^#define\s+RSYNC_VERSION\s+"(\d.+?)"', txt)
|
||||
if m:
|
||||
return m[1]
|
||||
die("Unable to find RSYNC_VERSION define in version.h")
|
||||
|
||||
|
||||
def get_OLDNEWS_version_info():
|
||||
rel_re = re.compile(r'^\| \d{2} \w{3} \d{4}\s+\|\s+(?P<ver>\d+\.\d+\.\d+)\s+\|\s+(?P<pdate>\d{2} \w{3} \d{4}\s+)?\|\s+(?P<pver>\d+)\s+\|')
|
||||
def get_NEWS_version_info():
|
||||
rel_re = re.compile(r'^\| \S{2} \w{3} \d{4}\s+\|\s+(?P<ver>\d+\.\d+\.\d+)\s+\|\s+(?P<pdate>\d{2} \w{3} \d{4})?\s+\|\s+(?P<pver>\d+)\s+\|')
|
||||
last_version = last_protocol_version = None
|
||||
pdate = { }
|
||||
|
||||
with open('OLDNEWS.md', 'r', encoding='utf-8') as fh:
|
||||
with open('NEWS.md', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
if not last_version:
|
||||
m = re.search(r'(\d+\.\d+\.\d+)', line)
|
||||
if not last_version: # Find the first non-dev|pre version with a release date.
|
||||
m = re.search(r'rsync (\d+\.\d+\.\d+) .*\d\d\d\d', line)
|
||||
if m:
|
||||
last_version = m[1]
|
||||
m = rel_re.match(line)
|
||||
@@ -228,12 +234,11 @@ def get_OLDNEWS_version_info():
|
||||
pdate[m['ver']] = m['pdate']
|
||||
if m['ver'] == last_version:
|
||||
last_protocol_version = m['pver']
|
||||
break
|
||||
|
||||
if not last_protocol_version:
|
||||
die(f"Unable to determine protocol_version for {last_version}.")
|
||||
|
||||
return last_version, last_protocol_version
|
||||
return last_version, last_protocol_version, pdate
|
||||
|
||||
|
||||
def get_protocol_versions():
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash -e
|
||||
|
||||
cat >/dev/null # Just discard stdin data
|
||||
make gensend
|
||||
|
||||
if [[ -f /proc/$PPID/cmdline ]]; then
|
||||
while read -d $'\0' arg ; do
|
||||
if [[ "$arg" == '--tags' ]] ; then
|
||||
exit 0
|
||||
fi
|
||||
done </proc/$PPID/cmdline
|
||||
fi
|
||||
|
||||
branch=`git rev-parse --abbrev-ref HEAD`
|
||||
if [[ "$branch" = master && "$*" == *github* ]]; then
|
||||
make gensend
|
||||
fi
|
||||
|
||||
43
packaging/prep-auto-dir
Executable file
43
packaging/prep-auto-dir
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# This script will setup the build dir based on the current git branch and the
|
||||
# directory auto-build-save/$BRANCH. We don't use a symlink for the build dir
|
||||
# because we want to maximize the ccache reuse, so all builds must happen in
|
||||
# the same real dir. When a dir is moved out of auto-build-save/$BRANCH to the
|
||||
# build dir, it is replaced with a symlink so that it can still be found under
|
||||
# that dir. The build dir also gets a .branch -> $BRANCH symlink so that we
|
||||
# can figure out the current build dir's branch.
|
||||
|
||||
# To get started, just clone the rsync git repo and create the auto-build-save
|
||||
# dir. If you have an existing git checkout and it is not in a pristine state,
|
||||
# run "make distclean" before creating the auto-build-save dir.
|
||||
|
||||
auto_top='auto-build-save'
|
||||
if test -d $auto_top && test -d .git; then
|
||||
desired_branch=`git rev-parse --abbrev-ref HEAD | tr / %`
|
||||
if test "$desired_branch" = HEAD; then
|
||||
echo "ERROR: switch to the right build dir manually when in detached HEAD mode." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
auto_dir="$auto_top/$desired_branch"
|
||||
if test -d build; then
|
||||
cur_branch=`readlink build/.branch`
|
||||
else
|
||||
cur_branch='/'
|
||||
fi
|
||||
if test "$desired_branch" != "$cur_branch"; then
|
||||
if test "$cur_branch" != /; then
|
||||
rm -f "$auto_top/$cur_branch"
|
||||
mv build "$auto_top/$cur_branch"
|
||||
fi
|
||||
test -d "$auto_dir" || mkdir "$auto_dir"
|
||||
test -h "$auto_dir/.branch" || ln -s "$desired_branch" "$auto_dir/.branch"
|
||||
mv "$auto_dir" build
|
||||
ln -s ../build "$auto_dir"
|
||||
fi
|
||||
if test ! -h Makefile; then
|
||||
rm -f Makefile
|
||||
ln -s packaging/auto-Makefile Makefile
|
||||
fi
|
||||
echo $desired_branch
|
||||
fi
|
||||
@@ -13,10 +13,14 @@ sys.path = ['packaging'] + sys.path
|
||||
|
||||
from pkglib import *
|
||||
|
||||
os.environ['LESS'] = 'mqeiXR'; # Make sure that -F is turned off and -R is turned on.
|
||||
dest = os.environ['HOME'] + '/samba-rsync-ftp'
|
||||
ORIGINAL_PATH = os.environ['PATH']
|
||||
|
||||
def main():
|
||||
if not os.path.isfile('packaging/release-rsync'):
|
||||
die('You must run this script from the top of your rsync checkout.')
|
||||
|
||||
now = datetime.now()
|
||||
cl_today = now.strftime('* %a %b %d %Y')
|
||||
year = now.strftime('%Y')
|
||||
@@ -29,7 +33,11 @@ def main():
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
gen_files = get_gen_files()
|
||||
if cmd_txt_chk(['packaging/prep-auto-dir']).out == '':
|
||||
die('You must setup an auto-build-save dir to use this script.');
|
||||
|
||||
auto_dir, gen_files = get_gen_files(True)
|
||||
gen_pathnames = [ os.path.join(auto_dir, fn) for fn in gen_files ]
|
||||
|
||||
dash_line = '=' * 74
|
||||
|
||||
@@ -39,6 +47,17 @@ def main():
|
||||
{dash_line}
|
||||
""")
|
||||
|
||||
with open('build/rsync.1') as fh:
|
||||
for line in fh:
|
||||
if line.startswith(r'.\" prefix='):
|
||||
doc_prefix = line.split('=')[1].strip()
|
||||
if doc_prefix != '/usr':
|
||||
warn(f"*** The documentation was built with prefix {doc_prefix} instead of /usr ***")
|
||||
die("*** Read the md2man script for a way to override this. ***")
|
||||
break
|
||||
if line.startswith('.P'):
|
||||
die("Failed to find the prefix comment at the start of the rsync.1 manpage.")
|
||||
|
||||
if not os.path.isdir(dest):
|
||||
die(dest, "dest does not exist")
|
||||
if not os.path.isdir('.git'):
|
||||
@@ -52,13 +71,13 @@ def main():
|
||||
|
||||
check_git_state(args.master_branch, True, 'patches')
|
||||
|
||||
confversion = get_configure_version()
|
||||
curversion = get_rsync_version()
|
||||
|
||||
# All version values are strings!
|
||||
lastversion, last_protocol_version = get_OLDNEWS_version_info()
|
||||
lastversion, last_protocol_version, pdate = get_NEWS_version_info()
|
||||
protocol_version, subprotocol_version = get_protocol_versions()
|
||||
|
||||
version = confversion
|
||||
version = curversion
|
||||
m = re.search(r'pre(\d+)', version)
|
||||
if m:
|
||||
version = re.sub(r'pre\d+', 'pre' + str(int(m[1]) + 1), version)
|
||||
@@ -79,7 +98,7 @@ def main():
|
||||
if os.path.lexists(rsync_ver):
|
||||
die(f'"{rsync_ver}" must not exist in the current directory.')
|
||||
|
||||
out = cmd_txt_chk(['git', 'tag', '-l', v_ver])
|
||||
out = cmd_txt_chk(['git', 'tag', '-l', v_ver]).out
|
||||
if out != '':
|
||||
print(f"Tag {v_ver} already exists.")
|
||||
ans = input("\nDelete tag or quit? [Q/del] ")
|
||||
@@ -88,8 +107,8 @@ def main():
|
||||
cmd_chk(['git', 'tag', '-d', v_ver])
|
||||
|
||||
version = re.sub(r'[-.]*pre[-.]*', 'pre', version)
|
||||
if 'pre' in version and not confversion.endswith('dev'):
|
||||
lastversion = confversion
|
||||
if 'pre' in version and not curversion.endswith('dev'):
|
||||
lastversion = curversion
|
||||
|
||||
ans = input(f"Enter the previous version to produce a patch against: [{lastversion}] ")
|
||||
if ans != '':
|
||||
@@ -111,11 +130,8 @@ def main():
|
||||
release += '.' + pre
|
||||
|
||||
finalversion = re.sub(r'pre\d+', '', version)
|
||||
if protocol_version == last_protocol_version:
|
||||
proto_changed = 'unchanged'
|
||||
proto_change_date = ' ' * 11
|
||||
else:
|
||||
proto_changed = 'changed'
|
||||
proto_changed = protocol_version != last_protocol_version
|
||||
if proto_changed:
|
||||
if finalversion in pdate:
|
||||
proto_change_date = pdate[finalversion]
|
||||
else:
|
||||
@@ -124,6 +140,8 @@ def main():
|
||||
if re.match(r'^\d\d \w\w\w \d\d\d\d$', ans):
|
||||
break
|
||||
proto_change_date = ans
|
||||
else:
|
||||
proto_change_date = ' ' * 11
|
||||
|
||||
if 'pre' in lastversion:
|
||||
if not pre:
|
||||
@@ -152,8 +170,8 @@ release is "{release}"
|
||||
|
||||
About to:
|
||||
- tweak SUBPROTOCOL_VERSION in rsync.h, if needed
|
||||
- tweak the version in configure.ac and the spec files
|
||||
- tweak NEWS.md and OLDNEWS.md to ensure header values are correct
|
||||
- tweak the version in version.h and the spec files
|
||||
- tweak NEWS.md to ensure header values are correct
|
||||
- generate configure.sh, config.h.in, and proto.h
|
||||
- page through the differences
|
||||
""")
|
||||
@@ -167,16 +185,15 @@ About to:
|
||||
'%define srcdir': srcdir,
|
||||
}
|
||||
|
||||
tweak_files = 'configure.ac rsync.h NEWS.md OLDNEWS.md'.split()
|
||||
tweak_files = 'version.h rsync.h NEWS.md'.split()
|
||||
tweak_files += glob.glob('packaging/*.spec')
|
||||
tweak_files += glob.glob('packaging/*/*.spec')
|
||||
|
||||
for fn in tweak_files:
|
||||
with open(fn, 'r', encoding='utf-8') as fh:
|
||||
old_txt = txt = fh.read()
|
||||
if 'configure' in fn:
|
||||
x_re = re.compile(r'^(AC_INIT\(\[rsync\],\s*\[)\d.+?(\])', re.M)
|
||||
txt = replace_or_die(x_re, r'\g<1>%s\2' % version, txt, f"Unable to update AC_INIT with version in {fn}")
|
||||
if fn == 'version.h':
|
||||
txt = f'#define RSYNC_VERSION "{version}"\n'
|
||||
elif '.spec' in fn:
|
||||
for var, val in specvars.items():
|
||||
x_re = re.compile(r'^%s .*' % re.escape(var), re.M)
|
||||
@@ -185,19 +202,20 @@ About to:
|
||||
txt = replace_or_die(x_re, r'%s \1' % cl_today, txt, f"Unable to update ChangeLog header in {fn}")
|
||||
elif fn == 'rsync.h':
|
||||
x_re = re.compile('(#define\s+SUBPROTOCOL_VERSION)\s+(\d+)')
|
||||
repl = lambda m: m[1] + ' ' + '0' if not pre or proto_changed != 'changed' else 1 if m[2] == '0' else m[2]
|
||||
repl = lambda m: m[1] + ' ' + ('0' if not pre or not proto_changed else '1' if m[2] == '0' else m[2])
|
||||
txt = replace_or_die(x_re, repl, txt, f"Unable to find SUBPROTOCOL_VERSION define in {fn}")
|
||||
elif fn == 'NEWS.md':
|
||||
x_re = re.compile(
|
||||
r'^(# NEWS for rsync %s )(\(UNRELEASED\))\s*(\n\nProtocol: )(\d+) (\([^)]+\))\n' % re.escape(finalversion),
|
||||
re.I)
|
||||
repl = lambda m: m[1] + (m[2] if pre else f"({today})") + m[3] + f"{protocol_version} ({proto_changed})\n"
|
||||
msg = (f"The first 3 lines of {fn} are not in the right format. They must be:\n"
|
||||
+ f"# NEWS for rsync {finalversion} (UNRELEASED)\n\n"
|
||||
+ f"Protocol: {protocol_version} ({proto_changed})")
|
||||
txt = replace_or_die(x_re, repl, txt, msg)
|
||||
elif fn == 'OLDNEWS.md':
|
||||
efv = re.escape(finalversion)
|
||||
x_re = re.compile(r'^<.+>\s+# NEWS for rsync %s \(UNRELEASED\)\s+## Changes in this version:\n' % efv
|
||||
+ r'(\n### PROTOCOL NUMBER:\s+- The protocol number was changed to \d+\.\n)?')
|
||||
rel_day = 'UNRELEASED' if pre else today
|
||||
repl = (f'<a name="{finalversion}"></a>\n\n# NEWS for rsync {finalversion} ({rel_day})\n\n'
|
||||
+ '## Changes in this version:\n')
|
||||
if proto_changed:
|
||||
repl += f'\n### PROTOCOL NUMBER:\n\n - The protocol number was changed to {protocol_version}.\n'
|
||||
good_top = re.sub(r'\(.*?\)', '(UNRELEASED)', repl, 1)
|
||||
msg = f"The top lines of {fn} are not in the right format. It should be:\n" + good_top
|
||||
txt = replace_or_die(x_re, repl, txt, msg)
|
||||
x_re = re.compile(r'^(\| )(\S{2} \S{3} \d{4})(\s+\|\s+%s\s+\| ).{11}(\s+\| )\S{2}(\s+\|+)$' % efv, re.M)
|
||||
repl = lambda m: m[1] + (m[2] if pre else ztoday) + m[3] + proto_change_date + m[4] + protocol_version + m[5]
|
||||
txt = replace_or_die(x_re, repl, txt, f'Unable to find "| ?? ??? {year} | {finalversion} | ... |" line in {fn}')
|
||||
@@ -217,11 +235,10 @@ About to:
|
||||
srctar_name = f"{rsync_ver}.tar.gz"
|
||||
pattar_name = f"rsync-patches-{version}.tar.gz"
|
||||
diff_name = f"{rsync_lastver}-{version}.diffs.gz"
|
||||
srctar_file = f"{dest}/{srcdir}/{srctar_name}"
|
||||
pattar_file = f"{dest}/{srcdir}/{pattar_name}"
|
||||
diff_file = f"{dest}/{srcdiffdir}/{diff_name}"
|
||||
news_file = f"{dest}/{srcdir}/{rsync_ver}-NEWS.md"
|
||||
lasttar_file = f"{dest}/{lastsrcdir}/{rsync_lastver}.tar.gz"
|
||||
srctar_file = os.path.join(dest, srcdir, srctar_name)
|
||||
pattar_file = os.path.join(dest, srcdir, pattar_name)
|
||||
diff_file = os.path.join(dest, srcdiffdir, diff_name)
|
||||
lasttar_file = os.path.join(dest, lastsrcdir, rsync_lastver + '.tar.gz')
|
||||
|
||||
print(f"""\
|
||||
{dash_line}
|
||||
@@ -230,8 +247,8 @@ About to:
|
||||
- git commit all changes
|
||||
- generate the manpages
|
||||
- merge the {args.master_branch} branch into the patch/{args.master_branch}/* branches
|
||||
- update the files in the "patches" dir and OPTIONALLY
|
||||
(if you type 'y') to launch a shell for each patch
|
||||
- update the files in the "patches" dir and OPTIONALLY (if you type 'y') to
|
||||
run patch-update with the --make option (which opens a shell on error)
|
||||
""")
|
||||
ans = input("<Press Enter OR 'y' to continue> ")
|
||||
|
||||
@@ -239,8 +256,7 @@ About to:
|
||||
if s.returncode:
|
||||
die('Aborting')
|
||||
|
||||
cmd_chk('make reconfigure ; make gen')
|
||||
cmd_chk(['rsync', '-a', *gen_files, 'SaVeDiR/'])
|
||||
cmd_chk('make gen')
|
||||
|
||||
print(f'Creating any missing patch branches.')
|
||||
s = cmd_run(f'packaging/branch-from-patch --branch={args.master_branch} --add-missing')
|
||||
@@ -253,11 +269,8 @@ About to:
|
||||
die('Aborting')
|
||||
|
||||
if re.match(r'^y', ans, re.I):
|
||||
print(f'\nVisiting all "patch/{args.master_branch}/*" branches ...')
|
||||
cmd_run(f"packaging/patch-update --branch={args.master_branch} --skip-check --shell")
|
||||
|
||||
cmd_run("rm -f *.[o15] *.html")
|
||||
cmd_chk('rsync -a SaVeDiR/ .'.split())
|
||||
print(f'\nRunning smart-make on all "patch/{args.master_branch}/*" branches ...')
|
||||
cmd_run(f"packaging/patch-update --branch={args.master_branch} --skip-check --make")
|
||||
|
||||
if os.path.isdir('patches/.git'):
|
||||
s = cmd_run(f"cd patches && git commit -a -m 'The patches for {version}.'")
|
||||
@@ -273,7 +286,7 @@ About to:
|
||||
- create release tar, "{srctar_name}"
|
||||
- generate {rsync_ver}/patches/* files
|
||||
- create patches tar, "{pattar_name}"
|
||||
- update top-level README.md, *NEWS.md, TODO, and ChangeLog
|
||||
- update top-level README.md, NEWS.md, TODO, and ChangeLog
|
||||
- update top-level rsync*.html manpages
|
||||
- gpg-sign the release files
|
||||
- update hard-linked top-level release files{skipping}
|
||||
@@ -283,13 +296,13 @@ About to:
|
||||
# TODO: is there a better way to ensure that our passphrase is in the agent?
|
||||
cmd_run("touch TeMp; gpg --sign TeMp; rm TeMp*")
|
||||
|
||||
out = cmd_txt(f"git tag -s -m 'Version {version}.' {v_ver}", capture='combined')
|
||||
out = cmd_txt(f"git tag -s -m 'Version {version}.' {v_ver}", capture='combined').out
|
||||
print(out, end='')
|
||||
if 'bad passphrase' in out or 'failed' in out:
|
||||
die('Aborting')
|
||||
|
||||
if os.path.isdir('patches/.git'):
|
||||
out = cmd_txt(f"cd patches && git tag -s -m 'Version {version}.' {v_ver}", capture='combined')
|
||||
out = cmd_txt(f"cd patches && git tag -s -m 'Version {version}.' {v_ver}", capture='combined').out
|
||||
print(out, end='')
|
||||
if 'bad passphrase' in out or 'failed' in out:
|
||||
die('Aborting')
|
||||
@@ -297,12 +310,12 @@ About to:
|
||||
os.environ['PATH'] = ORIGINAL_PATH
|
||||
|
||||
# Extract the generated files from the old tar.
|
||||
tweaked_gen_files = [ f"{rsync_lastver}/{x}" for x in gen_files ]
|
||||
tweaked_gen_files = [ os.path.join(rsync_lastver, fn) for fn in gen_files ]
|
||||
cmd_run(['tar', 'xzf', lasttar_file, *tweaked_gen_files])
|
||||
os.rename(rsync_lastver, 'a')
|
||||
|
||||
print(f"Creating {diff_file} ...")
|
||||
cmd_chk(['rsync', '-a', *gen_files, 'b/'])
|
||||
cmd_chk(['rsync', '-a', *gen_pathnames, 'b/'])
|
||||
|
||||
sed_script = r's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:' # CAUTION: must not contain any single quotes!
|
||||
cmd_chk(f"(git diff v{lastversion} {v_ver} -- ':!.github'; diff -upN a b | sed -r '{sed_script}') | gzip -9 >{diff_file}")
|
||||
@@ -320,26 +333,15 @@ About to:
|
||||
os.mkdir(f"{rsync_ver}/patches", 0o755)
|
||||
cmd_chk(f"packaging/patch-update --skip-check --branch={args.master_branch} --gen={rsync_ver}/patches".split())
|
||||
|
||||
cmd_run("rm -f *.[o15] *.html")
|
||||
cmd_chk('rsync -a SaVeDiR/ .'.split())
|
||||
shutil.rmtree('SaVeDiR')
|
||||
cmd_chk('make gen'.split())
|
||||
|
||||
print(f"Creating {pattar_file} ...")
|
||||
cmd_chk(['fakeroot', 'tar', 'chzf', pattar_file, rsync_ver + '/patches'])
|
||||
shutil.rmtree(rsync_ver)
|
||||
|
||||
print(f"Updating the other files in {dest} ...")
|
||||
md_files = 'README.md NEWS.md OLDNEWS.md'.split()
|
||||
html_files = [ fn for fn in gen_files if fn.endswith('.html') ]
|
||||
md_files = 'README.md NEWS.md INSTALL.md'.split()
|
||||
html_files = [ fn for fn in gen_pathnames if fn.endswith('.html') ]
|
||||
cmd_chk(['rsync', '-a', *md_files, *html_files, dest])
|
||||
cmd_chk(["packaging/md2html"] + [ dest +'/'+ fn for fn in md_files ])
|
||||
|
||||
for topfn, verfn in (('NEWS.md', news_file), ('NEWS.html', news_file.replace('.md', '.html'))):
|
||||
topfn = dest + '/' + topfn
|
||||
if os.path.lexists(verfn):
|
||||
os.unlink(verfn)
|
||||
os.link(topfn, verfn)
|
||||
cmd_chk(["./md-convert"] + [ dest +'/'+ fn for fn in md_files ])
|
||||
|
||||
cmd_chk(f"git log --name-status | gzip -9 >{dest}/ChangeLog.gz")
|
||||
|
||||
@@ -352,14 +354,13 @@ About to:
|
||||
die("gpg signing failed")
|
||||
|
||||
if not pre:
|
||||
for find in f'{dest}/rsync-*.gz {dest}/rsync-*.asc {dest}/rsync-*-NEWS.md {dest}/src-previews/rsync-*diffs.gz*'.split():
|
||||
for find in f'{dest}/rsync-*.gz {dest}/rsync-*.asc {dest}/src-previews/rsync-*diffs.gz*'.split():
|
||||
for fn in glob.glob(find):
|
||||
os.unlink(fn)
|
||||
top_link = [
|
||||
srctar_file, f"{srctar_file}.asc",
|
||||
pattar_file, f"{pattar_file}.asc",
|
||||
diff_file, f"{diff_file}.asc",
|
||||
news_file,
|
||||
]
|
||||
for fn in top_link:
|
||||
os.link(fn, re.sub(r'/src(-\w+)?/', '/', fn))
|
||||
@@ -391,4 +392,4 @@ if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
# vim: sw=4 et ft=python
|
||||
|
||||
45
packaging/smart-make
Executable file
45
packaging/smart-make
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
export LANG=C
|
||||
|
||||
branch=`packaging/prep-auto-dir`
|
||||
if test x"$branch" = x; then
|
||||
srcdir=.
|
||||
else
|
||||
cd build
|
||||
srcdir=..
|
||||
fi
|
||||
|
||||
if test -f configure.sh; then
|
||||
cp -p configure.sh configure.sh.old
|
||||
else
|
||||
touch configure.sh.old
|
||||
fi
|
||||
|
||||
if test -f .fetch; then
|
||||
$srcdir/prepare-source fetch
|
||||
else
|
||||
$srcdir/prepare-source
|
||||
fi
|
||||
|
||||
if diff configure.sh configure.sh.old >/dev/null 2>&1; then
|
||||
echo "configure.sh is unchanged."
|
||||
rm configure.sh.old
|
||||
else
|
||||
echo "configure.sh has CHANGED."
|
||||
if test -f config.status; then
|
||||
./config.status --recheck
|
||||
else
|
||||
$srcdir/configure
|
||||
fi
|
||||
fi
|
||||
|
||||
./config.status
|
||||
|
||||
make all
|
||||
|
||||
if test x"$1" = x"check"; then
|
||||
make check
|
||||
fi
|
||||
@@ -2,6 +2,7 @@
|
||||
Description=fast remote file copy program daemon
|
||||
ConditionPathExists=/etc/rsyncd.conf
|
||||
After=network.target
|
||||
Documentation=man:rsync(1) man:rsyncd.conf(5)
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/rsync --daemon --no-detach
|
||||
@@ -15,14 +16,14 @@ RestartSec=1
|
||||
# This is generally used for public file distribution, [...]
|
||||
#
|
||||
# So let's assume some extra security is more than welcome here. We do full
|
||||
# system protection (which makes it read-only) and hide users' homes and
|
||||
# system protection (which makes /usr, /boot, & /etc read-only) and hide
|
||||
# devices. To override these defaults, it's best to do so in the drop-in
|
||||
# directory, often done via `systemctl edit rsync.service`. The file needs
|
||||
# just the bare minimum of the right [heading] and override values.
|
||||
# See systemd.unit(5) and search for "drop-in" for full details.
|
||||
|
||||
ProtectSystem=full
|
||||
ProtectHome=on
|
||||
#ProtectHome=on|off|read-only
|
||||
PrivateDevices=on
|
||||
NoNewPrivileges=on
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ StandardError=journal
|
||||
# This is generally used for public file distribution, [...]
|
||||
#
|
||||
# So let's assume some extra security is more than welcome here. We do full
|
||||
# system protection (which makes it read-only) and hide users' homes and
|
||||
# system protection (which makes /usr, /boot, & /etc read-only) and hide
|
||||
# devices. To override these defaults, it's best to do so in the drop-in
|
||||
# directory, often done via `systemctl edit rsync@.service`. The file needs
|
||||
# just the bare minimum of the right [heading] and override values.
|
||||
# See systemd.unit(5) and search for "drop-in" for full details.
|
||||
|
||||
ProtectSystem=full
|
||||
ProtectHome=on
|
||||
#ProtectHome=on|off|read-only
|
||||
PrivateDevices=on
|
||||
NoNewPrivileges=on
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# for vars that are defined but not used, and for inconsistent array
|
||||
# sizes. Run it from inside the main rsync directory.
|
||||
|
||||
import re, argparse, glob
|
||||
import os, sys, re, argparse, glob
|
||||
|
||||
VARS_RE = re.compile(r'^(?!(?:extern|enum)\s)([a-zA-Z]\S*\s+.*);', re.M)
|
||||
EXTERNS_RE = re.compile(r'^extern\s+(.*);', re.M)
|
||||
@@ -15,8 +15,15 @@ def main():
|
||||
add_syscall_c = set('t_stub.c t_unsafe.c tls.c trimslash.c'.split())
|
||||
add_util_c = set('t_stub.c t_unsafe.c'.split())
|
||||
|
||||
if not os.path.exists('syscall.c'):
|
||||
if os.path.exists('var-checker'):
|
||||
os.chdir('..')
|
||||
else:
|
||||
print("Couldn't find the source dir.")
|
||||
sys.exit(1)
|
||||
|
||||
syscall_c = slurp_file('syscall.c', True)
|
||||
util_c = slurp_file('util.c', True)
|
||||
util_c = slurp_file('util1.c', True)
|
||||
|
||||
for fn in sorted(glob.glob('*.c')):
|
||||
txt = slurp_file(fn)
|
||||
@@ -84,4 +91,4 @@ if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
# vim: sw=4 et ft=python
|
||||
|
||||
21
params.c
21
params.c
@@ -212,11 +212,6 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FLOG, "%s Memory re-allocation failure.", func);
|
||||
return( False );
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle a single character. */
|
||||
@@ -306,11 +301,6 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
|
||||
return( False );
|
||||
}
|
||||
}
|
||||
|
||||
switch( c )
|
||||
@@ -382,11 +372,6 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
|
||||
return( False );
|
||||
}
|
||||
}
|
||||
|
||||
switch( c )
|
||||
@@ -639,12 +624,6 @@ int pm_process( char *FileName,
|
||||
{ /* allocate one, then parse, */
|
||||
bSize = BUFR_INC; /* then free. */
|
||||
bufr = new_array( char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FLOG, "%s memory allocation failure.\n", func);
|
||||
fclose(InFile);
|
||||
return( False );
|
||||
}
|
||||
result = Parse( InFile, sfunc, pfunc );
|
||||
free( bufr );
|
||||
bufr = NULL;
|
||||
|
||||
@@ -11,6 +11,10 @@ extern __const __int32_t *__ctype_toupper;
|
||||
/*@=declundef@*/
|
||||
#endif
|
||||
|
||||
#ifdef __TANDEM
|
||||
# include <floss.h(floss_execvp,floss_read)>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# Specify one action or more than one to provide a fall-back:
|
||||
#
|
||||
# build build the config files [the default w/no arg]
|
||||
# fetch fetch the latest dev config files
|
||||
# fetchgen fetch all the latest dev generated files
|
||||
# fetch fetch the latest dev autoconfig files
|
||||
# fetchgen fetch all the latest dev generated files (including man pages)
|
||||
# fetchSRC fetch the latest dev source files [NON-GENERATED FILES]
|
||||
#
|
||||
# The script stops after the first successful action.
|
||||
@@ -16,6 +16,26 @@ if test x"$dir" = x; then
|
||||
dir=.
|
||||
fi
|
||||
|
||||
if test "$dir" = '.'; then
|
||||
branch=`packaging/prep-auto-dir` || exit 1
|
||||
if test x"$branch" != x; then
|
||||
cd build || exit 1
|
||||
dir=..
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$dir" != '.'; then
|
||||
for lnk in configure.ac m4; do
|
||||
if test ! -h $lnk; then
|
||||
rm -f $lnk # Just in case
|
||||
ln -s "$dir/$lnk" $lnk
|
||||
fi
|
||||
done
|
||||
for fn in configure.sh config.h.in aclocal.m4; do
|
||||
test ! -f $fn && test -f "$dir/$fn" && cp -p "$dir/$fn" $fn
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# = 0; then
|
||||
set -- build
|
||||
fi
|
||||
@@ -23,17 +43,18 @@ fi
|
||||
for action in "${@}"; do
|
||||
case "$action" in
|
||||
build|make)
|
||||
(cd $dir && make -f prepare-source.mak)
|
||||
make -f "$dir/prepare-source.mak"
|
||||
;;
|
||||
fetch)
|
||||
$dir/rsync-ssl -iip --no-motd rsync://download.samba.org/rsyncftp/generated-files/'[ca]*' $dir
|
||||
if ! perl --version >/dev/null 2>/dev/null; then
|
||||
$dir/rsync-ssl -iip --no-motd rsync://download.samba.org/rsyncftp/generated-files/'p*' .
|
||||
fetch|fetchgen)
|
||||
if test "$action" = fetchgen; then
|
||||
match='*'
|
||||
else
|
||||
match='[ca]*'
|
||||
fi
|
||||
;;
|
||||
fetchgen)
|
||||
$dir/rsync-ssl -iip --no-motd rsync://download.samba.org/rsyncftp/generated-files/'[ca]*' $dir
|
||||
$dir/rsync-ssl -iip --no-motd rsync://download.samba.org/rsyncftp/generated-files/'[^ca]*' .
|
||||
$dir/rsync-ssl -iipc --no-motd "rsync://download.samba.org/rsyncftp/generated-files/$match" ./
|
||||
test $? != 0 && continue
|
||||
sleep 1 # The following files need to be newer than aclocal.m4
|
||||
touch configure.sh config.h.in
|
||||
;;
|
||||
fetchSRC)
|
||||
./rsync-ssl -iipr --no-motd --exclude=/.git/ rsync://download.samba.org/ftp/pub/unpacked/rsync/ .
|
||||
@@ -41,6 +62,7 @@ for action in "${@}"; do
|
||||
*)
|
||||
echo "Unknown action: $action"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if test $? = 0; then
|
||||
exit
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
SHELL=/bin/sh
|
||||
|
||||
conf: configure.sh config.h.in
|
||||
.PHONY: conf
|
||||
|
||||
aclocal.m4: m4/*.m4
|
||||
aclocal -I m4
|
||||
|
||||
21
receiver.c
21
receiver.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -41,6 +41,7 @@ extern int preserve_hard_links;
|
||||
extern int preserve_perms;
|
||||
extern int write_devices;
|
||||
extern int preserve_xattrs;
|
||||
extern int do_fsync;
|
||||
extern int basis_dir_cnt;
|
||||
extern int make_backups;
|
||||
extern int cleanup_got_literal;
|
||||
@@ -394,6 +395,11 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
|
||||
sum_len = sum_end(file_sum1);
|
||||
|
||||
if (do_fsync && fd != -1 && fsync(fd) != 0) {
|
||||
rsyserr(FERROR, errno, "fsync failed on %s", full_fname(fname));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
if (mapbuf)
|
||||
unmap_file(mapbuf);
|
||||
|
||||
@@ -539,6 +545,9 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
if (delay_updates)
|
||||
delayed_bits = bitbag_create(cur_flist->used + 1);
|
||||
|
||||
if (whole_file < 0)
|
||||
whole_file = 0;
|
||||
|
||||
progress_init();
|
||||
|
||||
while (1) {
|
||||
@@ -826,6 +835,12 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
if (inplace || one_inplace) {
|
||||
fnametmp = one_inplace ? partialptr : fname;
|
||||
fd2 = do_open(fnametmp, O_WRONLY|O_CREAT, 0600);
|
||||
#ifdef linux
|
||||
if (fd2 == -1 && errno == EACCES) {
|
||||
/* Maybe the error was due to protected_regular setting? */
|
||||
fd2 = do_open(fname, O_WRONLY, 0600);
|
||||
}
|
||||
#endif
|
||||
if (fd2 == -1) {
|
||||
rsyserr(FERROR_XFER, errno, "open %s failed",
|
||||
full_fname(fnametmp));
|
||||
@@ -878,7 +893,7 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
do_unlink(partialptr);
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
}
|
||||
} else if (keep_partial && partialptr && !one_inplace) {
|
||||
} else if (keep_partial && partialptr && (!one_inplace || delay_updates)) {
|
||||
if (!handle_partial_dir(partialptr, PDIR_CREATE)) {
|
||||
rprintf(FERROR,
|
||||
"Unable to create partial-dir for %s -- discarding %s.\n",
|
||||
@@ -912,7 +927,7 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
break;
|
||||
case 0: {
|
||||
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
|
||||
if (msgtype == FERROR_XFER || INFO_GTE(NAME, 1)) {
|
||||
if (msgtype == FERROR_XFER || INFO_GTE(NAME, 1) || stdout_format_has_i) {
|
||||
char *errstr, *redostr, *keptstr;
|
||||
if (!(keep_partial && partialptr) && !inplace)
|
||||
keptstr = "discarded";
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
struct test {
|
||||
union file_extras extras[ARRAY_LEN];
|
||||
struct file_struct file;
|
||||
int64 test;
|
||||
};
|
||||
|
||||
#define ACTUAL_SIZE SIZEOF(struct test)
|
||||
#define EXPECTED_SIZE (SIZEOF(union file_extras) * ARRAY_LEN + SIZEOF(struct file_struct))
|
||||
#define EXPECTED_SIZE (SIZEOF(union file_extras) * ARRAY_LEN + SIZEOF(int64))
|
||||
|
||||
int main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
{
|
||||
|
||||
16
rsync-ssl
16
rsync-ssl
@@ -73,8 +73,16 @@ function rsync_ssl_helper {
|
||||
certopt=""
|
||||
gnutls_cert_opt=""
|
||||
else
|
||||
certopt="cert$optsep$RSYNC_SSL_CERT"
|
||||
gnutls_cert_opt="--x509keyfile=$RSYNC_SSL_CERT"
|
||||
certopt="-cert$optsep$RSYNC_SSL_CERT"
|
||||
gnutls_cert_opt="--x509certfile=$RSYNC_SSL_CERT"
|
||||
fi
|
||||
|
||||
if [[ -z "$RSYNC_SSL_KEY" ]]; then
|
||||
keyopt=""
|
||||
gnutls_key_opt=""
|
||||
else
|
||||
keyopt="-key$optsep$RSYNC_SSL_KEY"
|
||||
gnutls_key_opt="--x509keyfile=$RSYNC_SSL_KEY"
|
||||
fi
|
||||
|
||||
if [[ -z ${RSYNC_SSL_CA_CERT+x} ]]; then
|
||||
@@ -129,9 +137,9 @@ function rsync_ssl_helper {
|
||||
fi
|
||||
|
||||
if [[ $RSYNC_SSL_TYPE == openssl ]]; then
|
||||
exec $RSYNC_SSL_OPENSSL s_client $caopt $certopt -quiet -verify_quiet -servername $hostname -connect $hostname:$port
|
||||
exec $RSYNC_SSL_OPENSSL s_client $caopt $certopt $keyopt -quiet -verify_quiet -servername $hostname -verify_hostname $hostname -connect $hostname:$port
|
||||
elif [[ $RSYNC_SSL_TYPE == gnutls ]]; then
|
||||
exec $RSYNC_SSL_GNUTLS --logfile=/dev/null $gnutls_cert_opt $gnutls_opts $hostname:$port
|
||||
exec $RSYNC_SSL_GNUTLS --logfile=/dev/null $gnutls_cert_opt $gnutls_key_opt $gnutls_opts $hostname:$port
|
||||
else
|
||||
# devzero@web.de came up with this no-tmpfile calling syntax:
|
||||
exec $RSYNC_SSL_STUNNEL -fd 10 11<&0 <<EOF 10<&0 0<&11 11<&-
|
||||
|
||||
@@ -13,6 +13,13 @@ rsync-ssl [--type=SSL_TYPE] RSYNC_ARGS
|
||||
The rsync-ssl script helps you to run an rsync copy to/from an rsync daemon
|
||||
that requires ssl connections.
|
||||
|
||||
The script requires that you specify an rsync-daemon arg in the style of either
|
||||
`hostname::` (with 2 colons) or `rsync://hostname/`. The default port used for
|
||||
connecting is 874 (one higher than the normal 873) unless overridden in the
|
||||
environment. You can specify an overriding port via `--port` or by including
|
||||
it in the normal spot in the URL format, though both of those require your
|
||||
rsync version to be at least 3.2.0.
|
||||
|
||||
# OPTIONS
|
||||
|
||||
If the **first** arg is a `--type=SSL_TYPE` option, the script will only use
|
||||
@@ -23,7 +30,7 @@ option must specify one of `openssl` or `stunnel`. The equal sign is
|
||||
required for this particular option.
|
||||
|
||||
All the other options are passed through to the rsync command, so consult the
|
||||
**rsync** manpage for more information on how it works.
|
||||
**rsync**(1) manpage for more information on how it works.
|
||||
|
||||
# ENVIRONMENT VARIABLES
|
||||
|
||||
@@ -39,6 +46,8 @@ The ssl helper scripts are affected by the following environment variables:
|
||||
value to the helper script.)
|
||||
0. `RSYNC_SSL_CERT` If specified, the value is a filename that contains a
|
||||
certificate to use for the connection.
|
||||
0. `RSYNC_SSL_KEY` If specified, the value is a filename that contains a
|
||||
key for the provided certificate to use for the connection.
|
||||
0. `RSYNC_SSL_CA_CERT` If specified, the value is a filename that contains a
|
||||
certificate authority certificate that is used to validate the connection.
|
||||
0. `RSYNC_SSL_OPENSSL` Specifies the openssl executable to run when the
|
||||
@@ -53,9 +62,13 @@ The ssl helper scripts are affected by the following environment variables:
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
> rsync-ssl -aiv example.com::src/ dest
|
||||
> rsync-ssl -aiv example.com::mod/ dest
|
||||
|
||||
> rsync-ssl --type=openssl -aiv example.com::src/ dest
|
||||
> rsync-ssl --type=openssl -aiv example.com::mod/ dest
|
||||
|
||||
> rsync-ssl -aiv --port 9874 example.com::mod/ dest
|
||||
|
||||
> rsync-ssl -aiv rsync://example.com:9874/mod/ dest
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
@@ -76,7 +89,7 @@ exported RSYNC_SSL_TYPE environment variable to make its use the default.
|
||||
|
||||
# BUGS
|
||||
|
||||
Please report bugs! See the web site at <http://rsync.samba.org/>.
|
||||
Please report bugs! See the web site at <https://rsync.samba.org/>.
|
||||
|
||||
# VERSION
|
||||
|
||||
@@ -87,7 +100,7 @@ This man page is current for version @VERSION@ of rsync.
|
||||
rsync is distributed under the GNU General Public License. See the file
|
||||
COPYING for details.
|
||||
|
||||
A web site is available at <http://rsync.samba.org/>. The site includes an
|
||||
A web site is available at <https://rsync.samba.org/>. The site includes an
|
||||
FAQ-O-Matic which may cover questions unanswered by this manual page.
|
||||
|
||||
# AUTHOR
|
||||
@@ -95,4 +108,4 @@ FAQ-O-Matic which may cover questions unanswered by this manual page.
|
||||
This manpage was written by Wayne Davison.
|
||||
|
||||
Mailing lists for support and development are available at
|
||||
<http://lists.samba.org/>.
|
||||
<https://lists.samba.org/>.
|
||||
|
||||
749
rsync.1.md
749
rsync.1.md
File diff suppressed because it is too large
Load Diff
61
rsync.c
61
rsync.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -32,7 +32,9 @@ extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_executability;
|
||||
extern int preserve_times;
|
||||
extern int preserve_mtimes;
|
||||
extern int omit_dir_times;
|
||||
extern int omit_link_times;
|
||||
extern int am_root;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
@@ -63,8 +65,7 @@ extern char *iconv_opt;
|
||||
#define UPDATED_ATIME (1<<3)
|
||||
#define UPDATED_ACLS (1<<4)
|
||||
#define UPDATED_MODE (1<<5)
|
||||
|
||||
#define UPDATED_TIMES (UPDATED_MTIME|UPDATED_ATIME)
|
||||
#define UPDATED_CRTIME (1<<6)
|
||||
|
||||
#ifdef ICONV_CONST
|
||||
iconv_t ic_chck = (iconv_t)-1;
|
||||
@@ -576,14 +577,20 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
set_xattr(fname, file, fnamecmp, sxp);
|
||||
#endif
|
||||
|
||||
if (!preserve_times
|
||||
|| (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
|
||||
|| (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
|
||||
flags |= ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME;
|
||||
else if (sxp != &sx2)
|
||||
memcpy(&sx2.st, &sxp->st, sizeof (sx2.st));
|
||||
if (!atimes_ndx || S_ISDIR(sxp->st.st_mode))
|
||||
flags |= ATTRS_SKIP_ATIME;
|
||||
if ((omit_dir_times && S_ISDIR(sxp->st.st_mode))
|
||||
|| (omit_link_times && S_ISLNK(sxp->st.st_mode)))
|
||||
flags |= ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME | ATTRS_SKIP_CRTIME;
|
||||
else {
|
||||
if (!preserve_mtimes)
|
||||
flags |= ATTRS_SKIP_MTIME;
|
||||
if (!atimes_ndx || S_ISDIR(sxp->st.st_mode))
|
||||
flags |= ATTRS_SKIP_ATIME;
|
||||
/* Don't set the creation date on the root folder of an HFS+ volume. */
|
||||
if (sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode))
|
||||
flags |= ATTRS_SKIP_CRTIME;
|
||||
}
|
||||
if (sxp != &sx2)
|
||||
memcpy(&sx2.st, &sxp->st, sizeof sx2.st);
|
||||
if (!(flags & ATTRS_SKIP_MTIME) && !same_mtime(file, &sxp->st, flags & ATTRS_ACCURATE_TIME)) {
|
||||
sx2.st.st_mtime = file->modtime;
|
||||
#ifdef ST_MTIME_NSEC
|
||||
@@ -601,15 +608,33 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
updated |= UPDATED_ATIME;
|
||||
}
|
||||
}
|
||||
if (updated & UPDATED_TIMES) {
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
|
||||
time_t file_crtime = F_CRTIME(file);
|
||||
if (sxp->crtime == 0)
|
||||
sxp->crtime = get_create_time(fname, &sxp->st);
|
||||
if (!same_time(sxp->crtime, 0L, file_crtime, 0L)) {
|
||||
if (
|
||||
#ifdef HAVE_GETATTRLIST
|
||||
do_setattrlist_crtime(fname, file_crtime) == 0
|
||||
#elif defined __CYGWIN__
|
||||
do_SetFileTime(fname, file_crtime) == 0
|
||||
#else
|
||||
#error Unknown crtimes implementation
|
||||
#endif
|
||||
)
|
||||
updated |= UPDATED_CRTIME;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (updated & (UPDATED_MTIME|UPDATED_ATIME)) {
|
||||
int ret = set_times(fname, &sx2.st);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR_XFER, errno, "failed to set times on %s",
|
||||
full_fname(fname));
|
||||
rsyserr(FERROR_XFER, errno, "failed to set times on %s", full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
if (ret > 0) { /* ret == 1 if symlink could not be set */
|
||||
updated &= ~UPDATED_TIMES;
|
||||
updated &= ~(UPDATED_MTIME|UPDATED_ATIME);
|
||||
file->flags |= FLAG_TIME_FAILED;
|
||||
}
|
||||
}
|
||||
@@ -718,7 +743,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
|
||||
|
||||
/* Change permissions before putting the file into place. */
|
||||
set_file_attrs(fnametmp, file, NULL, fnamecmp,
|
||||
ok_to_set_time ? ATTRS_ACCURATE_TIME : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME);
|
||||
ok_to_set_time ? ATTRS_ACCURATE_TIME : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME | ATTRS_SKIP_CRTIME);
|
||||
|
||||
/* move tmp file over real file */
|
||||
if (DEBUG_GTE(RECV, 1))
|
||||
@@ -743,7 +768,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
|
||||
|
||||
do_set_file_attrs:
|
||||
set_file_attrs(fnametmp, file, NULL, fnamecmp,
|
||||
ok_to_set_time ? ATTRS_ACCURATE_TIME : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME);
|
||||
ok_to_set_time ? ATTRS_ACCURATE_TIME : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME | ATTRS_SKIP_CRTIME);
|
||||
|
||||
if (temp_copy_name) {
|
||||
if (do_rename(fnametmp, fname) < 0) {
|
||||
|
||||
149
rsync.h
149
rsync.h
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 1996, 2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,8 +18,14 @@
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
|
||||
incompatible with older versions :-( */
|
||||
#define CHAR_OFFSET 0
|
||||
|
||||
#ifndef AVX2_ASM /* do not include the rest of file for assembly */
|
||||
#define False 0
|
||||
#define True 1
|
||||
#define Unset (-1) /* Our BOOL values are always an int. */
|
||||
|
||||
#define BLOCK_SIZE 700
|
||||
#define RSYNC_RSH_ENV "RSYNC_RSH"
|
||||
@@ -37,9 +43,6 @@
|
||||
|
||||
#define BACKUP_SUFFIX "~"
|
||||
|
||||
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
|
||||
incompatible with older versions :-( */
|
||||
#define CHAR_OFFSET 0
|
||||
|
||||
/* These flags are only used during the flist transfer. */
|
||||
|
||||
@@ -69,7 +72,7 @@
|
||||
/* The following XMIT flags require an rsync that uses a varint for the flag values */
|
||||
|
||||
#define XMIT_RESERVED_16 (1<<16) /* reserved for future fileflags use */
|
||||
#define XMIT_RESERVED_17 (1<<17) /* reserved for future crtimes use */
|
||||
#define XMIT_CRTIME_EQ_MTIME (1<<17) /* any protocol - restricted by command-line option */
|
||||
|
||||
/* These flags are used in the live flist data. */
|
||||
|
||||
@@ -107,12 +110,22 @@
|
||||
#define BITS_EQUAL(b1,b2,mask) (((unsigned)(b1) & (unsigned)(mask)) \
|
||||
== ((unsigned)(b2) & (unsigned)(mask)))
|
||||
|
||||
/* update this if you make incompatible changes */
|
||||
/* Update this if you make incompatible changes and ALSO update the
|
||||
* SUBPROTOCOL_VERSION if it is not a final (official) release. */
|
||||
#define PROTOCOL_VERSION 31
|
||||
|
||||
/* This is used when working on a new protocol version in CVS, and should
|
||||
* be a new non-zero value for each CVS change that affects the protocol.
|
||||
* It must ALWAYS be 0 when the protocol goes final (and NEVER before)! */
|
||||
/* This is used when working on a new protocol version or for any unofficial
|
||||
* protocol tweaks. It should be a non-zero value for each pre-release repo
|
||||
* change that affects the protocol. The official pre-release versions should
|
||||
* start with 1 (after incrementing the PROTOCOL_VERSION) and go up by 1 for
|
||||
* each new protocol change. For unofficial changes, pick a fairly large
|
||||
* random number that will hopefully not collide with anyone else's unofficial
|
||||
* protocol. It must ALWAYS be 0 when the protocol goes final (and official)
|
||||
* and NEVER before! When rsync negotiates a protocol match, it will only
|
||||
* allow the newest protocol to be used if the SUBPROTOCOL_VERSION matches.
|
||||
* All older protocol versions MUST be compatible with the final, official
|
||||
* release of the protocol, so don't tweak the code to change the protocol
|
||||
* behavior for an older protocol version. */
|
||||
#define SUBPROTOCOL_VERSION 0
|
||||
|
||||
/* We refuse to interoperate with versions that are not in this range.
|
||||
@@ -181,6 +194,7 @@
|
||||
#define ATTRS_SKIP_MTIME (1<<1)
|
||||
#define ATTRS_ACCURATE_TIME (1<<2)
|
||||
#define ATTRS_SKIP_ATIME (1<<3)
|
||||
#define ATTRS_SKIP_CRTIME (1<<5)
|
||||
|
||||
#define MSG_FLUSH 2
|
||||
#define FULL_FLUSH 1
|
||||
@@ -208,6 +222,7 @@
|
||||
#define ITEM_REPORT_GROUP (1<<6)
|
||||
#define ITEM_REPORT_ACL (1<<7)
|
||||
#define ITEM_REPORT_XATTR (1<<8)
|
||||
#define ITEM_REPORT_CRTIME (1<<10)
|
||||
#define ITEM_BASIS_TYPE_FOLLOWS (1<<11)
|
||||
#define ITEM_XNAME_FOLLOWS (1<<12)
|
||||
#define ITEM_IS_NEW (1<<13)
|
||||
@@ -264,6 +279,10 @@ enum msgcode {
|
||||
MSG_NO_SEND=102,/* sender failed to open a file we wanted */
|
||||
};
|
||||
|
||||
enum filetype {
|
||||
FT_UNSUPPORTED, FT_REG, FT_DIR, FT_SYMLINK, FT_SPECIAL, FT_DEVICE
|
||||
};
|
||||
|
||||
#define NDX_DONE -1
|
||||
#define NDX_FLIST_EOF -2
|
||||
#define NDX_DEL_STATS -3
|
||||
@@ -440,7 +459,9 @@ enum delret {
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <syslog.h>
|
||||
#ifdef HAVE_SYS_FILE_H
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
@@ -469,7 +490,22 @@ enum delret {
|
||||
#ifdef MAKEDEV_TAKES_3_ARGS
|
||||
#define MAKEDEV(devmajor,devminor) makedev(0,devmajor,devminor)
|
||||
#else
|
||||
#ifndef __TANDEM
|
||||
#define MAKEDEV(devmajor,devminor) makedev(devmajor,devminor)
|
||||
#else
|
||||
# define major DEV_TO_MAJOR
|
||||
# define minor DEV_TO_MINOR
|
||||
# define MAKEDEV MAJORMINOR_TO_DEV
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __TANDEM
|
||||
# include <floss.h(floss_read,floss_write,floss_fork,floss_execvp)>
|
||||
# include <floss.h(floss_getpwuid,floss_select,floss_seteuid)>
|
||||
# define S_IEXEC S_IXUSR
|
||||
# define ROOT_UID 65535
|
||||
#else
|
||||
# define ROOT_UID 0
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
@@ -548,6 +584,14 @@ typedef unsigned int size_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined __APPLE__ || defined HAVE_GETATTRLIST
|
||||
#define SUPPORT_ATIMES 1
|
||||
#endif
|
||||
|
||||
#if defined HAVE_GETATTRLIST || defined __CYGWIN__
|
||||
#define SUPPORT_CRTIMES 1
|
||||
#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. */
|
||||
@@ -691,6 +735,10 @@ struct ht_int64_node {
|
||||
#define NAME_MAX 255
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX ((size_t)-1)
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
@@ -730,6 +778,15 @@ struct ht_int64_node {
|
||||
# error Character pointers are not 4 or 8 bytes.
|
||||
#endif
|
||||
|
||||
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
|
||||
#define USE_FLEXIBLE_ARRAY 1
|
||||
#define SIZE_T_FMT_MOD "z" /* printf supports %zd */
|
||||
#define SIZE_T_FMT_CAST size_t
|
||||
#else
|
||||
#define SIZE_T_FMT_MOD "l" /* printf supports %ld */
|
||||
#define SIZE_T_FMT_CAST long
|
||||
#endif
|
||||
|
||||
union file_extras {
|
||||
int32 num;
|
||||
uint32 unum;
|
||||
@@ -751,12 +808,17 @@ struct file_struct {
|
||||
uint32 len32; /* Lowest 32 bits of the file's length */
|
||||
uint16 mode; /* The item's type and permissions */
|
||||
uint16 flags; /* The FLAG_* bits for this item */
|
||||
const char basename[1]; /* The basename (AKA filename) follows */
|
||||
#ifdef USE_FLEXIBLE_ARRAY
|
||||
const char basename[]; /* The basename (AKA filename) follows */
|
||||
#else
|
||||
const char basename[1]; /* A kluge that should work like a flexible array */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int file_extra_cnt;
|
||||
extern int inc_recurse;
|
||||
extern int atimes_ndx;
|
||||
extern int crtimes_ndx;
|
||||
extern int pathname_ndx;
|
||||
extern int depth_ndx;
|
||||
extern int uid_ndx;
|
||||
@@ -764,7 +826,11 @@ extern int gid_ndx;
|
||||
extern int acls_ndx;
|
||||
extern int xattrs_ndx;
|
||||
|
||||
#ifdef USE_FLEXIBLE_ARRAY
|
||||
#define FILE_STRUCT_LEN (sizeof (struct file_struct))
|
||||
#else
|
||||
#define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
|
||||
#endif
|
||||
#define EXTRA_LEN (sizeof (union file_extras))
|
||||
#define DEV_EXTRA_CNT 2
|
||||
#define DIRNODE_EXTRA_CNT 3
|
||||
@@ -815,6 +881,7 @@ extern int xattrs_ndx;
|
||||
#define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
|
||||
#define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
|
||||
#define F_ATIME(f) REQ_EXTRA64(f, atimes_ndx)->num
|
||||
#define F_CRTIME(f) REQ_EXTRA64(f, crtimes_ndx)->num
|
||||
|
||||
/* These items are per-entry optional: */
|
||||
#define F_HL_GNUM(f) OPT_EXTRA(f, START_BUMP(f))->num /* non-dirs */
|
||||
@@ -856,8 +923,9 @@ extern int xattrs_ndx;
|
||||
* 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)
|
||||
#define FLIST_START (32)
|
||||
#define FLIST_START_LARGE (32 * 1024)
|
||||
#define FLIST_LINEAR (FLIST_START_LARGE * 512)
|
||||
|
||||
/*
|
||||
* Extent size for allocation pools: A minimum size of 128KB
|
||||
@@ -1033,9 +1101,19 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
char name_type;
|
||||
char fname[1]; /* has variable size */
|
||||
#ifdef USE_FLEXIBLE_ARRAY
|
||||
char fname[]; /* has variable size */
|
||||
#else
|
||||
char fname[1]; /* A kluge that should work like a flexible array */
|
||||
#endif
|
||||
} relnamecache;
|
||||
|
||||
#ifdef USE_FLEXIBLE_ARRAY
|
||||
#define RELNAMECACHE_LEN (sizeof (relnamecache))
|
||||
#else
|
||||
#define RELNAMECACHE_LEN (offsetof(relnamecache, fname))
|
||||
#endif
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "lib/mdigest.h"
|
||||
#include "lib/wildmatch.h"
|
||||
@@ -1057,6 +1135,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
STRUCT_STAT st;
|
||||
time_t crtime;
|
||||
#ifdef SUPPORT_ACLS
|
||||
struct rsync_acl *acc_acl; /* access ACL */
|
||||
struct rsync_acl *def_acl; /* default ACL */
|
||||
@@ -1078,6 +1157,9 @@ typedef struct {
|
||||
#define CPRES_LZ4 3
|
||||
#define CPRES_ZSTD 4
|
||||
|
||||
#define NSTR_CHECKSUM 0
|
||||
#define NSTR_COMPRESS 1
|
||||
|
||||
struct name_num_item {
|
||||
int num;
|
||||
const char *name, *main_name;
|
||||
@@ -1089,7 +1171,7 @@ struct name_num_obj {
|
||||
uchar *saw;
|
||||
int saw_len;
|
||||
int negotiated_num;
|
||||
struct name_num_item list[];
|
||||
struct name_num_item list[10]; /* we'll get a compile error/warning if this is ever too small */
|
||||
};
|
||||
|
||||
#ifndef __cplusplus
|
||||
@@ -1250,10 +1332,6 @@ extern int errno;
|
||||
#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
|
||||
|
||||
#define PRESERVE_FILE_TIMES (1<<0)
|
||||
#define PRESERVE_DIR_TIMES (1<<1)
|
||||
#define PRESERVE_LINK_TIMES (1<<2)
|
||||
|
||||
/* 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 */
|
||||
@@ -1262,12 +1340,22 @@ extern int errno;
|
||||
/* handler for null strings in printf format */
|
||||
#define NS(s) ((s)?(s):"<NULL>")
|
||||
|
||||
extern char *do_calloc;
|
||||
|
||||
/* Convenient wrappers for malloc and realloc. Use them. */
|
||||
#define new(type) ((type*)malloc(sizeof (type)))
|
||||
#define new0(type) ((type*)calloc(1, sizeof (type)))
|
||||
#define new_array(type, num) ((type*)_new_array((num), sizeof (type), 0))
|
||||
#define new_array0(type, num) ((type*)_new_array((num), sizeof (type), 1))
|
||||
#define realloc_array(ptr, type, num) ((type*)_realloc_array((ptr), sizeof(type), (num)))
|
||||
#define new(type) ((type*)my_alloc(NULL, sizeof (type), 1, __FILE__, __LINE__))
|
||||
#define new0(type) ((type*)my_alloc(do_calloc, sizeof (type), 1, __FILE__, __LINE__))
|
||||
#define realloc_buf(ptr, num) my_alloc((ptr), (num), 1, __FILE__, __LINE__)
|
||||
|
||||
#define new_array(type, num) ((type*)my_alloc(NULL, (num), sizeof (type), __FILE__, __LINE__))
|
||||
#define new_array0(type, num) ((type*)my_alloc(do_calloc, (num), sizeof (type), __FILE__, __LINE__))
|
||||
#define realloc_array(ptr, type, num) ((type*)my_alloc((ptr), (num), sizeof (type), __FILE__, __LINE__))
|
||||
|
||||
#undef strdup
|
||||
#define strdup(s) my_strdup(s, __FILE__, __LINE__)
|
||||
|
||||
#define out_of_memory(msg) _out_of_memory(msg, __FILE__, __LINE__)
|
||||
#define overflow_exit(msg) _overflow_exit(msg, __FILE__, __LINE__)
|
||||
|
||||
/* use magic gcc attributes to catch format errors */
|
||||
void rprintf(enum logcode , const char *, ...)
|
||||
@@ -1333,7 +1421,8 @@ extern short info_levels[], debug_levels[];
|
||||
#define INFO_MISC (INFO_FLIST+1)
|
||||
#define INFO_MOUNT (INFO_MISC+1)
|
||||
#define INFO_NAME (INFO_MOUNT+1)
|
||||
#define INFO_PROGRESS (INFO_NAME+1)
|
||||
#define INFO_NONREG (INFO_NAME+1)
|
||||
#define INFO_PROGRESS (INFO_NONREG+1)
|
||||
#define INFO_REMOVE (INFO_PROGRESS+1)
|
||||
#define INFO_SKIP (INFO_REMOVE+1)
|
||||
#define INFO_STATS (INFO_SKIP+1)
|
||||
@@ -1383,3 +1472,15 @@ char *getpass(const char *prompt);
|
||||
#ifdef MAINTAINER_MODE
|
||||
const char *get_panic_action(void);
|
||||
#endif
|
||||
|
||||
#define NOISY_DEATH(msg) do { \
|
||||
fprintf(stderr, "%s in %s at line %d\n", msg, __FILE__, __LINE__); \
|
||||
exit_cleanup(RERR_UNSUPPORTED); \
|
||||
} while (0)
|
||||
#endif /* AVX2_ASM */
|
||||
|
||||
#ifdef HAVE_MALLINFO2
|
||||
#define MEM_ALLOC_INFO mallinfo2
|
||||
#elif defined HAVE_MALLINFO
|
||||
#define MEM_ALLOC_INFO mallinfo
|
||||
#endif
|
||||
|
||||
@@ -396,7 +396,7 @@ Conflict resolution:
|
||||
would be useful.
|
||||
|
||||
|
||||
Moved files: <http://rsync.samba.org/cgi-bin/rsync.fom?file=44>
|
||||
Moved files:
|
||||
|
||||
- There's no trivial way to detect renamed files, especially if they
|
||||
move between directories.
|
||||
@@ -457,13 +457,11 @@ Streaming:
|
||||
|
||||
Related work:
|
||||
|
||||
- mirror.pl http://freshmeat.net/project/mirror/
|
||||
- mirror.pl
|
||||
|
||||
- ProFTPd
|
||||
|
||||
- Apache
|
||||
|
||||
- http://freshmeat.net/search/?site=Freshmeat&q=mirror§ion=projects
|
||||
|
||||
- BitTorrent -- p2p mirroring
|
||||
http://bitconjurer.org/BitTorrent/
|
||||
|
||||
136
rsyncd.conf.5.md
136
rsyncd.conf.5.md
@@ -60,9 +60,9 @@ When run via inetd you should add a line like this to /etc/services:
|
||||
|
||||
and a single line something like this to /etc/inetd.conf:
|
||||
|
||||
> rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon
|
||||
> rsync stream tcp nowait root @BINDIR@/rsync rsyncd --daemon
|
||||
|
||||
Replace "/usr/bin/rsync" with the path to where you have rsync installed on
|
||||
Replace "@BINDIR@/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.
|
||||
|
||||
@@ -207,21 +207,18 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
they would escape the module hierarchy. The default for "use chroot" is
|
||||
true, and is the safer choice (especially if the module is not read-only).
|
||||
|
||||
When this parameter is enabled, the "numeric-ids" option will also default
|
||||
to being enabled (disabling name lookups). See below for what a chroot
|
||||
needs in order for name lookups to succeed.
|
||||
When this parameter is enabled *and* the "name converter" parameter is
|
||||
*not* set, the "numeric ids" parameter will default to being enabled
|
||||
(disabling name lookups). This means that if you manually setup
|
||||
name-lookup libraries in your chroot (instead of using a name converter)
|
||||
that you need to explicitly set `numeric ids = false` for rsync to do name
|
||||
lookups.
|
||||
|
||||
If you copy library resources into the module's chroot area, you should
|
||||
protect them through your OS's normal user/group or ACL settings (to
|
||||
prevent the rsync module's user from being able to change them), and then
|
||||
hide them from the user's view via "exclude" (see how in the discussion of
|
||||
that parameter). At that point it will be safe to enable the mapping of
|
||||
users and groups by name using the "numeric ids" daemon parameter (see
|
||||
below).
|
||||
|
||||
Note also that you are free to setup custom user/group information in the
|
||||
chroot area that is different from your normal system. For example, you
|
||||
could abbreviate the list of users and groups.
|
||||
that parameter). However, it's easier and safer to setup a name converter.
|
||||
|
||||
0. `daemon chroot`
|
||||
|
||||
@@ -258,6 +255,27 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
others, then you will need to setup multiple rsync daemon processes on
|
||||
different ports.
|
||||
|
||||
0. `name converter`
|
||||
|
||||
This parameter lets you specify a program that will be run by the rsync
|
||||
daemon to do user & group conversions between names & ids. This script
|
||||
is started prior to any chroot being setup, and runs as the daemon user
|
||||
(not the transfer user). You can specify a fully qualified pathname or
|
||||
a program name that is on the $PATH.
|
||||
|
||||
The program can be used to do normal user & group lookups without having to
|
||||
put any extra files into the chroot area of the module *or* you can do
|
||||
customized conversions.
|
||||
|
||||
The nameconvert program has access to all of the environment variables that
|
||||
are described in the section on `pre-xfer exec`. This is useful if you
|
||||
want to customize the conversion using information about the module and/or
|
||||
the copy request.
|
||||
|
||||
There is a sample python script in the support dir named "nameconvert" that
|
||||
implements the normal user & group lookups. Feel free to customize it or
|
||||
just use it as documentation to implement your own.
|
||||
|
||||
0. `numeric ids`
|
||||
|
||||
Enabling this parameter disables the mapping of users and groups by name
|
||||
@@ -269,13 +287,10 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
uid/gid preservation requires the module to be running as root (see "uid")
|
||||
or for "fake super" to be configured.
|
||||
|
||||
A chroot-enabled module should not have this parameter enabled unless
|
||||
you've taken steps to ensure that the module has the necessary resources it
|
||||
needs to translate names, and that it is not possible for a user to change
|
||||
those resources. That includes being the code being able to call functions
|
||||
like **getpwuid()**, **getgrgid()**, **getpwname()**, and **getgrnam()**.
|
||||
You should test what libraries and config files are required for your OS
|
||||
and get those setup before starting to test name mapping in rsync.
|
||||
A chroot-enabled module should not have this parameter set to false unless
|
||||
you're using a "name converter" program *or* you've taken steps to ensure
|
||||
that the module has the necessary resources it needs to translate names and
|
||||
that it is not possible for a user to change those resources.
|
||||
|
||||
0. `munge symlinks`
|
||||
|
||||
@@ -424,6 +439,22 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
Helpful hint: you probably want to specify "refuse options = delete" for a
|
||||
write-only module.
|
||||
|
||||
0. `open noatime`
|
||||
|
||||
When set to True, this parameter tells the rsync daemon to open files with
|
||||
the O_NOATIME flag
|
||||
(on systems that support it) to avoid changing the access time of the files
|
||||
that are being transferred. If your OS does not support the O_NOATIME flag
|
||||
then rsync will silently ignore this option. Note also that some
|
||||
filesystems are mounted to avoid updating the atime on read access even
|
||||
without the O_NOATIME flag being set.
|
||||
|
||||
When set to False, this parameters ensures that files on the server are not
|
||||
opened with O_NOATIME.
|
||||
|
||||
When set to Unset (the default) the user controls the setting via
|
||||
`--open-noatime`.
|
||||
|
||||
0. `list`
|
||||
|
||||
This parameter determines whether this module is listed when the client
|
||||
@@ -669,7 +700,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
client's hostname and IP address. If none of the patterns match, then the
|
||||
connection is rejected.
|
||||
|
||||
Each pattern can be in one of five forms:
|
||||
Each pattern can be in one of six forms:
|
||||
|
||||
- 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
|
||||
@@ -689,6 +720,8 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
connecting IP (if "reverse lookup" is enabled), and/or the IP of the
|
||||
given hostname is matched against the connecting IP (if "forward lookup"
|
||||
is enabled, as it is by default). Any match will be allowed in.
|
||||
- an '@' followed by a netgroup name, which will match if the reverse DNS
|
||||
of the connecting IP is in the specified netgroup.
|
||||
|
||||
Note IPv6 link-local addresses can have a scope in the address
|
||||
specification:
|
||||
@@ -697,12 +730,12 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
> fe80::%link1/64
|
||||
> fe80::%link1/ffff:ffff:ffff:ffff::
|
||||
|
||||
You can also combine "hosts allow" with a separate "hosts deny" parameter.
|
||||
If both parameters are specified then the "hosts allow" parameter is
|
||||
checked first and a match results in the client being able to connect. The
|
||||
"hosts deny" parameter is then checked and a match means that the host is
|
||||
rejected. If the host does not match either the "hosts allow" or the
|
||||
"hosts deny" patterns then it is allowed to connect.
|
||||
You can also combine "hosts allow" with "hosts deny" as a way to add
|
||||
exceptions to your deny list. When both parameters are specified, the
|
||||
"hosts allow" parameter is checked first and a match results in the client
|
||||
being able to connect. A non-allowed host is then matched against the
|
||||
"hosts deny" list to see if it should be rejected. A host that does not
|
||||
match either list is allowed to connect.
|
||||
|
||||
The default is no "hosts allow" parameter, which means all hosts can
|
||||
connect.
|
||||
@@ -889,13 +922,14 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
> refuse options = * !a !delete* delete-after
|
||||
|
||||
A note on refusing "compress" -- it is better to set the "dont compress"
|
||||
daemon parameter to "`*`" because that disables compression silently
|
||||
A note on refusing "compress": it may be better to set the "dont compress"
|
||||
daemon parameter to "`*`" and ensure that `RSYNC_COMPRESS_LIST=zlib` is set
|
||||
in the environment of the daemon in order to disable compression silently
|
||||
instead of returning an error that forces the client to remove the `-z`
|
||||
option.
|
||||
|
||||
If you are un-refusing the compress option, you probably want to match
|
||||
"`!compress*`" so that you also accept the `--compress-level` option.
|
||||
If you are un-refusing the compress option, you may want to match
|
||||
"`!compress*`" if you also want to allow the `--compress-level` option.
|
||||
|
||||
Note that the "write-devices" option is refused by default, but can be
|
||||
explicitly accepted with "`!write-devices`". The options "log-file" and
|
||||
@@ -905,15 +939,15 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
- `--server`: Required for rsync to even work.
|
||||
- `--rsh`, `-e`: Required to convey compatibility flags to the server.
|
||||
- `--log-format`: This is required to convey things like
|
||||
`--itemize-changes` to a remote receiver. Is an older name for
|
||||
`--out-format` that is still passed to the server for improved backward
|
||||
compatibility and should not be confused with `--log-file-format`.
|
||||
- `--out-format`: This is required to convey output behavior to a remote
|
||||
receiver. While rsync passes the older alias `--log-format` for
|
||||
compatibility reasons, this options should not be confused with
|
||||
`--log-file-format`.
|
||||
- `--sender`: Use "write only" parameter instead of refusing this.
|
||||
- `--dry-run`, `-n`: Who would want to disable this?
|
||||
- `--protect-args`, `-n`: This actually makes transfers safer.
|
||||
- `--from0`, `-0`: Make it easier to accept/refuse `--files-from` without
|
||||
affecting this modifier.
|
||||
- `--protect-args`, `-s`: This actually makes transfers safer.
|
||||
- `--from0`, `-0`: Makes it easier to accept/refuse `--files-from` without
|
||||
affecting this helpful modifier.
|
||||
- `--iconv`: This is auto-disabled based on "charset" parameter.
|
||||
- `--no-iconv`: Most transfers use this option.
|
||||
- `--checksum-seed`: Is a fairly rare, safe option.
|
||||
@@ -921,6 +955,10 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
0. `dont compress`
|
||||
|
||||
**NOTE:** This parameter currently has no effect except in one instance: if
|
||||
it is set to "`*`" then it minimizes or disables compression for all files
|
||||
(for those that don't want to refuse the `--compress` option completely).
|
||||
|
||||
This parameter allows you to select filenames based on wildcard patterns
|
||||
that should not be compressed when pulling files from the daemon (no
|
||||
analogous parameter exists to govern the pushing of files to a daemon).
|
||||
@@ -931,14 +969,14 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
The "dont compress" parameter takes a space-separated list of
|
||||
case-insensitive wildcard patterns. Any source filename matching one of the
|
||||
patterns will be compressed as little as possible during the transfer. If
|
||||
the compression algorithm has an "off" level (such as zlib/zlibx) then no
|
||||
compression occurs for those files. Other algorithms have the level
|
||||
minimized to reduces the CPU usage as much as possible.
|
||||
the compression algorithm has an "off" level, then no compression occurs
|
||||
for those files. If an algorithms has the ability to change the level in
|
||||
mid-stream, it will be minimized to reduce the CPU usage as much as
|
||||
possible.
|
||||
|
||||
See the `--skip-compress` parameter in the **rsync**(1) manpage for the
|
||||
list of file suffixes that are not compressed by default. Specifying a
|
||||
value for the "dont compress" parameter changes the default when the daemon
|
||||
is the sender.
|
||||
list of file suffixes that are skipped by default if this parameter is not
|
||||
set.
|
||||
|
||||
0. `early exec`, `pre-xfer exec`, `post-xfer exec`
|
||||
|
||||
@@ -957,7 +995,9 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
request is known except for the module name. This helper script can be
|
||||
used to setup a disk mount or decrypt some data into a module dir, but you
|
||||
may need to use `lock file` and `max connections` to avoid concurrency
|
||||
issues.
|
||||
issues. If the client rsync specified the `--early-input=FILE` option, it
|
||||
can send up to about 5K of data to the stdin of the early script. The
|
||||
stdin will otherwise be empty.
|
||||
|
||||
Note that the `post-xfer exec` command is still run even if one of the
|
||||
other scripts returns an error code. The `pre-xfer exec` command will _not_
|
||||
@@ -1103,7 +1143,7 @@ An example nginx proxy setup is as follows:
|
||||
> listen [::]:874 ssl;
|
||||
>
|
||||
> ssl_certificate /etc/letsencrypt/example.com/fullchain.pem;
|
||||
> ssl_certificate_key /etc/letsencrypt/example.com/privkey.pem
|
||||
> ssl_certificate_key /etc/letsencrypt/example.com/privkey.pem;
|
||||
>
|
||||
> proxy_pass localhost:873;
|
||||
> proxy_protocol on; # Requires "proxy protocol = true"
|
||||
@@ -1173,7 +1213,7 @@ The /etc/rsyncd.secrets file would look something like this:
|
||||
# BUGS
|
||||
|
||||
Please report bugs! The rsync bug tracking system is online at
|
||||
<http://rsync.samba.org/>.
|
||||
<https://rsync.samba.org/>.
|
||||
|
||||
# VERSION
|
||||
|
||||
@@ -1186,7 +1226,7 @@ COPYING for details.
|
||||
|
||||
The primary ftp site for rsync is <ftp://rsync.samba.org/pub/rsync>
|
||||
|
||||
A web site is available at <http://rsync.samba.org/>.
|
||||
A web site is available at <https://rsync.samba.org/>.
|
||||
|
||||
We would be delighted to hear from you if you like this program.
|
||||
|
||||
@@ -1204,4 +1244,4 @@ 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
|
||||
<http://lists.samba.org/>.
|
||||
<https://lists.samba.org/>.
|
||||
|
||||
33
runtests.sh
33
runtests.sh
@@ -1,7 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
# Copyright (C) 2003-2020 Wayne Davison
|
||||
# Copyright (C) 2003-2021 Wayne Davison
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version
|
||||
@@ -155,7 +155,7 @@ if test x"$TOOLDIR" = x; then
|
||||
TOOLDIR=`pwd`
|
||||
fi
|
||||
srcdir=`dirname $0`
|
||||
if test x"$srcdir" = x -o x"$srcdir" = x.; then
|
||||
if test x"$srcdir" = x || test x"$srcdir" = x.; then
|
||||
srcdir="$TOOLDIR"
|
||||
fi
|
||||
if test x"$rsync_bin" = x; then
|
||||
@@ -167,10 +167,10 @@ RSYNC="$rsync_bin $*"
|
||||
#RSYNC="valgrind $rsync_bin $*"
|
||||
|
||||
TLS_ARGS=''
|
||||
if egrep '^#define HAVE_LUTIMES 1' config.h >/dev/null; then
|
||||
if grep -E '^#define HAVE_LUTIMES 1' config.h >/dev/null; then
|
||||
TLS_ARGS="$TLS_ARGS -l"
|
||||
fi
|
||||
if egrep '#undef CHOWN_MODIFIES_SYMLINK' config.h >/dev/null; then
|
||||
if grep -E '#undef CHOWN_MODIFIES_SYMLINK' config.h >/dev/null; then
|
||||
TLS_ARGS="$TLS_ARGS -L"
|
||||
fi
|
||||
|
||||
@@ -226,6 +226,8 @@ if [ ! -d "$srcdir" ]; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
expect_skipped="${RSYNC_EXPECT_SKIPPED-IGNORE}"
|
||||
skipped_list=''
|
||||
skipped=0
|
||||
missing=0
|
||||
passed=0
|
||||
@@ -249,7 +251,7 @@ prep_scratch() {
|
||||
[ -d "$scratchdir" ] && chmod -R u+rwX "$scratchdir" && rm -rf "$scratchdir"
|
||||
mkdir "$scratchdir"
|
||||
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
|
||||
$setfacl_nodef "$scratchdir" || true
|
||||
$setfacl_nodef "$scratchdir" 2>/dev/null || true
|
||||
chmod g-s "$scratchdir"
|
||||
case "$srcdir" in
|
||||
/*) ln -s "$srcdir" "$scratchdir/src" ;;
|
||||
@@ -265,10 +267,12 @@ maybe_discard_scratch() {
|
||||
|
||||
if [ "x$whichtests" = x ]; then
|
||||
whichtests="*.test"
|
||||
full_run=yes
|
||||
else
|
||||
full_run=no
|
||||
fi
|
||||
|
||||
for testscript in $suitedir/$whichtests
|
||||
do
|
||||
for testscript in $suitedir/$whichtests; do
|
||||
testbase=`echo $testscript | sed -e 's!.*/!!' -e 's/.test\$//'`
|
||||
scratchdir="$scratchbase/$testbase"
|
||||
|
||||
@@ -284,7 +288,7 @@ do
|
||||
result=$?
|
||||
set -e
|
||||
|
||||
if [ "x$always_log" = xyes -o \( $result != 0 -a $result != 77 -a $result != 78 \) ]
|
||||
if [ "x$always_log" = xyes ] || ( [ $result != 0 ] && [ $result != 77 ] && [ $result != 78 ] )
|
||||
then
|
||||
echo "----- $testbase log follows"
|
||||
cat "$scratchdir/test.log"
|
||||
@@ -306,6 +310,7 @@ do
|
||||
# backticks will fill the whole file onto one line, which is a feature
|
||||
whyskipped=`cat "$scratchdir/whyskipped"`
|
||||
echo "SKIP $testbase ($whyskipped)"
|
||||
skipped_list="$skipped_list,$testbase"
|
||||
skipped=`expr $skipped + 1`
|
||||
maybe_discard_scratch
|
||||
;;
|
||||
@@ -331,6 +336,15 @@ echo " $passed passed"
|
||||
[ "$failed" -gt 0 ] && echo " $failed failed"
|
||||
[ "$skipped" -gt 0 ] && echo " $skipped skipped"
|
||||
[ "$missing" -gt 0 ] && echo " $missing missing"
|
||||
if [ "$full_run" = yes ] && [ "$expect_skipped" != IGNORE ]; then
|
||||
skipped_list=`echo "$skipped_list" | sed 's/^,//'`
|
||||
echo "----- skipped results:"
|
||||
echo " expected: $expect_skipped"
|
||||
echo " got: $skipped_list"
|
||||
else
|
||||
skipped_list=''
|
||||
expect_skipped=''
|
||||
fi
|
||||
echo '------------------------------------------------------------'
|
||||
|
||||
# OK, so expr exits with 0 if the result is neither null nor zero; and
|
||||
@@ -339,5 +353,8 @@ echo '------------------------------------------------------------'
|
||||
# because -e is set.
|
||||
|
||||
result=`expr $failed + $missing || true`
|
||||
if [ "$result" = 0 ] && [ "$skipped_list" != "$expect_skipped" ]; then
|
||||
result=1
|
||||
fi
|
||||
echo "overall result is $result"
|
||||
exit $result
|
||||
|
||||
26
sender.c
26
sender.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -35,6 +35,7 @@ extern int append_mode;
|
||||
extern int copy_links;
|
||||
extern int io_error;
|
||||
extern int flist_eof;
|
||||
extern int whole_file;
|
||||
extern int allowed_lull;
|
||||
extern int preserve_xattrs;
|
||||
extern int protocol_version;
|
||||
@@ -65,13 +66,10 @@ BOOL extra_flist_sending_enabled;
|
||||
**/
|
||||
static struct sum_struct *receive_sums(int f)
|
||||
{
|
||||
struct sum_struct *s;
|
||||
int32 i;
|
||||
struct sum_struct *s = new(struct sum_struct);
|
||||
int lull_mod = protocol_version >= 31 ? 0 : allowed_lull * 5;
|
||||
OFF_T offset = 0;
|
||||
|
||||
if (!(s = new(struct sum_struct)))
|
||||
out_of_memory("receive_sums");
|
||||
int32 i;
|
||||
|
||||
read_sum_head(f, s);
|
||||
|
||||
@@ -92,8 +90,7 @@ static struct sum_struct *receive_sums(int f)
|
||||
if (s->count == 0)
|
||||
return(s);
|
||||
|
||||
if (!(s->sums = new_array(struct sum_buf, s->count)))
|
||||
out_of_memory("receive_sums");
|
||||
s->sums = new_array(struct sum_buf, s->count);
|
||||
|
||||
for (i = 0; i < s->count; i++) {
|
||||
s->sums[i].sum1 = read_int(f);
|
||||
@@ -208,6 +205,9 @@ void send_files(int f_in, int f_out)
|
||||
if (DEBUG_GTE(SEND, 1))
|
||||
rprintf(FINFO, "send_files starting\n");
|
||||
|
||||
if (whole_file < 0)
|
||||
whole_file = 0;
|
||||
|
||||
progress_init();
|
||||
|
||||
while (1) {
|
||||
@@ -366,6 +366,16 @@ void send_files(int f_in, int f_out)
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
if (append_mode > 0 && st.st_size < F_LENGTH(file)) {
|
||||
rprintf(FWARNING, "skipped diminished file: %s\n",
|
||||
full_fname(fname));
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
if (protocol_version >= 30)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
169
simd-checksum-avx2.S
Normal file
169
simd-checksum-avx2.S
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifdef __APPLE__
|
||||
#define get_checksum1_avx2 _get_checksum1_avx2
|
||||
#endif
|
||||
|
||||
.intel_syntax noprefix
|
||||
.text
|
||||
|
||||
.p2align 5
|
||||
.globl get_checksum1_avx2
|
||||
|
||||
# rdi=*buf, esi=len, edx=i, rcx= *ps1, r8= *ps2
|
||||
get_checksum1_avx2:
|
||||
vmovd xmm6,[rcx] # load *ps1
|
||||
lea eax, [rsi-128] # at least 128 bytes to process?
|
||||
cmp edx, eax
|
||||
jg .exit
|
||||
lea rax, .mul_T2[rip]
|
||||
vmovntdqa ymm7, [rax] # load T2 multiplication constants
|
||||
vmovntdqa ymm12,[rax+32]# from memory.
|
||||
vpcmpeqd ymm15, ymm15, ymm15 # set all elements to -1.
|
||||
|
||||
#if CHAR_OFFSET != 0
|
||||
mov eax, 32*CHAR_OFFSET
|
||||
vmovd xmm10, eax
|
||||
vpbroadcastd ymm10, xmm10
|
||||
mov eax, 528*CHAR_OFFSET
|
||||
vmovd xmm13, eax
|
||||
vpbroadcastd ymm13, xmm13
|
||||
#endif
|
||||
vpabsb ymm15, ymm15 # set all byte size elements to 1.
|
||||
add rdi, rdx
|
||||
vmovdqu ymm2, [rdi] # preload the first 64 bytes.
|
||||
vmovdqu ymm3, [rdi+32]
|
||||
and esi, ~63 # only needed during final reduction,
|
||||
# done here to avoid a longer nop for
|
||||
# alignment below.
|
||||
add edx, esi
|
||||
shr rsi, 6 # longer opcode for alignment
|
||||
add rdi, 64
|
||||
vpxor xmm1, xmm1, xmm1 # reset both partial sums accumulators.
|
||||
vpxor xmm4, xmm4, xmm4
|
||||
mov eax, [r8]
|
||||
.p2align 4 # should fit into the LSD allocation queue.
|
||||
.loop:
|
||||
vpmaddubsw ymm0, ymm15, ymm2 # s1 partial sums
|
||||
vpmaddubsw ymm5, ymm15, ymm3
|
||||
vmovdqu ymm8, [rdi] # preload the next
|
||||
vmovdqu ymm9, [rdi+32] # 64 bytes.
|
||||
add rdi, 64
|
||||
vpaddd ymm4, ymm4, ymm6
|
||||
vpaddw ymm5, ymm5, ymm0
|
||||
vpsrld ymm0, ymm5, 16
|
||||
vpaddw ymm5, ymm0, ymm5
|
||||
vpaddd ymm6, ymm5, ymm6
|
||||
vpmaddubsw ymm2, ymm7, ymm2 # s2 partial sums
|
||||
vpmaddubsw ymm3, ymm12, ymm3
|
||||
prefetcht0 [rdi+384] # prefetch 6 cachelines ahead.
|
||||
vpaddw ymm3, ymm2, ymm3
|
||||
vpsrldq ymm2, ymm3, 2
|
||||
vpaddd ymm3, ymm2, ymm3
|
||||
vpaddd ymm1, ymm1, ymm3
|
||||
|
||||
#if CHAR_OFFSET != 0
|
||||
vpaddd ymm6, ymm10, ymm6 # 32*CHAR_OFFSET
|
||||
vpaddd ymm1, ymm13, ymm1 # 528*CHAR_OFFSET
|
||||
#endif
|
||||
vmovdqa ymm2, ymm8 # move the next 64 bytes
|
||||
vmovdqa ymm3, ymm9 # into the right registers
|
||||
sub esi, 1
|
||||
jnz .loop
|
||||
|
||||
# now we reduce the partial sums.
|
||||
vpslld ymm3, ymm4, 6
|
||||
vpsrldq ymm2, ymm6, 4
|
||||
|
||||
vpaddd ymm0, ymm3, ymm1
|
||||
vpaddd ymm6, ymm2, ymm6
|
||||
vpsrlq ymm3, ymm0, 32
|
||||
|
||||
vpsrldq ymm2, ymm6, 8
|
||||
vpaddd ymm0, ymm3, ymm0
|
||||
vpsrldq ymm3, ymm0, 8
|
||||
vpaddd ymm6, ymm2, ymm6
|
||||
vpaddd ymm0, ymm3, ymm0
|
||||
vextracti128 xmm2, ymm6, 0x1
|
||||
vextracti128 xmm1, ymm0, 0x1
|
||||
vpaddd xmm6, xmm2, xmm6
|
||||
vmovd [rcx], xmm6
|
||||
vpaddd xmm1, xmm1, xmm0
|
||||
vmovd ecx, xmm1
|
||||
add eax, ecx
|
||||
mov [r8], eax
|
||||
.exit:
|
||||
vzeroupper
|
||||
mov eax, edx
|
||||
ret
|
||||
|
||||
#ifdef __APPLE__
|
||||
.data
|
||||
.align 6
|
||||
#else
|
||||
.section .rodata
|
||||
.p2align 6
|
||||
#endif
|
||||
.mul_T2:
|
||||
.byte 64
|
||||
.byte 63
|
||||
.byte 62
|
||||
.byte 61
|
||||
.byte 60
|
||||
.byte 59
|
||||
.byte 58
|
||||
.byte 57
|
||||
.byte 56
|
||||
.byte 55
|
||||
.byte 54
|
||||
.byte 53
|
||||
.byte 52
|
||||
.byte 51
|
||||
.byte 50
|
||||
.byte 49
|
||||
.byte 48
|
||||
.byte 47
|
||||
.byte 46
|
||||
.byte 45
|
||||
.byte 44
|
||||
.byte 43
|
||||
.byte 42
|
||||
.byte 41
|
||||
.byte 40
|
||||
.byte 39
|
||||
.byte 38
|
||||
.byte 37
|
||||
.byte 36
|
||||
.byte 35
|
||||
.byte 34
|
||||
.byte 33
|
||||
.byte 32
|
||||
.byte 31
|
||||
.byte 30
|
||||
.byte 29
|
||||
.byte 28
|
||||
.byte 27
|
||||
.byte 26
|
||||
.byte 25
|
||||
.byte 24
|
||||
.byte 23
|
||||
.byte 22
|
||||
.byte 21
|
||||
.byte 20
|
||||
.byte 19
|
||||
.byte 18
|
||||
.byte 17
|
||||
.byte 16
|
||||
.byte 15
|
||||
.byte 14
|
||||
.byte 13
|
||||
.byte 12
|
||||
.byte 11
|
||||
.byte 10
|
||||
.byte 9
|
||||
.byte 8
|
||||
.byte 7
|
||||
.byte 6
|
||||
.byte 5
|
||||
.byte 4
|
||||
.byte 3
|
||||
.byte 2
|
||||
.byte 1
|
||||
@@ -45,9 +45,10 @@
|
||||
* the available xmm registers, this optimized version may not be faster than
|
||||
* the pure C version anyway. Note that all x86-64 CPUs support at least SSE2.
|
||||
*
|
||||
* This file is compiled using GCC 4.8+'s C++ front end to allow the use of
|
||||
* the target attribute, selecting the fastest code path based on runtime
|
||||
* detection of CPU capabilities.
|
||||
* This file is compiled using GCC 4.8+/clang 6+'s C++ front end to allow the
|
||||
* use of the target attribute, selecting the fastest code path based on
|
||||
* dispatch priority (GCC 5) or runtime detection of CPU capabilities (GCC 6+).
|
||||
* GCC 4.x are not supported to ease configure.ac logic.
|
||||
*/
|
||||
|
||||
#ifdef __x86_64__
|
||||
@@ -59,73 +60,33 @@
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
/* Compatibility functions to let our SSSE3 algorithm run on SSE2 */
|
||||
/* Some clang versions don't like it when you use static with multi-versioned functions: linker errors */
|
||||
#ifdef __clang__
|
||||
#define MVSTATIC
|
||||
#else
|
||||
#define MVSTATIC static
|
||||
#endif
|
||||
|
||||
__attribute__ ((target("sse2"))) static inline __m128i sse_interleave_odd_epi16(__m128i a, __m128i b)
|
||||
{
|
||||
return _mm_packs_epi32(
|
||||
_mm_srai_epi32(a, 16),
|
||||
_mm_srai_epi32(b, 16)
|
||||
);
|
||||
}
|
||||
// Missing from the headers on gcc 6 and older, clang 8 and older
|
||||
typedef long long __m128i_u __attribute__((__vector_size__(16), __may_alias__, __aligned__(1)));
|
||||
typedef long long __m256i_u __attribute__((__vector_size__(32), __may_alias__, __aligned__(1)));
|
||||
|
||||
__attribute__ ((target("sse2"))) static inline __m128i sse_interleave_even_epi16(__m128i a, __m128i b)
|
||||
{
|
||||
return sse_interleave_odd_epi16(
|
||||
_mm_slli_si128(a, 2),
|
||||
_mm_slli_si128(b, 2)
|
||||
);
|
||||
}
|
||||
/* Compatibility macros to let our SSSE3 algorithm run with only SSE2.
|
||||
These used to be neat individual functions with target attributes switching between SSE2 and SSSE3 implementations
|
||||
as needed, but though this works perfectly with GCC, clang fails to inline those properly leading to a near 50%
|
||||
performance drop - combined with static and inline modifiers gets you linker errors and even compiler crashes...
|
||||
*/
|
||||
|
||||
__attribute__ ((target("sse2"))) static inline __m128i sse_mulu_odd_epi8(__m128i a, __m128i b)
|
||||
{
|
||||
return _mm_mullo_epi16(
|
||||
_mm_srli_epi16(a, 8),
|
||||
_mm_srai_epi16(b, 8)
|
||||
);
|
||||
}
|
||||
#define SSE2_INTERLEAVE_ODD_EPI16(a, b) _mm_packs_epi32(_mm_srai_epi32(a, 16), _mm_srai_epi32(b, 16))
|
||||
#define SSE2_INTERLEAVE_EVEN_EPI16(a, b) SSE2_INTERLEAVE_ODD_EPI16(_mm_slli_si128(a, 2), _mm_slli_si128(b, 2))
|
||||
#define SSE2_MULU_ODD_EPI8(a, b) _mm_mullo_epi16(_mm_srli_epi16(a, 8), _mm_srai_epi16(b, 8))
|
||||
#define SSE2_MULU_EVEN_EPI8(a, b) _mm_mullo_epi16(_mm_and_si128(a, _mm_set1_epi16(0xFF)), _mm_srai_epi16(_mm_slli_si128(b, 1), 8))
|
||||
|
||||
__attribute__ ((target("sse2"))) static inline __m128i sse_mulu_even_epi8(__m128i a, __m128i b)
|
||||
{
|
||||
return _mm_mullo_epi16(
|
||||
_mm_and_si128(a, _mm_set1_epi16(0xFF)),
|
||||
_mm_srai_epi16(_mm_slli_si128(b, 1), 8)
|
||||
);
|
||||
}
|
||||
#define SSE2_HADDS_EPI16(a, b) _mm_adds_epi16(SSE2_INTERLEAVE_EVEN_EPI16(a, b), SSE2_INTERLEAVE_ODD_EPI16(a, b))
|
||||
#define SSE2_MADDUBS_EPI16(a, b) _mm_adds_epi16(SSE2_MULU_EVEN_EPI8(a, b), SSE2_MULU_ODD_EPI8(a, b))
|
||||
|
||||
__attribute__ ((target("sse2"))) static inline __m128i sse_hadds_epi16(__m128i a, __m128i b)
|
||||
{
|
||||
return _mm_adds_epi16(
|
||||
sse_interleave_even_epi16(a, b),
|
||||
sse_interleave_odd_epi16(a, b)
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__ ((target("ssse3"))) static inline __m128i sse_hadds_epi16(__m128i a, __m128i b)
|
||||
{
|
||||
return _mm_hadds_epi16(a, b);
|
||||
}
|
||||
|
||||
__attribute__ ((target("sse2"))) static inline __m128i sse_maddubs_epi16(__m128i a, __m128i b)
|
||||
{
|
||||
return _mm_adds_epi16(
|
||||
sse_mulu_even_epi8(a, b),
|
||||
sse_mulu_odd_epi8(a, b)
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__ ((target("ssse3"))) static inline __m128i sse_maddubs_epi16(__m128i a, __m128i b)
|
||||
{
|
||||
return _mm_maddubs_epi16(a, b);
|
||||
}
|
||||
|
||||
/* These don't actually get called, but we need to define them. */
|
||||
__attribute__ ((target("default"))) static inline __m128i sse_interleave_odd_epi16(__m128i a, __m128i b) { return a; }
|
||||
__attribute__ ((target("default"))) static inline __m128i sse_interleave_even_epi16(__m128i a, __m128i b) { return a; }
|
||||
__attribute__ ((target("default"))) static inline __m128i sse_mulu_odd_epi8(__m128i a, __m128i b) { return a; }
|
||||
__attribute__ ((target("default"))) static inline __m128i sse_mulu_even_epi8(__m128i a, __m128i b) { return a; }
|
||||
__attribute__ ((target("default"))) static inline __m128i sse_hadds_epi16(__m128i a, __m128i b) { return a; }
|
||||
__attribute__ ((target("default"))) static inline __m128i sse_maddubs_epi16(__m128i a, __m128i b) { return a; }
|
||||
__attribute__ ((target("default"))) MVSTATIC int32 get_checksum1_ssse3_32(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2) { return i; }
|
||||
__attribute__ ((target("default"))) MVSTATIC int32 get_checksum1_sse2_32(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2) { return i; }
|
||||
|
||||
/*
|
||||
Original loop per 4 bytes:
|
||||
@@ -146,12 +107,7 @@ __attribute__ ((target("default"))) static inline __m128i sse_maddubs_epi16(__m1
|
||||
s1 += (uint32)(t1[0] + t1[1] + t1[2] + t1[3] + t1[4] + t1[5] + t1[6] + t1[7]) +
|
||||
32*CHAR_OFFSET;
|
||||
*/
|
||||
/*
|
||||
Both sse2 and ssse3 targets must be specified here or we lose (a lot) of
|
||||
performance, possibly due to not unrolling+inlining the called targeted
|
||||
functions.
|
||||
*/
|
||||
__attribute__ ((target("sse2", "ssse3"))) static int32 get_checksum1_sse2_32(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
__attribute__ ((target("ssse3"))) MVSTATIC int32 get_checksum1_ssse3_32(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
if (len > 32) {
|
||||
int aligned = ((uintptr_t)buf & 15) == 0;
|
||||
@@ -167,16 +123,11 @@ __attribute__ ((target("sse2", "ssse3"))) static int32 get_checksum1_sse2_32(sch
|
||||
|
||||
for (; i < (len-32); i+=32) {
|
||||
// Load ... 2*[int8*16]
|
||||
// SSSE3 has _mm_lqqdu_si128, but this requires another
|
||||
// target function for each SSE2 and SSSE3 loads. For reasons
|
||||
// unknown (to me) we lose about 10% performance on some CPUs if
|
||||
// we do that right here. We just use _mm_loadu_si128 as for all
|
||||
// but a handful of specific old CPUs they are synonymous, and
|
||||
// take the 1-5% hit on those specific CPUs where it isn't.
|
||||
__m128i in8_1, in8_2;
|
||||
if (!aligned) {
|
||||
in8_1 = _mm_loadu_si128((__m128i_u*)&buf[i]);
|
||||
in8_2 = _mm_loadu_si128((__m128i_u*)&buf[i + 16]);
|
||||
// Synonymous with _mm_loadu_si128 on all but a handful of old CPUs
|
||||
in8_1 = _mm_lddqu_si128((__m128i_u*)&buf[i]);
|
||||
in8_2 = _mm_lddqu_si128((__m128i_u*)&buf[i + 16]);
|
||||
} else {
|
||||
in8_1 = _mm_load_si128((__m128i_u*)&buf[i]);
|
||||
in8_2 = _mm_load_si128((__m128i_u*)&buf[i + 16]);
|
||||
@@ -185,13 +136,13 @@ __attribute__ ((target("sse2", "ssse3"))) static int32 get_checksum1_sse2_32(sch
|
||||
// (1*buf[i] + 1*buf[i+1]), (1*buf[i+2], 1*buf[i+3]), ... 2*[int16*8]
|
||||
// Fastest, even though multiply by 1
|
||||
__m128i mul_one = _mm_set1_epi8(1);
|
||||
__m128i add16_1 = sse_maddubs_epi16(mul_one, in8_1);
|
||||
__m128i add16_2 = sse_maddubs_epi16(mul_one, in8_2);
|
||||
__m128i add16_1 = _mm_maddubs_epi16(mul_one, in8_1);
|
||||
__m128i add16_2 = _mm_maddubs_epi16(mul_one, in8_2);
|
||||
|
||||
// (4*buf[i] + 3*buf[i+1]), (2*buf[i+2], buf[i+3]), ... 2*[int16*8]
|
||||
__m128i mul_const = _mm_set1_epi32(4 + (3 << 8) + (2 << 16) + (1 << 24));
|
||||
__m128i mul_add16_1 = sse_maddubs_epi16(mul_const, in8_1);
|
||||
__m128i mul_add16_2 = sse_maddubs_epi16(mul_const, in8_2);
|
||||
__m128i mul_add16_1 = _mm_maddubs_epi16(mul_const, in8_1);
|
||||
__m128i mul_add16_2 = _mm_maddubs_epi16(mul_const, in8_2);
|
||||
|
||||
// s2 += 32*s1
|
||||
ss2 = _mm_add_epi32(ss2, _mm_slli_epi32(ss1, 5));
|
||||
@@ -224,7 +175,7 @@ __attribute__ ((target("sse2", "ssse3"))) static int32 get_checksum1_sse2_32(sch
|
||||
// [t1[0] + t1[1], t1[2] + t1[3] ...] [int16*8]
|
||||
// We could've combined this with generating sum_add32 above and
|
||||
// save an instruction but benchmarking shows that as being slower
|
||||
__m128i add16 = sse_hadds_epi16(add16_1, add16_2);
|
||||
__m128i add16 = _mm_hadds_epi16(add16_1, add16_2);
|
||||
|
||||
// [t1[0], t1[1], ...] -> [t1[0]*28 + t1[1]*24, ...] [int32*4]
|
||||
__m128i mul32 = _mm_madd_epi16(add16, mul_t1);
|
||||
@@ -256,138 +207,112 @@ __attribute__ ((target("sse2", "ssse3"))) static int32 get_checksum1_sse2_32(sch
|
||||
}
|
||||
|
||||
/*
|
||||
AVX2 loop per 64 bytes:
|
||||
int16 t1[16];
|
||||
int16 t2[16];
|
||||
for (int j = 0; j < 16; j++) {
|
||||
t1[j] = buf[j*4 + i] + buf[j*4 + i+1] + buf[j*4 + i+2] + buf[j*4 + i+3];
|
||||
t2[j] = 4*buf[j*4 + i] + 3*buf[j*4 + i+1] + 2*buf[j*4 + i+2] + buf[j*4 + i+3];
|
||||
}
|
||||
s2 += 64*s1 + (uint32)(
|
||||
60*t1[0] + 56*t1[1] + 52*t1[2] + 48*t1[3] + 44*t1[4] + 40*t1[5] + 36*t1[6] + 32*t1[7] + 28*t1[8] + 24*t1[9] + 20*t1[10] + 16*t1[11] + 12*t1[12] + 8*t1[13] + 4*t1[14] +
|
||||
t2[0] + t2[1] + t2[2] + t2[3] + t2[4] + t2[5] + t2[6] + t2[7] + t2[8] + t2[9] + t2[10] + t2[11] + t2[12] + t2[13] + t2[14] + t2[15]
|
||||
) + 2080*CHAR_OFFSET;
|
||||
s1 += (uint32)(t1[0] + t1[1] + t1[2] + t1[3] + t1[4] + t1[5] + t1[6] + t1[7] + t1[8] + t1[9] + t1[10] + t1[11] + t1[12] + t1[13] + t1[14] + t1[15]) +
|
||||
64*CHAR_OFFSET;
|
||||
Same as SSSE3 version, but using macros defined above to emulate SSSE3 calls that are not available with SSE2.
|
||||
For GCC-only the SSE2 and SSSE3 versions could be a single function calling other functions with the right
|
||||
target attributes to emulate SSSE3 calls on SSE2 if needed, but clang doesn't inline those properly leading
|
||||
to a near 50% performance drop.
|
||||
*/
|
||||
__attribute__ ((target("avx2"))) static int32 get_checksum1_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
__attribute__ ((target("sse2"))) MVSTATIC int32 get_checksum1_sse2_32(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
if (len > 64) {
|
||||
// Instructions reshuffled compared to SSE2 for slightly better performance
|
||||
int aligned = ((uintptr_t)buf & 31) == 0;
|
||||
if (len > 32) {
|
||||
int aligned = ((uintptr_t)buf & 15) == 0;
|
||||
|
||||
uint32 x[8] = {0};
|
||||
uint32 x[4] = {0};
|
||||
x[0] = *ps1;
|
||||
__m256i ss1 = _mm256_lddqu_si256((__m256i_u*)x);
|
||||
__m128i ss1 = _mm_loadu_si128((__m128i_u*)x);
|
||||
x[0] = *ps2;
|
||||
__m256i ss2 = _mm256_lddqu_si256((__m256i_u*)x);
|
||||
__m128i ss2 = _mm_loadu_si128((__m128i_u*)x);
|
||||
|
||||
// The order gets shuffled compared to SSE2
|
||||
const int16 mul_t1_buf[16] = {60, 56, 52, 48, 28, 24, 20, 16, 44, 40, 36, 32, 12, 8, 4, 0};
|
||||
__m256i mul_t1 = _mm256_lddqu_si256((__m256i_u*)mul_t1_buf);
|
||||
const int16 mul_t1_buf[8] = {28, 24, 20, 16, 12, 8, 4, 0};
|
||||
__m128i mul_t1 = _mm_loadu_si128((__m128i_u*)mul_t1_buf);
|
||||
|
||||
for (; i < (len-64); i+=64) {
|
||||
// Load ... 2*[int8*32]
|
||||
__m256i in8_1, in8_2;
|
||||
for (; i < (len-32); i+=32) {
|
||||
// Load ... 2*[int8*16]
|
||||
__m128i in8_1, in8_2;
|
||||
if (!aligned) {
|
||||
in8_1 = _mm256_lddqu_si256((__m256i_u*)&buf[i]);
|
||||
in8_2 = _mm256_lddqu_si256((__m256i_u*)&buf[i + 32]);
|
||||
in8_1 = _mm_loadu_si128((__m128i_u*)&buf[i]);
|
||||
in8_2 = _mm_loadu_si128((__m128i_u*)&buf[i + 16]);
|
||||
} else {
|
||||
in8_1 = _mm256_load_si256((__m256i_u*)&buf[i]);
|
||||
in8_2 = _mm256_load_si256((__m256i_u*)&buf[i + 32]);
|
||||
in8_1 = _mm_load_si128((__m128i_u*)&buf[i]);
|
||||
in8_2 = _mm_load_si128((__m128i_u*)&buf[i + 16]);
|
||||
}
|
||||
|
||||
// Prefetch for next loops. This has no observable effect on the
|
||||
// tested AMD but makes as much as 20% difference on the Intel.
|
||||
// Curiously that same Intel sees no benefit from this with SSE2
|
||||
// or SSSE3.
|
||||
_mm_prefetch(&buf[i + 64], _MM_HINT_T0);
|
||||
_mm_prefetch(&buf[i + 96], _MM_HINT_T0);
|
||||
_mm_prefetch(&buf[i + 128], _MM_HINT_T0);
|
||||
_mm_prefetch(&buf[i + 160], _MM_HINT_T0);
|
||||
|
||||
// (1*buf[i] + 1*buf[i+1]), (1*buf[i+2], 1*buf[i+3]), ... 2*[int16*16]
|
||||
// (1*buf[i] + 1*buf[i+1]), (1*buf[i+2], 1*buf[i+3]), ... 2*[int16*8]
|
||||
// Fastest, even though multiply by 1
|
||||
__m256i mul_one = _mm256_set1_epi8(1);
|
||||
__m256i add16_1 = _mm256_maddubs_epi16(mul_one, in8_1);
|
||||
__m256i add16_2 = _mm256_maddubs_epi16(mul_one, in8_2);
|
||||
__m128i mul_one = _mm_set1_epi8(1);
|
||||
__m128i add16_1 = SSE2_MADDUBS_EPI16(mul_one, in8_1);
|
||||
__m128i add16_2 = SSE2_MADDUBS_EPI16(mul_one, in8_2);
|
||||
|
||||
// (4*buf[i] + 3*buf[i+1]), (2*buf[i+2], buf[i+3]), ... 2*[int16*16]
|
||||
__m256i mul_const = _mm256_set1_epi32(4 + (3 << 8) + (2 << 16) + (1 << 24));
|
||||
__m256i mul_add16_1 = _mm256_maddubs_epi16(mul_const, in8_1);
|
||||
__m256i mul_add16_2 = _mm256_maddubs_epi16(mul_const, in8_2);
|
||||
// (4*buf[i] + 3*buf[i+1]), (2*buf[i+2], buf[i+3]), ... 2*[int16*8]
|
||||
__m128i mul_const = _mm_set1_epi32(4 + (3 << 8) + (2 << 16) + (1 << 24));
|
||||
__m128i mul_add16_1 = SSE2_MADDUBS_EPI16(mul_const, in8_1);
|
||||
__m128i mul_add16_2 = SSE2_MADDUBS_EPI16(mul_const, in8_2);
|
||||
|
||||
// s2 += 64*s1
|
||||
ss2 = _mm256_add_epi32(ss2, _mm256_slli_epi32(ss1, 6));
|
||||
// s2 += 32*s1
|
||||
ss2 = _mm_add_epi32(ss2, _mm_slli_epi32(ss1, 5));
|
||||
|
||||
// [t1[0] + t1[1], t1[2] + t1[3] ...] [int16*16]
|
||||
__m256i add16 = _mm256_hadds_epi16(add16_1, add16_2);
|
||||
// [sum(t1[0]..t1[7]), X, X, X] [int32*4]; faster than multiple _mm_hadds_epi16
|
||||
// Shifting left, then shifting right again and shuffling (rather than just
|
||||
// shifting right as with mul32 below) to cheaply end up with the correct sign
|
||||
// extension as we go from int16 to int32.
|
||||
__m128i sum_add32 = _mm_add_epi16(add16_1, add16_2);
|
||||
sum_add32 = _mm_add_epi16(sum_add32, _mm_slli_si128(sum_add32, 2));
|
||||
sum_add32 = _mm_add_epi16(sum_add32, _mm_slli_si128(sum_add32, 4));
|
||||
sum_add32 = _mm_add_epi16(sum_add32, _mm_slli_si128(sum_add32, 8));
|
||||
sum_add32 = _mm_srai_epi32(sum_add32, 16);
|
||||
sum_add32 = _mm_shuffle_epi32(sum_add32, 3);
|
||||
|
||||
// [t1[0], t1[1], ...] -> [t1[0]*60 + t1[1]*56, ...] [int32*8]
|
||||
__m256i mul32 = _mm256_madd_epi16(add16, mul_t1);
|
||||
// [sum(t2[0]..t2[7]), X, X, X] [int32*4]; faster than multiple _mm_hadds_epi16
|
||||
__m128i sum_mul_add32 = _mm_add_epi16(mul_add16_1, mul_add16_2);
|
||||
sum_mul_add32 = _mm_add_epi16(sum_mul_add32, _mm_slli_si128(sum_mul_add32, 2));
|
||||
sum_mul_add32 = _mm_add_epi16(sum_mul_add32, _mm_slli_si128(sum_mul_add32, 4));
|
||||
sum_mul_add32 = _mm_add_epi16(sum_mul_add32, _mm_slli_si128(sum_mul_add32, 8));
|
||||
sum_mul_add32 = _mm_srai_epi32(sum_mul_add32, 16);
|
||||
sum_mul_add32 = _mm_shuffle_epi32(sum_mul_add32, 3);
|
||||
|
||||
// [sum(t1[0]..t1[15]), X, X, X, X, X, X, X] [int32*8]
|
||||
__m256i sum_add32 = _mm256_add_epi16(add16_1, add16_2);
|
||||
sum_add32 = _mm256_add_epi16(sum_add32, _mm256_permute4x64_epi64(sum_add32, 2 + (3 << 2) + (0 << 4) + (1 << 6)));
|
||||
sum_add32 = _mm256_add_epi16(sum_add32, _mm256_slli_si256(sum_add32, 2));
|
||||
sum_add32 = _mm256_add_epi16(sum_add32, _mm256_slli_si256(sum_add32, 4));
|
||||
sum_add32 = _mm256_add_epi16(sum_add32, _mm256_slli_si256(sum_add32, 8));
|
||||
sum_add32 = _mm256_srai_epi32(sum_add32, 16);
|
||||
sum_add32 = _mm256_shuffle_epi32(sum_add32, 3);
|
||||
// s1 += t1[0] + t1[1] + t1[2] + t1[3] + t1[4] + t1[5] + t1[6] + t1[7]
|
||||
ss1 = _mm_add_epi32(ss1, sum_add32);
|
||||
|
||||
// s1 += t1[0] + t1[1] + t1[2] + t1[3] + t1[4] + t1[5] + t1[6] + t1[7] + t1[8] + t1[9] + t1[10] + t1[11] + t1[12] + t1[13] + t1[14] + t1[15]
|
||||
ss1 = _mm256_add_epi32(ss1, sum_add32);
|
||||
// s2 += t2[0] + t2[1] + t2[2] + t2[3] + t2[4] + t2[5] + t2[6] + t2[7]
|
||||
ss2 = _mm_add_epi32(ss2, sum_mul_add32);
|
||||
|
||||
// [sum(t2[0]..t2[15]), X, X, X, X, X, X, X] [int32*8]
|
||||
__m256i sum_mul_add32 = _mm256_add_epi16(mul_add16_1, mul_add16_2);
|
||||
sum_mul_add32 = _mm256_add_epi16(sum_mul_add32, _mm256_permute4x64_epi64(sum_mul_add32, 2 + (3 << 2) + (0 << 4) + (1 << 6)));
|
||||
sum_mul_add32 = _mm256_add_epi16(sum_mul_add32, _mm256_slli_si256(sum_mul_add32, 2));
|
||||
sum_mul_add32 = _mm256_add_epi16(sum_mul_add32, _mm256_slli_si256(sum_mul_add32, 4));
|
||||
sum_mul_add32 = _mm256_add_epi16(sum_mul_add32, _mm256_slli_si256(sum_mul_add32, 8));
|
||||
sum_mul_add32 = _mm256_srai_epi32(sum_mul_add32, 16);
|
||||
sum_mul_add32 = _mm256_shuffle_epi32(sum_mul_add32, 3);
|
||||
// [t1[0] + t1[1], t1[2] + t1[3] ...] [int16*8]
|
||||
// We could've combined this with generating sum_add32 above and
|
||||
// save an instruction but benchmarking shows that as being slower
|
||||
__m128i add16 = SSE2_HADDS_EPI16(add16_1, add16_2);
|
||||
|
||||
// s2 += t2[0] + t2[1] + t2[2] + t2[3] + t2[4] + t2[5] + t2[6] + t2[7] + t2[8] + t2[9] + t2[10] + t2[11] + t2[12] + t2[13] + t2[14] + t2[15]
|
||||
ss2 = _mm256_add_epi32(ss2, sum_mul_add32);
|
||||
// [t1[0], t1[1], ...] -> [t1[0]*28 + t1[1]*24, ...] [int32*4]
|
||||
__m128i mul32 = _mm_madd_epi16(add16, mul_t1);
|
||||
|
||||
// [sum(mul32), X, X, X, X, X, X, X] [int32*8]
|
||||
mul32 = _mm256_add_epi32(mul32, _mm256_permute2x128_si256(mul32, mul32, 1));
|
||||
mul32 = _mm256_add_epi32(mul32, _mm256_srli_si256(mul32, 4));
|
||||
mul32 = _mm256_add_epi32(mul32, _mm256_srli_si256(mul32, 8));
|
||||
// [sum(mul32), X, X, X] [int32*4]; faster than multiple _mm_hadd_epi32
|
||||
mul32 = _mm_add_epi32(mul32, _mm_srli_si128(mul32, 4));
|
||||
mul32 = _mm_add_epi32(mul32, _mm_srli_si128(mul32, 8));
|
||||
|
||||
// s2 += 60*t1[0] + 56*t1[1] + 52*t1[2] + 48*t1[3] + 44*t1[4] + 40*t1[5] + 36*t1[6] + 32*t1[7] + 28*t1[8] + 24*t1[9] + 20*t1[10] + 16*t1[11] + 12*t1[12] + 8*t1[13] + 4*t1[14]
|
||||
ss2 = _mm256_add_epi32(ss2, mul32);
|
||||
// s2 += 28*t1[0] + 24*t1[1] + 20*t1[2] + 16*t1[3] + 12*t1[4] + 8*t1[5] + 4*t1[6]
|
||||
ss2 = _mm_add_epi32(ss2, mul32);
|
||||
|
||||
#if CHAR_OFFSET != 0
|
||||
// s1 += 64*CHAR_OFFSET
|
||||
__m256i char_offset_multiplier = _mm256_set1_epi32(64 * CHAR_OFFSET);
|
||||
ss1 = _mm256_add_epi32(ss1, char_offset_multiplier);
|
||||
// s1 += 32*CHAR_OFFSET
|
||||
__m128i char_offset_multiplier = _mm_set1_epi32(32 * CHAR_OFFSET);
|
||||
ss1 = _mm_add_epi32(ss1, char_offset_multiplier);
|
||||
|
||||
// s2 += 2080*CHAR_OFFSET
|
||||
char_offset_multiplier = _mm256_set1_epi32(2080 * CHAR_OFFSET);
|
||||
ss2 = _mm256_add_epi32(ss2, char_offset_multiplier);
|
||||
// s2 += 528*CHAR_OFFSET
|
||||
char_offset_multiplier = _mm_set1_epi32(528 * CHAR_OFFSET);
|
||||
ss2 = _mm_add_epi32(ss2, char_offset_multiplier);
|
||||
#endif
|
||||
}
|
||||
|
||||
_mm256_store_si256((__m256i_u*)x, ss1);
|
||||
_mm_store_si128((__m128i_u*)x, ss1);
|
||||
*ps1 = x[0];
|
||||
_mm256_store_si256((__m256i_u*)x, ss2);
|
||||
_mm_store_si128((__m128i_u*)x, ss2);
|
||||
*ps2 = x[0];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
__attribute__ ((target("default"))) static int32 get_checksum1_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
extern "C" __attribute__ ((target("avx2"))) int32 get_checksum1_avx2(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2);
|
||||
|
||||
__attribute__ ((target("default"))) static int32 get_checksum1_sse2_32(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline int32 get_checksum1_default_1(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
static int32 get_checksum1_default_1(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
uint32 s1 = *ps1;
|
||||
uint32 s2 = *ps2;
|
||||
@@ -403,18 +328,22 @@ static inline int32 get_checksum1_default_1(schar* buf, int32 len, int32 i, uint
|
||||
return i;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
uint32 get_checksum1(char *buf1, int32 len)
|
||||
/* With GCC 10 putting this implementation inside 'extern "C"' causes an
|
||||
assembler error. That worked fine on GCC 5-9 and clang 6-10...
|
||||
*/
|
||||
static inline uint32 get_checksum1_cpp(char *buf1, int32 len)
|
||||
{
|
||||
int32 i = 0;
|
||||
uint32 s1 = 0;
|
||||
uint32 s2 = 0;
|
||||
|
||||
// multiples of 64 bytes using AVX2 (if available)
|
||||
i = get_checksum1_avx2_64((schar*)buf1, len, i, &s1, &s2);
|
||||
i = get_checksum1_avx2((schar*)buf1, len, i, &s1, &s2);
|
||||
|
||||
// multiples of 32 bytes using SSE2/SSSE3 (if available)
|
||||
// multiples of 32 bytes using SSSE3 (if available)
|
||||
i = get_checksum1_ssse3_32((schar*)buf1, len, i, &s1, &s2);
|
||||
|
||||
// multiples of 32 bytes using SSE2 (if available)
|
||||
i = get_checksum1_sse2_32((schar*)buf1, len, i, &s1, &s2);
|
||||
|
||||
// whatever is left
|
||||
@@ -423,7 +352,70 @@ uint32 get_checksum1(char *buf1, int32 len)
|
||||
return (s1 & 0xffff) + (s2 << 16);
|
||||
}
|
||||
|
||||
} // "C"
|
||||
extern "C" {
|
||||
|
||||
uint32 get_checksum1(char *buf1, int32 len)
|
||||
{
|
||||
return get_checksum1_cpp(buf1, len);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#ifdef BENCHMARK_SIMD_CHECKSUM1
|
||||
#pragma clang optimize off
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
|
||||
#define ROUNDS 1024
|
||||
#define BLOCK_LEN 1024*1024
|
||||
|
||||
#ifndef CLOCK_MONOTONIC_RAW
|
||||
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
static void benchmark(const char* desc, int32 (*func)(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2), schar* buf, int32 len) {
|
||||
struct timespec start, end;
|
||||
uint64_t us;
|
||||
uint32_t cs, s1, s2;
|
||||
int i, next;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
|
||||
for (i = 0; i < ROUNDS; i++) {
|
||||
s1 = s2 = 0;
|
||||
next = func((schar*)buf, len, 0, &s1, &s2);
|
||||
get_checksum1_default_1((schar*)buf, len, next, &s1, &s2);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
|
||||
us = next == 0 ? 0 : (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
|
||||
cs = next == 0 ? 0 : (s1 & 0xffff) + (s2 << 16);
|
||||
printf("%-5s :: %5.0f MB/s :: %08x\n", desc, us ? (float)(len / (1024 * 1024) * ROUNDS) / ((float)us / 1000000.0f) : 0, cs);
|
||||
}
|
||||
|
||||
static int32 get_checksum1_auto(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2) {
|
||||
uint32 cs = get_checksum1((char*)buf, len);
|
||||
*ps1 = cs & 0xffff;
|
||||
*ps2 = cs >> 16;
|
||||
return len;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
unsigned char* buf = (unsigned char*)aligned_alloc(64,BLOCK_LEN);
|
||||
for (i = 0; i < BLOCK_LEN; i++) buf[i] = (i + (i % 3) + (i % 11)) % 256;
|
||||
|
||||
benchmark("Auto", get_checksum1_auto, (schar*)buf, BLOCK_LEN);
|
||||
benchmark("Raw-C", get_checksum1_default_1, (schar*)buf, BLOCK_LEN);
|
||||
benchmark("SSE2", get_checksum1_sse2_32, (schar*)buf, BLOCK_LEN);
|
||||
benchmark("SSSE3", get_checksum1_ssse3_32, (schar*)buf, BLOCK_LEN);
|
||||
benchmark("AVX2", get_checksum1_avx2, (schar*)buf, BLOCK_LEN);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
#pragma clang optimize on
|
||||
#endif /* BENCHMARK_SIMD_CHECKSUM1 */
|
||||
|
||||
#endif /* HAVE_SIMD */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
11
socket.c
11
socket.c
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "rsync.h"
|
||||
#include "itypes.h"
|
||||
#include "ifuncs.h"
|
||||
#ifdef HAVE_NETINET_IN_SYSTM_H
|
||||
#include <netinet/in_systm.h>
|
||||
#endif
|
||||
@@ -248,8 +249,6 @@ int open_socket_out(char *host, int port, const char *bind_addr, int af_hint)
|
||||
|
||||
for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {}
|
||||
errnos = new_array0(int, addr_cnt);
|
||||
if (!errnos)
|
||||
out_of_memory("open_socket_out");
|
||||
|
||||
s = -1;
|
||||
/* Try to connect to all addresses for this machine until we get
|
||||
@@ -354,8 +353,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr, int af_
|
||||
len += hlen;
|
||||
}
|
||||
f = prog;
|
||||
if (!(prog = new_array(char, len)))
|
||||
out_of_memory("open_socket_out_wrapped");
|
||||
prog = new_array(char, len);
|
||||
for (t = prog; *f; f++) {
|
||||
if (*f == '%') {
|
||||
switch (*++f) {
|
||||
@@ -423,8 +421,6 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
|
||||
|
||||
socks = new_array(int, maxs + 1);
|
||||
errmsgs = new_array(char *, maxs);
|
||||
if (!socks || !errmsgs)
|
||||
out_of_memory("open_socket_in");
|
||||
|
||||
/* We may not be able to create the socket, if for example the
|
||||
* machine knows about IPv6 in the C library, but not in the
|
||||
@@ -684,9 +680,6 @@ void set_socket_options(int fd, char *options)
|
||||
|
||||
options = strdup(options);
|
||||
|
||||
if (!options)
|
||||
out_of_memory("set_socket_options");
|
||||
|
||||
for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) {
|
||||
int ret=0,i;
|
||||
int value = 1;
|
||||
|
||||
@@ -1,92 +1,94 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
#!/usr/bin/env python3
|
||||
# This script lets you update a hierarchy of files in an atomic way by
|
||||
# first creating a new hierarchy using rsync's --link-dest option, and
|
||||
# then swapping the hierarchy into place. **See the usage message for
|
||||
# more details and some important caveats!**
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd 'abs_path';
|
||||
import os, sys, re, subprocess, shutil
|
||||
|
||||
my $RSYNC_PROG = '/usr/bin/rsync';
|
||||
my $RM_PROG = '/bin/rm';
|
||||
ALT_DEST_ARG_RE = re.compile('^--[a-z][^ =]+-dest(=|$)')
|
||||
|
||||
my $dest_dir = $ARGV[-1];
|
||||
&usage if !defined $dest_dir || $dest_dir =~ /(^-|^$)/ || grep(/^--help/, @ARGV);
|
||||
$dest_dir =~ s{(?<=.)/+$} {};
|
||||
RSYNC_PROG = '/usr/bin/rsync'
|
||||
|
||||
if (!-d $dest_dir) {
|
||||
die "$dest_dir is not a directory.\nUse --help for help.\n";
|
||||
}
|
||||
def main():
|
||||
cmd_args = sys.argv[1:]
|
||||
if '--help' in cmd_args:
|
||||
usage_and_exit()
|
||||
|
||||
if (@_ = grep(/^--[a-z]+-dest\b/, @ARGV)) {
|
||||
$_ = join(' or ', @_);
|
||||
die "You cannot use the $_ option with atomic-rsync.\nUse --help for help.\n";
|
||||
}
|
||||
if len(cmd_args) < 2:
|
||||
usage_and_exit(True)
|
||||
|
||||
my $symlink_content = readlink $dest_dir; # undef when a real dir
|
||||
dest_dir = cmd_args[-1].rstrip('/')
|
||||
if dest_dir == '' or dest_dir.startswith('-'):
|
||||
usage_and_exit(True)
|
||||
|
||||
my $dest_arg = $dest_dir;
|
||||
# This gives us the real destination dir, with all symlinks dereferenced.
|
||||
$dest_dir = abs_path($dest_dir);
|
||||
if ($dest_dir eq '/') {
|
||||
die qq|You must not use "/" as the destination directory.\nUse --help for help.\n|;
|
||||
}
|
||||
if not os.path.isdir(dest_dir):
|
||||
die(dest_dir, "is not a directory or a symlink to a dir.\nUse --help for help.")
|
||||
|
||||
my($old_dir, $new_dir);
|
||||
if (defined $symlink_content && $dest_dir =~ /-([12])$/) {
|
||||
my $num = 3 - $1;
|
||||
$old_dir = undef;
|
||||
($new_dir = $dest_dir) =~ s/-[12]$/-$num/;
|
||||
$symlink_content =~ s/-[12]$/-$num/;
|
||||
} else {
|
||||
$old_dir = "$dest_dir~old~";
|
||||
$new_dir = "$dest_dir~new~";
|
||||
}
|
||||
bad_args = [ arg for arg in cmd_args if ALT_DEST_ARG_RE.match(arg) ]
|
||||
if bad_args:
|
||||
die("You cannot use the", ' or '.join(bad_args), "option with atomic-rsync.\nUse --help for help.")
|
||||
|
||||
$ARGV[-1] = "$new_dir/";
|
||||
# We ignore exit-code 24 (file vanished) by default.
|
||||
allowed_exit_codes = '0 ' + os.environ.get('ATOMIC_RSYNC_OK_CODES', '24')
|
||||
try:
|
||||
allowed_exit_codes = set(int(num) for num in re.split(r'[, ]+', allowed_exit_codes) if num != '')
|
||||
except ValueError:
|
||||
die('Invalid integer in ATOMIC_RSYNC_OK_CODES:', allowed_exit_codes[2:])
|
||||
|
||||
system($RM_PROG, '-rf', $old_dir) if defined $old_dir && -d $old_dir;
|
||||
system($RM_PROG, '-rf', $new_dir) if -d $new_dir;
|
||||
symlink_content = os.readlink(dest_dir) if os.path.islink(dest_dir) else None
|
||||
|
||||
if (system($RSYNC_PROG, "--link-dest=$dest_dir", @ARGV)) {
|
||||
if ($? == -1) {
|
||||
print "failed to execute $RSYNC_PROG: $!\n";
|
||||
} elsif ($? & 127) {
|
||||
printf "child died with signal %d, %s coredump\n",
|
||||
($? & 127), ($? & 128) ? 'with' : 'without';
|
||||
} else {
|
||||
printf "child exited with value %d\n", $? >> 8;
|
||||
}
|
||||
exit 1;
|
||||
}
|
||||
dest_arg = dest_dir
|
||||
dest_dir = os.path.realpath(dest_dir) # The real destination dir with all symlinks dereferenced
|
||||
if dest_dir == '/':
|
||||
die('You must not use "/" as the destination directory.\nUse --help for help.')
|
||||
|
||||
if (!defined $old_dir) {
|
||||
atomic_symlink($symlink_content, $dest_arg);
|
||||
exit;
|
||||
}
|
||||
old_dir = new_dir = None
|
||||
if symlink_content is not None and dest_dir.endswith(('-1','-2')):
|
||||
if not symlink_content.endswith(dest_dir[-2:]):
|
||||
die("Symlink suffix out of sync with dest_dir name:", symlink_content, 'vs', dest_dir)
|
||||
num = 3 - int(dest_dir[-1]);
|
||||
old_dir = None
|
||||
new_dir = dest_dir[:-1] + str(num)
|
||||
symlink_content = symlink_content[:-1] + str(num)
|
||||
else:
|
||||
old_dir = dest_dir + '~old~'
|
||||
new_dir = dest_dir + '~new~'
|
||||
|
||||
rename($dest_dir, $old_dir) or die "Unable to rename $dest_dir to $old_dir: $!";
|
||||
rename($new_dir, $dest_dir) or die "Unable to rename $new_dir to $dest_dir: $!";
|
||||
cmd_args[-1] = new_dir + '/'
|
||||
|
||||
exit;
|
||||
if old_dir is not None and os.path.isdir(old_dir):
|
||||
shutil.rmtree(old_dir)
|
||||
if os.path.isdir(new_dir):
|
||||
shutil.rmtree(new_dir)
|
||||
|
||||
sub atomic_symlink
|
||||
{
|
||||
my($target, $link) = @_;
|
||||
my $newlink = "$link~new~";
|
||||
child = subprocess.run([RSYNC_PROG, '--link-dest=' + dest_dir, *cmd_args])
|
||||
if child.returncode not in allowed_exit_codes:
|
||||
die('The rsync copy failed with code', child.returncode, exitcode=child.returncode)
|
||||
|
||||
unlink($newlink); # Just in case
|
||||
symlink($target, $newlink) or die "Unable to symlink $newlink -> $target: $!\n";
|
||||
rename($newlink, $link) or die "Unable to rename $newlink to $link: $!\n";
|
||||
}
|
||||
if not os.path.isdir(new_dir):
|
||||
die('The rsync copy failed to create:', new_dir)
|
||||
|
||||
if old_dir is None:
|
||||
atomic_symlink(symlink_content, dest_arg)
|
||||
else:
|
||||
os.rename(dest_dir, old_dir)
|
||||
os.rename(new_dir, dest_dir)
|
||||
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: atomic-rsync [RSYNC-OPTIONS] HOST:/SOURCE/DIR/ /DEST/DIR/
|
||||
def atomic_symlink(target, link):
|
||||
newlink = link + "~new~"
|
||||
try:
|
||||
os.unlink(newlink); # Just in case
|
||||
except OSError:
|
||||
pass
|
||||
os.symlink(target, newlink)
|
||||
os.rename(newlink, link)
|
||||
|
||||
|
||||
def usage_and_exit(use_stderr=False):
|
||||
usage_msg = """\
|
||||
Usage: atomic-rsync [RSYNC-OPTIONS] [HOST:]/SOURCE/DIR/ /DEST/DIR/
|
||||
atomic-rsync [RSYNC-OPTIONS] HOST::MOD/DIR/ /DEST/DIR/
|
||||
|
||||
This script lets you update a hierarchy of files in an atomic way by first
|
||||
@@ -96,27 +98,41 @@ to a local directory, and that directory must already exist. For example:
|
||||
|
||||
mkdir /local/files-1
|
||||
ln -s files-1 /local/files
|
||||
atomic-rsync -av host:/remote/files/ /local/files/
|
||||
atomic-rsync -aiv host:/remote/files/ /local/files/
|
||||
|
||||
If /local/files is a symlink to a directory that ends in -1 or -2, the
|
||||
copy will go to the alternate suffix and the symlink will be changed to
|
||||
point to the new dir. This is a fully atomic update. If the destination
|
||||
is not a symlink (or not a symlink to a *-1 or a *-2 directory), this
|
||||
will instead create a directory with "~new~" suffixed, move the current
|
||||
directory to a name with "~old~" suffixed, and then move the ~new~
|
||||
directory to the original destination name (this double rename is not
|
||||
fully atomic, but is rapid). In both cases, the prior destintaion
|
||||
directory will be preserved until the next update, at which point it
|
||||
will be deleted.
|
||||
If /local/files is a symlink to a directory that ends in -1 or -2, the copy
|
||||
will go to the alternate suffix and the symlink will be changed to point to
|
||||
the new dir. This is a fully atomic update. If the destination is not a
|
||||
symlink (or not a symlink to a *-1 or a *-2 directory), this will instead
|
||||
create a directory with "~new~" suffixed, move the current directory to a
|
||||
name with "~old~" suffixed, and then move the ~new~ directory to the original
|
||||
destination name (this double rename is not fully atomic, but is rapid). In
|
||||
both cases, the prior destintaion directory will be preserved until the next
|
||||
update, at which point it will be deleted.
|
||||
|
||||
In all likelihood, you do NOT want to specify this command:
|
||||
By default, rsync exit-code 24 (file vanished) is allowed without halting the
|
||||
atomic update. If you want to change that, specify the environment variable
|
||||
ATOMIC_RSYNC_OK_CODES with numeric values separated by spaces and/or commas.
|
||||
Specify an empty string to only allow a successful copy. An override example:
|
||||
|
||||
atomic-rsync -av host:/remote/files /local/
|
||||
ATOMIC_RSYNC_OK_CODES='23 24' atomic-rsync -aiv host:src/ dest/
|
||||
|
||||
... UNLESS you want the entire /local dir to be swapped out!
|
||||
See the errcode.h file for a list of all the exit codes.
|
||||
|
||||
See the "rsync" command for its list of options. You may not use the
|
||||
--link-dest, --compare-dest, or --copy-dest options (since this script
|
||||
uses --link-dest to make the transfer efficient).
|
||||
EOT
|
||||
}
|
||||
"""
|
||||
print(usage_msg, file=sys.stderr if use_stderr else sys.stdout)
|
||||
sys.exit(1 if use_stderr else 0)
|
||||
|
||||
|
||||
def die(*args, exitcode=1):
|
||||
print(*args, file=sys.stderr)
|
||||
sys.exit(exitcode)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
|
||||
@@ -27,11 +27,12 @@ def main():
|
||||
|
||||
if not args.tree:
|
||||
# All modified files keep their current mtime.
|
||||
proc = subprocess.Popen(git + 'ls-files -m -z'.split(), stdout=subprocess.PIPE, encoding='utf-8')
|
||||
proc = subprocess.Popen(git + 'status -z --no-renames'.split(), stdout=subprocess.PIPE, encoding='utf-8')
|
||||
out = proc.communicate()[0]
|
||||
for fn in out.split('\0'):
|
||||
if fn == '':
|
||||
if fn == '' or (fn[0] != 'M' and fn[1] != 'M'):
|
||||
continue
|
||||
fn = fn[3:]
|
||||
if args.list:
|
||||
mtime = os.lstat(fn).st_mtime
|
||||
print_line(fn, mtime, mtime)
|
||||
@@ -79,10 +80,10 @@ def print_line(fn, mtime, commit_time):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Set the times of the current git checkout to their last-changed time.", add_help=False)
|
||||
parser = argparse.ArgumentParser(description="Set the times of the files in the current git checkout to their last-changed time.", add_help=False)
|
||||
parser.add_argument('--git-dir', metavar='GIT_DIR', help="The git dir to query (defaults to affecting the current git checkout).")
|
||||
parser.add_argument('--tree', metavar='TREE-ISH', help="The tree-ish to query (defaults to the current branch).")
|
||||
parser.add_argument('--prefix', metavar='PREFIX_STR', help="Prepend the PREFIX_STR to each filename we tweak.")
|
||||
parser.add_argument('--prefix', metavar='PREFIX_STR', help="Prepend the PREFIX_STR to each filename we tweak (defaults to the top of current checkout).")
|
||||
parser.add_argument('--quiet', '-q', action='store_true', help="Don't output the changed-file information.")
|
||||
parser.add_argument('--list', '-l', action='count', help="List files & times instead of changing them. Repeat for Unix timestamp instead of human readable.")
|
||||
parser.add_argument('files', metavar='FILE', nargs='*', help="Specify a subset of checked-out files to tweak.")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user