1 This patch from Antti Tapaninen added the --omit-dir-changes option, which
2 tells rsync to not affect any attributes on the directories in the transfer.
4 To use this patch, run these commands for a successful build:
6 patch -p1 <patches/omit-dir-changes.diff
7 ./configure (optional if already run)
10 based-on: ed4b3448be243b1bdb30a5da811f1e217f5a0601
11 diff --git a/generator.c b/generator.c
14 @@ -45,6 +45,7 @@ extern int preserve_hard_links;
15 extern int preserve_executability;
16 extern int preserve_perms;
17 extern int preserve_mtimes;
18 +extern int omit_dir_changes;
19 extern int omit_dir_times;
20 extern int omit_link_times;
21 extern int delete_mode;
22 @@ -510,6 +511,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
23 : S_ISDIR(file->mode) ? !omit_dir_times
24 : S_ISLNK(file->mode) ? !omit_link_times
26 + int omit_uid_gid = omit_dir_changes && S_ISDIR(sxp->st.st_mode);
28 if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
29 iflags |= ITEM_REPORT_SIZE;
30 @@ -543,9 +545,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
31 } else if (preserve_executability
32 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
33 iflags |= ITEM_REPORT_PERMS;
34 - if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
35 + if (uid_ndx && !omit_uid_gid && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
36 iflags |= ITEM_REPORT_OWNER;
37 - if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file))
38 + if (gid_ndx && !omit_uid_gid && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file))
39 iflags |= ITEM_REPORT_GROUP;
41 if (preserve_acls && !S_ISLNK(file->mode)) {
42 @@ -1451,7 +1453,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
44 if (file->flags & FLAG_DIR_CREATED)
46 - if (!preserve_perms) { /* See comment in non-dir code below. */
47 + if (!preserve_perms || omit_dir_changes) { /* See comment in non-dir code below. */
48 file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms, statret == 0);
50 if (statret != 0 && basis_dir[0] != NULL) {
51 diff --git a/options.c b/options.c
54 @@ -64,6 +64,7 @@ int preserve_gid = 0;
55 int preserve_mtimes = 0;
56 int preserve_atimes = 0;
57 int preserve_crtimes = 0;
58 +int omit_dir_changes = 0;
59 int omit_dir_times = 0;
60 int omit_link_times = 0;
62 @@ -646,6 +647,7 @@ static struct poptOption long_options[] = {
63 {"omit-link-times", 'J', POPT_ARG_VAL, &omit_link_times, 1, 0, 0 },
64 {"no-omit-link-times",0, POPT_ARG_VAL, &omit_link_times, 0, 0, 0 },
65 {"no-J", 0, POPT_ARG_VAL, &omit_link_times, 0, 0, 0 },
66 + {"omit-dir-changes", 0, POPT_ARG_NONE, &omit_dir_changes, 0, 0, 0 },
67 {"modify-window", '@', POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
68 {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 },
69 {"no-super", 0, POPT_ARG_VAL, &am_root, 0, 0, 0 },
70 @@ -2302,7 +2304,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
71 parse_filter_str(&filter_list, backup_dir_buf, rule_template(0), 0);
74 - if (make_backups && !backup_dir)
75 + if (omit_dir_changes || (make_backups && !backup_dir))
76 omit_dir_times = -1; /* Implied, so avoid -O to sender. */
79 @@ -2815,6 +2817,8 @@ void server_options(char **args, int *argc_p)
80 args[ac++] = "--size-only";
82 args[ac++] = "--stats";
83 + if (omit_dir_changes)
84 + args[ac++] = "--omit-dir-changes";
87 args[ac++] = safe_arg("--skip-compress", skip_compress);
88 diff --git a/rsync.1.md b/rsync.1.md
91 @@ -427,6 +427,7 @@ has its own detailed description later in this manpage.
92 --crtimes, -N preserve create times (newness)
93 --omit-dir-times, -O omit directories from --times
94 --omit-link-times, -J omit symlinks from --times
95 +--omit-dir-changes omit directories from any attribute changes
96 --super receiver attempts super-user activities
97 --fake-super store/recover privileged attrs using xattrs
98 --sparse, -S turn sequences of nulls into sparse blocks
99 @@ -1604,6 +1605,11 @@ expand it.
100 This tells rsync to omit symlinks when it is preserving modification,
101 access, and create times.
103 +0. `--omit-dir-changes`
105 + This tells rsync to omit directories when applying any preserved attributes
106 + (owner, group, times, permissions) to already existing directories.
110 This tells the receiving side to attempt super-user activities even if the
111 diff --git a/rsync.c b/rsync.c
114 @@ -35,6 +35,7 @@ extern int preserve_executability;
115 extern int preserve_mtimes;
116 extern int omit_dir_times;
117 extern int omit_link_times;
118 +extern int omit_dir_changes;
120 extern int am_server;
121 extern int am_daemon;
122 @@ -490,6 +491,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
124 int change_uid, change_gid;
125 mode_t new_mode = file->mode;
130 @@ -520,9 +522,10 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
134 - change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
135 - change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
136 - && sxp->st.st_gid != (gid_t)F_GROUP(file);
137 + omit_uid_gid = omit_dir_changes && S_ISDIR(sxp->st.st_mode);
138 + change_uid = am_root && !omit_uid_gid && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
139 + change_gid = gid_ndx && !omit_uid_gid && !(file->flags & FLAG_SKIP_GROUP)
140 + && sxp->st.st_gid != (gid_t)F_GROUP(file);
141 #ifndef CAN_CHOWN_SYMLINK
142 if (S_ISLNK(sxp->st.st_mode)) {