Commit | Line | Data |
---|---|---|
bd006671 MP |
1 | diff --unified -r --new-file rsync-2.5.5.orig/Makefile.in rsync-2.5.5/Makefile.in |
2 | --- rsync-2.5.5.orig/Makefile.in Mon Mar 25 15:36:56 2002 | |
3 | +++ rsync-2.5.5/Makefile.in Wed Apr 3 21:45:22 2002 | |
4 | @@ -31,7 +31,7 @@ | |
5 | zlib/zutil.o zlib/adler32.o | |
6 | OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o backup.o | |
7 | OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o batch.o \ | |
8 | - clientname.o | |
9 | + clientname.o chmod.o | |
10 | DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o | |
11 | popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ | |
12 | popt/popthelp.o popt/poptparse.o | |
13 | diff --unified -r --new-file rsync-2.5.5.orig/chmod.c rsync-2.5.5/chmod.c | |
14 | --- rsync-2.5.5.orig/chmod.c Thu Jan 1 10:00:00 1970 | |
15 | +++ rsync-2.5.5/chmod.c Wed Apr 3 22:56:30 2002 | |
16 | @@ -0,0 +1,134 @@ | |
17 | +#include "rsync.h" | |
18 | + | |
19 | +struct chmod_mode_struct { | |
20 | + int ModeAND; | |
21 | + int ModeOR; | |
22 | + char Xkeep; | |
23 | + struct chmod_mode_struct *next; | |
24 | +}; | |
25 | + | |
26 | +#define CHMOD_ADD 1 | |
27 | +#define CHMOD_SUB 2 | |
28 | +#define CHMOD_EQ 3 | |
29 | + | |
30 | +/* Parse a chmod-style argument, and break it down into one or more AND/OR | |
31 | + pairs in a linked list. | |
32 | + We use a state machine to walk through the options - states 1 and 3 | |
33 | + before/including the operation (+, - or =), state 2 after the operation and | |
34 | + state 4 if we hit an error. | |
35 | +*/ | |
36 | +struct chmod_mode_struct *parse_chmod (char *modestr) | |
37 | +{ | |
38 | + int state = 1; | |
39 | + int where = 0, what = 0, op = 0, topbits = 0, topoct = 0, Xkeep=0; | |
40 | + struct chmod_mode_struct *first_mode = NULL, *curr_mode = NULL, *prev_mode = NULL; | |
41 | + | |
42 | + while (*modestr) { | |
43 | + if (state!=2) { | |
44 | + switch (*modestr) { | |
45 | + case 'u' : where |= 0100; topbits |= 04000; break; | |
46 | + case 'g' : where |= 0010; topbits |= 02000; break; | |
47 | + case 'o' : where |= 0001; break; | |
48 | + case 'a' : where |= 0111; break; | |
49 | + case '+' : op = CHMOD_ADD; state=2; break; | |
50 | + case '-' : op = CHMOD_SUB; state=2; break; | |
51 | + case '=' : op = CHMOD_EQ; state=2; break; | |
52 | + case ',' : break; | |
53 | + default : state=4; /* Invalid Mode! */ | |
54 | + } | |
55 | + } else if (state==2) { | |
56 | + switch (*modestr) { | |
57 | + case 'r' : what |= 4; break; | |
58 | + case 'w' : what |= 2; break; | |
59 | + case 'X' : Xkeep = 1; | |
60 | + case 'x' : what |= 1; break; | |
61 | + case 's' : if (topbits) { | |
62 | + topoct |= topbits; | |
63 | + } else { | |
64 | + topoct = 04000; | |
65 | + } | |
66 | + break; | |
67 | + case 't' : topoct |= 01000; break; | |
68 | + default : state=4; /* Invalid Mode! */ | |
69 | + } | |
70 | + } | |
71 | + | |
72 | + if (state==4) { | |
73 | + break; | |
74 | + } | |
75 | + | |
76 | + modestr++; | |
77 | + if (!*modestr || *modestr == ',') { | |
78 | + prev_mode = curr_mode; | |
79 | + curr_mode = malloc(sizeof(struct chmod_mode_struct)); | |
80 | + if (prev_mode) { | |
81 | + prev_mode->next = curr_mode; | |
82 | + } else { | |
83 | + first_mode = curr_mode; | |
84 | + } | |
85 | + curr_mode->next = NULL; | |
86 | + | |
87 | + switch (op) { | |
88 | + case CHMOD_ADD: | |
89 | + curr_mode->ModeAND = 07777; | |
90 | + curr_mode->ModeOR = (where * what) + topoct; | |
91 | + break; | |
92 | + case CHMOD_SUB: | |
93 | + curr_mode->ModeAND = 07777 - (where * what) - topoct; | |
94 | + curr_mode->ModeOR = 0; | |
95 | + break; | |
96 | + case CHMOD_EQ: | |
97 | + curr_mode->ModeAND = 07777 - (where * 7); | |
98 | + curr_mode->ModeOR = where * what - topoct; | |
99 | + break; | |
100 | + } | |
101 | + | |
102 | + curr_mode->Xkeep = Xkeep; | |
103 | + | |
104 | + state=3; | |
105 | + where = what = topoct = topbits = Xkeep = 0; | |
106 | + } | |
107 | + } | |
108 | + | |
109 | + if (state==4) { | |
110 | + free_chmod_mode(first_mode); | |
111 | + first_mode=NULL; | |
112 | + } | |
113 | + return first_mode; | |
114 | +} | |
115 | + | |
116 | + | |
117 | +/* Takes an existing file permission and a list of AND/OR changes, and create a | |
118 | + new permissions | |
119 | +*/ | |
120 | +int newmode (int oldmode, struct chmod_mode_struct *chmod_modes) | |
121 | +{ | |
122 | + int IsX = (oldmode & 0111); | |
123 | + int NonPerm = oldmode - (oldmode & 07777); | |
124 | + | |
125 | + while (chmod_modes) { | |
126 | + oldmode &= chmod_modes->ModeAND; | |
127 | + if (chmod_modes->Xkeep && !IsX) { | |
128 | + oldmode |= chmod_modes->ModeOR & (07777 - 0111); | |
129 | + } else { | |
130 | + oldmode |= chmod_modes->ModeOR; | |
131 | + } | |
132 | + chmod_modes = chmod_modes->next; | |
133 | + } | |
134 | + | |
135 | + return (oldmode + NonPerm); | |
136 | +} | |
137 | + | |
138 | +/* Free the linked list created by parse_chmod | |
139 | +*/ | |
140 | +int free_chmod_mode (struct chmod_mode_struct *chmod_modes) | |
141 | +{ | |
142 | + struct chmod_mode_struct *next; | |
143 | + | |
144 | + while (chmod_modes) { | |
145 | + next = chmod_modes->next; | |
146 | + free(chmod_modes); | |
147 | + chmod_modes = next; | |
148 | + } | |
149 | + return 0; | |
150 | +} | |
151 | diff --unified -r --new-file rsync-2.5.5.orig/flist.c rsync-2.5.5/flist.c | |
152 | --- rsync-2.5.5.orig/flist.c Fri Mar 15 08:20:20 2002 | |
153 | +++ rsync-2.5.5/flist.c Wed Apr 3 21:54:42 2002 | |
154 | @@ -36,6 +36,7 @@ | |
155 | extern int verbose; | |
156 | extern int do_progress; | |
157 | extern int am_server; | |
158 | +extern int am_sender; | |
159 | extern int always_checksum; | |
160 | ||
161 | extern int cvs_exclude; | |
162 | @@ -61,6 +62,8 @@ | |
163 | extern int read_batch; | |
164 | extern int write_batch; | |
165 | ||
166 | +extern struct chmod_mode_struct *chmod_modes; | |
167 | + | |
168 | static char topsrcname[MAXPATHLEN]; | |
169 | ||
170 | static struct exclude_struct **local_exclude_list; | |
171 | @@ -715,6 +718,10 @@ | |
172 | #ifdef HAVE_STRUCT_STAT_ST_RDEV | |
173 | file->rdev = st.st_rdev; | |
174 | #endif | |
175 | + | |
176 | + if (am_sender && chmod_modes && S_ISREG(st.st_mode)) { | |
177 | + file->mode = newmode(file->mode, chmod_modes); | |
178 | + } | |
179 | ||
180 | #if SUPPORT_LINKS | |
181 | if (S_ISLNK(st.st_mode)) { | |
182 | diff --unified -r --new-file rsync-2.5.5.orig/options.c rsync-2.5.5/options.c | |
183 | --- rsync-2.5.5.orig/options.c Wed Mar 20 07:16:42 2002 | |
184 | +++ rsync-2.5.5/options.c Wed Apr 3 22:24:46 2002 | |
185 | @@ -112,6 +112,7 @@ | |
186 | char *password_file = NULL; | |
187 | char *rsync_path = RSYNC_PATH; | |
188 | char *backup_dir = NULL; | |
189 | +char *chmod_mode = NULL; | |
190 | int rsync_port = RSYNC_PORT; | |
191 | ||
192 | int verbose = 0; | |
193 | @@ -128,6 +129,7 @@ | |
194 | * address, or a hostname. **/ | |
195 | char *bind_address; | |
196 | ||
197 | +struct chmod_mode_struct *chmod_modes = NULL; | |
198 | ||
199 | static void print_rsync_version(enum logcode f) | |
200 | { | |
201 | @@ -220,6 +222,7 @@ | |
202 | rprintf(F," -g, --group preserve group\n"); | |
203 | rprintf(F," -D, --devices preserve devices (root only)\n"); | |
204 | rprintf(F," -t, --times preserve times\n"); | |
205 | + rprintf(F," --chmod=CHMOD change destination permissions\n"); | |
206 | rprintf(F," -S, --sparse handle sparse files efficiently\n"); | |
207 | rprintf(F," -n, --dry-run show what would have been transferred\n"); | |
208 | rprintf(F," -W, --whole-file copy whole files, no incremental checks\n"); | |
209 | @@ -285,7 +288,7 @@ | |
210 | OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST, | |
211 | OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS, | |
212 | OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR, | |
213 | - OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO, | |
214 | + OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO, OPT_CHMOD, | |
215 | OPT_NO_BLOCKING_IO, OPT_WHOLE_FILE, OPT_NO_WHOLE_FILE, | |
216 | OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_IGNORE_EXISTING}; | |
217 | ||
218 | @@ -325,6 +328,7 @@ | |
219 | {"perms", 'p', POPT_ARG_NONE, &preserve_perms , 0, 0, 0 }, | |
220 | {"owner", 'o', POPT_ARG_NONE, &preserve_uid , 0, 0, 0 }, | |
221 | {"group", 'g', POPT_ARG_NONE, &preserve_gid , 0, 0, 0 }, | |
222 | + {"chmod", 0, POPT_ARG_STRING, &chmod_mode, OPT_CHMOD, 0, 0 }, | |
223 | {"devices", 'D', POPT_ARG_NONE, &preserve_devices , 0, 0, 0 }, | |
224 | {"times", 't', POPT_ARG_NONE, &preserve_times , 0, 0, 0 }, | |
225 | {"checksum", 'c', POPT_ARG_NONE, &always_checksum , 0, 0, 0 }, | |
226 | @@ -563,6 +567,15 @@ | |
227 | read_batch = 1; | |
228 | break; | |
229 | ||
230 | + case OPT_CHMOD: | |
231 | + chmod_modes = parse_chmod(chmod_mode); | |
232 | + if (!chmod_modes) { | |
233 | + snprintf(err_buf,sizeof(err_buf), | |
234 | + "Invalud argument passed to chmod\n"); | |
235 | + rprintf(FERROR,"ERROR: Invalid argument passed to chmod\n"); | |
236 | + return 0; | |
237 | + } | |
238 | + break; | |
239 | default: | |
240 | /* FIXME: If --daemon is specified, then errors for later | |
241 | * parameters seem to disappear. */ | |
242 | @@ -787,6 +800,11 @@ | |
243 | */ | |
244 | args[ac++] = "--compare-dest"; | |
245 | args[ac++] = compare_dest; | |
246 | + } | |
247 | + | |
248 | + if (chmod_mode && !am_sender) { | |
249 | + args[ac++] = "--chmod"; | |
250 | + args[ac++] = chmod_mode; | |
251 | } | |
252 | ||
253 | *argc = ac; | |
254 | diff --unified -r --new-file rsync-2.5.5.orig/proto.h rsync-2.5.5/proto.h | |
255 | --- rsync-2.5.5.orig/proto.h Mon Mar 25 14:51:17 2002 | |
256 | +++ rsync-2.5.5/proto.h Wed Apr 3 21:51:32 2002 | |
257 | @@ -31,6 +31,9 @@ | |
258 | void sum_init(void); | |
259 | void sum_update(char *p,int len); | |
260 | void sum_end(char *sum); | |
261 | +struct chmod_mode_struct *parse_chmod (char *modestr); | |
262 | +int newmode (int oldmode, struct chmod_mode_struct *chmod_modes); | |
263 | +int free_chmod_mode (struct chmod_mode_struct *chmod_modes); | |
264 | void _exit_cleanup(int code, const char *file, int line); | |
265 | void cleanup_disable(void); | |
266 | void cleanup_set(char *fnametmp, char *fname, struct file_struct *file, | |
267 | diff --unified -r --new-file rsync-2.5.5.orig/rsync.yo rsync-2.5.5/rsync.yo | |
268 | --- rsync-2.5.5.orig/rsync.yo Thu Feb 7 08:20:49 2002 | |
269 | +++ rsync-2.5.5/rsync.yo Wed Apr 3 23:32:30 2002 | |
270 | @@ -236,6 +236,7 @@ | |
271 | -g, --group preserve group | |
272 | -D, --devices preserve devices (root only) | |
273 | -t, --times preserve times | |
274 | + --chmod=CHMOD change destination permissions | |
275 | -S, --sparse handle sparse files efficiently | |
276 | -n, --dry-run show what would have been transferred | |
277 | -W, --whole-file copy whole files, no incremental checks | |
278 | @@ -440,6 +441,9 @@ | |
279 | cause the next transfer to behave as if it used -I, and all files will have | |
280 | their checksums compared and show up in log messages even if they haven't | |
281 | changed. | |
282 | + | |
283 | +dit(bf(--chmod)) This options tells rsync to apply the listed "chmod" pattern | |
284 | +to the permission of the files on the destination. | |
285 | ||
286 | dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers, | |
287 | instead it will just report the actions it would have taken. | |
288 | diff --unified -r --new-file rsync-2.5.5.orig/testsuite/chmod.test rsync-2.5.5/testsuite/chmod.test | |
289 | --- rsync-2.5.5.orig/testsuite/chmod.test Thu Jan 1 10:00:00 1970 | |
290 | +++ rsync-2.5.5/testsuite/chmod.test Wed Apr 3 23:23:36 2002 | |
291 | @@ -0,0 +1,38 @@ | |
292 | +#! /bin/sh | |
293 | + | |
294 | +# Copyright (C) 2002 by Martin Pool <mbp@samba.org> | |
295 | + | |
296 | +# This program is distributable under the terms of the GNU GPL (see | |
297 | +# COPYING). | |
298 | + | |
299 | +# Test that the --chmod option functions correctly. | |
300 | + | |
301 | +. $srcdir/testsuite/rsync.fns | |
302 | + | |
303 | +set -x | |
304 | + | |
305 | +# Build some files | |
306 | + | |
307 | +fromdir="$scratchdir/from" | |
308 | +todir="$scratchdir/to" | |
309 | +checkdir="$scratchdir/check" | |
310 | + | |
311 | +mkdir "$fromdir" | |
312 | +name1="$fromdir/name1" | |
313 | +name2="$fromdir/name2" | |
314 | +echo "This is the file" > "$name1" | |
315 | +echo "This is the other file" > "$name2" | |
316 | + | |
317 | +chmod 4700 "$name1" || test_skipped "Can't chown" | |
318 | + | |
319 | +# Copy the files we've created over to another directory | |
320 | +checkit "rsync -avv \"$fromdir/\" \"$checkdir/\"" "$fromdir" "$checkdir" | |
321 | + | |
322 | +# And then manually make the changes which should occur | |
323 | +chmod ug-s,a+rX $checkdir/* | |
324 | + | |
325 | +checkit "rsync -avv --chmod ug-s,a+rX \"$fromdir/\" \"$todir/\"" "$checkdir" "$todir" | |
326 | + | |
327 | +exit 0 | |
328 | +# last [] may have failed but if we get here then we've won | |
329 | + |