]>
git.ipfire.org Git - thirdparty/rsync.git/blob - chmod.c
5 #define FLAG_X_KEEP (1<<0)
6 #define FLAG_DIRS_ONLY (1<<1)
7 #define FLAG_FILES_ONLY (1<<2)
9 struct chmod_mode_struct
{
10 struct chmod_mode_struct
*next
;
20 #define STATE_1ST_HALF 1
21 #define STATE_2ND_HALF 2
23 /* Parse a chmod-style argument, and break it down into one or more AND/OR
24 * pairs in a linked list. We use a state machine to walk through the
26 struct chmod_mode_struct
*parse_chmod(char *modestr
)
28 int state
= STATE_1ST_HALF
;
29 int where
= 0, what
= 0, op
= 0, topbits
= 0, topoct
= 0, flags
= 0;
30 struct chmod_mode_struct
*first_mode
= NULL
, *curr_mode
= NULL
,
33 while (state
!= STATE_ERROR
) {
34 if (!*modestr
|| *modestr
== ',') {
41 prev_mode
= curr_mode
;
42 curr_mode
= new_array(struct chmod_mode_struct
, 1);
44 prev_mode
->next
= curr_mode
;
46 first_mode
= curr_mode
;
47 curr_mode
->next
= NULL
;
53 bits
= (where
* what
) & ~orig_umask
;
58 curr_mode
->ModeAND
= 07777;
59 curr_mode
->ModeOR
= bits
+ topoct
;
62 curr_mode
->ModeAND
= 07777 - bits
- topoct
;
63 curr_mode
->ModeOR
= 0;
66 curr_mode
->ModeAND
= 07777 - (where
* 7) - (topoct
? topbits
: 0);
67 curr_mode
->ModeOR
= bits
+ topoct
;
71 curr_mode
->flags
= flags
;
77 state
= STATE_1ST_HALF
;
78 where
= what
= op
= topoct
= topbits
= flags
= 0;
81 if (state
!= STATE_2ND_HALF
) {
84 if (flags
& FLAG_FILES_ONLY
)
86 flags
|= FLAG_DIRS_ONLY
;
89 if (flags
& FLAG_DIRS_ONLY
)
91 flags
|= FLAG_FILES_ONLY
;
109 state
= STATE_2ND_HALF
;
113 state
= STATE_2ND_HALF
;
117 state
= STATE_2ND_HALF
;
132 flags
|= FLAG_X_KEEP
;
154 if (state
== STATE_ERROR
) {
155 free_chmod_mode(first_mode
);
162 /* Takes an existing file permission and a list of AND/OR changes, and
163 * create a new permissions. */
164 int tweak_mode(int mode
, struct chmod_mode_struct
*chmod_modes
)
166 int IsX
= mode
& 0111;
167 int NonPerm
= mode
& ~07777;
169 for ( ; chmod_modes
; chmod_modes
= chmod_modes
->next
) {
170 if ((chmod_modes
->flags
& FLAG_DIRS_ONLY
) && !S_ISDIR(NonPerm
))
172 if ((chmod_modes
->flags
& FLAG_FILES_ONLY
) && S_ISDIR(NonPerm
))
174 mode
&= chmod_modes
->ModeAND
;
175 if ((chmod_modes
->flags
& FLAG_X_KEEP
) && !IsX
&& !S_ISDIR(NonPerm
))
176 mode
|= chmod_modes
->ModeOR
& ~0111;
178 mode
|= chmod_modes
->ModeOR
;
181 return mode
| NonPerm
;
184 /* Free the linked list created by parse_chmod. */
185 int free_chmod_mode(struct chmod_mode_struct
*chmod_modes
)
187 struct chmod_mode_struct
*next
;
189 while (chmod_modes
) {
190 next
= chmod_modes
->next
;