LongFiles internals
This is based on code inspection, rather than anything more tangible! I did write this in the last century - October 1999 is the date stamp of some of the files...
!LongFiles intercepts various Operating System calls, detecting when an application is querying the list of files, opening and closing file streams, and loading and saving whole files. It uses a method to map a 10-character filename to a longer filename, identifying if a file exists (when overwriting), or it is something new.
To maintain the map of 10-character filenames to long filenames, it hides a file called !ZZ!!Z!!LF (called the "zzfile" in the code), which is a name that I chose which I hoped no-one else would create a file of that name.
A filename that is stored on the file system that has a long file name must fit a particular pattern in order for the map code to work:
- The filename must be 10 characters long
- The 7th character must be a specific character (this depends on the file system)
- The 8th, 9th and 10th characters indicates an ID value
If any of these criteria do not match, then the filename is returned unmodified; otherwise it is converted into the long version of the filename.
When creating a new filename into the map, then the following criteria must be met:
- The filename must be longer than 10 characters long
If this criteria does not match, then it will use the filename itself. Otherwise, it will allocate a new filename based on:
- The first 6 characters of the long filename
- The specific character for the filesystem
- An ID value that is allocated based on available 'slots' in the "zzfile" file
The ID value is simply a hex value, allowing up to 4095 long files in a directory (let's ignore the 77 files per directory limit! I did start writing something which allowed more than 77 files per directory, but it was unstable and I didn't release it). ID 0 is reserved.
The special character is "}" for FileCore systems, but can be "/" for CD-ROMs (allowing long files on CD-ROMs; in this case, the "zzfile" is "LONG__FS").
Mapping short names to long names
When looking at the map to get the long filename, !LongFiles reads the "zzfile" file, and scans it. This is an array of data, combining IDs, the length of the long filename, and the long versions of the filename. Each long filename stored in this file is an 'entry' in the map.
The code calculates the file's ID (based on the 8th to 10th character), and then scans the file:
- Read the two bytes at the current position (starting with the beginning of the file)
- This gives this map's ID as a 16-bit value, with the first byte being the low byte, and the second byte being the high byte
- If the map's ID is zero, then all files have been scanned, and the ID cannot be found
- If the ID matches
- The next byte is the length of the long filename
- Replace the existing filename with the long filename
- Note that the whole filename is stored in the zzfile, rather than the 7th character onwards. This allows CD-ROM files to be mixed case.
- If the ID doesn't match
- Skip the number of bytes indicated by the length of the filename
Mapping long names to short names
Checking to see if an existing long filename exists is a similar process - if the filename is greater than 10 characters, then it will look through the entries, and if one exists, it can convert it into the short version of the filename.
Creating a new entry
If a new entry needs to be created, then the first unused ID will be allocated, and the filename converted using the first 6 characters of the long filename, followed by the special character, and then the hex version of the ID.
Deleting a file
If an file is deleted, then it is checked to see if it is a long filename; if it is, then the map is searched for the ID, and it will shuffle down any entries. IDs are not renumbered for performance reasons. When this succeeds, !LongFiles deletes the file from the file system.
Renaming a file
Renaming a file requires a number of checks - converting the original file into the short-version of the names, and converting the new file into the short-version where it can. If the new name is a short name, then it will remove it from the map, and simply rename the file to the given filename; if it is a long file, then it can either reuse the ID, or allocate a new ID.
Directory structures
!LongFiles will do this for all parts of the path, iterating over each one to see if it's a long filename or not. So if you have a directory that is 6 levels deep, then it may scan 6 zzfiles to get the actual filename"
RISC OS filename length limit
!LongFiles can't change the way applications deal with filenames and their maximum length, so if a user nests files too deep, then applications may crash as a result. Unfortunately, there isn't much !LongFiles can do about that!
