mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-24 23:05:52 -04:00
Compare commits
300 Commits
v3.2.0pre3
...
v3.2.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
22
.cirrus.yml
Normal file
22
.cirrus.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
freebsd_task:
|
||||
name: FreeBSD
|
||||
freebsd_instance:
|
||||
image: freebsd-12-1-release-amd64
|
||||
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 autotools xxhash zstd liblz4
|
||||
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_MAX_SKIPPED=3 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
|
||||
117
.github/workflows/build.yml
vendored
Normal file
117
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
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
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: prep
|
||||
run: |
|
||||
sudo apt-get install acl libacl1-dev attr libattr1-dev liblz4-dev libzstd-dev libxxhash-dev python3-cmarkgfm openssl
|
||||
echo "::add-path::/usr/local/bin"
|
||||
- name: configure
|
||||
run: ./configure
|
||||
- name: make
|
||||
run: make
|
||||
- name: install
|
||||
run: sudo make install
|
||||
- name: info
|
||||
run: rsync --version
|
||||
- name: check
|
||||
run: sudo RSYNC_MAX_SKIPPED=1 make check
|
||||
- name: check30
|
||||
run: sudo RSYNC_MAX_SKIPPED=1 make check30
|
||||
- name: check29
|
||||
run: sudo RSYNC_MAX_SKIPPED=1 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
|
||||
|
||||
macos-build:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: prep
|
||||
run: |
|
||||
brew install automake openssl xxhash zstd lz4
|
||||
sudo pip3 install commonmark
|
||||
echo "::add-path::/usr/local/bin"
|
||||
- name: configure
|
||||
run: CPPFLAGS=-I/usr/local/opt/openssl/include/ LDFLAGS=-L/usr/local/opt/openssl/lib/ ./configure
|
||||
- name: make
|
||||
run: make
|
||||
- name: install
|
||||
run: sudo make install
|
||||
- name: info
|
||||
run: rsync --version
|
||||
- name: check
|
||||
run: sudo 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
|
||||
|
||||
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 python3 python36-commonmark libzstd-devel liblz4-devel libssl-devel
|
||||
echo "::add-path::C:/tools/cygwin/bin"
|
||||
- name: configure
|
||||
run: bash -c './configure --disable-xxhash'
|
||||
- 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 '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
|
||||
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
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -19,6 +19,9 @@ aclocal.m4
|
||||
/rsync*.5
|
||||
/rsync*.html
|
||||
/help-rsync*.h
|
||||
/default-cvsignore.h
|
||||
/default-dont-compress.h
|
||||
/daemon-parm.h
|
||||
/.md2man-works
|
||||
/autom4te*.cache
|
||||
/confdefs.h
|
||||
@@ -29,6 +32,7 @@ aclocal.m4
|
||||
/rsync
|
||||
/stunnel-rsyncd.conf
|
||||
/shconfig
|
||||
/git-version.h
|
||||
/testdir
|
||||
/tests-dont-exist
|
||||
/testtmp
|
||||
@@ -46,5 +50,8 @@ aclocal.m4
|
||||
/testsuite/devices-fake.test
|
||||
/testsuite/xattrs-hlink.test
|
||||
/patches
|
||||
/SaVeDiR
|
||||
/patches.gen
|
||||
/build
|
||||
/auto-build-save
|
||||
.deps
|
||||
/*.exe
|
||||
|
||||
215
INSTALL.md
215
INSTALL.md
@@ -1,13 +1,165 @@
|
||||
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):
|
||||
|
||||
> pip3 install --user commonmark
|
||||
|
||||
You can test if you've got it fixed by running (from the src dir):
|
||||
|
||||
> ./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.
|
||||
|
||||
[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 libzlz4-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
|
||||
> pip3 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,python3,python36-commonmark
|
||||
> 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
|
||||
|
||||
## 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
|
||||
@@ -25,50 +177,59 @@ 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
|
||||
|
||||
100
Makefile.in
100
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@
|
||||
@@ -10,6 +9,7 @@ mandir=@mandir@
|
||||
|
||||
LIBS=@LIBS@
|
||||
CC=@CC@
|
||||
AWK=@AWK@
|
||||
CFLAGS=@CFLAGS@
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
CXX=@CXX@
|
||||
@@ -26,17 +26,16 @@ 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
|
||||
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 version.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 \
|
||||
@@ -44,8 +43,8 @@ zlib_OBJS=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.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
|
||||
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@
|
||||
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
|
||||
@@ -68,28 +67,28 @@ 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@
|
||||
|
||||
.PHONY: all
|
||||
all: Makefile rsync$(EXEEXT) stunnel-rsyncd.conf @MAKE_MAN@
|
||||
.PHONY: all
|
||||
|
||||
.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
|
||||
|
||||
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
|
||||
@@ -99,12 +98,20 @@ rsync$(EXEEXT): $(OBJS)
|
||||
|
||||
$(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: 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 +131,17 @@ 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
|
||||
# While $(wildcard ...) is a GNU make idiom, at least other makes should just turn it into an
|
||||
# empty string (we need something that will vanish if we're not building a git checkout).
|
||||
# If you want an updated git version w/o GNU make, remove git-version.h after a pull.
|
||||
git-version.h: mkgitver $(wildcard $(srcdir)/.git/logs/HEAD)
|
||||
$(srcdir)/mkgitver
|
||||
|
||||
lib/md5-asm-x86_64.o: lib/md5-asm-x86_64.s
|
||||
$(CC) -c -o $@ $(srcdir)/lib/md5-asm-x86_64.s
|
||||
simd-checksum-x86_64.o: simd-checksum-x86_64.cpp
|
||||
@$(srcdir)/cmdormsg disable-simd $(CXX) -I. $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $(srcdir)/simd-checksum-x86_64.cpp
|
||||
|
||||
lib/md5-asm-x86_64.o: lib/md5-asm-x86_64.S config.h lib/md-defines.h
|
||||
@$(srcdir)/cmdormsg 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)
|
||||
@@ -195,6 +208,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 +236,26 @@ 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
|
||||
|
||||
rsync.1: rsync.1.md md2man NEWS.md Makefile
|
||||
rsync.1: rsync.1.md md2man version.h Makefile
|
||||
@$(srcdir)/maybe-make-man $(srcdir) rsync.1.md
|
||||
|
||||
rsync-ssl.1: rsync-ssl.1.md md2man NEWS.md Makefile
|
||||
rsync-ssl.1: rsync-ssl.1.md md2man version.h Makefile
|
||||
@$(srcdir)/maybe-make-man $(srcdir) rsync-ssl.1.md
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.5.md md2man NEWS.md Makefile
|
||||
rsyncd.conf.5: rsyncd.conf.5.md md2man version.h Makefile
|
||||
@$(srcdir)/maybe-make-man $(srcdir) rsyncd.conf.5.md
|
||||
|
||||
.PHONY: clean
|
||||
clean: cleantests
|
||||
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
rounding rounding.h *.old rsync*.1 rsync*.5 rsync*.html
|
||||
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 +266,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 +280,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
70
README.md
70
README.md
@@ -26,6 +26,15 @@ options. To get a complete list of supported options type:
|
||||
See the manpage for more detailed information.
|
||||
|
||||
|
||||
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 +72,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 +86,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 +117,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
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/
|
||||
|
||||
|
||||
-- --
|
||||
|
||||
15
access.c
15
access.c
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
|
||||
static int allow_forward_dns;
|
||||
|
||||
@@ -33,6 +34,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 +58,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 +245,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")) {
|
||||
|
||||
16
acls.c
16
acls.c
@@ -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++) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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++;
|
||||
|
||||
@@ -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 {
|
||||
@@ -481,7 +481,7 @@ 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 (strchr(s, ':') == NULL && strchr(s, '.') != NULL) {
|
||||
if ((!saw_double_colon && count != 6) || (saw_double_colon && count > 6))
|
||||
|
||||
265
clientserver.c
265
clientserver.c
@@ -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)
|
||||
@@ -391,13 +423,13 @@ void set_env_num(const char *var, long num)
|
||||
}
|
||||
#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 +438,36 @@ 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++) {
|
||||
char *p;
|
||||
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);
|
||||
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) >= 0)
|
||||
putenv(p);
|
||||
}
|
||||
|
||||
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 +479,18 @@ 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)
|
||||
static void write_pre_exec_args(int write_fd, char *request, char **early_argv, char **argv, int exec_type)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
@@ -475,11 +503,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 +695,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 +716,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 +749,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 +786,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 ((*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 +838,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 +846,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 +865,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 +916,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 +968,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 +999,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 +1026,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 +1051,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 +1112,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 +1137,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 +1258,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 +1277,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 +1451,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
cmdormsg
Executable file
11
cmdormsg
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
|
||||
198
compat.c
198
compat.c
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "itypes.h"
|
||||
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
@@ -42,6 +43,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;
|
||||
@@ -72,9 +74,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 +111,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;
|
||||
|
||||
@@ -173,6 +177,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 +247,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 +266,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 +287,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 +303,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 +331,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 +362,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 +461,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 +482,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 +505,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 +516,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,6 +556,8 @@ 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 (preserve_crtimes)
|
||||
crtimes_ndx = (file_extra_cnt += EXTRA64_CNT);
|
||||
if (am_sender) /* This is most likely in the in64 union as well. */
|
||||
pathname_ndx = (file_extra_cnt += PTR_EXTRA_CNT);
|
||||
else
|
||||
@@ -601,11 +699,11 @@ void setup_protocol(int f_out,int f_in)
|
||||
compat_flags |= CF_CHKSUM_SEED_FIX;
|
||||
if (local_server || strchr(client_info, 'I') != NULL)
|
||||
compat_flags |= CF_INPLACE_PARTIAL_DIR;
|
||||
if (local_server || strchr(client_info, 'u') != NULL)
|
||||
compat_flags |= CF_ID0_NAMES;
|
||||
if (local_server || strchr(client_info, 'v') != NULL) {
|
||||
if (!write_batch || protocol_version >= 30) {
|
||||
do_negotiated_strings = 1;
|
||||
compat_flags |= CF_VARINT_FLIST_FLAGS;
|
||||
}
|
||||
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 +721,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
|
||||
@@ -654,6 +757,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" "${@}"
|
||||
|
||||
207
configure.ac
207
configure.ac
@@ -1,16 +1,15 @@
|
||||
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_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-""}
|
||||
|
||||
@@ -42,6 +41,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,6 +57,11 @@ 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]))
|
||||
if test x"$enable_profile" = x"yes"; then
|
||||
@@ -68,7 +73,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
|
||||
@@ -88,8 +93,10 @@ if test x"$enable_md2man" != x"no"; then
|
||||
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
|
||||
@@ -197,35 +204,104 @@ 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([--disable-simd],[disable SIMD optimizations (requires c++)]))
|
||||
|
||||
if test x"$enable_simd" = x"yes"; then
|
||||
# For x86-64 SIMD, g++ is also required
|
||||
# Clag is crashing with -g -O2, so we'll get rid of -g for now.
|
||||
CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-g //'`
|
||||
|
||||
if test x"$enable_simd" != x"no"; then
|
||||
# For x86-64 SIMD, g++ >=5 or clang++ >=7 is 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"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR(Failed to find g++ for SIMD speedups.
|
||||
AC_LANG(C++)
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
|
||||
#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_ssse3(42) != 42 || test_sse2(42) != 42 || test_avx2(42) != 42) exit(1);]])],[CXX_OK=yes],[CXX_OK=no])
|
||||
AC_LANG(C)
|
||||
if test x"$CXX_OK" = x"yes"; then
|
||||
# AC_MSG_RESULT() is called below.
|
||||
SIMD="x86_64"
|
||||
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 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([--disable-asm],[disable ASM optimizations]))
|
||||
|
||||
if test x"$enable_asm" != x"no"; then
|
||||
if test x"$build_cpu" = x"x86_64"; then
|
||||
ASM="$build_cpu"
|
||||
elif test x"$enable_asm" = x"yes"; then
|
||||
AC_MSG_RESULT(unavailable)
|
||||
AC_MSG_ERROR(The ASM optimizations are currently x86_64 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,[
|
||||
@@ -277,7 +353,7 @@ 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
|
||||
for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta cygwin TANDEM; do
|
||||
case $i in
|
||||
inria)
|
||||
# http://www.kame.net/
|
||||
@@ -369,6 +445,15 @@ yes
|
||||
#include <netinet/in.h>
|
||||
#ifdef _CYGWIN_IN6_H
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
TANDEM)
|
||||
AC_EGREP_CPP(yes, [
|
||||
#include <netinet/ip6.h>
|
||||
#ifdef __TANDEM
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
@@ -410,9 +495,9 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.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 \
|
||||
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 netinet/ip.h \
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h)
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h sys/file.h)
|
||||
AC_HEADER_MAJOR_FIXED
|
||||
|
||||
AC_MSG_CHECKING([whether to enable use of openssl crypto library])
|
||||
@@ -425,12 +510,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)
|
||||
@@ -446,12 +531,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)
|
||||
@@ -467,12 +552,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)
|
||||
@@ -488,17 +573,34 @@ 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([[
|
||||
#include <sys/types.h>
|
||||
@@ -630,7 +732,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,
|
||||
@@ -742,9 +844,9 @@ 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 \
|
||||
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
|
||||
@@ -868,6 +970,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 +985,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
|
||||
@@ -1143,11 +1254,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,6 +1275,11 @@ 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)
|
||||
@@ -1212,7 +1323,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)
|
||||
@@ -1268,5 +1379,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;
|
||||
}
|
||||
|
||||
|
||||
138
flist.c
138
flist.c
@@ -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);
|
||||
|
||||
@@ -301,8 +303,7 @@ 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) {
|
||||
rprintf(FCLIENT, "[%s] expand file_list pointer array to %s bytes, did%s move\n",
|
||||
@@ -312,9 +313,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 +379,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 +448,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 +487,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 +581,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 +677,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 +699,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 +788,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 +832,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 +1035,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 +1382,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 +1436,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);
|
||||
#endif
|
||||
|
||||
if (basename != thisname)
|
||||
file->dirname = lastdir;
|
||||
@@ -1661,8 +1710,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 +1943,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 +2105,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;
|
||||
|
||||
@@ -2414,10 +2458,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 +2467,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)
|
||||
@@ -2597,10 +2639,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 +2650,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 +2782,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 +2844,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;
|
||||
|
||||
53
generator.c
53
generator.c
@@ -84,7 +84,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;
|
||||
@@ -396,6 +396,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);
|
||||
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 +463,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_times & PRESERVE_LINK_TIMES && any_time_differs(sxp, file, fname))
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef CAN_CHMOD_SYMLINK
|
||||
@@ -470,7 +483,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_times && any_time_differs(sxp, file, fname))
|
||||
return 0;
|
||||
if (perms_differ(file, sxp))
|
||||
return 0;
|
||||
@@ -512,6 +525,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);
|
||||
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)) {
|
||||
;
|
||||
@@ -1131,6 +1152,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 +1163,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 +1180,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);
|
||||
}
|
||||
}
|
||||
@@ -1255,6 +1278,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
return;
|
||||
}
|
||||
}
|
||||
sx.crtime = 0;
|
||||
|
||||
if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
|
||||
int i;
|
||||
@@ -1277,20 +1301,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;
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
9
hlink.c
9
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]))
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
ifuncs.h
15
ifuncs.h
@@ -1,6 +1,6 @@
|
||||
/* Inline functions for rsync.
|
||||
*
|
||||
* 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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -104,3 +101,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;
|
||||
}
|
||||
|
||||
66
io.c
66
io.c
@@ -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;
|
||||
@@ -463,7 +465,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 +483,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;
|
||||
@@ -565,7 +567,7 @@ static char *perform_io(size_t needed, int flags)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, %sinput)\n",
|
||||
who_am_i(), (long)needed, flags & PIO_CONSUME_INPUT ? "consume&" : "");
|
||||
}
|
||||
@@ -579,7 +581,7 @@ static char *perform_io(size_t needed, int flags)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, outroom) needs to flush %ld\n",
|
||||
who_am_i(), (long)needed,
|
||||
iobuf.out.len + needed > iobuf.out.size
|
||||
@@ -595,7 +597,7 @@ static char *perform_io(size_t needed, int flags)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3)) {
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, msgroom) needs to flush %ld\n",
|
||||
who_am_i(), (long)needed,
|
||||
iobuf.msg.len + needed > iobuf.msg.size
|
||||
@@ -604,7 +606,7 @@ static char *perform_io(size_t needed, int flags)
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 3))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 3))
|
||||
rprintf(FINFO, "[%s] perform_io(%ld, %d)\n", who_am_i(), (long)needed, flags);
|
||||
break;
|
||||
|
||||
@@ -662,7 +664,7 @@ 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)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 1)) {
|
||||
rprintf(FINFO, "[%s] send_msg(%d, %ld)\n",
|
||||
who_am_i(), (int)MSG_DATA, (long)iobuf.out.len - 4);
|
||||
}
|
||||
@@ -782,12 +784,16 @@ static char *perform_io(size_t needed, int flags)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
}
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2))
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2))
|
||||
rprintf(FINFO, "[%s] recv=%ld\n", who_am_i(), (long)n);
|
||||
|
||||
if (io_timeout) {
|
||||
if (io_timeout || stop_at_utime) {
|
||||
last_io_in = time(NULL);
|
||||
if (flags & PIO_NEED_INPUT)
|
||||
if (stop_at_utime && last_io_in >= stop_at_utime) {
|
||||
rprintf(FERROR, "stopping at requested limit\n");
|
||||
exit_cleanup(RERR_TIMEOUT);
|
||||
}
|
||||
if (io_timeout && flags & PIO_NEED_INPUT)
|
||||
maybe_send_keepalive(last_io_in, 0);
|
||||
}
|
||||
stats.total_read += n;
|
||||
@@ -817,7 +823,7 @@ static char *perform_io(size_t needed, int flags)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
}
|
||||
if (msgs2stderr && DEBUG_GTE(IO, 2)) {
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 2)) {
|
||||
rprintf(FINFO, "[%s] %s sent=%ld\n",
|
||||
who_am_i(), out == &iobuf.out ? "out" : "msg", (long)n);
|
||||
}
|
||||
@@ -912,7 +918,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,7 +940,7 @@ 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;
|
||||
@@ -1239,8 +1249,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 +1262,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 +1270,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 +1279,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 +1295,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 +1314,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 +1333,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 +1348,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,7 +1436,7 @@ static void read_a_msg(void)
|
||||
msg_bytes = tag & 0xFFFFFF;
|
||||
tag = (tag >> 24) - MPLEX_BASE;
|
||||
|
||||
if (DEBUG_GTE(IO, 1) && msgs2stderr)
|
||||
if (msgs2stderr == 1 && DEBUG_GTE(IO, 1))
|
||||
rprintf(FINFO, "[%s] got msg=%d, len=%ld\n", who_am_i(), (int)tag, (long)msg_bytes);
|
||||
|
||||
switch (tag) {
|
||||
@@ -2302,7 +2308,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 +2325,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 +2336,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 +2354,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)
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -45,13 +45,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 (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 +169,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);
|
||||
|
||||
622
lib/sysacls.c
622
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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
459
loadparm.c
459
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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
25
log.c
25
log.c
@@ -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
|
||||
@@ -716,8 +720,9 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
|
||||
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';
|
||||
@@ -886,10 +891,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
123
main.c
123
main.c
@@ -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;
|
||||
@@ -92,6 +97,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 +109,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 +304,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] = ':';
|
||||
@@ -512,8 +518,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 +567,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 +592,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 +604,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 +657,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 +665,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 +683,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 +716,26 @@ 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 ret = make_path(dest_path, file_total > 1 && !trailing_slash ? 0 : MKP_DROP_NAME);
|
||||
if (ret < 0)
|
||||
goto mkdir_error;
|
||||
if (INFO_GTE(NAME, 1)) {
|
||||
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 (file_total > 1 || trailing_slash)
|
||||
statret = do_stat(dest_path, &st);
|
||||
}
|
||||
|
||||
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 +765,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 +778,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);
|
||||
@@ -824,8 +845,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 +1003,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 +1126,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 +1375,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 +1401,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 +1429,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 +1461,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 +1482,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 +1531,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,7 +1562,7 @@ 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);
|
||||
#endif
|
||||
|
||||
@@ -1535,7 +1570,7 @@ static int start_client(int argc, char *argv[])
|
||||
|
||||
/* 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 +1602,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))
|
||||
{
|
||||
@@ -1682,7 +1719,7 @@ 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;
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
65
md2man
65
md2man
@@ -35,6 +35,7 @@ body, b, strong, u {
|
||||
code {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-weight: bold;
|
||||
white-space: pre;
|
||||
}
|
||||
pre code {
|
||||
display: block;
|
||||
@@ -64,7 +65,9 @@ MAN_END = """\
|
||||
|
||||
NORM_FONT = ('\1', r"\fP")
|
||||
BOLD_FONT = ('\2', r"\fB")
|
||||
ULIN_FONT = ('\3', r"\fI")
|
||||
UNDR_FONT = ('\3', r"\fI")
|
||||
NBR_DASH = ('\4', r"\-")
|
||||
NBR_SPACE = ('\xa0', r"\ ")
|
||||
|
||||
md_parser = None
|
||||
|
||||
@@ -80,8 +83,9 @@ def main():
|
||||
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()))
|
||||
git_dir = fi.srcdir + '.git'
|
||||
if os.path.lexists(git_dir):
|
||||
fi.mtime = int(subprocess.check_output(['git', '--git-dir', git_dir, 'log', '-1', '--format=%at']))
|
||||
|
||||
env_subs = { 'prefix': os.environ.get('RSYNC_OVERRIDE_PREFIX', None) }
|
||||
|
||||
@@ -89,26 +93,31 @@ def main():
|
||||
env_subs['VERSION'] = '1.0.0'
|
||||
env_subs['libdir'] = '/usr'
|
||||
else:
|
||||
for fn in 'NEWS.md Makefile'.split():
|
||||
for fn in (fi.srcdir + 'version.h', 'Makefile'):
|
||||
try:
|
||||
st = os.lstat(fi.srcdir + fn)
|
||||
st = os.lstat(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:
|
||||
with open(fi.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[1], m[2])
|
||||
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[1]], val)
|
||||
val = re.sub(r'\$\{(\w+)\}', lambda m: env_subs[m.group(1)], val)
|
||||
env_subs[var] = val
|
||||
if var == 'VERSION':
|
||||
if var == 'srcdir':
|
||||
break
|
||||
|
||||
with open(fi.fn, 'r', encoding='utf-8') as fh:
|
||||
@@ -135,10 +144,6 @@ def main():
|
||||
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))
|
||||
|
||||
@@ -212,7 +217,7 @@ class HtmlToManPage(HTMLParser):
|
||||
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]
|
||||
st.txt += UNDR_FONT[0]
|
||||
elif tag == 'ol':
|
||||
start = 1
|
||||
for var, val in attrs_list:
|
||||
@@ -305,15 +310,21 @@ class HtmlToManPage(HTMLParser):
|
||||
st.at_first_tag_in_dd = True
|
||||
|
||||
|
||||
def handle_data(self, data):
|
||||
def handle_data(self, txt):
|
||||
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
|
||||
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):
|
||||
@@ -331,17 +342,15 @@ class HtmlToManPage(HTMLParser):
|
||||
|
||||
def manify(txt):
|
||||
return re.sub(r"^(['.])", r'\&\1', txt.replace('\\', '\\\\')
|
||||
.replace("\xa0", r'\ ') # non-breaking space
|
||||
.replace('--', r'\-\-') # non-breaking double dash
|
||||
.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(ULIN_FONT[0], ULIN_FONT[1]), flags=re.M)
|
||||
.replace(UNDR_FONT[0], UNDR_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", ' '))
|
||||
return txt.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def warn(*msg):
|
||||
@@ -363,7 +372,7 @@ if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
import cmarkgfm
|
||||
md_parser = html_via_cmarkgfm
|
||||
md_parser = cmarkgfm.markdown_to_html
|
||||
except:
|
||||
try:
|
||||
import commonmark
|
||||
|
||||
11
mkgitver
Executable file
11
mkgitver
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
srcdir=`dirname $0`
|
||||
gitver=`git describe --abbrev=8 2>/dev/null`
|
||||
|
||||
if test x"$gitver" != x; then
|
||||
gitver=\""$gitver"\"
|
||||
else
|
||||
gitver=RSYNC_VERSION
|
||||
fi
|
||||
echo "#define RSYNC_GITVER $gitver" >git-version.h
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
609
options.c
609
options.c
@@ -21,16 +21,13 @@
|
||||
|
||||
#include "rsync.h"
|
||||
#include "itypes.h"
|
||||
#include "latest-year.h"
|
||||
#include "ifuncs.h"
|
||||
#include <popt.h>
|
||||
|
||||
extern int module_id;
|
||||
extern int local_server;
|
||||
extern int sanitize_paths;
|
||||
extern int daemon_over_rsh;
|
||||
extern unsigned int module_dirlen;
|
||||
extern struct name_num_obj valid_checksums;
|
||||
extern struct name_num_obj valid_compressions;
|
||||
extern filter_rule_list filter_list;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
|
||||
@@ -63,6 +60,7 @@ int preserve_uid = 0;
|
||||
int preserve_gid = 0;
|
||||
int preserve_times = 0;
|
||||
int preserve_atimes = 0;
|
||||
int preserve_crtimes = 0;
|
||||
int update_only = 0;
|
||||
int open_noatime = 0;
|
||||
int cvs_exclude = 0;
|
||||
@@ -89,7 +87,7 @@ int relative_paths = -1;
|
||||
int implied_dirs = 1;
|
||||
int missing_args = 0; /* 0 = FERROR_XFER, 1 = ignore, 2 = delete */
|
||||
int numeric_ids = 0;
|
||||
int msgs2stderr = 0;
|
||||
int msgs2stderr = 2; /* Default: send errors to stderr for local & remote-shell transfers */
|
||||
int allow_8bit_chars = 0;
|
||||
int force_delete = 0;
|
||||
int io_timeout = 0;
|
||||
@@ -102,6 +100,7 @@ int eol_nulls = 0;
|
||||
int protect_args = -1;
|
||||
int human_readable = 1;
|
||||
int recurse = 0;
|
||||
int mkpath_dest_arg = 0;
|
||||
int allow_inc_recurse = 1;
|
||||
int xfer_dirs = -1;
|
||||
int am_daemon = 0;
|
||||
@@ -127,7 +126,8 @@ int blocking_io = -1;
|
||||
int checksum_seed = 0;
|
||||
int inplace = 0;
|
||||
int delay_updates = 0;
|
||||
long block_size = 0; /* "long" because popt can't set an int32. */
|
||||
int32 block_size = 0;
|
||||
time_t stop_at_utime = 0;
|
||||
char *skip_compress = NULL;
|
||||
char *copy_as = NULL;
|
||||
item_list dparam_list = EMPTY_ITEM_LIST;
|
||||
@@ -170,6 +170,7 @@ char *logfile_name = NULL;
|
||||
char *logfile_format = NULL;
|
||||
char *stdout_format = NULL;
|
||||
char *password_file = NULL;
|
||||
char *early_input_file = NULL;
|
||||
char *rsync_path = RSYNC_PATH;
|
||||
char *backup_dir = NULL;
|
||||
char backup_dir_buf[MAXPATHLEN];
|
||||
@@ -180,6 +181,11 @@ int rsync_port = 0;
|
||||
int alt_dest_type = 0;
|
||||
int basis_dir_cnt = 0;
|
||||
|
||||
#define DEFAULT_MAX_ALLOC (1024L * 1024 * 1024)
|
||||
size_t max_alloc = DEFAULT_MAX_ALLOC;
|
||||
char *max_alloc_arg;
|
||||
|
||||
static int version_opt_cnt = 0;
|
||||
static int remote_option_alloc = 0;
|
||||
int remote_option_cnt = 0;
|
||||
const char **remote_options = NULL;
|
||||
@@ -376,8 +382,7 @@ static char *make_output_option(struct output_struct *words, short *levels, ucha
|
||||
return NULL;
|
||||
|
||||
len++;
|
||||
if (!(buf = new_array(char, len)))
|
||||
out_of_memory("make_output_option");
|
||||
buf = new_array(char, len);
|
||||
pos = 0;
|
||||
|
||||
if (skipped || max < 5)
|
||||
@@ -563,182 +568,14 @@ void negate_output_levels(void)
|
||||
debug_levels[j] *= -1;
|
||||
}
|
||||
|
||||
static char *istring(const char *fmt, int val)
|
||||
{
|
||||
char *str;
|
||||
if (asprintf(&str, fmt, val) < 0)
|
||||
out_of_memory("istring");
|
||||
return str;
|
||||
}
|
||||
|
||||
static void print_capabilities(enum logcode f)
|
||||
{
|
||||
STRUCT_STAT *dumstat;
|
||||
char line_buf[75];
|
||||
int line_len, j;
|
||||
char *capabilities[] = {
|
||||
istring("%d-bit files", (int)(sizeof (OFF_T) * 8)),
|
||||
istring("%d-bit inums", (int)(sizeof dumstat->st_ino * 8)), /* Don't check ino_t! */
|
||||
istring("%d-bit timestamps", (int)(sizeof (time_t) * 8)),
|
||||
istring("%d-bit long ints", (int)(sizeof (int64) * 8)),
|
||||
|
||||
#ifndef HAVE_SOCKETPAIR
|
||||
"no "
|
||||
#endif
|
||||
"socketpairs",
|
||||
|
||||
#ifndef SUPPORT_HARD_LINKS
|
||||
"no "
|
||||
#endif
|
||||
"hardlinks",
|
||||
|
||||
#ifndef SUPPORT_LINKS
|
||||
"no "
|
||||
#endif
|
||||
"symlinks",
|
||||
|
||||
#ifndef INET6
|
||||
"no "
|
||||
#endif
|
||||
"IPv6",
|
||||
|
||||
"batchfiles",
|
||||
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
"no "
|
||||
#endif
|
||||
"inplace",
|
||||
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
"no "
|
||||
#endif
|
||||
"append",
|
||||
|
||||
#ifndef SUPPORT_ACLS
|
||||
"no "
|
||||
#endif
|
||||
"ACLs",
|
||||
|
||||
#ifndef SUPPORT_XATTRS
|
||||
"no "
|
||||
#endif
|
||||
"xattrs",
|
||||
|
||||
#ifndef ICONV_OPTION
|
||||
"no "
|
||||
#endif
|
||||
"iconv",
|
||||
|
||||
#ifndef CAN_SET_SYMLINK_TIMES
|
||||
"no "
|
||||
#endif
|
||||
"symtimes",
|
||||
|
||||
#ifndef SUPPORT_PREALLOCATION
|
||||
"no "
|
||||
#endif
|
||||
"prealloc",
|
||||
|
||||
#ifndef HAVE_SIMD
|
||||
"no "
|
||||
#endif
|
||||
"SIMD",
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
for (line_len = 0, j = 0; ; j++) {
|
||||
char *cap = capabilities[j];
|
||||
int cap_len = cap ? strlen(cap) : 1000;
|
||||
int need_comma = cap && capabilities[j+1] != NULL ? 1 : 0;
|
||||
if (line_len + 1 + cap_len + need_comma >= (int)sizeof line_buf) {
|
||||
rprintf(f, " %s\n", line_buf);
|
||||
line_len = 0;
|
||||
}
|
||||
if (!cap)
|
||||
break;
|
||||
line_len += snprintf(line_buf+line_len, sizeof line_buf - line_len, " %s%s", cap, need_comma ? "," : "");
|
||||
}
|
||||
}
|
||||
|
||||
static void print_rsync_version(enum logcode f)
|
||||
{
|
||||
char tmpbuf[256], *subprotocol = "";
|
||||
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
subprotocol = istring(".PR%d", SUBPROTOCOL_VERSION);
|
||||
#endif
|
||||
rprintf(f, "%s version %s protocol version %d%s\n",
|
||||
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
|
||||
|
||||
rprintf(f, "Copyright (C) 1996-" LATEST_YEAR " by Andrew Tridgell, Wayne Davison, and others.\n");
|
||||
rprintf(f, "Web site: http://rsync.samba.org/\n");
|
||||
|
||||
rprintf(f, "Capabilities:\n");
|
||||
print_capabilities(f);
|
||||
|
||||
rprintf(f, "Checksum list:\n");
|
||||
get_default_nno_list(&valid_checksums, tmpbuf, sizeof tmpbuf, '(');
|
||||
rprintf(f, " %s\n", tmpbuf);
|
||||
|
||||
rprintf(f, "Compress list:\n");
|
||||
get_default_nno_list(&valid_compressions, tmpbuf, sizeof tmpbuf, '(');
|
||||
rprintf(f, " %s\n", tmpbuf);
|
||||
|
||||
#ifdef MAINTAINER_MODE
|
||||
rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INT64 < 8
|
||||
rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
|
||||
#endif
|
||||
if (sizeof (int64) != SIZEOF_INT64) {
|
||||
rprintf(f,
|
||||
"WARNING: size mismatch in SIZEOF_INT64 define (%d != %d)\n",
|
||||
(int) SIZEOF_INT64, (int) sizeof (int64));
|
||||
}
|
||||
|
||||
rprintf(f,"\n");
|
||||
rprintf(f,"rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n");
|
||||
rprintf(f,"are welcome to redistribute it under certain conditions. See the GNU\n");
|
||||
rprintf(f,"General Public Licence for details.\n");
|
||||
}
|
||||
|
||||
|
||||
void usage(enum logcode F)
|
||||
{
|
||||
print_rsync_version(F);
|
||||
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"rsync is a file transfer program capable of efficient remote update\n");
|
||||
rprintf(F,"via a fast differencing algorithm.\n");
|
||||
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC [DEST]\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
|
||||
rprintf(F," or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
|
||||
rprintf(F,"The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect\n");
|
||||
rprintf(F,"to an rsync daemon, and require SRC or DEST to start with a module name.\n");
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"Options\n");
|
||||
#include "help-rsync.h"
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"Use \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
|
||||
rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) man pages for full documentation.\n");
|
||||
rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
|
||||
}
|
||||
|
||||
enum {OPT_SERVER = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
|
||||
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
|
||||
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
|
||||
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG,
|
||||
OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_BWLIMIT,
|
||||
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG, OPT_BLOCK_SIZE,
|
||||
OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_BWLIMIT, OPT_STDERR,
|
||||
OPT_OLD_COMPRESS, OPT_NEW_COMPRESS, OPT_NO_COMPRESS,
|
||||
OPT_STOP_AFTER, OPT_STOP_AT,
|
||||
OPT_REFUSED_BASE = 9000};
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
@@ -750,7 +587,8 @@ static struct poptOption long_options[] = {
|
||||
{"no-v", 0, POPT_ARG_VAL, &verbose, 0, 0, 0 },
|
||||
{"info", 0, POPT_ARG_STRING, 0, OPT_INFO, 0, 0 },
|
||||
{"debug", 0, POPT_ARG_STRING, 0, OPT_DEBUG, 0, 0 },
|
||||
{"msgs2stderr", 0, POPT_ARG_NONE, &msgs2stderr, 0, 0, 0 },
|
||||
{"stderr", 0, POPT_ARG_STRING, 0, OPT_STDERR, 0, 0 },
|
||||
{"msgs2stderr", 0, POPT_ARG_VAL, &msgs2stderr, 1, 0, 0 },
|
||||
{"no-msgs2stderr", 0, POPT_ARG_VAL, &msgs2stderr, 0, 0, 0 },
|
||||
{"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 },
|
||||
{"motd", 0, POPT_ARG_VAL, &output_motd, 1, 0, 0 },
|
||||
@@ -791,6 +629,9 @@ static struct poptOption long_options[] = {
|
||||
{"no-U", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
|
||||
{"open-noatime", 0, POPT_ARG_VAL, &open_noatime, 1, 0, 0 },
|
||||
{"no-open-noatime", 0, POPT_ARG_VAL, &open_noatime, 0, 0, 0 },
|
||||
{"crtimes", 'N', POPT_ARG_VAL, &preserve_crtimes, 1, 0, 0 },
|
||||
{"no-crtimes", 0, POPT_ARG_VAL, &preserve_crtimes, 0, 0, 0 },
|
||||
{"no-N", 0, POPT_ARG_VAL, &preserve_crtimes, 0, 0, 0 },
|
||||
{"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 1, 0, 0 },
|
||||
{"no-omit-dir-times",0, POPT_ARG_VAL, &omit_dir_times, 0, 0, 0 },
|
||||
{"no-O", 0, POPT_ARG_VAL, &omit_dir_times, 0, 0, 0 },
|
||||
@@ -847,6 +688,7 @@ static struct poptOption long_options[] = {
|
||||
{"ignore-existing", 0, POPT_ARG_NONE, &ignore_existing, 0, 0, 0 },
|
||||
{"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
|
||||
{"min-size", 0, POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
|
||||
{"max-alloc", 0, POPT_ARG_STRING, &max_alloc_arg, 0, 0, 0 },
|
||||
{"sparse", 'S', POPT_ARG_VAL, &sparse_files, 1, 0, 0 },
|
||||
{"no-sparse", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
|
||||
{"no-S", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
|
||||
@@ -887,7 +729,7 @@ static struct poptOption long_options[] = {
|
||||
{"no-c", 0, POPT_ARG_VAL, &always_checksum, 0, 0, 0 },
|
||||
{"checksum-choice", 0, POPT_ARG_STRING, &checksum_choice, 0, 0, 0 },
|
||||
{"cc", 0, POPT_ARG_STRING, &checksum_choice, 0, 0, 0 },
|
||||
{"block-size", 'B', POPT_ARG_LONG, &block_size, 0, 0, 0 },
|
||||
{"block-size", 'B', POPT_ARG_STRING, 0, OPT_BLOCK_SIZE, 0, 0 },
|
||||
{"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
|
||||
{"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
|
||||
@@ -903,6 +745,7 @@ static struct poptOption long_options[] = {
|
||||
{"zc", 0, POPT_ARG_STRING, &compress_choice, 0, 0, 0 },
|
||||
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
|
||||
{"compress-level", 0, POPT_ARG_INT, &do_compression_level, 0, 0, 0 },
|
||||
{"zl", 0, POPT_ARG_INT, &do_compression_level, 0, 0, 0 },
|
||||
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
|
||||
{"progress", 0, POPT_ARG_VAL, &do_progress, 1, 0, 0 },
|
||||
{"no-progress", 0, POPT_ARG_VAL, &do_progress, 0, 0, 0 },
|
||||
@@ -946,6 +789,9 @@ static struct poptOption long_options[] = {
|
||||
{"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 },
|
||||
{"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 },
|
||||
{"no-contimeout", 0, POPT_ARG_VAL, &connect_timeout, 0, 0, 0 },
|
||||
{"stop-after", 0, POPT_ARG_STRING, 0, OPT_STOP_AFTER, 0, 0 },
|
||||
{"time-limit", 0, POPT_ARG_STRING, 0, OPT_STOP_AFTER, 0, 0 }, /* earlier stop-after name */
|
||||
{"stop-at", 0, POPT_ARG_STRING, 0, OPT_STOP_AT, 0, 0 },
|
||||
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
|
||||
{"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
|
||||
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
|
||||
@@ -956,12 +802,15 @@ static struct poptOption long_options[] = {
|
||||
{"8-bit-output", '8', POPT_ARG_VAL, &allow_8bit_chars, 1, 0, 0 },
|
||||
{"no-8-bit-output", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
|
||||
{"no-8", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
|
||||
{"mkpath", 0, POPT_ARG_VAL, &mkpath_dest_arg, 1, 0, 0 },
|
||||
{"no-mkpath", 0, POPT_ARG_VAL, &mkpath_dest_arg, 0, 0, 0 },
|
||||
{"qsort", 0, POPT_ARG_NONE, &use_qsort, 0, 0, 0 },
|
||||
{"copy-as", 0, POPT_ARG_STRING, ©_as, 0, 0, 0 },
|
||||
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
|
||||
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
|
||||
{"sockopts", 0, POPT_ARG_STRING, &sockopts, 0, 0, 0 },
|
||||
{"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
|
||||
{"early-input", 0, POPT_ARG_STRING, &early_input_file, 0, 0, 0 },
|
||||
{"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
|
||||
{"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
|
||||
{"outbuf", 0, POPT_ARG_STRING, &outbuf_mode, 0, 0, 0 },
|
||||
@@ -979,18 +828,6 @@ static struct poptOption long_options[] = {
|
||||
{0,0,0,0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void daemon_usage(enum logcode F)
|
||||
{
|
||||
print_rsync_version(F);
|
||||
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"Usage: rsync --daemon [OPTION]...\n");
|
||||
#include "help-rsyncd.h"
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"If you were not trying to invoke rsync as a daemon, avoid using any of the\n");
|
||||
rprintf(F,"daemon-specific rsync options. See also the rsyncd.conf(5) man page.\n");
|
||||
}
|
||||
|
||||
static struct poptOption long_daemon_options[] = {
|
||||
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
|
||||
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
|
||||
@@ -1143,15 +980,24 @@ static void set_refuse_options(void)
|
||||
parse_one_refuse_match(0, "log-file*", list_end);
|
||||
}
|
||||
|
||||
#ifndef SUPPORT_ATIMES
|
||||
parse_one_refuse_match(0, "atimes", list_end);
|
||||
#endif
|
||||
#ifndef SUPPORT_HARD_LINKS
|
||||
parse_one_refuse_match(0, "link-dest", list_end);
|
||||
#endif
|
||||
#ifndef HAVE_MKTIME
|
||||
parse_one_refuse_match(0, "stop-at", list_end);
|
||||
#endif
|
||||
#ifndef ICONV_OPTION
|
||||
parse_one_refuse_match(0, "iconv", list_end);
|
||||
#endif
|
||||
#ifndef HAVE_SETVBUF
|
||||
parse_one_refuse_match(0, "outbuf", list_end);
|
||||
#endif
|
||||
#ifndef SUPPORT_CRTIMES
|
||||
parse_one_refuse_match(0, "crtimes", list_end);
|
||||
#endif
|
||||
|
||||
/* Now we use the descrip values to actually mark the options for refusal. */
|
||||
for (op = long_options; op != list_end; op++) {
|
||||
@@ -1204,15 +1050,18 @@ static int count_args(const char **argv)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static OFF_T parse_size_arg(char **size_arg, char def_suf)
|
||||
/* If the size_arg is an invalid string or the value is < min_value, an error
|
||||
* is put into err_buf & the return is -1. Note that this parser does NOT
|
||||
* support negative numbers, so a min_value < 0 doesn't make any sense. */
|
||||
static ssize_t parse_size_arg(const char *size_arg, char def_suf, const char *opt_name,
|
||||
ssize_t min_value, ssize_t max_value, BOOL unlimited_0)
|
||||
{
|
||||
int reps, mult, make_compatible = 0;
|
||||
const char *arg;
|
||||
OFF_T size = 1;
|
||||
int reps, mult, len;
|
||||
const char *arg, *err = "invalid", *min_max = NULL;
|
||||
ssize_t limit = -1, size = 1;
|
||||
|
||||
for (arg = *size_arg; isDigit(arg); arg++) {}
|
||||
if (*arg == '.')
|
||||
for (arg = size_arg; isDigit(arg); arg++) {}
|
||||
if (*arg == '.' || *arg == get_decimal_point()) /* backward compatibility: always allow '.' */
|
||||
for (arg++; isDigit(arg); arg++) {}
|
||||
switch (*arg && *arg != '+' && *arg != '-' ? *arg++ : def_suf) {
|
||||
case 'b': case 'B':
|
||||
@@ -1227,40 +1076,197 @@ static OFF_T parse_size_arg(char **size_arg, char def_suf)
|
||||
case 'g': case 'G':
|
||||
reps = 3;
|
||||
break;
|
||||
case 't': case 'T':
|
||||
reps = 4;
|
||||
break;
|
||||
case 'p': case 'P':
|
||||
reps = 5;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
goto failure;
|
||||
}
|
||||
if (*arg == 'b' || *arg == 'B')
|
||||
mult = 1000, make_compatible = 1, arg++;
|
||||
mult = 1000, arg++;
|
||||
else if (!*arg || *arg == '+' || *arg == '-')
|
||||
mult = 1024;
|
||||
else if (strncasecmp(arg, "ib", 2) == 0)
|
||||
mult = 1024, arg += 2;
|
||||
else
|
||||
return -1;
|
||||
goto failure;
|
||||
while (reps--)
|
||||
size *= mult;
|
||||
size *= atof(*size_arg);
|
||||
if ((*arg == '+' || *arg == '-') && arg[1] == '1')
|
||||
size += atoi(arg), make_compatible = 1, arg += 2;
|
||||
size *= atof(size_arg);
|
||||
if ((*arg == '+' || *arg == '-') && arg[1] == '1' && arg != size_arg)
|
||||
size += atoi(arg), arg += 2;
|
||||
if (*arg)
|
||||
return -1;
|
||||
if (size > 0 && make_compatible && def_suf == 'b') {
|
||||
/* We convert this manually because we may need %lld precision,
|
||||
* and that's not a portable sprintf() escape. */
|
||||
char buf[128], *s = buf + sizeof buf - 1;
|
||||
OFF_T num = size;
|
||||
*s = '\0';
|
||||
while (num) {
|
||||
*--s = (char)(num % 10) + '0';
|
||||
num /= 10;
|
||||
}
|
||||
if (!(*size_arg = strdup(s)))
|
||||
out_of_memory("parse_size_arg");
|
||||
goto failure;
|
||||
if (size < 0 || (max_value >= 0 && size > max_value)) {
|
||||
err = "too large";
|
||||
min_max = "max";
|
||||
limit = max_value;
|
||||
goto failure;
|
||||
}
|
||||
if (size < min_value && (!unlimited_0 || size != 0)) {
|
||||
err = "too small";
|
||||
min_max = "min";
|
||||
limit = min_value;
|
||||
goto failure;
|
||||
}
|
||||
return size;
|
||||
|
||||
failure:
|
||||
len = snprintf(err_buf, sizeof err_buf - 1, "--%s=%s is %s", opt_name, size_arg, err);
|
||||
if (min_max && limit >= 0 && len < (int)sizeof err_buf - 10) {
|
||||
len += snprintf(err_buf + len, sizeof err_buf - len - 1, " (%s: %s%s)",
|
||||
min_max, do_big_num(limit, 3, NULL),
|
||||
unlimited_0 && min_max[1] == 'i' ? " or 0 for unlimited" : "");
|
||||
}
|
||||
err_buf[len] = '\n';
|
||||
err_buf[len+1] = '\0';
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MKTIME
|
||||
/* Allow the user to specify a time in the format yyyy-mm-ddThh:mm while
|
||||
* also allowing abbreviated data. For instance, if the time is omitted,
|
||||
* it defaults to midnight. If the date is omitted, it defaults to the
|
||||
* next possible date in the future with the specified time. Even the
|
||||
* year or year-month can be omitted, again defaulting to the next date
|
||||
* in the future that matches the specified information. A 2-digit year
|
||||
* is also OK, as is using '/' instead of '-'. */
|
||||
static time_t parse_time(const char *arg)
|
||||
{
|
||||
const char *cp;
|
||||
time_t val, now = time(NULL);
|
||||
struct tm t, *today = localtime(&now);
|
||||
int in_date, old_mday, n;
|
||||
|
||||
memset(&t, 0, sizeof t);
|
||||
t.tm_year = t.tm_mon = t.tm_mday = -1;
|
||||
t.tm_hour = t.tm_min = t.tm_isdst = -1;
|
||||
cp = arg;
|
||||
if (*cp == 'T' || *cp == 't' || *cp == ':') {
|
||||
in_date = *cp == ':' ? 0 : -1;
|
||||
cp++;
|
||||
} else
|
||||
in_date = 1;
|
||||
for ( ; ; cp++) {
|
||||
if (!isDigit(cp))
|
||||
return (time_t)-1;
|
||||
n = 0;
|
||||
do {
|
||||
n = n * 10 + *cp++ - '0';
|
||||
} while (isDigit(cp));
|
||||
if (*cp == ':')
|
||||
in_date = 0;
|
||||
if (in_date > 0) {
|
||||
if (t.tm_year != -1)
|
||||
return (time_t)-1;
|
||||
t.tm_year = t.tm_mon;
|
||||
t.tm_mon = t.tm_mday;
|
||||
t.tm_mday = n;
|
||||
if (!*cp)
|
||||
break;
|
||||
if (*cp == 'T' || *cp == 't') {
|
||||
if (!cp[1])
|
||||
break;
|
||||
in_date = -1;
|
||||
} else if (*cp != '-' && *cp != '/')
|
||||
return (time_t)-1;
|
||||
continue;
|
||||
}
|
||||
if (t.tm_hour != -1)
|
||||
return (time_t)-1;
|
||||
t.tm_hour = t.tm_min;
|
||||
t.tm_min = n;
|
||||
if (!*cp) {
|
||||
if (in_date < 0)
|
||||
return (time_t)-1;
|
||||
break;
|
||||
}
|
||||
if (*cp != ':')
|
||||
return (time_t)-1;
|
||||
in_date = 0;
|
||||
}
|
||||
|
||||
in_date = 0;
|
||||
if (t.tm_year < 0) {
|
||||
t.tm_year = today->tm_year;
|
||||
in_date = 1;
|
||||
} else if (t.tm_year < 100) {
|
||||
while (t.tm_year < today->tm_year)
|
||||
t.tm_year += 100;
|
||||
} else
|
||||
t.tm_year -= 1900;
|
||||
if (t.tm_mon < 0) {
|
||||
t.tm_mon = today->tm_mon;
|
||||
in_date = 2;
|
||||
} else
|
||||
t.tm_mon--;
|
||||
if (t.tm_mday < 0) {
|
||||
t.tm_mday = today->tm_mday;
|
||||
in_date = 3;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
if (t.tm_min < 0) {
|
||||
t.tm_hour = t.tm_min = 0;
|
||||
} else if (t.tm_hour < 0) {
|
||||
if (in_date != 3)
|
||||
return (time_t)-1;
|
||||
in_date = 0;
|
||||
t.tm_hour = today->tm_hour;
|
||||
n = 60*60;
|
||||
}
|
||||
|
||||
/* Note that mktime() might change a too-large tm_mday into the start of
|
||||
* the following month which we need to undo in the following code! */
|
||||
old_mday = t.tm_mday;
|
||||
if (t.tm_hour > 23 || t.tm_min > 59
|
||||
|| t.tm_mon < 0 || t.tm_mon >= 12
|
||||
|| t.tm_mday < 1 || t.tm_mday > 31
|
||||
|| (val = mktime(&t)) == (time_t)-1)
|
||||
return (time_t)-1;
|
||||
|
||||
while (in_date && (val <= now || t.tm_mday < old_mday)) {
|
||||
switch (in_date) {
|
||||
case 3:
|
||||
old_mday = ++t.tm_mday;
|
||||
break;
|
||||
case 2:
|
||||
if (t.tm_mday < old_mday)
|
||||
t.tm_mday = old_mday; /* The month already got bumped forward */
|
||||
else if (++t.tm_mon == 12) {
|
||||
t.tm_mon = 0;
|
||||
t.tm_year++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (t.tm_mday < old_mday) {
|
||||
/* mon==1 mday==29 got bumped to mon==2 */
|
||||
if (t.tm_mon != 2 || old_mday != 29)
|
||||
return (time_t)-1;
|
||||
t.tm_mon = 1;
|
||||
t.tm_mday = 29;
|
||||
}
|
||||
t.tm_year++;
|
||||
break;
|
||||
}
|
||||
if ((val = mktime(&t)) == (time_t)-1) {
|
||||
/* This code shouldn't be needed, as mktime() should auto-round to the next month. */
|
||||
if (in_date != 3 || t.tm_mday <= 28)
|
||||
return (time_t)-1;
|
||||
t.tm_mday = old_mday = 1;
|
||||
in_date = 2;
|
||||
}
|
||||
}
|
||||
if (n) {
|
||||
while (val <= now)
|
||||
val += n;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void create_refuse_error(int which)
|
||||
{
|
||||
@@ -1310,7 +1316,7 @@ char *alt_dest_opt(int type)
|
||||
case LINK_DEST:
|
||||
return "--link-dest";
|
||||
default:
|
||||
assert(0);
|
||||
NOISY_DEATH("Unknown alt_dest_opt type");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1361,8 +1367,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
|
||||
switch (opt) {
|
||||
case 'V':
|
||||
print_rsync_version(FINFO);
|
||||
exit_cleanup(0);
|
||||
version_opt_cnt++;
|
||||
break;
|
||||
|
||||
case OPT_SERVER:
|
||||
if (!am_server) {
|
||||
@@ -1483,8 +1489,6 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (daemon_filter_list.head) {
|
||||
int rej;
|
||||
char *cp = strdup(arg);
|
||||
if (!cp)
|
||||
out_of_memory("parse_arguments");
|
||||
if (!*cp)
|
||||
rej = 1;
|
||||
else {
|
||||
@@ -1608,8 +1612,6 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
remote_option_alloc += 16;
|
||||
remote_options = realloc_array(remote_options,
|
||||
const char *, remote_option_alloc);
|
||||
if (!remote_options)
|
||||
out_of_memory("parse_arguments");
|
||||
if (!remote_option_cnt)
|
||||
remote_options[0] = "ARG0";
|
||||
}
|
||||
@@ -1638,40 +1640,39 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_MAX_SIZE:
|
||||
if ((max_size = parse_size_arg(&max_size_arg, 'b')) < 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--max-size value is invalid: %s\n",
|
||||
max_size_arg);
|
||||
case OPT_BLOCK_SIZE: {
|
||||
/* We may not know the real protocol_version at this point if this is the client
|
||||
* option parsing, but we still want to check it so that the client can specify
|
||||
* a --protocol=29 option with a larger block size. */
|
||||
int max_blength = protocol_version < 30 ? OLD_MAX_BLOCK_SIZE : MAX_BLOCK_SIZE;
|
||||
ssize_t size;
|
||||
arg = poptGetOptArg(pc);
|
||||
if ((size = parse_size_arg(arg, 'b', "block-size", 0, max_blength, False)) < 0)
|
||||
return 0;
|
||||
}
|
||||
block_size = (int32)size;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_MAX_SIZE:
|
||||
if ((max_size = parse_size_arg(max_size_arg, 'b', "max-size", 0, -1, False)) < 0)
|
||||
return 0;
|
||||
max_size_arg = strdup(do_big_num(max_size, 0, NULL));
|
||||
break;
|
||||
|
||||
case OPT_MIN_SIZE:
|
||||
if ((min_size = parse_size_arg(&min_size_arg, 'b')) < 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--min-size value is invalid: %s\n",
|
||||
min_size_arg);
|
||||
if ((min_size = parse_size_arg(min_size_arg, 'b', "min-size", 0, -1, False)) < 0)
|
||||
return 0;
|
||||
}
|
||||
min_size_arg = strdup(do_big_num(min_size, 0, NULL));
|
||||
break;
|
||||
|
||||
case OPT_BWLIMIT:
|
||||
{
|
||||
OFF_T limit = parse_size_arg(&bwlimit_arg, 'K');
|
||||
if (limit < 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--bwlimit value is invalid: %s\n", bwlimit_arg);
|
||||
return 0;
|
||||
}
|
||||
bwlimit = (limit + 512) / 1024;
|
||||
if (limit && !bwlimit) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--bwlimit value is too small: %s\n", bwlimit_arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case OPT_BWLIMIT: {
|
||||
ssize_t size = parse_size_arg(bwlimit_arg, 'K', "bwlimit", 512, -1, True);
|
||||
if (size < 0)
|
||||
return 0;
|
||||
bwlimit_arg = strdup(do_big_num(size, 0, NULL));
|
||||
bwlimit = (size + 512) / 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_APPEND:
|
||||
if (am_server)
|
||||
@@ -1833,6 +1834,50 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
case OPT_STOP_AFTER: {
|
||||
long val;
|
||||
arg = poptGetOptArg(pc);
|
||||
stop_at_utime = time(NULL);
|
||||
if ((val = atol(arg) * 60) <= 0 || LONG_MAX - val < stop_at_utime || (long)(time_t)val != val) {
|
||||
snprintf(err_buf, sizeof err_buf, "invalid --stop-after value: %s\n", arg);
|
||||
return 0;
|
||||
}
|
||||
stop_at_utime += val;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MKTIME
|
||||
case OPT_STOP_AT:
|
||||
arg = poptGetOptArg(pc);
|
||||
if ((stop_at_utime = parse_time(arg)) == (time_t)-1) {
|
||||
snprintf(err_buf, sizeof err_buf, "invalid --stop-at format: %s\n", arg);
|
||||
return 0;
|
||||
}
|
||||
if (stop_at_utime <= time(NULL)) {
|
||||
snprintf(err_buf, sizeof err_buf, "--stop-at time is not in the future: %s\n", arg);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case OPT_STDERR: {
|
||||
int len;
|
||||
arg = poptGetOptArg(pc);
|
||||
len = strlen(arg);
|
||||
if (len && strncmp("errors", arg, len) == 0)
|
||||
msgs2stderr = 2;
|
||||
else if (len && strncmp("all", arg, len) == 0)
|
||||
msgs2stderr = 1;
|
||||
else if (len && strncmp("client", arg, len) == 0)
|
||||
msgs2stderr = 0;
|
||||
else {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--stderr mode \"%s\" is not one of errors, all, or client\n", arg);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* A large opt value means that set_refuse_options()
|
||||
* turned this option off. */
|
||||
@@ -1848,6 +1893,23 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
}
|
||||
}
|
||||
|
||||
if (version_opt_cnt) {
|
||||
print_rsync_version(FINFO);
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
if (!max_alloc_arg) {
|
||||
max_alloc_arg = getenv("RSYNC_MAX_ALLOC");
|
||||
if (max_alloc_arg && !*max_alloc_arg)
|
||||
max_alloc_arg = NULL;
|
||||
}
|
||||
if (max_alloc_arg) {
|
||||
ssize_t size = parse_size_arg(max_alloc_arg, 'B', "max-alloc", 1024*1024, -1, True);
|
||||
if (size < 0)
|
||||
return 0;
|
||||
max_alloc = size;
|
||||
}
|
||||
|
||||
if (protect_args < 0) {
|
||||
if (am_server)
|
||||
protect_args = 0;
|
||||
@@ -1918,7 +1980,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
setvbuf(stdout, (char *)NULL, mode, 0);
|
||||
}
|
||||
|
||||
if (msgs2stderr) {
|
||||
if (msgs2stderr == 1) { /* Are all messages going to stderr? */
|
||||
/* Make stderr line buffered for better sharing of the stream. */
|
||||
fflush(stderr); /* Just in case... */
|
||||
setvbuf(stderr, (char *)NULL, _IOLBF, 0);
|
||||
@@ -1990,19 +2052,6 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (block_size) {
|
||||
/* We may not know the real protocol_version at this point if this is the client
|
||||
* option parsing, but we still want to check it so that the client can specify
|
||||
* a --protocol=29 option with a larger block size. */
|
||||
int32 max_blength = protocol_version < 30 ? OLD_MAX_BLOCK_SIZE : MAX_BLOCK_SIZE;
|
||||
|
||||
if (block_size > max_blength) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--block-size=%lu is too large (max: %u)\n", block_size, max_blength);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (write_batch && read_batch) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--write-batch and --read-batch can not be used together\n");
|
||||
@@ -2171,6 +2220,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
}
|
||||
if (backup_dir) {
|
||||
size_t len;
|
||||
make_backups = 1; /* --backup-dir implies --backup */
|
||||
while (*backup_dir == '.' && backup_dir[1] == '/')
|
||||
backup_dir += 2;
|
||||
if (*backup_dir == '.' && backup_dir[1] == '\0')
|
||||
@@ -2416,13 +2466,6 @@ void server_options(char **args, int *argc_p)
|
||||
/* This should always remain first on the server's command-line. */
|
||||
args[ac++] = "--server";
|
||||
|
||||
if (daemon_over_rsh > 0) {
|
||||
args[ac++] = "--daemon";
|
||||
*argc_p = ac;
|
||||
/* if we're passing --daemon, we're done */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!am_sender)
|
||||
args[ac++] = "--sender";
|
||||
|
||||
@@ -2493,6 +2536,10 @@ void server_options(char **args, int *argc_p)
|
||||
if (preserve_atimes > 1)
|
||||
argstr[x++] = 'U';
|
||||
}
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
if (preserve_crtimes)
|
||||
argstr[x++] = 'N';
|
||||
#endif
|
||||
if (preserve_perms)
|
||||
argstr[x++] = 'p';
|
||||
else if (preserve_executability && am_sender)
|
||||
@@ -2560,6 +2607,7 @@ void server_options(char **args, int *argc_p)
|
||||
eFlags[x++] = 'C'; /* support checksum seed order fix */
|
||||
eFlags[x++] = 'I'; /* support inplace_partial behavior */
|
||||
eFlags[x++] = 'v'; /* use varint for flist & compat flags; negotiate checksum */
|
||||
eFlags[x++] = 'u'; /* include name of uid 0 & gid 0 in the id map */
|
||||
/* NOTE: Avoid using 'V' -- it was the high bit of a write_byte() that became write_varint(). */
|
||||
#undef eFlags
|
||||
}
|
||||
@@ -2625,8 +2673,13 @@ void server_options(char **args, int *argc_p)
|
||||
args[ac++] = "--log-format=X";
|
||||
}
|
||||
|
||||
if (msgs2stderr == 1)
|
||||
args[ac++] = "--msgs2stderr";
|
||||
else if (msgs2stderr == 0)
|
||||
args[ac++] = "--no-msgs2stderr";
|
||||
|
||||
if (block_size) {
|
||||
if (asprintf(&arg, "-B%lu", block_size) < 0)
|
||||
if (asprintf(&arg, "-B%u", (int)block_size) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
}
|
||||
@@ -2717,6 +2770,11 @@ void server_options(char **args, int *argc_p)
|
||||
}
|
||||
}
|
||||
|
||||
if (max_alloc_arg && max_alloc != DEFAULT_MAX_ALLOC) {
|
||||
args[ac++] = "--max-alloc";
|
||||
args[ac++] = max_alloc_arg;
|
||||
}
|
||||
|
||||
/* --delete-missing-args needs the cooperation of both sides, but
|
||||
* the sender can handle --ignore-missing-args by itself. */
|
||||
if (missing_args == 2)
|
||||
@@ -2843,6 +2901,9 @@ void server_options(char **args, int *argc_p)
|
||||
if (open_noatime && preserve_atimes <= 1)
|
||||
args[ac++] = "--open-noatime";
|
||||
|
||||
if (mkpath_dest_arg && am_sender)
|
||||
args[ac++] = "--mkpath";
|
||||
|
||||
if (ac > MAX_SERVER_ARGS) { /* Not possible... */
|
||||
rprintf(FERROR, "argc overflow in server_options().\n");
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
|
||||
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
|
||||
|
||||
.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,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
|
||||
%define srcdir src-previews
|
||||
Version: 3.2.3
|
||||
%define fullversion %{version}
|
||||
Release: 1
|
||||
%define srcdir src
|
||||
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.
|
||||
* Thu Aug 06 2020 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.2.3.
|
||||
|
||||
* Fri Mar 21 2008 Wayne Davison <wayne@opencoder.net>
|
||||
Added installation of /etc/xinetd.d/rsync file and some commented-out
|
||||
|
||||
@@ -32,6 +32,22 @@ blockquote pre code {
|
||||
dd p:first-of-type {
|
||||
margin-block-start: 0em;
|
||||
}
|
||||
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;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
"""
|
||||
@@ -59,7 +75,7 @@ def main():
|
||||
|
||||
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 = re.sub(r'(?<!<pre>)(<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)
|
||||
|
||||
@@ -72,14 +88,6 @@ def main():
|
||||
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.")
|
||||
@@ -88,12 +96,9 @@ if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
import cmarkgfm
|
||||
md_parser = html_via_cmarkgfm
|
||||
# Our NEWS.md file has a gfm table in it.
|
||||
md_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.")
|
||||
die("Failed to find cmarkgfm 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']) == '':
|
||||
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
|
||||
|
||||
@@ -181,45 +181,50 @@ def mandate_gensend_hook():
|
||||
|
||||
|
||||
# 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').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 +233,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():
|
||||
|
||||
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 -a -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,6 +13,7 @@ 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']
|
||||
|
||||
@@ -29,7 +30,11 @@ def main():
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
gen_files = get_gen_files()
|
||||
if cmd_txt_chk(['packaging/prep-auto-dir']) == '':
|
||||
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
|
||||
|
||||
@@ -52,13 +57,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)
|
||||
@@ -88,8 +93,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 +116,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 +126,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 +156,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 +171,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 +188,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 +221,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 +233,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 +242,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 +255,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 +272,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}
|
||||
@@ -297,12 +296,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,27 +319,16 @@ 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(f"git log --name-status | gzip -9 >{dest}/ChangeLog.gz")
|
||||
|
||||
for fn in (srctar_file, pattar_file, diff_file):
|
||||
@@ -352,14 +340,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 +378,4 @@ if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
# vim: sw=4 et ft=python
|
||||
|
||||
47
packaging/smart-make
Executable file
47
packaging/smart-make
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
export LANG=C
|
||||
|
||||
make=`which gmake 2>/dev/null` || make=`which make 2>/dev/null`
|
||||
|
||||
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
|
||||
|
||||
@@ -84,4 +84,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 -a -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
|
||||
|
||||
@@ -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[]))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -53,9 +60,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 +87,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 +98,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 +106,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/>.
|
||||
|
||||
631
rsync.1.md
631
rsync.1.md
File diff suppressed because it is too large
Load Diff
17
rsync.c
17
rsync.c
@@ -584,6 +584,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
memcpy(&sx2.st, &sxp->st, sizeof (sx2.st));
|
||||
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 (!(flags & ATTRS_SKIP_MTIME) && !same_mtime(file, &sxp->st, flags & ATTRS_ACCURATE_TIME)) {
|
||||
sx2.st.st_mtime = file->modtime;
|
||||
#ifdef ST_MTIME_NSEC
|
||||
@@ -613,6 +616,16 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
file->flags |= FLAG_TIME_FAILED;
|
||||
}
|
||||
}
|
||||
#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);
|
||||
if (!same_time(sxp->crtime, 0L, file_crtime, 0L)
|
||||
&& set_create_time(fname, file_crtime) == 0)
|
||||
updated = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
/* It's OK to call set_acl() now, even for a dir, as the generator
|
||||
@@ -718,7 +731,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 +756,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) {
|
||||
|
||||
95
rsync.h
95
rsync.h
@@ -20,6 +20,7 @@
|
||||
|
||||
#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"
|
||||
@@ -69,7 +70,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. */
|
||||
|
||||
@@ -181,6 +182,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 +210,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)
|
||||
@@ -297,6 +300,7 @@ enum delret {
|
||||
#include "errcode.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "version.h"
|
||||
|
||||
/* The default RSYNC_RSH is always set in config.h. */
|
||||
|
||||
@@ -440,7 +444,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 +475,23 @@ 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
|
||||
# include <sys/stat.h>
|
||||
# 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 +570,14 @@ typedef unsigned int size_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__ /* Do we need a configure check for this? */
|
||||
#define SUPPORT_ATIMES 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETATTRLIST
|
||||
#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 +721,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 +764,10 @@ 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
|
||||
#endif
|
||||
|
||||
union file_extras {
|
||||
int32 num;
|
||||
uint32 unum;
|
||||
@@ -751,12 +789,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 +807,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 +862,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 */
|
||||
@@ -1033,9 +1081,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 +1115,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 +1137,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 +1151,7 @@ struct name_num_obj {
|
||||
uchar *saw;
|
||||
int saw_len;
|
||||
int negotiated_num;
|
||||
struct name_num_item list[];
|
||||
struct name_num_item list[8]; /* A big-enough len (we'll get a compile error if it is ever too small) */
|
||||
};
|
||||
|
||||
#ifndef __cplusplus
|
||||
@@ -1262,12 +1324,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 *, ...)
|
||||
@@ -1383,3 +1455,8 @@ 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)
|
||||
|
||||
@@ -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/
|
||||
|
||||
107
rsyncd.conf.5.md
107
rsyncd.conf.5.md
@@ -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.
|
||||
@@ -905,15 +938,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.
|
||||
@@ -957,7 +990,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 +1138,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 +1208,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 +1221,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 +1239,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/>.
|
||||
|
||||
@@ -249,7 +249,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" ;;
|
||||
@@ -339,5 +339,8 @@ echo '------------------------------------------------------------'
|
||||
# because -e is set.
|
||||
|
||||
result=`expr $failed + $missing || true`
|
||||
if [ "$result" = 0 -a "$skipped" -gt "${RSYNC_MAX_SKIPPED:-9999}" ]; then
|
||||
result=1
|
||||
fi
|
||||
echo "overall result is $result"
|
||||
exit $result
|
||||
|
||||
10
sender.c
10
sender.c
@@ -65,13 +65,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 +89,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);
|
||||
|
||||
@@ -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,34 @@
|
||||
|
||||
#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_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2) { return i; }
|
||||
__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 +108,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 +124,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 +137,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 +176,111 @@ __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);
|
||||
|
||||
// [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 += 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 += 32*CHAR_OFFSET
|
||||
__m128i char_offset_multiplier = _mm_set1_epi32(32 * CHAR_OFFSET);
|
||||
ss1 = _mm_add_epi32(ss1, 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
|
||||
}
|
||||
|
||||
_mm_store_si128((__m128i_u*)x, ss1);
|
||||
*ps1 = x[0];
|
||||
_mm_store_si128((__m128i_u*)x, ss2);
|
||||
*ps2 = x[0];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
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("sse2"))) MVSTATIC int32 get_checksum1_sse2_32(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
if (len > 32) {
|
||||
int aligned = ((uintptr_t)buf & 15) == 0;
|
||||
|
||||
uint32 x[4] = {0};
|
||||
x[0] = *ps1;
|
||||
__m128i ss1 = _mm_loadu_si128((__m128i_u*)x);
|
||||
x[0] = *ps2;
|
||||
__m128i ss2 = _mm_loadu_si128((__m128i_u*)x);
|
||||
|
||||
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-32); i+=32) {
|
||||
// Load ... 2*[int8*16]
|
||||
__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]);
|
||||
} else {
|
||||
in8_1 = _mm_load_si128((__m128i_u*)&buf[i]);
|
||||
in8_2 = _mm_load_si128((__m128i_u*)&buf[i + 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
|
||||
__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*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 += 32*s1
|
||||
ss2 = _mm_add_epi32(ss2, _mm_slli_epi32(ss1, 5));
|
||||
|
||||
// [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);
|
||||
|
||||
// [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);
|
||||
|
||||
// s1 += t1[0] + t1[1] + t1[2] + t1[3] + t1[4] + t1[5] + t1[6] + t1[7]
|
||||
ss1 = _mm_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);
|
||||
|
||||
// [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);
|
||||
|
||||
// [t1[0], t1[1], ...] -> [t1[0]*28 + t1[1]*24, ...] [int32*4]
|
||||
__m128i mul32 = _mm_madd_epi16(add16, mul_t1);
|
||||
@@ -270,7 +326,7 @@ __attribute__ ((target("sse2", "ssse3"))) static int32 get_checksum1_sse2_32(sch
|
||||
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;
|
||||
*/
|
||||
__attribute__ ((target("avx2"))) static int32 get_checksum1_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
__attribute__ ((target("avx2"))) MVSTATIC int32 get_checksum1_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
if (len > 64) {
|
||||
// Instructions reshuffled compared to SSE2 for slightly better performance
|
||||
@@ -377,17 +433,7 @@ __attribute__ ((target("avx2"))) static int32 get_checksum1_avx2_64(schar* buf,
|
||||
return i;
|
||||
}
|
||||
|
||||
__attribute__ ((target("default"))) static int32 get_checksum1_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
__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,9 +449,10 @@ 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;
|
||||
@@ -414,7 +461,10 @@ uint32 get_checksum1(char *buf1, int32 len)
|
||||
// multiples of 64 bytes using AVX2 (if available)
|
||||
i = get_checksum1_avx2_64((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 +473,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*)malloc(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_64, (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;
|
||||
|
||||
@@ -79,10 +79,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.")
|
||||
|
||||
20
support/lsh
20
support/lsh
@@ -1,10 +1,6 @@
|
||||
#!/usr/bin/env perl
|
||||
# This script can be used as a "remote shell" command that is only
|
||||
# capable of pretending to connect to "localhost". This is useful
|
||||
# for testing or for running a local copy where the sender and the
|
||||
# receiver needs to use different options (e.g. --fake-super). If
|
||||
# we get -l USER, we try to become the USER, either directly (must
|
||||
# be root) or by using "sudo -H -u USER" (requires --sudo option).
|
||||
# This is a "local shell" command that works like a remote shell but only for
|
||||
# the local host. See the usage message for more details.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
@@ -78,9 +74,15 @@ die "Failed to exec: $!\n";
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: lsh [-l user] [--sudo] [--no-cd] localhost COMMAND [...]
|
||||
Usage: lsh [-l USER] [--sudo] [--no-cd] localhost COMMAND [...]
|
||||
|
||||
Note that if you pass hostname "lh" instead of "localhost" that
|
||||
the --no-cd option is implied.
|
||||
This is a "local shell" command that works like a remote shell but only for the
|
||||
local host. This is useful for rsync testing or for running a local copy where
|
||||
the sender and the receiver need to use different options (e.g. --fake-super).
|
||||
If the -l option is used, we try to become the USER, either directly (when
|
||||
root) or by using "sudo -H -u USER" (requires --sudo option).
|
||||
|
||||
Note that if you pass hostname "lh" instead of "localhost" that the --no-cd
|
||||
option is implied. The default is to "cd \$HOME" to simulate ssh behavior.
|
||||
EOT
|
||||
}
|
||||
|
||||
50
support/nameconvert
Executable file
50
support/nameconvert
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This implements a simple protocol to do user & group conversions between
|
||||
# names & ids. All input and output consists of simple strings with a
|
||||
# terminating newline.
|
||||
#
|
||||
# The requests can be:
|
||||
#
|
||||
# uid ID_NUM\n -> NAME\n
|
||||
# gid ID_NUM\n -> NAME\n
|
||||
# usr NAME\n -> ID_NUM\n
|
||||
# grp NAME\n -> ID_NUM\n
|
||||
#
|
||||
# An unknown ID_NUM or NAME results in an empty return value.
|
||||
#
|
||||
# This is used by an rsync daemon when configured with the "name converter" and
|
||||
# (often) "use chroot = true". While this converter uses real user & group
|
||||
# lookups you could change it to use any mapping idiom you'd like.
|
||||
|
||||
import sys, argparse, pwd, grp
|
||||
|
||||
def main():
|
||||
for line in sys.stdin:
|
||||
try:
|
||||
req, arg = line.rstrip().split(' ', 1)
|
||||
except:
|
||||
req = None
|
||||
try:
|
||||
if req == 'uid':
|
||||
ans = pwd.getpwuid(int(arg)).pw_name
|
||||
elif req == 'gid':
|
||||
ans = grp.getgrgid(int(arg)).gr_name
|
||||
elif req == 'usr':
|
||||
ans = pwd.getpwnam(arg).pw_uid
|
||||
elif req == 'grp':
|
||||
ans = grp.getgrnam(arg).gr_gid
|
||||
else:
|
||||
print("Invalid request", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except KeyError:
|
||||
ans = ''
|
||||
print(ans, flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Convert users & groups between names & numbers for an rsync daemon.")
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
@@ -111,6 +111,7 @@ our %long_opt = (
|
||||
'list-only' => 0,
|
||||
'log-file' => $only eq 'r' ? -1 : 3,
|
||||
'log-format' => 1,
|
||||
'max-alloc' => 1,
|
||||
'max-delete' => 1,
|
||||
'max-size' => 1,
|
||||
'min-size' => 1,
|
||||
|
||||
53
syscall.c
53
syscall.c
@@ -54,6 +54,15 @@ extern int open_noatime;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
#pragma pack(push, 4)
|
||||
struct create_time {
|
||||
uint32 length;
|
||||
struct timespec crtime;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#define RETURN_ERROR_IF(x,e) \
|
||||
do { \
|
||||
if (x) { \
|
||||
@@ -120,12 +129,16 @@ ssize_t do_readlink(const char *path, char *buf, size_t bufsiz)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINK
|
||||
#if defined HAVE_LINK || defined HAVE_LINKAT
|
||||
int do_link(const char *old_path, const char *new_path)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
#ifdef HAVE_LINKAT
|
||||
return linkat(AT_FDCWD, old_path, AT_FDCWD, new_path, 0);
|
||||
#else
|
||||
return link(old_path, new_path);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -385,6 +398,40 @@ int do_setattrlist_times(const char *fname, STRUCT_STAT *stp)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
time_t get_create_time(const char *path)
|
||||
{
|
||||
static struct create_time attrBuf;
|
||||
struct attrlist attrList;
|
||||
|
||||
memset(&attrList, 0, sizeof attrList);
|
||||
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attrList.commonattr = ATTR_CMN_CRTIME;
|
||||
if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
|
||||
return 0;
|
||||
return attrBuf.crtime.tv_sec;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_CRTIMES
|
||||
int set_create_time(const char *path, time_t crtime)
|
||||
{
|
||||
struct attrlist attrList;
|
||||
struct timespec ts;
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
ts.tv_sec = crtime;
|
||||
ts.tv_nsec = 0;
|
||||
|
||||
memset(&attrList, 0, sizeof attrList);
|
||||
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attrList.commonattr = ATTR_CMN_CRTIME;
|
||||
return setattrlist(path, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIMENSAT
|
||||
int do_utimensat(const char *fname, STRUCT_STAT *stp)
|
||||
{
|
||||
@@ -523,7 +570,7 @@ OFF_T do_fallocate(int fd, OFF_T offset, OFF_T length)
|
||||
|
||||
/* Punch a hole at pos for len bytes. The current file position must be at pos and will be
|
||||
* changed to be at pos + len. */
|
||||
int do_punch_hole(int fd, UNUSED(OFF_T pos), OFF_T len)
|
||||
int do_punch_hole(int fd, OFF_T pos, OFF_T len)
|
||||
{
|
||||
#ifdef HAVE_FALLOCATE
|
||||
# ifdef HAVE_FALLOC_FL_PUNCH_HOLE
|
||||
@@ -540,6 +587,8 @@ int do_punch_hole(int fd, UNUSED(OFF_T pos), OFF_T len)
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
(void)pos;
|
||||
#endif
|
||||
{
|
||||
char zeros[4096];
|
||||
|
||||
1
t_stub.c
1
t_stub.c
@@ -33,6 +33,7 @@ int preserve_xattrs = 0;
|
||||
int preserve_perms = 0;
|
||||
int preserve_executability = 0;
|
||||
int open_noatime = 0;
|
||||
size_t max_alloc = 0; /* max_alloc is needed when combined with util2.o */
|
||||
char *partial_dir;
|
||||
char *module_dir;
|
||||
filter_rule_list daemon_filter_list;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
$RSYNC --version | grep "[, ] atimes" >/dev/null || test_skipped "Rsync is configured without atimes support"
|
||||
|
||||
mkdir "$fromdir"
|
||||
|
||||
touch "$fromdir/foo"
|
||||
|
||||
@@ -37,6 +37,13 @@ EOF
|
||||
done
|
||||
}
|
||||
;;
|
||||
freebsd*)
|
||||
chown() {
|
||||
own=$1
|
||||
shift
|
||||
setextattr -h user "rsync.%stat" "100644 0,0 $own" "${@}"
|
||||
}
|
||||
;;
|
||||
*)
|
||||
chown() {
|
||||
own=$1
|
||||
@@ -48,15 +55,16 @@ EOF
|
||||
;;
|
||||
*)
|
||||
RSYNC="$RSYNC --super"
|
||||
case `get_testuid` in
|
||||
'') ;; # If "id" failed, try to continue...
|
||||
0) ;;
|
||||
*) if [ -e "$FAKEROOT_PATH" ]; then
|
||||
my_uid=`get_testuid`
|
||||
root_uid=`get_rootuid`
|
||||
if test x"$my_uid" = x; then
|
||||
: # If "id" failed, try to continue...
|
||||
elif test x"$my_uid" != x"$root_uid"; then
|
||||
if [ -e "$FAKEROOT_PATH" ]; then
|
||||
echo "Let's try re-running the script under fakeroot..."
|
||||
exec "$FAKEROOT_PATH" "$SHELL_PATH" "$0"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
26
testsuite/crtimes.test
Normal file
26
testsuite/crtimes.test
Normal file
@@ -0,0 +1,26 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Test rsync copying create times
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
$RSYNC --version | grep "[, ] crtimes" >/dev/null || test_skipped "Rsync is configured without crtimes support"
|
||||
|
||||
# Setting an older time via touch sets the create time to the mtime.
|
||||
# Setting it to a newer time affects just the mtime.
|
||||
|
||||
mkdir "$fromdir"
|
||||
echo hiho "$fromdir/foo"
|
||||
|
||||
touch -t 200101011111.11 "$fromdir"
|
||||
touch -t 200202022222.22 "$fromdir"
|
||||
|
||||
touch -t 200111111111.11 "$fromdir/foo"
|
||||
touch -t 200212122222.22 "$fromdir/foo"
|
||||
|
||||
TLS_ARGS=--crtimes
|
||||
|
||||
checkit "$RSYNC -rtgvvv --crtimes \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
@@ -41,14 +41,14 @@ cd "$scratchdir"
|
||||
|
||||
ln -s test-rsyncd.conf rsyncd.conf
|
||||
|
||||
my_uid=`get_testuid`
|
||||
root_uid=`get_rootuid`
|
||||
confopt=''
|
||||
case `get_testuid` in
|
||||
0)
|
||||
if test x"$my_uid" = x"$root_uid"; then
|
||||
# Root needs to specify the config file, or it uses /etc/rsyncd.conf.
|
||||
echo "Forcing --config=$conf"
|
||||
confopt=" --config=$conf"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# These have a space-padded 15-char name, then a tab, then a comment.
|
||||
sed 's/NOCOMMENT//' <<EOT >"$chkfile"
|
||||
@@ -91,12 +91,13 @@ drwxr-xr-x DIR ####/##/## ##:##:## foo
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
|
||||
$RSYNC -rU localhost::test-from/f* \
|
||||
| sed "$FILE_REPL" | sed "$DIR_REPL" | sed "$LS_REPL" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
if $RSYNC --version | grep "[, ] atimes" >/dev/null; then
|
||||
$RSYNC -rU localhost::test-from/f* \
|
||||
| sed "$FILE_REPL" | sed "$DIR_REPL" | sed "$LS_REPL" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
drwxr-xr-x DIR ####/##/## ##:##:## foo
|
||||
-rw-r--r-- 4 ####/##/## ##:##:## ####/##/## ##:##:## foo/one
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
fi
|
||||
|
||||
@@ -50,6 +50,20 @@ echo "$mode $maj,$min 0:0" > rsync.%stat
|
||||
EOF
|
||||
}
|
||||
;;
|
||||
freebsd*)
|
||||
mknod() {
|
||||
fn="$1"
|
||||
case "$2" in
|
||||
p) mode=10644 ;;
|
||||
c) mode=20644 ;;
|
||||
b) mode=60644 ;;
|
||||
esac
|
||||
maj="${3:-0}"
|
||||
min="${4:-0}"
|
||||
touch "$fn"
|
||||
setextattr -h user "rsync.%stat" "$mode $maj,$min 0:0" "$fn"
|
||||
}
|
||||
;;
|
||||
*)
|
||||
mknod() {
|
||||
fn="$1"
|
||||
@@ -67,21 +81,24 @@ EOF
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
case `get_testuid` in
|
||||
'') ;; # If "id" failed, try to continue...
|
||||
0) ;;
|
||||
*) if [ -e "$FAKEROOT_PATH" ]; then
|
||||
my_uid=`get_testuid`
|
||||
root_uid=`get_rootuid`
|
||||
if test x"$my_uid" = x; then
|
||||
: # If "id" failed, try to continue...
|
||||
elif test x"$my_uid" != x"$root_uid"; then
|
||||
if [ -e "$FAKEROOT_PATH" ]; then
|
||||
echo "Let's try re-running the script under fakeroot..."
|
||||
exec "$FAKEROOT_PATH" "$SHELL_PATH" $RUNSHFLAGS "$0"
|
||||
fi
|
||||
test_skipped "Rsync needs root/fakeroot for device tests"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
|
||||
|
||||
$RSYNC --version | grep "[, ] hardlink-special" >/dev/null && CAN_HLINK_SPECIAL=yes || CAN_HLINK_SPECIAL=no
|
||||
|
||||
mkdir "$fromdir"
|
||||
mkdir "$todir"
|
||||
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node"
|
||||
@@ -90,7 +107,11 @@ mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node"
|
||||
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node"
|
||||
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node"
|
||||
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node"
|
||||
ln "$fromdir/block3" "$fromdir/block3.5" || echo "Skipping hard-linked device test..."
|
||||
if test "$CAN_HLINK_SPECIAL" = yes; then
|
||||
ln "$fromdir/block3" "$fromdir/block3.5"
|
||||
else
|
||||
echo "Skipping hard-linked device test..."
|
||||
fi
|
||||
mkfifo "$fromdir/fifo" || mknod "$fromdir/fifo" p || test_skipped "Can't run mkfifo"
|
||||
# Work around time rounding/truncating issue by touching both files.
|
||||
touch -r "$fromdir/block" "$fromdir/block" "$fromdir/block2"
|
||||
@@ -132,7 +153,7 @@ cD$all_plus char2
|
||||
cD$all_plus char3
|
||||
cS$all_plus fifo
|
||||
EOT
|
||||
if test ! -r "$fromdir/block3.5"; then
|
||||
if test "$CAN_HLINK_SPECIAL" = no; then
|
||||
grep -v block3.5 <"$chkfile" >"$chkfile.new"
|
||||
mv "$chkfile.new" "$chkfile"
|
||||
fi
|
||||
@@ -144,7 +165,7 @@ echo ""
|
||||
( cd "$todir" && rsync_ls_lR . ) > "$tmpdir/ls-to"
|
||||
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to"
|
||||
|
||||
if test -r "$fromdir/block3.5"; then
|
||||
if test "$CAN_HLINK_SPECIAL" = yes; then
|
||||
set -x
|
||||
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
|
||||
| tee "$outfile"
|
||||
|
||||
@@ -23,12 +23,19 @@ testit() {
|
||||
check_perms "$todir/to/program" $4 "Target $1"
|
||||
}
|
||||
|
||||
mkdir "$scratchdir/dir"
|
||||
# Cygwin has a persistent default dir ACL that ruins this test.
|
||||
case `getfacl "$scratchdir/dir" 2>/dev/null || true` in
|
||||
*default:user::*) test_skipped "The default ACL mode interferes with this test" ;;
|
||||
esac
|
||||
|
||||
echo "File!" >"$scratchdir/file"
|
||||
echo "#!/bin/sh" >"$scratchdir/program"
|
||||
mkdir "$scratchdir/dir"
|
||||
|
||||
chmod u=rwx,g=rw,g+s,o=r "$scratchdir/dir" || test_skipped "Can't chmod"
|
||||
chmod 664 "$scratchdir/file"
|
||||
chmod 775 "$scratchdir/program"
|
||||
|
||||
[ -g "$scratchdir/dir" ] || test_skipped "The directory setgid bit vanished!"
|
||||
mkdir "$scratchdir/dir/blah"
|
||||
[ -g "$scratchdir/dir/blah" ] || test_skipped "Your filesystem doesn't use directory setgid; maybe it's BSD."
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
mkdir "$fromdir"
|
||||
mkdir "$todir"
|
||||
|
||||
cp -p "$srcdir"/rsync.c "$fromdir"/rsync.c
|
||||
cp_p "$srcdir"/rsync.c "$fromdir"/rsync.c
|
||||
cp_touch "$fromdir"/rsync.c "$todir"/rsync2.c
|
||||
sleep 1
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ DEBUG_OPTS="--debug=all0,deltasum0"
|
||||
runtest "basic operation" 'checkit "$RSYNC -av \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
ln "$fromdir/filelist" "$fromdir/dir"
|
||||
runtest "hard links" 'checkit "$RSYNC -avH $DEBUG_OPTS \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
runtest "hard links" 'checkit "$RSYNC -avH --bwlimit=0 $DEBUG_OPTS \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
rm "$todir/text"
|
||||
runtest "one file" 'checkit "$RSYNC -avH $DEBUG_OPTS \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
@@ -17,9 +17,9 @@ outfile="$scratchdir/rsync.out"
|
||||
|
||||
makepath "$fromdir/foo"
|
||||
makepath "$fromdir/bar/baz"
|
||||
cp -p "$srcdir/configure.ac" "$fromdir/foo/config1"
|
||||
cp -p "$srcdir/config.h.in" "$fromdir/foo/config2"
|
||||
cp -p "$srcdir/rsync.h" "$fromdir/bar/baz/rsync"
|
||||
cp_p "$srcdir/configure.ac" "$fromdir/foo/config1"
|
||||
cp_p "$srcdir/config.sub" "$fromdir/foo/config2"
|
||||
cp_p "$srcdir/rsync.h" "$fromdir/bar/baz/rsync"
|
||||
chmod 600 "$fromdir"/foo/config? "$fromdir/bar/baz/rsync"
|
||||
umask 0
|
||||
ln -s ../bar/baz/rsync "$fromdir/foo/sym"
|
||||
@@ -66,7 +66,7 @@ diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
|
||||
# Ensure there are no accidental directory-time problems.
|
||||
$RSYNC -a -f '-! */' "$fromdir/" "$todir"
|
||||
|
||||
cp -p "$srcdir/configure.ac" "$fromdir/foo/config2"
|
||||
cp_p "$srcdir/configure.ac" "$fromdir/foo/config2"
|
||||
chmod 601 "$fromdir/foo/config2"
|
||||
$RSYNC -iplrH "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
@@ -79,12 +79,12 @@ EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
|
||||
|
||||
$RSYNC -a -f '-! */' "$fromdir/" "$todir"
|
||||
cp_p "$srcdir/config.sub" "$fromdir/foo/config2"
|
||||
sleep 1 # For directory mod below to ensure time difference
|
||||
rm "$todir/foo/sym"
|
||||
umask 0
|
||||
ln -s ../bar/baz "$todir/foo/sym"
|
||||
umask 022
|
||||
cp -p "$srcdir/config.h.in" "$fromdir/foo/config2"
|
||||
chmod 600 "$fromdir/foo/config2"
|
||||
chmod 777 "$todir/bar/baz/rsync"
|
||||
|
||||
@@ -99,7 +99,7 @@ cLc$T.$dots foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
|
||||
cp -p "$srcdir/configure.ac" "$fromdir/foo/config2"
|
||||
cp_p "$srcdir/configure.ac" "$fromdir/foo/config2"
|
||||
chmod 600 "$fromdir/foo/config2"
|
||||
# Lack of -t is for unchanged hard-link stress-test!
|
||||
$RSYNC -vvplrH "$fromdir/" "$todir/" \
|
||||
|
||||
43
testsuite/mkpath.test
Executable file
43
testsuite/mkpath.test
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
makepath "$fromdir"
|
||||
makepath "$todir"
|
||||
|
||||
cp_p "$srcdir/rsync.h" "$fromdir/text"
|
||||
cp_p "$srcdir/configure.ac" "$fromdir/extra"
|
||||
|
||||
cd "$tmpdir"
|
||||
|
||||
deep_dir=to/foo/bar/baz/down/deep
|
||||
|
||||
# Check that we can create several levels of dest dir
|
||||
$RSYNC -aiv --mkpath from/text $deep_dir/new
|
||||
test -f $deep_dir/new || test_fail "'new' file not found in $deep_dir dir"
|
||||
rm -rf to/foo
|
||||
|
||||
$RSYNC -aiv --mkpath from/text $deep_dir/
|
||||
test -f $deep_dir/text || test_fail "'text' file not found in $deep_dir dir"
|
||||
rm $deep_dir/text
|
||||
|
||||
# Make sure we can handle an existing path
|
||||
mkdir $deep_dir/new
|
||||
$RSYNC -aiv --mkpath from/text $deep_dir/new
|
||||
test -f $deep_dir/new/text || test_fail "'text' file not found in $deep_dir/new dir"
|
||||
rm -rf to/foo
|
||||
|
||||
# Try the tests again with multiple source args
|
||||
$RSYNC -aiv --mkpath from/ $deep_dir
|
||||
test -f $deep_dir/extra || test_fail "'extra' file not found in $deep_dir dir"
|
||||
rm -rf to/foo
|
||||
|
||||
$RSYNC -aiv --mkpath from/ $deep_dir/
|
||||
test -f $deep_dir/text || test_fail "'text' file not found in $deep_dir dir"
|
||||
|
||||
# Make sure that we can handle no path
|
||||
$RSYNC -aiv --mkpath from/text to_text
|
||||
test -f to_text || test_fail "'to_text' file not found in current dir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
@@ -62,7 +62,7 @@ set_cp_destdir() {
|
||||
# Perform a "cp -p", making sure that timestamps are really the same,
|
||||
# even if the copy rounded microsecond times on the destination file.
|
||||
cp_touch() {
|
||||
cp -p "${@}" || test_fail "cp -p failed"
|
||||
cp_p "${@}"
|
||||
if test $# -gt 2 -o -d "$2"; then
|
||||
set_cp_destdir "${@}" # sets destdir var
|
||||
while test $# -gt 1; do
|
||||
@@ -97,11 +97,46 @@ printmsg() {
|
||||
}
|
||||
|
||||
rsync_ls_lR() {
|
||||
find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
|
||||
find "$@" -name .git -prune -o -name auto-build-save -prune -o -print | \
|
||||
sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
|
||||
}
|
||||
|
||||
get_testuid() {
|
||||
id 2>/dev/null | sed 's/^[^0-9]*\([0-9][0-9]*\).*/\1/'
|
||||
uid=`id -u 2>/dev/null || true`
|
||||
case "$uid" in
|
||||
[0-9]*) echo "$uid" ;;
|
||||
*) id 2>/dev/null | sed 's/^[^0-9]*\([0-9][0-9]*\).*/\1/' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_rootuid() {
|
||||
uid=`id -u root 2>/dev/null || true`
|
||||
case "$uid" in
|
||||
[0-9]*) echo "$uid" ;;
|
||||
*) echo 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_rootgid() {
|
||||
gid=`id -g root 2>/dev/null || true`
|
||||
case "$gid" in
|
||||
[0-9]*) echo "$gid" ;;
|
||||
*) echo 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# When copying via "cp -p", we want to ensure that a non-root user does not
|
||||
# preserve ownership (we want our files to be created as the testing user).
|
||||
# For instance, a Cygwin CI run might have git files owned by a different
|
||||
# user than the (admin) user running the tests.
|
||||
cp_cmd="cp -p"
|
||||
if test x`get_testuid` != x0; then
|
||||
case `cp --help 2>/dev/null` in
|
||||
*--no-preserve=*) cp_cmd="cp -p --no-preserve=ownership" ;;
|
||||
esac
|
||||
fi
|
||||
cp_p() {
|
||||
$cp_cmd "${@}" || test_fail "$cp_cmd failed"
|
||||
}
|
||||
|
||||
check_perms() {
|
||||
@@ -277,16 +312,18 @@ build_rsyncd_conf() {
|
||||
logfile="$scratchdir/rsyncd.log"
|
||||
hostname=`uname -n`
|
||||
|
||||
uid_setting='uid = 0'
|
||||
gid_setting='gid = 0'
|
||||
case `get_testuid` in
|
||||
0) ;;
|
||||
*)
|
||||
my_uid=`get_testuid`
|
||||
root_uid=`get_rootuid`
|
||||
root_gid=`get_rootgid`
|
||||
|
||||
uid_setting="uid = $root_uid"
|
||||
gid_setting="gid = $root_gid"
|
||||
|
||||
if test x"$my_uid" != x"$root_uid"; then
|
||||
# Non-root cannot specify uid & gid settings
|
||||
uid_setting="#$uid_setting"
|
||||
gid_setting="#$gid_setting"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
cat >"$conf" <<EOF
|
||||
# rsyncd configuration file autogenerated by $0
|
||||
@@ -296,8 +333,9 @@ use chroot = no
|
||||
munge symlinks = no
|
||||
hosts allow = localhost 127.0.0.0/24 192.168.0.0/16 10.0.0.0/8 $hostname
|
||||
log file = $logfile
|
||||
log format = %i %h [%a] %m (%u) %l %f%L
|
||||
transfer logging = yes
|
||||
# We don't define log format here so that the test-hidden module will default
|
||||
# to the internal static string (since we had a crash trying to tweak it).
|
||||
exclude = ? foobar.baz
|
||||
max verbosity = 4
|
||||
$uid_setting
|
||||
@@ -305,16 +343,19 @@ $gid_setting
|
||||
|
||||
[test-from]
|
||||
path = $fromdir
|
||||
log format = %i %h [%a] %m (%u) %l %f%L
|
||||
read only = yes
|
||||
comment = r/o
|
||||
|
||||
[test-to]
|
||||
path = $todir
|
||||
log format = %i %h [%a] %m (%u) %l %f%L
|
||||
read only = no
|
||||
comment = r/w
|
||||
|
||||
[test-scratch]
|
||||
path = $scratchdir
|
||||
log format = %i %h [%a] %m (%u) %l %f%L
|
||||
read only = no
|
||||
|
||||
[test-hidden]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user