MVS::VBFile - Perl extension to read and write variable-length MVS files


  use MVS::VBFile qw(:all);  # only vbget is exported by default
  $next_record = vbget(*FILEHANDLE);
  @whole_enchilada = vbget(*FILEHANDLE);

  vbopen(*FILEHANDLE, ">output_file", $blksize);
  vbput(*FILEHANDLE, $record);
  $b = vb_blocks_written(*FILEHANDLE);


This module provides functions to get records from mainframe MVS files in variable blocked (VB) format and to write records in a similar format.


vbget is exported by default; if you want any other functions, you must ask for them by name. qw(:all) exports all functions.


The input function, vbget(), works like the angle operator: when called in scalar context, it returns the next record; when in array context, it returns the entire file in a single array. The file must be in "binary" format (no translation of bytes) and include record descriptor words. The file may include block descriptor words but need not.

The rationale behind this is as follows. Most files from MVS systems are either fixed-length (record format FB) or variable-length (recfm VB). Perl can read fixed-length mainframe files just as it reads other fixed-length files -- open, read a certain number of bytes, close -- but variable-length files require some special handling. Since Perl provides open and close, the only function needed is one to get the next record.

Read the file as follows:

  open FILEHANDLE, "";
  while (vbget(*FILEHANDLE)) {  # Be sure to use '*'!!
     # process and reality...
  # OR do this:
  @much_in_little = vbget(*FILEHANDLE);
  # and then process the array (only on small files, of course).

Three output functions are provided: vbopen(), vbput(), and vbclose(). These functions allow you to write out records (to tape, most likely) that can later be read by an MVS system. Like vbget(), these functions do not translate any of the data given to them; any translation to EBCDIC (or anything else) must be done before the record is written.

vbopen() is similar to Perl's open, but you must pass a typeglob as the first argument (in other words, put a * on the front of it). The third argument is the blksize of the file. The minimum blksize is 9 bytes; the maximum, 256KB (262_144 bytes); the default, 32760. If you wish to use a blksize larger than 32760, make sure that your MVS system will support it. Your output must be blocked; in other words, you cannot write out files with RDW's but no BDW's.

You may have more than one filehandle open at a time.


Puts a single logical record to the file.


Closes the file. Be sure to use this function, since it will write a final block that contains any remaining logical records.

vb_blocks_written *FILEHANDLE

Can be called at any time to find the number of blocks written to the file. This would be most useful after closing the file; the count could, for instance, be used to build an MVS-style tape header.

Here's a full example of writing output:

  vbopen(*VBO, ">$outfile", 32760);
  foreach $record (@my_array) {
     vbput(*VBO, $record);
  $b = vb_blocks_written(*VBO);


The variable MVS::VBFile::bdws applies only to input. It tells the module whether the file to be read contains block descriptor words. The default is 0 (false); set it to 1 or any other true value if the file contains BDW's.

The variable MVS::VBFile::keep_rdw applies only to input. It tells vbget whether to keep the RDW on each record when getting it. The default is 0 (false); set it to 1 or any other true value if you want to keep the RDW's on the records.


For input, both VB (blocked) and V (unblocked) formats are supported. vbget() will not work properly on format VBS (spanned). Since VB is by far the most commonly used format, this should not be a major snag.

Output must be blocked (VB); in other words, you cannot write out files with RDW's but no BDW's.


Record descriptor words are 4 bytes that appear at the beginning of each record in a VB file. The first two bytes contain the record length in binary (16 bits, signed, big-endian); the last two are used only by spanned records and are ignored by this module. Block descriptor words, likewise, are 4 bytes that appear at the beginning of each block, having the same format.

My experience with FTP from MVS is limited, but it seems that if you transfer a file from an MVS host via FTP including the RDW's, the RDW's will be transferred but the BDW's will not. Most applications do not require BDW's, but if you want them, they can be transferred by converting the VB file to undefined records (recfm=U) under MVS and then transferring the converted file.


W. Geoffrey Rommel,, March 1999.

Thanks to Bob Shair for suggesting vbput and providing preliminary code.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 269:

You forgot a '=back' before '=head1'