stat.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /* Implementation of the STAT and FSTAT intrinsics.
  2. Copyright (C) 2004-2015 Free Software Foundation, Inc.
  3. Contributed by Steven G. Kargl <kargls@comcast.net>.
  4. This file is part of the GNU Fortran runtime library (libgfortran).
  5. Libgfortran is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public
  7. License as published by the Free Software Foundation; either
  8. version 3 of the License, or (at your option) any later version.
  9. Libgfortran is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. #include "libgfortran.h"
  21. #include <string.h>
  22. #include <errno.h>
  23. #ifdef HAVE_SYS_STAT_H
  24. #include <sys/stat.h>
  25. #endif
  26. #include <stdlib.h>
  27. #ifdef HAVE_STAT
  28. /* SUBROUTINE STAT(FILE, SARRAY, STATUS)
  29. CHARACTER(len=*), INTENT(IN) :: FILE
  30. INTEGER, INTENT(OUT), :: SARRAY(13)
  31. INTEGER, INTENT(OUT), OPTIONAL :: STATUS
  32. FUNCTION STAT(FILE, SARRAY)
  33. INTEGER STAT
  34. CHARACTER(len=*), INTENT(IN) :: FILE
  35. INTEGER, INTENT(OUT), :: SARRAY(13) */
  36. /*extern void stat_i4_sub_0 (char *, gfc_array_i4 *, GFC_INTEGER_4 *,
  37. gfc_charlen_type, int);
  38. internal_proto(stat_i4_sub_0);*/
  39. static void
  40. stat_i4_sub_0 (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status,
  41. gfc_charlen_type name_len, int is_lstat __attribute__ ((unused)))
  42. {
  43. int val;
  44. char *str;
  45. struct stat sb;
  46. /* If the rank of the array is not 1, abort. */
  47. if (GFC_DESCRIPTOR_RANK (sarray) != 1)
  48. runtime_error ("Array rank of SARRAY is not 1.");
  49. /* If the array is too small, abort. */
  50. if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
  51. runtime_error ("Array size of SARRAY is too small.");
  52. /* Make a null terminated copy of the string. */
  53. str = fc_strdup (name, name_len);
  54. /* On platforms that don't provide lstat(), we use stat() instead. */
  55. #ifdef HAVE_LSTAT
  56. if (is_lstat)
  57. val = lstat(str, &sb);
  58. else
  59. #endif
  60. val = stat(str, &sb);
  61. free (str);
  62. if (val == 0)
  63. {
  64. index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
  65. /* Device ID */
  66. sarray->base_addr[0 * stride] = sb.st_dev;
  67. /* Inode number */
  68. sarray->base_addr[1 * stride] = sb.st_ino;
  69. /* File mode */
  70. sarray->base_addr[2 * stride] = sb.st_mode;
  71. /* Number of (hard) links */
  72. sarray->base_addr[3 * stride] = sb.st_nlink;
  73. /* Owner's uid */
  74. sarray->base_addr[4 * stride] = sb.st_uid;
  75. /* Owner's gid */
  76. sarray->base_addr[5 * stride] = sb.st_gid;
  77. /* ID of device containing directory entry for file (0 if not available) */
  78. #if HAVE_STRUCT_STAT_ST_RDEV
  79. sarray->base_addr[6 * stride] = sb.st_rdev;
  80. #else
  81. sarray->base_addr[6 * stride] = 0;
  82. #endif
  83. /* File size (bytes) */
  84. sarray->base_addr[7 * stride] = sb.st_size;
  85. /* Last access time */
  86. sarray->base_addr[8 * stride] = sb.st_atime;
  87. /* Last modification time */
  88. sarray->base_addr[9 * stride] = sb.st_mtime;
  89. /* Last file status change time */
  90. sarray->base_addr[10 * stride] = sb.st_ctime;
  91. /* Preferred I/O block size (-1 if not available) */
  92. #if HAVE_STRUCT_STAT_ST_BLKSIZE
  93. sarray->base_addr[11 * stride] = sb.st_blksize;
  94. #else
  95. sarray->base_addr[11 * stride] = -1;
  96. #endif
  97. /* Number of blocks allocated (-1 if not available) */
  98. #if HAVE_STRUCT_STAT_ST_BLOCKS
  99. sarray->base_addr[12 * stride] = sb.st_blocks;
  100. #else
  101. sarray->base_addr[12 * stride] = -1;
  102. #endif
  103. }
  104. if (status != NULL)
  105. *status = (val == 0) ? 0 : errno;
  106. }
  107. extern void stat_i4_sub (char *, gfc_array_i4 *, GFC_INTEGER_4 *,
  108. gfc_charlen_type);
  109. iexport_proto(stat_i4_sub);
  110. void
  111. stat_i4_sub (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status,
  112. gfc_charlen_type name_len)
  113. {
  114. stat_i4_sub_0 (name, sarray, status, name_len, 0);
  115. }
  116. iexport(stat_i4_sub);
  117. extern void lstat_i4_sub (char *, gfc_array_i4 *, GFC_INTEGER_4 *,
  118. gfc_charlen_type);
  119. iexport_proto(lstat_i4_sub);
  120. void
  121. lstat_i4_sub (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status,
  122. gfc_charlen_type name_len)
  123. {
  124. stat_i4_sub_0 (name, sarray, status, name_len, 1);
  125. }
  126. iexport(lstat_i4_sub);
  127. static void
  128. stat_i8_sub_0 (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status,
  129. gfc_charlen_type name_len, int is_lstat __attribute__ ((unused)))
  130. {
  131. int val;
  132. char *str;
  133. struct stat sb;
  134. /* If the rank of the array is not 1, abort. */
  135. if (GFC_DESCRIPTOR_RANK (sarray) != 1)
  136. runtime_error ("Array rank of SARRAY is not 1.");
  137. /* If the array is too small, abort. */
  138. if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
  139. runtime_error ("Array size of SARRAY is too small.");
  140. /* Make a null terminated copy of the string. */
  141. str = fc_strdup (name, name_len);
  142. /* On platforms that don't provide lstat(), we use stat() instead. */
  143. #ifdef HAVE_LSTAT
  144. if (is_lstat)
  145. val = lstat(str, &sb);
  146. else
  147. #endif
  148. val = stat(str, &sb);
  149. free (str);
  150. if (val == 0)
  151. {
  152. index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
  153. /* Device ID */
  154. sarray->base_addr[0] = sb.st_dev;
  155. /* Inode number */
  156. sarray->base_addr[stride] = sb.st_ino;
  157. /* File mode */
  158. sarray->base_addr[2 * stride] = sb.st_mode;
  159. /* Number of (hard) links */
  160. sarray->base_addr[3 * stride] = sb.st_nlink;
  161. /* Owner's uid */
  162. sarray->base_addr[4 * stride] = sb.st_uid;
  163. /* Owner's gid */
  164. sarray->base_addr[5 * stride] = sb.st_gid;
  165. /* ID of device containing directory entry for file (0 if not available) */
  166. #if HAVE_STRUCT_STAT_ST_RDEV
  167. sarray->base_addr[6 * stride] = sb.st_rdev;
  168. #else
  169. sarray->base_addr[6 * stride] = 0;
  170. #endif
  171. /* File size (bytes) */
  172. sarray->base_addr[7 * stride] = sb.st_size;
  173. /* Last access time */
  174. sarray->base_addr[8 * stride] = sb.st_atime;
  175. /* Last modification time */
  176. sarray->base_addr[9 * stride] = sb.st_mtime;
  177. /* Last file status change time */
  178. sarray->base_addr[10 * stride] = sb.st_ctime;
  179. /* Preferred I/O block size (-1 if not available) */
  180. #if HAVE_STRUCT_STAT_ST_BLKSIZE
  181. sarray->base_addr[11 * stride] = sb.st_blksize;
  182. #else
  183. sarray->base_addr[11 * stride] = -1;
  184. #endif
  185. /* Number of blocks allocated (-1 if not available) */
  186. #if HAVE_STRUCT_STAT_ST_BLOCKS
  187. sarray->base_addr[12 * stride] = sb.st_blocks;
  188. #else
  189. sarray->base_addr[12 * stride] = -1;
  190. #endif
  191. }
  192. if (status != NULL)
  193. *status = (val == 0) ? 0 : errno;
  194. }
  195. extern void stat_i8_sub (char *, gfc_array_i8 *, GFC_INTEGER_8 *,
  196. gfc_charlen_type);
  197. iexport_proto(stat_i8_sub);
  198. void
  199. stat_i8_sub (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status,
  200. gfc_charlen_type name_len)
  201. {
  202. stat_i8_sub_0 (name, sarray, status, name_len, 0);
  203. }
  204. iexport(stat_i8_sub);
  205. extern void lstat_i8_sub (char *, gfc_array_i8 *, GFC_INTEGER_8 *,
  206. gfc_charlen_type);
  207. iexport_proto(lstat_i8_sub);
  208. void
  209. lstat_i8_sub (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status,
  210. gfc_charlen_type name_len)
  211. {
  212. stat_i8_sub_0 (name, sarray, status, name_len, 1);
  213. }
  214. iexport(lstat_i8_sub);
  215. extern GFC_INTEGER_4 stat_i4 (char *, gfc_array_i4 *, gfc_charlen_type);
  216. export_proto(stat_i4);
  217. GFC_INTEGER_4
  218. stat_i4 (char *name, gfc_array_i4 *sarray, gfc_charlen_type name_len)
  219. {
  220. GFC_INTEGER_4 val;
  221. stat_i4_sub (name, sarray, &val, name_len);
  222. return val;
  223. }
  224. extern GFC_INTEGER_8 stat_i8 (char *, gfc_array_i8 *, gfc_charlen_type);
  225. export_proto(stat_i8);
  226. GFC_INTEGER_8
  227. stat_i8 (char *name, gfc_array_i8 *sarray, gfc_charlen_type name_len)
  228. {
  229. GFC_INTEGER_8 val;
  230. stat_i8_sub (name, sarray, &val, name_len);
  231. return val;
  232. }
  233. /* SUBROUTINE LSTAT(FILE, SARRAY, STATUS)
  234. CHARACTER(len=*), INTENT(IN) :: FILE
  235. INTEGER, INTENT(OUT), :: SARRAY(13)
  236. INTEGER, INTENT(OUT), OPTIONAL :: STATUS
  237. FUNCTION LSTAT(FILE, SARRAY)
  238. INTEGER LSTAT
  239. CHARACTER(len=*), INTENT(IN) :: FILE
  240. INTEGER, INTENT(OUT), :: SARRAY(13) */
  241. extern GFC_INTEGER_4 lstat_i4 (char *, gfc_array_i4 *, gfc_charlen_type);
  242. export_proto(lstat_i4);
  243. GFC_INTEGER_4
  244. lstat_i4 (char *name, gfc_array_i4 *sarray, gfc_charlen_type name_len)
  245. {
  246. GFC_INTEGER_4 val;
  247. lstat_i4_sub (name, sarray, &val, name_len);
  248. return val;
  249. }
  250. extern GFC_INTEGER_8 lstat_i8 (char *, gfc_array_i8 *, gfc_charlen_type);
  251. export_proto(lstat_i8);
  252. GFC_INTEGER_8
  253. lstat_i8 (char *name, gfc_array_i8 *sarray, gfc_charlen_type name_len)
  254. {
  255. GFC_INTEGER_8 val;
  256. lstat_i8_sub (name, sarray, &val, name_len);
  257. return val;
  258. }
  259. #endif
  260. #ifdef HAVE_FSTAT
  261. /* SUBROUTINE FSTAT(UNIT, SARRAY, STATUS)
  262. INTEGER, INTENT(IN) :: UNIT
  263. INTEGER, INTENT(OUT) :: SARRAY(13)
  264. INTEGER, INTENT(OUT), OPTIONAL :: STATUS
  265. FUNCTION FSTAT(UNIT, SARRAY)
  266. INTEGER FSTAT
  267. INTEGER, INTENT(IN) :: UNIT
  268. INTEGER, INTENT(OUT) :: SARRAY(13) */
  269. extern void fstat_i4_sub (GFC_INTEGER_4 *, gfc_array_i4 *, GFC_INTEGER_4 *);
  270. iexport_proto(fstat_i4_sub);
  271. void
  272. fstat_i4_sub (GFC_INTEGER_4 *unit, gfc_array_i4 *sarray, GFC_INTEGER_4 *status)
  273. {
  274. int val;
  275. struct stat sb;
  276. /* If the rank of the array is not 1, abort. */
  277. if (GFC_DESCRIPTOR_RANK (sarray) != 1)
  278. runtime_error ("Array rank of SARRAY is not 1.");
  279. /* If the array is too small, abort. */
  280. if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
  281. runtime_error ("Array size of SARRAY is too small.");
  282. /* Convert Fortran unit number to C file descriptor. */
  283. val = unit_to_fd (*unit);
  284. if (val >= 0)
  285. val = fstat(val, &sb);
  286. if (val == 0)
  287. {
  288. index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
  289. /* Device ID */
  290. sarray->base_addr[0 * stride] = sb.st_dev;
  291. /* Inode number */
  292. sarray->base_addr[1 * stride] = sb.st_ino;
  293. /* File mode */
  294. sarray->base_addr[2 * stride] = sb.st_mode;
  295. /* Number of (hard) links */
  296. sarray->base_addr[3 * stride] = sb.st_nlink;
  297. /* Owner's uid */
  298. sarray->base_addr[4 * stride] = sb.st_uid;
  299. /* Owner's gid */
  300. sarray->base_addr[5 * stride] = sb.st_gid;
  301. /* ID of device containing directory entry for file (0 if not available) */
  302. #if HAVE_STRUCT_STAT_ST_RDEV
  303. sarray->base_addr[6 * stride] = sb.st_rdev;
  304. #else
  305. sarray->base_addr[6 * stride] = 0;
  306. #endif
  307. /* File size (bytes) */
  308. sarray->base_addr[7 * stride] = sb.st_size;
  309. /* Last access time */
  310. sarray->base_addr[8 * stride] = sb.st_atime;
  311. /* Last modification time */
  312. sarray->base_addr[9 * stride] = sb.st_mtime;
  313. /* Last file status change time */
  314. sarray->base_addr[10 * stride] = sb.st_ctime;
  315. /* Preferred I/O block size (-1 if not available) */
  316. #if HAVE_STRUCT_STAT_ST_BLKSIZE
  317. sarray->base_addr[11 * stride] = sb.st_blksize;
  318. #else
  319. sarray->base_addr[11 * stride] = -1;
  320. #endif
  321. /* Number of blocks allocated (-1 if not available) */
  322. #if HAVE_STRUCT_STAT_ST_BLOCKS
  323. sarray->base_addr[12 * stride] = sb.st_blocks;
  324. #else
  325. sarray->base_addr[12 * stride] = -1;
  326. #endif
  327. }
  328. if (status != NULL)
  329. *status = (val == 0) ? 0 : errno;
  330. }
  331. iexport(fstat_i4_sub);
  332. extern void fstat_i8_sub (GFC_INTEGER_8 *, gfc_array_i8 *, GFC_INTEGER_8 *);
  333. iexport_proto(fstat_i8_sub);
  334. void
  335. fstat_i8_sub (GFC_INTEGER_8 *unit, gfc_array_i8 *sarray, GFC_INTEGER_8 *status)
  336. {
  337. int val;
  338. struct stat sb;
  339. /* If the rank of the array is not 1, abort. */
  340. if (GFC_DESCRIPTOR_RANK (sarray) != 1)
  341. runtime_error ("Array rank of SARRAY is not 1.");
  342. /* If the array is too small, abort. */
  343. if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13)
  344. runtime_error ("Array size of SARRAY is too small.");
  345. /* Convert Fortran unit number to C file descriptor. */
  346. val = unit_to_fd ((int) *unit);
  347. if (val >= 0)
  348. val = fstat(val, &sb);
  349. if (val == 0)
  350. {
  351. index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0);
  352. /* Device ID */
  353. sarray->base_addr[0] = sb.st_dev;
  354. /* Inode number */
  355. sarray->base_addr[stride] = sb.st_ino;
  356. /* File mode */
  357. sarray->base_addr[2 * stride] = sb.st_mode;
  358. /* Number of (hard) links */
  359. sarray->base_addr[3 * stride] = sb.st_nlink;
  360. /* Owner's uid */
  361. sarray->base_addr[4 * stride] = sb.st_uid;
  362. /* Owner's gid */
  363. sarray->base_addr[5 * stride] = sb.st_gid;
  364. /* ID of device containing directory entry for file (0 if not available) */
  365. #if HAVE_STRUCT_STAT_ST_RDEV
  366. sarray->base_addr[6 * stride] = sb.st_rdev;
  367. #else
  368. sarray->base_addr[6 * stride] = 0;
  369. #endif
  370. /* File size (bytes) */
  371. sarray->base_addr[7 * stride] = sb.st_size;
  372. /* Last access time */
  373. sarray->base_addr[8 * stride] = sb.st_atime;
  374. /* Last modification time */
  375. sarray->base_addr[9 * stride] = sb.st_mtime;
  376. /* Last file status change time */
  377. sarray->base_addr[10 * stride] = sb.st_ctime;
  378. /* Preferred I/O block size (-1 if not available) */
  379. #if HAVE_STRUCT_STAT_ST_BLKSIZE
  380. sarray->base_addr[11 * stride] = sb.st_blksize;
  381. #else
  382. sarray->base_addr[11 * stride] = -1;
  383. #endif
  384. /* Number of blocks allocated (-1 if not available) */
  385. #if HAVE_STRUCT_STAT_ST_BLOCKS
  386. sarray->base_addr[12 * stride] = sb.st_blocks;
  387. #else
  388. sarray->base_addr[12 * stride] = -1;
  389. #endif
  390. }
  391. if (status != NULL)
  392. *status = (val == 0) ? 0 : errno;
  393. }
  394. iexport(fstat_i8_sub);
  395. extern GFC_INTEGER_4 fstat_i4 (GFC_INTEGER_4 *, gfc_array_i4 *);
  396. export_proto(fstat_i4);
  397. GFC_INTEGER_4
  398. fstat_i4 (GFC_INTEGER_4 *unit, gfc_array_i4 *sarray)
  399. {
  400. GFC_INTEGER_4 val;
  401. fstat_i4_sub (unit, sarray, &val);
  402. return val;
  403. }
  404. extern GFC_INTEGER_8 fstat_i8 (GFC_INTEGER_8 *, gfc_array_i8 *);
  405. export_proto(fstat_i8);
  406. GFC_INTEGER_8
  407. fstat_i8 (GFC_INTEGER_8 *unit, gfc_array_i8 *sarray)
  408. {
  409. GFC_INTEGER_8 val;
  410. fstat_i8_sub (unit, sarray, &val);
  411. return val;
  412. }
  413. #endif