* tree-outof-ssa.h (ssaexpand): Add partitions_for_undefined_values.
[official-gcc.git] / libgfortran / intrinsics / stat.c
blob6391c13eea0816f749b89d7674c5ba7c4e51b2c4
1 /* Implementation of the STAT and FSTAT intrinsics.
2 Copyright (C) 2004-2017 Free Software Foundation, Inc.
3 Contributed by Steven G. Kargl <kargls@comcast.net>.
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
28 #include <errno.h>
30 #ifdef HAVE_SYS_STAT_H
31 #include <sys/stat.h>
32 #endif
36 #ifdef HAVE_STAT
38 /* SUBROUTINE STAT(FILE, SARRAY, STATUS)
39 CHARACTER(len=*), INTENT(IN) :: FILE
40 INTEGER, INTENT(OUT), :: SARRAY(13)
41 INTEGER, INTENT(OUT), OPTIONAL :: STATUS
43 FUNCTION STAT(FILE, SARRAY)
44 INTEGER STAT
45 CHARACTER(len=*), INTENT(IN) :: FILE
46 INTEGER, INTENT(OUT), :: SARRAY(13) */
48 /*extern void stat_i4_sub_0 (char *, gfc_array_i4 *, GFC_INTEGER_4 *,
49 gfc_charlen_type, int);
50 internal_proto(stat_i4_sub_0);*/
52 static void
53 stat_i4_sub_0 (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status,
54 gfc_charlen_type name_len, int is_lstat __attribute__ ((unused)))
56 int val;
57 char *str;
58 struct stat sb;
60 /* If the rank of the array is not 1, abort. */
61 if (GFC_DESCRIPTOR_RANK (sarray) != 1)
62 runtime_error ("Array rank of SARRAY is not 1.");
64 /* If the array is too small, abort. */
65 if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
66 runtime_error ("Array size of SARRAY is too small.");
68 /* Make a null terminated copy of the string. */
69 str = fc_strdup (name, name_len);
71 /* On platforms that don't provide lstat(), we use stat() instead. */
72 #ifdef HAVE_LSTAT
73 if (is_lstat)
74 val = lstat(str, &sb);
75 else
76 #endif
77 val = stat(str, &sb);
79 free (str);
81 if (val == 0)
83 index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
85 /* Device ID */
86 sarray->base_addr[0 * stride] = sb.st_dev;
88 /* Inode number */
89 sarray->base_addr[1 * stride] = sb.st_ino;
91 /* File mode */
92 sarray->base_addr[2 * stride] = sb.st_mode;
94 /* Number of (hard) links */
95 sarray->base_addr[3 * stride] = sb.st_nlink;
97 /* Owner's uid */
98 sarray->base_addr[4 * stride] = sb.st_uid;
100 /* Owner's gid */
101 sarray->base_addr[5 * stride] = sb.st_gid;
103 /* ID of device containing directory entry for file (0 if not available) */
104 #if HAVE_STRUCT_STAT_ST_RDEV
105 sarray->base_addr[6 * stride] = sb.st_rdev;
106 #else
107 sarray->base_addr[6 * stride] = 0;
108 #endif
110 /* File size (bytes) */
111 sarray->base_addr[7 * stride] = sb.st_size;
113 /* Last access time */
114 sarray->base_addr[8 * stride] = sb.st_atime;
116 /* Last modification time */
117 sarray->base_addr[9 * stride] = sb.st_mtime;
119 /* Last file status change time */
120 sarray->base_addr[10 * stride] = sb.st_ctime;
122 /* Preferred I/O block size (-1 if not available) */
123 #if HAVE_STRUCT_STAT_ST_BLKSIZE
124 sarray->base_addr[11 * stride] = sb.st_blksize;
125 #else
126 sarray->base_addr[11 * stride] = -1;
127 #endif
129 /* Number of blocks allocated (-1 if not available) */
130 #if HAVE_STRUCT_STAT_ST_BLOCKS
131 sarray->base_addr[12 * stride] = sb.st_blocks;
132 #else
133 sarray->base_addr[12 * stride] = -1;
134 #endif
137 if (status != NULL)
138 *status = (val == 0) ? 0 : errno;
142 extern void stat_i4_sub (char *, gfc_array_i4 *, GFC_INTEGER_4 *,
143 gfc_charlen_type);
144 iexport_proto(stat_i4_sub);
146 void
147 stat_i4_sub (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status,
148 gfc_charlen_type name_len)
150 stat_i4_sub_0 (name, sarray, status, name_len, 0);
152 iexport(stat_i4_sub);
155 extern void lstat_i4_sub (char *, gfc_array_i4 *, GFC_INTEGER_4 *,
156 gfc_charlen_type);
157 iexport_proto(lstat_i4_sub);
159 void
160 lstat_i4_sub (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status,
161 gfc_charlen_type name_len)
163 stat_i4_sub_0 (name, sarray, status, name_len, 1);
165 iexport(lstat_i4_sub);
169 static void
170 stat_i8_sub_0 (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status,
171 gfc_charlen_type name_len, int is_lstat __attribute__ ((unused)))
173 int val;
174 char *str;
175 struct stat sb;
177 /* If the rank of the array is not 1, abort. */
178 if (GFC_DESCRIPTOR_RANK (sarray) != 1)
179 runtime_error ("Array rank of SARRAY is not 1.");
181 /* If the array is too small, abort. */
182 if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
183 runtime_error ("Array size of SARRAY is too small.");
185 /* Make a null terminated copy of the string. */
186 str = fc_strdup (name, name_len);
188 /* On platforms that don't provide lstat(), we use stat() instead. */
189 #ifdef HAVE_LSTAT
190 if (is_lstat)
191 val = lstat(str, &sb);
192 else
193 #endif
194 val = stat(str, &sb);
196 free (str);
198 if (val == 0)
200 index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
202 /* Device ID */
203 sarray->base_addr[0] = sb.st_dev;
205 /* Inode number */
206 sarray->base_addr[stride] = sb.st_ino;
208 /* File mode */
209 sarray->base_addr[2 * stride] = sb.st_mode;
211 /* Number of (hard) links */
212 sarray->base_addr[3 * stride] = sb.st_nlink;
214 /* Owner's uid */
215 sarray->base_addr[4 * stride] = sb.st_uid;
217 /* Owner's gid */
218 sarray->base_addr[5 * stride] = sb.st_gid;
220 /* ID of device containing directory entry for file (0 if not available) */
221 #if HAVE_STRUCT_STAT_ST_RDEV
222 sarray->base_addr[6 * stride] = sb.st_rdev;
223 #else
224 sarray->base_addr[6 * stride] = 0;
225 #endif
227 /* File size (bytes) */
228 sarray->base_addr[7 * stride] = sb.st_size;
230 /* Last access time */
231 sarray->base_addr[8 * stride] = sb.st_atime;
233 /* Last modification time */
234 sarray->base_addr[9 * stride] = sb.st_mtime;
236 /* Last file status change time */
237 sarray->base_addr[10 * stride] = sb.st_ctime;
239 /* Preferred I/O block size (-1 if not available) */
240 #if HAVE_STRUCT_STAT_ST_BLKSIZE
241 sarray->base_addr[11 * stride] = sb.st_blksize;
242 #else
243 sarray->base_addr[11 * stride] = -1;
244 #endif
246 /* Number of blocks allocated (-1 if not available) */
247 #if HAVE_STRUCT_STAT_ST_BLOCKS
248 sarray->base_addr[12 * stride] = sb.st_blocks;
249 #else
250 sarray->base_addr[12 * stride] = -1;
251 #endif
254 if (status != NULL)
255 *status = (val == 0) ? 0 : errno;
259 extern void stat_i8_sub (char *, gfc_array_i8 *, GFC_INTEGER_8 *,
260 gfc_charlen_type);
261 iexport_proto(stat_i8_sub);
263 void
264 stat_i8_sub (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status,
265 gfc_charlen_type name_len)
267 stat_i8_sub_0 (name, sarray, status, name_len, 0);
270 iexport(stat_i8_sub);
273 extern void lstat_i8_sub (char *, gfc_array_i8 *, GFC_INTEGER_8 *,
274 gfc_charlen_type);
275 iexport_proto(lstat_i8_sub);
277 void
278 lstat_i8_sub (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status,
279 gfc_charlen_type name_len)
281 stat_i8_sub_0 (name, sarray, status, name_len, 1);
284 iexport(lstat_i8_sub);
287 extern GFC_INTEGER_4 stat_i4 (char *, gfc_array_i4 *, gfc_charlen_type);
288 export_proto(stat_i4);
290 GFC_INTEGER_4
291 stat_i4 (char *name, gfc_array_i4 *sarray, gfc_charlen_type name_len)
293 GFC_INTEGER_4 val;
294 stat_i4_sub (name, sarray, &val, name_len);
295 return val;
298 extern GFC_INTEGER_8 stat_i8 (char *, gfc_array_i8 *, gfc_charlen_type);
299 export_proto(stat_i8);
301 GFC_INTEGER_8
302 stat_i8 (char *name, gfc_array_i8 *sarray, gfc_charlen_type name_len)
304 GFC_INTEGER_8 val;
305 stat_i8_sub (name, sarray, &val, name_len);
306 return val;
310 /* SUBROUTINE LSTAT(FILE, SARRAY, STATUS)
311 CHARACTER(len=*), INTENT(IN) :: FILE
312 INTEGER, INTENT(OUT), :: SARRAY(13)
313 INTEGER, INTENT(OUT), OPTIONAL :: STATUS
315 FUNCTION LSTAT(FILE, SARRAY)
316 INTEGER LSTAT
317 CHARACTER(len=*), INTENT(IN) :: FILE
318 INTEGER, INTENT(OUT), :: SARRAY(13) */
320 extern GFC_INTEGER_4 lstat_i4 (char *, gfc_array_i4 *, gfc_charlen_type);
321 export_proto(lstat_i4);
323 GFC_INTEGER_4
324 lstat_i4 (char *name, gfc_array_i4 *sarray, gfc_charlen_type name_len)
326 GFC_INTEGER_4 val;
327 lstat_i4_sub (name, sarray, &val, name_len);
328 return val;
331 extern GFC_INTEGER_8 lstat_i8 (char *, gfc_array_i8 *, gfc_charlen_type);
332 export_proto(lstat_i8);
334 GFC_INTEGER_8
335 lstat_i8 (char *name, gfc_array_i8 *sarray, gfc_charlen_type name_len)
337 GFC_INTEGER_8 val;
338 lstat_i8_sub (name, sarray, &val, name_len);
339 return val;
342 #endif
345 #ifdef HAVE_FSTAT
347 /* SUBROUTINE FSTAT(UNIT, SARRAY, STATUS)
348 INTEGER, INTENT(IN) :: UNIT
349 INTEGER, INTENT(OUT) :: SARRAY(13)
350 INTEGER, INTENT(OUT), OPTIONAL :: STATUS
352 FUNCTION FSTAT(UNIT, SARRAY)
353 INTEGER FSTAT
354 INTEGER, INTENT(IN) :: UNIT
355 INTEGER, INTENT(OUT) :: SARRAY(13) */
357 extern void fstat_i4_sub (GFC_INTEGER_4 *, gfc_array_i4 *, GFC_INTEGER_4 *);
358 iexport_proto(fstat_i4_sub);
360 void
361 fstat_i4_sub (GFC_INTEGER_4 *unit, gfc_array_i4 *sarray, GFC_INTEGER_4 *status)
363 int val;
364 struct stat sb;
366 /* If the rank of the array is not 1, abort. */
367 if (GFC_DESCRIPTOR_RANK (sarray) != 1)
368 runtime_error ("Array rank of SARRAY is not 1.");
370 /* If the array is too small, abort. */
371 if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
372 runtime_error ("Array size of SARRAY is too small.");
374 /* Convert Fortran unit number to C file descriptor. */
375 val = unit_to_fd (*unit);
376 if (val >= 0)
377 val = fstat(val, &sb);
379 if (val == 0)
381 index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
383 /* Device ID */
384 sarray->base_addr[0 * stride] = sb.st_dev;
386 /* Inode number */
387 sarray->base_addr[1 * stride] = sb.st_ino;
389 /* File mode */
390 sarray->base_addr[2 * stride] = sb.st_mode;
392 /* Number of (hard) links */
393 sarray->base_addr[3 * stride] = sb.st_nlink;
395 /* Owner's uid */
396 sarray->base_addr[4 * stride] = sb.st_uid;
398 /* Owner's gid */
399 sarray->base_addr[5 * stride] = sb.st_gid;
401 /* ID of device containing directory entry for file (0 if not available) */
402 #if HAVE_STRUCT_STAT_ST_RDEV
403 sarray->base_addr[6 * stride] = sb.st_rdev;
404 #else
405 sarray->base_addr[6 * stride] = 0;
406 #endif
408 /* File size (bytes) */
409 sarray->base_addr[7 * stride] = sb.st_size;
411 /* Last access time */
412 sarray->base_addr[8 * stride] = sb.st_atime;
414 /* Last modification time */
415 sarray->base_addr[9 * stride] = sb.st_mtime;
417 /* Last file status change time */
418 sarray->base_addr[10 * stride] = sb.st_ctime;
420 /* Preferred I/O block size (-1 if not available) */
421 #if HAVE_STRUCT_STAT_ST_BLKSIZE
422 sarray->base_addr[11 * stride] = sb.st_blksize;
423 #else
424 sarray->base_addr[11 * stride] = -1;
425 #endif
427 /* Number of blocks allocated (-1 if not available) */
428 #if HAVE_STRUCT_STAT_ST_BLOCKS
429 sarray->base_addr[12 * stride] = sb.st_blocks;
430 #else
431 sarray->base_addr[12 * stride] = -1;
432 #endif
435 if (status != NULL)
436 *status = (val == 0) ? 0 : errno;
438 iexport(fstat_i4_sub);
440 extern void fstat_i8_sub (GFC_INTEGER_8 *, gfc_array_i8 *, GFC_INTEGER_8 *);
441 iexport_proto(fstat_i8_sub);
443 void
444 fstat_i8_sub (GFC_INTEGER_8 *unit, gfc_array_i8 *sarray, GFC_INTEGER_8 *status)
446 int val;
447 struct stat sb;
449 /* If the rank of the array is not 1, abort. */
450 if (GFC_DESCRIPTOR_RANK (sarray) != 1)
451 runtime_error ("Array rank of SARRAY is not 1.");
453 /* If the array is too small, abort. */
454 if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
455 runtime_error ("Array size of SARRAY is too small.");
457 /* Convert Fortran unit number to C file descriptor. */
458 val = unit_to_fd ((int) *unit);
459 if (val >= 0)
460 val = fstat(val, &sb);
462 if (val == 0)
464 index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
466 /* Device ID */
467 sarray->base_addr[0] = sb.st_dev;
469 /* Inode number */
470 sarray->base_addr[stride] = sb.st_ino;
472 /* File mode */
473 sarray->base_addr[2 * stride] = sb.st_mode;
475 /* Number of (hard) links */
476 sarray->base_addr[3 * stride] = sb.st_nlink;
478 /* Owner's uid */
479 sarray->base_addr[4 * stride] = sb.st_uid;
481 /* Owner's gid */
482 sarray->base_addr[5 * stride] = sb.st_gid;
484 /* ID of device containing directory entry for file (0 if not available) */
485 #if HAVE_STRUCT_STAT_ST_RDEV
486 sarray->base_addr[6 * stride] = sb.st_rdev;
487 #else
488 sarray->base_addr[6 * stride] = 0;
489 #endif
491 /* File size (bytes) */
492 sarray->base_addr[7 * stride] = sb.st_size;
494 /* Last access time */
495 sarray->base_addr[8 * stride] = sb.st_atime;
497 /* Last modification time */
498 sarray->base_addr[9 * stride] = sb.st_mtime;
500 /* Last file status change time */
501 sarray->base_addr[10 * stride] = sb.st_ctime;
503 /* Preferred I/O block size (-1 if not available) */
504 #if HAVE_STRUCT_STAT_ST_BLKSIZE
505 sarray->base_addr[11 * stride] = sb.st_blksize;
506 #else
507 sarray->base_addr[11 * stride] = -1;
508 #endif
510 /* Number of blocks allocated (-1 if not available) */
511 #if HAVE_STRUCT_STAT_ST_BLOCKS
512 sarray->base_addr[12 * stride] = sb.st_blocks;
513 #else
514 sarray->base_addr[12 * stride] = -1;
515 #endif
518 if (status != NULL)
519 *status = (val == 0) ? 0 : errno;
521 iexport(fstat_i8_sub);
523 extern GFC_INTEGER_4 fstat_i4 (GFC_INTEGER_4 *, gfc_array_i4 *);
524 export_proto(fstat_i4);
526 GFC_INTEGER_4
527 fstat_i4 (GFC_INTEGER_4 *unit, gfc_array_i4 *sarray)
529 GFC_INTEGER_4 val;
530 fstat_i4_sub (unit, sarray, &val);
531 return val;
534 extern GFC_INTEGER_8 fstat_i8 (GFC_INTEGER_8 *, gfc_array_i8 *);
535 export_proto(fstat_i8);
537 GFC_INTEGER_8
538 fstat_i8 (GFC_INTEGER_8 *unit, gfc_array_i8 *sarray)
540 GFC_INTEGER_8 val;
541 fstat_i8_sub (unit, sarray, &val);
542 return val;
545 #endif