-/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Andy Vaught
F2003 I/O support contributed by Jerry DeLisle
/* Unix stream I/O module */
#include "io.h"
+#include "unix.h"
#include <stdlib.h>
#include <limits.h>
/* For mingw, we don't identify files by their inode number, but by a
64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
-#if defined(__MINGW32__) && !HAVE_WORKING_STAT
+#ifdef __MINGW32__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#define lseek _lseeki64
+#define fstat _fstati64
+#define stat _stati64
+typedef struct _stati64 gfstat_t;
+
+#ifndef HAVE_WORKING_STAT
static uint64_t
id_from_handle (HANDLE hFile)
{
#endif
+#else
+typedef struct stat gfstat_t;
+#endif
+
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
return nbyte - bytes_left;
}
-static off_t
-raw_seek (unix_stream * s, off_t offset, int whence)
+static gfc_offset
+raw_seek (unix_stream * s, gfc_offset offset, int whence)
{
return lseek (s->fd, offset, whence);
}
-static off_t
+static gfc_offset
raw_tell (unix_stream * s)
{
return lseek (s->fd, 0, SEEK_CUR);
}
static int
-raw_truncate (unix_stream * s, off_t length)
+raw_truncate (unix_stream * s, gfc_offset length)
{
-#ifdef HAVE_FTRUNCATE
+#ifdef __MINGW32__
+ HANDLE h;
+ gfc_offset cur;
+
+ if (isatty (s->fd))
+ {
+ errno = EBADF;
+ return -1;
+ }
+ h = _get_osfhandle (s->fd);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ cur = lseek (s->fd, 0, SEEK_CUR);
+ if (cur == -1)
+ return -1;
+ if (lseek (s->fd, length, SEEK_SET) == -1)
+ goto error;
+ if (!SetEndOfFile (h))
+ {
+ errno = EBADF;
+ goto error;
+ }
+ if (lseek (s->fd, cur, SEEK_SET) == -1)
+ return -1;
+ return 0;
+ error:
+ lseek (s->fd, cur, SEEK_SET);
+ return -1;
+#elif defined HAVE_FTRUNCATE
return ftruncate (s->fd, length);
#elif defined HAVE_CHSIZE
return chsize (s->fd, length);
s->ndirty += nbyte;
}
else
- {
- if (s->file_length != -1 && s->physical_offset != s->logical_offset
- && lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
- return -1;
- nbyte = raw_write (s, buf, nbyte);
- s->physical_offset += nbyte;
- }
+ {
+ if (s->file_length != -1 && s->physical_offset != s->logical_offset)
+ {
+ if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
+ return -1;
+ s->physical_offset = s->logical_offset;
+ }
+
+ nbyte = raw_write (s, buf, nbyte);
+ s->physical_offset += nbyte;
+ }
}
s->logical_offset += nbyte;
/* Don't increment file_length if the file is non-seekable. */
return nbyte;
}
-static off_t
-buf_seek (unix_stream * s, off_t offset, int whence)
+static gfc_offset
+buf_seek (unix_stream * s, gfc_offset offset, int whence)
{
switch (whence)
{
return offset;
}
-static off_t
+static gfc_offset
buf_tell (unix_stream * s)
{
return s->logical_offset;
}
static int
-buf_truncate (unix_stream * s, off_t length)
+buf_truncate (unix_stream * s, gfc_offset length)
{
int r;
}
-static off_t
-mem_seek (stream * strm, off_t offset, int whence)
+static gfc_offset
+mem_seek (stream * strm, gfc_offset offset, int whence)
{
unix_stream * s = (unix_stream *) strm;
switch (whence)
}
-static off_t
+static gfc_offset
mem_tell (stream * s)
{
return ((unix_stream *)s)->logical_offset;
static int
mem_truncate (unix_stream * s __attribute__ ((unused)),
- off_t length __attribute__ ((unused)))
+ gfc_offset length __attribute__ ((unused)))
{
return 0;
}
static stream *
fd_to_stream (int fd, int prot)
{
- struct stat statbuf;
+ gfstat_t statbuf;
unix_stream *s;
s = get_mem (sizeof (unix_stream));
fstat (fd, &statbuf);
- if (lseek (fd, 0, SEEK_CUR) == (off_t) -1)
+ if (lseek (fd, 0, SEEK_CUR) == (gfc_offset) -1)
s->file_length = -1;
else
s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
template = get_mem (strlen (tempdir) + 20);
- sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
-
#ifdef HAVE_MKSTEMP
+ sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
fd = mkstemp (template);
#else /* HAVE_MKSTEMP */
-
- if (mktemp (template))
- do
+ fd = -1;
+ do
+ {
+ sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
+ if (!mktemp (template))
+ break;
#if defined(HAVE_CRLF) && defined(O_BINARY)
fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
S_IREAD | S_IWRITE);
#else
fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
#endif
- while (!(fd == -1 && errno == EEXIST) && mktemp (template));
- else
- fd = -1;
+ }
+ while (fd == -1 && errno == EEXIST);
#endif /* HAVE_MKSTEMP */
}
#endif
+
+#ifdef __MINGW32__
+ if (opp->file_len == 7)
+ {
+ if (strncmp (path, "CONOUT$", 7) == 0
+ || strncmp (path, "CONERR$", 7) == 0)
+ {
+ fd = open ("CONOUT$", O_WRONLY);
+ flags->action = ACTION_WRITE;
+ return fd;
+ }
+ }
+
+ if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
+ {
+ fd = open ("CONIN$", O_RDONLY);
+ flags->action = ACTION_READ;
+ return fd;
+ }
+#endif
+
rwflag = 0;
switch (flags->action)
compare_file_filename (gfc_unit *u, const char *name, int len)
{
char path[PATH_MAX + 1];
- struct stat st1;
+ gfstat_t st1;
#ifdef HAVE_WORKING_STAT
- struct stat st2;
+ gfstat_t st2;
#else
# ifdef __MINGW32__
uint64_t id1, id2;
#ifdef HAVE_WORKING_STAT
-# define FIND_FILE0_DECL struct stat *st
+# define FIND_FILE0_DECL gfstat_t *st
# define FIND_FILE0_ARGS st
#else
# define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
find_file (const char *file, gfc_charlen_type file_len)
{
char path[PATH_MAX + 1];
- struct stat st[2];
+ gfstat_t st[2];
gfc_unit *u;
- uint64_t id;
+#if defined(__MINGW32__) && !HAVE_WORKING_STAT
+ uint64_t id = 0ULL;
+#endif
if (unpack_filename (path, file, file_len))
return NULL;
#if defined(__MINGW32__) && !HAVE_WORKING_STAT
id = id_from_path (path);
-#else
- id = 0;
#endif
__gthread_mutex_lock (&unit_lock);
file_exists (const char *file, gfc_charlen_type file_len)
{
char path[PATH_MAX + 1];
- struct stat statbuf;
+ gfstat_t statbuf;
if (unpack_filename (path, file, file_len))
return 0;
}
+/* file_size()-- Returns the size of the file. */
+
+GFC_IO_INT
+file_size (const char *file, gfc_charlen_type file_len)
+{
+ char path[PATH_MAX + 1];
+ gfstat_t statbuf;
+
+ if (unpack_filename (path, file, file_len))
+ return -1;
+
+ if (stat (path, &statbuf) < 0)
+ return -1;
+
+ return (GFC_IO_INT) statbuf.st_size;
+}
static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
inquire_sequential (const char *string, int len)
{
char path[PATH_MAX + 1];
- struct stat statbuf;
+ gfstat_t statbuf;
if (string == NULL ||
unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
inquire_direct (const char *string, int len)
{
char path[PATH_MAX + 1];
- struct stat statbuf;
+ gfstat_t statbuf;
if (string == NULL ||
unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
inquire_formatted (const char *string, int len)
{
char path[PATH_MAX + 1];
- struct stat statbuf;
+ gfstat_t statbuf;
if (string == NULL ||
unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
gfc_offset
file_length (stream * s)
{
- off_t curr, end;
+ gfc_offset curr, end;
if (!is_seekable (s))
return -1;
curr = stell (s);