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
103 GETJPI
104 Lexical functions: F$GETSYI
105 GETSYI
106 Lexical functions: F$INTEGER, F$LENGTH, F$LOCATE, and F$MATCH_WILD
107 Lexical function: F$PARSE
108 FILESCAN
109 SYS_PARSE
110 Lexical Functions: F$MODE, F$PRIVILEGE, and F$PROCESS
111 File Lookup Service
112 Lexical Functions: F$SEARCH
113 SYS_SEARCH
114 F$SETPRV and SYS_SETPRV
115 Lexical Functions: F$STRING, F$TIME, and F$TYPE
116 More on symbols
117 Lexical Functions: F$TRNLNM
118 SYS_TRNLNM, Part 2
119 Lexical functions: F$UNIQUE, F$USER, and F$VERIFY
120 Lexical functions: F$MESSAGE
121 TUOS_File_Wrapper
122 OPEN, CLOSE, and READ system services

UCL Commands
123 WRITE
124 Symbol assignment
125 The @ command
126 @ and EXIT
127 CRELNT system service
128 DELLNT system service
129 IF...THEN...ELSE
130 Comments, labels, and GOTO
131 GOSUB and RETURN
132 CALL, SUBROUTINE, and ENDSUBROUTINE
133 ON, SET {NO}ON, and error handling
134 INQUIRE
135 SYS_WRITE Service
136 OPEN
137 CLOSE
138 DELLNM system service
139 READ
140 Command Recall
141 RECALL
142 RUN
143 LIB_RUN
144 The Data Stream Interface
145 Preparing for execution
146 EOJ and LOGOUT
147 SYS_DELPROC and LIB_GET_FOREIGN

CUSPs and utilities
148 The I/O Queue
149 Timers
150 Logging in, part one
151 Logging in, part 2
152 System configuration
153 SET NODE utility
154 UUI
155 SETTERM utility
156 SETTERM utility, part 2
157 SETTERM utility, part 3
158 AUTHORIZE utility
159 AUTHORIZE utility, UI
160 AUTHORIZE utility, Access Restrictions
161 AUTHORIZE utility, Part 4
162 AUTHORIZE utility, Reporting
163 AUTHORIZE utility, Part 6
164 Authentication
165 Hashlib
166 Authenticate, Part 7
167 Logging in, part 3
168 DAY_OF_WEEK, CVT_FROM_INTERNAL_TIME, and SPAWN
169 DAY_OF_WEEK and CVT_FROM_INTERNAL_TIME
170 LIB_SPAWN
171 CREPRC
172 CREPRC, Part 2
173 COPY
174 COPY, part 2
175 COPY, part 3
176 COPY, part 4
177 LIB_Get_Default_File_Protection and LIB_Substitute_Wildcards
178 CREATESTREAM, STREAMNAME, and Set_Contiguous
179 Help Files
180 LBR Services
181 LBR Services, Part 2
182 LIBRARY utility
183 LIBRARY utility, Part 2
184 FS Services
185 FS Services, Part 2
186 Implementing Help
187 HELP
188 HELP, Part 2
189 DMG_Get_Key and LIB_Put_Formatted_Output
190 LIBRARY utility, Part 3
191 Shutting Down UOS
192 SHUTDOWN
193 WAIT
194 SETIMR
195 WAITFR and Scheduling
196 REPLY, OPCOM, and Mailboxes
197 REPLY utility
198 Mailboxes
199 BRKTHRU
200 OPCOM

Glossary/Index


Downloads

GetDVI, part 3

In this article, we look at the changes made in various places in conjunction with the GETDVI system call we've discussed in the previous two articles.

                         _Device : TUOS_Device ;
First, we add instance data to TResource. This is the device instance for the device associated with the resource.

        S := F.Name ;
        Dummy := pos( ':', S ) ;
        Device := Devices.TDevice( Get_Device( copy( S, 1, Dummy ) ) ) ;
In the TUOS_FiP.Create_File_Handle method, when a file is specified we pull the device name from the file name and assign the TResource's _Device instance data to that device.

        if( ( S <> '' ) and ( not Device.Mounted ) ) then
        begin
            Set_Last_Error( Create_Error( UOSErr_Device_Not_Mounted ) ) ;
            exit ;
        end else
        if( ( S = '' ) or ( Device.FS = nil ) ) then // No file structure on device or only device specified
        begin
            if( ( S <> '' ) and ( ( Flags and FO_Block_Mode ) = 0 ) ) then // Opening non-file-structured
            begin
                Set_Last_Error( Create_Error( UOSErr_Device_Not_File_Structured ) ) ;
                exit ;
            end ;
We altered the next part of the method slightyly. Whereas before we returned an error if the device is not mounted, now we only do this if a folder/file name was specified in addition to the device. This is to allow us to obtain a handle to an unmounted device. Generally we don't allow operations on unmounted devices, but there are a few exceptions. For now, we want to get information on the device. In the future, there are some cases where we will want to do other operations to unmounted devices. Additionally, we altered the code to allow a handle for a device if FO_Block_Mode is not specified if only the device was specified.

    Result._Device := Device ;
If a device is specified when a file handle is requested, we have to get the device instance to see if the file exists. So we assign that to _Device.

                       public // API...
                           function Buffer_Size : int64 ;
                           function Write_Locked : boolean ;
                           function Max_IO_Size : int64 ;
                           function Description : PChar ;
                           function Revision : PChar ;
                           function Operation_Count : int64 ;
                           function Queue_Length : int64 ;
                           function Serial_Number : PChar ;
We add several methods to the TDevice class.

function TDevice.Buffer_Size : int64 ;

begin
    Result := 0 ;
    if( FS <> nil ) then
    begin
        Result := FS.Store.Min_Storage ;
        exit ;
    end ;
    if( Terminal <> nil ) then
    begin
        Result := Terminal.Char_Columns ;
        exit ;
    end ;
    if( Stream <> nil ) then
    begin
        Result := Stream.Min_Record_Size ;
    end ;
end ;


function TDevice.Write_Locked : boolean ;

begin
    Result := False ;
    if( FS <> nil ) then
    begin
        Result := FS.Store.Read_Only ;
        exit ;
    end ;
    if( Stream <> nil ) then
    begin
        Result := Stream.Read_Only ;
        exit ;
    end ;
end ;


function TDevice.Max_IO_Size : int64 ;

begin
    Result := 1 ;
    if( FS <> nil ) then
    begin
        Result := FS.Store.Max_Storage ;
        exit ;
    end ;
    if( Terminal <> nil ) then
    begin
        Result := 255 ;
        exit ;
    end ;
    if( Stream <> nil ) then
    begin
        Result := Stream.Max_Record_Size ;
        exit ;
    end ;
end ;


function TDevice.Description : PChar ;

begin
    Result := nil ;
end ;


function TDevice.Revision : PChar ;

begin
    Result := nil ;
end ;


function TDevice.Operation_Count : int64 ;

begin
    Result := 0 ;
    if( Store <> nil ) then
    begin
        Result := Store.Reads + Store.Writes ;
    end else
    if( Terminal <> nil ) then
    begin
        Result := Terminal.Reads + Terminal.Writes ;
    end else
    if( Stream <> nil ) then
    begin
        Result := Stream.Reads + Stream.Writes ;
    end ;
end ;


function TDevice.Queue_Length : int64 ;

begin
    Result := 0 ;
end ;


function TDevice.Serial_Number : PChar ;

begin
    Result := nil ;
end ;
Some of these methods simply return 0/nil/null because we have yet to address the feature.
Buffer_Size is the device default buffer size, in bytes. For stores, this is the minimum allocation size. For terminals, the default buffer size is the number of character columns on the termianl, although this can be larger as needed. For all other streams, we return the minimum record size supported by that stream.
Max_IO_Size is the maximum amount of data, in bytes, that can be transferred to the device in a single operation. Other considerations may result in a difference from this theoretical value. As an example, there may not be enough memory to hold a buffer that would match the theoretical maximum I/O size. For stores, this is the entire size of the store. For terminals, it is the same as the default buffer size. For all other streams, we return the maximum record size.
Operation_Count returns the sum of the reads and writes for the appropriate device.
Write_Locked returns true if the device cannot be written to. This comes from the device and we simply pass the value on. The devices themselves expose this characteristic via their Read_Only methods.

      // Terminal flags...
const TT_M_SCOPE = 1 ; // Video (0 = hardcopy)
      TT_M_EIGHTBIT = 2 ; // Terminal uses the 8-bit ASCII character set otherwise use 7-bit ASCII code.
      TT_M_ESCAPE = 4 ; // Terminal generates escape sequences
      TT_M_HALFDUP = 8 ; // Terminal is in half-duplex mode
      TT_M_HOSTSYNC = 16 ; // Ctrl/Q and Ctrl/S are used to control data flow
      TT_M_LFFILL = 32 ; // Terminal requires fill after the line-feed character is processed.
      TT_M_UPPERCASE = 64 ; // Terminal doesn't have the lowercase character set.
      TT_M_MBXDSABL = 128 ; // Mailboxes associated with device not notified of unsolicited input or hangup
      TT_M_MECHFORM = 256 ; // Terminal has mechanical form feed.
      TT_M_MECHTAB = 512 ; // Terminal has mechanical tabs and is capable of tab expansion
      TT_M_MODEM = 1024 ; // Honor modem signals
      TT_M_NOBRDCST = 2048 ; // Terminal does not receive any broadcast messages.
      TT_M_NOECHO = 4096 ; // Input characters are not echoed on this terminal line
      TT_M_NOTYPEAHD = 8192 ; // Data must be solicited by a read operation.
      TT_M_READSYNC = 16384 ; // Host explicitly solicits all reads with Ctrl/Q and terminates with Ctrl/S.
      TT_M_REMOTE = 32768 ; // Dialup characteristic is enabled. Terminal returns to local mode on hangup
      TT_M_CRFILL = $10000 ; // Terminal requires fill after the Return key is pressed
      TT_M_TTSYNC = $20000 ; // Output to the terminal is controlled by terminal-generated Ctrl/Q or Ctrl/S.
      TT_M_WRAP = $40000 ; // A CRLF combination should be inserted if the cursor moves beyond right margin.

      TT2_M_ALTYPEAHD = $80000 ; // Alternate type-ahead buffer size is enabled
      TT2_M_ANSICRT = $100000 ; // ANSI CRT terminal is enabled.
      TT2_M_APP_KEYPAD = $200000 ; // Notifies applications of state to set the keypad to when exiting.
      TT2_M_AUTOBAUD = $400000 ; // Automatic baud rate detection is enabled.
      TT2_M_AVO = $800000 ; // Advanced video is enabled.
      TT2_M_BLOCK = $1000000 ; // Block mode is enabled.
      TT2_M_BRDCSTMBX = $2000000 ; // Broadcast messages are sent to an associated mailbox, if one exists.
      TT2_M_COMMSYNC = $4000000 ; // Enables devices such as printers to be connected to terminal ports.
      TT2_M_DECCRT = $8000000 ; // DIGITAL CRT terminal.
      TT2_M_DECCRT2 = $10000000 ; // DIGITAL CRT terminal.
      TT2_M_DECCRT3 = $20000000 ; // DIGITAL CRT terminal.
      TT2_M_DECCRT4 = $40000000 ; // DIGITAL CRT terminal.
      TT2_M_DIALUP = $80000000 ; // Terminal is a dialup line.
      TT2_M_DISCONNECT = $100000000 ; // Allows terminal disconnect when a hangup or disconnect occurs
      TT2_M_DMA = $200000000 ; // Direct memory access (DMA) mode.
      TT2_M_DRCS = $400000000 ; // Terminal supports loadable character fonts.
      TT2_M_EDIT = $800000000 ; // Terminal edit for those that support ANSI-defined advanced edit functions.
      TT2_M_EDITING = $1000000000 ; // Line editing is allowed.
      TT2_M_FALLBACK = $2000000000 ; // Transform output from 8-bit multinational characters to 7-bit ASCII
      TT2_M_NOHANGUP = $4000000000 ; // UOS will not force modem to hangup when user logs off.
      TT2_M_INSERT = $8000000000 ; // Sets default mode for insert or overstrike at the beginning of read.
      TT2_M_LOCALECHO = $10000000000 ; { Local echo. This characteristic is used with TT_M_NOECHO. If both
                          characteristics are set, only terminators and special control
                          characters are echoed. Use of this mode is restricted to command-line
                          read operations. Local echo is not compatible with line editing
                          (TT2_M_EDITING). }
      TT2_M_MODHANGUP = $20000000000 ; // Modify hangup.  Allow hangup with privileges.
      TT2_M_PASTHRU = $40000000000 ; // Terminal is in PASTHRU mode
      TT2_M_PRINTER = $80000000000 ; // Terminal with a local printer port.
      TT2_M_REGIS = $100000000000 ; // ReGIS graphics. The terminal supports ReGIS graphics instruction set.
      TT2_M_SIXEL = $200000000000 ; // SIXEL graphics. The terminal supports SIXEL graphics instruction set.
      TT2_M_SECURE = $400000000000 ; // Guarantees that no process is connected after BREAK is received.
      TT2_M_SETSPEED = $800000000000 ; // Set speed requries either LOG_IO or PHY_IO privilege.
      TT2_M_SYSPWD = $1000000000000 ; // The login procedure should require the system password
      TT2_M_XON = $2000000000000 ; // XON/XOFF control.
      TF_Query = $4000000000000 ; // Send query sequence to terminal
      TF_Graphics = $8000000000000 ; // Graphics device (0 = character)
      TF_Set_Host = $10000000000000 ; // Terminal is connected from remote node via set host
      // $20000000000000 - $4000000000000000 = reserved
Finally, we have the definitions of the VMS terminal flags. We've replaced some of the older TF_ constants with the appropriate VMS flags. But there are some flags that don't correspond to any VMS flags, these will remain prefixed with "TF_".

In the next article, we will look at the next lexical function.

 

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