📄 filesys.doc
字号:
Copyright (c) 1991-1993 R.A. Burgess
MMURTL File System Service (MS-DOS FAT Compatible)
INTRODUCTION
The file system included with MMURTL is compatible with the MS-DOS FAT (File Allocation Table) file system. This means that MMURTL can read and write MS-DOS disks (Hard and Floppy). This was done so MMURTL could be used without reformatting your hard disks or working from floppies. It certainly wasn't done because we liked the design or the filename length limitations. MS-DOS has the unenviable task of being compatible with its previous versions. This ties its hands so to speak. There are better file systems (disk formats) in use, but none as wide spread.
The internal management of a file system is no trivial matter. Because we are simply accessing one that was designed by someone else, there isn't anything new about the format, just how we access it. We have tried to keep with the simplicity motto, and limited the number of functions down to what is necessary for decent operation. The Service Name is FILESYS.
FILE SPECIFICATIONS
A filename consists of 1 to 8 characters, a period, then 0 to 3 more characters. Example:
filename.txt
A full file specification for the FAT compatible file system consist of a Disk letter identifier followed by a colon, then the path (each directory separated by the back-slash character, and finally the filename itself. Example:
C:\Dir1\Dir2\Dir3\Filename.txt
FILE HANDLES
When a file is opened (any mode or type), a number is returned to you called a file handle. Make no assumptions about this number. The filehandle is used in a all subsequent file operations on that file (this is how you refer to that file until closed). A file handle is a 32 bit unsigned number (DWord).
FILE OPEN MODE (MODIFY or READ)
A file may be opened for reading and writing, or just reading alone. These two modes are called MODIFY (Read and Write) and READ (Readonly).
Only a single user may open a file in MODIFY mode. This user is granted exclusive access to the file while it is open.
Multiple users may open and access a READ mode file. When a file is opened in READ mode, it may not be opened in MODIFY mode.
FILE ACCESS TYPE (Block or Stream)
A file may be opened in Block or Stream mode.
Block mode operation is the fastest file access method because no internal buffering is required. The data is moved in whole blocks in the fastest means determined by hte device driver. No internal file buffers are allocated by the filesystem in block mode. The only restriction is that whole blocks must be read or written. The standard block size is 512 bytes for disk devices. Block mode operation allows use of the following file system functions:
ReadBlock ()
WriteBlock()
CloseFile()
GetFileSize()
SetFileSize()
DeleteFile()
In Stream mode, the file system allocates an internal buffer to use for all read and write operations. This is a one page (4096 byte buffer). Stream mode operation allows use of the following file system functions:
CloseFile()
ReadBytes()
WriteBytes()
SetFileLFA()
GetFileLFA()
GetFileSize()
SetFileSize()
DeleteFile()
Errors will be returned from any function not compatible with the file access type you specified when the file was opened.
LOGICAL FILE ADDRESS
All files are logically stored as 1 to n Bytes. The LFA is an unsigned DWord (dLFA). This is the byte offset in the file to read or write from. LFA 0 is the beginning of the file. The filesize - 1 is the last logical byte in the file.
Block Access file system functions require to you specify a Logical File Address (LFA). Block access files have no internal buffers and do not maintain a "Current LFA" (file pointer).
Stream Access files have internal buffers and maintain your "Current LFA" (called a file pointer in some systems). This means for Stream files you do not specifiy an LFA to read or write from. The current LFA for stream files is updated with each ReadBytes and WriteBytes function. Additional functions are provided to allow you to find and set the current LFA. When a file is initially open for Stream access the file pointer is set to 0 (no matter what Mode).
FILE SYSTEM REQUESTS
The MMURTL FAT file system is a message based system service. This means it is accessed directly with the Request primitive. The procedural interface for Request has 12 parameters. If you studied MMURTL's architecture, you know that a file system is an ideal candidate for a message based service. It meets all the requirements. The small amount of time for message routing will not make any measurable difference in the speed of it's operation because most of the time is spent accessing hardware. It also provides the shared access required for for a true multitasking system. The file system actually runs as a separate task in MMURTL. Here is an example of a File System request in the C programming language (Openfile) :
erc = Request(
"FILESYS ", /* ptr to name of service */
1, /* wSvcCode -- 1 for OpenFile */
MyExch, /* dRespExch -- respond here */
&MyRqhandle, /* pRqHndlRet -- may be needed */
1, /* nSendPtrs -- 1 Send ptr */
&"AnyFile.doc", /* pData1 -- ptr to name */
11, /* cbData1 -- size of name */
&FileHandle /* pData2 -- returned handle */
4, /* cbData2 -- Size of a handle */
1, /* dData0 -- ModeRead */
0, /* dData1 -- Block Type Access */
0); /* dData2 -- not used */
NOTE: Unused Request parameters MUST be set to 0.
All message based services use the same request based interface. Using the Request interface allows for asynchronous program operation. You can make a request, then go do something else before you come back to wait or check the function to see if it's completed (true multitasking). Each of the functions is identifed by its Service Code number. The file system supports the following functions (service codes):
Function Service Code
OpenFile 1
CloseFile 2
ReadBlock 3
WriteBlock 4
ReadBytes 5
WriteBytes 6
GetFileLFA 7
SetFileLFA 8
GetFileSize 9
SetFileSize 10
CreateFile 11
RenameFile 12
DeleteFile 13
CreateDirectory 14
DeleteDirectory 15
GetDirectorySector 16
PROCEDURAL INTERFACES
If you don't have a need for asynchronous disk access, you can use a blocking procedural interface which is included in the filesystem itself. The procedural interface actually makes the request for you using your TSS Exchange (it's transparent). It is easier to use (has less parameters). This means there is a simple procedural interface call for each file system function. The blocking procedural interface is described with each of the call descriptions that follow.
DEVICE ACCESS THROUGH THE FILE SYSTEM
TTY stream access to the NUL, VID and KBD devices may be accessed through the file system, but ONLY through the procedural interfaces. The Request interface will not allow device access. High level language libraries that implement device access (such as "putchar" in C) must use the procedural interfaces for file access.
All system device names are reserved and should not be used as filenames on the system. These include:
NUL NULL device (Write Only)
KBD Keyboard (ReadOnly)
VID Video (WriteOnly)
LPT1 Printer 1
LPT2 Printer 2
COM1 RS-232 1
COM2 RS-232 2
COM3 RS-232 3
COM4 RS-232 4
FD0 Floppy Disk
FD1 Floppy Disk
HD0 Hard disk
HD1 Hard disk
Device access is currently implemented for NUL, KBD and VID device only.
File System Functions in Detail
The following pages detail each of the file system functions that are available.
-------------------------------
OpenFile
Procedural Interface:
OpenFile (pName, dcbname, dOpenMode,
dAccessType, pdHandleRet): dError
Desc: OpenFile opens an existing file in the current path for Block or Stream operations. A full file specification may be provided to override the current job path.
Opening in ModeModify excludes all others from opening the file. Multiple users can open a file in ModeRead. If a file is open in ModeRead, it can not be opened in ModeModify by any other users.
Params:
pName - pointer to the filename or full file specification.
dcbName - DWord with length of the filename
dOpenMode - READ = 0, MODIFY = 1
dAccessType - Block = 0, Stream = 1.
pdHandleRet - pointer to a DWord where the handle to the file will be returned to you.
Request Parameters for OpenFile:
wSvcCode = 1
nSend = 1
pData1 = pName
cbData1 = dcbName
pData2 = pdHandleRet
cbData2 = 4 (Size of a file handle)
dData0 = dOpenMode
dData1 = dAccessType
dData2 = Not used (0)
-------------------------------
CloseFile
Procedural Interface:
CloseFile (dHandle): dError
Desc: CloseFile closes a file that was previously opened. If stream acces type was specified, all buffers are flushed and deleted.
Params:
dHandle - a DWord that was returned from OpenFile.
Request Parameters for CloseFile:
wSvcCode = 2
nSend = 0
pData1 = 0
cbData1 = 0
pData2 = 0
cbData2 = 0
dData0 = dHandle
dData1 = 0
dData2 = 0
-------------------------------
ReadBlock
Procedural Interface:
ReadBlock(dHandle, pDataRet, nBytes,
dLFA, pdnBytesRet): dError
Desc: This reads one or more blocks from a file. The file must be opened for Block access or an error occurs.
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile.
pDataRet - Pointer to a buffer large enough to hold the count of blocks you specify to read.
nBytes - DWord with number of bytes to read. This MUST be a multiple of the block size for the disk (512 bytes).
dLFA - Logical File Address to read from. This MUST be a multiple of the block size.
pdnBlkRet - pointer to a DWord where the count of bytes succesfully read will be returned. This will alwyas be a multiple of the block size (n * 512).
Request Parameters for ReadBlock:
wSvcCode = 3
nSend = 0
pData1 = pDataRet
cbData1 = nBytes (multiple of 512)
pData2 = pdnBytesRet
cbData2 = 4 (size of dnBytesRet)
dData0 = dHandle
dData1 = 0
dData2 = 0
-------------------------------
WriteBlock
Procedural Interface:
WriteBlock(dHandle, pData, nBytes,
dLFA, pdnBytesRet): dError
Desc: This writes one or more blocks to a file. The file must be opened for Block access in MODIFY mode or an error occurs. Writing beyond the current file length is NOT allowed. SetFileSize must be used to extend the file length if you intend to write beyond the current filesize (See SetFileLength).
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile.
pData - Pointer to the data to write
nBytes - DWord with number of bytes to write. This must always be a multiple of 512. One Block = 512 bytes.
dLFA - Logical File Address to write to. This MUST be a multiple of the block size.
pdnBytesRet - pointer to a DWord where the number of bytes succesfully written will be returned. This will always return a multiple of 512.
Request Parameters for ReadBlock:
wSvcCode = 4
nSend = 1
pData1 = pData
cbData1 = nBytes (512 = 1 Block)
pData2 = pdnBytesRet
cbData2 = 4 (size of dnBytesRet)
dData0 = dHandle
dData1 = 0
dData2 = 0
-------------------------------
ReadBytes
Procedural Interface:
ReadBytes(dHandle, pDataRet, nBytes,
pdnBytesRet): dError
Desc: This reads one or bytes from a file. The file must be opened for Stream access or an error occurs. The bytes are read from the current LFA. The LFA is updated to the next byte address following the data you read. Use SetFileLFA to move the stream file pointer if you want to read from an LFA other than the current LFA. GetFileLFA may be used to find the current LFA.
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile).
pDataRet - Pointer to a buffer large enough to hold the count of bytes you specify to read.
nBytes - DWord with number of bytes to read.
pdnBytesRet - pointer to a DWord where the number of bytes succesfully read will be returned.
Request Parameters for ReadBytes:
wSvcCode = 5
nSend = 0
pData1 = pDataRet
cbData1 = nBytes
pData2 = pdnBytesRet
cbData2 = 4 (size of dnBytesRet)
dData0 = dHandle
dData1 = 0
dData2 = 0
-------------------------------
WriteBytes
Procedural Interface:
WriteBytes(dHandle, pData, nBytes,
pdnBytesRet): dError
Desc: This writes one or bytes from a file. The file must be opened for Stream access in MODIFY mode or an error occurs. The bytes are written begining at the current LFA. The LFA is updated to the next byte address following the data you wrote. The file length is extended automatically if you write past the current End Of File. Use SetFileLFA to move the stream file pointer if you want to read from an LFA other than the current LFA. GetFileLFA may be used to find the current LFA.
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile).
pData - Pointer to the data to write.
nBytes - DWord with number of bytes to write.
pdnBytesRet - pointer to a DWord where the number of bytes succesfully written will be returned.
Request Parameters for ReadBytes:
wSvcCode = 6
nSend = 1
pData1 = pData
cbData1 = nBytes
pData2 = pdnBytesRet
cbData2 = 4 (size of dnBytesRet)
dData0 = dHandle
dData1 = 0
dData2 = 0
-------------------------------
GetFileLFA(dHandle, pdLFARet): dError
DESC: This gets the current LFA (file pointer) for Stream Access files. An error occurs if the file is opened for Block access.
Params:
dhandle - DWord with a valid file handle (as returned from OpenFile).
pdLFARet - a pointer to a DWord where the current LFA (file pointer) will be returned.
Request Parameters for GetFileLFA:
wSvcCode = 7
nSend = 0
pData1 = pdLFARet
cbData1 = 4
pData2 = 0
cbData2 = 0
dData0 = dHandle
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -