/* * \file design.dox * Documentation title page with design information */ /** \mainpage File System Wrapper Documentation Welcome to the documentation for FSW. This doxygen-generated documentation is intended for developers that either want to integrate FSW into their own project or want to write additional file system drivers. \section goals Design Goals File System Wrapper wants to provide reusable, read-only file system drivers for a range of common file systems. Reusability is achieved through a common abstraction layer (called the "core"), which serves as the API for the host environment driver. Once the required glue code is written for a host environment, that host has access to all file system types implemented by FSW, with no code to be written per file system type. Why read-only? There are a range of reasons why FSW only provides read-only access: - Read-only drivers are much easier to write than read-write drivers. - Write access isn't easily abstracted in an OS-independent way because of more delicate buffer I/O handling requirements and features like journalling. - There is no risk of destroying data on the disk. - Having read access is much better than having no access at all. (Read-only drivers for several file systems can be written in the time it would take to develop a read-write driver for just one file system.) - Boot loaders only need read access in most cases. \section model Object and Data Model \subsection main_objects Main Objects There are three main "objects" that FSW works with: volume, dnode, and shandle. The fsw_volume structure keeps the information that applies to a file system volume as a whole. Most importantly, it keeps pointers to the host driver and file system driver dispatch tables, which are used by the core to call the appropriate functions. The fsw_dnode structure represents a "directory node", that is any file-like object in the file system: regular files, directories, symbolic links as well as special files like device nodes. When compared with Unix-style file systems, a dnode is very similar to an inode, but it retains some essential information from the directory: the canonical name and the parent directory. FSW requires that a dnode is uniquely identified by an integer number (currently 32 bit in size). Inode numbers can be used for this purpose, non-Unix file systems will have to come up with a unique number in some way. The fsw_shandle structure is used to access file data ("storage handle"). A dnode only represents the file as such and doesn't offer access to its data. An shandle is linked to a certain dnode, but there may be several shandles per dnode. The shandle stores a file position pointer (byte offset) that can be changed at will. With the current design, an shandle is also used for directory iteration, even if the file system stores directory information in a central tree structure. \subsection disk_access Disk Data Access Data on the disk is accessed in blocks, addressed by a sequential number starting at zero. The block size to use can be set by the file system driver. FSW supports two separate block sizes: the "physical block size" is used when accessing the disk, the "logical block size" is used when accessing a file's data. For most file systems, these two are identical, but there may be some where the file allocation block size is larger than the sector or block size used to store metadata. (FAT comes to mind as an example.) For accessing the actual file data, the file system driver doesn't handle the disk I/O, but merely returns information about the mapping from file logical blocks to disk physical blocks in the fsw_extent structure. This allows host OS buffer mechanisms to be used for file data. In special cases, like tail-packing, fragments or compressed file systems, the file system driver can return file data in an allocated buffer. \subsection data_hooks Data Extension Hooks File system specific data can be stored by extending the fsw_volume and fsw_dnode structures. The core code uses the structure sizes stored in the fsw_fstype_table to allocate memory for these structures. The fsw_shandle and fsw_extent structures are not designed to be extended. Host specific data must be stored in separate structures private to the host environment driver. The fsw_volume structure provides a host_data variable to store a pointer. The fsw_dnode structure has no such field, because it is assumed that all actions regarding dnodes are initiated on the host side and so the host-specific private structure is known. \section callconv Calling Conventions All functions that can fail return a status code in a fsw_status_t. This type is an integer. A boolean test yields true if there was an error and false if the function executed successfully, i.e. success is signalled by a 0 return value. Functions that return data do so either by filling a structure passed in by the caller, or by allocating a structure on the heap and returning a pointer through a double-indirect parameter. A returned object pointer is the last parameter in the parameter list. (More to be written about specific conventions for dnodes, shandles, strings.) */