Chapter Contents

Previous

Next
BSAM Record-Oriented Interface Functions

BSAM Record-Oriented Interface Functions



Descriptions of each BSAM record-oriented interface function follow.

Portability SAS/C extension


SYNOPSIS
DESCRIPTION
osdcb
osopen, osopenj
osclose
osget
osput
osflush
ostell
osseek
RETURN VALUE
IMPLEMENTATION
EXAMPLE


SYNOPSIS

#include <osio.h>

DCB_t *osdcb(const char *ddn, const char *keywords, 
             exit_t exit_list, char **errp); 
int osopen(DCB_t *dcbp, const char *option, int autonote); 
int osopenj(DCB_t *dcbp, const char *option, int autonote); 
int osclose(DCB_t *dcbp, const char *option); 
int osget(DCB_t *dcbp, void **bufp, int *lenp); 
int osput(DCB_t *dcbp, const void *buf, int len); 
int osflush(DCB_t *dcbp, int func); 
int ostell(DCB_t *dcbp, ospos_t *posp); 
int osseek(DCB_t *dcbp, ospos_t pos);


DESCRIPTION


osdcb

The osdcb function builds and initializes a BSAM DCB and returns its address. It is somewhat easier to use in complicated applications than osbdcb but has more overhead. Either osdcb or osbdcb can be used to build a DCB to be processed by either BSAM interface. As with the DCB built by osbdcb , the DCB includes a 16-byte extension area for library and user use.

The ddn argument to osdcb is the DDname of the file to open. The DDname should be null-terminated and can be in either upper- or lowercase. A ddn value of 0 can be specified if the DDname is not known when the DCB is built. (In this case, the DDname must be stored in the DCBDDNAM field by the program before the DCB is opened.)

The keywords argument to osdcb is a null-terminated string containing DCB macro keywords, such as "dsorg=po,bufno=5". The supported keywords are DSORG, RECFM, LRECL, BLKSIZE, OPTCD, NCP and BUFNO. Keywords and their values can be specified in either upper- or lowercase. If several keywords are specified, they can be separated by blanks or commas.

The exit_list argument of osdcb is the same in all respects as the exit_list argument of osbdcb . See the description of that function for details.

The errp argument of osdcb is used to control the processing of errors in the keywords string. If errp is 0 and there is an error in the keywords string, a library warning message is written to stderr . If errp is not 0 , it should address a char * variable, in which is stored the address of the invalid keyword. This pointer can be used by the program to send a diagnostic or correct the error.

osdcb returns the address of the new DCB or 0 if no DCB was created because of an error in the keywords string.

osopen, osopenj

osopen and osopenj open a BSAM DCB for record-oriented access using a normal OPEN macro or an OPEN TYPE=J respectively. The option argument is a character string that should specify a valid OPEN macro keyword such as "input", "inout" or "updat". The string can be either upper- or lowercase. An invalid option is treated as "input". The autonote argument is an integer specifying whether the NOTE macro should be issued automatically after a READ or WRITE. A value of 0 means that NOTE is not issued automatically, and a nonzero argument means it is issued automatically. See Using osseek and ostell for more information on autonote .

When you use the record interface, RECFM=D data sets can be processed only with BUFOFF=L. (You do not need to set this option yourself; it is set automatically by the library.)

osopen and osopenj return 0 if successful or nonzero if unsuccessful.

osclose

osclose is called to close and free a DCB opened using osopen or osopenj . All buffers also are freed at the same time. The option argument is a character string that should specify a valid CLOSE macro keyword such as "leave" or "reread". The string can be either upper- or lowercase. An invalid option is treated as "disp". osclose returns 0 if the DCB is closed successfully or nonzero if any problems occur. Even if the return code is nonzero, the DCB will have been freed. (A nonzero return code generally indicates a problem flushing buffers.) Note that osclose can be used to free the storage for a DCB that failed to open.

osget

The osget function is called to read a record or record segment and return its address and length. The bufp argument addresses a void * variable in which the address of the record or record segment will be stored. The value stored always addresses the data, rather than the record prefix for V-format data. The lenp argument addresses an int variable in which to store the record or segment length. For a spanned data set, the negative of the segment length is stored except for the last or only segment of a record.

The return value from osget is 0 for normal completion, -1 for the end of the file, or -2 for some other error. See oscheck for more details on the return code meaning.

osput

The osput function is called to write a record or record segment. The buf argument is a void * pointer addressing the record or record segment to be written. The record should contain only data; any record prefix needed is built by the library. The len argument is the length of the record or record segment to be written. For a spanned record segment, len should be positive for the last (or only) segment of a record or, in any other case, the negative of the segment length. If the record length does not match the DCB LRECL specification, the record is padded with nulls or truncated. (This is not considered an error.) A length of 0 can be used to terminate a spanned record without adding any additional data.

The return value from osput is 0 in the normal case, -2 if an I/O error occurred, or -3 if osput was called for a file opened for UPDAT to write more bytes than were returned by the previous osget .

osflush

The osflush function is called to terminate all I/O to a DCB so the DCB can be modified safely. For instance, you should call osflush for a DCB before you issue the BSP SVC to backspace the file. The func argument to osflush can take on one of four values: QUIESCE , REPOS , SYNCH , or CONCAT . These macros are defined in <osio.h> .

A func value of QUIESCE to osflush informs the library that the position of the file will not be changed by processing after osflush completes. This enables the library to retain any blocks that are already read at the time osflush is called.

A func value of REPOS to osflush informs the library that the position of the file may change, or that for some other reason, all information about current file contents retained by the library should be purged. Specifying REPOS unnecessarily causes additional library processing the next time osget or osput is called for the DCB.

A func value of SYNCH to osflush specifies the same processing as REPOS , except that at the completion of all other processing, a CLOSE TYPE=T is issued to the DCB, thus writing an end-of-file mark and updating the directory for a PDS member.

A func value of CONCAT should be passed to osflush only for a call from an open exit for a concatenated input file. It handles resynchronization and reallocation of buffers, and it should not be used in any other circumstances.

The return value from osflush is normally 0 , but can be a negative value returned by oscheck if errors occur during processing.

ostell

The ostell function is called to store the current record address for a BSAM file. The argument posp is a pointer to an area of type ospos_t , in which the current record address should be stored. The definition of ospos_t is as follows:

typedef struct {
   unsigned _blkaddr;
   unsigned _recno;
} ospos_t;

The first field is the block address for the current block (as returned by osnote ) and the second field is the current record number. See Using osseek and ostell for more information on this function.

ostell returns 0 if successful or a nonzero value if it fails.

osseek

The osseek function is called to reposition a BSAM file. The argument pos is a value of type ospos_t defining the record to seek. It is not necessary to call osflush before calling osseek ; osseek does this automatically. See Using osseek and ostell for more information on this function.

osseek returns 0 if successful or a nonzero value if it fails. Note that an invalid argument to osseek may cause an ABEND or incorrect results later in processing rather than a nonzero return code.


RETURN VALUE

See the function descriptions here for return code details.


IMPLEMENTATION

These functions are implemented by the L$UOSIO module, which issues calls to the direct BSAM interface as necessary to perform I/O.


EXAMPLE

This example copies the contents of DDname INPUT to the DDname OUTPUT, and then uses the osstow function to update the PDS directory. The osflush(REPOS) function is used to force all output buffers to disk before updating the directory. Also, note the use of an open exit to define default attributes for the output data set.

#include <osio.h>
#include <stdio.h>

static DCB_t *input, *output;
static int open_exit();

main()
{
   exit_t out_exlst[1] = {LAST | OPEN, &open_exit};
   char *rec;
   int length;
   int err;
   int count = 0;
   struct {
      char name[8];
      unsigned TTRC;
   } stow_data = {"MYMEMBER", 0};

   input = osdcb("input", "recfm=fb,lrecl=80,bufno=10", 0, 0);
   if (osopen(input, "input", 0)) {
      puts("Input open failed.");
      exit(16);
   }
   output = osdcb("output", "recfm=fb,lrecl=80,bufno=10,dsorg=po",
                   out_exlst, 0);
   if (osopen(output, "output", 0)) {
      puts("Output open failed.");
      exit(16);
   }

   for (;;) {
      err = osget(input, &rec, &length);
      if (err != 0) {
         if (err != -1) puts("Input error.");
         break;
      }
      err = osput(output, rec, length);
      if (err != 0) {
         puts("Output error.");
         break;
      }
      ++count;
   }

   if (err == 0) {                   /* if there were no errors   */
      err = osflush(output, REPOS);   /* Flush output buffers.     */
      if (err == 0)
            /* Add member to PDS directory. */
         err = osstow(output, &stow_data, 'A');
   }
   if ((input->DCBRECFM & (DCBRECU | DCBRECSB)) ==
       (DCBRECV | DCBRECSB))          /* if input file was spanned */
      printf("%d segments copied.\n", count);
   else
      printf("%d records copied.\n", count);
   osclose(output, "");
   osclose(input, "");
}

static int open_exit(reg1, reg0)
DCB_t *reg1;
void *reg0;
{
   /* If output file attributes unset, copy from input attributes. */
   if (reg1->DCBRECFM == 0) {
      reg1->DCBRECFM = input->DCBRECFM;
      reg1->DCBLRECL = input->DCBLRECL;
      reg1->DCBBLKSI = input->DCBBLKSI;
   }
   return 0;
}


Chapter Contents

Previous

Next

Top of Page

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