13th November 2022

Fixed Block Files

On MVS there are mainly VB and FB files. This is abbreviated RECFM=VB or RECFM=FB (record format). VB files are variable block, each record in the file contains a 4-byte header for the length information. FB are fixed block, each record having a fixed number of bytes. The record length is abbreviated with LRECL (logical record length).

When you process FB files on Linux and want to work with them with wc, grep, cut, etc., then you have to convert them beforehand. This means every fixed length record needs a finishing '\n' byte at the end. Also, you usually you want to get rid of all the space character at the end of the line. I.e., you want to trim each line.

Below short C program does just that. Each record is terminated with a newline character. Additionaly, each line is trimmed.

/* Every 32.000 bytes insert a newline, this number can be changed with command line flag -c
   Trim space at end of line
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int c, i, k, reclen=32000;
    FILE *fp = NULL;

    while ((c = getopt(argc,argv,"c:")) != -1) {
        switch (c) {
        case 'c':
            reclen = atoi(optarg);
            break;
        default:
            printf("Illegal command line flag: %c\n",c);
            break;
        }
    }

    if (optind >= argc) fp = stdin;
    if (fp != stdin && (fp = fopen(argv[optind],"r")) == NULL) {
        printf("Cannot open %s\n",argv[optind]);
        return 1;
    }

    i = reclen;	// number of char's
    k = 0;	// number of spaces
    while ((c = fgetc(fp)) != EOF) {
        if (c == ' ') ++k;
        else {
            //printf("(k=%d)",k);
            for (; k>0; --k) putchar(' ');
            putchar(c);
        }
        if (--i <= 0) {
            i = reclen;
            k = 0;
            putchar('\n');
        }
    }

    if (fp != stdin) fclose(fp);

    return 0;
}

Example usage:

printf "ab cde fg" | corefixedblock -c4
ab c
de f
g%