1 ------------------------------------------------------------------------------
3 -- GNAT RUNTIME COMPONENTS --
5 -- S Y S T E M . D I R E C T _ I O --
9 -- Copyright (C) 1992-2003 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Ada
.IO_Exceptions
; use Ada
.IO_Exceptions
;
35 with Interfaces
.C_Streams
; use Interfaces
.C_Streams
;
36 with System
; use System
;
39 with System
.Soft_Links
;
40 with Unchecked_Deallocation
;
42 package body System
.Direct_IO
is
44 package FIO
renames System
.File_IO
;
45 package SSL
renames System
.Soft_Links
;
47 subtype AP
is FCB
.AFCB_Ptr
;
48 use type FCB
.Shared_Status_Type
;
50 use type System
.CRTL
.long
;
51 use type System
.CRTL
.size_t
;
53 -----------------------
54 -- Local Subprograms --
55 -----------------------
57 procedure Set_Position
(File
: in File_Type
);
58 -- Sets file position pointer according to value of current index
64 function AFCB_Allocate
(Control_Block
: Direct_AFCB
) return FCB
.AFCB_Ptr
is
65 pragma Unreferenced
(Control_Block
);
68 return new Direct_AFCB
;
75 -- No special processing required for Direct_IO close
77 procedure AFCB_Close
(File
: access Direct_AFCB
) is
78 pragma Unreferenced
(File
);
88 procedure AFCB_Free
(File
: access Direct_AFCB
) is
90 type FCB_Ptr
is access all Direct_AFCB
;
92 FT
: FCB_Ptr
:= FCB_Ptr
(File
);
95 Unchecked_Deallocation
(Direct_AFCB
, FCB_Ptr
);
106 (File
: in out File_Type
;
107 Mode
: in FCB
.File_Mode
:= FCB
.Inout_File
;
108 Name
: in String := "";
109 Form
: in String := "")
111 Dummy_File_Control_Block
: Direct_AFCB
;
112 pragma Warnings
(Off
, Dummy_File_Control_Block
);
113 -- Yes, we know this is never assigned a value, only the tag
114 -- is used for dispatching purposes, so that's expected.
117 FIO
.Open
(File_Ptr
=> AP
(File
),
118 Dummy_FCB
=> Dummy_File_Control_Block
,
131 function End_Of_File
(File
: in File_Type
) return Boolean is
133 FIO
.Check_Read_Status
(AP
(File
));
134 return Count
(File
.Index
) > Size
(File
);
141 function Index
(File
: in File_Type
) return Positive_Count
is
143 FIO
.Check_File_Open
(AP
(File
));
144 return Count
(File
.Index
);
152 (File
: in out File_Type
;
153 Mode
: in FCB
.File_Mode
;
155 Form
: in String := "")
157 Dummy_File_Control_Block
: Direct_AFCB
;
158 pragma Warnings
(Off
, Dummy_File_Control_Block
);
159 -- Yes, we know this is never assigned a value, only the tag
160 -- is used for dispatching purposes, so that's expected.
163 FIO
.Open
(File_Ptr
=> AP
(File
),
164 Dummy_FCB
=> Dummy_File_Control_Block
,
178 (File
: in File_Type
;
180 Size
: in Interfaces
.C_Streams
.size_t
;
181 From
: in Positive_Count
)
184 Set_Index
(File
, From
);
185 Read
(File
, Item
, Size
);
189 (File
: in File_Type
;
191 Size
: in Interfaces
.C_Streams
.size_t
)
194 FIO
.Check_Read_Status
(AP
(File
));
196 -- If last operation was not a read, or if in file sharing mode,
197 -- then reset the physical pointer of the file to match the index
198 -- We lock out task access over the two operations in this case.
200 if File
.Last_Op
/= Op_Read
201 or else File
.Shared_Status
= FCB
.Yes
203 if End_Of_File
(File
) then
207 Locked_Processing
: begin
210 FIO
.Read_Buf
(AP
(File
), Item
, Size
);
217 end Locked_Processing
;
220 FIO
.Read_Buf
(AP
(File
), Item
, Size
);
223 File
.Index
:= File
.Index
+ 1;
225 -- Set last operation to read, unless we did not read a full record
226 -- (happens with the variant record case) in which case we set the
227 -- last operation as other, to force the file position to be reset
230 if File
.Bytes
= Size
then
231 File
.Last_Op
:= Op_Read
;
233 File
.Last_Op
:= Op_Other
;
237 -- The following is the required overriding for Stream.Read, which is
238 -- not used, since we do not do Stream operations on Direct_IO files.
241 (File
: in out Direct_AFCB
;
242 Item
: out Ada
.Streams
.Stream_Element_Array
;
243 Last
: out Ada
.Streams
.Stream_Element_Offset
)
253 procedure Reset
(File
: in out File_Type
; Mode
: in FCB
.File_Mode
) is
255 FIO
.Reset
(AP
(File
), Mode
);
257 File
.Last_Op
:= Op_Read
;
260 procedure Reset
(File
: in out File_Type
) is
262 FIO
.Reset
(AP
(File
));
264 File
.Last_Op
:= Op_Read
;
271 procedure Set_Index
(File
: in File_Type
; To
: in 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
: in File_Type
) is
285 (File
.Stream
, long
(File
.Bytes
) *
286 long
(File
.Index
- 1), SEEK_SET
) /= 0
296 function Size
(File
: in 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
: in Interfaces
.C_Streams
.size_t
;
316 Zeroes
: System
.Storage_Elements
.Storage_Array
)
320 -- Do the actual write
322 procedure Do_Write
is
324 FIO
.Write_Buf
(AP
(File
), Item
, Size
);
326 -- If we did not write the whole record (happens with the variant
327 -- record case), then fill out the rest of the record with zeroes.
328 -- This is cleaner in any case, and is required for the last
329 -- record, since otherwise the length of the file is wrong.
331 if File
.Bytes
> Size
then
332 FIO
.Write_Buf
(AP
(File
), Zeroes
'Address, File
.Bytes
- Size
);
336 -- Start of processing for Write
339 FIO
.Check_Write_Status
(AP
(File
));
341 -- If last operation was not a write, or if in file sharing mode,
342 -- then reset the physical pointer of the file to match the index
343 -- We lock out task access over the two operations in this case.
345 if File
.Last_Op
/= Op_Write
346 or else File
.Shared_Status
= FCB
.Yes
348 Locked_Processing
: begin
358 end Locked_Processing
;
364 File
.Index
:= File
.Index
+ 1;
366 -- Set last operation to write, unless we did not read a full record
367 -- (happens with the variant record case) in which case we set the
368 -- last operation as other, to force the file position to be reset
369 -- on the next write.
371 if File
.Bytes
= Size
then
372 File
.Last_Op
:= Op_Write
;
374 File
.Last_Op
:= 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
: in Ada
.Streams
.Stream_Element_Array
)
389 end System
.Direct_IO
;