HP OpenVMS Systems Documentation

Content starts here

OpenVMS Record Management Services Reference Manual

Previous Contents Index

3.3 Program to Show Index Root Levels

Example 3-3 shows the index root level(s) for a specified file. You can modify the program to display more parameters, add LIB$FIND_FILE, and so forth.

To use the program, define an external DCL command and pass the filespec to the program as a parameter.

Example 3-3 Displaying the Index Root for a File

** Show_roots.c

#include <rms>
#include <stdio>
#define MAXKEY 10
main (int argc, char *argv[])
struct FAB      fab;
struct XABSUM   sum;
struct XABKEY   xab[MAXKEY];
int             i, stat, lvl, keys;

fab = cc$rms_fab;
sum = cc$rms_xabsum;
fab.fab$b_shr = FAB$M_SHRPUT;
fab.fab$b_fac = FAB$M_GET;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = STRLEN( argv[1] );
fab.fab$l_xab = &sum;
stat = SYS$OPEN ( &fab );
if (!(stat&1)) return stat;
if (fab.fab$b_org!=FAB$C_IDX) return RMS$_ORG;
keys = sum.xab$b_nok;
fab.fab$l_xab = &xab[0];
for (i=0; i<keys; i++)
    ** Init Xab Key for each defined key
    ** Point previous to current except first.
    xab[i] = cc$rms_xabkey;
    xab[i].xab$b_ref = i;
    if (i) xab[i-1].xab$l_nxt = &xab[i];
** Ask RMS to fill in the XABs hooked off the FAB.
stat = SYS$DISPLAY ( &fab );
if (!(stat&1)) return stat;
printf ("File %s, Root levels: %d", argv[1], xab[0].xab$b_lvl);
for (i=1; i<keys; i++) printf (", %d", xab[i].xab$b_lvl);
printf (".\n");
return stat;

3.4 Program to Illustrate Using NAML Blocks for Extended File Specifications (Alpha Only)

Example 3-4 contains a sample program which uses the new NAML blocks available beginning with OpenVMS V7.2. The NAML block is similar to the NAM block, except that it contains long fields to allow for the extended file names and deep directory structures supported on ODS-5 disks.

NAML blocks are only supported on Alpha platforms, and are only supported for V7.2 and later. If you attempt to compile this sample program on the VAX platform, you will get compiler errors indicating that the NAML symbols, structures and offsets are not defined, similar to the following:

   %CC-E-UNDECLARED, In the declaration of "primarySpec", "NAML$C_MAXRSS"
   is not declared.

Although the program compiles correctly on an OpenVMS Alpha system prior to V7.2, when you run the program you get the error:

   %RMS-F-NAM, invalid NAM block or NAM block not accessible

The sample program does the following:

  • Creates string buffers for resultant and expanded filenames.
  • Prompts the user for a primary file specification.
  • Uses the long input buffer field of the NAML for the primary specification.
  • Uses the short input buffer field of the FAB for the default specification (providing a default of "*.*;*").
  • Does a $PARSE and displays the expanded file specifications (short and long).
  • Does repeated $SEARCHes (until no-more-files or failure) and displays the resultant file specifications (short and long) each time.

The program prompts for the file specification to process, and then displays the results.

In order for the full capabilities of the NAML block to be seen, you can set up an ODS-5 file system, which allows files with long file names, filenames with the extended character set, and deep directory structures (greater than 8 levels) to be created.

Example 3-4 Using NAML Blocks for Extended File Specifications

 *   This sample program uses NAML blocks (short and long
 *   buffers) with RMS $PARSE and $SEARCH functions to
 *   demonstrate extended file specification capabilities.
 *   NAML blocks are supported only on Alpha platforms.
 *   Notes:
 *      The no-short-upcase NAML bit is set, so the short expanded
 *      specification will not be upcased.

#include <string>                       // for strlen, etc.
#include <ssdef>                        // for SS$_NORMAL
#include <stdio>                        // for printf, etc.
#include <starlet>                      // sys$parse, sys$search
                                        // function prototypes
#include <rms>                          // NAML and FAB structure definitions

int main()
    int vms_status;
    int primarySpecLength = 0;
    char primarySpec[NAML$C_MAXRSS+2];  // (Include room for LF and \0.)
    char defaultSpec[] = "*.*;*";

     *  Create the string buffers for the resultant and expanded strings

    char Naml_Shrt_Esa[NAM$C_MAXRSS],

     *  Declare the FAB and NAML structures

    struct FAB fab;
    struct namldef naml;

     *  Initialize the FAB and NAML using the default structures,
     *  then set them up for our use.

    fab = cc$rms_fab;
    naml = cc$rms_naml;

     *  To indicate that the NAML fields should be used rather
     *  than the FAB fields for the filename, we put a -1 in
     *  the FNA field, and a zero in the FNS field.

    fab.fab$l_fna = (char *)-1;
    fab.fab$b_fns = 0;

    fab.fab$l_dna = defaultSpec;
    fab.fab$b_dns = strlen(defaultSpec);

    fab.fab$l_naml = &naml;     //  tie the NAML to the FAB

    naml.naml$l_long_filename = primarySpec;
    naml.naml$l_esa = Naml_Shrt_Esa;
    naml.naml$b_ess = sizeof (Naml_Shrt_Esa);
    naml.naml$l_rsa = Naml_Shrt_Rsa;
    naml.naml$b_rss = sizeof (Naml_Shrt_Rsa);

    naml.naml$l_long_expand       = Naml_Long_Esa;
    naml.naml$l_long_expand_alloc = sizeof (Naml_Long_Esa);
    naml.naml$l_long_result       = Naml_Long_Rsa;
    naml.naml$l_long_result_alloc = sizeof (Naml_Long_Rsa);

     *  Set NAML options flags

    naml.naml$v_synchk = 0;             // Have $PARSE do directory
                                        //   existence check
    naml.naml$v_no_short_upcase = 1;    // Don't upcase short expanded spec.

     *  Prompt for the input file specification.  A blank
     *  response will use the default filespec of *.*;*

    printf("File specification to be scanned: ");

    naml.naml$l_long_filename_size = strlen(primarySpec);

     *  Parse the given file specification.  This sets up for
     *  the $SEARCH loop.  On success, print out the expanded
     *  file specifications.

    printf ("\n\nParsing: %s\n", primarySpec);
    vms_status = sys$parse (&fab);
    if (!(vms_status & 1))                      //  return any error
        return vms_status;

    naml.naml$l_esa[naml.naml$b_esl] = '\0';    //  terminate the string
    printf ("   (Short) Expanded Specification: '%s'\n",

    naml.naml$l_long_expand[naml.naml$l_long_expand_size] = '\0';
    printf ("   (Long)  Expanded Specification: '%s'\n",

     *  Go into the $SEARCH loop.  We loop until the
     *  $SEARCH fails or returns No More Files (NMF)
     *  For each successful $SEARCH, print out the
     *  resultant file names from the NAML block.

    printf ("\n\nSearching for files matching: %s\n", primarySpec);
    while (1)
        vms_status = sys$search (&fab);
        if (!(vms_status & 1))          //  handle any error
            if (vms_status == RMS$_NMF)
                return SS$_NORMAL;
                return vms_status;

        printf ("   (Short) Resultant Specification: '%-*.*s'\n",

        printf ("   (Long)  Resultant Specification: '%-*.*s'\n",

    }  //  end of while loop

}  // end of function main()

3.5 Program to Illustrate Using the RAB64 Structure

This section contains an example program, written in C, which demonstrates the use of the RAB64 structure. The RAB64 structure has the same fields as the RAB structure, but contains additional quadword fields to allow addressing of the 64-bit Alpha address space. The RAB64 structure is only supported on Alpha platforms beginning with OpenVMS V7.0. This program does the following:

  • Declares RMS structures
  • Declares 64-bit pointers and values for allocating Alpha P2 space.
  • Opens a given file
  • Allocates Alpha P2 space for a record buffer.
  • Sets up the RAB64 structure to use the returned Alpha P2 address space.
  • Connects a record stream using the RAB64
  • Reads the first record from the file for illustration purposes
  • Closes the file and deallocates the P2 memory.

Prior to OpenVMS V7.2, the cc$rms_rab64 initializer was not available. The example program sets up the RAB64 structure explicitly by zeroing the structure and setting the block-id and block length fields. As of OpenVMS V7.2, this explicit set up can be replaced with the assignment:

        x_rab = cc$rms_rab64;

Example 3-5 Using the RAB64 Structure

 *  Description:
 *      This sample program uses the 64-bit pointers in the new RAB64
 *      structure to allow addressing of the full 64-bit Alpha
 *      address space.
 *  NOTE:
 *      Prior to V7.2, the cc$rms_rab64 initializer was not available
 *      and the RAB64 structure had to be initialized manually.  See
 *      the comment in the code for details.

#define __NEW_STARLET

#include <far_pointers.h>    // basic set of 64-bit pointer types
#include <rms.h>             // both RAB and RAB64 structures
#include <lib$routines.h>    // for lib$signal
#include <starlet.h>         // for RMS function prototypes
#include <stdio.h>           // for printf, gets, etc.
#include <string.h>          // for strlen
#include <ssdef.h>           // for status codes

#include <stdlib.h>          // for memset

 *  Start of code

int main()
    int status;

     *  Define the structures for RMS

    struct FAB   fab;
    struct RAB64 x_rab;

    char file_name[NAM$C_MAXRSS];

     *  Set up variables for allocating a record buffer
     *  from 64-bit P2 address space.

    VOID_PQ p2_va;
    CHAR_PQ record_buffer;

    __int64 num_bytes = 1024;
    __int64 num_pagelets = (num_bytes / 512);

     *  Get the filename

    printf("Enter filename to read: ");

     *  Set up the FAB using the default structures, then
     *  set it up for our use.

    fab = cc$rms_fab;

    fab.fab$l_fna = file_name;
    fab.fab$b_fns = strlen(file_name);
    fab.fab$b_org = FAB$C_SEQ;
    fab.fab$b_fac = FAB$M_GET;
    fab.fab$b_shr = FAB$M_NIL;

     *  Open the file

    status = sys$open(&fab);
    if (!(status & 1))
        return status;
    printf("File %s was opened.\n", file_name);

     *  Dynamically allocate record buffer in 64-bit P2 space

    status = LIB$GET_VM_PAGE_64 ( &num_pagelets, &p2_va );
    if (!(status & 1))
        return status;
    printf("Allocated %Ld pagelets of P2 space starting at %LX\n",num_pagelets,p2_va);

    record_buffer = p2_va;

     *  Initialize rab64
     *  NOTE:  Prior to OpenVMS V7.2, the cc$rms_rab64 initializer
     *  was not available.  As of V7.2, the following memset, block-id
     *  and length assignments may be replaced with the assignment:
     *    x_rab = cc$rms_rab64;

    memset(&x_rab,0,RAB$C_BLN64);       //  requires stdlib.h
    x_rab.rab64$b_bid    = RAB$C_BID;   //  block id
    x_rab.rab64$b_bln    = RAB$C_BLN64; //  block length

    x_rab.rab64$l_fab    = &fab;        //  tie the FAB to the RAB
    x_rab.rab64$b_rac    = RAB$C_SEQ;
    x_rab.rab64$l_ubf    = (char *) -1; //  -1 says use the PQ field
    x_rab.rab64$pq_ubf   = record_buffer;
    x_rab.rab64$w_usz    = 0;           //  0 says use the Q field
    x_rab.rab64$q_usz    = num_bytes;

     *  Connect our record stream

    status = sys$connect( (struct _rabdef *) &x_rab);
    if (!(status & 1))
        return status;
    printf("Record stream was connected.\n");

     *  Retrieve first record in file for illustration purposes

    status = sys$get ( (struct _rabdef *) &x_rab);
    if (!(status & 1))
         *  Signal the error rather than just returning
         *  it so we can include the STV field from
         *  the RAB

        lib$signal ( status, x_rab.rab64$l_stv);

     *  Add null byte to terminate record in record buffer

    record_buffer[x_rab.rab64$q_rsz] = 0;
    printf ("Record = %s\n",record_buffer);

     *  Close the file, doing an implicit disconnect of
     *  the record stream.

    status = sys$close (&fab);
    if (!(status & 1))
        return status;
    printf("File was closed.\n");

     *  Deallocate record buffer in 64-bit P2 space

    status = LIB$FREE_VM_PAGE_64 ( &num_pagelets, &p2_va );
    if (!(status & 1))
        return status;
    printf("Deallocated %Ld pagelets of P2 space starting at %LX\n",num_pagelets,p2_va);

    return SS$_NORMAL;

Part 2
RMS Control Blocks

Part II describes each RMS control block, including a complete listing and description of each field.

Chapter 4
File Access Block (FAB)

The file access block (FAB) defines file characteristics, file access, and certain run-time options. It also indicates whether other control blocks are associated with the file.

4.1 Summary of Fields

Many FAB fields are directly equivalent to certain File Definition Language (FDL) attributes. For information about FDL, refer to the OpenVMS Record Management Utilities Reference Manual.

The symbolic offset, the size, the FDL equivalent, and a brief description of each FAB field are presented in Table 4-1.

Table 4-1 FAB Fields
Field Offset Size
FDL Equivalent Description
FAB$B_ACMODES 1 None File access modes
FAB$L_ALQ 4 FILE ALLOCATION Allocation quantity (blocks)
FAB$B_BID 1 1 None Block identifier
FAB$B_BLN 1 1 None Block length
FAB$W_BLS 2 FILE MT_BLOCK_SIZE Magnetic tape block size
FAB$V_CHAN_MODE 2 -- None Channel access mode protection
FAB$W_DEQ 2 FILE EXTENSION Default file extension quantity
FAB$L_DEV 3 4 None Device characteristics
FAB$L_DNA 4 FILE DEFAULT_NAME Default file specification string address
FAB$B_DNS 1 FILE DEFAULT_NAME Default file specification string size
FAB$B_FAC 1 ACCESS 3 File access
FAB$L_FNA 4 FILE NAME File specification string address
FAB$B_FNS 1 FILE NAME File specification string size
FAB$L_FOP 4 FILE 3 File-processing options
FAB$B_FSZ 1 RECORD CONTROL_FIELD_SIZE Fixed-length control area size
FAB$W_IFI 4 2 None Internal file identifier
FAB$B_JOURNAL 1 None Journal flags status
FAB$V_LNM_MODE - 2 None Logical name translation access mode
FAB$L_MRN 4 FILE MAX_RECORD_NUMBER Maximum record number
FAB$W_MRS 2 RECORD SIZE Maximum record size
FAB$L_NAM 5 4 None Name (NAM) or long name (NAML) block address
FAB$B_RAT 1 RECORD 3 Record attributes
FAB$B_RTV 1 FILE WINDOW_SIZE Retrieval window size
FAB$L_SDC 4 4 None Secondary device characteristics
FAB$B_SHR 1 SHARING 3 File sharing
FAB$L_STS 4 4 None Completion status code
FAB$L_STV 4 4 None Status values
FAB$L_XAB 4 None Extended attribute block address

1This field is statically initialized by the $FAB macro to identify this control block as a FAB.
2This is a 2-bit subfield.
3This field contains options; corresponding FDL equivalents are listed in the description of the field.
4This field cannot be initialized by the $FAB macro.
5FAB$L_NAML is available as an alternative definition for C programmers to allow for appropriate type checking of a NAML block.

Each FAB field is described in this section. Unless indicated otherwise, each field is supported for DECnet for OpenVMS operations on files at the remote OpenVMS systems. For information about the support of RMS options for remote file access to other systems, see the DECnet for OpenVMS Networking Manual.

To use a FAB, you must allocate process storage and specify the character string for the primary file specification and, optionally, the default file specification. The FAB$L_FNA and FAB$B_FNS fields define the primary file specification to RMS; the FAB$L_DNA and FAB$B_DNS fields define the default file specification to RMS.


This field comprises four 2-bit subfields, two of which are unsupported. The supported subfields are the FAB$V_CHAN_MODE subfield and the FAB$V_LNM_MODE subfield (see Section 4.22).

4.3 FAB$L_ALQ Field

The allocation quantity (ALQ) field defines the number of blocks to be initially allocated to a disk file when it is created (using the Create service) or to be added to the file when it is explicitly extended (using the Extend service). This field corresponds to the FDL attribute FILE ALLOCATION.

The field takes numeric values in the range of 0 through 4,294,967,295, although the maximum value depends on the number of blocks available on the disk. There are several rules concerning the use of the value 0:

  • If you specify 0 blocks when you create a sequential file, RMS allocates no initial space for the file.
  • If you specify 0 blocks for relative or indexed files, RMS allocates the minimum number of blocks needed to support the file organization. For example, if you specify 0 blocks when you create an indexed file, RMS allocates the number of blocks necessary to contain specified key and area definitions as the initial extent.
  • A value of 0 blocks is meaningless when you intend to extend a file.
When RMS opens an existing file, it puts the highest virtual block number currently allocated to the file in the FAB$L_ALQ field.

For the Extend service, this field specifies the number of blocks to be added to the file. Note that RMS uses this as the extension value when a process extends a file using the Extend service, unless the process changes the value before it invokes the Extend service.

When you use the Create and Extend services, the allocation quantity value is rounded up to the next disk cluster boundary; the number of blocks actually allocated is returned in the FAB$L_ALQ field.

Note that the function of the FAB$L_ALQ field changes if allocation control XABs are used when you create or extend a file. The description of the XABALL control block (see Chapter 9) discusses how allocation control XABs affect the FAB$L_ALQ field.

Previous Next Contents Index