fix(p7-output-fs): address c-review (fake-super mode sanitization HIGH; sparse/preallocate precedence; partial no_replace guard; stronger tests)

- fake_super_restore_fd now sanitizes mode like metadata_mode (never grants
  S_IWGRP|S_IWOTH; 0666 -> 0644), fixing a privilege regression
- --sparse takes precedence over --preallocate (skip posix_fallocate when
  sparse) so holes are not re-allocated; docs corrected
- --partial retention disabled under --no_replace (ignore/existing) and only
  marks write_attempted after the write begins (no empty-temp retention)
- accept --block-size=SIZE / --delta-block=SIZE inline forms; neutral messages
- fake-super EPERM/EACCES skipped silently (docs aligned); EINVAL still logged
- sparse unit test now memcmp's the full buffer; TestBlockSize integration keeps
  the destination basis so delta is genuinely exercised
- unit 37/37, cppcheck 0, clang-format 0
This commit is contained in:
2026-09-12 09:55:40 +02:00
parent 47de05d215
commit f2ba8211ce
9 changed files with 83 additions and 38 deletions
+7 -6
View File
@@ -4350,22 +4350,23 @@ class TestBlockSize:
payload = os.urandom(300 * 1024) # enough for several 1 KiB blocks
with open(os.path.join(source, "big.bin"), "wb") as f:
f.write(payload)
# First run installs the file; second run with delta + a small block size.
result, _ = run_client(source, dest, flags=["-S"],
port=shared_server.port)
# First run installs the file as the destination basis (do NOT wipe it
# afterwards: the second run's delta must be computed against it).
result, _ = run_client(source, dest, port=shared_server.port)
assert result.returncode == 0
received = get_dest_received_dir(dest, source)
# Change the source, then delta-transfer with a non-default block size.
# Extend the source so it differs from the installed basis: the second
# run with --delta must compute a real delta against that basis.
with open(os.path.join(source, "big.bin"), "ab") as f:
f.write(os.urandom(4096))
clean_dir(dest)
result, _ = run_client(source, dest,
flags=["--incremental", "--delta", flag, "1024"],
port=shared_server.port)
assert result.returncode == 0, \
f"{flag} 1024 delta transfer failed: {(result.stderr or result.stdout)[:300]}"
with open(os.path.join(received, "big.bin"), "rb") as f:
assert f.read() == open(os.path.join(source, "big.bin"), "rb").read()
with open(os.path.join(source, "big.bin"), "rb") as expect:
assert f.read() == expect.read()
class TestOmitTimes:
"""-O/--omit-dir-times and -J/--omit-link-times are recognized and cross the
+7
View File
@@ -2930,6 +2930,13 @@ static void test_parse_args_block_size() {
EXPECT_EQ_INT(parse_args(cfg, 5, argv_delta, positional_args, &positional_count), 0);
EXPECT_EQ_INT((int)cfg->delta_block_size, 2048);
/* Inline =SIZE forms (the documented rsync spelling) are accepted too. */
cfg->delta_block_size = DELTA_BLOCK_SIZE_DEFAULT;
char* argv_eq[] = {"fastsync", "--block-size=8192", "/src", "/dst"};
positional_count = 0;
EXPECT_EQ_INT(parse_args(cfg, 4, argv_eq, positional_args, &positional_count), 0);
EXPECT_EQ_INT((int)cfg->delta_block_size, 8192);
/* Out of range: parsed, warned, and the default is kept. */
cfg->delta_block_size = DELTA_BLOCK_SIZE_DEFAULT;
char* argv_bad[] = {"fastsync", "--block-size", "1", "/src", "/dst"};
+6 -10
View File
@@ -1244,14 +1244,15 @@ static void test_file_write_to_disk_sparse_preserves_holes() {
}
EXPECT_TRUE(file_store_write_secure(path, buf, size, false, true, NULL, false));
free(buf);
/* Logical size must equal data_size exactly. */
struct stat st;
EXPECT_EQ_INT(stat(path, &st), 0);
EXPECT_EQ_INT((int)st.st_size, (int)size);
/* Content must round-trip exactly. */
/* Content must round-trip exactly: the full readback must equal the original
buffer byte-for-byte (header, the hole region staying zero, and tail) —
a writer bug in the lseek-offset bookkeeping would show up here. */
int fd = open(path, O_RDONLY);
EXPECT_TRUE(fd >= 0);
/* cppcheck-suppress knownConditionTrueFalse -- EXPECT_TRUE above asserts,
@@ -1267,14 +1268,8 @@ static void test_file_write_to_disk_sparse_preserves_holes() {
got += (unsigned long long)n;
}
EXPECT_EQ_INT((int)got, (int)size);
if (got == size) {
/* The middle hole region stays all-zero. */
for (unsigned long long i = 4096; i < size - 4096; i++)
if (readback[i] != 0) {
EXPECT_EQ_INT(0, 1);
break;
}
}
if (got == size)
EXPECT_EQ_INT(memcmp(readback, buf, size), 0);
free(readback);
}
/* Tolerant sparseness check: seek for holes; skip if unsupported. */
@@ -1288,6 +1283,7 @@ static void test_file_write_to_disk_sparse_preserves_holes() {
}
close(fd);
}
free(buf);
unlink(path);
}
+8
View File
@@ -250,6 +250,14 @@ static void test_fake_super_restore() {
EXPECT_EQ_INT(fstat(fd, &st), 0);
EXPECT_EQ_INT((int)(st.st_mode & 07777), 0751);
/* Mode sanitization: the normal metadata path never grants group/other write
bits, and fake-super replay must not re-add them (a recorded 0666 restores
as 0644, never as world-writable). */
fake_super_store_fd(fd, 1001, 1002, 0666, 1700000000, 0);
EXPECT_TRUE(fake_super_restore_fd(fd));
EXPECT_EQ_INT(fstat(fd, &st), 0);
EXPECT_EQ_INT((int)(st.st_mode & 0777), 0644);
/* Restore with a malformed record must skip without failing. */
time_t before = st.st_mtime;
int wfd = open(path, O_RDONLY);