The OSKit file system framework has parallel goals to the OSKit device driver framework; the framework provides a file system interface specification designed to allow existing filesystem implementations to be borrowed from well-established operating systems in source form and used mostly unchanged to provide file system support in new operating systems. The framework is also designed to allow file systems to be implemented in diverse ways and then composed together.
The OSKit file system framework encompasses a collection of COM interfaces used by the client operating system to invoke the file system libraries, and a collection of interfaces used by the file system libraries to request services from the client operating system. The individual file system libraries supply additional interfaces to the client operating system for initialization, and may supply additional interfaces for supporting extended features unique to particular file system implementations.
The OSKit File, Directory and Open File COM interfaces inherit from several general COM interfaces, such as Stream, Absolute IO and POSIX IO. The inheritance relationships among these COM interfaces are shown in Figure 9.1. Refer to Section 4 for more details on COM interfaces.
The oskit_principal COM interface defines an interface for obtaining identity information about a principal (aka subject or client). The filesystem libraries obtain an oskit_principal object for the current client by invoking oskit_get_call_context on oskit_principal_iid.
The oskit_principal COM interface inherits from IUnknown, and has one additional method:
#include <oskit/principal.h>
oskit_error_t oskit_principal_getid(oskit_principal_t *p, [out] oskit_identity_t *out_id);
filesystem library client OS
This method returns the identity attributes of this principal. out_id is a pointer to an oskit_identity_t structure defined as follows:
oskit_uid_t | uid; | /* effective user id | */ | |
oskit_gid_t | gid; | /* effective group id | */ | |
oskit_u32_t | ngroups; | /* number of groups | */ | |
oskit_u32_t | *groups; | /* supplemental groups | */ | |
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
The oskit_filesystem COM interface defines an interface for operating on a filesystem, which is a logical collection of files and a tree-structured namespace with a single root. The filesystem itself exists independent of any given namespace, for there is no notion of mounts in this interface. That functionality must be implemented at a higher level.
The oskit_filesystem COM interface inherits from IUnknown, and has the following additional methods:
#include <oskit/fs/filesystem.h>
oskit_error_t oskit_filesystem_statfs(oskit_filesystem_t *f, [out] oskit_statfs_t *out_stats);
client OS filesystem library
This method returns the attributes of this filesystem. out_stats is a pointer to an oskit_statfs_t structure defined as follows:
oskit_u32_t | bsize; | /* file system block size | */ | |
oskit_u32_t | frsize; | /* fundamental file system block size | */ | |
oskit_u32_t | blocks; | /* total blocks in fs in units of frsize | */ | |
oskit_u32_t | bfree; | /* free blocks in fs | */ | |
oskit_u32_t | bavail; | /* free blocks avail to non-superuser | */ | |
oskit_u32_t | files; | /* total file nodes in file system | */ | |
oskit_u32_t | ffree; | /* free file nodes in fs | */ | |
oskit_u32_t | favail; | /* free file nodes avail to non-superuser | */ | |
oskit_u32_t | fsid; | /* file system id | */ | |
oskit_u32_t | flag; | /* mount flags | */ | |
oskit_u32_t | namemax; | /* max bytes in a file name | */ | |
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/filesystem.h>
oskit_error_t oskit_filesystem_sync(oskit_filesystem_t *f, oskit_bool_t wait);
client OS filesystem library
This method writes all of this filesystem’s data back to permanent storage. If wait is TRUE, then the call does not return until all pending data has been completely written.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/filesystem.h>
oskit_error_t oskit_filesystem_getroot(oskit_filesystem_t *f, [out] oskit_dir_t **out_dir);
client OS filesystem library
This method returns a reference to the root directory of this filesystem. out_dir is a pointer to the oskit_dir COM interface for the root directory.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/filesystem.h>
oskit_error_t oskit_filesystem_remount(oskit_filesystem_t *f, oskit_u32_t flags);
client OS filesystem library
This method changes the mount flags associated with this filesystem. For example, this method might be used to change a filesystem from read-only to read-write, or vice versa.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
client OS filesystem library
This method forcibly unmounts this filesystem. Ordinarily, a filesystem is unmounted when the last reference to it is released; in contrast, this method forces an unmount regardless of external references to the filesystem, and is consequently unsafe. Subsequent attempts to use references to the filesystem or to use references to files within the filesystem may yield undefined results.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/filesystem.h>
oskit_error_t oskit_filesystem_lookupi(oskit_filesystem_t *f, oskit_ino_t ino, [out] oskit_file_t **out_file);
client OS filesystem library
This method looks up a file given its inode number. If the inode number is invalid, the behavior is undefined.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
The oskit_file COM interface defines an interface for operating on a file. The interface does not imply any per-open state; per-open methods are defined by the oskit_openfile COM interface.
The oskit_file COM interface inherits from the oskit_posixio COM interface, and has the following additional methods:
Additionally, an oskit_file object may export a oskit_absio COM interface; this may be determined by querying the object.
client OS filesystem library
This method synchronizes the in-core copy of this file’s data and metadata with the on-disk copy. If wait is TRUE, then the call does not return until all pending data has been completely written.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
client OS filesystem library
This method synchronizes the in-core copy of this file’s data with the on-disk copy. The file metadata need not be sychronized by this method. If wait is TRUE, then the call does not return until all pending data has been completely written.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
client OS filesystem library
This method checks whether the form of access specified by mask would be granted. mask may be any combination of OSKIT_R_OK (read access), OSKIT_W_OK (write access), or OSKIT_X_OK (execute access). If the access would not be granted, then this method will return the error that would be returned if the actual access were attempted.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_file_readlink(oskit_file_t *f, char *buf, oskit_u32_t len, [out] oskit_u32_t *out_actual);
client OS filesystem library
If this file is a symbolic link, then this method reads the contents of the symbolic link into buf. No more than len bytes will be read. out_actual will be set to the actual number of bytes read.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
If the file is not a symbolic link, then OSKIT_E_NOTIMPL is returned.
#include <oskit/fs/file.h>
#include <oskit/fs/openfile.h>
oskit_error_t oskit_file_open(oskit_file_t *f, oskit_oflags_t flags, [out] oskit_openfile_t **out_openfile);
client OS filesystem library
This method returns an oskit_openfile COM interface for an open instance of this file. flags specifies the file open flags, as defined in <oskit/fs/file.h>. If OSKIT_O_TRUNC is specified, then the file will be truncated to zero length.
This method may only be used on regular files and directories. Directories may not be opened with OSKIT_O_WRONLY, OSKIT_O_RDWR or OSKIT_O_TRUNC.
This method may return success but set *out_openfile to NULL, indicating that the requested operation is allowed but the filesystem does not support per-open state; the client operating system must provide this functionality.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/file.h>
oskit_error_t oskit_file_getfs(oskit_file_t *f, [out] oskit_filesystem_t **out_fs);
client OS filesystem library
Returns the oskit_filesystem COM interface for the filesystem in which this file resides.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
The oskit_dir COM interface defines an interface for operating on a directory. The interface does not imply any per-open state; per-open methods are defined by the oskit_openfile COM interface.
The oskit_dir COM interface inherits from the oskit_file COM interface, and has the following additional methods:
Additionally, an oskit_dir object may export a oskit_absio COM interface; this may be determined by querying the object.
All name parameters to directory methods must be a single component, ie an entry in one of the specified directories. With the exception of rename, name parameters always refer to entries in the target directory itself.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_lookup(oskit_dir_t *d, const char *name, [out] oskit_file_t **out_file);
client OS filesystem library
This method returns the oskit_file COM interface for the file named by name in this directory. The name may only be a single component; multi-component lookups are not supported. If the file is a symbolic link, then out_file will reference the symbolic link itself.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_create(oskit_dir_t *d, const char *name, oskit_bool_t excl, oskit_mode_t mode, [out] oskit_file_t **out_file);
client OS filesystem library
This method is the same as oskit_dir_lookup, except that if the file does not exist, then a regular file will be created with the specified name and mode.
If a file with name already exists, and excl is TRUE, then OSKIT_EEXIST will be returned.
The name may only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_link(oskit_dir_t *d, const char *name, oskit_file_t *file);
client OS filesystem library
This method adds an entry for file into this directory, using name for the new directory entry. Typically, this is only supported if file resides in the same filesystem as d.
file may not be a symbolic link.
The name may only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
client OS filesystem library
This method removes the directory entry for name from d.
The name may only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_rename(oskit_dir_t *old_dir, const char *old_name, oskit_dir_t *new_dir, const char *new_name);
client OS filesystem library
This method atomically links the file named by old_name in old_dir into new_dir, using new_name for the new directory entry, and unlinks old_name from old_dir.
If a file named new_name already exists in new_dir, then it is first removed. In this case, the source and target files must either both be directories or both be non-directories, and if the target file is a directory, it must be empty.
Typically, this is only supported if new_dir resides in the same filesystem as old_dir.
The old_name and new_name may each only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_mkdir(oskit_dir_t *d, const char *name, oskit_mode_t mode);
client OS filesystem library
This method creates a new subdirectory in this directory, with the specified name and mode.
The name may only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
client OS filesystem library
This method removes the subdirectory named name from this directory. Typically, this is only supported if the subdirectory is empty.
The name may only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h> #include <oskit/fs/dirents.h>
oskit_error_t oskit_dir_getdirentries(oskit_dir_t *d, oskit_u32_t *inout_ofs, oskit_u32_t nentries, [out] oskit_dirents_t **out_dirents);
client OS filesystem library
This method reads one or more entries from this directory. On entry, inout_ofs contains the offset of the first entry to be read. Before returning, this method updates the value at inout_ofs to contain the offset of the next entry after the last entry returned in out_dirents. The returned value of inout_ofs is opaque; it should only be used in subsequent calls to this method.
This method will return at least nentries entries if there are at least that many entries remaining in the directory; however, this method may return more entries.
The return value out_dirents will contain a pointer to an oskit_dirents_t COM object, which holds the individual directory entries. The number of actual entries returned can be determined with the oskit_dirents_getcount method. Each successive directory entry is accessed using the oskit_dirents_getnext method. Once all the entries have been read, the dirents COM object should be released with the oskit_dirents_release method.
The data structure to retrieve the individual entries is:
oskit_size_t | namelen; | /* name length | */ | |
oskit_ino_t | ino; | /* entry inode | */ | |
char | name[0]; | /* entry name | */ | |
The namelen field should be initialized to the amount of storage available for the name. Upon return from the getnext method, namelen will be set to the actual length of the name. The pointer that is passed should obviously be large enough to hold the size of the structure above, plus the additional size of the character array.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_mknod(oskit_dir_t *d, const char *name, oskit_mode_t mode, oskit_dev_t dev);
client OS filesystem library
This method creates a device special file in this directory, with the specified name and file mode, and with the specified device number dev. The device number is opaque to the filesystem library.
The name may only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_symlink(oskit_dir_t *d, const char *link_name, char *dest_name);
client OS filesystem library
This method creates a symbolic link in this directory, named link_name, with contents dest_name.
The link_name may only be a single component; multi-component lookups are not supported.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
#include <oskit/fs/dir.h>
oskit_error_t oskit_dir_reparent(oskit_dir_t *d, oskit_dir_t *parent, [out] oskit_dir_t **out_dir);
client OS filesystem library
This method creates a virtual directory out_dir which refers to the same underlying directory as d, but whose logical parent directory is parent. If parent is NULL, then the logical parent directory of out_dir will be itself.
Lookups of the parent directory entry (’..’) in the virtual directory will return a reference to the logical parent directory.
This method may be used to provide equivalent functionality to the Unix chroot operation.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
The oskit_openfile COM interface defines an interface for operating on an open instance of a file.
The oskit_openfile COM interface inherits from the oskit_stream COM interface, and has the following additional method:
Additionally, an oskit_openfile object may export a oskit_absio COM interface; this may be determined by querying the object.
#include <oskit/fs/openfile.h>
oskit_error_t oskit_openfile_getfile(oskit_openfile_t *f, [out] oskit_file_t **out_file);
client OS filesystem library
This method returns the oskit_file COM interface for the underlying file object to which this open file refers.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.
This section describes the interfaces which must be provided by the client operating system to the filesystem library.
These interfaces consist of:
#include <oskit/com.h>
oskit_error_t oskit_get_call_context(oskit_guid_t *iid, [out] void **out_if);
filesystem library client OS
This function returns the requested COM interface for the current caller.
Typically, this is used to obtain the oskit_principal object for the current client of the filesystem library.
Returns 0 on success, or an error code specified in <oskit/error.h>, on error.