aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io/unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgfortran/io/unix.c')
-rw-r--r--libgfortran/io/unix.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index d33c110..b3645f0 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -706,16 +706,28 @@ fd_truncate (unix_stream * s)
/* Using ftruncate on a seekable special file (like /dev/null)
is undefined, so we treat it as if the ftruncate succeeded. */
+ if (!s->special_file
+ && (
#ifdef HAVE_FTRUNCATE
- if (s->special_file || ftruncate (s->fd, s->logical_offset))
+ ftruncate (s->fd, s->logical_offset) != 0
+#elif defined HAVE_CHSIZE
+ chsize (s->fd, s->logical_offset) != 0
#else
-#ifdef HAVE_CHSIZE
- if (s->special_file || chsize (s->fd, s->logical_offset))
-#endif
+ /* If we have neither, always fail and exit, noisily. */
+ runtime_error ("required ftruncate or chsize support not present"), 1
#endif
+ ))
{
- s->physical_offset = s->file_length = 0;
- return SUCCESS;
+ /* The truncation failed and we need to handle this gracefully.
+ The file length remains the same, but the file-descriptor
+ offset needs adjustment per the successful lseek above.
+ (Similarly, the contents of the buffer isn't valid anymore.)
+ A ftruncate call does not affect the physical (file-descriptor)
+ offset, according to the ftruncate manual, so neither should a
+ failed call. */
+ s->physical_offset = s->logical_offset;
+ s->active = 0;
+ return FAILURE;
}
s->physical_offset = s->file_length = s->logical_offset;