1 /* Implementation of the STAT and FSTAT intrinsics.
2 Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 Contributed by Steven G. Kargl <kargls@comcast.net>.
5 This file is part of the GNU Fortran 95 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 2 of the License, or (at your option) any later version.
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public
27 License along with libgfortran; see the file COPYING. If not,
28 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
31 #include "libgfortran.h"
36 #ifdef HAVE_SYS_STAT_H
47 /* SUBROUTINE STAT(FILE, SARRAY, STATUS)
48 CHARACTER(len=*), INTENT(IN) :: FILE
49 INTEGER, INTENT(OUT), :: SARRAY(13)
50 INTEGER, INTENT(OUT), OPTIONAL :: STATUS
52 FUNCTION STAT(FILE, SARRAY)
54 CHARACTER(len=*), INTENT(IN) :: FILE
55 INTEGER, INTENT(OUT), :: SARRAY(13) */
57 /*extern void stat_i4_sub_0 (char *, gfc_array_i4 *, GFC_INTEGER_4 *,
58 gfc_charlen_type, int);
59 internal_proto(stat_i4_sub_0);*/
62 stat_i4_sub_0 (char *name
, gfc_array_i4
*sarray
, GFC_INTEGER_4
*status
,
63 gfc_charlen_type name_len
, int is_lstat
)
69 /* If the rank of the array is not 1, abort. */
70 if (GFC_DESCRIPTOR_RANK (sarray
) != 1)
71 runtime_error ("Array rank of SARRAY is not 1.");
73 /* If the array is too small, abort. */
74 if (sarray
->dim
[0].ubound
+ 1 - sarray
->dim
[0].lbound
< 13)
75 runtime_error ("Array size of SARRAY is too small.");
77 /* Trim trailing spaces from name. */
78 while (name_len
> 0 && name
[name_len
- 1] == ' ')
81 /* Make a null terminated copy of the string. */
82 str
= gfc_alloca (name_len
+ 1);
83 memcpy (str
, name
, name_len
);
86 /* On platforms that don't provide lstat(), we use stat() instead. */
89 val
= lstat(str
, &sb
);
97 sarray
->data
[0 * sarray
->dim
[0].stride
] = sb
.st_dev
;
100 sarray
->data
[1 * sarray
->dim
[0].stride
] = sb
.st_ino
;
103 sarray
->data
[2 * sarray
->dim
[0].stride
] = sb
.st_mode
;
105 /* Number of (hard) links */
106 sarray
->data
[3 * sarray
->dim
[0].stride
] = sb
.st_nlink
;
109 sarray
->data
[4 * sarray
->dim
[0].stride
] = sb
.st_uid
;
112 sarray
->data
[5 * sarray
->dim
[0].stride
] = sb
.st_gid
;
114 /* ID of device containing directory entry for file (0 if not available) */
115 #if HAVE_STRUCT_STAT_ST_RDEV
116 sarray
->data
[6 * sarray
->dim
[0].stride
] = sb
.st_rdev
;
118 sarray
->data
[6 * sarray
->dim
[0].stride
] = 0;
121 /* File size (bytes) */
122 sarray
->data
[7 * sarray
->dim
[0].stride
] = sb
.st_size
;
124 /* Last access time */
125 sarray
->data
[8 * sarray
->dim
[0].stride
] = sb
.st_atime
;
127 /* Last modification time */
128 sarray
->data
[9 * sarray
->dim
[0].stride
] = sb
.st_mtime
;
130 /* Last file status change time */
131 sarray
->data
[10 * sarray
->dim
[0].stride
] = sb
.st_ctime
;
133 /* Preferred I/O block size (-1 if not available) */
134 #if HAVE_STRUCT_STAT_ST_BLKSIZE
135 sarray
->data
[11 * sarray
->dim
[0].stride
] = sb
.st_blksize
;
137 sarray
->data
[11 * sarray
->dim
[0].stride
] = -1;
140 /* Number of blocks allocated (-1 if not available) */
141 #if HAVE_STRUCT_STAT_ST_BLOCKS
142 sarray
->data
[12 * sarray
->dim
[0].stride
] = sb
.st_blocks
;
144 sarray
->data
[12 * sarray
->dim
[0].stride
] = -1;
149 *status
= (val
== 0) ? 0 : errno
;
153 extern void stat_i4_sub (char *, gfc_array_i4
*, GFC_INTEGER_4
*,
155 iexport_proto(stat_i4_sub
);
158 stat_i4_sub (char *name
, gfc_array_i4
*sarray
, GFC_INTEGER_4
*status
,
159 gfc_charlen_type name_len
)
161 stat_i4_sub_0 (name
, sarray
, status
, name_len
, 0);
163 iexport(stat_i4_sub
);
166 extern void lstat_i4_sub (char *, gfc_array_i4
*, GFC_INTEGER_4
*,
168 iexport_proto(lstat_i4_sub
);
171 lstat_i4_sub (char *name
, gfc_array_i4
*sarray
, GFC_INTEGER_4
*status
,
172 gfc_charlen_type name_len
)
174 stat_i4_sub_0 (name
, sarray
, status
, name_len
, 1);
176 iexport(lstat_i4_sub
);
181 stat_i8_sub_0 (char *name
, gfc_array_i8
*sarray
, GFC_INTEGER_8
*status
,
182 gfc_charlen_type name_len
, int is_lstat
)
188 /* If the rank of the array is not 1, abort. */
189 if (GFC_DESCRIPTOR_RANK (sarray
) != 1)
190 runtime_error ("Array rank of SARRAY is not 1.");
192 /* If the array is too small, abort. */
193 if (sarray
->dim
[0].ubound
+ 1 - sarray
->dim
[0].lbound
< 13)
194 runtime_error ("Array size of SARRAY is too small.");
196 /* Trim trailing spaces from name. */
197 while (name_len
> 0 && name
[name_len
- 1] == ' ')
200 /* Make a null terminated copy of the string. */
201 str
= gfc_alloca (name_len
+ 1);
202 memcpy (str
, name
, name_len
);
203 str
[name_len
] = '\0';
205 /* On platforms that don't provide lstat(), we use stat() instead. */
208 val
= lstat(str
, &sb
);
211 val
= stat(str
, &sb
);
216 sarray
->data
[0] = sb
.st_dev
;
219 sarray
->data
[sarray
->dim
[0].stride
] = sb
.st_ino
;
222 sarray
->data
[2 * sarray
->dim
[0].stride
] = sb
.st_mode
;
224 /* Number of (hard) links */
225 sarray
->data
[3 * sarray
->dim
[0].stride
] = sb
.st_nlink
;
228 sarray
->data
[4 * sarray
->dim
[0].stride
] = sb
.st_uid
;
231 sarray
->data
[5 * sarray
->dim
[0].stride
] = sb
.st_gid
;
233 /* ID of device containing directory entry for file (0 if not available) */
234 #if HAVE_STRUCT_STAT_ST_RDEV
235 sarray
->data
[6 * sarray
->dim
[0].stride
] = sb
.st_rdev
;
237 sarray
->data
[6 * sarray
->dim
[0].stride
] = 0;
240 /* File size (bytes) */
241 sarray
->data
[7 * sarray
->dim
[0].stride
] = sb
.st_size
;
243 /* Last access time */
244 sarray
->data
[8 * sarray
->dim
[0].stride
] = sb
.st_atime
;
246 /* Last modification time */
247 sarray
->data
[9 * sarray
->dim
[0].stride
] = sb
.st_mtime
;
249 /* Last file status change time */
250 sarray
->data
[10 * sarray
->dim
[0].stride
] = sb
.st_ctime
;
252 /* Preferred I/O block size (-1 if not available) */
253 #if HAVE_STRUCT_STAT_ST_BLKSIZE
254 sarray
->data
[11 * sarray
->dim
[0].stride
] = sb
.st_blksize
;
256 sarray
->data
[11 * sarray
->dim
[0].stride
] = -1;
259 /* Number of blocks allocated (-1 if not available) */
260 #if HAVE_STRUCT_STAT_ST_BLOCKS
261 sarray
->data
[12 * sarray
->dim
[0].stride
] = sb
.st_blocks
;
263 sarray
->data
[12 * sarray
->dim
[0].stride
] = -1;
268 *status
= (val
== 0) ? 0 : errno
;
272 extern void stat_i8_sub (char *, gfc_array_i8
*, GFC_INTEGER_8
*,
274 iexport_proto(stat_i8_sub
);
277 stat_i8_sub (char *name
, gfc_array_i8
*sarray
, GFC_INTEGER_8
*status
,
278 gfc_charlen_type name_len
)
280 stat_i8_sub_0 (name
, sarray
, status
, name_len
, 0);
283 iexport(stat_i8_sub
);
286 extern void lstat_i8_sub (char *, gfc_array_i8
*, GFC_INTEGER_8
*,
288 iexport_proto(lstat_i8_sub
);
291 lstat_i8_sub (char *name
, gfc_array_i8
*sarray
, GFC_INTEGER_8
*status
,
292 gfc_charlen_type name_len
)
294 stat_i8_sub_0 (name
, sarray
, status
, name_len
, 1);
297 iexport(lstat_i8_sub
);
300 extern GFC_INTEGER_4
stat_i4 (char *, gfc_array_i4
*, gfc_charlen_type
);
301 export_proto(stat_i4
);
304 stat_i4 (char *name
, gfc_array_i4
*sarray
, gfc_charlen_type name_len
)
307 stat_i4_sub (name
, sarray
, &val
, name_len
);
311 extern GFC_INTEGER_8
stat_i8 (char *, gfc_array_i8
*, gfc_charlen_type
);
312 export_proto(stat_i8
);
315 stat_i8 (char *name
, gfc_array_i8
*sarray
, gfc_charlen_type name_len
)
318 stat_i8_sub (name
, sarray
, &val
, name_len
);
323 /* SUBROUTINE LSTAT(FILE, SARRAY, STATUS)
324 CHARACTER(len=*), INTENT(IN) :: FILE
325 INTEGER, INTENT(OUT), :: SARRAY(13)
326 INTEGER, INTENT(OUT), OPTIONAL :: STATUS
328 FUNCTION LSTAT(FILE, SARRAY)
330 CHARACTER(len=*), INTENT(IN) :: FILE
331 INTEGER, INTENT(OUT), :: SARRAY(13) */
333 extern GFC_INTEGER_4
lstat_i4 (char *, gfc_array_i4
*, gfc_charlen_type
);
334 export_proto(lstat_i4
);
337 lstat_i4 (char *name
, gfc_array_i4
*sarray
, gfc_charlen_type name_len
)
340 lstat_i4_sub (name
, sarray
, &val
, name_len
);
344 extern GFC_INTEGER_8
lstat_i8 (char *, gfc_array_i8
*, gfc_charlen_type
);
345 export_proto(lstat_i8
);
348 lstat_i8 (char *name
, gfc_array_i8
*sarray
, gfc_charlen_type name_len
)
351 lstat_i8_sub (name
, sarray
, &val
, name_len
);
360 /* SUBROUTINE FSTAT(UNIT, SARRAY, STATUS)
361 INTEGER, INTENT(IN) :: UNIT
362 INTEGER, INTENT(OUT) :: SARRAY(13)
363 INTEGER, INTENT(OUT), OPTIONAL :: STATUS
365 FUNCTION FSTAT(UNIT, SARRAY)
367 INTEGER, INTENT(IN) :: UNIT
368 INTEGER, INTENT(OUT) :: SARRAY(13) */
370 extern void fstat_i4_sub (GFC_INTEGER_4
*, gfc_array_i4
*, GFC_INTEGER_4
*);
371 iexport_proto(fstat_i4_sub
);
374 fstat_i4_sub (GFC_INTEGER_4
*unit
, gfc_array_i4
*sarray
, GFC_INTEGER_4
*status
)
379 /* If the rank of the array is not 1, abort. */
380 if (GFC_DESCRIPTOR_RANK (sarray
) != 1)
381 runtime_error ("Array rank of SARRAY is not 1.");
383 /* If the array is too small, abort. */
384 if (sarray
->dim
[0].ubound
+ 1 - sarray
->dim
[0].lbound
< 13)
385 runtime_error ("Array size of SARRAY is too small.");
387 /* Convert Fortran unit number to C file descriptor. */
388 val
= unit_to_fd (*unit
);
390 val
= fstat(val
, &sb
);
395 sarray
->data
[0 * sarray
->dim
[0].stride
] = sb
.st_dev
;
398 sarray
->data
[1 * sarray
->dim
[0].stride
] = sb
.st_ino
;
401 sarray
->data
[2 * sarray
->dim
[0].stride
] = sb
.st_mode
;
403 /* Number of (hard) links */
404 sarray
->data
[3 * sarray
->dim
[0].stride
] = sb
.st_nlink
;
407 sarray
->data
[4 * sarray
->dim
[0].stride
] = sb
.st_uid
;
410 sarray
->data
[5 * sarray
->dim
[0].stride
] = sb
.st_gid
;
412 /* ID of device containing directory entry for file (0 if not available) */
413 #if HAVE_STRUCT_STAT_ST_RDEV
414 sarray
->data
[6 * sarray
->dim
[0].stride
] = sb
.st_rdev
;
416 sarray
->data
[6 * sarray
->dim
[0].stride
] = 0;
419 /* File size (bytes) */
420 sarray
->data
[7 * sarray
->dim
[0].stride
] = sb
.st_size
;
422 /* Last access time */
423 sarray
->data
[8 * sarray
->dim
[0].stride
] = sb
.st_atime
;
425 /* Last modification time */
426 sarray
->data
[9 * sarray
->dim
[0].stride
] = sb
.st_mtime
;
428 /* Last file status change time */
429 sarray
->data
[10 * sarray
->dim
[0].stride
] = sb
.st_ctime
;
431 /* Preferred I/O block size (-1 if not available) */
432 #if HAVE_STRUCT_STAT_ST_BLKSIZE
433 sarray
->data
[11 * sarray
->dim
[0].stride
] = sb
.st_blksize
;
435 sarray
->data
[11 * sarray
->dim
[0].stride
] = -1;
438 /* Number of blocks allocated (-1 if not available) */
439 #if HAVE_STRUCT_STAT_ST_BLOCKS
440 sarray
->data
[12 * sarray
->dim
[0].stride
] = sb
.st_blocks
;
442 sarray
->data
[12 * sarray
->dim
[0].stride
] = -1;
447 *status
= (val
== 0) ? 0 : errno
;
449 iexport(fstat_i4_sub
);
451 extern void fstat_i8_sub (GFC_INTEGER_8
*, gfc_array_i8
*, GFC_INTEGER_8
*);
452 iexport_proto(fstat_i8_sub
);
455 fstat_i8_sub (GFC_INTEGER_8
*unit
, gfc_array_i8
*sarray
, GFC_INTEGER_8
*status
)
460 /* If the rank of the array is not 1, abort. */
461 if (GFC_DESCRIPTOR_RANK (sarray
) != 1)
462 runtime_error ("Array rank of SARRAY is not 1.");
464 /* If the array is too small, abort. */
465 if (sarray
->dim
[0].ubound
+ 1 - sarray
->dim
[0].lbound
< 13)
466 runtime_error ("Array size of SARRAY is too small.");
468 /* Convert Fortran unit number to C file descriptor. */
469 val
= unit_to_fd ((int) *unit
);
471 val
= fstat(val
, &sb
);
476 sarray
->data
[0] = sb
.st_dev
;
479 sarray
->data
[sarray
->dim
[0].stride
] = sb
.st_ino
;
482 sarray
->data
[2 * sarray
->dim
[0].stride
] = sb
.st_mode
;
484 /* Number of (hard) links */
485 sarray
->data
[3 * sarray
->dim
[0].stride
] = sb
.st_nlink
;
488 sarray
->data
[4 * sarray
->dim
[0].stride
] = sb
.st_uid
;
491 sarray
->data
[5 * sarray
->dim
[0].stride
] = sb
.st_gid
;
493 /* ID of device containing directory entry for file (0 if not available) */
494 #if HAVE_STRUCT_STAT_ST_RDEV
495 sarray
->data
[6 * sarray
->dim
[0].stride
] = sb
.st_rdev
;
497 sarray
->data
[6 * sarray
->dim
[0].stride
] = 0;
500 /* File size (bytes) */
501 sarray
->data
[7 * sarray
->dim
[0].stride
] = sb
.st_size
;
503 /* Last access time */
504 sarray
->data
[8 * sarray
->dim
[0].stride
] = sb
.st_atime
;
506 /* Last modification time */
507 sarray
->data
[9 * sarray
->dim
[0].stride
] = sb
.st_mtime
;
509 /* Last file status change time */
510 sarray
->data
[10 * sarray
->dim
[0].stride
] = sb
.st_ctime
;
512 /* Preferred I/O block size (-1 if not available) */
513 #if HAVE_STRUCT_STAT_ST_BLKSIZE
514 sarray
->data
[11 * sarray
->dim
[0].stride
] = sb
.st_blksize
;
516 sarray
->data
[11 * sarray
->dim
[0].stride
] = -1;
519 /* Number of blocks allocated (-1 if not available) */
520 #if HAVE_STRUCT_STAT_ST_BLOCKS
521 sarray
->data
[12 * sarray
->dim
[0].stride
] = sb
.st_blocks
;
523 sarray
->data
[12 * sarray
->dim
[0].stride
] = -1;
528 *status
= (val
== 0) ? 0 : errno
;
530 iexport(fstat_i8_sub
);
532 extern GFC_INTEGER_4
fstat_i4 (GFC_INTEGER_4
*, gfc_array_i4
*);
533 export_proto(fstat_i4
);
536 fstat_i4 (GFC_INTEGER_4
*unit
, gfc_array_i4
*sarray
)
539 fstat_i4_sub (unit
, sarray
, &val
);
543 extern GFC_INTEGER_8
fstat_i8 (GFC_INTEGER_8
*, gfc_array_i8
*);
544 export_proto(fstat_i8
);
547 fstat_i8 (GFC_INTEGER_8
*unit
, gfc_array_i8
*sarray
)
550 fstat_i8_sub (unit
, sarray
, &val
);