Chapter Contents

Previous

Next
Direct BSAM Interface Functions

Direct BSAM Interface Functions



Descriptions of each direct BSAM interface function follow.

Portability SAS/C extension


SYNOPSIS
DESCRIPTION
osbdcb
osfind
osbldl
osbopen, osbopenj
osfindc
osbclose, ostclose
osread, oswrite
oscheck
osnote, ospoint
osstow
RETURN VALUE
IMPLEMENTATION
EXAMPLE


SYNOPSIS

#include <osio.h>

DCB_t *osbdcb(exit_t exit_list); 
int osbopen(DCB_t *dcbp, const char *option); 
int osbopenj(DCB_t *dcbp, const char *option); 
int osbldl(DCB_t *dcbp, void *bldl_data); 
int osfind(DCB_t *dcbp, const char *member); 
int osfindc(DCB_t *dcbp, unsigned TTRK); 
void osbclose(DCB_t *dcbp, const char *option, int free); 
void ostclose(DCB_t *dcbp, const char *option); 
void osread(DECB_t decb, DCB_t *dcbp, void *buf, int length); 
void oswrite(DECB_t decb, DCB_t *dcbp, const void *buf,
             int length); 
int oscheck(DECB_t decb); 
unsigned osnote(DCB_t *dcbp); 
void ospoint(DCB_t *dcbp, unsigned blkaddr); 
int osstow(DCB_t *dcbp, const void *data, char type);


DESCRIPTION


osbdcb

The osbdcb function builds and initializes a BSAM DCB, and returns its address. The DCB address is then passed to the other routines to control their operation. The DCB includes a 16-byte extension of which 12 bytes are used by the library and 4 bytes are available for your use. (The name of the available field is DCBUSER.)

The argument to osbdcb , exit_list , is of type exit_t [] , and the return value is of type DCB_t * . Both of these types are defined in <osio.h> . The definition of exit_t is as follows:

enum _e_exit {INACTIVE, INHDR, OUTHDR, INTLR, OUTTLR, OPEN, EOV, JFCB,
         USER_TOTAL=10, BLK_COUNT, DEFER_INTLR, DEFER_NONSTD_INTLR,
         FCB=16, ABEND, JFCBE=21, TAPE_MOUNT=23, SECURITY=24,
         LAST=128, SYNAD=256};              /* exit type             */

typedef __remote int (*_e_exit_fp)(void *, void *);
                                  /* exit function type              */
typedef struct _e_exit_list {     /* exit list entry definition      */
   unsigned exit_code;            /* actually an enum _e_exit,       */
                                  /* possibly with LAST bit set      */
   union {     
      _e_exit_fp exit_addr;       /* exit function address           */
      void *area_addr;            /* pseudo-exit (e.g., JFCB) address*/
   };
} exit_t;

Consult IBM publication MVS/DFP Using Data Sets (SC26-4749) for information on the functions of the individual exits described by the codes above. Note that the last entry in the list must have the LAST bit set in its exit_code field. If only the LAST bit is set, the entry is considered inactive and ignored. You should specify an exit_code similar to (LAST | ABEND) if the last entry actually defines an exit.

If you need to pass a data address in the exit list, use the field name data_addr rather than area_addr to store it. Note that data addresses cannot be supplied as initial values for an exit list.

Note that the exit_list is converted by osbdcb into an assembler format exit list whose address is stored in DCBEXLST of the returned DCB. Modifications to the list passed to osbdcb after the call do not update the DCBEXLST value and, therefore, have no effect. Also note that if no exits are required, an argument of 0 should be passed to osbdcb .

The definition of DCB_t is too long to reprint here. It was generated from the DFP version 2 IHADCB DSECT using the DSECT2C utility. In addition to all the usual DCB symbols, the symbol DCBLRC_X has been defined as the DCBLRECL code stored to indicate LRECL=X.

Note:    The definition of DCB_t requires the use of the compiler option bitfield , with a default allocation unit of char , in order to compile correctly.  [cautionend]

osfind

The osfind function is called to issue the FIND macro for a DCB, to position the file to the start of a member. The member name is passed as a null-terminated string, in either upper- or lowercase. The value returned by osfind is the same as the return code from the FIND macro.

osbldl

The osbldl function can be used to locate PDS members more efficiently than with the osfind function. osbldl can look up more than one member at once.

The osbldl function is called to issue the MVS BLDL SVC to locate one or more members of a PDS. The dcbp argument is a pointer to the DCB for the PDS. The bldl_data argument is an area of storage defining the number and names of the members to be located. See IBM's DFP Macro Instructions for Data Sets for information on the format of the BLDL input data. bldl_data should be allocated below the 16 megabyte line. The value returned by osbldl is the R15 value returned by the BLDL SVC.

If you are using the record-oriented BSAM interface, you may need to use osflush before calling osfind to quiesce any outstanding I/O.

osbopen, osbopenj

The functions osbopen and osbopenj are called to open a DCB using either the normal OPEN macro or an OPEN with TYPE=J. The option argument is a character string that should specify a valid OPEN macro keyword such as "input", "inout", or "updat". The string may be either upper- or lowercase. An invalid option is treated as "input". osbopen and osbopenj return 0 if successful or nonzero if unsuccessful.

osfindc

The osfindc function can be used to locate PDS members more efficiently than with the osfind function. osfindc can locate a member without having to search the PDS directory.

The osfindc function is called to position to a PDS member using data returned by the osbldl function by issuing the MVS FIND C macro. The dcbp argument is a pointer to the DCB for the PDS. The TTRK argument is the TTRK value returned by osbldl for the required member. The osfindc function returns the value stored in register 15 by the FIND C macro.

Using the record-oriented BSAM interface, you may need to use osflush before calling osfind to quiesce any outstanding I/O.

osbclose, ostclose

The functions osbclose and ostclose are called to close a BSAM DCB permanently ( osbclose ) or temporarily ( ostclose ). The option argument is a character string that should specify a valid CLOSE macro keyword such as "leave" or "reread". The string may be either upper- or lowercase. An invalid option is treated as "disp". The free argument of osbclose specifies whether the DCB should be freed after the close: 0 leaves the DCB allocated and nonzero frees it. If the DCB is freed, a FREEPOOL macro also is issued to release any buffers allocated by OPEN. Note that osbclose can process a DCB that has already been closed or never opened. This is useful for freeing a DCB that could not be opened.

Note:    Files processed via MVS low-level I/O are not closed automatically by the library at program termination. This can cause a C03 ABEND for a program that opens one or more DCBs and then calls exit . You can use the atexit library function to define a cleanup routine that closes all open DCBs to avoid this problem.  [cautionend]

osread, oswrite

The functions osread and oswrite are called to read or write a block of data using a BSAM DCB. You must pass a DECB to control the operation. (This control block is later passed to oscheck to wait for the I/O to complete.) The data type DECB_t is defined by the library (as unsigned [5] ) as the type of a DECB. You must also pass osread and oswrite the address of the buffer containing the data to be read or written and the length to read or write. The length is meaningful only for RECFM=U records; you can specify a length of 0 to use the value in DCBBLKSI. (A length of 0 is equivalent to the assembler specification 'S'.) No value is returned by osread or oswrite because you need to call oscheck to determine whether an I/O operation was successful. Note that the buffer passed to osread or oswrite must be allocated below the 16-megabyte line in MVS/XA. One way to assure this is to define the buffer areas as auto because auto variables always are allocated below the line.

oscheck

oscheck is called to wait for a READ or WRITE to complete and to determine whether the I/O was successful. The argument to oscheck is the address of the DECB for the operation to check. The value returned by oscheck is 0 for a successful read or write, -1 if the end of the file was detected, and -2 if an I/O error occurred (that is, if the SYNAD exit was called) or if some other condition occurred that caused the DCB to be closed. Note that information on the length of an input block is not returned. See IBM's Using Data Sets for information on determining this for various record formats.

osnote, ospoint

The osnote and ospoint functions are used to query or modify the file position for a BSAM file. For a sequential file, you must set the DCBMRPT1 and DCBMRPT2 bits in the DCB before the file is opened to use these functions. osnote returns the value returned by the NOTE macro in register 1. This is a block number for a tape file or a TTRz value for a disk file.

osstow

The osstow function is used to update a PDS directory by issuing the STOW macro. The arguments to osstow must be located in storage below the 16Mb line. To ensure this, the arguments should be defined as auto variables or if they are external or static variables the RENT compiler option should be specified. The type argument is a single character specifying the operation to be performed, such as 'A' to add a directory entry or 'D' to delete one. The format of the data argument varies according to the type of request, as described in IBM's Using Data Sets. Note that a member name contained in the data area should not be null-terminated and will not be translated to uppercase. The return value from osstow is the same as the register 15 return code from the STOW macro.


RETURN VALUE

Return values are described in the section above on a function-by-function basis.


IMPLEMENTATION

With the exception of osbdcb , each function invokes the associated BSAM macro. Refer to IBM's Using Data Sets and the Macro Instructions for Data Sets (IBM publication SC26-4747) for more information on individual macros.


EXAMPLE

This example copies the DDname INPUT to the DDname OUTPUT a block at a time. Only record formats F, V, and VB are handled to avoid code to determine block length. A DCB ABEND exit is provided to intercept B37 and similar ABENDs and terminate execution cleanly in this example.

Note that this example uses several other unique features of the compiler, such as the inline SVC interface and anonymous unions.

#include <osio.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getmain.h>

static int abend_exit(void *reg1, void *reg0);

        /* Register 1 argument to DCB ABEND exit. */
struct abend_info {
   unsigned abend_code: 12;
   unsigned :4;
   unsigned char return_code;
   union {
      struct {
         unsigned :4;
         unsigned recover: 1;
         unsigned ignore: 1;
         unsigned delay: 1;
         unsigned :1;
      }ok_to;
      char action;
   };
   DCB_t *dcbp;
   void *O_C_EOV_workarea;
   void *recovery_work_area;
};

int full;     /* Set to 1 if "file full" ABEND occurs. */

main()
{
   DCB_t *input, *output;
   exit_t out_exlst[1] = {LAST | ABEND, &abend_exit };
   DECB_t input_DECB, output_DECB;
   char *buf;
   int count = 0;
   int err;

   input = osbdcb(0);
   memcpy(input->DCBDDNAM, "INPUT   ", 8);
   if (osbopen(input, "input")) {
      puts("Input open failed.");
      exit(16);
   }
   output = osbdcb(out_exlst);

      /* Copy output file characteristics from input. */
   output->DCBRECFM = input->DCBRECFM;
   output->DCBLRECL = input->DCBLRECL;
   output->DCBBLKSI = input->DCBBLKSI;
   memcpy(output->DCBDDNAM, "OUTPUT  ", 8);
   if (osbopen(output, "output")) {
      puts("Output open failed.");
      osbclose(input, "", 1);
      exit(16);
   }
   buf = (char *) GETMAIN_U(input->DCBBLKSI, 0, LOC_BELOW);

      /* Allocate buffer below the 16 megabyte line. */
   for (;;) {
      osread(input_DECB, input, buf, 0);
      if ((err = oscheck(input_DECB)) != 0) {
         if (err != -1) puts("Input error.");
         break;
      }
      oswrite(output_DECB, output, buf, 0);
      if (oscheck(output_DECB) != 0) {
         if (full) puts("Output file full.");
         else puts("Output error.");
         break;
      }
      ++count;
   }

   printf("%d blocks copied.", count);
   FREEMAIN(buf, input->DCBBLKSI, 0, UNCOND);
   osbclose(output, "", 1);
   osbclose(input, "", 1);
   return 0;
}

   /* reg0 is undefined and unused for this exit.            */
static int abend_exit(void *reg1, void *reg0)
{
   struct abend_info *info;

   info = (struct abend_info *) reg1;
   if ((info->abend_code == 0xb37 ||
        info->abend_code == 0xd37 ||
        info->abend_code == 0xe37) && info->ok_to.ignore)
        /* if ignorable file full condition */
   {
      full = 1;
      info->action = 4;      /* Tell BSAM to ignore ABEND.   */
   }
   else
      info->action = 0;      /* Let any other ABEND proceed. */
   return 0;
}


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.