1 Introduction
2 Ground Rules

Building a File System
3 File Systems
4 File Content Data Structure
5 Allocation Cluster Manager
6 Exceptions and Emancipation
7 Base Classes, Testing, and More
8 File Meta Data
9 Native File Class
10 Our File System
11 Allocation Table
12 File System Support Code
13 Initializing the File System
14 Contiguous Files
15 Rebuilding the File System
16 Native File System Support Methods
17 Lookups, Wildcards, and Unicode, Oh My
18 Finishing the File System Class

The Init Program
19 Hardware Abstraction and UOS Architecture
20 Init Command Mode
21 Using Our File System
22 Hardware and Device Lists
23 Fun with Stores: Partitions
24 Fun with Stores: RAID
25 Fun with Stores: RAM Disks
26 Init wrap-up

The Executive
27 Overview of The Executive
28 Starting the Kernel
29 The Kernel
30 Making a Store Bootable
31 The MMC
32 The HMC
33 Loading the components
34 Using the File Processor
35 Symbols and the SSC
36 The File Processor and Device Management
37 The File Processor and File System Management
38 Finishing Executive Startup

Users and Security
39 Introduction to Users and Security
40 More Fun With Stores: File Heaps
41 File Heaps, part 2
42 SysUAF
43 TUser
44 SysUAF API

Terminal I/O
45 Shells and UCL
46 UOS API, the Application Side
47 UOS API, the Executive Side
48 I/O Devices
49 Streams
50 Terminal Output Filters
51 The TTerminal Class
52 Handles
53 Putting it All Together
54 Getting Terminal Input
55 QIO
56 Cooking Terminal Input
57 Putting it all together, part 2
58 Quotas and I/O

UCL
59 UCL Basics
60 Symbol Substitution
61 Command execution
62 Command execution, part 2
63 Command Abbreviation
64 ASTs
65 Expressions, Part 1
66 Expressions, Part 2: Support code
67 Expressions, part 3: Parsing
68 SYS_GETJPIW and SYS_TRNLNM
69 Expressions, part 4: Evaluation

UCL Lexical Functions
70 PROCESS_SCAN
71 PROCESS_SCAN, Part 2
72 TProcess updates
73 Unicode revisted
74 Lexical functions: F$CONTEXT
75 Lexical functions: F$PID
76 Lexical Functions: F$CUNITS
77 Lexical Functions: F$CVSI and F$CVUI
78 UOS Date and Time Formatting
79 Lexical Functions: F$CVTIME
80 LIB_CVTIME
81 Date/Time Contexts
82 SYS_GETTIM, LIB_Get_Timestamp, SYS_ASCTIM, and LIB_SYS_ASCTIM
83 Lexical Functions: F$DELTA_TIME
84 Lexical functions: F$DEVICE
85 SYS_DEVICE_SCAN
86 Lexical functions: F$DIRECTORY
87 Lexical functions: F$EDIT and F$ELEMENT
88 Lexical functions: F$ENVIRONMENT
89 SYS_GETUAI
90 Lexical functions: F$EXTRACT and F$IDENTIFIER
91 LIB_FAO and LIB_FAOL
92 LIB_FAO and LIB_FAOL, part 2
93 Lexical functions: F$FAO
94 File Processing Structures
95 Lexical functions: F$FILE_ATTRIBUTES
96 SYS_DISPLAY
97 Lexical functions: F$GETDVI
98 Parse_GetDVI
99 GetDVI
100 GetDVI, part 2
101 GetDVI, part 3
102 Lexical functions: F$GETJPI

Glossary/Index


Download sources
Download binaries

File Processing Structures

The VMS file system is based on RMS (Record Management Services). All files are RMS files and this is built into the VMS executive. In UOS we take a different approach. Essentially, UOS files are simply streams of binary data. How that data is interpreted is not up to the executive. We will support RMS in UOS, but it will be an optional utility that can be used by applications, which simply imposes a format onto the binary file. However, we won't be discussing RMS for quite some time. But some of the structures, constants, and functions we use for other file processing will have some RMS-related aspects. Such will be ignored until we finally address RMS. In the code I will be using the //TODO comment to indicate something that we will address in the future. I try to limit the code only to that which is applicable to what we have covered, or are covering. This allows us to focus on the topic at hand.

VMS file processing uses the FAB (File Access Block) structure. This structure can point to other structures, and some of those structures can point to other structures. This creates a chain of structures of different types that contain various kinds of information on the file. This is more complicated than a single large file structure, but by asking (or specifying) only that information that is of importance, we can reduce the overhead of system calls, especially in an cluster environment. For the sake of following the VMS "specification", UOS also uses these structures. However, the UOS structures are not 100% identical to the VMS structures - either in content or layout - although they are similar. For instance, the VMS FAB structure contains 32-bit addresses, but in UOS they are 64-bit. We will cover these structures, and related constants, here.

      // FAB_L_FOP (file operation) flags:
const FAB_V_CIF = 1 ; // Create if doesn't exist
      FAB_V_MXV = 2 ; { Creates the file with the specified version number or 
                        a version number one greater than a file of the same name in that directory }
      FAB_V_SUP = 4 ; // Overwrite existing file with same name in directory
      FAB_V_TMP = 8 ; // Create temporary file (made untemporary on close)
      FAB_V_TMD = 16 ; // Create temporary file marked as deleted
      FAB_V_CBT = 32 ; // Create contiguous if possible, with large clustersize if not
      FAB_V_PPF = 64 ; // Process Permanent file
      FAB_V_NFS = 128 ; // Non-file structured
      FAB_V_UFO = 256 ; // User File Open
      FAB_V_RWO = 512 ; // Rewind on open

      FAB_V_SPL = 1024 ; // Spool on close
      FAB_V_SCF = 2048 ; // Submit Command File on close
      FAB_V_DLT = 4096 ; // Delete file on close
      FAB_V_RWC = 8102 ; // Rewind on close

      FAB_V_DFW = 16384 ; // Deferred Write
      FAB_V_CTG = 32768 ; // Contiguous
      FAB_V_SQO = 65536 ; // Sequential Processing Only
      RAB_V_ASY = $10000 ; // Asynchronous
      FAB_V_PRN = $20000 ; // This is a print file
      FAB_V_NEF = $40000 ; // Not end of file (writing record to somewhere other than EOF)
      FAB_V_POS = $80000 ; // Write to current file position
      FAB_V_TEF = $100000 ; // Truncate file
      FAB_V_OFP = $200000 ; // Output file parsing
      FAB_V_RCK = $400000 ; // Read check
      FAB_V_WCK = $800000 ; // Write check

      // FAB$B_FAC flags:
const FAB_V_GET = 1 ; // Get or find
      FAB_V_DEL = 2 ; // Delete
      FAB_V_UPD = 4 ; // Modify
      FAB_V_PUT = 8 ; // Update
      FAB_V_TRN = 16 ; // Truncate
      FAB_V_BIO = 32 ; // Block I/O

      // FAB$B_SHR flags:
const FAB_V_NIL = 0 ; // No sharing
      FAB_V_SHRGET = 1 ; // Get or find
      FAB_V_SHRDEL = 2 ; // Delete
      FAB_V_SHRUPD = 4 ; // Modify
      FAB_V_SHRPUT = 8 ; // Update
      FAB_V_UPI = 16 ; // User interlocking
      FAB_V_MSE = 32 ; // Multistreaming
      FAB_V_NQL = 64 ; // No query locking

type TFAB = packed record
                FAB_B_BLN : byte ; // FAB Block length
                FAB_B_ACMODES : byte ; // File access modes
                FAB_L_ALQ : longint ; // RMS Allocation quantity (blocks), rounded up to clustersize
                FAB_B_BID : byte ; // RMS Block identifier
                FAB_B_BKS : byte ; // RMS Bucket size
                FAB_W_BLS : word ; // Magnetic tape block size
                FAB_L_CTX : longint ; // Context
                FAB_W_DEQ : word ; // Default RMS file extension quantity in blocks
                FAB_L_DEV : cardinal ; // Device characteristics
                FAB_L_DNA : int64 ; // Default file specification string address
                FAB_B_DNS : byte ; // Default file specification string size
                FAB_B_FAC : byte ; // File access control (ignored on open)
                FAB_L_FNA : int64 ; // File specification string address
                FAB_B_FNS : byte ; // File specification string size
                FAB_L_FOP : cardinal ; // File-processing options
                FAB_B_FSZ : byte ; // Number of bytes in the RMS fixed-length control field of a VFC record
                FAB_W_GBC : word ; // Global buffer count
                FAB_W_IFI : word ; // File handle
                FAB_B_JOURNAL : byte ; // Journal flags status
                FAB_L_MRN : cardinal ; // Maximum record number for relative files
                FAB_W_MRS : word ; { Maximum record size: Defines the maximum record size for all records in 
                                     the file. Maximum record size refers to the size of all records
                                     in a file with fixed-length records, the size of the largest
                                     record with variable-length records, or the size of the
                                     variable-length portion of VFC records. A value of 0 with
                                     variable-length records means that there is no limit on
                                     the record size, except for magnetic tape files, for which
                                     a value of 0 sets an effective maximum record size equal
                                     to the block size minus 4.}
                FAB_L_NAM : int64 ; // Name block (TNAML) address
                FAB_B_ORG : byte ; // File organization (0 = binary, other = RMS format)
                FAB_B_RAT : byte ; // RMS Record attributes
                FAB_B_RFM : byte ; // RMS Record format
                FAB_B_RTV : byte ; // Retrieval window size
                FAB_L_SDC : longint ; // Secondary device characteristics
                FAB_B_SHR : byte ; // File sharing
                FAB_L_STS : longint ; // Completion status code
                FAB_L_STV : longint ; // Status values
                FAB_L_XAB : int64 ; // Extended attribute block address
            end ; // TFAB
TFAB is the basic file processing structure. Most of the fields are used for purposes of opening or closing files. And many of them are RMS-specific. I'll point out a few important components:

FAB_B_BLN
The size of the entire FAB structure, in bytes.

FAB_L_NAM
Address of a TNAML block (see below).

FAB_L_XAB
Address of XAB (extended attribute block) structure (see below).

      // NAM code types...
const NAML_C_BID = 1 ;
      NAM_C_BID = 2 ;

type TNAM = packed record
                NAM_B_BID : byte ; // Block identifier (must be NAM_C_BID)
                NAM_B_BLN : byte ; // Block length
                NAM_B_DEV : longword ; // Device string length
                NAM_L_DEV : int64 ; // Device string address
                NAM_W_DID : int64 ; // Directory identification
                NAM_B_DIR : longword ; // Directory string length
                NAM_L_DIR : int64 ; // Directory string address
                NAM_T_DVI : int64 ; // Device identification
                NAM_L_ESA : int64 ; // Expanded string area address
                NAM_B_ESL : longword ; // Expanded string length
                NAM_B_ESS : byte ; // Expanded string area size
                NAM_W_FID : int64 ; // File handle
                NAM_L_FNB : longword ; // File name status bits
                NAM_B_NAME : longword ; // File name string length
                NAM_L_NAME : int64 ; // File name string address
                NAM_B_NODE : longword ; // Node name string length
                NAM_L_NODE : int64 ; // Node name string address
                NAM_B_NOP : byte ; // Name block options
                NAM_L_RLF : int64 ; // Related file NAM block address
                NAM_L_RSA : int64 ; // Resultant string area address
                NAM_B_RSL : longword ; // Resultant string length
                NAM_B_RSS : byte ; // Resultant string area size
                NAM_B_TYPE : longword ; // File type string length
                NAM_L_TYPE : int64 ; // File type string address
                NAM_B_VER : longword ; // File version string length
                NAM_L_VER : int64 ; // File version string address
                NAM_L_WCC : int64 ; // Wildcard context
            end ; // TNAM

type TNAML = packed record
                NAML_B_BID : byte ; // Block identifier (must be NAML_C_BID)
                NAML_B_BLN : byte ; // Block length
                NAML_L_FILESYS_NAME : int64 ; // File system name buffer address.
                NAML_L_FILESYS_NAME_ALLOC : cardinal ; // File system name buffer allocated size
                NAML_L_FILESYS_NAME_SIZE : cardinal ; // File system name length
                NAML_L_INPUT_FLAGS : cardinal ; // Additional flags specified as input
                NAML_L_LONG_DEFNAME : int64 ; { Default file specification string address specified as input  
                                                (used if FAB_L_DNA contains -1) }
                NAML_L_LONG_DEFNAME_SIZE : cardinal ; // default file spec string size specified as input
                NAML_L_LONG_DEV : int64 ; // Device string address
                NAML_B_LONG_DEV_SIZE : cardinal ; // Device string length
                NAML_L_LONG_DIR : int64 ; // Directory string address
                NAML_L_LONG_DIR_SIZE : cardinal ; // Directory string length
                NAML_L_LONG_EXPAND : int64 ; // Expanded string area address
                NAML_L_LONG_EXPAND_ALLOC : cardinal ; // Expanded string area size
                NAML_L_LONG_EXPAND_SIZE : cardinal ; // Expanded string length
                NAML_L_LONG_FILENAME : int64 ; // Specification string address
                NAML_L_LONG_FILENAME_SIZE : cardinal ; // Specification string size
                NAML_L_LONG_NAME : int64 ; // File name string address
                NAML_L_LONG_NAME_SIZE : cardinal ; // File name string length
                NAML_L_LONG_NODE : int64 ; // Node name string address
                NAML_L_LONG_NODE_SIZE : cardinal ; // Node name string length
                NAML_L_LONG_RESULT : int64 ; // Resultant string area address
                NAML_L_LONG_RESULT_ALLOC : cardinal ; // Resultant string area size
                NAML_L_LONG_RESULT_SIZE : cardinal ; // Resultant string length
                NAML_L_LONG_TYPE : cardinal ; // File type string length
                NAML_L_LONG_TYPE_SIZE : int64 ; // File type string address
                NAML_L_LONG_VER : int64 ; // File version string address
                NAML_L_LONG_VER_SIZE : cardinal ; // File version string length
                NAML_L_OUTPUT_FLAGS : cardinal ; // Additional status bits passed as output
                NAML_L_USER_CONTEXT : int64 ; // User context
            end ; // TNAML
There are two types of NAM blocks. TNAML was used by VMS on 64-bit Alpha systems, but either structure could be used. UOS will only use TNAML, unless otherwise specified. To distinguish between the two name blocks, use the appropriate constant value.

NAML_B_BLN
Must be NAML_C_BID

NAML_L_LONG_DEV and NAML_L_LONG_DEV_SIZE
A pointer to the device name and the length of that name.

NAML_L_LONG_DIR and NAML_L_LONG_DIR_SIZE
A pointer to the directory path and the length of that path.

NAML_L_LONG_NAME and NAML_L_LONG_NAME_SIZE
A pointer to the filename and the length of that name.

NAML_L_LONG_NODE and NAML_L_LONG_NODE_SIZE
A pointer to the node name and the length of that name.

NAML_L_LONG_TYPE and NAML_L_LONG_TYPE_SIZE
A pointer to the filename extension and the length of that extension.

NAML_L_LONG_VER and NAML_L_LONG_VER_SIZE
A pointer to the version identifier string and the length of that string.

      // XAB code types...
const XAB_C_ALL = 1 ; // TXABALL
      XAB_C_DAT = 2 ; // TXABDAT
      XAB_C_FHC = 3 ; // TXABFHC
      XAB_C_ITM = 4 ; // TXABITM
      XAB_C_KEY = 5 ; // TXABKEY
      XAB_C_PRO = 6 ; // TXABPRO
      XAB_C_RDT = 7 ; // TXABRDT
      XAB_C_SUM = 8 ; // TXABSUM
      XAB_C_TRM = 9 ; // TXABTRM
The XAB (eXtended Attribute Block) structures can be "chained" together in a single-link list. There are several types of XAB that we will cover in this article, but they all have the following three elements:

XAB_B_COD
Must be a code indicating the type of XAB.

XAB_B_BLN
The total number of bytes in this structure.

XAB_L_NXT
Address of next XAB in the chain. 0 if this is the last XAB in the list.

type TXABALL = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_ALL)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_B_AID : byte ; // Area identification number
                   XAB_B_ALN : byte ; // Alignment boundary type
                   XAB_L_ALQ : longint ; // Allocation quantity
                   XAB_B_AOP : byte ; // Allocation options
                   XAB_B_BKZ : byte ; // Bucket size
                   XAB_W_DEQ : word ; // Default extension quantity
                   XAB_L_LOC : longint ; // Location
                   XAB_W_RFI : int64 ; // Related file identifier or FILE_NAME
                   XAB_W_VOL : word ; // Related volume number
               end ;
This block has to do with RMS structure allocation within an RMS file.

type TXABDAT = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_DAT)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_Q_ACC : int64 ; // Last access date and time
                   XAB_Q_BDT : int64 ; // Backup date and time
                   XAB_Q_CDT : int64 ; // Creation date and time
                   XAB_Q_EDT : int64 ; // Expiration date and time
                   XAB_Q_RDT : int64 ; // Revision date and time
                   XAB_W_RVN : word ; // Revision number
               end 
This block contains timestamps related to the file. These are pulled from the file header that we discussed in past articles.

XAB_Q_ACC
Last access timestamp.

XAB_Q_BDT
Backup timestamp.

XAB_Q_CDT
File creation timestamp.

XAB_Q_EDT
Expiration timestamp.

XAB_Q_RDT
Last modification timestamp.

XAB_Q_RVN
Revision number.

type TXABFHC = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_FHC)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_B_ATR : byte ; // Record attributes; equivalent to FAB_B_RAT
                   XAB_B_BKS : byte ; // Bucket size; equivalent to FAB_B_BKS
                   XAB_W_DXQ : word ; // Default file extension quantity; equivalent to FAB_W_DEQ
                   XAB_Q_EOF : int64 ; // End-of-file (logical file length)
                   XAB_W_GBC : word ; // Default global buffer count
                   XAB_L_HBK : int64 ; // Highest virtual block in the file; equivalent to FAB_L_ALQ
                   XAB_B_HSZ : byte ; // Fixed-length control header size; equivalent to FAB_B_FSZ
                   XAB_W_LRL : word ; // Longest RMS record length in file
                   XAB_W_MRS : word ; // Maximum record size; equivalent to FAB_W_MRS
                   XAB_B_RFO : byte ; // File organization/record format; combines FAB_B_RFM and FAB_B_ORG
                   XAB_L_SBN : int64 ; { Starting logical block number for the file if it is contiguous;  
                                         otherwise this field is 0 }
                   XAB_W_VERLIMIT : word ; // Version limit for the file
                   XAB_Q_SIZ : int64 ; // Size on disk
                   XAB_Q_USZ : int64 ; // Uncompressed size
                   XAB_L_CLS : cardinal ; // Clustersize
                   XAB_L_CRE : cardinal ; // Creator UIC
                   XAB_W_FLG : word ; // Flags (not including protection codes)
               end ;
This block contains file header information not provided by another block type. Many of the fields are RMS-specific.

XAB_Q_EOF
The logical end of file. In other words, the logical file size, in bytes.

XAB_W_MRS
Maximum record size for the file.

XAB_W_VERLIMIT
Version limit for the file.

XAB_Q_SIZ
Physical file size, in bytes, on the disk.

XAB_Q_USZ
Physical file size when uncompressed, for compressed files.

XAB_Q_CLS
File clustersize, in bytes.

XAB_Q_CRE
UIC of the file creator.

XAB_Q_FLG
File flags, not including the protection codes. See the XABPRO block for file protection codes.

const XAB_K_SENSEMODE = 0 ; // Sense item
      XAB_K_SETMODE = 1 ; // Set item
      
type TXABITM = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_ITM)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_L_ITEMLIST : int64 ; // Address of item list
                   XAB_M_MODE : byte ; // Mode (XAB_K_SENSEMODE or XAB_K_SETMODE)
               end ;
This block contains a pointer to an item list.

XAB_M_MODE
This field indicates whether the items are used to retrieve information from the file (XAB_K_SENSEMODE) or set file attributes from the items (XAB_K_SETMODE).

type TXABKEY = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_KEY)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_L_COLNAM : longint ; // Collating sequence name
                   XAB_L_COLSIZ : longint ; // Collating sequence table size
                   XAB_L_COLTBL : int64 ; // Collating sequence table address
                   XAB_B_DAN : byte ; // Data bucket area number
                   XAB_B_DBS : byte ; // Data bucket size
                   XAB_W_DFL : word ; // Data bucket fill size
                   XAB_B_DTP : byte ; // Data type of the key
                   XAB_L_DVB : int64 ; // First data bucket virtual block number
                   XAB_B_FLG : byte ; // Key options flag
                   XAB_B_IAN : byte ; // Index bucket area number
                   XAB_B_IBS : byte ; // Index bucket size
                   XAB_W_IFL : int64 ; // Index bucket file size
                   XAB_L_KNM : int64 ; // Key name buffer address
                   XAB_B_LAN : byte ; // Lowest level of index area number
                   XAB_B_LVL : byte ; // Level of root bucket
                   XAB_W_MRL : word ; // Minimum record length
                   XAB_B_NSG : byte ; // Number of key segments
                   XAB_B_NUL : byte ; // Null key value
                   XAB_W_POS0 : word ; // Key position
                   XAB_W_POS1 : word ; // Key position
                   XAB_W_POS2 : word ; // Key position
                   XAB_W_POS3 : word ; // Key position
                   XAB_W_POS4 : word ; // Key position
                   XAB_W_POS5 : word ; // Key position
                   XAB_W_POS6 : word ; // Key position
                   XAB_W_POS7 : word ; // Key position
                   XAB_B_PROLOG : byte ; //  Prolog level
                   XAB_B_REF : byte ; // Key of reference
                   XAB_L_RVB : int64 ; // Root bucket virtual block number
                   XAB_B_SIZ0 : byte ; // Key size
                   XAB_B_SIZ1 : byte ; // Key size
                   XAB_B_SIZ2 : byte ; // Key size
                   XAB_B_SIZ3 : byte ; // Key size
                   XAB_B_SIZ4 : byte ; // Key size
                   XAB_B_SIZ5 : byte ; // Key size
                   XAB_B_SIZ6 : byte ; // Key size
                   XAB_B_SIZ7 : byte ; // Key size
                   XAB_B_TKS : byte ; // Total key field size
               end ;
This block contains key information for RMS indexed files.

type TXABPRO = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_PRO)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_L_ACLBUF : int64 ; // Address of buffer that contains ACL
                   XAB_L_ACLCTX : longword ; // ACL positioning context
                   XAB_W_ACLLEN : int64 ; // Receives the length of an ACL during an Open or Display service
                   XAB_W_ACLSIZ : int64 ; // Length of buffer containing binary ACEs
                   XAB_L_ACLSTS : longword ; // System error status for ACL processing
                   XAB_B_MTACC : byte ; // Magnetic tape accessibility
                   XAB_W_PRO : word ; { File protection; contains four separate fields denoting protection 
                                        for system, owner, group, and world
                   XAB_B_PROT_OPT : byte ; // File protection options
                   XAB_L_UIC : cardinal ; // User identification code
               end ;
This block contains file protection information.

XAB_W_PRO
File protection codes.

XAB_W_UIC
The UIC of the file owner.

type TXABRDT = packed record // Revision date to apply on close
                   XAB_B_COD : byte ; // Type code (must be XAB_C_RDT)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_Q_RDT : int64 ; // Revision date and time
                   XAB_W_RVN : word ; // Revision number
               end ;
This block contains a revision date/number to be applied when an open file is closed.

type TXABSUM = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_SUM)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_B_NOA : byte ; // Number of allocation areas defined for the file
                   XAB_B_NOK : byte ; // Numbers of keys defined for the file
                   XAB_W_PVN : word ; // Prolog version number
               end ;
This block contains RMS summary information.

type TXABTRM = packed record
                   XAB_B_COD : byte ; // Type code (must be XAB_C_TRM)
                   XAB_B_BLN : byte ; // Block length
                   XAB_L_NXT : int64 ; // Next XAB address
                   XAB_L_ITMLST : int64 ; // Item list address
                   XAB_W_ITMLST_LEN : word ; // Item list length
               end ;
This block is used for terminal-specific actions.

In the next article, we'll look at the F$FILE_ATTRIBUTES lexical function which makes use of the above structures.

 

Copyright © 2020 by Alan Conroy. This article may be copied in whole or in part as long as this copyright is included.