Difference between revisions of "OSFILE"
m (Updated notes on DFS.) |
|||
(55 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:MOS_API]] | [[Category:MOS_API]] | ||
− | + | {{PageTitle|OSFILE: File and directory information}} | |
− | OSFILE: File and directory information | ||
− | |||
__TOC__ | __TOC__ | ||
==Specification== | ==Specification== | ||
{| cellpadding="0" cellspacing="0" border="1" | {| cellpadding="0" cellspacing="0" border="1" | ||
− | | 6502 || Z80 || 6809 || PDP11 || 80x86 || 32016 || ARM || align="left" valign="top" | '''On entry:''' || align="left" valign="top" | '''On exit:''' | + | | 6502 || Z80 || 6809 || PDP11 || 80x86 || 32016 || ARM || 68000 || RISC-V || align="left" valign="top" | '''On entry:''' || align="left" valign="top" | '''On exit:''' |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | A || A || A || R0 || AL || R1 || R0 || align="left" valign="top" | = function code || align="left" valign="top" | object type or preserved if function unsupported | + | | A || A || A || R0 || AL || R1 || R0 || D0 || A0 || align="left" valign="top" | = function code || align="left" valign="top" | object type or preserved if function unsupported |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | | + | | YX || HL || X || R1 || BX || || || || || align="left" | =>control block || align="left" valign="top" | undefined, control block updated |
|- | |- | ||
− | | colspan=" | + | | colspan="5" align="center" valign="top" | '''Control block''' || || || || || || |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | colspan=" | + | | colspan="5" | &00 || R2 || R1 || D1 || A1 || align="left" valign="top" | =>filename || align="left" valign="top" | undefined |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | colspan=" | + | | colspan="5" | &02 || R3 || R2 || D2 || A2 || align="left" | Load address || align="left" | Load address |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | colspan=" | + | | colspan="5" | &06 || R4 || R3 || D3 || A3 || align="left" | Execution address || align="left" | Execution address |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | colspan=" | + | | colspan="5" | &0A || R5 || R4 || D4 || A4 || align="left" | Start address || align="left" | Length |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | colspan=" | + | | colspan="5" | &0E || R6 || R5 || D5 || A5 || align="left" | End address or Attributes || align="left" | Attributes |
|- align="center" valign="top" | |- align="center" valign="top" | ||
− | | colspan=" | + | | colspan="5" | &12 || || || || || || |
|} | |} | ||
− | + | <p> | |
− | {| cellpadding="0" cellspacing="0" | + | {| cellpadding="0" cellspacing="0" border="0" |
− | | colspan=" | + | | colspan="4" | <font size="+0">'''Function summary''' </font> |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- valign="top" | |- valign="top" | ||
− | | | + | | colspan="2" | '''Extensions''' || colspan="4" | '''Core functions''' |
|- valign="top" | |- valign="top" | ||
− | | &04 || Write | + | | &FA || || &FF || Load file || &04 || Write attributes |
|- valign="top" | |- valign="top" | ||
− | | &05 || Read | + | | &FB || || &00 || Save file || &05 || Read information |
|- valign="top" | |- valign="top" | ||
− | | &06 || Delete object | + | | &FC || Write system information || &01 || Write information || &06 || Delete object |
|- valign="top" | |- valign="top" | ||
− | | &07 || Create | + | | &FD || Read system information || &02 || Write load address || &07 || Create file |
|- valign="top" | |- valign="top" | ||
− | | &08 || Create | + | | &FE || Verify file || &03 || Write exec address || &08 || Create directory |
|} | |} | ||
− | {| cellpadding="0" cellspacing="0" | + | On the return from all calls if the object exists the control block is |
− | | colspan=" | + | updated with the information of the object referenced and A holds the |
+ | object type. LOAD is the only call that generates an error if the object | ||
+ | is not found, in all other cases the call returns with A=0. | ||
+ | |||
+ | {| cellpadding="0" cellspacing="0" border="0" | ||
+ | | colspan="4" | <font size="+0">'''Object types returned in A are:''' </font> | ||
+ | |- valign="top" | ||
+ | | &00 || Object not found || &03 || Image file found (file accessible as a directory) | ||
+ | |- valign="top" | ||
+ | | &01 || File found || &04 || Unresolved symbolic link found | ||
|- | |- | ||
− | | | + | | &02 || Directory found || &FF || Execute-only file (rarely implemented) |
|- | |- | ||
− | | | + | | colspan="4" | The returned object type is also a bitmap: |
|- | |- | ||
− | | valign="top" | | + | | valign="top" | bit 0:|| file |
|- | |- | ||
− | | valign="top" | | + | | valign="top" | bit 1:|| directory |
|- | |- | ||
− | | valign="top" | | + | | valign="top" | bit 2:|| symbolic link |
− | |||
− | |||
|} | |} | ||
− | Note: The Tube protocol masks off bit 7 of the return value from OSFILE, so A=&FF is returned as A=&7F. | + | Note: The Tube protocol masks off bit 7 of the return value from OSFILE, so |
+ | A=&FF is returned as A=&7F. | ||
+ | |||
+ | The object attributes holds the object's access information and the object's | ||
+ | modification date. | ||
{| cellpadding="0" cellspacing="0" | {| cellpadding="0" cellspacing="0" | ||
− | | colspan="5" | ''' | + | | colspan="5" | <font size="+0">'''Object attributes:'''</font> |
|- valign="top" | |- valign="top" | ||
− | | Byte &0E || bit 7 || Private || bit 3 || Locked | + | | Byte &0E || bit 7 || Private || bit 3 || Locked |
|- valign="top" | |- valign="top" | ||
| || bit 6 || Executable by others || bit 2 || Executable by owner | | || bit 6 || Executable by others || bit 2 || Executable by owner | ||
Line 86: | Line 81: | ||
| || bit 4 || Readable by others || bit 0 || Readable by owner | | || bit 4 || Readable by others || bit 0 || Readable by owner | ||
|- valign="top" | |- valign="top" | ||
− | | Byte &0F || bits 0 | + | | Byte &0F || bits 0‑4 || Date: day of month || bits 5‑7 || Date: year since 1981, bits 4-6 |
|- valign="top" | |- valign="top" | ||
| Byte &10 || bits 0-3 || Date: month of year || bits 4-7 || Date: year since 1981, bits 0-3 | | Byte &10 || bits 0-3 || Date: month of year || bits 4-7 || Date: year since 1981, bits 0-3 | ||
Line 94: | Line 89: | ||
Note that lots and lots of documentation incorrectly describe the access | Note that lots and lots of documentation incorrectly describe the access | ||
− | + | bits as being ''not'' readable, etc. This is further propagated by DFS using | |
a restricted and mangled access byte. Each bit being ''not'' readable, etc., | a restricted and mangled access byte. Each bit being ''not'' readable, etc., | ||
is '''incorrect'''. Each bit is set if the corresponding access permission | is '''incorrect'''. Each bit is set if the corresponding access permission | ||
Line 100: | Line 95: | ||
The normal access of WR/WR is an access byte of &33. See also [[File access]]. | The normal access of WR/WR is an access byte of &33. See also [[File access]]. | ||
+ | |||
+ | ==Functions== | ||
+ | {| cellpadding="0" cellspacing="0" | ||
+ | | colspan="2" | '''Functions''' | ||
+ | |- valign="top" | ||
+ | | &FC || Write file system information. | ||
+ | |- valign="top" | ||
+ | | &FD || Read file system information (System Internal Name). The attributes field is returned holding the sector start address. | ||
+ | |- valign="top" | ||
+ | | &FE || Verify file. Control block is as for A=&FF, Load. If the verification is successful, A is returned holding &01 and the control block holds the file information. If the verification fails, A is returned holding &00 and the load address is returned holding the address where the verification failed. If the file does not exist or is a directory or does not have read access, then an error is generated. | ||
+ | |- valign="top" | ||
+ | | &FF || Load a file into memory. If the low byte of the execution address is zero the file is loaded to the supplied load address, otherwise the file is loaded to the file's own load address. If the filename does not exist, or is a directory, or an execute-only file, or does not have read access, then an error is generated. | ||
+ | |- valign="top" | ||
+ | | &00 || Save a file. If a file already exists with the same name, it is overwritten, with the file access staying the same. If the file is locked, or a directory exists with the same name, then an error is generated. | ||
+ | |- valign="top" | ||
+ | | &01 || Write a object's reload address, execution address and attributes. | ||
+ | |- valign="top" | ||
+ | | &02 || Write a object's reload address. | ||
+ | |- valign="top" | ||
+ | | &03 || Write a object's execution address. | ||
+ | |- valign="top" | ||
+ | | &04 || Write a object's attributes. | ||
+ | |- valign="top" | ||
+ | | &05 || Read object's catalogue information into the control block. | ||
+ | |- valign="top" | ||
+ | | &06 || Delete object. If the object does not exist, A returned as &00. If the object is locked, or is not owned, or is a directory that is not empty, or is open, then an error is generated. | ||
+ | |- valign="top" | ||
+ | | &07 || Create an empty file of defined length. Block as for SAVE. The supplied start address is usually passed as &0 and the end address as the required length. No data is transfered, and the file does not necessarily contain zeros. Some file systems may deliberately overwrite any existing data in the file. If a file already exists with the same name, it is overwritten, with the file access and the case of the name staying the same. If the file is locked, or a directory exists with the same name, or the file is open, then an error is generated. | ||
+ | |- valign="top" | ||
+ | | &08 || Create a directory. The length field is passed holding a suggested minimum number of entries required, or zero for a default number. If a directory already exists, there is no error. The created directory is locked. If a file already exists, an error is generated. | ||
+ | |} | ||
==Calling from BBC BASIC== | ==Calling from BBC BASIC== | ||
Line 115: | Line 141: | ||
* PDP-11 Entry Address: EMT 7, vector &07 | * PDP-11 Entry Address: EMT 7, vector &07 | ||
* ARM Entry Address: SWI &08 "OS_File", vector &08 | * ARM Entry Address: SWI &08 "OS_File", vector &08 | ||
+ | * 68000 Entry Address: MOV #&08,A0:TRAP 12 | ||
+ | * RISC-V Entry address: ECALL &AC0007 | ||
==Implementations== | ==Implementations== | ||
+ | Some implementations generate an error if an object does not exist instead | ||
+ | of the correct action of returning object=&00. LOAD and VERIFY are the only | ||
+ | functions that should generate an error if the file is not found. | ||
+ | |||
+ | Some implementations generate an error when writing load or execution | ||
+ | addresses to directories. The correct action is to not generate an error; | ||
+ | either actually write the information, or - if not possible - just return. | ||
+ | |||
+ | Some implementations generate an error when creating a directory if a | ||
+ | directory already exists. The correct action is to just return, "create | ||
+ | directory" is functionally "ensure the specified directory exists". | ||
+ | |||
+ | Some implementations return the wrong return values. All functions should | ||
+ | return the relevent object type, regardless of the call. | ||
+ | |||
===CFS=== | ===CFS=== | ||
CFS implements functions &00 (Save) and &FF (Load), and returns with any | CFS implements functions &00 (Save) and &FF (Load), and returns with any | ||
Line 134: | Line 177: | ||
bits 1 or 3 of byte &0E are set (ie Locked or Writable). See also [[File access]]. | bits 1 or 3 of byte &0E are set (ie Locked or Writable). See also [[File access]]. | ||
− | Some clones of Acorn DFS | + | Some versions of DFS do not return the control block correctly updated |
− | file is found. | + | when writing file metadata. Some clones of Acorn DFS never return A=0, |
+ | causing an error instead if no file is found. | ||
===ADFS=== | ===ADFS=== | ||
+ | ADFS implements &FF to &08. | ||
+ | |||
When called with an unsupported action some versions of ADFS return A | When called with an unsupported action some versions of ADFS return A | ||
preserved, some versions return A corrupted. | preserved, some versions return A corrupted. | ||
Line 149: | Line 195: | ||
HDFS also inverts the [[File access]] byte. | HDFS also inverts the [[File access]] byte. | ||
− | |||
− | |||
− | |||
===HADFS=== | ===HADFS=== | ||
Line 161: | Line 204: | ||
directory's load and execution addresses, but the action is ignored. | directory's load and execution addresses, but the action is ignored. | ||
+ | {{Filing}} | ||
[[User:Jgharston|Jgharston]] ([[User talk:Jgharston|talk]]) 22:30, 9 March 2015 (UTC) | [[User:Jgharston|Jgharston]] ([[User talk:Jgharston|talk]]) 22:30, 9 March 2015 (UTC) | ||
[[User:Jgharston|Jgharston]] ([[User talk:Jgharston|talk]]) 21:01, 15 January 2017 (UTC) | [[User:Jgharston|Jgharston]] ([[User talk:Jgharston|talk]]) 21:01, 15 January 2017 (UTC) |
Latest revision as of 18:44, 5 September 2024
Contents
Specification
6502 | Z80 | 6809 | PDP11 | 80x86 | 32016 | ARM | 68000 | RISC-V | On entry: | On exit: |
A | A | A | R0 | AL | R1 | R0 | D0 | A0 | = function code | object type or preserved if function unsupported |
YX | HL | X | R1 | BX | =>control block | undefined, control block updated | ||||
Control block | ||||||||||
&00 | R2 | R1 | D1 | A1 | =>filename | undefined | ||||
&02 | R3 | R2 | D2 | A2 | Load address | Load address | ||||
&06 | R4 | R3 | D3 | A3 | Execution address | Execution address | ||||
&0A | R5 | R4 | D4 | A4 | Start address | Length | ||||
&0E | R6 | R5 | D5 | A5 | End address or Attributes | Attributes | ||||
&12 |
Function summary | |||||
Extensions | Core functions | ||||
&FA | &FF | Load file | &04 | Write attributes | |
&FB | &00 | Save file | &05 | Read information | |
&FC | Write system information | &01 | Write information | &06 | Delete object |
&FD | Read system information | &02 | Write load address | &07 | Create file |
&FE | Verify file | &03 | Write exec address | &08 | Create directory |
On the return from all calls if the object exists the control block is updated with the information of the object referenced and A holds the object type. LOAD is the only call that generates an error if the object is not found, in all other cases the call returns with A=0.
Object types returned in A are: | |||
&00 | Object not found | &03 | Image file found (file accessible as a directory) |
&01 | File found | &04 | Unresolved symbolic link found |
&02 | Directory found | &FF | Execute-only file (rarely implemented) |
The returned object type is also a bitmap: | |||
bit 0: | file | ||
bit 1: | directory | ||
bit 2: | symbolic link |
Note: The Tube protocol masks off bit 7 of the return value from OSFILE, so A=&FF is returned as A=&7F.
The object attributes holds the object's access information and the object's modification date.
Object attributes: | ||||
Byte &0E | bit 7 | Private | bit 3 | Locked |
bit 6 | Executable by others | bit 2 | Executable by owner | |
bit 5 | Writable by others | bit 1 | Writable by owner | |
bit 4 | Readable by others | bit 0 | Readable by owner | |
Byte &0F | bits 0‑4 | Date: day of month | bits 5‑7 | Date: year since 1981, bits 4-6 |
Byte &10 | bits 0-3 | Date: month of year | bits 4-7 | Date: year since 1981, bits 0-3 |
Byte &11 | bits 0-7 | Undefined (returned as zero) |
Note that lots and lots of documentation incorrectly describe the access bits as being not readable, etc. This is further propagated by DFS using a restricted and mangled access byte. Each bit being not readable, etc., is incorrect. Each bit is set if the corresponding access permission is present.
The normal access of WR/WR is an access byte of &33. See also File access.
Functions
Functions | |
&FC | Write file system information. |
&FD | Read file system information (System Internal Name). The attributes field is returned holding the sector start address. |
&FE | Verify file. Control block is as for A=&FF, Load. If the verification is successful, A is returned holding &01 and the control block holds the file information. If the verification fails, A is returned holding &00 and the load address is returned holding the address where the verification failed. If the file does not exist or is a directory or does not have read access, then an error is generated. |
&FF | Load a file into memory. If the low byte of the execution address is zero the file is loaded to the supplied load address, otherwise the file is loaded to the file's own load address. If the filename does not exist, or is a directory, or an execute-only file, or does not have read access, then an error is generated. |
&00 | Save a file. If a file already exists with the same name, it is overwritten, with the file access staying the same. If the file is locked, or a directory exists with the same name, then an error is generated. |
&01 | Write a object's reload address, execution address and attributes. |
&02 | Write a object's reload address. |
&03 | Write a object's execution address. |
&04 | Write a object's attributes. |
&05 | Read object's catalogue information into the control block. |
&06 | Delete object. If the object does not exist, A returned as &00. If the object is locked, or is not owned, or is a directory that is not empty, or is open, then an error is generated. |
&07 | Create an empty file of defined length. Block as for SAVE. The supplied start address is usually passed as &0 and the end address as the required length. No data is transfered, and the file does not necessarily contain zeros. Some file systems may deliberately overwrite any existing data in the file. If a file already exists with the same name, it is overwritten, with the file access and the case of the name staying the same. If the file is locked, or a directory exists with the same name, or the file is open, then an error is generated. |
&08 | Create a directory. The length field is passed holding a suggested minimum number of entries required, or zero for a default number. If a directory already exists, there is no error. The created directory is locked. If a file already exists, an error is generated. |
Calling from BBC BASIC
-
LOAD fn$
calls OSFILE &FF -
CHAIN fn$
calls OSFILE &FF -
SAVE fn$
calls OSFILE &00
Entry points
- BBC BASIC Entry Address: &FFDD
- 6502 Entry Address: &FFDD, vectors via &0212
- Z80 Entry Address: &FFDD, vectors via &FFDE
- 6809 Entry Address: &FFDD, vectors via &FFDE
- 80x86 Entry Address: INT &45, vectors via &0000:0114
- 32000 Entry Address: SVC &0A
- PDP-11 Entry Address: EMT 7, vector &07
- ARM Entry Address: SWI &08 "OS_File", vector &08
- 68000 Entry Address: MOV #&08,A0:TRAP 12
- RISC-V Entry address: ECALL &AC0007
Implementations
Some implementations generate an error if an object does not exist instead of the correct action of returning object=&00. LOAD and VERIFY are the only functions that should generate an error if the file is not found.
Some implementations generate an error when writing load or execution addresses to directories. The correct action is to not generate an error; either actually write the information, or - if not possible - just return.
Some implementations generate an error when creating a directory if a directory already exists. The correct action is to just return, "create directory" is functionally "ensure the specified directory exists".
Some implementations return the wrong return values. All functions should return the relevent object type, regardless of the call.
CFS
CFS implements functions &00 (Save) and &FF (Load), and returns with any other value with A unchanged.
ROMFS
ROMFS gives an error for &00 (Save), implements &FF (Load), and returns with any other value with A unchanged.
DFS
Acorn DFS and contemporary filing systems implement functions &00 to &06 and &FF, and return with A unchanged if called with any other value.
As Acorn DFS and its clones allocate a single bit for attribute storage when reading the attributes the byte at &0E is returned as &08 if the file is Locked, and as &00 otherwise. When setting attributes the file is Locked if bits 1 or 3 of byte &0E are set (ie Locked or Writable). See also File access.
Some versions of DFS do not return the control block correctly updated when writing file metadata. Some clones of Acorn DFS never return A=0, causing an error instead if no file is found.
ADFS
ADFS implements &FF to &08.
When called with an unsupported action some versions of ADFS return A preserved, some versions return A corrupted.
HDFS
Andrew Duggan's Hierarchial DFS implements &FF to &06 and &08. It also implements functions &07 and &09, but with different parameters.
- A=7 Create an object, but with the control block set up as with OSFILE &05, not OSFILE &00.
- A=9 Changes the length of an existing file.
- A=10 Changes the attributes, load and execution addresses, and length of a file. This is like OSFILE 1, but the length is also changed.
HDFS also inverts the File access byte.
HADFS
HADFS implements &FC, &FD and &FF to &08.
NFS
Acorn file servers give an error if an attempt is made to write the load and execution address of a directory. MDFS servers allow writing of a directory's load and execution addresses, but the action is ignored.
Filing System Calls | |
---|---|
Jgharston (talk) 22:30, 9 March 2015 (UTC)
Jgharston (talk) 21:01, 15 January 2017 (UTC)