|
OpenVMS Record Management Services Reference
Manual
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 = ∑
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 (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 |
/*--------------------------------------------------------------
*
* NAML_EXAMPLE.C
*
* 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],
Naml_Long_Esa[NAML$C_MAXRSS],
Naml_Shrt_Rsa[NAM$C_MAXRSS],
Naml_Long_Rsa[NAML$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: ");
gets(primarySpec);
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_esa);
naml.naml$l_long_expand[naml.naml$l_long_expand_size] = '\0';
printf (" (Long) Expanded Specification: '%s'\n",
naml.naml$l_long_expand);
/*
* 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;
else
return vms_status;
}
printf (" (Short) Resultant Specification: '%-*.*s'\n",
naml.naml$b_rsl,
naml.naml$b_rsl,
naml.naml$l_rsa);
printf (" (Long) Resultant Specification: '%-*.*s'\n",
naml.naml$l_long_result_size,
naml.naml$l_long_result_size,
naml.naml$l_long_result);
} // 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:
Example 3-5 Using the RAB64 Structure |
/*
* RAB64_EXAMPLE.C
*
* 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: ");
gets(file_name);
/*
* 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 (Bytes) |
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_BKS
|
1
|
FILE BUCKET_SIZE
|
Bucket size
|
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$L_CTX
|
4
|
FILE CONTEXT
|
Context
|
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_GBC
|
2
|
FILE GLOBAL_BUFFER_COUNT
|
Global buffer count
|
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_ORG
|
1
|
FILE ORGANIZATION
|
File organization
|
FAB$B_RAT
|
1
|
RECORD
3
|
Record attributes
|
FAB$B_RFM
|
1
|
RECORD FORMAT
|
Record format
|
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.
4.2 FAB$B_ACMODES Field
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.
|