From aef2b8ce4124db39f715d38c7ade329005645e0d Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Thu, 16 Dec 2010 21:38:23 -0800 Subject: [PATCH] Enhance --chmod to allow octal values. --- chmod.c | 30 +++++++++++++++++++++++++++--- rsync.yo | 11 +++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/chmod.c b/chmod.c index 3d0d05df..74e3ad79 100644 --- a/chmod.c +++ b/chmod.c @@ -19,6 +19,7 @@ */ #include "rsync.h" +#include "itypes.h" extern mode_t orig_umask; @@ -35,10 +36,12 @@ struct chmod_mode_struct { #define CHMOD_ADD 1 #define CHMOD_SUB 2 #define CHMOD_EQ 3 +#define CHMOD_SET 4 #define STATE_ERROR 0 #define STATE_1ST_HALF 1 #define STATE_2ND_HALF 2 +#define STATE_OCTAL_NUM 3 /* Parse a chmod-style argument, and break it down into one or more AND/OR * pairs in a linked list. We return a pointer to new items on succcess @@ -87,6 +90,10 @@ struct chmod_mode_struct *parse_chmod(const char *modestr, curr_mode->ModeAND = CHMOD_BITS - (where * 7) - (topoct ? topbits : 0); curr_mode->ModeOR = bits + topoct; break; + case CHMOD_SET: + curr_mode->ModeAND = 0; + curr_mode->ModeOR = bits; + break; } curr_mode->flags = flags; @@ -99,7 +106,8 @@ struct chmod_mode_struct *parse_chmod(const char *modestr, where = what = op = topoct = topbits = flags = 0; } - if (state != STATE_2ND_HALF) { + switch (state) { + case STATE_1ST_HALF: switch (*modestr) { case 'D': if (flags & FLAG_FILES_ONLY) @@ -138,10 +146,17 @@ struct chmod_mode_struct *parse_chmod(const char *modestr, state = STATE_2ND_HALF; break; default: - state = STATE_ERROR; + if (isDigit(modestr) && *modestr < '8' && !where) { + op = CHMOD_SET; + state = STATE_OCTAL_NUM; + where = 1; + what = *modestr - '0'; + } else + state = STATE_ERROR; break; } - } else { + break; + case STATE_2ND_HALF: switch (*modestr) { case 'r': what |= 4; @@ -168,6 +183,15 @@ struct chmod_mode_struct *parse_chmod(const char *modestr, state = STATE_ERROR; break; } + break; + case STATE_OCTAL_NUM: + if (isDigit(modestr) && *modestr < '8') { + what = what*8 + *modestr - '0'; + if (what > CHMOD_BITS) + state = STATE_ERROR; + } else + state = STATE_ERROR; + break; } modestr++; } diff --git a/rsync.yo b/rsync.yo index 5f5365aa..0ad14f39 100644 --- a/rsync.yo +++ b/rsync.yo @@ -1051,7 +1051,7 @@ used by bf(--fake-super)) unless you repeat the option (e.g. -XX). This "copy all xattrs" mode cannot be used with bf(--fake-super). dit(bf(--chmod)) This option tells rsync to apply one or more -comma-separated "chmod" strings to the permission of the files in the +comma-separated "chmod" modes to the permission of the files in the transfer. The resulting value is treated as though it were the permissions that the sending side supplied for the file, which means that this option can seem to have no effect on existing files if bf(--perms) is not enabled. @@ -1059,10 +1059,17 @@ can seem to have no effect on existing files if bf(--perms) is not enabled. In addition to the normal parsing rules specified in the bf(chmod)(1) 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: +file by prefixing it with a 'F'. For example, the following will ensure +that all directories get marked set-gid, that no files are other-writable, +that both are user-writable and group-writable, and that both have +consistent executability across all bits: quote(--chmod=Dg+s,ug+w,Fo-w,+X) +Using octal mode numbers is also allowed: + +quote(--chmod=D2775,F664) + It is also legal to specify multiple bf(--chmod) options, as each additional option is just appended to the list of changes to make. -- 2.34.1