CMS Low-Level I/O Functions

The library provides a set of functions that perform CMS disk file input and output operations. These functions are characterized as low-level I/O functions because they use the CMS file system directly. The library provides a second set of functions that can perform I/O operations on files in XEDIT storage. These functions are known as the XEDIT low-level I/O functions.

This chapter covers the low-level I/O functions as well as three utility functions that can be used with the I/O functions. Note that these functions are not portable.

The CMS low-level I/O functions are:

cmsstate
verifies the existence of a CMS disk file
cmsopen
opens a CMS disk file
cmsread
reads a record from a CMS disk file
cmswrite
writes a record to a CMS disk file
cmspoint
changes the current record pointer for a CMS disk file
cmsclose
closes a CMS disk file
cmserase
erases a CMS disk file.
The low-level XEDIT I/O functions are:
cmsxflst
verifies the existence of an XEDIT file
cmsxflrd
reads a record from XEDIT storage
cmsxflwr
writes a record to XEDIT storage
cmsxflpt
moves the current line pointer in an XEDIT file.
The related utility functions are:
cmspid
tokenizes a filename string in "cms" or "xed" style
cmsdfind
finds a file identifier that matches a pattern
cmsdnext
finds the next file identifier that matches a pattern.

CMS Low-Level I/O Functions

Descriptions of each CMS low-level I/O function follow.

SYNOPSIS

 #include <cmsio.h>

 int cmsstate(struct CMSFSCB *fscbp, struct CMSFST *fstp);
 int cmsopen(struct CMSFSCB *fscbp);
 int cmsread(struct CMSFSCB *fscbp);
 int cmswrite(struct CMSFSCB *fscbp);
 int cmspoint(struct CMSFSCB *fscbp);
 int cmsclose(struct CMSFSCB *fscbp);
 int cmserase(struct CMSFSCB *fscbp);
 

DESCRIPTION

The cmsstate function states or verifies the existence of a CMS disk file. The first argument to cmsstate is a pointer to a CMS File System Control Block (CMSFSCB) structure, and the second is a pointer to a CMS File Status Table (CMSFST) structure.

The remaining functions are as follows:

cmsopen
opens a CMS disk file.
cmsread
reads a record from a CMS disk file.
cmswrite
writes a record to a CMS disk file.
cmspoint
changes the current record pointer of a CMS disk file.
cmsclose
closes a CMS disk file.
cmserase
erases a CMS disk file.
The header file <cmsio.h> defines two structures for the CMS and XEDIT low-level I/O functions. The first structure maps a CMS FSCB and is defined as follows. (Note that extended FSCBs (FORM=E) are included.)
 struct CMSFSCB {   /* CMSFSCB definition            */
    char comm[8];   /* file system command           */
    char fn[8];     /* filename                      */
    char ft[8];     /* filetype                      */
    char fm[2];     /* filemode                      */
    short itno;     /* relative record number        */
    char *buff;     /* address of r/w buffer         */
    int size;       /* length of buffer              */
    char fv;        /* recfm - C'F' or C'V'          */

    char flg;       /* flag byte                     */
    short noit;     /* number of records             */
    int nord;       /* number of bytes actually read */
    int aitn;       /* extended record number        */
    int anit;       /* extended number of records    */
    int wptr;       /* extended write pointer        */
    int rptr;       /* extended read pointer         */
 };
 
The second structure maps a CMS FST and is defined as follows. (Again, note that the FORM=E fields are included.)
 struct CMSFST {
    char fname[8];  /* filename                      */
    char ftype[8];  /* filetype                      */
    short datew;    /* date last written - MMDD      */
    short timew;    /* time last written - HHMM      */
    short wrpnt;    /* write pointer - item number   */
    short rdpnt;    /* read pointer - item number    */
    char fmode[2];  /* filemode - letter and number  */
    short recct;    /* number of logical records     */
    short fclpt;    /* first chain link pointer      */
    char recfm;     /* record format - F or V        */
    char flags;     /* fST flag byte (read/write)    */
    int lrecl;      /* logical record length         */
    short blkcnt;   /* number of 800 byte blocks     */
    short yearw;    /* year last written             */
    int fop;        /* alternate file origin pointer */
    int adbc;       /* alt number of data blocks     */
    int aic;        /* alternate item count          */
    char nlvl;      /* number of ptr block levels    */
    char ptrsz;     /* length of a pointer element   */
    char adati[6];  /* alt date/time (YYMMDDHHMMSS)  */
    int _;
 };
 

RETURN VALUE

All of the functions return the return code from their associated CMS macro. If the return code from FSSTATE is 0, cmsstate copies the information from the CMS FST to the CMSFST structure pointed to by fstp.

IMPLEMENTATION

Each function invokes the associated CMS macro. All of the functions expect an extended format (FORM=E) FSCB. The following table lists each function and the CMS macro it executes:
Function  CMS Macro
-------------------
cmsstate  FSSTATE

cmsopen   FSOPEN

cmsread   FSREAD

cmswrite  FSWRITE

cmsclose  FSCLOSE

cmspoint  FSPOINT

cmserase  FSERASE
Refer to the appropriate IBM documentation for information about the data associated with the FSCB and FST and for information about these CMS macros.

EXAMPLE

The following example illustrates an interesting, if none too useful, change from the CMS TYPE command. This program reads a file backward and types each record to stdout.
 #include <cmsio.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>

 main(int argc, char **argv)
 {
    struct CMSFSCB fscb;
    struct CMSFST fst;
    register int rc;
    register char *buffer;

       /* Perform error checking as necessary.                      */
    if (argc < 2) {
       puts("Missing fileid");
       exit(4);
    }

    if (argc > 2) {
       puts("Extraneous parameters");
       exit(4);
    }

       /* Call cmspid to tokenize the fileid.                       */
    memset((void *) &fscb,'\0',sizeof(fscb));
    rc = cmspid(argv[1],&fscb);
    if (rc != 0) {
       printf("Fileid \"%s\" is invalid",argv[1]);
       exit(4);
    }

       /* Call cmsstate to get the file characteristics.            */
    rc = cmsstate(&fscb,&fst);
    if (rc != 0) {
       if (rc == 28)
          printf("File \"%s\" not found.\n",argv[1]);
       else
          printf("Error occurred while issuing FSSTATE.  RC=%d\n",rc);
       exit(rc);
    }

    buffer = malloc(fst.lrecl + 1);
    if (!buffer)
       exit(8);

       /* Fill in the required FSCB fields.                         */
    fscb.buff = buffer;
    fscb.size = fst.lrecl;
    fscb.fv = fst.recfm;
    fscb.anit = 1;

       /* Set current record number to number of records in file.   */
    fscb.aitn = fst.aic;
 
       /* Read the file backward; type records to the terminal.   */
    while ((rc = cmsread(&fscb)) == 0 && fscb.aitn > 0) {
       buffer[fscb.nord]= '\0';
       puts(buffer);
       --fscb.aitn;    /* Decrement the current record number.    */
    }

       /* Check for error while reading.                          */
    if (rc > 0) {
       printf("Error occurred while reading \"%s\".
               RC=%d\n", argv[1],rc);
       exit(rc);
    }
    exit(0);
 }
 

XEDIT Low-Level I/O Functions

Descriptions of each XEDIT low-level I/O function follow.

SYNOPSIS

 #include <cmsio.h>

 int cmsxflst(struct CMSFSCB *fscbp, struct CMSFST *fstp);
 int cmsxflrd(struct CMSFSCB *fscbp);
 int cmsxflwr(struct CMSFSCB *fscbp);
 int cmsxflpt(struct CMSFSCB *fscbp);
 

DESCRIPTION

The cmsxflst function states or verifies the existence of an XEDIT file. The first argument to cmsxflst is a pointer to a CMSFSCB structure, and the second argument is a pointer to a CMSFST structure.

The remaining functions are as follows:

cmsxflrd
reads a record from XEDIT storage.
cmsxflwr
writes a record to XEDIT storage.
cmsxflpt
moves the current line pointer in an XEDIT file.
A pointer to a CMSFSCB structure is the only argument for these functions.

Refer to the "CMS Low-Level I/O Functions" for a description of these structures.

RETURN VALUE

All of the functions return the return code from their associated XEDIT subcommand. If the return code from DMSXFST is 0, cmsstate copies the information from the CMS FST to the CMSFST structure pointed to by fstp.

IMPLEMENTATION

Each function invokes the associated XEDIT subcommand. All of the functions expect an extended format (FORM=E) FSCB. The following table lists each function and the XEDIT subcommand it executes:
Function  XEDIT Subcommand
--------------------------
cmsxflst  DMSXFLST

cmsxflrd  DMSXFLRD

cmsxflwr  DMSXFLWR

cmsxflpt  DMSXFLPT
Refer to the appropriate IBM documentation for information about the data associated with the FSCB and FST and for information about these XEDIT subcommands.

MACROS

Each of the XEDIT low-level I/O functions has an associated macro that can be used to provide a more readable name. The macros are defined in <cmsio.h> and are listed as follows:
 #define xedstate(fscb,fst) cmsxflst(fscb,fst)
 #define xedread(fscb) cmsxflrd(fscb)
 #define xedwrite(fscb) cmsxflwr(fscb)
 #define xedpoint(fscb) cmsxflpt(fscb)
 

EXAMPLE

The following example shows a program that uses cmsxflwr to write a date and time string at the current line of a file in XEDIT. The example shows how a program can communicate with XEDIT via the system function (using the "XEDIT prefix) and the cmsxflst function.

Note that XEDIT and either EXEC2 or REXX must be active when this function is executed. This sort of interaction between XEDIT and a program via an EXEC processor is most appropriate in a program using the SUBCOM interface or a program that is a REXX function package.

The example invokes the EXTRACT subcommand to place the filename, filetype, and filemode of the file into EXEC2 or REXX variables. Then, it calls execfetch to fetch the values of these variables and put them into a CMSFSCB structure. Next, it uses the time and ctime functions to create a date and time string. Finally, cmsxflwr writes the string into the file at the current line.

The example assumes that the file has fixed format records and a logical record length of 80. In practice, this information can be obtained with a call to cmsstat, cmsxflst, or via the EXTRACT subcommand. For clarity, all error checking after the initial call to system has been omitted.

For more information on the time, ctime, or system functions, refer to Chapter 6, "Function Descriptions," in SAS/C Library Reference, Third Edition, Volume 1,& Release 6.00 . For more information on the cmsshv function, refer to The CMS REXX SAS/C® Interface in this book.

 #include <cmsio.h>
 #include <lclib.h>
 #include <cmsexec.h>
 #include <lcstring.h>
 #include <time.h>

 main()
 {
    time_t now;
    struct CMSFSCB fscb;
    char timestring[80];
    int s, rc;

    rc = system("xedit: extract /fname/ftype/fmode");

    if (rc != 0) {
       printf("Unable to determine current fileid.  ");
       switch (rc) {
          case SYS_TNAC:
             puts("XEDIT is not active.");
             break;
          case SYS_CUNK:
             puts("Not called from EXEC2 or REXX exec.");
             break;
          default:
             if (rc > 0)
                printf("EXTRACT subcommand returned %d\n", rc);
             else
                printf("System function returned %d\n", rc);
             break;
       }
    }
    exit(rc);
 }

       /* Set all fields in CMSFSCB structure to zeros.    */
       /* Fetch fileid components.                         */
    memset((void *) &fscb,'\0',sizeof(fscb));
    cmsshv(SHV_FETCH_DIRECT,"FNAME.1",7,fscb.fn,8,&s);
    cmsshv(SHV_FETCH_DIRECT,"FTYPE.1",7,fscb.ft,8,&s);
    cmsshv(SHV_FETCH_DIRECT,"FMODE.1",7,fscb.fm,2,&s);

    fscb.fv = 'F';           /* RECFM F                    */
    fscb.size = 80;          /* LRECL 80                   */
    fscb.buff = timestring;  /* record buffer address      */
    fscb.aitn = 0;  /* A zero indicates the current line.  */

       /* Initialize record buffer.  Get the date and time */
       /* and copy to the record. Call cmsxflwr to write   */
       /* the record.                                      */
    memset(timestring,' ',80);
    now = time(NULL);
    memcpy(timestring,ctime(&now),24);
    cmsxflwr(&fscb);

    exit(0);
 }
 

Related Utility Functions

The cmspid, cmsdfind, and cmsdnext functions are often used in connection with CMS low-level I/O tasks. cmspid separates a CMS or XEDIT style filename string into filename, filetype, and filemode. cmsdfind and cmsdnext can be used to search for a specific CMS file. A description of cmspid follows. (See SAS/C Library Reference, Third Edition, Volume 1 for descriptions of cmsdfind and comsdnext.)

cmspid -- Tokenize a CMS Fileid

SYNOPSIS

 #include <cmsio.h>

 int cmspid(const char *name, struct CMSFSCB *fscbp);
 

DESCRIPTION

cmspid tokenizes the string pointed to by name and fills in the filename, filetype, and filemode in the CMSFSCB structure pointed to by fscbp. The string pointed to by name may be any filename in the cms or xed style.

RETURN VALUE

cmspid returns 0 if tokenizing is successful and fills in the appropriate fields in the CMSFSCB structure. If name cannot be tokenized or does not refer to a CMS or XEDIT file, -1 is returned.

CAUTION

A return code of 0 from cmspid does not imply that the file exists.

EXAMPLE

 #include <cmsio.h>

 struct CMSFSCB fscb;

 rc = cmspid("cms:profile.exec.a",&fscb);
 .
 .
 .
 

SEE ALSO


Copyright (c) 1998 SAS Institute Inc. Cary, NC, USA. All rights reserved.