raFS Technical Details

Technical Details

This part of the manual describes more technical aspects of raFS. It is not necessary for you to read it, but there are a few things here that aren't mentioned in the User Manual.

Corrupted discs

raFS includes code to deal as cleanly as possible with discs that contain invalid directories or file references. For example, a disc may become corrupted due to changed but not yet saved directory data being lost when the computer crashes.

Whenever directory data is loaded into memory, the filing system performs a number of checks to ensure that it really represents a valid directory - incorrect directories could have disastrous effects. An error message of the form directory data in 'ADFS::4.$.A0.A0.A0' is invalid is given in this case.

Before a new file or directory is written to the host filing system, raFS also ensures that the directory doesn't contain any files with invalid names. If a file is found whose name is not one of the 77 names A0 to Z1, the save operation fails with Name inside the directory containing a raFS disc is not of the form 'A0.A0.A0'

Finally, special code deals with files on raFS which refer to files on the host filing system that either don't exist or that have a different time/date stamp. If a file is missing, a dummy file (length zero, file type zero, date stamp 01-01-1900) is created to prevent other files from being assigned that ID. (Depending on the configured TimeZone of your machine, the year may also be displayed as 2248 instead of 1900.)

If the date stamp, file type or the file length does not match the directory entry, all open, load, save, delete and create operations on files will only produce an error like 'ADFS::4.$.A0.A0.A0' does not belong to this directory entry - verify the raFS disc. In this state, the only possible operations are renaming the file, stamping it (or changing its access details) and deleting it (only if it refers to a dummy file). Stamping the file causes the data to be synchronized, so that any operation can be applied to it again, but only do this if you are very sure about it!

Because there are filing systems that cannot store the date stamp in centiseconds like the native RiscOS filing systems do, the stamp will still be considered valid if it doesn't differ by more than 24 hours from what the raFS directory entry contains. Some filing systems don't allow file stamps at all. Consequently, it is possible to disable the checks by setting the system variable raFS$NoChecks to a comma-separated list of filing system names or image file types of the form &FC8 before mounting discs on those filing systems. The names are matched case-sensitively.


The verify operation attempts to detect invalid raFS discs and to repair them. This is achieved with several passes:
  1. Scan the storage directory and its subdirectories and build a map of used IDs.
  2. Scan the directory structure of the raFS disc, taking note of referenced IDs in the map. This allows for detection of duplicate references and non-existent files/directories.
  3. If any unreferenced objects remain, test whether one of them represents valid directory data. Once such an unreferenced directory is found, re-insert it into "Lost+Found" and return to the second pass to have the contents of this new directory verified.
  4. If no more unreferenced directories can be found, directly insert any remaining files into "Lost+Found", except for zero length files; they are deleted.

Back to the top of the page

Behaviour in special situations

There are a few points worth noting about how raFS behaves in certain situations.
  • As a result of raFS' ability to have a file opened more than once, it is also possible to save on top of an opened file. In this case, the file extent will be set to the size of the file that is saved.
  • Once a file is opened multiple times, it is possible that the file extent becomes smaller than the sequential pointer. This happens only for those sequential pointers that don't belong to the file handle used for changing the extent, i.e. if file handles A and B were returned when a file was opened twice, and file handle A is used to set the extent, then the sequential pointer of A will be set to the extent if it is greater whereas the sequential pointer of B won't be. This is not a bug, the behaviour is intended!
  • raFS will sometimes automatically close files on its discs. This happens when you use Close on one of raFS' host filing systems. For example, if you issue ADFS:Close and you have one raFS disc on ADFS and one on SCSIFS, any open files on the raFS disc stored on ADFS will be closed, but open files on the other disc remain unaffected.

    raFS claims FindV (called by OS_Find) and FSCV (called by OS_FSControl) and will close its own files before FileSwitch closes them on the host filing system. This is done either only for one filing system in the case of OS_Find 0,0 (close all files on current filing system), or for all filing systems in the case of OS_FSControl 22 (close all open files) and OS_FSControl 23 (shutdown all filing systems).

  • Try running the following program on a file on a FileCore disc which is locked and has no write access, only read access. It uses OS_Args 6 to ensure an open file's size:


    Whereas FileCore ensures the specified size regardless of whether or not write access was granted, raFS gets it right and ignores FSEntry_Args 6 if the file is read-only. (By the way: Could this be used to compromise security when a FileCore-based filing system is shared over a network? Just a thought...)

Back to the top of the page

Limits of raFS

The following gives some information about the limits imposed by raFS on its discs. In practice. you are very unlikely to reach any of them, though.
  • The maximum number of discs that can be mounted at the same time is 50. (This can easily be altered to up to 255 in the source code.)
  • One disc may contain at most 76·77·77 = 450604 objects (an object is a directory or file). Note that FileCore-based filing systems cannot store more than 32766 disc objects on a disc anyway.
  • Consequently, you can theoretically have up to 450603 entries in a directory...
  • The limit for the length of filenames is about 500 characters, though FileSwitch imposes a limit of nearly 256 characters and the Filer will only handle properly up to 63 characters.
  • Disc names can be up to 63 characters long. For longer names no error is given, instead the name is truncated. (However, at present RiscOS insists on a disc name length of 2 to 10 characters with OS_FSControl 50 - you must use NameDisc for longer names.)
  • Up to 65535 directories may be cached at the same time, otherwise things start going wrong.
  • raFS is not re-entrant. This means that you cannot use raFS as the host filing system for another raFS disc - this wouldn't serve any purpose, anyway. Because this is no image filing system, it doesn't need to be re-entrant.

Back to the top of the page

Known problems

  • If access to a directory becomes extremely slow as soon as it contains several hundred files, this is no problem at all: Just increase the size of the directory cache!
  • Should deletion of files on raFS be very slow and you are using Undelete by Quantum Software, turn off deletion protection either for raFS or for the storage directory on the host filing system. You should also upgrade to V1.50 of the Model module.
  • There appears to be a problem in FileSwitch or in the Filer which causes crashes for very long disc names. Only use at most 16 characters for now!
  • For the RiscOS 3.1 version, other programs may corrupt the sprite area and can make raFS crash. If this is the case for you, enable RMA support by uncommenting the relevant lines in !raFS.!Boot and !raFS.!Run.
  • With older versions of the AlSystems SCSI podule (e.g. SCSIFS 1.34), raFSFiler crashes when started, unless it is loaded before the desktop starts up (for example, by copying it into !Boot.Choices.Boot.PreDesk).
  • Several users have experienced Cannot extend raFS buffers errors when there was still enough free memory left. This seems to be caused by the ANT internet suite (more specifically, the Mbuf Manager module). Apart from this, commands like Copy are known to cause the same error.
  • If you get the error Name inside the directory containing an raFS disc is not of the form A0.A0.A0 then this is probably caused by an older version of the ImageFSFix module - ArcFS version, earlier than V0.30 (25-Aug-1996). Note that the ImageFSFix modules supplied with SparkFS (e.g. V0.04) do not cause any problems.
  • For every file on a raFS disc that is opened, raFS will open another one on the host filing system. Because file handles are used up twice as quickly, it is theoretically possible that e.g. the FontManager causes the main application to run out of file handles. However, this is unlikely to happen.
  • Some filing system calls that are supported by FileCore for backward compatibility are now deprecated in favour of other calls. They are not implemented in raFS:
    • OS_GBPB 5 (read name and boot option) - use OS_FSControl 37 and/or 47
    • OS_GBPB 6 or 7 (read directory name and privilege byte) - use OS_FSControl 37
    • OS_GBPB 8 (read directory entries) - use OS_GBPB 9
  • If Filer_Action fails with Internal error, no stack for trap handler: Internal error: Branch through zero at... while deleting files, the reason is that it has attempted to access a directory in order to see whether it is empty, but the file on the host filing system which contains the directory data is not there. If you double-click on the relevant directory, you will get an error message saying something like Error when reading 'raFS::DiscName.$.X.Dir' - 'ADFS::HardDisc4.$.MyDisc.A0.V8.U2' not found

    A similar thing happens when you try to rename an object whose file isn't found on the host filing system. This is a bug in the Filer_Action module. (The module's programmer assumed that there will never be an error under certain circumstances.)

  • You may occasionally notice that the Dismount submenu is closed after a click with Adjust. This incorrect behaviour is also caused by the Filer.
  • If an error occurs on the host filing system at a certain point during renaming a file, you may end up with two directory entries pointing to the same file. Don't attempt to delete one of them - this will also delete the actual file, so the second entry won't work any longer! Instead, verify the disc.

    In practice, this is very unlikely to happen.

  • Do not use Memphis (a memory-based filing system) as the host filing system for a raFS disc with the pre-RiscOS 3.5 version of raFS (i.e. the one that uses the sprite area, just like Memphis does). This seems to work for a while, but sooner or later something causes data loss. I cannot be 100% sure, but my log files indicate that Memphis and not raFS itself is the culprit (Data that I write to Memphis and then re-load immediately afterwards is corrupted).

    The reason for the problem might lie in the fact that Memphis might not expect that data saved to it is somewhere in the sprite area: raFS makes a call to FileSwitch to save data to Memphis. Upon receiving the query from FileSwitch, Memphis does some housekeeping, during which the size of one of its sprites is altered, so that the sprite that belongs to raFS is copied to a different memory location. Then Memphis "saves" the area of memory specified by FileSwitch, but this no longer points to the correct data! The correct behaviour of Memphis would be to check whether the data to be saved is in the sprite area, and if it is, to update its pointer to it whenever a sprite with a lower address changes size.
    [By the way: At present, raFS itself doesn't perform these checks either...]

    It should be possible to use Memphis at the same time as raFS as long as it is not the host filing system. However, don't blame me if something screws up...

  • ...there might be the odd bug.

Back to the top of the page

Command line interface

The raFSFiler module provides two *commands:

Desktop_raFSFiler [-choices] [-newdisc] [-left] [-right] [-priority <nr>]
If issued without any arguments, this command causes raFS to install its icon on the icon bar. You can change the position of the icon bar icon by adding -left, -right and -priority switches to the command in the !Run file.

The -choices and -newdisc switches are useful for executing when the icon bar icon is clicked on. They open the "Choices" and "Create new disc" windows, respectively.

Desktop_raFSFiler also supports -options, -mount, -select and -adjust switches, but these are intended for internal use only.

raFSFiler_Menu <command> <menutitle> [-X <OSunits>] [-Y <OSunits>] [-one | -first]
This command is intended to be executed by a click on the icon bar menu. It opens a menu with the names of all currently mounted discs and with the specified string as the menu's title string. Once one of the names has been selected, the following substitutions take place before the command is executed:
  • %0 in the string is replaced with the disc name.
  • %1 is replaced with the path of the disc's storage directory.
  • %2 is replaced with the path of the parent of the disc's storage directory.
By default, the menu is opened at the position of the pointer, but this can be overridden by giving absolute coordinates for the upper left corner of the menu with the -X and -Y switches. For -Y, negative values have a special meaning - they indicate that the (absolute) value is the y coordinate of the lower edge of the menu, making it possible to position the menu above the icon bar with a value of -96 (which must be specified as 0-96 because of the leading dash).

In some cases, it may be desirable not to open the menu if only one disc is mounted, so the -one switch can be used to execute the command immediately if this is the case; otherwise, the menu is displayed first.

-first is similar to -one, but always executes the command immediately. If there is more than one disc, the first disc in the list is chosen. The -first and -one switches cannot be used at the same time.

If no discs are mounted at all, raFSFiler_Menu is ignored. Remember to enclose the command and menu title in quotation marks if they consist of more than one word.

raFS provides several *commands. While the raFSFiler module offers a more convenient way of working with discs, you may sometimes prefer to use the command line instead.

This command selects raFS as the current filing system. For raFS commands that are also supported by other filing systems, like Mount, you must switch to raFS with this command before using them. (Alternatively, you can use raFS:Mount to switch to raFS temporarily.)
raFS_Create <directory> <DiscName> [-app <SpriteName>]
This command sets up a storage directory for a disc, so that you can subsequently mount it with Mount <directory>. If you use a whole hard or floppy disc just for raFS, use the root directory "$" as the storage directory, otherwise choose a directory as near to the root as possible.

The storage directory is the directory to which all files saved to the disc will be written. If the specified directory does not already exist, it is created. If it isn't empty, raFS will give an error.

If the given directory's leafname begins with "!", the optional -app switch can be used to specify the name of a sprite to use for this application, for example -app directory to make it look like an ordinary directory. This sprite must be present in the Wimp's pool when the command is issued. raFS also saves a !Run file so that double-clicking on the application will mount the disc and open its root directory. The -app switch has no effect if the first character of the leafname is not "!".

To delete a complete raFS disc, make sure it has been dismounted and then Wipe the storage directory.

This command saves the directory information of any altered directories to the host filing system. However, in contrast to Dismount the cached directories remain in memory. It is useful to ensure that a subsequent crash will not cause data to be lost.
raFS_Discs or the equivalent raFS_Disks gives a list of all discs that are mounted at the time the command is entered. One line of text will be printed for each disc, consisting of the disc name followed by a space character and the name of the disc's storage directory.

Future versions of raFS may print out additional information after that described above, with further items appended to the printed lines after spaces. Take this into account when writing programs that make use of this command's output.

Mount <directory> [-readonly] [-path] [-X]
This command makes sure that you can access the raFS disc stored in the specified directory, e.g. that you can open the root directory "raFS::DiscName.$". It will also set the current directory to the disc's root directory, unset the User Root Directory (URD), and set the system variable raFS$Disc to the new disc's name. A file called Lock is created inside the storage directory if possible.

Two discs with the same name cannot be mounted at the same time - an error will be given if this is attempted. However, if you try to mount a disc that is already mounted (i.e. the disc of that name has the same storage directory as specified in the Mount command), raFS will give no error and will ignore the command.

raFS automatically decides whether or not the disc is read-only by looking at the file !Atterer. If this file does not have write access (either because it resides on a read-only filing system or because you set its attributes in order to permanently "write protect" the disc), all attempts to modify files or directories will be faulted.

The optional -readonly switch (short -ro) write protects the disc even if !Atterer has write access.

Any -path switch appended to the command will only come into effect if the disc stored in the specified directory has the same name as one of the currently mounted discs. In this case, it is assumed that the name of that disc's storage directory has changed (e.g. because you renamed a directory in the path) and that raFS should update its workspace accordingly. Use this with care! You must not use this feature to set the path to the storage directory of a different disc!

When mounting discs without an -X switch appended to the Mount command, raFS looks for a file called !Mount in the storage directory. If the file is not present, the disc is just mounted, but if !Mount is found, it is Run. Apart from that, nothing happens; the disc is not mounted if !Mount is run. However, it can be an Obey file containing the command "raFS:Mount <Obey$Dir> -X". The presence of the -X switch indicates to raFS that the disc should be mounted without searching for !Mount. (Be careful not to create a loop by forgetting to add the -X switch!) With this system, it is possible to execute *commands before and after the disc is mounted.

Dismount [<DiscName>]
This command does the opposite of Mount, removing the specified disc (or all mounted discs if you omit the name) from its internal list and saving any cached directory data. Discs must always be dismounted before you reset or switch off the computer, but usually you don't need to use Dismount because raFS is automatically called when the desktop shuts down and when you issue Shutdown.

Note that in case raFS is RMKilled, it will try to dismount all discs. However, any errors while doing this will be ignored, and the module will not refuse to die, which means you lose data! It behaves like this because if it refused to be RMKilled, you would not be able to reload it unless you reset the machine.

Before a disc is dismounted, raFS sets the system variable raFS$DDisc to its name, removes the Lock file and tries to run any file called !Dismount residing in the storage directory. If errors occur during its execution, they are ignored; the disc is always dismounted. You must not dismount raFS discs in a !Dismount file. When the module is RMKilled, the !Dismount files are not executed.

Verify [-quiet] <DiscName>|*
Performs a verify operation for the disc. Unless the -quiet switch is present, verifying is interactive, i.e. before altering the disc in any way, the user is prompted.

Specifying * instead of the disc name does not verify all discs - rather, it verifies those discs that need verifying, either because they weren't dismounted properly or because a file could not be accessed due to inconsistencies.

NameDisc <OldDiscName> <NewDiscName>
This command (or also NameDisk) is used to change the name of a disc. Obviously, the disc must have been mounted for it to work.
The Free command is just passed on to the host filing system that the currently selected raFS directory is stored on, e.g. if the disc is on ADFS, ADFS:Free will be executed.
raFS_Unsafe [-verbose]
By default, raFS only saves changed directory data to the host filing system after a delay. Usually, this is desirable because it is faster, but sometimes you may want to temporarily switch on write-through of the cache, so any changes are saved immediately. Instead of raFS_Opt -dd 1, you can also switch on write-through with this command.

The -verbose switch has the same functionality as for raFS_Safe below.

raFS_Safe [-smash] [-verbose]
This does the opposite of raFS_Unsafe, re-enabling the chosen delay values for saving directory cache contents. Note that an internal counter is kept, which means that in order to disable write-through after issuing raFS_Unsafe twice, you would also have to execute raFS_Safe twice. (After that, any additional raFS_Safe will have no effect.) If the number of raFS_Unsafe commands is unknown, you can use raFS_Safe -smash to disable write-through immediately.

A -verbose switch makes raFS print out the value of the internal counter after it has been modified.

raFS_Unsafe and raFS_Safe can be added to a Wimp application's !Run file if the application tends to crash the computer, in such a way that write-through is disabled once the application is quit:

other commands, e.g. WimpSlot, IconSprites etc.
Run <App$Dir>.!RunImage %*0

raFS_Opt [-DirCache <kB>] [-DirsaveDelay <cs>] [-DirsaveMods <nr>] [-DirUpcall 0|1] [-OpenRename 0|1] [-MsgTimeout <cs>] [-LoadMessages <name>]
This command is used to influence various miscellaneous aspects of raFS' behaviour, or to output the current settings if no parameters are given. Each of the optional keywords is followed by a value, in some cases just 0 or 1 to switch on and off. The keywords can be abbreviated to the characters written in uppercase, e.g. -dc instead of -DirCache. However, case doesn't matter on the command line; -dircache or -dC are the same as -DirCache.

Currently, the following keywords have an effect:

  • -DirCache <kBytes> selects the amount of memory that will be used for cacheing directory information. There is one directory cache for all discs. You can switch directory cacheing off completely by specifying -DirCache 0, but this makes raFS very slow. The recommended minimum for the cache size is 16k - when the filing system module is loaded, the value defaults to 30k.
  • -DirsaveDelay <centiseconds> sets the delay between the last change to a directory and the moment it is saved to the host filing system. Supplying a value of 0 causes no automatic saving whereas a value of 1 makes raFS save immediately after each change. The default value is 500 - five seconds.

    If both this and -DirsaveMods below are enabled at the same time, the directory will be saved when the delay or the number of changes is reached, whichever comes first.

  • -DirsaveMods <number> allows you to specify the number of changes allowed to be made to a buffered directory before it must be saved to the host filing system. For instance, if you want to have the directory saved after every 5 files written/deleted/renamed, use -DirsaveMods 5. Again, supplying a value of 0 switches the counting off and a value of 1 forces immediate write-through. The maximum for this value is 255, the default is 10.

    When the number of changes is counted, stamping of files, changing their access details or closing open files is not taken into account. This is necessary to ensure a Filer copy operation only increases the count by 1.

  • -DirUpcall followed by 0 or 1 disables or enables whether raFS will cause directory displays to be updated immediately when the size of a directory changes. (Unlike with other filing systems, the directory size is not fixed and when it changes, this will be reflected.) By default, this is switched off because it causes a lot of flickering when the Filer continually updates its displays. Even when the Upcalls are switched off, the directory size is updated eventually when you re-open the parent of that directory or write to it.

    By the way: Have you noticed that RiscOS does not have an Upcall for informing that an object's size has changed? I'm using OS_Upcall 3,1 (Writing catalogue information), but even this excludes the size.

  • -OpenRename followed by 0 or 1 disables or enables whether it is possible to rename an open file. The default value is 1.
  • If a disc has not been dismounted properly and the desktop is active, raFS opens an error box. To prevent this from stopping the boot process, the error box is closed automatically after, by default, five seconds. -MsgTimeout can be used to specify a different delay in centiseconds.
  • -LoadMessages followed by the name of a Messages file is special in that it doesn't set internal variables. Instead, this is used to override the hard-coded English defaults used for error messages, help texts and the !Mount/!Run files.

    You can use -LoadMessages null: to discard the messages and revert to the default ones.

raFS_ExecAfter <centiseconds> <command line>
This command has little to do with raFS. It simply passes the specified command line to the CLI after the given delay. Due to the way this is achieved, only few commands can be used. Filer_Run is the only way to start a program using this command (if at least one disc is always mounted, you can also use raFSFiler_Menu -first).

Back to the top of the page

Calling raFS from assembler

As of version 1.10, there is a way of calling certain routines inside the raFS module directly from assembler. raFSFiler uses these calls to get information about discs and current settings.

To call an raFS routine, you must first find out the address of the module workspace with:

    SYS "XOS_Module",18,"raFS" TO R0%,R1%,R2%,R3%,workspace%

Move the returned value into R11 before calling raFS with the following instructions:

    LDR PC,[R11,#rout_offset%]

If you use MOV LR,PC (and not ADD LR,PC,#0) before calling the routine, the N, Z and C flags will be preserved. When calling raFS from SVC code, you must use MOV, otherwise the processor will switch to USR mode once the call returns.

The rout_offset% is zero for the routine described first below, and increases in the order the routines are described. The Docs directory contains a small BASIC program which sets up the offsets with a horrible EVAL trick and which also provides a macro for the BASIC assembler so the above can be reduced to, e.g. FNcall(raFS_Info).

Registers not mentioned in "On exit" are preserved. (Of course, R14 is corrupted.) For all calls, R11 must point to the workspace of the raFS module. Processor must be in USR or SVC mode, R13 must point to a full descending stack with at least 1k free.

In the following description, any bits in fields that are not described are reserved. It should not be assumed that they are zero, and when setting the word's value, they must be preserved.

On entry:

On exit:
R0 = module version number * 100
R1 = maximum number of discs this version can have mounted
R2 = bit 0 set => module's heap is in sprite area, bits 24-31 = country number (1 for UK, 7 for Germany / as of V1.12, is always 1)
R3-R5 corrupted

Never returns an error.

On entry:

On exit:
R0 = number of discs currently mounted

Never returns an error.

On entry:
R9 = -1 for first call

On exit:
R0 = word-aligned pointer to zero-terminated disc name
R1 = word-aligned pointer to unterminated name of storage directory
R2 = length of name of storage directory
R9 = disc number (also value of R9 for next call to this routine) or -1 and C set if no more discs

Never returns an error. The information must be copied away immediately; it may change during any call to raFS (except raFS_MemCopy) or accesses to the filing system.

After the disc name there are 1 to 4 zero bytes, up to the next word boundary, so you can find the length faster by first loading words and only looking at the high byte with TST Rx,#&FF<<24

On entry:
R1 => zero-terminated disc name

On exit:
R0 = word-aligned pointer to zero-terminated disc name
R1 = word-aligned pointer to unterminated name of storage directory
R2 = length of name of storage directory
R8 = internal ID of the disc's root directory
R9 = disc number
R14 = length of disc name

If a disc of the given name is not mounted, an error is returned. Again, the returned pointers to the disc name (whose case may differ from that passed to the routine) and storage directory are read-only and must be copied away immediately.

On entry:
R9 = disc number

On exit:
R0 = word-aligned pointer to zero-terminated disc name
R1 = word-aligned pointer to unterminated name of storage directory
R2 = length of name of storage directory
R3 = flags:
    bit 0 set => the disc is read-only
    bit 1 set => integrity checks are performed (raFS$NoChecks)
R8 = internal ID of the disc's root directory
or C set if disc of that number not mounted

If the given disc number is in the valid range (zero to maximum number - 1) and a disc of that number does not exist, this returns with C set. Obviously, this call is much faster than raFS_FindDisc because it doesn't have to search for the disc name.

On entry:
R2 => source (word-aligned)
R3 => destination (word-aligned)
R4 = number of bytes to copy (multiple of 4)

On exit:
Registers preserved

The memory areas may overlap.

On entry:
R0 = number of variable to read

On exit:
R0 = value / pointer to string (depending on variable type)
R1 corrupted

Currently, the following variables are supported:

  • 0 => DirCache (kBytes) - is internally stored as bytes, so don't set to a value higher than &3fffff
  • 1 => DirsaveDelay (centiseconds)
  • 2 => DirsaveMods (nr)
  • 3 => Misc flags:
        Bit 0 set => DirUpcall happens
  • 4 => MsgTimeout (nr)
On entry:
R0 = number of variable to set value of
R1 = new value

On exit:
R0, R1 corrupted

R0 on entry contains the same values as for raFS_ReadVar

Back to the top of the page

File formats

This section outlines the format of a raFS disc. In the following description, an ID word is of the form &00zzyyxx where xx is the first level directory, yy the second, and zz the leaf name, e.g. &00010203 is the file 'B0.A2.A1'. The root directory is always 'A0.A0.A0'.

The !Atterer file

Size Description
64   disc name, null terminated, padded with zeroes
4    there is guaranteed no unused ID lower than this one
4    attribute flags for root directory (0 at present)
4    0 (unimplemented)
4    o = number of buffer settings following (always 0 at present)
??*o buffer settings

Directory format

Size Description
4    n = nr of entries
4    m = 0 (unimplemented)
4    ID of parent (max. - word contains -1 for root
4    &80000000 (unimplemented)
4*n  offset to start of directory entries
     (words must be sorted in ascending order, filenames in ASCII order,
     offsets are relative to start of these offsets)
4*m  if any, offset to... (unimplemented)
4    offset to first unused byte after dir entries/dir names (also from
     beginning of offsets, so that if there are no entries, this contains the
     value 4)

This is followed by the individual entries, if any:

4    load address
4    exec address
4    length (or FileSwitch handle if flag bit 12 set)
4    attributes
4    raFS attributes/flags:
     bits 0-1: 0 (unimplemented)
          2-3: 0 (unimplemented)
          4-5: 0 (unimplemented)
          6-7: 0=normal file, 1/2 unimplemented, 3=directory
          12:  if set, file is open => 'length' contains FileSwitch handle
4    0 (unimplemented)
4    ID of file/directory
4*?  name of file/directory, zero-terminated, padded with zeroes to the next
     multiple of 4.
4*?  (unimplemented, always null at present)

If an entry with bit 12 set is encountered upon loading directory data, raFS checks whether its own list of files contains that file ID together with the FileSwitch handle found in the directory entry. If there is no such entry in the list of open files, it is assumed that the machine crashed and the length is restored.