From 873299df363c3b5a33747f52cdcf444751080905 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Mon, 7 Nov 2005 04:39:10 +0000 Subject: [PATCH] Committed to the trunk. --- chmod-option.diff | 371 ---------------------------------------------- 1 file changed, 371 deletions(-) delete mode 100644 chmod-option.diff diff --git a/chmod-option.diff b/chmod-option.diff deleted file mode 100644 index 4add86d..0000000 --- a/chmod-option.diff +++ /dev/null @@ -1,371 +0,0 @@ -After applying this patch and running configure, you MUST run this -command before "make": - - make proto - - ---- orig/Makefile.in 2005-07-07 23:11:07 -+++ Makefile.in 2004-07-03 20:13:41 -@@ -33,7 +33,7 @@ ZLIBOBJ=zlib/deflate.o zlib/inffast.o zl - 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 - OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \ -- fileio.o batch.o clientname.o -+ fileio.o batch.o clientname.o chmod.o - OBJS3=progress.o pipe.o - DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o - popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ ---- orig/chmod.c 2005-07-09 16:09:14 -+++ chmod.c 2005-07-09 16:09:14 -@@ -0,0 +1,195 @@ -+#include "rsync.h" -+ -+extern int orig_umask; -+ -+#define FLAG_X_KEEP (1<<0) -+#define FLAG_DIRS_ONLY (1<<1) -+#define FLAG_FILES_ONLY (1<<2) -+ -+struct chmod_mode_struct { -+ struct chmod_mode_struct *next; -+ int ModeAND, ModeOR; -+ char flags; -+}; -+ -+#define CHMOD_ADD 1 -+#define CHMOD_SUB 2 -+#define CHMOD_EQ 3 -+ -+#define STATE_ERROR 0 -+#define STATE_1ST_HALF 1 -+#define STATE_2ND_HALF 2 -+ -+/* Parse a chmod-style argument, and break it down into one or more AND/OR -+ * pairs in a linked list. We use a state machine to walk through the -+ * options. */ -+struct chmod_mode_struct *parse_chmod(char *modestr) -+{ -+ int state = STATE_1ST_HALF; -+ int where = 0, what = 0, op = 0, topbits = 0, topoct = 0, flags = 0; -+ struct chmod_mode_struct *first_mode = NULL, *curr_mode = NULL, -+ *prev_mode = NULL; -+ -+ while (state != STATE_ERROR) { -+ if (!*modestr || *modestr == ',') { -+ int bits; -+ -+ if (!op) { -+ state = STATE_ERROR; -+ break; -+ } -+ prev_mode = curr_mode; -+ curr_mode = new_array(struct chmod_mode_struct, 1); -+ if (prev_mode) -+ prev_mode->next = curr_mode; -+ else -+ first_mode = curr_mode; -+ curr_mode->next = NULL; -+ -+ if (where) -+ bits = where * what; -+ else { -+ where = 0111; -+ bits = (where * what) & ~orig_umask; -+ } -+ -+ switch (op) { -+ case CHMOD_ADD: -+ curr_mode->ModeAND = 07777; -+ curr_mode->ModeOR = bits + topoct; -+ break; -+ case CHMOD_SUB: -+ curr_mode->ModeAND = 07777 - bits - topoct; -+ curr_mode->ModeOR = 0; -+ break; -+ case CHMOD_EQ: -+ curr_mode->ModeAND = 07777 - (where * 7) - (topoct ? topbits : 0); -+ curr_mode->ModeOR = bits + topoct; -+ break; -+ } -+ -+ curr_mode->flags = flags; -+ -+ if (!*modestr) -+ break; -+ modestr++; -+ -+ state = STATE_1ST_HALF; -+ where = what = op = topoct = topbits = flags = 0; -+ } -+ -+ if (state != STATE_2ND_HALF) { -+ switch (*modestr) { -+ case 'D': -+ if (flags & FLAG_FILES_ONLY) -+ state = STATE_ERROR; -+ flags |= FLAG_DIRS_ONLY; -+ break; -+ case 'F': -+ if (flags & FLAG_DIRS_ONLY) -+ state = STATE_ERROR; -+ flags |= FLAG_FILES_ONLY; -+ break; -+ case 'u': -+ where |= 0100; -+ topbits |= 04000; -+ break; -+ case 'g': -+ where |= 0010; -+ topbits |= 02000; -+ break; -+ case 'o': -+ where |= 0001; -+ break; -+ case 'a': -+ where |= 0111; -+ break; -+ case '+': -+ op = CHMOD_ADD; -+ state = STATE_2ND_HALF; -+ break; -+ case '-': -+ op = CHMOD_SUB; -+ state = STATE_2ND_HALF; -+ break; -+ case '=': -+ op = CHMOD_EQ; -+ state = STATE_2ND_HALF; -+ break; -+ default: -+ state = STATE_ERROR; -+ break; -+ } -+ } else { -+ switch (*modestr) { -+ case 'r': -+ what |= 4; -+ break; -+ case 'w': -+ what |= 2; -+ break; -+ case 'X': -+ flags |= FLAG_X_KEEP; -+ /* FALL THROUGH */ -+ case 'x': -+ what |= 1; -+ break; -+ case 's': -+ if (topbits) -+ topoct |= topbits; -+ else -+ topoct = 04000; -+ break; -+ case 't': -+ topoct |= 01000; -+ break; -+ default: -+ state = STATE_ERROR; -+ break; -+ } -+ } -+ modestr++; -+ } -+ -+ if (state == STATE_ERROR) { -+ free_chmod_mode(first_mode); -+ first_mode = NULL; -+ } -+ return first_mode; -+} -+ -+ -+/* Takes an existing file permission and a list of AND/OR changes, and -+ * create a new permissions. */ -+int tweak_mode(int mode, struct chmod_mode_struct *chmod_modes) -+{ -+ int IsX = mode & 0111; -+ int NonPerm = mode & ~07777; -+ -+ for ( ; chmod_modes; chmod_modes = chmod_modes->next) { -+ if ((chmod_modes->flags & FLAG_DIRS_ONLY) && !S_ISDIR(NonPerm)) -+ continue; -+ if ((chmod_modes->flags & FLAG_FILES_ONLY) && S_ISDIR(NonPerm)) -+ continue; -+ mode &= chmod_modes->ModeAND; -+ if ((chmod_modes->flags & FLAG_X_KEEP) && !IsX && !S_ISDIR(NonPerm)) -+ mode |= chmod_modes->ModeOR & ~0111; -+ else -+ mode |= chmod_modes->ModeOR; -+ } -+ -+ return mode | NonPerm; -+} -+ -+/* Free the linked list created by parse_chmod. */ -+int free_chmod_mode(struct chmod_mode_struct *chmod_modes) -+{ -+ struct chmod_mode_struct *next; -+ -+ while (chmod_modes) { -+ next = chmod_modes->next; -+ free(chmod_modes); -+ chmod_modes = next; -+ } -+ return 0; -+} ---- orig/flist.c 2005-08-17 06:45:07 -+++ flist.c 2004-09-18 01:51:11 -@@ -62,6 +62,8 @@ extern struct file_list *the_file_list; - - extern char curr_dir[MAXPATHLEN]; - -+extern struct chmod_mode_struct *chmod_modes; -+ - extern struct filter_list_struct filter_list; - extern struct filter_list_struct server_filter_list; - -@@ -883,7 +885,10 @@ skip_filters: - file->flags = flags; - file->modtime = st.st_mtime; - file->length = st.st_size; -- file->mode = st.st_mode; -+ if (chmod_modes && am_sender && (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) -+ file->mode = tweak_mode(st.st_mode, chmod_modes); -+ else -+ file->mode = st.st_mode; - file->uid = st.st_uid; - file->gid = st.st_gid; - ---- orig/options.c 2005-08-27 21:11:26 -+++ options.c 2005-08-27 21:18:52 -@@ -141,6 +141,7 @@ char *log_format = NULL; - char *password_file = NULL; - char *rsync_path = RSYNC_PATH; - char *backup_dir = NULL; -+char *chmod_mode = NULL; - char backup_dir_buf[MAXPATHLEN]; - int rsync_port = 0; - int compare_dest = 0; -@@ -160,6 +161,8 @@ int list_only = 0; - #define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */ - char *batch_name = NULL; - -+struct chmod_mode_struct *chmod_modes = NULL; -+ - static int daemon_opt; /* sets am_daemon after option error-reporting */ - static int F_option_cnt = 0; - static int modify_window_set; -@@ -289,6 +292,7 @@ void usage(enum logcode F) - rprintf(F," -D, --devices preserve devices (root only)\n"); - rprintf(F," -t, --times preserve times\n"); - rprintf(F," -O, --omit-dir-times omit directories when preserving times\n"); -+ rprintf(F," --chmod=CHMOD change destination permissions\n"); - rprintf(F," -S, --sparse handle sparse files efficiently\n"); - rprintf(F," -n, --dry-run show what would have been transferred\n"); - rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n"); -@@ -411,6 +415,7 @@ static struct poptOption long_options[] - {"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 }, - {"no-R", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 }, - {"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 }, -+ {"chmod", 0, POPT_ARG_STRING, &chmod_mode, 0, 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, &one_file_system, 0, 0, 0 }, -@@ -1122,6 +1127,13 @@ int parse_arguments(int *argc, const cha - if (make_backups && !backup_dir) - omit_dir_times = 1; - -+ if (chmod_mode && !(chmod_modes = parse_chmod(chmod_mode))) { -+ snprintf(err_buf, sizeof err_buf, -+ "Invalid argument passed to chmod\n"); -+ rprintf(FERROR, "ERROR: %s", err_buf); -+ return 0; -+ } -+ - if (log_format) { - if (log_format_has(log_format, 'i')) - log_format_has_i = 1; -@@ -1507,6 +1519,11 @@ void server_options(char **args,int *arg - } - } - -+ if (chmod_mode && !am_sender) { -+ args[ac++] = "--chmod"; -+ args[ac++] = chmod_mode; -+ } -+ - if (files_from && (!am_sender || filesfrom_host)) { - if (filesfrom_host) { - args[ac++] = "--files-from"; ---- orig/rsync.yo 2005-08-27 21:05:12 -+++ rsync.yo 2005-01-24 01:48:43 -@@ -323,6 +323,7 @@ to the detailed description below for a - -D, --devices preserve devices (root only) - -t, --times preserve times - -O, --omit-dir-times omit directories when preserving times -+ --chmod=CHMOD change destination permissions - -S, --sparse handle sparse files efficiently - -n, --dry-run show what would have been transferred - -W, --whole-file copy files whole (without rsync algorithm) -@@ -695,6 +696,14 @@ it is preserving modification times (see - the directories on the receiving side, it is a good idea to use bf(-O). - This option is inferred if you use bf(--backup) without bf(--backup-dir). - -+dit(bf(--chmod)) This options tells rsync to apply the listed "chmod" pattern -+to the permission of the files on the destination. In addition to the normal -+parsing rules specified in the chmod manpage, you can specify an item that -+should only apply to a directory by prefixing it with a 'D', or specify an -+item that should only apply to a file by prefixing it with a 'F'. For example: -+ -+quote(--chmod=Dg+s,ug+w,Fo-w,+X) -+ - dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers, - instead it will just report the actions it would have taken. - ---- orig/testsuite/chmod-option.test 2005-07-09 15:49:59 -+++ testsuite/chmod-option.test 2005-07-09 15:49:59 -@@ -0,0 +1,44 @@ -+#! /bin/sh -+ -+# Copyright (C) 2002 by Martin Pool -+ -+# This program is distributable under the terms of the GNU GPL (see -+# COPYING). -+ -+# Test that the --chmod option functions correctly. -+ -+. $srcdir/testsuite/rsync.fns -+ -+set -x -+ -+# Build some files -+ -+fromdir="$scratchdir/from" -+todir="$scratchdir/to" -+checkdir="$scratchdir/check" -+ -+mkdir "$fromdir" -+name1="$fromdir/name1" -+name2="$fromdir/name2" -+dir1="$fromdir/dir1" -+dir2="$fromdir/dir2" -+echo "This is the file" > "$name1" -+echo "This is the other file" > "$name2" -+mkdir "$dir1" "$dir2" -+ -+chmod 4700 "$name1" || test_skipped "Can't chmod" -+chmod 700 "$dir1" -+chmod 770 "$dir2" -+ -+# Copy the files we've created over to another directory -+checkit "$RSYNC -avv \"$fromdir/\" \"$checkdir/\"" "$fromdir" "$checkdir" -+ -+# And then manually make the changes which should occur -+umask 002 -+chmod ug-s,a+rX "$checkdir"/* -+chmod +w "$checkdir" "$checkdir"/dir* -+ -+checkit "$RSYNC -avv --chmod ug-s,a+rX,D+w \"$fromdir/\" \"$todir/\"" "$checkdir" "$todir" -+ -+# The script would have aborted on error, so getting here means we've won. -+exit 0 -- 2.34.1