Skip to content

Add --chmod-dest option for handling --fake-super permissions #751

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion options.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ char *iconv_opt =
#endif

struct chmod_mode_struct *chmod_modes = NULL;
struct chmod_mode_struct *dest_chmod_modes = NULL;

static const char *debug_verbosity[] = {
/*0*/ NULL,
Expand Down Expand Up @@ -584,7 +585,7 @@ enum {OPT_SERVER = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG, OPT_BLOCK_SIZE,
OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_BWLIMIT, OPT_STDERR,
OPT_OLD_COMPRESS, OPT_NEW_COMPRESS, OPT_NO_COMPRESS, OPT_OLD_ARGS,
OPT_STOP_AFTER, OPT_STOP_AT,
OPT_STOP_AFTER, OPT_STOP_AT, OPT_CHMOD_DEST,
OPT_REFUSED_BASE = 9000};

static struct poptOption long_options[] = {
Expand Down Expand Up @@ -687,6 +688,7 @@ static struct poptOption long_options[] = {
{"i-d", 0, POPT_ARG_VAL, &implied_dirs, 1, 0, 0 },
{"no-i-d", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
{"chmod", 0, POPT_ARG_STRING, 0, OPT_CHMOD, 0, 0 },
{"chmod-dest", 0, POPT_ARG_STRING, 0, OPT_CHMOD_DEST, 0, 0 },
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
{"one-file-system", 'x', POPT_ARG_NONE, 0, 'x', 0, 0 },
Expand Down Expand Up @@ -1751,6 +1753,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
}
break;

case OPT_CHMOD_DEST:
arg = poptGetOptArg(pc);
if (!parse_chmod(arg, &dest_chmod_modes)) {
snprintf(err_buf, sizeof err_buf,
"Invalid argument passed to --chmod-dest (%s)\n",
arg);
goto cleanup;
}
break;

case OPT_INFO:
arg = poptGetOptArg(pc);
parse_output_words(info_words, info_levels, arg, USER_PRIORITY);
Expand Down
15 changes: 15 additions & 0 deletions rsync.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ has its own detailed description later in this manpage.
--perms, -p preserve permissions
--executability, -E preserve executability
--chmod=CHMOD affect file and/or directory permissions
--chmod-dest=CHMOD override permissions with --fake-super
--acls, -A preserve ACLs (implies --perms)
--xattrs, -X preserve extended attributes
--owner, -o preserve owner (super-user only)
Expand Down Expand Up @@ -1518,6 +1519,20 @@ expand it.
See the [`--perms`](#opt) and [`--executability`](#opt) options for how the
resulting permission value can be applied to the files in the transfer.

0. `--chmod-dest=CHMOD`

This option tells rsync to apply one or more comma-separated "chmod" modes
to the permissions of the destination file on disk. The syntax is identical
to the [`--chmod`](#opt) option.

This option is used with the [`--fake-super`](#opt) option to apply the
original source permissions to the fake super attributes, while applying
different permissions to the destination file.

When the destination file is being used as a backup, this allows permissions
to be applied to the backup independent of the permissions of the source
file being backed up.

0. `--owner`, `-o`

This option causes rsync to set the owner of the destination file to be the
Expand Down
6 changes: 5 additions & 1 deletion rsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ extern int make_backups;
extern int sanitize_paths;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct chmod_mode_struct *daemon_chmod_modes;
extern struct chmod_mode_struct *dest_chmod_modes;
#ifdef ICONV_OPTION
extern char *iconv_opt;
#endif
Expand Down Expand Up @@ -655,9 +656,12 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
}
#endif

if (dest_chmod_modes)
new_mode = tweak_mode(new_mode, dest_chmod_modes);

#ifdef HAVE_CHMOD
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
int ret = am_root < 0 && !dest_chmod_modes ? 0 : do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR_XFER, errno,
"failed to set permissions on %s",
Expand Down