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