![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Files and I/O This chapter describes file access and I/O as performed using Rational Apex. Sections include:
- Predefined I/O Packages
- Opening and Creating Files
- Using Special File Types
- File I/O
- Determining a File's Name
- I/O Deviations from POSIX.5
Predefined I/O PackagesImplementation-dependent aspects of the Ada-predefined I/O packages are described in Input/Output Packages in the Ada Compiler Reference Guide.
POSIX.5 describes how the predefined I/O packages should manage files and I/O, but leaves room for interpretations and implementation decisions. This chapter includes descriptions of how Rational Apex performs in comparison to POSIX.5.
Opening and Creating FilesForm Parameter for Create and Open Procedures
POSIX.5 specifies that the Form parameter on Create and Open procedures that perform text I/O should have a specific set of legal values (POSIX.5 8.1.1.2). Apex supports those values as described in the following subsections:
Note: Form parameter is not supported on VxWorks or Rational Exec.
Syntax of the Form Parameter
The Form parameter can contain a string consisting of the following fields:
[ APPEND =>boolean_literal
] [, BLOCKING => PROGRAM | TASKS | NONE ] [, FILE_DESCRIPTOR =>integer_literal
] [, FILE_STRUCTURE => REGULAR | FIFO ] [, OWNER | GROUP | OTHER => NONE | READ | WRITE | EXECUTE | READ_WRITE | READ_EXECUTE | WRITE_EXECUTE | READ_WRITE_EXECUTE ] [, PAGE_TERMINATORS =>boolean_literal
] [, REPLACE =>boolean_literal
] [, RESOLVE_PATH =>boolean_literal
] [, TERMINAL_INPUT => LINES | CHARACTERS ] [, TRUNCATE =>boolean_literal
]
Field Defaults
Two default sets are defined for the Form parameter: the POSIX default set and the Apex default set. Both sets are shown in Table 3.
To select the POSIX default set, use pragma Main with its Posix_Compliant argument set to True. This is the default. In this case, the Ada-predefined I/O routines behave as required by POSIX.5 and as modified by the descriptions in this chapter.
The Apex default set is selected when Posix_Compliant is set to False. In this case, Ada-predefined I/O provides upward compatibility with Apex releases prior to 1.2.
1 Error file descriptor.
Descriptions
All fields are allowed for all Create and Open procedures in packages Text_Io, Sequential_Io, and Direct_Io, unless otherwise specified.
Each field can appear only once in any given Form parameter. If a field appears more than once, Use_Error is raised. Note that Owner, Group, and Other can all appear in the same Form parameter.
The field names can be abbreviated. The abbreviated names are treated in POSIX.5 terms as implementation-defined fields having the same functionality as the full POSIX.5 defined field names.
Warning: The subprograms of Posix_Supplement_To_Ada_Io do not recognize abbreviations. To ensure POSIX.5 compliance, it is recommended that your program use the full field names.
Creating Files
The Create procedures in the predefined I/O packages always create a new file. If a file with the same name already exists when Create executes, setting the Form parameter's Replace field determines whether to replace the file or to raise an exception.
Owner Access Permissions for File Creation
The Create procedures allow you to set access permissions for a newly created file with the Form parameter's Owner, Group, and Other fields.
Permissions are granted only as allowed by the operating system. If higher access permission is requested than is available, Create grants only the highest allowed permission. No warning is generated.
If the Owner permissions are not appropriate for the value specified for the Mode parameter, the Create operation will create the file and then raise the Use_Error exception without opening the file. Specific cases include:
- Creating a file with output mode without giving the owner write permission. For example:
Create (Mode => Out_File, Form => "Owner => Read");
- Creating a file and giving the owner no access, regardless of the Mode. For example:
Create (Form => "Owner => None");
Note: By contrast, the UNIX open call using O_CREAT as the flag value opens the file even if the Owner permissions aren't appropriate. The Apex strategy, however, ensures consistent behavior for regular and FIFO files.
Opening Files
POSIX.5 allows files to be opened in two ways:
- By specifying the external filename of a file, in which case, Open finds the external file, opens it as an Ada file, and assigns an internal (not user-visible) file descriptor
- By specifying an existing OS file descriptor for an external file that has been opened using some other OS or POSIX.5 utility, in which case, Open associates the open descriptor with an Ada file
The former is achieved by calling Open without the Form parameter's File_Descriptor field, whether or not the file was previously opened by any other operation. The latter is achieved by calling Open with a File_Descriptor.
POSIX.5 does not clearly describe the impact during an Open of associating an Ada file with a file descriptor, and the effect of subsequent I/O operations on such files is not specified at all.
Apex attempts to make such files act as ordinary Ada files when the Ada-predefined I/O packages operate on them. The seek pointer and file flags are set as if the file is an ordinary, named Ada file. In particular, the Form parameter's Append, Blocking, Page_Terminator, Truncate, and Terminal_Input fields have the usual effect. Ada-predefined I/O might leave the file descriptor in a state different than it was before it was associated with an Ada file.
There are differences, however:
- The Name parameter supplied to Open is ignored; calling the Name function raises Use_Error.
- The file Mode provided with Open and Reset must be compatible with the actual file access mode of the existing file descriptor. Compatible modes are:
O_RDONLY => In_File O_WRONLY => Out_File O_RDWR => In_File | Out_File | Inout_File
- Close does not close the file descriptor; it only severs the association between the Ada file and the descriptor and marks the Ada file as closed.
- Delete does not delete the external file; it closes the Ada file as described above and then raises Use_Error.
Using Special File TypesUsing FIFO Special Files
All Ada-predefined I/O packages allow access to FIFO special files (POSIX.5 2.2.2.27). However, some I/O operations applied to FIFO files behave in unexpected ways or are not supported.
Unsupported operations that raise the Use_Error exception include:
- Index and Set_Index.
- End_Of_File for Sequential_Io and Direct_Io. As an alternative method for determining end of file, use Direct_Io.Size.
Operations with unexpected results include:
- Text_Io.End_Of_File is unreliable in that, once an end of file has been returned, Text_Io continues to act as though end of file has been reached.
- Create, Open, and Reset with a Mode of In_File or Out_File cause blocking until the file is opened a second time with a Mode of Out_File or In_File, respectively. Using Inout_File on Create and Open avoids blocking.
- Reading from an empty FIFO file causes blocking.
- Reading from a FIFO file that has been closed by the writing task raises the End_Error exception.
- Writing into a FIFO file that has been closed by the reading task generates the SIGPIPE UNIX signal, which is not handled by Apex.
- Page, Line, and Col —— and other routines dealing with text structures such as pages, lines, and columns —— return meaningless results or raise Use_Error.
- Text_Io has unpredictable blocking behavior as described in Blocking I/O on FIFO Files.
Using Files Associated with Terminal Devices
The following Form-parameter field values, when applied to a file associated with a terminal device, affect the device in addition to the file:
- Terminal_Input => Characters
- Blocking => None
- Blocking => Tasks
Opening a terminal device with one of these field values might adversely affect other files already associated with the device. In Apex, the Ada-predefined I/O routines keep track of these side effects only as far as necessary to maintain internal consistency. A program that does not take the side effects into account is considered erroneous.
File I/OAdding Output to Files
When Open or Reset is called on an existing file opened for output, you must decide how to apply new output:
- Append it after any existing file content
- Truncate all existing content before placing new output into the file
- Leave existing content in the file and overwrite the content starting at the beginning of the file
POSIX.5 provides the Form parameter's Append field to specify whether to append new output after opening a file with an Out_File Mode.
POSIX.5 does not specify what to do, however, if Append is False, nor whether the Append field from the Open call applies to the resetting of the file with an Out_File Mode.
Apex provides the additional field, Truncate, where True corresponds to truncating existing content and False corresponds to overwriting, assuming that Append is False. Together, these fields affect the Open and Reset procedures as shown in Table 4.
The default value of Truncate depends on the kind of I/O to be performed. For files opened by Sequential_Io or Text_Io, the default value is True; for files opened by Direct_Io, the default value is False.
Direct_Io does not support the Append field, but it does support Truncate.
The functions Page, Line, and Col return the page, line, and column numbers as counted since the last Reset or Open. This might correspond to the actual number of pages, lines, or columns in the file, unless Truncate is True and Append is False, in which case the returned values are correct.
Ada83 LRM 14.3(6), Ada95 LRM A.10 states that closing a file will implicitly terminate the current line and the current page; however, Apex does not write explicit end-of-line or end-of-page characters to a file when it is closed.
Note: When Text_Io opens a text file with existing content in Append mode, output appended to the file starts on a new line but not on a new page.
Using Blocking and Nonblocking I/O
Whether tasks perform blocking I/O on a given file is determined by the Form parameter's Blocking field on the Create or Open procedure for the file and by the Nonblocking_Io argument on pragma Main. Blocking and nonblocking I/O is also discussed in I/O in Tasking Programs.
Valid Blocking field values and their meanings are:
- Program —— All tasks of a program block when UNIX cannot immediately satisfy an I/O request on that file. Any I/O operation might cause a program to block.
This is the standard behavior of Ada-predefined I/O and is a POSIX.5-defined value.
- Tasks —— Only one task of a program (the task issuing the I/O request) blocks if UNIX cannot immediately satisfy an I/O request on that file. This value applies only to files corresponding to TTY devices; otherwise, the results are unpredictable (in particular, a task might block forever).
On rare occasions, the entire program might block when a task performs I/O on a file accessed using this value. This happens only when a device signals that it is ready to accept or provide data when it actually is not because the I/O would exceed UNIX system limitations or quotas.
This is a POSIX.5-defined value; its behavior is shown in Table 5.
- None —— No tasks of a program block if UNIX cannot immediately satisfy an I/O request on the file. Instead, an exception (Use_Error, Data_Error, or Device_Error) is propagated to the task that invoked the I/O operation.
This is an implementation-defined value; its behavior is shown in Table 5.
Blocking I/O on FIFO Files
When applied to FIFO files, the blocking behavior of Text_Io is unpredictable, so avoid using Text_Io for FIFO file operations. Instead, use Sequential_Io instantiated with a fixed-length string.
Table 5 Nonblocking I/O Summary
I/O routine File mode Blocking = tasks Blocking = none
Create, Open, Reset In_File or Inout_File Never blocks Never blocks
Create, Open, Reset Out_File Raises Device_Error if the operation would otherwise block, which should happen only when the file is a broken FIFO, pipe, or communication link.
Close, Delete n/a Raises Device_Error if the operation would otherwise block (should never happen).
Write, Put, Put_Line, Set_Col, Set_Line, New_Line, New_Page Out_File or Inout_File Causes the calling task to block if the output device is not immediately ready to accept data. Raises Use_Error if the operation would otherwise block.
Read, Get, Get_Line, Set_Col, Set_Line, Skip_Line,
Skip-_Page,
End_Of_Line,
End_Of_PageIn_File or Inout_File Causes the calling task to block if no data is immediately available from the input device. Raises Data_Error if the operation would otherwise block.
Text_Io maintains input as well as output buffers, so Text_Io operations might delay output and read ahead upon input. To keep its input buffer full, Text_Io might actually access the external file even if a Get request could be satisfied solely from data that is already in the buffer. As a result, Text_Io will block more often than necessary upon input from a FIFO file, unless the writer and reader of the file maintain a strict data-exchange protocol.
Setting the Form parameter's Blocking field to None does not prevent this blocking behavior; it just replaces unexpected blocking with unexpected exceptions.
Flushing Text Files
Text files are normally written in units of entire lines, where a complete line includes a line terminator. Before Apex flushes a text file's buffer, explicitly with Flush_Text_Io or implicitly with Flush_All (both of Posix_Supplement_To_Ada_Io), it adds a line terminator to a nonempty buffer that does not already contain a line terminator. Subsequent output using Text_Io starts on a new line.
Warning: Flush_Text_Io and Flush_All on files opened using Text_Io, adds a line terminator without incrementing the line counter or resetting the column counter to 1. To avoid problems, use these procedures only after an entire line has been written using Put_Line or New_Line;. Otherwise, other Text_Io operations might behave in an unexpected manner.
Errors and Exceptions
The End_Error exception (and also End_Of_File = True, if supported) indicates that no more data will ever be available from a file. This exception is raised when, for example, the end of a regular file is reached, a communication link is closed, or a pipe is broken.
The Data_Error exception indicates that no more data is currently available.
Determining a File's NameApex supports two different approaches to identifying files using the Name functions found in all Ada-predefined I/O packages: the POSIX approach and the Apex approach.
Ada83 LRM 14.2.1(21), Ada95 LRM A.8.2 states that the Name function should return a string that uniquely identifies the file. To support this, POSIX.5 8.1.1.4(163) suggests that the Name function, when applied to an open file:
- Return the absolute pathname of the file, if a filename can be determined.
- Raise Use_Error if the filename cannot be determined (that is, if the file is not a named object in the file system).
In standard Apex, the Name function:
- Returns exactly what was specified upon Open or Create if the filename can be determined. For example, if the program specified an absolute pathname, Name returns the absolute pathname; if the program specified a name relative to the current working directory, Name returns only the specified part of the name.
- Returns the null string ("") if the filename cannot be determined.
The second approach is more efficient, because it does not have to scan the directory tree for the name of the current working directory.
You can select the approach that you prefer using the Resolve_Path field of the Form parameter. The POSIX.5 approach is achieved by setting Resolve_Path to True; setting it to False achieves the standard Apex approach.
The Name function is POSIX.5-compliant if Resolve_Path is True or if Resolve_Path is False, but files are always opened or created using an absolute pathname.
This field's default changes depending on various factors. Refer to Field Defaults, for more information.
I/O Deviations from POSIX.5The generic procedures Flush_Sequential_Io and Flush_Direct_Io of Posix_Supplement_To_Ada_Io are not implemented; calls to these procedures will result in semantic errors.
Rational Software Corporation http://www.rational.com support@rational.com techpubs@rational.com Copyright © 1993-2002, Rational Software Corporation. All rights reserved. |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |