Closing files

Use the fclose() library function to close a file. z/OS® XL C/C++ automatically closes files on normal program termination and attempts to do so under abnormal program termination or abend. See z/OS XL C/C++ Runtime Library Reference for more information on this library function.

For files opened in fixed binary mode, incomplete records will be padded with null characters when you close the file.

For files opened in variable binary mode, incomplete records are flushed to the system. In a spanned file, closing a file can cause a zero-length segment to be written. This segment will still be part of the non-zero-length record. For files opened in undefined binary mode, any incomplete output is flushed on close.

Closing files opened in text mode causes any incomplete new record to be completed with a new-line character. All records not yet flushed to the file are written out when the file is closed.

For files opened for record I/O, closing causes all records not yet flushed to the file to be written out.

Note: If an application has locked a (FILE *) object (with flockfile() or ftrylockfile()), it is responsible for relinquishing the locked (FILE *) object (with funlockfile()) before calling fclose(). Failure to relinquish a locked (FILE *) object may cause deadlock or looping.

When fclose() is used to close a stream associated with a z/OS data set, some failures may be unrecoverable, and will result in an ABEND. These ABENDs may include I/O ABENDs of the form x14 and x37. Control will not be returned to the caller of fclose() to report the error. To process these types of errors, applications need to use z/OS Language Environment® condition handling to receive control (see z/OS Language Environment Programming Guide), or register a signal handler for SIGABND (see Handling error conditions, exceptions, and signals).

If an application fails during fclose() with a x37 abend, and the application would like to recover and perform any functions not related to file I/O, the following technique can be used. Refer to Figure 1 for an example.

  1. Register a signal handler for SIGABND and SIGIOERR.
  2. fopen() the file. The NOSEEK option cannot be specified.
  3. Manipulate the file as needed by the application.
  4. When the application is done with the file, fflush() the file, before any fclose() is issued. This will ensure, if an x37 is going to occur during fflush() or fclose() processing, that the x37 occurs in the fflush(), before the fclose() occurs.
  5. An x37 abend occurs during fflush().
  6. The signal handler will receive control.
  7. Once inside the signal handler, any functions not related to file I/O may be performed.
Figure 1. Example of signal handler
/* example of signal handler */

#include <stdio.h>
#include <stdlib.h>
#include <dynit.h>
#include <signal.h>
#include <setjmp.h>

void sighandler();
jmp_buf env;
FILE *f;

int main()
{
    int rc;
    int s=80;
    int w;
    char buff 80 ="data";
    __dyn_t ip;

    redo:
    dyninit(&ip);
    ip.__dsname="MY.DATASET";
    ip.__status=__DISP_OLD;
    ip.__ddname="NAMEDD";
    ip.__conddisp=__DISP_CATLG;
    rc=dynalloc(&ip);

    f=fopen("DD:NAMEDD","wb");
    if (f==0)
    {   perror("open error");
    return 12;
    }

    signal(SIGABND,sighandler);
    signal(SIGIOERR,sighandler);

    while (1)
    {
        if (setjmp(env))
        {
            dyninit(&ip);
            ip.__ddname="NAMEDD";
            ip.__conddisp=__DISP_CATLG;
            rc= dynfree(&ip);
            goto retry;
        }
        w=fwrite(buff,1,s,f);
    }

    fflush(f);
    fclose(f);

    retry:
    goto redo;
}

void sighandler() {
    fclose(f);
    longjmp(env,1);
}
Note: When an abend condition occurs, a write-to-programmer message about the abend is issued and your DCB abend exit is given control, provided there is an active DCB abend exit routine address in the exit list contained in the DCB being processed. If STOW called the end-of-volume routines to get secondary space to write an end-of-file mark for a PDS, or if the DCB being processed is for an indexed sequential data set, the DCB abend exit routine is not given control if an abend condition occurs. If the situation described above is encountered, the Language Environment DCB abend exit will not receive control, and therefore the signal handler routine in an application will not receive control for the x37 abend.