Mercurial > hg > octave-shane > gnulib-hg
annotate lib/modechange.c @ 17632:86af85d364e1 default tip
unistd: port readlink to Mac OS X 10.3.9
* lib/unistd.in.h (_GL_INCLUDING_UNISTD_H): New macro, to work
around self-include problem in Mac OS X 10.3.9 when combined with
readlink module. Problem reported by Klaus Zietler in
<http://bugs.gnu.org/16825>.
author | Paul Eggert <eggert@penguin.cs.ucla.edu> |
---|---|
date | Tue, 25 Feb 2014 11:16:27 -0800 |
parents | 344018b6e5d7 |
children |
rev | line source |
---|---|
5 | 1 /* modechange.c -- file mode manipulation |
4360 | 2 |
17587 | 3 Copyright (C) 1989-1990, 1997-1999, 2001, 2003-2006, 2009-2014 Free Software |
12518
b5e42ef33b49
update nearly all FSF copyright year lists to include 2009
Jim Meyering <meyering@redhat.com>
parents:
12421
diff
changeset
|
4 Foundation, Inc. |
5 | 5 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
6 This program is free software: you can redistribute it and/or modify |
5 | 7 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
8 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
9 (at your option) any later version. |
5 | 10 |
11 This program is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
5 | 18 |
19 /* Written by David MacKenzie <djm@ai.mit.edu> */ | |
20 | |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
21 /* The ASCII mode string is compiled into an array of 'struct |
5 | 22 modechange', which can then be applied to each file to be changed. |
23 We do this instead of re-parsing the ASCII string for each file | |
24 because the compiled form requires less computation to use; when | |
25 changing the mode of many files, this probably results in a | |
5813 | 26 performance gain. */ |
5 | 27 |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
7056
diff
changeset
|
28 #include <config.h> |
229 | 29 |
1818
b2644b45e17f
(make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents:
1769
diff
changeset
|
30 #include "modechange.h" |
5 | 31 #include <sys/stat.h> |
5813 | 32 #include "stat-macros.h" |
33 #include "xalloc.h" | |
4666 | 34 #include <stdlib.h> |
5 | 35 |
3081
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
36 /* The traditional octal values corresponding to each mode bit. */ |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
37 #define SUID 04000 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
38 #define SGID 02000 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
39 #define SVTX 01000 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
40 #define RUSR 00400 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
41 #define WUSR 00200 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
42 #define XUSR 00100 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
43 #define RGRP 00040 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
44 #define WGRP 00020 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
45 #define XGRP 00010 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
46 #define ROTH 00004 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
47 #define WOTH 00002 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
48 #define XOTH 00001 |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
49 #define ALLM 07777 /* all octal mode bits */ |
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
50 |
6969 | 51 /* Convert OCTAL, which uses one of the traditional octal values, to |
52 an internal mode_t value. */ | |
53 static mode_t | |
54 octal_to_mode (unsigned int octal) | |
55 { | |
56 /* Help the compiler optimize the usual case where mode_t uses | |
57 the traditional octal representation. */ | |
58 return ((S_ISUID == SUID && S_ISGID == SGID && S_ISVTX == SVTX | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
59 && S_IRUSR == RUSR && S_IWUSR == WUSR && S_IXUSR == XUSR |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
60 && S_IRGRP == RGRP && S_IWGRP == WGRP && S_IXGRP == XGRP |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
61 && S_IROTH == ROTH && S_IWOTH == WOTH && S_IXOTH == XOTH) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
62 ? octal |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
63 : (mode_t) ((octal & SUID ? S_ISUID : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
64 | (octal & SGID ? S_ISGID : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
65 | (octal & SVTX ? S_ISVTX : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
66 | (octal & RUSR ? S_IRUSR : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
67 | (octal & WUSR ? S_IWUSR : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
68 | (octal & XUSR ? S_IXUSR : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
69 | (octal & RGRP ? S_IRGRP : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
70 | (octal & WGRP ? S_IWGRP : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
71 | (octal & XGRP ? S_IXGRP : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
72 | (octal & ROTH ? S_IROTH : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
73 | (octal & WOTH ? S_IWOTH : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
74 | (octal & XOTH ? S_IXOTH : 0))); |
6969 | 75 } |
76 | |
5813 | 77 /* Special operations flags. */ |
78 enum | |
79 { | |
80 /* For the sentinel at the end of the mode changes array. */ | |
81 MODE_DONE, | |
82 | |
83 /* The typical case. */ | |
84 MODE_ORDINARY_CHANGE, | |
85 | |
86 /* In addition to the typical case, affect the execute bits if at | |
87 least one execute bit is set already, or if the file is a | |
88 directory. */ | |
89 MODE_X_IF_ANY_X, | |
1818
b2644b45e17f
(make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents:
1769
diff
changeset
|
90 |
5813 | 91 /* Instead of the typical case, copy some existing permissions for |
92 u, g, or o onto the other two. Which of u, g, or o is copied | |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
93 is determined by which bits are set in the 'value' field. */ |
5813 | 94 MODE_COPY_EXISTING |
95 }; | |
1818
b2644b45e17f
(make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents:
1769
diff
changeset
|
96 |
5813 | 97 /* Description of a mode change. */ |
98 struct mode_change | |
99 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
100 char op; /* One of "=+-". */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
101 char flag; /* Special operations flag. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
102 mode_t affected; /* Set for u, g, o, or a. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
103 mode_t value; /* Bits to add/remove. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
104 mode_t mentioned; /* Bits explicitly mentioned. */ |
5813 | 105 }; |
5 | 106 |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
107 /* Return a mode_change array with the specified "=ddd"-style |
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
108 mode change operation, where NEW_MODE is "ddd" and MENTIONED |
6969 | 109 contains the bits explicitly mentioned in the mode are MENTIONED. */ |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
110 |
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
111 static struct mode_change * |
6969 | 112 make_node_op_equals (mode_t new_mode, mode_t mentioned) |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
113 { |
5813 | 114 struct mode_change *p = xmalloc (2 * sizeof *p); |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
115 p->op = '='; |
5813 | 116 p->flag = MODE_ORDINARY_CHANGE; |
117 p->affected = CHMOD_MODE_BITS; | |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
118 p->value = new_mode; |
6969 | 119 p->mentioned = mentioned; |
5813 | 120 p[1].flag = MODE_DONE; |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
121 return p; |
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
122 } |
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
123 |
5813 | 124 /* Return a pointer to an array of file mode change operations created from |
5 | 125 MODE_STRING, an ASCII string that contains either an octal number |
126 specifying an absolute mode, or symbolic mode change operations with | |
127 the form: | |
128 [ugoa...][[+-=][rwxXstugo...]...][,...] | |
129 | |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
130 Return NULL if 'mode_string' does not contain a valid |
5813 | 131 representation of file mode change operations. */ |
5 | 132 |
133 struct mode_change * | |
5813 | 134 mode_compile (char const *mode_string) |
5 | 135 { |
5813 | 136 /* The array of mode-change directives to be returned. */ |
137 struct mode_change *mc; | |
138 size_t used = 0; | |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
139 char const *p; |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
140 |
5813 | 141 if ('0' <= *mode_string && *mode_string < '8') |
142 { | |
6969 | 143 unsigned int octal_mode = 0; |
7056
db9b9e26e735
* modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents:
6969
diff
changeset
|
144 mode_t mode; |
db9b9e26e735
* modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents:
6969
diff
changeset
|
145 mode_t mentioned; |
5 | 146 |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
147 p = mode_string; |
5813 | 148 do |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
149 { |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
150 octal_mode = 8 * octal_mode + *p++ - '0'; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
151 if (ALLM < octal_mode) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
152 return NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
153 } |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
154 while ('0' <= *p && *p < '8'); |
3081
b7402f1afb7b
Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents:
2950
diff
changeset
|
155 |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
156 if (*p) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
157 return NULL; |
6527 | 158 |
7056
db9b9e26e735
* modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents:
6969
diff
changeset
|
159 mode = octal_to_mode (octal_mode); |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
160 mentioned = (p - mode_string < 5 |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
161 ? (mode & (S_ISUID | S_ISGID)) | S_ISVTX | S_IRWXUGO |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
162 : CHMOD_MODE_BITS); |
7056
db9b9e26e735
* modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents:
6969
diff
changeset
|
163 return make_node_op_equals (mode, mentioned); |
5 | 164 } |
165 | |
5813 | 166 /* Allocate enough space to hold the result. */ |
167 { | |
168 size_t needed = 1; | |
169 for (p = mode_string; *p; p++) | |
170 needed += (*p == '=' || *p == '+' || *p == '-'); | |
171 mc = xnmalloc (needed, sizeof *mc); | |
172 } | |
5 | 173 |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
174 /* One loop iteration for each |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
175 '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=][0-7]+'. */ |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
176 for (p = mode_string; ; p++) |
5 | 177 { |
5813 | 178 /* Which bits in the mode are operated on. */ |
179 mode_t affected = 0; | |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
180 |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
181 /* Turn on all the bits in 'affected' for each group given. */ |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
182 for (;; p++) |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
183 switch (*p) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
184 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
185 default: |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
186 goto invalid; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
187 case 'u': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
188 affected |= S_ISUID | S_IRWXU; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
189 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
190 case 'g': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
191 affected |= S_ISGID | S_IRWXG; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
192 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
193 case 'o': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
194 affected |= S_ISVTX | S_IRWXO; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
195 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
196 case 'a': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
197 affected |= CHMOD_MODE_BITS; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
198 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
199 case '=': case '+': case '-': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
200 goto no_more_affected; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
201 } |
5813 | 202 no_more_affected:; |
5 | 203 |
5813 | 204 do |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
205 { |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
206 char op = *p++; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
207 mode_t value; |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
208 mode_t mentioned = 0; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
209 char flag = MODE_COPY_EXISTING; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
210 struct mode_change *change; |
5 | 211 |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
212 switch (*p) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
213 { |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
214 case '0': case '1': case '2': case '3': |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
215 case '4': case '5': case '6': case '7': |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
216 { |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
217 unsigned int octal_mode = 0; |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
218 |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
219 do |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
220 { |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
221 octal_mode = 8 * octal_mode + *p++ - '0'; |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
222 if (ALLM < octal_mode) |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
223 return NULL; |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
224 } |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
225 while ('0' <= *p && *p < '8'); |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
226 |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
227 if (affected || (*p && *p != ',')) |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
228 return NULL; |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
229 affected = mentioned = CHMOD_MODE_BITS; |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
230 value = octal_to_mode (octal_mode); |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
231 flag = MODE_ORDINARY_CHANGE; |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
232 break; |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
233 } |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
234 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
235 case 'u': |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
236 /* Set the affected bits to the value of the "u" bits |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
237 on the same file. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
238 value = S_IRWXU; |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
239 p++; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
240 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
241 case 'g': |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
242 /* Set the affected bits to the value of the "g" bits |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
243 on the same file. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
244 value = S_IRWXG; |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
245 p++; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
246 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
247 case 'o': |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
248 /* Set the affected bits to the value of the "o" bits |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
249 on the same file. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
250 value = S_IRWXO; |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
251 p++; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
252 break; |
5 | 253 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
254 default: |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
255 value = 0; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
256 flag = MODE_ORDINARY_CHANGE; |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
257 |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
258 for (;; p++) |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
259 switch (*p) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
260 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
261 case 'r': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
262 value |= S_IRUSR | S_IRGRP | S_IROTH; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
263 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
264 case 'w': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
265 value |= S_IWUSR | S_IWGRP | S_IWOTH; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
266 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
267 case 'x': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
268 value |= S_IXUSR | S_IXGRP | S_IXOTH; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
269 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
270 case 'X': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
271 flag = MODE_X_IF_ANY_X; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
272 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
273 case 's': |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
274 /* Set the setuid/gid bits if 'u' or 'g' is selected. */ |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
275 value |= S_ISUID | S_ISGID; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
276 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
277 case 't': |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
278 /* Set the "save text image" bit if 'o' is selected. */ |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
279 value |= S_ISVTX; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
280 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
281 default: |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
282 goto no_more_values; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
283 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
284 no_more_values:; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
285 } |
1769
bc0ac225f0a8
(make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents:
1760
diff
changeset
|
286 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
287 change = &mc[used++]; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
288 change->op = op; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
289 change->flag = flag; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
290 change->affected = affected; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
291 change->value = value; |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
292 change->mentioned = |
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
293 (mentioned ? mentioned : affected ? affected & value : value); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
294 } |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
295 while (*p == '=' || *p == '+' || *p == '-'); |
5304
707482f5c106
(mode_compile): Don't decrement a pointer that
Paul Eggert <eggert@cs.ucla.edu>
parents:
5159
diff
changeset
|
296 |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
297 if (*p != ',') |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
298 break; |
5304
707482f5c106
(mode_compile): Don't decrement a pointer that
Paul Eggert <eggert@cs.ucla.edu>
parents:
5159
diff
changeset
|
299 } |
707482f5c106
(mode_compile): Don't decrement a pointer that
Paul Eggert <eggert@cs.ucla.edu>
parents:
5159
diff
changeset
|
300 |
16629
02cc478e0dc0
modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16235
diff
changeset
|
301 if (*p == 0) |
5813 | 302 { |
303 mc[used].flag = MODE_DONE; | |
304 return mc; | |
305 } | |
306 | |
5 | 307 invalid: |
5813 | 308 free (mc); |
309 return NULL; | |
5 | 310 } |
311 | |
989
c68ed1182a64
(mode_create_from_ref): Don't use umask.
Jim Meyering <jim@meyering.net>
parents:
972
diff
changeset
|
312 /* Return a file mode change operation that sets permissions to match those |
5813 | 313 of REF_FILE. Return NULL (setting errno) if REF_FILE can't be accessed. */ |
972
b30f9ff1e92e
(mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents:
761
diff
changeset
|
314 |
b30f9ff1e92e
(mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents:
761
diff
changeset
|
315 struct mode_change * |
1494 | 316 mode_create_from_ref (const char *ref_file) |
972
b30f9ff1e92e
(mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents:
761
diff
changeset
|
317 { |
b30f9ff1e92e
(mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents:
761
diff
changeset
|
318 struct stat ref_stats; |
b30f9ff1e92e
(mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents:
761
diff
changeset
|
319 |
5813 | 320 if (stat (ref_file, &ref_stats) != 0) |
321 return NULL; | |
6969 | 322 return make_node_op_equals (ref_stats.st_mode, CHMOD_MODE_BITS); |
972
b30f9ff1e92e
(mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents:
761
diff
changeset
|
323 } |
b30f9ff1e92e
(mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents:
761
diff
changeset
|
324 |
6969 | 325 /* Return the file mode bits of OLDMODE (which is the mode of a |
326 directory if DIR), assuming the umask is UMASK_VALUE, adjusted as | |
327 indicated by the list of change operations CHANGES. If DIR, the | |
328 type 'X' change affects the returned value even if no execute bits | |
7056
db9b9e26e735
* modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents:
6969
diff
changeset
|
329 were set in OLDMODE, and set user and group ID bits are preserved |
db9b9e26e735
* modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents:
6969
diff
changeset
|
330 unless CHANGES mentioned them. If PMODE_BITS is not null, store into |
6969 | 331 *PMODE_BITS a mask denoting file mode bits that are affected by |
332 CHANGES. | |
333 | |
334 The returned value and *PMODE_BITS contain only file mode bits. | |
335 For example, they have the S_IFMT bits cleared on a standard | |
336 Unix-like host. */ | |
5 | 337 |
1818
b2644b45e17f
(make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents:
1769
diff
changeset
|
338 mode_t |
6969 | 339 mode_adjust (mode_t oldmode, bool dir, mode_t umask_value, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
340 struct mode_change const *changes, mode_t *pmode_bits) |
5 | 341 { |
5813 | 342 /* The adjusted mode. */ |
343 mode_t newmode = oldmode & CHMOD_MODE_BITS; | |
5 | 344 |
6969 | 345 /* File mode bits that CHANGES cares about. */ |
346 mode_t mode_bits = 0; | |
347 | |
5813 | 348 for (; changes->flag != MODE_DONE; changes++) |
5 | 349 { |
5813 | 350 mode_t affected = changes->affected; |
6969 | 351 mode_t omit_change = |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
352 (dir ? S_ISUID | S_ISGID : 0) & ~ changes->mentioned; |
5813 | 353 mode_t value = changes->value; |
354 | |
355 switch (changes->flag) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
356 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
357 case MODE_ORDINARY_CHANGE: |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
358 break; |
5813 | 359 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
360 case MODE_COPY_EXISTING: |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
361 /* Isolate in 'value' the bits in 'newmode' to copy. */ |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
362 value &= newmode; |
5 | 363 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
364 /* Copy the isolated bits to the other two parts. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
365 value |= ((value & (S_IRUSR | S_IRGRP | S_IROTH) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
366 ? S_IRUSR | S_IRGRP | S_IROTH : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
367 | (value & (S_IWUSR | S_IWGRP | S_IWOTH) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
368 ? S_IWUSR | S_IWGRP | S_IWOTH : 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
369 | (value & (S_IXUSR | S_IXGRP | S_IXOTH) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
370 ? S_IXUSR | S_IXGRP | S_IXOTH : 0)); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
371 break; |
5 | 372 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
373 case MODE_X_IF_ANY_X: |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
374 /* Affect the execute bits if execute bits are already set |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
375 or if the file is a directory. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
376 if ((newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) | dir) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
377 value |= S_IXUSR | S_IXGRP | S_IXOTH; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
378 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
379 } |
5813 | 380 |
381 /* If WHO was specified, limit the change to the affected bits. | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
382 Otherwise, apply the umask. Either way, omit changes as |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
383 requested. */ |
6969 | 384 value &= (affected ? affected : ~umask_value) & ~ omit_change; |
5 | 385 |
386 switch (changes->op) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
387 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
388 case '=': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
389 /* If WHO was specified, preserve the previous values of |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
390 bits that are not affected by this change operation. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
391 Otherwise, clear all the bits. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
392 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
393 mode_t preserved = (affected ? ~affected : 0) | omit_change; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
394 mode_bits |= CHMOD_MODE_BITS & ~preserved; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
395 newmode = (newmode & preserved) | value; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
396 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
397 } |
6969 | 398 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
399 case '+': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
400 mode_bits |= value; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
401 newmode |= value; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
402 break; |
5813 | 403 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
404 case '-': |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
405 mode_bits |= value; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
406 newmode &= ~value; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
407 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
408 } |
5 | 409 } |
5813 | 410 |
6969 | 411 if (pmode_bits) |
412 *pmode_bits = mode_bits; | |
5 | 413 return newmode; |
414 } |