1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
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).
*/
};
|