TapTap
f43f236f66
Merge feat/p6-batch: residual batch --write-batch/--only-write-batch/--read-batch
2026-09-10 22:06:23 +02:00
TapTap
fc2d144492
fix(p6-batch): reject clean EOF on record read; add traversal/EOF security tests
2026-09-10 22:05:18 +02:00
TapTap
c026176bb3
feat(p6-batch): residual-batch write/read driver + codec
...
Implements the client-only residual-batch feature end-to-end:
- src/shared/batch.{c,h}: self-contained single-file batch codec using the
existing chunk_serialize/chunk_deserialize codec (byte-identical by
construction). Magic+format-version header (metadata mode is persisted into
the header so a batch is self-describing across machines), length-prefixed
chunk records, bounded reads that reject malformed/truncated/oversized
records cleanly.
- src/client/client_send.c: write_batch_from_source (deterministic separate
scan pass, loads every chunk's file images, emits header+records) and
apply_batch_to_dest (local apply to a destination root via
file_save_to_disk_full). No wire change, no server involved.
- src/client/client_validation.c: --write-batch XOR --only-write-batch;
--read-batch exclusive with both; --read-batch needs only a DEST,
--only-write-batch only a SOURCE.
- src/client/client_cli.c: main() drives the three batch modes without
connecting/transferring for read/only-write; --write-batch runs the live
transfer (single-threaded so the config survives) then emits the batch.
- tests/test_batch.{c,h} (unit: byte-identical roundtrip with and without
metadata; bad-magic/truncated/oversized rejection) + tests/integration/
test_batch.py (only-write no-server, read-batch no-source roundtrip,
--write-batch with a live transfer, conflict rejections).
- clang-format: realign PART-1 config.h comment block.
No PROTOCOL_VERSION bump, no config-frame field, no server flag.
2026-09-10 21:40:07 +02:00
TapTap
4930127312
feat(p6-batch): CLI/config plumbing for --write-batch/--only-write-batch/--read-batch
2026-09-10 21:14:30 +02:00
TapTap
52f45692b9
docs: recount RSYNC_COMPAT to 126/5 after --protocol (Wave C)
CI / lint (push) Successful in 1m15s
CI / sanitizers (undefined) (push) Successful in 54s
CI / sanitizers (address) (push) Successful in 56s
CI / fuzz-build (push) Successful in 21s
CI / coverage (push) Successful in 45s
CI / valgrind (push) Successful in 39s
CI / build-and-test (push) Successful in 4m41s
2026-09-10 20:45:32 +02:00
TapTap
40b0870514
Merge feat/p6-protocol: --protocol version-force flag (client-only)
2026-09-10 20:44:44 +02:00
TapTap
5262cc2597
test(p6-protocol): harden validation null-check; cover missing-arg --protocol
2026-09-10 20:44:33 +02:00
TapTap
9fe6d6c748
test(p6-protocol): unit + integration coverage for --protocol
2026-09-10 20:36:05 +02:00
TapTap
2b7bb2d523
feat(p6-protocol): --protocol version-force flag (client-only)
2026-09-10 20:36:05 +02:00
TapTap
bb27b2af50
docs: correct RSYNC_COMPAT selection/update rows to implemented (no code change)
CI / lint (push) Successful in 1m15s
CI / sanitizers (undefined) (push) Successful in 55s
CI / sanitizers (address) (push) Successful in 56s
CI / fuzz-build (push) Successful in 21s
CI / coverage (push) Successful in 44s
CI / valgrind (push) Successful in 38s
CI / build-and-test (push) Successful in 4m43s
2026-09-10 20:16:03 +02:00
TapTap
a2ac599298
docs: recount RSYNC_COMPAT to 121/10 after Phase 6 waves A-B (--stop-after/--stop-at, --iconv)
CI / lint (push) Successful in 1m15s
CI / sanitizers (address) (push) Successful in 53s
CI / sanitizers (undefined) (push) Successful in 52s
CI / fuzz-build (push) Successful in 22s
CI / coverage (push) Successful in 45s
CI / valgrind (push) Successful in 38s
CI / build-and-test (push) Successful in 4m40s
2026-09-10 18:18:17 +02:00
TapTap
282aebb7f5
Merge feat/p6-stop: --stop-after/--stop-at deadline stop
2026-09-10 18:16:55 +02:00
TapTap
b2afcf2c65
Merge feat/p6-iconv: --iconv charset conversion + PROTOCOL 2.16.0
2026-09-10 18:16:51 +02:00
TapTap
09a07179c9
fix(p6-stop): init -m scan_stopped_early; gate delete warning; stabilize partial-stop test
2026-09-10 18:16:35 +02:00
TapTap
cac805b661
fix(p6-iconv): prevent convert buffer overflow; validate both directions; reset on error; more tests
2026-09-10 17:49:29 +02:00
TapTap
ac7e9e3bc1
fix(p6-stop): block delete-manifest on early stop; sync -m manifest access; overflow guard
2026-09-10 17:39:34 +02:00
TapTap
7d6665633d
test(p6-iconv): iconv unit, config wire-roundtrip, integration tests
2026-09-10 17:13:06 +02:00
TapTap
6e02a24232
feat(p6-iconv): --iconv charset conversion + PROTOCOL 2.16.0
2026-09-10 17:13:01 +02:00
TapTap
37cff96537
test(p6-stop): unit and integration tests for stop deadlines
2026-09-10 16:27:49 +02:00
TapTap
24d1448246
feat(p6-stop): --stop-after/--stop-at deadline transfer stop
2026-09-10 16:27:49 +02:00
TapTap
6bb63c6f21
docs: recount RSYNC_COMPAT to 118/13 after daemon Wave C (--no-motd + MOTD)
CI / lint (push) Successful in 1m14s
CI / sanitizers (address) (push) Successful in 55s
CI / sanitizers (undefined) (push) Successful in 53s
CI / fuzz-build (push) Successful in 21s
CI / coverage (push) Successful in 45s
CI / valgrind (push) Successful in 38s
CI / build-and-test (push) Successful in 5m42s
2026-09-10 13:59:15 +02:00
TapTap
61eb08023a
Merge feat/d5-daemon-motd: daemon MOTD display + --no-motd
2026-09-10 13:59:07 +02:00
TapTap
0c35cf2b82
test(d5-daemon-motd): assert no banner when no config key
2026-09-10 13:58:21 +02:00
TapTap
cf5f730940
feat(d5-daemon-motd): daemon MOTD display + --no-motd
2026-09-10 13:52:24 +02:00
TapTap
8330f275a6
docs: recount RSYNC_COMPAT to 117/14 after daemon Wave B auth (--password-file, --early-input)
CI / lint (push) Successful in 1m13s
CI / sanitizers (undefined) (push) Successful in 54s
CI / sanitizers (address) (push) Successful in 56s
CI / fuzz-build (push) Successful in 20s
CI / coverage (push) Successful in 44s
CI / valgrind (push) Successful in 38s
CI / build-and-test (push) Successful in 5m10s
2026-09-10 13:27:39 +02:00
TapTap
d3c9f1d218
Merge feat/d5-daemon-auth: daemon password auth (--password-file, --early-input)
2026-09-10 13:27:27 +02:00
TapTap
accd34ad60
fix(d5-daemon-auth): address auth review findings (Wave B)
...
- test_credentials.c: NUL-terminate the overlong-line stack buffer before
make_tmp_file's strlen() (was a stack-buffer-overflow READ under ASan);
still exercises the overlong-rejection path.
- Add redacted protocol string variants (protocol_send_str_redacted /
receive + fd send_str_redacted/receive_str_redacted) and use them for the
daemon auth username/digest so --verbose / LOG_DEBUG_ALL never logs a
replayable credential while other protocol strings keep their debug trace.
- credentials_verify/gate: replace byte-wise-short-circuiting strcmp with a
fixed-length constant-time username compare (closes user-enumeration oracle);
update doc comment to match.
- read_secret_file: preserve password exact bytes (only strip trailing CR/LF)
and burn the stack line buffer; document the whitespace behavior.
- test_server_cli.c: note the parser zero-inits opts on failure.
- Add debug-level daemon test asserting the digest never appears under --verbose.
PROTOCOL_VERSION stays 2.15.0.
2026-09-10 13:20:42 +02:00
TapTap
dd5ae60459
feat(d5-daemon-auth): password auth, --password-file, --early-input
2026-09-10 12:50:56 +02:00
TapTap
958eddf414
docs: recount RSYNC_COMPAT to 115/16 after daemon Wave A (--daemon/--config/--dparam/--no-detach)
CI / lint (push) Successful in 1m12s
CI / sanitizers (undefined) (push) Successful in 54s
CI / sanitizers (address) (push) Successful in 55s
CI / fuzz-build (push) Successful in 22s
CI / coverage (push) Successful in 46s
CI / valgrind (push) Successful in 38s
CI / build-and-test (push) Successful in 4m41s
2026-09-09 18:40:06 +02:00
TapTap
8440dbfdb8
Merge feat/d5-daemon-core: daemon lifecycle, module config, ::dest (PROTOCOL 2.15.0)
2026-09-09 18:39:37 +02:00
TapTap
7c55409a6b
fix(d5-daemon-core): cppcheck const-correctness, wire module length cap, daemonize chdir/umask, daemon confinement tests
...
- daemon_conf.c/server.c/test_daemon_conf.c: const-qualify parse/loop pointers;
scope user_path static inside its block (clears the 9-wave-A cppcheck findings)
- config.c receive_daemon_module: reject invalid/over-long wire module names
(> DAEMON_MAX_MODULE_NAME) with a clean STATUS_ERROR; client side already
enforced via daemon_module_name_valid in config_parse_daemon_dest
- server.c daemonize: chdir(/) and umask(0) so module paths resolve from /
and config-requested file modes are honored; PROTOCOL_VERSION stays 2.15.0
- test_daemon.py: confinement (read-only/unknown no-write anywhere), module-less
and dot-dot destination refusal, real daemon_detach double-fork path
2026-09-09 18:30:52 +02:00
TapTap
b3d7d64347
feat(d5-daemon-core): daemon lifecycle, module config, ::dest, PROTOCOL 2.15.0
2026-09-09 17:48:07 +02:00
TapTap
9d17e951f1
docs: recount RSYNC_COMPAT to 111/20 after Phase 5 waves A-C; clang-format 18 reflow
CI / lint (push) Successful in 1m9s
CI / sanitizers (undefined) (push) Successful in 53s
CI / sanitizers (address) (push) Successful in 55s
CI / fuzz-build (push) Successful in 19s
CI / coverage (push) Successful in 43s
CI / valgrind (push) Successful in 37s
CI / build-and-test (push) Successful in 4m28s
2026-09-09 14:37:52 +02:00
TapTap
1e02ebcd32
Merge feat/p5-remote-option: --remote-option, --trust-sender
...
# Conflicts:
# RSYNC_COMPAT.md
# src/client/client_cli.c
# src/client/client_send.c
# src/shared/transport_ssh.c
# src/shared/transport_ssh.h
# tests/integration/test_ssh.py
# tests/test_client_cli.c
# tests/test_transport_ssh.c
2026-09-09 14:35:26 +02:00
TapTap
b1c63ff947
Merge feat/p5-socket: --address, -4/-6, --sockopts, server bind options
...
# Conflicts:
# RSYNC_COMPAT.md
# tests/test_client_cli.c
2026-09-09 14:30:36 +02:00
TapTap
35f4297538
Merge feat/p5-rsh: --rsh/-e, --rsync-path, --blocking-io, --outbuf
2026-09-09 14:29:58 +02:00
TapTap
f86ba7a556
fix(p5-socket): clang-format 18 reflow + cppcheck const-correctness
2026-09-09 14:29:46 +02:00
TapTap
cdcaf21acd
fix(p5-rsh): NULL-check argv tail str_dups in ssh_build_client_argv
2026-09-09 14:29:46 +02:00
TapTap
ad228db915
fix(p5-remote-option): wire server --trust-sender, align save-layer gates, add hostile-sender test
2026-09-09 14:23:59 +02:00
TapTap
07d1dd84f7
feat(p5-socket): --address, -4/-6, --sockopts, server bind options
2026-09-09 13:41:28 +02:00
TapTap
858af3d63d
feat(p5-rsh): --rsh/-e, --rsync-path, --blocking-io, --outbuf
2026-09-09 13:41:28 +02:00
TapTap
5e79d7d76b
feat(p5-remote-option): --remote-option (probe 2.14.0), --trust-sender
2026-09-09 13:41:28 +02:00
TapTap
90ccf297d7
style: cppcheck — const-correctness in file_send_special and test_chunk
...
CI / lint (push) Successful in 1m7s
CI / sanitizers (address) (push) Successful in 53s
CI / sanitizers (undefined) (push) Successful in 53s
CI / fuzz-build (push) Successful in 21s
CI / coverage (push) Successful in 44s
CI / valgrind (push) Successful in 37s
CI / build-and-test (push) Successful in 4m41s
file_send_special now takes const File*; test_chunk declares the deserialized
Chunk* const. cppcheck (--error-exitcode=1) now exits clean; clang-format
clean; unit 29/29.
2026-09-08 22:53:47 +02:00
TapTap
5a00a4fe2b
style: cppcheck — drop redundant if(fd>=0) in test_xattr copy-fallback test
...
CI / lint (push) Failing after 1m6s
CI / build-and-test (push) Skipped
CI / sanitizers (address) (push) Skipped
CI / sanitizers (undefined) (push) Skipped
CI / fuzz-build (push) Skipped
CI / coverage (push) Skipped
CI / valgrind (push) Skipped
EXPECT_TRUE(fd >= 0) already guards; the enclosing if is flagged always-true
by cppcheck. read(-1) is safe.
2026-09-08 22:46:43 +02:00
TapTap
743b00ffdd
docs: recount RSYNC_COMPAT summary after Phase-4 wave C (symlink-trust + devices + acl/xattr)
...
CI / lint (push) Failing after 1m8s
CI / build-and-test (push) Skipped
CI / sanitizers (address) (push) Skipped
CI / sanitizers (undefined) (push) Skipped
CI / fuzz-build (push) Skipped
CI / coverage (push) Skipped
CI / valgrind (push) Skipped
Wave C moved 12 rows: -l/--links now real (was Partial). New Implemented (7):
--munge-links, -k/--copy-dirlinks, -K/--keep-dirlinks, -D, -A/--acls, -X/--xattrs
(links was Partial->Implemented). New Partial (5): --devices, --specials,
--copy-devices, --write-devices, --fake-super. Summary: Implemented 94->101,
Partial 6->10, Not Implemented 41->30 (Total 147).
Final Phase-4 summary: 101/3/10/3/30 = 147; PROTOCOL_VERSION 2.13.0.
2026-09-08 22:42:02 +02:00
TapTap
94b6662018
Merge feat/p4-acl-xattr: -X/-A/--fake-super
...
# Conflicts:
# src/shared/config.c
# src/shared/file.c
# src/shared/file_types.h
# tests/integration/test_features.py
# tests/test_client_cli.c
# tests/test_config.c
2026-09-08 22:38:15 +02:00
TapTap
5bbdc5b450
Merge feat/p4-devices
...
# Conflicts:
# src/client/client_send.c
# src/server/receiver.c
# src/shared/chunk.c
# src/shared/file.c
# src/shared/file_receive.c
# src/shared/file_receive.h
# src/shared/file_types.h
# src/shared/protocol.h
# tests/test_chunk.c
2026-09-08 22:33:52 +02:00
TapTap
e600b56f10
Merge feat/p4-symlink-trust
2026-09-08 22:27:56 +02:00
TapTap
747946c318
acls/xattrs: -X/--xattrs, -A/--acls, --fake-super
...
CI / lint (pull_request) Failing after 55s
CI / build-and-test (pull_request) Skipped
CI / sanitizers (address) (pull_request) Skipped
CI / sanitizers (undefined) (pull_request) Skipped
CI / fuzz-build (pull_request) Skipped
CI / coverage (pull_request) Skipped
CI / valgrind (pull_request) Skipped
New src/shared/xattr.{c,h}: capture user.* + POSIX ACL xattrs, transmit a bounded
per-file block, re-apply fd-relative. security.*/trusted.*/other system.* never
transmitted/applied (receiver re-validates). Bounds: name<=255 value<=1MiB count
<=256 total<=4MiB. --fake-super records uid:gid:mode:mtime in reserved
user.fastsync.stat (receiver-only). PROTOCOL_VERSION 2.12.0->2.13.0. Review
fixes: reserved key not forwardable, link/hardlink copy-fallback preserves
xattrs, no const-param mutation, per-file warning dedup.
2026-09-08 22:27:53 +02:00
TapTap
007e8f90f2
devices: --devices/--specials/-D/--copy-devices/--write-devices
...
CI / lint (pull_request) Failing after 56s
CI / build-and-test (pull_request) Skipped
CI / sanitizers (address) (pull_request) Skipped
CI / sanitizers (undefined) (pull_request) Skipped
CI / fuzz-build (pull_request) Skipped
CI / coverage (pull_request) Skipped
CI / valgrind (pull_request) Skipped
Recreate char/block nodes via mknodat (privilege-gated, EPERM->warn+skip) and
FIFOs via mkfifoat; new STATUS_SPECIAL frame + validated rdev; sockets skipped;
-copy-devices copies st_size; -write-devices O_NOFOLLOW+O_NONBLOCK warn+skip.
preserve_specials/copy_devices/write_devices cross the wire. PROTOCOL_VERSION
2.12.0->2.13.0. Review fixes: -m source-removal keeps recreated specials, FIFO
ENXIO skip, rdev bounds at chunk_deserialize, STATUS_ERROR on receive branch,
scanner_prepare_special dedup.
2026-09-08 22:27:53 +02:00