mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-27 08:22:52 -04:00
Compare commits
243 Commits
v3.2.4pre1
...
v3.3.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c8ca91c73 | ||
|
|
079e74a30f | ||
|
|
abc3c74652 | ||
|
|
99ab59464b | ||
|
|
a47ae6fad9 | ||
|
|
2f9b963aba | ||
|
|
3476caea3e | ||
|
|
6f3c5eccee | ||
|
|
79fda35342 | ||
|
|
cd76993461 | ||
|
|
05a683900f | ||
|
|
86f41650fb | ||
|
|
9a06b2edb0 | ||
|
|
273dced284 | ||
|
|
b6e2321973 | ||
|
|
fe95a9369a | ||
|
|
6ae7f4085a | ||
|
|
0f599d3641 | ||
|
|
c3d3b49d72 | ||
|
|
c69dc7a5ab | ||
|
|
2c82006b1f | ||
|
|
0698ea9aeb | ||
|
|
90df93e446 | ||
|
|
5c93dedf45 | ||
|
|
f1e3434b59 | ||
|
|
48252c3c2b | ||
|
|
5b67ff2a86 | ||
|
|
8990ad96de | ||
|
|
0f44e864d4 | ||
|
|
ab0d5021ed | ||
|
|
7402896523 | ||
|
|
5374994089 | ||
|
|
526366129a | ||
|
|
556a2c5bc2 | ||
|
|
27feda0436 | ||
|
|
bf96cd314c | ||
|
|
1b2688807d | ||
|
|
08ec80ac65 | ||
|
|
6b5ae825db | ||
|
|
3b719d1d6e | ||
|
|
ebe1af749c | ||
|
|
de6848ed97 | ||
|
|
42f8386823 | ||
|
|
ad6245f394 | ||
|
|
ca980b5863 | ||
|
|
677aa0dc91 | ||
|
|
025596757c | ||
|
|
449d9bf950 | ||
|
|
35ecec972a | ||
|
|
d76cabe54f | ||
|
|
b5544a95b1 | ||
|
|
11bd2a4fd6 | ||
|
|
6ba434de5c | ||
|
|
3296351442 | ||
|
|
0088a85aeb | ||
|
|
4923c4dc0c | ||
|
|
76c4fa8b54 | ||
|
|
25efa10802 | ||
|
|
fdf5e577f5 | ||
|
|
19bd0dd340 | ||
|
|
ed4b3448be | ||
|
|
4d44bf122d | ||
|
|
6af27a538e | ||
|
|
f9e29dfb09 | ||
|
|
591de7ce5c | ||
|
|
c8c627756a | ||
|
|
46884e4ff6 | ||
|
|
97e02bf21a | ||
|
|
77d762ced8 | ||
|
|
5b27d2e6f3 | ||
|
|
7e634f5355 | ||
|
|
8fe8cfd60a | ||
|
|
7a2dbf7177 | ||
|
|
8449539a0f | ||
|
|
71c2b5d0e3 | ||
|
|
f3f5d8420f | ||
|
|
8b1b81e054 | ||
|
|
e8161304f7 | ||
|
|
b012cde1ed | ||
|
|
464555ea92 | ||
|
|
df904f590e | ||
|
|
208d6ad1cd | ||
|
|
51dae12c92 | ||
|
|
950730313d | ||
|
|
81c5c81381 | ||
|
|
a6a0d2f77c | ||
|
|
418e38a878 | ||
|
|
b2dcabdbb9 | ||
|
|
ad53a9b5a0 | ||
|
|
1750288660 | ||
|
|
087fffaa2b | ||
|
|
5c1fa2a21d | ||
|
|
0efa63f2e6 | ||
|
|
ae16850dc5 | ||
|
|
7e2711bb2b | ||
|
|
b8c2fde3a5 | ||
|
|
1f12b196fd | ||
|
|
bafe73dd5c | ||
|
|
db5bfe67a5 | ||
|
|
5447d038c6 | ||
|
|
711773631b | ||
|
|
bf3e49b453 | ||
|
|
034d5e8770 | ||
|
|
ad8917437a | ||
|
|
1b664d30e4 | ||
|
|
ea38f34d02 | ||
|
|
44d4727664 | ||
|
|
1f2f413167 | ||
|
|
0a09df2c5e | ||
|
|
cc861cf8c0 | ||
|
|
5183c0d6f0 | ||
|
|
706bff9176 | ||
|
|
2c1204032b | ||
|
|
8adc2240e0 | ||
|
|
84ad83525b | ||
|
|
9a3449a398 | ||
|
|
3258534e99 | ||
|
|
b94bba4036 | ||
|
|
a182507bef | ||
|
|
2895b65f53 | ||
|
|
def595c559 | ||
|
|
68b1ce1dc3 | ||
|
|
5a4116e553 | ||
|
|
024bf1d831 | ||
|
|
db4f919ebe | ||
|
|
6ac2c7b682 | ||
|
|
0e10163a9d | ||
|
|
5fcf20ee9d | ||
|
|
fc72d2b771 | ||
|
|
b7ea3fcd19 | ||
|
|
9cb7529ba6 | ||
|
|
55ad8757ec | ||
|
|
3e4b01173a | ||
|
|
2f1d1d5cac | ||
|
|
4c0a4067df | ||
|
|
8550142804 | ||
|
|
97f40754ba | ||
|
|
cff8f04477 | ||
|
|
db8034f12e | ||
|
|
c86763dc38 | ||
|
|
5ce575b157 | ||
|
|
fabef23bea | ||
|
|
685bf58046 | ||
|
|
9e2921fce8 | ||
|
|
80d8f7c7cb | ||
|
|
38e1b075b4 | ||
|
|
d659610afc | ||
|
|
6cafc1f8bf | ||
|
|
788f11ea6a | ||
|
|
b7fdc9ef0e | ||
|
|
0d8cc26044 | ||
|
|
2955888468 | ||
|
|
0773cecc1f | ||
|
|
8e33586359 | ||
|
|
da5c72da4b | ||
|
|
2f7c583143 | ||
|
|
51fd4993ba | ||
|
|
e37bfdb445 | ||
|
|
3d7015afa2 | ||
|
|
7e5424b806 | ||
|
|
43f70b961e | ||
|
|
b7231c7d02 | ||
|
|
15c34f0a8c | ||
|
|
d1e42ffa16 | ||
|
|
36f489c211 | ||
|
|
defe2287aa | ||
|
|
112bef11ad | ||
|
|
b38780f3fd | ||
|
|
5f33238f06 | ||
|
|
3592ac3c02 | ||
|
|
c897b16f32 | ||
|
|
4f741addbd | ||
|
|
355b81d8bc | ||
|
|
6f35553372 | ||
|
|
71090b7e2c | ||
|
|
2ab2ee166e | ||
|
|
1e858e39e6 | ||
|
|
664639e349 | ||
|
|
517b9d91fc | ||
|
|
0ac7ebceef | ||
|
|
85c56b2603 | ||
|
|
10aeb75cea | ||
|
|
d41bb98c09 | ||
|
|
2fda51692b | ||
|
|
1de71e8a78 | ||
|
|
60dd42be60 | ||
|
|
d821e4cbfb | ||
|
|
8aa465117f | ||
|
|
8977815f5d | ||
|
|
a48c20c97c | ||
|
|
601f47436f | ||
|
|
ef76d6cfa5 | ||
|
|
96ed4b47b9 | ||
|
|
13c4019e94 | ||
|
|
b7b387b1f7 | ||
|
|
7569edfaef | ||
|
|
55b2a06812 | ||
|
|
b81a509556 | ||
|
|
26f4dbe12c | ||
|
|
b3f1970f18 | ||
|
|
c51da9174f | ||
|
|
81f71f6f29 | ||
|
|
48e7005554 | ||
|
|
2b3e68814b | ||
|
|
cc83294316 | ||
|
|
08c8375acb | ||
|
|
824a057935 | ||
|
|
d91ddb97d1 | ||
|
|
5bb637ca04 | ||
|
|
142aba00d5 | ||
|
|
8687e44d10 | ||
|
|
0bd8e85185 | ||
|
|
00a5ab2364 | ||
|
|
f44e76b65c | ||
|
|
1174d97072 | ||
|
|
d9eaffe564 | ||
|
|
6197385d1f | ||
|
|
d07272d631 | ||
|
|
e2a011d9d0 | ||
|
|
76dc7d0a76 | ||
|
|
7e94e52144 | ||
|
|
5ef7e3c9c5 | ||
|
|
d2cc1149b3 | ||
|
|
c3b553a93f | ||
|
|
eb0b41587c | ||
|
|
3c0bb7ff51 | ||
|
|
995ce7198b | ||
|
|
38ffa522f6 | ||
|
|
8898aecb21 | ||
|
|
f08505e92b | ||
|
|
c1e8809a8f | ||
|
|
6130c4fa3c | ||
|
|
8c4ceb3b86 | ||
|
|
30a5909544 | ||
|
|
e841944b47 | ||
|
|
635d8c0632 | ||
|
|
6b8db0f644 | ||
|
|
3b2804c815 | ||
|
|
ff1792edf1 | ||
|
|
b985123d2e | ||
|
|
c983279020 | ||
|
|
ee9199b542 | ||
|
|
f1a6998df2 |
@@ -1,7 +1,7 @@
|
||||
freebsd_task:
|
||||
name: FreeBSD
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-2
|
||||
image_family: freebsd-13-1
|
||||
env:
|
||||
PATH: /usr/local/bin:$PATH
|
||||
prep_script:
|
||||
|
||||
21
.github/workflows/build.yml
vendored
21
.github/workflows/build.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
ubuntu-build:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: prep
|
||||
run: |
|
||||
sudo apt-get install acl libacl1-dev attr libattr1-dev liblz4-dev libzstd-dev libxxhash-dev python3-cmarkgfm openssl wget
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
- name: ssl file list
|
||||
run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
|
||||
- name: save artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ubuntu-bin
|
||||
path: |
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
macos-build:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: prep
|
||||
run: |
|
||||
brew install automake openssl xxhash zstd lz4 wget
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
- name: ssl file list
|
||||
run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
|
||||
- name: save artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: macos-bin
|
||||
path: |
|
||||
@@ -86,16 +86,15 @@ jobs:
|
||||
rrsync
|
||||
|
||||
cygwin-build:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2022
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
- name: cygwin
|
||||
run: choco install -y --no-progress cygwin cyg-get
|
||||
- name: prep
|
||||
run: |
|
||||
cyg-get make autoconf automake gcc-core attr libattr-devel python38 python38-pip libzstd-devel liblz4-devel libssl-devel libxxhash0 libxxhash-devel
|
||||
cyg-get make autoconf automake gcc-core attr libattr-devel python39 python39-pip libzstd-devel liblz4-devel libssl-devel libxxhash0 libxxhash-devel
|
||||
curl.exe -o git-version.h https://gist.githubusercontent.com/WayneD/c11243fa374fc64d4e42f2855c8e3827/raw/rsync-git-version.h
|
||||
echo "C:/tools/cygwin/bin" >>$Env:GITHUB_PATH
|
||||
- name: commonmark
|
||||
@@ -113,7 +112,7 @@ jobs:
|
||||
- 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
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cygwin-bin
|
||||
path: |
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,6 +16,7 @@ aclocal.m4
|
||||
/proto.h
|
||||
/proto.h-tstamp
|
||||
/rsync*.[15]
|
||||
/rrsync
|
||||
/rrsync*.1
|
||||
/rsync*.html
|
||||
/rrsync*.html
|
||||
|
||||
@@ -13,11 +13,11 @@ 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
|
||||
## Autoconf & manpages
|
||||
|
||||
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).
|
||||
markdown libraries: cmarkgfm or commonmark (needed to generate the manpages).
|
||||
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):
|
||||
@@ -26,9 +26,9 @@ build user (after installing python3's pip package):
|
||||
|
||||
You can test if you've got it fixed by running (from the rsync checkout):
|
||||
|
||||
> ./md2man --test rsync-ssl.1.md
|
||||
> ./md-convert --test rsync-ssl.1.md
|
||||
|
||||
Alternately, you can avoid generating the man pages by fetching the very latest
|
||||
Alternately, you can avoid generating the manpages 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:
|
||||
|
||||
|
||||
26
Makefile.in
26
Makefile.in
@@ -30,11 +30,13 @@ SHELL=/bin/sh
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
SIMD_x86_64=simd-checksum-x86_64.o simd-checksum-avx2.o
|
||||
ASM_x86_64=lib/md5-asm-x86_64.o
|
||||
ROLL_SIMD_x86_64=simd-checksum-x86_64.o
|
||||
ROLL_ASM_x86_64=simd-checksum-avx2.o
|
||||
MD5_ASM_x86_64=lib/md5-asm-x86_64.o
|
||||
|
||||
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
|
||||
rsync-ssl.1 rsync-ssl.1.html rsyncd.conf.5 rsyncd.conf.5.html \
|
||||
@GEN_RRSYNC@
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h itypes.h inums.h \
|
||||
lib/pool_alloc.h lib/mdigest.h lib/md-defines.h
|
||||
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
|
||||
@@ -45,7 +47,7 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
|
||||
util1.o util2.o main.o checksum.o match.o syscall.o log.o backup.o delete.o
|
||||
OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
|
||||
usage.o fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
|
||||
OBJS3=progress.o pipe.o @ASM@ @SIMD@
|
||||
OBJS3=progress.o pipe.o @MD5_ASM@ @ROLL_SIMD@ @ROLL_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,6 +70,8 @@ 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@
|
||||
|
||||
# NOTE: consider running "packaging/smart-make" instead of "make" to auto-handle
|
||||
# any changes to configure.sh and the main Makefile prior to a "make all".
|
||||
all: Makefile rsync$(EXEEXT) stunnel-rsyncd.conf @MAKE_RRSYNC@ @MAKE_MAN@
|
||||
.PHONY: all
|
||||
|
||||
@@ -146,13 +150,13 @@ git-version.h: ALWAYS_RUN
|
||||
ALWAYS_RUN:
|
||||
|
||||
simd-checksum-x86_64.o: simd-checksum-x86_64.cpp
|
||||
@$(srcdir)/cmd-or-msg disable-simd $(CXX) -I. $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $(srcdir)/simd-checksum-x86_64.cpp
|
||||
@$(srcdir)/cmd-or-msg disable-roll-simd $(CXX) -I. $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $(srcdir)/simd-checksum-x86_64.cpp
|
||||
|
||||
simd-checksum-avx2.o: simd-checksum-avx2.S
|
||||
@$(srcdir)/cmd-or-msg disable-asm $(CC) $(CFLAGS) --include=$(srcdir)/rsync.h -DAVX2_ASM -I. @NOEXECSTACK@ -c -o $@ $(srcdir)/simd-checksum-avx2.S
|
||||
@$(srcdir)/cmd-or-msg disable-roll-asm $(CC) $(CFLAGS) -I. @NOEXECSTACK@ -c -o $@ $(srcdir)/simd-checksum-avx2.S
|
||||
|
||||
lib/md5-asm-x86_64.o: lib/md5-asm-x86_64.S config.h lib/md-defines.h
|
||||
@$(srcdir)/cmd-or-msg disable-asm $(CC) -I. @NOEXECSTACK@ -c -o $@ $(srcdir)/lib/md5-asm-x86_64.S
|
||||
lib/md5-asm-x86_64.o: lib/md5-asm-x86_64.S lib/md-defines.h
|
||||
@$(srcdir)/cmd-or-msg disable-md5-asm $(CC) -I. @NOEXECSTACK@ -c -o $@ $(srcdir)/lib/md5-asm-x86_64.S
|
||||
|
||||
tls$(EXEEXT): $(TLS_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
|
||||
@@ -271,9 +275,9 @@ rrsync.1: support/rrsync.1.md md-convert Makefile
|
||||
|
||||
.PHONY: clean
|
||||
clean: cleantests
|
||||
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
git-version.h rounding rounding.h *.old rsync*.1 rsync*.5 rsync*.html \
|
||||
daemon-parm.h help-*.h default-*.h proto.h proto.h-tstamp
|
||||
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) @MAKE_RRSYNC@ \
|
||||
git-version.h rounding rounding.h *.old rsync*.1 rsync*.5 @MAKE_RRSYNC_1@ \
|
||||
*.html daemon-parm.h help-*.h default-*.h proto.h proto.h-tstamp
|
||||
|
||||
.PHONY: cleantests
|
||||
cleantests:
|
||||
|
||||
@@ -65,8 +65,8 @@ RSYNC DAEMONS
|
||||
-------------
|
||||
|
||||
Rsync can also talk to "rsync daemons" which can provide anonymous or
|
||||
authenticated rsync. See the rsyncd.conf(5) man page for details on how
|
||||
to setup an rsync daemon. See the rsync(1) man page for info on how to
|
||||
authenticated rsync. See the rsyncd.conf(5) manpage for details on how
|
||||
to setup an rsync daemon. See the rsync(1) manpage for info on how to
|
||||
connect to an rsync daemon.
|
||||
|
||||
|
||||
|
||||
2
access.c
2
access.c
@@ -2,7 +2,7 @@
|
||||
* Routines to authenticate access to a daemon (hosts allow/deny).
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2004-2021 Wayne Davison
|
||||
* Copyright (C) 2004-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
3
acls.c
3
acls.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2006-2021 Wayne Davison
|
||||
* Copyright (C) 2006-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -519,6 +519,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
|
||||
|
||||
sys_acl_free_acl(sacl);
|
||||
if (!ok) {
|
||||
rsyserr(FERROR_XFER, errno, "get_acl: unpack_smb_acl(%s)", fname);
|
||||
return -1;
|
||||
}
|
||||
} else if (no_acl_syscall_error(errno)) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Support rsync daemon authentication.
|
||||
*
|
||||
* Copyright (C) 1998-2000 Andrew Tridgell
|
||||
* Copyright (C) 2002-2020 Wayne Davison
|
||||
* Copyright (C) 2002-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
extern int read_only;
|
||||
extern char *password_file;
|
||||
extern struct name_num_obj valid_auth_checksums;
|
||||
|
||||
/***************************************************************************
|
||||
encode a buffer using base64 - simple and slow algorithm. null terminates
|
||||
@@ -72,9 +73,9 @@ static void gen_challenge(const char *addr, char *challenge)
|
||||
SIVAL(input, 20, tv.tv_usec);
|
||||
SIVAL(input, 24, getpid());
|
||||
|
||||
sum_init(-1, 0);
|
||||
len = sum_init(valid_auth_checksums.negotiated_nni, 0);
|
||||
sum_update(input, sizeof input);
|
||||
len = sum_end(digest);
|
||||
sum_end(digest);
|
||||
|
||||
base64_encode(digest, len, challenge, 0);
|
||||
}
|
||||
@@ -86,10 +87,10 @@ static void generate_hash(const char *in, const char *challenge, char *out)
|
||||
char buf[MAX_DIGEST_LEN];
|
||||
int len;
|
||||
|
||||
sum_init(-1, 0);
|
||||
len = sum_init(valid_auth_checksums.negotiated_nni, 0);
|
||||
sum_update(in, strlen(in));
|
||||
sum_update(challenge, strlen(challenge));
|
||||
len = sum_end(buf);
|
||||
sum_end(buf);
|
||||
|
||||
base64_encode(buf, len, out, 0);
|
||||
}
|
||||
@@ -238,6 +239,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
|
||||
if (!users || !*users)
|
||||
return "";
|
||||
|
||||
negotiate_daemon_auth(f_out, 0);
|
||||
gen_challenge(addr, challenge);
|
||||
|
||||
io_printf(f_out, "%s%s\n", leader, challenge);
|
||||
@@ -350,6 +352,7 @@ void auth_client(int fd, const char *user, const char *challenge)
|
||||
|
||||
if (!user || !*user)
|
||||
user = "nobody";
|
||||
negotiate_daemon_auth(-1, 1);
|
||||
|
||||
if (!(pass = getpassf(password_file))
|
||||
&& !(pass = getenv("RSYNC_PASSWORD"))) {
|
||||
|
||||
2
backup.c
2
backup.c
@@ -2,7 +2,7 @@
|
||||
* Backup handling code.
|
||||
*
|
||||
* Copyright (C) 1999 Andrew Tridgell
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
4
batch.c
4
batch.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1999 Weiss
|
||||
* Copyright (C) 2004 Chris Shoemaker
|
||||
* Copyright (C) 2004-2020 Wayne Davison
|
||||
* Copyright (C) 2004-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -194,7 +194,7 @@ static int write_opt(const char *opt, const char *arg)
|
||||
{
|
||||
int len = strlen(opt);
|
||||
int err = write(batch_sh_fd, " ", 1) != 1;
|
||||
err = write(batch_sh_fd, opt, len) != len ? 1 : 0;
|
||||
err = write(batch_sh_fd, opt, len) != len ? 1 : 0;
|
||||
if (arg) {
|
||||
err |= write(batch_sh_fd, "=", 1) != 1;
|
||||
err |= write_arg(arg);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Simple byteorder handling.
|
||||
*
|
||||
* Copyright (C) 1992-1995 Andrew Tridgell
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -129,4 +129,3 @@ SIVAL(char *buf, int pos, uint32 val)
|
||||
{
|
||||
SIVALu((uchar*)buf, pos, val);
|
||||
}
|
||||
|
||||
|
||||
473
checksum.c
473
checksum.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2004-2020 Wayne Davison
|
||||
* Copyright (C) 2004-2023 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
|
||||
@@ -42,41 +42,94 @@ extern int protocol_version;
|
||||
extern int proper_seed_order;
|
||||
extern const char *checksum_choice;
|
||||
|
||||
struct name_num_obj valid_checksums = {
|
||||
"checksum", NULL, NULL, 0, 0, {
|
||||
#define NNI_BUILTIN (1<<0)
|
||||
#define NNI_EVP (1<<1)
|
||||
#define NNI_EVP_OK (1<<2)
|
||||
|
||||
struct name_num_item valid_checksums_items[] = {
|
||||
#ifdef SUPPORT_XXH3
|
||||
{ CSUM_XXH3_128, "xxh128", NULL },
|
||||
{ CSUM_XXH3_64, "xxh3", NULL },
|
||||
{ CSUM_XXH3_128, 0, "xxh128", NULL },
|
||||
{ CSUM_XXH3_64, 0, "xxh3", NULL },
|
||||
#endif
|
||||
#ifdef SUPPORT_XXHASH
|
||||
{ CSUM_XXH64, "xxh64", NULL },
|
||||
{ CSUM_XXH64, "xxhash", NULL },
|
||||
{ CSUM_XXH64, 0, "xxh64", NULL },
|
||||
{ CSUM_XXH64, 0, "xxhash", NULL },
|
||||
#endif
|
||||
{ CSUM_MD5, "md5", NULL },
|
||||
{ CSUM_MD4, "md4", NULL },
|
||||
{ CSUM_NONE, "none", NULL },
|
||||
{ 0, NULL, NULL }
|
||||
}
|
||||
{ CSUM_MD5, NNI_BUILTIN|NNI_EVP, "md5", NULL },
|
||||
{ CSUM_MD4, NNI_BUILTIN|NNI_EVP, "md4", NULL },
|
||||
#ifdef SHA_DIGEST_LENGTH
|
||||
{ CSUM_SHA1, NNI_EVP, "sha1", NULL },
|
||||
#endif
|
||||
{ CSUM_NONE, 0, "none", NULL },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
int xfersum_type = 0; /* used for the file transfer checksums */
|
||||
int checksum_type = 0; /* used for the pre-transfer (--checksum) checksums */
|
||||
struct name_num_obj valid_checksums = {
|
||||
"checksum", NULL, 0, 0, valid_checksums_items
|
||||
};
|
||||
|
||||
int parse_csum_name(const char *name, int len)
|
||||
struct name_num_item valid_auth_checksums_items[] = {
|
||||
#ifdef SHA512_DIGEST_LENGTH
|
||||
{ CSUM_SHA512, NNI_EVP, "sha512", NULL },
|
||||
#endif
|
||||
#ifdef SHA256_DIGEST_LENGTH
|
||||
{ CSUM_SHA256, NNI_EVP, "sha256", NULL },
|
||||
#endif
|
||||
#ifdef SHA_DIGEST_LENGTH
|
||||
{ CSUM_SHA1, NNI_EVP, "sha1", NULL },
|
||||
#endif
|
||||
{ CSUM_MD5, NNI_BUILTIN|NNI_EVP, "md5", NULL },
|
||||
{ CSUM_MD4, NNI_BUILTIN|NNI_EVP, "md4", NULL },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
struct name_num_obj valid_auth_checksums = {
|
||||
"daemon auth checksum", NULL, 0, 0, valid_auth_checksums_items
|
||||
};
|
||||
|
||||
/* These cannot make use of openssl, so they're marked just as built-in */
|
||||
struct name_num_item implied_checksum_md4 =
|
||||
{ CSUM_MD4, NNI_BUILTIN, "md4", NULL };
|
||||
struct name_num_item implied_checksum_md5 =
|
||||
{ CSUM_MD5, NNI_BUILTIN, "md5", NULL };
|
||||
|
||||
struct name_num_item *xfer_sum_nni; /* used for the transfer checksum2 computations */
|
||||
int xfer_sum_len;
|
||||
struct name_num_item *file_sum_nni; /* used for the pre-transfer --checksum computations */
|
||||
int file_sum_len, file_sum_extra_cnt;
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
const EVP_MD *xfer_sum_evp_md;
|
||||
const EVP_MD *file_sum_evp_md;
|
||||
EVP_MD_CTX *ctx_evp = NULL;
|
||||
#endif
|
||||
|
||||
static int initialized_choices = 0;
|
||||
|
||||
struct name_num_item *parse_csum_name(const char *name, int len)
|
||||
{
|
||||
struct name_num_item *nni;
|
||||
|
||||
if (len < 0 && name)
|
||||
len = strlen(name);
|
||||
|
||||
init_checksum_choices();
|
||||
|
||||
if (!name || (len == 4 && strncasecmp(name, "auto", 4) == 0)) {
|
||||
if (protocol_version >= 30)
|
||||
return CSUM_MD5;
|
||||
if (protocol_version >= 27)
|
||||
return CSUM_MD4_OLD;
|
||||
if (protocol_version >= 21)
|
||||
return CSUM_MD4_BUSTED;
|
||||
return CSUM_MD4_ARCHAIC;
|
||||
if (protocol_version >= 30) {
|
||||
if (!proper_seed_order)
|
||||
return &implied_checksum_md5;
|
||||
name = "md5";
|
||||
len = 3;
|
||||
} else {
|
||||
if (protocol_version >= 27)
|
||||
implied_checksum_md4.num = CSUM_MD4_OLD;
|
||||
else if (protocol_version >= 21)
|
||||
implied_checksum_md4.num = CSUM_MD4_BUSTED;
|
||||
else
|
||||
implied_checksum_md4.num = CSUM_MD4_ARCHAIC;
|
||||
return &implied_checksum_md4;
|
||||
}
|
||||
}
|
||||
|
||||
nni = get_nni_by_name(&valid_checksums, name, len);
|
||||
@@ -86,44 +139,74 @@ int parse_csum_name(const char *name, int len)
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
return nni->num;
|
||||
return nni;
|
||||
}
|
||||
|
||||
static const char *checksum_name(int num)
|
||||
#ifdef USE_OPENSSL
|
||||
static const EVP_MD *csum_evp_md(struct name_num_item *nni)
|
||||
{
|
||||
struct name_num_item *nni = get_nni_by_num(&valid_checksums, num);
|
||||
const EVP_MD *emd;
|
||||
if (!(nni->flags & NNI_EVP))
|
||||
return NULL;
|
||||
|
||||
return nni ? nni->name : num < CSUM_MD4 ? "md4" : "UNKNOWN";
|
||||
#ifdef USE_MD5_ASM
|
||||
if (nni->num == CSUM_MD5)
|
||||
emd = NULL;
|
||||
else
|
||||
#endif
|
||||
emd = EVP_get_digestbyname(nni->name);
|
||||
if (emd && !(nni->flags & NNI_EVP_OK)) { /* Make sure it works before we advertise it */
|
||||
if (!ctx_evp && !(ctx_evp = EVP_MD_CTX_create()))
|
||||
out_of_memory("csum_evp_md");
|
||||
/* Some routines are marked as legacy and are not enabled in the openssl.cnf file.
|
||||
* If we can't init the emd, we'll fall back to our built-in code. */
|
||||
if (EVP_DigestInit_ex(ctx_evp, emd, NULL) == 0)
|
||||
emd = NULL;
|
||||
else
|
||||
nni->flags = (nni->flags & ~NNI_BUILTIN) | NNI_EVP_OK;
|
||||
}
|
||||
if (!emd)
|
||||
nni->flags &= ~NNI_EVP;
|
||||
return emd;
|
||||
}
|
||||
#endif
|
||||
|
||||
void parse_checksum_choice(int final_call)
|
||||
{
|
||||
if (valid_checksums.negotiated_name)
|
||||
xfersum_type = checksum_type = valid_checksums.negotiated_num;
|
||||
if (valid_checksums.negotiated_nni)
|
||||
xfer_sum_nni = file_sum_nni = valid_checksums.negotiated_nni;
|
||||
else {
|
||||
char *cp = checksum_choice ? strchr(checksum_choice, ',') : NULL;
|
||||
if (cp) {
|
||||
xfersum_type = parse_csum_name(checksum_choice, cp - checksum_choice);
|
||||
checksum_type = parse_csum_name(cp+1, -1);
|
||||
xfer_sum_nni = parse_csum_name(checksum_choice, cp - checksum_choice);
|
||||
file_sum_nni = parse_csum_name(cp+1, -1);
|
||||
} else
|
||||
xfersum_type = checksum_type = parse_csum_name(checksum_choice, -1);
|
||||
xfer_sum_nni = file_sum_nni = parse_csum_name(checksum_choice, -1);
|
||||
if (am_server && checksum_choice)
|
||||
validate_choice_vs_env(NSTR_CHECKSUM, xfersum_type, checksum_type);
|
||||
validate_choice_vs_env(NSTR_CHECKSUM, xfer_sum_nni->num, file_sum_nni->num);
|
||||
}
|
||||
xfer_sum_len = csum_len_for_type(xfer_sum_nni->num, 0);
|
||||
file_sum_len = csum_len_for_type(file_sum_nni->num, 0);
|
||||
#ifdef USE_OPENSSL
|
||||
xfer_sum_evp_md = csum_evp_md(xfer_sum_nni);
|
||||
file_sum_evp_md = csum_evp_md(file_sum_nni);
|
||||
#endif
|
||||
|
||||
if (xfersum_type == CSUM_NONE)
|
||||
file_sum_extra_cnt = (file_sum_len + EXTRA_LEN - 1) / EXTRA_LEN;
|
||||
|
||||
if (xfer_sum_nni->num == CSUM_NONE)
|
||||
whole_file = 1;
|
||||
|
||||
/* Snag the checksum name for both write_batch's option output & the following debug output. */
|
||||
if (valid_checksums.negotiated_name)
|
||||
checksum_choice = valid_checksums.negotiated_name;
|
||||
if (valid_checksums.negotiated_nni)
|
||||
checksum_choice = valid_checksums.negotiated_nni->name;
|
||||
else if (checksum_choice == NULL)
|
||||
checksum_choice = checksum_name(xfersum_type);
|
||||
checksum_choice = xfer_sum_nni->name;
|
||||
|
||||
if (final_call && DEBUG_GTE(NSTR, am_server ? 3 : 1)) {
|
||||
rprintf(FINFO, "%s%s checksum: %s\n",
|
||||
am_server ? "Server" : "Client",
|
||||
valid_checksums.negotiated_name ? " negotiated" : "",
|
||||
valid_checksums.negotiated_nni ? " negotiated" : "",
|
||||
checksum_choice);
|
||||
}
|
||||
}
|
||||
@@ -143,6 +226,18 @@ int csum_len_for_type(int cst, BOOL flist_csum)
|
||||
return MD4_DIGEST_LEN;
|
||||
case CSUM_MD5:
|
||||
return MD5_DIGEST_LEN;
|
||||
#ifdef SHA_DIGEST_LENGTH
|
||||
case CSUM_SHA1:
|
||||
return SHA_DIGEST_LENGTH;
|
||||
#endif
|
||||
#ifdef SHA256_DIGEST_LENGTH
|
||||
case CSUM_SHA256:
|
||||
return SHA256_DIGEST_LENGTH;
|
||||
#endif
|
||||
#ifdef SHA512_DIGEST_LENGTH
|
||||
case CSUM_SHA512:
|
||||
return SHA512_DIGEST_LENGTH;
|
||||
#endif
|
||||
case CSUM_XXH64:
|
||||
case CSUM_XXH3_64:
|
||||
return 64/8;
|
||||
@@ -168,6 +263,9 @@ int canonical_checksum(int csum_type)
|
||||
break;
|
||||
case CSUM_MD4:
|
||||
case CSUM_MD5:
|
||||
case CSUM_SHA1:
|
||||
case CSUM_SHA256:
|
||||
case CSUM_SHA512:
|
||||
return -1;
|
||||
case CSUM_XXH64:
|
||||
case CSUM_XXH3_64:
|
||||
@@ -179,7 +277,7 @@ int canonical_checksum(int csum_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_SIMD /* See simd-checksum-*.cpp. */
|
||||
#ifndef USE_ROLL_SIMD /* See simd-checksum-*.cpp. */
|
||||
/*
|
||||
a simple 32 bit checksum that can be updated from either end
|
||||
(inspired by Mark Adler's Adler-32 checksum)
|
||||
@@ -202,9 +300,25 @@ uint32 get_checksum1(char *buf1, int32 len)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The "sum" buffer must be at least MAX_DIGEST_LEN bytes! */
|
||||
void get_checksum2(char *buf, int32 len, char *sum)
|
||||
{
|
||||
switch (xfersum_type) {
|
||||
#ifdef USE_OPENSSL
|
||||
if (xfer_sum_evp_md) {
|
||||
static EVP_MD_CTX *evp = NULL;
|
||||
uchar seedbuf[4];
|
||||
if (!evp && !(evp = EVP_MD_CTX_create()))
|
||||
out_of_memory("get_checksum2");
|
||||
EVP_DigestInit_ex(evp, xfer_sum_evp_md, NULL);
|
||||
if (checksum_seed) {
|
||||
SIVALu(seedbuf, 0, checksum_seed);
|
||||
EVP_DigestUpdate(evp, seedbuf, 4);
|
||||
}
|
||||
EVP_DigestUpdate(evp, (uchar *)buf, len);
|
||||
EVP_DigestFinal_ex(evp, (uchar *)sum, NULL);
|
||||
} else
|
||||
#endif
|
||||
switch (xfer_sum_nni->num) {
|
||||
#ifdef SUPPORT_XXHASH
|
||||
case CSUM_XXH64:
|
||||
SIVAL64(sum, 0, XXH64(buf, len, checksum_seed));
|
||||
@@ -222,40 +336,26 @@ void get_checksum2(char *buf, int32 len, char *sum)
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD5: {
|
||||
MD5_CTX m5;
|
||||
md_context m5;
|
||||
uchar seedbuf[4];
|
||||
MD5_Init(&m5);
|
||||
md5_begin(&m5);
|
||||
if (proper_seed_order) {
|
||||
if (checksum_seed) {
|
||||
SIVALu(seedbuf, 0, checksum_seed);
|
||||
MD5_Update(&m5, seedbuf, 4);
|
||||
md5_update(&m5, seedbuf, 4);
|
||||
}
|
||||
MD5_Update(&m5, (uchar *)buf, len);
|
||||
md5_update(&m5, (uchar *)buf, len);
|
||||
} else {
|
||||
MD5_Update(&m5, (uchar *)buf, len);
|
||||
md5_update(&m5, (uchar *)buf, len);
|
||||
if (checksum_seed) {
|
||||
SIVALu(seedbuf, 0, checksum_seed);
|
||||
MD5_Update(&m5, seedbuf, 4);
|
||||
md5_update(&m5, seedbuf, 4);
|
||||
}
|
||||
}
|
||||
MD5_Final((uchar *)sum, &m5);
|
||||
md5_result(&m5, (uchar *)sum);
|
||||
break;
|
||||
}
|
||||
case CSUM_MD4:
|
||||
#ifdef USE_OPENSSL
|
||||
{
|
||||
MD4_CTX m4;
|
||||
MD4_Init(&m4);
|
||||
MD4_Update(&m4, (uchar *)buf, len);
|
||||
if (checksum_seed) {
|
||||
uchar seedbuf[4];
|
||||
SIVALu(seedbuf, 0, checksum_seed);
|
||||
MD4_Update(&m4, seedbuf, 4);
|
||||
}
|
||||
MD4_Final((uchar *)sum, &m4);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD4_OLD:
|
||||
case CSUM_MD4_BUSTED:
|
||||
case CSUM_MD4_ARCHAIC: {
|
||||
@@ -288,7 +388,7 @@ void get_checksum2(char *buf, int32 len, char *sum)
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0 || xfersum_type > CSUM_MD4_BUSTED)
|
||||
if (len - i > 0 || xfer_sum_nni->num > CSUM_MD4_BUSTED)
|
||||
mdfour_update(&m, (uchar *)(buf1+i), len-i);
|
||||
|
||||
mdfour_result(&m, (uchar *)sum);
|
||||
@@ -306,15 +406,33 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
|
||||
int32 remainder;
|
||||
int fd;
|
||||
|
||||
memset(sum, 0, MAX_DIGEST_LEN);
|
||||
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1)
|
||||
if (fd == -1) {
|
||||
memset(sum, 0, file_sum_len);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = map_file(fd, len, MAX_MAP_SIZE, CHUNK_SIZE);
|
||||
|
||||
switch (checksum_type) {
|
||||
#ifdef USE_OPENSSL
|
||||
if (file_sum_evp_md) {
|
||||
static EVP_MD_CTX *evp = NULL;
|
||||
if (!evp && !(evp = EVP_MD_CTX_create()))
|
||||
out_of_memory("file_checksum");
|
||||
|
||||
EVP_DigestInit_ex(evp, file_sum_evp_md, NULL);
|
||||
|
||||
for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
|
||||
EVP_DigestUpdate(evp, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
|
||||
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0)
|
||||
EVP_DigestUpdate(evp, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
EVP_DigestFinal_ex(evp, (uchar *)sum, NULL);
|
||||
} else
|
||||
#endif
|
||||
switch (file_sum_nni->num) {
|
||||
#ifdef SUPPORT_XXHASH
|
||||
case CSUM_XXH64: {
|
||||
static XXH64_state_t* state = NULL;
|
||||
@@ -374,38 +492,21 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD5: {
|
||||
MD5_CTX m5;
|
||||
md_context m5;
|
||||
|
||||
MD5_Init(&m5);
|
||||
md5_begin(&m5);
|
||||
|
||||
for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
|
||||
MD5_Update(&m5, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
|
||||
md5_update(&m5, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
|
||||
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0)
|
||||
MD5_Update(&m5, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
md5_update(&m5, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
MD5_Final((uchar *)sum, &m5);
|
||||
md5_result(&m5, (uchar *)sum);
|
||||
break;
|
||||
}
|
||||
case CSUM_MD4:
|
||||
#ifdef USE_OPENSSL
|
||||
{
|
||||
MD4_CTX m4;
|
||||
|
||||
MD4_Init(&m4);
|
||||
|
||||
for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
|
||||
MD4_Update(&m4, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
|
||||
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0)
|
||||
MD4_Update(&m4, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
MD4_Final((uchar *)sum, &m4);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD4_OLD:
|
||||
case CSUM_MD4_BUSTED:
|
||||
case CSUM_MD4_ARCHAIC: {
|
||||
@@ -413,15 +514,15 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
|
||||
|
||||
mdfour_begin(&m);
|
||||
|
||||
for (i = 0; i + CHUNK_SIZE <= len; i += CHUNK_SIZE)
|
||||
mdfour_update(&m, (uchar *)map_ptr(buf, i, CHUNK_SIZE), CHUNK_SIZE);
|
||||
for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK)
|
||||
mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK), CSUM_CHUNK);
|
||||
|
||||
/* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes. */
|
||||
remainder = (int32)(len - i);
|
||||
if (remainder > 0 || checksum_type > CSUM_MD4_BUSTED)
|
||||
if (remainder > 0 || file_sum_nni->num > CSUM_MD4_BUSTED)
|
||||
mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
|
||||
|
||||
mdfour_result(&m, (uchar *)sum);
|
||||
@@ -429,7 +530,7 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
|
||||
}
|
||||
default:
|
||||
rprintf(FERROR, "Invalid checksum-choice for --checksum: %s (%d)\n",
|
||||
checksum_name(checksum_type), checksum_type);
|
||||
file_sum_nni->name, file_sum_nni->num);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
@@ -438,30 +539,43 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
|
||||
}
|
||||
|
||||
static int32 sumresidue;
|
||||
static union {
|
||||
md_context md;
|
||||
#ifdef USE_OPENSSL
|
||||
MD4_CTX m4;
|
||||
#endif
|
||||
MD5_CTX m5;
|
||||
} ctx;
|
||||
static md_context ctx_md;
|
||||
#ifdef SUPPORT_XXHASH
|
||||
static XXH64_state_t* xxh64_state;
|
||||
#endif
|
||||
#ifdef SUPPORT_XXH3
|
||||
static XXH3_state_t* xxh3_state;
|
||||
#endif
|
||||
static int cursum_type;
|
||||
static struct name_num_item *cur_sum_nni;
|
||||
int cur_sum_len;
|
||||
|
||||
void sum_init(int csum_type, int seed)
|
||||
#ifdef USE_OPENSSL
|
||||
static const EVP_MD *cur_sum_evp_md;
|
||||
#endif
|
||||
|
||||
/* Initialize a hash digest accumulator. Data is supplied via
|
||||
* sum_update() and the resulting binary digest is retrieved via
|
||||
* sum_end(). This only supports one active sum at a time. */
|
||||
int sum_init(struct name_num_item *nni, int seed)
|
||||
{
|
||||
char s[4];
|
||||
|
||||
if (csum_type < 0)
|
||||
csum_type = parse_csum_name(NULL, 0);
|
||||
cursum_type = csum_type;
|
||||
if (!nni)
|
||||
nni = parse_csum_name(NULL, 0);
|
||||
cur_sum_nni = nni;
|
||||
cur_sum_len = csum_len_for_type(nni->num, 0);
|
||||
#ifdef USE_OPENSSL
|
||||
cur_sum_evp_md = csum_evp_md(nni);
|
||||
#endif
|
||||
|
||||
switch (csum_type) {
|
||||
#ifdef USE_OPENSSL
|
||||
if (cur_sum_evp_md) {
|
||||
if (!ctx_evp && !(ctx_evp = EVP_MD_CTX_create()))
|
||||
out_of_memory("file_checksum");
|
||||
EVP_DigestInit_ex(ctx_evp, cur_sum_evp_md, NULL);
|
||||
} else
|
||||
#endif
|
||||
switch (cur_sum_nni->num) {
|
||||
#ifdef SUPPORT_XXHASH
|
||||
case CSUM_XXH64:
|
||||
if (!xxh64_state && !(xxh64_state = XXH64_createState()))
|
||||
@@ -482,20 +596,16 @@ void sum_init(int csum_type, int seed)
|
||||
break;
|
||||
#endif
|
||||
case CSUM_MD5:
|
||||
MD5_Init(&ctx.m5);
|
||||
md5_begin(&ctx_md);
|
||||
break;
|
||||
case CSUM_MD4:
|
||||
#ifdef USE_OPENSSL
|
||||
MD4_Init(&ctx.m4);
|
||||
#else
|
||||
mdfour_begin(&ctx.md);
|
||||
mdfour_begin(&ctx_md);
|
||||
sumresidue = 0;
|
||||
#endif
|
||||
break;
|
||||
case CSUM_MD4_OLD:
|
||||
case CSUM_MD4_BUSTED:
|
||||
case CSUM_MD4_ARCHAIC:
|
||||
mdfour_begin(&ctx.md);
|
||||
mdfour_begin(&ctx_md);
|
||||
sumresidue = 0;
|
||||
SIVAL(s, 0, seed);
|
||||
sum_update(s, 4);
|
||||
@@ -505,19 +615,19 @@ void sum_init(int csum_type, int seed)
|
||||
default: /* paranoia to prevent missing case values */
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
return cur_sum_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Feed data into an MD4 accumulator, md. The results may be
|
||||
* retrieved using sum_end(). md is used for different purposes at
|
||||
* different points during execution.
|
||||
*
|
||||
* @todo Perhaps get rid of md and just pass in the address each time.
|
||||
* Very slightly clearer and slower.
|
||||
**/
|
||||
/* Feed data into a hash digest accumulator. */
|
||||
void sum_update(const char *p, int32 len)
|
||||
{
|
||||
switch (cursum_type) {
|
||||
#ifdef USE_OPENSSL
|
||||
if (cur_sum_evp_md) {
|
||||
EVP_DigestUpdate(ctx_evp, (uchar *)p, len);
|
||||
} else
|
||||
#endif
|
||||
switch (cur_sum_nni->num) {
|
||||
#ifdef SUPPORT_XXHASH
|
||||
case CSUM_XXH64:
|
||||
XXH64_update(xxh64_state, p, len);
|
||||
@@ -532,39 +642,35 @@ void sum_update(const char *p, int32 len)
|
||||
break;
|
||||
#endif
|
||||
case CSUM_MD5:
|
||||
MD5_Update(&ctx.m5, (uchar *)p, len);
|
||||
md5_update(&ctx_md, (uchar *)p, len);
|
||||
break;
|
||||
case CSUM_MD4:
|
||||
#ifdef USE_OPENSSL
|
||||
MD4_Update(&ctx.m4, (uchar *)p, len);
|
||||
break;
|
||||
#endif
|
||||
case CSUM_MD4_OLD:
|
||||
case CSUM_MD4_BUSTED:
|
||||
case CSUM_MD4_ARCHAIC:
|
||||
if (len + sumresidue < CSUM_CHUNK) {
|
||||
memcpy(ctx.md.buffer + sumresidue, p, len);
|
||||
memcpy(ctx_md.buffer + sumresidue, p, len);
|
||||
sumresidue += len;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sumresidue) {
|
||||
int32 i = CSUM_CHUNK - sumresidue;
|
||||
memcpy(ctx.md.buffer + sumresidue, p, i);
|
||||
mdfour_update(&ctx.md, (uchar *)ctx.md.buffer, CSUM_CHUNK);
|
||||
memcpy(ctx_md.buffer + sumresidue, p, i);
|
||||
mdfour_update(&ctx_md, (uchar *)ctx_md.buffer, CSUM_CHUNK);
|
||||
len -= i;
|
||||
p += i;
|
||||
}
|
||||
|
||||
while (len >= CSUM_CHUNK) {
|
||||
mdfour_update(&ctx.md, (uchar *)p, CSUM_CHUNK);
|
||||
mdfour_update(&ctx_md, (uchar *)p, CSUM_CHUNK);
|
||||
len -= CSUM_CHUNK;
|
||||
p += CSUM_CHUNK;
|
||||
}
|
||||
|
||||
sumresidue = len;
|
||||
if (sumresidue)
|
||||
memcpy(ctx.md.buffer, p, sumresidue);
|
||||
memcpy(ctx_md.buffer, p, sumresidue);
|
||||
break;
|
||||
case CSUM_NONE:
|
||||
break;
|
||||
@@ -573,13 +679,18 @@ void sum_update(const char *p, int32 len)
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: all the callers of sum_end() pass in a pointer to a buffer that is
|
||||
* MAX_DIGEST_LEN in size, so even if the csum-len is shorter that that (i.e.
|
||||
* CSUM_MD4_ARCHAIC), we don't have to worry about limiting the data we write
|
||||
* into the "sum" buffer. */
|
||||
int sum_end(char *sum)
|
||||
/* The sum buffer only needs to be as long as the current checksum's digest
|
||||
* len, not MAX_DIGEST_LEN. Note that for CSUM_MD4_ARCHAIC that is the full
|
||||
* MD4_DIGEST_LEN even if the file-list code is going to ignore all but the
|
||||
* first 2 bytes of it. */
|
||||
void sum_end(char *sum)
|
||||
{
|
||||
switch (cursum_type) {
|
||||
#ifdef USE_OPENSSL
|
||||
if (cur_sum_evp_md) {
|
||||
EVP_DigestFinal_ex(ctx_evp, (uchar *)sum, NULL);
|
||||
} else
|
||||
#endif
|
||||
switch (cur_sum_nni->num) {
|
||||
#ifdef SUPPORT_XXHASH
|
||||
case CSUM_XXH64:
|
||||
SIVAL64(sum, 0, XXH64_digest(xxh64_state));
|
||||
@@ -597,22 +708,18 @@ int sum_end(char *sum)
|
||||
}
|
||||
#endif
|
||||
case CSUM_MD5:
|
||||
MD5_Final((uchar *)sum, &ctx.m5);
|
||||
md5_result(&ctx_md, (uchar *)sum);
|
||||
break;
|
||||
case CSUM_MD4:
|
||||
#ifdef USE_OPENSSL
|
||||
MD4_Final((uchar *)sum, &ctx.m4);
|
||||
break;
|
||||
#endif
|
||||
case CSUM_MD4_OLD:
|
||||
mdfour_update(&ctx.md, (uchar *)ctx.md.buffer, sumresidue);
|
||||
mdfour_result(&ctx.md, (uchar *)sum);
|
||||
mdfour_update(&ctx_md, (uchar *)ctx_md.buffer, sumresidue);
|
||||
mdfour_result(&ctx_md, (uchar *)sum);
|
||||
break;
|
||||
case CSUM_MD4_BUSTED:
|
||||
case CSUM_MD4_ARCHAIC:
|
||||
if (sumresidue)
|
||||
mdfour_update(&ctx.md, (uchar *)ctx.md.buffer, sumresidue);
|
||||
mdfour_result(&ctx.md, (uchar *)sum);
|
||||
mdfour_update(&ctx_md, (uchar *)ctx_md.buffer, sumresidue);
|
||||
mdfour_result(&ctx_md, (uchar *)sum);
|
||||
break;
|
||||
case CSUM_NONE:
|
||||
*sum = '\0';
|
||||
@@ -620,6 +727,78 @@ int sum_end(char *sum)
|
||||
default: /* paranoia to prevent missing case values */
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
return csum_len_for_type(cursum_type, 0);
|
||||
}
|
||||
|
||||
#if defined SUPPORT_XXH3 || defined USE_OPENSSL
|
||||
static void verify_digest(struct name_num_item *nni, BOOL check_auth_list)
|
||||
{
|
||||
#ifdef SUPPORT_XXH3
|
||||
static int xxh3_result = 0;
|
||||
#endif
|
||||
#ifdef USE_OPENSSL
|
||||
static int prior_num = 0, prior_flags = 0, prior_result = 0;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_XXH3
|
||||
if (nni->num == CSUM_XXH3_64 || nni->num == CSUM_XXH3_128) {
|
||||
if (!xxh3_result) {
|
||||
char buf[32816];
|
||||
int j;
|
||||
for (j = 0; j < (int)sizeof buf; j++)
|
||||
buf[j] = ' ' + (j % 96);
|
||||
sum_init(nni, 0);
|
||||
sum_update(buf, 32816);
|
||||
sum_update(buf, 31152);
|
||||
sum_update(buf, 32474);
|
||||
sum_update(buf, 9322);
|
||||
xxh3_result = XXH3_64bits_digest(xxh3_state) != 0xadbcf16d4678d1de ? -1 : 1;
|
||||
}
|
||||
if (xxh3_result < 0)
|
||||
nni->num = CSUM_gone;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
if (BITS_SETnUNSET(nni->flags, NNI_EVP, NNI_BUILTIN|NNI_EVP_OK)) {
|
||||
if (nni->num == prior_num && nni->flags == prior_flags) {
|
||||
nni->flags = prior_result;
|
||||
if (!(nni->flags & NNI_EVP))
|
||||
nni->num = CSUM_gone;
|
||||
} else {
|
||||
prior_num = nni->num;
|
||||
prior_flags = nni->flags;
|
||||
if (!csum_evp_md(nni))
|
||||
nni->num = CSUM_gone;
|
||||
prior_result = nni->flags;
|
||||
if (check_auth_list && (nni = get_nni_by_num(&valid_auth_checksums, prior_num)) != NULL)
|
||||
verify_digest(nni, False);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_checksum_choices()
|
||||
{
|
||||
#if defined SUPPORT_XXH3 || defined USE_OPENSSL
|
||||
struct name_num_item *nni;
|
||||
#endif
|
||||
|
||||
if (initialized_choices)
|
||||
return;
|
||||
|
||||
#if defined USE_OPENSSL && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
OpenSSL_add_all_algorithms();
|
||||
#endif
|
||||
|
||||
#if defined SUPPORT_XXH3 || defined USE_OPENSSL
|
||||
for (nni = valid_checksums.list; nni->name; nni++)
|
||||
verify_digest(nni, True);
|
||||
|
||||
for (nni = valid_auth_checksums.list; nni->name; nni++)
|
||||
verify_digest(nni, False);
|
||||
#endif
|
||||
|
||||
initialized_choices = 1;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2021 Wayne Davison
|
||||
* Copyright (C) 2002-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
115
clientserver.c
115
clientserver.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2021 Wayne Davison
|
||||
* Copyright (C) 2002-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -47,6 +47,7 @@ extern int protocol_version;
|
||||
extern int io_timeout;
|
||||
extern int no_detach;
|
||||
extern int write_batch;
|
||||
extern int old_style_args;
|
||||
extern int default_af_hint;
|
||||
extern int logfile_format_has_i;
|
||||
extern int logfile_format_has_o_or_i;
|
||||
@@ -66,6 +67,7 @@ extern uid_t our_uid;
|
||||
extern gid_t our_gid;
|
||||
|
||||
char *auth_user;
|
||||
char *daemon_auth_choices;
|
||||
int read_only = 0;
|
||||
int module_id = -1;
|
||||
int pid_file_fd = -1;
|
||||
@@ -148,13 +150,9 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
|
||||
static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int am_client)
|
||||
{
|
||||
int remote_sub = -1;
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
|
||||
#else
|
||||
int our_sub = 0;
|
||||
#endif
|
||||
int our_sub = get_subprotocol_version();
|
||||
|
||||
io_printf(f_out, "@RSYNCD: %d.%d\n", protocol_version, our_sub);
|
||||
output_daemon_greeting(f_out, am_client);
|
||||
if (!am_client) {
|
||||
char *motd = lp_motd_file();
|
||||
if (motd && *motd) {
|
||||
@@ -186,16 +184,30 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int
|
||||
}
|
||||
|
||||
if (remote_sub < 0) {
|
||||
if (remote_protocol == 30) {
|
||||
if (remote_protocol >= 30) {
|
||||
if (am_client)
|
||||
rprintf(FERROR, "rsync: server is speaking an incompatible beta of protocol 30\n");
|
||||
rprintf(FERROR, "rsync: the server omitted the subprotocol value: %s\n", buf);
|
||||
else
|
||||
io_printf(f_out, "@ERROR: your client is speaking an incompatible beta of protocol 30\n");
|
||||
io_printf(f_out, "@ERROR: your client omitted the subprotocol value: %s\n", buf);
|
||||
return -1;
|
||||
}
|
||||
remote_sub = 0;
|
||||
}
|
||||
|
||||
daemon_auth_choices = strchr(buf + 9, ' ');
|
||||
if (daemon_auth_choices) {
|
||||
char *cp;
|
||||
daemon_auth_choices = strdup(daemon_auth_choices + 1);
|
||||
if ((cp = strchr(daemon_auth_choices, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
} else if (remote_protocol > 31) {
|
||||
if (am_client)
|
||||
rprintf(FERROR, "rsync: the server omitted the digest name list: %s\n", buf);
|
||||
else
|
||||
io_printf(f_out, "@ERROR: your client omitted the digest name list: %s\n", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (protocol_version > remote_protocol) {
|
||||
protocol_version = remote_protocol;
|
||||
if (remote_sub)
|
||||
@@ -288,20 +300,45 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
|
||||
sargs[sargc++] = ".";
|
||||
|
||||
if (!old_style_args)
|
||||
snprintf(line, sizeof line, " %.*s/", modlen, modname);
|
||||
|
||||
while (argc > 0) {
|
||||
if (sargc >= MAX_ARGS - 1) {
|
||||
arg_overflow:
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (strncmp(*argv, modname, modlen) == 0
|
||||
&& argv[0][modlen] == '\0')
|
||||
if (strncmp(*argv, modname, modlen) == 0 && argv[0][modlen] == '\0')
|
||||
sargs[sargc++] = modname; /* we send "modname/" */
|
||||
else if (**argv == '-') {
|
||||
if (asprintf(sargs + sargc++, "./%s", *argv) < 0)
|
||||
out_of_memory("start_inband_exchange");
|
||||
} else
|
||||
sargs[sargc++] = *argv;
|
||||
else {
|
||||
char *arg = *argv;
|
||||
int extra_chars = *arg == '-' ? 2 : 0; /* a leading dash needs a "./" prefix. */
|
||||
/* If --old-args was not specified, make sure that the arg won't split at a mod name! */
|
||||
if (!old_style_args && (p = strstr(arg, line)) != NULL) {
|
||||
do {
|
||||
extra_chars += 2;
|
||||
} while ((p = strstr(p+1, line)) != NULL);
|
||||
}
|
||||
if (extra_chars) {
|
||||
char *f = arg;
|
||||
char *t = arg = new_array(char, strlen(arg) + extra_chars + 1);
|
||||
if (*f == '-') {
|
||||
*t++ = '.';
|
||||
*t++ = '/';
|
||||
}
|
||||
while (*f) {
|
||||
if (*f == ' ' && strncmp(f, line, modlen+2) == 0) {
|
||||
*t++ = '[';
|
||||
*t++ = *f++;
|
||||
*t++ = ']';
|
||||
} else
|
||||
*t++ = *f++;
|
||||
}
|
||||
*t = '\0';
|
||||
}
|
||||
sargs[sargc++] = arg;
|
||||
}
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
@@ -355,7 +392,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
|
||||
if (rl_nulls) {
|
||||
for (i = 0; i < sargc; i++) {
|
||||
if (!sargs[i]) /* stop at --protect-args NULL */
|
||||
if (!sargs[i]) /* stop at --secluded-args NULL */
|
||||
break;
|
||||
write_sbuf(f_out, sargs[i]);
|
||||
write_byte(f_out, 0);
|
||||
@@ -403,7 +440,7 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_env_str(const char *var, const char *str)
|
||||
void set_env_str(const char *var, const char *str)
|
||||
{
|
||||
#ifdef HAVE_SETENV
|
||||
if (setenv(var, str, 1) < 0)
|
||||
@@ -664,7 +701,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
int set_uid;
|
||||
char *p, *err_msg = NULL;
|
||||
char *name = lp_name(i);
|
||||
int use_chroot = lp_use_chroot(i);
|
||||
int use_chroot = lp_use_chroot(i); /* might be 1 (yes), 0 (no), or -1 (unset) */
|
||||
int ret, pre_exec_arg_fd = -1, pre_exec_error_fd = -1;
|
||||
int save_munge_symlinks;
|
||||
pid_t pre_exec_pid = 0;
|
||||
@@ -789,6 +826,20 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
io_printf(f_out, "@ERROR: no path setting.\n");
|
||||
return -1;
|
||||
}
|
||||
if (use_chroot < 0) {
|
||||
if (strstr(module_dir, "/./") != NULL)
|
||||
use_chroot = 1; /* The module is expecting a chroot inner & outer path. */
|
||||
else if (chroot("/") < 0) {
|
||||
rprintf(FLOG, "chroot test failed: %s. "
|
||||
"Switching 'use chroot' from unset to false.\n",
|
||||
strerror(errno));
|
||||
use_chroot = 0;
|
||||
} else {
|
||||
if (chdir("/") < 0)
|
||||
rsyserr(FLOG, errno, "chdir(\"/\") failed");
|
||||
use_chroot = 1;
|
||||
}
|
||||
}
|
||||
if (use_chroot) {
|
||||
if ((p = strstr(module_dir, "/./")) != NULL) {
|
||||
*p = '\0'; /* Temporary... */
|
||||
@@ -925,20 +976,8 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
}
|
||||
|
||||
if (use_chroot) {
|
||||
/*
|
||||
* XXX: The 'use chroot' flag is a fairly reliable
|
||||
* source of confusion, because it fails under two
|
||||
* important circumstances: running as non-root,
|
||||
* running on Win32 (or possibly others). On the
|
||||
* other hand, if you are running as root, then it
|
||||
* might be better to always use chroot.
|
||||
*
|
||||
* So, perhaps if we can't chroot we should just issue
|
||||
* a warning, unless a "require chroot" flag is set,
|
||||
* in which case we fail.
|
||||
*/
|
||||
if (chroot(module_chdir)) {
|
||||
rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
|
||||
rsyserr(FLOG, errno, "chroot(\"%s\") failed", module_chdir);
|
||||
io_printf(f_out, "@ERROR: chroot failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -947,7 +986,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
|
||||
if (!change_dir(module_chdir, CD_NORMAL))
|
||||
return path_failure(f_out, module_chdir, True);
|
||||
if (module_dirlen || (!use_chroot && !*lp_daemon_chroot()))
|
||||
if (module_dirlen)
|
||||
sanitize_paths = 1;
|
||||
|
||||
if ((munge_symlinks = lp_munge_symlinks(module_id)) < 0)
|
||||
@@ -1262,8 +1301,12 @@ int start_daemon(int f_in, int f_out)
|
||||
p = lp_daemon_chroot();
|
||||
if (*p) {
|
||||
log_init(0); /* Make use we've initialized syslog before chrooting. */
|
||||
if (chroot(p) < 0 || chdir("/") < 0) {
|
||||
rsyserr(FLOG, errno, "daemon chroot %s failed", p);
|
||||
if (chroot(p) < 0) {
|
||||
rsyserr(FLOG, errno, "daemon chroot(\"%s\") failed", p);
|
||||
return -1;
|
||||
}
|
||||
if (chdir("/") < 0) {
|
||||
rsyserr(FLOG, errno, "daemon chdir(\"/\") failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
208
compat.c
208
compat.c
@@ -60,13 +60,16 @@ extern char *files_from;
|
||||
extern char *filesfrom_host;
|
||||
extern const char *checksum_choice;
|
||||
extern const char *compress_choice;
|
||||
extern char *daemon_auth_choices;
|
||||
extern filter_rule_list filter_list;
|
||||
extern int need_unsorted_flist;
|
||||
#ifdef ICONV_OPTION
|
||||
extern iconv_t ic_send, ic_recv;
|
||||
extern char *iconv_opt;
|
||||
#endif
|
||||
extern struct name_num_obj valid_checksums;
|
||||
extern struct name_num_obj valid_checksums, valid_auth_checksums;
|
||||
|
||||
extern struct name_num_item *xfer_sum_nni;
|
||||
|
||||
int remote_protocol = 0;
|
||||
int file_extra_cnt = 0; /* count of file-list extras that everyone gets */
|
||||
@@ -79,6 +82,9 @@ int inplace_partial = 0;
|
||||
int do_negotiated_strings = 0;
|
||||
int xmit_id0_names = 0;
|
||||
|
||||
struct name_num_item *xattr_sum_nni;
|
||||
int xattr_sum_len = 0;
|
||||
|
||||
/* These index values are for the file-list's extra-attribute array. */
|
||||
int pathname_ndx, depth_ndx, atimes_ndx, crtimes_ndx, uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
|
||||
|
||||
@@ -91,19 +97,21 @@ int filesfrom_convert = 0;
|
||||
|
||||
#define MAX_NSTR_STRLEN 256
|
||||
|
||||
struct name_num_obj valid_compressions = {
|
||||
"compress", NULL, NULL, 0, 0, {
|
||||
struct name_num_item valid_compressions_items[] = {
|
||||
#ifdef SUPPORT_ZSTD
|
||||
{ CPRES_ZSTD, "zstd", NULL },
|
||||
{ CPRES_ZSTD, 0, "zstd", NULL },
|
||||
#endif
|
||||
#ifdef SUPPORT_LZ4
|
||||
{ CPRES_LZ4, "lz4", NULL },
|
||||
{ CPRES_LZ4, 0, "lz4", NULL },
|
||||
#endif
|
||||
{ CPRES_ZLIBX, "zlibx", NULL },
|
||||
{ CPRES_ZLIB, "zlib", NULL },
|
||||
{ CPRES_NONE, "none", NULL },
|
||||
{ 0, NULL, NULL }
|
||||
}
|
||||
{ CPRES_ZLIBX, 0, "zlibx", NULL },
|
||||
{ CPRES_ZLIB, 0, "zlib", NULL },
|
||||
{ CPRES_NONE, 0, "none", NULL },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
struct name_num_obj valid_compressions = {
|
||||
"compress", NULL, 0, 0, valid_compressions_items
|
||||
};
|
||||
|
||||
#define CF_INC_RECURSE (1<<0)
|
||||
@@ -125,11 +133,7 @@ static void check_sub_protocol(void)
|
||||
{
|
||||
char *dot;
|
||||
int their_protocol, their_sub;
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
|
||||
#else
|
||||
int our_sub = 0;
|
||||
#endif
|
||||
int our_sub = get_subprotocol_version();
|
||||
|
||||
/* client_info starts with VER.SUB string if client is a pre-release. */
|
||||
if (!(their_protocol = atoi(client_info))
|
||||
@@ -176,8 +180,8 @@ void set_allow_inc_recurse(void)
|
||||
|
||||
void parse_compress_choice(int final_call)
|
||||
{
|
||||
if (valid_compressions.negotiated_name)
|
||||
do_compression = valid_compressions.negotiated_num;
|
||||
if (valid_compressions.negotiated_nni)
|
||||
do_compression = valid_compressions.negotiated_nni->num;
|
||||
else if (compress_choice) {
|
||||
struct name_num_item *nni = get_nni_by_name(&valid_compressions, compress_choice, -1);
|
||||
if (!nni) {
|
||||
@@ -199,8 +203,8 @@ void parse_compress_choice(int final_call)
|
||||
compress_choice = NULL;
|
||||
|
||||
/* Snag the compression name for both write_batch's option output & the following debug output. */
|
||||
if (valid_compressions.negotiated_name)
|
||||
compress_choice = valid_compressions.negotiated_name;
|
||||
if (valid_compressions.negotiated_nni)
|
||||
compress_choice = valid_compressions.negotiated_nni->name;
|
||||
else if (compress_choice == NULL) {
|
||||
struct name_num_item *nni = get_nni_by_num(&valid_compressions, do_compression);
|
||||
compress_choice = nni ? nni->name : "UNKNOWN";
|
||||
@@ -210,7 +214,7 @@ void parse_compress_choice(int final_call)
|
||||
&& (do_compression != CPRES_NONE || do_compression_level != CLVL_NOT_SPECIFIED)) {
|
||||
rprintf(FINFO, "%s%s compress: %s (level %d)\n",
|
||||
am_server ? "Server" : "Client",
|
||||
valid_compressions.negotiated_name ? " negotiated" : "",
|
||||
valid_compressions.negotiated_nni ? " negotiated" : "",
|
||||
compress_choice, do_compression_level);
|
||||
}
|
||||
}
|
||||
@@ -223,6 +227,8 @@ struct name_num_item *get_nni_by_name(struct name_num_obj *nno, const char *name
|
||||
len = strlen(name);
|
||||
|
||||
for (nni = nno->list; nni->name; nni++) {
|
||||
if (nni->num == CSUM_gone)
|
||||
continue;
|
||||
if (strncasecmp(name, nni->name, len) == 0 && nni->name[len] == '\0')
|
||||
return nni;
|
||||
}
|
||||
@@ -257,10 +263,12 @@ static void init_nno_saw(struct name_num_obj *nno, int val)
|
||||
if (!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. */
|
||||
/* We'll take this opportunity to set the main_nni values for duplicates. */
|
||||
for (cnt = 1, nni = nno->list; nni->name; nni++, cnt++) {
|
||||
if (nni->num == CSUM_gone)
|
||||
continue;
|
||||
if (nno->saw[nni->num])
|
||||
nni->main_name = nno->list[nno->saw[nni->num]-1].name;
|
||||
nni->main_nni = &nno->list[nno->saw[nni->num]-1];
|
||||
else
|
||||
nno->saw[nni->num] = cnt;
|
||||
}
|
||||
@@ -286,8 +294,8 @@ static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf
|
||||
struct name_num_item *nni = get_nni_by_name(nno, tok, to - tok);
|
||||
if (nni && !nno->saw[nni->num]) {
|
||||
nno->saw[nni->num] = ++cnt;
|
||||
if (nni->main_name) {
|
||||
to = tok + strlcpy(tok, nni->main_name, tobuf_len - (tok - tobuf));
|
||||
if (nni->main_nni) {
|
||||
to = tok + strlcpy(tok, nni->main_nni->name, tobuf_len - (tok - tobuf));
|
||||
if (to - tobuf >= tobuf_len) {
|
||||
to = tok - 1;
|
||||
break;
|
||||
@@ -321,13 +329,44 @@ static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf
|
||||
return to - tobuf;
|
||||
}
|
||||
|
||||
static int parse_negotiate_str(struct name_num_obj *nno, char *tmpbuf)
|
||||
{
|
||||
struct name_num_item *nni, *ret = NULL;
|
||||
int best = nno->saw_len; /* We want best == 1 from the client list, so start with a big number. */
|
||||
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 || am_server) /* The server side stops at the first acceptable client choice */
|
||||
break;
|
||||
}
|
||||
if (ret) {
|
||||
free(nno->saw);
|
||||
nno->saw = NULL;
|
||||
nno->negotiated_nni = ret->main_nni ? ret->main_nni : ret;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (len < 0)
|
||||
len = read_vstring(f_in, tmpbuf, MAX_NSTR_STRLEN);
|
||||
|
||||
@@ -338,37 +377,8 @@ static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf,
|
||||
rprintf(FINFO, "Server %s list (on client): %s\n", nno->type, 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 *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 || am_server) /* The server side stops at the first acceptable client choice */
|
||||
break;
|
||||
}
|
||||
if (ret) {
|
||||
free(nno->saw);
|
||||
nno->saw = NULL;
|
||||
nno->negotiated_name = ret->main_name ? ret->main_name : ret->name;
|
||||
nno->negotiated_num = ret->num;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (len > 0 && parse_negotiate_str(nno, tmpbuf))
|
||||
return;
|
||||
|
||||
if (!am_server || !do_negotiated_strings) {
|
||||
char *cp = tmpbuf;
|
||||
@@ -400,7 +410,7 @@ 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)
|
||||
if (write_batch)
|
||||
env_str = ntype == NSTR_COMPRESS ? "zlib" : protocol_version >= 30 ? "md5" : "md4";
|
||||
|
||||
if (am_server && env_str) {
|
||||
@@ -433,7 +443,7 @@ void validate_choice_vs_env(int ntype, int num1, int num2)
|
||||
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",
|
||||
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);
|
||||
@@ -464,8 +474,10 @@ int get_default_nno_list(struct name_num_obj *nno, char *to_buf, int to_buf_len,
|
||||
init_nno_saw(nno, 0);
|
||||
|
||||
for (nni = nno->list, len = 0; nni->name; nni++) {
|
||||
if (nni->main_name) {
|
||||
if (!dup_markup)
|
||||
if (nni->num == CSUM_gone)
|
||||
continue;
|
||||
if (nni->main_nni) {
|
||||
if (!dup_markup || nni->main_nni->num == CSUM_gone)
|
||||
continue;
|
||||
delim = dup_markup;
|
||||
}
|
||||
@@ -523,6 +535,8 @@ 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. */
|
||||
|
||||
init_checksum_choices();
|
||||
|
||||
if (!checksum_choice)
|
||||
send_negotiate_str(f_out, &valid_checksums, NSTR_CHECKSUM);
|
||||
|
||||
@@ -552,7 +566,7 @@ static void negotiate_the_strings(int f_in, int f_out)
|
||||
/* 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;
|
||||
valid_checksums.negotiated_nni = valid_compressions.negotiated_nni = NULL;
|
||||
}
|
||||
|
||||
void setup_protocol(int f_out,int f_in)
|
||||
@@ -604,7 +618,7 @@ void setup_protocol(int f_out,int f_in)
|
||||
if (remote_protocol < MIN_PROTOCOL_VERSION
|
||||
|| remote_protocol > MAX_PROTOCOL_VERSION) {
|
||||
rprintf(FERROR,"protocol version mismatch -- is your shell clean?\n");
|
||||
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
|
||||
rprintf(FERROR,"(see the rsync manpage for an explanation)\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (remote_protocol < OLD_PROTOCOL_VERSION) {
|
||||
@@ -801,11 +815,77 @@ void setup_protocol(int f_out,int f_in)
|
||||
checksum_seed = read_int(f_in);
|
||||
}
|
||||
|
||||
parse_checksum_choice(1); /* Sets checksum_type & xfersum_type */
|
||||
parse_checksum_choice(1); /* Sets file_sum_nni & xfer_sum_nni */
|
||||
parse_compress_choice(1); /* Sets do_compression */
|
||||
|
||||
/* TODO in the future allow this algorithm to be chosen somehow, but it can't get too
|
||||
* long or the size starts to cause a problem in the xattr abbrev/non-abbrev code. */
|
||||
xattr_sum_nni = parse_csum_name(NULL, 0);
|
||||
xattr_sum_len = csum_len_for_type(xattr_sum_nni->num, 0);
|
||||
|
||||
if (write_batch && !am_server)
|
||||
write_batch_shell_file();
|
||||
|
||||
init_flist();
|
||||
}
|
||||
|
||||
void output_daemon_greeting(int f_out, int am_client)
|
||||
{
|
||||
char tmpbuf[MAX_NSTR_STRLEN];
|
||||
int our_sub = get_subprotocol_version();
|
||||
|
||||
init_checksum_choices();
|
||||
|
||||
get_default_nno_list(&valid_auth_checksums, tmpbuf, MAX_NSTR_STRLEN, '\0');
|
||||
|
||||
io_printf(f_out, "@RSYNCD: %d.%d %s\n", protocol_version, our_sub, tmpbuf);
|
||||
|
||||
if (am_client && DEBUG_GTE(NSTR, 2))
|
||||
rprintf(FINFO, "Client %s list (on client): %s\n", valid_auth_checksums.type, tmpbuf);
|
||||
}
|
||||
|
||||
void negotiate_daemon_auth(int f_out, int am_client)
|
||||
{
|
||||
char tmpbuf[MAX_NSTR_STRLEN];
|
||||
int save_am_server = am_server;
|
||||
int md4_is_old = 0;
|
||||
|
||||
if (!am_client)
|
||||
am_server = 1;
|
||||
|
||||
if (daemon_auth_choices)
|
||||
strlcpy(tmpbuf, daemon_auth_choices, MAX_NSTR_STRLEN);
|
||||
else {
|
||||
strlcpy(tmpbuf, protocol_version >= 30 ? "md5" : "md4", MAX_NSTR_STRLEN);
|
||||
md4_is_old = 1;
|
||||
}
|
||||
|
||||
if (am_client) {
|
||||
recv_negotiate_str(-1, &valid_auth_checksums, tmpbuf, strlen(tmpbuf));
|
||||
if (DEBUG_GTE(NSTR, 1)) {
|
||||
rprintf(FINFO, "Client negotiated %s: %s\n", valid_auth_checksums.type,
|
||||
valid_auth_checksums.negotiated_nni->name);
|
||||
}
|
||||
} else {
|
||||
if (!parse_negotiate_str(&valid_auth_checksums, tmpbuf)) {
|
||||
get_default_nno_list(&valid_auth_checksums, tmpbuf, MAX_NSTR_STRLEN, '\0');
|
||||
io_printf(f_out, "@ERROR: your client does not support one of our daemon-auth checksums: %s\n",
|
||||
tmpbuf);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
am_server = save_am_server;
|
||||
if (md4_is_old && valid_auth_checksums.negotiated_nni->num == CSUM_MD4) {
|
||||
valid_auth_checksums.negotiated_nni->num = CSUM_MD4_OLD;
|
||||
valid_auth_checksums.negotiated_nni->flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int get_subprotocol_version()
|
||||
{
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
return protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
1210
config.guess
vendored
1210
config.guess
vendored
File diff suppressed because it is too large
Load Diff
676
config.sub
vendored
676
config.sub
vendored
File diff suppressed because it is too large
Load Diff
227
configure.ac
227
configure.ac
@@ -4,7 +4,6 @@ AC_INIT([rsync],[ ],[https://rsync.samba.org/bug-tracking.html])
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_TIME
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
|
||||
unistd.h utime.h compat.h sys/param.h ctype.h sys/wait.h sys/stat.h \
|
||||
@@ -13,16 +12,17 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h mcheck.h \
|
||||
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h dl.h \
|
||||
popt.h popt/popt.h linux/falloc.h netinet/in_systm.h netgroup.h \
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h sys/file.h)
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h sys/file.h \
|
||||
bsd/string.h)
|
||||
AC_CHECK_HEADERS([netinet/ip.h], [], [], [[#include <netinet/in.h>]])
|
||||
AC_HEADER_MAJOR_FIXED
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
PACKAGE_VERSION=`sed 's/.*"\(.*\)".*/\1/' <$srcdir/version.h`
|
||||
PACKAGE_VERSION=`sed -n 's/.*RSYNC_VERSION.*"\(.*\)".*/\1/p' <$srcdir/version.h`
|
||||
|
||||
AC_MSG_NOTICE([Configuring rsync $PACKAGE_VERSION])
|
||||
|
||||
@@ -60,7 +60,6 @@ AC_PROG_AWK
|
||||
AC_PROG_EGREP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MKDIR_P
|
||||
AC_PROG_CC_STDC
|
||||
AC_SUBST(SHELL)
|
||||
AC_PATH_PROG([PERL], [perl])
|
||||
AC_PATH_PROG([PYTHON3], [python3])
|
||||
@@ -83,7 +82,7 @@ if test x"$enable_profile" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -pg"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if md2man can create man pages])
|
||||
AC_MSG_CHECKING([if md2man can create manpages])
|
||||
if test x"$ac_cv_path_PYTHON3" = x; then
|
||||
AC_MSG_RESULT(no - python3 not found)
|
||||
md2man_works=no
|
||||
@@ -101,7 +100,7 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([if we require man-page building])
|
||||
AC_ARG_ENABLE([md2man],
|
||||
AS_HELP_STRING([--disable-md2man],[disable to omit man page creation]))
|
||||
AS_HELP_STRING([--disable-md2man],[disable to omit manpage creation]))
|
||||
if test x"$enable_md2man" != x"no"; then
|
||||
if test -f "$srcdir/rsync.1"; then
|
||||
AC_MSG_RESULT(optional)
|
||||
@@ -109,7 +108,7 @@ if test x"$enable_md2man" != x"no"; then
|
||||
AC_MSG_RESULT(required)
|
||||
if test x"$md2man_works" = x"no"; then
|
||||
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 to build manpages based on the git source (manpages are included in the"
|
||||
err_msg="$err_msg$nl official release tar files)."
|
||||
no_lib="$no_lib md2man"
|
||||
fi
|
||||
@@ -135,13 +134,24 @@ if test x"$GCC" = x"yes"; then
|
||||
CFLAGS="$CFLAGS -Wall -W"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(openssl-conf,
|
||||
AS_HELP_STRING([--with-openssl-conf=PATH],[set default OPENSSL_CONF path for rsync]))
|
||||
case "$with_openssl_conf" in
|
||||
*[^-/a-zA-Z0-9.,=@+_]*) AC_MSG_ERROR([Invalid path given to --with-openssl-conf]) ;;
|
||||
/*) CFLAGS="$CFLAGS -DSET_OPENSSL_CONF=$with_openssl_conf" ;;
|
||||
no|'') ;;
|
||||
yes) AC_MSG_ERROR([No path given to --with-openssl-conf]) ;;
|
||||
*) AC_MSG_ERROR([Non absolute path given to --with-openssl-conf]) ;;
|
||||
esac
|
||||
|
||||
AC_ARG_WITH(rrsync,
|
||||
AS_HELP_STRING([--with-rrsync],[also install the rrsync script and its man page]))
|
||||
AS_HELP_STRING([--with-rrsync],[also install the rrsync script and its manpage]))
|
||||
if test x"$with_rrsync" != x"yes"; then
|
||||
with_rrsync=no
|
||||
else
|
||||
MAKE_RRSYNC='rrsync'
|
||||
MAKE_RRSYNC_1='rrsync.1'
|
||||
GEN_RRSYNC='rrsync.1 rrsync.1.html'
|
||||
fi
|
||||
AC_SUBST(with_rrsync)
|
||||
|
||||
@@ -151,10 +161,10 @@ AC_ARG_WITH(included-popt,
|
||||
AC_ARG_WITH(included-zlib,
|
||||
AS_HELP_STRING([--with-included-zlib],[use bundled zlib library, not from system]))
|
||||
|
||||
AC_ARG_WITH(protected-args,
|
||||
AS_HELP_STRING([--with-protected-args],[make --protected-args option the default]))
|
||||
if test x"$with_protected_args" = x"yes"; then
|
||||
AC_DEFINE_UNQUOTED(RSYNC_USE_PROTECTED_ARGS, 1, [Define to 1 if --protected-args should be the default])
|
||||
AC_ARG_WITH(secluded-args,
|
||||
AS_HELP_STRING([--with-secluded-args],[make --secluded-args option the default]))
|
||||
if test x"$with_secluded_args" = x"yes"; then
|
||||
AC_DEFINE_UNQUOTED(RSYNC_USE_SECLUDED_ARGS, 1, [Define to 1 if --secluded-args should be the default])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(rsync-path,
|
||||
@@ -228,12 +238,12 @@ fi
|
||||
AC_DEFINE_UNQUOTED(NOBODY_USER, "$NOBODY_USER", [unprivileged user--e.g. nobody])
|
||||
AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unprivileged user])
|
||||
|
||||
# SIMD optimizations
|
||||
SIMD=
|
||||
# rolling-checksum SIMD optimizations
|
||||
ROLL_SIMD=
|
||||
|
||||
AC_MSG_CHECKING([whether to enable SIMD optimizations])
|
||||
AC_ARG_ENABLE(simd,
|
||||
AS_HELP_STRING([--enable-simd],[enable/disable to control SIMD optimizations (requires c++)]))
|
||||
AC_MSG_CHECKING([whether to enable rolling-checksum SIMD optimizations])
|
||||
AC_ARG_ENABLE(roll-simd,
|
||||
AS_HELP_STRING([--enable-roll-simd],[enable/disable to control rolling-checksum SIMD optimizations (requires c++)]))
|
||||
|
||||
# Clag is crashing with -g -O2, so we'll get rid of -g for now.
|
||||
CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-g //'`
|
||||
@@ -262,14 +272,14 @@ __attribute__ ((target("ssse3"))) void more_testing(char* buf, int len)
|
||||
}
|
||||
]])
|
||||
|
||||
if test x"$enable_simd" = x""; then
|
||||
if test x"$enable_roll_simd" = x""; then
|
||||
case "$host_os" in
|
||||
*linux*) ;;
|
||||
*) enable_simd=no ;;
|
||||
*) enable_roll_simd=no ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x"$enable_simd" != x"no"; then
|
||||
if test x"$enable_roll_simd" != x"no"; then
|
||||
# For x86-64 SIMD, g++ >=5 or clang++ >=7 is required
|
||||
if test x"$host_cpu" = x"x86_64" || test x"$host_cpu" = x"amd64"; then
|
||||
AC_LANG(C++)
|
||||
@@ -282,23 +292,23 @@ if test x"$enable_simd" != x"no"; then
|
||||
AC_LANG(C)
|
||||
if test x"$CXX_OK" = x"yes"; then
|
||||
# AC_MSG_RESULT() is called below.
|
||||
SIMD="$host_cpu"
|
||||
elif test x"$enable_simd" = x"yes"; then
|
||||
ROLL_SIMD="$host_cpu"
|
||||
elif test x"$enable_roll_simd" = x"yes"; then
|
||||
AC_MSG_RESULT(error)
|
||||
AC_MSG_ERROR(The SIMD compilation test failed.
|
||||
Omit --enable-simd to continue without it.)
|
||||
AC_MSG_ERROR(The rolling-checksum SIMD compilation test failed.
|
||||
Omit --enable-roll-simd to continue without it.)
|
||||
fi
|
||||
elif test x"$enable_simd" = x"yes"; then
|
||||
elif test x"$enable_roll_simd" = x"yes"; then
|
||||
AC_MSG_RESULT(unavailable)
|
||||
AC_MSG_ERROR(The SIMD optimizations are currently x86_64|amd64 only.
|
||||
Omit --enable-simd to continue without it.)
|
||||
AC_MSG_ERROR(The rolling-checksum SIMD optimizations are currently x86_64|amd64 only.
|
||||
Omit --enable-roll-simd to continue without it.)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x"$SIMD" != x""; then
|
||||
AC_MSG_RESULT([yes ($SIMD)])
|
||||
AC_DEFINE(HAVE_SIMD, 1, [Define to 1 to enable SIMD optimizations])
|
||||
SIMD='$(SIMD_'"$SIMD)"
|
||||
if test x"$ROLL_SIMD" != x""; then
|
||||
AC_MSG_RESULT([yes ($ROLL_SIMD)])
|
||||
AC_DEFINE(USE_ROLL_SIMD, 1, [Define to 1 to enable rolling-checksum SIMD optimizations])
|
||||
ROLL_SIMD='$(ROLL_SIMD_'"$ROLL_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.
|
||||
@@ -310,7 +320,7 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_SUBST(SIMD)
|
||||
AC_SUBST(ROLL_SIMD)
|
||||
|
||||
AC_MSG_CHECKING([if assembler accepts noexecstack])
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
@@ -321,52 +331,19 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[return 0;]])],
|
||||
CFLAGS="$OLD_CFLAGS"
|
||||
AC_SUBST(NOEXECSTACK)
|
||||
|
||||
ASM=
|
||||
|
||||
AC_MSG_CHECKING([whether to enable ASM optimizations])
|
||||
AC_ARG_ENABLE(asm,
|
||||
AS_HELP_STRING([--enable-asm],[enable/disable to control ASM optimizations]))
|
||||
|
||||
if test x"$enable_asm" = x""; then
|
||||
case "$host_os" in
|
||||
*linux*) ;;
|
||||
*) enable_asm=no ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x"$enable_asm" != x"no"; then
|
||||
if test x"$host_cpu" = x"x86_64" || test x"$host_cpu" = x"amd64"; then
|
||||
ASM="$host_cpu"
|
||||
elif test x"$enable_asm" = x"yes"; then
|
||||
AC_MSG_RESULT(unavailable)
|
||||
AC_MSG_ERROR(The ASM optimizations are currently x86_64|amd64 only.
|
||||
Omit --enable-asm to continue without it.)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x"$ASM" != x""; then
|
||||
AC_MSG_RESULT([yes ($ASM)])
|
||||
AC_DEFINE(HAVE_ASM, 1, [Define to 1 to enable ASM optimizations])
|
||||
ASM='$(ASM_'"$ASM)"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_SUBST(ASM)
|
||||
|
||||
# arrgh. libc in some old debian version screwed up the largefile
|
||||
# stuff, getting byte range locking wrong
|
||||
AC_CACHE_CHECK([for broken largefile support],rsync_cv_HAVE_BROKEN_LARGEFILE,[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
$ac_includes_default
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#elif defined HAVE_SYS_FCNTL_H
|
||||
# include <sys/fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
@@ -411,7 +388,7 @@ AS_HELP_STRING([--disable-ipv6],[disable to omit ipv6 support]),
|
||||
;;
|
||||
esac ],
|
||||
|
||||
AC_TRY_RUN([ /* AF_INET6 avalable check */
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[ /* AF_INET6 availability check */
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -422,11 +399,11 @@ main()
|
||||
else
|
||||
exit(0);
|
||||
}
|
||||
],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6]),
|
||||
AC_MSG_RESULT(no),
|
||||
AC_MSG_RESULT(no)
|
||||
]])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(INET6, 1, true if you have IPv6)],
|
||||
[AC_MSG_RESULT(no)],
|
||||
[AC_MSG_RESULT(no)]
|
||||
))
|
||||
|
||||
dnl Do you want to disable use of locale functions
|
||||
@@ -455,19 +432,77 @@ AH_TEMPLATE([USE_OPENSSL],
|
||||
if test x"$enable_openssl" != x"no"; then
|
||||
if test x"$ac_cv_header_openssl_md4_h" = x"yes" && test x"$ac_cv_header_openssl_md5_h" = x"yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_SEARCH_LIBS(MD5_Init, crypto,
|
||||
[AC_DEFINE(USE_OPENSSL)],
|
||||
[err_msg="$err_msg$nl- Failed to find MD5_Init function in openssl crypto lib.";
|
||||
AC_SEARCH_LIBS(EVP_MD_CTX_copy, crypto,
|
||||
[AC_DEFINE(USE_OPENSSL)
|
||||
enable_openssl=yes],
|
||||
[err_msg="$err_msg$nl- Failed to find EVP_MD_CTX_copy function in openssl crypto lib.";
|
||||
no_lib="$no_lib openssl"])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
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
|
||||
if test x"$enable_md5_asm" != x"yes"; then
|
||||
enable_md5_asm=no
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
MD5_ASM=
|
||||
|
||||
AC_MSG_CHECKING([whether to enable MD5 ASM optimizations])
|
||||
AC_ARG_ENABLE(md5-asm,
|
||||
AS_HELP_STRING([--enable-md5-asm],[enable/disable to control MD5 ASM optimizations]))
|
||||
|
||||
if test x"$enable_md5_asm" = x""; then
|
||||
case "$host_os" in
|
||||
*linux*) ;;
|
||||
*) enable_md5_asm=no ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x"$enable_md5_asm" != x"no"; then
|
||||
if test x"$host_cpu" = x"x86_64" || test x"$host_cpu" = x"amd64"; then
|
||||
MD5_ASM="$host_cpu"
|
||||
elif test x"$enable_md5_asm" = x"yes"; then
|
||||
AC_MSG_RESULT(unavailable)
|
||||
AC_MSG_ERROR(The ASM optimizations are currently x86_64|amd64 only.
|
||||
Omit --enable-md5-asm to continue without it.)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x"$MD5_ASM" != x""; then
|
||||
AC_MSG_RESULT([yes ($MD5_ASM)])
|
||||
AC_DEFINE(USE_MD5_ASM, 1, [Define to 1 to enable MD5 ASM optimizations])
|
||||
MD5_ASM='$(MD5_ASM_'"$MD5_ASM)"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_SUBST(MD5_ASM)
|
||||
|
||||
ROLL_ASM=
|
||||
|
||||
AC_MSG_CHECKING([whether to enable rolling-checksum ASM optimizations])
|
||||
AC_ARG_ENABLE(roll-asm,
|
||||
AS_HELP_STRING([--enable-roll-asm],[enable/disable to control rolling-checksum ASM optimizations (requires --enable-roll-simd)]))
|
||||
|
||||
if test x"$ROLL_SIMD" = x""; then
|
||||
enable_roll_asm=no
|
||||
fi
|
||||
|
||||
if test x"$enable_roll_asm" = x"yes"; then
|
||||
ROLL_ASM="$host_cpu"
|
||||
AC_MSG_RESULT([yes ($ROLL_ASM)])
|
||||
AC_DEFINE(USE_ROLL_ASM, 1, [Define to 1 to enable rolling-checksum ASM optimizations (requires --enable-roll-simd)])
|
||||
ROLL_ASM='$(ROLL_ASM_'"$ROLL_ASM)"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_SUBST(ROLL_ASM)
|
||||
|
||||
AC_MSG_CHECKING([whether to enable xxhash checksum support])
|
||||
AC_ARG_ENABLE([xxhash],
|
||||
AS_HELP_STRING([--disable-xxhash],[disable to omit xxhash checksums]))
|
||||
@@ -491,7 +526,7 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([whether to enable zstd compression])
|
||||
AC_ARG_ENABLE([zstd],
|
||||
AC_HELP_STRING([--disable-zstd], [disable to omit zstd compression]))
|
||||
AS_HELP_STRING([--disable-zstd], [disable to omit zstd compression]))
|
||||
AH_TEMPLATE([SUPPORT_ZSTD],
|
||||
[Undefine if you do not want zstd compression. By default this is defined.])
|
||||
if test x"$enable_zstd" != x"no"; then
|
||||
@@ -512,7 +547,7 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([whether to enable LZ4 compression])
|
||||
AC_ARG_ENABLE([lz4],
|
||||
AC_HELP_STRING([--disable-lz4], [disable to omit LZ4 compression]))
|
||||
AS_HELP_STRING([--disable-lz4], [disable to omit LZ4 compression]))
|
||||
AH_TEMPLATE([SUPPORT_LZ4],
|
||||
[Undefine if you do not want LZ4 compression. By default this is defined.])
|
||||
if test x"$enable_lz4" != x"no"; then
|
||||
@@ -537,7 +572,7 @@ if test x"$no_lib" != x; then
|
||||
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 "how to generate (or fetch) manpages:"
|
||||
echo " https://github.com/WayneD/rsync/blob/master/INSTALL.md"
|
||||
echo ""
|
||||
echo "To disable one or more features, the relevant configure options are:"
|
||||
@@ -598,7 +633,11 @@ fi
|
||||
|
||||
AC_TYPE_UID_T
|
||||
AC_CHECK_TYPES([mode_t,off_t,size_t,pid_t,id_t])
|
||||
AC_TYPE_GETGROUPS
|
||||
if test "$cross_compiling" = no; then
|
||||
AC_TYPE_GETGROUPS
|
||||
else
|
||||
AC_DEFINE([GETGROUPS_T],[gid_t],[Define to the type of elements in the array set by `getgroups'. Usually this is either `int' or `gid_t'.])
|
||||
fi
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev,
|
||||
struct stat.st_mtimensec,
|
||||
struct stat.st_mtimespec.tv_nsec,
|
||||
@@ -1040,21 +1079,6 @@ elif test x"$ac_cv_header_popt_h" != x"yes"; then
|
||||
with_included_popt=yes
|
||||
fi
|
||||
|
||||
if test x"$GCC" = x"yes"; then
|
||||
if test x"$with_included_popt" != x"yes"; then
|
||||
# Turn pedantic warnings into errors to ensure an array-init overflow is an error.
|
||||
CFLAGS="$CFLAGS -pedantic-errors"
|
||||
else
|
||||
# Our internal popt code cannot be compiled with pedantic warnings as errors, so try to
|
||||
# turn off pedantic warnings (which will not lose the error for array-init overflow).
|
||||
# Older gcc versions don't understand -Wno-pedantic, so check if --help=warnings lists
|
||||
# -Wpedantic and use that as a flag.
|
||||
case `$CC --help=warnings 2>/dev/null | grep Wpedantic` in
|
||||
*-Wpedantic*) CFLAGS="$CFLAGS -pedantic-errors -Wno-pedantic" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to use included libpopt])
|
||||
if test x"$with_included_popt" = x"yes"; then
|
||||
AC_MSG_RESULT($srcdir/popt)
|
||||
@@ -1091,7 +1115,7 @@ else
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for unsigned char],rsync_cv_SIGNED_CHAR_OK,[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[signed char *s = ""]])],[rsync_cv_SIGNED_CHAR_OK=yes],[rsync_cv_SIGNED_CHAR_OK=no])])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[signed char *s = (signed char *)""]])],[rsync_cv_SIGNED_CHAR_OK=yes],[rsync_cv_SIGNED_CHAR_OK=no])])
|
||||
if test x"$rsync_cv_SIGNED_CHAR_OK" = x"yes"; then
|
||||
AC_DEFINE(SIGNED_CHAR_OK, 1, [Define to 1 if "signed char" is a valid type])
|
||||
fi
|
||||
@@ -1257,6 +1281,7 @@ AC_SUBST(BUILD_POPT)
|
||||
AC_SUBST(BUILD_ZLIB)
|
||||
AC_SUBST(MAKE_RRSYNC)
|
||||
AC_SUBST(MAKE_RRSYNC_1)
|
||||
AC_SUBST(GEN_RRSYNC)
|
||||
AC_SUBST(MAKE_MAN)
|
||||
|
||||
AC_CHECK_FUNCS(_acl __acl _facl __facl)
|
||||
|
||||
@@ -7,39 +7,54 @@ basically a summary of clientserver.c and authenticate.c.
|
||||
This is the protocol used for rsync --daemon; i.e. connections to port
|
||||
873 rather than invocations over a remote shell.
|
||||
|
||||
When the server accepts a connection, it prints a greeting
|
||||
When the server accepts a connection, it prints a newline-terminated
|
||||
greeting line:
|
||||
|
||||
@RSYNCD: <version>.<subprotocol>
|
||||
@RSYNCD: <version>.<subprotocol> <digest1> <digestN>
|
||||
|
||||
where <version> is the numeric version (see PROTOCOL_VERSION in rsync.h)
|
||||
'.' is a literal period, and <subprotocol> is the numeric subprotocol
|
||||
version (see SUBPROTOCOL_VERSION -- it will be 0 for final releases).
|
||||
Protocols prior to 30 only output <version> alone. The daemon expects
|
||||
to see a similar greeting back from the client. For protocols prior to
|
||||
30, an absent ".<subprotocol>" value is assumed to be 0. For protocol
|
||||
30, an absent value is a fatal error. The daemon then follows this line
|
||||
with a free-format text message-of-the-day (if any is defined).
|
||||
The <version> is the numeric version (see PROTOCOL_VERSION in rsync.h)
|
||||
The <subprotocol> is the numeric subprotocol version (which is 0 for a
|
||||
final protocol version, as the SUBPROTOCOL_VERSION define discusses).
|
||||
The <digestN> names are the authentication digest algorithms that the
|
||||
daemon supports, listed in order of preference.
|
||||
|
||||
An rsync prior to 3.2.7 omits the digest names. An rsync prior to 3.0.0
|
||||
also omits the period and the <subprotocol> value. Since a final
|
||||
protocol has a subprotocol value of 0, a missing subprotocol value is
|
||||
assumed to be 0 for any protocol prior to 30. It is considered a fatal
|
||||
error for protocol 30 and above to omit it. It is considered a fatal
|
||||
error for protocol 32 and above to omit the digest name list (currently
|
||||
31 is the newest protocol).
|
||||
|
||||
The daemon expects to see a similar greeting line back from the client.
|
||||
Once received, the daemon follows the opening line with a free-format
|
||||
text message-of-the-day (if any is defined).
|
||||
|
||||
The server is now in the connected state. The client can either send
|
||||
the command
|
||||
the command:
|
||||
|
||||
#list
|
||||
|
||||
to get a listing of modules, or the name of a module. After this, the
|
||||
(to get a listing of modules) or the name of a module. After this, the
|
||||
connection is now bound to a particular module. Access per host for
|
||||
this module is now checked, as is per-module connection limits.
|
||||
|
||||
If authentication is required to use this module, the server will say
|
||||
If authentication is required to use this module, the server will say:
|
||||
|
||||
@RSYNCD: AUTHREQD <challenge>
|
||||
|
||||
where <challenge> is a random string of base64 characters. The client
|
||||
must respond with
|
||||
must respond with:
|
||||
|
||||
<user> <response>
|
||||
|
||||
where <user> is the username they claim to be, and <response> is the
|
||||
base64 form of the MD4 hash of challenge+password.
|
||||
The <user> is the username they claim to be. The <response> is the
|
||||
base64 form of the digest hash of the challenge+password string. The
|
||||
chosen digest method is the most preferred client method that is also in
|
||||
the server's list. If no digest list was explicitly provided, the side
|
||||
expecting a list assumes the other side provided either the single name
|
||||
"md5" (for a negotiated protocol 30 or 31), or the single name "md4"
|
||||
(for an older protocol).
|
||||
|
||||
At this point the server applies all remaining constraints before
|
||||
handing control to the client, including switching uid/gid, setting up
|
||||
@@ -76,6 +91,13 @@ stay tuned (or write it yourself!).
|
||||
------------
|
||||
Protocol version changes
|
||||
|
||||
31 (2013-09-28, 3.1.0)
|
||||
|
||||
Initial release of protocol 31 had no changes. Rsync 3.2.7
|
||||
introduced the suffixed list of digest names on the greeting
|
||||
line. The presence of the list is allowed even if the greeting
|
||||
indicates an older protocol version number.
|
||||
|
||||
30 (2007-10-04, 3.0.0pre1)
|
||||
|
||||
The use of a ".<subprotocol>" number was added to
|
||||
|
||||
@@ -60,9 +60,9 @@ 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
|
||||
BOOL3 use_chroot Unset
|
||||
|
||||
4
delete.c
4
delete.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2024 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
|
||||
@@ -188,7 +188,7 @@ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
|
||||
stats.deleted_symlinks++;
|
||||
#endif
|
||||
else if (IS_DEVICE(mode))
|
||||
stats.deleted_symlinks++;
|
||||
stats.deleted_devices++;
|
||||
else
|
||||
stats.deleted_specials++;
|
||||
}
|
||||
|
||||
339
exclude.c
339
exclude.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2024 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
|
||||
@@ -25,16 +25,21 @@
|
||||
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int eol_nulls;
|
||||
extern int io_error;
|
||||
extern int xfer_dirs;
|
||||
extern int recurse;
|
||||
extern int local_server;
|
||||
extern int prune_empty_dirs;
|
||||
extern int ignore_perishable;
|
||||
extern int relative_paths;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
extern int cvs_exclude;
|
||||
extern int sanitize_paths;
|
||||
extern int protocol_version;
|
||||
extern int trust_sender_args;
|
||||
extern int module_id;
|
||||
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
@@ -44,8 +49,11 @@ extern unsigned int module_dirlen;
|
||||
filter_rule_list filter_list = { .debug_type = "" };
|
||||
filter_rule_list cvs_filter_list = { .debug_type = " [global CVS]" };
|
||||
filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" };
|
||||
filter_rule_list implied_filter_list = { .debug_type = " [implied]" };
|
||||
|
||||
int saw_xattr_filter = 0;
|
||||
int trust_sender_args = 0;
|
||||
int trust_sender_filter = 0;
|
||||
|
||||
/* Need room enough for ":MODS " prefix plus some room to grow. */
|
||||
#define MAX_RULE_PREFIX (16)
|
||||
@@ -70,6 +78,10 @@ static filter_rule **mergelist_parents;
|
||||
static int mergelist_cnt = 0;
|
||||
static int mergelist_size = 0;
|
||||
|
||||
#define LOCAL_RULE 1
|
||||
#define REMOTE_RULE 2
|
||||
static uchar cur_elide_value = REMOTE_RULE;
|
||||
|
||||
/* Each filter_list_struct describes a singly-linked list by keeping track
|
||||
* of both the head and tail pointers. The list is slightly unusual in that
|
||||
* a parent-dir's content can be appended to the end of the local list in a
|
||||
@@ -152,13 +164,17 @@ static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_
|
||||
{
|
||||
const char *cp;
|
||||
unsigned int pre_len, suf_len, slash_cnt = 0;
|
||||
char *mention_rule_suffix;
|
||||
|
||||
if (DEBUG_GTE(FILTER, 2)) {
|
||||
rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n",
|
||||
if (DEBUG_GTE(FILTER, 1) && pat_len && (pat[pat_len-1] == ' ' || pat[pat_len-1] == '\t'))
|
||||
mention_rule_suffix = " -- CAUTION: trailing whitespace!";
|
||||
else
|
||||
mention_rule_suffix = DEBUG_GTE(FILTER, 2) ? "" : NULL;
|
||||
if (mention_rule_suffix) {
|
||||
rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s%s\n",
|
||||
who_am_i(), get_rule_prefix(rule, pat, 0, NULL),
|
||||
(int)pat_len, pat,
|
||||
(rule->rflags & FILTRULE_DIRECTORY) ? "/" : "",
|
||||
listp->debug_type);
|
||||
(int)pat_len, pat, (rule->rflags & FILTRULE_DIRECTORY) ? "/" : "",
|
||||
listp->debug_type, mention_rule_suffix);
|
||||
}
|
||||
|
||||
/* These flags also indicate that we're reading a list that
|
||||
@@ -208,6 +224,7 @@ static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_
|
||||
slash_cnt++;
|
||||
}
|
||||
}
|
||||
rule->elide = 0;
|
||||
strlcpy(rule->pattern + pre_len, pat, pat_len + 1);
|
||||
pat_len += pre_len;
|
||||
if (suf_len) {
|
||||
@@ -288,6 +305,271 @@ static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_
|
||||
}
|
||||
}
|
||||
|
||||
/* If the wildcards failed, the remote shell might give us a file matching the literal
|
||||
* wildcards. Since "*" & "?" already match themselves, this just needs to deal with
|
||||
* failed "[foo]" idioms.
|
||||
*/
|
||||
static void maybe_add_literal_brackets_rule(filter_rule const *based_on, int arg_len)
|
||||
{
|
||||
filter_rule *rule;
|
||||
const char *arg = based_on->pattern, *cp;
|
||||
char *p;
|
||||
int cnt = 0;
|
||||
|
||||
if (arg_len < 0)
|
||||
arg_len = strlen(arg);
|
||||
|
||||
for (cp = arg; *cp; cp++) {
|
||||
if (*cp == '\\' && cp[1]) {
|
||||
cp++;
|
||||
} else if (*cp == '[')
|
||||
cnt++;
|
||||
}
|
||||
if (!cnt)
|
||||
return;
|
||||
|
||||
rule = new0(filter_rule);
|
||||
rule->rflags = based_on->rflags;
|
||||
rule->u.slash_cnt = based_on->u.slash_cnt;
|
||||
p = rule->pattern = new_array(char, arg_len + cnt + 1);
|
||||
for (cp = arg; *cp; ) {
|
||||
if (*cp == '\\' && cp[1]) {
|
||||
*p++ = *cp++;
|
||||
} else if (*cp == '[')
|
||||
*p++ = '\\';
|
||||
*p++ = *cp++;
|
||||
}
|
||||
*p++ = '\0';
|
||||
|
||||
rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = rule;
|
||||
if (DEBUG_GTE(FILTER, 3)) {
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s%s)\n", who_am_i(), rule->pattern,
|
||||
rule->rflags & FILTRULE_DIRECTORY ? "/" : "");
|
||||
}
|
||||
}
|
||||
|
||||
static char *partial_string_buf = NULL;
|
||||
static int partial_string_len = 0;
|
||||
void implied_include_partial_string(const char *s_start, const char *s_end)
|
||||
{
|
||||
partial_string_len = s_end - s_start;
|
||||
if (partial_string_len <= 0 || partial_string_len >= MAXPATHLEN) { /* too-large should be impossible... */
|
||||
partial_string_len = 0;
|
||||
return;
|
||||
}
|
||||
if (!partial_string_buf)
|
||||
partial_string_buf = new_array(char, MAXPATHLEN);
|
||||
memcpy(partial_string_buf, s_start, partial_string_len);
|
||||
}
|
||||
|
||||
void free_implied_include_partial_string()
|
||||
{
|
||||
if (partial_string_buf) {
|
||||
if (partial_string_len)
|
||||
add_implied_include("", 0);
|
||||
free(partial_string_buf);
|
||||
partial_string_buf = NULL;
|
||||
}
|
||||
partial_string_len = 0; /* paranoia */
|
||||
}
|
||||
|
||||
/* Each arg the client sends to the remote sender turns into an implied include
|
||||
* that the receiver uses to validate the file list from the sender. */
|
||||
void add_implied_include(const char *arg, int skip_daemon_module)
|
||||
{
|
||||
int arg_len, saw_wild = 0, saw_live_open_brkt = 0, backslash_cnt = 0;
|
||||
int slash_cnt = 0;
|
||||
const char *cp;
|
||||
char *p;
|
||||
if (trust_sender_args)
|
||||
return;
|
||||
if (partial_string_len) {
|
||||
arg_len = strlen(arg);
|
||||
if (partial_string_len + arg_len >= MAXPATHLEN) {
|
||||
partial_string_len = 0;
|
||||
return; /* Should be impossible... */
|
||||
}
|
||||
memcpy(partial_string_buf + partial_string_len, arg, arg_len + 1);
|
||||
partial_string_len = 0;
|
||||
arg = partial_string_buf;
|
||||
}
|
||||
if (skip_daemon_module) {
|
||||
if ((cp = strchr(arg, '/')) != NULL)
|
||||
arg = cp + 1;
|
||||
else
|
||||
arg = "";
|
||||
}
|
||||
if (relative_paths) {
|
||||
if ((cp = strstr(arg, "/./")) != NULL)
|
||||
arg = cp + 3;
|
||||
} else if ((cp = strrchr(arg, '/')) != NULL) {
|
||||
arg = cp + 1;
|
||||
}
|
||||
if (*arg == '.' && arg[1] == '\0')
|
||||
arg++;
|
||||
arg_len = strlen(arg);
|
||||
if (arg_len) {
|
||||
char *new_pat;
|
||||
if (strpbrk(arg, "*[?")) {
|
||||
/* We need to add room to escape backslashes if wildcard chars are present. */
|
||||
for (cp = arg; (cp = strchr(cp, '\\')) != NULL; cp++)
|
||||
arg_len++;
|
||||
saw_wild = 1;
|
||||
}
|
||||
arg_len++; /* Leave room for the prefixed slash */
|
||||
p = new_pat = new_array(char, arg_len + 1);
|
||||
*p++ = '/';
|
||||
slash_cnt++;
|
||||
for (cp = arg; *cp; ) {
|
||||
switch (*cp) {
|
||||
case '\\':
|
||||
if (cp[1] == ']') {
|
||||
if (!saw_wild)
|
||||
cp++; /* A \] in a non-wild filter causes a problem, so drop the \ . */
|
||||
} else if (!strchr("*[?", cp[1])) {
|
||||
backslash_cnt++;
|
||||
if (saw_wild)
|
||||
*p++ = '\\';
|
||||
}
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
case '/':
|
||||
if (p[-1] == '/') { /* This is safe because of the initial slash. */
|
||||
if (*++cp == '\0') {
|
||||
slash_cnt--;
|
||||
p--;
|
||||
}
|
||||
} else if (cp[1] == '\0') {
|
||||
cp++;
|
||||
} else {
|
||||
slash_cnt++;
|
||||
*p++ = *cp++;
|
||||
}
|
||||
break;
|
||||
case '.':
|
||||
if (p[-1] == '/') {
|
||||
if (cp[1] == '/') {
|
||||
cp += 2;
|
||||
if (!*cp) {
|
||||
slash_cnt--;
|
||||
p--;
|
||||
}
|
||||
} else if (cp[1] == '\0') {
|
||||
cp++;
|
||||
slash_cnt--;
|
||||
p--;
|
||||
} else
|
||||
*p++ = *cp++;
|
||||
} else
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
case '[':
|
||||
saw_live_open_brkt = 1;
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
default:
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
arg_len = p - new_pat;
|
||||
if (!arg_len)
|
||||
free(new_pat);
|
||||
else {
|
||||
filter_rule *rule = new0(filter_rule);
|
||||
rule->rflags = FILTRULE_INCLUDE + (saw_wild ? FILTRULE_WILD : 0);
|
||||
rule->u.slash_cnt = slash_cnt;
|
||||
arg = rule->pattern = new_pat;
|
||||
if (!implied_filter_list.head)
|
||||
implied_filter_list.head = implied_filter_list.tail = rule;
|
||||
else {
|
||||
rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = rule;
|
||||
}
|
||||
if (DEBUG_GTE(FILTER, 3))
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s)\n", who_am_i(), arg);
|
||||
if (saw_live_open_brkt)
|
||||
maybe_add_literal_brackets_rule(rule, arg_len);
|
||||
if (relative_paths && slash_cnt) {
|
||||
int sub_slash_cnt = slash_cnt;
|
||||
while ((p = strrchr(new_pat, '/')) != NULL && p != new_pat) {
|
||||
filter_rule const *ent;
|
||||
filter_rule *R_rule;
|
||||
int found = 0;
|
||||
*p = '\0';
|
||||
for (ent = implied_filter_list.head; ent; ent = ent->next) {
|
||||
if (ent != rule && strcmp(ent->pattern, new_pat) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
*p = '/';
|
||||
break; /* We added all parent dirs already */
|
||||
}
|
||||
R_rule = new0(filter_rule);
|
||||
R_rule->rflags = FILTRULE_INCLUDE | FILTRULE_DIRECTORY;
|
||||
/* Check if our sub-path has wildcards or escaped backslashes */
|
||||
if (saw_wild && strpbrk(new_pat, "*[?\\"))
|
||||
R_rule->rflags |= FILTRULE_WILD;
|
||||
R_rule->pattern = strdup(new_pat);
|
||||
R_rule->u.slash_cnt = --sub_slash_cnt;
|
||||
R_rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = R_rule;
|
||||
if (DEBUG_GTE(FILTER, 3)) {
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s/)\n",
|
||||
who_am_i(), R_rule->pattern);
|
||||
}
|
||||
if (saw_live_open_brkt)
|
||||
maybe_add_literal_brackets_rule(R_rule, -1);
|
||||
}
|
||||
for (p = new_pat; sub_slash_cnt < slash_cnt; sub_slash_cnt++) {
|
||||
p += strlen(p);
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (recurse || xfer_dirs) {
|
||||
/* Now create a rule with an added "/" & "**" or "*" at the end */
|
||||
filter_rule *rule = new0(filter_rule);
|
||||
rule->rflags = FILTRULE_INCLUDE | FILTRULE_WILD;
|
||||
if (recurse)
|
||||
rule->rflags |= FILTRULE_WILD2;
|
||||
/* We must leave enough room for / * * \0. */
|
||||
if (!saw_wild && backslash_cnt) {
|
||||
/* We are appending a wildcard, so now the backslashes need to be escaped. */
|
||||
p = rule->pattern = new_array(char, arg_len + backslash_cnt + 3 + 1);
|
||||
for (cp = arg; *cp; ) { /* Note that arg_len != 0 because backslash_cnt > 0 */
|
||||
if (*cp == '\\')
|
||||
*p++ = '\\';
|
||||
*p++ = *cp++;
|
||||
}
|
||||
} else {
|
||||
p = rule->pattern = new_array(char, arg_len + 3 + 1);
|
||||
if (arg_len) {
|
||||
memcpy(p, arg, arg_len);
|
||||
p += arg_len;
|
||||
}
|
||||
}
|
||||
*p++ = '/';
|
||||
*p++ = '*';
|
||||
if (recurse)
|
||||
*p++ = '*';
|
||||
*p = '\0';
|
||||
rule->u.slash_cnt = slash_cnt + 1;
|
||||
rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = rule;
|
||||
if (DEBUG_GTE(FILTER, 3))
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s)\n", who_am_i(), rule->pattern);
|
||||
if (saw_live_open_brkt)
|
||||
maybe_add_literal_brackets_rule(rule, p - rule->pattern);
|
||||
}
|
||||
}
|
||||
|
||||
/* This frees any non-inherited items, leaving just inherited items on the list. */
|
||||
static void pop_filter_list(filter_rule_list *listp)
|
||||
{
|
||||
@@ -438,7 +720,8 @@ static BOOL setup_merge_file(int mergelist_num, filter_rule *ex,
|
||||
parent_dirscan = True;
|
||||
while (*y) {
|
||||
char save[MAXPATHLEN];
|
||||
strlcpy(save, y, MAXPATHLEN);
|
||||
/* copylen is strlen(y) which is < MAXPATHLEN. +1 for \0 */
|
||||
size_t copylen = strlcpy(save, y, MAXPATHLEN) + 1;
|
||||
*y = '\0';
|
||||
dirbuf_len = y - dirbuf;
|
||||
strlcpy(x, ex->pattern, MAXPATHLEN - (x - buf));
|
||||
@@ -452,7 +735,7 @@ static BOOL setup_merge_file(int mergelist_num, filter_rule *ex,
|
||||
lp->head = NULL;
|
||||
}
|
||||
lp->tail = NULL;
|
||||
strlcpy(y, save, MAXPATHLEN);
|
||||
strlcpy(y, save, copylen);
|
||||
while ((*x++ = *y++) != '/') {}
|
||||
}
|
||||
parent_dirscan = False;
|
||||
@@ -625,7 +908,7 @@ static int rule_matches(const char *fname, filter_rule *ex, int name_flags)
|
||||
const char *strings[16]; /* more than enough */
|
||||
const char *name = fname + (*fname == '/');
|
||||
|
||||
if (!*name)
|
||||
if (!*name || ex->elide == cur_elide_value)
|
||||
return 0;
|
||||
|
||||
if (!(name_flags & NAME_IS_XATTR) ^ !(ex->rflags & FILTRULE_XATTR))
|
||||
@@ -702,11 +985,12 @@ static void report_filter_result(enum logcode code, char const *name,
|
||||
filter_rule const *ent,
|
||||
int name_flags, const char *type)
|
||||
{
|
||||
int log_level = am_sender || am_generator ? 1 : 3;
|
||||
|
||||
/* If a trailing slash is present to match only directories,
|
||||
* then it is stripped out by add_rule(). So as a special
|
||||
* case we add it back in here. */
|
||||
|
||||
if (DEBUG_GTE(FILTER, 1)) {
|
||||
* case we add it back in the log output. */
|
||||
if (DEBUG_GTE(FILTER, log_level)) {
|
||||
static char *actions[2][2]
|
||||
= { {"show", "hid"}, {"risk", "protect"} };
|
||||
const char *w = who_am_i();
|
||||
@@ -714,7 +998,7 @@ static void report_filter_result(enum logcode code, char const *name,
|
||||
: name_flags & NAME_IS_DIR ? "directory"
|
||||
: "file";
|
||||
rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
|
||||
w, actions[*w!='s'][!(ent->rflags & FILTRULE_INCLUDE)],
|
||||
w, actions[*w=='g'][!(ent->rflags & FILTRULE_INCLUDE)],
|
||||
t, name, ent->pattern,
|
||||
ent->rflags & FILTRULE_DIRECTORY ? "/" : "", type);
|
||||
}
|
||||
@@ -740,6 +1024,15 @@ int name_is_excluded(const char *fname, int name_flags, int filter_level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_server_filter(filter_rule_list *listp, enum logcode code, const char *name, int name_flags)
|
||||
{
|
||||
int ret;
|
||||
cur_elide_value = LOCAL_RULE;
|
||||
ret = check_filter(listp, code, name, name_flags);
|
||||
cur_elide_value = REMOTE_RULE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return -1 if file "name" is defined to be excluded by the specified
|
||||
* exclude list, 1 if it is included, and 0 if it was not matched. */
|
||||
int check_filter(filter_rule_list *listp, enum logcode code,
|
||||
@@ -886,6 +1179,7 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
|
||||
}
|
||||
switch (ch) {
|
||||
case ':':
|
||||
trust_sender_filter = 1;
|
||||
rule->rflags |= FILTRULE_PERDIR_MERGE
|
||||
| FILTRULE_FINISH_SETUP;
|
||||
/* FALL THROUGH */
|
||||
@@ -1294,7 +1588,7 @@ char *get_rule_prefix(filter_rule *rule, const char *pat, int for_xfer,
|
||||
|
||||
static void send_rules(int f_out, filter_rule_list *flp)
|
||||
{
|
||||
filter_rule *ent, *prev = NULL;
|
||||
filter_rule *ent;
|
||||
|
||||
for (ent = flp->head; ent; ent = ent->next) {
|
||||
unsigned int len, plen, dlen;
|
||||
@@ -1309,21 +1603,15 @@ static void send_rules(int f_out, filter_rule_list *flp)
|
||||
* merge files as an optimization (since they can only have
|
||||
* include/exclude rules). */
|
||||
if (ent->rflags & FILTRULE_SENDER_SIDE)
|
||||
elide = am_sender ? 1 : -1;
|
||||
elide = am_sender ? LOCAL_RULE : REMOTE_RULE;
|
||||
if (ent->rflags & FILTRULE_RECEIVER_SIDE)
|
||||
elide = elide ? 0 : am_sender ? -1 : 1;
|
||||
elide = elide ? 0 : am_sender ? REMOTE_RULE : LOCAL_RULE;
|
||||
else if (delete_excluded && !elide
|
||||
&& (!(ent->rflags & FILTRULE_PERDIR_MERGE)
|
||||
|| ent->rflags & FILTRULE_NO_PREFIXES))
|
||||
elide = am_sender ? 1 : -1;
|
||||
if (elide < 0) {
|
||||
if (prev)
|
||||
prev->next = ent->next;
|
||||
else
|
||||
flp->head = ent->next;
|
||||
} else
|
||||
prev = ent;
|
||||
if (elide > 0)
|
||||
elide = am_sender ? LOCAL_RULE : REMOTE_RULE;
|
||||
ent->elide = elide;
|
||||
if (elide == LOCAL_RULE)
|
||||
continue;
|
||||
if (ent->rflags & FILTRULE_CVS_IGNORE
|
||||
&& !(ent->rflags & FILTRULE_MERGE_FILE)) {
|
||||
@@ -1351,7 +1639,6 @@ static void send_rules(int f_out, filter_rule_list *flp)
|
||||
if (dlen)
|
||||
write_byte(f_out, '/');
|
||||
}
|
||||
flp->tail = prev;
|
||||
}
|
||||
|
||||
/* This is only called by the client. */
|
||||
|
||||
46
fileio.c
46
fileio.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2004-2020 Wayne Davison
|
||||
* Copyright (C) 2004-2023 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -40,30 +40,34 @@ OFF_T preallocated_len = 0;
|
||||
static OFF_T sparse_seek = 0;
|
||||
static OFF_T sparse_past_write = 0;
|
||||
|
||||
int sparse_end(int f, OFF_T size)
|
||||
int sparse_end(int f, OFF_T size, int updating_basis_or_equiv)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
sparse_past_write = 0;
|
||||
|
||||
if (!sparse_seek)
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
ret = do_ftruncate(f, size);
|
||||
#else
|
||||
if (do_lseek(f, sparse_seek-1, SEEK_CUR) != size-1)
|
||||
ret = -1;
|
||||
else {
|
||||
do {
|
||||
ret = write(f, "", 1);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
ret = ret <= 0 ? -1 : 0;
|
||||
}
|
||||
if (updating_basis_or_equiv) {
|
||||
if (sparse_seek && do_punch_hole(f, sparse_past_write, sparse_seek) < 0)
|
||||
ret = -1;
|
||||
#ifdef HAVE_FTRUNCATE /* A compilation formality -- in-place requires ftruncate() */
|
||||
else /* Just in case the original file was longer */
|
||||
ret = do_ftruncate(f, size);
|
||||
#endif
|
||||
} else if (sparse_seek) {
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
ret = do_ftruncate(f, size);
|
||||
#else
|
||||
if (do_lseek(f, sparse_seek-1, SEEK_CUR) != size-1)
|
||||
ret = -1;
|
||||
else {
|
||||
do {
|
||||
ret = write(f, "", 1);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
sparse_seek = 0;
|
||||
ret = ret <= 0 ? -1 : 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
sparse_past_write = sparse_seek = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
66
flist.c
66
flist.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2021 Wayne Davison
|
||||
* Copyright (C) 2002-2023 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
|
||||
@@ -33,7 +33,6 @@ extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int inc_recurse;
|
||||
extern int always_checksum;
|
||||
extern int checksum_type;
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
extern int numeric_ids;
|
||||
@@ -43,6 +42,7 @@ extern int use_qsort;
|
||||
extern int xfer_dirs;
|
||||
extern int filesfrom_fd;
|
||||
extern int one_file_system;
|
||||
extern int copy_devices;
|
||||
extern int copy_dirlinks;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
@@ -72,18 +72,20 @@ extern int need_unsorted_flist;
|
||||
extern int sender_symlink_iconv;
|
||||
extern int output_needs_newline;
|
||||
extern int sender_keeps_checksum;
|
||||
extern int trust_sender_filter;
|
||||
extern int unsort_ndx;
|
||||
extern uid_t our_uid;
|
||||
extern struct stats stats;
|
||||
extern char *filesfrom_host;
|
||||
extern char *usermap, *groupmap;
|
||||
|
||||
extern struct name_num_item *file_sum_nni;
|
||||
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
|
||||
extern struct chmod_mode_struct *chmod_modes;
|
||||
|
||||
extern filter_rule_list filter_list;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
extern filter_rule_list filter_list, implied_filter_list, daemon_filter_list;
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
extern int filesfrom_convert;
|
||||
@@ -144,7 +146,8 @@ void init_flist(void)
|
||||
rprintf(FINFO, "FILE_STRUCT_LEN=%d, EXTRA_LEN=%d\n",
|
||||
(int)FILE_STRUCT_LEN, (int)EXTRA_LEN);
|
||||
}
|
||||
flist_csum_len = csum_len_for_type(checksum_type, 1);
|
||||
/* Note that this isn't identical to file_sum_len in the case of CSUM_MD4_ARCHAIC: */
|
||||
flist_csum_len = csum_len_for_type(file_sum_nni->num, 1);
|
||||
|
||||
show_filelist_progress = INFO_GTE(FLIST, 1) && xfer_dirs && !am_server && !inc_recurse;
|
||||
}
|
||||
@@ -700,6 +703,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
int alloc_len, basename_len, linkname_len;
|
||||
int extra_len = file_extra_cnt * EXTRA_LEN;
|
||||
int first_hlink_ndx = -1;
|
||||
char real_ISREG_entry;
|
||||
int64 file_length;
|
||||
#ifdef CAN_SET_NSEC
|
||||
uint32 modtime_nsec;
|
||||
@@ -752,7 +756,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
if (*thisname
|
||||
&& (clean_fname(thisname, CFN_REFUSE_DOT_DOT_DIRS) < 0 || (!relative_paths && *thisname == '/'))) {
|
||||
rprintf(FERROR, "ABORTING due to unsafe pathname from sender: %s\n", thisname);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (sanitize_paths)
|
||||
@@ -814,6 +818,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
linkname_len = strlen(F_SYMLINK(first)) + 1;
|
||||
else
|
||||
linkname_len = 0;
|
||||
real_ISREG_entry = S_ISREG(mode) ? 1 : 0;
|
||||
goto create_object;
|
||||
}
|
||||
}
|
||||
@@ -831,7 +836,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
}
|
||||
#endif
|
||||
} else
|
||||
modtime = read_int(f);
|
||||
modtime = read_uint(f);
|
||||
}
|
||||
if (xflags & XMIT_MOD_NSEC)
|
||||
#ifndef CAN_SET_NSEC
|
||||
@@ -941,10 +946,20 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
#endif
|
||||
linkname_len = 0;
|
||||
|
||||
if (copy_devices && IS_DEVICE(mode)) {
|
||||
/* This is impossible in the official release, but some pre-release patches
|
||||
* didn't convert the device into a file before sending, so we'll do it here
|
||||
* (even though the length is typically 0 and any checksum data is zeros). */
|
||||
mode = S_IFREG | (mode & ACCESSPERMS);
|
||||
modtime = time(NULL); /* The mtime on the device is not up-to-date, so set it to "now". */
|
||||
real_ISREG_entry = 0;
|
||||
} else
|
||||
real_ISREG_entry = S_ISREG(mode) ? 1 : 0;
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
create_object:
|
||||
if (preserve_hard_links) {
|
||||
if (protocol_version < 28 && S_ISREG(mode))
|
||||
if (protocol_version < 28 && real_ISREG_entry)
|
||||
xflags |= XMIT_HLINKED;
|
||||
if (xflags & XMIT_HLINKED)
|
||||
extra_len += (inc_recurse+1) * EXTRA_LEN;
|
||||
@@ -973,6 +988,19 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (*thisname == '/' ? thisname[1] != '.' || thisname[2] != '\0' : *thisname != '.' || thisname[1] != '\0') {
|
||||
int filt_flags = S_ISDIR(mode) ? NAME_IS_DIR : NAME_IS_FILE;
|
||||
if (!trust_sender_filter /* a per-dir filter rule means we must trust the sender's filtering */
|
||||
&& filter_list.head && check_server_filter(&filter_list, FINFO, thisname, filt_flags) < 0) {
|
||||
rprintf(FERROR, "ERROR: rejecting excluded file-list name: %s\n", thisname);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
if (implied_filter_list.head && check_filter(&implied_filter_list, FINFO, thisname, filt_flags) <= 0) {
|
||||
rprintf(FERROR, "ERROR: rejecting unrequested file-list name: %s\n", thisname);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
if (inc_recurse && S_ISDIR(mode)) {
|
||||
if (one_file_system) {
|
||||
/* Room to save the dir's device for -x */
|
||||
@@ -1160,8 +1188,8 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
}
|
||||
#endif
|
||||
|
||||
if (always_checksum && (S_ISREG(mode) || protocol_version < 28)) {
|
||||
if (S_ISREG(mode))
|
||||
if (always_checksum && (real_ISREG_entry || protocol_version < 28)) {
|
||||
if (real_ISREG_entry)
|
||||
bp = F_SUM(file);
|
||||
else {
|
||||
/* Prior to 28, we get a useless set of nulls. */
|
||||
@@ -1360,6 +1388,18 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
linkname_len = 0;
|
||||
#endif
|
||||
|
||||
if (copy_devices && am_sender && IS_DEVICE(st.st_mode)) {
|
||||
if (st.st_size == 0) {
|
||||
int fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd >= 0) {
|
||||
st.st_size = get_device_size(fd, fname);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
st.st_mode = S_IFREG | (st.st_mode & ACCESSPERMS);
|
||||
st.st_mtime = time(NULL); /* The mtime on the device is not up-to-date, so set it to "now". */
|
||||
}
|
||||
|
||||
#ifdef ST_MTIME_NSEC
|
||||
if (st.ST_MTIME_NSEC && protocol_version >= 31)
|
||||
extra_len += EXTRA_LEN;
|
||||
@@ -2327,7 +2367,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
}
|
||||
|
||||
dirlen = dir ? strlen(dir) : 0;
|
||||
if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
|
||||
if (dirlen != lastdir_len || (dirlen && memcmp(lastdir, dir, dirlen) != 0)) {
|
||||
if (!change_pathname(NULL, dir, -dirlen))
|
||||
goto bad_path;
|
||||
lastdir = pathname;
|
||||
@@ -2602,7 +2642,7 @@ struct file_list *recv_file_list(int f, int dir_ndx)
|
||||
rprintf(FERROR,
|
||||
"ABORTING due to invalid path from sender: %s/%s\n",
|
||||
cur_dir, file->basename);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
good_dirname = cur_dir;
|
||||
}
|
||||
@@ -2619,7 +2659,7 @@ struct file_list *recv_file_list(int f, int dir_ndx)
|
||||
} else if (S_ISLNK(file->mode))
|
||||
stats.num_symlinks++;
|
||||
else if (IS_DEVICE(file->mode))
|
||||
stats.num_symlinks++;
|
||||
stats.num_devices++;
|
||||
else
|
||||
stats.num_specials++;
|
||||
|
||||
|
||||
35
generator.c
35
generator.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2023 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -35,11 +35,11 @@ extern int inc_recurse;
|
||||
extern int relative_paths;
|
||||
extern int implied_dirs;
|
||||
extern int keep_dirlinks;
|
||||
extern int write_devices;
|
||||
extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int preserve_links;
|
||||
extern int preserve_devices;
|
||||
extern int write_devices;
|
||||
extern int preserve_specials;
|
||||
extern int preserve_hard_links;
|
||||
extern int preserve_executability;
|
||||
@@ -532,7 +532,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
|
||||
iflags |= ITEM_REPORT_CRTIME;
|
||||
}
|
||||
#endif
|
||||
#if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
|
||||
#ifndef CAN_CHMOD_SYMLINK
|
||||
if (S_ISLNK(file->mode)) {
|
||||
;
|
||||
} else
|
||||
@@ -783,7 +783,7 @@ static int generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
|
||||
for (i = 0; i < sum.count; i++) {
|
||||
int32 n1 = (int32)MIN(len, (OFF_T)sum.blength);
|
||||
char *map = map_ptr(mapbuf, offset, n1);
|
||||
char sum2[SUM_LENGTH];
|
||||
char sum2[MAX_DIGEST_LEN];
|
||||
uint32 sum1;
|
||||
|
||||
len -= n1;
|
||||
@@ -875,9 +875,12 @@ static struct file_struct *find_fuzzy(struct file_struct *file, struct file_list
|
||||
len = strlen(name);
|
||||
suf = find_filename_suffix(name, len, &suf_len);
|
||||
|
||||
dist = fuzzy_distance(name, len, fname, fname_len);
|
||||
/* Add some extra weight to how well the suffixes match. */
|
||||
dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len) * 10;
|
||||
dist = fuzzy_distance(name, len, fname, fname_len, lowest_dist);
|
||||
/* Add some extra weight to how well the suffixes match unless we've already disqualified
|
||||
* this file based on a heuristic. */
|
||||
if (dist < 0xFFFF0000U) {
|
||||
dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len, 0xFFFF0000U) * 10;
|
||||
}
|
||||
if (DEBUG_GTE(FUZZY, 2)) {
|
||||
rprintf(FINFO, "fuzzy distance for %s = %d.%05d\n",
|
||||
f_name(fp, NULL), (int)(dist>>16), (int)(dist&0xFFFF));
|
||||
@@ -1793,6 +1796,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (write_devices && IS_DEVICE(sx.st.st_mode) && sx.st.st_size == 0) {
|
||||
/* This early open into fd skips the regular open below. */
|
||||
if ((fd = do_open(fnamecmp, O_RDONLY, 0)) >= 0)
|
||||
real_sx.st.st_size = sx.st.st_size = get_device_size(fd, fnamecmp);
|
||||
}
|
||||
|
||||
if (fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH)
|
||||
;
|
||||
else if (fnamecmp_type >= FNAMECMP_FUZZY)
|
||||
@@ -1813,7 +1822,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
return_with_success:
|
||||
if (!dry_run)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
send_msg_success(fname, ndx);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -1858,7 +1867,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
if ((fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) {
|
||||
if (fd < 0 && (fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) {
|
||||
rsyserr(FERROR, errno, "failed to open %s, continuing",
|
||||
full_fname(fnamecmp));
|
||||
pretend_missing:
|
||||
@@ -1875,11 +1884,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
|
||||
if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) {
|
||||
if (!(backupptr = get_backup_name(fname))) {
|
||||
close(fd);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) {
|
||||
close(fd);
|
||||
goto pretend_missing;
|
||||
}
|
||||
if (robust_unlink(backupptr) && errno != ENOENT) {
|
||||
@@ -1887,14 +1894,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
full_fname(backupptr));
|
||||
unmake_file(back_file);
|
||||
back_file = NULL;
|
||||
close(fd);
|
||||
goto cleanup;
|
||||
}
|
||||
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
|
||||
rsyserr(FERROR_XFER, errno, "open %s", full_fname(backupptr));
|
||||
unmake_file(back_file);
|
||||
back_file = NULL;
|
||||
close(fd);
|
||||
goto cleanup;
|
||||
}
|
||||
fnamecmp_type = FNAMECMP_BACKUP;
|
||||
@@ -1945,7 +1950,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
write_sum_head(f_out, NULL);
|
||||
else if (sx.st.st_size <= 0) {
|
||||
write_sum_head(f_out, NULL);
|
||||
close(fd);
|
||||
} else {
|
||||
if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) {
|
||||
rprintf(FWARNING,
|
||||
@@ -1953,10 +1957,11 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
fnamecmp);
|
||||
write_sum_head(f_out, NULL);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (back_file) {
|
||||
int save_preserve_xattrs = preserve_xattrs;
|
||||
if (f_copy >= 0)
|
||||
|
||||
174
hashtable.c
174
hashtable.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Routines to provide a memory-efficient hashtable.
|
||||
*
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -350,6 +350,9 @@ void *hashtable_find(struct hashtable *tbl, int64 key, void *data_when_new)
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define NON_ZERO_32(x) ((x) ? (x) : (uint32_t)1)
|
||||
#define NON_ZERO_64(x, y) ((x) || (y) ? (y) | (int64)(x) << 32 | (y) : (int64)1)
|
||||
|
||||
uint32_t hashlittle(const void *key, size_t length)
|
||||
{
|
||||
uint32_t a,b,c; /* internal state */
|
||||
@@ -390,7 +393,7 @@ uint32_t hashlittle(const void *key, size_t length)
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
|
||||
case 1 : a+=k8[0]; break;
|
||||
case 0 : return c;
|
||||
case 0 : return NON_ZERO_32(c);
|
||||
}
|
||||
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
|
||||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
|
||||
@@ -436,7 +439,7 @@ uint32_t hashlittle(const void *key, size_t length)
|
||||
break;
|
||||
case 1 : a+=k8[0];
|
||||
break;
|
||||
case 0 : return c; /* zero length requires no mixing */
|
||||
case 0 : return NON_ZERO_32(c); /* zero length requires no mixing */
|
||||
}
|
||||
|
||||
} else { /* need to read the key one byte at a time */
|
||||
@@ -489,10 +492,171 @@ uint32_t hashlittle(const void *key, size_t length)
|
||||
/* FALLTHROUGH */
|
||||
case 1 : a+=k[0];
|
||||
break;
|
||||
case 0 : return c;
|
||||
case 0 : return NON_ZERO_32(c);
|
||||
}
|
||||
}
|
||||
|
||||
final(a,b,c);
|
||||
return c;
|
||||
return NON_ZERO_32(c);
|
||||
}
|
||||
|
||||
#if SIZEOF_INT64 >= 8
|
||||
/*
|
||||
* hashlittle2: return 2 32-bit hash values joined into an int64.
|
||||
*
|
||||
* This is identical to hashlittle(), except it returns two 32-bit hash
|
||||
* values instead of just one. This is good enough for hash table
|
||||
* lookup with 2^^64 buckets, or if you want a second hash if you're not
|
||||
* happy with the first, or if you want a probably-unique 64-bit ID for
|
||||
* the key. *pc is better mixed than *pb, so use *pc first. If you want
|
||||
* a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
|
||||
*/
|
||||
int64 hashlittle2(const void *key, size_t length)
|
||||
{
|
||||
uint32_t a,b,c; /* internal state */
|
||||
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)length);
|
||||
|
||||
u.ptr = key;
|
||||
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
|
||||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
|
||||
const uint8_t *k8;
|
||||
|
||||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
|
||||
case 1 : a+=k8[0]; break;
|
||||
case 0 : return NON_ZERO_64(b, c);
|
||||
}
|
||||
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
|
||||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
|
||||
const uint8_t *k8;
|
||||
|
||||
/*--------------- all but last block: aligned reads and different mixing */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0] + (((uint32_t)k[1])<<16);
|
||||
b += k[2] + (((uint32_t)k[3])<<16);
|
||||
c += k[4] + (((uint32_t)k[5])<<16);
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 6;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[4]+(((uint32_t)k[5])<<16);
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=k[4];
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=k[2];
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=k[0];
|
||||
break;
|
||||
case 1 : a+=k8[0];
|
||||
break;
|
||||
case 0 : return NON_ZERO_64(b, c); /* zero length strings require no mixing */
|
||||
}
|
||||
|
||||
} else { /* need to read the key one byte at a time */
|
||||
const uint8_t *k = (const uint8_t *)key;
|
||||
|
||||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
a += ((uint32_t)k[1])<<8;
|
||||
a += ((uint32_t)k[2])<<16;
|
||||
a += ((uint32_t)k[3])<<24;
|
||||
b += k[4];
|
||||
b += ((uint32_t)k[5])<<8;
|
||||
b += ((uint32_t)k[6])<<16;
|
||||
b += ((uint32_t)k[7])<<24;
|
||||
c += k[8];
|
||||
c += ((uint32_t)k[9])<<8;
|
||||
c += ((uint32_t)k[10])<<16;
|
||||
c += ((uint32_t)k[11])<<24;
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
|
||||
/*-------------------------------- last block: affect all 32 bits of (c) */
|
||||
switch(length) /* all the case statements fall through */
|
||||
{
|
||||
case 12: c+=((uint32_t)k[11])<<24;
|
||||
/* FALLTHROUGH */
|
||||
case 11: c+=((uint32_t)k[10])<<16;
|
||||
/* FALLTHROUGH */
|
||||
case 10: c+=((uint32_t)k[9])<<8;
|
||||
/* FALLTHROUGH */
|
||||
case 9 : c+=k[8];
|
||||
/* FALLTHROUGH */
|
||||
case 8 : b+=((uint32_t)k[7])<<24;
|
||||
/* FALLTHROUGH */
|
||||
case 7 : b+=((uint32_t)k[6])<<16;
|
||||
/* FALLTHROUGH */
|
||||
case 6 : b+=((uint32_t)k[5])<<8;
|
||||
/* FALLTHROUGH */
|
||||
case 5 : b+=k[4];
|
||||
/* FALLTHROUGH */
|
||||
case 4 : a+=((uint32_t)k[3])<<24;
|
||||
/* FALLTHROUGH */
|
||||
case 3 : a+=((uint32_t)k[2])<<16;
|
||||
/* FALLTHROUGH */
|
||||
case 2 : a+=((uint32_t)k[1])<<8;
|
||||
/* FALLTHROUGH */
|
||||
case 1 : a+=k[0];
|
||||
break;
|
||||
case 0 : return NON_ZERO_64(b, c);
|
||||
}
|
||||
}
|
||||
|
||||
final(a,b,c);
|
||||
return NON_ZERO_64(b, c);
|
||||
}
|
||||
#else
|
||||
#define hashlittle2(key, len) hashlittle(key, len)
|
||||
#endif
|
||||
|
||||
6
hlink.c
6
hlink.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2004-2020 Wayne Davison
|
||||
* Copyright (C) 2004-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -446,7 +446,7 @@ int hard_link_check(struct file_struct *file, int ndx, char *fname,
|
||||
return -1;
|
||||
|
||||
if (remove_source_files == 1 && do_xfers)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
send_msg_success(fname, ndx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -519,7 +519,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
|
||||
if (val < 0)
|
||||
continue;
|
||||
if (remove_source_files == 1 && do_xfers)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
send_msg_success(fname, ndx);
|
||||
}
|
||||
|
||||
if (inc_recurse) {
|
||||
|
||||
2
ifuncs.h
2
ifuncs.h
@@ -1,6 +1,6 @@
|
||||
/* Inline functions for rsync.
|
||||
*
|
||||
* Copyright (C) 2007-2021 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
49
io.c
49
io.c
@@ -41,6 +41,7 @@ extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_receiver;
|
||||
extern int am_generator;
|
||||
extern int local_server;
|
||||
extern int msgs2stderr;
|
||||
extern int inc_recurse;
|
||||
extern int io_error;
|
||||
@@ -84,6 +85,8 @@ int sock_f_out = -1;
|
||||
int64 total_data_read = 0;
|
||||
int64 total_data_written = 0;
|
||||
|
||||
char num_dev_ino_buf[4 + 8 + 8];
|
||||
|
||||
static struct {
|
||||
xbuf in, out, msg;
|
||||
int in_fd;
|
||||
@@ -376,6 +379,7 @@ static void forward_filesfrom_data(void)
|
||||
free_xbuf(&ff_xb);
|
||||
if (ff_reenable_multiplex >= 0)
|
||||
io_start_multiplex_out(ff_reenable_multiplex);
|
||||
free_implied_include_partial_string();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -419,6 +423,7 @@ static void forward_filesfrom_data(void)
|
||||
while (s != eob) {
|
||||
if (*s++ == '\0') {
|
||||
ff_xb.len = s - sob - 1;
|
||||
add_implied_include(sob, 0);
|
||||
if (iconvbufs(ic_send, &ff_xb, &iobuf.out, flags) < 0)
|
||||
exit_cleanup(RERR_PROTOCOL); /* impossible? */
|
||||
write_buf(iobuf.out_fd, s-1, 1); /* Send the '\0'. */
|
||||
@@ -434,6 +439,7 @@ static void forward_filesfrom_data(void)
|
||||
ff_lastchar = '\0';
|
||||
else {
|
||||
/* Handle a partial string specially, saving any incomplete chars. */
|
||||
implied_include_partial_string(sob, s);
|
||||
flags &= ~ICB_INCLUDE_INCOMPLETE;
|
||||
if (iconvbufs(ic_send, &ff_xb, &iobuf.out, flags) < 0) {
|
||||
if (errno == E2BIG)
|
||||
@@ -450,13 +456,17 @@ static void forward_filesfrom_data(void)
|
||||
char *f = ff_xb.buf + ff_xb.pos;
|
||||
char *t = ff_xb.buf;
|
||||
char *eob = f + len;
|
||||
char *cur = t;
|
||||
/* Eliminate any multi-'\0' runs. */
|
||||
while (f != eob) {
|
||||
if (!(*t++ = *f++)) {
|
||||
add_implied_include(cur, 0);
|
||||
cur = t;
|
||||
while (f != eob && *f == '\0')
|
||||
f++;
|
||||
}
|
||||
}
|
||||
implied_include_partial_string(cur, t);
|
||||
ff_lastchar = f[-1];
|
||||
if ((len = t - ff_xb.buf) != 0) {
|
||||
/* This will not circle back to perform_io() because we only get
|
||||
@@ -1057,6 +1067,24 @@ void send_msg_int(enum msgcode code, int num)
|
||||
send_msg(code, numbuf, 4, -1);
|
||||
}
|
||||
|
||||
void send_msg_success(const char *fname, int num)
|
||||
{
|
||||
if (local_server) {
|
||||
STRUCT_STAT st;
|
||||
|
||||
if (DEBUG_GTE(IO, 1))
|
||||
rprintf(FINFO, "[%s] send_msg_success(%d)\n", who_am_i(), num);
|
||||
|
||||
if (stat(fname, &st) < 0)
|
||||
memset(&st, 0, sizeof (STRUCT_STAT));
|
||||
SIVAL(num_dev_ino_buf, 0, num);
|
||||
SIVAL64(num_dev_ino_buf, 4, st.st_dev);
|
||||
SIVAL64(num_dev_ino_buf, 4+8, st.st_ino);
|
||||
send_msg(MSG_SUCCESS, num_dev_ino_buf, sizeof num_dev_ino_buf, -1);
|
||||
} else
|
||||
send_msg_int(MSG_SUCCESS, num);
|
||||
}
|
||||
|
||||
static void got_flist_entry_status(enum festatus status, int ndx)
|
||||
{
|
||||
struct file_list *flist = flist_for_ndx(ndx, "got_flist_entry_status");
|
||||
@@ -1071,8 +1099,12 @@ static void got_flist_entry_status(enum festatus status, int ndx)
|
||||
|
||||
switch (status) {
|
||||
case FES_SUCCESS:
|
||||
if (remove_source_files)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
if (remove_source_files) {
|
||||
if (local_server)
|
||||
send_msg(MSG_SUCCESS, num_dev_ino_buf, sizeof num_dev_ino_buf, -1);
|
||||
else
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case FES_NO_SEND:
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
@@ -1567,14 +1599,15 @@ static void read_a_msg(void)
|
||||
}
|
||||
break;
|
||||
case MSG_SUCCESS:
|
||||
if (msg_bytes != 4) {
|
||||
if (msg_bytes != (local_server ? 4+8+8 : 4)) {
|
||||
invalid_msg:
|
||||
rprintf(FERROR, "invalid multi-message %d:%lu [%s%s]\n",
|
||||
tag, (unsigned long)msg_bytes, who_am_i(),
|
||||
inc_recurse ? "/inc" : "");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
val = raw_read_int();
|
||||
raw_read_buf(num_dev_ino_buf, msg_bytes);
|
||||
val = IVAL(num_dev_ino_buf, 0);
|
||||
iobuf.in_multiplexed = 1;
|
||||
if (am_generator)
|
||||
got_flist_entry_status(FES_SUCCESS, val);
|
||||
@@ -1751,6 +1784,13 @@ int32 read_int(int f)
|
||||
return num;
|
||||
}
|
||||
|
||||
uint32 read_uint(int f)
|
||||
{
|
||||
char b[4];
|
||||
read_buf(f, b, 4);
|
||||
return IVAL(b, 0);
|
||||
}
|
||||
|
||||
int32 read_varint(int f)
|
||||
{
|
||||
union {
|
||||
@@ -1843,6 +1883,7 @@ int64 read_longint(int f)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Debugging note: this will be named read_buf_() when using an external zlib. */
|
||||
void read_buf(int f, char *buf, size_t len)
|
||||
{
|
||||
if (f != iobuf.in_fd) {
|
||||
|
||||
2
itypes.h
2
itypes.h
@@ -1,6 +1,6 @@
|
||||
/* Inline functions for rsync.
|
||||
*
|
||||
* Copyright (C) 2007-2021 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define LATEST_YEAR "2022"
|
||||
#define LATEST_YEAR "2024"
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
/* Keep this simple so both C and ASM can use it */
|
||||
|
||||
/* These allow something like CFLAGS=-DDISABLE_SHA512_DIGEST */
|
||||
#ifdef DISABLE_SHA256_DIGEST
|
||||
#undef SHA256_DIGEST_LENGTH
|
||||
#endif
|
||||
#ifdef DISABLE_SHA512_DIGEST
|
||||
#undef SHA512_DIGEST_LENGTH
|
||||
#endif
|
||||
|
||||
#define MD4_DIGEST_LEN 16
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#if defined SHA512_DIGEST_LENGTH
|
||||
#define MAX_DIGEST_LEN SHA512_DIGEST_LENGTH
|
||||
#elif defined SHA256_DIGEST_LENGTH
|
||||
#define MAX_DIGEST_LEN SHA256_DIGEST_LENGTH
|
||||
#elif defined SHA_DIGEST_LENGTH
|
||||
#define MAX_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||
#else
|
||||
#define MAX_DIGEST_LEN MD5_DIGEST_LEN
|
||||
#endif
|
||||
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
#define CSUM_gone -1
|
||||
#define CSUM_NONE 0
|
||||
#define CSUM_MD4_ARCHAIC 1
|
||||
#define CSUM_MD4_BUSTED 2
|
||||
@@ -15,3 +32,6 @@
|
||||
#define CSUM_XXH64 6
|
||||
#define CSUM_XXH3_64 7
|
||||
#define CSUM_XXH3_128 8
|
||||
#define CSUM_SHA1 9
|
||||
#define CSUM_SHA256 10
|
||||
#define CSUM_SHA512 11
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "config.h"
|
||||
#include "md-defines.h"
|
||||
|
||||
#if !defined USE_OPENSSL && CSUM_CHUNK == 64
|
||||
#ifdef USE_MD5_ASM /* { */
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define md5_process_asm _md5_process_asm
|
||||
@@ -698,4 +698,4 @@ md5_process_asm:
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
#endif /* !USE_OPENSSL ... */
|
||||
#endif /* } USE_MD5_ASM */
|
||||
|
||||
19
lib/md5.c
19
lib/md5.c
@@ -2,7 +2,7 @@
|
||||
* RFC 1321 compliant MD5 implementation
|
||||
*
|
||||
* Copyright (C) 2001-2003 Christophe Devine
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#ifndef USE_OPENSSL
|
||||
void md5_begin(md_context *ctx)
|
||||
{
|
||||
ctx->A = 0x67452301;
|
||||
@@ -148,7 +147,10 @@ static void md5_process(md_context *ctx, const uchar data[CSUM_CHUNK])
|
||||
ctx->D += D;
|
||||
}
|
||||
|
||||
#if defined HAVE_ASM && CSUM_CHUNK == 64
|
||||
#ifdef USE_MD5_ASM
|
||||
#if CSUM_CHUNK != 64
|
||||
#error The MD5 ASM code does not support CSUM_CHUNK != 64
|
||||
#endif
|
||||
extern void md5_process_asm(md_context *ctx, const void *data, size_t num);
|
||||
#endif
|
||||
|
||||
@@ -176,20 +178,20 @@ void md5_update(md_context *ctx, const uchar *input, uint32 length)
|
||||
left = 0;
|
||||
}
|
||||
|
||||
#if defined HAVE_ASM && CSUM_CHUNK == 64
|
||||
#ifdef USE_MD5_ASM /* { */
|
||||
if (length >= CSUM_CHUNK) {
|
||||
uint32 chunks = length / CSUM_CHUNK;
|
||||
md5_process_asm(ctx, input, chunks);
|
||||
length -= chunks * CSUM_CHUNK;
|
||||
input += chunks * CSUM_CHUNK;
|
||||
}
|
||||
#else
|
||||
#else /* } { */
|
||||
while (length >= CSUM_CHUNK) {
|
||||
md5_process(ctx, input);
|
||||
length -= CSUM_CHUNK;
|
||||
input += CSUM_CHUNK;
|
||||
}
|
||||
#endif
|
||||
#endif /* } */
|
||||
|
||||
if (length)
|
||||
memcpy(ctx->buffer + left, input, length);
|
||||
@@ -221,9 +223,8 @@ void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN])
|
||||
SIVALu(digest, 8, ctx->C);
|
||||
SIVALu(digest, 12, ctx->D);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_MD5
|
||||
#ifdef TEST_MD5 /* { */
|
||||
|
||||
void get_md5(uchar *out, const uchar *input, int n)
|
||||
{
|
||||
@@ -317,4 +318,4 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* } */
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* The include file for both the MD4 and MD5 routines. */
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#include "openssl/md4.h"
|
||||
#include "openssl/md5.h"
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
#include "md-defines.h"
|
||||
|
||||
@@ -17,13 +17,6 @@ void mdfour_begin(md_context *md);
|
||||
void mdfour_update(md_context *md, const uchar *in, uint32 length);
|
||||
void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN]);
|
||||
|
||||
#ifndef USE_OPENSSL
|
||||
#define MD5_CTX md_context
|
||||
#define MD5_Init md5_begin
|
||||
#define MD5_Update md5_update
|
||||
#define MD5_Final(digest, cptr) md5_result(cptr, digest)
|
||||
|
||||
void md5_begin(md_context *ctx);
|
||||
void md5_update(md_context *ctx, const uchar *input, uint32 length);
|
||||
void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN]);
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* for string length. This covers a nasty loophole.
|
||||
*
|
||||
* The other functions are there to prevent NULL pointers from
|
||||
* causing nast effects.
|
||||
* causing nasty effects.
|
||||
*
|
||||
* More Recently:
|
||||
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
|
||||
|
||||
178
lib/sysacls.c
178
lib/sysacls.c
@@ -2,7 +2,7 @@
|
||||
* Unix SMB/CIFS implementation.
|
||||
* Based on the Samba ACL support code.
|
||||
* Copyright (C) Jeremy Allison 2000.
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* The permission functions have been changed to get/set all bits via
|
||||
* one call. Some functions that rsync doesn't need were also removed.
|
||||
@@ -175,7 +175,7 @@ int sys_acl_delete_def_file(const char *name)
|
||||
return acl_delete_def_file(name);
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
{
|
||||
return acl_free(the_acl);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
* The interface to DEC/Compaq Tru64 UNIX ACLs
|
||||
* is based on Draft 13 of the POSIX spec which is
|
||||
* slightly different from the Draft 16 interface.
|
||||
*
|
||||
*
|
||||
* Also, some of the permset manipulation functions
|
||||
* such as acl_clear_perm() and acl_add_perm() appear
|
||||
* to be broken on Tru64 so we have to manipulate
|
||||
@@ -310,7 +310,7 @@ int sys_acl_delete_def_file(const char *name)
|
||||
return acl_delete_def_file((char *)name);
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
{
|
||||
return acl_free(the_acl);
|
||||
}
|
||||
@@ -457,7 +457,7 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
break;
|
||||
}
|
||||
ndefault = count - naccess;
|
||||
|
||||
|
||||
/*
|
||||
* if the caller wants the default ACL we have to copy
|
||||
* the entries down to the start of the acl[] buffer
|
||||
@@ -517,7 +517,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
acl_d->count = naccess;
|
||||
|
||||
return acl_d;
|
||||
@@ -532,7 +532,7 @@ int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *b
|
||||
|
||||
if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
|
||||
*u_g_id_p = entry->a_id;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -633,7 +633,7 @@ static int acl_sort(SMB_ACL_T acl_d)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sys_acl_valid(SMB_ACL_T acl_d)
|
||||
{
|
||||
return acl_sort(acl_d);
|
||||
@@ -755,11 +755,11 @@ int sys_acl_delete_def_file(const char *path)
|
||||
ret = acl(path, SETACL, acl_d->count, acl_d->acl);
|
||||
|
||||
sys_acl_free_acl(acl_d);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
{
|
||||
SAFE_FREE(acl_d);
|
||||
return 0;
|
||||
@@ -895,10 +895,10 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
int ndefault; /* # of default ACL entries */
|
||||
|
||||
if (hpux_acl_call_presence() == False) {
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
* May be the system doesn't have the latest version of JFS.
|
||||
*/
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
|
||||
@@ -949,7 +949,7 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
break;
|
||||
}
|
||||
ndefault = count - naccess;
|
||||
|
||||
|
||||
/*
|
||||
* if the caller wants the default ACL we have to copy
|
||||
* the entries down to the start of the acl[] buffer
|
||||
@@ -1109,9 +1109,9 @@ struct hpux_acl_types {
|
||||
* aclp - Array of ACL structures.
|
||||
* acl_type_count - Pointer to acl_types structure. Should already be
|
||||
* allocated.
|
||||
* Output:
|
||||
* Output:
|
||||
*
|
||||
* acl_type_count - This structure is filled up with counts of various
|
||||
* acl_type_count - This structure is filled up with counts of various
|
||||
* acl types.
|
||||
*/
|
||||
|
||||
@@ -1123,28 +1123,28 @@ static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_type
|
||||
|
||||
for (i = 0; i < acl_count; i++) {
|
||||
switch (aclp[i].a_type) {
|
||||
case USER:
|
||||
case USER:
|
||||
acl_type_count->n_user++;
|
||||
break;
|
||||
case USER_OBJ:
|
||||
case USER_OBJ:
|
||||
acl_type_count->n_user_obj++;
|
||||
break;
|
||||
case DEF_USER_OBJ:
|
||||
case DEF_USER_OBJ:
|
||||
acl_type_count->n_def_user_obj++;
|
||||
break;
|
||||
case GROUP:
|
||||
case GROUP:
|
||||
acl_type_count->n_group++;
|
||||
break;
|
||||
case GROUP_OBJ:
|
||||
case GROUP_OBJ:
|
||||
acl_type_count->n_group_obj++;
|
||||
break;
|
||||
case DEF_GROUP_OBJ:
|
||||
case DEF_GROUP_OBJ:
|
||||
acl_type_count->n_def_group_obj++;
|
||||
break;
|
||||
case OTHER_OBJ:
|
||||
case OTHER_OBJ:
|
||||
acl_type_count->n_other_obj++;
|
||||
break;
|
||||
case DEF_OTHER_OBJ:
|
||||
case DEF_OTHER_OBJ:
|
||||
acl_type_count->n_def_other_obj++;
|
||||
break;
|
||||
case CLASS_OBJ:
|
||||
@@ -1159,14 +1159,14 @@ static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_type
|
||||
case DEF_GROUP:
|
||||
acl_type_count->n_def_group++;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
acl_type_count->n_illegal_obj++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* swap_acl_entries: Swaps two ACL entries.
|
||||
/* swap_acl_entries: Swaps two ACL entries.
|
||||
*
|
||||
* Inputs: aclp0, aclp1 - ACL entries to be swapped.
|
||||
*/
|
||||
@@ -1189,25 +1189,25 @@ static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
|
||||
}
|
||||
|
||||
/* prohibited_duplicate_type
|
||||
* Identifies if given ACL type can have duplicate entries or
|
||||
* Identifies if given ACL type can have duplicate entries or
|
||||
* not.
|
||||
*
|
||||
* Inputs: acl_type - ACL Type.
|
||||
*
|
||||
* Outputs:
|
||||
* Outputs:
|
||||
*
|
||||
* Return..
|
||||
* Return..
|
||||
*
|
||||
* True - If the ACL type matches any of the prohibited types.
|
||||
* False - If the ACL type doesn't match any of the prohibited types.
|
||||
*/
|
||||
*/
|
||||
|
||||
static BOOL hpux_prohibited_duplicate_type(int acl_type)
|
||||
{
|
||||
switch (acl_type) {
|
||||
case USER:
|
||||
case GROUP:
|
||||
case DEF_USER:
|
||||
case DEF_USER:
|
||||
case DEF_GROUP:
|
||||
return True;
|
||||
default:
|
||||
@@ -1217,7 +1217,7 @@ static BOOL hpux_prohibited_duplicate_type(int acl_type)
|
||||
|
||||
/* get_needed_class_perm
|
||||
* Returns the permissions of a ACL structure only if the ACL
|
||||
* type matches one of the pre-determined types for computing
|
||||
* type matches one of the pre-determined types for computing
|
||||
* CLASS_OBJ permissions.
|
||||
*
|
||||
* Inputs: aclp - Pointer to ACL structure.
|
||||
@@ -1226,17 +1226,17 @@ static BOOL hpux_prohibited_duplicate_type(int acl_type)
|
||||
static int hpux_get_needed_class_perm(struct acl *aclp)
|
||||
{
|
||||
switch (aclp->a_type) {
|
||||
case USER:
|
||||
case GROUP_OBJ:
|
||||
case GROUP:
|
||||
case DEF_USER_OBJ:
|
||||
case USER:
|
||||
case GROUP_OBJ:
|
||||
case GROUP:
|
||||
case DEF_USER_OBJ:
|
||||
case DEF_USER:
|
||||
case DEF_GROUP_OBJ:
|
||||
case DEF_GROUP_OBJ:
|
||||
case DEF_GROUP:
|
||||
case DEF_CLASS_OBJ:
|
||||
case DEF_OTHER_OBJ:
|
||||
case DEF_OTHER_OBJ:
|
||||
return aclp->a_perm;
|
||||
default:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1267,15 +1267,15 @@ static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
|
||||
#if !defined(HAVE_HPUX_ACLSORT)
|
||||
/*
|
||||
* The aclsort() system call is available on the latest HPUX General
|
||||
* Patch Bundles. So for HPUX, we developed our version of acl_sort
|
||||
* function. Because, we don't want to update to a new
|
||||
* Patch Bundles. So for HPUX, we developed our version of acl_sort
|
||||
* function. Because, we don't want to update to a new
|
||||
* HPUX GR bundle just for aclsort() call.
|
||||
*/
|
||||
|
||||
struct hpux_acl_types acl_obj_count;
|
||||
int n_class_obj_perm = 0;
|
||||
int i, j;
|
||||
|
||||
|
||||
if (!acl_count) {
|
||||
DEBUG(10, ("Zero acl count passed. Returning Success\n"));
|
||||
return 0;
|
||||
@@ -1290,8 +1290,8 @@ static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
|
||||
|
||||
hpux_count_obj(acl_count, aclp, &acl_obj_count);
|
||||
|
||||
/* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
|
||||
* CLASS_OBJ and OTHER_OBJ
|
||||
/* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
|
||||
* CLASS_OBJ and OTHER_OBJ
|
||||
*/
|
||||
|
||||
if (acl_obj_count.n_user_obj != 1
|
||||
@@ -1313,15 +1313,15 @@ or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
|
||||
* structures.
|
||||
/* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
|
||||
* structures.
|
||||
*
|
||||
* Sorting crieteria - First sort by ACL type. If there are multiple entries of
|
||||
* same ACL type, sort by ACL id.
|
||||
*
|
||||
* I am using the trivial kind of sorting method here because, performance isn't
|
||||
* I am using the trivial kind of sorting method here because, performance isn't
|
||||
* really effected by the ACLs feature. More over there aren't going to be more
|
||||
* than 17 entries on HPUX.
|
||||
* than 17 entries on HPUX.
|
||||
*/
|
||||
|
||||
for (i = 0; i < acl_count; i++) {
|
||||
@@ -1390,7 +1390,7 @@ static int acl_sort(SMB_ACL_T acl_d)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sys_acl_valid(SMB_ACL_T acl_d)
|
||||
{
|
||||
return acl_sort(acl_d);
|
||||
@@ -1405,11 +1405,11 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
|
||||
int ret;
|
||||
|
||||
if (hpux_acl_call_presence() == False) {
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
* May be the system doesn't have the latest version of JFS.
|
||||
*/
|
||||
errno=ENOSYS;
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
|
||||
@@ -1538,11 +1538,11 @@ int sys_acl_delete_def_file(const char *path)
|
||||
ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
|
||||
|
||||
sys_acl_free_acl(acl_d);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
{
|
||||
free(acl_d);
|
||||
return 0;
|
||||
@@ -1723,7 +1723,7 @@ int sys_acl_delete_def_file(const char *name)
|
||||
return acl_delete_def_file(name);
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
{
|
||||
if (acl_d->freeaclp) {
|
||||
acl_free(acl_d->aclp);
|
||||
@@ -1834,12 +1834,12 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
}
|
||||
|
||||
/* Get the acl using statacl */
|
||||
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_get_file\n"));
|
||||
DEBUG(10, ("path_p is %s\n", path_p));
|
||||
|
||||
file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
|
||||
|
||||
|
||||
if (file_acl == NULL) {
|
||||
errno=ENOMEM;
|
||||
DEBUG(0, ("Error in AIX sys_acl_get_file: %d\n", errno));
|
||||
@@ -1931,9 +1931,9 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
* to be specified but, it's better than leaving it 0 */
|
||||
|
||||
acl_entry_link->entryp->ace_type = acl_entry->ace_type;
|
||||
|
||||
|
||||
acl_entry_link->entryp->ace_access = acl_entry->ace_access;
|
||||
|
||||
|
||||
memcpy(acl_entry_link->entryp->ace_id, idp, sizeof (struct ace_id));
|
||||
|
||||
/* The access in the acl entries must be left shifted by *
|
||||
@@ -1962,7 +1962,7 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
|
||||
DEBUG(10, ("acl_entry = %d\n", acl_entry));
|
||||
DEBUG(10, ("The ace_type is %d\n", acl_entry->ace_type));
|
||||
|
||||
|
||||
acl_entry = acl_nxt(acl_entry);
|
||||
}
|
||||
} /* end of if enabled */
|
||||
@@ -2014,12 +2014,12 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
new_acl_entry->ace_access = file_acl->o_access << 6;
|
||||
idp->id_type = SMB_ACL_OTHER;
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
new_acl_entry->ace_access = file_acl->u_access << 6;
|
||||
idp->id_type = SMB_ACL_USER_OBJ;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
@@ -2048,7 +2048,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
int rc = 0;
|
||||
|
||||
/* Get the acl using fstatacl */
|
||||
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_get_fd\n"));
|
||||
DEBUG(10, ("fd is %d\n", fd));
|
||||
file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
|
||||
@@ -2095,12 +2095,12 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
|
||||
DEBUG(10, ("acl_entry is %d\n", acl_entry));
|
||||
DEBUG(10, ("acl_last(file_acl) id %d\n", acl_last(file_acl)));
|
||||
|
||||
|
||||
/* Check if the extended acl bit is on. *
|
||||
* If it isn't, do not show the *
|
||||
* contents of the acl since AIX intends *
|
||||
* the extended info to remain unused */
|
||||
|
||||
|
||||
if (file_acl->acl_mode & S_IXACL){
|
||||
/* while we are not pointing to the very end */
|
||||
while (acl_entry < acl_last(file_acl)) {
|
||||
@@ -2115,7 +2115,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
}
|
||||
|
||||
idp = acl_entry->ace_id;
|
||||
|
||||
|
||||
/* Check if this is the first entry in the linked list. *
|
||||
* The first entry needs to keep prevp pointing to NULL *
|
||||
* and already has entryp allocated. */
|
||||
@@ -2177,7 +2177,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
|
||||
DEBUG(10, ("acl_entry = %d\n", acl_entry));
|
||||
DEBUG(10, ("The ace_type is %d\n", acl_entry->ace_type));
|
||||
|
||||
|
||||
acl_entry = acl_nxt(acl_entry);
|
||||
}
|
||||
} /* end of if enabled */
|
||||
@@ -2210,43 +2210,43 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
}
|
||||
|
||||
acl_entry_link->nextp = NULL;
|
||||
|
||||
|
||||
new_acl_entry = acl_entry_link->entryp;
|
||||
idp = new_acl_entry->ace_id;
|
||||
|
||||
|
||||
new_acl_entry->ace_len = sizeof (struct acl_entry);
|
||||
new_acl_entry->ace_type = ACC_PERMIT;
|
||||
idp->id_len = sizeof (struct ace_id);
|
||||
DEBUG(10, ("idp->id_len = %d\n", idp->id_len));
|
||||
memset(idp->id_data, 0, sizeof (uid_t));
|
||||
|
||||
|
||||
switch (i) {
|
||||
case 2:
|
||||
new_acl_entry->ace_access = file_acl->g_access << 6;
|
||||
idp->id_type = SMB_ACL_GROUP_OBJ;
|
||||
break;
|
||||
|
||||
|
||||
case 3:
|
||||
new_acl_entry->ace_access = file_acl->o_access << 6;
|
||||
idp->id_type = SMB_ACL_OTHER;
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
new_acl_entry->ace_access = file_acl->u_access << 6;
|
||||
idp->id_type = SMB_ACL_USER_OBJ;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
acl_entry_link_head->count++;
|
||||
DEBUG(10, ("new_acl_entry->ace_access = %d\n", new_acl_entry->ace_access));
|
||||
}
|
||||
|
||||
acl_entry_link_head->count = 0;
|
||||
SAFE_FREE(file_acl);
|
||||
|
||||
|
||||
return acl_entry_link_head;
|
||||
}
|
||||
#endif
|
||||
@@ -2274,7 +2274,7 @@ int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *b
|
||||
SMB_ACL_T sys_acl_init(int count)
|
||||
{
|
||||
struct acl_entry_link *theacl = NULL;
|
||||
|
||||
|
||||
if (count < 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
@@ -2383,9 +2383,9 @@ int sys_acl_valid(SMB_ACL_T theacl)
|
||||
}
|
||||
|
||||
DEBUG(10, ("user_obj=%d, group_obj=%d, other_obj=%d\n", user_obj, group_obj, other_obj));
|
||||
|
||||
|
||||
if (user_obj != 1 || group_obj != 1 || other_obj != 1)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2404,7 +2404,7 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_set_file\n"));
|
||||
DEBUG(10, ("File name is %s\n", name));
|
||||
|
||||
|
||||
/* AIX has no default ACL */
|
||||
if (acltype == SMB_ACL_TYPE_DEFAULT)
|
||||
return 0;
|
||||
@@ -2449,7 +2449,7 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
|
||||
errno = ENOMEM;
|
||||
DEBUG(0, ("Error in sys_acl_set_file is %d\n", errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(file_acl_temp, file_acl, file_acl->acl_len);
|
||||
SAFE_FREE(file_acl);
|
||||
@@ -2460,15 +2460,15 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
|
||||
file_acl->acl_len += sizeof (struct acl_entry);
|
||||
acl_entry->ace_len = acl_entry_link->entryp->ace_len;
|
||||
acl_entry->ace_access = acl_entry_link->entryp->ace_access;
|
||||
|
||||
|
||||
/* In order to use this, we'll need to wait until we can get denies */
|
||||
/* if (!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
|
||||
acl_entry->ace_type = ACC_SPECIFY; */
|
||||
|
||||
acl_entry->ace_type = ACC_SPECIFY;
|
||||
|
||||
|
||||
ace_id = acl_entry->ace_id;
|
||||
|
||||
|
||||
ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
|
||||
DEBUG(10, ("The id type is %d\n", ace_id->id_type));
|
||||
ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
|
||||
@@ -2496,7 +2496,7 @@ int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
|
||||
uint user_id;
|
||||
uint acl_length;
|
||||
uint rc;
|
||||
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_set_fd\n"));
|
||||
acl_length = BUFSIZ;
|
||||
file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
|
||||
@@ -2508,7 +2508,7 @@ int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
|
||||
}
|
||||
|
||||
memset(file_acl, 0, BUFSIZ);
|
||||
|
||||
|
||||
file_acl->acl_len = ACL_SIZ;
|
||||
file_acl->acl_mode = S_IXACL;
|
||||
|
||||
@@ -2550,22 +2550,22 @@ int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
|
||||
file_acl->acl_len += sizeof (struct acl_entry);
|
||||
acl_entry->ace_len = acl_entry_link->entryp->ace_len;
|
||||
acl_entry->ace_access = acl_entry_link->entryp->ace_access;
|
||||
|
||||
|
||||
/* In order to use this, we'll need to wait until we can get denies */
|
||||
/* if (!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
|
||||
acl_entry->ace_type = ACC_SPECIFY; */
|
||||
|
||||
|
||||
acl_entry->ace_type = ACC_SPECIFY;
|
||||
|
||||
|
||||
ace_id = acl_entry->ace_id;
|
||||
|
||||
|
||||
ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
|
||||
DEBUG(10, ("The id type is %d\n", ace_id->id_type));
|
||||
ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
|
||||
memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof (uid_t));
|
||||
memcpy(ace_id->id_data, &user_id, sizeof (uid_t));
|
||||
}
|
||||
|
||||
|
||||
rc = fchacl(fd, file_acl, file_acl->acl_len);
|
||||
DEBUG(10, ("errno is %d\n", errno));
|
||||
DEBUG(10, ("return code is %d\n", rc));
|
||||
@@ -2594,7 +2594,7 @@ int sys_acl_free_acl(SMB_ACL_T posix_acl)
|
||||
SAFE_FREE(acl_entry_link->prevp);
|
||||
SAFE_FREE(acl_entry_link->entryp);
|
||||
SAFE_FREE(acl_entry_link);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Version 2.2.x
|
||||
* Portable SMB ACL interface
|
||||
* Copyright (C) Jeremy Allison 2000
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -232,7 +232,7 @@ struct new_acl_entry{
|
||||
|
||||
#define SMB_ACL_ENTRY_T struct new_acl_entry*
|
||||
#define SMB_ACL_T struct acl_entry_link*
|
||||
|
||||
|
||||
#define SMB_ACL_TAG_T unsigned short
|
||||
#define SMB_ACL_TYPE_T int
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Extended attribute support for rsync.
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc.
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
* Written by Jay Fenlason.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
12
log.c
12
log.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -36,8 +36,6 @@ extern int protocol_version;
|
||||
extern int always_checksum;
|
||||
extern int preserve_mtimes;
|
||||
extern int msgs2stderr;
|
||||
extern int xfersum_type;
|
||||
extern int checksum_type;
|
||||
extern int stdout_format_has_i;
|
||||
extern int stdout_format_has_o_or_i;
|
||||
extern int logfile_format_has_i;
|
||||
@@ -62,6 +60,8 @@ extern unsigned int module_dirlen;
|
||||
extern char sender_file_sum[MAX_DIGEST_LEN];
|
||||
extern const char undetermined_hostname[];
|
||||
|
||||
extern struct name_num_item *xfer_sum_nni, *file_sum_nni;
|
||||
|
||||
static int log_initialised;
|
||||
static int logfile_was_closed;
|
||||
static FILE *logfile_fp;
|
||||
@@ -680,12 +680,12 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
|
||||
n = NULL;
|
||||
if (S_ISREG(file->mode)) {
|
||||
if (always_checksum)
|
||||
n = sum_as_hex(checksum_type, F_SUM(file), 1);
|
||||
n = sum_as_hex(file_sum_nni->num, F_SUM(file), 1);
|
||||
else if (iflags & ITEM_TRANSFER)
|
||||
n = sum_as_hex(xfersum_type, sender_file_sum, 0);
|
||||
n = sum_as_hex(xfer_sum_nni->num, sender_file_sum, 0);
|
||||
}
|
||||
if (!n) {
|
||||
int sum_len = csum_len_for_type(always_checksum ? checksum_type : xfersum_type,
|
||||
int sum_len = csum_len_for_type(always_checksum ? file_sum_nni->num : xfer_sum_nni->num,
|
||||
always_checksum);
|
||||
memset(buf2, ' ', sum_len*2);
|
||||
buf2[sum_len*2] = '\0';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
dnl AC_HAVE_TYPE(TYPE,INCLUDES)
|
||||
AC_DEFUN([AC_HAVE_TYPE], [
|
||||
AC_REQUIRE([AC_HEADER_STDC])
|
||||
cv=`echo "$1" | sed 'y%./+- %__p__%'`
|
||||
AC_MSG_CHECKING(for $1)
|
||||
AC_CACHE_VAL([ac_cv_type_$cv],
|
||||
|
||||
64
main.c
64
main.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -48,6 +48,7 @@ extern int called_from_signal_handler;
|
||||
extern int need_messages_from_generator;
|
||||
extern int kluge_around_eof;
|
||||
extern int got_xfer_error;
|
||||
extern int old_style_args;
|
||||
extern int msgs2stderr;
|
||||
extern int module_id;
|
||||
extern int read_only;
|
||||
@@ -88,6 +89,8 @@ extern int backup_dir_len;
|
||||
extern int basis_dir_cnt;
|
||||
extern int default_af_hint;
|
||||
extern int stdout_format_has_i;
|
||||
extern int trust_sender_filter;
|
||||
extern int trust_sender_args;
|
||||
extern struct stats stats;
|
||||
extern char *stdout_format;
|
||||
extern char *logfile_format;
|
||||
@@ -103,7 +106,7 @@ extern char curr_dir[MAXPATHLEN];
|
||||
extern char backup_dir_buf[MAXPATHLEN];
|
||||
extern char *basis_dir[MAX_BASIS_DIRS+1];
|
||||
extern struct file_list *first_flist;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
extern filter_rule_list daemon_filter_list, implied_filter_list;
|
||||
|
||||
uid_t our_uid;
|
||||
gid_t our_gid;
|
||||
@@ -477,7 +480,7 @@ static void show_malloc_stats(void)
|
||||
|
||||
#define PRINT_ALLOC_NUM(title, descr, num) \
|
||||
rprintf(FINFO, " %-11s%10" SIZE_T_FMT_MOD "d (" descr ")\n", \
|
||||
title ":", (SIZE_T_FMT_CAST)(num));
|
||||
title ":", (SIZE_T_FMT_CAST)(num));
|
||||
|
||||
PRINT_ALLOC_NUM("arena", "bytes from sbrk", mi.arena);
|
||||
PRINT_ALLOC_NUM("ordblks", "chunks not in use", mi.ordblks);
|
||||
@@ -607,11 +610,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (**remote_argv == '-') {
|
||||
if (asprintf(args + argc++, "./%s", *remote_argv++) < 0)
|
||||
out_of_memory("do_cmd");
|
||||
} else
|
||||
args[argc++] = *remote_argv++;
|
||||
args[argc++] = safe_arg(NULL, *remote_argv++);
|
||||
remote_argc--;
|
||||
}
|
||||
}
|
||||
@@ -663,6 +662,16 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* Older versions turn an empty string as a reference to the current directory.
|
||||
* We now treat this as an error unless --old-args was used. */
|
||||
static char *dot_dir_or_error()
|
||||
{
|
||||
if (old_style_args || am_server)
|
||||
return ".";
|
||||
rprintf(FERROR, "Empty destination arg specified (use \".\" or see --old-args).\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
/* The receiving side operates in one of two modes:
|
||||
*
|
||||
* 1. it receives any number of files into a destination directory,
|
||||
@@ -690,9 +699,8 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
if (!dest_path || list_only)
|
||||
return NULL;
|
||||
|
||||
/* Treat an empty string as a copy into the current directory. */
|
||||
if (!*dest_path)
|
||||
dest_path = ".";
|
||||
dest_path = dot_dir_or_error();
|
||||
|
||||
if (daemon_filter_list.head) {
|
||||
char *slash = strrchr(dest_path, '/');
|
||||
@@ -1079,6 +1087,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
|
||||
}
|
||||
|
||||
am_generator = 1;
|
||||
implied_filter_list.head = implied_filter_list.tail = NULL;
|
||||
flist_receiving_enabled = True;
|
||||
|
||||
io_end_multiplex_in(MPLX_SWITCHING);
|
||||
@@ -1374,15 +1383,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
return MAX(exit_code, exit_code2);
|
||||
}
|
||||
|
||||
static void dup_argv(char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; argv[i]; i++)
|
||||
argv[i] = strdup(argv[i]);
|
||||
}
|
||||
|
||||
|
||||
/* Start a client for either type of remote connection. Work out
|
||||
* whether the arguments request a remote shell or rsyncd connection,
|
||||
* and call the appropriate connection function, then run_client.
|
||||
@@ -1398,10 +1398,6 @@ static int start_client(int argc, char *argv[])
|
||||
int ret;
|
||||
pid_t pid;
|
||||
|
||||
/* Don't clobber argv[] so that ps(1) can still show the right
|
||||
* command line. */
|
||||
dup_argv(argv);
|
||||
|
||||
if (!read_batch) { /* for read_batch, NO source is specified */
|
||||
char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
|
||||
if (path) { /* source is remote */
|
||||
@@ -1434,6 +1430,8 @@ static int start_client(int argc, char *argv[])
|
||||
|
||||
if (argc > 1) {
|
||||
p = argv[--argc];
|
||||
if (!*p)
|
||||
p = dot_dir_or_error();
|
||||
remote_argv = argv + argc;
|
||||
} else {
|
||||
static char *dotarg[1] = { "." };
|
||||
@@ -1474,6 +1472,12 @@ static int start_client(int argc, char *argv[])
|
||||
rsync_port = 0;
|
||||
}
|
||||
|
||||
/* A local transfer doesn't unbackslash anything, so leave the args alone. */
|
||||
if (local_server) {
|
||||
old_style_args = 2;
|
||||
trust_sender_args = trust_sender_filter = 1;
|
||||
}
|
||||
|
||||
if (!rsync_port && remote_argc && !**remote_argv) /* Turn an empty arg into a dot dir. */
|
||||
*remote_argv = ".";
|
||||
|
||||
@@ -1499,6 +1503,8 @@ static int start_client(int argc, char *argv[])
|
||||
char *dummy_host;
|
||||
int dummy_port = rsync_port;
|
||||
int i;
|
||||
if (filesfrom_fd < 0)
|
||||
add_implied_include(remote_argv[0], daemon_connection);
|
||||
/* For remote source, any extra source args must have either
|
||||
* the same hostname or an empty hostname. */
|
||||
for (i = 1; i < remote_argc; i++) {
|
||||
@@ -1522,6 +1528,7 @@ static int start_client(int argc, char *argv[])
|
||||
if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */
|
||||
arg = ".";
|
||||
remote_argv[i] = arg;
|
||||
add_implied_include(arg, daemon_connection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1738,6 +1745,17 @@ int main(int argc,char *argv[])
|
||||
|
||||
unset_env_var("DISPLAY");
|
||||
|
||||
#if defined USE_OPENSSL && defined SET_OPENSSL_CONF
|
||||
#define TO_STR2(x) #x
|
||||
#define TO_STR(x) TO_STR2(x)
|
||||
/* ./configure --with-openssl-conf=/etc/ssl/openssl-rsync.cnf
|
||||
* defines SET_OPENSSL_CONF as that unquoted pathname. */
|
||||
if (!getenv("OPENSSL_CONF")) /* Don't override it if it's already set. */
|
||||
set_env_str("OPENSSL_CONF", TO_STR(SET_OPENSSL_CONF));
|
||||
#undef TO_STR
|
||||
#undef TO_STR2
|
||||
#endif
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
/* Even a non-daemon runs needs the default config values to be set, e.g.
|
||||
|
||||
22
match.c
22
match.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2023 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
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
extern int checksum_seed;
|
||||
extern int append_mode;
|
||||
extern int xfersum_type;
|
||||
|
||||
extern struct name_num_item *xfer_sum_nni;
|
||||
extern int xfer_sum_len;
|
||||
|
||||
int updating_basis_file;
|
||||
char sender_file_sum[MAX_DIGEST_LEN];
|
||||
@@ -140,7 +142,7 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
{
|
||||
OFF_T offset, aligned_offset, end;
|
||||
int32 k, want_i, aligned_i, backup;
|
||||
char sum2[SUM_LENGTH];
|
||||
char sum2[MAX_DIGEST_LEN];
|
||||
uint32 s1, s2, sum;
|
||||
int more;
|
||||
schar *map;
|
||||
@@ -356,15 +358,13 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
**/
|
||||
void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
int sum_len;
|
||||
|
||||
last_match = 0;
|
||||
false_alarms = 0;
|
||||
hash_hits = 0;
|
||||
matches = 0;
|
||||
data_transfer = 0;
|
||||
|
||||
sum_init(xfersum_type, checksum_seed);
|
||||
sum_init(xfer_sum_nni, checksum_seed);
|
||||
|
||||
if (append_mode > 0) {
|
||||
if (append_mode == 2) {
|
||||
@@ -405,22 +405,22 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
matched(f, s, buf, len, -1);
|
||||
}
|
||||
|
||||
sum_len = sum_end(sender_file_sum);
|
||||
sum_end(sender_file_sum);
|
||||
|
||||
/* If we had a read error, send a bad checksum. We use all bits
|
||||
* off as long as the checksum doesn't happen to be that, in
|
||||
* which case we turn the last 0 bit into a 1. */
|
||||
if (buf && buf->status != 0) {
|
||||
int i;
|
||||
for (i = 0; i < sum_len && sender_file_sum[i] == 0; i++) {}
|
||||
memset(sender_file_sum, 0, sum_len);
|
||||
if (i == sum_len)
|
||||
for (i = 0; i < xfer_sum_len && sender_file_sum[i] == 0; i++) {}
|
||||
memset(sender_file_sum, 0, xfer_sum_len);
|
||||
if (i == xfer_sum_len)
|
||||
sender_file_sum[i-1]++;
|
||||
}
|
||||
|
||||
if (DEBUG_GTE(DELTASUM, 2))
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f, sender_file_sum, sum_len);
|
||||
write_buf(f, sender_file_sum, xfer_sum_len);
|
||||
|
||||
if (DEBUG_GTE(DELTASUM, 2)) {
|
||||
rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
|
||||
|
||||
@@ -8,6 +8,7 @@ fi
|
||||
inname="$1"
|
||||
srcdir=`dirname "$0"`
|
||||
flagfile="$srcdir/.md2man-works"
|
||||
force_flagfile="$srcdir/.md2man-force"
|
||||
|
||||
if [ ! -f "$flagfile" ]; then
|
||||
# We test our smallest manpage just to see if the python setup works.
|
||||
@@ -32,4 +33,10 @@ if [ ! -f "$flagfile" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
"$srcdir/md-convert" "$srcdir/$inname"
|
||||
if [ -f "$force_flagfile" ]; then
|
||||
opt='--force-link-text'
|
||||
else
|
||||
opt=''
|
||||
fi
|
||||
|
||||
"$srcdir/md-convert" $opt "$srcdir/$inname"
|
||||
|
||||
228
md-convert
228
md-convert
@@ -32,11 +32,14 @@
|
||||
import os, sys, re, argparse, subprocess, time
|
||||
from html.parser import HTMLParser
|
||||
|
||||
CONSUMES_TXT = set('h1 h2 p li pre'.split())
|
||||
VALID_PAGES = 'README INSTALL COPYING rsync.1 rrsync.1 rsync-ssl.1 rsyncd.conf.5'.split()
|
||||
|
||||
CONSUMES_TXT = set('h1 h2 h3 p li pre'.split())
|
||||
|
||||
HTML_START = """\
|
||||
<html><head>
|
||||
<title>%s</title>
|
||||
<title>%TITLE%</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto&family=Roboto+Mono&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
@@ -46,6 +49,10 @@ body {
|
||||
body, b, strong, u {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
a.tgt { font-face: symbol; font-weight: 400; font-size: 70%; visibility: hidden; text-decoration: none; color: #ddd; padding: 0 4px; border: 0; }
|
||||
a.tgt:after { content: '🔗'; }
|
||||
a.tgt:hover { color: #444; background-color: #eaeaea; }
|
||||
h1:hover > a.tgt, h2:hover > a.tgt, h3:hover > a.tgt, dt:hover > a.tgt { visibility: visible; }
|
||||
code {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-weight: bold;
|
||||
@@ -106,9 +113,27 @@ UNDR_FONT = ('\3', r"\fI")
|
||||
NBR_DASH = ('\4', r"\-")
|
||||
NBR_SPACE = ('\xa0', r"\ ")
|
||||
|
||||
FILENAME_RE = re.compile(r'^(?P<fn>(?P<srcdir>.+/)?(?P<name>(?P<prog>[^/]+?)(\.(?P<sect>\d+))?)\.md)$')
|
||||
ASSIGNMENT_RE = re.compile(r'^(\w+)=(.+)')
|
||||
VER_RE = re.compile(r'^#define\s+RSYNC_VERSION\s+"(\d.+?)"', re.M)
|
||||
TZ_RE = re.compile(r'^#define\s+MAINTAINER_TZ_OFFSET\s+(-?\d+(\.\d+)?)', re.M)
|
||||
VAR_REF_RE = re.compile(r'\$\{(\w+)\}')
|
||||
VERSION_RE = re.compile(r' (\d[.\d]+)[, ]')
|
||||
BIN_CHARS_RE = re.compile(r'[\1-\7]+')
|
||||
SPACE_DOUBLE_DASH_RE = re.compile(r'\s--(\s)')
|
||||
NON_SPACE_SINGLE_DASH_RE = re.compile(r'(^|\W)-')
|
||||
WHITESPACE_RE = re.compile(r'\s')
|
||||
CODE_BLOCK_RE = re.compile(r'[%s]([^=%s]+)[=%s]' % (BOLD_FONT[0], NORM_FONT[0], NORM_FONT[0]))
|
||||
NBR_DASH_RE = re.compile(r'[%s]' % NBR_DASH[0])
|
||||
INVALID_TARGET_CHARS_RE = re.compile(r'[^-A-Za-z0-9._]')
|
||||
INVALID_START_CHAR_RE = re.compile(r'^([^A-Za-z0-9])')
|
||||
MANIFY_LINESTART_RE = re.compile(r"^(['.])", flags=re.M)
|
||||
|
||||
md_parser = None
|
||||
env_subs = { }
|
||||
|
||||
warning_count = 0
|
||||
|
||||
def main():
|
||||
for mdfn in args.mdfiles:
|
||||
parse_md_file(mdfn)
|
||||
@@ -118,15 +143,15 @@ def main():
|
||||
|
||||
|
||||
def parse_md_file(mdfn):
|
||||
fi = re.match(r'^(?P<fn>(?P<srcdir>.+/)?(?P<name>(?P<prog>[^/]+?)(\.(?P<sect>\d+))?)\.md)$', mdfn)
|
||||
fi = FILENAME_RE.match(mdfn)
|
||||
if not fi:
|
||||
die('Failed to parse a md input file name:', mdfn)
|
||||
fi = argparse.Namespace(**fi.groupdict())
|
||||
fi.want_manpage = not not fi.sect
|
||||
if fi.want_manpage:
|
||||
fi.title = fi.prog + '(' + fi.sect + ') man page'
|
||||
fi.title = fi.prog + '(' + fi.sect + ') manpage'
|
||||
else:
|
||||
fi.title = fi.prog
|
||||
fi.title = fi.prog + ' for rsync'
|
||||
|
||||
if fi.want_manpage:
|
||||
if not env_subs:
|
||||
@@ -165,6 +190,8 @@ def parse_md_file(mdfn):
|
||||
if fi.want_manpage:
|
||||
output_list += [ (fi.name, fi.man_out) ]
|
||||
for fn, txt in output_list:
|
||||
if args.dest and args.dest != '.':
|
||||
fn = os.path.join(args.dest, fn)
|
||||
if os.path.lexists(fn):
|
||||
os.unlink(fn)
|
||||
print("Wrote:", fn)
|
||||
@@ -187,6 +214,7 @@ def find_man_substitutions():
|
||||
env_subs['VERSION'] = '1.0.0'
|
||||
env_subs['bindir'] = '/usr/bin'
|
||||
env_subs['libdir'] = '/usr/lib/rsync'
|
||||
tz_offset = 0
|
||||
else:
|
||||
for fn in (srcdir + 'version.h', 'Makefile'):
|
||||
try:
|
||||
@@ -198,24 +226,26 @@ def find_man_substitutions():
|
||||
|
||||
with open(srcdir + 'version.h', 'r', encoding='utf-8') as fh:
|
||||
txt = fh.read()
|
||||
m = re.search(r'"(.+?)"', txt)
|
||||
m = VER_RE.search(txt)
|
||||
env_subs['VERSION'] = m.group(1)
|
||||
m = TZ_RE.search(txt) # the tzdata lib may not be installed, so we use a simple hour offset
|
||||
tz_offset = float(m.group(1)) * 60 * 60
|
||||
|
||||
with open('Makefile', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
m = re.match(r'^(\w+)=(.+)', line)
|
||||
m = ASSIGNMENT_RE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
var, val = (m.group(1), m.group(2))
|
||||
if var == 'prefix' and env_subs[var] is not None:
|
||||
continue
|
||||
while re.search(r'\$\{', val):
|
||||
val = re.sub(r'\$\{(\w+)\}', lambda m: env_subs[m.group(1)], val)
|
||||
while VAR_REF_RE.search(val):
|
||||
val = VAR_REF_RE.sub(lambda m: env_subs[m.group(1)], val)
|
||||
env_subs[var] = val
|
||||
if var == 'srcdir':
|
||||
break
|
||||
|
||||
env_subs['date'] = time.strftime('%d %b %Y', time.localtime(mtime))
|
||||
env_subs['date'] = time.strftime('%d %b %Y', time.gmtime(mtime + tz_offset)).lstrip('0')
|
||||
|
||||
|
||||
def html_via_commonmark(txt):
|
||||
@@ -226,6 +256,8 @@ class TransformHtml(HTMLParser):
|
||||
def __init__(self, fi):
|
||||
HTMLParser.__init__(self, convert_charrefs=True)
|
||||
|
||||
self.fn = fi.fn
|
||||
|
||||
st = self.state = argparse.Namespace(
|
||||
list_state = [ ],
|
||||
p_macro = ".P\n",
|
||||
@@ -234,10 +266,21 @@ class TransformHtml(HTMLParser):
|
||||
dt_from = None,
|
||||
in_pre = False,
|
||||
in_code = False,
|
||||
html_out = [ HTML_START % fi.title ],
|
||||
html_out = [ HTML_START.replace('%TITLE%', fi.title) ],
|
||||
man_out = [ ],
|
||||
txt = '',
|
||||
want_manpage = fi.want_manpage,
|
||||
created_hashtags = set(),
|
||||
derived_hashtags = set(),
|
||||
referenced_hashtags = set(),
|
||||
bad_hashtags = set(),
|
||||
latest_targets = [ ],
|
||||
opt_prefix = 'opt',
|
||||
a_href = None,
|
||||
a_href_external = False,
|
||||
a_txt_start = None,
|
||||
after_a_tag = False,
|
||||
target_suf = '',
|
||||
)
|
||||
|
||||
if st.want_manpage:
|
||||
@@ -260,6 +303,27 @@ class TransformHtml(HTMLParser):
|
||||
fi.man_out = ''.join(st.man_out)
|
||||
st.man_out = None
|
||||
|
||||
for tgt, txt in st.derived_hashtags:
|
||||
derived = txt2target(txt, tgt)
|
||||
if derived not in st.created_hashtags:
|
||||
txt = BIN_CHARS_RE.sub('', txt.replace(NBR_DASH[0], '-').replace(NBR_SPACE[0], ' '))
|
||||
warn('Unknown derived hashtag link in', self.fn, 'based on:', (tgt, txt))
|
||||
|
||||
for bad in st.bad_hashtags:
|
||||
if bad in st.created_hashtags:
|
||||
warn('Missing "#" in hashtag link in', self.fn + ':', bad)
|
||||
else:
|
||||
warn('Unknown non-hashtag link in', self.fn + ':', bad)
|
||||
|
||||
for bad in st.referenced_hashtags - st.created_hashtags:
|
||||
warn('Unknown hashtag link in', self.fn + ':', '#' + bad)
|
||||
|
||||
def handle_UE(self):
|
||||
st = self.state
|
||||
if st.txt.startswith(('.', ',', '!', '?', ';', ':')):
|
||||
st.man_out[-1] = ".UE " + st.txt[0] + "\n"
|
||||
st.txt = st.txt[1:]
|
||||
st.after_a_tag = False
|
||||
|
||||
def handle_starttag(self, tag, attrs_list):
|
||||
st = self.state
|
||||
@@ -300,7 +364,7 @@ class TransformHtml(HTMLParser):
|
||||
st.txt += BOLD_FONT[0]
|
||||
elif tag == 'em' or tag == 'i':
|
||||
if st.want_manpage:
|
||||
tag = 'u' # Change it into underline to be more like the man page
|
||||
tag = 'u' # Change it into underline to be more like the manpage
|
||||
st.txt += UNDR_FONT[0]
|
||||
elif tag == 'ol':
|
||||
start = 1
|
||||
@@ -328,6 +392,32 @@ class TransformHtml(HTMLParser):
|
||||
st.man_out.append(".l\n")
|
||||
st.html_out.append("<hr />")
|
||||
return
|
||||
elif tag == 'a':
|
||||
st.a_href = None
|
||||
for var, val in attrs_list:
|
||||
if var == 'href':
|
||||
if val.startswith(('https://', 'http://', 'mailto:', 'ftp:')):
|
||||
if st.after_a_tag:
|
||||
self.handle_UE()
|
||||
st.man_out.append(manify(st.txt.strip()) + "\n")
|
||||
st.man_out.append(".UR " + val + "\n")
|
||||
st.txt = ''
|
||||
st.a_href = val
|
||||
st.a_href_external = True
|
||||
elif '#' in val:
|
||||
pg, tgt = val.split('#', 1)
|
||||
if pg and pg not in VALID_PAGES or '#' in tgt:
|
||||
st.bad_hashtags.add(val)
|
||||
elif tgt in ('', 'opt', 'dopt'):
|
||||
st.a_href = val
|
||||
st.a_href_external = False
|
||||
elif pg == '':
|
||||
st.referenced_hashtags.add(tgt)
|
||||
if tgt in st.latest_targets:
|
||||
warn('Found link to the current section in', self.fn + ':', val)
|
||||
elif val not in VALID_PAGES:
|
||||
st.bad_hashtags.add(val)
|
||||
st.a_txt_start = len(st.txt)
|
||||
st.html_out.append('<' + tag + ''.join(' ' + var + '="' + htmlify(val) + '"' for var, val in attrs_list) + '>')
|
||||
st.at_first_tag_in_dd = False
|
||||
|
||||
@@ -336,6 +426,8 @@ class TransformHtml(HTMLParser):
|
||||
st = self.state
|
||||
if args.debug:
|
||||
self.output_debug('END', (tag,))
|
||||
if st.after_a_tag:
|
||||
self.handle_UE()
|
||||
if tag in CONSUMES_TXT or st.dt_from == tag:
|
||||
txt = st.txt.strip()
|
||||
st.txt = ''
|
||||
@@ -343,13 +435,27 @@ class TransformHtml(HTMLParser):
|
||||
txt = None
|
||||
add_to_txt = None
|
||||
if tag == 'h1':
|
||||
st.man_out.append(st.p_macro + '.SH "' + manify(txt) + '"\n')
|
||||
tgt = txt
|
||||
target_suf = ''
|
||||
if tgt.startswith('NEWS for '):
|
||||
m = VERSION_RE.search(tgt)
|
||||
if m:
|
||||
tgt = m.group(1)
|
||||
st.target_suf = '-' + tgt
|
||||
self.add_targets(tag, tgt)
|
||||
elif tag == 'h2':
|
||||
st.man_out.append(st.p_macro + '.SH "' + manify(txt) + '"\n')
|
||||
self.add_targets(tag, txt, st.target_suf)
|
||||
st.opt_prefix = 'dopt' if txt == 'DAEMON OPTIONS' else 'opt'
|
||||
elif tag == 'h3':
|
||||
st.man_out.append(st.p_macro + '.SS "' + manify(txt) + '"\n')
|
||||
self.add_targets(tag, txt, st.target_suf)
|
||||
elif tag == 'p':
|
||||
if st.dt_from == 'p':
|
||||
tag = 'dt'
|
||||
st.man_out.append('.IP "' + manify(txt) + '"\n')
|
||||
if txt.startswith(BOLD_FONT[0]):
|
||||
self.add_targets(tag, txt)
|
||||
st.dt_from = None
|
||||
elif txt != '':
|
||||
st.man_out.append(manify(txt) + "\n")
|
||||
@@ -373,7 +479,7 @@ class TransformHtml(HTMLParser):
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'em' or tag == 'i':
|
||||
if st.want_manpage:
|
||||
tag = 'u' # Change it into underline to be more like the man page
|
||||
tag = 'u' # Change it into underline to be more like the manpage
|
||||
add_to_txt = NORM_FONT[0]
|
||||
elif tag == 'ol' or tag == 'ul':
|
||||
if st.list_state.pop() == 'dl':
|
||||
@@ -385,6 +491,30 @@ class TransformHtml(HTMLParser):
|
||||
st.at_first_tag_in_dd = False
|
||||
elif tag == 'hr':
|
||||
return
|
||||
elif tag == 'a':
|
||||
if st.a_href_external:
|
||||
st.txt = st.txt.strip()
|
||||
if args.force_link_text or st.a_href != st.txt:
|
||||
st.man_out.append(manify(st.txt) + "\n")
|
||||
st.man_out.append(".UE\n") # This might get replaced with a punctuation version in handle_UE()
|
||||
st.after_a_tag = True
|
||||
st.a_href_external = False
|
||||
st.txt = ''
|
||||
elif st.a_href:
|
||||
atxt = st.txt[st.a_txt_start:]
|
||||
find = 'href="' + st.a_href + '"'
|
||||
for j in range(len(st.html_out)-1, 0, -1):
|
||||
if find in st.html_out[j]:
|
||||
pg, tgt = st.a_href.split('#', 1)
|
||||
derived = txt2target(atxt, tgt)
|
||||
if pg == '':
|
||||
if derived in st.latest_targets:
|
||||
warn('Found link to the current section in', self.fn + ':', st.a_href)
|
||||
st.derived_hashtags.add((tgt, atxt))
|
||||
st.html_out[j] = st.html_out[j].replace(find, 'href="' + pg + '#' + derived + '"')
|
||||
break
|
||||
else:
|
||||
die('INTERNAL ERROR: failed to find href in html data:', find)
|
||||
st.html_out.append('</' + tag + '>')
|
||||
if add_to_txt:
|
||||
if txt is None:
|
||||
@@ -403,21 +533,56 @@ class TransformHtml(HTMLParser):
|
||||
|
||||
def handle_data(self, txt):
|
||||
st = self.state
|
||||
if '](' in txt:
|
||||
warn('Malformed link in', self.fn + ':', txt)
|
||||
if args.debug:
|
||||
self.output_debug('DATA', (txt,))
|
||||
if st.in_pre:
|
||||
html = htmlify(txt)
|
||||
else:
|
||||
txt = re.sub(r'\s--(\s)', NBR_SPACE[0] + r'--\1', txt).replace('--', NBR_DASH[0]*2)
|
||||
txt = re.sub(r'(^|\W)-', r'\1' + NBR_DASH[0], txt)
|
||||
txt = SPACE_DOUBLE_DASH_RE.sub(NBR_SPACE[0] + r'--\1', txt).replace('--', NBR_DASH[0]*2)
|
||||
txt = NON_SPACE_SINGLE_DASH_RE.sub(r'\1' + NBR_DASH[0], txt)
|
||||
html = htmlify(txt)
|
||||
if st.in_code:
|
||||
txt = re.sub(r'\s', NBR_SPACE[0], txt)
|
||||
txt = WHITESPACE_RE.sub(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 add_targets(self, tag, txt, suf=None):
|
||||
st = self.state
|
||||
tag = '<' + tag + '>'
|
||||
targets = CODE_BLOCK_RE.findall(txt)
|
||||
if not targets:
|
||||
targets = [ txt ]
|
||||
tag_pos = 0
|
||||
for txt in targets:
|
||||
txt = txt2target(txt, st.opt_prefix)
|
||||
if not txt:
|
||||
continue
|
||||
if suf:
|
||||
txt += suf
|
||||
if txt in st.created_hashtags:
|
||||
for j in range(2, 1000):
|
||||
chk = txt + '-' + str(j)
|
||||
if chk not in st.created_hashtags:
|
||||
print('Made link target unique:', chk)
|
||||
txt = chk
|
||||
break
|
||||
if tag_pos == 0:
|
||||
tag_pos -= 1
|
||||
while st.html_out[tag_pos] != tag:
|
||||
tag_pos -= 1
|
||||
st.html_out[tag_pos] = tag[:-1] + ' id="' + txt + '">'
|
||||
st.html_out.append('<a href="#' + txt + '" class="tgt"></a>')
|
||||
tag_pos -= 1 # take into account the append
|
||||
else:
|
||||
st.html_out[tag_pos] = '<span id="' + txt + '"></span>' + st.html_out[tag_pos]
|
||||
st.created_hashtags.add(txt)
|
||||
st.latest_targets = targets
|
||||
|
||||
|
||||
def output_debug(self, event, extra):
|
||||
import pprint
|
||||
st = self.state
|
||||
@@ -431,13 +596,28 @@ class TransformHtml(HTMLParser):
|
||||
pprint.PrettyPrinter(indent=2).pprint(vars(st))
|
||||
|
||||
|
||||
def txt2target(txt, opt_prefix):
|
||||
txt = txt.strip().rstrip(':')
|
||||
m = CODE_BLOCK_RE.search(txt)
|
||||
if m:
|
||||
txt = m.group(1)
|
||||
txt = NBR_DASH_RE.sub('-', txt)
|
||||
txt = BIN_CHARS_RE.sub('', txt)
|
||||
txt = INVALID_TARGET_CHARS_RE.sub('_', txt)
|
||||
if opt_prefix and txt.startswith('-'):
|
||||
txt = opt_prefix + txt
|
||||
else:
|
||||
txt = INVALID_START_CHAR_RE.sub(r't\1', txt)
|
||||
return txt
|
||||
|
||||
|
||||
def manify(txt):
|
||||
return re.sub(r"^(['.])", r'\&\1', txt.replace('\\', '\\\\')
|
||||
return MANIFY_LINESTART_RE.sub(r'\&\1', txt.replace('\\', '\\\\')
|
||||
.replace(NBR_SPACE[0], NBR_SPACE[1])
|
||||
.replace(NBR_DASH[0], NBR_DASH[1])
|
||||
.replace(NORM_FONT[0], NORM_FONT[1])
|
||||
.replace(BOLD_FONT[0], BOLD_FONT[1])
|
||||
.replace(UNDR_FONT[0], UNDR_FONT[1]), flags=re.M)
|
||||
.replace(UNDR_FONT[0], UNDR_FONT[1]))
|
||||
|
||||
|
||||
def htmlify(txt):
|
||||
@@ -446,6 +626,8 @@ def htmlify(txt):
|
||||
|
||||
def warn(*msg):
|
||||
print(*msg, file=sys.stderr)
|
||||
global warning_count
|
||||
warning_count += 1
|
||||
|
||||
|
||||
def die(*msg):
|
||||
@@ -454,11 +636,13 @@ def die(*msg):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Output html and (optionally) nroff for markdown pages.", add_help=False)
|
||||
parser = argparse.ArgumentParser(description="Convert markdown into html and (optionally) nroff. Each input filename must have a .md suffix, which is changed to .html for the output filename. If the input filename ends with .num.md (e.g. foo.1.md) then a nroff file is also output with the input filename's .md suffix removed (e.g. foo.1).", add_help=False)
|
||||
parser.add_argument('--test', action='store_true', help="Just test the parsing without outputting any files.")
|
||||
parser.add_argument('--dest', metavar='DIR', help="Create files in DIR instead of the current directory.")
|
||||
parser.add_argument('--force-link-text', action='store_true', help="Don't remove the link text if it matches the link href. Useful when nroff doesn't understand .UR and .UE.")
|
||||
parser.add_argument('--debug', '-D', action='count', default=0, help='Output copious info on the html parsing. Repeat for even more.')
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument("mdfiles", nargs='+', help="The source .md files to convert.")
|
||||
parser.add_argument("mdfiles", metavar='FILE.md', nargs='+', help="One or more .md files to convert.")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
@@ -474,3 +658,5 @@ if __name__ == '__main__':
|
||||
gfm_parser = None
|
||||
|
||||
main()
|
||||
if warning_count:
|
||||
sys.exit(1)
|
||||
|
||||
12
mkgitver
12
mkgitver
@@ -1,14 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
srcdir=`dirname $0`
|
||||
gitver=`git describe --abbrev=8 2>/dev/null`
|
||||
|
||||
if [ ! -f git-version.h ]; then
|
||||
touch git-version.h
|
||||
fi
|
||||
|
||||
case "$gitver" in
|
||||
*.*)
|
||||
if test -d "$srcdir/.git" || test -f "$srcdir/.git"; then
|
||||
gitver=`git describe --abbrev=8 2>/dev/null`
|
||||
# NOTE: I'm avoiding "|" in sed since I'm not sure if sed -r is portable and "\|" fails on some OSes.
|
||||
verchk=`echo "$gitver-" | sed -n '/^v3\.[0-9][0-9]*\.[0-9][0-9]*\(pre[0-9]*\)*-/p'`
|
||||
if [ -n "$verchk" ]; then
|
||||
echo "#define RSYNC_GITVER \"$gitver\"" >git-version.h.new
|
||||
if ! diff git-version.h.new git-version.h >/dev/null; then
|
||||
echo "Updating git-version.h"
|
||||
@@ -16,5 +18,5 @@ case "$gitver" in
|
||||
else
|
||||
rm git-version.h.new
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
366
options.c
366
options.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2000, 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2022 Wayne Davison
|
||||
* Copyright (C) 2002-2023 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
|
||||
@@ -27,6 +27,8 @@
|
||||
extern int module_id;
|
||||
extern int local_server;
|
||||
extern int sanitize_paths;
|
||||
extern int trust_sender_args;
|
||||
extern int trust_sender_filter;
|
||||
extern unsigned int module_dirlen;
|
||||
extern filter_rule_list filter_list;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
@@ -47,6 +49,7 @@ int append_mode = 0;
|
||||
int keep_dirlinks = 0;
|
||||
int copy_dirlinks = 0;
|
||||
int copy_links = 0;
|
||||
int copy_devices = 0;
|
||||
int write_devices = 0;
|
||||
int preserve_links = 0;
|
||||
int preserve_hard_links = 0;
|
||||
@@ -63,6 +66,7 @@ int preserve_atimes = 0;
|
||||
int preserve_crtimes = 0;
|
||||
int omit_dir_times = 0;
|
||||
int omit_link_times = 0;
|
||||
int trust_sender = 0;
|
||||
int update_only = 0;
|
||||
int open_noatime = 0;
|
||||
int cvs_exclude = 0;
|
||||
@@ -102,6 +106,7 @@ int filesfrom_fd = -1;
|
||||
char *filesfrom_host = NULL;
|
||||
int eol_nulls = 0;
|
||||
int protect_args = -1;
|
||||
int old_style_args = -1;
|
||||
int human_readable = 1;
|
||||
int recurse = 0;
|
||||
int mkpath_dest_arg = 0;
|
||||
@@ -195,6 +200,7 @@ int remote_option_cnt = 0;
|
||||
const char **remote_options = NULL;
|
||||
const char *checksum_choice = NULL;
|
||||
const char *compress_choice = NULL;
|
||||
static const char *empty_argv[1];
|
||||
|
||||
int quiet = 0;
|
||||
int output_motd = 1;
|
||||
@@ -291,7 +297,7 @@ static struct output_struct debug_words[COUNT_DEBUG+1] = {
|
||||
DEBUG_WORD(DELTASUM, W_SND|W_REC, "Debug delta-transfer checksumming (levels 1-4)"),
|
||||
DEBUG_WORD(DUP, W_REC, "Debug weeding of duplicate names"),
|
||||
DEBUG_WORD(EXIT, W_CLI|W_SRV, "Debug exit events (levels 1-3)"),
|
||||
DEBUG_WORD(FILTER, W_SND|W_REC, "Debug filter actions (levels 1-2)"),
|
||||
DEBUG_WORD(FILTER, W_SND|W_REC, "Debug filter actions (levels 1-3)"),
|
||||
DEBUG_WORD(FLIST, W_SND|W_REC, "Debug file-list operations (levels 1-4)"),
|
||||
DEBUG_WORD(FUZZY, W_REC, "Debug fuzzy scoring (levels 1-2)"),
|
||||
DEBUG_WORD(GENR, W_REC, "Debug generator functions"),
|
||||
@@ -577,7 +583,7 @@ enum {OPT_SERVER = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
|
||||
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_BLOCK_SIZE,
|
||||
OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_BWLIMIT, OPT_STDERR,
|
||||
OPT_OLD_COMPRESS, OPT_NEW_COMPRESS, OPT_NO_COMPRESS,
|
||||
OPT_OLD_COMPRESS, OPT_NEW_COMPRESS, OPT_NO_COMPRESS, OPT_OLD_ARGS,
|
||||
OPT_STOP_AFTER, OPT_STOP_AT,
|
||||
OPT_REFUSED_BASE = 9000};
|
||||
|
||||
@@ -655,6 +661,7 @@ static struct poptOption long_options[] = {
|
||||
{"no-D", 0, POPT_ARG_NONE, 0, OPT_NO_D, 0, 0 },
|
||||
{"devices", 0, POPT_ARG_VAL, &preserve_devices, 1, 0, 0 },
|
||||
{"no-devices", 0, POPT_ARG_VAL, &preserve_devices, 0, 0, 0 },
|
||||
{"copy-devices", 0, POPT_ARG_NONE, ©_devices, 0, 0, 0 },
|
||||
{"write-devices", 0, POPT_ARG_VAL, &write_devices, 1, 0, 0 },
|
||||
{"no-write-devices", 0, POPT_ARG_VAL, &write_devices, 0, 0, 0 },
|
||||
{"specials", 0, POPT_ARG_VAL, &preserve_specials, 1, 0, 0 },
|
||||
@@ -780,9 +787,14 @@ static struct poptOption long_options[] = {
|
||||
{"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
|
||||
{"from0", '0', POPT_ARG_VAL, &eol_nulls, 1, 0, 0},
|
||||
{"no-from0", 0, POPT_ARG_VAL, &eol_nulls, 0, 0, 0},
|
||||
{"protect-args", 's', POPT_ARG_VAL, &protect_args, 1, 0, 0},
|
||||
{"old-args", 0, POPT_ARG_NONE, 0, OPT_OLD_ARGS, 0, 0},
|
||||
{"no-old-args", 0, POPT_ARG_VAL, &old_style_args, 0, 0, 0},
|
||||
{"secluded-args", 's', POPT_ARG_VAL, &protect_args, 1, 0, 0},
|
||||
{"no-secluded-args", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0},
|
||||
{"protect-args", 0, POPT_ARG_VAL, &protect_args, 1, 0, 0},
|
||||
{"no-protect-args", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0},
|
||||
{"no-s", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0},
|
||||
{"trust-sender", 0, POPT_ARG_VAL, &trust_sender, 1, 0, 0},
|
||||
{"numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 1, 0, 0 },
|
||||
{"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 },
|
||||
{"usermap", 0, POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 },
|
||||
@@ -941,11 +953,12 @@ static void set_refuse_options(void)
|
||||
if (!am_daemon
|
||||
|| op->shortName == 'e' /* Required for compatibility flags */
|
||||
|| op->shortName == '0' /* --from0 just modifies --files-from, so refuse that instead (or not) */
|
||||
|| op->shortName == 's' /* --protect-args is always OK */
|
||||
|| op->shortName == 's' /* --secluded-args is always OK */
|
||||
|| op->shortName == 'n' /* --dry-run is always OK */
|
||||
|| strcmp("iconv", longName) == 0
|
||||
|| strcmp("no-iconv", longName) == 0
|
||||
|| strcmp("checksum-seed", longName) == 0
|
||||
|| strcmp("copy-devices", longName) == 0 /* disable wild-match (it gets refused below) */
|
||||
|| strcmp("write-devices", longName) == 0 /* disable wild-match (it gets refused below) */
|
||||
|| strcmp("log-format", longName) == 0 /* aka out-format (NOT log-file-format) */
|
||||
|| strcmp("sender", longName) == 0
|
||||
@@ -957,6 +970,7 @@ static void set_refuse_options(void)
|
||||
assert(list_end != NULL);
|
||||
|
||||
if (am_daemon) { /* Refused by default, but can be accepted via a negated exact match. */
|
||||
parse_one_refuse_match(0, "copy-devices", list_end);
|
||||
parse_one_refuse_match(0, "write-devices", list_end);
|
||||
}
|
||||
|
||||
@@ -1334,7 +1348,7 @@ char *alt_dest_opt(int type)
|
||||
**/
|
||||
int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
{
|
||||
static poptContext pc;
|
||||
poptContext pc;
|
||||
const char *arg, **argv = *argv_p;
|
||||
int argc = *argc_p;
|
||||
int opt, want_dest_type;
|
||||
@@ -1354,10 +1368,6 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
|
||||
/* TODO: Call poptReadDefaultConfig; handle errors. */
|
||||
|
||||
/* The context leaks in case of an error, but if there's a
|
||||
* problem we always exit anyhow. */
|
||||
if (pc)
|
||||
poptFreeContext(pc);
|
||||
pc = poptGetContext(RSYNC_NAME, argc, argv, long_options, 0);
|
||||
if (!am_server) {
|
||||
poptReadDefaultConfig(pc, 0);
|
||||
@@ -1400,7 +1410,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
strlcpy(err_buf,
|
||||
"Attempt to hack rsync thwarted!\n",
|
||||
sizeof err_buf);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
#ifdef ICONV_OPTION
|
||||
iconv_opt = NULL;
|
||||
@@ -1446,7 +1456,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"the --temp-dir path is WAY too long.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!daemon_opt) {
|
||||
@@ -1456,8 +1466,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
*argv_p = argv = poptGetArgs(pc);
|
||||
*argc_p = argc = count_args(argv);
|
||||
argv = poptGetArgs(pc);
|
||||
argc = count_args(argv);
|
||||
if (!argc) {
|
||||
*argv_p = empty_argv;
|
||||
*argc_p = 0;
|
||||
} else if (poptDupArgv(argc, argv, argc_p, argv_p) != 0)
|
||||
out_of_memory("parse_arguments");
|
||||
argv = *argv_p;
|
||||
poptFreeContext(pc);
|
||||
|
||||
am_starting_up = 0;
|
||||
daemon_opt = 0;
|
||||
am_daemon = 1;
|
||||
@@ -1512,7 +1530,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
case 'a':
|
||||
if (refused_archive_part) {
|
||||
create_refuse_error(refused_archive_part);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (!recurse) /* preserve recurse == 2 */
|
||||
recurse = 1;
|
||||
@@ -1582,7 +1600,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
case 'P':
|
||||
if (refused_partial || refused_progress) {
|
||||
create_refuse_error(refused_partial ? refused_partial : refused_progress);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
do_progress = 1;
|
||||
keep_partial = 1;
|
||||
@@ -1605,12 +1623,19 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
compress_choice = NULL;
|
||||
break;
|
||||
|
||||
case OPT_OLD_ARGS:
|
||||
if (old_style_args <= 0)
|
||||
old_style_args = 1;
|
||||
else
|
||||
old_style_args++;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
arg = poptGetOptArg(pc);
|
||||
if (*arg != '-') {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"Remote option must start with a dash: %s\n", arg);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (remote_option_cnt+2 >= remote_option_alloc) {
|
||||
remote_option_alloc += 16;
|
||||
@@ -1652,27 +1677,27 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
ssize_t size;
|
||||
arg = poptGetOptArg(pc);
|
||||
if ((size = parse_size_arg(arg, 'b', "block-size", 0, max_blength, False)) < 0)
|
||||
return 0;
|
||||
goto cleanup;
|
||||
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;
|
||||
goto cleanup;
|
||||
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', "min-size", 0, -1, False)) < 0)
|
||||
return 0;
|
||||
goto cleanup;
|
||||
min_size_arg = strdup(do_big_num(min_size, 0, NULL));
|
||||
break;
|
||||
|
||||
case OPT_BWLIMIT: {
|
||||
ssize_t size = parse_size_arg(bwlimit_arg, 'K', "bwlimit", 512, -1, True);
|
||||
if (size < 0)
|
||||
return 0;
|
||||
goto cleanup;
|
||||
bwlimit_arg = strdup(do_big_num(size, 0, NULL));
|
||||
bwlimit = (size + 512) / 1024;
|
||||
break;
|
||||
@@ -1701,7 +1726,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"ERROR: the %s option conflicts with the %s option\n",
|
||||
alt_dest_opt(want_dest_type), alt_dest_opt(0));
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
alt_dest_type = want_dest_type;
|
||||
|
||||
@@ -1709,7 +1734,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"ERROR: at most %d %s args may be specified\n",
|
||||
MAX_BASIS_DIRS, alt_dest_opt(0));
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
/* We defer sanitizing this arg until we know what
|
||||
* our destination directory is going to be. */
|
||||
@@ -1722,7 +1747,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"Invalid argument passed to --chmod (%s)\n",
|
||||
arg);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1741,11 +1766,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (usermap_via_chown) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--usermap conflicts with prior --chown.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"You can only specify --usermap once.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
usermap = (char *)poptGetOptArg(pc);
|
||||
usermap_via_chown = False;
|
||||
@@ -1757,11 +1782,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (groupmap_via_chown) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--groupmap conflicts with prior --chown.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"You can only specify --groupmap once.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
groupmap = (char *)poptGetOptArg(pc);
|
||||
groupmap_via_chown = False;
|
||||
@@ -1780,11 +1805,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (!usermap_via_chown) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--chown conflicts with prior --usermap.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"You can only specify a user-affecting --chown once.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (asprintf(&usermap, "*:%.*s", len, chown) < 0)
|
||||
out_of_memory("parse_arguments");
|
||||
@@ -1796,11 +1821,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (!groupmap_via_chown) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--chown conflicts with prior --groupmap.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"You can only specify a group-affecting --chown once.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (asprintf(&groupmap, "*:%s", arg) < 0)
|
||||
out_of_memory("parse_arguments");
|
||||
@@ -1828,7 +1853,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf,sizeof(err_buf),
|
||||
"ACLs are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
#endif
|
||||
|
||||
case 'X':
|
||||
@@ -1839,7 +1864,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf,sizeof(err_buf),
|
||||
"extended attributes are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
#endif
|
||||
|
||||
case OPT_STOP_AFTER: {
|
||||
@@ -1848,7 +1873,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
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;
|
||||
goto cleanup;
|
||||
}
|
||||
stop_at_utime += val;
|
||||
break;
|
||||
@@ -1859,11 +1884,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
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;
|
||||
goto cleanup;
|
||||
}
|
||||
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;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1881,7 +1906,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
else {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--stderr mode \"%s\" is not one of errors, all, or client\n", arg);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
saw_stderr_opt = 1;
|
||||
break;
|
||||
@@ -1892,13 +1917,13 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
* turned this option off. */
|
||||
if (opt >= OPT_REFUSED_BASE) {
|
||||
create_refuse_error(opt);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
snprintf(err_buf, sizeof err_buf, "%s%s: %s\n",
|
||||
am_server ? "on remote machine: " : "",
|
||||
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(opt));
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1906,7 +1931,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
saw_stderr_opt = 1;
|
||||
|
||||
if (version_opt_cnt) {
|
||||
print_rsync_version(FINFO);
|
||||
print_rsync_version(version_opt_cnt > 1 && !am_server ? FNONE : FINFO);
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
@@ -1918,9 +1943,26 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
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;
|
||||
goto cleanup;
|
||||
max_alloc = size;
|
||||
}
|
||||
if (!max_alloc)
|
||||
max_alloc = SIZE_MAX;
|
||||
|
||||
if (old_style_args < 0) {
|
||||
if (!am_server && protect_args <= 0 && (arg = getenv("RSYNC_OLD_ARGS")) != NULL && *arg) {
|
||||
protect_args = 0;
|
||||
old_style_args = atoi(arg);
|
||||
} else
|
||||
old_style_args = 0;
|
||||
} else if (old_style_args) {
|
||||
if (protect_args > 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--secluded-args conflicts with --old-args.\n");
|
||||
goto cleanup;
|
||||
}
|
||||
protect_args = 0;
|
||||
}
|
||||
|
||||
if (protect_args < 0) {
|
||||
if (am_server)
|
||||
@@ -1928,7 +1970,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
else if ((arg = getenv("RSYNC_PROTECT_ARGS")) != NULL && *arg)
|
||||
protect_args = atoi(arg) ? 1 : 0;
|
||||
else {
|
||||
#ifdef RSYNC_USE_PROTECTED_ARGS
|
||||
#ifdef RSYNC_USE_SECLUDED_ARGS
|
||||
protect_args = 1;
|
||||
#else
|
||||
protect_args = 0;
|
||||
@@ -1962,7 +2004,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
do_compression = CPRES_AUTO;
|
||||
if (do_compression && refused_compress) {
|
||||
create_refuse_error(refused_compress);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1987,7 +2029,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
default:
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"Invalid --outbuf setting -- specify N, L, or B.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
setvbuf(stdout, (char *)NULL, mode, 0);
|
||||
}
|
||||
@@ -2015,7 +2057,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
}
|
||||
if (refused_no_iconv && !iconv_opt) {
|
||||
create_refuse_error(refused_no_iconv);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2026,18 +2068,30 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (orig_protect_args == 2 && am_server)
|
||||
protect_args = orig_protect_args;
|
||||
|
||||
if (protect_args == 1 && am_server)
|
||||
if (protect_args == 1 && am_server) {
|
||||
poptFreeContext(pc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*argv_p = argv = poptGetArgs(pc);
|
||||
*argc_p = argc = count_args(argv);
|
||||
/* Because popt 1.19 has started to free the returned args data, we now
|
||||
* make a copy of the array and then do an immediate cleanup. */
|
||||
argv = poptGetArgs(pc);
|
||||
argc = count_args(argv);
|
||||
if (!argc) {
|
||||
*argv_p = empty_argv;
|
||||
*argc_p = 0;
|
||||
} else if (poptDupArgv(argc, argv, argc_p, argv_p) != 0)
|
||||
out_of_memory("parse_arguments");
|
||||
argv = *argv_p;
|
||||
poptFreeContext(pc);
|
||||
pc = NULL;
|
||||
|
||||
#ifndef SUPPORT_LINKS
|
||||
if (preserve_links && !am_sender) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"symlinks are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2046,7 +2100,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"hard links are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2054,20 +2108,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (am_root < 0 && preserve_xattrs > 1) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--fake-super conflicts with -XX\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
#else
|
||||
if (am_root < 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--fake-super requires an rsync with extended attributes enabled\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (write_batch && read_batch) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--write-batch and --read-batch can not be used together\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (write_batch > 0 || read_batch) {
|
||||
if (am_server) {
|
||||
@@ -2086,25 +2140,25 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (read_batch && files_from) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--read-batch cannot be used with --files-from\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (read_batch && remove_source_files) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--read-batch cannot be used with --remove-%s-files\n",
|
||||
remove_source_files == 1 ? "source" : "sent");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"the batch-file name must be %d characters or less.\n",
|
||||
MAX_BATCH_NAME_LEN);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"the --temp-dir path is WAY too long.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (max_delete < 0 && max_delete != INT_MIN) {
|
||||
@@ -2138,7 +2192,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (delete_before + !!delete_during + delete_after > 1) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"You may not combine multiple --delete-WHEN options.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (delete_before || delete_during || delete_after)
|
||||
delete_mode = 1;
|
||||
@@ -2149,7 +2203,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
delete_during = 1;
|
||||
else {
|
||||
create_refuse_error(refused_delete_before);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (refused_delete_during)
|
||||
delete_before = 1;
|
||||
@@ -2158,14 +2212,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (!xfer_dirs && delete_mode) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--delete does not work without --recursive (-r) or --dirs (-d).\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (missing_args == 3) /* simplify if both options were specified */
|
||||
missing_args = 2;
|
||||
if (refused_delete && (delete_mode || missing_args == 2)) {
|
||||
create_refuse_error(refused_delete);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (remove_source_files) {
|
||||
@@ -2174,7 +2228,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
* options. */
|
||||
if (refused_delete && am_sender) {
|
||||
create_refuse_error(refused_delete);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
need_messages_from_generator = 1;
|
||||
}
|
||||
@@ -2228,7 +2282,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--suffix cannot contain slashes: %s\n",
|
||||
backup_suffix);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (backup_dir) {
|
||||
size_t len;
|
||||
@@ -2241,7 +2295,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (len > sizeof backup_dir_buf - 128) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"the --backup-dir path is WAY too long.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
backup_dir_len = (int)len;
|
||||
if (!backup_dir_len) {
|
||||
@@ -2260,7 +2314,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
"--suffix cannot be empty %s\n", backup_dir_len < 0
|
||||
? "when --backup-dir is the same as the dest dir"
|
||||
: "without a --backup-dir");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
} else if (make_backups && delete_mode && !delete_excluded && !am_server) {
|
||||
snprintf(backup_dir_buf, sizeof backup_dir_buf,
|
||||
"P *%s", backup_suffix);
|
||||
@@ -2288,7 +2342,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (do_progress && !am_server) {
|
||||
if (!log_before_transfer && INFO_EQ(NAME, 0))
|
||||
parse_output_words(info_words, info_levels, "name", DEFAULT_PRIORITY);
|
||||
parse_output_words(info_words, info_levels, "flist2,progress", DEFAULT_PRIORITY);
|
||||
parse_output_words(info_words, info_levels, "FLIST2,PROGRESS", DEFAULT_PRIORITY);
|
||||
}
|
||||
|
||||
if (dry_run)
|
||||
@@ -2329,11 +2383,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (whole_file > 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--append cannot be used with --whole-file\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
if (refused_inplace) {
|
||||
create_refuse_error(refused_inplace);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
inplace = 1;
|
||||
}
|
||||
@@ -2341,7 +2395,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (write_devices) {
|
||||
if (refused_inplace) {
|
||||
create_refuse_error(refused_inplace);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
inplace = 1;
|
||||
}
|
||||
@@ -2356,13 +2410,13 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
"--%s cannot be used with --%s\n",
|
||||
append_mode ? "append" : "inplace",
|
||||
delay_updates ? "delay-updates" : "partial-dir");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
/* --inplace implies --partial for refusal purposes, but we
|
||||
* clear the keep_partial flag for internal logic purposes. */
|
||||
if (refused_partial) {
|
||||
create_refuse_error(refused_partial);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
keep_partial = 0;
|
||||
#else
|
||||
@@ -2370,7 +2424,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
"--%s is not supported on this %s\n",
|
||||
append_mode ? "append" : "inplace",
|
||||
am_server ? "server" : "client");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
#endif
|
||||
} else {
|
||||
if (keep_partial && !partial_dir && !am_server) {
|
||||
@@ -2384,7 +2438,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
partial_dir = NULL;
|
||||
if (!partial_dir && refused_partial) {
|
||||
create_refuse_error(refused_partial);
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
keep_partial = 1;
|
||||
}
|
||||
@@ -2405,14 +2459,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
if (am_server) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"The --files-from sent to the server cannot specify a host.\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
files_from = p;
|
||||
filesfrom_host = h;
|
||||
if (strcmp(files_from, "-") == 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"Invalid --files-from remote filename\n");
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (sanitize_paths)
|
||||
@@ -2431,11 +2485,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"failed to open files-from file %s: %s\n",
|
||||
files_from, strerror(errno));
|
||||
return 0;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trust_sender || am_server || read_batch)
|
||||
trust_sender_args = trust_sender_filter = 1;
|
||||
else if (old_style_args || filesfrom_host != NULL)
|
||||
trust_sender_args = 1;
|
||||
|
||||
am_starting_up = 0;
|
||||
|
||||
return 1;
|
||||
@@ -2443,10 +2502,80 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
options_rejected:
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"Your options have been rejected by the server.\n");
|
||||
cleanup:
|
||||
if (pc)
|
||||
poptFreeContext(pc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char SPLIT_ARG_WHEN_OLD[1];
|
||||
|
||||
/**
|
||||
* Do backslash quoting of any weird chars in "arg", append the resulting
|
||||
* string to the end of the "opt" (which gets a "=" appended if it is not
|
||||
* an empty or NULL string), and return the (perhaps malloced) result.
|
||||
* If opt is NULL, arg is considered a filename arg that allows wildcards.
|
||||
* If it is "" or any other value, it is considered an option.
|
||||
**/
|
||||
char *safe_arg(const char *opt, const char *arg)
|
||||
{
|
||||
#define SHELL_CHARS "!#$&;|<>(){}\"'` \t\\"
|
||||
#define WILD_CHARS "*?[]" /* We don't allow remote brace expansion */
|
||||
BOOL is_filename_arg = !opt;
|
||||
char *escapes = is_filename_arg ? SHELL_CHARS : WILD_CHARS SHELL_CHARS;
|
||||
BOOL escape_leading_dash = is_filename_arg && *arg == '-';
|
||||
BOOL escape_leading_tilde = 0;
|
||||
int len1 = opt && *opt ? strlen(opt) + 1 : 0;
|
||||
int len2 = strlen(arg);
|
||||
int extras = escape_leading_dash ? 2 : 0;
|
||||
char *ret;
|
||||
if (!protect_args && old_style_args < 2 && (!old_style_args || (!is_filename_arg && opt != SPLIT_ARG_WHEN_OLD))) {
|
||||
const char *f;
|
||||
if (*arg == '~' && is_filename_arg && !am_sender && !trust_sender_args
|
||||
&& ((relative_paths && !strstr(arg, "/./"))
|
||||
|| !strchr(arg, '/'))) {
|
||||
extras++;
|
||||
escape_leading_tilde = 1;
|
||||
}
|
||||
for (f = arg; *f; f++) {
|
||||
if (strchr(escapes, *f))
|
||||
extras++;
|
||||
}
|
||||
}
|
||||
if (!len1 && !extras)
|
||||
return (char*)arg;
|
||||
ret = new_array(char, len1 + len2 + extras + 1);
|
||||
if (len1) {
|
||||
memcpy(ret, opt, len1-1);
|
||||
ret[len1-1] = '=';
|
||||
}
|
||||
if (escape_leading_dash) {
|
||||
ret[len1++] = '.';
|
||||
ret[len1++] = '/';
|
||||
extras -= 2;
|
||||
}
|
||||
if (!extras)
|
||||
memcpy(ret + len1, arg, len2);
|
||||
else {
|
||||
const char *f = arg;
|
||||
char *t = ret + len1;
|
||||
if (escape_leading_tilde)
|
||||
*t++ = '\\';
|
||||
while (*f) {
|
||||
if (*f == '\\') {
|
||||
if (!is_filename_arg || !strchr(WILD_CHARS, f[1]))
|
||||
*t++ = '\\';
|
||||
} else if (strchr(escapes, *f))
|
||||
*t++ = '\\';
|
||||
*t++ = *f++;
|
||||
}
|
||||
}
|
||||
ret[len1+len2+extras] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a filtered list of options to pass through from the
|
||||
* client to the server.
|
||||
@@ -2590,9 +2719,7 @@ void server_options(char **args, int *argc_p)
|
||||
set++;
|
||||
else
|
||||
set = iconv_opt;
|
||||
if (asprintf(&arg, "--iconv=%s", set) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
args[ac++] = safe_arg("--iconv", set);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2658,33 +2785,24 @@ void server_options(char **args, int *argc_p)
|
||||
}
|
||||
|
||||
if (backup_dir) {
|
||||
/* This split idiom allows for ~/path expansion via the shell. */
|
||||
args[ac++] = "--backup-dir";
|
||||
args[ac++] = backup_dir;
|
||||
args[ac++] = safe_arg("", backup_dir);
|
||||
}
|
||||
|
||||
/* Only send --suffix if it specifies a non-default value. */
|
||||
if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
|
||||
/* We use the following syntax to avoid weirdness with '~'. */
|
||||
if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
}
|
||||
if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0)
|
||||
args[ac++] = safe_arg("--suffix", backup_suffix);
|
||||
|
||||
if (checksum_choice) {
|
||||
if (asprintf(&arg, "--checksum-choice=%s", checksum_choice) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
}
|
||||
if (checksum_choice)
|
||||
args[ac++] = safe_arg("--checksum-choice", checksum_choice);
|
||||
|
||||
if (do_compression == CPRES_ZLIBX)
|
||||
args[ac++] = "--new-compress";
|
||||
else if (compress_choice && do_compression == CPRES_ZLIB)
|
||||
args[ac++] = "--old-compress";
|
||||
else if (compress_choice) {
|
||||
if (asprintf(&arg, "--compress-choice=%s", compress_choice) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
}
|
||||
else if (compress_choice)
|
||||
args[ac++] = safe_arg("--compress-choice", compress_choice);
|
||||
|
||||
if (am_sender) {
|
||||
if (max_delete > 0) {
|
||||
@@ -2693,14 +2811,10 @@ void server_options(char **args, int *argc_p)
|
||||
args[ac++] = arg;
|
||||
} else if (max_delete == 0)
|
||||
args[ac++] = "--max-delete=-1";
|
||||
if (min_size >= 0) {
|
||||
args[ac++] = "--min-size";
|
||||
args[ac++] = min_size_arg;
|
||||
}
|
||||
if (max_size >= 0) {
|
||||
args[ac++] = "--max-size";
|
||||
args[ac++] = max_size_arg;
|
||||
}
|
||||
if (min_size >= 0)
|
||||
args[ac++] = safe_arg("--min-size", min_size_arg);
|
||||
if (max_size >= 0)
|
||||
args[ac++] = safe_arg("--max-size", max_size_arg);
|
||||
if (delete_before)
|
||||
args[ac++] = "--delete-before";
|
||||
else if (delete_during == 2)
|
||||
@@ -2724,17 +2838,12 @@ void server_options(char **args, int *argc_p)
|
||||
if (do_stats)
|
||||
args[ac++] = "--stats";
|
||||
} else {
|
||||
if (skip_compress) {
|
||||
if (asprintf(&arg, "--skip-compress=%s", skip_compress) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
}
|
||||
if (skip_compress)
|
||||
args[ac++] = safe_arg("--skip-compress", skip_compress);
|
||||
}
|
||||
|
||||
if (max_alloc_arg && max_alloc != DEFAULT_MAX_ALLOC) {
|
||||
args[ac++] = "--max-alloc";
|
||||
args[ac++] = max_alloc_arg;
|
||||
}
|
||||
if (max_alloc_arg && max_alloc != DEFAULT_MAX_ALLOC)
|
||||
args[ac++] = safe_arg("--max-alloc", max_alloc_arg);
|
||||
|
||||
/* --delete-missing-args needs the cooperation of both sides, but
|
||||
* the sender can handle --ignore-missing-args by itself. */
|
||||
@@ -2759,7 +2868,7 @@ void server_options(char **args, int *argc_p)
|
||||
if (partial_dir && am_sender) {
|
||||
if (partial_dir != tmp_partialdir) {
|
||||
args[ac++] = "--partial-dir";
|
||||
args[ac++] = partial_dir;
|
||||
args[ac++] = safe_arg("", partial_dir);
|
||||
}
|
||||
if (delay_updates)
|
||||
args[ac++] = "--delay-updates";
|
||||
@@ -2782,17 +2891,11 @@ void server_options(char **args, int *argc_p)
|
||||
args[ac++] = "--use-qsort";
|
||||
|
||||
if (am_sender) {
|
||||
if (usermap) {
|
||||
if (asprintf(&arg, "--usermap=%s", usermap) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
}
|
||||
if (usermap)
|
||||
args[ac++] = safe_arg("--usermap", usermap);
|
||||
|
||||
if (groupmap) {
|
||||
if (asprintf(&arg, "--groupmap=%s", groupmap) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
}
|
||||
if (groupmap)
|
||||
args[ac++] = safe_arg("--groupmap", groupmap);
|
||||
|
||||
if (ignore_existing)
|
||||
args[ac++] = "--ignore-existing";
|
||||
@@ -2803,7 +2906,7 @@ void server_options(char **args, int *argc_p)
|
||||
|
||||
if (tmpdir) {
|
||||
args[ac++] = "--temp-dir";
|
||||
args[ac++] = tmpdir;
|
||||
args[ac++] = safe_arg("", tmpdir);
|
||||
}
|
||||
|
||||
if (do_fsync)
|
||||
@@ -2816,7 +2919,7 @@ void server_options(char **args, int *argc_p)
|
||||
*/
|
||||
for (i = 0; i < basis_dir_cnt; i++) {
|
||||
args[ac++] = alt_dest_opt(0);
|
||||
args[ac++] = basis_dir[i];
|
||||
args[ac++] = safe_arg("", basis_dir[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2834,14 +2937,14 @@ void server_options(char **args, int *argc_p)
|
||||
} else if (inplace) {
|
||||
args[ac++] = "--inplace";
|
||||
/* Work around a bug in older rsync versions (on the remote side) for --inplace --sparse */
|
||||
if (sparse_files && !whole_file)
|
||||
if (sparse_files && !whole_file && am_sender)
|
||||
args[ac++] = "--no-W";
|
||||
}
|
||||
|
||||
if (files_from && (!am_sender || filesfrom_host)) {
|
||||
if (filesfrom_host) {
|
||||
args[ac++] = "--files-from";
|
||||
args[ac++] = files_from;
|
||||
args[ac++] = safe_arg("", files_from);
|
||||
if (eol_nulls)
|
||||
args[ac++] = "--from0";
|
||||
} else {
|
||||
@@ -2863,6 +2966,9 @@ void server_options(char **args, int *argc_p)
|
||||
else if (remove_source_files)
|
||||
args[ac++] = "--remove-sent-files";
|
||||
|
||||
if (copy_devices && !am_sender)
|
||||
args[ac++] = "--copy-devices";
|
||||
|
||||
if (preallocate_files && am_sender)
|
||||
args[ac++] = "--preallocate";
|
||||
|
||||
@@ -2884,7 +2990,7 @@ void server_options(char **args, int *argc_p)
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
for (j = 1; j <= remote_option_cnt; j++)
|
||||
args[ac++] = (char*)remote_options[j];
|
||||
args[ac++] = safe_arg(SPLIT_ARG_WHEN_OLD, remote_options[j]);
|
||||
}
|
||||
|
||||
*argc_p = ac;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import re, argparse
|
||||
|
||||
short_no_arg = { }
|
||||
short_with_num = { '@': 1 };
|
||||
short_with_num = { '@': 1 }
|
||||
long_opts = { # These include some extra long-args that BackupPC uses:
|
||||
'block-size': 1,
|
||||
'daemon': -1,
|
||||
@@ -27,6 +27,7 @@ long_opts = { # These include some extra long-args that BackupPC uses:
|
||||
'recursive': 0,
|
||||
'stderr': 1,
|
||||
'times': 0,
|
||||
'copy-devices': -1,
|
||||
'write-devices': -1,
|
||||
}
|
||||
|
||||
@@ -57,11 +58,13 @@ def main():
|
||||
continue
|
||||
|
||||
if last_long_opt:
|
||||
m = re.search(r'args\[ac\+\+\] = ([^["\s]+);', line)
|
||||
m = re.search(r'args\[ac\+\+\] = safe_arg\("", ([^[("\s]+)\);', line)
|
||||
if m:
|
||||
long_opts[last_long_opt] = 2
|
||||
last_long_opt = None
|
||||
continue
|
||||
if 'args[ac++] = ' in line:
|
||||
last_long_opt = None
|
||||
|
||||
m = re.search(r'return "--([^"]+-dest)";', line)
|
||||
if m:
|
||||
@@ -73,7 +76,9 @@ def main():
|
||||
if not m:
|
||||
m = re.search(r'args\[ac\+\+\] = "--([^"=]+)=', line)
|
||||
if not m:
|
||||
m = re.search(r'fmt = .*: "--([^"=]+)=', line)
|
||||
m = re.search(r'args\[ac\+\+\] = safe_arg\("--([^"=]+)"', line)
|
||||
if not m:
|
||||
m = re.search(r'fmt = .*: "--([^"=]+)=', line)
|
||||
if m:
|
||||
long_opts[m.group(1)] = 1
|
||||
last_long_opt = None
|
||||
@@ -81,7 +86,7 @@ def main():
|
||||
long_opts['files-from'] = 3
|
||||
|
||||
txt = """\
|
||||
### START of options data produced by the cull_options script. ###
|
||||
### START of options data produced by the cull-options script. ###
|
||||
|
||||
# To disable a short-named option, add its letter to this string:
|
||||
"""
|
||||
@@ -119,7 +124,7 @@ def main():
|
||||
print("}")
|
||||
else:
|
||||
print(");")
|
||||
print("\n### END of options data produced by the cull_options script. ###")
|
||||
print("\n### END of options data produced by the cull-options script. ###")
|
||||
|
||||
|
||||
def str_assign(name, val, comment=None):
|
||||
@@ -1,9 +1,9 @@
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.2.4
|
||||
%define fullversion %{version}pre1
|
||||
Release: 0.1.pre1
|
||||
%define srcdir src-previews
|
||||
Version: 3.3.0
|
||||
%define fullversion %{version}
|
||||
Release: 1
|
||||
%define srcdir src
|
||||
Group: Applications/Internet
|
||||
License: GPL
|
||||
Source0: https://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz
|
||||
@@ -79,8 +79,8 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%dir /etc/rsync-ssl/certs
|
||||
|
||||
%changelog
|
||||
* Sun Jan 02 2022 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.2.4pre1.
|
||||
* Sat Apr 06 2024 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.3.0.
|
||||
|
||||
* Fri Mar 21 2008 Wayne Davison <wayne@opencoder.net>
|
||||
Added installation of /etc/xinetd.d/rsync file and some commented-out
|
||||
|
||||
18
packaging/openssl-rsync.cnf
Normal file
18
packaging/openssl-rsync.cnf
Normal file
@@ -0,0 +1,18 @@
|
||||
# This config file can be used with rsync to enable legacy digests
|
||||
# (such as MD4) by using the OPENSSL_CONF environment variable.
|
||||
# See rsync's configure --with-openssl-conf=/path/name option.
|
||||
|
||||
openssl_conf = openssl_init
|
||||
|
||||
[openssl_init]
|
||||
providers = provider_sect
|
||||
|
||||
[provider_sect]
|
||||
default = default_sect
|
||||
legacy = legacy_sect
|
||||
|
||||
[default_sect]
|
||||
activate = 1
|
||||
|
||||
[legacy_sect]
|
||||
activate = 1
|
||||
@@ -32,7 +32,7 @@ def _tweak_opts(cmd, opts, **maybe_set_args):
|
||||
opts = opts.copy()
|
||||
_maybe_set(opts, **maybe_set_args)
|
||||
|
||||
if type(cmd) == str:
|
||||
if isinstance(cmd, str):
|
||||
_maybe_set(opts, shell=True)
|
||||
|
||||
want_raw = opts.pop('raw', False)
|
||||
@@ -176,12 +176,12 @@ def mandate_gensend_hook():
|
||||
print('Creating hook file:', hook)
|
||||
cmd_chk(['./rsync', '-a', 'packaging/pre-push', hook])
|
||||
else:
|
||||
ct = cmd_txt(['fgrep', 'make gensend', hook], discard='output')
|
||||
ct = cmd_txt(['grep', 'make gensend', hook], discard='output')
|
||||
if ct.rc:
|
||||
die('Please add a "make gensend" into your', hook, 'script.')
|
||||
|
||||
|
||||
# Snag the GENFILES values out of the Makefile.in file and return them as a list.
|
||||
# Snag the GENFILES values out of the Makefile file and return them as a list.
|
||||
def get_gen_files(want_dir_plus_list=False):
|
||||
cont_re = re.compile(r'\\\n')
|
||||
|
||||
@@ -189,7 +189,7 @@ def get_gen_files(want_dir_plus_list=False):
|
||||
|
||||
auto_dir = os.path.join('auto-build-save', cmd_txt('git rev-parse --abbrev-ref HEAD').out.strip().replace('/', '%'))
|
||||
|
||||
with open('Makefile.in', 'r', encoding='utf-8') as fh:
|
||||
with open(auto_dir + '/Makefile', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
if not gen_files:
|
||||
chk = re.sub(r'^GENFILES=', '', line)
|
||||
|
||||
@@ -105,6 +105,8 @@ def main():
|
||||
if not re.match(r'^del', ans, flags=re.I):
|
||||
die("Aborted")
|
||||
cmd_chk(['git', 'tag', '-d', v_ver])
|
||||
if os.path.isdir('patches/.git'):
|
||||
cmd_chk(f"cd patches && git tag -d '{v_ver}'")
|
||||
|
||||
version = re.sub(r'[-.]*pre[-.]*', 'pre', version)
|
||||
if 'pre' in version and not curversion.endswith('dev'):
|
||||
@@ -193,7 +195,9 @@ About to:
|
||||
with open(fn, 'r', encoding='utf-8') as fh:
|
||||
old_txt = txt = fh.read()
|
||||
if fn == 'version.h':
|
||||
txt = f'#define RSYNC_VERSION "{version}"\n'
|
||||
x_re = re.compile(r'^(#define RSYNC_VERSION).*', re.M)
|
||||
msg = f"Unable to update RSYNC_VERSION in {fn}"
|
||||
txt = replace_or_die(x_re, r'\1 "%s"' % version, txt, msg)
|
||||
elif '.spec' in fn:
|
||||
for var, val in specvars.items():
|
||||
x_re = re.compile(r'^%s .*' % re.escape(var), re.M)
|
||||
@@ -206,10 +210,10 @@ About to:
|
||||
txt = replace_or_die(x_re, repl, txt, f"Unable to find SUBPROTOCOL_VERSION define in {fn}")
|
||||
elif fn == 'NEWS.md':
|
||||
efv = re.escape(finalversion)
|
||||
x_re = re.compile(r'^<.+>\s+# NEWS for rsync %s \(UNRELEASED\)\s+## Changes in this version:\n' % efv
|
||||
x_re = re.compile(r'^# 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'
|
||||
repl = (f'# 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'
|
||||
@@ -230,7 +234,7 @@ About to:
|
||||
cmd_chk(['packaging/year-tweak'])
|
||||
|
||||
print(dash_line)
|
||||
cmd_run("git diff --color | less -p '^diff .*'")
|
||||
cmd_run("git diff".split())
|
||||
|
||||
srctar_name = f"{rsync_ver}.tar.gz"
|
||||
pattar_name = f"rsync-patches-{version}.tar.gz"
|
||||
@@ -245,20 +249,20 @@ About to:
|
||||
|
||||
About to:
|
||||
- git commit all changes
|
||||
- generate the manpages
|
||||
- run a full build, ensuring that the manpages & configure.sh are up-to-date
|
||||
- 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
|
||||
run patch-update with the --make option (which opens a shell on error)
|
||||
""")
|
||||
ans = input("<Press Enter OR 'y' to continue> ")
|
||||
|
||||
s = cmd_run(['git', 'commit', '-a', '-m', f'Preparing for release of {version}'])
|
||||
s = cmd_run(['git', 'commit', '-a', '-m', f'Preparing for release of {version} [buildall]'])
|
||||
if s.returncode:
|
||||
die('Aborting')
|
||||
|
||||
cmd_chk('make gen')
|
||||
cmd_chk('touch configure.ac && packaging/smart-make && make gen')
|
||||
|
||||
print(f'Creating any missing patch branches.')
|
||||
print('Creating any missing patch branches.')
|
||||
s = cmd_run(f'packaging/branch-from-patch --branch={args.master_branch} --add-missing')
|
||||
if s.returncode:
|
||||
die('Aborting')
|
||||
@@ -341,7 +345,7 @@ About to:
|
||||
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(["./md-convert"] + [ dest +'/'+ fn for fn in md_files ])
|
||||
cmd_chk(["./md-convert", "--dest", dest, *md_files])
|
||||
|
||||
cmd_chk(f"git log --name-status | gzip -9 >{dest}/ChangeLog.gz")
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ Documentation=man:rsync(1) man:rsyncd.conf(5)
|
||||
[Service]
|
||||
ExecStart=/usr/bin/rsync --daemon --no-detach
|
||||
RestartSec=1
|
||||
Restart=on-failure
|
||||
|
||||
# Citing README.md:
|
||||
#
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#
|
||||
# build build the config files [the default w/no arg]
|
||||
# fetch fetch the latest dev autoconfig files
|
||||
# fetchgen fetch all the latest dev generated files (including man pages)
|
||||
# fetchgen fetch all the latest dev generated files (including manpages)
|
||||
# fetchSRC fetch the latest dev source files [NON-GENERATED FILES]
|
||||
#
|
||||
# The script stops after the first successful action.
|
||||
|
||||
12
progress.c
12
progress.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2020 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -115,13 +115,13 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now, int is_l
|
||||
units = "kB/s";
|
||||
}
|
||||
|
||||
if (remain < 0)
|
||||
if (remain < 0 || remain > 9999.0 * 3600.0)
|
||||
strlcpy(rembuf, " ??:??:??", sizeof rembuf);
|
||||
else {
|
||||
snprintf(rembuf, sizeof rembuf, "%4d:%02d:%02d",
|
||||
(int) (remain / 3600.0),
|
||||
(int) (remain / 60.0) % 60,
|
||||
(int) remain % 60);
|
||||
snprintf(rembuf, sizeof rembuf, "%4u:%02u:%02u",
|
||||
(unsigned int) (remain / 3600.0),
|
||||
(unsigned int) (remain / 60.0) % 60,
|
||||
(unsigned int) remain % 60);
|
||||
}
|
||||
|
||||
output_needs_newline = 0;
|
||||
|
||||
50
receiver.c
50
receiver.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2023 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -56,7 +56,6 @@ extern int inplace;
|
||||
extern int inplace_partial;
|
||||
extern int allowed_lull;
|
||||
extern int delay_updates;
|
||||
extern int xfersum_type;
|
||||
extern BOOL want_progress_now;
|
||||
extern mode_t orig_umask;
|
||||
extern struct stats stats;
|
||||
@@ -68,6 +67,9 @@ extern struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
extern OFF_T preallocated_len;
|
||||
|
||||
extern struct name_num_item *xfer_sum_nni;
|
||||
extern int xfer_sum_len;
|
||||
|
||||
static struct bitbag *delayed_bits = NULL;
|
||||
static int phase = 0, redoing = 0;
|
||||
static flist_ndx_list batch_redo_list;
|
||||
@@ -240,7 +242,6 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
static char file_sum1[MAX_DIGEST_LEN];
|
||||
struct map_struct *mapbuf;
|
||||
struct sum_struct sum;
|
||||
int sum_len;
|
||||
int32 len;
|
||||
OFF_T total_size = F_LENGTH(file);
|
||||
OFF_T offset = 0;
|
||||
@@ -280,7 +281,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
} else
|
||||
mapbuf = NULL;
|
||||
|
||||
sum_init(xfersum_type, checksum_seed);
|
||||
sum_init(xfer_sum_nni, checksum_seed);
|
||||
|
||||
if (append_mode > 0) {
|
||||
OFF_T j;
|
||||
@@ -371,7 +372,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
|
||||
if (fd != -1 && offset > 0) {
|
||||
if (sparse_files > 0) {
|
||||
if (sparse_end(fd, offset) != 0)
|
||||
if (sparse_end(fd, offset, updating_basis_or_equiv) != 0)
|
||||
goto report_write_error;
|
||||
} else if (flush_write_file(fd) < 0) {
|
||||
report_write_error:
|
||||
@@ -393,7 +394,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
if (INFO_GTE(PROGRESS, 1))
|
||||
end_progress(total_size);
|
||||
|
||||
sum_len = sum_end(file_sum1);
|
||||
sum_end(file_sum1);
|
||||
|
||||
if (do_fsync && fd != -1 && fsync(fd) != 0) {
|
||||
rsyserr(FERROR, errno, "fsync failed on %s", full_fname(fname));
|
||||
@@ -403,10 +404,10 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
if (mapbuf)
|
||||
unmap_file(mapbuf);
|
||||
|
||||
read_buf(f_in, sender_file_sum, sum_len);
|
||||
read_buf(f_in, sender_file_sum, xfer_sum_len);
|
||||
if (DEBUG_GTE(DELTASUM, 2))
|
||||
rprintf(FINFO,"got file_sum\n");
|
||||
if (fd != -1 && memcmp(file_sum1, sender_file_sum, sum_len) != 0)
|
||||
if (fd != -1 && memcmp(file_sum1, sender_file_sum, xfer_sum_len) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -439,9 +440,8 @@ static void handle_delayed_updates(char *local_name)
|
||||
"rename failed for %s (from %s)",
|
||||
full_fname(fname), partialptr);
|
||||
} else {
|
||||
if (remove_source_files
|
||||
|| (preserve_hard_links && F_IS_HLINKED(file)))
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
if (remove_source_files || (preserve_hard_links && F_IS_HLINKED(file)))
|
||||
send_msg_success(fname, ndx);
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
}
|
||||
}
|
||||
@@ -593,10 +593,13 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
if (DEBUG_GTE(RECV, 1))
|
||||
rprintf(FINFO, "recv_files(%s)\n", fname);
|
||||
|
||||
if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0')
|
||||
&& check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) {
|
||||
rprintf(FERROR, "attempt to hack rsync failed.\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0')) {
|
||||
int filt_flags = S_ISDIR(file->mode) ? NAME_IS_DIR : NAME_IS_FILE;
|
||||
if (check_filter(&daemon_filter_list, FLOG, fname, filt_flags) < 0) {
|
||||
rprintf(FERROR, "ERROR: rejecting file transfer request for daemon excluded file: %s\n",
|
||||
fname);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
@@ -695,7 +698,7 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
if (!am_server)
|
||||
discard_receive_data(f_in, file);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
send_msg_success(fname, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -808,14 +811,16 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !(S_ISREG(st.st_mode) || (write_devices && IS_DEVICE(st.st_mode)))) {
|
||||
if (write_devices && IS_DEVICE(st.st_mode)) {
|
||||
if (fd1 != -1 && st.st_size == 0)
|
||||
st.st_size = get_device_size(fd1, fname);
|
||||
/* Mark the file entry as a device so that we don't try to truncate it later on. */
|
||||
file->mode = S_IFBLK | (file->mode & ACCESSPERMS);
|
||||
} else if (fd1 != -1 && !(S_ISREG(st.st_mode))) {
|
||||
close(fd1);
|
||||
fd1 = -1;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && IS_DEVICE(st.st_mode) && st.st_size == 0)
|
||||
st.st_size = get_device_size(fd1, fname);
|
||||
|
||||
/* If we're not preserving permissions, change the file-list's
|
||||
* mode based on the local permissions and some heuristics. */
|
||||
if (!preserve_perms) {
|
||||
@@ -921,9 +926,8 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
if (remove_source_files || inc_recurse
|
||||
|| (preserve_hard_links && F_IS_HLINKED(file)))
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
if (remove_source_files || inc_recurse || (preserve_hard_links && F_IS_HLINKED(file)))
|
||||
send_msg_success(fname, ndx);
|
||||
break;
|
||||
case 0: {
|
||||
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
|
||||
|
||||
107
rsync-ssl.1.md
107
rsync-ssl.1.md
@@ -1,14 +1,17 @@
|
||||
# NAME
|
||||
## NAME
|
||||
|
||||
rsync-ssl - a helper script for connecting to an ssl rsync daemon
|
||||
|
||||
# SYNOPSIS
|
||||
## SYNOPSIS
|
||||
|
||||
```
|
||||
rsync-ssl [--type=SSL_TYPE] RSYNC_ARGS
|
||||
```
|
||||
|
||||
# DESCRIPTION
|
||||
The online version of this manpage (that includes cross-linking of topics)
|
||||
is available at <https://download.samba.org/pub/rsync/rsync-ssl.1>.
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
The rsync-ssl script helps you to run an rsync copy to/from an rsync daemon
|
||||
that requires ssl connections.
|
||||
@@ -20,7 +23,7 @@ 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
|
||||
## OPTIONS
|
||||
|
||||
If the **first** arg is a `--type=SSL_TYPE` option, the script will only use
|
||||
that particular program to open an ssl connection instead of trying to find an
|
||||
@@ -32,35 +35,56 @@ required for this particular option.
|
||||
All the other options are passed through to the rsync command, so consult the
|
||||
**rsync**(1) manpage for more information on how it works.
|
||||
|
||||
# ENVIRONMENT VARIABLES
|
||||
## ENVIRONMENT VARIABLES
|
||||
|
||||
The ssl helper scripts are affected by the following environment variables:
|
||||
|
||||
0. `RSYNC_SSL_TYPE` Specifies the program type that should be used to open the
|
||||
ssl connection. It must be one of `openssl` or `stunnel`. The
|
||||
`--type=SSL_TYPE` option overrides this, when specified.
|
||||
0. `RSYNC_SSL_PORT` If specified, the value is the port number that is used as
|
||||
the default when the user does not specify a port in their rsync command.
|
||||
When not specified, the default port number is 874. (Note that older rsync
|
||||
versions (prior to 3.2.0) did not communicate an overriding port number
|
||||
value to the helper script.)
|
||||
0. `RSYNC_SSL_CERT` If specified, the value is a filename that contains a
|
||||
certificate to use for the connection.
|
||||
0. `RSYNC_SSL_KEY` If specified, the value is a filename that contains a
|
||||
key for the provided certificate to use for the connection.
|
||||
0. `RSYNC_SSL_CA_CERT` If specified, the value is a filename that contains a
|
||||
certificate authority certificate that is used to validate the connection.
|
||||
0. `RSYNC_SSL_OPENSSL` Specifies the openssl executable to run when the
|
||||
connection type is set to openssl. If unspecified, the $PATH is searched
|
||||
for "openssl".
|
||||
0. `RSYNC_SSL_GNUTLS` Specifies the gnutls-cli executable to run when the
|
||||
connection type is set to gnutls. If unspecified, the $PATH is searched
|
||||
for "gnutls-cli".
|
||||
0. `RSYNC_SSL_STUNNEL` Specifies the stunnel executable to run when the
|
||||
connection type is set to stunnel. If unspecified, the $PATH is searched
|
||||
first for "stunnel4" and then for "stunnel".
|
||||
0. `RSYNC_SSL_TYPE`
|
||||
|
||||
# EXAMPLES
|
||||
Specifies the program type that should be used to open the ssl connection.
|
||||
It must be one of `openssl` or `stunnel`. The `--type=SSL_TYPE` option
|
||||
overrides this, when specified.
|
||||
|
||||
0. `RSYNC_SSL_PORT`
|
||||
|
||||
If specified, the value is the port number that is used as the default when
|
||||
the user does not specify a port in their rsync command. When not
|
||||
specified, the default port number is 874. (Note that older rsync versions
|
||||
(prior to 3.2.0) did not communicate an overriding port number value to the
|
||||
helper script.)
|
||||
|
||||
0. `RSYNC_SSL_CERT`
|
||||
|
||||
If specified, the value is a filename that contains a certificate to use
|
||||
for the connection.
|
||||
|
||||
0. `RSYNC_SSL_KEY`
|
||||
|
||||
If specified, the value is a filename that contains a key for the provided
|
||||
certificate to use for the connection.
|
||||
|
||||
0. `RSYNC_SSL_CA_CERT`
|
||||
|
||||
If specified, the value is a filename that contains a certificate authority
|
||||
certificate that is used to validate the connection.
|
||||
|
||||
0. `RSYNC_SSL_OPENSSL`
|
||||
|
||||
Specifies the openssl executable to run when the connection type is set to
|
||||
openssl. If unspecified, the $PATH is searched for "openssl".
|
||||
|
||||
0. `RSYNC_SSL_GNUTLS`
|
||||
|
||||
Specifies the gnutls-cli executable to run when the connection type is set
|
||||
to gnutls. If unspecified, the $PATH is searched for "gnutls-cli".
|
||||
|
||||
0. `RSYNC_SSL_STUNNEL`
|
||||
|
||||
Specifies the stunnel executable to run when the connection type is set to
|
||||
stunnel. If unspecified, the $PATH is searched first for "stunnel4" and
|
||||
then for "stunnel".
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
> rsync-ssl -aiv example.com::mod/ dest
|
||||
|
||||
@@ -70,11 +94,16 @@ The ssl helper scripts are affected by the following environment variables:
|
||||
|
||||
> rsync-ssl -aiv rsync://example.com:9874/mod/ dest
|
||||
|
||||
# SEE ALSO
|
||||
## THE SERVER SIDE
|
||||
|
||||
**rsync**(1), **rsyncd.conf**(5)
|
||||
For help setting up an SSL/TLS supporting rsync, see the [instructions in
|
||||
rsyncd.conf](rsyncd.conf.5#SSL_TLS_Daemon_Setup).
|
||||
|
||||
# CAVEATS
|
||||
## SEE ALSO
|
||||
|
||||
[**rsync**(1)](rsync.1), [**rsyncd.conf**(5)](rsyncd.conf.5)
|
||||
|
||||
## CAVEATS
|
||||
|
||||
Note that using an stunnel connection requires at least version 4 of stunnel,
|
||||
which should be the case on modern systems. Also, it does not verify a
|
||||
@@ -87,23 +116,23 @@ release the gnutls-cli command was dropping output, making it unusable. If
|
||||
that bug has been fixed in your version, feel free to put gnutls into an
|
||||
exported RSYNC_SSL_TYPE environment variable to make its use the default.
|
||||
|
||||
# BUGS
|
||||
## BUGS
|
||||
|
||||
Please report bugs! See the web site at <https://rsync.samba.org/>.
|
||||
|
||||
# VERSION
|
||||
## VERSION
|
||||
|
||||
This man page is current for version @VERSION@ of rsync.
|
||||
This manpage is current for version @VERSION@ of rsync.
|
||||
|
||||
# CREDITS
|
||||
## CREDITS
|
||||
|
||||
rsync is distributed under the GNU General Public License. See the file
|
||||
COPYING for details.
|
||||
Rsync is distributed under the GNU General Public License. See the file
|
||||
[COPYING](COPYING) for details.
|
||||
|
||||
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
|
||||
## AUTHOR
|
||||
|
||||
This manpage was written by Wayne Davison.
|
||||
|
||||
|
||||
2861
rsync.1.md
2861
rsync.1.md
File diff suppressed because it is too large
Load Diff
4
rsync.c
4
rsync.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -642,7 +642,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
#ifdef SUPPORT_ACLS
|
||||
/* It's OK to call set_acl() now, even for a dir, as the generator
|
||||
* will enable owner-writability using chmod, if necessary.
|
||||
*
|
||||
*
|
||||
* If set_acl() changes permission bits in the process of setting
|
||||
* an access ACL, it changes sxp->st.st_mode so we know whether we
|
||||
* need to chmod(). */
|
||||
|
||||
40
rsync.h
40
rsync.h
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 1996, 2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,11 +18,6 @@
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
|
||||
incompatible with older versions :-( */
|
||||
#define CHAR_OFFSET 0
|
||||
|
||||
#ifndef AVX2_ASM /* do not include the rest of file for assembly */
|
||||
#define False 0
|
||||
#define True 1
|
||||
#define Unset (-1) /* Our BOOL values are always an int. */
|
||||
@@ -43,6 +38,9 @@
|
||||
|
||||
#define BACKUP_SUFFIX "~"
|
||||
|
||||
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
|
||||
incompatible with older versions :-( */
|
||||
#define CHAR_OFFSET 0
|
||||
|
||||
/* These flags are only used during the flist transfer. */
|
||||
|
||||
@@ -340,6 +338,9 @@ enum delret {
|
||||
# endif
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_BSD_STRING_H
|
||||
# include <bsd/string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
@@ -365,16 +366,10 @@ enum delret {
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#else
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#endif
|
||||
#include <time.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
@@ -825,6 +820,7 @@ extern int uid_ndx;
|
||||
extern int gid_ndx;
|
||||
extern int acls_ndx;
|
||||
extern int xattrs_ndx;
|
||||
extern int file_sum_extra_cnt;
|
||||
|
||||
#ifdef USE_FLEXIBLE_ARRAY
|
||||
#define FILE_STRUCT_LEN (sizeof (struct file_struct))
|
||||
@@ -835,7 +831,7 @@ extern int xattrs_ndx;
|
||||
#define DEV_EXTRA_CNT 2
|
||||
#define DIRNODE_EXTRA_CNT 3
|
||||
#define EXTRA64_CNT ((sizeof (union file_extras64) + EXTRA_LEN - 1) / EXTRA_LEN)
|
||||
#define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
|
||||
#define SUM_EXTRA_CNT file_sum_extra_cnt
|
||||
|
||||
#define REQ_EXTRA(f,ndx) ((union file_extras*)(f) - (ndx))
|
||||
#define OPT_EXTRA(f,bump) ((union file_extras*)(f) - file_extra_cnt - 1 - (bump))
|
||||
@@ -1022,6 +1018,7 @@ typedef struct filter_struct {
|
||||
int slash_cnt;
|
||||
struct filter_list_struct *mergelist;
|
||||
} u;
|
||||
uchar elide;
|
||||
} filter_rule;
|
||||
|
||||
typedef struct filter_list_struct {
|
||||
@@ -1161,19 +1158,23 @@ typedef struct {
|
||||
#define NSTR_COMPRESS 1
|
||||
|
||||
struct name_num_item {
|
||||
int num;
|
||||
const char *name, *main_name;
|
||||
int num, flags;
|
||||
const char *name;
|
||||
struct name_num_item *main_nni;
|
||||
};
|
||||
|
||||
struct name_num_obj {
|
||||
const char *type;
|
||||
const char *negotiated_name;
|
||||
struct name_num_item *negotiated_nni;
|
||||
uchar *saw;
|
||||
int saw_len;
|
||||
int negotiated_num;
|
||||
struct name_num_item list[10]; /* we'll get a compile error/warning if this is ever too small */
|
||||
struct name_num_item *list;
|
||||
};
|
||||
|
||||
#ifdef EXTERNAL_ZLIB
|
||||
#define read_buf read_buf_
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include "proto.h"
|
||||
#endif
|
||||
@@ -1477,7 +1478,6 @@ const char *get_panic_action(void);
|
||||
fprintf(stderr, "%s in %s at line %d\n", msg, __FILE__, __LINE__); \
|
||||
exit_cleanup(RERR_UNSUPPORTED); \
|
||||
} while (0)
|
||||
#endif /* AVX2_ASM */
|
||||
|
||||
#ifdef HAVE_MALLINFO2
|
||||
#define MEM_ALLOC_INFO mallinfo2
|
||||
|
||||
324
rsyncd.conf.5.md
324
rsyncd.conf.5.md
@@ -1,12 +1,15 @@
|
||||
# NAME
|
||||
## NAME
|
||||
|
||||
rsyncd.conf - configuration file for rsync in daemon mode
|
||||
|
||||
# SYNOPSIS
|
||||
## SYNOPSIS
|
||||
|
||||
rsyncd.conf
|
||||
|
||||
# DESCRIPTION
|
||||
The online version of this manpage (that includes cross-linking of topics)
|
||||
is available at <https://download.samba.org/pub/rsync/rsyncd.conf.5>.
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
The rsyncd.conf file is the runtime configuration file for rsync when run as an
|
||||
rsync daemon.
|
||||
@@ -14,7 +17,7 @@ rsync daemon.
|
||||
The rsyncd.conf file controls authentication, access, logging and available
|
||||
modules.
|
||||
|
||||
# FILE FORMAT
|
||||
## FILE FORMAT
|
||||
|
||||
The file consists of modules and parameters. A module begins with the name of
|
||||
the module in square brackets and continues until the next module begins.
|
||||
@@ -40,10 +43,9 @@ The values following the equals sign in parameters are all either a string (no
|
||||
quotes needed) or a boolean, which may be given as yes/no, 0/1 or true/false.
|
||||
Case is not significant in boolean values, but is preserved in string values.
|
||||
|
||||
# LAUNCHING THE RSYNC DAEMON
|
||||
## LAUNCHING THE RSYNC DAEMON
|
||||
|
||||
The rsync daemon is launched by specifying the `--daemon` option to
|
||||
rsync.
|
||||
The rsync daemon is launched by specifying the `--daemon` option to rsync.
|
||||
|
||||
The daemon must run with root privileges if you wish to use chroot, to bind to
|
||||
a port numbered under 1024 (as is the default 873), or to set file ownership.
|
||||
@@ -69,36 +71,18 @@ reread its config file.
|
||||
Note that you should **not** send the rsync daemon a HUP signal to force it to
|
||||
reread the `rsyncd.conf` file. The file is re-read on each client connection.
|
||||
|
||||
# GLOBAL PARAMETERS
|
||||
## GLOBAL PARAMETERS
|
||||
|
||||
The first parameters in the file (before a [module] header) are the global
|
||||
parameters. Rsync also allows for the use of a "[global]" module name to
|
||||
indicate the start of one or more global-parameter sections (the name must be
|
||||
lower case).
|
||||
|
||||
You may also include any module parameters in the global part of the config
|
||||
file in which case the supplied value will override the default for that
|
||||
parameter.
|
||||
|
||||
You may use references to environment variables in the values of parameters.
|
||||
String parameters will have %VAR% references expanded as late as possible (when
|
||||
the string is first used in the program), allowing for the use of variables
|
||||
that rsync sets at connection time, such as RSYNC_USER_NAME. Non-string
|
||||
parameters (such as true/false settings) are expanded when read from the config
|
||||
file. If a variable does not exist in the environment, or if a sequence of
|
||||
characters is not a valid reference (such as an un-paired percent sign), the
|
||||
raw characters are passed through unchanged. This helps with backward
|
||||
compatibility and safety (e.g. expanding a non-existent %VAR% to an empty
|
||||
string in a path could result in a very unsafe path). The safest way to insert
|
||||
a literal % into a value is to use %%.
|
||||
parameters:
|
||||
|
||||
[comment]: # (An OL starting at 0 is converted into a DL by the parser.)
|
||||
|
||||
0. `motd file`
|
||||
|
||||
This parameter allows you to specify a "message of the day" to display to
|
||||
clients on each connect. This usually contains site information and any
|
||||
legal notices. The default is no motd file. This can be overridden by the
|
||||
This parameter allows you to specify a "message of the day" (MOTD) to display
|
||||
to clients on each connect. This usually contains site information and any
|
||||
legal notices. The default is no MOTD file. This can be overridden by the
|
||||
`--dparam=motdfile=FILE` command-line option when starting the daemon.
|
||||
|
||||
0. `pid file`
|
||||
@@ -126,7 +110,7 @@ a literal % into a value is to use %%.
|
||||
|
||||
This parameter can provide endless fun for people who like to tune their
|
||||
systems to the utmost degree. You can set all sorts of socket options which
|
||||
may make transfers faster (or slower!). Read the man page for the
|
||||
may make transfers faster (or slower!). Read the manpage for the
|
||||
**setsockopt()** system call for details on some of the options you may be
|
||||
able to set. By default no special socket options are set. These settings
|
||||
can also be specified via the `--sockopts` command-line option.
|
||||
@@ -136,7 +120,23 @@ a literal % into a value is to use %%.
|
||||
You can override the default backlog value when the daemon listens for
|
||||
connections. It defaults to 5.
|
||||
|
||||
# MODULE PARAMETERS
|
||||
You may also include any [MODULE PARAMETERS](#) in the global part of the
|
||||
config file, in which case the supplied value will override the default for
|
||||
that parameter.
|
||||
|
||||
You may use references to environment variables in the values of parameters.
|
||||
String parameters will have %VAR% references expanded as late as possible (when
|
||||
the string is first used in the program), allowing for the use of variables
|
||||
that rsync sets at connection time, such as RSYNC_USER_NAME. Non-string
|
||||
parameters (such as true/false settings) are expanded when read from the config
|
||||
file. If a variable does not exist in the environment, or if a sequence of
|
||||
characters is not a valid reference (such as an un-paired percent sign), the
|
||||
raw characters are passed through unchanged. This helps with backward
|
||||
compatibility and safety (e.g. expanding a non-existent %VAR% to an empty
|
||||
string in a path could result in a very unsafe path). The safest way to insert
|
||||
a literal % into a value is to use %%.
|
||||
|
||||
## MODULE PARAMETERS
|
||||
|
||||
After the global parameters you should define a number of modules, each module
|
||||
exports a directory tree as a symbolic name. Modules are exported by specifying
|
||||
@@ -144,11 +144,17 @@ a module name in square brackets [module] followed by the parameters for that
|
||||
module. The module name cannot contain a slash or a closing square bracket.
|
||||
If the name contains whitespace, each internal sequence of whitespace will be
|
||||
changed into a single space, while leading or trailing whitespace will be
|
||||
discarded. Also, the name cannot be "global" as that exact name indicates that
|
||||
global parameters follow (see above).
|
||||
discarded.
|
||||
|
||||
As with GLOBAL PARAMETERS, you may use references to environment variables in
|
||||
the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
There is also a special module name of "[global]" that does not define a module
|
||||
but instead switches back to the global settings context where default
|
||||
parameters can be specified. Because each defined module gets its full set of
|
||||
parameters as a combination of the default values that are set at that position
|
||||
in the config file plus its own parameter list, the use of a "[global]" section
|
||||
can help to maintain shared config values for multiple modules.
|
||||
|
||||
As with [GLOBAL PARAMETERS](#), you may use references to environment variables
|
||||
in the values of parameters. See that section for details.
|
||||
|
||||
0. `comment`
|
||||
|
||||
@@ -162,6 +168,16 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
available in this module. You must specify this parameter for each module
|
||||
in `rsyncd.conf`.
|
||||
|
||||
If the value contains a "/./" element then the path will be divided at that
|
||||
point into a chroot dir and an inner-chroot subdir. If [`use chroot`](#)
|
||||
is set to false, though, the extraneous dot dir is just cleaned out of the
|
||||
path. An example of this idiom is:
|
||||
|
||||
> path = /var/rsync/./module1
|
||||
|
||||
This will (when chrooting) chroot to "/var/rsync" and set the inside-chroot
|
||||
path to "/module1".
|
||||
|
||||
You may base the path's value off of an environment variable by surrounding
|
||||
the variable name with percent signs. You can even reference a variable
|
||||
that is set by rsync when the user connects. For example, this would use
|
||||
@@ -177,7 +193,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
0. `use chroot`
|
||||
|
||||
If "use chroot" is true, the rsync daemon will chroot to the "path" before
|
||||
If "use chroot" is true, the rsync daemon will chroot to the "[path](#)" before
|
||||
starting the file transfer with the client. This has the advantage of
|
||||
extra protection against possible implementation security holes, but it has
|
||||
the disadvantages of requiring super-user privileges, of not being able to
|
||||
@@ -185,30 +201,48 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
path, and of complicating the preservation of users and groups by name (see
|
||||
below).
|
||||
|
||||
As an additional safety feature, you can specify a dot-dir in the module's
|
||||
"path" to indicate the point where the chroot should occur. This allows
|
||||
rsync to run in a chroot with a non-"/" path for the top of the transfer
|
||||
hierarchy. Doing this guards against unintended library loading (since
|
||||
those absolute paths will not be inside the transfer hierarchy unless you
|
||||
have used an unwise pathname), and lets you setup libraries for the chroot
|
||||
that are outside of the transfer. For example, specifying
|
||||
"/var/rsync/./module1" will chroot to the "/var/rsync" directory and set
|
||||
the inside-chroot path to "/module1". If you had omitted the dot-dir, the
|
||||
chroot would have used the whole path, and the inside-chroot path would
|
||||
have been "/".
|
||||
If `use chroot` is not set, it defaults to trying to enable a chroot but
|
||||
allows the daemon to continue (after logging a warning) if it fails. The
|
||||
one exception to this is when a module's [`path`](#) has a "/./" chroot
|
||||
divider in it -- this causes an unset value to be treated as true for that
|
||||
module.
|
||||
|
||||
When both "use chroot" and "daemon chroot" are false, OR the inside-chroot
|
||||
path of "use chroot" is not "/", rsync will: (1) munge symlinks by default
|
||||
for security reasons (see "munge symlinks" for a way to turn this off, but
|
||||
only if you trust your users), (2) substitute leading slashes in absolute
|
||||
paths with the module's path (so that options such as `--backup-dir`,
|
||||
`--compare-dest`, etc. interpret an absolute path as rooted in the module's
|
||||
"path" dir), and (3) trim ".." path elements from args if rsync believes
|
||||
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).
|
||||
Prior to rsync 3.2.7, the default value was "true". The new "unset"
|
||||
default makes it easier to setup an rsync daemon as a non-root user or to
|
||||
run a daemon on a system where chroot fails. Explicitly setting the value
|
||||
to "true" in rsyncd.conf will always require the chroot to succeed.
|
||||
|
||||
When this parameter is enabled *and* the "name converter" parameter is
|
||||
*not* set, the "numeric ids" parameter will default to being enabled
|
||||
It is also possible to specify a dot-dir in the module's "[path](#)" to
|
||||
indicate that you want to chdir to the earlier part of the path and then
|
||||
serve files from inside the latter part of the path (with sanitizing and
|
||||
default symlink munging). This can be useful if you need some library dirs
|
||||
inside the chroot (typically for uid & gid lookups) but don't want to put
|
||||
the lib dir into the top of the served path (even though they can be hidden
|
||||
with an [`exclude`](#) directive). However, a better choice for a modern
|
||||
rsync setup is to use a [`name converter`](#)" and try to avoid inner lib
|
||||
dirs altogether. See also the [`daemon chroot`](#) parameter, which causes
|
||||
rsync to chroot into its own chroot area before doing any path-related
|
||||
chrooting.
|
||||
|
||||
If the daemon is serving the "/" dir (either directly or due to being
|
||||
chrooted to the module's path), rsync does not do any path sanitizing or
|
||||
(default) munging.
|
||||
|
||||
When it has to limit access to a particular subdir (either due to chroot
|
||||
being disabled or having an inside-chroot path set), rsync will munge
|
||||
symlinks (by default) and sanitize paths. Those that dislike munged
|
||||
symlinks (and really, really trust their users to not break out of the
|
||||
subdir) can disable the symlink munging via the "[munge symlinks](#)"
|
||||
parameter.
|
||||
|
||||
When rsync is sanitizing paths, it trims ".." path elements from args that
|
||||
it believes would escape the module hierarchy. It also substitutes leading
|
||||
slashes in absolute paths with the module's path (so that options such as
|
||||
`--backup-dir` & `--compare-dest` interpret an absolute path as rooted in
|
||||
the module's "[path](#)" dir).
|
||||
|
||||
When a chroot is in effect *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
|
||||
@@ -217,16 +251,16 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
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
|
||||
hide them from the user's view via "[exclude](#)" (see how in the discussion of
|
||||
that parameter). However, it's easier and safer to setup a name converter.
|
||||
|
||||
0. `daemon chroot`
|
||||
|
||||
This parameter specifies a path to which the daemon will chroot before
|
||||
beginning communication with clients. Module paths (and any "use chroot"
|
||||
beginning communication with clients. Module paths (and any "[use chroot](#)"
|
||||
settings) will then be related to this one. This lets you choose if you
|
||||
want the whole daemon to be chrooted (with this setting), just the
|
||||
transfers to be chrooted (with "use chroot"), or both. Keep in mind that
|
||||
transfers to be chrooted (with "[use chroot](#)"), or both. Keep in mind that
|
||||
the "daemon chroot" area may need various OS/lib/etc files installed to
|
||||
allow the daemon to function. By default the daemon runs without any
|
||||
chrooting.
|
||||
@@ -284,11 +318,11 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
transfer behave as if the client had passed the `--numeric-ids`
|
||||
command-line option. By default, this parameter is enabled for chroot
|
||||
modules and disabled for non-chroot modules. Also keep in mind that
|
||||
uid/gid preservation requires the module to be running as root (see "uid")
|
||||
or for "fake super" to be configured.
|
||||
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 set to false unless
|
||||
you're using a "name converter" program *or* you've taken steps to ensure
|
||||
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.
|
||||
|
||||
@@ -298,12 +332,12 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
(non-daemon-affecting) `--munge-links` command-line option (using a method
|
||||
described below). This should help protect your files from user trickery
|
||||
when your daemon module is writable. The default is disabled when
|
||||
"use chroot" is on with an inside-chroot path of "/", OR if "daemon chroot"
|
||||
"[use chroot](#)" is on with an inside-chroot path of "/", OR if "[daemon chroot](#)"
|
||||
is on, otherwise it is enabled.
|
||||
|
||||
If you disable this parameter on a daemon that is not read-only, there are
|
||||
tricks that a user can play with uploaded symlinks to access
|
||||
daemon-excluded items (if your module has any), and, if "use chroot" is
|
||||
daemon-excluded items (if your module has any), and, if "[use chroot](#)" is
|
||||
off, rsync can even be tricked into showing or changing data that is
|
||||
outside the module's path (as access-permissions allow).
|
||||
|
||||
@@ -324,7 +358,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
the source code named "munge-symlinks" that can be used to add or remove
|
||||
this prefix from your symlinks.
|
||||
|
||||
When this parameter is disabled on a writable module and "use chroot" is
|
||||
When this parameter is disabled on a writable module and "[use chroot](#)" is
|
||||
off (or the inside-chroot path is not "/"), incoming symlinks will be
|
||||
modified to drop a leading slash and to remove ".." path elements that
|
||||
rsync believes will allow a symlink to escape the module's hierarchy.
|
||||
@@ -340,10 +374,10 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
conversion in a chroot module without extra files in the chroot area, and
|
||||
also ensures that name-translation is done in a consistent manner. If the
|
||||
"charset" parameter is not set, the `--iconv` option is refused, just as if
|
||||
"iconv" had been specified via "refuse options".
|
||||
"iconv" had been specified via "[refuse options](#)".
|
||||
|
||||
If you wish to force users to always use `--iconv` for a particular module,
|
||||
add "no-iconv" to the "refuse options" parameter. Keep in mind that this
|
||||
add "no-iconv" to the "[refuse options](#)" parameter. Keep in mind that this
|
||||
will restrict access to your module to very new rsync clients.
|
||||
|
||||
0. `max connections`
|
||||
@@ -352,7 +386,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
connections you will allow. Any clients connecting when the maximum has
|
||||
been reached will receive a message telling them to try later. The default
|
||||
is 0, which means no limit. A negative value disables the module. See
|
||||
also the "lock file" parameter.
|
||||
also the "[lock file](#)" parameter.
|
||||
|
||||
0. `log file`
|
||||
|
||||
@@ -381,7 +415,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
facility name which is defined on your system. Common names are auth,
|
||||
authpriv, cron, daemon, ftp, kern, lpr, mail, news, security, syslog, user,
|
||||
uucp, local0, local1, local2, local3, local4, local5, local6 and local7.
|
||||
The default is daemon. This setting has no effect if the "log file"
|
||||
The default is daemon. This setting has no effect if the "[log file](#)"
|
||||
setting is a non-empty string (either set in the per-modules settings, or
|
||||
inherited from the global settings).
|
||||
|
||||
@@ -389,7 +423,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
This parameter allows you to specify the syslog tag to use when logging
|
||||
messages from the rsync daemon. The default is "rsyncd". This setting has
|
||||
no effect if the "log file" setting is a non-empty string (either set in
|
||||
no effect if the "[log file](#)" setting is a non-empty string (either set in
|
||||
the per-modules settings, or inherited from the global settings).
|
||||
|
||||
For example, if you wanted each authenticated user's name to be included in
|
||||
@@ -414,7 +448,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
0. `lock file`
|
||||
|
||||
This parameter specifies the file to use to support the "max connections"
|
||||
This parameter specifies the file to use to support the "[max connections](#)"
|
||||
parameter. The rsync daemon uses record locking on this file to ensure that
|
||||
the max connections limit is not exceeded for the modules sharing the lock
|
||||
file. The default is `/var/run/rsyncd.lock`.
|
||||
@@ -426,7 +460,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
"read only" is false then uploads will be possible if file permissions on
|
||||
the daemon side allow them. The default is for all modules to be read only.
|
||||
|
||||
Note that "auth users" can override this setting on a per-user basis.
|
||||
Note that "[auth users](#)" can override this setting on a per-user basis.
|
||||
|
||||
0. `write only`
|
||||
|
||||
@@ -460,8 +494,8 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
This parameter determines whether this module is listed when the client
|
||||
asks for a listing of available modules. In addition, if this is false,
|
||||
the daemon will pretend the module does not exist when a client denied by
|
||||
"hosts allow" or "hosts deny" attempts to access it. Realize that if
|
||||
"reverse lookup" is disabled globally but enabled for the module, the
|
||||
"[hosts allow](#)" or "[hosts deny](#)" attempts to access it. Realize that if
|
||||
"[reverse lookup](#)" is disabled globally but enabled for the module, the
|
||||
resulting reverse lookup to a potentially client-controlled DNS server may
|
||||
still reveal to the client that it hit an existing module. The default is
|
||||
for modules to be listable.
|
||||
@@ -470,10 +504,10 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
This parameter specifies the user name or user ID that file transfers to
|
||||
and from that module should take place as when the daemon was run as root.
|
||||
In combination with the "gid" parameter this determines what file
|
||||
In combination with the "[gid](#)" parameter this determines what file
|
||||
permissions are available. The default when run by a super-user is to
|
||||
switch to the system's "nobody" user. The default for a non-super-user is
|
||||
to not try to change the user. See also the "gid" parameter.
|
||||
to not try to change the user. See also the "[gid](#)" parameter.
|
||||
|
||||
The RSYNC_USER_NAME environment variable may be used to request that rsync
|
||||
run as the authorizing user. For example, if you want a rsync to run as
|
||||
@@ -489,7 +523,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
accessing the module. The first one will be the default group, and any
|
||||
extra ones be set as supplemental groups. You may also specify a "`*`" as
|
||||
the first gid in the list, which will be replaced by all the normal groups
|
||||
for the transfer's user (see "uid"). The default when run by a super-user
|
||||
for the transfer's user (see "[uid](#)"). The default when run by a super-user
|
||||
is to switch to your OS's "nobody" (or perhaps "nogroup") group with no
|
||||
other supplementary groups. The default for a non-super-user is to not
|
||||
change any group attributes (and indeed, your OS may not allow a
|
||||
@@ -505,13 +539,13 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
This parameter specifies a uid under which the daemon will run. The daemon
|
||||
usually runs as user root, and when this is left unset the user is left
|
||||
unchanged. See also the "uid" parameter.
|
||||
unchanged. See also the "[uid](#)" parameter.
|
||||
|
||||
0. `daemon gid`
|
||||
|
||||
This parameter specifies a gid under which the daemon will run. The daemon
|
||||
usually runs as group root, and when this is left unset, the group is left
|
||||
unchanged. See also the "gid" parameter.
|
||||
unchanged. See also the "[gid](#)" parameter.
|
||||
|
||||
0. `fake super`
|
||||
|
||||
@@ -532,8 +566,8 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
or tampering with private administrative files, such as files you may add
|
||||
to support uid/gid name translations.
|
||||
|
||||
The daemon filter chain is built from the "filter", "include from",
|
||||
"include", "exclude from", and "exclude" parameters, in that order of
|
||||
The daemon filter chain is built from the "filter", "[include from](#)",
|
||||
"[include](#)", "[exclude from](#)", and "[exclude](#)" parameters, in that order of
|
||||
priority. Anchored patterns are anchored at the root of the module. To
|
||||
prevent access to an entire subtree, for example, "`/secret`", you **must**
|
||||
exclude everything in the subtree; the easiest way to do this is with a
|
||||
@@ -560,8 +594,8 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
0. `include`
|
||||
|
||||
Use an "include" to override the effects of the "exclude" parameter. Only
|
||||
one "include" parameter can apply to a given module. See the "filter"
|
||||
Use an "include" to override the effects of the "[exclude](#)" parameter. Only
|
||||
one "include" parameter can apply to a given module. See the "[filter](#)"
|
||||
parameter for a description of how excluded files affect the daemon.
|
||||
|
||||
0. `exclude from`
|
||||
@@ -569,14 +603,14 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
This parameter specifies the name of a file on the daemon that contains
|
||||
daemon exclude patterns, one per line. Only one "exclude from" parameter
|
||||
can apply to a given module; if you have multiple exclude-from files, you
|
||||
can specify them as a merge file in the "filter" parameter. See the
|
||||
"filter" parameter for a description of how excluded files affect the
|
||||
can specify them as a merge file in the "[filter](#)" parameter. See the
|
||||
"[filter](#)" parameter for a description of how excluded files affect the
|
||||
daemon.
|
||||
|
||||
0. `include from`
|
||||
|
||||
Analogue of "exclude from" for a file of daemon include patterns. Only one
|
||||
"include from" parameter can apply to a given module. See the "filter"
|
||||
Analogue of "[exclude from](#)" for a file of daemon include patterns. Only one
|
||||
"include from" parameter can apply to a given module. See the "[filter](#)"
|
||||
parameter for a description of how excluded files affect the daemon.
|
||||
|
||||
0. `incoming chmod`
|
||||
@@ -611,7 +645,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
to supply a username and password to connect to the module. A challenge
|
||||
response authentication protocol is used for this exchange. The plain text
|
||||
usernames and passwords are stored in the file specified by the
|
||||
"secrets file" parameter. The default is for all users to be able to
|
||||
"[secrets file](#)" parameter. The default is for all users to be able to
|
||||
connect without a password (this is called "anonymous rsync").
|
||||
|
||||
In addition to username matching, you can specify groupname matching via a
|
||||
@@ -623,7 +657,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
Finally, options may be specified after a colon (:). The options allow you
|
||||
to "deny" a user or a group, set the access to "ro" (read-only), or set the
|
||||
access to "rw" (read/write). Setting an auth-rule-specific ro/rw setting
|
||||
overrides the module's "read only" setting.
|
||||
overrides the module's "[read only](#)" setting.
|
||||
|
||||
Be sure to put the rules in the order you want them to be matched, because
|
||||
the checking stops at the first matching user or group, and that is the
|
||||
@@ -661,7 +695,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
This parameter specifies the name of a file that contains the
|
||||
username:password and/or @groupname:password pairs used for authenticating
|
||||
this module. This file is only consulted if the "auth users" parameter is
|
||||
this module. This file is only consulted if the "[auth users](#)" parameter is
|
||||
specified. The file is line-based and contains one name:password pair per
|
||||
line. Any line has a hash (#) as the very first character on the line is
|
||||
considered a comment and is skipped. The passwords can contain any
|
||||
@@ -675,14 +709,14 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
"@groupname:password" line for the group that triggered the authentication.
|
||||
|
||||
It is up to you what kind of password entries you want to include, either
|
||||
users, groups, or both. The use of group rules in "auth users" does not
|
||||
users, groups, or both. The use of group rules in "[auth users](#)" does not
|
||||
require that you specify a group password if you do not want to use shared
|
||||
passwords.
|
||||
|
||||
There is no default for the "secrets file" parameter, you must choose a
|
||||
name (such as `/etc/rsyncd.secrets`). The file must normally not be
|
||||
readable by "other"; see "strict modes". If the file is not found or is
|
||||
rejected, no logins for a "user auth" module will be possible.
|
||||
readable by "other"; see "[strict modes](#)". If the file is not found or is
|
||||
rejected, no logins for an "[auth users](#)" module will be possible.
|
||||
|
||||
0. `strict modes`
|
||||
|
||||
@@ -714,11 +748,11 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
addresses which match the masked IP address will be allowed in.
|
||||
- a hostname pattern using wildcards. If the hostname of the connecting IP
|
||||
(as determined by a reverse lookup) matches the wildcarded name (using
|
||||
the same rules as normal unix filename matching), the client is allowed
|
||||
in. This only works if "reverse lookup" is enabled (the default).
|
||||
the same rules as normal Unix filename matching), the client is allowed
|
||||
in. This only works if "[reverse lookup](#)" is enabled (the default).
|
||||
- a hostname. A plain hostname is matched against the reverse DNS of the
|
||||
connecting IP (if "reverse lookup" is enabled), and/or the IP of the
|
||||
given hostname is matched against the connecting IP (if "forward lookup"
|
||||
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.
|
||||
@@ -730,11 +764,11 @@ 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 "hosts deny" as a way to add
|
||||
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
|
||||
"[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
|
||||
@@ -745,7 +779,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
This parameter allows you to specify a list of comma- and/or
|
||||
whitespace-separated patterns that are matched against a connecting clients
|
||||
hostname and IP address. If the pattern matches then the connection is
|
||||
rejected. See the "hosts allow" parameter for more information.
|
||||
rejected. See the "[hosts allow](#)" parameter for more information.
|
||||
|
||||
The default is no "hosts deny" parameter, which means all hosts can
|
||||
connect.
|
||||
@@ -753,8 +787,8 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
0. `reverse lookup`
|
||||
|
||||
Controls whether the daemon performs a reverse lookup on the client's IP
|
||||
address to determine its hostname, which is used for "hosts allow" &
|
||||
"hosts deny" checks and the "%h" log escape. This is enabled by default,
|
||||
address to determine its hostname, which is used for "[hosts allow](#)" &
|
||||
"[hosts deny](#)" checks and the "%h" log escape. This is enabled by default,
|
||||
but you may wish to disable it to save time if you know the lookup will not
|
||||
return a useful result, in which case the daemon will use the name
|
||||
"UNDETERMINED" instead.
|
||||
@@ -794,7 +828,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
logs the transfer at the end, so if a transfer is aborted, no mention will
|
||||
be made in the log file.
|
||||
|
||||
If you want to customize the log lines, see the "log format" parameter.
|
||||
If you want to customize the log lines, see the "[log format](#)" parameter.
|
||||
|
||||
0. `log format`
|
||||
|
||||
@@ -811,7 +845,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
(e.g. "`%''l %'b %f`").
|
||||
|
||||
The default log format is "`%o %h [%a] %m (%u) %f %l`", and a "`%t [%p] `"
|
||||
is always prefixed when using the "log file" parameter. (A perl script
|
||||
is always prefixed when using the "[log file](#)" parameter. (A perl script
|
||||
that will summarize this default log format is included in the rsync source
|
||||
code distribution in the "support" subdirectory: rsyncstats.)
|
||||
|
||||
@@ -892,7 +926,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
> refuse options = * !a !v !compress*
|
||||
|
||||
Don't worry that the "`*`" will refuse certain vital options such as
|
||||
`--dry-run`, `--server`, `--no-iconv`, `--protect-args`, etc. These
|
||||
`--dry-run`, `--server`, `--no-iconv`, `--seclude-args`, etc. These
|
||||
important options are not matched by wild-card, so they must be overridden
|
||||
by their exact name. For instance, if you're forcing iconv transfers you
|
||||
could use something like this:
|
||||
@@ -922,7 +956,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
|
||||
> refuse options = * !a !delete* delete-after
|
||||
|
||||
A note on refusing "compress": it may be better to set the "dont compress"
|
||||
A note on refusing "compress": it may be better to set the "[dont compress](#)"
|
||||
daemon parameter to "`*`" and ensure that `RSYNC_COMPRESS_LIST=zlib` is set
|
||||
in the environment of the daemon in order to disable compression silently
|
||||
instead of returning an error that forces the client to remove the `-z`
|
||||
@@ -931,9 +965,10 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
If you are un-refusing the compress option, you may want to match
|
||||
"`!compress*`" if you also want to allow the `--compress-level` option.
|
||||
|
||||
Note that the "write-devices" option is refused by default, but can be
|
||||
explicitly accepted with "`!write-devices`". The options "log-file" and
|
||||
"log-file-format" are forcibly refused and cannot be accepted.
|
||||
Note that the "copy-devices" & "write-devices" options are refused by
|
||||
default, but they can be explicitly accepted with "`!copy-devices`" and/or
|
||||
"`!write-devices`". The options "log-file" and "log-file-format" are
|
||||
forcibly refused and cannot be accepted.
|
||||
|
||||
Here are all the options that are not matched by wild-cards:
|
||||
|
||||
@@ -943,12 +978,12 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
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.
|
||||
- `--sender`: Use "[write only](#)" parameter instead of refusing this.
|
||||
- `--dry-run`, `-n`: Who would want to disable this?
|
||||
- `--protect-args`, `-s`: This actually makes transfers safer.
|
||||
- `--seclude-args`, `-s`: Is the oldest arg-protection method.
|
||||
- `--from0`, `-0`: Makes it easier to accept/refuse `--files-from` without
|
||||
affecting this helpful modifier.
|
||||
- `--iconv`: This is auto-disabled based on "charset" parameter.
|
||||
- `--iconv`: This is auto-disabled based on "[charset](#)" parameter.
|
||||
- `--no-iconv`: Most transfers use this option.
|
||||
- `--checksum-seed`: Is a fairly rare, safe option.
|
||||
- `--write-devices`: Is non-wild but also auto-disabled.
|
||||
@@ -988,7 +1023,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
_not_ displayed if the script returns success. The other programs cannot
|
||||
send any text to the user. All output except for the `pre-xfer exec`
|
||||
stdout goes to the corresponding daemon's stdout/stderr, which is typically
|
||||
discarded. See the `--no-detatch` option for a way to see the daemon's
|
||||
discarded. See the `--no-detach` option for a way to see the daemon's
|
||||
output, which can assist with debugging.
|
||||
|
||||
Note that the `early exec` command runs before any part of the transfer
|
||||
@@ -1038,7 +1073,7 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
**system()** call's default shell), and use RSYNC_NO_XFER_EXEC to disable
|
||||
both options completely.
|
||||
|
||||
# CONFIG DIRECTIVES
|
||||
## CONFIG DIRECTIVES
|
||||
|
||||
There are currently two config directives available that allow a config file to
|
||||
incorporate the contents of other files: `&include` and `&merge`. Both allow
|
||||
@@ -1093,7 +1128,7 @@ This would merge any `/etc/rsyncd.d/*.inc` files (for global values that should
|
||||
stay in effect), and then include any `/etc/rsyncd.d/*.conf` files (defining
|
||||
modules without any global-value cross-talk).
|
||||
|
||||
# AUTHENTICATION STRENGTH
|
||||
## AUTHENTICATION STRENGTH
|
||||
|
||||
The authentication protocol used in rsync is a 128 bit MD4 based challenge
|
||||
response system. This is fairly weak protection, though (with at least one
|
||||
@@ -1108,18 +1143,18 @@ authentication is provided. Use ssh as the transport if you want encryption.
|
||||
You can also make use of SSL/TLS encryption if you put rsync behind an
|
||||
SSL proxy.
|
||||
|
||||
# SSL/TLS Daemon Setup
|
||||
## SSL/TLS Daemon Setup
|
||||
|
||||
When setting up an rsync daemon for access via SSL/TLS, you will need to
|
||||
configure a proxy (such as haproxy or nginx) as the front-end that handles the
|
||||
encryption.
|
||||
configure a TCP proxy (such as haproxy or nginx) as the front-end that handles
|
||||
the encryption.
|
||||
|
||||
- You should limit the access to the backend-rsyncd port to only allow the
|
||||
proxy to connect. If it is on the same host as the proxy, then configuring
|
||||
it to only listen on localhost is a good idea.
|
||||
- You should consider turning on the `proxy protocol` parameter if your proxy
|
||||
supports sending that information. The examples below assume that this is
|
||||
enabled.
|
||||
- You should consider turning on the `proxy protocol` rsync-daemon parameter if
|
||||
your proxy supports sending that information. The examples below assume that
|
||||
this is enabled.
|
||||
|
||||
An example haproxy setup is as follows:
|
||||
|
||||
@@ -1146,14 +1181,14 @@ An example nginx proxy setup is as follows:
|
||||
> ssl_certificate_key /etc/letsencrypt/example.com/privkey.pem;
|
||||
>
|
||||
> proxy_pass localhost:873;
|
||||
> proxy_protocol on; # Requires "proxy protocol = true"
|
||||
> proxy_protocol on; # Requires rsyncd.conf "proxy protocol = true"
|
||||
> proxy_timeout 1m;
|
||||
> proxy_connect_timeout 5s;
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
|
||||
# EXAMPLES
|
||||
## DAEMON CONFIG EXAMPLES
|
||||
|
||||
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
|
||||
`/home/ftp` would be:
|
||||
@@ -1202,46 +1237,41 @@ The /etc/rsyncd.secrets file would look something like this:
|
||||
> tridge:mypass
|
||||
> susan:herpass
|
||||
|
||||
# FILES
|
||||
## FILES
|
||||
|
||||
/etc/rsyncd.conf or rsyncd.conf
|
||||
|
||||
# SEE ALSO
|
||||
## SEE ALSO
|
||||
|
||||
**rsync**(1), **rsync-ssl**(1)
|
||||
[**rsync**(1)](rsync.1), [**rsync-ssl**(1)](rsync-ssl.1)
|
||||
|
||||
# BUGS
|
||||
## BUGS
|
||||
|
||||
Please report bugs! The rsync bug tracking system is online at
|
||||
<https://rsync.samba.org/>.
|
||||
|
||||
# VERSION
|
||||
## VERSION
|
||||
|
||||
This man page is current for version @VERSION@ of rsync.
|
||||
This manpage is current for version @VERSION@ of rsync.
|
||||
|
||||
# CREDITS
|
||||
## CREDITS
|
||||
|
||||
rsync is distributed under the GNU General Public License. See the file
|
||||
COPYING for details.
|
||||
Rsync is distributed under the GNU General Public License. See the file
|
||||
[COPYING](COPYING) for details.
|
||||
|
||||
The primary ftp site for rsync is <ftp://rsync.samba.org/pub/rsync>
|
||||
An rsync web site is available at <https://rsync.samba.org/> and its github
|
||||
project is <https://github.com/WayneD/rsync>.
|
||||
|
||||
A web site is available at <https://rsync.samba.org/>.
|
||||
|
||||
We would be delighted to hear from you if you like this program.
|
||||
|
||||
This program uses the zlib compression library written by Jean-loup Gailly and
|
||||
Mark Adler.
|
||||
|
||||
# THANKS
|
||||
## THANKS
|
||||
|
||||
Thanks to Warren Stanley for his original idea and patch for the rsync daemon.
|
||||
Thanks to Karsten Thygesen for his many suggestions and documentation!
|
||||
|
||||
# AUTHOR
|
||||
## AUTHOR
|
||||
|
||||
rsync was written by Andrew Tridgell and Paul Mackerras. Many people have
|
||||
later contributed to it.
|
||||
Rsync was originally written by Andrew Tridgell and Paul Mackerras. Many
|
||||
people have later contributed to it. It is currently maintained by Wayne
|
||||
Davison.
|
||||
|
||||
Mailing lists for support and development are available at
|
||||
<https://lists.samba.org/>.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
# Copyright (C) 2003-2021 Wayne Davison
|
||||
# Copyright (C) 2003-2022 Wayne Davison
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version
|
||||
@@ -238,7 +238,7 @@ failed=0
|
||||
# failure to aid investigation. We don't remove the testtmp subdir at
|
||||
# the end so that it can be configured as a symlink to a filesystem that
|
||||
# has ACLs and xattr support enabled (if desired).
|
||||
scratchbase="$TOOLDIR"/testtmp
|
||||
scratchbase="${scratchbase:-$TOOLDIR}"/testtmp
|
||||
echo " scratchbase=$scratchbase"
|
||||
[ -d "$scratchbase" ] || mkdir "$scratchbase"
|
||||
|
||||
|
||||
21
sender.c
21
sender.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,6 +25,7 @@
|
||||
extern int do_xfers;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int local_server;
|
||||
extern int inc_recurse;
|
||||
extern int log_before_transfer;
|
||||
extern int stdout_format_has_i;
|
||||
@@ -37,6 +38,7 @@ extern int io_error;
|
||||
extern int flist_eof;
|
||||
extern int whole_file;
|
||||
extern int allowed_lull;
|
||||
extern int copy_devices;
|
||||
extern int preserve_xattrs;
|
||||
extern int protocol_version;
|
||||
extern int remove_source_files;
|
||||
@@ -50,6 +52,7 @@ extern int file_old_total;
|
||||
extern BOOL want_progress_now;
|
||||
extern struct stats stats;
|
||||
extern struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
extern char num_dev_ino_buf[4 + 8 + 8];
|
||||
|
||||
BOOL extra_flist_sending_enabled;
|
||||
|
||||
@@ -143,6 +146,13 @@ void successful_send(int ndx)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (local_server
|
||||
&& (int64)st.st_dev == IVAL64(num_dev_ino_buf, 4)
|
||||
&& (int64)st.st_ino == IVAL64(num_dev_ino_buf, 4 + 8)) {
|
||||
rprintf(FERROR_XFER, "ERROR: Skipping sender remove of destination file: %s\n", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (st.st_size != F_LENGTH(file) || st.st_mtime != file->modtime
|
||||
#ifdef ST_MTIME_NSEC
|
||||
|| (NSEC_BUMP(file) && (uint32)st.ST_MTIME_NSEC != F_MOD_NSEC(file))
|
||||
@@ -366,6 +376,15 @@ void send_files(int f_in, int f_out)
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
if (IS_DEVICE(st.st_mode)) {
|
||||
if (!copy_devices) {
|
||||
rprintf(FERROR, "attempt to copy device contents without --copy-devices\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (st.st_size == 0)
|
||||
st.st_size = get_device_size(fd, fname);
|
||||
}
|
||||
|
||||
if (append_mode > 0 && st.st_size < F_LENGTH(file)) {
|
||||
rprintf(FWARNING, "skipped diminished file: %s\n",
|
||||
full_fname(fname));
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_ROLL_ASM /* { */
|
||||
|
||||
#define CHAR_OFFSET 0 /* Keep this the same as rsync.h, which isn't likely to change. */
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define get_checksum1_avx2 _get_checksum1_avx2
|
||||
#define get_checksum1_avx2_asm _get_checksum1_avx2_asm
|
||||
#endif
|
||||
|
||||
.intel_syntax noprefix
|
||||
.text
|
||||
|
||||
.p2align 5
|
||||
.globl get_checksum1_avx2
|
||||
.globl get_checksum1_avx2_asm
|
||||
|
||||
# rdi=*buf, esi=len, edx=i, rcx= *ps1, r8= *ps2
|
||||
get_checksum1_avx2:
|
||||
get_checksum1_avx2_asm:
|
||||
vmovd xmm6,[rcx] # load *ps1
|
||||
lea eax, [rsi-128] # at least 128 bytes to process?
|
||||
cmp edx, eax
|
||||
@@ -167,3 +173,5 @@ get_checksum1_avx2:
|
||||
.byte 3
|
||||
.byte 2
|
||||
.byte 1
|
||||
|
||||
#endif /* } USE_ROLL_ASM */
|
||||
|
||||
@@ -51,12 +51,12 @@
|
||||
* GCC 4.x are not supported to ease configure.ac logic.
|
||||
*/
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef __cplusplus
|
||||
#ifdef __x86_64__ /* { */
|
||||
#ifdef __cplusplus /* { */
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#ifdef HAVE_SIMD
|
||||
#ifdef USE_ROLL_SIMD /* { */
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
@@ -85,6 +85,9 @@ typedef long long __m256i_u __attribute__((__vector_size__(32), __may_alias__, _
|
||||
#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))
|
||||
|
||||
#ifndef USE_ROLL_ASM
|
||||
__attribute__ ((target("default"))) MVSTATIC int32 get_checksum1_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2) { return i; }
|
||||
#endif
|
||||
__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; }
|
||||
|
||||
@@ -245,7 +248,7 @@ __attribute__ ((target("sse2"))) MVSTATIC int32 get_checksum1_sse2_32(schar* buf
|
||||
|
||||
// (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_1 = SSE2_MADDUBS_EPI16(mul_const, in8_1);
|
||||
__m128i mul_add16_2 = SSE2_MADDUBS_EPI16(mul_const, in8_2);
|
||||
|
||||
// s2 += 32*s1
|
||||
@@ -310,7 +313,127 @@ __attribute__ ((target("sse2"))) MVSTATIC int32 get_checksum1_sse2_32(schar* buf
|
||||
return i;
|
||||
}
|
||||
|
||||
extern "C" __attribute__ ((target("avx2"))) int32 get_checksum1_avx2(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2);
|
||||
#ifdef USE_ROLL_ASM /* { */
|
||||
|
||||
extern "C" __attribute__ ((target("avx2"))) int32 get_checksum1_avx2_asm(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2);
|
||||
|
||||
#else /* } { */
|
||||
|
||||
/*
|
||||
AVX2 loop per 64 bytes:
|
||||
int16 t1[16];
|
||||
int16 t2[16];
|
||||
for (int j = 0; j < 16; j++) {
|
||||
t1[j] = buf[j*4 + i] + buf[j*4 + i+1] + buf[j*4 + i+2] + buf[j*4 + i+3];
|
||||
t2[j] = 4*buf[j*4 + i] + 3*buf[j*4 + i+1] + 2*buf[j*4 + i+2] + buf[j*4 + i+3];
|
||||
}
|
||||
s2 += 64*s1 + (uint32)(
|
||||
60*t1[0] + 56*t1[1] + 52*t1[2] + 48*t1[3] + 44*t1[4] + 40*t1[5] + 36*t1[6] + 32*t1[7] + 28*t1[8] + 24*t1[9] + 20*t1[10] + 16*t1[11] + 12*t1[12] + 8*t1[13] + 4*t1[14] +
|
||||
t2[0] + t2[1] + t2[2] + t2[3] + t2[4] + t2[5] + t2[6] + t2[7] + t2[8] + t2[9] + t2[10] + t2[11] + t2[12] + t2[13] + t2[14] + t2[15]
|
||||
) + 2080*CHAR_OFFSET;
|
||||
s1 += (uint32)(t1[0] + t1[1] + t1[2] + t1[3] + t1[4] + t1[5] + t1[6] + t1[7] + t1[8] + t1[9] + t1[10] + t1[11] + t1[12] + t1[13] + t1[14] + t1[15]) +
|
||||
64*CHAR_OFFSET;
|
||||
*/
|
||||
|
||||
__attribute__ ((target("avx2"))) MVSTATIC int32 get_checksum1_avx2_64(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
if (len > 64) {
|
||||
|
||||
uint32 x[4] = {0};
|
||||
__m128i ss1 = _mm_cvtsi32_si128(*ps1);
|
||||
__m128i ss2 = _mm_cvtsi32_si128(*ps2);
|
||||
|
||||
const char mul_t1_buf[16] = {60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0};
|
||||
__m128i tmp = _mm_load_si128((__m128i*) mul_t1_buf);
|
||||
__m256i mul_t1 = _mm256_cvtepu8_epi16(tmp);
|
||||
__m256i mul_const = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(4 | (3 << 8) | (2 << 16) | (1 << 24)));
|
||||
__m256i mul_one;
|
||||
mul_one = _mm256_abs_epi8(_mm256_cmpeq_epi16(mul_one,mul_one)); // set all vector elements to 1
|
||||
|
||||
for (; i < (len-64); i+=64) {
|
||||
// Load ... 4*[int8*16]
|
||||
__m256i in8_1, in8_2;
|
||||
__m128i in8_1_low, in8_2_low, in8_1_high, in8_2_high;
|
||||
in8_1_low = _mm_loadu_si128((__m128i_u*)&buf[i]);
|
||||
in8_2_low = _mm_loadu_si128((__m128i_u*)&buf[i+16]);
|
||||
in8_1_high = _mm_loadu_si128((__m128i_u*)&buf[i+32]);
|
||||
in8_2_high = _mm_loadu_si128((__m128i_u*)&buf[i+48]);
|
||||
in8_1 = _mm256_inserti128_si256(_mm256_castsi128_si256(in8_1_low), in8_1_high,1);
|
||||
in8_2 = _mm256_inserti128_si256(_mm256_castsi128_si256(in8_2_low), in8_2_high,1);
|
||||
|
||||
// (1*buf[i] + 1*buf[i+1]), (1*buf[i+2], 1*buf[i+3]), ... 2*[int16*8]
|
||||
// Fastest, even though multiply by 1
|
||||
__m256i add16_1 = _mm256_maddubs_epi16(mul_one, in8_1);
|
||||
__m256i add16_2 = _mm256_maddubs_epi16(mul_one, in8_2);
|
||||
|
||||
// (4*buf[i] + 3*buf[i+1]), (2*buf[i+2], buf[i+3]), ... 2*[int16*8]
|
||||
__m256i mul_add16_1 = _mm256_maddubs_epi16(mul_const, in8_1);
|
||||
__m256i mul_add16_2 = _mm256_maddubs_epi16(mul_const, in8_2);
|
||||
|
||||
// s2 += 64*s1
|
||||
ss2 = _mm_add_epi32(ss2, _mm_slli_epi32(ss1, 6));
|
||||
|
||||
// [sum(t1[0]..t1[7]), X, X, X] [int32*4]; faster than multiple _mm_hadds_epi16
|
||||
__m256i sum_add32 = _mm256_add_epi16(add16_1, add16_2);
|
||||
sum_add32 = _mm256_add_epi16(sum_add32, _mm256_srli_epi32(sum_add32, 16));
|
||||
sum_add32 = _mm256_add_epi16(sum_add32, _mm256_srli_si256(sum_add32, 4));
|
||||
sum_add32 = _mm256_add_epi16(sum_add32, _mm256_srli_si256(sum_add32, 8));
|
||||
|
||||
// [sum(t2[0]..t2[7]), X, X, X] [int32*4]; faster than multiple _mm_hadds_epi16
|
||||
__m256i sum_mul_add32 = _mm256_add_epi16(mul_add16_1, mul_add16_2);
|
||||
sum_mul_add32 = _mm256_add_epi16(sum_mul_add32, _mm256_srli_epi32(sum_mul_add32, 16));
|
||||
sum_mul_add32 = _mm256_add_epi16(sum_mul_add32, _mm256_srli_si256(sum_mul_add32, 4));
|
||||
sum_mul_add32 = _mm256_add_epi16(sum_mul_add32, _mm256_srli_si256(sum_mul_add32, 8));
|
||||
|
||||
// s1 += t1[0] + t1[1] + t1[2] + t1[3] + t1[4] + t1[5] + t1[6] + t1[7]
|
||||
__m128i sum_add32_hi = _mm256_extracti128_si256(sum_add32, 0x1);
|
||||
ss1 = _mm_add_epi32(ss1, _mm256_castsi256_si128(sum_add32));
|
||||
ss1 = _mm_add_epi32(ss1, sum_add32_hi);
|
||||
|
||||
// s2 += t2[0] + t2[1] + t2[2] + t2[3] + t2[4] + t2[5] + t2[6] + t2[7]
|
||||
__m128i sum_mul_add32_hi = _mm256_extracti128_si256(sum_mul_add32, 0x1);
|
||||
ss2 = _mm_add_epi32(ss2, _mm256_castsi256_si128(sum_mul_add32));
|
||||
ss2 = _mm_add_epi32(ss2, sum_mul_add32_hi);
|
||||
|
||||
// [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
|
||||
__m256i add16 = _mm256_hadds_epi16(add16_1, add16_2);
|
||||
|
||||
// [t1[0], t1[1], ...] -> [t1[0]*28 + t1[1]*24, ...] [int32*4]
|
||||
__m256i mul32 = _mm256_madd_epi16(add16, mul_t1);
|
||||
|
||||
// [sum(mul32), X, X, X] [int32*4]; faster than multiple _mm_hadd_epi32
|
||||
mul32 = _mm256_add_epi32(mul32, _mm256_srli_si256(mul32, 4));
|
||||
mul32 = _mm256_add_epi32(mul32, _mm256_srli_si256(mul32, 8));
|
||||
// prefetch 2 cacheline ahead
|
||||
_mm_prefetch(&buf[i + 160], _MM_HINT_T0);
|
||||
|
||||
// s2 += 28*t1[0] + 24*t1[1] + 20*t1[2] + 16*t1[3] + 12*t1[4] + 8*t1[5] + 4*t1[6]
|
||||
__m128i mul32_hi = _mm256_extracti128_si256(mul32, 0x1);
|
||||
ss2 = _mm_add_epi32(ss2, _mm256_castsi256_si128(mul32));
|
||||
ss2 = _mm_add_epi32(ss2, mul32_hi);
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#endif /* } !USE_ROLL_ASM */
|
||||
|
||||
static int32 get_checksum1_default_1(schar* buf, int32 len, int32 i, uint32* ps1, uint32* ps2)
|
||||
{
|
||||
@@ -338,7 +461,11 @@ static inline uint32 get_checksum1_cpp(char *buf1, int32 len)
|
||||
uint32 s2 = 0;
|
||||
|
||||
// multiples of 64 bytes using AVX2 (if available)
|
||||
i = get_checksum1_avx2((schar*)buf1, len, i, &s1, &s2);
|
||||
#ifdef USE_ROLL_ASM
|
||||
i = get_checksum1_avx2_asm((schar*)buf1, len, i, &s1, &s2);
|
||||
#else
|
||||
i = get_checksum1_avx2_64((schar*)buf1, len, i, &s1, &s2);
|
||||
#endif
|
||||
|
||||
// multiples of 32 bytes using SSSE3 (if available)
|
||||
i = get_checksum1_ssse3_32((schar*)buf1, len, i, &s1, &s2);
|
||||
@@ -407,7 +534,11 @@ int main() {
|
||||
benchmark("Raw-C", get_checksum1_default_1, (schar*)buf, BLOCK_LEN);
|
||||
benchmark("SSE2", get_checksum1_sse2_32, (schar*)buf, BLOCK_LEN);
|
||||
benchmark("SSSE3", get_checksum1_ssse3_32, (schar*)buf, BLOCK_LEN);
|
||||
benchmark("AVX2", get_checksum1_avx2, (schar*)buf, BLOCK_LEN);
|
||||
#ifdef USE_ROLL_ASM
|
||||
benchmark("AVX2-ASM", get_checksum1_avx2_asm, (schar*)buf, BLOCK_LEN);
|
||||
#else
|
||||
benchmark("AVX2", get_checksum1_avx2_64, (schar*)buf, BLOCK_LEN);
|
||||
#endif
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
@@ -417,6 +548,6 @@ int main() {
|
||||
#pragma clang optimize on
|
||||
#endif /* BENCHMARK_SIMD_CHECKSUM1 */
|
||||
|
||||
#endif /* HAVE_SIMD */
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __x86_64__ */
|
||||
#endif /* } USE_ROLL_SIMD */
|
||||
#endif /* } __cplusplus */
|
||||
#endif /* } __x86_64__ */
|
||||
|
||||
@@ -1,42 +1,63 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
#!/usr/bin/env python3
|
||||
# This script finds all CVS/Entries files in the current directory and below
|
||||
# and creates a local .cvsinclude file with non-inherited rules including each
|
||||
# checked-in file. Then, use this option whenever using --cvs-exclude (-C):
|
||||
#
|
||||
# -f ': .cvsinclude'
|
||||
# -f ': .cvsinclude'
|
||||
#
|
||||
# That ensures that all checked-in files/dirs are included in the transfer.
|
||||
# (You could alternately put ": .cvsinclude" into an .rsync-filter file and
|
||||
# use the -F option, which is easier to type.)
|
||||
#
|
||||
# The downside is that you need to remember to re-run cvs2includes whenever
|
||||
# you add a new file to the project.
|
||||
use strict;
|
||||
# CVS gets an added or removed file. Maybe just run it before every copy.
|
||||
|
||||
open(FIND, 'find . -name CVS -type d |') or die $!;
|
||||
while (<FIND>) {
|
||||
chomp;
|
||||
s#^\./##;
|
||||
import os, argparse
|
||||
|
||||
my $entries = "$_/Entries";
|
||||
s/CVS$/.cvsinclude/;
|
||||
my $filter = $_;
|
||||
INC_NAME = '.cvsinclude'
|
||||
|
||||
open(ENTRIES, $entries) or die "Unable to open $entries: $!\n";
|
||||
my @includes;
|
||||
while (<ENTRIES>) {
|
||||
push(@includes, $1) if m#/(.+?)/#;
|
||||
}
|
||||
close ENTRIES;
|
||||
if (@includes) {
|
||||
open(FILTER, ">$filter") or die "Unable to write $filter: $!\n";
|
||||
print FILTER map "+ /$_\n", @includes;
|
||||
close FILTER;
|
||||
print "Updated $filter\n";
|
||||
} elsif (-f $filter) {
|
||||
unlink($filter);
|
||||
print "Removed $filter\n";
|
||||
}
|
||||
}
|
||||
close FIND;
|
||||
def main():
|
||||
if args.dir:
|
||||
os.chdir(args.dir)
|
||||
|
||||
cvs_includes = set()
|
||||
for root, dirs, files in os.walk('.'):
|
||||
if INC_NAME in files:
|
||||
cvs_includes.add((root + '/' + INC_NAME)[2:])
|
||||
if root.endswith('/CVS') and 'Entries' in files:
|
||||
entries = root[2:] + '/Entries'
|
||||
includes = [ ]
|
||||
with open(entries) as fh:
|
||||
for line in fh:
|
||||
if line.startswith(('/', 'D/')):
|
||||
includes.append(line.split('/', 2)[1])
|
||||
if includes:
|
||||
inc = root[2:-3] + INC_NAME
|
||||
cvs_includes.discard(inc)
|
||||
try:
|
||||
with open(inc) as fh:
|
||||
old_txt = fh.read()
|
||||
except OSError:
|
||||
old_txt = ''
|
||||
txt = ''.join(f"+ /{x}\n" for x in includes)
|
||||
if txt == old_txt:
|
||||
print("Unchanged", inc)
|
||||
else:
|
||||
print("Updating", inc)
|
||||
with open(inc, 'w') as fh:
|
||||
fh.write(txt)
|
||||
dirs.sort()
|
||||
|
||||
for inc in sorted(cvs_includes):
|
||||
print("Removing", inc)
|
||||
os.unlink(inc)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=f"Transform CVS/Entries into {INC_NAME} files.", add_help=False)
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument("dir", nargs='?', help="The top CVS dir. Defaults to the current directory.")
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
|
||||
@@ -1,27 +1,37 @@
|
||||
#!/usr/bin/env perl
|
||||
# This script takes an input of filenames and outputs a set of
|
||||
# include/exclude directives that can be used by rsync to copy
|
||||
# just the indicated files using an --exclude-from=FILE option.
|
||||
use strict;
|
||||
#!/usr/bin/env python3
|
||||
# This script takes an input of filenames and outputs a set of include/exclude
|
||||
# directives that can be used by rsync to copy just the indicated files using
|
||||
# an --exclude-from=FILE or -f'. FILE' option. To be able to delete files on
|
||||
# the receiving side, either use --delete-excluded or change the exclude (-)
|
||||
# rules to hide filter rules (H) that only affect the sending side.
|
||||
|
||||
my %hash;
|
||||
import os, fileinput, argparse
|
||||
|
||||
while (<>) {
|
||||
chomp;
|
||||
s#^/+##;
|
||||
my $path = '/';
|
||||
while (m#([^/]+/)/*#g) {
|
||||
$path .= $1;
|
||||
print "+ $path\n" unless $hash{$path}++;
|
||||
}
|
||||
if (m#([^/]+)$#) {
|
||||
print "+ $path$1\n";
|
||||
} else {
|
||||
delete $hash{$path};
|
||||
}
|
||||
}
|
||||
def main():
|
||||
paths = set()
|
||||
for line in fileinput.input(args.files):
|
||||
dirs = line.strip().lstrip('/').split('/')
|
||||
if not dirs:
|
||||
continue
|
||||
for j in range(1, len(dirs)):
|
||||
if dirs[j] == '':
|
||||
continue
|
||||
path = '/' + '/'.join(dirs[:j]) + '/'
|
||||
if path not in paths:
|
||||
print('+', path)
|
||||
paths.add(path)
|
||||
print('+', '/' + '/'.join(dirs))
|
||||
|
||||
foreach (sort keys %hash) {
|
||||
print "- $_*\n";
|
||||
}
|
||||
print "- /*\n";
|
||||
for path in sorted(paths):
|
||||
print('-', path + '*')
|
||||
print('-', '/*')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Transform a list of files into a set of include/exclude rules.", add_help=False)
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument("files", metavar="FILE", default='-', nargs='*', help="The file(s) that hold the pathnames to translate. Defaults to stdin.")
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
|
||||
@@ -38,7 +38,7 @@ def main():
|
||||
print_line(fn, mtime, mtime)
|
||||
ls.discard(fn)
|
||||
|
||||
cmd = git + 'log -r --name-only --no-color --pretty=raw --no-renames -z'.split()
|
||||
cmd = git + 'log -r --name-only --format=%x00commit%x20%H%n%x00commit_time%x20%ct%n --no-renames -z'.split()
|
||||
if args.tree:
|
||||
cmd.append(args.tree)
|
||||
cmd += ['--'] + args.files
|
||||
@@ -46,7 +46,7 @@ def main():
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, encoding='utf-8')
|
||||
for line in proc.stdout:
|
||||
line = line.strip()
|
||||
m = re.match(r'^committer .*? (\d+) [-+]\d+$', line)
|
||||
m = re.match(r'^\0commit_time (\d+)$', line)
|
||||
if m:
|
||||
commit_time = int(m[1])
|
||||
elif NULL_COMMIT_RE.search(line):
|
||||
|
||||
45
support/idmap
Executable file
45
support/idmap
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
# This helper script makes it easy to use a passwd or group file to map values
|
||||
# in a LOCAL transfer. For instance, if you mount a backup that does not have
|
||||
# the same passwd setup as the local machine, you can do a copy to/from the
|
||||
# backup area as follows and get the differing ID values mapped just like a
|
||||
# remote transfer to/from the backed-up machine would do:
|
||||
#
|
||||
# rsync -av --usermap=`idmap --to /mnt/backup/etc/passwd` \
|
||||
# --groupmap=`idmap --to /mnt/backup/etc/group` \
|
||||
# /some/src/ /mnt/backup/some/dest/
|
||||
#
|
||||
# rsync -av --usermap=`idmap --from /mnt/backup/etc/passwd` \
|
||||
# --groupmap=`idmap --from /mnt/backup/etc/group` \
|
||||
# /mnt/backup/some/src/ /some/dest/
|
||||
|
||||
import re, fileinput, argparse
|
||||
|
||||
NAME_ID_RE = re.compile(r'^(\w+):[^:]+:(\d+)')
|
||||
|
||||
def main():
|
||||
maps = [ ]
|
||||
for line in fileinput.input(args.files):
|
||||
m = NAME_ID_RE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
if args.to:
|
||||
pair = (m[1], m[2])
|
||||
else:
|
||||
pair = (m[2], m[1])
|
||||
maps.append(':'.join(pair))
|
||||
print(','.join(maps))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Output usermap or groupmap args for rsync.", add_help=False)
|
||||
action = parser.add_argument_group()
|
||||
action = parser.add_mutually_exclusive_group(required=True)
|
||||
action.add_argument("--from", action="store_true", help="Output the map for use on the sending side.")
|
||||
action.add_argument("--to", action="store_true", help="Output the map for use on the receiving side.")
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument("files", metavar="FILE", default='-', nargs='*', help="The file(s) that hold the name & id pairs. Defaults to stdin.")
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
93
support/json-rsync-version
Executable file
93
support/json-rsync-version
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys, argparse, subprocess, json
|
||||
|
||||
TWEAK_NAME = {
|
||||
'asm': 'asm_roll',
|
||||
'ASM': 'asm_roll',
|
||||
'hardlink_special': 'hardlink_specials',
|
||||
'protect_args': 'secluded_args',
|
||||
'protected_args': 'secluded_args',
|
||||
'SIMD': 'SIMD_roll',
|
||||
}
|
||||
|
||||
MOVE_OPTIM = set('asm_roll SIMD_roll'.split())
|
||||
|
||||
def main():
|
||||
if not args.rsync or args.rsync == '-':
|
||||
ver_out = sys.stdin.read().strip()
|
||||
else:
|
||||
ver_out = subprocess.check_output([args.rsync, '--version', '--version'], encoding='utf-8').strip()
|
||||
if ver_out.startswith('{'):
|
||||
print(ver_out)
|
||||
return
|
||||
info = { }
|
||||
misplaced_optims = { }
|
||||
for line in ver_out.splitlines():
|
||||
if line.startswith('rsync '):
|
||||
prog, vstr, ver, pstr, vstr2, proto = line.split()
|
||||
info['program'] = prog
|
||||
if ver.startswith('v'):
|
||||
ver = ver[1:]
|
||||
info[vstr] = ver
|
||||
if '.' not in proto:
|
||||
proto += '.0'
|
||||
else:
|
||||
proto = proto.replace('.PR', '.')
|
||||
info[pstr] = proto
|
||||
elif line.startswith('Copyright '):
|
||||
info['copyright'] = line[10:]
|
||||
elif line.startswith('Web site: '):
|
||||
info['url'] = line[10:]
|
||||
elif line.startswith(' '):
|
||||
if not saw_comma and ',' in line:
|
||||
saw_comma = True
|
||||
info[sect_name] = { }
|
||||
if saw_comma:
|
||||
for x in line.strip(' ,').split(', '):
|
||||
if ' ' in x:
|
||||
val, var = x.split(' ', 1)
|
||||
if val == 'no':
|
||||
val = False
|
||||
elif val.endswith('-bit'):
|
||||
var = var[:-1] + '_bits'
|
||||
val = int(val.split('-')[0])
|
||||
else:
|
||||
var = x
|
||||
val = True
|
||||
var = var.replace(' ', '_').replace('-', '_')
|
||||
if var in TWEAK_NAME:
|
||||
var = TWEAK_NAME[var]
|
||||
if sect_name[0] != 'o' and var in MOVE_OPTIM:
|
||||
misplaced_optims[var] = val
|
||||
else:
|
||||
info[sect_name][var] = val
|
||||
else:
|
||||
info[sect_name] += [ x for x in line.split() if not x.startswith('(') ]
|
||||
elif line == '':
|
||||
break
|
||||
else:
|
||||
sect_name = line.strip(' :').replace(' ', '_').lower()
|
||||
info[sect_name] = [ ]
|
||||
saw_comma = False
|
||||
for chk in 'capabilities optimizations'.split():
|
||||
if chk not in info:
|
||||
info[chk] = { }
|
||||
if misplaced_optims:
|
||||
info['optimizations'].update(misplaced_optims)
|
||||
for chk in 'checksum_list compress_list daemon_auth_list'.split():
|
||||
if chk not in info:
|
||||
info[chk] = [ ]
|
||||
info['license'] = 'GPLv3' if ver[0] == '3' else 'GPLv2'
|
||||
info['caveat'] = 'rsync comes with ABSOLUTELY NO WARRANTY'
|
||||
print(json.dumps(info))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Output rsync's version data in JSON format, even if the rsync doesn't support a native json-output method.", add_help=False)
|
||||
parser.add_argument('rsync', nargs='?', help="Specify an rsync command to run. Otherwise stdin is consumed.")
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
@@ -4,7 +4,8 @@
|
||||
# for testing or for running a local copy where the sender and the
|
||||
# receiver needs to use different options (e.g. --fake-super). If
|
||||
# we get a -l USER option, we try to use "sudo -u USER" to run the
|
||||
# command.
|
||||
# command. Supports only the hostnames "localhost" and "lh", with
|
||||
# the latter implying the --no-cd option.
|
||||
|
||||
user=''
|
||||
do_cd=y # Default path is user's home dir (just like ssh) unless host is "lh".
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# This helper script makes it easy to use a passwd or group file to map
|
||||
# values in a LOCAL transfer. For instance, if you mount a backup that
|
||||
# does not have the same passwd setup as the local machine, you can do
|
||||
# a copy FROM the backup area as follows and get the differing ID values
|
||||
# mapped just like a remote transfer FROM the backed-up machine would do:
|
||||
#
|
||||
# rsync -av --usermap=`mapfrom /mnt/backup/etc/passwd` \
|
||||
# --groupmap=`mapfrom /mnt/backup/etc/group` \
|
||||
# /mnt/backup/some/src/ /some/dest/
|
||||
|
||||
while (<>) {
|
||||
push @_, "$2:$1" if /^(\w+):[^:]+:(\d+)/;
|
||||
}
|
||||
print join(',', @_), "\n";
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# This helper script makes it easy to use a passwd or group file to map
|
||||
# values in a LOCAL transfer. For instance, if you mount a backup that
|
||||
# does not have the same passwd setup as the local machine, you can do
|
||||
# a copy TO the backup area as follows and get the differing ID values
|
||||
# mapped just like a remote transfer TO the backed-up machine would do:
|
||||
#
|
||||
# rsync -av --usermap=`mapto /mnt/backup/etc/passwd` \
|
||||
# --groupmap=`mapto /mnt/backup/etc/group` \
|
||||
# /some/src/ /mnt/backup/some/dest/
|
||||
|
||||
while (<>) {
|
||||
push @_, "$1:$2" if /^(\w+):[^:]+:(\d+)/;
|
||||
}
|
||||
print join(',', @_), "\n";
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env perl
|
||||
#!/usr/bin/env python3
|
||||
# This script takes a command-line arg of a source directory
|
||||
# that will be passed to rsync, and generates a set of excludes
|
||||
# that will exclude all mount points from the list. This is
|
||||
@@ -27,23 +27,33 @@
|
||||
# awk '{print $2}' /proc/mounts | grep -v '^/$' | \
|
||||
# rsync -avf 'merge,/- -' /dir host:/dest/
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd 'abs_path';
|
||||
import os, argparse
|
||||
|
||||
my $file = '/proc/mounts';
|
||||
my $dir = shift || '/';
|
||||
my $trailing_slash = $dir =~ m{./$} ? '/' : '';
|
||||
$dir = abs_path($dir) . $trailing_slash;
|
||||
$dir =~ s{([^/]*)$}{};
|
||||
my $trailing = $1;
|
||||
$trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
|
||||
$trailing .= '/' if $trailing ne '';
|
||||
MNT_FILE = '/proc/mounts';
|
||||
|
||||
open(IN, $file) or die "Unable to open $file: $!\n";
|
||||
while (<IN>) {
|
||||
$_ = (split)[1];
|
||||
next unless s{^\Q$dir$trailing\E}{}o && $_ ne '';
|
||||
print "- /$trailing$_\n";
|
||||
}
|
||||
close IN;
|
||||
def main():
|
||||
trailing_slash = '/' if args.path.endswith(('/', '/.')) and args.path != '/' else ''
|
||||
args.path = os.path.realpath(args.path) + trailing_slash
|
||||
parent_dir = os.path.dirname(args.path)
|
||||
trailing = os.path.basename(args.path)
|
||||
if not os.path.isdir(args.path):
|
||||
trailing = ''
|
||||
elif trailing != '':
|
||||
trailing += '/'
|
||||
want_path = os.path.join(parent_dir, trailing)
|
||||
wp_len = len(want_path)
|
||||
|
||||
with open(MNT_FILE) as fh:
|
||||
for line in fh:
|
||||
mnt_path = line.split()[1]
|
||||
if mnt_path.startswith(want_path) and mnt_path != want_path:
|
||||
print(f"- /{trailing}{mnt_path[wp_len:]}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Output mount points as rsync excludes.", add_help=False)
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument('path', metavar='PATH', nargs='?', default='/', help="Limit output to those within the PATH hierarchy.")
|
||||
args = parser.parse_args()
|
||||
main()
|
||||
|
||||
# vim: sw=4 et
|
||||
|
||||
@@ -21,7 +21,7 @@ LOGFILE = 'rrsync.log' # NOTE: the file must exist for a line to be appended!
|
||||
|
||||
# NOTE when disabling: check for both a short & long version of the option!
|
||||
|
||||
### START of options data produced by the cull_options script. ###
|
||||
### START of options data produced by the cull-options script. ###
|
||||
|
||||
# To disable a short-named option, add its letter to this string:
|
||||
short_disabled = 's'
|
||||
@@ -47,6 +47,7 @@ long_opts = {
|
||||
'compress-choice': 1,
|
||||
'compress-level': 1,
|
||||
'copy-dest': 2,
|
||||
'copy-devices': -1,
|
||||
'copy-unsafe-links': 0,
|
||||
'daemon': -1,
|
||||
'debug': 1,
|
||||
@@ -63,7 +64,7 @@ long_opts = {
|
||||
'files-from': 3,
|
||||
'force': 0,
|
||||
'from0': 0,
|
||||
'fsync': 2,
|
||||
'fsync': 0,
|
||||
'fuzzy': 0,
|
||||
'group': 0,
|
||||
'groupmap': 1,
|
||||
@@ -127,7 +128,7 @@ long_opts = {
|
||||
'write-devices': -1,
|
||||
}
|
||||
|
||||
### END of options data produced by the cull_options script. ###
|
||||
### END of options data produced by the cull-options script. ###
|
||||
|
||||
import os, sys, re, argparse, glob, socket, time, subprocess
|
||||
from argparse import RawTextHelpFormatter
|
||||
@@ -257,6 +258,9 @@ def main():
|
||||
|
||||
if args.munge:
|
||||
rsync_opts.append('--munge-links')
|
||||
|
||||
if args.no_overwrite:
|
||||
rsync_opts.append('--ignore-existing')
|
||||
|
||||
if not rsync_args:
|
||||
rsync_args = [ '.' ]
|
||||
@@ -360,9 +364,10 @@ if __name__ == '__main__':
|
||||
only_group = arg_parser.add_mutually_exclusive_group()
|
||||
only_group.add_argument('-ro', action='store_true', help="Allow only reading from the DIR. Implies -no-del and -no-lock.")
|
||||
only_group.add_argument('-wo', action='store_true', help="Allow only writing to the DIR.")
|
||||
arg_parser.add_argument('-munge', action='store_true', help="Enable rsync's --munge-links on the server side.")
|
||||
arg_parser.add_argument('-no-del', action='store_true', help="Disable rsync's --delete* and --remove* options.")
|
||||
arg_parser.add_argument('-no-lock', action='store_true', help="Avoid the single-run (per-user) lock check.")
|
||||
arg_parser.add_argument('-munge', action='store_true', help="Enable rsync's --munge-links on the server side.")
|
||||
arg_parser.add_argument('-no-overwrite', action='store_true', help="Prevent overwriting existing files by enforcing --ignore-existing")
|
||||
arg_parser.add_argument('-help', '-h', action='help', help="Output this help message and exit.")
|
||||
arg_parser.add_argument('dir', metavar='DIR', help="The restricted directory to use.")
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
@@ -1,18 +1,30 @@
|
||||
# NAME
|
||||
## NAME
|
||||
|
||||
rrsync - a script to setup restricted rsync users via ssh logins
|
||||
|
||||
# SYNOPSIS
|
||||
## SYNOPSIS
|
||||
|
||||
```
|
||||
rrsync [-ro|-rw] [-munge] [-no-del] DIR
|
||||
rrsync [-ro|-rw] [-munge] [-no-del] [-no-lock] [-no-overwrite] DIR
|
||||
```
|
||||
|
||||
# DESCRIPTION
|
||||
The single non-option argument specifies the restricted _DIR_ to use. It can be
|
||||
relative to the user's home directory or an absolute path.
|
||||
|
||||
The online version of this manpage (that includes cross-linking of topics)
|
||||
is available at <https://download.samba.org/pub/rsync/rrsync.1>.
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
A user's ssh login can be restricted to only allow the running of an rsync
|
||||
transfer in one of two easy ways: forcing the running of the rrsync script
|
||||
or forcing the running of an rsync daemon-over-ssh command.
|
||||
transfer in one of two easy ways:
|
||||
|
||||
* forcing the running of the rrsync script
|
||||
* forcing the running of an rsync daemon-over-ssh command.
|
||||
|
||||
Both of these setups use a feature of ssh that allows a command to be forced to
|
||||
run instead of an interactive shell. However, if the user's home shell is bash,
|
||||
please see [BASH SECURITY ISSUE](#) for a potential issue.
|
||||
|
||||
To use the rrsync script, edit the user's `~/.ssh/authorized_keys` file and add
|
||||
a prefix like one of the following (followed by a space) in front of each
|
||||
@@ -27,7 +39,7 @@ ssh-key line that should be restricted:
|
||||
Then, ensure that the rrsync script has your desired option restrictions. You
|
||||
may want to copy the script to a local bin dir with a unique name if you want
|
||||
to have multiple configurations. One or more rrsync options can be specified
|
||||
prior to the `DIR` if you want to further restrict the transfer.
|
||||
prior to the _DIR_ if you want to further restrict the transfer.
|
||||
|
||||
To use an rsync daemon setup, edit the user's `~/.ssh/authorized_keys` file and
|
||||
add a prefix like one of the following (followed by a space) in front of each
|
||||
@@ -39,41 +51,62 @@ ssh-key line that should be restricted:
|
||||
> ```
|
||||
|
||||
Then, ensure that the rsyncd.conf file is created with one or more module names
|
||||
with the appropriate path and option restrictions. If the `--config` option is
|
||||
omitted, it defaults to `~/rsyncd.conf`. See the `rsyncd.conf` man page for
|
||||
details of how to configure an rsync daemon.
|
||||
with the appropriate path and option restrictions. If rsync's
|
||||
[`--config`](rsync.1#dopt) option is omitted, it defaults to `~/rsyncd.conf`.
|
||||
See the [**rsyncd.conf**(5)](rsyncd.conf.5) manpage for details of how to
|
||||
configure an rsync daemon.
|
||||
|
||||
When using rrsync, there can be just one restricted dir per authorized key. A
|
||||
daemon setup, on the other hand, allows multiple module names inside the config
|
||||
file, each one with its own path setting.
|
||||
|
||||
The remainder of this man page is dedicated to using the rrsync script.
|
||||
The remainder of this manpage is dedicated to using the rrsync script.
|
||||
|
||||
# OPTION SUMMARY
|
||||
## OPTIONS
|
||||
|
||||
```
|
||||
-ro Allow only reading from the DIR. Implies -no-del.
|
||||
-wo Allow only writing to the DIR.
|
||||
-no-del Disable rsync's --delete* and --remove* options.
|
||||
-munge Enable rsync's --munge-links on the server side.
|
||||
-help, -h Output this help message and exit.
|
||||
```
|
||||
0. `-ro`
|
||||
|
||||
A single non-option argument specifies the restricted DIR to use. It can be
|
||||
relative to the user's home directory or an absolute path.
|
||||
Allow only reading from the DIR. Implies [`-no-del`](#opt) and
|
||||
[`-no-lock`](#opt).
|
||||
|
||||
# SECURITY RESTRICTIONS
|
||||
0. `-wo`
|
||||
|
||||
Allow only writing to the DIR.
|
||||
|
||||
0. `-munge`
|
||||
|
||||
Enable rsync's [`--munge-links`](rsync.1#opt) on the server side.
|
||||
|
||||
0. `-no-del`
|
||||
|
||||
Disable rsync's `--delete*` and `--remove*` options.
|
||||
|
||||
0. `-no-lock`
|
||||
|
||||
Avoid the single-run (per-user) lock check. Useful with [`-munge`](#opt).
|
||||
|
||||
0. `-no-overwrite`
|
||||
|
||||
Enforce `--ignore-existing` on the server. Prevents overwriting existing
|
||||
files when the server is the receiver.
|
||||
|
||||
0. `-help`, `-h`
|
||||
|
||||
Output this help message and exit.
|
||||
|
||||
## SECURITY RESTRICTIONS
|
||||
|
||||
The rrsync script validates the path arguments it is sent to try to restrict
|
||||
them to staying within the specified DIR.
|
||||
|
||||
The rrsync script rejects rsync's `--copy-links`` option (by default) so that a
|
||||
copy cannot dereference a symlink within the DIR to get to a file outside the
|
||||
DIR.
|
||||
The rrsync script rejects rsync's [`--copy-links`](rsync.1#opt) option (by
|
||||
default) so that a copy cannot dereference a symlink within the DIR to get to a
|
||||
file outside the DIR.
|
||||
|
||||
The rrsync script rejects rsync's `--protect-args` (`-s`) option because it
|
||||
would allow options to be sent to the server-side that the script could not
|
||||
check. If you want to support `--protect-args`, use a daemon-over-ssh setup.
|
||||
The rrsync script rejects rsync's [`--protect-args`](rsync.1#opt) (`-s`) option
|
||||
because it would allow options to be sent to the server-side that the script
|
||||
cannot check. If you want to support `--protect-args`, use a daemon-over-ssh
|
||||
setup.
|
||||
|
||||
The rrsync script accepts just a subset of rsync's options that the real rsync
|
||||
uses when running the server command. A few extra convenience options are also
|
||||
@@ -83,11 +116,56 @@ overrides.
|
||||
The script (or a copy of it) can be manually edited if you want it to customize
|
||||
the option handling.
|
||||
|
||||
# EXAMPLES
|
||||
## BASH SECURITY ISSUE
|
||||
|
||||
The `.ssh/authorized_keys` file might have lines in it like this:
|
||||
If your users have bash set as their home shell, bash may try to be overly
|
||||
helpful and ensure that the user's login bashrc files are run prior to
|
||||
executing the forced command. This can be a problem if the user can somehow
|
||||
update their home bashrc files, perhaps via the restricted copy, a shared home
|
||||
directory, or something similar.
|
||||
|
||||
One simple way to avoid the issue is to switch the user to a simpler shell,
|
||||
such as dash. When choosing the new home shell, make sure that you're not
|
||||
choosing bash in disguise, as it is unclear if it avoids the security issue.
|
||||
|
||||
Another potential fix is to ensure that the user's home directory is not a
|
||||
shared mount and that they have no means of copying files outside of their
|
||||
restricted directories. This may require you to force the enabling of symlink
|
||||
munging on the server side.
|
||||
|
||||
A future version of openssh may have a change to the handling of forced
|
||||
commands that allows it to avoid using the user's home shell.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
The `~/.ssh/authorized_keys` file might have lines in it like this:
|
||||
|
||||
> ```
|
||||
> command="rrsync client/logs" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAzG...
|
||||
> command="rrsync -ro results" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAmk...
|
||||
> ```
|
||||
|
||||
## FILES
|
||||
|
||||
~/.ssh/authorized_keys
|
||||
|
||||
## SEE ALSO
|
||||
|
||||
[**rsync**(1)](rsync.1), [**rsyncd.conf**(5)](rsyncd.conf.5)
|
||||
|
||||
## VERSION
|
||||
|
||||
This manpage is current for version @VERSION@ of rsync.
|
||||
|
||||
## CREDITS
|
||||
|
||||
rsync is distributed under the GNU General Public License. See the file
|
||||
[COPYING](COPYING) for details.
|
||||
|
||||
An rsync web site is available at <https://rsync.samba.org/> and its github
|
||||
project is <https://github.com/WayneD/rsync>.
|
||||
|
||||
## AUTHOR
|
||||
|
||||
The original rrsync perl script was written by Joe Smith. Many people have
|
||||
later contributed to it. The python version was created by Wayne Davison.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -247,7 +247,7 @@ int do_chmod(const char *path, mode_t mode)
|
||||
else if (errno != ENOTSUP)
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (S_ISLNK(mode)) {
|
||||
# if defined HAVE_SETATTRLIST
|
||||
@@ -257,7 +257,10 @@ int do_chmod(const char *path, mode_t mode)
|
||||
memset(&attrList, 0, sizeof attrList);
|
||||
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attrList.commonattr = ATTR_CMN_ACCESSMASK;
|
||||
code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
|
||||
if ((code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW)) == 0)
|
||||
break;
|
||||
if (errno == ENOTSUP)
|
||||
code = 1;
|
||||
# else
|
||||
code = 1;
|
||||
# endif
|
||||
|
||||
3
t_stub.c
3
t_stub.c
@@ -3,7 +3,7 @@
|
||||
* functions, so that module test harnesses can run standalone.
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2021 Wayne Davison
|
||||
* Copyright (C) 2003-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,7 +29,6 @@ int protect_args = 0;
|
||||
int module_id = -1;
|
||||
int relative_paths = 0;
|
||||
int module_dirlen = 0;
|
||||
int preserve_mtimes = 0;
|
||||
int preserve_xattrs = 0;
|
||||
int preserve_perms = 0;
|
||||
int preserve_executability = 0;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_fail() {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
# Test some foundational things.
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
RSYNC_RSH="$scratchdir/src/support/lsh.sh"
|
||||
export RSYNC_RSH
|
||||
|
||||
echo $0 running
|
||||
|
||||
@@ -12,3 +14,48 @@ $RSYNC --version || test_fail '--version output failed'
|
||||
$RSYNC --info=help || test_fail '--info=help output failed'
|
||||
|
||||
$RSYNC --debug=help || test_fail '--debug=help output failed'
|
||||
|
||||
weird_name="A weird)name"
|
||||
|
||||
mkdir "$fromdir"
|
||||
mkdir "$fromdir/$weird_name"
|
||||
|
||||
append_line() {
|
||||
echo "$1"
|
||||
echo "$1" >>"$fromdir/$weird_name/file"
|
||||
}
|
||||
|
||||
append_line test1
|
||||
checkit "$RSYNC -ai '$fromdir/' '$todir/'" "$fromdir" "$todir"
|
||||
|
||||
copy_weird() {
|
||||
checkit "$RSYNC $1 --rsync-path='$RSYNC' '$2$fromdir/$weird_name/' '$3$todir/$weird_name'" "$fromdir" "$todir"
|
||||
}
|
||||
|
||||
append_line test2
|
||||
copy_weird '-ai' 'lh:' ''
|
||||
|
||||
append_line test3
|
||||
copy_weird '-ai' '' 'lh:'
|
||||
|
||||
append_line test4
|
||||
copy_weird '-ais' 'lh:' ''
|
||||
|
||||
append_line test5
|
||||
copy_weird '-ais' '' 'lh:'
|
||||
|
||||
echo test6
|
||||
|
||||
touch "$fromdir/one" "$fromdir/two"
|
||||
(cd "$fromdir" && $RSYNC -ai --old-args --rsync-path="$RSYNC" lh:'one two' "$todir/")
|
||||
if [ ! -f "$todir/one" ] || [ ! -f "$todir/two" ]; then
|
||||
test_fail "old-args copy of 'one two' failed"
|
||||
fi
|
||||
|
||||
echo test7
|
||||
|
||||
rm "$todir/one" "$todir/two"
|
||||
(cd "$fromdir" && RSYNC_OLD_ARGS=1 $RSYNC -ai --rsync-path="$RSYNC" lh:'one two' "$todir/")
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
. $suitedir/rsync.fns
|
||||
|
||||
$RSYNC --version | grep "[, ] ACLs" >/dev/null || test_skipped "Rsync is configured without ACL support"
|
||||
$RSYNC -VV | grep '"ACLs": true' >/dev/null || test_skipped "Rsync is configured without ACL support"
|
||||
|
||||
case "$setfacl_nodef" in
|
||||
true) test_skipped "I don't know how to use your setfacl command" ;;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
. $suitedir/rsync.fns
|
||||
|
||||
$RSYNC --version | grep "[, ] ACLs" >/dev/null || test_skipped "Rsync is configured without ACL support"
|
||||
$RSYNC -VV | grep '"ACLs": true' >/dev/null || test_skipped "Rsync is configured without ACL support"
|
||||
|
||||
makepath "$fromdir/foo"
|
||||
echo something >"$fromdir/file1"
|
||||
|
||||
68
testsuite/alt-dest.test
Normal file
68
testsuite/alt-dest.test
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2004-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Test rsync handling of --compare-dest and similar options.
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
alt1dir="$tmpdir/alt1"
|
||||
alt2dir="$tmpdir/alt2"
|
||||
alt3dir="$tmpdir/alt3"
|
||||
|
||||
SSH="$scratchdir/src/support/lsh.sh"
|
||||
|
||||
# Build some files/dirs/links to copy
|
||||
|
||||
hands_setup
|
||||
|
||||
# Setup the alt and chk dirs
|
||||
$RSYNC -av --include=text --include='*/' --exclude='*' "$fromdir/" "$alt1dir/"
|
||||
$RSYNC -av --include=etc-ltr-list --include='*/' --exclude='*' "$fromdir/" "$alt2dir/"
|
||||
|
||||
# Create a side dir where there is a candidate destfile of the same name as a sourcefile
|
||||
echo "This is a test file" >"$fromdir/likely"
|
||||
|
||||
mkdir "$alt3dir"
|
||||
echo "This is a test file" >"$alt3dir/likely"
|
||||
|
||||
sleep 1
|
||||
touch "$fromdir/dir/text" "$fromdir/likely"
|
||||
|
||||
$RSYNC -av --exclude=/text --exclude=etc-ltr-list "$fromdir/" "$chkdir/"
|
||||
|
||||
# Let's do it!
|
||||
checkit "$RSYNC -avv --no-whole-file \
|
||||
--compare-dest='$alt1dir' --compare-dest='$alt2dir' \
|
||||
'$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
|
||||
rm -rf "$todir"
|
||||
checkit "$RSYNC -avv --no-whole-file \
|
||||
--copy-dest='$alt1dir' --copy-dest='$alt2dir' \
|
||||
'$fromdir/' '$todir/'" "$fromdir" "$todir"
|
||||
|
||||
# Test that copy_file() works correctly with tmpfiles
|
||||
for maybe_inplace in '' --inplace; do
|
||||
rm -rf "$todir"
|
||||
checkit "$RSYNC -av $maybe_inplace --copy-dest='$alt3dir' \
|
||||
'$fromdir/' '$todir/'" "$fromdir" "$todir"
|
||||
|
||||
for srchost in '' 'localhost:'; do
|
||||
if [ -z "$srchost" ]; then
|
||||
desthost='localhost:'
|
||||
else
|
||||
desthost=''
|
||||
fi
|
||||
|
||||
rm -rf "$todir"
|
||||
checkit "$RSYNC -ave '$SSH' --rsync-path='$RSYNC' $maybe_inplace \
|
||||
--copy-dest='$alt3dir' '$srchost$fromdir/' '$desthost$todir/'" \
|
||||
"$fromdir" "$todir"
|
||||
done
|
||||
done
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
$RSYNC --version | grep "[, ] atimes" >/dev/null || test_skipped "Rsync is configured without atimes support"
|
||||
$RSYNC -VV | grep '"atimes": true' >/dev/null || test_skipped "Rsync is configured without atimes support"
|
||||
|
||||
mkdir "$fromdir"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2004-2021 Wayne Davison
|
||||
# Copyright (C) 2004-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2004-2021 Wayne Davison
|
||||
# Copyright (C) 2004-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2004-2021 Wayne Davison
|
||||
# Copyright (C) 2004-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
case $0 in
|
||||
*fake*)
|
||||
$RSYNC --version | grep "[, ] xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
|
||||
$RSYNC -VV | grep '"xattrs": true' >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
|
||||
RSYNC="$RSYNC --fake-super"
|
||||
TLS_ARGS="$TLS_ARGS --fake-super"
|
||||
case "$HOST_OS" in
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2004-2021 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Test rsync handling of the --compare-dest option.
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
alt1dir="$tmpdir/alt1"
|
||||
alt2dir="$tmpdir/alt2"
|
||||
|
||||
# Build some files/dirs/links to copy
|
||||
|
||||
hands_setup
|
||||
|
||||
# Setup the alt and chk dirs
|
||||
$RSYNC -av --include=text --include='*/' --exclude='*' "$fromdir/" "$alt1dir/"
|
||||
$RSYNC -av --include=etc-ltr-list --include='*/' --exclude='*' "$fromdir/" "$alt2dir/"
|
||||
|
||||
sleep 1
|
||||
touch "$fromdir/dir/text"
|
||||
|
||||
$RSYNC -av --exclude=/text --exclude=etc-ltr-list "$fromdir/" "$chkdir/"
|
||||
|
||||
# Let's do it!
|
||||
checkit "$RSYNC -avv --no-whole-file \
|
||||
--compare-dest='$alt1dir' --compare-dest='$alt2dir' \
|
||||
'$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
checkit "$RSYNC -avv --no-whole-file \
|
||||
--copy-dest='$alt1dir' --copy-dest='$alt2dir' \
|
||||
'$fromdir/' '$todir/'" "$fromdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
$RSYNC --version | grep "[, ] crtimes" >/dev/null || test_skipped "Rsync is configured without crtimes support"
|
||||
$RSYNC -VV | grep '"crtimes": true' >/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"
|
||||
echo hiho >"$fromdir/foo"
|
||||
|
||||
touch -t 200101011111.11 "$fromdir"
|
||||
touch -t 200202022222.22 "$fromdir"
|
||||
|
||||
@@ -81,7 +81,7 @@ drwxr-xr-x DIR ####/##/## ##:##:## foo
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
|
||||
if $RSYNC --version | grep "[, ] atimes" >/dev/null; then
|
||||
if $RSYNC -VV | grep '"atimes": true' >/dev/null; then
|
||||
checkdiff "$RSYNC -rU localhost::test-from/f*" \
|
||||
"sed -e '$FILE_REPL' -e '$DIR_REPL' -e '$LS_REPL'" <<EOT
|
||||
drwxr-xr-x DIR ####/##/## ##:##:## foo
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2005-2021 Wayne Davison
|
||||
# Copyright (C) 2005-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
case $0 in
|
||||
*fake*)
|
||||
$RSYNC --version | grep "[, ] xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
|
||||
$RSYNC -VV | grep '"xattrs": true' >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
|
||||
RSYNC="$RSYNC --fake-super"
|
||||
TLS_ARGS="$TLS_ARGS --fake-super"
|
||||
case "$HOST_OS" in
|
||||
@@ -94,7 +94,7 @@ 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
|
||||
$RSYNC -VV | grep '"hardlink_specials": true' >/dev/null && CAN_HLINK_SPECIAL=yes || CAN_HLINK_SPECIAL=no
|
||||
|
||||
mkdir "$fromdir"
|
||||
mkdir "$todir"
|
||||
|
||||
1
testsuite/exclude-lsh.test
Symbolic link
1
testsuite/exclude-lsh.test
Symbolic link
@@ -0,0 +1 @@
|
||||
exclude.test
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2003-2021 Wayne Davison
|
||||
# Copyright (C) 2003-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
@@ -15,6 +15,19 @@
|
||||
CVSIGNORE='*.junk'
|
||||
export CVSIGNORE
|
||||
|
||||
case $0 in
|
||||
*-lsh.*)
|
||||
RSYNC_RSH="$scratchdir/src/support/lsh.sh"
|
||||
export RSYNC_RSH
|
||||
rpath=" --rsync-path='$RSYNC'"
|
||||
host='lh:'
|
||||
;;
|
||||
*)
|
||||
rpath=''
|
||||
host=''
|
||||
;;
|
||||
esac
|
||||
|
||||
# Build some files/dirs/links to copy
|
||||
|
||||
makepath "$fromdir/foo/down/to/you"
|
||||
@@ -106,8 +119,8 @@ home-cvs-exclude
|
||||
EOF
|
||||
|
||||
# Start with a check of --prune-empty-dirs:
|
||||
$RSYNC -av -f -_foo/too/ -f -_foo/down/ -f -_foo/and/ -f -_new/ "$fromdir/" "$chkdir/"
|
||||
checkit "$RSYNC -av --prune-empty-dirs '$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
$RSYNC -av --rsync-path="$RSYNC" -f -_foo/too/ -f -_foo/down/ -f -_foo/and/ -f -_new/ "$host$fromdir/" "$chkdir/"
|
||||
checkit "$RSYNC -av$rpath --prune-empty-dirs '$host$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
rm -rf "$todir"
|
||||
|
||||
# Add a directory symlink.
|
||||
@@ -120,7 +133,7 @@ touch "$scratchdir/up1/same-newness" "$scratchdir/up2/same-newness"
|
||||
touch "$scratchdir/up1/extra-src" "$scratchdir/up2/extra-dest"
|
||||
|
||||
# Create chkdir with what we expect to be excluded.
|
||||
checkit "$RSYNC -avv '$fromdir/' '$chkdir/'" "$fromdir" "$chkdir"
|
||||
checkit "$RSYNC -avv$rpath '$host$fromdir/' '$chkdir/'" "$fromdir" "$chkdir"
|
||||
sleep 1 # Ensures that the rm commands will tweak the directory times.
|
||||
rm -r "$chkdir"/foo/down
|
||||
rm -r "$chkdir"/mid/for/foo/and
|
||||
@@ -135,12 +148,12 @@ touch "$scratchdir/up1/src-newness" "$scratchdir/up2/dst-newness"
|
||||
|
||||
# Un-tweak the directory times in our first (weak) exclude test (though
|
||||
# it's a good test of the --existing option).
|
||||
$RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --existing --include='*/' --exclude='*' "$host$fromdir/" "$chkdir/"
|
||||
|
||||
# Now, test if rsync excludes the same files.
|
||||
|
||||
checkit "$RSYNC -avv --exclude-from='$excl' \
|
||||
--delete-during '$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
checkit "$RSYNC -avv$rpath --exclude-from='$excl' \
|
||||
--delete-during '$host$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
|
||||
# Modify the chk dir by removing cvs-ignored files and then tweaking the dir times.
|
||||
|
||||
@@ -150,13 +163,15 @@ rm "$chkdir"/bar/down/to/foo/*.junk
|
||||
rm "$chkdir"/bar/down/to/home-cvs-exclude
|
||||
rm "$chkdir"/mid/one-in-one-out
|
||||
|
||||
$RSYNC -av --existing --filter='exclude,! */' "$fromdir/" "$chkdir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --existing --filter='exclude,! */' "$host$fromdir/" "$chkdir/"
|
||||
|
||||
# Now, test if rsync excludes the same files, this time with --cvs-exclude
|
||||
# and --delete-excluded.
|
||||
|
||||
checkit "$RSYNC -avvC --filter='merge $excl' --delete-excluded \
|
||||
--delete-during '$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
# The -C option gets applied in a different order when pushing & pulling, so we instead
|
||||
# add the 2 --cvs-exclude filter rules (":C" & "-C") via -f to keep the order the same.
|
||||
checkit "$RSYNC -avv$rpath --filter='merge $excl' -f:C -f-C --delete-excluded \
|
||||
--delete-during '$host$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
|
||||
# Modify the chk dir for our merge-exclude test and then tweak the dir times.
|
||||
|
||||
@@ -165,19 +180,19 @@ rm "$chkdir"/bar/down/to/bar/baz/*.deep
|
||||
cp_touch "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
|
||||
cp_touch "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
|
||||
|
||||
$RSYNC -av --existing -f 'show .filt*' -f 'hide,! */' --del "$fromdir/" "$todir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --existing -f 'show .filt*' -f 'hide,! */' --del "$host$fromdir/" "$todir/"
|
||||
|
||||
echo retained >"$todir"/bar/down/to/bar/baz/nodel.deep
|
||||
cp_touch "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
|
||||
|
||||
$RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --existing --filter='-! */' "$host$fromdir/" "$chkdir/"
|
||||
|
||||
# Now, test if rsync excludes the same files, this time with a merge-exclude
|
||||
# file.
|
||||
|
||||
checkit "sed '/!/d' '$excl' |
|
||||
$RSYNC -avv -f dir-merge_.filt -f merge_- \
|
||||
--delete-during '$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
$RSYNC -avv$rpath -f dir-merge_.filt -f merge_- \
|
||||
--delete-during '$host$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
|
||||
# Remove the files that will be deleted.
|
||||
|
||||
@@ -188,14 +203,14 @@ rm "$chkdir"/bar/down/to/foo/.filt2
|
||||
rm "$chkdir"/bar/down/to/bar/.filt2
|
||||
rm "$chkdir"/mid/.filt
|
||||
|
||||
$RSYNC -av --protocol=28 --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --existing --include='*/' --exclude='*' "$host$fromdir/" "$chkdir/"
|
||||
|
||||
# Now, try the prior command with --delete-before and some side-specific
|
||||
# rules.
|
||||
|
||||
checkit "sed '/!/d' '$excl' |
|
||||
$RSYNC -avv -f :s_.filt -f .s_- -f P_nodel.deep \
|
||||
--delete-before '$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
$RSYNC -avv$rpath -f :s_.filt -f .s_- -f P_nodel.deep \
|
||||
--delete-before '$host$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
|
||||
# Next, we'll test some rule-restricted filter files.
|
||||
|
||||
@@ -206,26 +221,26 @@ cat >"$fromdir/bar/down/to/foo/.excl" <<EOF
|
||||
+ file3
|
||||
*.bak
|
||||
EOF
|
||||
$RSYNC -av --del "$fromdir/" "$chkdir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --del "$host$fromdir/" "$chkdir/"
|
||||
rm "$chkdir/bar/down/to/foo/file1.bak"
|
||||
rm "$chkdir/bar/down/to/foo/file3"
|
||||
rm "$chkdir/bar/down/to/foo/+ file3"
|
||||
$RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"
|
||||
$RSYNC -av --delete-excluded --exclude='*' "$fromdir/" "$todir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --existing --filter='-! */' "$host$fromdir/" "$chkdir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" --delete-excluded --exclude='*' "$host$fromdir/" "$todir/"
|
||||
|
||||
checkit "$RSYNC -avv -f dir-merge,-_.excl \
|
||||
'$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
checkit "$RSYNC -avv$rpath -f dir-merge,-_.excl \
|
||||
'$host$fromdir/' '$todir/'" "$chkdir" "$todir"
|
||||
|
||||
relative_opts='--relative --chmod=Du+w --copy-unsafe-links'
|
||||
$RSYNC -av $relative_opts "$fromdir/foo" "$chkdir/"
|
||||
$RSYNC -av --rsync-path="$RSYNC" $relative_opts "$host$fromdir/foo" "$chkdir/"
|
||||
rm -rf "$chkdir$fromdir/foo/down"
|
||||
$RSYNC -av $relative_opts --existing --filter='-! */' "$fromdir/foo" "$chkdir/"
|
||||
|
||||
checkit "$RSYNC -avv $relative_opts --exclude='$fromdir/foo/down' \
|
||||
'$fromdir/foo' '$todir'" "$chkdir$fromdir/foo" "$todir$fromdir/foo"
|
||||
checkit "$RSYNC -avv$rpath $relative_opts --exclude='$fromdir/foo/down' \
|
||||
'$host$fromdir/foo' '$todir'" "$chkdir$fromdir/foo" "$todir$fromdir/foo"
|
||||
|
||||
# Now we'll test the --update option.
|
||||
checkdiff "$RSYNC -aiiO --update --info=skip '$scratchdir/up1/' '$scratchdir/up2/'" \
|
||||
checkdiff "$RSYNC -aiiO$rpath --update --info=skip '$host$scratchdir/up1/' '$scratchdir/up2/'" \
|
||||
"grep -v '^\.d$allspace'" <<EOT
|
||||
dst-newness is newer
|
||||
>f$all_plus extra-src
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2005-2021 Wayne Davison
|
||||
# Copyright (C) 2005-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2005-2021 Wayne Davison
|
||||
# Copyright (C) 2005-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
@@ -25,7 +25,7 @@ ln "$fromdir/foo/config1" "$fromdir/foo/extra"
|
||||
rm -f "$to2dir"
|
||||
|
||||
# Check if rsync is set to hard-link symlinks.
|
||||
if $RSYNC --version | grep "[, ] hardlink-symlinks" >/dev/null; then
|
||||
if $RSYNC -VV | grep '"hardlink_symlinks": true' >/dev/null; then
|
||||
L=hL
|
||||
sym_dots="$allspace"
|
||||
L_sym_dots=".L$allspace"
|
||||
@@ -45,7 +45,7 @@ case "$RSYNC" in
|
||||
T=.T
|
||||
;;
|
||||
*)
|
||||
if $RSYNC --version | grep "[, ] symtimes" >/dev/null; then
|
||||
if $RSYNC -VV | grep '"symtimes": true' >/dev/null; then
|
||||
T=.t
|
||||
else
|
||||
T=.T
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2004-2021 Wayne Davison
|
||||
# Copyright (C) 2004-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2003-2021 Wayne Davison
|
||||
# Copyright (C) 2003-2022 Wayne Davison
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user