]>
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 return a pointer to new items on succcess
25 * (appending the items to the specified list), or NULL on error. */
26 struct chmod_mode_struct
*parse_chmod(const char *modestr
,
27 struct chmod_mode_struct
**root_mode_ptr
)
29 int state
= STATE_1ST_HALF
;
30 int where
= 0, what
= 0, op
= 0, topbits
= 0, topoct
= 0, flags
= 0;
31 struct chmod_mode_struct
*first_mode
= NULL
, *curr_mode
= NULL
,
34 while (state
!= STATE_ERROR
) {
35 if (!*modestr
|| *modestr
== ',') {
42 prev_mode
= curr_mode
;
43 curr_mode
= new_array(struct chmod_mode_struct
, 1);
45 prev_mode
->next
= curr_mode
;
47 first_mode
= curr_mode
;
48 curr_mode
->next
= NULL
;
54 bits
= (where
* what
) & ~orig_umask
;
59 curr_mode
->ModeAND
= 07777;
60 curr_mode
->ModeOR
= bits
+ topoct
;
63 curr_mode
->ModeAND
= 07777 - bits
- topoct
;
64 curr_mode
->ModeOR
= 0;
67 curr_mode
->ModeAND
= 07777 - (where
* 7) - (topoct
? topbits
: 0);
68 curr_mode
->ModeOR
= bits
+ topoct
;
72 curr_mode
->flags
= flags
;
78 state
= STATE_1ST_HALF
;
79 where
= what
= op
= topoct
= topbits
= flags
= 0;
82 if (state
!= STATE_2ND_HALF
) {
85 if (flags
& FLAG_FILES_ONLY
)
87 flags
|= FLAG_DIRS_ONLY
;
90 if (flags
& FLAG_DIRS_ONLY
)
92 flags
|= FLAG_FILES_ONLY
;
110 state
= STATE_2ND_HALF
;
114 state
= STATE_2ND_HALF
;
118 state
= STATE_2ND_HALF
;
133 flags
|= FLAG_X_KEEP
;
155 if (state
== STATE_ERROR
) {
156 free_chmod_mode(first_mode
);
160 if (!(curr_mode
= *root_mode_ptr
))
161 *root_mode_ptr
= first_mode
;
163 while (curr_mode
->next
)
164 curr_mode
= curr_mode
->next
;
165 curr_mode
->next
= first_mode
;
172 /* Takes an existing file permission and a list of AND/OR changes, and
173 * create a new permissions. */
174 int tweak_mode(int mode
, struct chmod_mode_struct
*chmod_modes
)
176 int IsX
= mode
& 0111;
177 int NonPerm
= mode
& ~07777;
179 for ( ; chmod_modes
; chmod_modes
= chmod_modes
->next
) {
180 if ((chmod_modes
->flags
& FLAG_DIRS_ONLY
) && !S_ISDIR(NonPerm
))
182 if ((chmod_modes
->flags
& FLAG_FILES_ONLY
) && S_ISDIR(NonPerm
))
184 mode
&= chmod_modes
->ModeAND
;
185 if ((chmod_modes
->flags
& FLAG_X_KEEP
) && !IsX
&& !S_ISDIR(NonPerm
))
186 mode
|= chmod_modes
->ModeOR
& ~0111;
188 mode
|= chmod_modes
->ModeOR
;
191 return mode
| NonPerm
;
194 /* Free the linked list created by parse_chmod. */
195 int free_chmod_mode(struct chmod_mode_struct
*chmod_modes
)
197 struct chmod_mode_struct
*next
;
199 while (chmod_modes
) {
200 next
= chmod_modes
->next
;