├── .gitattributes ├── .github └── workflows │ ├── cygwin-build.yml │ ├── freebsd-build.yml │ ├── macos-build.yml │ ├── solaris-build.yml │ └── ubuntu-build.yml ├── .gitignore ├── COPYING ├── Doxyfile ├── INSTALL.md ├── Makefile.in ├── NEWS.md ├── README.md ├── SECURITY.md ├── TODO ├── access.c ├── acls.c ├── authenticate.c ├── backup.c ├── batch.c ├── byteorder.h ├── case_N.h ├── checksum.c ├── chmod.c ├── cleanup.c ├── clientname.c ├── clientserver.c ├── cmd-or-msg ├── compat.c ├── config.guess ├── config.sub ├── configure ├── configure.ac ├── connection.c ├── csprotocol.txt ├── daemon-parm.awk ├── daemon-parm.txt ├── define-from-md.awk ├── delete.c ├── doc ├── README-SGML ├── profile.txt └── rsync.sgml ├── errcode.h ├── exclude.c ├── fileio.c ├── flist.c ├── generator.c ├── getfsdev.c ├── getgroups.c ├── hashtable.c ├── help-from-md.awk ├── hlink.c ├── ifuncs.h ├── install-sh ├── inums.h ├── io.c ├── io.h ├── itypes.h ├── latest-year.h ├── lib ├── addrinfo.h ├── compat.c ├── dummy.in ├── getaddrinfo.c ├── getpass.c ├── inet_ntop.c ├── inet_pton.c ├── md-defines.h ├── md5-asm-x86_64.S ├── md5.c ├── mdfour.c ├── mdigest.h ├── permstring.c ├── permstring.h ├── pool_alloc.3 ├── pool_alloc.c ├── pool_alloc.h ├── snprintf.c ├── sysacls.c ├── sysacls.h ├── sysxattrs.c ├── sysxattrs.h ├── wildmatch.c └── wildmatch.h ├── loadparm.c ├── log.c ├── m4 ├── have_type.m4 ├── header_major_fixed.m4 ├── socklen_t.m4 └── validate_cache_system_type.m4 ├── main.c ├── match.c ├── maybe-make-man ├── md-convert ├── md2man ├── mkgitver ├── mkproto.awk ├── options.c ├── packaging ├── auto-Makefile ├── branch-from-patch ├── cull-options ├── lsb │ ├── rsync.spec │ └── rsync.xinetd ├── openssl-rsync.cnf ├── patch-update ├── pkglib.py ├── prep-auto-dir ├── release-rsync ├── samba-rsync ├── send-news ├── smart-make ├── solaris │ └── build_pkg.sh ├── systemd │ ├── rsync.service │ ├── rsync.socket │ └── rsync@.service ├── var-checker └── year-tweak ├── params.c ├── pipe.c ├── popt ├── CHANGES ├── COPYING ├── README ├── README.rsync ├── dummy.in ├── lookup3.c ├── popt.c ├── popt.h ├── poptconfig.c ├── popthelp.c ├── poptint.c ├── poptint.h ├── poptparse.c └── system.h ├── prepare-source ├── prepare-source.mak ├── progress.c ├── receiver.c ├── rounding.c ├── rsync-ssl ├── rsync-ssl.1.md ├── rsync.1.md ├── rsync.c ├── rsync.h ├── rsync3.txt ├── rsyncd.conf.5.md ├── rsyncsh.txt ├── runtests.sh ├── sender.c ├── shconfig.in ├── simd-checksum-avx2.S ├── simd-checksum-x86_64.cpp ├── socket.c ├── stunnel-rsyncd.conf.in ├── support ├── Makefile ├── atomic-rsync ├── cvs2includes ├── deny-rsync ├── file-attr-restore ├── files-to-excludes ├── git-set-file-times ├── idmap ├── install_deps_ubuntu.sh ├── instant-rsyncd ├── json-rsync-version ├── logfilter ├── lsh ├── lsh.sh ├── mnt-excl ├── munge-symlinks ├── nameconvert ├── rrsync ├── rrsync.1.md ├── rsync-no-vanished ├── rsync-slash-strip ├── rsyncstats └── savetransfer.c ├── syscall.c ├── t_stub.c ├── t_unsafe.c ├── tech_report.tex ├── testhelp └── maketree.py ├── testrun.c ├── testsuite ├── 00-hello.test ├── README.testsuite ├── acls-default.test ├── acls.test ├── alt-dest.test ├── atimes.test ├── backup.test ├── batch-mode.test ├── chgrp.test ├── chmod-option.test ├── chmod-temp-dir.test ├── chmod.test ├── chown.test ├── crtimes.test ├── daemon-gzip-download.test ├── daemon-gzip-upload.test ├── daemon.test ├── delay-updates.test ├── delete.test ├── devices.test ├── dir-sgid.test ├── duplicates.test ├── exclude-lsh.test ├── exclude.test ├── executability.test ├── files-from.test ├── fuzzy.test ├── hands.test ├── hardlinks.test ├── itemize.test ├── longdir.test ├── merge.test ├── missing.test ├── mkpath.test ├── protected-regular.test ├── relative.test ├── rsync.fns ├── safe-links.test ├── ssh-basic.test ├── symlink-ignore.test ├── trimslash.test ├── unsafe-byname.test ├── unsafe-links.test ├── wildmatch.test └── xattrs.test ├── tls.c ├── token.c ├── trimslash.c ├── uidlist.c ├── usage.c ├── util1.c ├── util2.c ├── version.h ├── wildtest.c ├── wildtest.txt ├── xattrs.c └── zlib ├── ChangeLog ├── README ├── README.rsync ├── adler32.c ├── compress.c ├── crc32.c ├── crc32.h ├── deflate.c ├── deflate.h ├── dummy.in ├── gzguts.h ├── inffast.c ├── inffast.h ├── inffixed.h ├── inflate.c ├── inflate.h ├── inftrees.c ├── inftrees.h ├── trees.c ├── trees.h ├── zconf.h ├── zlib.h ├── zutil.c └── zutil.h /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/cygwin-build.yml: -------------------------------------------------------------------------------- 1 | name: Test rsync on Cygwin 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths-ignore: 7 | - '.github/workflows/*.yml' 8 | - '!.github/workflows/cygwin-build.yml' 9 | pull_request: 10 | branches: [ master ] 11 | paths-ignore: 12 | - '.github/workflows/*.yml' 13 | - '!.github/workflows/cygwin-build.yml' 14 | schedule: 15 | - cron: '42 8 * * *' 16 | 17 | jobs: 18 | test: 19 | runs-on: windows-2022 20 | name: Test rsync on Cygwin 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - name: cygwin 26 | run: choco install -y --no-progress cygwin cyg-get 27 | - name: prep 28 | run: | 29 | cyg-get make autoconf automake gcc-core attr libattr-devel python39 python39-pip libzstd-devel liblz4-devel libssl-devel libxxhash0 libxxhash-devel 30 | echo "C:/tools/cygwin/bin" >>$Env:GITHUB_PATH 31 | - name: commonmark 32 | run: bash -c 'python3 -mpip install --user commonmark' 33 | - name: configure 34 | run: bash -c './configure --with-rrsync' 35 | - name: make 36 | run: bash -c 'make' 37 | - name: install 38 | run: bash -c 'make install' 39 | - name: info 40 | run: bash -c '/usr/local/bin/rsync --version' 41 | - name: check 42 | run: bash -c 'RSYNC_EXPECT_SKIPPED=acls-default,acls,chown,devices,dir-sgid,protected-regular make check' 43 | - name: ssl file list 44 | run: bash -c 'PATH="/usr/local/bin:$PATH" rsync-ssl --no-motd download.samba.org::rsyncftp/ || true' 45 | - name: save artifact 46 | uses: actions/upload-artifact@v4 47 | with: 48 | name: cygwin-bin 49 | path: | 50 | rsync.exe 51 | rsync-ssl 52 | rsync.1 53 | rsync-ssl.1 54 | rsyncd.conf.5 55 | rrsync.1 56 | rrsync 57 | -------------------------------------------------------------------------------- /.github/workflows/freebsd-build.yml: -------------------------------------------------------------------------------- 1 | name: Test rsync on FreeBSD 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths-ignore: 7 | - '.github/workflows/*.yml' 8 | - '!.github/workflows/freebsd-build.yml' 9 | pull_request: 10 | branches: [ master ] 11 | paths-ignore: 12 | - '.github/workflows/*.yml' 13 | - '!.github/workflows/freebsd-build.yml' 14 | schedule: 15 | - cron: '42 8 * * *' 16 | 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | name: Test rsync on FreeBSD 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - name: Test in FreeBSD VM 26 | id: test 27 | uses: vmactions/freebsd-vm@v1 28 | with: 29 | usesh: true 30 | prepare: | 31 | pkg install -y bash autotools m4 devel/xxhash zstd liblz4 python3 archivers/liblz4 git 32 | run: | 33 | freebsd-version 34 | ./configure --with-rrsync -disable-zstd --disable-md2man --disable-xxhash --disable-lz4 35 | make 36 | ./rsync --version 37 | ./rsync-ssl --no-motd download.samba.org::rsyncftp/ || true 38 | - name: save artifact 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: freebsd-bin 42 | path: | 43 | rsync 44 | rsync-ssl 45 | rsync.1 46 | rsync-ssl.1 47 | rsyncd.conf.5 48 | rrsync.1 49 | rrsync 50 | -------------------------------------------------------------------------------- /.github/workflows/macos-build.yml: -------------------------------------------------------------------------------- 1 | name: Test rsync on macOS 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths-ignore: 7 | - '.github/workflows/*.yml' 8 | - '!.github/workflows/macos-build.yml' 9 | pull_request: 10 | branches: [ master ] 11 | paths-ignore: 12 | - '.github/workflows/*.yml' 13 | - '!.github/workflows/macos-build.yml' 14 | schedule: 15 | - cron: '42 8 * * *' 16 | 17 | jobs: 18 | test: 19 | runs-on: macos-latest 20 | name: Test rsync on macOS 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - name: prep 26 | run: | 27 | brew install automake openssl xxhash zstd lz4 28 | sudo pip3 install commonmark 29 | echo "/usr/local/bin" >>$GITHUB_PATH 30 | - name: configure 31 | run: CPPFLAGS=-I/usr/local/opt/openssl/include/ LDFLAGS=-L/usr/local/opt/openssl/lib/ ./configure --with-rrsync 32 | - name: make 33 | run: make 34 | - name: install 35 | run: sudo make install 36 | - name: info 37 | run: rsync --version 38 | - name: check 39 | run: sudo RSYNC_EXPECT_SKIPPED=acls-default,chmod-temp-dir,chown-fake,devices-fake,dir-sgid,protected-regular,xattrs-hlink,xattrs make check 40 | - name: ssl file list 41 | run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true 42 | - name: save artifact 43 | uses: actions/upload-artifact@v3 44 | with: 45 | name: macos-bin 46 | path: | 47 | rsync 48 | rsync-ssl 49 | rsync.1 50 | rsync-ssl.1 51 | rsyncd.conf.5 52 | rrsync.1 53 | rrsync 54 | -------------------------------------------------------------------------------- /.github/workflows/solaris-build.yml: -------------------------------------------------------------------------------- 1 | name: Test rsync on Solaris 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths-ignore: 7 | - '.github/workflows/*.yml' 8 | - '!.github/workflows/solaris-build.yml' 9 | pull_request: 10 | branches: [ master ] 11 | paths-ignore: 12 | - '.github/workflows/*.yml' 13 | - '!.github/workflows/solaris-build.yml' 14 | schedule: 15 | - cron: '42 8 * * *' 16 | 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | name: Test rsync on Solaris 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - name: Test in Solaris VM 26 | id: test 27 | uses: vmactions/solaris-vm@v1 28 | with: 29 | usesh: true 30 | prepare: | 31 | pkg install bash automake gnu-m4 pkg://solaris/runtime/python-35 autoconf gcc git 32 | run: | 33 | uname -a 34 | ./configure --with-rrsync -disable-zstd --disable-md2man --disable-xxhash --disable-lz4 35 | make 36 | ./rsync --version 37 | ./rsync-ssl --no-motd download.samba.org::rsyncftp/ || true 38 | - name: save artifact 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: solaris-bin 42 | path: | 43 | rsync 44 | rsync-ssl 45 | rsync.1 46 | rsync-ssl.1 47 | rsyncd.conf.5 48 | rrsync.1 49 | rrsync 50 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu-build.yml: -------------------------------------------------------------------------------- 1 | name: Test rsync on Ubuntu 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths-ignore: 7 | - '.github/workflows/*.yml' 8 | - '!.github/workflows/ubuntu-build.yml' 9 | pull_request: 10 | branches: [ master ] 11 | paths-ignore: 12 | - '.github/workflows/*.yml' 13 | - '!.github/workflows/ubuntu-build.yml' 14 | schedule: 15 | - cron: '42 8 * * *' 16 | 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | name: Test rsync on Ubuntu 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - name: prep 26 | run: | 27 | sudo apt-get install acl libacl1-dev attr libattr1-dev liblz4-dev libzstd-dev libxxhash-dev python3-cmarkgfm openssl 28 | echo "/usr/local/bin" >>$GITHUB_PATH 29 | - name: configure 30 | run: ./configure --with-rrsync 31 | - name: make 32 | run: make 33 | - name: install 34 | run: sudo make install 35 | - name: info 36 | run: rsync --version 37 | - name: check 38 | run: sudo RSYNC_EXPECT_SKIPPED=crtimes make check 39 | - name: check30 40 | run: sudo RSYNC_EXPECT_SKIPPED=crtimes make check30 41 | - name: check29 42 | run: sudo RSYNC_EXPECT_SKIPPED=crtimes make check29 43 | - name: ssl file list 44 | run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true 45 | - name: save artifact 46 | uses: actions/upload-artifact@v4 47 | with: 48 | name: ubuntu-bin 49 | path: | 50 | rsync 51 | rsync-ssl 52 | rsync.1 53 | rsync-ssl.1 54 | rsyncd.conf.5 55 | rrsync.1 56 | rrsync 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.[oa] 2 | *~ 3 | dummy 4 | ID 5 | Makefile 6 | Makefile.old 7 | configure.sh 8 | configure.sh.old 9 | config.cache 10 | config.h 11 | config.h.in 12 | config.h.in.old 13 | config.log 14 | config.status 15 | aclocal.m4 16 | /proto.h 17 | /proto.h-tstamp 18 | /rsync*.[15] 19 | /rrsync 20 | /rrsync*.1 21 | /rsync*.html 22 | /rrsync*.html 23 | /help-rsync*.h 24 | /default-cvsignore.h 25 | /default-dont-compress.h 26 | /daemon-parm.h 27 | /.md2man-works 28 | /autom4te*.cache 29 | /confdefs.h 30 | /conftest* 31 | /dox 32 | /getgroups 33 | /gists 34 | /gmon.out 35 | /rsync 36 | /stunnel-rsyncd.conf 37 | /shconfig 38 | /git-version.h 39 | /testdir 40 | /tests-dont-exist 41 | /testtmp 42 | /tls 43 | /testrun 44 | /trimslash 45 | /t_unsafe 46 | /wildtest 47 | /getfsdev 48 | /rounding.h 49 | /doc/rsync.pdf 50 | /doc/rsync.ps 51 | /support/savetransfer 52 | /testsuite/chown-fake.test 53 | /testsuite/devices-fake.test 54 | /testsuite/xattrs-hlink.test 55 | /patches 56 | /patches.gen 57 | /build 58 | /auto-build-save 59 | .deps 60 | /*.exe 61 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only the current release of the software is actively supported. If you need 6 | help backporting fixes into an older release, feel free to ask. 7 | 8 | ## Reporting a Vulnerability 9 | 10 | Email your vulnerability information to rsync's maintainer: 11 | 12 | Rsync Project 13 | 14 | -------------------------------------------------------------------------------- /byteorder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple byteorder handling. 3 | * 4 | * Copyright (C) 1992-1995 Andrew Tridgell 5 | * Copyright (C) 2007-2022 Wayne Davison 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, visit the http://fsf.org website. 19 | */ 20 | 21 | #undef CAREFUL_ALIGNMENT 22 | 23 | /* We know that the x86 can handle misalignment and has the same 24 | * byte order (LSB-first) as the 32-bit numbers we transmit. */ 25 | #if defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__ || __amd64 26 | #define CAREFUL_ALIGNMENT 0 27 | #endif 28 | 29 | #ifndef CAREFUL_ALIGNMENT 30 | #define CAREFUL_ALIGNMENT 1 31 | #endif 32 | 33 | #define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) 34 | #define UVAL(buf,pos) ((uint32)CVAL(buf,pos)) 35 | 36 | #if CAREFUL_ALIGNMENT 37 | 38 | static inline uint32 39 | IVALu(const uchar *buf, int pos) 40 | { 41 | return UVAL(buf, pos) 42 | | UVAL(buf, pos + 1) << 8 43 | | UVAL(buf, pos + 2) << 16 44 | | UVAL(buf, pos + 3) << 24; 45 | } 46 | 47 | static inline void 48 | SIVALu(uchar *buf, int pos, uint32 val) 49 | { 50 | CVAL(buf, pos) = val; 51 | CVAL(buf, pos + 1) = val >> 8; 52 | CVAL(buf, pos + 2) = val >> 16; 53 | CVAL(buf, pos + 3) = val >> 24; 54 | } 55 | 56 | static inline int64 57 | IVAL64(const char *buf, int pos) 58 | { 59 | return IVALu((uchar*)buf, pos) | (int64)IVALu((uchar*)buf, pos + 4) << 32; 60 | } 61 | 62 | static inline void 63 | SIVAL64(char *buf, int pos, int64 val) 64 | { 65 | SIVALu((uchar*)buf, pos, val); 66 | SIVALu((uchar*)buf, pos + 4, val >> 32); 67 | } 68 | 69 | #else /* !CAREFUL_ALIGNMENT */ 70 | 71 | /* This handles things for architectures like the 386 that can handle alignment errors. 72 | * WARNING: This section is dependent on the length of an int32 (and thus a uint32) 73 | * being correct (4 bytes)! Set CAREFUL_ALIGNMENT if it is not. */ 74 | 75 | static inline uint32 76 | IVALu(const uchar *buf, int pos) 77 | { 78 | union { 79 | const uchar *b; 80 | const uint32 *num; 81 | } u; 82 | u.b = buf + pos; 83 | return *u.num; 84 | } 85 | 86 | static inline void 87 | SIVALu(uchar *buf, int pos, uint32 val) 88 | { 89 | union { 90 | uchar *b; 91 | uint32 *num; 92 | } u; 93 | u.b = buf + pos; 94 | *u.num = val; 95 | } 96 | 97 | static inline int64 98 | IVAL64(const char *buf, int pos) 99 | { 100 | union { 101 | const char *b; 102 | const int64 *num; 103 | } u; 104 | u.b = buf + pos; 105 | return *u.num; 106 | } 107 | 108 | static inline void 109 | SIVAL64(char *buf, int pos, int64 val) 110 | { 111 | union { 112 | char *b; 113 | int64 *num; 114 | } u; 115 | u.b = buf + pos; 116 | *u.num = val; 117 | } 118 | 119 | #endif /* !CAREFUL_ALIGNMENT */ 120 | 121 | static inline uint32 122 | IVAL(const char *buf, int pos) 123 | { 124 | return IVALu((uchar*)buf, pos); 125 | } 126 | 127 | static inline void 128 | SIVAL(char *buf, int pos, uint32 val) 129 | { 130 | SIVALu((uchar*)buf, pos, val); 131 | } 132 | -------------------------------------------------------------------------------- /case_N.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Allow an arbitrary sequence of case labels. 3 | * 4 | * Copyright (C) 2006-2020 Wayne Davison 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, visit the http://fsf.org website. 18 | */ 19 | 20 | /* This is included multiple times, once for every segment in a switch statement. 21 | * This produces the next "case N:" statement in sequence. */ 22 | 23 | #if !defined CASE_N_STATE_0 24 | #define CASE_N_STATE_0 25 | case 0: 26 | #elif !defined CASE_N_STATE_1 27 | #define CASE_N_STATE_1 28 | /* FALLTHROUGH */ 29 | case 1: 30 | #elif !defined CASE_N_STATE_2 31 | #define CASE_N_STATE_2 32 | /* FALLTHROUGH */ 33 | case 2: 34 | #elif !defined CASE_N_STATE_3 35 | #define CASE_N_STATE_3 36 | /* FALLTHROUGH */ 37 | case 3: 38 | #elif !defined CASE_N_STATE_4 39 | #define CASE_N_STATE_4 40 | /* FALLTHROUGH */ 41 | case 4: 42 | #elif !defined CASE_N_STATE_5 43 | #define CASE_N_STATE_5 44 | /* FALLTHROUGH */ 45 | case 5: 46 | #elif !defined CASE_N_STATE_6 47 | #define CASE_N_STATE_6 48 | /* FALLTHROUGH */ 49 | case 6: 50 | #elif !defined CASE_N_STATE_7 51 | #define CASE_N_STATE_7 52 | /* FALLTHROUGH */ 53 | case 7: 54 | #elif !defined CASE_N_STATE_8 55 | #define CASE_N_STATE_8 56 | /* FALLTHROUGH */ 57 | case 8: 58 | #elif !defined CASE_N_STATE_9 59 | #define CASE_N_STATE_9 60 | /* FALLTHROUGH */ 61 | case 9: 62 | #elif !defined CASE_N_STATE_10 63 | #define CASE_N_STATE_10 64 | /* FALLTHROUGH */ 65 | case 10: 66 | #elif !defined CASE_N_STATE_11 67 | #define CASE_N_STATE_11 68 | /* FALLTHROUGH */ 69 | case 11: 70 | #elif !defined CASE_N_STATE_12 71 | #define CASE_N_STATE_12 72 | /* FALLTHROUGH */ 73 | case 12: 74 | #elif !defined CASE_N_STATE_13 75 | #define CASE_N_STATE_13 76 | /* FALLTHROUGH */ 77 | case 13: 78 | #elif !defined CASE_N_STATE_14 79 | #define CASE_N_STATE_14 80 | /* FALLTHROUGH */ 81 | case 14: 82 | #elif !defined CASE_N_STATE_15 83 | #define CASE_N_STATE_15 84 | /* FALLTHROUGH */ 85 | case 15: 86 | #elif !defined CASE_N_STATE_16 87 | #define CASE_N_STATE_16 88 | /* FALLTHROUGH */ 89 | case 16: 90 | #else 91 | #error Need to add more case statements! 92 | #endif 93 | -------------------------------------------------------------------------------- /cmd-or-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | srcdir=`dirname $0` 4 | opt="$1" 5 | shift 6 | 7 | echo "$*" 8 | if ! "${@}"; then 9 | echo "If you can't fix the issue, re-run $srcdir/configure with --$opt." 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # This configure script ensures that the configure.sh script exists, and 3 | # if not, it tries to fetch rsync's generated files or build them. We 4 | # then transfer control to the configure.sh script to do the real work. 5 | 6 | dir=`dirname $0` 7 | if test x"$dir" = x; then 8 | dir=. 9 | fi 10 | 11 | if test "$dir" = '.'; then 12 | branch=`packaging/prep-auto-dir` || exit 1 13 | if test x"$branch" != x; then 14 | cd build || exit 1 15 | dir=.. 16 | fi 17 | fi 18 | 19 | if test ! -f configure.sh; then 20 | if ! "$dir/prepare-source" build; then 21 | echo 'Failed to build configure.sh and/or config.h.in -- giving up.' >&2 22 | rm -f configure.sh 23 | exit 1 24 | fi 25 | fi 26 | 27 | exec ./configure.sh --srcdir="$dir" "${@}" 28 | -------------------------------------------------------------------------------- /connection.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Support the max connections option. 3 | * 4 | * Copyright (C) 1998 Andrew Tridgell 5 | * Copyright (C) 2006-2020 Wayne Davison 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, visit the http://fsf.org website. 19 | */ 20 | 21 | #include "rsync.h" 22 | 23 | /* A simple routine to do connection counting. This returns 1 on success 24 | * and 0 on failure, with errno also being set if the open() failed (errno 25 | * will be 0 if the lock request failed). */ 26 | int claim_connection(char *fname, int max_connections) 27 | { 28 | int fd, i; 29 | 30 | if (max_connections == 0) 31 | return 1; 32 | 33 | if ((fd = open(fname, O_RDWR|O_CREAT, 0600)) < 0) 34 | return 0; 35 | 36 | /* Find a free spot. */ 37 | for (i = 0; i < max_connections; i++) { 38 | if (lock_range(fd, i*4, 4)) 39 | return 1; 40 | } 41 | 42 | close(fd); 43 | 44 | /* A lock failure needs to return an errno of 0. */ 45 | errno = 0; 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /daemon-parm.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | 3 | # The caller must pass arg: daemon-parm.txt 4 | # The resulting code is output into daemon-parm.h 5 | 6 | BEGIN { 7 | heading = "/* DO NOT EDIT THIS FILE! It is auto-generated from a list of values in " ARGV[1] "! */\n\n" 8 | sect = psect = defines = accessors = prior_ptype = "" 9 | parms = "\nstatic struct parm_struct parm_table[] = {" 10 | comment_fmt = "\n/********** %s **********/\n" 11 | tdstruct = "typedef struct {" 12 | } 13 | 14 | /^\s*$/ { next } 15 | /^#/ { next } 16 | 17 | /^Globals:/ { 18 | if (defines != "") { 19 | print "The Globals section must come first!" 20 | defines = "" 21 | exit 22 | } 23 | defines = tdstruct 24 | values = "\nstatic const all_vars Defaults = {\n { /* Globals: */\n" 25 | exps = exp_values = sprintf(comment_fmt, "EXP") 26 | sect = "GLOBAL" 27 | psect = ", P_GLOBAL, &Vars.g." 28 | next 29 | } 30 | 31 | /^Locals:/ { 32 | if (sect == "") { 33 | print "The Locals section must come after the Globals!" 34 | exit 35 | } 36 | defines = defines exps "} global_vars;\n\n" tdstruct 37 | values = values exp_values "\n }, { /* Locals: */\n" 38 | exps = exp_values = sprintf(comment_fmt, "EXP") 39 | sect = "LOCAL" 40 | psect = ", P_LOCAL, &Vars.l." 41 | next 42 | } 43 | 44 | /^(STRING|CHAR|PATH|INTEGER|ENUM|OCTAL|BOOL|BOOLREV|BOOL3)[ \t]/ { 45 | ptype = $1 46 | name = $2 47 | $1 = $2 = "" 48 | sub(/^[ \t]+/, "") 49 | 50 | if (ptype != prior_ptype) { 51 | comment = sprintf(comment_fmt, ptype) 52 | defines = defines comment 53 | values = values comment 54 | parms = parms "\n" 55 | accessors = accessors "\n" 56 | prior_ptype = ptype 57 | } 58 | 59 | if (ptype == "STRING" || ptype == "PATH") { 60 | atype = "STRING" 61 | vtype = "char*" 62 | } else if (ptype ~ /BOOL/) { 63 | atype = vtype = "BOOL" 64 | } else if (ptype == "CHAR") { 65 | atype = "CHAR" 66 | vtype = "char" 67 | } else { 68 | atype = "INTEGER" 69 | vtype = "int" 70 | } 71 | 72 | # The name might be var_name|public_name 73 | pubname = name 74 | sub(/\|.*/, "", name) 75 | sub(/.*\|/, "", pubname) 76 | gsub(/_/, " ", pubname) 77 | gsub(/-/, "", name) 78 | 79 | if (ptype == "ENUM") 80 | enum = "enum_" name 81 | else 82 | enum = "NULL" 83 | 84 | defines = defines "\t" vtype " " name ";\n" 85 | values = values "\t" $0 ", /* " name " */\n" 86 | parms = parms " {\"" pubname "\", P_" ptype psect name ", " enum ", 0},\n" 87 | accessors = accessors "FN_" sect "_" atype "(lp_" name ", " name ")\n" 88 | 89 | if (vtype == "char*") { 90 | exps = exps "\tBOOL " name "_EXP;\n" 91 | exp_values = exp_values "\tFalse, /* " name "_EXP */\n" 92 | } 93 | 94 | next 95 | } 96 | 97 | /./ { 98 | print "Extraneous line:" $0 99 | defines = "" 100 | exit 101 | } 102 | 103 | END { 104 | if (sect != "" && defines != "") { 105 | defines = defines exps "} local_vars;\n\n" 106 | defines = defines tdstruct "\n\tglobal_vars g;\n\tlocal_vars l;\n} all_vars;\n" 107 | values = values exp_values "\n }\n};\n\nstatic all_vars Vars;\n" 108 | parms = parms "\n {NULL, P_BOOL, P_NONE, NULL, NULL, 0}\n};\n" 109 | print heading defines values parms accessors > "daemon-parm.h" 110 | } else { 111 | print "Failed to parse the data in " ARGV[1] 112 | exit 1 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /daemon-parm.txt: -------------------------------------------------------------------------------- 1 | Globals: ================================================================ 2 | 3 | STRING bind_address|address NULL 4 | STRING daemon_chroot NULL 5 | STRING daemon_gid NULL 6 | STRING daemon_uid NULL 7 | STRING motd_file NULL 8 | STRING pid_file NULL 9 | STRING socket_options NULL 10 | 11 | INTEGER listen_backlog 5 12 | INTEGER rsync_port|port 0 13 | 14 | BOOL proxy_protocol False 15 | 16 | Locals: ================================================================= 17 | 18 | STRING auth_users NULL 19 | STRING charset NULL 20 | STRING comment NULL 21 | STRING dont_compress DEFAULT_DONT_COMPRESS 22 | STRING early_exec NULL 23 | STRING exclude NULL 24 | STRING exclude_from NULL 25 | STRING filter NULL 26 | STRING gid NULL 27 | STRING hosts_allow NULL 28 | STRING hosts_deny NULL 29 | STRING include NULL 30 | STRING include_from NULL 31 | STRING incoming_chmod NULL 32 | STRING lock_file DEFAULT_LOCK_FILE 33 | STRING log_file NULL 34 | STRING log_format "%o %h [%a] %m (%u) %f %l" 35 | STRING name NULL 36 | STRING name_converter NULL 37 | STRING outgoing_chmod NULL 38 | STRING post-xfer_exec NULL 39 | STRING pre-xfer_exec NULL 40 | STRING refuse_options NULL 41 | STRING secrets_file NULL 42 | STRING syslog_tag "rsyncd" 43 | STRING uid NULL 44 | 45 | PATH path NULL 46 | PATH temp_dir NULL 47 | 48 | INTEGER max_connections 0 49 | INTEGER max_verbosity 1 50 | INTEGER timeout 0 51 | 52 | ENUM syslog_facility LOG_DAEMON 53 | 54 | BOOL fake_super False 55 | BOOL forward_lookup True 56 | BOOL ignore_errors False 57 | BOOL ignore_nonreadable False 58 | BOOL list True 59 | BOOL read_only True 60 | BOOL reverse_lookup True 61 | BOOL strict_modes True 62 | BOOL transfer_logging False 63 | BOOL write_only False 64 | 65 | BOOL3 munge_symlinks Unset 66 | BOOL3 numeric_ids Unset 67 | BOOL3 open_noatime Unset 68 | BOOL3 use_chroot Unset 69 | -------------------------------------------------------------------------------- /define-from-md.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | 3 | # The caller must pass args: -v hfile=NAME rsync.1.md 4 | 5 | BEGIN { 6 | heading = "/* DO NOT EDIT THIS FILE! It is auto-generated from a list of values in " ARGV[1] "! */" 7 | if (hfile ~ /compress/) { 8 | define = "#define DEFAULT_DONT_COMPRESS" 9 | prefix = "*." 10 | } else { 11 | define = "#define DEFAULT_CVSIGNORE" 12 | prefix = "" 13 | } 14 | value_list = "" 15 | } 16 | 17 | /^ > [^ ]+$/ { 18 | gsub(/`/, "") 19 | if (value_list != "") value_list = value_list " " 20 | value_list = value_list prefix $2 21 | next 22 | } 23 | 24 | value_list ~ /\.gz / && hfile ~ /compress/ { 25 | exit 26 | } 27 | 28 | value_list ~ /SCCS / && hfile ~ /cvsignore/ { 29 | exit 30 | } 31 | 32 | value_list = "" 33 | 34 | END { 35 | if (value_list != "") 36 | print heading "\n\n" define " \"" value_list "\"" > hfile 37 | else { 38 | print "Failed to find a value list in " ARGV[1] " for " hfile 39 | exit 1 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /doc/README-SGML: -------------------------------------------------------------------------------- 1 | Handling the rsync SGML documentation 2 | 3 | rsync documentation is now primarily in Docbook format. Docbook is an 4 | SGML/XML documentation format that is becoming standard on free 5 | operating systems. It's also used for Samba documentation. 6 | 7 | The SGML files are source code that can be translated into various 8 | useful output formats, primarily PDF, HTML, Postscript and plain text. 9 | 10 | To do this transformation on Debian, you should install the 11 | docbook-utils package. Having done that, you can say 12 | 13 | docbook2pdf rsync.sgml 14 | 15 | and so on. 16 | 17 | On other systems you probably need James Clark's "sp" and "JadeTeX" 18 | packages. Work it out for yourself and send a note to the mailing 19 | list. 20 | 21 | -------------------------------------------------------------------------------- /doc/profile.txt: -------------------------------------------------------------------------------- 1 | Notes on rsync profiling 2 | 3 | strlcpy is hot: 4 | 5 | 0.00 0.00 1/7735635 push_dir [68] 6 | 0.00 0.00 1/7735635 pop_dir [71] 7 | 0.00 0.00 1/7735635 send_file_list [15] 8 | 0.01 0.00 18857/7735635 send_files [4] 9 | 0.04 0.00 129260/7735635 send_file_entry [18] 10 | 0.04 0.00 129260/7735635 make_file [20] 11 | 0.04 0.00 141666/7735635 send_directory [36] 12 | 2.29 0.00 7316589/7735635 f_name [13] 13 | [14] 11.7 2.42 0.00 7735635 strlcpy [14] 14 | 15 | 16 | Here's the top few functions: 17 | 18 | 46.23 9.57 9.57 13160929 0.00 0.00 mdfour64 19 | 14.78 12.63 3.06 13160929 0.00 0.00 copy64 20 | 11.69 15.05 2.42 7735635 0.00 0.00 strlcpy 21 | 10.05 17.13 2.08 41438 0.05 0.38 sum_update 22 | 4.11 17.98 0.85 13159996 0.00 0.00 mdfour_update 23 | 1.50 18.29 0.31 file_compare 24 | 1.45 18.59 0.30 129261 0.00 0.01 send_file_entry 25 | 1.23 18.84 0.26 2557585 0.00 0.00 f_name 26 | 1.11 19.07 0.23 1483750 0.00 0.00 u_strcmp 27 | 1.11 19.30 0.23 118129 0.00 0.00 writefd_unbuffered 28 | 0.92 19.50 0.19 1085011 0.00 0.00 writefd 29 | 0.43 19.59 0.09 156987 0.00 0.00 read_timeout 30 | 0.43 19.68 0.09 129261 0.00 0.00 clean_fname 31 | 0.39 19.75 0.08 32887 0.00 0.38 matched 32 | 0.34 19.82 0.07 1 70.00 16293.92 send_files 33 | 0.29 19.89 0.06 129260 0.00 0.00 make_file 34 | 0.29 19.95 0.06 75430 0.00 0.00 read_unbuffered 35 | 36 | 37 | 38 | mdfour could perhaps be made faster: 39 | 40 | /* NOTE: This code makes no attempt to be fast! */ 41 | 42 | There might be an optimized version somewhere that we can borrow. 43 | -------------------------------------------------------------------------------- /errcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Error codes returned by rsync. 3 | * 4 | * Copyright (C) 1998-2000 Andrew Tridgell 5 | * Copyright (C) 2003-2019 Wayne Davison 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, visit the http://fsf.org website. 19 | */ 20 | 21 | /* If you change these, please also update the string mappings in log.c and 22 | * the EXIT VALUES in rsync.yo. */ 23 | 24 | #define RERR_OK 0 25 | #define RERR_SYNTAX 1 /* syntax or usage error */ 26 | #define RERR_PROTOCOL 2 /* protocol incompatibility */ 27 | #define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */ 28 | #define RERR_UNSUPPORTED 4 /* requested action not supported */ 29 | #define RERR_STARTCLIENT 5 /* error starting client-server protocol */ 30 | 31 | #define RERR_SOCKETIO 10 /* error in socket IO */ 32 | #define RERR_FILEIO 11 /* error in file IO */ 33 | #define RERR_STREAMIO 12 /* error in rsync protocol data stream */ 34 | #define RERR_MESSAGEIO 13 /* errors with program diagnostics */ 35 | #define RERR_IPC 14 /* error in IPC code */ 36 | #define RERR_CRASHED 15 /* sibling crashed */ 37 | #define RERR_TERMINATED 16 /* sibling terminated abnormally */ 38 | 39 | #define RERR_SIGNAL1 19 /* status returned when sent SIGUSR1 */ 40 | #define RERR_SIGNAL 20 /* status returned when sent SIGINT, SIGTERM, SIGHUP */ 41 | #define RERR_WAITCHILD 21 /* some error returned by waitpid() */ 42 | #define RERR_MALLOC 22 /* error allocating core memory buffers */ 43 | #define RERR_PARTIAL 23 /* partial transfer */ 44 | #define RERR_VANISHED 24 /* file(s) vanished on sender side */ 45 | #define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */ 46 | 47 | #define RERR_TIMEOUT 30 /* timeout in data send/receive */ 48 | #define RERR_CONTIMEOUT 35 /* timeout waiting for daemon connection */ 49 | 50 | /* Although it doesn't seem to be specified anywhere, 51 | * ssh and the shell seem to return these values: 52 | * 53 | * 124 if the command exited with status 255 54 | * 125 if the command is killed by a signal 55 | * 126 if the command cannot be run 56 | * 127 if the command is not found 57 | * 58 | * and we could use this to give a better explanation if the remote 59 | * command is not found. 60 | */ 61 | #define RERR_CMD_FAILED 124 62 | #define RERR_CMD_KILLED 125 63 | #define RERR_CMD_RUN 126 64 | #define RERR_CMD_NOTFOUND 127 65 | -------------------------------------------------------------------------------- /getfsdev.c: -------------------------------------------------------------------------------- 1 | #include "rsync.h" 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | STRUCT_STAT st; 6 | int ret; 7 | 8 | while (--argc > 0) { 9 | #ifdef USE_STAT64_FUNCS 10 | ret = stat64(*++argv, &st); 11 | #else 12 | ret = stat(*++argv, &st); 13 | #endif 14 | if (ret < 0) { 15 | fprintf(stderr, "Unable to stat `%s'\n", *argv); 16 | exit(1); 17 | } 18 | printf("%ld/%ld\n", (long)major(st.st_dev), (long)minor(st.st_dev)); 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /getgroups.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Print out the gids of all groups for the current user. This is like 3 | * `id -G` on Linux, but it's too hard to find a portable equivalent. 4 | * 5 | * Copyright (C) 2002 Martin Pool 6 | * Copyright (C) 2003-2020 Wayne Davison 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License version 3 as 10 | * published by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, visit the http://fsf.org website. 19 | */ 20 | 21 | #include "rsync.h" 22 | 23 | int main(UNUSED(int argc), UNUSED(char *argv[])) 24 | { 25 | int n, i; 26 | gid_t *list; 27 | gid_t gid = MY_GID(); 28 | int gid_in_list = 0; 29 | 30 | #ifdef HAVE_GETGROUPS 31 | if ((n = getgroups(0, NULL)) < 0) { 32 | perror("getgroups"); 33 | return 1; 34 | } 35 | #else 36 | n = 0; 37 | #endif 38 | 39 | list = (gid_t*)malloc(sizeof (gid_t) * (n + 1)); 40 | if (!list) { 41 | fprintf(stderr, "out of memory!\n"); 42 | exit(1); 43 | } 44 | 45 | #ifdef HAVE_GETGROUPS 46 | if (n > 0) 47 | n = getgroups(n, list); 48 | #endif 49 | 50 | for (i = 0; i < n; i++) { 51 | printf("%lu ", (unsigned long)list[i]); 52 | if (list[i] == gid) 53 | gid_in_list = 1; 54 | } 55 | /* The default gid might not be in the list on some systems. */ 56 | if (!gid_in_list) 57 | printf("%lu", (unsigned long)gid); 58 | printf("\n"); 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /help-from-md.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | 3 | # The caller must pass args: -v hfile=help-NAME.h NAME.NUM.md 4 | 5 | BEGIN { 6 | heading = "/* DO NOT EDIT THIS FILE! It is auto-generated from the option list in " ARGV[1] "! */" 7 | findcomment = hfile 8 | sub("\\.", "\\.", findcomment) 9 | findcomment = "\\[comment\\].*" findcomment 10 | backtick_cnt = 0 11 | prints = "" 12 | } 13 | 14 | /^```/ { 15 | backtick_cnt++ 16 | next 17 | } 18 | 19 | foundcomment { 20 | if (backtick_cnt > 1) exit 21 | if (backtick_cnt == 1) { 22 | gsub(/"/, "\\\"") 23 | prints = prints "\n rprintf(F,\"" $0 "\\n\");" 24 | } 25 | next 26 | } 27 | 28 | $0 ~ findcomment { 29 | foundcomment = 1 30 | backtick_cnt = 0 31 | } 32 | 33 | END { 34 | if (foundcomment && backtick_cnt > 1) 35 | print heading "\n" prints > hfile 36 | else { 37 | print "Failed to find " hfile " section in " ARGV[1] 38 | exit 1 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ifuncs.h: -------------------------------------------------------------------------------- 1 | /* Inline functions for rsync. 2 | * 3 | * Copyright (C) 2007-2022 Wayne Davison 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, visit the http://fsf.org website. 17 | */ 18 | 19 | static inline void 20 | alloc_xbuf(xbuf *xb, size_t sz) 21 | { 22 | xb->buf = new_array(char, sz); 23 | xb->size = sz; 24 | xb->len = xb->pos = 0; 25 | } 26 | 27 | static inline void 28 | realloc_xbuf(xbuf *xb, size_t sz) 29 | { 30 | char *bf = realloc_array(xb->buf, char, sz); 31 | xb->buf = bf; 32 | xb->size = sz; 33 | } 34 | 35 | static inline void 36 | free_xbuf(xbuf *xb) 37 | { 38 | if (xb->buf) 39 | free(xb->buf); 40 | memset(xb, 0, sizeof (xbuf)); 41 | } 42 | 43 | static inline int 44 | to_wire_mode(mode_t mode) 45 | { 46 | #ifdef SUPPORT_LINKS 47 | #if _S_IFLNK != 0120000 48 | if (S_ISLNK(mode)) 49 | return (mode & ~(_S_IFMT)) | 0120000; 50 | #endif 51 | #endif 52 | return mode; 53 | } 54 | 55 | static inline mode_t 56 | from_wire_mode(int mode) 57 | { 58 | #if _S_IFLNK != 0120000 59 | if ((mode & (_S_IFMT)) == 0120000) 60 | return (mode & ~(_S_IFMT)) | _S_IFLNK; 61 | #endif 62 | return mode; 63 | } 64 | 65 | static inline char * 66 | d_name(struct dirent *di) 67 | { 68 | #ifdef HAVE_BROKEN_READDIR 69 | return (di->d_name - 2); 70 | #else 71 | return di->d_name; 72 | #endif 73 | } 74 | 75 | static inline void 76 | init_stat_x(stat_x *sx_p) 77 | { 78 | sx_p->crtime = 0; 79 | #ifdef SUPPORT_ACLS 80 | sx_p->acc_acl = sx_p->def_acl = NULL; 81 | #endif 82 | #ifdef SUPPORT_XATTRS 83 | sx_p->xattr = NULL; 84 | #endif 85 | } 86 | 87 | static inline void 88 | free_stat_x(stat_x *sx_p) 89 | { 90 | #ifdef SUPPORT_ACLS 91 | { 92 | extern int preserve_acls; 93 | if (preserve_acls) 94 | free_acl(sx_p); 95 | } 96 | #endif 97 | #ifdef SUPPORT_XATTRS 98 | { 99 | extern int preserve_xattrs; 100 | if (preserve_xattrs) 101 | free_xattr(sx_p); 102 | } 103 | #endif 104 | } 105 | 106 | static inline char *my_strdup(const char *str, const char *file, int line) 107 | { 108 | int len = strlen(str)+1; 109 | char *buf = my_alloc(NULL, len, 1, file, line); 110 | memcpy(buf, str, len); 111 | return buf; 112 | } 113 | -------------------------------------------------------------------------------- /inums.h: -------------------------------------------------------------------------------- 1 | /* Inline functions for rsync. 2 | * 3 | * Copyright (C) 2008-2019 Wayne Davison 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, visit the http://fsf.org website. 17 | */ 18 | 19 | static inline char * 20 | big_num(int64 num) 21 | { 22 | return do_big_num(num, 0, NULL); 23 | } 24 | 25 | static inline char * 26 | comma_num(int64 num) 27 | { 28 | extern int human_readable; 29 | return do_big_num(num, human_readable != 0, NULL); 30 | } 31 | 32 | static inline char * 33 | human_num(int64 num) 34 | { 35 | extern int human_readable; 36 | return do_big_num(num, human_readable, NULL); 37 | } 38 | 39 | static inline char * 40 | big_dnum(double dnum, int decimal_digits) 41 | { 42 | return do_big_dnum(dnum, 0, decimal_digits); 43 | } 44 | 45 | static inline char * 46 | comma_dnum(double dnum, int decimal_digits) 47 | { 48 | extern int human_readable; 49 | return do_big_dnum(dnum, human_readable != 0, decimal_digits); 50 | } 51 | 52 | static inline char * 53 | human_dnum(double dnum, int decimal_digits) 54 | { 55 | extern int human_readable; 56 | return do_big_dnum(dnum, human_readable, decimal_digits); 57 | } 58 | -------------------------------------------------------------------------------- /io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2019 Wayne Davison 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, visit the http://fsf.org website. 16 | */ 17 | 18 | extern int protocol_version; 19 | 20 | static inline int32 21 | read_varint30(int f) 22 | { 23 | if (protocol_version < 30) 24 | return read_int(f); 25 | return read_varint(f); 26 | } 27 | 28 | static inline int64 29 | read_varlong30(int f, uchar min_bytes) 30 | { 31 | if (protocol_version < 30) 32 | return read_longint(f); 33 | return read_varlong(f, min_bytes); 34 | } 35 | 36 | static inline void 37 | write_varint30(int f, int32 x) 38 | { 39 | if (protocol_version < 30) 40 | write_int(f, x); 41 | else 42 | write_varint(f, x); 43 | } 44 | 45 | static inline void 46 | write_varlong30(int f, int64 x, uchar min_bytes) 47 | { 48 | if (protocol_version < 30) 49 | write_longint(f, x); 50 | else 51 | write_varlong(f, x, min_bytes); 52 | } 53 | -------------------------------------------------------------------------------- /itypes.h: -------------------------------------------------------------------------------- 1 | /* Inline functions for rsync. 2 | * 3 | * Copyright (C) 2007-2022 Wayne Davison 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, visit the http://fsf.org website. 17 | */ 18 | 19 | static inline int 20 | isDigit(const char *ptr) 21 | { 22 | return isdigit(*(unsigned char *)ptr); 23 | } 24 | 25 | static inline int 26 | isHexDigit(const char *ptr) 27 | { 28 | return isxdigit(*(unsigned char *)ptr); 29 | } 30 | 31 | static inline int 32 | isPrint(const char *ptr) 33 | { 34 | return isprint(*(unsigned char *)ptr); 35 | } 36 | 37 | static inline int 38 | isSpace(const char *ptr) 39 | { 40 | return isspace(*(unsigned char *)ptr); 41 | } 42 | 43 | static inline int 44 | isAlNum(const char *ptr) 45 | { 46 | return isalnum(*(unsigned char *)ptr); 47 | } 48 | 49 | static inline int 50 | isLower(const char *ptr) 51 | { 52 | return islower(*(unsigned char *)ptr); 53 | } 54 | 55 | static inline int 56 | isUpper(const char *ptr) 57 | { 58 | return isupper(*(unsigned char *)ptr); 59 | } 60 | 61 | static inline int 62 | toLower(const char *ptr) 63 | { 64 | return tolower(*(unsigned char *)ptr); 65 | } 66 | 67 | static inline int 68 | toUpper(const char *ptr) 69 | { 70 | return toupper(*(unsigned char *)ptr); 71 | } 72 | -------------------------------------------------------------------------------- /latest-year.h: -------------------------------------------------------------------------------- 1 | #define LATEST_YEAR "2025" 2 | -------------------------------------------------------------------------------- /lib/dummy.in: -------------------------------------------------------------------------------- 1 | This is a dummy file to ensure that the lib directory gets created 2 | by configure when a VPATH is used. 3 | -------------------------------------------------------------------------------- /lib/getpass.c: -------------------------------------------------------------------------------- 1 | /* 2 | * An implementation of getpass for systems that lack one. 3 | * 4 | * Copyright (C) 2013 Roman Donchenko 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, visit the http://fsf.org website. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "rsync.h" 25 | 26 | char *getpass(const char *prompt) 27 | { 28 | static char password[256]; 29 | 30 | BOOL tty_changed = False, read_success; 31 | struct termios tty_old, tty_new; 32 | FILE *in = stdin, *out = stderr; 33 | FILE *tty = fopen("/dev/tty", "w+"); 34 | 35 | if (tty) 36 | in = out = tty; 37 | 38 | if (tcgetattr(fileno(in), &tty_old) == 0) { 39 | tty_new = tty_old; 40 | tty_new.c_lflag &= ~(ECHO | ISIG); 41 | 42 | if (tcsetattr(fileno(in), TCSAFLUSH, &tty_new) == 0) 43 | tty_changed = True; 44 | } 45 | 46 | if (!tty_changed) 47 | fputs("(WARNING: will be visible) ", out); 48 | fputs(prompt, out); 49 | fflush(out); 50 | 51 | read_success = fgets(password, sizeof password, in) != NULL; 52 | 53 | /* Print the newline that hasn't been echoed. */ 54 | fputc('\n', out); 55 | 56 | if (tty_changed) 57 | tcsetattr(fileno(in), TCSAFLUSH, &tty_old); 58 | 59 | if (tty) 60 | fclose(tty); 61 | 62 | if (read_success) { 63 | /* Remove the trailing newline. */ 64 | size_t password_len = strlen(password); 65 | if (password_len && password[password_len - 1] == '\n') 66 | password[password_len - 1] = '\0'; 67 | 68 | return password; 69 | } 70 | 71 | return NULL; 72 | } 73 | -------------------------------------------------------------------------------- /lib/md-defines.h: -------------------------------------------------------------------------------- 1 | /* Keep this simple so both C and ASM can use it */ 2 | 3 | /* These allow something like CFLAGS=-DDISABLE_SHA512_DIGEST */ 4 | #ifdef DISABLE_SHA256_DIGEST 5 | #undef SHA256_DIGEST_LENGTH 6 | #endif 7 | #ifdef DISABLE_SHA512_DIGEST 8 | #undef SHA512_DIGEST_LENGTH 9 | #endif 10 | 11 | #define MD4_DIGEST_LEN 16 12 | #define MD5_DIGEST_LEN 16 13 | #if defined SHA512_DIGEST_LENGTH 14 | #define MAX_DIGEST_LEN SHA512_DIGEST_LENGTH 15 | #elif defined SHA256_DIGEST_LENGTH 16 | #define MAX_DIGEST_LEN SHA256_DIGEST_LENGTH 17 | #elif defined SHA_DIGEST_LENGTH 18 | #define MAX_DIGEST_LEN SHA_DIGEST_LENGTH 19 | #else 20 | #define MAX_DIGEST_LEN MD5_DIGEST_LEN 21 | #endif 22 | 23 | #define CSUM_CHUNK 64 24 | 25 | #define CSUM_gone -1 26 | #define CSUM_NONE 0 27 | #define CSUM_MD4_ARCHAIC 1 28 | #define CSUM_MD4_BUSTED 2 29 | #define CSUM_MD4_OLD 3 30 | #define CSUM_MD4 4 31 | #define CSUM_MD5 5 32 | #define CSUM_XXH64 6 33 | #define CSUM_XXH3_64 7 34 | #define CSUM_XXH3_128 8 35 | #define CSUM_SHA1 9 36 | #define CSUM_SHA256 10 37 | #define CSUM_SHA512 11 38 | -------------------------------------------------------------------------------- /lib/mdigest.h: -------------------------------------------------------------------------------- 1 | /* The include file for both the MD4 and MD5 routines. */ 2 | 3 | #ifdef USE_OPENSSL 4 | #include 5 | #include 6 | #endif 7 | #include "md-defines.h" 8 | 9 | typedef struct { 10 | uint32 A, B, C, D; 11 | uint32 totalN; /* bit count, lower 32 bits */ 12 | uint32 totalN2; /* bit count, upper 32 bits */ 13 | uchar buffer[CSUM_CHUNK]; 14 | } md_context; 15 | 16 | void mdfour_begin(md_context *md); 17 | void mdfour_update(md_context *md, const uchar *in, uint32 length); 18 | void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN]); 19 | 20 | void md5_begin(md_context *ctx); 21 | void md5_update(md_context *ctx, const uchar *input, uint32 length); 22 | void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN]); 23 | -------------------------------------------------------------------------------- /lib/permstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A single utility routine. 3 | * 4 | * Copyright (C) 1996 Andrew Tridgell 5 | * Copyright (C) 1996 Paul Mackerras 6 | * Copyright (C) 2001 Martin Pool 7 | * Copyright (C) 2003-2019 Wayne Davison 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along 20 | * with this program; if not, visit the http://fsf.org website. 21 | */ 22 | 23 | #include "rsync.h" 24 | 25 | /* Produce a string representation of Unix mode bits like that used by ls(1). 26 | * The "buf" buffer must be at least 11 characters. */ 27 | void permstring(char *perms, mode_t mode) 28 | { 29 | static const char *perm_map = "rwxrwxrwx"; 30 | int i; 31 | 32 | strlcpy(perms, "----------", 11); 33 | 34 | for (i = 0; i < 9; i++) { 35 | if (mode & (1 << i)) 36 | perms[9-i] = perm_map[8-i]; 37 | } 38 | 39 | /* Handle setuid/sticky bits. You might think the indices are 40 | * off by one, but remember there's a type char at the 41 | * start. */ 42 | if (mode & S_ISUID) 43 | perms[3] = (mode & S_IXUSR) ? 's' : 'S'; 44 | 45 | if (mode & S_ISGID) 46 | perms[6] = (mode & S_IXGRP) ? 's' : 'S'; 47 | 48 | #ifdef S_ISVTX 49 | if (mode & S_ISVTX) 50 | perms[9] = (mode & S_IXOTH) ? 't' : 'T'; 51 | #endif 52 | 53 | if (S_ISDIR(mode)) 54 | perms[0] = 'd'; 55 | else if (S_ISLNK(mode)) 56 | perms[0] = 'l'; 57 | else if (S_ISBLK(mode)) 58 | perms[0] = 'b'; 59 | else if (S_ISCHR(mode)) 60 | perms[0] = 'c'; 61 | else if (S_ISSOCK(mode)) 62 | perms[0] = 's'; 63 | else if (S_ISFIFO(mode)) 64 | perms[0] = 'p'; 65 | } 66 | -------------------------------------------------------------------------------- /lib/permstring.h: -------------------------------------------------------------------------------- 1 | #define PERMSTRING_SIZE 11 2 | 3 | void permstring(char *perms, mode_t mode); 4 | -------------------------------------------------------------------------------- /lib/pool_alloc.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define POOL_CLEAR (1<<0) /* zero fill allocations */ 4 | #define POOL_NO_QALIGN (1<<1) /* don't align data to quanta */ 5 | #define POOL_INTERN (1<<2) /* Allocate extent structures */ 6 | #define POOL_PREPEND (1<<3) /* or prepend to extent data */ 7 | 8 | typedef void *alloc_pool_t; 9 | 10 | alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(const char*, const char*, int), int flags); 11 | void pool_destroy(alloc_pool_t pool); 12 | void *pool_alloc(alloc_pool_t pool, size_t size, const char *bomb_msg); 13 | void pool_free(alloc_pool_t pool, size_t size, void *addr); 14 | void pool_free_old(alloc_pool_t pool, void *addr); 15 | void *pool_boundary(alloc_pool_t pool, size_t size); 16 | 17 | #define pool_talloc(pool, type, count, bomb_msg) \ 18 | ((type *)pool_alloc(pool, sizeof(type) * count, bomb_msg)) 19 | 20 | #define pool_tfree(pool, type, count, addr) \ 21 | (pool_free(pool, sizeof(type) * count, addr)) 22 | -------------------------------------------------------------------------------- /lib/sysxattrs.h: -------------------------------------------------------------------------------- 1 | #ifdef SUPPORT_XATTRS 2 | 3 | #if defined HAVE_SYS_XATTR_H 4 | #include 5 | #elif defined HAVE_ATTR_XATTR_H 6 | #include 7 | #elif defined HAVE_SYS_EXTATTR_H 8 | #include 9 | #endif 10 | 11 | /* Linux 2.4 does not define this as a distinct errno value: */ 12 | #ifndef ENOATTR 13 | #define ENOATTR ENODATA 14 | #endif 15 | 16 | ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size); 17 | ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size); 18 | int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size); 19 | int sys_lremovexattr(const char *path, const char *name); 20 | ssize_t sys_llistxattr(const char *path, char *list, size_t size); 21 | 22 | #else 23 | 24 | /* No xattrs available */ 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lib/wildmatch.h: -------------------------------------------------------------------------------- 1 | /* wildmatch.h */ 2 | 3 | int wildmatch(const char *pattern, const char *text); 4 | int iwildmatch(const char *pattern, const char *text); 5 | int wildmatch_array(const char *pattern, const char*const *texts, int where); 6 | int litmatch_array(const char *string, const char*const *texts, int where); 7 | -------------------------------------------------------------------------------- /m4/have_type.m4: -------------------------------------------------------------------------------- 1 | dnl AC_HAVE_TYPE(TYPE,INCLUDES) 2 | AC_DEFUN([AC_HAVE_TYPE], [ 3 | cv=`echo "$1" | sed 'y%./+- %__p__%'` 4 | AC_MSG_CHECKING(for $1) 5 | AC_CACHE_VAL([ac_cv_type_$cv], 6 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 7 | AC_INCLUDES_DEFAULT 8 | $2]], 9 | [[$1 foo;]])], 10 | [eval "ac_cv_type_$cv=yes"], 11 | [eval "ac_cv_type_$cv=no"]))dnl 12 | ac_foo=`eval echo \\$ac_cv_type_$cv` 13 | AC_MSG_RESULT($ac_foo) 14 | if test "$ac_foo" = yes; then 15 | ac_tr_hdr=HAVE_`echo $1 | sed 'y%abcdefghijklmnopqrstuvwxyz./- %ABCDEFGHIJKLMNOPQRSTUVWXYZ____%'` 16 | if false; then 17 | AC_CHECK_TYPES($1) 18 | fi 19 | AC_DEFINE_UNQUOTED($ac_tr_hdr, 1, [Define if you have type `$1']) 20 | fi 21 | ]) 22 | -------------------------------------------------------------------------------- /m4/header_major_fixed.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AC_HEADER_MAJOR_FIXED], 2 | [AC_CACHE_CHECK(whether sys/types.h defines makedev, 3 | ac_cv_header_sys_types_h_makedev, 4 | [AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 5 | [[return makedev(0, 0);]])], 6 | [if grep sys/sysmacros.h conftest.err >/dev/null; then 7 | ac_cv_header_sys_types_h_makedev=no 8 | else 9 | ac_cv_header_sys_types_h_makedev=yes 10 | fi], 11 | [ac_cv_header_sys_types_h_makedev=no]) 12 | ]) 13 | 14 | if test $ac_cv_header_sys_types_h_makedev = no; then 15 | AC_CHECK_HEADER(sys/mkdev.h, 16 | [AC_DEFINE(MAJOR_IN_MKDEV, 1, 17 | [Define to 1 if `major', `minor', and `makedev' are 18 | declared in .])]) 19 | 20 | if test $ac_cv_header_sys_mkdev_h = no; then 21 | AC_CHECK_HEADER(sys/sysmacros.h, 22 | [AC_DEFINE(MAJOR_IN_SYSMACROS, 1, 23 | [Define to 1 if `major', `minor', and `makedev' 24 | are declared in .])]) 25 | fi 26 | fi 27 | ]) 28 | -------------------------------------------------------------------------------- /m4/socklen_t.m4: -------------------------------------------------------------------------------- 1 | dnl Check for socklen_t: historically on BSD it is an int, and in 2 | dnl POSIX 1g it is a type of its own, but some platforms use different 3 | dnl types for the argument to getsockopt, getpeername, etc. So we 4 | dnl have to test to find something that will work. 5 | 6 | dnl This is no good, because passing the wrong pointer on C compilers is 7 | dnl likely to only generate a warning, not an error. We don't call this at 8 | dnl the moment. 9 | 10 | AC_DEFUN([TYPE_SOCKLEN_T], 11 | [ 12 | AC_CHECK_TYPE([socklen_t], ,[ 13 | AC_MSG_CHECKING([for socklen_t equivalent]) 14 | AC_CACHE_VAL([rsync_cv_socklen_t_equiv], 15 | [ 16 | # Systems have either "struct sockaddr *" or 17 | # "void *" as the second argument to getpeername 18 | rsync_cv_socklen_t_equiv= 19 | for arg2 in "struct sockaddr" void; do 20 | for t in int size_t unsigned long "unsigned long"; do 21 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 22 | #include 23 | #include 24 | 25 | int getpeername (int, $arg2 *, $t *); 26 | ]],[[ 27 | $t len; 28 | getpeername(0,0,&len); 29 | ]])],[ 30 | rsync_cv_socklen_t_equiv="$t" 31 | break 32 | ]) 33 | done 34 | done 35 | 36 | if test "x$rsync_cv_socklen_t_equiv" = x; then 37 | AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) 38 | fi 39 | ]) 40 | AC_MSG_RESULT($rsync_cv_socklen_t_equiv) 41 | AC_DEFINE_UNQUOTED(socklen_t, $rsync_cv_socklen_t_equiv, 42 | [type to use in place of socklen_t if not defined])], 43 | [#include 44 | #include ]) 45 | ]) 46 | -------------------------------------------------------------------------------- /m4/validate_cache_system_type.m4: -------------------------------------------------------------------------------- 1 | dnl AC_VALIDATE_CACHE_SYSTEM_TYPE[(cmd)] 2 | dnl if the cache file is inconsistent with the current host, 3 | dnl target and build system types, execute CMD or print a default 4 | dnl error message. 5 | AC_DEFUN([AC_VALIDATE_CACHE_SYSTEM_TYPE], [ 6 | AC_REQUIRE([AC_CANONICAL_SYSTEM]) 7 | AC_MSG_CHECKING([config.cache system type]) 8 | if { test x"${ac_cv_host_system_type+set}" = x"set" && 9 | test x"$ac_cv_host_system_type" != x"$host"; } || 10 | { test x"${ac_cv_build_system_type+set}" = x"set" && 11 | test x"$ac_cv_build_system_type" != x"$build"; } || 12 | { test x"${ac_cv_target_system_type+set}" = x"set" && 13 | test x"$ac_cv_target_system_type" != x"$target"; }; then 14 | AC_MSG_RESULT([different]) 15 | ifelse($#, 1, [$1], 16 | [AC_MSG_ERROR(["you must remove config.cache and restart configure"])]) 17 | else 18 | AC_MSG_RESULT([same]) 19 | fi 20 | ac_cv_host_system_type="$host" 21 | ac_cv_build_system_type="$build" 22 | ac_cv_target_system_type="$target" 23 | ]) 24 | -------------------------------------------------------------------------------- /maybe-make-man: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ]; then 4 | echo "Usage: $0 NAME.NUM.md" 1>&2 5 | exit 1 6 | fi 7 | 8 | inname="$1" 9 | srcdir=`dirname "$0"` 10 | flagfile="$srcdir/.md2man-works" 11 | force_flagfile="$srcdir/.md2man-force" 12 | 13 | if [ ! -f "$flagfile" ]; then 14 | # We test our smallest manpage just to see if the python setup works. 15 | if "$srcdir/md-convert" --test "$srcdir/rsync-ssl.1.md" >/dev/null 2>&1; then 16 | touch $flagfile 17 | else 18 | outname=`echo "$inname" | sed 's/\.md$//'` 19 | if [ -f "$outname" ]; then 20 | exit 0 21 | elif [ -f "$srcdir/$outname" ]; then 22 | echo "Copying $srcdir/$outname" 23 | cp -p "$srcdir/$outname" . 24 | exit 0 25 | else 26 | echo "ERROR: $outname cannot be created." 27 | if [ -f "$HOME/build_farm/build_test.fns" ]; then 28 | exit 0 # No exit errorno to avoid a build failure in the samba build farm 29 | else 30 | exit 1 31 | fi 32 | fi 33 | fi 34 | fi 35 | 36 | if [ -f "$force_flagfile" ]; then 37 | opt='--force-link-text' 38 | else 39 | opt='' 40 | fi 41 | 42 | "$srcdir/md-convert" $opt "$srcdir/$inname" 43 | -------------------------------------------------------------------------------- /md2man: -------------------------------------------------------------------------------- 1 | md-convert -------------------------------------------------------------------------------- /mkgitver: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | srcdir=`dirname $0` 4 | 5 | if [ ! -f git-version.h ]; then 6 | touch git-version.h 7 | fi 8 | 9 | if test -d "$srcdir/.git" || test -f "$srcdir/.git"; then 10 | gitver=`git describe --abbrev=8 2>/dev/null` 11 | # NOTE: I'm avoiding "|" in sed since I'm not sure if sed -r is portable and "\|" fails on some OSes. 12 | verchk=`echo "$gitver-" | sed -n '/^v3\.[0-9][0-9]*\.[0-9][0-9]*\(pre[0-9]*\)*-/p'` 13 | if [ -n "$verchk" ]; then 14 | echo "#define RSYNC_GITVER \"$gitver\"" >git-version.h.new 15 | if ! diff git-version.h.new git-version.h >/dev/null; then 16 | echo "Updating git-version.h" 17 | mv git-version.h.new git-version.h 18 | else 19 | rm git-version.h.new 20 | fi 21 | fi 22 | fi 23 | -------------------------------------------------------------------------------- /mkproto.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | 3 | BEGIN { 4 | while ((getline i < "proto.h") > 0) old_protos = old_protos ? old_protos "\n" i : i 5 | close("proto.h") 6 | protos = "/* This file is automatically generated with \"make proto\". DO NOT EDIT */\n" 7 | } 8 | 9 | inheader { 10 | protos = protos "\n" ((inheader = /\)[ \t]*$/ ? 0 : 1) ? $0 : $0 ";") 11 | next 12 | } 13 | 14 | /^FN_(LOCAL|GLOBAL)_[^(]+\([^,()]+/ { 15 | local = /^FN_LOCAL/ 16 | gsub(/^FN_(LOC|GLOB)AL_|,.*$/, "") 17 | sub(/^BOOL\(/, "BOOL ") 18 | sub(/^CHAR\(/, "char ") 19 | sub(/^INTEGER\(/, "int ") 20 | sub(/^STRING\(/, "char *") 21 | protos = protos "\n" $0 (local ? "(int module_id);" : "(void);") 22 | next 23 | } 24 | 25 | /^static|^extern|;/||!/^[A-Za-z][A-Za-z0-9_]* / { next } 26 | 27 | /\(.*\)[ \t]*$/ { 28 | protos = protos "\n" $0 ";" 29 | next 30 | } 31 | 32 | /\(/ { 33 | inheader = 1 34 | protos = protos "\n" $0 35 | } 36 | 37 | END { 38 | if (old_protos != protos) print protos > "proto.h" 39 | system("touch proto.h-tstamp") 40 | } 41 | -------------------------------------------------------------------------------- /packaging/auto-Makefile: -------------------------------------------------------------------------------- 1 | TARGETS := all install install-ssl-daemon install-all install-strip conf gen reconfigure restatus \ 2 | proto man clean cleantests distclean test check check29 check30 installcheck splint \ 3 | doxygen doxygen-upload finddead rrsync 4 | 5 | .PHONY: $(TARGETS) auto-prep 6 | 7 | $(TARGETS): auto-prep 8 | make -C build $@ 9 | 10 | auto-prep: 11 | @if test x`packaging/prep-auto-dir` = x; then echo "auto-build-save is not setup"; exit 1; fi 12 | @echo 'Build branch: '`readlink build/.branch | tr % /` 13 | -------------------------------------------------------------------------------- /packaging/lsb/rsync.spec: -------------------------------------------------------------------------------- 1 | Summary: A fast, versatile, remote (and local) file-copying tool 2 | Name: rsync 3 | Version: 3.4.1 4 | %define fullversion %{version} 5 | Release: 1 6 | %define srcdir src 7 | Group: Applications/Internet 8 | License: GPL 9 | Source0: https://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz 10 | #Source1: https://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-patches-%{fullversion}.tar.gz 11 | URL: https://rsync.samba.org/ 12 | 13 | Prefix: %{_prefix} 14 | BuildRoot: /var/tmp/%{name}-root 15 | 16 | %package ssl-daemon 17 | Summary: An stunnel config file to support ssl rsync daemon connections. 18 | Group: Applications/Internet 19 | Requires: rsync, stunnel >= 4 20 | 21 | %description 22 | Rsync is a fast and extraordinarily versatile file copying tool. It can 23 | copy locally, to/from another host over any remote shell, or to/from a 24 | remote rsync daemon. It offers a large number of options that control 25 | every aspect of its behavior and permit very flexible specification of the 26 | set of files to be copied. It is famous for its delta-transfer algorithm, 27 | which reduces the amount of data sent over the network by sending only the 28 | differences between the source files and the existing files in the 29 | destination. Rsync is widely used for backups and mirroring and as an 30 | improved copy command for everyday use. 31 | 32 | %description ssl-daemon 33 | Provides a config file for stunnel that will (if you start your stunnel 34 | service) cause stunnel to listen for ssl rsync-daemon connections and run 35 | "rsync --daemon" to handle them. 36 | 37 | %prep 38 | # Choose one -- setup source only, or setup source + rsync-patches: 39 | %setup -q -n rsync-%{fullversion} 40 | #%setup -q -b1 -n rsync-%{fullversion} 41 | 42 | # If you you used "%setup -q -b1 ...", choose the patches you wish to apply: 43 | #patch -p1 83 | Released 3.4.1. 84 | -------------------------------------------------------------------------------- /packaging/lsb/rsync.xinetd: -------------------------------------------------------------------------------- 1 | # default: off 2 | # description: The rsync server is a good addition to an ftp server, as it 3 | # allows crc checksumming etc. 4 | service rsync 5 | { 6 | disable = yes 7 | socket_type = stream 8 | wait = no 9 | user = root 10 | server = /usr/bin/rsync 11 | server_args = --daemon 12 | log_on_failure += USERID 13 | } 14 | -------------------------------------------------------------------------------- /packaging/openssl-rsync.cnf: -------------------------------------------------------------------------------- 1 | # This config file can be used with rsync to enable legacy digests 2 | # (such as MD4) by using the OPENSSL_CONF environment variable. 3 | # See rsync's configure --with-openssl-conf=/path/name option. 4 | 5 | openssl_conf = openssl_init 6 | 7 | [openssl_init] 8 | providers = provider_sect 9 | 10 | [provider_sect] 11 | default = default_sect 12 | legacy = legacy_sect 13 | 14 | [default_sect] 15 | activate = 1 16 | 17 | [legacy_sect] 18 | activate = 1 19 | -------------------------------------------------------------------------------- /packaging/prep-auto-dir: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # This script will setup the build dir based on the current git branch and the 4 | # directory auto-build-save/$BRANCH. We don't use a symlink for the build dir 5 | # because we want to maximize the ccache reuse, so all builds must happen in 6 | # the same real dir. When a dir is moved out of auto-build-save/$BRANCH to the 7 | # build dir, it is replaced with a symlink so that it can still be found under 8 | # that dir. The build dir also gets a .branch -> $BRANCH symlink so that we 9 | # can figure out the current build dir's branch. 10 | 11 | # To get started, just clone the rsync git repo and create the auto-build-save 12 | # dir. If you have an existing git checkout and it is not in a pristine state, 13 | # run "make distclean" before creating the auto-build-save dir. 14 | 15 | auto_top='auto-build-save' 16 | if test -d $auto_top && test -d .git; then 17 | desired_branch=`git rev-parse --abbrev-ref HEAD | tr / %` 18 | if test "$desired_branch" = HEAD; then 19 | echo "ERROR: switch to the right build dir manually when in detached HEAD mode." 1>&2 20 | exit 1 21 | fi 22 | auto_dir="$auto_top/$desired_branch" 23 | if test -d build; then 24 | cur_branch=`readlink build/.branch` 25 | else 26 | cur_branch='/' 27 | fi 28 | if test "$desired_branch" != "$cur_branch"; then 29 | if test "$cur_branch" != /; then 30 | rm -f "$auto_top/$cur_branch" 31 | mv build "$auto_top/$cur_branch" 32 | fi 33 | test -d "$auto_dir" || mkdir "$auto_dir" 34 | test -h "$auto_dir/.branch" || ln -s "$desired_branch" "$auto_dir/.branch" 35 | mv "$auto_dir" build 36 | ln -s ../build "$auto_dir" 37 | fi 38 | if test ! -h Makefile; then 39 | rm -f Makefile 40 | ln -s packaging/auto-Makefile Makefile 41 | fi 42 | echo $desired_branch 43 | fi 44 | -------------------------------------------------------------------------------- /packaging/samba-rsync: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script makes it easy to update the ftp & html directories on the samba.org server. 3 | # It expects the 2 *_DEST directories to contain updated files that need to be sent to 4 | # the remote server. If these directories don't exist yet, they will be copied from the 5 | # remote server (while also making the html dir a git checkout). 6 | 7 | FTP_SRC="$HOME/samba-rsync-ftp" 8 | HTML_SRC="$HOME/samba-rsync-html" 9 | 10 | FTP_DEST="/home/ftp/pub/rsync" 11 | HTML_DEST="/home/httpd/html/rsync" 12 | 13 | HTML_GIT='git.samba.org:/data/git/rsync-web.git' 14 | 15 | export RSYNC_PARTIAL_DIR='' 16 | 17 | case "$RSYNC_SAMBA_HOST" in 18 | *.samba.org) ;; 19 | *) 20 | echo "You must set RSYNC_SAMBA_HOST in your environment to the samba hostname to use." >&2 21 | exit 1 22 | ;; 23 | esac 24 | 25 | MODE='' 26 | REVERSE='' 27 | while (( $# )); do 28 | case "$1" in 29 | -R|--reverse) REVERSE=yes ;; 30 | f|ftp) MODE=ftp ;; 31 | h|html) MODE=html ;; 32 | -h|--help) 33 | echo "Usage: [-R] [f|ftp|h|html]" 34 | echo "-R --reverse Copy the files from the server to the local host." 35 | echo " The default is to update the remote files." 36 | echo "-h --help Output this help message." 37 | echo " " 38 | echo "The script will prompt if ftp or html is not specified on the command line." 39 | echo "Only one category can be copied at a time. When pulling html files, a git" 40 | echo "checkout will be either created or updated prior to the rsync copy." 41 | exit 42 | ;; 43 | *) 44 | echo "Invalid option: $1" >&2 45 | exit 1 46 | ;; 47 | esac 48 | shift 49 | done 50 | 51 | while [ ! "$MODE" ]; do 52 | if [ "$REVERSE" = yes ]; then 53 | DIRECTION=FROM 54 | else 55 | DIRECTION=TO 56 | fi 57 | echo -n "Copy which files $DIRECTION the server? ftp or html? " 58 | read ans 59 | case "$ans" in 60 | f*) MODE=ftp ;; 61 | h*) MODE=html ;; 62 | '') exit 1 ;; 63 | *) echo "You must answer f or h to copy the ftp or html data." ;; 64 | esac 65 | done 66 | 67 | if [ "$MODE" = ftp ]; then 68 | SRC_DIR="$FTP_SRC" 69 | DEST_DIR="$FTP_DEST" 70 | FILT=".filt" 71 | else 72 | SRC_DIR="$HTML_SRC" 73 | DEST_DIR="$HTML_DEST" 74 | FILT="filt" 75 | fi 76 | 77 | function do_rsync { 78 | rsync --dry-run "${@}" | grep -v 'is uptodate$' 79 | echo '' 80 | echo -n "Run without --dry-run? [n] " 81 | read ans 82 | case "$ans" in 83 | y*) rsync "${@}" | grep -v 'is uptodate$' ;; 84 | esac 85 | } 86 | 87 | if [ -d "$SRC_DIR" ]; then 88 | REVERSE_RSYNC=do_rsync 89 | else 90 | echo "The directory $SRC_DIR does not exist yet." 91 | echo -n "Do you want to create it? [n] " 92 | read ans 93 | case "$ans" in 94 | y*) ;; 95 | *) exit 1 ;; 96 | esac 97 | REVERSE=yes 98 | REVERSE_RSYNC=rsync 99 | fi 100 | 101 | if [ "$REVERSE" = yes ]; then 102 | OPTS='-aivOHP' 103 | TMP_FILT="$SRC_DIR/tmp-filt" 104 | echo "Copying files from $RSYNC_SAMBA_HOST to $SRC_DIR ..." 105 | if [ "$MODE" = html ]; then 106 | if [ $REVERSE_RSYNC = rsync ]; then 107 | git clone "$HTML_GIT" "$SRC_DIR" || exit 1 108 | else 109 | cd "$SRC_DIR" || exit 1 110 | git pull || exit 1 111 | fi 112 | sed -n -e 's/[-P]/H/p' "$SRC_DIR/$FILT" >"$TMP_FILT" 113 | OPTS="${OPTS}f._$TMP_FILT" 114 | else 115 | OPTS="${OPTS}f:_$FILT" 116 | fi 117 | $REVERSE_RSYNC "$OPTS" "$RSYNC_SAMBA_HOST:$DEST_DIR/" "$SRC_DIR/" 118 | rm -f "$TMP_FILT" 119 | exit 120 | fi 121 | 122 | cd "$SRC_DIR" || exit 1 123 | echo "Copying files from $SRC_DIR to $RSYNC_SAMBA_HOST ..." 124 | do_rsync -aivOHP --chown=:rsync --del -f._$FILT . "$RSYNC_SAMBA_HOST:$DEST_DIR/" 125 | -------------------------------------------------------------------------------- /packaging/send-news: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # This script expects the ~/src/rsync directory to contain the rsync 4 | # source that has been updated. It also expects the auto-build-save 5 | # directory to have been created prior to the running of configure so 6 | # that each branch has its own build directory underneath. This supports 7 | # the maintainer workflow for the rsync-patches files maintenace. 8 | 9 | FTP_SRC="$HOME/samba-rsync-ftp" 10 | FTP_DEST="/home/ftp/pub/rsync" 11 | MD_FILES="README.md INSTALL.md NEWS.md" 12 | 13 | case "$RSYNC_SAMBA_HOST" in 14 | *.samba.org) ;; 15 | *) 16 | echo "You must set RSYNC_SAMBA_HOST in your environment to the samba hostname to use." >&2 17 | exit 1 18 | ;; 19 | esac 20 | 21 | if [ ! -d "$FTP_SRC" ]; then 22 | packaging/samba-rsync ftp # Ask to initialize the local ftp dir 23 | fi 24 | 25 | cd ~/src/rsync 26 | 27 | make man 28 | ./md-convert --dest="$FTP_SRC" $MD_FILES 29 | rsync -aiic $MD_FILES auto-build-save/master/*.?.html "$FTP_SRC" 30 | 31 | cd "$FTP_SRC" 32 | 33 | rsync -aiic README.* INSTALL.* NEWS.* *.?.html "$RSYNC_SAMBA_HOST:$FTP_DEST/" 34 | -------------------------------------------------------------------------------- /packaging/smart-make: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | export LANG=C 6 | 7 | branch=`packaging/prep-auto-dir` 8 | if test x"$branch" = x; then 9 | srcdir=. 10 | else 11 | cd build 12 | srcdir=.. 13 | fi 14 | 15 | if test -f configure.sh; then 16 | cp -p configure.sh configure.sh.old 17 | else 18 | touch configure.sh.old 19 | fi 20 | 21 | if test -f .fetch; then 22 | $srcdir/prepare-source fetch 23 | else 24 | $srcdir/prepare-source 25 | fi 26 | 27 | if diff configure.sh configure.sh.old >/dev/null 2>&1; then 28 | echo "configure.sh is unchanged." 29 | rm configure.sh.old 30 | else 31 | echo "configure.sh has CHANGED." 32 | if test -f config.status; then 33 | ./config.status --recheck 34 | else 35 | $srcdir/configure 36 | fi 37 | fi 38 | 39 | ./config.status 40 | 41 | make all 42 | 43 | if test x"$1" = x"check"; then 44 | make check 45 | fi 46 | -------------------------------------------------------------------------------- /packaging/solaris/build_pkg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Shell script for building Solaris package of rsync 3 | # Author: Jens Apel 4 | # License: GPL 5 | # 6 | # BASEDIR is /usr/local and should be the same as the 7 | # --prefix parameter of configure 8 | # 9 | # this script should be copied under 10 | # packaging/solaris/5.8/build_pkg.sh 11 | 12 | # Definitions start here 13 | # you can edit this, if you like 14 | 15 | # The Package name under which rsync will b installed 16 | PKGNAME=SMBrsync 17 | 18 | # Extract common info requires for the 'info' part of the package. 19 | # This should be made generic and generated by the configure script 20 | # but for now it is hard coded 21 | BASEDIR=/usr/local 22 | VERSION="2.5.5" 23 | ARCH=`uname -p` 24 | NAME=rsync 25 | 26 | # Definitions end here 27 | # Please do not edit below this line or you know what you do. 28 | 29 | ## Start by faking root install 30 | echo "Creating install directory (fake $BASEDIR)..." 31 | START=`pwd` 32 | FAKE_ROOT=$START/${PKGNAME} 33 | mkdir $FAKE_ROOT 34 | 35 | # copy the binary and the man page to their places 36 | mkdir $FAKE_ROOT/bin 37 | mkdir -p $FAKE_ROOT/doc/rsync 38 | mkdir -p $FAKE_ROOT/man/man1 39 | mkdir -p $FAKE_ROOT/man/man5 40 | 41 | cp ../../../rsync $FAKE_ROOT/bin/rsync 42 | cp ../../../rsync.1 $FAKE_ROOT/man/man1/rsync.1 43 | cp ../../../rsyncd.conf.5 $FAKE_ROOT/man/man5/rsyncd.conf.5 44 | cp ../../../README.md $FAKE_ROOT/doc/rsync/README.md 45 | cp ../../../COPYING $FAKE_ROOT/doc/rsync/COPYING 46 | cp ../../../tech_report.pdf $FAKE_ROOT/doc/rsync/tech_report.pdf 47 | cp ../../../COPYING $FAKE_ROOT/COPYING 48 | 49 | ## Build info file 50 | echo "Building pkginfo file..." 51 | cat > $FAKE_ROOT/pkginfo << EOF_INFO 52 | PKG=$PKGNAME 53 | NAME=$NAME 54 | DESC="Program for efficient remote updates of files." 55 | VENDOR="Samba Team URL: http://samba.anu.edu.au/rsync/" 56 | BASEDIR=$BASEDIR 57 | ARCH=$ARCH 58 | VERSION=$VERSION 59 | CATEGORY=application 60 | CLASSES=none 61 | EOF_INFO 62 | 63 | ## Build prototype file 64 | cat > $FAKE_ROOT/prototype << EOFPROTO 65 | i copyright=COPYING 66 | i pkginfo=pkginfo 67 | d none bin 0755 bin bin 68 | f none bin/rsync 0755 bin bin 69 | d none doc 0755 bin bin 70 | d none doc/$NAME 0755 bin bin 71 | f none doc/$NAME/README.md 0644 bin bin 72 | f none doc/$NAME/COPYING 0644 bin bin 73 | f none doc/$NAME/tech_report.pdf 0644 bin bin 74 | d none man 0755 bin bin 75 | d none man/man1 0755 bin bin 76 | f none man/man1/rsync.1 0644 bin bin 77 | d none man/man5 0755 bin bin 78 | f none man/man5/rsyncd.conf.5 0644 bin bin 79 | EOFPROTO 80 | 81 | ## And now build the package. 82 | OUTPUTFILE=$PKGNAME-$VERSION-sol8-$ARCH-local.pkg 83 | echo "Building package.." 84 | echo FAKE_ROOT = $FAKE_ROOT 85 | cd $FAKE_ROOT 86 | pkgmk -d . -r . -f ./prototype -o 87 | pkgtrans -os . $OUTPUTFILE $PKGNAME 88 | 89 | mv $OUTPUTFILE .. 90 | cd .. 91 | 92 | # Comment this out if you want to see, which file structure has been created 93 | rm -rf $FAKE_ROOT 94 | 95 | -------------------------------------------------------------------------------- /packaging/systemd/rsync.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=fast remote file copy program daemon 3 | ConditionPathExists=/etc/rsyncd.conf 4 | After=network.target 5 | Documentation=man:rsync(1) man:rsyncd.conf(5) 6 | 7 | [Service] 8 | ExecStart=/usr/bin/rsync --daemon --no-detach 9 | RestartSec=1 10 | Restart=on-failure 11 | 12 | # Citing README.md: 13 | # 14 | # [...] Using ssh is recommended for its security features. 15 | # 16 | # Alternatively, rsync can run in `daemon' mode, listening on a socket. 17 | # This is generally used for public file distribution, [...] 18 | # 19 | # So let's assume some extra security is more than welcome here. We do full 20 | # system protection (which makes /usr, /boot, & /etc read-only) and hide 21 | # devices. To override these defaults, it's best to do so in the drop-in 22 | # directory, often done via `systemctl edit rsync.service`. The file needs 23 | # just the bare minimum of the right [heading] and override values. 24 | # See systemd.unit(5) and search for "drop-in" for full details. 25 | 26 | ProtectSystem=full 27 | #ProtectHome=on|off|read-only 28 | PrivateDevices=on 29 | NoNewPrivileges=on 30 | 31 | [Install] 32 | WantedBy=multi-user.target 33 | -------------------------------------------------------------------------------- /packaging/systemd/rsync.socket: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=socket for fast remote file copy program daemon 3 | Conflicts=rsync.service 4 | 5 | [Socket] 6 | ListenStream=873 7 | Accept=true 8 | 9 | [Install] 10 | WantedBy=sockets.target 11 | -------------------------------------------------------------------------------- /packaging/systemd/rsync@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=fast remote file copy program daemon 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=-/usr/bin/rsync --daemon 7 | StandardInput=socket 8 | StandardOutput=inherit 9 | StandardError=journal 10 | 11 | # Citing README.md: 12 | # 13 | # [...] Using ssh is recommended for its security features. 14 | # 15 | # Alternatively, rsync can run in `daemon' mode, listening on a socket. 16 | # This is generally used for public file distribution, [...] 17 | # 18 | # So let's assume some extra security is more than welcome here. We do full 19 | # system protection (which makes /usr, /boot, & /etc read-only) and hide 20 | # devices. To override these defaults, it's best to do so in the drop-in 21 | # directory, often done via `systemctl edit rsync@.service`. The file needs 22 | # just the bare minimum of the right [heading] and override values. 23 | # See systemd.unit(5) and search for "drop-in" for full details. 24 | 25 | ProtectSystem=full 26 | #ProtectHome=on|off|read-only 27 | PrivateDevices=on 28 | NoNewPrivileges=on 29 | -------------------------------------------------------------------------------- /packaging/year-tweak: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # This uses the output from "support/git-set-file-times --list" to discern 4 | # the last-modified year of each *.c & *.h file and updates the copyright 5 | # year if it isn't set right. 6 | 7 | import sys, os, re, argparse, subprocess 8 | from datetime import datetime 9 | 10 | def main(): 11 | latest_year = '2000' 12 | 13 | proc = subprocess.Popen('support/git-set-file-times --list'.split(), stdout=subprocess.PIPE, encoding='utf-8') 14 | for line in proc.stdout: 15 | m = re.match(r'^\S\s+(?P\d\d\d\d)\S+\s+\S+\s+(?P.+)', line) 16 | if not m: 17 | print("Failed to parse line from git-set-file-times:", line) 18 | sys.exit(1) 19 | m = argparse.Namespace(**m.groupdict()) 20 | if m.year > latest_year: 21 | latest_year = m.year 22 | proc.communicate() 23 | 24 | fn = 'latest-year.h' 25 | with open(fn, 'r', encoding='utf-8') as fh: 26 | old_txt = fh.read() 27 | 28 | txt = f'#define LATEST_YEAR "{latest_year}"\n' 29 | if txt != old_txt: 30 | print(f"Updating {fn} with year {latest_year}") 31 | with open(fn, 'w', encoding='utf-8') as fh: 32 | fh.write(txt) 33 | 34 | 35 | if __name__ == '__main__': 36 | parser = argparse.ArgumentParser(description="Grab the year of the last mod for our c & h files and make sure the LATEST_YEAR value is accurate.") 37 | args = parser.parse_args() 38 | main() 39 | 40 | # vim: sw=4 et 41 | -------------------------------------------------------------------------------- /popt/CHANGES: -------------------------------------------------------------------------------- 1 | 1.5 -> 1.6 2 | - add ability to perform callbacks for every, not just first, match. 3 | 4 | 1.3 -> 1.5 5 | - heavy dose of const's 6 | - poptParseArgvString() now NULL terminates the list 7 | 8 | 1.2.3 -> 1.3 9 | - added support for single - 10 | - misc bug fixes 11 | - portability improvements 12 | 13 | 1.2.2 -> 1.2.3 14 | - fixed memset() in help message generation (Dale Hawkins) 15 | - added extern "C" stuff to popt.h for C++ compilers (Dale Hawkins) 16 | - const'ified poptParseArgvString (Jeff Garzik) 17 | 18 | 1.2.1 -> 1.2.2 19 | - fixed bug in chaind alias happens which seems to have only 20 | affected --triggers in rpm 21 | - added POPT_ARG_VAL 22 | - popt.3 installed by default 23 | 24 | 1.2 -> 1.2.1 25 | - added POPT_ARG_INTL_DOMAIN (Elliot Lee) 26 | - updated Makefile's to be more GNUish (Elliot Lee) 27 | 28 | 1.1 -> 1.2 29 | - added popt.3 man page (Robert Lynch) 30 | - don't use mmap anymore (its lack of portability isn't worth the 31 | trouble) 32 | - added test script 33 | - added support for exec 34 | - removed support for *_POPT_ALIASES env variable -- it was a bad 35 | idea 36 | - reorganized into multiple source files 37 | - added automatic help generation, POPT_AUTOHELP 38 | - added table callbacks 39 | - added table inclusion 40 | - updated man page for new features 41 | - added test scripts 42 | 43 | 1.0 -> 1.1 44 | - moved to autoconf (Fred Fish) 45 | - added STRERROR replacement (Norbert Warmuth) 46 | - added const keywords (Bruce Perens) 47 | -------------------------------------------------------------------------------- /popt/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 1998 Red Hat Software 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 17 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | Except as contained in this notice, the name of the X Consortium shall not be 21 | used in advertising or otherwise to promote the sale, use or other dealings 22 | in this Software without prior written authorization from the X Consortium. 23 | -------------------------------------------------------------------------------- /popt/README: -------------------------------------------------------------------------------- 1 | This is the popt command line option parsing library. While it is similiar 2 | to getopt(3), it contains a number of enhancements, including: 3 | 4 | 1) popt is fully reentrant 5 | 2) popt can parse arbitrary argv[] style arrays while 6 | getopt(2) makes this quite difficult 7 | 3) popt allows users to alias command line arguments 8 | 4) popt provides convience functions for parsing strings 9 | into argv[] style arrays 10 | 11 | popt is used by rpm, the Red Hat install program, and many other Red Hat 12 | utilities, all of which provide excellent examples of how to use popt. 13 | Complete documentation on popt is available in popt.ps (included in this 14 | tarball), which is excerpted with permission from the book "Linux 15 | Application Development" by Michael K. Johnson and Erik Troan (availble 16 | from Addison Wesley in May, 1998). 17 | 18 | Comments on popt should be addressed to ewt@redhat.com. 19 | -------------------------------------------------------------------------------- /popt/README.rsync: -------------------------------------------------------------------------------- 1 | This is a perfectly ordinary copy of libpopt. It is only used on platforms 2 | that do not have a sufficiently up-to-date copy of their own. If you build 3 | rsync on a platform which has popt, this directory should not be used. (You 4 | can control that using the --with-included-popt configure flag.) 5 | -------------------------------------------------------------------------------- /popt/dummy.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RsyncProject/rsync/9994933c8ccf7ead27c81fe4ce2eb4e08af20c7f/popt/dummy.in -------------------------------------------------------------------------------- /popt/system.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | */ 4 | 5 | #ifdef HAVE_CONFIG_H 6 | #include "config.h" 7 | #endif 8 | 9 | #include 10 | 11 | /* XXX isspace(3) has i18n encoding signedness issues on Solaris. */ 12 | #define _isspaceptr(_chp) isspace((int)(*(unsigned const char *)(_chp))) 13 | 14 | #ifdef HAVE_MCHECK_H 15 | #include 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | void * xmalloc (size_t size); 23 | 24 | void * xcalloc (size_t nmemb, size_t size); 25 | 26 | void * xrealloc (void * ptr, size_t size); 27 | 28 | char * xstrdup (const char *str); 29 | 30 | #if !defined(HAVE_STPCPY) 31 | /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ 32 | static inline char * stpcpy (char *dest, const char * src) { 33 | register char *d = dest; 34 | register const char *s = src; 35 | 36 | do 37 | *d++ = *s; 38 | while (*s++ != '\0'); 39 | return d - 1; 40 | } 41 | #endif 42 | 43 | /* Memory allocation via macro defs to get meaningful locations from mtrace() */ 44 | #if defined(HAVE_MCHECK_H) && defined(__GNUC__) 45 | #define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) 46 | #define xmalloc(_size) (malloc(_size) ? : vmefail()) 47 | #define xcalloc(_nmemb, _size) (calloc((_nmemb), (_size)) ? : vmefail()) 48 | #define xrealloc(_ptr, _size) (realloc((_ptr), (_size)) ? : vmefail()) 49 | #define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str))) 50 | #else 51 | #define xmalloc(_size) malloc(_size) 52 | #define xcalloc(_nmemb, _size) calloc((_nmemb), (_size)) 53 | #define xrealloc(_ptr, _size) realloc((_ptr), (_size)) 54 | #define xstrdup(_str) strdup(_str) 55 | #endif /* defined(HAVE_MCHECK_H) && defined(__GNUC__) */ 56 | 57 | #if defined(HAVE_SECURE_GETENV) 58 | #define getenv(_s) secure_getenv(_s) 59 | #elif defined(HAVE___SECURE_GETENV) 60 | #define getenv(_s) __secure_getenv(_s) 61 | #endif 62 | 63 | #if !defined(__GNUC__) && !defined(__attribute__) 64 | #define __attribute__(x) 65 | #endif 66 | #define UNUSED(x) x __attribute__((__unused__)) 67 | #define FORMAT(a, b, c) __attribute__((__format__ (a, b, c))) 68 | #define NORETURN __attribute__((__noreturn__)) 69 | 70 | #include "popt.h" 71 | -------------------------------------------------------------------------------- /prepare-source: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Either use autoconf and autoheader to create configure.sh and config.h.in 3 | # or (optionally) fetch the latest development versions of generated files. 4 | # 5 | # Specify one action or more than one to provide a fall-back: 6 | # 7 | # build build the config files [the default w/no arg] 8 | # fetch fetch the latest dev autoconfig files 9 | # fetchgen fetch all the latest dev generated files (including manpages) 10 | # fetchSRC fetch the latest dev source files [NON-GENERATED FILES] 11 | # 12 | # The script stops after the first successful action. 13 | 14 | dir=`dirname $0` 15 | if test x"$dir" = x; then 16 | dir=. 17 | fi 18 | 19 | if test "$dir" = '.'; then 20 | branch=`packaging/prep-auto-dir` || exit 1 21 | if test x"$branch" != x; then 22 | cd build || exit 1 23 | dir=.. 24 | fi 25 | fi 26 | 27 | if test "$dir" != '.'; then 28 | for lnk in configure.ac m4; do 29 | if test ! -h $lnk; then 30 | rm -f $lnk # Just in case 31 | ln -s "$dir/$lnk" $lnk 32 | fi 33 | done 34 | for fn in configure.sh config.h.in aclocal.m4; do 35 | test ! -f $fn && test -f "$dir/$fn" && cp -p "$dir/$fn" $fn 36 | done 37 | fi 38 | 39 | if test $# = 0; then 40 | set -- build 41 | fi 42 | 43 | for action in "${@}"; do 44 | case "$action" in 45 | build|make) 46 | make -f "$dir/prepare-source.mak" 47 | ;; 48 | fetch|fetchgen) 49 | if test "$action" = fetchgen; then 50 | match='*' 51 | else 52 | match='[ca]*' 53 | fi 54 | $dir/rsync-ssl -iipc --no-motd "rsync://download.samba.org/rsyncftp/generated-files/$match" ./ 55 | test $? != 0 && continue 56 | sleep 1 # The following files need to be newer than aclocal.m4 57 | touch configure.sh config.h.in 58 | ;; 59 | fetchSRC) 60 | ./rsync-ssl -iipr --no-motd --exclude=/.git/ rsync://download.samba.org/ftp/pub/unpacked/rsync/ . 61 | ;; 62 | *) 63 | echo "Unknown action: $action" 64 | exit 1 65 | ;; 66 | esac 67 | if test $? = 0; then 68 | exit 69 | fi 70 | done 71 | 72 | exit 1 73 | -------------------------------------------------------------------------------- /prepare-source.mak: -------------------------------------------------------------------------------- 1 | SHELL=/bin/sh 2 | 3 | conf: configure.sh config.h.in 4 | .PHONY: conf 5 | 6 | aclocal.m4: m4/*.m4 7 | aclocal -I m4 8 | 9 | configure.sh: configure.ac aclocal.m4 10 | autoconf -o configure.sh 11 | 12 | config.h.in: configure.ac aclocal.m4 13 | autoheader && touch config.h.in 14 | -------------------------------------------------------------------------------- /rounding.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A pre-compilation helper program to aid in the creation of rounding.h. 3 | * 4 | * Copyright (C) 2007-2020 Wayne Davison 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, visit the http://fsf.org website. 18 | */ 19 | 20 | #include "rsync.h" 21 | 22 | #define ARRAY_LEN (EXTRA_ROUNDING+1) 23 | #define SIZEOF(x) ((long int)sizeof (x)) 24 | 25 | struct test { 26 | union file_extras extras[ARRAY_LEN]; 27 | int64 test; 28 | }; 29 | 30 | #define ACTUAL_SIZE SIZEOF(struct test) 31 | #define EXPECTED_SIZE (SIZEOF(union file_extras) * ARRAY_LEN + SIZEOF(int64)) 32 | 33 | int main(UNUSED(int argc), UNUSED(char *argv[])) 34 | { 35 | static int test_array[1 - 2 * (ACTUAL_SIZE != EXPECTED_SIZE)]; 36 | test_array[0] = 0; 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /rsyncsh.txt: -------------------------------------------------------------------------------- 1 | rsyncsh 2 | Copyright (C) 2001 by Martin Pool 3 | 4 | This is a quick hack to build an interactive shell around rsync, the 5 | same way we have the ftp, lftp and ncftp programs for the FTP 6 | protocol. The key application for this is connecting to a public 7 | rsync server, such as rsync.kernel.org, change down through and list 8 | directories, and finally pull down the file you want. 9 | 10 | rsync is somewhat ill-at-ease as an interactive operation, since every 11 | network connection is used to carry out exactly one operation. rsync 12 | kind of "forks across the network" passing the options and filenames 13 | to operate upon, and the connection is closed when the transfer is 14 | complete. (This might be fixed in the future, either by adapting the 15 | current protocol to allow chained operations over a single socket, or 16 | by writing a new protocol that better supports interactive use.) 17 | 18 | So, rsyncsh runs a new rsync command and opens a new socket for every 19 | (network-based) command you type. 20 | 21 | This has two consequences. Firstly, there is more command latency 22 | than is really desirable. More seriously, if the connection cannot be 23 | done automatically, because for example it uses SSH with a password, 24 | then you will need to enter the password every time. We might even 25 | fix this in the future, though, by having a way to automatically feed 26 | the password to SSH if it's entered once. 27 | -------------------------------------------------------------------------------- /shconfig.in: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # config.sh.in 4 | 5 | # This file is processed by config.status to produce config.status, 6 | # containing autoconf-determined values needed by the test scripts. 7 | 8 | ECHO_T="@ECHO_T@" 9 | ECHO_N="@ECHO_N@" 10 | ECHO_C="@ECHO_C@" 11 | HOST_OS="@host_os@" 12 | SHELL_PATH="@SHELL_PATH@" 13 | FAKEROOT_PATH="@FAKEROOT_PATH@" 14 | 15 | export ECHO_T ECHO_N ECHO_C HOST_OS SHELL_PATH FAKEROOT_PATH 16 | -------------------------------------------------------------------------------- /simd-checksum-avx2.S: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #ifdef USE_ROLL_ASM /* { */ 4 | 5 | #define CHAR_OFFSET 0 /* Keep this the same as rsync.h, which isn't likely to change. */ 6 | 7 | #ifdef __APPLE__ 8 | #define get_checksum1_avx2_asm _get_checksum1_avx2_asm 9 | #endif 10 | 11 | .intel_syntax noprefix 12 | .text 13 | 14 | .p2align 5 15 | .globl get_checksum1_avx2_asm 16 | 17 | # rdi=*buf, esi=len, edx=i, rcx= *ps1, r8= *ps2 18 | get_checksum1_avx2_asm: 19 | vmovd xmm6,[rcx] # load *ps1 20 | lea eax, [rsi-128] # at least 128 bytes to process? 21 | cmp edx, eax 22 | jg .exit 23 | lea rax, .mul_T2[rip] 24 | vmovntdqa ymm7, [rax] # load T2 multiplication constants 25 | vmovntdqa ymm12,[rax+32]# from memory. 26 | vpcmpeqd ymm15, ymm15, ymm15 # set all elements to -1. 27 | 28 | #if CHAR_OFFSET != 0 29 | mov eax, 32*CHAR_OFFSET 30 | vmovd xmm10, eax 31 | vpbroadcastd ymm10, xmm10 32 | mov eax, 528*CHAR_OFFSET 33 | vmovd xmm13, eax 34 | vpbroadcastd ymm13, xmm13 35 | #endif 36 | vpabsb ymm15, ymm15 # set all byte size elements to 1. 37 | add rdi, rdx 38 | vmovdqu ymm2, [rdi] # preload the first 64 bytes. 39 | vmovdqu ymm3, [rdi+32] 40 | and esi, ~63 # only needed during final reduction, 41 | # done here to avoid a longer nop for 42 | # alignment below. 43 | add edx, esi 44 | shr rsi, 6 # longer opcode for alignment 45 | add rdi, 64 46 | vpxor xmm1, xmm1, xmm1 # reset both partial sums accumulators. 47 | vpxor xmm4, xmm4, xmm4 48 | mov eax, [r8] 49 | .p2align 4 # should fit into the LSD allocation queue. 50 | .loop: 51 | vpmaddubsw ymm0, ymm15, ymm2 # s1 partial sums 52 | vpmaddubsw ymm5, ymm15, ymm3 53 | vmovdqu ymm8, [rdi] # preload the next 54 | vmovdqu ymm9, [rdi+32] # 64 bytes. 55 | add rdi, 64 56 | vpaddd ymm4, ymm4, ymm6 57 | vpaddw ymm5, ymm5, ymm0 58 | vpsrld ymm0, ymm5, 16 59 | vpaddw ymm5, ymm0, ymm5 60 | vpaddd ymm6, ymm5, ymm6 61 | vpmaddubsw ymm2, ymm7, ymm2 # s2 partial sums 62 | vpmaddubsw ymm3, ymm12, ymm3 63 | prefetcht0 [rdi+384] # prefetch 6 cachelines ahead. 64 | vpaddw ymm3, ymm2, ymm3 65 | vpsrldq ymm2, ymm3, 2 66 | vpaddd ymm3, ymm2, ymm3 67 | vpaddd ymm1, ymm1, ymm3 68 | 69 | #if CHAR_OFFSET != 0 70 | vpaddd ymm6, ymm10, ymm6 # 32*CHAR_OFFSET 71 | vpaddd ymm1, ymm13, ymm1 # 528*CHAR_OFFSET 72 | #endif 73 | vmovdqa ymm2, ymm8 # move the next 64 bytes 74 | vmovdqa ymm3, ymm9 # into the right registers 75 | sub esi, 1 76 | jnz .loop 77 | 78 | # now we reduce the partial sums. 79 | vpslld ymm3, ymm4, 6 80 | vpsrldq ymm2, ymm6, 4 81 | 82 | vpaddd ymm0, ymm3, ymm1 83 | vpaddd ymm6, ymm2, ymm6 84 | vpsrlq ymm3, ymm0, 32 85 | 86 | vpsrldq ymm2, ymm6, 8 87 | vpaddd ymm0, ymm3, ymm0 88 | vpsrldq ymm3, ymm0, 8 89 | vpaddd ymm6, ymm2, ymm6 90 | vpaddd ymm0, ymm3, ymm0 91 | vextracti128 xmm2, ymm6, 0x1 92 | vextracti128 xmm1, ymm0, 0x1 93 | vpaddd xmm6, xmm2, xmm6 94 | vmovd [rcx], xmm6 95 | vpaddd xmm1, xmm1, xmm0 96 | vmovd ecx, xmm1 97 | add eax, ecx 98 | mov [r8], eax 99 | .exit: 100 | vzeroupper 101 | mov eax, edx 102 | ret 103 | 104 | #ifdef __APPLE__ 105 | .data 106 | .align 6 107 | #else 108 | .section .rodata 109 | .p2align 6 110 | #endif 111 | .mul_T2: 112 | .byte 64 113 | .byte 63 114 | .byte 62 115 | .byte 61 116 | .byte 60 117 | .byte 59 118 | .byte 58 119 | .byte 57 120 | .byte 56 121 | .byte 55 122 | .byte 54 123 | .byte 53 124 | .byte 52 125 | .byte 51 126 | .byte 50 127 | .byte 49 128 | .byte 48 129 | .byte 47 130 | .byte 46 131 | .byte 45 132 | .byte 44 133 | .byte 43 134 | .byte 42 135 | .byte 41 136 | .byte 40 137 | .byte 39 138 | .byte 38 139 | .byte 37 140 | .byte 36 141 | .byte 35 142 | .byte 34 143 | .byte 33 144 | .byte 32 145 | .byte 31 146 | .byte 30 147 | .byte 29 148 | .byte 28 149 | .byte 27 150 | .byte 26 151 | .byte 25 152 | .byte 24 153 | .byte 23 154 | .byte 22 155 | .byte 21 156 | .byte 20 157 | .byte 19 158 | .byte 18 159 | .byte 17 160 | .byte 16 161 | .byte 15 162 | .byte 14 163 | .byte 13 164 | .byte 12 165 | .byte 11 166 | .byte 10 167 | .byte 9 168 | .byte 8 169 | .byte 7 170 | .byte 6 171 | .byte 5 172 | .byte 4 173 | .byte 3 174 | .byte 2 175 | .byte 1 176 | 177 | #endif /* } USE_ROLL_ASM */ 178 | -------------------------------------------------------------------------------- /stunnel-rsyncd.conf.in: -------------------------------------------------------------------------------- 1 | # This config for stunnel will start up rsync for an incoming ssl connection. 2 | foreground = no 3 | #output = /var/log/stunnel-rsyncd.log 4 | pid = /var/run/stunnel-rsyncd.pid 5 | socket = l:TCP_NODELAY=1 6 | socket = r:TCP_NODELAY=1 7 | #compression = rle 8 | # This must be root for rsync to use chroot -- rsync will drop permissions: 9 | setuid = root 10 | setgid = root 11 | 12 | [rsync] 13 | accept = 874 14 | # You can set the cert to a combo *.pem file and omit the key, if you like. 15 | cert = /etc/rsync-ssl/certs/server.crt 16 | key = /etc/rsync-ssl/certs/server.key 17 | client = no 18 | 19 | # To allow anyone to try an ssl connection, use this: 20 | verify = 0 21 | CAfile = /etc/ssl/certs/ca-certificates.crt 22 | 23 | # To allow only cert-authorized clients, use something like this instead of the above: 24 | #verify = 3 25 | #CAfile = /etc/rsync-ssl/certs/allowed-clients.cert.pem 26 | 27 | exec = @bindir@/rsync 28 | # You can either share the same config as a normal daemon, or specify a separate config: 29 | execargs = rsync --server --daemon . 30 | #execargs = rsync --server --daemon --config=/etc/rsync-ssl/rsyncd.conf . 31 | -------------------------------------------------------------------------------- /support/Makefile: -------------------------------------------------------------------------------- 1 | all: savetransfer 2 | 3 | savetransfer: savetransfer.o 4 | 5 | clean: 6 | rm -f *.o savetransfer 7 | -------------------------------------------------------------------------------- /support/cvs2includes: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # This script finds all CVS/Entries files in the current directory and below 3 | # and creates a local .cvsinclude file with non-inherited rules including each 4 | # checked-in file. Then, use this option whenever using --cvs-exclude (-C): 5 | # 6 | # -f ': .cvsinclude' 7 | # 8 | # That ensures that all checked-in files/dirs are included in the transfer. 9 | # (You could alternately put ": .cvsinclude" into an .rsync-filter file and 10 | # use the -F option, which is easier to type.) 11 | # 12 | # The downside is that you need to remember to re-run cvs2includes whenever 13 | # CVS gets an added or removed file. Maybe just run it before every copy. 14 | 15 | import os, argparse 16 | 17 | INC_NAME = '.cvsinclude' 18 | 19 | def main(): 20 | if args.dir: 21 | os.chdir(args.dir) 22 | 23 | cvs_includes = set() 24 | for root, dirs, files in os.walk('.'): 25 | if INC_NAME in files: 26 | cvs_includes.add((root + '/' + INC_NAME)[2:]) 27 | if root.endswith('/CVS') and 'Entries' in files: 28 | entries = root[2:] + '/Entries' 29 | includes = [ ] 30 | with open(entries) as fh: 31 | for line in fh: 32 | if line.startswith(('/', 'D/')): 33 | includes.append(line.split('/', 2)[1]) 34 | if includes: 35 | inc = root[2:-3] + INC_NAME 36 | cvs_includes.discard(inc) 37 | try: 38 | with open(inc) as fh: 39 | old_txt = fh.read() 40 | except OSError: 41 | old_txt = '' 42 | txt = ''.join(f"+ /{x}\n" for x in includes) 43 | if txt == old_txt: 44 | print("Unchanged", inc) 45 | else: 46 | print("Updating", inc) 47 | with open(inc, 'w') as fh: 48 | fh.write(txt) 49 | dirs.sort() 50 | 51 | for inc in sorted(cvs_includes): 52 | print("Removing", inc) 53 | os.unlink(inc) 54 | 55 | 56 | if __name__ == '__main__': 57 | parser = argparse.ArgumentParser(description=f"Transform CVS/Entries into {INC_NAME} files.", add_help=False) 58 | parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.") 59 | parser.add_argument("dir", nargs='?', help="The top CVS dir. Defaults to the current directory.") 60 | args = parser.parse_args() 61 | main() 62 | 63 | # vim: sw=4 et 64 | -------------------------------------------------------------------------------- /support/deny-rsync: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Send an error message via the rsync-protocol to a non-daemon client rsync. 3 | # 4 | # Usage: deny-rsync "message" 5 | 6 | protocol_version=29 7 | exit_code=4 # same as a daemon that refuses an option 8 | 9 | # e.g. byte_escape 29 => \035 10 | function byte_escape { 11 | echo -ne "\\0$(printf "%o" $1)" 12 | } 13 | 14 | msg="$1" 15 | if [ "${#msg}" -gt 254 ]; then 16 | # truncate a message that is too long for this naive script to handle 17 | msg="${msg:0:251}..." 18 | fi 19 | msglen=$(( ${#msg} + 1 )) # add 1 for the newline we append below 20 | 21 | # Send protocol version. All numbers are LSB-first 4-byte ints. 22 | echo -ne "$(byte_escape $protocol_version)\\000\\000\\000" 23 | 24 | # Send a zero checksum seed. 25 | echo -ne "\\000\\000\\000\\000" 26 | 27 | # The following is equivalent to rprintf(FERROR_XFER, "%s\n", $msg). 28 | # 1. Message header: ((MPLEX_BASE + FERROR_XFER) << 24) + $msglen. 29 | echo -ne "$(byte_escape $msglen)\\000\\000\\010" 30 | # 2. The actual data. 31 | echo -E "$msg" 32 | 33 | # Make sure the client gets our message, not a write failure. 34 | sleep 1 35 | 36 | exit $exit_code 37 | -------------------------------------------------------------------------------- /support/files-to-excludes: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # This script takes an input of filenames and outputs a set of include/exclude 3 | # directives that can be used by rsync to copy just the indicated files using 4 | # an --exclude-from=FILE or -f'. FILE' option. To be able to delete files on 5 | # the receiving side, either use --delete-excluded or change the exclude (-) 6 | # rules to hide filter rules (H) that only affect the sending side. 7 | 8 | import os, fileinput, argparse 9 | 10 | def main(): 11 | paths = set() 12 | for line in fileinput.input(args.files): 13 | dirs = line.strip().lstrip('/').split('/') 14 | if not dirs: 15 | continue 16 | for j in range(1, len(dirs)): 17 | if dirs[j] == '': 18 | continue 19 | path = '/' + '/'.join(dirs[:j]) + '/' 20 | if path not in paths: 21 | print('+', path) 22 | paths.add(path) 23 | print('+', '/' + '/'.join(dirs)) 24 | 25 | for path in sorted(paths): 26 | print('-', path + '*') 27 | print('-', '/*') 28 | 29 | 30 | if __name__ == '__main__': 31 | parser = argparse.ArgumentParser(description="Transform a list of files into a set of include/exclude rules.", add_help=False) 32 | parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.") 33 | parser.add_argument("files", metavar="FILE", default='-', nargs='*', help="The file(s) that hold the pathnames to translate. Defaults to stdin.") 34 | args = parser.parse_args() 35 | main() 36 | 37 | # vim: sw=4 et 38 | -------------------------------------------------------------------------------- /support/git-set-file-times: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os, re, argparse, subprocess 4 | from datetime import datetime, UTC 5 | 6 | NULL_COMMIT_RE = re.compile(r'\0\0commit [a-f0-9]{40}$|\0$') 7 | 8 | def main(): 9 | if not args.git_dir: 10 | cmd = 'git rev-parse --show-toplevel 2>/dev/null || echo .' 11 | top_dir = subprocess.check_output(cmd, shell=True, encoding='utf-8').strip() 12 | args.git_dir = os.path.join(top_dir, '.git') 13 | if not args.prefix: 14 | os.chdir(top_dir) 15 | 16 | git = [ 'git', '--git-dir=' + args.git_dir ] 17 | 18 | if args.tree: 19 | cmd = git + 'ls-tree -z -r --name-only'.split() + [ args.tree ] 20 | else: 21 | cmd = git + 'ls-files -z'.split() 22 | 23 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, encoding='utf-8') 24 | out = proc.communicate()[0] 25 | ls = set(out.split('\0')) 26 | ls.discard('') 27 | 28 | if not args.tree: 29 | # All modified files keep their current mtime. 30 | proc = subprocess.Popen(git + 'status -z --no-renames'.split(), stdout=subprocess.PIPE, encoding='utf-8') 31 | out = proc.communicate()[0] 32 | for fn in out.split('\0'): 33 | if fn == '' or (fn[0] != 'M' and fn[1] != 'M'): 34 | continue 35 | fn = fn[3:] 36 | if args.list: 37 | mtime = os.lstat(fn).st_mtime 38 | print_line(fn, mtime, mtime) 39 | ls.discard(fn) 40 | 41 | cmd = git + 'log -r --name-only --format=%x00commit%x20%H%n%x00commit_time%x20%ct%n --no-renames -z'.split() 42 | if args.tree: 43 | cmd.append(args.tree) 44 | cmd += ['--'] + args.files 45 | 46 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, encoding='utf-8') 47 | for line in proc.stdout: 48 | line = line.strip() 49 | m = re.match(r'^\0commit_time (\d+)$', line) 50 | if m: 51 | commit_time = int(m[1]) 52 | elif NULL_COMMIT_RE.search(line): 53 | line = NULL_COMMIT_RE.sub('', line) 54 | files = set(fn for fn in line.split('\0') if fn in ls) 55 | if not files: 56 | continue 57 | for fn in files: 58 | if args.prefix: 59 | fn = args.prefix + fn 60 | mtime = os.lstat(fn).st_mtime 61 | if args.list: 62 | print_line(fn, mtime, commit_time) 63 | elif mtime != commit_time: 64 | if not args.quiet: 65 | print(f"Setting {fn}") 66 | os.utime(fn, (commit_time, commit_time), follow_symlinks = False) 67 | ls -= files 68 | if not ls: 69 | break 70 | proc.communicate() 71 | 72 | 73 | def print_line(fn, mtime, commit_time): 74 | if args.list > 1: 75 | ts = str(commit_time).rjust(10) 76 | else: 77 | ts = datetime.fromtimestamp(commit_time, UTC).strftime("%Y-%m-%d %H:%M:%S") 78 | chg = '.' if mtime == commit_time else '*' 79 | print(chg, ts, fn) 80 | 81 | 82 | if __name__ == '__main__': 83 | parser = argparse.ArgumentParser(description="Set the times of the files in the current git checkout to their last-changed time.", add_help=False) 84 | parser.add_argument('--git-dir', metavar='GIT_DIR', help="The git dir to query (defaults to affecting the current git checkout).") 85 | parser.add_argument('--tree', metavar='TREE-ISH', help="The tree-ish to query (defaults to the current branch).") 86 | parser.add_argument('--prefix', metavar='PREFIX_STR', help="Prepend the PREFIX_STR to each filename we tweak (defaults to the top of current checkout).") 87 | parser.add_argument('--quiet', '-q', action='store_true', help="Don't output the changed-file information.") 88 | parser.add_argument('--list', '-l', action='count', help="List files & times instead of changing them. Repeat for Unix timestamp instead of human readable.") 89 | parser.add_argument('files', metavar='FILE', nargs='*', help="Specify a subset of checked-out files to tweak.") 90 | parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.") 91 | args = parser.parse_args() 92 | main() 93 | 94 | # vim: sw=4 et 95 | -------------------------------------------------------------------------------- /support/idmap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # This helper script makes it easy to use a passwd or group file to map values 3 | # in a LOCAL transfer. For instance, if you mount a backup that does not have 4 | # the same passwd setup as the local machine, you can do a copy to/from the 5 | # backup area as follows and get the differing ID values mapped just like a 6 | # remote transfer to/from the backed-up machine would do: 7 | # 8 | # rsync -av --usermap=`idmap --to /mnt/backup/etc/passwd` \ 9 | # --groupmap=`idmap --to /mnt/backup/etc/group` \ 10 | # /some/src/ /mnt/backup/some/dest/ 11 | # 12 | # rsync -av --usermap=`idmap --from /mnt/backup/etc/passwd` \ 13 | # --groupmap=`idmap --from /mnt/backup/etc/group` \ 14 | # /mnt/backup/some/src/ /some/dest/ 15 | 16 | import re, fileinput, argparse 17 | 18 | NAME_ID_RE = re.compile(r'^(\w+):[^:]+:(\d+)') 19 | 20 | def main(): 21 | maps = [ ] 22 | for line in fileinput.input(args.files): 23 | m = NAME_ID_RE.match(line) 24 | if not m: 25 | continue 26 | if args.to: 27 | pair = (m[1], m[2]) 28 | else: 29 | pair = (m[2], m[1]) 30 | maps.append(':'.join(pair)) 31 | print(','.join(maps)) 32 | 33 | 34 | if __name__ == '__main__': 35 | parser = argparse.ArgumentParser(description="Output usermap or groupmap args for rsync.", add_help=False) 36 | action = parser.add_argument_group() 37 | action = parser.add_mutually_exclusive_group(required=True) 38 | action.add_argument("--from", action="store_true", help="Output the map for use on the sending side.") 39 | action.add_argument("--to", action="store_true", help="Output the map for use on the receiving side.") 40 | parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.") 41 | parser.add_argument("files", metavar="FILE", default='-', nargs='*', help="The file(s) that hold the name & id pairs. Defaults to stdin.") 42 | args = parser.parse_args() 43 | main() 44 | 45 | # vim: sw=4 et 46 | -------------------------------------------------------------------------------- /support/install_deps_ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # install script for build dependencies for ubuntu/debian systems 4 | 5 | sudo apt install -y gcc g++ gawk autoconf automake python3-cmarkgfm 6 | sudo apt install -y acl libacl1-dev 7 | sudo apt install -y attr libattr1-dev 8 | sudo apt install -y libxxhash-dev 9 | sudo apt install -y libzstd-dev 10 | sudo apt install -y liblz4-dev 11 | sudo apt install -y libssl-dev 12 | -------------------------------------------------------------------------------- /support/instant-rsyncd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # instant-rsyncd lets you quickly set up and start a simple, unprivileged rsync 4 | # daemon with a single module in the current directory. I've found it 5 | # invaluable for quick testing, and I use it when writing a list of commands 6 | # that people can paste into a terminal to reproduce a daemon-related bug. 7 | # Sysadmins deploying an rsync daemon for the first time may find it helpful as 8 | # a starting point. 9 | # 10 | # Usage: instant-rsyncd MODULE PORT RSYNCD-USERNAME [RSYNC-PATH] 11 | # The script asks for the rsyncd user's password twice on stdin, once to set it 12 | # and once to log in to test the daemon. 13 | # -- Matt McCutchen 14 | 15 | set -e 16 | 17 | dir="$(pwd)" 18 | 19 | echo 20 | echo "This will setup an rsync daemon in $dir" 21 | 22 | if [ $# = 0 ]; then 23 | IFS='' read -p 'Module name to create (or return to exit): ' module 24 | [ ! "$module" ] && exit 25 | else 26 | module="$1" 27 | shift 28 | fi 29 | 30 | if [ $# = 0 ]; then 31 | IFS='' read -p 'Port number the daemon should listen on [873]: ' port 32 | else 33 | port="$1" 34 | shift 35 | fi 36 | [ "$port" ] || port=873 37 | 38 | if [ $# = 0 ]; then 39 | IFS='' read -p 'User name for authentication (empty for none): ' user 40 | else 41 | user="$1" 42 | shift 43 | fi 44 | 45 | if [ "$user" ]; then 46 | IFS='' read -s -p 'Desired password: ' password 47 | echo 48 | fi 49 | 50 | rsync="$1" 51 | [ "$rsync" ] || rsync=rsync 52 | 53 | moduledir="${dir%/}/$module" 54 | 55 | mkdir "$module" 56 | 57 | cat >rsyncd.conf <>rsyncd.conf <<-EOF 70 | auth users = $user 71 | secrets file = $module.secrets 72 | EOF 73 | touch "$module".secrets 74 | chmod go-rwx "$module".secrets 75 | echo "$user:$password" >"$module".secrets 76 | user="$user@" 77 | fi 78 | 79 | cat >start <stop <<"EOF" 92 | #!/bin/bash 93 | set -e 94 | cd `dirname $0` 95 | ! [ -e rsyncd.pid ] || kill -s SIGTERM $(< rsyncd.pid) 96 | EOF 97 | chmod +x stop 98 | 99 | path="rsync://$user$(hostname):$port/$module/" 100 | 101 | if ./start; then 102 | sleep .2 103 | echo 104 | echo "I ran the start command for the daemon. The log file rsyncd.log says:" 105 | echo 106 | cat rsyncd.log 107 | echo 108 | echo "You can start and stop it with ./start and ./stop respectively." 109 | echo "You can customize the configuration file rsyncd.conf." 110 | echo 111 | echo "Give rsync the following path to access the module:" 112 | echo " $path" 113 | echo 114 | if [ "$user" ]; then 115 | echo "Let's test the daemon now. Enter the password you chose at the prompt." 116 | else 117 | echo "Let's test the daemon now." 118 | fi 119 | echo 120 | echo '$' $rsync --list-only "$path" 121 | $rsync --list-only "$path" 122 | echo 123 | echo "You should see an empty folder; it's $moduledir." 124 | else 125 | echo "Something went wrong. Do you see an error message?" 126 | fi 127 | -------------------------------------------------------------------------------- /support/json-rsync-version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, argparse, subprocess, json 4 | 5 | TWEAK_NAME = { 6 | 'asm': 'asm_roll', 7 | 'ASM': 'asm_roll', 8 | 'hardlink_special': 'hardlink_specials', 9 | 'protect_args': 'secluded_args', 10 | 'protected_args': 'secluded_args', 11 | 'SIMD': 'SIMD_roll', 12 | } 13 | 14 | MOVE_OPTIM = set('asm_roll SIMD_roll'.split()) 15 | 16 | def main(): 17 | if not args.rsync or args.rsync == '-': 18 | ver_out = sys.stdin.read().strip() 19 | else: 20 | ver_out = subprocess.check_output([args.rsync, '--version', '--version'], encoding='utf-8').strip() 21 | if ver_out.startswith('{'): 22 | print(ver_out) 23 | return 24 | info = { } 25 | misplaced_optims = { } 26 | for line in ver_out.splitlines(): 27 | if line.startswith('rsync '): 28 | prog, vstr, ver, pstr, vstr2, proto = line.split() 29 | info['program'] = prog 30 | if ver.startswith('v'): 31 | ver = ver[1:] 32 | info[vstr] = ver 33 | if '.' not in proto: 34 | proto += '.0' 35 | else: 36 | proto = proto.replace('.PR', '.') 37 | info[pstr] = proto 38 | elif line.startswith('Copyright '): 39 | info['copyright'] = line[10:] 40 | elif line.startswith('Web site: '): 41 | info['url'] = line[10:] 42 | elif line.startswith(' '): 43 | if not saw_comma and ',' in line: 44 | saw_comma = True 45 | info[sect_name] = { } 46 | if saw_comma: 47 | for x in line.strip(' ,').split(', '): 48 | if ' ' in x: 49 | val, var = x.split(' ', 1) 50 | if val == 'no': 51 | val = False 52 | elif val.endswith('-bit'): 53 | var = var[:-1] + '_bits' 54 | val = int(val.split('-')[0]) 55 | else: 56 | var = x 57 | val = True 58 | var = var.replace(' ', '_').replace('-', '_') 59 | if var in TWEAK_NAME: 60 | var = TWEAK_NAME[var] 61 | if sect_name[0] != 'o' and var in MOVE_OPTIM: 62 | misplaced_optims[var] = val 63 | else: 64 | info[sect_name][var] = val 65 | else: 66 | info[sect_name] += [ x for x in line.split() if not x.startswith('(') ] 67 | elif line == '': 68 | break 69 | else: 70 | sect_name = line.strip(' :').replace(' ', '_').lower() 71 | info[sect_name] = [ ] 72 | saw_comma = False 73 | for chk in 'capabilities optimizations'.split(): 74 | if chk not in info: 75 | info[chk] = { } 76 | if misplaced_optims: 77 | info['optimizations'].update(misplaced_optims) 78 | for chk in 'checksum_list compress_list daemon_auth_list'.split(): 79 | if chk not in info: 80 | info[chk] = [ ] 81 | info['license'] = 'GPLv3' if ver[0] == '3' else 'GPLv2' 82 | info['caveat'] = 'rsync comes with ABSOLUTELY NO WARRANTY' 83 | print(json.dumps(info)) 84 | 85 | 86 | if __name__ == '__main__': 87 | 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) 88 | parser.add_argument('rsync', nargs='?', help="Specify an rsync command to run. Otherwise stdin is consumed.") 89 | parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.") 90 | args = parser.parse_args() 91 | main() 92 | 93 | # vim: sw=4 et 94 | -------------------------------------------------------------------------------- /support/logfilter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # Filter the rsync daemon log messages by module name. The log file can be 3 | # in either syslog format or rsync's own log-file format. Note that the 4 | # MODULE_NAME parameter is used in a regular-expression match in order to 5 | # allow regex wildcards to be used. You can also limit the output by 6 | # directory hierarchy in a module. Examples: 7 | # 8 | # logfilter foo /var/log/rsyncd.log # output lines for module foo 9 | # logfilter foo/dir /var/log/syslog # limit lines to those in dir of foo 10 | 11 | use strict; 12 | 13 | my $match = shift; 14 | die "Usage: logfilter MODULE_NAME [LOGFILE ...]\n" unless defined $match; 15 | 16 | my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd'; 17 | my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d '; 18 | 19 | my %pids; 20 | 21 | while (<>) { 22 | my($pid,$msg) = /^(?:$syslog_prefix|$rsyncd_prefix)\[(\d+)\]:? (.*)/o; 23 | next unless defined $pid; 24 | my($mod_spec) = $msg =~ /^rsync (?:on|to) (\S+) from /; 25 | if (defined $mod_spec) { 26 | if ($mod_spec =~ /^$match(\/\S*)?$/o) { 27 | $pids{$pid} = 1; 28 | } else { 29 | delete $pids{$pid}; 30 | } 31 | } 32 | next unless $pids{$pid}; 33 | print $_; 34 | } 35 | -------------------------------------------------------------------------------- /support/lsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # This is a "local shell" command that works like a remote shell but only for 3 | # the local host. See the usage message for more details. 4 | 5 | use strict; 6 | use warnings; 7 | use Getopt::Long; 8 | use English '-no_match_vars'; 9 | 10 | &Getopt::Long::Configure('bundling'); 11 | &Getopt::Long::Configure('require_order'); 12 | GetOptions( 13 | 'l=s' => \( my $login_name ), 14 | '1|2|4|6|A|a|C|f|g|k|M|N|n|q|s|T|t|V|v|X|x|Y' => sub { }, # Ignore 15 | 'b|c|D|e|F|i|L|m|O|o|p|R|S|w=s' => sub { }, # Ignore 16 | 'no-cd' => \( my $no_chdir ), 17 | 'sudo' => \( my $use_sudo ), 18 | 'rrsync=s' => \( my $rrsync_dir ), 19 | 'rropts=s' => \( my $rrsync_opts ), 20 | ) or &usage; 21 | &usage unless @ARGV > 1; 22 | 23 | my $host = shift; 24 | if ($host =~ s/^([^@]+)\@//) { 25 | $login_name = $1; 26 | } 27 | if ($host eq 'lh') { 28 | $no_chdir = 1; 29 | } elsif ($host ne 'localhost') { 30 | die "lsh: unable to connect to host $host\n"; 31 | } 32 | 33 | my ($home_dir, @cmd); 34 | if ($login_name) { 35 | my ($uid, $gid); 36 | if ($login_name =~ /\D/) { 37 | $uid = getpwnam($login_name); 38 | die "Unknown user: $login_name\n" unless defined $uid; 39 | } else { 40 | $uid = $login_name; 41 | } 42 | ($login_name, $gid, $home_dir) = (getpwuid($uid))[0,3,7]; 43 | if ($use_sudo) { 44 | unshift @ARGV, "cd '$home_dir' &&" unless $no_chdir; 45 | unshift @cmd, qw( sudo -H -u ), $login_name; 46 | $no_chdir = 1; 47 | } else { 48 | my $groups = "$gid $gid"; 49 | while (my ($grgid, $grmembers) = (getgrent)[2,3]) { 50 | if ($grgid != $gid && $grmembers =~ /(^|\s)\Q$login_name\E(\s|$)/o) { 51 | $groups .= " $grgid"; 52 | } 53 | } 54 | 55 | my ($ruid, $euid) = ($UID, $EUID); 56 | $GID = $EGID = $groups; 57 | $UID = $EUID = $uid; 58 | die "Cannot set ruid: $! (use --sudo?)\n" if $UID == $ruid && $ruid != $uid; 59 | die "Cannot set euid: $! (use --sudo?)\n" if $EUID == $euid && $euid != $uid; 60 | 61 | $ENV{USER} = $ENV{USERNAME} = $login_name; 62 | $ENV{HOME} = $home_dir; 63 | } 64 | } else { 65 | $home_dir = (getpwuid($UID))[7]; 66 | } 67 | 68 | unless ($no_chdir) { 69 | chdir $home_dir or die "Unable to chdir to $home_dir: $!\n"; 70 | } 71 | 72 | if ($rrsync_dir) { 73 | $ENV{SSH_ORIGINAL_COMMAND} = join(' ', @ARGV); 74 | push @cmd, 'rrsync'; 75 | if ($rrsync_opts) { 76 | foreach my $opt (split(/[ ,]+/, $rrsync_opts)) { 77 | $opt = "-$opt" unless $opt =~ /^-/; 78 | push @cmd, $opt; 79 | } 80 | } 81 | push @cmd, $rrsync_dir; 82 | } else { 83 | push @cmd, '/bin/sh', '-c', "@ARGV"; 84 | } 85 | exec @cmd; 86 | die "Failed to exec: $!\n"; 87 | 88 | sub usage 89 | { 90 | die <&2; exit 1 ;; 22 | esac 23 | done 24 | 25 | if [ "$user" ]; then 26 | prefix='' 27 | if [ $do_cd = y ]; then 28 | home=`perl -e "print((getpwnam('$user'))[7])"` 29 | prefix="cd '$home' &&" 30 | fi 31 | sudo -H -u "$user" sh -c "$prefix $*" 32 | else 33 | if [ $do_cd = y ]; then 34 | cd || exit 1 35 | fi 36 | eval "${@}" 37 | fi 38 | -------------------------------------------------------------------------------- /support/mnt-excl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # This script takes a command-line arg of a source directory 3 | # that will be passed to rsync, and generates a set of excludes 4 | # that will exclude all mount points from the list. This is 5 | # useful if you have "bind" mounts since the --one-file-system 6 | # option won't notice the transition to a different spot on 7 | # the same disk. For example: 8 | # 9 | # mnt-excl /dir | rsync --exclude-from=- ... /dir /dest/ 10 | # mnt-excl /dir/ | rsync --exclude-from=- ... /dir/ /dest/ 11 | # ssh host mnt-excl /dir | rsync --exclude-from=- ... host:/dir /dest/ 12 | # 13 | # Imagine that /dir/foo is a mount point: the first invocation of 14 | # mnt-excl would have output /dir/foo, while the second would have 15 | # output /foo (which are the properly anchored excludes). 16 | # 17 | # NOTE: This script expects /proc/mounts to exist, but could be 18 | # easily adapted to read /etc/mtab or similar. 19 | # 20 | # ADDENDUM: The addition of the --filter option (which has support for 21 | # absolute-anchored excludes) can make this script unneeded in some 22 | # scenarios. If you don't need delete protection on the receiving side 23 | # (or if the destination path is identical to the source path), then you 24 | # can exclude some absolute paths from the transfer based on the mount 25 | # dirs. For instance: 26 | # 27 | # awk '{print $2}' /proc/mounts | grep -v '^/$' | \ 28 | # rsync -avf 'merge,/- -' /dir host:/dest/ 29 | 30 | import os, argparse 31 | 32 | MNT_FILE = '/proc/mounts'; 33 | 34 | def main(): 35 | trailing_slash = '/' if args.path.endswith(('/', '/.')) and args.path != '/' else '' 36 | args.path = os.path.realpath(args.path) + trailing_slash 37 | parent_dir = os.path.dirname(args.path) 38 | trailing = os.path.basename(args.path) 39 | if not os.path.isdir(args.path): 40 | trailing = '' 41 | elif trailing != '': 42 | trailing += '/' 43 | want_path = os.path.join(parent_dir, trailing) 44 | wp_len = len(want_path) 45 | 46 | with open(MNT_FILE) as fh: 47 | for line in fh: 48 | mnt_path = line.split()[1] 49 | if mnt_path.startswith(want_path) and mnt_path != want_path: 50 | print(f"- /{trailing}{mnt_path[wp_len:]}") 51 | 52 | if __name__ == '__main__': 53 | parser = argparse.ArgumentParser(description="Output mount points as rsync excludes.", add_help=False) 54 | parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.") 55 | parser.add_argument('path', metavar='PATH', nargs='?', default='/', help="Limit output to those within the PATH hierarchy.") 56 | args = parser.parse_args() 57 | main() 58 | 59 | # vim: sw=4 et 60 | -------------------------------------------------------------------------------- /support/munge-symlinks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # This script will either prefix all symlink values with the string 3 | # "/rsyncd-munged/" or remove that prefix. 4 | 5 | import os, sys, argparse 6 | 7 | SYMLINK_PREFIX = '/rsyncd-munged/' 8 | PREFIX_LEN = len(SYMLINK_PREFIX) 9 | 10 | def main(): 11 | for arg in args.names: 12 | if os.path.islink(arg): 13 | process_one_arg(arg) 14 | elif os.path.isdir(arg): 15 | for fn in find_symlinks(arg): 16 | process_one_arg(fn) 17 | else: 18 | print("Arg is not a symlink or a dir:", arg, file=sys.stderr) 19 | 20 | 21 | def find_symlinks(path): 22 | for entry in os.scandir(path): 23 | if entry.is_symlink(): 24 | yield entry.path 25 | elif entry.is_dir(follow_symlinks=False): 26 | yield from find_symlinks(entry.path) 27 | 28 | 29 | def process_one_arg(fn): 30 | lnk = os.readlink(fn) 31 | if args.unmunge: 32 | if not lnk.startswith(SYMLINK_PREFIX): 33 | return 34 | lnk = lnk[PREFIX_LEN:] 35 | while args.all and lnk.startswith(SYMLINK_PREFIX): 36 | lnk = lnk[PREFIX_LEN:] 37 | else: 38 | if not args.all and lnk.startswith(SYMLINK_PREFIX): 39 | return 40 | lnk = SYMLINK_PREFIX + lnk 41 | 42 | try: 43 | os.unlink(fn) 44 | except OSError as e: 45 | print("Unable to unlink symlink:", str(e), file=sys.stderr) 46 | return 47 | try: 48 | os.symlink(lnk, fn) 49 | except OSError as e: 50 | print("Unable to recreate symlink", fn, '->', lnk + ':', str(e), file=sys.stderr) 51 | return 52 | print(fn, '->', lnk) 53 | 54 | 55 | if __name__ == '__main__': 56 | our_desc = """\ 57 | Adds or removes the %s prefix to/from the start of each symlink's value. 58 | When given the name of a directory, affects all the symlinks in that directory hierarchy. 59 | """ % SYMLINK_PREFIX 60 | epilog = 'See the "munge symlinks" option in the rsyncd.conf manpage for more details.' 61 | parser = argparse.ArgumentParser(description=our_desc, epilog=epilog, add_help=False) 62 | uniq_group = parser.add_mutually_exclusive_group() 63 | uniq_group.add_argument('--munge', action='store_true', help="Add the prefix to symlinks (the default).") 64 | uniq_group.add_argument('--unmunge', action='store_true', help="Remove the prefix from symlinks.") 65 | parser.add_argument('--all', action='store_true', help="Always adds the prefix when munging (even if already munged) or removes multiple instances of the prefix when unmunging.") 66 | parser.add_argument('--help', '-h', action='help', help="Output this help message and exit.") 67 | parser.add_argument('names', metavar='NAME', nargs='+', help="One or more directories and/or symlinks to process.") 68 | args = parser.parse_args() 69 | main() 70 | 71 | # vim: sw=4 et 72 | -------------------------------------------------------------------------------- /support/nameconvert: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # This implements a simple protocol to do user & group conversions between 4 | # names & ids. All input and output consists of simple strings with a 5 | # terminating newline. 6 | # 7 | # The requests can be: 8 | # 9 | # uid ID_NUM\n -> NAME\n 10 | # gid ID_NUM\n -> NAME\n 11 | # usr NAME\n -> ID_NUM\n 12 | # grp NAME\n -> ID_NUM\n 13 | # 14 | # An unknown ID_NUM or NAME results in an empty return value. 15 | # 16 | # This is used by an rsync daemon when configured with the "name converter" and 17 | # (often) "use chroot = true". While this converter uses real user & group 18 | # lookups you could change it to use any mapping idiom you'd like. 19 | 20 | import sys, argparse, pwd, grp 21 | 22 | def main(): 23 | for line in sys.stdin: 24 | try: 25 | req, arg = line.rstrip().split(' ', 1) 26 | except: 27 | req = None 28 | try: 29 | if req == 'uid': 30 | ans = pwd.getpwuid(int(arg)).pw_name 31 | elif req == 'gid': 32 | ans = grp.getgrgid(int(arg)).gr_name 33 | elif req == 'usr': 34 | ans = pwd.getpwnam(arg).pw_uid 35 | elif req == 'grp': 36 | ans = grp.getgrnam(arg).gr_gid 37 | else: 38 | print("Invalid request", file=sys.stderr) 39 | sys.exit(1) 40 | except KeyError: 41 | ans = '' 42 | print(ans, flush=True) 43 | 44 | 45 | if __name__ == '__main__': 46 | parser = argparse.ArgumentParser(description="Convert users & groups between names & numbers for an rsync daemon.") 47 | args = parser.parse_args() 48 | main() 49 | 50 | # vim: sw=4 et 51 | -------------------------------------------------------------------------------- /support/rsync-no-vanished: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | REAL_RSYNC=/usr/bin/rsync 4 | IGNOREEXIT=24 5 | IGNOREOUT='^(file has vanished: |rsync warning: some files vanished before they could be transferred)' 6 | 7 | # If someone installs this as "rsync", make sure we don't affect a server run. 8 | for arg in "${@}"; do 9 | if [[ "$arg" == --server ]]; then 10 | exec $REAL_RSYNC "${@}" 11 | exit $? # Not reached 12 | fi 13 | done 14 | 15 | set -o pipefail 16 | 17 | # This filters stderr without merging it with stdout: 18 | { $REAL_RSYNC "${@}" 2>&1 1>&3 3>&- | grep -E -v "$IGNOREOUT"; ret=${PIPESTATUS[0]}; } 3>&1 1>&2 19 | 20 | if [[ $ret == $IGNOREEXIT ]]; then 21 | ret=0 22 | fi 23 | 24 | exit $ret 25 | -------------------------------------------------------------------------------- /support/rsync-slash-strip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script can be used as an rsync command-line filter that strips a single 3 | # trailing slash from each arg. That treats "src/" the same as "src", thus 4 | # you need to use "src/." or "src//" for just the contents of the "src" dir. 5 | # (Note that command-line dir-excludes would need to use "excl//" too.) 6 | # 7 | # To use this, name it something like "rs", put it somewhere in your path, and 8 | # then use "rs" in place of "rsync" when you are typing your copy commands. 9 | 10 | REAL_RSYNC=/usr/bin/rsync 11 | 12 | args=() 13 | for arg in "${@}"; do 14 | if [[ "$arg" == --server ]]; then 15 | exec $REAL_RSYNC "${@}" 16 | exit $? # Not reached 17 | fi 18 | if [[ "$arg" == / ]]; then 19 | args=("${args[@]}" /) 20 | else 21 | args=("${args[@]}" "${arg%/}") 22 | fi 23 | done 24 | exec $REAL_RSYNC "${args[@]}" 25 | -------------------------------------------------------------------------------- /t_stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file contains really simple implementations for rsync global 3 | * functions, so that module test harnesses can run standalone. 4 | * 5 | * Copyright (C) 2001, 2002 Martin Pool 6 | * Copyright (C) 2003-2022 Wayne Davison 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along 19 | * with this program; if not, visit the http://fsf.org website. 20 | */ 21 | 22 | #include "rsync.h" 23 | 24 | int do_fsync = 0; 25 | int inplace = 0; 26 | int modify_window = 0; 27 | int preallocate_files = 0; 28 | int protect_args = 0; 29 | int module_id = -1; 30 | int relative_paths = 0; 31 | unsigned int module_dirlen = 0; 32 | int preserve_xattrs = 0; 33 | int preserve_perms = 0; 34 | int preserve_executability = 0; 35 | int omit_link_times = 0; 36 | int open_noatime = 0; 37 | size_t max_alloc = 0; /* max_alloc is needed when combined with util2.o */ 38 | char *partial_dir; 39 | char *module_dir; 40 | filter_rule_list daemon_filter_list; 41 | 42 | void rprintf(UNUSED(enum logcode code), const char *format, ...) 43 | { 44 | va_list ap; 45 | va_start(ap, format); 46 | vfprintf(stderr, format, ap); 47 | va_end(ap); 48 | } 49 | 50 | void rsyserr(UNUSED(enum logcode code), int errcode, const char *format, ...) 51 | { 52 | va_list ap; 53 | fputs(RSYNC_NAME ": ", stderr); 54 | va_start(ap, format); 55 | vfprintf(stderr, format, ap); 56 | va_end(ap); 57 | fprintf(stderr, ": %s (%d)\n", strerror(errcode), errcode); 58 | } 59 | 60 | void _exit_cleanup(int code, const char *file, int line) 61 | { 62 | fprintf(stderr, "exit(%d): %s(%d)\n", 63 | code, file, line); 64 | exit(code); 65 | } 66 | 67 | int check_filter(UNUSED(filter_rule_list *listp), UNUSED(enum logcode code), 68 | UNUSED(const char *name), UNUSED(int name_is_dir)) 69 | { 70 | /* This function doesn't really get called in this test context, so 71 | * just return 0. */ 72 | return 0; 73 | } 74 | 75 | int copy_xattrs(UNUSED(const char *source), UNUSED(const char *dest)) 76 | { 77 | return -1; 78 | } 79 | 80 | void free_xattr(UNUSED(stat_x *sxp)) 81 | { 82 | return; 83 | } 84 | 85 | void free_acl(UNUSED(stat_x *sxp)) 86 | { 87 | return; 88 | } 89 | 90 | char *lp_name(UNUSED(int mod)) 91 | { 92 | return NULL; 93 | } 94 | 95 | BOOL lp_use_chroot(UNUSED(int mod)) 96 | { 97 | return 0; 98 | } 99 | 100 | const char *who_am_i(void) 101 | { 102 | return "tester"; 103 | } 104 | 105 | int csum_len_for_type(int cst, int flg) 106 | { 107 | return cst || !flg ? 16 : 1; 108 | } 109 | 110 | int canonical_checksum(int cst) 111 | { 112 | return cst ? 0 : 0; 113 | } 114 | -------------------------------------------------------------------------------- /t_unsafe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Test harness for unsafe_symlink(). Not linked into rsync itself. 3 | * 4 | * Copyright (C) 2002 Martin Pool 5 | * Copyright (C) 2003-2020 Wayne Davison 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, visit the http://fsf.org website. 19 | */ 20 | 21 | /* Prints either "safe" or "unsafe" depending on the two arguments. 22 | * Always returns 0 unless something extraordinary happens. */ 23 | 24 | #include "rsync.h" 25 | 26 | int dry_run = 0; 27 | int am_root = 0; 28 | int am_sender = 1; 29 | int read_only = 0; 30 | int list_only = 0; 31 | int copy_links = 0; 32 | int copy_unsafe_links = 0; 33 | 34 | short info_levels[COUNT_INFO], debug_levels[COUNT_DEBUG]; 35 | 36 | int 37 | main(int argc, char **argv) 38 | { 39 | if (argc != 3) { 40 | fprintf(stderr, "usage: t_unsafe LINKDEST SRCDIR\n"); 41 | return 1; 42 | } 43 | 44 | printf("%s\n", unsafe_symlink(argv[1], argv[2]) ? "unsafe" : "safe"); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /testhelp/maketree.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | # Copyright (C) 2002 by Martin Pool 4 | 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License version 7 | # 2 as published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 | 18 | # Populate a tree with pseudo-randomly distributed files to test 19 | # rsync. 20 | 21 | from __future__ import generators 22 | import random, string, os, os.path 23 | 24 | nfiles = 10000 25 | depth = 5 26 | n_children = 20 27 | n_files = 20 28 | n_symlinks = 10 29 | 30 | name_chars = string.digits + string.letters 31 | 32 | abuffer = 'a' * 1024 33 | 34 | def random_name_chars(): 35 | a = "" 36 | for i in range(10): 37 | a = a + random.choice(name_chars) 38 | return a 39 | 40 | 41 | def generate_names(): 42 | n = 0 43 | while 1: 44 | yield "%05d_%s" % (n, random_name_chars()) 45 | n += 1 46 | 47 | 48 | class TreeBuilder: 49 | def __init__(self): 50 | self.n_children = 20 51 | self.n_files = 100 52 | self.total_entries = 100000 # long(1e8) 53 | self.actual_size = 0 54 | self.name_gen = generate_names() 55 | self.all_files = [] 56 | self.all_dirs = [] 57 | self.all_symlinks = [] 58 | 59 | 60 | def random_size(self): 61 | return random.lognormvariate(4, 4) 62 | 63 | 64 | def random_symlink_target(self): 65 | what = random.choice(['directory', 'file', 'symlink', 'none']) 66 | try: 67 | if what == 'directory': 68 | return random.choice(self.all_dirs) 69 | elif what == 'file': 70 | return random.choice(self.all_files) 71 | elif what == 'symlink': 72 | return random.choice(self.all_symlinks) 73 | elif what == 'none': 74 | return self.name_gen.next() 75 | except IndexError: 76 | return self.name_gen.next() 77 | 78 | 79 | def can_continue(self): 80 | self.total_entries -= 1 81 | return self.total_entries > 0 82 | 83 | 84 | def build_tree(self, prefix, depth): 85 | """Generate a breadth-first tree""" 86 | for count, function in [[n_files, self.make_file], 87 | [n_children, self.make_child_recurse], 88 | [n_symlinks, self.make_symlink]]: 89 | for i in range(count): 90 | if not self.can_continue(): 91 | return 92 | name = os.path.join(prefix, self.name_gen.next()) 93 | function(name, depth) 94 | 95 | 96 | def print_summary(self): 97 | print "total bytes: %d" % self.actual_size 98 | 99 | 100 | def make_child_recurse(self, dname, depth): 101 | if depth > 1: 102 | self.make_dir(dname) 103 | self.build_tree(dname, depth-1) 104 | 105 | 106 | def make_dir(self, dname, depth='ignore'): 107 | print "%s/" % (dname) 108 | os.mkdir(dname) 109 | self.all_dirs.append(dname) 110 | 111 | 112 | def make_symlink(self, lname, depth='ignore'): 113 | print "%s -> %s" % (lname, self.random_symlink_target()) 114 | 115 | 116 | def make_file(self, fname, depth='ignore'): 117 | size = long(self.random_size()) 118 | print "%-70s %d" % (fname, size) 119 | f = open(fname, 'w') 120 | f.truncate(size) 121 | self.fill_file(f, size) 122 | self.all_files.append(fname) 123 | self.actual_size += size 124 | 125 | def fill_file(self, f, size): 126 | while size > 0: 127 | f.write(abuffer[:size]) 128 | size -= len(abuffer) 129 | 130 | 131 | tb = TreeBuilder() 132 | tb.build_tree('/tmp/foo', 3) 133 | tb.print_summary() 134 | -------------------------------------------------------------------------------- /testrun.c: -------------------------------------------------------------------------------- 1 | /* Run a testsuite script with a timeout. */ 2 | 3 | #include "rsync.h" 4 | 5 | #define DEFAULT_TIMEOUT_SECS (5*60) 6 | #define TIMEOUT_ENV "TESTRUN_TIMEOUT" 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | pid_t pid; 11 | char *timeout_env; 12 | int status, timeout_secs, slept = 0; 13 | 14 | if (argc < 2) { 15 | fprintf(stderr, "Usage: testrun [SHELL_OPTIONS] TESTSUITE_SCRIPT [ARGS]\n"); 16 | exit(1); 17 | } 18 | 19 | if ((timeout_env = getenv(TIMEOUT_ENV)) != NULL) 20 | timeout_secs = atoi(timeout_env); 21 | else 22 | timeout_secs = DEFAULT_TIMEOUT_SECS; 23 | 24 | if ((pid = fork()) < 0) { 25 | fprintf(stderr, "TESTRUN ERROR: fork failed: %s\n", strerror(errno)); 26 | exit(1); 27 | } 28 | 29 | if (pid == 0) { 30 | argv[0] = "sh"; 31 | execvp(argv[0], argv); 32 | fprintf(stderr, "TESTRUN ERROR: failed to exec %s: %s\n", argv[0], strerror(errno)); 33 | _exit(1); 34 | } 35 | 36 | while (1) { 37 | int ret = waitpid(pid, &status, WNOHANG); 38 | if (ret > 0) 39 | break; 40 | if (ret < 0) { 41 | if (errno == EINTR) 42 | continue; 43 | fprintf(stderr, "TESTRUN ERROR: waitpid failed: %s\n", strerror(errno)); 44 | exit(1); 45 | } 46 | if (slept++ > timeout_secs) { 47 | fprintf(stderr, "TESTRUN TIMEOUT: test took over %d seconds.\n", timeout_secs); 48 | if (kill(pid, SIGTERM) < 0) 49 | fprintf(stderr, "TESTRUN ERROR: failed to kill pid %d: %s\n", (int)pid, strerror(errno)); 50 | else 51 | fprintf(stderr, "TESTRUN INFO: killed pid %d\n", (int)pid); 52 | exit(1); 53 | } 54 | sleep(1); 55 | } 56 | 57 | if (!WIFEXITED(status)) 58 | exit(255); 59 | 60 | return WEXITSTATUS(status); 61 | } 62 | -------------------------------------------------------------------------------- /testsuite/00-hello.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Test some foundational things. 4 | 5 | . "$suitedir/rsync.fns" 6 | 7 | RSYNC_RSH="$scratchdir/src/support/lsh.sh" 8 | export RSYNC_RSH 9 | 10 | echo $0 running 11 | 12 | $RSYNC --version || test_fail '--version output failed' 13 | 14 | $RSYNC --info=help || test_fail '--info=help output failed' 15 | 16 | $RSYNC --debug=help || test_fail '--debug=help output failed' 17 | 18 | weird_name="A weird)name" 19 | 20 | mkdir "$fromdir" 21 | mkdir "$fromdir/$weird_name" 22 | 23 | append_line() { 24 | echo "$1" 25 | echo "$1" >>"$fromdir/$weird_name/file" 26 | } 27 | 28 | append_line test1 29 | checkit "$RSYNC -ai '$fromdir/' '$todir/'" "$fromdir" "$todir" 30 | 31 | copy_weird() { 32 | checkit "$RSYNC $1 --rsync-path='$RSYNC' '$2$fromdir/$weird_name/' '$3$todir/$weird_name'" "$fromdir" "$todir" 33 | } 34 | 35 | append_line test2 36 | copy_weird '-ai' 'lh:' '' 37 | 38 | append_line test3 39 | copy_weird '-ai' '' 'lh:' 40 | 41 | append_line test4 42 | copy_weird '-ais' 'lh:' '' 43 | 44 | append_line test5 45 | copy_weird '-ais' '' 'lh:' 46 | 47 | echo test6 48 | 49 | touch "$fromdir/one" "$fromdir/two" 50 | (cd "$fromdir" && $RSYNC -ai --old-args --rsync-path="$RSYNC" lh:'one two' "$todir/") 51 | if [ ! -f "$todir/one" ] || [ ! -f "$todir/two" ]; then 52 | test_fail "old-args copy of 'one two' failed" 53 | fi 54 | 55 | echo test7 56 | 57 | rm "$todir/one" "$todir/two" 58 | (cd "$fromdir" && RSYNC_OLD_ARGS=1 $RSYNC -ai --rsync-path="$RSYNC" lh:'one two' "$todir/") 59 | 60 | # The script would have aborted on error, so getting here means we've won. 61 | exit 0 62 | -------------------------------------------------------------------------------- /testsuite/README.testsuite: -------------------------------------------------------------------------------- 1 | automatic testsuite for rsync -*- text -*- 2 | 3 | We're trying to develop some more substantial tests to prevent rsync 4 | regressions. Ideally, all code changes or bug reports would come with 5 | an appropriate test suite. 6 | 7 | You can run these tests by typing "make check" in the build directory. 8 | The tests will run using the rsync binary in the build directory, so 9 | you do not need to do "make install" first. Indeed, you probably 10 | should not install rsync before running the tests. 11 | 12 | If you instead type "make installcheck" then the suite will test the 13 | rsync binary from its installed location (e.g. /usr/local/bin/rsync). 14 | You can use this to test a distribution build, or perhaps to run a new 15 | test suite against an old version of rsync. Note that in accordance 16 | with the GNU Standards, installcheck does not look for rsync on the 17 | path. 18 | 19 | If the tests pass, you should see a report to that effect. Some tests 20 | require being root or some other precondition, and so will normally not 21 | be checked -- look at the test scripts for more information. 22 | 23 | If the tests fail, you will see rather more output. The scratch 24 | directory will remain in the build directory. It would be useful if 25 | you could include the log messages when reporting a failure. 26 | 27 | These tests also run automatically on the build farm, and you can see 28 | the results on http://build.samba.org/. 29 | -------------------------------------------------------------------------------- /testsuite/acls-default.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This program is distributable under the terms of the GNU GPL (see 4 | # COPYING). 5 | 6 | # Test that rsync obeys default ACLs. -- Matt McCutchen 7 | 8 | . $suitedir/rsync.fns 9 | 10 | $RSYNC -VV | grep '"ACLs": true' >/dev/null || test_skipped "Rsync is configured without ACL support" 11 | 12 | case "$setfacl_nodef" in 13 | true) test_skipped "I don't know how to use your setfacl command" ;; 14 | *-k*) opts='-dm u::7,g::5,o:5' ;; 15 | *) opts='-m d:u::7,d:g::5,d:o:5' ;; 16 | esac 17 | setfacl $opts "$scratchdir" || test_skipped "Your filesystem has ACLs disabled" 18 | 19 | # Call as: testit 20 | testit() { 21 | todir="$scratchdir/$1" 22 | mkdir "$todir" 23 | $setfacl_nodef "$todir" 24 | if [ -n "$2" ]; then 25 | case "$setfacl_nodef" in 26 | *-k*) opts="-dm $2" ;; 27 | *) opts="-m `echo $2 | sed 's/\([ugom]:\)/d:\1/g'`" 28 | esac 29 | setfacl $opts "$todir" 30 | fi 31 | # Make sure we obey ACLs when creating a directory to hold multiple transferred files, 32 | # even though the directory itself is outside the transfer 33 | $RSYNC -rvv "$scratchdir/dir" "$scratchdir/file" "$scratchdir/program" "$todir/to/" 34 | check_perms "$todir/to" $4 "Target $1" 35 | check_perms "$todir/to/dir" $4 "Target $1" 36 | check_perms "$todir/to/file" $3 "Target $1" 37 | check_perms "$todir/to/program" $4 "Target $1" 38 | # Make sure get_local_name doesn't mess us up when transferring only one file 39 | $RSYNC -rvv "$scratchdir/file" "$todir/to/anotherfile" 40 | check_perms "$todir/to/anotherfile" $3 "Target $1" 41 | # Make sure we obey default ACLs when not transferring a regular file 42 | $RSYNC -rvv "$scratchdir/dir/" "$todir/to/anotherdir/" 43 | check_perms "$todir/to/anotherdir" $4 "Target $1" 44 | } 45 | 46 | mkdir "$scratchdir/dir" 47 | echo "File!" >"$scratchdir/file" 48 | echo "#!/bin/sh" >"$scratchdir/program" 49 | chmod 777 "$scratchdir/dir" 50 | chmod 666 "$scratchdir/file" 51 | chmod 777 "$scratchdir/program" 52 | 53 | # Test some target directories 54 | umask 0077 55 | testit da777 u::7,g::7,o:7 rw-rw-rw- rwxrwxrwx 56 | testit da775 u::7,g::7,o:5 rw-rw-r-- rwxrwxr-x 57 | testit da750 u::7,g::5,o:0 rw-r----- rwxr-x--- 58 | testit da750mask u::7,u:0:7,g::7,m:5,o:0 rw-r----- rwxr-x--- 59 | testit noda1 '' rw------- rwx------ 60 | umask 0000 61 | testit noda2 '' rw-rw-rw- rwxrwxrwx 62 | umask 0022 63 | testit noda3 '' rw-r--r-- rwxr-xr-x 64 | 65 | # Hooray 66 | exit 0 67 | -------------------------------------------------------------------------------- /testsuite/acls.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This program is distributable under the terms of the GNU GPL (see 4 | # COPYING). 5 | 6 | # Test that rsync handles basic ACL preservation. 7 | 8 | . $suitedir/rsync.fns 9 | 10 | $RSYNC -VV | grep '"ACLs": true' >/dev/null || test_skipped "Rsync is configured without ACL support" 11 | 12 | makepath "$fromdir/foo" 13 | echo something >"$fromdir/file1" 14 | echo else >"$fromdir/file2" 15 | 16 | files='foo file1 file2' 17 | 18 | case "$setfacl_nodef" in 19 | true) 20 | if ! chmod --help 2>&1 | grep -F +a >/dev/null; then 21 | test_skipped "I don't know how to use setfacl or chmod for ACLs" 22 | fi 23 | chmod +a "root allow read,write,execute" "$fromdir/foo" || test_skipped "Your filesystem has ACLs disabled" 24 | chmod +a "root allow read,execute" "$fromdir/file1" 25 | chmod +a "admin allow read" "$fromdir/file1" 26 | chmod +a "daemon allow read,write" "$fromdir/file1" 27 | chmod +a "root allow read,execute" "$fromdir/file2" 28 | 29 | see_acls() { 30 | ls -le "${@}" 31 | } 32 | ;; 33 | *) 34 | setfacl -m u:0:7 "$fromdir/foo" || test_skipped "Your filesystem has ACLs disabled" 35 | setfacl -m g:1:5 "$fromdir/foo" 36 | setfacl -m g:2:1 "$fromdir/foo" 37 | setfacl -m g:0:7 "$fromdir/foo" 38 | setfacl -m u:2:1 "$fromdir/foo" 39 | setfacl -m u:1:5 "$fromdir/foo" 40 | 41 | setfacl -m u:0:5 "$fromdir/file1" 42 | setfacl -m g:0:4 "$fromdir/file1" 43 | setfacl -m u:1:6 "$fromdir/file1" 44 | 45 | setfacl -m u:0:5 "$fromdir/file2" 46 | 47 | see_acls() { 48 | getfacl "${@}" 49 | } 50 | ;; 51 | esac 52 | 53 | cd "$fromdir" 54 | $RSYNC -avvA $files "$todir/" 55 | 56 | see_acls $files >"$scratchdir/acls.txt" 57 | 58 | cd "$todir" 59 | see_acls $files | diff $diffopt "$scratchdir/acls.txt" - 60 | 61 | # The script would have aborted on error, so getting here means we've won. 62 | exit 0 63 | -------------------------------------------------------------------------------- /testsuite/alt-dest.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2004-2022 Wayne Davison 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test rsync handling of --compare-dest and similar options. 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | alt1dir="$tmpdir/alt1" 13 | alt2dir="$tmpdir/alt2" 14 | alt3dir="$tmpdir/alt3" 15 | 16 | SSH="$scratchdir/src/support/lsh.sh" 17 | 18 | # Build some files/dirs/links to copy 19 | 20 | hands_setup 21 | 22 | # Setup the alt and chk dirs 23 | $RSYNC -av --include=text --include='*/' --exclude='*' "$fromdir/" "$alt1dir/" 24 | $RSYNC -av --include=etc-ltr-list --include='*/' --exclude='*' "$fromdir/" "$alt2dir/" 25 | 26 | # Create a side dir where there is a candidate destfile of the same name as a sourcefile 27 | echo "This is a test file" >"$fromdir/likely" 28 | 29 | mkdir "$alt3dir" 30 | echo "This is a test file" >"$alt3dir/likely" 31 | 32 | sleep 1 33 | touch "$fromdir/dir/text" "$fromdir/likely" 34 | 35 | $RSYNC -av --exclude=/text --exclude=etc-ltr-list "$fromdir/" "$chkdir/" 36 | 37 | # Let's do it! 38 | checkit "$RSYNC -avv --no-whole-file \ 39 | --compare-dest='$alt1dir' --compare-dest='$alt2dir' \ 40 | '$fromdir/' '$todir/'" "$chkdir" "$todir" 41 | 42 | rm -rf "$todir" 43 | checkit "$RSYNC -avv --no-whole-file \ 44 | --copy-dest='$alt1dir' --copy-dest='$alt2dir' \ 45 | '$fromdir/' '$todir/'" "$fromdir" "$todir" 46 | 47 | # Test that copy_file() works correctly with tmpfiles 48 | for maybe_inplace in '' --inplace; do 49 | rm -rf "$todir" 50 | checkit "$RSYNC -av $maybe_inplace --copy-dest='$alt3dir' \ 51 | '$fromdir/' '$todir/'" "$fromdir" "$todir" 52 | 53 | for srchost in '' 'localhost:'; do 54 | if [ -z "$srchost" ]; then 55 | desthost='localhost:' 56 | else 57 | desthost='' 58 | fi 59 | 60 | rm -rf "$todir" 61 | checkit "$RSYNC -ave '$SSH' --rsync-path='$RSYNC' $maybe_inplace \ 62 | --copy-dest='$alt3dir' '$srchost$fromdir/' '$desthost$todir/'" \ 63 | "$fromdir" "$todir" 64 | done 65 | done 66 | 67 | # The script would have aborted on error, so getting here means we've won. 68 | exit 0 69 | -------------------------------------------------------------------------------- /testsuite/atimes.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Test rsync copying atimes 4 | 5 | . "$suitedir/rsync.fns" 6 | 7 | $RSYNC -VV | grep '"atimes": true' >/dev/null || test_skipped "Rsync is configured without atimes support" 8 | 9 | mkdir "$fromdir" 10 | 11 | touch "$fromdir/foo" 12 | touch -a -t 200102031717.42 "$fromdir/foo" 13 | 14 | TLS_ARGS=--atimes 15 | 16 | checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" 17 | 18 | # The script would have aborted on error, so getting here means we've won. 19 | exit 0 20 | -------------------------------------------------------------------------------- /testsuite/backup.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2004-2022 Wayne Davison 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test that the --backup option works right. 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | bakdir="$tmpdir/bak" 13 | 14 | makepath "$fromdir/deep" "$bakdir/dname" 15 | name1="$fromdir/deep/name1" 16 | name2="$fromdir/deep/name2" 17 | 18 | cat "$srcdir"/[gr]*.[ch] > "$name1" 19 | cat "$srcdir"/[et]*.[ch] > "$name2" 20 | 21 | checkit "$RSYNC -ai --info=backup '$fromdir/' '$todir/'" "$fromdir" "$todir" 22 | 23 | checkit "$RSYNC -ai --info=backup '$fromdir/' '$chkdir/'" "$fromdir" "$chkdir" 24 | cat "$srcdir"/[fgpr]*.[ch] > "$name1" 25 | cat "$srcdir"/[etw]*.[ch] > "$name2" 26 | 27 | checktee "$RSYNC -ai --info=backup --no-whole-file --backup '$fromdir/' '$todir/'" 28 | for fn in deep/name1 deep/name2; do 29 | grep "backed up $fn to $fn~" "$outfile" >/dev/null || test_fail "no backup message output for $fn" 30 | diff $diffopt "$fromdir/$fn" "$todir/$fn" || test_fail "copy of $fn failed" 31 | diff $diffopt "$chkdir/$fn" "$todir/$fn~" || test_fail "backup of $fn to $fn~ failed" 32 | mv "$todir/$fn~" "$todir/$fn" 33 | done 34 | 35 | echo deleted-file >"$todir/dname" 36 | cp_touch "$todir/dname" "$chkdir" 37 | 38 | checkit "$RSYNC -ai --info=backup --no-whole-file --delete-delay \ 39 | --backup --backup-dir='$bakdir' '$fromdir/' '$todir/'" "$fromdir" "$todir" \ 40 | | tee "$outfile" 41 | 42 | for fn in deep/name1 deep/name2; do 43 | grep "backed up $fn to .*/$fn$" "$outfile" >/dev/null || test_fail "no backup message output for $fn" 44 | done 45 | diff -r $diffopt "$chkdir" "$bakdir" || test_fail "backup dir contents are bogus" 46 | rm "$bakdir/dname" 47 | 48 | checkit "$RSYNC -ai --info=backup --del '$fromdir/' '$chkdir/'" "$fromdir" "$chkdir" 49 | cat "$srcdir"/[efgr]*.[ch] > "$name1" 50 | cat "$srcdir"/[ew]*.[ch] > "$name2" 51 | 52 | checkit "$RSYNC -ai --info=backup --inplace --no-whole-file --backup --backup-dir='$bakdir' '$fromdir/' '$todir/'" "$fromdir" "$todir" \ 53 | | tee "$outfile" 54 | 55 | for fn in deep/name1 deep/name2; do 56 | grep "backed up $fn to .*/$fn$" "$outfile" >/dev/null || test_fail "no backup message output for $fn" 57 | done 58 | diff -r $diffopt "$chkdir" "$bakdir" || test_fail "backup dir contents are bogus" 59 | 60 | checkit "$RSYNC -ai --info=backup --inplace --no-whole-file '$fromdir/' '$bakdir/'" "$fromdir" "$bakdir" 61 | 62 | # The script would have aborted on error, so getting here means we've won. 63 | exit 0 64 | -------------------------------------------------------------------------------- /testsuite/batch-mode.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2004 by Chris Shoemaker 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test rsync's --write-batch and --read-batch options 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | hands_setup 13 | 14 | cd "$tmpdir" 15 | 16 | # Build chkdir for the daemon tests using a normal rsync and an --exclude. 17 | $RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/" 18 | 19 | $RSYNC -av --only-write-batch=BATCH --exclude=foobar.baz "$fromdir/" "$todir/missing/" 20 | test -d "$todir/missing" && test_fail "--only-write-batch should not have created destination dir" 21 | 22 | runtest "--read-batch (only)" 'checkit "$RSYNC -av --read-batch=BATCH \"$todir\"" "$chkdir" "$todir"' 23 | 24 | rm -rf "$todir" BATCH* 25 | runtest "local --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH \"$fromdir/\" \"$todir\"" "$fromdir" "$todir"' 26 | 27 | rm -rf "$todir" 28 | runtest "--read-batch" 'checkit "$RSYNC -av --read-batch=BATCH \"$todir\"" "$fromdir" "$todir"' 29 | 30 | build_rsyncd_conf 31 | 32 | RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon" 33 | export RSYNC_CONNECT_PROG 34 | 35 | rm -rf "$todir" 36 | runtest "daemon sender --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH rsync://localhost/test-from/ \"$todir\"" "$chkdir" "$todir"' 37 | 38 | rm -rf "$todir" 39 | runtest "--read-batch from daemon" 'checkit "$RSYNC -av --read-batch=BATCH \"$todir\"" "$chkdir" "$todir"' 40 | 41 | rm -rf "$todir" 42 | runtest "BATCH.sh use of --read-batch" 'checkit "./BATCH.sh" "$chkdir" "$todir"' 43 | 44 | runtest "do-nothing re-run of batch" 'checkit "./BATCH.sh" "$chkdir" "$todir"' 45 | 46 | rm -rf "$todir" 47 | mkdir "$todir" || test_fail "failed to restore empty destination directory" 48 | runtest "daemon recv --write-batch" 'checkit "\"$ignore23\" $RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"' 49 | 50 | # The script would have aborted on error, so getting here means we pass. 51 | exit 0 52 | -------------------------------------------------------------------------------- /testsuite/chgrp.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2002 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test that rsync with -gr will preserve groups when the user running 9 | # the test is a member of them. Hopefully they're in at least one 10 | # test. 11 | 12 | . "$suitedir/rsync.fns" 13 | 14 | # Build some hardlinks 15 | 16 | mygrps="`rsync_getgroups`" || test_fail "Can't get groups" 17 | mkdir "$fromdir" 18 | 19 | for g in $mygrps; do 20 | name="$fromdir/foo-$g" 21 | date > "$name" 22 | chgrp "$g" "$name" || test_fail "Can't chgrp" 23 | done 24 | sleep 2 25 | 26 | checkit "$RSYNC -rtgpvvv '$fromdir/' '$todir/'" "$fromdir" "$todir" 27 | 28 | # The script would have aborted on error, so getting here means we've won. 29 | exit 0 30 | -------------------------------------------------------------------------------- /testsuite/chmod-option.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2002 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test that the --chmod option functions correctly. 9 | 10 | . $suitedir/rsync.fns 11 | 12 | # Build some files 13 | 14 | fromdir="$scratchdir/from" 15 | todir="$scratchdir/to" 16 | checkdir="$scratchdir/check" 17 | 18 | mkdir "$fromdir" 19 | name1="$fromdir/name1" 20 | name2="$fromdir/name2" 21 | dir1="$fromdir/dir1" 22 | dir2="$fromdir/dir2" 23 | echo "This is the file" > "$name1" 24 | echo "This is the other file" > "$name2" 25 | mkdir "$dir1" "$dir2" 26 | 27 | chmod 4700 "$name1" || test_skipped "Can't chmod" 28 | chmod 700 "$dir1" 29 | chmod 770 "$dir2" 30 | 31 | # Copy the files we've created over to another directory 32 | checkit "$RSYNC -avv '$fromdir/' '$checkdir/'" "$fromdir" "$checkdir" 33 | 34 | # And then manually make the changes which should occur 35 | umask 002 36 | chmod ug-s,a+rX "$checkdir"/* 37 | chmod +w "$checkdir" "$checkdir"/dir* 38 | 39 | checkit "$RSYNC -avv --chmod ug-s,a+rX,D+w '$fromdir/' '$todir/'" "$checkdir" "$todir" 40 | 41 | rm -r "$fromdir" "$checkdir" "$todir" 42 | makepath "$todir" "$fromdir/foo" 43 | touch "$fromdir/bar" 44 | 45 | checkit "$RSYNC -avv '$fromdir/' '$checkdir/'" "$fromdir" "$checkdir" 46 | chmod o+x "$fromdir"/bar 47 | 48 | checkit "$RSYNC -avv --chmod=Fo-x '$fromdir/' '$todir/'" "$checkdir" "$todir" 49 | 50 | # Tickle a bug in rsync 2.6.8: if you push a new directory with --perms off to 51 | # a daemon with an incoming chmod, the daemon pretends the directory is a file 52 | # for the purposes of the second application of the incoming chmod. 53 | 54 | build_rsyncd_conf 55 | cat >>"$scratchdir/test-rsyncd.conf" < 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test that when rsync is running as root and has -a it correctly sets 9 | # the ownership of the destination. 10 | 11 | # We don't know what users will be present on this system, so we just 12 | # use random numeric uids and gids. 13 | 14 | . "$suitedir/rsync.fns" 15 | 16 | case $0 in 17 | *fake*) 18 | $RSYNC -VV | grep '"xattrs": true' >/dev/null || test_skipped "Rsync needs xattrs for fake device tests" 19 | RSYNC="$RSYNC --fake-super" 20 | TLS_ARGS="$TLS_ARGS --fake-super" 21 | case "$HOST_OS" in 22 | darwin*) 23 | chown() { 24 | own=$1 25 | shift 26 | xattr -s 'rsync.%stat' "100644 0,0 $own" "${@}" 27 | } 28 | ;; 29 | solaris*) 30 | chown() { 31 | own=$1 32 | shift 33 | for fn in "${@}"; do 34 | runat "$fn" "$SHELL_PATH" < rsync.%stat 36 | EOF 37 | done 38 | } 39 | ;; 40 | freebsd*) 41 | chown() { 42 | own=$1 43 | shift 44 | setextattr -h user "rsync.%stat" "100644 0,0 $own" "${@}" 45 | } 46 | ;; 47 | *) 48 | chown() { 49 | own=$1 50 | shift 51 | setfattr -n 'user.rsync.%stat' -v "100644 0,0 $own" "${@}" 52 | } 53 | ;; 54 | esac 55 | ;; 56 | *) 57 | RSYNC="$RSYNC --super" 58 | my_uid=`get_testuid` 59 | root_uid=`get_rootuid` 60 | if test x"$my_uid" = x; then 61 | : # If "id" failed, try to continue... 62 | elif test x"$my_uid" != x"$root_uid"; then 63 | if [ -e "$FAKEROOT_PATH" ]; then 64 | echo "Let's try re-running the script under fakeroot..." 65 | exec "$FAKEROOT_PATH" "$SHELL_PATH" "$0" 66 | fi 67 | fi 68 | ;; 69 | esac 70 | 71 | # Build some hardlinks 72 | 73 | mkdir "$fromdir" 74 | name1="$fromdir/name1" 75 | name2="$fromdir/name2" 76 | echo "This is the file" > "$name1" 77 | echo "This is the other file" > "$name2" 78 | 79 | chown 5000:5002 "$name1" || test_skipped "Can't chown (probably need root)" 80 | chown 5001:5003 "$name2" || test_skipped "Can't chown (probably need root)" 81 | 82 | cd "$fromdir/.." 83 | checkit "$RSYNC -aHvv from/ to/" "$fromdir" "$todir" 84 | 85 | # The script would have aborted on error, so getting here means we've won. 86 | exit 0 87 | -------------------------------------------------------------------------------- /testsuite/crtimes.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Test rsync copying create times 4 | 5 | . "$suitedir/rsync.fns" 6 | 7 | $RSYNC -VV | grep '"crtimes": true' >/dev/null || test_skipped "Rsync is configured without crtimes support" 8 | 9 | # Setting an older time via touch sets the create time to the mtime. 10 | # Setting it to a newer time affects just the mtime. 11 | 12 | mkdir "$fromdir" 13 | echo hiho >"$fromdir/foo" 14 | 15 | touch -t 200101011111.11 "$fromdir" 16 | touch -t 200202022222.22 "$fromdir" 17 | 18 | touch -t 200111111111.11 "$fromdir/foo" 19 | touch -t 200212122222.22 "$fromdir/foo" 20 | 21 | TLS_ARGS=--crtimes 22 | 23 | checkit "$RSYNC -rtgvvv --crtimes \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" 24 | 25 | # The script would have aborted on error, so getting here means we've won. 26 | exit 0 27 | -------------------------------------------------------------------------------- /testsuite/daemon-gzip-download.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2001, 2002 by Martin Pool 4 | 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | 19 | # This test tries to download a tree over a compressed connection from 20 | # the server. This ought to exercise (exorcise?) a bug in 2.5.3. 21 | 22 | . "$suitedir/rsync.fns" 23 | 24 | build_rsyncd_conf 25 | 26 | RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon" 27 | export RSYNC_CONNECT_PROG 28 | 29 | hands_setup 30 | 31 | # Build chkdir with a normal rsync and an --exclude. 32 | $RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/" 33 | 34 | checkit "$RSYNC -avvvvzz localhost::test-from/ '$todir/'" "$chkdir" "$todir" 35 | 36 | # The script would have aborted on error, so getting here means we've won. 37 | exit 0 38 | -------------------------------------------------------------------------------- /testsuite/daemon-gzip-upload.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2001, 2002 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING) 7 | 8 | # We don't really want to start the server listening, because that 9 | # might interfere with the security or operation of the test machine. 10 | # Instead we use the fake-connect feature to dynamically assign a pair 11 | # of ports. 12 | 13 | # This test tries to upload a file over a compressed connection to the 14 | # server. This ought to exercise (exorcise?) a bug in 2.5.3. 15 | 16 | . "$suitedir/rsync.fns" 17 | 18 | build_rsyncd_conf 19 | 20 | RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon" 21 | export RSYNC_CONNECT_PROG 22 | 23 | hands_setup 24 | 25 | # Build chkdir with a normal rsync and an --exclude. 26 | $RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/" 27 | 28 | checkit "'$ignore23' $RSYNC -avvvvzz '$fromdir/' localhost::test-to/" "$chkdir" "$todir" 29 | 30 | # The script would have aborted on error, so getting here means we've won. 31 | exit 0 32 | -------------------------------------------------------------------------------- /testsuite/daemon.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2001 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING) 7 | 8 | # We don't really want to start the server listening, because that 9 | # might interfere with the security or operation of the test machine. 10 | # Instead we use the fake-connect feature to dynamically assign a pair 11 | # of ports. 12 | 13 | # Having started the server we try some basic operations against it: 14 | 15 | # getting a list of module 16 | # listing files in a module 17 | # retrieving a module 18 | # uploading to a module 19 | # checking the log file 20 | # password authentication 21 | 22 | . "$suitedir/rsync.fns" 23 | 24 | SSH="src/support/lsh.sh --no-cd" 25 | FILE_REPL='s/^\([^d][^ ]*\) *\(..........[0-9]\) /\1 \2 /' 26 | DIR_REPL='s/^\(d[^ ]*\) *[0-9][.,0-9]* /\1 DIR /' 27 | LS_REPL='s;[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ;####/##/## ##:##:## ;g' 28 | 29 | build_rsyncd_conf 30 | 31 | makepath "$fromdir/foo" "$fromdir/bar/baz" 32 | makepath "$todir" 33 | echo one >"$fromdir/foo/one" 34 | echo two >"$fromdir/bar/two" 35 | echo three >"$fromdir/bar/baz/three" 36 | 37 | cd "$scratchdir" 38 | 39 | ln -s test-rsyncd.conf rsyncd.conf 40 | 41 | my_uid=`get_testuid` 42 | root_uid=`get_rootuid` 43 | confopt='' 44 | if test x"$my_uid" = x"$root_uid"; then 45 | # Root needs to specify the config file, or it uses /etc/rsyncd.conf. 46 | echo "Forcing --config=$conf" 47 | confopt=" --config=$conf" 48 | fi 49 | 50 | # These have a space-padded 15-char name, then a tab, then a comment. 51 | sed 's/NOCOMMENT//' <"$chkfile" 52 | test-from r/o 53 | test-to r/w 54 | test-scratch NOCOMMENT 55 | EOT 56 | 57 | checkdiff2 "$RSYNC -ve '$SSH' --rsync-path='$RSYNC$confopt' localhost::" 58 | echo '====' 59 | 60 | RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon" 61 | export RSYNC_CONNECT_PROG 62 | 63 | checkdiff2 "$RSYNC -v localhost::" 64 | echo '====' 65 | 66 | checkdiff "$RSYNC -r localhost::test-hidden" \ 67 | "sed -e '$FILE_REPL' -e '$DIR_REPL' -e '$LS_REPL'" </dev/null; then 85 | checkdiff "$RSYNC -rU localhost::test-from/f*" \ 86 | "sed -e '$FILE_REPL' -e '$DIR_REPL' -e '$LS_REPL'" < "$fromdir/foo" 10 | 11 | checkit "$RSYNC -aiv --delay-updates \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" 12 | 13 | mkdir "$todir/.~tmp~" 14 | echo 2 > "$todir/.~tmp~/foo" 15 | touch -r .. "$todir/.~tmp~/foo" "$todir/foo" 16 | echo 3 > "$fromdir/foo" 17 | 18 | checkit "$RSYNC -aiv --delay-updates \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" 19 | 20 | # The script would have aborted on error, so getting here means we've won. 21 | exit 0 22 | -------------------------------------------------------------------------------- /testsuite/delete.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2005-2022 Wayne Davison 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test rsync handling of various delete directives. 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | hands_setup 13 | 14 | makepath "$chkdir" "$todir/extradir" "$todir/emptydir/subdir" 15 | 16 | echo extra >"$todir"/remove1 17 | echo extra >"$todir"/remove2 18 | echo extra >"$todir"/extradir/remove3 19 | echo extra >"$todir"/emptydir/subdir/remove4 20 | 21 | # Create two chk dirs, one with a copy of the source files, and one with 22 | # what we expect to be left behind by the copy using --remove-source-files. 23 | # Also, make sure that --dry-run --del doesn't output anything extraneous. 24 | $RSYNC -av "$fromdir/" "$chkdir/copy/" >"$tmpdir/copy.out" 2>&1 25 | cat "$tmpdir/copy.out" 26 | grep -E -v '^(created directory|sent|total size) ' "$tmpdir/copy.out" >"$tmpdir/copy.new" 27 | mv "$tmpdir/copy.new" "$tmpdir/copy.out" 28 | 29 | $RSYNC -avn --del "$fromdir/" "$chkdir/copy2/" >"$tmpdir/copy2.out" 2>&1 || true 30 | cat "$tmpdir/copy2.out" 31 | grep -E -v '^(created directory|sent|total size) ' "$tmpdir/copy2.out" >"$tmpdir/copy2.new" 32 | mv "$tmpdir/copy2.new" "$tmpdir/copy2.out" 33 | 34 | diff $diffopt "$tmpdir/copy.out" "$tmpdir/copy2.out" 35 | 36 | $RSYNC -av -f 'exclude,! */' "$fromdir/" "$chkdir/empty/" 37 | 38 | checkit "$RSYNC -avv --del --remove-source-files '$fromdir/' '$todir/'" "$chkdir/copy" "$todir" 39 | 40 | diff -r "$chkdir/empty" "$fromdir" 41 | 42 | # Make sure that "P" but not "-" per-dir merge-file filters take effect with 43 | # --delete-excluded. 44 | cat >"$todir/filters" < 13 | testit() { 14 | todir="$scratchdir/$1" 15 | mkdir "$todir" 16 | chmod $2 "$todir" 17 | # Make sure we obey directory setgid when creating a directory to hold multiple transferred files, 18 | # even though the directory itself is outside the transfer 19 | $RSYNC -rvv "$scratchdir/dir" "$scratchdir/file" "$scratchdir/program" "$todir/to/" 20 | check_perms "$todir/to" $5 "Target $1" 21 | check_perms "$todir/to/dir" $5 "Target $1" 22 | check_perms "$todir/to/file" $3 "Target $1" 23 | check_perms "$todir/to/program" $4 "Target $1" 24 | } 25 | 26 | mkdir "$scratchdir/dir" 27 | # Cygwin has a persistent default dir ACL that ruins this test. 28 | case `getfacl "$scratchdir/dir" 2>/dev/null || true` in 29 | *default:user::*) test_skipped "The default ACL mode interferes with this test" ;; 30 | esac 31 | 32 | echo "File!" >"$scratchdir/file" 33 | echo "#!/bin/sh" >"$scratchdir/program" 34 | 35 | chmod u=rwx,g=rw,g+s,o=r "$scratchdir/dir" || test_skipped "Can't chmod" 36 | chmod 664 "$scratchdir/file" 37 | chmod 775 "$scratchdir/program" 38 | 39 | [ -g "$scratchdir/dir" ] || test_skipped "The directory setgid bit vanished!" 40 | mkdir "$scratchdir/dir/blah" 41 | [ -g "$scratchdir/dir/blah" ] || test_skipped "Your filesystem doesn't use directory setgid; maybe it's BSD." 42 | 43 | # Test some target directories 44 | testit setgid-off 700 rw------- rwx------ rwx------ 45 | testit setgid-on u=rwx,g=rw,g+s,o-rwx rw------- rwx------ rwx--S--- 46 | 47 | # Hooray 48 | exit 0 49 | -------------------------------------------------------------------------------- /testsuite/duplicates.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2002 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test rsync handling of duplicate filenames. 9 | 10 | # It's quite possible that the user might specify the same source file 11 | # more than once on the command line, perhaps through shell variables 12 | # or wildcard expansions. It might cause problems for rsync if the 13 | # same name occurred more than once in the file list, because we might 14 | # be trying to update the first copy and generate checksums for the 15 | # second copy at the same time. See clean_flist() for the implementation. 16 | 17 | # We don't need to worry about hardlinks or symlinks. Because we 18 | # always rename-and-replace the new copy, they can't affect us. 19 | 20 | # This test is not great, because it is a timing-dependent bug. 21 | 22 | . "$suitedir/rsync.fns" 23 | 24 | # Build some hardlinks 25 | 26 | mkdir "$fromdir" 27 | name1="$fromdir/name1" 28 | name2="$fromdir/name2" 29 | echo "This is the file" > "$name1" 30 | ln -s "$name1" "$name2" || test_fail "can't create symlink" 31 | 32 | checkit "$RSYNC -avv '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$fromdir/' '$todir/'" "$fromdir" "$todir" \ 33 | | tee "$outfile" 34 | 35 | # Make sure each file was only copied once... 36 | if [ `grep -c '^name1$' "$outfile"` != 1 ]; then 37 | test_fail "name1 was not copied exactly once" 38 | fi 39 | if [ `grep -c '^name2 -> ' "$outfile"` != 1 ]; then 40 | test_fail "name2 was not copied exactly once" 41 | fi 42 | 43 | # The script would have aborted on error, so getting here means we've won. 44 | exit 0 45 | -------------------------------------------------------------------------------- /testsuite/exclude-lsh.test: -------------------------------------------------------------------------------- 1 | exclude.test -------------------------------------------------------------------------------- /testsuite/executability.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This program is distributable under the terms of the GNU GPL (see 4 | # COPYING). 5 | 6 | # Test the --executability or -E option. -- Matt McCutchen 7 | 8 | . $suitedir/rsync.fns 9 | 10 | # Put some files in the From directory 11 | mkdir "$fromdir" 12 | cat <"$fromdir/1" 13 | #!/bin/sh 14 | echo 'Program One!' 15 | EOF 16 | cat <"$fromdir/2" 17 | #!/bin/sh 18 | echo 'Program Two!' 19 | EOF 20 | 21 | chmod 1700 "$fromdir/1" || test_skipped "Can't chmod" 22 | chmod 600 "$fromdir/2" 23 | 24 | $RSYNC -rvv "$fromdir/" "$todir/" 25 | 26 | check_perms "$todir/1" rwx------ 1 27 | check_perms "$todir/2" rw------- 1 28 | 29 | # Mix up the permissions a bit 30 | chmod 600 "$fromdir/1" 31 | chmod 601 "$fromdir/2" 32 | chmod 604 "$todir/2" 33 | 34 | $RSYNC -rvv "$fromdir/" "$todir/" 35 | 36 | # No -E, so nothing should have changed 37 | check_perms "$todir/1" rwx------ 2 38 | check_perms "$todir/2" rw----r-- 2 39 | 40 | $RSYNC -rvvE "$fromdir/" "$todir/" 41 | 42 | # Now things should have happened! 43 | check_perms "$todir/1" rw------- 3 44 | check_perms "$todir/2" rwx---r-x 3 45 | 46 | # Hooray 47 | exit 0 48 | -------------------------------------------------------------------------------- /testsuite/files-from.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2008-2020 Wayne Davison 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test that --files-from=FILE works right. 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | SSH="$scratchdir/src/support/lsh.sh" 13 | 14 | hands_setup 15 | 16 | # This list of files skips the contents of "subsubdir" but includes 17 | # the contents of "subsubdir2" due to its trailing slash. 18 | cat >"$scratchdir/filelist" < 4 | # Copyright (C) 2001, 2002 by Martin Pool 5 | # 6 | # This program is distributable under the terms of the GNU GPL (see COPYING) 7 | 8 | . "$suitedir/rsync.fns" 9 | 10 | hands_setup 11 | 12 | DEBUG_OPTS="--debug=all0,deltasum0" 13 | 14 | # Main script starts here 15 | 16 | runtest "basic operation" 'checkit "$RSYNC -av \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"' 17 | 18 | ln "$fromdir/filelist" "$fromdir/dir" 19 | runtest "hard links" 'checkit "$RSYNC -avH --bwlimit=0 $DEBUG_OPTS \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"' 20 | 21 | rm "$todir/text" 22 | runtest "one file" 'checkit "$RSYNC -avH $DEBUG_OPTS \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"' 23 | 24 | echo "extra line" >> "$todir/text" 25 | runtest "extra data" 'checkit "$RSYNC -avH $DEBUG_OPTS --no-whole-file \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"' 26 | 27 | cp "$fromdir/text" "$todir/ThisShouldGo" 28 | runtest " --delete" 'checkit "$RSYNC --delete -avH $DEBUG_OPTS \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"' 29 | 30 | cd "$tmpdir" 31 | rm -rf to from/*dir 32 | 33 | # Do the real copy, touch up the parent-dir's time, and then check the copy. 34 | $RSYNC -av from/* to/ 35 | checkit "$RSYNC -av --exclude='*' from/ to/" "$fromdir" "$todir" 36 | 37 | # The script would have aborted on error, so getting here means we've won. 38 | exit 0 39 | -------------------------------------------------------------------------------- /testsuite/hardlinks.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2002 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test rsync handling of hardlinks. By default, rsync does not detect 9 | # hard links and they get sent as separate files. If you specify -H, 10 | # then hard links are detected and linked together on the receiver. 11 | 12 | . "$suitedir/rsync.fns" 13 | 14 | SSH="$scratchdir/src/support/lsh.sh" 15 | 16 | # Build some hardlinks 17 | 18 | fromdir="$scratchdir/from" 19 | todir="$scratchdir/to" 20 | 21 | # TODO: Need to test whether hardlinks are possible on this OS/filesystem 22 | 23 | mkdir "$fromdir" 24 | name1="$fromdir/name1" 25 | name2="$fromdir/name2" 26 | name3="$fromdir/name3" 27 | name4="$fromdir/name4" 28 | echo "This is the file" > "$name1" 29 | ln "$name1" "$name2" || test_skipped "Can't create hardlink" 30 | ln "$name2" "$name3" || test_fail "Can't create hardlink" 31 | cp "$name2" "$name4" || test_fail "Can't copy file" 32 | cat $srcdir/*.c >"$fromdir/text" 33 | 34 | checkit "$RSYNC -aHivv --debug=HLINK5 '$fromdir/' '$todir/'" "$fromdir" "$todir" 35 | 36 | echo "extra extra" >>"$todir/name1" 37 | 38 | checkit "$RSYNC -aHivv --debug=HLINK5 --no-whole-file '$fromdir/' '$todir/'" "$fromdir" "$todir" 39 | 40 | # Add a new link in a new subdirectory to test that we don't try to link 41 | # the files before the directory gets created. We also create a bunch of 42 | # extra files to ensure that an incremental-recursion transfer works across 43 | # distant files. 44 | makepath "$fromdir/subdir/down/deep" 45 | 46 | files='' 47 | for x in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9; do 48 | for y in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9; do 49 | files="$files $x$y" 50 | done 51 | done 52 | (cd "$fromdir/subdir"; touch $files) 53 | 54 | ln "$name1" "$fromdir/subdir/down/deep/new-file" 55 | rm "$todir/text" 56 | 57 | checkit "$RSYNC -aHivve '$SSH' --debug=HLINK5 --rsync-path='$RSYNC' '$fromdir/' localhost:'$todir/'" "$fromdir" "$todir" 58 | 59 | # Do some duplicate copies using --link-dest and --copy-dest to test that 60 | # we hard-link all locally-inherited items. 61 | checkit "$RSYNC -aHivv --debug=HLINK5 --link-dest='$todir' '$fromdir/' '$chkdir/'" "$todir" "$chkdir" 62 | 63 | rm -rf "$chkdir" 64 | checkit "$RSYNC -aHivv --debug=HLINK5 --copy-dest='$todir' '$fromdir/' '$chkdir/'" "$fromdir" "$chkdir" 65 | 66 | # Create a hard link that has only one part in the hierarchy. 67 | echo "This is another file" >"$fromdir/solo" 68 | ln "$fromdir/solo" "$chkdir/solo" || test_fail "Can't create hardlink" 69 | 70 | # Make sure that the checksum data doesn't slide due to an HLINK_BUMP() change. 71 | checktee "$RSYNC -aHivc --debug=HLINK5 '$fromdir/' '$chkdir/'" 72 | grep solo "$outfile" && test_fail "Erroneous copy of solo file occurred!" 73 | 74 | # Make sure there's nothing wrong with sending a single file with -H 75 | # enabled (this has broken twice so far, so we need this test). 76 | rm -rf "$todir" 77 | $RSYNC -aHivv --debug=HLINK5 "$name1" "$todir/" 78 | diff $diffopt "$name1" "$todir" || test_fail "solo copy of name1 failed" 79 | 80 | # Make sure there's nothing wrong with sending a single directory with -H 81 | # enabled (this has broken in 3.4.0 so far, so we need this test). 82 | rm -rf "$fromdir" "$todir" 83 | makepath "$fromdir/sym" "$todir" 84 | checkit "$RSYNC -aH '$fromdir/sym' '$todir'" "$fromdir" "$todir" 85 | 86 | # The script would have aborted on error, so getting here means we've won. 87 | exit 0 88 | -------------------------------------------------------------------------------- /testsuite/longdir.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 1998,1999 Philip Hands 4 | # Copyright (C) 2001 by Martin Pool 5 | # 6 | # This program is distributable under the terms of the GNU GPL (see COPYING) 7 | 8 | . "$suitedir/rsync.fns" 9 | 10 | hands_setup 11 | 12 | longname=This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job 13 | longdir="$fromdir/$longname/$longname/$longname" 14 | 15 | makepath "$longdir" || test_skipped "unable to create long directory" 16 | touch "$longdir/1" || test_skipped "unable to create files in long directory" 17 | date > "$longdir/1" 18 | if [ -r /etc ]; then 19 | ls -la /etc >"$longdir/2" 20 | else 21 | ls -la / >"$longdir/2" 22 | fi 23 | checkit "$RSYNC --delete -avH '$fromdir/' '$todir'" "$fromdir/" "$todir" 24 | 25 | # The script would have aborted on error, so getting here means we've won. 26 | exit 0 27 | -------------------------------------------------------------------------------- /testsuite/merge.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2004-2022 Wayne Davison 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Make sure we can merge files from multiple directories into one. 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | # Build some files/dirs/links to copy 13 | 14 | # Use local dirnames to better exercise the arg-parsing code. 15 | cd "$tmpdir" 16 | 17 | mkdir from1 from2 from3 deep 18 | mkdir from2/sub1 from3/sub1 19 | mkdir from3/sub2 from1/dir-and-not-dir 20 | mkdir chk chk/sub1 chk/sub2 chk/dir-and-not-dir 21 | echo "one" >from1/one 22 | cp_touch from1/one from2/one 23 | cp_touch from1/one from3/one 24 | echo "two" >from1/two 25 | echo "three" >from2/three 26 | echo "four" >from3/four 27 | echo "five" >from1/five 28 | echo "six" >from3/six 29 | echo "sub1" >from2/sub1/uno 30 | cp_touch from2/sub1/uno from3/sub1/uno 31 | echo "sub2" >from3/sub1/dos 32 | echo "sub3" >from2/sub1/tres 33 | echo "subby" >from3/sub2/subby 34 | echo "extra" >from1/dir-and-not-dir/inside 35 | echo "not-dir" >from3/dir-and-not-dir 36 | echo "arg-test" >deep/arg-test 37 | echo "shallow" >shallow 38 | 39 | cp_touch from1/one from1/two from2/three from3/four from1/five from3/six chk 40 | cp_touch deep/arg-test shallow chk 41 | cp_touch from1/dir-and-not-dir/inside chk/dir-and-not-dir 42 | cp_touch from2/sub1/uno from3/sub1/dos from2/sub1/tres chk/sub1 43 | cp_touch from3/sub2/subby chk/sub2 44 | 45 | # Make sure that time has moved on. 46 | sleep 1 47 | 48 | # Get rid of any directory-time differences 49 | $RSYNC -av --existing -f 'exclude,! */' from1/ from2/ 50 | $RSYNC -av --existing -f 'exclude,! */' from2/ from3/ 51 | $RSYNC -av --existing -f 'exclude,! */' from1/ chk/ 52 | $RSYNC -av --existing -f 'exclude,! */' from3/ chk/ 53 | 54 | checkit "$RSYNC -avv deep/arg-test shallow from1/ from2/ from3/ to/" "$chkdir" "$todir" 55 | 56 | # The script would have aborted on error, so getting here means we've won. 57 | exit 0 58 | -------------------------------------------------------------------------------- /testsuite/missing.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This program is distributable under the terms of the GNU GPL (see 4 | # COPYING). 5 | 6 | # Test three bugs fixed by my redoing of the missing_below logic. 7 | 8 | . $suitedir/rsync.fns 9 | 10 | makepath "$fromdir/subdir" "$todir" 11 | echo data >"$fromdir/subdir/file" 12 | echo data >"$todir/other" 13 | 14 | # Test 1: Too much "not creating new..." output on a dry run 15 | $RSYNC -n -r --ignore-non-existing -vv "$fromdir/" "$todir/" | tee "$scratchdir/out" 16 | if grep 'not creating new.*subdir/file' "$scratchdir/out" >/dev/null; then 17 | test_fail 'test 1 failed' 18 | fi 19 | 20 | case "$RSYNC" in 21 | *protocol=29*) # FIXME can we get past the new flist sanity check in protocol 29? 22 | echo "Skipped test 2 for protocol 29." 23 | ;; 24 | *) 25 | # Test 2: Attempt to make a fuzzy dirlist for a dir not created on a dry run 26 | $RSYNC -n -r -R --no-implied-dirs -y "$fromdir/./subdir/file" "$todir/" \ 27 | || test_fail 'test 2 failed' 28 | ;; 29 | esac 30 | 31 | # Test 3: --delete-after pass skipped when last dir is dry-missing 32 | $RSYNC -n -r --delete-after -i "$fromdir/" "$todir/" | tee "$scratchdir/out" 33 | grep '^\*deleting * other' "$scratchdir/out" >/dev/null \ 34 | || test_fail 'test 3 failed' 35 | -------------------------------------------------------------------------------- /testsuite/mkpath.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . "$suitedir/rsync.fns" 4 | 5 | makepath "$fromdir" 6 | makepath "$todir" 7 | 8 | cp_p "$srcdir/rsync.h" "$fromdir/text" 9 | cp_p "$srcdir/configure.ac" "$fromdir/extra" 10 | 11 | cd "$tmpdir" 12 | 13 | deep_dir=to/foo/bar/baz/down/deep 14 | 15 | # Check that we can create several levels of dest dir 16 | $RSYNC -aiv --mkpath from/text $deep_dir/new 17 | test -f $deep_dir/new || test_fail "'new' file not found in $deep_dir dir" 18 | rm -rf to/foo 19 | 20 | $RSYNC -aiv --mkpath from/text $deep_dir/ 21 | test -f $deep_dir/text || test_fail "'text' file not found in $deep_dir dir" 22 | rm $deep_dir/text 23 | 24 | # Make sure we can handle an existing path 25 | mkdir $deep_dir/new 26 | $RSYNC -aiv --mkpath from/text $deep_dir/new 27 | test -f $deep_dir/new/text || test_fail "'text' file not found in $deep_dir/new dir" 28 | 29 | # ... and an existing path when an alternate dest filename is specified 30 | $RSYNC -aiv --mkpath from/text $deep_dir/new/text2 31 | test -f $deep_dir/new/text2 || test_fail "'text2' file not found in $deep_dir/new dir" 32 | rm -rf to/foo 33 | 34 | # Try the tests again with multiple source args 35 | $RSYNC -aiv --mkpath from/ $deep_dir 36 | test -f $deep_dir/extra || test_fail "'extra' file not found in $deep_dir dir" 37 | rm -rf to/foo 38 | 39 | $RSYNC -aiv --mkpath from/ $deep_dir/ 40 | test -f $deep_dir/text || test_fail "'text' file not found in $deep_dir dir" 41 | 42 | # Make sure that we can handle no path 43 | $RSYNC -aiv --mkpath from/text to_text 44 | test -f to_text || test_fail "'to_text' file not found in current dir" 45 | 46 | # The script would have aborted on error, so getting here means we've won. 47 | exit 0 48 | -------------------------------------------------------------------------------- /testsuite/protected-regular.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2021 by Achim Leitner 4 | # This program is distributable under the terms of the GNU GPL (see COPYING) 5 | # 6 | # Modern linux systems have the protected_regular feature set to 1 or 2 7 | # See https://www.kernel.org/doc/Documentation/sysctl/fs.txt 8 | # Make sure we can still write these files in --inplace mode 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | test -f /proc/sys/fs/protected_regular || test_skipped "Can't find protected_regular setting (only available on Linux)" 13 | pr_lvl=`cat /proc/sys/fs/protected_regular 2>/dev/null` || test_skipped "Can't check if fs.protected_regular is enabled (probably need root)" 14 | test "$pr_lvl" != 0 || test_skipped "fs.protected_regular is not enabled" 15 | 16 | workdir="$tmpdir/files" 17 | mkdir "$workdir" 18 | chmod 1777 "$workdir" 19 | 20 | echo "Source" > "$workdir/src" 21 | echo "" > "$workdir/dst" 22 | chown 5001 "$workdir/dst" || test_skipped "Can't chown (probably need root)" 23 | 24 | # Output is only shown in case of an error 25 | echo "Contents of $workdir:" 26 | ls -al "$workdir" 27 | 28 | $RSYNC --inplace "$workdir/src" "$workdir/dst" || test_fail 29 | 30 | # The script would have aborted on error, so getting here means we've won. 31 | exit 0 32 | -------------------------------------------------------------------------------- /testsuite/relative.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2005-2020 Wayne Davison 4 | # 5 | # This program is distributable under the terms of the GNU GPL (see COPYING) 6 | 7 | . "$suitedir/rsync.fns" 8 | 9 | deepstr='down/3/deep' 10 | deepdir="$fromdir/$deepstr" 11 | extradir="$fromdir/extra" 12 | makepath "$deepdir" "$extradir/$deepstr" "$chkdir" 13 | 14 | fromdir="$deepdir" 15 | hands_setup 16 | fromdir="$tmpdir/from" 17 | 18 | extrafile="$extradir/./$deepstr/extra.added.value" 19 | echo wowza >"$extrafile" 20 | 21 | $RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$extradir/" 22 | 23 | cd "$fromdir" 24 | 25 | # Main script starts here 26 | 27 | $RSYNC -ai --include=/down/ --exclude='/*' "$fromdir/" "$chkdir/" 28 | 29 | sleep 1 30 | runtest "basic relative" 'checkit "$RSYNC -avR ./$deepstr \"$todir\"" "$chkdir" "$todir"' 31 | 32 | ln $deepstr/filelist $deepstr/dir 33 | ln ../chk/$deepstr/filelist ../chk/$deepstr/dir 34 | # Work around time rounding/truncating issue by touching both dirs. 35 | touch -r $deepstr/dir $deepstr/dir ../chk/$deepstr/dir 36 | runtest "hard links" 'checkit "$RSYNC -avHR ./$deepstr/ \"$todir\"" "$chkdir" "$todir"' 37 | 38 | cp "$deepdir/text" "$todir/$deepstr/ThisShouldGo" 39 | cp "$deepdir/text" "$todir/$deepstr/dir/ThisShouldGoToo" 40 | runtest "deletion" 'checkit "$RSYNC -avHR --del ./$deepstr/ \"$todir\"" "$chkdir" "$todir"' 41 | 42 | runtest "non-deletion" 'checkit "$RSYNC -aiHR --del ./$deepstr/ \"$todir\"" "$chkdir" "$todir"' \ 43 | | tee "$outfile" 44 | 45 | # Make sure no files were deleted 46 | grep 'deleting ' "$outfile" && test_fail "Erroneous deletions occurred!" 47 | 48 | # Relative with merging. 49 | $RSYNC -ai "$extradir/down" "$chkdir/" 50 | 51 | checkit "$RSYNC -aiR $deepstr '$extrafile' '$todir'" "$chkdir" "$todir" 52 | 53 | checkit "$RSYNC -aiR --del $deepstr '$extrafile' '$todir'" "$chkdir" "$todir" \ 54 | | tee "$outfile" 55 | 56 | # Make sure no files were deleted 57 | grep 'deleting ' "$outfile" && test_fail "Erroneous deletions occurred! (2)" 58 | 59 | # The script would have aborted on error, so getting here means we've won. 60 | exit 0 61 | -------------------------------------------------------------------------------- /testsuite/safe-links.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . "$suitedir/rsync.fns" 4 | 5 | test_symlink() { 6 | is_a_link "$1" || test_fail "File $1 is not a symlink" 7 | } 8 | 9 | test_regular() { 10 | if [ ! -f "$1" ]; then 11 | test_fail "File $1 is not regular file or not exists" 12 | fi 13 | } 14 | 15 | test_notexist() { 16 | if [ -e "$1" ]; then 17 | test_fail "File $1 exists" 18 | fi 19 | if [ -h "$1" ]; then 20 | test_fail "File $1 exists as a symlink" 21 | fi 22 | } 23 | 24 | cd "$tmpdir" 25 | 26 | mkdir from 27 | 28 | mkdir "from/safe" 29 | mkdir "from/unsafe" 30 | 31 | mkdir "from/safe/files" 32 | mkdir "from/safe/links" 33 | 34 | touch "from/safe/files/file1" 35 | touch "from/safe/files/file2" 36 | touch "from/unsafe/unsafefile" 37 | 38 | ln -s ../files/file1 "from/safe/links/" 39 | ln -s ../files/file2 "from/safe/links/" 40 | ln -s ../../unsafe/unsafefile "from/safe/links/" 41 | ln -s a/a/a/../../../unsafe2 "from/safe/links/" 42 | 43 | #echo "LISTING FROM" 44 | #ls -lR from 45 | 46 | echo "rsync with relative path and just -a" 47 | $RSYNC -avv --safe-links from/safe/ to 48 | 49 | #echo "LISTING TO" 50 | #ls -lR to 51 | 52 | test_symlink to/links/file1 53 | test_symlink to/links/file2 54 | test_notexist to/links/unsafefile 55 | test_notexist to/links/unsafe2 56 | -------------------------------------------------------------------------------- /testsuite/ssh-basic.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 1998,1999 Philip Hands 4 | # Copyright (C) 2001 by Martin Pool 5 | 6 | # This program is distributable under the terms of the GNU GPL (see 7 | # COPYING) 8 | 9 | # This script tests ssh, if possible. It's called by runtests.sh 10 | 11 | . "$suitedir/rsync.fns" 12 | 13 | SSH="$scratchdir/src/support/lsh.sh" 14 | 15 | if test x"$rsync_enable_ssh_tests" = xyes; then 16 | if type ssh >/dev/null; then 17 | SSH=ssh 18 | fi 19 | fi 20 | 21 | if [ "`$SSH -o'BatchMode yes' localhost echo yes`" != "yes" ]; then 22 | test_skipped "Skipping SSH tests because ssh connection to localhost not authorised" 23 | fi 24 | 25 | echo "Using remote shell: $SSH" 26 | 27 | # Create some files for rsync to copy 28 | hands_setup 29 | 30 | runtest "ssh: basic test" 'checkit "$RSYNC -avH -e \"$SSH\" --rsync-path=\"$RSYNC\" \"$fromdir/\" \"localhost:$todir\"" "$fromdir/" "$todir"' 31 | 32 | mv "$todir/text" "$todir/ThisShouldGo" 33 | 34 | runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e \"$SSH\" --rsync-path=\"$RSYNC\" \"$fromdir/\" \"localhost:$todir\"" "$fromdir/" "$todir"' 35 | -------------------------------------------------------------------------------- /testsuite/symlink-ignore.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2001 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test rsync's somewhat over-featured symlink control: the default 9 | # behaviour is that symlinks should not be copied at all. 10 | 11 | . "$suitedir/rsync.fns" 12 | 13 | build_symlinks || test_fail "failed to build symlinks" 14 | 15 | # Copy recursively, but without -l or -L or -a, and all the symlinks 16 | # should be missing. 17 | $RSYNC -r "$fromdir/" "$todir" || test_fail "$RSYNC returned $?" 18 | 19 | [ -f "$todir/referent" ] || test_fail "referent was not copied" 20 | [ -d "$todir/from" ] && test_fail "extra level of directories" 21 | if is_a_link "$todir/dangling"; then 22 | test_fail "dangling symlink was copied" 23 | fi 24 | 25 | if is_a_link "$todir/relative"; then 26 | test_fail "relative symlink was copied" 27 | fi 28 | 29 | if is_a_link "$todir/absolute"; then 30 | test_fail "absolute symlink was copied" 31 | fi 32 | 33 | # The script would have aborted on error, so getting here means we've won. 34 | exit 0 35 | -------------------------------------------------------------------------------- /testsuite/trimslash.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2002 by Martin Pool 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test tiny function to trim trailing slashes. 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | "$TOOLDIR/trimslash" "/usr/local/bin" "/usr/local/bin/" "/usr/local/bin///" \ 13 | "//a//" "////" \ 14 | "/Users/Weird Macintosh Name/// Ooh, translucent plastic/" \ 15 | > "$scratchdir/slash.out" 16 | diff $diffopt "$scratchdir/slash.out" - < 4 | 5 | . "$suitedir/rsync.fns" 6 | 7 | test_symlink() { 8 | is_a_link "$1" || test_fail "File $1 is not a symlink" 9 | } 10 | 11 | test_regular() { 12 | if [ ! -f "$1" ]; then 13 | test_fail "File $1 is not regular file or not exists" 14 | fi 15 | } 16 | 17 | cd "$tmpdir" 18 | 19 | mkdir from 20 | 21 | mkdir "from/safe" 22 | mkdir "from/unsafe" 23 | 24 | mkdir "from/safe/files" 25 | mkdir "from/safe/links" 26 | 27 | touch "from/safe/files/file1" 28 | touch "from/safe/files/file2" 29 | touch "from/unsafe/unsafefile" 30 | 31 | ln -s ../files/file1 "from/safe/links/" 32 | ln -s ../files/file2 "from/safe/links/" 33 | ln -s ../../unsafe/unsafefile "from/safe/links/" 34 | 35 | echo "rsync with relative path and just -a" 36 | $RSYNC -avv from/safe/ to 37 | test_symlink to/links/file1 38 | test_symlink to/links/file2 39 | test_symlink to/links/unsafefile 40 | 41 | echo "rsync with relative path and -a --copy-links" 42 | $RSYNC -avv --copy-links from/safe/ to 43 | test_regular to/links/file1 44 | test_regular to/links/file2 45 | test_regular to/links/unsafefile 46 | 47 | echo "rsync with relative path and --copy-unsafe-links" 48 | $RSYNC -avv --copy-unsafe-links from/safe/ to 49 | test_symlink to/links/file1 50 | test_symlink to/links/file2 51 | test_regular to/links/unsafefile 52 | 53 | rm -rf to 54 | echo "rsync with relative2 path" 55 | (cd from; $RSYNC -avv --copy-unsafe-links safe/ ../to) 56 | test_symlink to/links/file1 57 | test_symlink to/links/file2 58 | test_regular to/links/unsafefile 59 | 60 | rm -rf to 61 | echo "rsync with absolute path" 62 | $RSYNC -avv --copy-unsafe-links `pwd`/from/safe/ to 63 | test_symlink to/links/file1 64 | test_symlink to/links/file2 65 | test_regular to/links/unsafefile 66 | -------------------------------------------------------------------------------- /testsuite/wildmatch.test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2003-2022 Wayne Davison 4 | 5 | # This program is distributable under the terms of the GNU GPL (see 6 | # COPYING). 7 | 8 | # Test the wildmatch functionality 9 | 10 | . "$suitedir/rsync.fns" 11 | 12 | # This test exercises the wildmatch() function (with no options) and the 13 | # wildmatch_join() function (using -x and/or -e). 14 | for opts in "" -x1 "-x1 -e1" "-x1 -e1se" -x2 "-x2 -ese" -x3 "-x3 -e1" -x4 "-x4 -e2e" -x5 "-x5 -es"; do 15 | echo Running wildtest with "$opts" 16 | "$TOOLDIR/wildtest" $opts "$srcdir/wildtest.txt" >"$scratchdir/wild.out" 17 | diff $diffopt "$scratchdir/wild.out" - < 7 | * Copyright (C) 2003-2024 Wayne Davison 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along 20 | * with this program; if not, visit the http://fsf.org website. 21 | */ 22 | 23 | #include "rsync.h" 24 | #include "itypes.h" 25 | #include "inums.h" 26 | 27 | extern size_t max_alloc; 28 | 29 | char *do_calloc = "42"; 30 | 31 | /** 32 | * Sleep for a specified number of milliseconds. 33 | * 34 | * Always returns True. 35 | **/ 36 | int msleep(int t) 37 | { 38 | #ifdef HAVE_NANOSLEEP 39 | struct timespec ts; 40 | 41 | ts.tv_sec = t / 1000; 42 | ts.tv_nsec = (t % 1000) * 1000000L; 43 | 44 | while (nanosleep(&ts, &ts) < 0 && errno == EINTR) {} 45 | 46 | #elif defined HAVE_USLEEP 47 | usleep(t*1000); 48 | 49 | #else 50 | int tdiff = 0; 51 | struct timeval tval, t1, t2; 52 | 53 | gettimeofday(&t1, NULL); 54 | 55 | while (tdiff < t) { 56 | tval.tv_sec = (t-tdiff)/1000; 57 | tval.tv_usec = 1000*((t-tdiff)%1000); 58 | 59 | errno = 0; 60 | select(0,NULL,NULL, NULL, &tval); 61 | 62 | gettimeofday(&t2, NULL); 63 | tdiff = (t2.tv_sec - t1.tv_sec)*1000 + 64 | (t2.tv_usec - t1.tv_usec)/1000; 65 | if (tdiff < 0) 66 | t1 = t2; /* Time went backwards, so start over. */ 67 | } 68 | #endif 69 | 70 | return True; 71 | } 72 | 73 | void *my_alloc(void *ptr, size_t num, size_t size, const char *file, int line) 74 | { 75 | if (num >= max_alloc/size) { 76 | if (!file) 77 | return NULL; 78 | rprintf(FERROR, "[%s] exceeded --max-alloc=%s setting (file=%s, line=%d)\n", 79 | who_am_i(), do_big_num(max_alloc, 0, NULL), src_file(file), line); 80 | exit_cleanup(RERR_MALLOC); 81 | } 82 | if (!ptr) 83 | ptr = malloc(num * size); 84 | else if (ptr == do_calloc) 85 | ptr = calloc(num, size); 86 | else 87 | ptr = realloc(ptr, num * size); 88 | if (!ptr && file) 89 | _out_of_memory("my_alloc caller", file, line); 90 | return ptr; 91 | } 92 | 93 | const char *sum_as_hex(int csum_type, const char *sum, int flist_csum) 94 | { 95 | static char buf[MAX_DIGEST_LEN*2+1]; 96 | int i, x1, x2; 97 | int canonical = canonical_checksum(csum_type); 98 | int sum_len = csum_len_for_type(csum_type, flist_csum); 99 | char *c; 100 | 101 | if (!canonical) 102 | return NULL; 103 | 104 | assert(sum_len*2 < (int)sizeof buf); 105 | 106 | for (i = sum_len, c = buf; --i >= 0; ) { 107 | int ndx = canonical < 0 ? sum_len - i - 1 : i; 108 | x2 = CVAL(sum, ndx); 109 | x1 = x2 >> 4; 110 | x2 &= 0xF; 111 | *c++ = x1 <= 9 ? x1 + '0' : x1 + 'a' - 10; 112 | *c++ = x2 <= 9 ? x2 + '0' : x2 + 'a' - 10; 113 | } 114 | 115 | *c = '\0'; 116 | 117 | return buf; 118 | } 119 | 120 | NORETURN void _out_of_memory(const char *msg, const char *file, int line) 121 | { 122 | rprintf(FERROR, "[%s] out of memory: %s (file=%s, line=%d)\n", who_am_i(), msg, src_file(file), line); 123 | exit_cleanup(RERR_MALLOC); 124 | } 125 | 126 | NORETURN void _overflow_exit(const char *msg, const char *file, int line) 127 | { 128 | rprintf(FERROR, "[%s] buffer overflow: %s (file=%s, line=%d)\n", who_am_i(), msg, src_file(file), line); 129 | exit_cleanup(RERR_MALLOC); 130 | } 131 | 132 | const char *src_file(const char *file) 133 | { 134 | static const char *util2 = __FILE__; 135 | static int prefix = -1; 136 | 137 | if (prefix < 0) { 138 | const char *cp = strrchr(util2, '/'); 139 | prefix = cp ? cp - util2 + 1 : 0; 140 | } 141 | 142 | if (prefix && strncmp(file, util2, prefix) == 0) 143 | return file + prefix; 144 | return file; 145 | } 146 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | #define RSYNC_VERSION "3.4.2dev" 2 | #define MAINTAINER_TZ_OFFSET -7.0 3 | -------------------------------------------------------------------------------- /wildtest.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RsyncProject/rsync/9994933c8ccf7ead27c81fe4ce2eb4e08af20c7f/wildtest.txt -------------------------------------------------------------------------------- /zlib/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RsyncProject/rsync/9994933c8ccf7ead27c81fe4ce2eb4e08af20c7f/zlib/ChangeLog -------------------------------------------------------------------------------- /zlib/README.rsync: -------------------------------------------------------------------------------- 1 | READ THIS BEFORE TRYING TO DYNAMICALLY LINK RSYNC AND ZLIB! 2 | 3 | zlib has been adapted slightly for use in rsync. Please don't bother 4 | the zlib authors with problems related to the use of zlib in rsync as 5 | any bugs are likely to be our fault and not theirs. 6 | 7 | Specific changes that have been made to zlib for rsync include: 8 | 9 | - add Z_INSERT_ONLY to allow for efficient history updating without 10 | actually emitting any data. This is used to compress the matched 11 | blocks that don't cross the wire, which gives better compression 12 | ratios on the literal data. 13 | 14 | - fixed a number of minor compilation issues. (redefinition of MAX and 15 | other such trivial things) 16 | 17 | - include rsync.h to ensure that we get a consistent set of includes 18 | for all C code in rsync and to take advantage of autoconf 19 | 20 | As a result of the first item, the streams from rsync's version of 21 | zlib are *not compatible* with those produced by the upstream version 22 | of rsync. In other words, if you link rsync against your system's 23 | copy, it will not be able to interoperate with any other version if 24 | the -z option is used. (Sorry. Sometimes standard is better than 25 | better.) 26 | 27 | The rsync maintainers hope to fix this problem in the future by either 28 | merging our changes into the upstream version, or backing them out of 29 | rsync in a way that preserves wire compatibility. But in the meantime 30 | this version must be maintained in parallel. 31 | 32 | -------------------------------------------------------------------------------- /zlib/compress.c: -------------------------------------------------------------------------------- 1 | /* compress.c -- compress a memory buffer 2 | * Copyright (C) 1995-2005 Jean-loup Gailly. 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* @(#) $Id$ */ 7 | 8 | #define ZLIB_INTERNAL 9 | #include "zlib.h" 10 | 11 | /* =========================================================================== 12 | Compresses the source buffer into the destination buffer. The level 13 | parameter has the same meaning as in deflateInit. sourceLen is the byte 14 | length of the source buffer. Upon entry, destLen is the total size of the 15 | destination buffer, which must be at least 0.1% larger than sourceLen plus 16 | 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. 17 | 18 | compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough 19 | memory, Z_BUF_ERROR if there was not enough room in the output buffer, 20 | Z_STREAM_ERROR if the level parameter is invalid. 21 | */ 22 | int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) 23 | Bytef *dest; 24 | uLongf *destLen; 25 | const Bytef *source; 26 | uLong sourceLen; 27 | int level; 28 | { 29 | z_stream stream; 30 | int err; 31 | 32 | stream.next_in = (z_const Bytef *)source; 33 | stream.avail_in = (uInt)sourceLen; 34 | #ifdef MAXSEG_64K 35 | /* Check for source > 64K on 16-bit machine: */ 36 | if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; 37 | #endif 38 | stream.next_out = dest; 39 | stream.avail_out = (uInt)*destLen; 40 | if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; 41 | 42 | stream.zalloc = (alloc_func)0; 43 | stream.zfree = (free_func)0; 44 | stream.opaque = (voidpf)0; 45 | 46 | err = deflateInit(&stream, level); 47 | if (err != Z_OK) return err; 48 | 49 | err = deflate(&stream, Z_FINISH); 50 | if (err != Z_STREAM_END) { 51 | deflateEnd(&stream); 52 | return err == Z_OK ? Z_BUF_ERROR : err; 53 | } 54 | *destLen = stream.total_out; 55 | 56 | err = deflateEnd(&stream); 57 | return err; 58 | } 59 | 60 | /* =========================================================================== 61 | */ 62 | int ZEXPORT compress (dest, destLen, source, sourceLen) 63 | Bytef *dest; 64 | uLongf *destLen; 65 | const Bytef *source; 66 | uLong sourceLen; 67 | { 68 | return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); 69 | } 70 | 71 | /* =========================================================================== 72 | If the default memLevel or windowBits for deflateInit() is changed, then 73 | this function needs to be updated. 74 | */ 75 | uLong ZEXPORT compressBound (sourceLen) 76 | uLong sourceLen; 77 | { 78 | return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 79 | (sourceLen >> 25) + 13; 80 | } 81 | -------------------------------------------------------------------------------- /zlib/dummy.in: -------------------------------------------------------------------------------- 1 | This is a dummy file to ensure that the lib directory gets created 2 | by configure when a VPATH is used. 3 | -------------------------------------------------------------------------------- /zlib/inffast.h: -------------------------------------------------------------------------------- 1 | /* inffast.h -- header to use inffast.c 2 | * Copyright (C) 1995-2003, 2010 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); 12 | -------------------------------------------------------------------------------- /zlib/inftrees.h: -------------------------------------------------------------------------------- 1 | /* inftrees.h -- header to use inftrees.c 2 | * Copyright (C) 1995-2005, 2010 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* Structure for decoding tables. Each entry provides either the 12 | information needed to do the operation requested by the code that 13 | indexed that table entry, or it provides a pointer to another 14 | table that indexes more bits of the code. op indicates whether 15 | the entry is a pointer to another table, a literal, a length or 16 | distance, an end-of-block, or an invalid code. For a table 17 | pointer, the low four bits of op is the number of index bits of 18 | that table. For a length or distance, the low four bits of op 19 | is the number of extra bits to get after the code. bits is 20 | the number of bits in this code or part of the code to drop off 21 | of the bit buffer. val is the actual byte to output in the case 22 | of a literal, the base length or distance, or the offset from 23 | the current table to the next table. Each entry is four bytes. */ 24 | typedef struct { 25 | unsigned char op; /* operation, extra bits, table bits */ 26 | unsigned char bits; /* bits in this part of the code */ 27 | unsigned short val; /* offset in table or code value */ 28 | } code; 29 | 30 | /* op values as set by inflate_table(): 31 | 00000000 - literal 32 | 0000tttt - table link, tttt != 0 is the number of table index bits 33 | 0001eeee - length or distance, eeee is the number of extra bits 34 | 01100000 - end of block 35 | 01000000 - invalid code 36 | */ 37 | 38 | /* Maximum size of the dynamic table. The maximum number of code structures is 39 | 1444, which is the sum of 852 for literal/length codes and 592 for distance 40 | codes. These values were found by exhaustive searches using the program 41 | examples/enough.c found in the zlib distribtution. The arguments to that 42 | program are the number of symbols, the initial root table size, and the 43 | maximum bit length of a code. "enough 286 9 15" for literal/length codes 44 | returns returns 852, and "enough 30 6 15" for distance codes returns 592. 45 | The initial root table size (9 or 6) is found in the fifth argument of the 46 | inflate_table() calls in inflate.c and infback.c. If the root table size is 47 | changed, then these maximum sizes would be need to be recalculated and 48 | updated. */ 49 | #define ENOUGH_LENS 852 50 | #define ENOUGH_DISTS 592 51 | #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) 52 | 53 | /* Type of code to build for inflate_table() */ 54 | typedef enum { 55 | CODES, 56 | LENS, 57 | DISTS 58 | } codetype; 59 | 60 | int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, 61 | unsigned codes, code FAR * FAR *table, 62 | unsigned FAR *bits, unsigned short FAR *work)); 63 | --------------------------------------------------------------------------------