[Ada] Add support for files > 2Gb on 32bit platforms.

Arnaud Charlet charlet@adacore.com
Thu Jul 31 13:30:00 GMT 2014


This patch set adds support for file larger than 2Gb on 32bit
platforms. The main visible change is that Stream_Element_Offset
is now a 64bit type on all platforms. The other changes are
internal only.

Tested on x86_64-pc-linux-gnu, committed on trunk

2014-07-31  Pascal Obry  <obry@adacore.com>

	* a-stream.ads (Stream_Element_Offset): Now a signed 64bit type.
	* i-cstrea.ads, s-crtl.ads (fseek64): Offset is always a 64bit value.
	(ftell64): Always returns a 64bit value.
	* cstreams.c (int64): New definition.
	(_FILE_OFFSET_BITS): Set to 64 to enable 64bit offset support.
	(__gnat_ftell64): Always returns a 64bit value. The implemenation now
	uses ftello() on UNIX.
	(__gnat_fseek64): Offset is always a 64bit value. The
	implementation now uses fseeko() on UNIX.
	* a-ststio.adb, s-direio.adb (Set_Position): Simplify code,
	always use fseek64 to set the offset.
	(Size): Simplify code, always use fseek64/ftell64.
	* s-direio.ads (Count): Now an int64.
	* g-socket.ads (Vector_Element): Adjust definition for Length
	to be a size_t. This matches the C definition and avoid using
	a 64bit integer on 32bit platforms now that Count is always 64bit.
	* g-socthi-mingw.adb (Ada.Streams): Removed as not used anymore.
	(C_Recvmsg): Change some conversion to account for change in
	Vector_Element.
	(C_Sendmsg): Likewise.

-------------- next part --------------
Index: a-stream.ads
===================================================================
--- a-stream.ads	(revision 213263)
+++ a-stream.ads	(working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
 --                                                                          --
 -- This specification is derived from the Ada Reference Manual for use with --
 -- GNAT. The copyright notice above, and the license provisions that follow --
@@ -41,9 +41,7 @@
 
    type Stream_Element is mod 2 ** Standard'Storage_Unit;
 
-   type Stream_Element_Offset is range
-     -(2 ** (Standard'Address_Size - 1)) ..
-     +(2 ** (Standard'Address_Size - 1)) - 1;
+   type Stream_Element_Offset is range -(2 ** 63) .. +(2 ** 63) - 1;
 
    subtype Stream_Element_Count is
       Stream_Element_Offset range 0 .. Stream_Element_Offset'Last;
Index: s-crtl.ads
===================================================================
--- s-crtl.ads	(revision 213263)
+++ s-crtl.ads	(working copy)
@@ -62,6 +62,8 @@
    type ssize_t is range -(2 ** (Standard'Address_Size - 1))
                       .. +(2 ** (Standard'Address_Size - 1)) - 1;
 
+   type int64 is range -(2 ** 63) .. (2 ** 63) - 1;
+
    type Filename_Encoding is (UTF8, ASCII_8bits, Unspecified);
    for Filename_Encoding use (UTF8 => 0, ASCII_8bits => 1, Unspecified => 2);
    pragma Convention (C, Filename_Encoding);
@@ -147,14 +149,14 @@
 
    function fseek64
      (stream : FILEs;
-      offset : ssize_t;
+      offset : int64;
       origin : int) return int;
    pragma Import (C, fseek64, "__gnat_fseek64");
 
    function ftell (stream : FILEs) return long;
    pragma Import (C, ftell, "ftell");
 
-   function ftell64 (stream : FILEs) return ssize_t;
+   function ftell64 (stream : FILEs) return int64;
    pragma Import (C, ftell64, "__gnat_ftell64");
 
    function getenv (S : String) return System.Address;
Index: i-cstrea.ads
===================================================================
--- i-cstrea.ads	(revision 213263)
+++ i-cstrea.ads	(working copy)
@@ -43,6 +43,7 @@
    subtype long is System.CRTL.long;
    subtype size_t is System.CRTL.size_t;
    subtype ssize_t is System.CRTL.ssize_t;
+   subtype int64 is System.CRTL.int64;
    subtype voids is System.Address;
 
    NULL_Stream : constant FILEs;
@@ -159,14 +160,14 @@
 
    function fseek64
      (stream : FILEs;
-      offset : ssize_t;
+      offset : int64;
       origin : int) return int
      renames System.CRTL.fseek64;
 
    function ftell (stream : FILEs) return long
      renames System.CRTL.ftell;
 
-   function ftell64 (stream : FILEs) return ssize_t
+   function ftell64 (stream : FILEs) return int64
      renames System.CRTL.ftell64;
 
    function fwrite
Index: a-ststio.adb
===================================================================
--- a-ststio.adb	(revision 213263)
+++ a-ststio.adb	(working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -382,17 +382,10 @@
    ------------------
 
    procedure Set_Position (File : File_Type) is
-      use type System.CRTL.long;
-      use type System.CRTL.ssize_t;
+      use type System.CRTL.int64;
       R : int;
    begin
-      if Standard'Address_Size = 64 then
-         R := fseek64 (File.Stream,
-                       System.CRTL.ssize_t (File.Index) - 1, SEEK_SET);
-      else
-         R := fseek (File.Stream,
-                     System.CRTL.long (File.Index) - 1, SEEK_SET);
-      end if;
+      R := fseek64 (File.Stream, System.CRTL.int64 (File.Index) - 1, SEEK_SET);
 
       if R /= 0 then
          raise Use_Error;
@@ -410,14 +403,14 @@
       if File.File_Size = -1 then
          File.Last_Op := Op_Other;
 
-         if fseek (File.Stream, 0, SEEK_END) /= 0 then
+         if fseek64 (File.Stream, 0, SEEK_END) /= 0 then
             raise Device_Error;
          end if;
 
-         if Standard'Address_Size = 64 then
-            File.File_Size := Stream_Element_Offset (ftell64 (File.Stream));
-         else
-            File.File_Size := Stream_Element_Offset (ftell (File.Stream));
+         File.File_Size := Stream_Element_Offset (ftell64 (File.Stream));
+
+         if File.File_Size = -1 then
+            raise Use_Error;
          end if;
       end if;
 
Index: g-socthi-mingw.adb
===================================================================
--- g-socthi-mingw.adb	(revision 213263)
+++ g-socthi-mingw.adb	(working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                     Copyright (C) 2001-2013, AdaCore                     --
+--                     Copyright (C) 2001-2014, AdaCore                     --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -35,7 +35,6 @@
 
 --  This version is for NT
 
-with Ada.Streams;             use Ada.Streams;
 with Ada.Unchecked_Conversion;
 with Interfaces.C.Strings;    use Interfaces.C.Strings;
 with System;                  use System;
@@ -334,11 +333,11 @@
             exit;
 
          else
-            pragma Assert (Stream_Element_Count (Res) <= Current_Iovec.Length);
+            pragma Assert (Interfaces.C.size_t (Res) <= Current_Iovec.Length);
 
             Count := Count + Res;
             Current_Iovec.Length :=
-              Current_Iovec.Length - Stream_Element_Count (Res);
+              Current_Iovec.Length - Interfaces.C.size_t (Res);
             Current_Iovec.Base :=
               To_Access (Current_Iovec.Base.all'Address
                 + Storage_Offset (Res));
@@ -507,7 +506,7 @@
 
          --  Exit now if the buffer is not fully transmitted
 
-         exit when Stream_Element_Count (Res) < Iovec (J).Length;
+         exit when Interfaces.C.size_t (Res) < Iovec (J).Length;
       end loop;
 
       return System.CRTL.ssize_t (Count);
Index: s-direio.adb
===================================================================
--- s-direio.adb	(revision 213263)
+++ s-direio.adb	(working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -45,7 +45,7 @@
    subtype AP is FCB.AFCB_Ptr;
    use type FCB.Shared_Status_Type;
 
-   use type System.CRTL.long;
+   use type System.CRTL.int64;
    use type System.CRTL.size_t;
 
    -----------------------
@@ -280,18 +280,10 @@
    ------------------
 
    procedure Set_Position (File : File_Type) is
-      use type System.CRTL.ssize_t;
       R : int;
    begin
-      if Standard'Address_Size = 64 then
-         R := fseek64
-           (File.Stream, ssize_t (File.Bytes) *
-              ssize_t (File.Index - 1), SEEK_SET);
-      else
-         R := fseek
-           (File.Stream, long (File.Bytes) *
-              long (File.Index - 1), SEEK_SET);
-      end if;
+      R := fseek64
+        (File.Stream, int64 (File.Bytes) * int64 (File.Index - 1), SEEK_SET);
 
       if R /= 0 then
          raise Use_Error;
@@ -303,20 +295,22 @@
    ----------
 
    function Size (File : File_Type) return Count is
-      use type System.CRTL.ssize_t;
+      Pos : int64;
    begin
       FIO.Check_File_Open (AP (File));
       File.Last_Op := Op_Other;
 
-      if fseek (File.Stream, 0, SEEK_END) /= 0 then
+      if fseek64 (File.Stream, 0, SEEK_END) /= 0 then
          raise Device_Error;
       end if;
 
-      if Standard'Address_Size = 64 then
-         return Count (ftell64 (File.Stream) / ssize_t (File.Bytes));
-      else
-         return Count (ftell (File.Stream) / long (File.Bytes));
+      Pos := ftell64 (File.Stream);
+
+      if Pos = -1 then
+         raise Use_Error;
       end if;
+
+      return Count (Pos / int64 (File.Bytes));
    end Size;
 
    -----------
Index: s-direio.ads
===================================================================
--- s-direio.ads	(revision 213263)
+++ s-direio.ads	(working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -45,7 +45,7 @@
    type Operation is (Op_Read, Op_Write, Op_Other);
    --  Type used to record last operation (to optimize sequential operations)
 
-   subtype Count is Interfaces.C_Streams.long;
+   subtype Count is Interfaces.C_Streams.int64;
    --  The Count type in each instantiation is derived from this type
 
    subtype Positive_Count is Count range 1 .. Count'Last;
Index: cstreams.c
===================================================================
--- cstreams.c	(revision 213364)
+++ cstreams.c	(working copy)
@@ -31,6 +31,12 @@
 
 /* Routines required for implementing routines in Interfaces.C.Streams.  */
 
+#define _FILE_OFFSET_BITS 64
+/* the define above will make off_t a 64bit type on GNU/Linux */
+
+#include <stdio.h>
+#include <sys/types.h>
+
 #ifdef __vxworks
 #include "vxWorks.h"
 #endif
@@ -247,8 +253,10 @@
   return buffer;
 }
 
-#ifdef _WIN64
-  /* On Windows 64 we want to use the fseek/fteel supporting large files. This
+#define __int64 long long
+
+#ifdef _WIN32
+  /* On Windows we want to use the fseek/fteel supporting large files. This
      issue is due to the fact that a long on Win64 is still a 32 bits value */
 __int64
 __gnat_ftell64 (FILE *stream)
@@ -263,16 +271,22 @@
 }
 
 #else
-long
+__int64
 __gnat_ftell64 (FILE *stream)
 {
-  return ftell (stream);
+  return (__int64)ftello (stream);
 }
 
 int
-__gnat_fseek64 (FILE *stream, long offset, int origin)
+__gnat_fseek64 (FILE *stream, __int64 offset, int origin)
 {
-  return fseek (stream, offset, origin);
+  /* make sure that the offset is not bigger than the OS off_t, if so return
+     with error as this mean that we are trying to handle files larger than
+     2Gb on a patform not supporting it. */
+  if ((off_t)offset == offset)
+    return fseeko (stream, (off_t) offset, origin);
+  else
+    return -1;
 }
 #endif
 
Index: g-socket.ads
===================================================================
--- g-socket.ads	(revision 213263)
+++ g-socket.ads	(working copy)
@@ -797,7 +797,7 @@
 
    type Vector_Element is record
       Base   : Stream_Element_Reference;
-      Length : Ada.Streams.Stream_Element_Count;
+      Length : Interfaces.C.size_t;
    end record;
 
    type Vector_Type is array (Integer range <>) of Vector_Element;


More information about the Gcc-patches mailing list