1 1.1 mrg /* Implementation of the CHMOD intrinsic. 2 1.1.1.3 mrg Copyright (C) 2006-2022 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.1.3 mrg #ifdef HAVE_UMASK 75 1.1.1.3 mrg mode_t mode_mask; 76 1.1.1.3 mrg #endif 77 1.1.1.3 mrg mode_t file_mode, new_mode; 78 1.1 mrg struct stat stat_buf; 79 1.1 mrg 80 1.1 mrg if (mode_len == 0) 81 1.1 mrg return 1; 82 1.1 mrg 83 1.1 mrg if (mode[0] >= '0' && mode[0] <= '9') 84 1.1 mrg { 85 1.1 mrg unsigned fmode; 86 1.1 mrg if (sscanf (mode, "%o", &fmode) != 1) 87 1.1 mrg return 1; 88 1.1 mrg return chmod (file, (mode_t) fmode); 89 1.1 mrg } 90 1.1 mrg 91 1.1 mrg /* Read the current file mode. */ 92 1.1 mrg if (stat (file, &stat_buf)) 93 1.1 mrg return 1; 94 1.1 mrg 95 1.1 mrg file_mode = stat_buf.st_mode & ~S_IFMT; 96 1.1 mrg #ifndef __MINGW32__ 97 1.1 mrg is_dir = stat_buf.st_mode & S_IFDIR; 98 1.1 mrg #endif 99 1.1 mrg 100 1.1 mrg #ifdef HAVE_UMASK 101 1.1 mrg /* Obtain the umask without distroying the setting. */ 102 1.1 mrg mode_mask = 0; 103 1.1 mrg mode_mask = umask (mode_mask); 104 1.1 mrg (void) umask (mode_mask); 105 1.1 mrg #else 106 1.1 mrg honor_umask = false; 107 1.1 mrg #endif 108 1.1 mrg 109 1.1 mrg for (gfc_charlen_type i = 0; i < mode_len; i++) 110 1.1 mrg { 111 1.1 mrg if (!continue_clause) 112 1.1 mrg { 113 1.1 mrg ugo[0] = false; 114 1.1 mrg ugo[1] = false; 115 1.1 mrg ugo[2] = false; 116 1.1 mrg #ifdef HAVE_UMASK 117 1.1 mrg honor_umask = true; 118 1.1 mrg #endif 119 1.1 mrg } 120 1.1 mrg continue_clause = false; 121 1.1 mrg rwxXstugo[0] = false; 122 1.1 mrg rwxXstugo[1] = false; 123 1.1 mrg rwxXstugo[2] = false; 124 1.1 mrg rwxXstugo[3] = false; 125 1.1 mrg rwxXstugo[4] = false; 126 1.1 mrg rwxXstugo[5] = false; 127 1.1 mrg rwxXstugo[6] = false; 128 1.1 mrg rwxXstugo[7] = false; 129 1.1 mrg rwxXstugo[8] = false; 130 1.1 mrg part = 0; 131 1.1 mrg set_mode = -1; 132 1.1 mrg for (; i < mode_len; i++) 133 1.1 mrg { 134 1.1 mrg switch (mode[i]) 135 1.1 mrg { 136 1.1 mrg /* User setting: a[ll]/u[ser]/g[roup]/o[ther]. */ 137 1.1 mrg case 'a': 138 1.1 mrg if (part > 1) 139 1.1 mrg return 1; 140 1.1 mrg ugo[0] = true; 141 1.1 mrg ugo[1] = true; 142 1.1 mrg ugo[2] = true; 143 1.1 mrg part = 1; 144 1.1 mrg #ifdef HAVE_UMASK 145 1.1 mrg honor_umask = false; 146 1.1 mrg #endif 147 1.1 mrg break; 148 1.1 mrg case 'u': 149 1.1 mrg if (part == 2) 150 1.1 mrg { 151 1.1 mrg rwxXstugo[6] = true; 152 1.1 mrg part = 4; 153 1.1 mrg break; 154 1.1 mrg } 155 1.1 mrg if (part > 1) 156 1.1 mrg return 1; 157 1.1 mrg ugo[0] = true; 158 1.1 mrg part = 1; 159 1.1 mrg #ifdef HAVE_UMASK 160 1.1 mrg honor_umask = false; 161 1.1 mrg #endif 162 1.1 mrg break; 163 1.1 mrg case 'g': 164 1.1 mrg if (part == 2) 165 1.1 mrg { 166 1.1 mrg rwxXstugo[7] = true; 167 1.1 mrg part = 4; 168 1.1 mrg break; 169 1.1 mrg } 170 1.1 mrg if (part > 1) 171 1.1 mrg return 1; 172 1.1 mrg ugo[1] = true; 173 1.1 mrg part = 1; 174 1.1 mrg #ifdef HAVE_UMASK 175 1.1 mrg honor_umask = false; 176 1.1 mrg #endif 177 1.1 mrg break; 178 1.1 mrg case 'o': 179 1.1 mrg if (part == 2) 180 1.1 mrg { 181 1.1 mrg rwxXstugo[8] = true; 182 1.1 mrg part = 4; 183 1.1 mrg break; 184 1.1 mrg } 185 1.1 mrg if (part > 1) 186 1.1 mrg return 1; 187 1.1 mrg ugo[2] = true; 188 1.1 mrg part = 1; 189 1.1 mrg #ifdef HAVE_UMASK 190 1.1 mrg honor_umask = false; 191 1.1 mrg #endif 192 1.1 mrg break; 193 1.1 mrg 194 1.1 mrg /* Mode setting: =+-. */ 195 1.1 mrg case '=': 196 1.1 mrg if (part > 2) 197 1.1 mrg { 198 1.1 mrg continue_clause = true; 199 1.1 mrg i--; 200 1.1 mrg part = 2; 201 1.1 mrg goto clause_done; 202 1.1 mrg } 203 1.1 mrg set_mode = 1; 204 1.1 mrg part = 2; 205 1.1 mrg break; 206 1.1 mrg 207 1.1 mrg case '-': 208 1.1 mrg if (part > 2) 209 1.1 mrg { 210 1.1 mrg continue_clause = true; 211 1.1 mrg i--; 212 1.1 mrg part = 2; 213 1.1 mrg goto clause_done; 214 1.1 mrg } 215 1.1 mrg set_mode = 2; 216 1.1 mrg part = 2; 217 1.1 mrg break; 218 1.1 mrg 219 1.1 mrg case '+': 220 1.1 mrg if (part > 2) 221 1.1 mrg { 222 1.1 mrg continue_clause = true; 223 1.1 mrg i--; 224 1.1 mrg part = 2; 225 1.1 mrg goto clause_done; 226 1.1 mrg } 227 1.1 mrg set_mode = 3; 228 1.1 mrg part = 2; 229 1.1 mrg break; 230 1.1 mrg 231 1.1 mrg /* Permissions: rwxXst - for ugo see above. */ 232 1.1 mrg case 'r': 233 1.1 mrg if (part != 2 && part != 3) 234 1.1 mrg return 1; 235 1.1 mrg rwxXstugo[0] = true; 236 1.1 mrg part = 3; 237 1.1 mrg break; 238 1.1 mrg 239 1.1 mrg case 'w': 240 1.1 mrg if (part != 2 && part != 3) 241 1.1 mrg return 1; 242 1.1 mrg rwxXstugo[1] = true; 243 1.1 mrg part = 3; 244 1.1 mrg break; 245 1.1 mrg 246 1.1 mrg case 'x': 247 1.1 mrg if (part != 2 && part != 3) 248 1.1 mrg return 1; 249 1.1 mrg rwxXstugo[2] = true; 250 1.1 mrg part = 3; 251 1.1 mrg break; 252 1.1 mrg 253 1.1 mrg case 'X': 254 1.1 mrg if (part != 2 && part != 3) 255 1.1 mrg return 1; 256 1.1 mrg rwxXstugo[3] = true; 257 1.1 mrg part = 3; 258 1.1 mrg break; 259 1.1 mrg 260 1.1 mrg case 's': 261 1.1 mrg if (part != 2 && part != 3) 262 1.1 mrg return 1; 263 1.1 mrg rwxXstugo[4] = true; 264 1.1 mrg part = 3; 265 1.1 mrg break; 266 1.1 mrg 267 1.1 mrg case 't': 268 1.1 mrg if (part != 2 && part != 3) 269 1.1 mrg return 1; 270 1.1 mrg rwxXstugo[5] = true; 271 1.1 mrg part = 3; 272 1.1 mrg break; 273 1.1 mrg 274 1.1.1.3 mrg /* Trailing blanks are valid in Fortran. */ 275 1.1 mrg case ' ': 276 1.1 mrg for (i++; i < mode_len; i++) 277 1.1 mrg if (mode[i] != ' ') 278 1.1 mrg break; 279 1.1 mrg if (i != mode_len) 280 1.1 mrg return 1; 281 1.1 mrg goto clause_done; 282 1.1 mrg 283 1.1 mrg case ',': 284 1.1 mrg goto clause_done; 285 1.1 mrg 286 1.1 mrg default: 287 1.1 mrg return 1; 288 1.1 mrg } 289 1.1 mrg } 290 1.1 mrg 291 1.1 mrg clause_done: 292 1.1 mrg if (part < 2) 293 1.1 mrg return 1; 294 1.1 mrg 295 1.1 mrg new_mode = 0; 296 1.1 mrg 297 1.1 mrg #ifdef __MINGW32__ 298 1.1 mrg 299 1.1 mrg /* Read. */ 300 1.1 mrg if (rwxXstugo[0] && (ugo[0] || honor_umask)) 301 1.1 mrg new_mode |= _S_IREAD; 302 1.1 mrg 303 1.1 mrg /* Write. */ 304 1.1 mrg if (rwxXstugo[1] && (ugo[0] || honor_umask)) 305 1.1 mrg new_mode |= _S_IWRITE; 306 1.1 mrg 307 1.1 mrg #else 308 1.1 mrg 309 1.1 mrg /* Read. */ 310 1.1 mrg if (rwxXstugo[0]) 311 1.1 mrg { 312 1.1 mrg if (ugo[0] || honor_umask) 313 1.1 mrg new_mode |= S_IRUSR; 314 1.1 mrg if (ugo[1] || honor_umask) 315 1.1 mrg new_mode |= S_IRGRP; 316 1.1 mrg if (ugo[2] || honor_umask) 317 1.1 mrg new_mode |= S_IROTH; 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg /* Write. */ 321 1.1 mrg if (rwxXstugo[1]) 322 1.1 mrg { 323 1.1 mrg if (ugo[0] || honor_umask) 324 1.1 mrg new_mode |= S_IWUSR; 325 1.1 mrg if (ugo[1] || honor_umask) 326 1.1 mrg new_mode |= S_IWGRP; 327 1.1 mrg if (ugo[2] || honor_umask) 328 1.1 mrg new_mode |= S_IWOTH; 329 1.1 mrg } 330 1.1 mrg 331 1.1 mrg /* Execute. */ 332 1.1 mrg if (rwxXstugo[2]) 333 1.1 mrg { 334 1.1 mrg if (ugo[0] || honor_umask) 335 1.1 mrg new_mode |= S_IXUSR; 336 1.1 mrg if (ugo[1] || honor_umask) 337 1.1 mrg new_mode |= S_IXGRP; 338 1.1 mrg if (ugo[2] || honor_umask) 339 1.1 mrg new_mode |= S_IXOTH; 340 1.1 mrg } 341 1.1 mrg 342 1.1 mrg /* 'X' execute. */ 343 1.1 mrg if (rwxXstugo[3] 344 1.1 mrg && (is_dir || (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) 345 1.1 mrg new_mode |= (S_IXUSR | S_IXGRP | S_IXOTH); 346 1.1 mrg 347 1.1 mrg /* 's'. */ 348 1.1 mrg if (rwxXstugo[4]) 349 1.1 mrg { 350 1.1 mrg if (ugo[0] || honor_umask) 351 1.1 mrg new_mode |= S_ISUID; 352 1.1 mrg if (ugo[1] || honor_umask) 353 1.1 mrg new_mode |= S_ISGID; 354 1.1 mrg } 355 1.1 mrg 356 1.1 mrg /* As original 'u'. */ 357 1.1 mrg if (rwxXstugo[6]) 358 1.1 mrg { 359 1.1 mrg if (ugo[1] || honor_umask) 360 1.1 mrg { 361 1.1 mrg if (file_mode & S_IRUSR) 362 1.1 mrg new_mode |= S_IRGRP; 363 1.1 mrg if (file_mode & S_IWUSR) 364 1.1 mrg new_mode |= S_IWGRP; 365 1.1 mrg if (file_mode & S_IXUSR) 366 1.1 mrg new_mode |= S_IXGRP; 367 1.1 mrg } 368 1.1 mrg if (ugo[2] || honor_umask) 369 1.1 mrg { 370 1.1 mrg if (file_mode & S_IRUSR) 371 1.1 mrg new_mode |= S_IROTH; 372 1.1 mrg if (file_mode & S_IWUSR) 373 1.1 mrg new_mode |= S_IWOTH; 374 1.1 mrg if (file_mode & S_IXUSR) 375 1.1 mrg new_mode |= S_IXOTH; 376 1.1 mrg } 377 1.1 mrg } 378 1.1 mrg 379 1.1 mrg /* As original 'g'. */ 380 1.1 mrg if (rwxXstugo[7]) 381 1.1 mrg { 382 1.1 mrg if (ugo[0] || honor_umask) 383 1.1 mrg { 384 1.1 mrg if (file_mode & S_IRGRP) 385 1.1 mrg new_mode |= S_IRUSR; 386 1.1 mrg if (file_mode & S_IWGRP) 387 1.1 mrg new_mode |= S_IWUSR; 388 1.1 mrg if (file_mode & S_IXGRP) 389 1.1 mrg new_mode |= S_IXUSR; 390 1.1 mrg } 391 1.1 mrg if (ugo[2] || honor_umask) 392 1.1 mrg { 393 1.1 mrg if (file_mode & S_IRGRP) 394 1.1 mrg new_mode |= S_IROTH; 395 1.1 mrg if (file_mode & S_IWGRP) 396 1.1 mrg new_mode |= S_IWOTH; 397 1.1 mrg if (file_mode & S_IXGRP) 398 1.1 mrg new_mode |= S_IXOTH; 399 1.1 mrg } 400 1.1 mrg } 401 1.1 mrg 402 1.1 mrg /* As original 'o'. */ 403 1.1 mrg if (rwxXstugo[8]) 404 1.1 mrg { 405 1.1 mrg if (ugo[0] || honor_umask) 406 1.1 mrg { 407 1.1 mrg if (file_mode & S_IROTH) 408 1.1 mrg new_mode |= S_IRUSR; 409 1.1 mrg if (file_mode & S_IWOTH) 410 1.1 mrg new_mode |= S_IWUSR; 411 1.1 mrg if (file_mode & S_IXOTH) 412 1.1 mrg new_mode |= S_IXUSR; 413 1.1 mrg } 414 1.1 mrg if (ugo[1] || honor_umask) 415 1.1 mrg { 416 1.1 mrg if (file_mode & S_IROTH) 417 1.1 mrg new_mode |= S_IRGRP; 418 1.1 mrg if (file_mode & S_IWOTH) 419 1.1 mrg new_mode |= S_IWGRP; 420 1.1 mrg if (file_mode & S_IXOTH) 421 1.1 mrg new_mode |= S_IXGRP; 422 1.1 mrg } 423 1.1 mrg } 424 1.1 mrg #endif /* __MINGW32__ */ 425 1.1 mrg 426 1.1 mrg #ifdef HAVE_UMASK 427 1.1 mrg if (honor_umask) 428 1.1 mrg new_mode &= ~mode_mask; 429 1.1 mrg #endif 430 1.1 mrg 431 1.1 mrg if (set_mode == 1) 432 1.1 mrg { 433 1.1 mrg #ifdef __MINGW32__ 434 1.1 mrg if (ugo[0] || honor_umask) 435 1.1 mrg file_mode = (file_mode & ~(_S_IWRITE | _S_IREAD)) 436 1.1 mrg | (new_mode & (_S_IWRITE | _S_IREAD)); 437 1.1 mrg #else 438 1.1 mrg /* Set '='. */ 439 1.1 mrg if ((ugo[0] || honor_umask) && !rwxXstugo[6]) 440 1.1 mrg file_mode = (file_mode & ~(S_ISUID | S_IRUSR | S_IWUSR | S_IXUSR)) 441 1.1 mrg | (new_mode & (S_ISUID | S_IRUSR | S_IWUSR | S_IXUSR)); 442 1.1 mrg if ((ugo[1] || honor_umask) && !rwxXstugo[7]) 443 1.1 mrg file_mode = (file_mode & ~(S_ISGID | S_IRGRP | S_IWGRP | S_IXGRP)) 444 1.1 mrg | (new_mode & (S_ISGID | S_IRGRP | S_IWGRP | S_IXGRP)); 445 1.1 mrg if ((ugo[2] || honor_umask) && !rwxXstugo[8]) 446 1.1 mrg file_mode = (file_mode & ~(S_IROTH | S_IWOTH | S_IXOTH)) 447 1.1 mrg | (new_mode & (S_IROTH | S_IWOTH | S_IXOTH)); 448 1.1 mrg #ifndef __VXWORKS__ 449 1.1 mrg if (is_dir && rwxXstugo[5]) 450 1.1 mrg file_mode |= S_ISVTX; 451 1.1 mrg else if (!is_dir) 452 1.1 mrg file_mode &= ~S_ISVTX; 453 1.1 mrg #endif 454 1.1 mrg #endif 455 1.1 mrg } 456 1.1 mrg else if (set_mode == 2) 457 1.1 mrg { 458 1.1 mrg /* Clear '-'. */ 459 1.1 mrg file_mode &= ~new_mode; 460 1.1 mrg #if !defined( __MINGW32__) && !defined (__VXWORKS__) 461 1.1 mrg if (rwxXstugo[5] || !is_dir) 462 1.1 mrg file_mode &= ~S_ISVTX; 463 1.1 mrg #endif 464 1.1 mrg } 465 1.1 mrg else if (set_mode == 3) 466 1.1 mrg { 467 1.1 mrg file_mode |= new_mode; 468 1.1 mrg #if !defined (__MINGW32__) && !defined (__VXWORKS__) 469 1.1 mrg if (rwxXstugo[5] && is_dir) 470 1.1 mrg file_mode |= S_ISVTX; 471 1.1 mrg else if (!is_dir) 472 1.1 mrg file_mode &= ~S_ISVTX; 473 1.1 mrg #endif 474 1.1 mrg } 475 1.1 mrg } 476 1.1 mrg 477 1.1 mrg return chmod (file, file_mode); 478 1.1 mrg } 479 1.1 mrg 480 1.1 mrg 481 1.1 mrg extern int chmod_func (char *, char *, gfc_charlen_type, gfc_charlen_type); 482 1.1 mrg export_proto(chmod_func); 483 1.1 mrg 484 1.1 mrg int 485 1.1 mrg chmod_func (char *name, char *mode, gfc_charlen_type name_len, 486 1.1 mrg gfc_charlen_type mode_len) 487 1.1 mrg { 488 1.1 mrg char *cname = fc_strdup (name, name_len); 489 1.1 mrg int ret = chmod_internal (cname, mode, mode_len); 490 1.1 mrg free (cname); 491 1.1 mrg return ret; 492 1.1 mrg } 493 1.1 mrg 494 1.1 mrg 495 1.1 mrg extern void chmod_i4_sub (char *, char *, GFC_INTEGER_4 *, 496 1.1 mrg gfc_charlen_type, gfc_charlen_type); 497 1.1 mrg export_proto(chmod_i4_sub); 498 1.1 mrg 499 1.1 mrg void 500 1.1 mrg chmod_i4_sub (char *name, char *mode, GFC_INTEGER_4 * status, 501 1.1 mrg gfc_charlen_type name_len, gfc_charlen_type mode_len) 502 1.1 mrg { 503 1.1 mrg int val; 504 1.1 mrg 505 1.1 mrg val = chmod_func (name, mode, name_len, mode_len); 506 1.1 mrg if (status) 507 1.1 mrg *status = val; 508 1.1 mrg } 509 1.1 mrg 510 1.1 mrg 511 1.1 mrg extern void chmod_i8_sub (char *, char *, GFC_INTEGER_8 *, 512 1.1 mrg gfc_charlen_type, gfc_charlen_type); 513 1.1 mrg export_proto(chmod_i8_sub); 514 1.1 mrg 515 1.1 mrg void 516 1.1 mrg chmod_i8_sub (char *name, char *mode, GFC_INTEGER_8 * status, 517 1.1 mrg gfc_charlen_type name_len, gfc_charlen_type mode_len) 518 1.1 mrg { 519 1.1 mrg int val; 520 1.1 mrg 521 1.1 mrg val = chmod_func (name, mode, name_len, mode_len); 522 1.1 mrg if (status) 523 1.1 mrg *status = val; 524 1.1 mrg } 525 1.1 mrg 526 1.1 mrg #endif 527