annotate libgfortran/intrinsics/chmod.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Implementation of the CHMOD intrinsic.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of the GNU Fortran runtime library (libgfortran).
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 Libgfortran is free software; you can redistribute it and/or
kono
parents:
diff changeset
8 modify it under the terms of the GNU General Public
kono
parents:
diff changeset
9 License as published by the Free Software Foundation; either
kono
parents:
diff changeset
10 version 3 of the License, or (at your option) any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 Libgfortran is distributed in the hope that it will be useful,
kono
parents:
diff changeset
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
15 GNU General Public License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
18 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
19 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
22 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
24 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 #include "libgfortran.h"
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 #if defined(HAVE_SYS_STAT_H)
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 #include <sys/stat.h> /* For stat, chmod and umask. */
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 /* INTEGER FUNCTION CHMOD (NAME, MODE)
kono
parents:
diff changeset
34 CHARACTER(len=*), INTENT(IN) :: NAME, MODE
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 Sets the file permission "chmod" using a mode string.
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 For MinGW, only _S_IWRITE and _S_IREAD are supported. To set those,
kono
parents:
diff changeset
39 only the user attributes are used.
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 The mode string allows for the same arguments as POSIX's chmod utility.
kono
parents:
diff changeset
42 a) string containing an octal number.
kono
parents:
diff changeset
43 b) Comma separated list of clauses of the form:
kono
parents:
diff changeset
44 [<who-list>]<op>[<perm-list>|<permcopy>][<op>[<perm-list>|<permcopy>],...]
kono
parents:
diff changeset
45 <who> - 'u', 'g', 'o', 'a'
kono
parents:
diff changeset
46 <op> - '+', '-', '='
kono
parents:
diff changeset
47 <perm> - 'r', 'w', 'x', 'X', 's', t'
kono
parents:
diff changeset
48 If <op> is not followed by a perm-list or permcopy, '-' and '+' do not
kono
parents:
diff changeset
49 change the mode while '=' clears all file mode bits. 'u' stands for the
kono
parents:
diff changeset
50 user permissions, 'g' for the group and 'o' for the permissions for others.
kono
parents:
diff changeset
51 'a' is equivalent to 'ugo'. '+' sets the given permission in addition to
kono
parents:
diff changeset
52 the ones of the file, '-' unsets the given permissions of the file, while
kono
parents:
diff changeset
53 '=' sets the file to that mode. 'r' sets the read, 'w' the write, and
kono
parents:
diff changeset
54 'x' the execute mode. 'X' sets the execute bit if the file is a directory
kono
parents:
diff changeset
55 or if the user, group or other executable bit is set. 't' sets the sticky
kono
parents:
diff changeset
56 bit, 's' (un)sets the and/or S_ISUID/S_ISGID bit.
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 Note that if <who> is omitted, the permissions are filtered by the umask.
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 A return value of 0 indicates success, -1 an error of chmod() while 1
kono
parents:
diff changeset
61 indicates a mode parsing error. */
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 static int
kono
parents:
diff changeset
65 chmod_internal (char *file, char *mode, gfc_charlen_type mode_len)
kono
parents:
diff changeset
66 {
kono
parents:
diff changeset
67 bool ugo[3];
kono
parents:
diff changeset
68 bool rwxXstugo[9];
kono
parents:
diff changeset
69 int set_mode, part;
kono
parents:
diff changeset
70 bool honor_umask, continue_clause = false;
kono
parents:
diff changeset
71 #ifndef __MINGW32__
kono
parents:
diff changeset
72 bool is_dir;
kono
parents:
diff changeset
73 #endif
kono
parents:
diff changeset
74 mode_t mode_mask, file_mode, new_mode;
kono
parents:
diff changeset
75 struct stat stat_buf;
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 if (mode_len == 0)
kono
parents:
diff changeset
78 return 1;
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 if (mode[0] >= '0' && mode[0] <= '9')
kono
parents:
diff changeset
81 {
kono
parents:
diff changeset
82 unsigned fmode;
kono
parents:
diff changeset
83 if (sscanf (mode, "%o", &fmode) != 1)
kono
parents:
diff changeset
84 return 1;
kono
parents:
diff changeset
85 return chmod (file, (mode_t) fmode);
kono
parents:
diff changeset
86 }
kono
parents:
diff changeset
87
kono
parents:
diff changeset
88 /* Read the current file mode. */
kono
parents:
diff changeset
89 if (stat (file, &stat_buf))
kono
parents:
diff changeset
90 return 1;
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 file_mode = stat_buf.st_mode & ~S_IFMT;
kono
parents:
diff changeset
93 #ifndef __MINGW32__
kono
parents:
diff changeset
94 is_dir = stat_buf.st_mode & S_IFDIR;
kono
parents:
diff changeset
95 #endif
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 #ifdef HAVE_UMASK
kono
parents:
diff changeset
98 /* Obtain the umask without distroying the setting. */
kono
parents:
diff changeset
99 mode_mask = 0;
kono
parents:
diff changeset
100 mode_mask = umask (mode_mask);
kono
parents:
diff changeset
101 (void) umask (mode_mask);
kono
parents:
diff changeset
102 #else
kono
parents:
diff changeset
103 honor_umask = false;
kono
parents:
diff changeset
104 #endif
kono
parents:
diff changeset
105
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
106 for (gfc_charlen_type i = 0; i < mode_len; i++)
111
kono
parents:
diff changeset
107 {
kono
parents:
diff changeset
108 if (!continue_clause)
kono
parents:
diff changeset
109 {
kono
parents:
diff changeset
110 ugo[0] = false;
kono
parents:
diff changeset
111 ugo[1] = false;
kono
parents:
diff changeset
112 ugo[2] = false;
kono
parents:
diff changeset
113 #ifdef HAVE_UMASK
kono
parents:
diff changeset
114 honor_umask = true;
kono
parents:
diff changeset
115 #endif
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117 continue_clause = false;
kono
parents:
diff changeset
118 rwxXstugo[0] = false;
kono
parents:
diff changeset
119 rwxXstugo[1] = false;
kono
parents:
diff changeset
120 rwxXstugo[2] = false;
kono
parents:
diff changeset
121 rwxXstugo[3] = false;
kono
parents:
diff changeset
122 rwxXstugo[4] = false;
kono
parents:
diff changeset
123 rwxXstugo[5] = false;
kono
parents:
diff changeset
124 rwxXstugo[6] = false;
kono
parents:
diff changeset
125 rwxXstugo[7] = false;
kono
parents:
diff changeset
126 rwxXstugo[8] = false;
kono
parents:
diff changeset
127 part = 0;
kono
parents:
diff changeset
128 set_mode = -1;
kono
parents:
diff changeset
129 for (; i < mode_len; i++)
kono
parents:
diff changeset
130 {
kono
parents:
diff changeset
131 switch (mode[i])
kono
parents:
diff changeset
132 {
kono
parents:
diff changeset
133 /* User setting: a[ll]/u[ser]/g[roup]/o[ther]. */
kono
parents:
diff changeset
134 case 'a':
kono
parents:
diff changeset
135 if (part > 1)
kono
parents:
diff changeset
136 return 1;
kono
parents:
diff changeset
137 ugo[0] = true;
kono
parents:
diff changeset
138 ugo[1] = true;
kono
parents:
diff changeset
139 ugo[2] = true;
kono
parents:
diff changeset
140 part = 1;
kono
parents:
diff changeset
141 #ifdef HAVE_UMASK
kono
parents:
diff changeset
142 honor_umask = false;
kono
parents:
diff changeset
143 #endif
kono
parents:
diff changeset
144 break;
kono
parents:
diff changeset
145 case 'u':
kono
parents:
diff changeset
146 if (part == 2)
kono
parents:
diff changeset
147 {
kono
parents:
diff changeset
148 rwxXstugo[6] = true;
kono
parents:
diff changeset
149 part = 4;
kono
parents:
diff changeset
150 break;
kono
parents:
diff changeset
151 }
kono
parents:
diff changeset
152 if (part > 1)
kono
parents:
diff changeset
153 return 1;
kono
parents:
diff changeset
154 ugo[0] = true;
kono
parents:
diff changeset
155 part = 1;
kono
parents:
diff changeset
156 #ifdef HAVE_UMASK
kono
parents:
diff changeset
157 honor_umask = false;
kono
parents:
diff changeset
158 #endif
kono
parents:
diff changeset
159 break;
kono
parents:
diff changeset
160 case 'g':
kono
parents:
diff changeset
161 if (part == 2)
kono
parents:
diff changeset
162 {
kono
parents:
diff changeset
163 rwxXstugo[7] = true;
kono
parents:
diff changeset
164 part = 4;
kono
parents:
diff changeset
165 break;
kono
parents:
diff changeset
166 }
kono
parents:
diff changeset
167 if (part > 1)
kono
parents:
diff changeset
168 return 1;
kono
parents:
diff changeset
169 ugo[1] = true;
kono
parents:
diff changeset
170 part = 1;
kono
parents:
diff changeset
171 #ifdef HAVE_UMASK
kono
parents:
diff changeset
172 honor_umask = false;
kono
parents:
diff changeset
173 #endif
kono
parents:
diff changeset
174 break;
kono
parents:
diff changeset
175 case 'o':
kono
parents:
diff changeset
176 if (part == 2)
kono
parents:
diff changeset
177 {
kono
parents:
diff changeset
178 rwxXstugo[8] = true;
kono
parents:
diff changeset
179 part = 4;
kono
parents:
diff changeset
180 break;
kono
parents:
diff changeset
181 }
kono
parents:
diff changeset
182 if (part > 1)
kono
parents:
diff changeset
183 return 1;
kono
parents:
diff changeset
184 ugo[2] = true;
kono
parents:
diff changeset
185 part = 1;
kono
parents:
diff changeset
186 #ifdef HAVE_UMASK
kono
parents:
diff changeset
187 honor_umask = false;
kono
parents:
diff changeset
188 #endif
kono
parents:
diff changeset
189 break;
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 /* Mode setting: =+-. */
kono
parents:
diff changeset
192 case '=':
kono
parents:
diff changeset
193 if (part > 2)
kono
parents:
diff changeset
194 {
kono
parents:
diff changeset
195 continue_clause = true;
kono
parents:
diff changeset
196 i--;
kono
parents:
diff changeset
197 part = 2;
kono
parents:
diff changeset
198 goto clause_done;
kono
parents:
diff changeset
199 }
kono
parents:
diff changeset
200 set_mode = 1;
kono
parents:
diff changeset
201 part = 2;
kono
parents:
diff changeset
202 break;
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 case '-':
kono
parents:
diff changeset
205 if (part > 2)
kono
parents:
diff changeset
206 {
kono
parents:
diff changeset
207 continue_clause = true;
kono
parents:
diff changeset
208 i--;
kono
parents:
diff changeset
209 part = 2;
kono
parents:
diff changeset
210 goto clause_done;
kono
parents:
diff changeset
211 }
kono
parents:
diff changeset
212 set_mode = 2;
kono
parents:
diff changeset
213 part = 2;
kono
parents:
diff changeset
214 break;
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 case '+':
kono
parents:
diff changeset
217 if (part > 2)
kono
parents:
diff changeset
218 {
kono
parents:
diff changeset
219 continue_clause = true;
kono
parents:
diff changeset
220 i--;
kono
parents:
diff changeset
221 part = 2;
kono
parents:
diff changeset
222 goto clause_done;
kono
parents:
diff changeset
223 }
kono
parents:
diff changeset
224 set_mode = 3;
kono
parents:
diff changeset
225 part = 2;
kono
parents:
diff changeset
226 break;
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 /* Permissions: rwxXst - for ugo see above. */
kono
parents:
diff changeset
229 case 'r':
kono
parents:
diff changeset
230 if (part != 2 && part != 3)
kono
parents:
diff changeset
231 return 1;
kono
parents:
diff changeset
232 rwxXstugo[0] = true;
kono
parents:
diff changeset
233 part = 3;
kono
parents:
diff changeset
234 break;
kono
parents:
diff changeset
235
kono
parents:
diff changeset
236 case 'w':
kono
parents:
diff changeset
237 if (part != 2 && part != 3)
kono
parents:
diff changeset
238 return 1;
kono
parents:
diff changeset
239 rwxXstugo[1] = true;
kono
parents:
diff changeset
240 part = 3;
kono
parents:
diff changeset
241 break;
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 case 'x':
kono
parents:
diff changeset
244 if (part != 2 && part != 3)
kono
parents:
diff changeset
245 return 1;
kono
parents:
diff changeset
246 rwxXstugo[2] = true;
kono
parents:
diff changeset
247 part = 3;
kono
parents:
diff changeset
248 break;
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 case 'X':
kono
parents:
diff changeset
251 if (part != 2 && part != 3)
kono
parents:
diff changeset
252 return 1;
kono
parents:
diff changeset
253 rwxXstugo[3] = true;
kono
parents:
diff changeset
254 part = 3;
kono
parents:
diff changeset
255 break;
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 case 's':
kono
parents:
diff changeset
258 if (part != 2 && part != 3)
kono
parents:
diff changeset
259 return 1;
kono
parents:
diff changeset
260 rwxXstugo[4] = true;
kono
parents:
diff changeset
261 part = 3;
kono
parents:
diff changeset
262 break;
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 case 't':
kono
parents:
diff changeset
265 if (part != 2 && part != 3)
kono
parents:
diff changeset
266 return 1;
kono
parents:
diff changeset
267 rwxXstugo[5] = true;
kono
parents:
diff changeset
268 part = 3;
kono
parents:
diff changeset
269 break;
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 /* Tailing blanks are valid in Fortran. */
kono
parents:
diff changeset
272 case ' ':
kono
parents:
diff changeset
273 for (i++; i < mode_len; i++)
kono
parents:
diff changeset
274 if (mode[i] != ' ')
kono
parents:
diff changeset
275 break;
kono
parents:
diff changeset
276 if (i != mode_len)
kono
parents:
diff changeset
277 return 1;
kono
parents:
diff changeset
278 goto clause_done;
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 case ',':
kono
parents:
diff changeset
281 goto clause_done;
kono
parents:
diff changeset
282
kono
parents:
diff changeset
283 default:
kono
parents:
diff changeset
284 return 1;
kono
parents:
diff changeset
285 }
kono
parents:
diff changeset
286 }
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 clause_done:
kono
parents:
diff changeset
289 if (part < 2)
kono
parents:
diff changeset
290 return 1;
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 new_mode = 0;
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 #ifdef __MINGW32__
kono
parents:
diff changeset
295
kono
parents:
diff changeset
296 /* Read. */
kono
parents:
diff changeset
297 if (rwxXstugo[0] && (ugo[0] || honor_umask))
kono
parents:
diff changeset
298 new_mode |= _S_IREAD;
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 /* Write. */
kono
parents:
diff changeset
301 if (rwxXstugo[1] && (ugo[0] || honor_umask))
kono
parents:
diff changeset
302 new_mode |= _S_IWRITE;
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 #else
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 /* Read. */
kono
parents:
diff changeset
307 if (rwxXstugo[0])
kono
parents:
diff changeset
308 {
kono
parents:
diff changeset
309 if (ugo[0] || honor_umask)
kono
parents:
diff changeset
310 new_mode |= S_IRUSR;
kono
parents:
diff changeset
311 if (ugo[1] || honor_umask)
kono
parents:
diff changeset
312 new_mode |= S_IRGRP;
kono
parents:
diff changeset
313 if (ugo[2] || honor_umask)
kono
parents:
diff changeset
314 new_mode |= S_IROTH;
kono
parents:
diff changeset
315 }
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 /* Write. */
kono
parents:
diff changeset
318 if (rwxXstugo[1])
kono
parents:
diff changeset
319 {
kono
parents:
diff changeset
320 if (ugo[0] || honor_umask)
kono
parents:
diff changeset
321 new_mode |= S_IWUSR;
kono
parents:
diff changeset
322 if (ugo[1] || honor_umask)
kono
parents:
diff changeset
323 new_mode |= S_IWGRP;
kono
parents:
diff changeset
324 if (ugo[2] || honor_umask)
kono
parents:
diff changeset
325 new_mode |= S_IWOTH;
kono
parents:
diff changeset
326 }
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 /* Execute. */
kono
parents:
diff changeset
329 if (rwxXstugo[2])
kono
parents:
diff changeset
330 {
kono
parents:
diff changeset
331 if (ugo[0] || honor_umask)
kono
parents:
diff changeset
332 new_mode |= S_IXUSR;
kono
parents:
diff changeset
333 if (ugo[1] || honor_umask)
kono
parents:
diff changeset
334 new_mode |= S_IXGRP;
kono
parents:
diff changeset
335 if (ugo[2] || honor_umask)
kono
parents:
diff changeset
336 new_mode |= S_IXOTH;
kono
parents:
diff changeset
337 }
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 /* 'X' execute. */
kono
parents:
diff changeset
340 if (rwxXstugo[3]
kono
parents:
diff changeset
341 && (is_dir || (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
kono
parents:
diff changeset
342 new_mode |= (S_IXUSR | S_IXGRP | S_IXOTH);
kono
parents:
diff changeset
343
kono
parents:
diff changeset
344 /* 's'. */
kono
parents:
diff changeset
345 if (rwxXstugo[4])
kono
parents:
diff changeset
346 {
kono
parents:
diff changeset
347 if (ugo[0] || honor_umask)
kono
parents:
diff changeset
348 new_mode |= S_ISUID;
kono
parents:
diff changeset
349 if (ugo[1] || honor_umask)
kono
parents:
diff changeset
350 new_mode |= S_ISGID;
kono
parents:
diff changeset
351 }
kono
parents:
diff changeset
352
kono
parents:
diff changeset
353 /* As original 'u'. */
kono
parents:
diff changeset
354 if (rwxXstugo[6])
kono
parents:
diff changeset
355 {
kono
parents:
diff changeset
356 if (ugo[1] || honor_umask)
kono
parents:
diff changeset
357 {
kono
parents:
diff changeset
358 if (file_mode & S_IRUSR)
kono
parents:
diff changeset
359 new_mode |= S_IRGRP;
kono
parents:
diff changeset
360 if (file_mode & S_IWUSR)
kono
parents:
diff changeset
361 new_mode |= S_IWGRP;
kono
parents:
diff changeset
362 if (file_mode & S_IXUSR)
kono
parents:
diff changeset
363 new_mode |= S_IXGRP;
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365 if (ugo[2] || honor_umask)
kono
parents:
diff changeset
366 {
kono
parents:
diff changeset
367 if (file_mode & S_IRUSR)
kono
parents:
diff changeset
368 new_mode |= S_IROTH;
kono
parents:
diff changeset
369 if (file_mode & S_IWUSR)
kono
parents:
diff changeset
370 new_mode |= S_IWOTH;
kono
parents:
diff changeset
371 if (file_mode & S_IXUSR)
kono
parents:
diff changeset
372 new_mode |= S_IXOTH;
kono
parents:
diff changeset
373 }
kono
parents:
diff changeset
374 }
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 /* As original 'g'. */
kono
parents:
diff changeset
377 if (rwxXstugo[7])
kono
parents:
diff changeset
378 {
kono
parents:
diff changeset
379 if (ugo[0] || honor_umask)
kono
parents:
diff changeset
380 {
kono
parents:
diff changeset
381 if (file_mode & S_IRGRP)
kono
parents:
diff changeset
382 new_mode |= S_IRUSR;
kono
parents:
diff changeset
383 if (file_mode & S_IWGRP)
kono
parents:
diff changeset
384 new_mode |= S_IWUSR;
kono
parents:
diff changeset
385 if (file_mode & S_IXGRP)
kono
parents:
diff changeset
386 new_mode |= S_IXUSR;
kono
parents:
diff changeset
387 }
kono
parents:
diff changeset
388 if (ugo[2] || honor_umask)
kono
parents:
diff changeset
389 {
kono
parents:
diff changeset
390 if (file_mode & S_IRGRP)
kono
parents:
diff changeset
391 new_mode |= S_IROTH;
kono
parents:
diff changeset
392 if (file_mode & S_IWGRP)
kono
parents:
diff changeset
393 new_mode |= S_IWOTH;
kono
parents:
diff changeset
394 if (file_mode & S_IXGRP)
kono
parents:
diff changeset
395 new_mode |= S_IXOTH;
kono
parents:
diff changeset
396 }
kono
parents:
diff changeset
397 }
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 /* As original 'o'. */
kono
parents:
diff changeset
400 if (rwxXstugo[8])
kono
parents:
diff changeset
401 {
kono
parents:
diff changeset
402 if (ugo[0] || honor_umask)
kono
parents:
diff changeset
403 {
kono
parents:
diff changeset
404 if (file_mode & S_IROTH)
kono
parents:
diff changeset
405 new_mode |= S_IRUSR;
kono
parents:
diff changeset
406 if (file_mode & S_IWOTH)
kono
parents:
diff changeset
407 new_mode |= S_IWUSR;
kono
parents:
diff changeset
408 if (file_mode & S_IXOTH)
kono
parents:
diff changeset
409 new_mode |= S_IXUSR;
kono
parents:
diff changeset
410 }
kono
parents:
diff changeset
411 if (ugo[1] || honor_umask)
kono
parents:
diff changeset
412 {
kono
parents:
diff changeset
413 if (file_mode & S_IROTH)
kono
parents:
diff changeset
414 new_mode |= S_IRGRP;
kono
parents:
diff changeset
415 if (file_mode & S_IWOTH)
kono
parents:
diff changeset
416 new_mode |= S_IWGRP;
kono
parents:
diff changeset
417 if (file_mode & S_IXOTH)
kono
parents:
diff changeset
418 new_mode |= S_IXGRP;
kono
parents:
diff changeset
419 }
kono
parents:
diff changeset
420 }
kono
parents:
diff changeset
421 #endif /* __MINGW32__ */
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 #ifdef HAVE_UMASK
kono
parents:
diff changeset
424 if (honor_umask)
kono
parents:
diff changeset
425 new_mode &= ~mode_mask;
kono
parents:
diff changeset
426 #endif
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 if (set_mode == 1)
kono
parents:
diff changeset
429 {
kono
parents:
diff changeset
430 #ifdef __MINGW32__
kono
parents:
diff changeset
431 if (ugo[0] || honor_umask)
kono
parents:
diff changeset
432 file_mode = (file_mode & ~(_S_IWRITE | _S_IREAD))
kono
parents:
diff changeset
433 | (new_mode & (_S_IWRITE | _S_IREAD));
kono
parents:
diff changeset
434 #else
kono
parents:
diff changeset
435 /* Set '='. */
kono
parents:
diff changeset
436 if ((ugo[0] || honor_umask) && !rwxXstugo[6])
kono
parents:
diff changeset
437 file_mode = (file_mode & ~(S_ISUID | S_IRUSR | S_IWUSR | S_IXUSR))
kono
parents:
diff changeset
438 | (new_mode & (S_ISUID | S_IRUSR | S_IWUSR | S_IXUSR));
kono
parents:
diff changeset
439 if ((ugo[1] || honor_umask) && !rwxXstugo[7])
kono
parents:
diff changeset
440 file_mode = (file_mode & ~(S_ISGID | S_IRGRP | S_IWGRP | S_IXGRP))
kono
parents:
diff changeset
441 | (new_mode & (S_ISGID | S_IRGRP | S_IWGRP | S_IXGRP));
kono
parents:
diff changeset
442 if ((ugo[2] || honor_umask) && !rwxXstugo[8])
kono
parents:
diff changeset
443 file_mode = (file_mode & ~(S_IROTH | S_IWOTH | S_IXOTH))
kono
parents:
diff changeset
444 | (new_mode & (S_IROTH | S_IWOTH | S_IXOTH));
kono
parents:
diff changeset
445 #ifndef __VXWORKS__
kono
parents:
diff changeset
446 if (is_dir && rwxXstugo[5])
kono
parents:
diff changeset
447 file_mode |= S_ISVTX;
kono
parents:
diff changeset
448 else if (!is_dir)
kono
parents:
diff changeset
449 file_mode &= ~S_ISVTX;
kono
parents:
diff changeset
450 #endif
kono
parents:
diff changeset
451 #endif
kono
parents:
diff changeset
452 }
kono
parents:
diff changeset
453 else if (set_mode == 2)
kono
parents:
diff changeset
454 {
kono
parents:
diff changeset
455 /* Clear '-'. */
kono
parents:
diff changeset
456 file_mode &= ~new_mode;
kono
parents:
diff changeset
457 #if !defined( __MINGW32__) && !defined (__VXWORKS__)
kono
parents:
diff changeset
458 if (rwxXstugo[5] || !is_dir)
kono
parents:
diff changeset
459 file_mode &= ~S_ISVTX;
kono
parents:
diff changeset
460 #endif
kono
parents:
diff changeset
461 }
kono
parents:
diff changeset
462 else if (set_mode == 3)
kono
parents:
diff changeset
463 {
kono
parents:
diff changeset
464 file_mode |= new_mode;
kono
parents:
diff changeset
465 #if !defined (__MINGW32__) && !defined (__VXWORKS__)
kono
parents:
diff changeset
466 if (rwxXstugo[5] && is_dir)
kono
parents:
diff changeset
467 file_mode |= S_ISVTX;
kono
parents:
diff changeset
468 else if (!is_dir)
kono
parents:
diff changeset
469 file_mode &= ~S_ISVTX;
kono
parents:
diff changeset
470 #endif
kono
parents:
diff changeset
471 }
kono
parents:
diff changeset
472 }
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 return chmod (file, file_mode);
kono
parents:
diff changeset
475 }
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 extern int chmod_func (char *, char *, gfc_charlen_type, gfc_charlen_type);
kono
parents:
diff changeset
479 export_proto(chmod_func);
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481 int
kono
parents:
diff changeset
482 chmod_func (char *name, char *mode, gfc_charlen_type name_len,
kono
parents:
diff changeset
483 gfc_charlen_type mode_len)
kono
parents:
diff changeset
484 {
kono
parents:
diff changeset
485 char *cname = fc_strdup (name, name_len);
kono
parents:
diff changeset
486 int ret = chmod_internal (cname, mode, mode_len);
kono
parents:
diff changeset
487 free (cname);
kono
parents:
diff changeset
488 return ret;
kono
parents:
diff changeset
489 }
kono
parents:
diff changeset
490
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 extern void chmod_i4_sub (char *, char *, GFC_INTEGER_4 *,
kono
parents:
diff changeset
493 gfc_charlen_type, gfc_charlen_type);
kono
parents:
diff changeset
494 export_proto(chmod_i4_sub);
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 void
kono
parents:
diff changeset
497 chmod_i4_sub (char *name, char *mode, GFC_INTEGER_4 * status,
kono
parents:
diff changeset
498 gfc_charlen_type name_len, gfc_charlen_type mode_len)
kono
parents:
diff changeset
499 {
kono
parents:
diff changeset
500 int val;
kono
parents:
diff changeset
501
kono
parents:
diff changeset
502 val = chmod_func (name, mode, name_len, mode_len);
kono
parents:
diff changeset
503 if (status)
kono
parents:
diff changeset
504 *status = val;
kono
parents:
diff changeset
505 }
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 extern void chmod_i8_sub (char *, char *, GFC_INTEGER_8 *,
kono
parents:
diff changeset
509 gfc_charlen_type, gfc_charlen_type);
kono
parents:
diff changeset
510 export_proto(chmod_i8_sub);
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 void
kono
parents:
diff changeset
513 chmod_i8_sub (char *name, char *mode, GFC_INTEGER_8 * status,
kono
parents:
diff changeset
514 gfc_charlen_type name_len, gfc_charlen_type mode_len)
kono
parents:
diff changeset
515 {
kono
parents:
diff changeset
516 int val;
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 val = chmod_func (name, mode, name_len, mode_len);
kono
parents:
diff changeset
519 if (status)
kono
parents:
diff changeset
520 *status = val;
kono
parents:
diff changeset
521 }
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 #endif