Document revision date: 15 July 2002 | |
Previous | Contents | Index |
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; } |
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:
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() |
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:
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 |
---|
/* * 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; } |
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.
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 |
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:
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 |
privacy and legal statement | ||
4523PRO_003.HTML |