Updated: 11 December 1998 |
Guide to OpenVMS File Applications
Previous | Contents | Index |
RMS supports the use of compound document text through the implementation of tagged files. The term compound documents refers to files that contain a number of integrated components including text, graphics, and scanned images.
Tagged files are made distinguishable by the RMS file attribute stored semantics. The value of the stored semantics attribute is called the file tag, and it specifies how file data is to be interpreted.
RMS support for compound document text requires that compound document files be tagged with the appropriate stored semantics values. These are binary values that can be up to 64 bytes long and can be expressed using hexadecimal notation. The hexadecimal value of the DDIF tag, for example, is 2B0C8773010301. The operating system lets you assign names to tag values so that DCL commands such as DIRECTORY/FULL and utilities such as FDL and ANALYZE/RMS_FILE display a more easily remembered mnemonic for the DDIF tag instead of the hexadecimal value.
Assigning a name to the tag also aids in using the /SEMANTICS qualifier with the DCL SET FILE command when you want to tag a file from the DCL interface. For example, you can use a command like the following:
$ SET FILE/SEMANTICS=DDIF MY.FILE |
To assign a tag a name, you must have privileges to make appropriate entries in two system tables, RMS$SEMANTIC_TAGS and RMS$SEMANTIC_OBJECTS.
For example, the following DCL commands have been included in the system startup command file to assign the mnemonic DDIF to the hexadecimal value for a DDIF tag:
$ DEFINE/TABLE=RMS$SEMANTIC_TAGS DDIF 2B0C8773010301 $ DEFINE/TABLE=RMS$SEMANTIC_OBJECTS 2B0C8773010301 DDIF |
You can tag files through the DCL interface, the FDL interface, or from your program by way of the RMS interface. This section describes the implementation of tagged files through the RMS interface including:
You can tag a file from the RMS interface by using the Create service in conjunction with an item XAB ($XABITM). See OpenVMS Record Management Services Reference Manual for more information about using the $XABITM macro.
Example 4-6 illustrates a BLISS--32 program that tags a DDIF file through the RMS interface. The tag value shown is a 7-byte hexadecimal number representing the code for the DDIF tag. The RMS program interface accepts only hexadecimal tag values.
To write to a tagged file, the application program must use a $XABITM macro to specify access semantics that match the file's stored semantics as established by a $XABITM macro. As shown in the example, the Create service tags the file and the Connect service specifies the appropriate access semantics.
Example 4-6 Tagging a File |
---|
MODULE TYPE$MAIN ( IDENT = 'X-1', MAIN = MAIN, ADDRESSING_MODE (EXTERNAL=GENERAL) ) = BEGIN ! FORWARD ROUTINE MAIN : NOVALUE; ! Main routine ! ! INCLUDE FILES: ! LIBRARY 'SYS$LIBRARY:LIB'; OWN NAM : $NAM(), RETLEN, DDIF_TAG : BLOCK[ 7, BYTE] INITIAL( BYTE( %X'2B', %X'0C', %X'87', %X'73', %X'01', %X'03', %X'01')), FAB_XABITM : $xabitm ( itemlist= $ITMLST_UPLIT ( (ITMCOD=XAB$_STORED_SEMANTICS, BUFADR=DDIF_TAG, BUFSIZ=%ALLOCATION(DDIF_TAG)) ), mode = SETMODE), RAB_XABITM : $xabitm ( itemlist= $ITMLST_UPLIT ( (ITMCOD=XAB$_ACCESS_SEMANTICS, BUFADR=DDIF_TAG, BUFSIZ=%ALLOCATION(DDIF_TAG)) ), mode = SETMODE), FAB : $FAB( fnm = 'TAGGED-FILE.TEST', nam = NAM, mrs = 512, rfm = FIX, fac = <GET,PUT,UPD>, xab = FAB_XABITM), REC : BLOCK[512,BYTE], STATUS, RAB : $RAB( xab = RAB_XABITM, fab = FAB, rsz = 512, rbf = REC, usz = 512, ubf = REC), DESC : BLOCK[8,BYTE] INITIAL(0); ROUTINE MAIN : NOVALUE = BEGIN STATUS = $CREATE( FAB = FAB ); IF NOT .STATUS THEN SIGNAL (.STATUS); STATUS = $CONNECT( RAB = RAB ); IF NOT .STATUS THEN SIGNAL (.STATUS); STATUS = $CLOSE( FAB = FAB ); IF NOT .STATUS THEN SIGNAL (.STATUS); END; END ELUDOM |
This section details how RMS handles access to tagged files at the program level. When a program accesses a tagged file, RMS must determine whether and when to associate an RMS extension with the access. This is important to the programmer because an RMS extension can change the attributes of the accessed file.
RMS extensions are system images that perform specialized file or record operations within the context of RMS. Record management services can invoke an extension if specified conditions are met. Functions provided by an extension are only accessible through the record managment services and are generally transparent to the application.
An example of an RMS extension is the DDIF-to-ASCII text translator. RMS can call this extension to extract ASCII text from a DDIF file. The conditions that determine when this extension is called are described in this section.
A DDIF file is a sequentially organized file with 512-byte, fixed-length records. If the DDIF-to-ASCII RMS extension is used to extract text from a DDIF file, the accessed file appears as a sequentially organized file having variable-length records with a maximum record size of 2048 bytes and an implicit carriage return.
One consideration in determining whether an access requires the RMS extension is the type of access (FAB$B_FAC). When an application program opens a file through the RMS program interface, it must specify if it will be doing record I/O (default), block I/O (BIO), or mixed I/O (BRO) operations, where the program has the option of using either block I/O or record I/O for each access. For example, if block I/O operations are specified, RMS does not associate the RMS extension with the file access.
Another consideration is whether the program senses the tag when it opens a file. If the program does not sense the tag when it opens a DDIF file for record access, RMS associates the RMS extension with the file access during the Open service and returns the file attributes that have been modified by the extension.
The final consideration is the access semantics that the program
specifies and the file's stored semantics (tag). If the program
specifies block I/O (FAB$V_BIO) operations, RMS does not associate the
RMS extension with the file access and the Open service returns the
file's stored attributes to the accessing program regardless of whether
the program senses tags.
4.3.2.1 File Accesses That Do Not Sense Tags
This section describes what happens when a program does not use a XABITM control block to sense a tag when it opens a file.
When a program opens a DDIF file for record operations and does not sense the tag, RMS assumes that the program wants to access text in the file. In this case, RMS associates the RMS extension with the file access, which provides file attributes that correspond to record-mode access.
When a program opens a DDIF file with the FAB$V_BRO option and does not
sense the tag, any subsequent attempt to use block I/O fails. If the
program specifies block I/O (FAB$V_BIO) when it invokes the Connect
service, the operation fails because the file attributes returned at
Open permit record access only. Similarly, if the program specifies the
FAB$V_BRO option when it opens the file and then specifies mixed mode
(block/record) operations by not specifying RAB$V_BIO at connect time,
block operations such as READ and WRITE are disallowed.
4.3.2.2 File Accesses That Sense Tags
RMS does not associate the RMS extension with the file access as part of the Open service if a program opens a DDIF file and senses the stored semantics. This allows the program to specify access semantics with the Connect service. RMS returns the file attributes, including the stored semantics attribute (tag value), to the program as part of the Open service.
When the program subsequently invokes the Connect service, RMS uses the specified operations mode to determine its response. If the program specified FAB$V_BRO with the Open service and then specifies block I/O (RAB$V_BIO) when it invokes the Connect service, RMS does not associate the RMS extension with the file access.
But, if the program specifies record access or FAB$V_BRO when it opens the file and then decides to use record I/O when it invokes the Connect service, RMS compares the access semantics with the file's stored semantics to determine whether to associate the RMS extension with the file access. If the access semantics match the stored semantics, RMS does not associate the RMS extension with the file access. If the access semantics do not match the stored semantics, RMS associates the RMS extension with the file access. In this case, the program must use the Display service to obtain the modified file attributes. If RMS cannot find the appropriate RMS extension, the operation fails and the Connect service returns the EXTNOTFOU error message.
If the application program senses the file's stored semantics, RMS allows mixed-mode operations. In this case, mixed block and record operations are permitted because the application gets record mode file attributes and data from the RMS extension and block mode file attributes and data from the file.
Example 4-7 illustrates a BLISS--32 program that accesses a tagged file from an application program that does not use an RMS extension.
Example 4-7 Accessing a Tagged File |
---|
MODULE TYPE$MAIN ( IDENT = 'X-1', MAIN = MAIN, ADDRESSING_MODE (EXTERNAL=GENERAL) ) = BEGIN ! FORWARD ROUTINE MAIN : NOVALUE; ! Main routine ! ! INCLUDE FILES: ! LIBRARY 'SYS$LIBRARY:STARLET'; OWN NAM : $NAM(), ITEM_BUFF : BLOCK[ XAB$K_SEMANTICS_MAX_LEN,BYTE ], RETLEN, FAB_XABITM : $xabitm ( itemlist= $ITMLST_UPLIT ((ITMCOD=XAB$_STORED_SEMANTICS, BUFADR=ITEM_BUFF, BUFSIZ=XAB$K_SEMANTICS_MAX_LEN, RETLEN=RETLEN)), mode = SENSEMODE), RAB_ITEMLIST : BLOCK[ ITM$S_ITEM + 4, BYTE ], RAB_XABITM : $XABITM ( itemlist=RAB_ITEMLIST, mode=SETMODE ), FAB : $FAB( fnm = 'TAGGED-FILE.TEST', nam = NAM, fac = <GET,PUT,UPD>, xab = FAB_XABITM), REC : BLOCK[512,BYTE], STATUS, RAB : $RAB( xab = RAB_XABITM, fab = FAB, rsz = 512, rbf = REC, usz = 512, ubf = REC), DESC : BLOCK[8,BYTE] INITIAL(0); ROUTINE MAIN : NOVALUE = BEGIN STATUS = $OPEN( FAB = FAB ); IF NOT .STATUS THEN SIGNAL (.STATUS); RAB_ITEMLIST[ ITM$W_BUFSIZ ] = .RETLEN; RAB_ITEMLIST[ ITM$L_BUFADR ] = ITEM_BUFF; RAB_ITEMLIST[ ITM$W_ITMCOD ] = XAB$_ACCESS_SEMANTICS; STATUS = $CONNECT( RAB = RAB ); IF NOT .STATUS THEN SIGNAL (.STATUS); STATUS = $CLOSE( FAB = FAB ); IF NOT .STATUS THEN SIGNAL (.STATUS); END; END ELUDOM |
In order to preserve the integrity of a tagged file that is being copied or transmitted, the tag must be preserved in the destination (output) file. The most efficient way to use the RMS interface for propagating tags involves a 2-step procedure:
. . . ITEMLIST[ ITM$W_BUFSIZ ] = XAB$K_SEMANTICS_MAX_LEN; ITEMLIST[ ITM$L_BUFADR ] = ITEM_BUFF; ITEMLIST[ ITM$L_RETLEN ] = RETLEN; ITEMLIST[ ITM$W_ITMCOD ] = XAB$_STORED_SEMANTICS; . . . XABITM[ XAB$B_MODE ] = XAB$K_SENSEMODE; STATUS = $OPEN( FAB = FAB ); . . . |
. . . IF .RETLEN GTR 0 THEN BEGIN ITEMLIST[ ITM$W_ITMCOD ] = XAB$_STORED_SEMANTICS; ITEMLIST[ ITM$L_SIZE ] = .RETLEN; XABITM[ XAB$B_MODE ] = XAB$K_SETMODE; END; STATUS = $CREATE( FAB = FAB ); . . . END; END ELUDOM |
You can protect a disk file in two ways:
You can protect the disk with UIC-based protect codes that are described in the OpenVMS Guide to System Security.
The owner UIC is normally the UIC of the person who created the file. The protection code indicates who is allowed access and what type of access they are permitted.
When you try to open a file, your UIC is compared to the owner UIC of the file. Depending on the relationship of the UICs, you might be classified under one or more of the following categories:
Depending on your classification, you may be allowed or denied the following types of access:
Read | Can examine, print, or copy a disk or tape file |
Write | Can modify or write to a disk or tape file |
Execute | Can execute a disk file that contains executable program images |
Delete | Can delete a disk file |
You can specify the UIC-based protection value you need when the file is created if you use either an FDL specification or RMS directly.
After you create a file, you can change its UIC-based protection with the DCL command SET PROTECTION. For more information about the SET PROTECTION command, see the OpenVMS DCL Dictionary.
The previous list omits CONTROL access because it is never specified in the standard UIC-based protection code. However, CONTROL access can be specified in an ACL and is automatically granted to certain user categories when UIC-based protection is evaluated.
CONTROL access grants the accessor all the privileges of the object's
actual owner. For more information, see the documentation related to
OpenVMS security.
4.4.2 ACL-Based Protection
You can also protect disk files with access control lists (ACLs). (ACLs cannot be used with magnetic tape files.)
An ACL is a list of people or groups who are allowed to access a particular file. ACLs offer more scope than UICs in determining what action you want taken when someone tries to access your file. You can provide an ACL on any file to permit as much or as little access as you want.
You can specify the ACL for a file when you create it if you use RMS directly. You cannot specify an ACL in an FDL specification, and ACLs are not supported over DECnet.
After a file is created, you can define the access control list for it with the ACL Editor. You can invoke this editor with either of the following DCL commands:
For more information about how to invoke, modify, and display ACLs, see
the OpenVMS System Management Utilities Reference Manual. For additional information about operating system
security features, see your system or security manager, or consult the
documentation related to OpenVMS security.
4.5 Populating a File
The next two sections explain how to use the Convert utility to
populate a file.
4.5.1 Using the Convert Utility
The Convert utility allows you to create and populate a file.
To create a file, you need an input data file and an FDL file that describes the output file you want to create. You issue a DCL command in the following form:
CONVERT/CREATE/FDL=fdl-file input-file output-file |
As with the CREATE/FDL command, the CONVERT/CREATE/FDL command creates a file named by the output-file parameter and having characteristics specified in your FDL file. Unlike the CREATE/FDL command, CONVERT populates the output file with the records from the input file. For example, to create the file CUST.IDX from the specifications in the FDL file STDINDEX.FDL and copy the records from the input file CUST.SEQ into CUST.IDX, you enter the following command:
$ CONVERT/CREATE/FDL=STDINDEX.FDL CUST.SEQ CUST.IDX |
RMS assigns the characteristics specified in the file STDINDEX.FDL to
the records in CUST.IDX. Note that the Convert utility processes
relative files by sequentially reading records from the input file,
then writing them to the output file. As a result, the relative record
numbers (RRN) change when the input file contains deleted or unused
records.
4.5.2 Using the Convert Routines
You can invoke the functions of the Convert utility from your application program by calling the following series of convert routines:
CONV$PASS_FILES | Names the files to be converted. You can also specify an FDL file. |
CONV$PASS_OPTIONS | Indicates the CONVERT qualifiers that you want to use. You may specify any legal CONVERT option, or you may accept the defaults. |
CONV$CONVERT | Copies records from one or more source data files to an output data file. The output file is not required to have the same file organization and format as the source files. |
The routines must be called in this order.
Example 4-8 shows how to call the CONVERT routines from a Fortran program.
Example 4-8 Using the CONVERT Routines in a Fortran Program |
---|
* This program calls the routines that perform the * functions of the Convert utility. It creates an * indexed output file named CUSTDATA.DAT from the * specifications in an FDL file named INDEXED.FDL. * The program then loads CUSTDATA.DAT with records * from the sequential file SEQ.DAT. No exception * file is created. This program also returns the * "BRIEF" CONVERT statistics. * Program declarations IMPLICIT INTEGER*4 (A - Z) * Set up parameter list: number of options, CREATE, * NOSHARE, FAST_LOAD, MERGE, APPEND, SORT, WORK_FILES, * KEY=0, NOPAD, PAD CHARACTER, NOTRUNCATE, * NOEXIT, NOFIXED_CONTROL, FILL_BUCKETS, NOREAD_CHECK, * NOWRITE_CHECK, FDL, and NOEXCEPTION. * INTEGER*4 OPTIONS(19), 1 /18,1,0,1,0,0,1,2,0,0,0,0,0,0,0,0,0,1,0/ * Set up statistics list as an array with the * number of statistics that requested. There are * four: number of files, number of records, exception * records, and good records, in that order. INTEGER*4 STATSBLK(5) /4,0,0,0,0/ * Declare the file names CHARACTER IN_FILE*7 /'SEQ.DAT'/, 1 OUT_FILE*12 /'CUSTDATA.DAT'/, 1 FDL_FILE*11 /'INDEXED.FDL'/ * Call the routines in their required order. STATUS = CONV$PASS_FILES (IN_FILE, OUT_FILE, FDL_FILE) IF (.NOT. STATUS) CALL LIB$STOP (%VAL(STATUS)) STATUS = CONV$PASS_OPTIONS (OPTIONS) IF (.NOT. STATUS) CALL LIB$STOP (%VAL(STATUS)) STATUS = CONV$CONVERT (STATSBLK) IF (.NOT. STATUS) CALL LIB$STOP (%VAL(STATUS)) * Display the statistics information. WRITE (6,1000) (STATSBLK(I),I=2,5) 1000 FORMAT (1X,'Number of files processed: ',I5/, 1 1X,'Number of records: ',I5/, 1 1X,'Number of exception records: ',I5/, 1 1X,'Number of valid records: ',I5) END |
Example 4-9 shows how to call the CONVERT routines from a COBOL program.
Example 4-9 Using the CONVERT Routines in a COBOL Program |
---|
* CONV.COB * * This program calls the routines that perform the * functions of the Convert utility. It creates an * indexed output file named CUSTDATA.DAT from the * specifications in an FDL file named INDEXED.FDL. * The program then loads CUSTDATA.DAT with records * from the sequential file SEQ.DAT. No exception * file is created. This program also returns the * "BRIEF" CONVERT statistics. * * DATA NAMES: * * IN-REC defines the input record * OUT-REC defines the output record * STATVALUE receives the status value from the * routine call * NORMAL receives the value from SS$_NORMAL * OPTIONS defines the CONVERT parameter list * STATSBLK receives the CONVERT statistics. The * first data field (NUM-STATS) contains * the total number of statistics requested. * There are four: * (1) number of files processed (NUM-STATS) * (2) number of records processed (NUM-FILES) * (3) number of exception records (NUM-RECS) * (4) number of valid records (NUM-VALRECS) * IDENTIFICATION DIVISION. PROGRAM-ID. PARTS. ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. VAX OBJECT-COMPUTER. VAX INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT IN-FILE ASSIGN TO SEQ. SELECT OUT-FILE ASSIGN TO CUSTDATA. DATA DIVISION. FILE SECTION. FD IN-FILE DATA RECORD IS IN-REC. 01 IN-REC. 02 IN-NUM PIC X(4). 02 IN-NAME PIC X(20). 02 IN-COLOR PIC X(4). 02 IN-WEIGHT PIC X(4). 02 SUPL-NAME PIC X(20). 02 FILLER PIC X(28). FD OUT-FILE DATA RECORD IS OUT-REC. 01 OUT-REC. 02 OUT-NUM PIC X(4). 02 OUT-NAME PIC X(20). 02 OUT-COLR PIC X(4). 02 OUT-WGHT PIC X(4). 02 SUPL-NAME PIC X(20). WORKING-STORAGE SECTION. 01 MORE-DATA-FLAGS PIC X(3) VALUE 'YES'. 88 THERE-IS-DATA VALUE 'YES'. 88 THERE-IS-NO-DATA VALUE 'NO '. 01 STATVALUE PIC S9(9) COMP. 01 OPTIONS USAGE IS COMP. 02 NUM-OPTS PIC S9(9) VALUE 18. 02 CREATE PIC S9(9) VALUE 1. 02 NOSHARE PIC S9(9) VALUE 0. 02 FASTLOAD PIC S9(9) VALUE 1. 02 NOMERGE PIC S9(9) VALUE 0. 02 NOPPEND PIC S9(9) VALUE 0. 02 XSORT PIC S9(9) VALUE 1. 02 XWORKFILES PIC S9(9) VALUE 2. 02 KEYS PIC S9(9) VALUE 0. 02 NOPAD PIC S9(9) VALUE 0. 02 PADCHAR PIC S9(9) VALUE 0. 02 NOTRUNCATE PIC S9(9) VALUE 0. 02 NOEXIT PIC S9(9) VALUE 0. 02 NOFIXEDCTRL PIC S9(9) VALUE 0. 02 NOFILLBUCKETS PIC S9(9) VALUE 0. 02 NOREADCHECK PIC S9(9) VALUE 0. 02 NOWRITECHECK PIC S9(9) VALUE 0. 02 FDL PIC S9(9) VALUE 1. 02 NOEXCEPTION PIC S9(9) VALUE 0. 01 STATSBLK USAGE IS COMP. 02 NUM-STATS PIC S9(9) VALUE 4. 02 NUM-FILES PIC S9(9) VALUE 0. 02 NUM-RECS PIC S9(9) VALUE 0. 02 NUM-EXCS PIC S9(9) VALUE 0. 02 NUM-VALRECS PIC S9(9) VALUE 0. PROCEDURE DIVISION. MAIN. PERFORM CONVERT-FILE THRU DISPLAY-STATS. OPEN INPUT IN-FILE. READ IN-FILE AT END MOVE 'NO ' TO MORE-DATA-FLAGS. CLOSE IN-FILE. STOP RUN. CONVERT-FILE. CALL 'CONV$PASS_FILES' USING BY DESCRIPTOR 'SEQ.DAT' BY DESCRIPTOR 'CUSTDATA.DAT' BY DESCRIPTOR 'INDEXED.FDL' GIVING STATVALUE. IF STATVALUE IS FAILURE CALL 'LIB$STOP' USING BY VALUE STATVALUE. CALL 'CONV$PASS_OPTIONS' USING BY CONTENT OPTIONS GIVING STATVALUE. IF STATVALUE IS FAILURE CALL 'LIB$STOP' USING BY VALUE STATVALUE. CALL 'CONV$CONVERT' USING BY REFERENCE STATSBLK GIVING STATVALUE. IF STATVALUE IS FAILURE CALL 'LIB$STOP' USING BY VALUE STATVALUE. DISPLAY-STATS. DISPLAY 'Number of files processed: ',NUM-FILES CONVERSION. DISPLAY 'Number of records: ',NUM-RECS CONVERSION. DISPLAY 'Number of exception records: ',NUM-EXCS CONVERSION. DISPLAY 'Number of valid records: ',NUM-VALRECS CONVERSION. |
For more information about calling the Convert routines, see the OpenVMS Utility Routines Manual.
Previous | Next | Contents | Index |
Copyright © Compaq Computer Corporation 1998. All rights reserved. Legal |
4506PRO_012.HTML
|