mainframezosjcl

Is a RECFM=VB dataset required to have a BDW?


I would like to know if a dataset with RECFM=VB is still considered valid if it doesn't contain any BDW? In other words, can RECFM=V also be considered a RECFM=VB?

If the answer depends on the program that processes the dataset, I'm interested in the behavior of the DFSORT (PGM=ICEMAN) program.

Here's some code that I've been trying to test with, but due to my little knowledge about DFSORT, I couldn't make it work to answer my question:

//TESTSORT  JOB ,MSGLEVEL=(2,0)
//STEP01    EXEC PGM=ICEMAN
//SYSOUT    DD SYSOUT=*
//SORTIN    DD DSN=TEST.DATA.VB100(SORTIN),
//             DISP=SHR,RECFM=VB,LRECL=100
//SORTOUT   DD DSN=TEST.DATA.FB80(SORTOUT),
//             DISP=OLD,RECFM=FB,LRECL=80
//SYSIN     DD *
  SORT FIELDS=COPY
  OUTFIL FNAMES=SORTOUT,OUTREC=(5,80),VTOF
  END
/*

Solution

  • No it would not. When you ask for VB records the underlying OS service manages the blocking and the Block Descriptior Word (BDW). Application programs do not manipulate the BDW.

    Consider the following simple assembler program that writes out two records names REC1 and REC2.

    WRITEVB  CSECT                                                          
             STM   14,12,12(13)                                             
             LR    12,15                                                    
             USING WRITEVB,12                                               
             LA    1,SAVEAREA                                               
             ST    1,8(13)             FORWARD POINTER                      
             ST    13,4(1)             BACKWARD POINTER                     
             LR    13,1                                                     
    *                                                                       
             OPEN  (VBOUT,OUTPUT)                                           
             PUT   VBOUT,REC1                                               
             PUT   VBOUT,REC2                                               
             CLOSE VBOUT                                                    
    *                                                                       
             SVC   3                                                        
    *                                                                       
    VBOUT    DCB   DDNAME=VBOUT,                                           *
                   MACRF=(PM),                                             *
                   RECFM=VB,                                               *
                   LRECL=255,                                              *
                   BLKSIZE=0,                                              *
                   DSORG=PS                                                 
    REC1     DS   0H                                                        
             DC    H'7'      Data length + 4 byte RDW                                               
             DC    H'0'                                                     
             DC    CL3'123'                                                 
    REC2     DS   0H                                                        
             DC    H'14'     Data length + 4 byte RDW                                               
             DC    H'0'                                                     
             DC    C'1234567890'                                          
    SAVEAREA DS    18F                                                      
             END   WRITEVB
    
                                                  
        
    

    When you dump the first block of the output file it looks like this

    Offset    +0       +4       +8       +C        +10      +14      +18      +1C        Data Record                      
    00000000  00190000 00070000 F1F2F300 0E0000F1  F2F3F4F5 F6F7F8F9 F0****** ********  *........123....1234567890********
    

    Notice the 4 bytes st the beginning are the BDW that describes the block. It's length if x'19 (27d) The following records are REC1 and REC2. They're lengths are 7 and e respectively. This includes the data and the RDW. Total they are x'15'. Add in the 4 for the BDW and the total block is z'19'.

    Note the manipulation of the BDW is done by the OS and is not generally available to the program reading or writing the data.

    You might ask about the second half of the RDW. That is used for RECFM VBS and indicates which portion of the spanned record this portion is. I didn't include spanned records in this discussion.

    UPDATE:

    I made the comment that the OS manages the BDW which is correct. However, you can access it; although I can't think of a use case for an application.

    To access the BDW you can open the file using RECFM=U (which is undefined). This means that you are essentially reading the blocks of data and you are responsible for interpreting the contents. Here is a C program that can read a VB file opened as U and see the blocks and access the BDW. You can do the same in HLASM but C is faster to code formatted output.

    #include <stdio.h>
    
    int main(int argc, char **argv) {
    char *fileName = "//'HOGSTRO.VBOUT'";
    
    int i = 0;
    int bytes = 0;
    char buffer[32767];
       struct {
          unsigned short blen;
          unsigned short bflags;
          unsigned short rlen;
          unsigned short rflags;
          } *bdw;
    
      FILE *inFile = fopen(fileName, "rb,abend=abend,recfm=u");
    
      if (inFile) {
          printf("Filename = %s\n", fileName);
          bytes = fread(buffer, 1, sizeof(buffer), inFile);
    
          bdw = (void *) buffer;
    
          printf("         Chars Read = %d\n", bytes);
          printf("       Block Length = %d(x'%0x')\n", bdw->blen, bdw->blen);
          printf("First Record Length = %d(x'%0x')\n", bdw->rlen, bdw->rlen);
          fclose(inFile);
      } else {
        perror();
        printf("File open failed");
      }
      printf("\n");
    }
    

    Running the above on the output file from the assembler sample would give you this output:

    Filename = //'HOGSTRO.VBOUT'
             Chars Read = 25
           Block Length = 25(x'19')
    First Record Length = 7(x'7')
    

    You can see the extracted data matches the block read previously in this answer.