This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, libfortran] PR 40812 Large file support on MinGW
- From: Janne Blomqvist <blomqvist dot janne at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Fortran List <fortran at gcc dot gnu dot org>
- Date: Tue, 1 Dec 2009 20:57:33 +0200
- Subject: Re: [Patch, libfortran] PR 40812 Large file support on MinGW
- References: <7b446c2e0912011018x75d29622g2387c1d9ab39c8c0@mail.gmail.com>
On Tue, Dec 1, 2009 at 20:18, Janne Blomqvist <blomqvist.janne@gmail.com> wrote:
> Hi,
>
> the attached patch should make gfortran support > 2 GB files on MinGW.
> I don't have a windows installation to test on, so I don't know if
> this works or not. Though I regtested on x86_64-unknown-linux-gnu to
> make sure that non-MinGW targets didn't change (it's all behind
> #ifdefs, but just to be sure).
>
> Another caveat is that it uses features from the Win32 API that
> according to MSDN are available only as of w2k and newer, so with this
> patch we effectively drop support for pre-w2k targets on MinGW. I
> don't know if anybody cares about such platforms any longer, if so
> maybe the interested party could step up to the plate and contribute
> some configure checks or somesuch so that we could fall back to the
> old ftruncate or chsize functions?
>
> Ok for trunk?
>
> 2009-12-01 ?Janne Blomqvist ?<jb@gcc.gnu.org>
>
> ? ? ? ?PR libfortran/40812
> ? ? ? ?* libgfortran.h: typedef gfc_offset differently for mingw.
> ? ? ? ?* io/unix.h (struct stream): Change function pointers to use
> ? ? ? ?gfc_offset instead of off_t.
> ? ? ? ?(sseek): Change prototype to use gfc_offset instead of off_t.
> ? ? ? ?(stell): Likewise.
> ? ? ? ?(struncate): Likewise.
> ? ? ? ?* io/unix.c: Redefine lseek() for mingw.
> ? ? ? ?(raw_seek): Use gfc_offset instead of off_t.
> ? ? ? ?(raw_tell): Likewise.
> ? ? ? ?(buf_seek): Likewise.
> ? ? ? ?(buf_tell): Likewise.
> ? ? ? ?(buf_truncate): Likewise.
> ? ? ? ?(mem_seek): Likewise.
> ? ? ? ?(mem_tell): Likewise.
> ? ? ? ?(mem_truncate): Likewise.
> ? ? ? ?(fd_to_stream): Likewise.
> ? ? ? ?(file_length): Likewise.
> ? ? ? ?(raw_truncate): Use gfc_offset instead of off_t, add large file
> ? ? ? ?capable implementation for MinGW.
Updated patch attached, sets errno to EBADF instead of calling
runtime_error() when something goes wrong. That should make it behave
more like the POSIX ftruncate() that defines the canonical behaviour
of raw_truncate().
--
Janne Blomqvist
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 8b32475..db32f7d 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -47,6 +47,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#define lseek _lseeki64
+
static uint64_t
id_from_handle (HANDLE hFile)
{
@@ -274,22 +276,63 @@ raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
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__
+ LARGE_INTEGER cur, tmp;
+ HANDLE h;
+ long htmp;
+
+ if (isatty (s->fd))
+ {
+ errno = EBADF;
+ return -1;
+ }
+ htmp = _get_osfhandle (s->fd);
+ if (htmp == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ h = (HANDLE) htmp;
+ tmp.LowPart = 0;
+ tmp.HighPart = 0;
+ if (!SetFilePointerEx (h, tmp, &cur, FILE_CURRENT))
+ {
+ errno = EBADF
+ return -1;
+ }
+ tmp.QuadPart = length;
+ if (!SetFilePointerEx (h, tmp, NULL, FILE_CURRENT))
+ {
+ errno = EBADF;
+ return -1;
+ }
+ if (!SetEndOfFile (h))
+ {
+ errno = EBADF;
+ return -1;
+ }
+ if (!SetFilePointerEx (h, cur, NULL, FILE_BEGIN))
+ {
+ errno = EBADF;
+ return -1;
+ }
+ return 0;
+#elif defined HAVE_FTRUNCATE
return ftruncate (s->fd, length);
#elif defined HAVE_CHSIZE
return chsize (s->fd, length);
@@ -470,8 +513,8 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
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)
{
@@ -495,14 +538,14 @@ buf_seek (unix_stream * s, off_t offset, int 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;
@@ -631,8 +674,8 @@ mem_write (stream * s, const void * buf, ssize_t nbytes)
}
-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)
@@ -668,7 +711,7 @@ mem_seek (stream * strm, off_t offset, int whence)
}
-static off_t
+static gfc_offset
mem_tell (stream * s)
{
return ((unix_stream *)s)->logical_offset;
@@ -677,7 +720,7 @@ mem_tell (stream * s)
static int
mem_truncate (unix_stream * s __attribute__ ((unused)),
- off_t length __attribute__ ((unused)))
+ gfc_offset length __attribute__ ((unused)))
{
return 0;
}
@@ -764,7 +807,7 @@ fd_to_stream (int fd, int prot)
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;
@@ -1602,7 +1645,7 @@ inquire_readwrite (const char *string, int len)
gfc_offset
file_length (stream * s)
{
- off_t curr, end;
+ gfc_offset curr, end;
if (!is_seekable (s))
return -1;
curr = stell (s);
diff --git a/libgfortran/io/unix.h b/libgfortran/io/unix.h
index f0f0712..e691982 100644
--- a/libgfortran/io/unix.h
+++ b/libgfortran/io/unix.h
@@ -33,10 +33,10 @@ struct stream
{
ssize_t (*read) (struct stream *, void *, ssize_t);
ssize_t (*write) (struct stream *, const void *, ssize_t);
- off_t (*seek) (struct stream *, off_t, int);
- off_t (*tell) (struct stream *);
+ gfc_offset (*seek) (struct stream *, gfc_offset, int);
+ gfc_offset (*tell) (struct stream *);
/* Avoid keyword truncate due to AIX namespace collision. */
- int (*trunc) (struct stream *, off_t);
+ int (*trunc) (struct stream *, gfc_offset);
int (*flush) (struct stream *);
int (*close) (struct stream *);
};
@@ -54,20 +54,20 @@ swrite (stream * s, const void * buf, ssize_t nbyte)
return s->write (s, buf, nbyte);
}
-static inline off_t
-sseek (stream * s, off_t offset, int whence)
+static inline gfc_offset
+sseek (stream * s, gfc_offset offset, int whence)
{
return s->seek (s, offset, whence);
}
-static inline off_t
+static inline gfc_offset
stell (stream * s)
{
return s->tell (s);
}
static inline int
-struncate (stream * s, off_t length)
+struncate (stream * s, gfc_offset length)
{
return s->trunc (s, length);
}
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index bba95f7..bb3f0ac 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -56,7 +56,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
+
+#ifdef __MINGW32__
+typedef _off64_t gfc_offset;
+#else
typedef off_t gfc_offset;
+#endif
#ifndef NULL
#define NULL (void *) 0