FILE STATUS and return codes
Every I/O statement can fail. The dataset might not exist, the job might have the wrong DD, the disk might be full. Production code checks the outcome of every OPEN, READ, WRITE and CLOSE, and COBOL reports that outcome through a two-character file status.
Declaring it
Add FILE STATUS IS to the SELECT and declare the field in
WORKING-STORAGE as PIC XX. After each I/O statement on that file, the
runtime stores the result code in it:
IDENTIFICATION DIVISION.
PROGRAM-ID. STATDEMO.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT RATE-FILE ASSIGN TO RATES
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-RATE-STATUS.
DATA DIVISION.
FILE SECTION.
FD RATE-FILE.
01 RATE-REC PIC X(20).
WORKING-STORAGE SECTION.
01 WS-RATE-STATUS PIC XX.
PROCEDURE DIVISION.
OPEN INPUT RATE-FILE
DISPLAY "OPEN: " WS-RATE-STATUS
READ RATE-FILE
DISPLAY "READ: " WS-RATE-STATUS " " RATE-REC
READ RATE-FILE
DISPLAY "READ: " WS-RATE-STATUS
READ RATE-FILE
DISPLAY "READ: " WS-RATE-STATUS
CLOSE RATE-FILE
DISPLAY "CLOSE: " WS-RATE-STATUS
STOP RUN.
With DD_RATES pointing at a one-record dataset:
OPEN: 00
READ: 00 EUR 1.0000
READ: 10
READ: 46
CLOSE: 00
With DD_RATES pointing at a dataset that does not exist:
OPEN: 35
READ: 47
READ: 47
READ: 47
CLOSE: 42
Look at the second run carefully. Nothing stopped the program. Once you
declare a FILE STATUS, the runtime assumes you are handling errors, so
a failed OPEN is simply recorded and the program ploughs on. Without a
FILE STATUS clause, the same failed OPEN ends the run with a runtime
error instead (in GnuCOBOL, libcob: error: file does not exist (status
= 35)). Declaring a status and then ignoring it is the worst of both.
The codes you will meet
The first digit is the category, the second the detail.
| Code | Meaning |
|---|---|
00 |
Success |
05 |
OPEN of an OPTIONAL file that is not there (not an error) |
10 |
End of file: no more records |
2x |
Invalid key (indexed files, later) |
30 |
Permanent I/O error (hardware, space) |
35 |
OPEN of a file that does not exist |
37 |
OPEN mode not allowed for this file |
39 |
File attributes do not match the program (e.g. record length) |
41 / 42 |
OPEN of a file already open / CLOSE of a file not open |
46 |
READ after end of file was already reached |
47 / 48 / 49 |
READ, WRITE or REWRITE in the wrong OPEN mode |
Checking it
Give the status field 88-level names and test it after each operation:
01 WS-IN-STATUS PIC XX.
88 IN-OK VALUE "00".
88 IN-EOF VALUE "10".
With a FILE STATUS declared, a READ without AT END is fine: status
10 tells you it hit the end, and anything other than 00 or 10 is a
real error.
Failing the job step
When a batch program cannot continue, it should say why and end with a
non-zero return code. Move a value to the special register
RETURN-CODE before STOP RUN:
IF NOT IN-OK
DISPLAY "OPEN FAILED: STATUS " WS-IN-STATUS
MOVE 12 TO RETURN-CODE
STOP RUN
END-IF
On z/OS the return code becomes the step's condition code, and the
JCL uses it to skip later steps that depend on this one. Common shop
conventions: 0 fine, 4 warning, 8 error, 12 or 16 severe.
On the job
"Check every file status" is on every COBOL code-review checklist. Many shops have a standard error paragraph that displays the program name, file name, operation and status, then sets the return code, so the operator reading the job log at 2 a.m. knows exactly what failed.
Your task
Write a small utility that counts the records in any dataset, and fails cleanly if the dataset is missing.
The input is assigned to DD name INFILE (line sequential, records
up to 80 characters; content does not matter).
- Declare a FILE STATUS for the file and check it after the OPEN and after every READ.
- If the OPEN fails, display
OPEN FAILED: STATUSfollowed by the status, set the return code to 12 and stop. - If a READ returns anything other than
00or10, displayREAD FAILED: STATUSand the status, set the return code to 16 and stop. -
Otherwise count the records and display:
RECORDS: 00003
For a missing dataset the output is:
OPEN FAILED: STATUS 35
and the program must end with return code 12.