Technical Capabilities
Having trouble finding what you need?
Get in touch with us, so we can answer your specific questions directly.
Get In Touch

VX/RMS – SYS$ Routines for RMS

Overview

VX/RMS is a call-compatible library that runs OpenVMS RMS applications on Linux and Windows without source code changes. It presents the OpenVMS RMS callable interface: the SYS$ record and file services operating on the familiar FAB, RAB, XAB, and NAM control blocks, so recompiled programs open, read, write, and lock records exactly as they did on VMS.

Underneath, VX/RMS is an emulation layer rather than a re-implementation of VAX or Alpha RMS internals. Sequential and relative files map onto plain host files, indexed files map onto a D-ISAM keyed store, VMS file specifications and logical names are translated automatically, and native host error codes are mapped back to their VMS RMS equivalents. Programs keep their VMS file organizations, access modes, record formats, and locking behaviour on the new platform.

Architecture and how it maps to the host

VX/RMS is a linked runtime library, not a server or daemon. It is archived into libvxrt.a, the same runtime archive shared with the other VX/TOOLS routines, and linked directly into the migrated application. There is no RMS process to administer: every record operation is serviced in-process by the library, which presents the OpenVMS RMS callable interface on top of ordinary host files.

Each RMS file organization is mapped onto a concrete host storage mechanism. Record I/O for sequential and relative files uses plain file reads, writes, and seeks; indexed files are backed by a D-ISAM keyed store; locking uses host byte-range locks for sequential and relative files and D-ISAM record locks for indexed files. Filename and version machinery is emulated on top of the host directory tree.

RMS organizationHost storageLockingNotes
SequentialPlain host fileByte-range locksOptional 44-byte file-header block records RAT, RFM, and MRS.
RelativePlain host fileByte-range locksRecords carry a 3-byte VMS-shaped header (control byte plus 2-byte length).
IndexedD-ISAM keyed storeD-ISAM record locksPrimary and secondary keys build a companion index alongside the data file.
No server to administer. VX/RMS has no daemon and no IPC substrate to configure. The library reads and writes the host files directly, in the address space of the migrated program, so deployment is a link step rather than a service install.

Layering

The runtime sits between the unchanged application and the host file system:

Migrated applicationUnchanged SYS$ and EXE$ calls
Calls into
VX/RMSIn-process runtime in libvxrt.a
Selects storage by file organization
Plain host filesSequential and relative organizations
D-ISAM keyed storeIndexed organization
Converges on host storage and locking
Host file systemByte-range locks for plain files and record locks for indexed files

The library also emulates the file-header block that VX/RMS optionally writes at the front of sequential and relative files. This can be turned off with the IGNORE_FHC, NOFHC, or EXTUNIX configuration options to produce a plain host file with no VMS-specific header, which is useful when the data needs to be read by native host tooling as well.

The SYS$ and EXE$ call model

Every RMS service is exposed as a two-layer pair so existing object references and calling conventions resolve without change. The outer SYS$ entry is the canonical caller name; the inner EXE$ entry does the work and is used internally by the runtime.

LayerRoleCallbacks
SYS$xxxOuter user entry. Takes two extra error and success AST callback pointers, then wraps the EXE$xxx call.Fires AST callbacks when enabled.
EXE$xxxInner entry that performs the operation. Called directly from inside the runtime, for example when EXE$CREATE opens an existing file.No AST callbacks.

Each service is aliased to upper-case, lower-case, and trailing-underscore forms (sys$xxx_, exe$xxx_), so Fortran callers reach the same body with no separate thunk. The two-layer wrapper shape is consistent across every routine:

extern "C" U32 SYS_D_OPEN( FABDEF *fab,
                        U32 (*error)(void),
                        U32 (*success)(void) )
{
    // do the work through the inner entry
    U32 rc = EXE_D_OPEN(fab);

    // AST callbacks fire only when RMSAST=Y (off by default)
    if (vxrt_RMS_Ast_Enable()) {
        if (success && ODD(rc))  (*success)();
        else if (error && !ODD(rc)) (*error)();
    }
    return rc;
}
// aliased to SYS$OPEN, sys$open, and sys$open_

AST gating

Callbacks are off by default. The error and success ASTs fire only when the RMSAST configuration option is set to Y. With it off, portable callers may pass null for the two callback pointers safely. With RMSAST=Y, passing null for a callback that is needed will dereference it, matching the original VMS behaviour.

Status convention

Every routine returns a 32-bit VMS-style condition code by value: the low bit set means success. Test it with ODD(status). There are no signal-raising paths: conditions that native VMS would raise as an exception are returned by value instead (usually RMS$_FAB or RMS$_RAB). A process-wide RMS_STATUS global is set as a side effect of almost every routine, which makes RMS calls non-reentrant across threads.

Control structures: FAB, RAB, XAB, NAM

VX/RMS operates on the same control blocks as native OpenVMS RMS. Application code fills these structures, passes them by reference, and reads results back from the same fields. The layouts are byte-compatible with the VMS definitions so recompiled programs bind to them unchanged.

BlockPurposeKey fields and notes
FAB (File Access Block)Describes the file: name, organization, record format, and sharing.Organization FAB$B_ORG selects sequential, relative, or indexed. Set up before SYS$OPEN or SYS$CREATE.
RAB (Record Access Block)Describes a record stream connected to an open file.Access mode RAB$B_RAC selects sequential, keyed, or record-file-address access. A 64-bit variant carries wide buffer and size slots for SYS$GET.
XAB (Extended Attribute Blocks)Optional chain of attribute blocks hung off the FAB or RAB.Recognised types include allocation, date, file-header, key, protection, and summary blocks, plus a host-specific block reporting the underlying file name and companion index and data files.
NAM (Name Block)Holds filename parse state and results.Expanded and resultant string areas plus wildcard context. Directory and file identifiers are populated with host inode numbers rather than VMS file identifiers.

XAB chain

Extended attribute blocks form a singly-linked chain located with a runtime helper. The file-header attribute block is the 44-byte header VX/RMS writes at the front of relative and sequential files; one key attribute block describes each key of an indexed file. Journalling and recovery-unit attribute blocks are recognised so that parsing does not error, but the underlying features are not implemented (see the compatibility matrix).

SYS$ routine reference

VX/RMS exports the OpenVMS RMS callable services. Each service is available under its SYS$ name (the canonical caller entry), an EXE$ inner variant, and the Fortran trailing-underscore aliases. The tables below group the routines by function and give each one a support status: live means implemented and doing the work, while stub means present for source compatibility but returning success without performing the named function.

File operations

SYS$ routineEXE$ variantPurposeStatus
SYS$OPENEXE$OPENOpen an existing file; organization is auto-sniffed from disk.live
SYS$CREATEEXE$CREATECreate an indexed, relative, or sequential file; build keys, write the file header, resolve version.live
SYS$CLOSEEXE$CLOSEClose a file, including delete-on-close and revision-date write.live
SYS$ERASEEXE$ERASEDelete a file, including wildcard erase via a parse, search, and unlink loop.live
SYS$RENAMEEXE$RENAMERename a file (implemented as link then unlink, not an atomic rename).live
SYS$COPYEXE$COPYCopy a file by opening, creating, and streaming raw chunks.live
SYS$DISPLAYEXE$DISPLAYFill FAB, NAM, and XAB output fields from the file on disk.live
SYS$PARSEEXE$PARSEParse a filename, translate logical names, and build the wildcard chain.live
SYS$SEARCHEXE$SEARCHReturn the next wildcard match.live
SYS$FREELISTnoneFree the internal parse and search directory chain.live

Record operations

SYS$ routineEXE$ variantPurposeStatus
SYS$CONNECTEXE$CONNECTAttach a record stream to an open file and position by key.live
SYS$DISCONNECTEXE$DISCONNECTDetach a record stream.live
SYS$GETEXE$GETRead a record (multi-way dispatch across organizations, plus terminal and mailbox paths).live
SYS$PUTEXE$PUTWrite a record (multi-way dispatch across organizations).live
SYS$FINDEXE$FINDPosition to a record without transferring it.live
SYS$UPDATEEXE$UPDATERewrite the current record.live
SYS$DELETEEXE$DELETEDelete the current record (indexed and relative organizations).live
SYS$READEXE$READBlock-level (virtual block number) read.live
SYS$WRITEEXE$WRITEBlock-level write.live
SYS$TRUNCATEEXE$TRUNCATETruncate a sequential file at the current record.live
SYS$REWINDEXE$REWINDReposition the stream to the first record.live
SYS$FLUSHEXE$FLUSHForce buffered output to disk.live

Locking

SYS$ routineEXE$ variantPurposeStatus
SYS$FREEEXE$FREERelease all record locks held on the stream.live
SYS$RELEASEEXE$RELEASERelease the lock on the current record only.live

Stubs (accepted for source compatibility)

SYS$ routinePurpose on VMSStatus
SYS$EXTENDExtend a file's allocation.stub: the host file system extends on demand
SYS$WAITWait for asynchronous completion.stub: all I/O is synchronous
SYS$START_RUBegin a recovery unit.stub: journalling not implemented
SYS$END_RUEnd a recovery unit.stub
SYS$ABORT_RUAbort a recovery unit.stub
Full surface, honest boundaries. VX/RMS exports the complete set of SYS$ entry points so existing code links cleanly. The record and file services are live; the five stubs above return success without acting, which matches how their functions behave under a host file system where allocation, asynchronous I/O, and RMS journalling are handled differently.

Status codes and error mapping

Applications that inspect RMS status values keep working unchanged, because VX/RMS returns the same VMS-style condition codes and maps native host error numbers back to their RMS equivalents. Status symbols are written RMS$_XXX in VMS notation. A representative set of the common codes:

SymbolDecimalMeaning
RMS$_NORMAL65537Successful completion.
RMS$_EOF98938End of file.
RMS$_FNF98962File not found.
RMS$_RLK98986Record is locked.
RMS$_OK_RLK98337Success, but the record was already locked.

Host errno to RMS status

When a host system call fails, VX/RMS translates the errno value into the matching RMS condition code, sets RMS_STATUS, and returns it. This is the mechanism behind automatic error-code mapping:

Host errnoRMS statusMeaning
ENOENTRMS$_FNFFile not found.
EAGAINRMS$_RLKRecord locked by another stream.
ENOSPCRMS$_FULDevice or file full.
EACCESRMS$_PRVPrivilege or protection violation.

Because the status is returned by value and also mirrored in the global RMS_STATUS, existing patterns such as testing ODD(status) or comparing against RMS$_EOF at the end of a read loop behave exactly as they did on VMS.

Compatibility with native OpenVMS RMS

VX/RMS covers the record and file services that production applications actually depend on, and is explicit about the areas that behave differently on a host file system. The matrix below places each capability in exactly one bucket.

CapabilityStatusNote
Sequential, relative, and indexed record I/OliveFull open, get, put, update, delete, and find.
Filename parse, logical-name translation, wildcard searchliveHandled by the parse and search services.
File-level operations (create, erase, rename, copy)liveRename is link-then-unlink, not an atomic operation.
Record and file lockingliveD-ISAM record locks for indexed; byte-range locks for sequential and relative.
Version emulationliveNext version on create, highest version on open.
Keyed indexed files with secondary keyslivePrimary and multiple secondary keys with various key types.
AST asynchronous callbackspartialGated by the RMSAST option, which is off by default.
Multi-stream sharing bitpartialSharing is taken from the share field rather than the multi-stream bit.
Asynchronous I/Oout of scopeAccepted but I/O blocks; the wait service is a no-op stub.
Recovery-unit and transaction journallingout of scopeAttribute blocks are recognised so parsing succeeds, but the feature is inert.
File pre-allocation (extend)out of scopeStub; the host file system extends on demand.
Magnetic tape and print-spool bitsout of scopeAccepted with no behaviour.

Deliberate divergences from native RMS

These are behaviours that differ by design because the storage layer is a host file system:

  • Storage layer. Sequential and relative files are plain host files; indexed files use a D-ISAM keyed store. Relative records carry a small VMS-shaped header, and an optional 44-byte file-header block records the record attributes.
  • No signals. Every error is returned by value; VMS condition handlers never fire.
  • Synchronous I/O. AST callbacks may fire, but the I/O itself blocks and the wait service returns immediately.
  • Rename is link-then-unlink. A crash mid-operation can leave the source under the new name with the old name dangling.
  • File identifiers. Directory and file identifiers hold host inode numbers, which are stable on the running host but are not portable VMS file identifiers.
  • Threading. The process-global status makes RMS non-reentrant across threads.

FDL file definition tooling

VX/RMS ships call-compatible File Definition Language (FDL) support, so the utilities and callable routines that describe and analyse RMS file structure carry over to the migrated environment. FDL definitions continue to drive file creation and tuning without change.

Routine or utilityPurpose
CREATE/FDLCreate an RMS file from an FDL definition.
ANALYZE/FDLAnalyse an existing file and report its FDL attributes.
FDL$CREATECallable routine to create a file from an in-memory FDL specification.
FDL$GENERATEGenerate an FDL description from a file's attributes.
FDL$PARSEParse an FDL specification into internal descriptors.
FDL$RELEASERelease descriptors allocated by a prior parse.

For the standalone FDL routine set and the broader file-conversion tooling, see VX/FDL File Description Language Routines, the FDL$ File Definition Language API, and CONV$ File Conversion.

Quick reference

SYS$ routines

SYS$OPEN
SYS$CREATE
SYS$CLOSE
SYS$CONNECT
SYS$DISCONNECT
SYS$GET
SYS$PUT
SYS$FIND
SYS$UPDATE
SYS$DELETE
SYS$READ
SYS$WRITE
SYS$TRUNCATE
SYS$REWIND
SYS$FLUSH
SYS$FREE
SYS$RELEASE
SYS$DISPLAY
SYS$PARSE
SYS$SEARCH
SYS$FREELIST
SYS$ERASE
SYS$RENAME
SYS$COPY

FDL routines and utilities

CREATE/FDL
ANALYZE/FDL
FDL$CREATE
FDL$GENERATE
FDL$PARSE
FDL$RELEASE

Control blocks

FAB
RAB
XAB
NAM

Organizations and access modes

Sequential
Relative
Indexed
Sequential access
Keyed access
Record-file-address access

Configuration options

RMSAST
IGNORE_FHC
NOFHC
EXTUNIX
UCMAP

Open, read, close skeleton

A migrated program links this unchanged against libvxrt.a. Note the ODD() status test after each call and the record buffer passed by reference:

// open the file and connect a record stream
status = SYS$OPEN(fab);                 // fab names BANKING:[ACCOUNTS]CUSTOMER.DAT
if (!ODD(status)) goto fail;
status = SYS$CONNECT(rab);
if (!ODD(status)) goto fail;

// read records until end of file
while (ODD(status = SYS$GET(rab))) {
    process_record(rab->RAB$L_UBF);     // application record buffer, filled by RMS
}
if (status != RMS$_EOF) goto fail;

// tear down
SYS$DISCONNECT(rab);
SYS$CLOSE(fab);

Frequently Asked Questions

Curious about how Sector7 can facilitate your application migration? Explore our FAQs for expert insights.

What is VX/RMS and how does it help with VMS migration?

VX/RMS is a call-compatible library that enables seamless migration of VMS/OpenVMS RMS applications to Linux without requiring any source code changes. It provides complete support for all VMS file types, access modes, record formats, and file locking mechanisms.

By implementing the SYS$ API set, VX/RMS ensures your applications function identically on Linux as they did on VMS/OpenVMS, eliminating the need for extensive rewrites. To discuss your specific migration requirements, contact us.

Which VMS file types does VX/RMS support?

VX/RMS supports all VMS/OpenVMS RMS file types including Indexed, Relative, Sequential, and Block mode files with full compatibility.

What SYS$ API functions are supported by VX/RMS?

VX/RMS implements all essential SYS$ API calls including SYS$OPEN, SYS$GET, SYS$PUT, SYS$READ, SYS$WRITE, SYS$UPDATE, SYS$SEARCH, SYS$PARSE, and SYS$RENAME among others.

How does VX/RMS handle file and record locking?

VX/RMS retains VMS/OpenVMS record-locking mechanisms while supporting enhanced Linux locking standards, ensuring data integrity and concurrent access control.

How does VX/RMS handle VMS file specifications and logical names?

VX/RMS automatically translates VMS-style file paths and logicals into Linux equivalents, maintaining application compatibility without manual intervention.

What FDL functions are supported by VX/RMS?

VX/RMS includes call-compatible FDL libraries supporting ANALYZE/FDL, CREATE/FDL, FDL$CREATE, FDL$GENERATE, FDL$PARSE, and FDL$RELEASE functions for complete file definition compatibility.

Do I need to change my application source code to migrate RMS with VX/RMS?

No. VX/RMS is a call-compatible library, so OpenVMS RMS applications move to Linux and Windows without source code changes. It presents the same SYS$ API and file behaviour, so existing programs open, read, write, and lock records exactly as they did on VMS.

Which RMS file organizations does VX/RMS support?

All OpenVMS RMS file organizations: indexed, relative, and sequential, along with their associated access modes and record formats. Sequential and relative files map onto plain host files, and indexed files use a keyed store.

Does VX/RMS preserve VMS record and file locking?

Yes. It retains the OpenVMS record-locking behaviour and applies host byte-range locks for sequential and relative files and record locks for indexed files, so concurrent-access behaviour is maintained after migration.

How are VMS file specifications and logical names handled after migration?

VX/RMS parses VMS-style file specifications and translates logical names into their host equivalents automatically, so applications keep using VMS file specs. File names are uppercased to match VMS behaviour, and paths cannot contain dots in any directory component.

What happens to RMS error codes when my application runs on Linux?

VX/RMS maps native host error numbers back to their corresponding VMS RMS status values. For example, a host file-not-found error becomes RMS$_FNF, so code that inspects RMS status values continues to behave as it did on VMS.

Which SYS$ routines does VX/RMS implement?

VX/RMS implements the OpenVMS RMS callable services, including SYS$OPEN, SYS$CREATE, SYS$CLOSE, SYS$CONNECT, SYS$GET, SYS$PUT, SYS$FIND, SYS$UPDATE, SYS$DELETE, SYS$PARSE, and SYS$SEARCH, each with an EXE$ inner variant and Fortran-compatible aliases.

Does VX/RMS support FDL file definition tooling?

Yes. VX/RMS provides call-compatible FDL support, including CREATE/FDL, ANALYZE/FDL, and the FDL$CREATE, FDL$GENERATE, FDL$PARSE, and FDL$RELEASE routines, so FDL-based file definition and analysis carry over to the migrated environment.

What is VX/RMS and how does it help with OpenVMS migration?

VX/RMS is a call-compatible library that runs OpenVMS RMS applications on Linux and Windows without source code changes. It supports all RMS file types, access modes, record formats, and locking, and implements the SYS$ API, so applications keep working on a modern platform with no rewrite.

Transform Your Legacy Software Today!

Get In Touch
Unlock the potential of your legacy software with our expert migration services.