feat(identity): implement --copy-as USER[:GROUP] safe subset (P7 Wave E)
Force the receiver to apply the requested owner/group to every written entry through the confined fd-relative identity path instead of switching the process credentials (unsafe for the multithreaded receiver). An unprivileged receiver refuses the transfer up front in server_module_gate, before STATUS_OK, so no data is written with the wrong ownership. - new Config fields copy_as_set/copy_as_uid/copy_as_gid + defaults - identity_parse_copy_as (name/@N/* resolution, primary-gid default, gid==uid fallback for numeric ids with no passwd entry); implies -M - identity snapshot + highest-priority forcing in identity_resolve_targets - identity_copy_as_refused() helper - trailing config-frame block (presence int + two int32 ids, >=0 checked) - PROTOCOL_VERSION 2.17.0 -> 2.18.0; version-sensitive tests updated - unit tests for parse + wire round-trip/negative-id rejection - integration TestCopyAs: unprivileged refusal + root chown assertion - RSYNC_COMPAT.md --copy-as row updated (safe subset + divergence); README protocol version refreshed
This commit is contained in:
@@ -1414,6 +1414,18 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args,
|
||||
if (identity_parse_chown(config, argv[++i]) != 0)
|
||||
return -1;
|
||||
config->use_metadata = true;
|
||||
} else if (strncmp(argv[i], "--copy-as=", 10) == 0) {
|
||||
if (identity_parse_copy_as(config, argv[i] + 10) != 0)
|
||||
return -1;
|
||||
config->use_metadata = true;
|
||||
} else if (opt_is(argv[i], "--copy-as", NULL)) {
|
||||
if (i + 1 >= argc) {
|
||||
log_message(LOG_LEVEL_ERROR, "missing argument for %s", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
if (identity_parse_copy_as(config, argv[++i]) != 0)
|
||||
return -1;
|
||||
config->use_metadata = true;
|
||||
} else if (strncmp(argv[i], "--outbuf=", 9) == 0) {
|
||||
if (set_outbuf_option(config, argv[i] + 9) != 0)
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user