1627f7eb2Smrg /* Implementation of the CHMOD intrinsic.
2*4c3eb207Smrg Copyright (C) 2006-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
4627f7eb2Smrg
5627f7eb2Smrg This file is part of the GNU Fortran runtime library (libgfortran).
6627f7eb2Smrg
7627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or
8627f7eb2Smrg modify it under the terms of the GNU General Public
9627f7eb2Smrg License as published by the Free Software Foundation; either
10627f7eb2Smrg version 3 of the License, or (at your option) any later version.
11627f7eb2Smrg
12627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15627f7eb2Smrg GNU General Public License for more details.
16627f7eb2Smrg
17627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg 3.1, as published by the Free Software Foundation.
20627f7eb2Smrg
21627f7eb2Smrg You should have received a copy of the GNU General Public License and
22627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24627f7eb2Smrg <http://www.gnu.org/licenses/>. */
25627f7eb2Smrg
26627f7eb2Smrg #include "libgfortran.h"
27627f7eb2Smrg
28627f7eb2Smrg #if defined(HAVE_SYS_STAT_H)
29627f7eb2Smrg
30627f7eb2Smrg #include <sys/stat.h> /* For stat, chmod and umask. */
31627f7eb2Smrg
32627f7eb2Smrg
33627f7eb2Smrg /* INTEGER FUNCTION CHMOD (NAME, MODE)
34627f7eb2Smrg CHARACTER(len=*), INTENT(IN) :: NAME, MODE
35627f7eb2Smrg
36627f7eb2Smrg Sets the file permission "chmod" using a mode string.
37627f7eb2Smrg
38627f7eb2Smrg For MinGW, only _S_IWRITE and _S_IREAD are supported. To set those,
39627f7eb2Smrg only the user attributes are used.
40627f7eb2Smrg
41627f7eb2Smrg The mode string allows for the same arguments as POSIX's chmod utility.
42627f7eb2Smrg a) string containing an octal number.
43627f7eb2Smrg b) Comma separated list of clauses of the form:
44627f7eb2Smrg [<who-list>]<op>[<perm-list>|<permcopy>][<op>[<perm-list>|<permcopy>],...]
45627f7eb2Smrg <who> - 'u', 'g', 'o', 'a'
46627f7eb2Smrg <op> - '+', '-', '='
47627f7eb2Smrg <perm> - 'r', 'w', 'x', 'X', 's', t'
48627f7eb2Smrg If <op> is not followed by a perm-list or permcopy, '-' and '+' do not
49627f7eb2Smrg change the mode while '=' clears all file mode bits. 'u' stands for the
50627f7eb2Smrg user permissions, 'g' for the group and 'o' for the permissions for others.
51627f7eb2Smrg 'a' is equivalent to 'ugo'. '+' sets the given permission in addition to
52627f7eb2Smrg the ones of the file, '-' unsets the given permissions of the file, while
53627f7eb2Smrg '=' sets the file to that mode. 'r' sets the read, 'w' the write, and
54627f7eb2Smrg 'x' the execute mode. 'X' sets the execute bit if the file is a directory
55627f7eb2Smrg or if the user, group or other executable bit is set. 't' sets the sticky
56627f7eb2Smrg bit, 's' (un)sets the and/or S_ISUID/S_ISGID bit.
57627f7eb2Smrg
58627f7eb2Smrg Note that if <who> is omitted, the permissions are filtered by the umask.
59627f7eb2Smrg
60627f7eb2Smrg A return value of 0 indicates success, -1 an error of chmod() while 1
61627f7eb2Smrg indicates a mode parsing error. */
62627f7eb2Smrg
63627f7eb2Smrg
64627f7eb2Smrg static int
chmod_internal(char * file,char * mode,gfc_charlen_type mode_len)65627f7eb2Smrg chmod_internal (char *file, char *mode, gfc_charlen_type mode_len)
66627f7eb2Smrg {
67627f7eb2Smrg bool ugo[3];
68627f7eb2Smrg bool rwxXstugo[9];
69627f7eb2Smrg int set_mode, part;
70627f7eb2Smrg bool honor_umask, continue_clause = false;
71627f7eb2Smrg #ifndef __MINGW32__
72627f7eb2Smrg bool is_dir;
73627f7eb2Smrg #endif
74627f7eb2Smrg mode_t mode_mask, file_mode, new_mode;
75627f7eb2Smrg struct stat stat_buf;
76627f7eb2Smrg
77627f7eb2Smrg if (mode_len == 0)
78627f7eb2Smrg return 1;
79627f7eb2Smrg
80627f7eb2Smrg if (mode[0] >= '0' && mode[0] <= '9')
81627f7eb2Smrg {
82627f7eb2Smrg unsigned fmode;
83627f7eb2Smrg if (sscanf (mode, "%o", &fmode) != 1)
84627f7eb2Smrg return 1;
85627f7eb2Smrg return chmod (file, (mode_t) fmode);
86627f7eb2Smrg }
87627f7eb2Smrg
88627f7eb2Smrg /* Read the current file mode. */
89627f7eb2Smrg if (stat (file, &stat_buf))
90627f7eb2Smrg return 1;
91627f7eb2Smrg
92627f7eb2Smrg file_mode = stat_buf.st_mode & ~S_IFMT;
93627f7eb2Smrg #ifndef __MINGW32__
94627f7eb2Smrg is_dir = stat_buf.st_mode & S_IFDIR;
95627f7eb2Smrg #endif
96627f7eb2Smrg
97627f7eb2Smrg #ifdef HAVE_UMASK
98627f7eb2Smrg /* Obtain the umask without distroying the setting. */
99627f7eb2Smrg mode_mask = 0;
100627f7eb2Smrg mode_mask = umask (mode_mask);
101627f7eb2Smrg (void) umask (mode_mask);
102627f7eb2Smrg #else
103627f7eb2Smrg honor_umask = false;
104627f7eb2Smrg #endif
105627f7eb2Smrg
106627f7eb2Smrg for (gfc_charlen_type i = 0; i < mode_len; i++)
107627f7eb2Smrg {
108627f7eb2Smrg if (!continue_clause)
109627f7eb2Smrg {
110627f7eb2Smrg ugo[0] = false;
111627f7eb2Smrg ugo[1] = false;
112627f7eb2Smrg ugo[2] = false;
113627f7eb2Smrg #ifdef HAVE_UMASK
114627f7eb2Smrg honor_umask = true;
115627f7eb2Smrg #endif
116627f7eb2Smrg }
117627f7eb2Smrg continue_clause = false;
118627f7eb2Smrg rwxXstugo[0] = false;
119627f7eb2Smrg rwxXstugo[1] = false;
120627f7eb2Smrg rwxXstugo[2] = false;
121627f7eb2Smrg rwxXstugo[3] = false;
122627f7eb2Smrg rwxXstugo[4] = false;
123627f7eb2Smrg rwxXstugo[5] = false;
124627f7eb2Smrg rwxXstugo[6] = false;
125627f7eb2Smrg rwxXstugo[7] = false;
126627f7eb2Smrg rwxXstugo[8] = false;
127627f7eb2Smrg part = 0;
128627f7eb2Smrg set_mode = -1;
129627f7eb2Smrg for (; i < mode_len; i++)
130627f7eb2Smrg {
131627f7eb2Smrg switch (mode[i])
132627f7eb2Smrg {
133627f7eb2Smrg /* User setting: a[ll]/u[ser]/g[roup]/o[ther]. */
134627f7eb2Smrg case 'a':
135627f7eb2Smrg if (part > 1)
136627f7eb2Smrg return 1;
137627f7eb2Smrg ugo[0] = true;
138627f7eb2Smrg ugo[1] = true;
139627f7eb2Smrg ugo[2] = true;
140627f7eb2Smrg part = 1;
141627f7eb2Smrg #ifdef HAVE_UMASK
142627f7eb2Smrg honor_umask = false;
143627f7eb2Smrg #endif
144627f7eb2Smrg break;
145627f7eb2Smrg case 'u':
146627f7eb2Smrg if (part == 2)
147627f7eb2Smrg {
148627f7eb2Smrg rwxXstugo[6] = true;
149627f7eb2Smrg part = 4;
150627f7eb2Smrg break;
151627f7eb2Smrg }
152627f7eb2Smrg if (part > 1)
153627f7eb2Smrg return 1;
154627f7eb2Smrg ugo[0] = true;
155627f7eb2Smrg part = 1;
156627f7eb2Smrg #ifdef HAVE_UMASK
157627f7eb2Smrg honor_umask = false;
158627f7eb2Smrg #endif
159627f7eb2Smrg break;
160627f7eb2Smrg case 'g':
161627f7eb2Smrg if (part == 2)
162627f7eb2Smrg {
163627f7eb2Smrg rwxXstugo[7] = true;
164627f7eb2Smrg part = 4;
165627f7eb2Smrg break;
166627f7eb2Smrg }
167627f7eb2Smrg if (part > 1)
168627f7eb2Smrg return 1;
169627f7eb2Smrg ugo[1] = true;
170627f7eb2Smrg part = 1;
171627f7eb2Smrg #ifdef HAVE_UMASK
172627f7eb2Smrg honor_umask = false;
173627f7eb2Smrg #endif
174627f7eb2Smrg break;
175627f7eb2Smrg case 'o':
176627f7eb2Smrg if (part == 2)
177627f7eb2Smrg {
178627f7eb2Smrg rwxXstugo[8] = true;
179627f7eb2Smrg part = 4;
180627f7eb2Smrg break;
181627f7eb2Smrg }
182627f7eb2Smrg if (part > 1)
183627f7eb2Smrg return 1;
184627f7eb2Smrg ugo[2] = true;
185627f7eb2Smrg part = 1;
186627f7eb2Smrg #ifdef HAVE_UMASK
187627f7eb2Smrg honor_umask = false;
188627f7eb2Smrg #endif
189627f7eb2Smrg break;
190627f7eb2Smrg
191627f7eb2Smrg /* Mode setting: =+-. */
192627f7eb2Smrg case '=':
193627f7eb2Smrg if (part > 2)
194627f7eb2Smrg {
195627f7eb2Smrg continue_clause = true;
196627f7eb2Smrg i--;
197627f7eb2Smrg part = 2;
198627f7eb2Smrg goto clause_done;
199627f7eb2Smrg }
200627f7eb2Smrg set_mode = 1;
201627f7eb2Smrg part = 2;
202627f7eb2Smrg break;
203627f7eb2Smrg
204627f7eb2Smrg case '-':
205627f7eb2Smrg if (part > 2)
206627f7eb2Smrg {
207627f7eb2Smrg continue_clause = true;
208627f7eb2Smrg i--;
209627f7eb2Smrg part = 2;
210627f7eb2Smrg goto clause_done;
211627f7eb2Smrg }
212627f7eb2Smrg set_mode = 2;
213627f7eb2Smrg part = 2;
214627f7eb2Smrg break;
215627f7eb2Smrg
216627f7eb2Smrg case '+':
217627f7eb2Smrg if (part > 2)
218627f7eb2Smrg {
219627f7eb2Smrg continue_clause = true;
220627f7eb2Smrg i--;
221627f7eb2Smrg part = 2;
222627f7eb2Smrg goto clause_done;
223627f7eb2Smrg }
224627f7eb2Smrg set_mode = 3;
225627f7eb2Smrg part = 2;
226627f7eb2Smrg break;
227627f7eb2Smrg
228627f7eb2Smrg /* Permissions: rwxXst - for ugo see above. */
229627f7eb2Smrg case 'r':
230627f7eb2Smrg if (part != 2 && part != 3)
231627f7eb2Smrg return 1;
232627f7eb2Smrg rwxXstugo[0] = true;
233627f7eb2Smrg part = 3;
234627f7eb2Smrg break;
235627f7eb2Smrg
236627f7eb2Smrg case 'w':
237627f7eb2Smrg if (part != 2 && part != 3)
238627f7eb2Smrg return 1;
239627f7eb2Smrg rwxXstugo[1] = true;
240627f7eb2Smrg part = 3;
241627f7eb2Smrg break;
242627f7eb2Smrg
243627f7eb2Smrg case 'x':
244627f7eb2Smrg if (part != 2 && part != 3)
245627f7eb2Smrg return 1;
246627f7eb2Smrg rwxXstugo[2] = true;
247627f7eb2Smrg part = 3;
248627f7eb2Smrg break;
249627f7eb2Smrg
250627f7eb2Smrg case 'X':
251627f7eb2Smrg if (part != 2 && part != 3)
252627f7eb2Smrg return 1;
253627f7eb2Smrg rwxXstugo[3] = true;
254627f7eb2Smrg part = 3;
255627f7eb2Smrg break;
256627f7eb2Smrg
257627f7eb2Smrg case 's':
258627f7eb2Smrg if (part != 2 && part != 3)
259627f7eb2Smrg return 1;
260627f7eb2Smrg rwxXstugo[4] = true;
261627f7eb2Smrg part = 3;
262627f7eb2Smrg break;
263627f7eb2Smrg
264627f7eb2Smrg case 't':
265627f7eb2Smrg if (part != 2 && part != 3)
266627f7eb2Smrg return 1;
267627f7eb2Smrg rwxXstugo[5] = true;
268627f7eb2Smrg part = 3;
269627f7eb2Smrg break;
270627f7eb2Smrg
271627f7eb2Smrg /* Tailing blanks are valid in Fortran. */
272627f7eb2Smrg case ' ':
273627f7eb2Smrg for (i++; i < mode_len; i++)
274627f7eb2Smrg if (mode[i] != ' ')
275627f7eb2Smrg break;
276627f7eb2Smrg if (i != mode_len)
277627f7eb2Smrg return 1;
278627f7eb2Smrg goto clause_done;
279627f7eb2Smrg
280627f7eb2Smrg case ',':
281627f7eb2Smrg goto clause_done;
282627f7eb2Smrg
283627f7eb2Smrg default:
284627f7eb2Smrg return 1;
285627f7eb2Smrg }
286627f7eb2Smrg }
287627f7eb2Smrg
288627f7eb2Smrg clause_done:
289627f7eb2Smrg if (part < 2)
290627f7eb2Smrg return 1;
291627f7eb2Smrg
292627f7eb2Smrg new_mode = 0;
293627f7eb2Smrg
294627f7eb2Smrg #ifdef __MINGW32__
295627f7eb2Smrg
296627f7eb2Smrg /* Read. */
297627f7eb2Smrg if (rwxXstugo[0] && (ugo[0] || honor_umask))
298627f7eb2Smrg new_mode |= _S_IREAD;
299627f7eb2Smrg
300627f7eb2Smrg /* Write. */
301627f7eb2Smrg if (rwxXstugo[1] && (ugo[0] || honor_umask))
302627f7eb2Smrg new_mode |= _S_IWRITE;
303627f7eb2Smrg
304627f7eb2Smrg #else
305627f7eb2Smrg
306627f7eb2Smrg /* Read. */
307627f7eb2Smrg if (rwxXstugo[0])
308627f7eb2Smrg {
309627f7eb2Smrg if (ugo[0] || honor_umask)
310627f7eb2Smrg new_mode |= S_IRUSR;
311627f7eb2Smrg if (ugo[1] || honor_umask)
312627f7eb2Smrg new_mode |= S_IRGRP;
313627f7eb2Smrg if (ugo[2] || honor_umask)
314627f7eb2Smrg new_mode |= S_IROTH;
315627f7eb2Smrg }
316627f7eb2Smrg
317627f7eb2Smrg /* Write. */
318627f7eb2Smrg if (rwxXstugo[1])
319627f7eb2Smrg {
320627f7eb2Smrg if (ugo[0] || honor_umask)
321627f7eb2Smrg new_mode |= S_IWUSR;
322627f7eb2Smrg if (ugo[1] || honor_umask)
323627f7eb2Smrg new_mode |= S_IWGRP;
324627f7eb2Smrg if (ugo[2] || honor_umask)
325627f7eb2Smrg new_mode |= S_IWOTH;
326627f7eb2Smrg }
327627f7eb2Smrg
328627f7eb2Smrg /* Execute. */
329627f7eb2Smrg if (rwxXstugo[2])
330627f7eb2Smrg {
331627f7eb2Smrg if (ugo[0] || honor_umask)
332627f7eb2Smrg new_mode |= S_IXUSR;
333627f7eb2Smrg if (ugo[1] || honor_umask)
334627f7eb2Smrg new_mode |= S_IXGRP;
335627f7eb2Smrg if (ugo[2] || honor_umask)
336627f7eb2Smrg new_mode |= S_IXOTH;
337627f7eb2Smrg }
338627f7eb2Smrg
339627f7eb2Smrg /* 'X' execute. */
340627f7eb2Smrg if (rwxXstugo[3]
341627f7eb2Smrg && (is_dir || (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
342627f7eb2Smrg new_mode |= (S_IXUSR | S_IXGRP | S_IXOTH);
343627f7eb2Smrg
344627f7eb2Smrg /* 's'. */
345627f7eb2Smrg if (rwxXstugo[4])
346627f7eb2Smrg {
347627f7eb2Smrg if (ugo[0] || honor_umask)
348627f7eb2Smrg new_mode |= S_ISUID;
349627f7eb2Smrg if (ugo[1] || honor_umask)
350627f7eb2Smrg new_mode |= S_ISGID;
351627f7eb2Smrg }
352627f7eb2Smrg
353627f7eb2Smrg /* As original 'u'. */
354627f7eb2Smrg if (rwxXstugo[6])
355627f7eb2Smrg {
356627f7eb2Smrg if (ugo[1] || honor_umask)
357627f7eb2Smrg {
358627f7eb2Smrg if (file_mode & S_IRUSR)
359627f7eb2Smrg new_mode |= S_IRGRP;
360627f7eb2Smrg if (file_mode & S_IWUSR)
361627f7eb2Smrg new_mode |= S_IWGRP;
362627f7eb2Smrg if (file_mode & S_IXUSR)
363627f7eb2Smrg new_mode |= S_IXGRP;
364627f7eb2Smrg }
365627f7eb2Smrg if (ugo[2] || honor_umask)
366627f7eb2Smrg {
367627f7eb2Smrg if (file_mode & S_IRUSR)
368627f7eb2Smrg new_mode |= S_IROTH;
369627f7eb2Smrg if (file_mode & S_IWUSR)
370627f7eb2Smrg new_mode |= S_IWOTH;
371627f7eb2Smrg if (file_mode & S_IXUSR)
372627f7eb2Smrg new_mode |= S_IXOTH;
373627f7eb2Smrg }
374627f7eb2Smrg }
375627f7eb2Smrg
376627f7eb2Smrg /* As original 'g'. */
377627f7eb2Smrg if (rwxXstugo[7])
378627f7eb2Smrg {
379627f7eb2Smrg if (ugo[0] || honor_umask)
380627f7eb2Smrg {
381627f7eb2Smrg if (file_mode & S_IRGRP)
382627f7eb2Smrg new_mode |= S_IRUSR;
383627f7eb2Smrg if (file_mode & S_IWGRP)
384627f7eb2Smrg new_mode |= S_IWUSR;
385627f7eb2Smrg if (file_mode & S_IXGRP)
386627f7eb2Smrg new_mode |= S_IXUSR;
387627f7eb2Smrg }
388627f7eb2Smrg if (ugo[2] || honor_umask)
389627f7eb2Smrg {
390627f7eb2Smrg if (file_mode & S_IRGRP)
391627f7eb2Smrg new_mode |= S_IROTH;
392627f7eb2Smrg if (file_mode & S_IWGRP)
393627f7eb2Smrg new_mode |= S_IWOTH;
394627f7eb2Smrg if (file_mode & S_IXGRP)
395627f7eb2Smrg new_mode |= S_IXOTH;
396627f7eb2Smrg }
397627f7eb2Smrg }
398627f7eb2Smrg
399627f7eb2Smrg /* As original 'o'. */
400627f7eb2Smrg if (rwxXstugo[8])
401627f7eb2Smrg {
402627f7eb2Smrg if (ugo[0] || honor_umask)
403627f7eb2Smrg {
404627f7eb2Smrg if (file_mode & S_IROTH)
405627f7eb2Smrg new_mode |= S_IRUSR;
406627f7eb2Smrg if (file_mode & S_IWOTH)
407627f7eb2Smrg new_mode |= S_IWUSR;
408627f7eb2Smrg if (file_mode & S_IXOTH)
409627f7eb2Smrg new_mode |= S_IXUSR;
410627f7eb2Smrg }
411627f7eb2Smrg if (ugo[1] || honor_umask)
412627f7eb2Smrg {
413627f7eb2Smrg if (file_mode & S_IROTH)
414627f7eb2Smrg new_mode |= S_IRGRP;
415627f7eb2Smrg if (file_mode & S_IWOTH)
416627f7eb2Smrg new_mode |= S_IWGRP;
417627f7eb2Smrg if (file_mode & S_IXOTH)
418627f7eb2Smrg new_mode |= S_IXGRP;
419627f7eb2Smrg }
420627f7eb2Smrg }
421627f7eb2Smrg #endif /* __MINGW32__ */
422627f7eb2Smrg
423627f7eb2Smrg #ifdef HAVE_UMASK
424627f7eb2Smrg if (honor_umask)
425627f7eb2Smrg new_mode &= ~mode_mask;
426627f7eb2Smrg #endif
427627f7eb2Smrg
428627f7eb2Smrg if (set_mode == 1)
429627f7eb2Smrg {
430627f7eb2Smrg #ifdef __MINGW32__
431627f7eb2Smrg if (ugo[0] || honor_umask)
432627f7eb2Smrg file_mode = (file_mode & ~(_S_IWRITE | _S_IREAD))
433627f7eb2Smrg | (new_mode & (_S_IWRITE | _S_IREAD));
434627f7eb2Smrg #else
435627f7eb2Smrg /* Set '='. */
436627f7eb2Smrg if ((ugo[0] || honor_umask) && !rwxXstugo[6])
437627f7eb2Smrg file_mode = (file_mode & ~(S_ISUID | S_IRUSR | S_IWUSR | S_IXUSR))
438627f7eb2Smrg | (new_mode & (S_ISUID | S_IRUSR | S_IWUSR | S_IXUSR));
439627f7eb2Smrg if ((ugo[1] || honor_umask) && !rwxXstugo[7])
440627f7eb2Smrg file_mode = (file_mode & ~(S_ISGID | S_IRGRP | S_IWGRP | S_IXGRP))
441627f7eb2Smrg | (new_mode & (S_ISGID | S_IRGRP | S_IWGRP | S_IXGRP));
442627f7eb2Smrg if ((ugo[2] || honor_umask) && !rwxXstugo[8])
443627f7eb2Smrg file_mode = (file_mode & ~(S_IROTH | S_IWOTH | S_IXOTH))
444627f7eb2Smrg | (new_mode & (S_IROTH | S_IWOTH | S_IXOTH));
445627f7eb2Smrg #ifndef __VXWORKS__
446627f7eb2Smrg if (is_dir && rwxXstugo[5])
447627f7eb2Smrg file_mode |= S_ISVTX;
448627f7eb2Smrg else if (!is_dir)
449627f7eb2Smrg file_mode &= ~S_ISVTX;
450627f7eb2Smrg #endif
451627f7eb2Smrg #endif
452627f7eb2Smrg }
453627f7eb2Smrg else if (set_mode == 2)
454627f7eb2Smrg {
455627f7eb2Smrg /* Clear '-'. */
456627f7eb2Smrg file_mode &= ~new_mode;
457627f7eb2Smrg #if !defined( __MINGW32__) && !defined (__VXWORKS__)
458627f7eb2Smrg if (rwxXstugo[5] || !is_dir)
459627f7eb2Smrg file_mode &= ~S_ISVTX;
460627f7eb2Smrg #endif
461627f7eb2Smrg }
462627f7eb2Smrg else if (set_mode == 3)
463627f7eb2Smrg {
464627f7eb2Smrg file_mode |= new_mode;
465627f7eb2Smrg #if !defined (__MINGW32__) && !defined (__VXWORKS__)
466627f7eb2Smrg if (rwxXstugo[5] && is_dir)
467627f7eb2Smrg file_mode |= S_ISVTX;
468627f7eb2Smrg else if (!is_dir)
469627f7eb2Smrg file_mode &= ~S_ISVTX;
470627f7eb2Smrg #endif
471627f7eb2Smrg }
472627f7eb2Smrg }
473627f7eb2Smrg
474627f7eb2Smrg return chmod (file, file_mode);
475627f7eb2Smrg }
476627f7eb2Smrg
477627f7eb2Smrg
478627f7eb2Smrg extern int chmod_func (char *, char *, gfc_charlen_type, gfc_charlen_type);
479627f7eb2Smrg export_proto(chmod_func);
480627f7eb2Smrg
481627f7eb2Smrg int
chmod_func(char * name,char * mode,gfc_charlen_type name_len,gfc_charlen_type mode_len)482627f7eb2Smrg chmod_func (char *name, char *mode, gfc_charlen_type name_len,
483627f7eb2Smrg gfc_charlen_type mode_len)
484627f7eb2Smrg {
485627f7eb2Smrg char *cname = fc_strdup (name, name_len);
486627f7eb2Smrg int ret = chmod_internal (cname, mode, mode_len);
487627f7eb2Smrg free (cname);
488627f7eb2Smrg return ret;
489627f7eb2Smrg }
490627f7eb2Smrg
491627f7eb2Smrg
492627f7eb2Smrg extern void chmod_i4_sub (char *, char *, GFC_INTEGER_4 *,
493627f7eb2Smrg gfc_charlen_type, gfc_charlen_type);
494627f7eb2Smrg export_proto(chmod_i4_sub);
495627f7eb2Smrg
496627f7eb2Smrg void
chmod_i4_sub(char * name,char * mode,GFC_INTEGER_4 * status,gfc_charlen_type name_len,gfc_charlen_type mode_len)497627f7eb2Smrg chmod_i4_sub (char *name, char *mode, GFC_INTEGER_4 * status,
498627f7eb2Smrg gfc_charlen_type name_len, gfc_charlen_type mode_len)
499627f7eb2Smrg {
500627f7eb2Smrg int val;
501627f7eb2Smrg
502627f7eb2Smrg val = chmod_func (name, mode, name_len, mode_len);
503627f7eb2Smrg if (status)
504627f7eb2Smrg *status = val;
505627f7eb2Smrg }
506627f7eb2Smrg
507627f7eb2Smrg
508627f7eb2Smrg extern void chmod_i8_sub (char *, char *, GFC_INTEGER_8 *,
509627f7eb2Smrg gfc_charlen_type, gfc_charlen_type);
510627f7eb2Smrg export_proto(chmod_i8_sub);
511627f7eb2Smrg
512627f7eb2Smrg void
chmod_i8_sub(char * name,char * mode,GFC_INTEGER_8 * status,gfc_charlen_type name_len,gfc_charlen_type mode_len)513627f7eb2Smrg chmod_i8_sub (char *name, char *mode, GFC_INTEGER_8 * status,
514627f7eb2Smrg gfc_charlen_type name_len, gfc_charlen_type mode_len)
515627f7eb2Smrg {
516627f7eb2Smrg int val;
517627f7eb2Smrg
518627f7eb2Smrg val = chmod_func (name, mode, name_len, mode_len);
519627f7eb2Smrg if (status)
520627f7eb2Smrg *status = val;
521627f7eb2Smrg }
522627f7eb2Smrg
523627f7eb2Smrg #endif
524