www.sas.com > Service and Support > Technical Support
 
Technical Support SAS - The power to know(tm)
  TS Home | Intro to Services | News and Info | Contact TS | Site Map | FAQ | Feedback


#pragma eject
/*--------------------------------------------------------------------+
|                                                                     |
|                 Copyright (c) 1996, SAS Institute Inc.              |
|                   Unpublished - All Rights Reserved                 |
|                                                                     |
|                     S A S / C  S A M P L E                          |
|                                                                     |
|                                                                     |
|       Name: PDSREAD                                                 |
|                                                                     |
|   Language: C                                                       |
|                                                                     |
| EntryPoint: PDSREAD                                                 |
|                                                                     |
| Entry Type: C Linkage                                               |
|                                                                     |
| Files Note: 'prefix' is the installation defined high level         |
|             qualifier for the SAS/C product.                        |
|                                                                     |
|   Function: Read the PDS directory one block at a time.  Decode     |
|             each block and copy the member name, ttr, and alias     |
|             status to the struct PDS_MBR provided by the caller.    |
|                                                                     |
|             Update static variables in preparation for next call.   |
|                                                                     |
| Parameters:                                                         |
|             PDS_MBR * pds       - pointer to PDS_MBR struct where   |
|                                   member name, ttr, and alias status|
|                                   will be returned                  |
|                                                                     |
|             FILE * fp           - file pointer to a PDS which has   |
|                                   been opened for directory access  |
|                                                                     |
|    Returns:                                                         |
|                                                                     |
|            MEMBER_READY    - Struct PDS_MBR has been updated with   |
|                              member information.                    |
|            END_PDS_MEMBERS - All members have been processed.       |
|            EXIT_FAILURE    - A error/failure has occured.  A unique |
|                              message describing the error has been  |
|                              written to stderr                      |
|                                                                     |
|      Notes:                                                         |
|            - If pdsread() has I/O errors, any type, reading the     |
|              input dataset a message is displayed and the program   |
|              terminates immediately.                                |
|                                                                     |
+--------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>

#define MEMBER_READY      2000        /* Member returned to process  */
#define END_PDS_MEMBERS   2001        /* No more members to process  */
#define MAX_MEMBER_NAME      8
#define LEN_TTR              3
#define TRUE                 1
#define FALSE                0
#define TERMINATION_MEMBER "\xff\xff\xff\xff\xff\xff\xff\xff"

#pragma eject
/*--------------------------------------------------------------------+
| Partioned Data Set Member Information - extracted and reformatted   |
| from the PDS directory                                              |
+--------------------------------------------------------------------*/
typedef struct PDS_MBR
      {
       char member(|8+1|);   /* member name in PDS                   */
       int  alias;           /* TRUE if alias, FALSE otherwise       */
       char ttrpds(|3|);     /* Pointer to first block of member     */
      }PDS_MBR;


/*--------------------------------------------------------------------+
| Member entry from a partioned data set directory                    |
+--------------------------------------------------------------------*/
struct MEMENTRY
      {
       char name(|8|);      /*  Member name.                         */
       char ttrmem(|3|);    /*  TTR.                                 */
       char c;              /*  Information about user data field    */
      };

/*--------------------------------------------------------------------+

 Ref: MVS/XA Data Administration Guide, IBM Publication GC26-4013

 A Partitioned Data Set Directory Block

 +----------+--------------------+--------------------+-------------...
 |Number of |    Member Entry    |    Member Entry    |    Member En
 |Bytes Used|         A          |         B          |           C
 |(Maximum  |                    |                    |
 |  256)    |                    |                    |
 +----------+--------------------+--------------------+-------------...
 <----2-----><----------------Maximum 254----------------------------->

 A Partitioned Data Set Member Entry

 +----------------+------+--+-----------------------------------------+
 |     Member     |  TTR |C |             Optional User Data          |
 |      Name      |      |  |  TTRN  |  TTRN    |  TTRN   |           |
 +----------------+------+--+-----------------------------------------+
 <-------8--------><--3--><1><------------0 to 31 halfwords----------->

 Data in Member Entry 'C' Field Bitfield Definitions
 +-----------+-------------+----------------------+
 |   1 if    |  Number of  |    Number of User    |
 |Name is an |  User Data  |    Data Halfwords    |
 |  Alias    |    TTRNs    |                      |
 +-----------+-------------+----------------------+
     0           1-2               3-7
+--------------------------------------------------------------------*/

#pragma eject
 int pdsread(
             PDS_MBR * pds,      /* ptr to member information       */
             FILE    * fp        /* PDS directory FILE pointer      */
            )
 {
  /*-----------------------------------------------------------------+
  | The following are static because their value must be retained    |
  | across calls to this function.                                   |
  +-----------------------------------------------------------------*/
  static struct MEMENTRY *member;/* Partial PDS member entry        */
  static char dirbuf[256];       /* Directory block buffer          */
  static int ud;                 /* Number of halfwords in user     */
                                 /*  data field of member entry     */
  static int blk_last_entry;     /* "Not last entry" flag           */
  static int   ld;               /* Length of directory block       */
  static short nb = 0;           /* Number of bytes used in         */
                                 /*  directory block.               */
                                 /*  NOTE: Must be initialized to   */
                                 /*        zero so that the first   */
                                 /*        time PDSREAD is called   */
                                 /*        a block will be read!    */
  static int   od = 0;           /* Current offset into directory   */
                                 /*  block                          */
  static int   exit_rc =         /* Exit return code                */
                 EXIT_SUCCESS;   /*   NOTE: Must be initialized to  */
                                 /*         EXIT_SUCCESS!           */
  static int   blocks_read = 0;  /* Block read total                */

#pragma eject

  /*-----------------------------------------------------------------+
  | Read another directory block if necessary.                       |
  |                                                                  |
  |  Note:                                                           |
  |    MVS:  DCB parameters  - RECFM=FB,BLKSIZE=256                  |
  |    CMS:  FILEDEF options - RECFM U BLKSIZE 256                   |
  +-----------------------------------------------------------------*/
  if (   nb <= 0  )
    {
     ld = afread(dirbuf,256,1,fp);
     if (ld == 1)  /* Was 1 block of 256 bytes read?                */
       {
        nb = *((short *) dirbuf) - 2;
        od = 2;
        blocks_read += 1;           /* bump block read count        */
       }
      else
       {
        /*-----------------------------------------------------------+
        | We should have read exactly one block, we didn't, this     |
        | should not happen and is serious.                          |
        +-----------------------------------------------------------*/
        fprintf(stderr,"\nERROR - Block Read Error, read: %d\n\n",ld);
        if ( (ferror(fp)) != 0)
          {
            fprintf(stderr,
               "\nERROR - ferror() also reports an error\n");
          };
        exit_rc = EXIT_FAILURE;
       };
    };

  /*-----------------------------------------------------------------+
  | The last member of the last directory block will be 8 hex        |
  | digits of 'FF'.  See if the current member is the last member,   |
  | if it is indicate last member and display blocks processed.      |
  +-----------------------------------------------------------------*/
   blk_last_entry = memcmp((dirbuf+od),TERMINATION_MEMBER,8);
   if (blk_last_entry == 0 ) /* Have we reached the end of the pds? */
     {
      exit_rc = END_PDS_MEMBERS;    /* Indicate last member...      */
      printf("Directory Blocks Processed: %5d\n", blocks_read);
     }
    else
     {
      exit_rc = MEMBER_READY;
     };

#pragma eject

  /*-----------------------------------------------------------------+
  | If exit_rc is MEMBER_READY, there is a PDS directory member to   |
  | process.  At this time we will also prepare for the next call.   |
  | Do nothing if not MEMBER_READY.                                  |
  +-----------------------------------------------------------------*/
  if (exit_rc == MEMBER_READY)
    {
     /* Process current entry                                       */
     member = (struct MEMENTRY *) (dirbuf + od);
     memset(pds,'\0',sizeof(PDS_MBR));
     strncpy(pds->member, member->name, MAX_MEMBER_NAME);
     memcpy( pds->ttrpds, member->ttrmem,  LEN_TTR);

     /* Mark alias members                                          */
     if ( (member->c & 0x80) == FALSE )
       { /* Mark as real member.                                    */
        pds->alias = FALSE;
       }
      else
       { /* Mark as alais member.                                   */
        pds->alias = TRUE;
       };

     /* Setup for next call, adjust to next directory member entry  */
     ud = 2 * (member->c & 0x1f);        /* Number of half words in */
                                         /* user data field         */
     od += sizeof(struct MEMENTRY) + ud; /* Adjust offset into dir  */
     nb -= sizeof(struct MEMENTRY) + ud; /* Adjust number of bytes  */
                                         /* used                    */

    };

  return(exit_rc);     /* return with the last return code set     */
 }


Copyright (c) 2000 SAS Institute Inc. All Rights Reserved.
Terms of Use & Legal Information | Privacy Statement