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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user