This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch, libfortran] PR 40812 Large file support on MinGW


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]