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