1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- S Y S T E M . D I R E C T _ I O --
9 -- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with Ada
.IO_Exceptions
; use Ada
.IO_Exceptions
;
33 with Interfaces
.C_Streams
; use Interfaces
.C_Streams
;
34 with System
; use System
;
37 with System
.Soft_Links
;
38 with Ada
.Unchecked_Deallocation
;
40 package body System
.Direct_IO
is
42 package FIO
renames System
.File_IO
;
43 package SSL
renames System
.Soft_Links
;
45 subtype AP
is FCB
.AFCB_Ptr
;
46 use type FCB
.Shared_Status_Type
;
48 use type System
.CRTL
.long
;
49 use type System
.CRTL
.size_t
;
51 -----------------------
52 -- Local Subprograms --
53 -----------------------
55 procedure Set_Position
(File
: File_Type
);
56 -- Sets file position pointer according to value of current index
62 function AFCB_Allocate
(Control_Block
: Direct_AFCB
) return FCB
.AFCB_Ptr
is
63 pragma Unreferenced
(Control_Block
);
65 return new Direct_AFCB
;
72 -- No special processing required for Direct_IO close
74 procedure AFCB_Close
(File
: not null access Direct_AFCB
) is
75 pragma Unreferenced
(File
);
84 procedure AFCB_Free
(File
: not null access Direct_AFCB
) is
86 type FCB_Ptr
is access all Direct_AFCB
;
88 FT
: FCB_Ptr
:= FCB_Ptr
(File
);
91 Ada
.Unchecked_Deallocation
(Direct_AFCB
, FCB_Ptr
);
102 (File
: in out File_Type
;
103 Mode
: FCB
.File_Mode
:= FCB
.Inout_File
;
107 Dummy_File_Control_Block
: Direct_AFCB
;
108 pragma Warnings
(Off
, Dummy_File_Control_Block
);
109 -- Yes, we know this is never assigned a value, only the tag is used for
110 -- dispatching purposes, so that's expected.
113 FIO
.Open
(File_Ptr
=> AP
(File
),
114 Dummy_FCB
=> Dummy_File_Control_Block
,
127 function End_Of_File
(File
: File_Type
) return Boolean is
129 FIO
.Check_Read_Status
(AP
(File
));
130 return File
.Index
> Size
(File
);
137 function Index
(File
: File_Type
) return Positive_Count
is
139 FIO
.Check_File_Open
(AP
(File
));
148 (File
: in out File_Type
;
149 Mode
: FCB
.File_Mode
;
153 Dummy_File_Control_Block
: Direct_AFCB
;
154 pragma Warnings
(Off
, Dummy_File_Control_Block
);
155 -- Yes, we know this is never assigned a value, only the tag is used for
156 -- dispatching purposes, so that's expected.
159 FIO
.Open
(File_Ptr
=> AP
(File
),
160 Dummy_FCB
=> Dummy_File_Control_Block
,
176 Size
: Interfaces
.C_Streams
.size_t
;
177 From
: Positive_Count
)
180 Set_Index
(File
, From
);
181 Read
(File
, Item
, Size
);
187 Size
: Interfaces
.C_Streams
.size_t
)
190 FIO
.Check_Read_Status
(AP
(File
));
192 -- If last operation was not a read, or if in file sharing mode,
193 -- then reset the physical pointer of the file to match the index
194 -- We lock out task access over the two operations in this case.
196 if File
.Last_Op
/= Op_Read
197 or else File
.Shared_Status
= FCB
.Yes
199 if End_Of_File
(File
) then
203 Locked_Processing
: begin
206 FIO
.Read_Buf
(AP
(File
), Item
, Size
);
213 end Locked_Processing
;
216 FIO
.Read_Buf
(AP
(File
), Item
, Size
);
219 File
.Index
:= File
.Index
+ 1;
221 -- Set last operation to read, unless we did not read a full record
222 -- (happens with the variant record case) in which case we set the
223 -- last operation as other, to force the file position to be reset
226 File
.Last_Op
:= (if File
.Bytes
= Size
then Op_Read
else Op_Other
);
229 -- The following is the required overriding for Stream.Read, which is
230 -- not used, since we do not do Stream operations on Direct_IO files.
233 (File
: in out Direct_AFCB
;
234 Item
: out Ada
.Streams
.Stream_Element_Array
;
235 Last
: out Ada
.Streams
.Stream_Element_Offset
)
245 procedure Reset
(File
: in out File_Type
; Mode
: FCB
.File_Mode
) is
246 pragma Warnings
(Off
, File
);
247 -- File is actually modified via Unrestricted_Access below, but
248 -- GNAT will generate a warning anyway.
250 -- Note that we do not use pragma Unmodified here, since in -gnatc mode,
251 -- GNAT will complain that File is modified for "File.Index := 1;"
253 FIO
.Reset
(AP
(File
)'Unrestricted_Access, Mode
);
255 File
.Last_Op
:= Op_Read
;
258 procedure Reset
(File
: in out File_Type
) is
259 pragma Warnings
(Off
, File
);
260 -- See above (other Reset procedure) for explanations on this pragma
262 FIO
.Reset
(AP
(File
)'Unrestricted_Access);
264 File
.Last_Op
:= Op_Read
;
271 procedure Set_Index
(File
: File_Type
; To
: Positive_Count
) is
273 FIO
.Check_File_Open
(AP
(File
));
274 File
.Index
:= Count
(To
);
275 File
.Last_Op
:= Op_Other
;
282 procedure Set_Position
(File
: File_Type
) is
285 (File
.Stream
, long
(File
.Bytes
) *
286 long
(File
.Index
- 1), SEEK_SET
) /= 0
296 function Size
(File
: File_Type
) return Count
is
298 FIO
.Check_File_Open
(AP
(File
));
299 File
.Last_Op
:= Op_Other
;
301 if fseek
(File
.Stream
, 0, SEEK_END
) /= 0 then
305 return Count
(ftell
(File
.Stream
) / long
(File
.Bytes
));
315 Size
: Interfaces
.C_Streams
.size_t
;
316 Zeroes
: System
.Storage_Elements
.Storage_Array
)
320 -- Do the actual write
326 procedure Do_Write
is
328 FIO
.Write_Buf
(AP
(File
), Item
, Size
);
330 -- If we did not write the whole record (happens with the variant
331 -- record case), then fill out the rest of the record with zeroes.
332 -- This is cleaner in any case, and is required for the last
333 -- record, since otherwise the length of the file is wrong.
335 if File
.Bytes
> Size
then
336 FIO
.Write_Buf
(AP
(File
), Zeroes
'Address, File
.Bytes
- Size
);
340 -- Start of processing for Write
343 FIO
.Check_Write_Status
(AP
(File
));
345 -- If last operation was not a write, or if in file sharing mode,
346 -- then reset the physical pointer of the file to match the index
347 -- We lock out task access over the two operations in this case.
349 if File
.Last_Op
/= Op_Write
350 or else File
.Shared_Status
= FCB
.Yes
352 Locked_Processing
: begin
362 end Locked_Processing
;
368 File
.Index
:= File
.Index
+ 1;
370 -- Set last operation to write, unless we did not read a full record
371 -- (happens with the variant record case) in which case we set the
372 -- last operation as other, to force the file position to be reset
373 -- on the next write.
375 File
.Last_Op
:= (if File
.Bytes
= Size
then Op_Write
else Op_Other
);
378 -- The following is the required overriding for Stream.Write, which is
379 -- not used, since we do not do Stream operations on Direct_IO files.
382 (File
: in out Direct_AFCB
;
383 Item
: Ada
.Streams
.Stream_Element_Array
)
389 end System
.Direct_IO
;