0,0 → 1,231 |
[Quoting from a C/370 manual, courtesy of Carl Forde.] |
|
C/370 supports three types of input and output: text streams, binary |
streams, and record I/O. Text and binary streams are both ANSI |
standards; record I/O is a C/370 extension. |
|
[...] |
|
Record I/O is a C/370 extension to the ANSI standard. For files |
opened in record format, C/370 reads and writes one record at a |
time. If you try to write more data to a record than the record |
can hold, the data is truncated. For record I/O, C/370 only allows |
the use of fread() and fwrite() to read and write to the files. Any |
other functions (such as fprintf(), fscanf(), getc(), and putc()) |
fail. For record-orientated files, records do not change size when |
you update them. If the new data has fewer characters than the |
original record, the new data fills the first n characters, where |
n is the number of characters of the new data. The record will |
remain the same size, and the old characters (those after) n are |
left unchanged. A subsequent update begins at the next boundary. |
For example, if you have the string "abcdefgh": |
|
abcdefgh |
|
and you overwrite it with the string "1234", the record will look |
like this: |
|
1234efgh |
|
C/370 record I/O is binary. That is, it does not interpret any of |
the data in a record file and therefore does not recognize control |
characters. |
|
|
The record model consists of: |
|
* A record, which is the unit of data transmitted to and from a |
program |
* A block, which is the unit of data transmitted to and from a |
device. Each block may contain one or more records. |
|
In the record model of I/O, records and blocks have the following |
attributes: |
|
RECFM Specifies the format of the data or how the data is organized |
on the physical device. |
LRECL Specifies the length of logical records (as opposed to |
physical ones). |
|
BLKSIZE Specifies the length of physical records (blocks on the |
physical device). |
|
|
Opening a File by Filename |
|
The filename that you specify on the call to fopen() or freopen() |
must be in the following format: |
|
>> ----filename---- ----filetype-------------------- |
| | | | |
--.-- -- --filemode-- |
| | |
--.-- |
where |
|
filename is a 1- to 8-character string of any of the characters, |
A-Z, a-z, 0-9, and +, -, $, #, @, :, and _. You can separate it |
from the filetype with one or more spaces, or with a period. |
[Further note: filenames are fully case-sensitive, as in Unix.] |
|
filetype is a 1- to 8-character string of any of the characters, |
A-Z, a-z, 0-9, and +, -, $, #, @, :, and _. You can separate it |
from the filemode with one or more spaces, or with a period. The |
separator between filetype and filemode must be the same as the |
one between filename and filetype. |
|
filemode is a 1- to 2-character string. The first must be any of |
the characters A-Z, a-z, or *. If you use the asis parameter on |
the fopen() or freopen() call, the first character of the filemode |
must be a capital letter or an asterisk. Otherwise, the function |
call fails. The second character of filemode is optional; if you |
specify it, it must be any of the digits 0-6. You cannot specify |
the second character if you have specified * for the first one. |
|
If you do not use periods as separators, there is no limit to how |
much whitespace you can have before and after the filename, the |
filetype, and filemode. |
|
|
Opening a File without a File Mode Specified |
|
If you omit the file mode or specify * for it, C/370 does one |
of the following when you call fopen() or freopen(): |
|
* If you have specified a read mode, C/370 looks for the named file |
on all the accessed readable disks, in order. If it does not find |
the file, the fopen() or freopen() call fails. |
* If you have specified any of the write modes, C/370 writes the file |
on the first writable disk you have accessed. Specifying a write |
mode on an fopen() or freopen() call that contains the filename of |
an existing file destroys that file. If you do not have any |
writable disks accessed, the call fails. |
|
|
fopen() and freopen() parameters |
|
recfm |
CMS supports only two RECFMs, V and F. [note that MVS supports |
27(!) different RECFMs.] If you do not specify the RECFM for a |
file, C/370 determines whether is is in fixed or variable format. |
|
lrecl and blksize |
For files in fixed format, CMS allows records to be read and |
written in blocks. To have a fixed format CMS file treated as a |
fixed blocked CMS file, you can open the file with recfm=fb and |
specify the lrecl and blksize. If you do not specify a recfm on |
the open, the blksize can be a multiple of the lrecl, and the |
file is treated as if it were blocked. |
|
For files in variable format, the CMS LRECL is different from the |
LRECL for the record model. In the record model, the LRECL is |
equal to the data length plus 4 bytes (for the record descriptor |
word), and the BLKSIZE is equal to the LRECL plus 4 bytes (for |
the block descriptor word). In CMS, BDWs and RDWs do not exist, |
but because CMS follows the record model, you must still account |
for them. When you specify V, you must still allocate the record |
descriptor word and block descriptor word. That is, if you want |
a maximum of n bytes per record, you must specify a minimum LRECL |
of n+4 and a minimum BLKSIZE of n+8. |
|
When you are appending to V files, you can enlarge the record size |
dynamically, but only if you have not specified LRECL or BLKSIZE |
on the fopen() or freopen() command that opened the file. |
|
type |
If you specify this parameter, the only valid value for CMS disk |
files is type =record. This opens a file for record I/O. |
|
asis |
If you use this parameter, you can open files with mixed-case |
filenames such as JaMeS dAtA or pErCy.FILE. If you specify this |
parameter, the file mode that you specify must be a capital letter |
(if it is not an asterisk); otherwise; the function call fails and |
the value returned is NULL. |
|
|
Reading from Record I/O Files |
fread() is the only interface allowed for reading record I/O files. |
Each time you call fread() for a record I/O file, fread() reads |
one record from the system. If you call fread() with a request for |
less than a complete record, the requested bytes are copied to your |
buffer, and the file position is set to the start fo the next |
record. If the request is for more bytes that are in the record, |
one record is read and the position is set to the start of the next |
record. C/370 does not strip any blank characters or interpret any |
data. |
|
fread() returns the number of items read successfully, so if you |
pass a size argument equal to 1 and a count argument equal to the |
maximum expected length of the record, fread() returns the length, |
in bytes, of the record read. If you pass a size argument equal |
to the maximum expected length of the record, and a count argument |
equal to 1, fread() returns either 0 or 1, indicating whether a |
record of length size read. If a record is read successfully but |
is less than size bytes long, fread() returns 0. |
|
|
Writing to Record I/O Files |
fwrite() is the only interface allowed for writing to a file |
opened for record I/O. Only one record is written at a time. If |
you attempt to write more new data than a full record can hold or |
try to update a record with more data than it currently has, C/370 |
truncates your output at the record boundary. When C/370 performs |
a truncation, it sets errno and raises SIGIOERR, if SIGIOERR is not |
set to SIG_IGN. |
|
When you are writing new records to a fixed-record I/O file, if you |
try to write a short record, C/370 pads the record with nulls out |
to LRECL. |
|
At the completion of an fwrite(), the file position is at the start |
of the next record. For new data, the block is flushed out to the |
system as soon as it is full. |
|
|
fldata() Behavior |
When you call the fldata() function for an open CMS minidisk file, |
it returns a data structure that looks like this: |
|
struct __filedata { |
unsigned int __recfmF : 1, /* fixed length records */ |
__recfmV : 1, /* variable length records */ |
__recfmU : 1, /* n/a */ |
__recfmS : 1, /* n/a */ |
__recfmBlk : 1, /* n/a */ |
__recfmASA : 1, /* text mode and ASA */ |
__recfmM : 1, /* n/a */ |
__dsorgPO : 1, /* n/a */ |
__dsorgPDSmem : 1, /* n/a */ |
__dsorgPDSdir : 1, /* n/a */ |
__dsorgPS : 1, /* sequential data set */ |
__dsorgConcat : 1, /* n/a */ |
__dsorgMem : 1, /* n/a */ |
__dsorgHiper : 1, /* n/a */ |
__dsorgTemp : 1, /* created with tmpfile() */ |
__dsorgVSAM : 1, /* n/a */ |
__reserve1 : 1, /* n/a */ |
__openmode : 2, /* see below 1 */ |
__modeflag : 4, /* see below 2 */ |
__reserve2 : 9, /* n/a */ |
|
char __device; __DISK |
unsigned long __blksize, /* see below 3 */ |
__maxreclen; /* see below 4 */ |
unsigned short __vsamtype; /* n/a */ |
unsigned long __vsamkeylen; /* n/a */ |
unsigned long __vsamRKP; /* n/a */ |
char * __dsname; /* fname ftype fmode */ |
unsigned int __reserve4; /* n/a */ |
|
/* note 1: values are: __TEXT, __BINARY, __RECORD |
note 2: values are: __READ, __WRITE, __APPEND, __UPDATE |
these values can be added together to determine |
the return value; for example, a file opened with |
a+ will have the value __READ + __APPEND. |
note 3: total block size of the file, including ASA |
characters as well as RDW information |
note 4: maximum record length of the data only (includes |
ASA characters but excludes RDW information). |
*/ |
}; |