Commit Graph
331 Commits
Author SHA1 Message Date
Andrew Tridgell b70a61f394 log: avoid recursive deletion-message overflow (#1130)
* log: avoid recursive deletion-message overflow

A quiet daemon receiver queued one MSG_DELETED per path until the generator hit --max-alloc, so skip names the client did not request. If requested output legitimately fills the queue, keep allocator error reporting from re-entering the same buffer and exhausting the stack. Preserve explicit deletion requests across the daemon max-verbosity clamp.

* NEWS: note daemon deletion-message overflow fix
2026-10-15 10:59:02 +10:00
Zen Dodd 6eb05b3451 daemon: recognise named Unix stdin sockets (#1121)
* daemon: recognise named Unix stdin sockets
* daemon: distinguish named Unix sockets portably
2026-10-08 16:05:12 +10:00
Zen Dodd 7ee931c7b9 daemon: distinguish inetd from local stdin sockets (#1075)
* daemon: require IP stream for inetd mode
* daemon: preserve bidirectional stdio mode
* daemon: honour explicit no-detach mode
* daemon: preserve inetd socket detection
* ci: fix daemon socket checks
2026-09-11 09:10:18 +10:00
Andrew Tridgell 4d7c243ca6 daemon: bound the pre-transfer handshake with a timeout
rsyncd.conf(5) says of "timeout": "Using this parameter you can ensure that
rsync won't wait on a dead client forever."  That did not hold before a module
was known.  set_io_timeout() ran at the very end of rsync_module(), so the
greeting, authentication and the whole argument list were read with no I/O
timeout at all -- a peer could stall at any of them and the child waited
indefinitely.  Measured: 20 connections sending "@RSYNCD: 31.0" with no newline
were all still alive well past timeout=5, and only went away when the client
hung up.

The consequence is worse than an idle process.  claim_connection() runs BEFORE
auth_server(), so naming a module is enough to take a slot: an attacker with no
credentials could occupy every "max connections" slot of an authenticated
module and hold them for as long as it kept the sockets open, with the
documented control unable to recover them.  It costs the attacker nothing --
five stalled children measured 0 CPU ticks over 5s -- so this is descriptor and
slot exhaustion, not load.

Bound the handshake at min(configured, 60s).  "timeout" is a Locals parameter,
so lp_timeout(-1) reads the global section -- the same -1 idiom start_daemon()
already uses for lp_reverse_lookup().

Both halves of that minimum matter.  "timeout" DEFAULTS TO 0, so honouring only
the configured value would leave the daemon most exposed to this -- one whose
administrator never set a timeout -- exactly as pinnable as before.  And capping
matters because an operator who sets "timeout = 86400" for slow links is asking
for patience during a TRANSFER, not for a stranger to hold a pre-auth slot for a
day.  The pre-module phase has no legitimate reason to take even a minute.

The bound is retired the moment the module is known, which is what lets the
configured value still govern the transfer.  That retirement is load-bearing:
the per-module test only ever LOWERS the timeout (`lp_timeout(module_id) <
io_timeout`), so leaving the handshake bound in place would silently clamp a
module that asked for more -- "timeout = 300" would get 60.  It is cleared
before that test runs, and only when io_timeout is still the value we armed,
since the client's own --timeout is parsed in between and must win on its own
terms.  Verified: with no global timeout and "timeout = 120" in the module, a
connection idles past 75s rather than being dropped at 60.

Applied only for a real socket daemon (am_daemon > 0): an rsh-run daemon has no
listener to exhaust.

Verified end to end with max connections = 2 and timeout = 5: with two stalled
unauthenticated connections holding both slots, a legitimate client is refused
during the timeout window and served once it elapses.  Before this change it was
refused both times.

Reported by Chamal De Silva.  Not a regression -- 3.2.7 behaves the same way.

An idle timeout alone is not enough, which the review of the first version of
this change made concrete: safe_read() consults it only when poll() TIMES OUT,
so a peer sending a byte more often than allowed_lull (timeout/2) is never
checked at all.  Measured: one byte every 20s held the handshake open for 182s
against a 60s bound, keeping its max-connections slot the whole time -- the
reported attack, merely with the attacker typing.

Non-positive configured values are treated as "use the built-in bound":
"timeout" is parsed with atoi(), so "timeout = -1" would otherwise reach
set_io_timeout() (which reads it as no timeout) and alarm() (which would take it
as a huge unsigned count), disabling the very bound it looks like it configures.

The client's own --timeout is no longer inferred by comparing values, which could
not distinguish it from an identical armed value: io_timeout is zeroed before
parse_arguments(), so anything non-zero afterwards came from the client.

So the bound is absolute and lives in the READ PATH, next to the idle timeout
it complements: safe_read() caps each poll() at whatever is left of it and
gives up when it expires, so it is re-checked on every iteration and a peer
that keeps typing cannot outrun it.

It is deliberately NOT alarm()/SIGALRM.  Three earlier attempts used one and
each regressed something: fork() clears pending alarms, so the "post-xfer exec"
parent -- which waits for the ENTIRE transfer -- kept the deadline and _exit()ed
mid-transfer, skipping the hook and releasing the max-connections fcntl lock
while the transfer child ran on; "pre-xfer exec" and the name converter are
operator scripts that may legitimately outlast any handshake bound; and the
cancellation sat inside an exec-environment compile guard, so a build without
setenv/putenv kept it armed through the transfer.  A deadline consulted only
where the daemon is already blocked reading a peer has none of those hazards.

It is also kept entirely separate from io_timeout, which is an idle timeout the
module or client may set.  Mixing them clamped a module asking for more than the
bound ("timeout = 300" became 60) and leaked the handshake value into the
transfer.  Verified: module 300 stays 300, and a client --timeout=7 still wins.

Armed for each peer-driven phase and cleared between them: at the start of the
handshake, tightened by the module's own timeout once the module is known and
its slot claimed, cleared across the hook/fork setup, re-armed before
"@RSYNCD: OK" so it spans BOTH read_args() calls including secluded args, and
cleared before the transfer.

That argument-read coverage is the part that matters most.  auth_server()
returns immediately when a module sets no "auth users", so on an ANONYMOUS
module nothing is authenticated: without a bound there, a peer could claim the
slot, take the OK, and trickle an unterminated argument line forever.  Measured:
still open after 150s before, closed at 60s after.
2026-08-02 13:26:41 +10:00
Andrew Tridgell 5eb99bb6b2 exclude: exempt the daemon's own filter parameters from the confinement
Confining every parse_filter_file() open to the module root also caught
"filter", "include from" and "exclude from" from rsyncd.conf.  Those name
operator-configured paths and pointing them outside the module -- at
/etc/rsync/excludes, say -- is the ordinary way to write them; rsyncd.conf(5)
puts no constraint on where the file lives.  The result was not a refused
rule but a refused connection:

    failed to open exclude file /etc/rsync/excludes:
        Too many levels of symbolic links (40)
    rsync error: error in file IO (code 11) at exclude.c(1582)

with no symlink involved anywhere -- just a regular file outside the module.

Mark the window in which the daemon loads its own parameters and skip the
confinement there.  Everything else, in particular the peer-driven dir-merge
the leak test exercises, is still confined.  Also fix the trailing whitespace
in the original hunk.
2026-07-29 11:31:57 +10:00
Andrew Tridgell 7b6fbf5940 daemon: make "insecure links = yes" fully restore 3.2.7 symlink following
The opt-out is meant to restore stock-3.2.7 "follow existing symlinks in the
module" behaviour, but several daemon symlink-resolution sites called the
confined resolver unconditionally and never consulted symlink_optout_allowed(),
so a module with "insecure links = yes" still refused to follow a symlinked
directory (change_dir ELOOP) or an alt-dest basis.  Gate every such site on the
opt-out -- follow plainly like 3.2.7 when set, confine otherwise:

  - change_dir() relative daemon branch (util1.c): plain chdir() under the
    opt-out instead of secure_relative_open(), so a peer can read a path through
    a symlinked directory again.
  - basis_link_stat() (generator.c): the chrooted-relative and non-chroot
    branches honour the opt-out.  The non-chroot ABSOLUTE branch (a basis rooted
    under the module by check_alt_basis_dirs, which can reach an in-module
    symlink) is, when NOT opted out, resolved through owner_walk_parent so a
    target landing outside the module root is refused -- closing a confirmed
    --compare-dest=/symlink out-of-module read oracle.  The leaf is taken
    O_NOFOLLOW under the confined parent so --copy-links can't follow a leaf
    symlink out; --fake-super folds its %stat via the held fd.  A relative
    sibling basis (--link-dest=../01) keeps the plain path (#915/#930).
  - secure_basis_open() (receiver.c): plain do_open() under the opt-out.
  - use_secure_symlinks (clientserver.c): cleared under the opt-out, so the
    receiver's protected-regular EACCES write fallback is legacy too.
  - secure_sender_parent_fd() (sender.c): declines (errno=0) under the opt-out
    so --remove-source-files re-stats the plain path.

Default modules (insecure links = no) are unchanged and stay fully confined;
the opt-out is per-module and a client cannot enable it.
2026-07-20 14:05:32 +10:00
Andrew Tridgell 5eb05f7409 flist/xattrs/generator/uidlist/clientserver: plug audit-reported leaks
Five error-path/cleanup memory leaks found by an external audit:

- flist.c send_file_name: free the ACL loaded by get_acl() when a later
  get_xattr() fails (and on the get_acl error path).
- xattrs.c copy_xattrs: free the xattr datum buffer when the setxattr fails.
- generator.c recv_generator: free real_sx at the cleanup label (the
  directory branch loaded its ACL via set_file_attrs but only the
  regular-file path freed it); zero-init real_sx so the early gotos are safe.
- uidlist.c send_one_list: free the strdup'd id-0 name after send_one_name.
- clientserver.c start_inband_exchange: free modname on the early error
  returns (it was freed only on the success path).

ASan/LSan regression tests cover the generator, uidlist and clientserver
leaks; the flist and xattrs leaks need a forced syscall failure and are
covered by the audit's standalone harnesses.

Reported-by: Leonid Bugaev <leonsbox@gmail.com>
(cherry picked from commit 078f3b99f4004510d418ee9d97d9b775dc8587bc)
2026-07-20 14:05:31 +10:00
Andrew TridgellandGreg Kroah-Hartman 3d3150c24a testsuite: code-scanner daemon/metadata coverage tests + gcov flush before chroot
Adds six coverage tests from the code-scanner run, each closing a measured
gap in a daemon or metadata code path the suite never reached:

  - daemon-include-maxconn: rsyncd.conf &include/&merge directives +
    `max connections`/`lock file` (params.c include_config, connection.c
    claim_connection, util1.c lock_range).
  - fake-super-acl-xattr: --fake-super -A stores ACLs as user.rsync.%aacl/
    %dacl xattrs (acls.c am_root<0 IVAL/SIVAL pack, xattrs.c get/set/
    del_def_xattr_acl); Linux-only (the user.rsync.* namespace).
  - backup-crossdev-copy: make_backup() EXDEV copy-fallback for non-regular
    files (do_symlink_at/do_mknod_at/copy_file); skips without a cross-dev
    tmpfs.
  - daemon-http-proxy: RSYNC_PROXY HTTP CONNECT (socket.c
    establish_proxy_connection + base64 Proxy-Authorization + 503 branch).
  - daemon-module-options: motd file, socket options, incoming/outgoing
    chmod, dont compress, list=no, comment, --sockopts.
  - daemon-chroot: `use chroot = yes` incl. the /outer/./inner split and
    `temp dir`; probes CAP_SYS_CHROOT and skips cleanly without it.

clientserver.c flushes gcov counters just before chroot() in rsync_module()
so the per-connection child's pre-chroot lines reach disk (the build-tree
.gcda paths are unreachable post-chroot); no-op without --enable-coverage.

CI: the require_tcp-gated tests (daemon-chroot/-http-proxy/-module-options)
plus the Linux-only fake-super-acl-xattr and the cross-dev backup-crossdev-copy
are listed in the per-platform RSYNC_EXPECT_SKIPPED sets where they skip on the
pipe-transport make-check jobs.

Co-authored-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-07-20 14:05:31 +10:00
Andrew TridgellandGreg Kroah-Hartman 0abb4ae6cb testsuite: code-scanner coverage and regression tests + gcov infra
Adds the coverage/regression tests from the code-scanner run and the
gcov plumbing they rely on:

  - scanner-argv-bounds, scanner-batch-flag-mismatch,
    scanner-delete-delay-overread, scanner-daemon-log-checksum:
    regression tests for the argv/-v/--info/--skip-compress bounds, the
    batch metadata-ndx corruption, the read_delay_line off-by-one, and
    the daemon -c/%C checksum-slot leak.
  - daemon-proxy-protocol, daemon-early-exec-nameconv, daemon-auth-group,
    daemon-standalone-detach, misc-coverage, nonroot-restrictive-perms,
    backup-acl-xattr-cache: daemon and path coverage tests.
  - rsyncfns.py: CAP_MKNOD probe in devices_supported().
  - gcov_flush() macro (rsync.h) + calls in the daemon fork/_exit paths
    (clientserver.c, socket.c); no-op without --enable-coverage. Makefile.in
    COVERAGE_EXCLUDE / gcovr / setuid .gcda refinements.
  - CI: list the new TCP/root/ACL tests in the per-platform
    RSYNC_EXPECT_SKIPPED sets.

Co-authored-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-07-20 14:05:31 +10:00
Andrew Tridgell defd7110ac confine operator- and peer-supplied paths to the served module
Route every operator-supplied directory path (--temp-dir / --partial-dir /
--backup-dir / alt-dest basis) and the transfer engine's own dest/source opens
through the secure resolver + ownership walk, so a symlink owned by another uid
can no longer redirect a read, a backup, a staging open, a rename, an unlink or a
new-destination create outside the module.  Covers backup.c, generator.c (alt/
link/in-place basis), receiver.c (basis open), sender.c (remove-source / source
open / copy-links leaf), rsync.c (held-fd attr stat), clientserver.c (pid-file
parent pin), and main.c (relative-basis make-absolute, mkpath dest-arg guard).
--insecure-links / "insecure links = yes" is the local opt-out (a daemon never
honors a peer-forwarded one).
2026-07-20 14:05:30 +10:00
Andrew Tridgell 4e67f87479 scan-build: fix resource leaks on error paths
clientserver.c: close the --early-input-file FILE* on the
fstat/oversize/early-EOF error returns; it was only closed on the
success path.
getgroups.c: free the gid list before returning.
2026-06-16 08:55:39 +10:00
Andrew Tridgell 6777170037 daemon: un-backslash escaped option args (#829)
Without --secluded-args, the client's safe_arg() backslash-escapes shell
and wildcard chars in option values before sending them to the server, so
--chown's --usermap=*:user is transmitted as --usermap=\*:user.  Over ssh a
remote shell removes the backslashes before rsync parses the args, but a
daemon has no shell and read_args() stored option args verbatim -- so the
receiver saw the literal "\*", the usermap/groupmap wildcard never matched,
and the module's configured uid/gid won instead.  A regression from the
secluded-args hardening; rsync 3.2.3 (protocol 31) worked.

Un-backslash option args in read_args() on the daemon's first
(non-protected) read, mirroring what the ssh-side shell does.  File args
after the dot are already handled by glob_expand(); the protected (NUL,
already-unescaped) re-read and the server's stdin read pass unescape=0 so
their raw args are left untouched.

Fixes: #829
2026-06-05 06:35:12 +10:00
Andrew TridgellandClaude Opus 4.7 c38f20c5ff clientserver: fix hostname ACL bypass when using daemon chroot
On an rsync daemon configured with "daemon chroot", the reverse-DNS
lookup of the connecting client was performed *after* the chroot
had been entered. If the chroot did not contain the files glibc
needs for resolution (/etc/resolv.conf, /etc/nsswitch.conf,
/etc/hosts, NSS service modules), the lookup failed and
client_name() returned "UNKNOWN". Hostname-based deny rules
("hosts deny = *.evil.example") therefore could not match, and
an attacker controlling their PTR record could connect from a
hostname the administrator had intended to deny. IP-based ACLs
were unaffected.

Do the reverse DNS lookup before chroot/setuid; client_name()
caches its result, so the post-chroot call uses the cached value
and hostname-based ACLs work even when DNS is unavailable
post-chroot.

Adds testsuite/daemon-chroot-acl.test as end-to-end regression
coverage. The test sets up an empty chroot directory, configures
"hosts deny = <localhost-resolved-name>" with daemon chroot, and
asserts the connection is refused with @ERROR access denied.
Uses unshare --user --map-root-user for non-root CAP_SYS_CHROOT;
skips cleanly on non-Linux or when user namespaces aren't
available.

Reporter: Joshua Rogers (MegaManSec).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:01:22 +10:00
Andrew TridgellandClaude Opus 4.7 f1c24ab03b syscall+clientserver: am_chrooted and use_secure_symlinks for daemon-no-chroot (CVE-2026-29518)
CVE-2026-29518: an rsync daemon configured with "use chroot = no"
is exposed to a TOCTOU race on parent path components. A local
attacker with write access to a module can replace a parent
directory component with a symlink between the receiver's check
and its open(), redirecting reads (basis-file disclosure) and
writes (file overwrite) outside the module. Under elevated daemon
privilege this allows privilege escalation. Default
"use chroot = yes" is not exposed.

Add secure_relative_open() in syscall.c. It walks the parent
components under RESOLVE_BENEATH (Linux 5.6+) /
O_RESOLVE_BENEATH (FreeBSD 13+, macOS 15+) / per-component
O_NOFOLLOW elsewhere, anchored at a trusted dirfd, so a parent-
symlink swap is rejected by the kernel. Route the receiver's
basis-file open in receiver.c through it when use_secure_symlinks
is set in clientserver.c rsync_module().

Reporters: Nullx3D (Batuhan SANCAK); Damien Neil; Michael Stapelberg.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:01:22 +10:00
Andrew TridgellandClaude Opus 4.6 567c40935f call tzset() before chroot to cache timezone data
localtime/localtime_r need /etc/localtime for timezone info.
After chroot this file is inaccessible, causing log timestamps
to fall back to UTC. Calling tzset() before chroot ensures the
timezone data is cached by glibc for subsequent calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-22 13:02:10 +10:00
Wayne Davison 4d44bf122d A few more doc tweaks & comment tweaks. 2022-09-30 12:34:58 -07:00
Wayne Davison 97e02bf21a Some "use chroot" improvements.
- The sanitize_paths variable was set too often. It only needs to be set
  when the "inner" path is not "/".  This change avoids sanitizing &
  munging things for a path=/ module just because chroot is off.
- The default for "use chroot" is now "unset" instead of "true".  When
  unset it checks if chrooting works, and if not, it proceeds with a
  sanitized copy instead of totally failing to work.  This makes it
  easier to setup a non-root rsync daemon, for instance.  It will have
  no effect on a typical Linux root-run daemon where the default will
  continue to use chroot (because chrooting works).  A config file can
  explicitly set "use chroot = true | false" to force the choice.
- Try to improve the "use chroot" manpage.
2022-09-20 00:08:16 -07:00
Wayne Davison a6a0d2f77c Require a newer protocol to specify the digest list. 2022-09-10 22:12:24 -07:00
Wayne Davison 7e2711bb2b Improve various things in the checksum code
- Size flist checksum data to hold the active size, not the max.
- Add a negotiated hash method to the daemon auth code.
- Use EVP for all openssl digests. This makes it easy to add more
  openssl digest methods and avoids deprecation warnings.
- Support a way to re-enable deprecated digests via openssl conf
  file and allow a default file to be configured.
- Supply a simple openssl-rsync.cnf file to enable legacy digests.
2022-09-10 11:39:37 -07:00
Wayne Davison 0a09df2c5e Rename --protect-args to --secluded-args. 2022-08-23 14:56:23 -07:00
Wayne Davison 1174d97072 Fix --old-args interaction with a daemon
Ensure that a remote rsync daemon will not split a filename arg unless
the user asked for `--old-args`.
2022-01-17 18:11:03 -08:00
Wayne Davison c3b553a93f Preparing for release of 3.2.4pre2 2022-01-15 17:21:01 -08:00
Wayne Davison 3e44bbd313 Preparing for release of 3.2.4pre1 2022-01-02 15:13:19 -08:00
Wayne Davison a6bdf313f2 Unset DISPLAY in environment.
Without a DISPLAY var, ssh won't try to forward X11 when making an
ssh connection.  This patch also makes use of setenv() and unsetenv()
if they are available.
2021-05-01 09:14:51 -07:00
Wayne Davison 47351c2b16 Use RSYNC_GITVER in more output 2020-08-03 10:46:31 -07:00
Wayne Davison f9bb8f76ee Change daemon variable & simplify some option code
- Rename daemon_over_rsh -> daemon_connection since it is also used to
  indicate if a non-rsh daemon connection is active.
- Move the daemon-over-rsh exception out of server_options() to the one
  caller that needs that behavior.
- Don't allow noop_io_until_death() to be short-circuited when talking
  to a daemon over a socket, because it can't send errors via stderr.
2020-07-25 09:36:42 -07:00
Wayne Davison 7e07a32504 Add the name converter daemon parameter.
This is based on the long-standing patch but with the protocol changed
to just use newlines as delimiters instead of null chars (since names
should not contain a newline AND it makes it easier to write a helper
script).  Lots of other small improvements and a better default value
for "numeric ids" when using "use chroot" with "name converter".
2020-07-17 10:30:59 -07:00
Wayne Davison 59cb358fda More TANDEM changes
- Handle a non-0 root uid.
- Handle alternate major/minor/MAKEDEV funcs.
- Other misc compatibility tweaks.
2020-07-06 00:05:46 -07:00
Wayne Davison f4184849c4 Use module_id more consistently after it is set. 2020-07-04 10:28:39 -07:00
Wayne Davison 565cde84a7 Don't turn off the user's open-noatime unless the module is forcing the value. 2020-07-04 10:28:38 -07:00
Paul Slootman f0e670b4c6 Add "open noatime" module option to rsyncd.conf 2020-07-04 09:30:35 -07:00
Wayne Davison 11eb67eec9 Some memory allocation improvements
- All the memory-allocation macros now auto-check for failure and exit
   with a failure message that incudes the caller's file and lineno
   info.  This includes strdup().

 - Added the `--max-alloc=SIZE` option to be able to override the memory
   allocator's sanity-check limit.  It defaults to 1G (as before).
   Fixes bugzilla bug 12769.
2020-06-25 20:54:21 -07:00
Wayne Davison a7c1690d62 One more >= tweak. 2020-06-21 15:30:34 -07:00
Wayne Davison 662fedd74b Get the early-input reading code right. 2020-06-21 15:23:13 -07:00
Wayne Davison e16b22751a Add --early-input=FILE option. 2020-06-21 14:32:00 -07:00
Wayne Davison 2e1b46db39 Close STDIN for early exec script. 2020-06-21 11:17:09 -07:00
Wayne Davison 3c56896d21 Simplify a variable. 2020-06-19 11:07:02 -07:00
Wayne Davison 249e28c75a Rename "haproxy header" to "proxy protocol". 2020-06-15 11:33:23 -07:00
Wayne Davison e63ff70eae Some indentation fixes. 2020-06-13 19:15:02 -07:00
Wayne Davison cff0764b7f Add haproxy header parameter to rsync daemon 2020-06-11 14:22:25 -07:00
Wayne Davison a3377921eb Add early exec daemon parameter.
Inspired by Ciprian Dorin Craciun's `bootstrap exec` patch.
2020-06-10 21:38:37 -07:00
Wayne Davison 2c6f0581ac A couple minor fixes. 2020-06-04 22:54:38 -07:00
Wayne Davison 916faecb83 Only sender can output non-final stats on error
The receiving side's stats are split between 2 processes until the very end.
2020-06-04 21:40:43 -07:00
Wayne Davison 5d7b71b7a7 Make use of O_NOFOLLOW if it is defined. 2020-06-04 19:47:59 -07:00
Wayne Davison b177311aee Use a lock to not fail on a left-over pid file. 2020-06-04 19:08:03 -07:00
Wayne Davison c0268d9217 Some improvements for --msgs2stderr and --daemon.
- Set am_daemon to -1 (from 1) when the daemon is run via rsh.
- Only disable --msgs2stderr for a normal (socket) daemon.
- Forward a -q to the server if --msgs2stderr was also specified.
- Added --no-msgs2stderr option to allow it to be overridden.
2020-05-31 16:02:46 -07:00
Wayne Davison f60bd811e9 Use MSG_FLUSH in a couple more spots. 2020-05-28 00:41:39 -07:00
Wayne Davison e448d31d63 Need to flush early errors before we exit. 2020-05-17 21:20:15 -07:00
Wayne Davison c5fabfb068 Set Copyright years and make them easier to update
I replaced git-set-file-times with an improved version that I wrote
recently (in python3). A new script uses it to figure out the
last-modified year for each *.[ch] file and updates its copyright.
It also puts the latest year into the latest-year.h file for the
output of --version.
2020-04-09 15:11:37 -07:00
Wayne Davison 70cbc66b7f Set RSYNC_PORT in the env for a daemon-over-rsh connection.
Fixes bug #14163.
2020-04-05 19:34:27 -07:00