Operations vector for a node. More...
Public Attributes | |
VNode Operations | |
status_t(* | lookup )(fs_volume *volume, fs_vnode *dir, const char *name, ino_t *_id) |
Looks up the node a directory entry refers to. | |
status_t(* | get_vnode_name )(fs_volume *volume, fs_vnode *vnode, char *buffer, size_t bufferSize) |
Return the file name of a directory vnode. | |
status_t(* | put_vnode )(fs_volume *volume, fs_vnode *vnode, bool reenter) |
Deletes the private data handle associated with the specified node. | |
status_t(* | remove_vnode )(fs_volume *volume, fs_vnode *vnode, bool reenter) |
Deletes the private data handle associated with the specified node. | |
VM file access | |
bool(* | can_page )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Deprecated. | |
status_t(* | read_pages )(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) |
Deprecated. | |
status_t(* | write_pages )(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) |
Deprecated. | |
Asynchronous I/O | |
status_t(* | io )(fs_volume *volume, fs_vnode *vnode, void *cookie, io_request *request) |
TODO: Document! | |
status_t(* | cancel_io )(fs_volume *volume, fs_vnode *vnode, void *cookie, io_request *request) |
TODO: Document! | |
Cache File Access | |
status_t(* | get_file_map )(fs_volume *volume, fs_vnode *vnode, off_t offset, size_t size, struct file_io_vec *vecs, size_t *_count) |
Fills the vecs with the extents of the file data stream. | |
Standard Operations | |
status_t(* | ioctl )(fs_volume *volume, fs_vnode *vnode, void *cookie, uint32 op, void *buffer, size_t length) |
Perform file system specific operations. | |
status_t(* | set_flags )(fs_volume *volume, fs_vnode *vnode, void *cookie, int flags) |
Set the open mode flags for an opened file. | |
status_t(* | select )(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event, selectsync *sync) |
Selects the specified vnode with the specified events. | |
status_t(* | deselect )(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event, selectsync *sync) |
Deselects the specified vnode from a previous select() call. | |
status_t(* | fsync )(fs_volume *volume, fs_vnode *vnode) |
Synchronize the buffers with the on disk data. | |
status_t(* | read_symlink )(fs_volume *volume, fs_vnode *link, char *buffer, size_t *_bufferSize) |
Read the value of a symbolic link. | |
status_t(* | create_symlink )(fs_volume *volume, fs_vnode *dir, const char *name, const char *path, int mode) |
Create a new symbolic link. | |
status_t(* | link )(fs_volume *volume, fs_vnode *dir, const char *name, fs_vnode *vnode) |
Create a new hard link. | |
status_t(* | unlink )(fs_volume *volume, fs_vnode *dir, const char *name) |
Remove a non-directory entry. | |
status_t(* | rename )(fs_volume *volume, fs_vnode *fromDir, const char *fromName, fs_vnode *toDir, const char *toName) |
Rename and/or relocate an entry. | |
status_t(* | access )(fs_volume *volume, fs_vnode *vnode, int mode) |
Checks whether the current user is allowed to access the node in the specified way. | |
status_t(* | read_stat )(fs_volume *volume, fs_vnode *vnode, struct stat *stat) |
Retrieves the stat data for a given node. | |
status_t(* | write_stat )(fs_volume *volume, fs_vnode *vnode, const struct stat *stat, uint32 statMask) |
Update the stats for a vnode. | |
File Operations | |
status_t(* | create )(fs_volume *volume, fs_vnode *dir, const char *name, int openMode, int perms, void **_cookie, ino_t *_newVnodeID) |
Creates and opens a new file. | |
status_t(* | open )(fs_volume *volume, fs_vnode *vnode, int openMode, void **_cookie) |
Opens the given node. | |
status_t(* | close )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Closes the given node cookie. | |
status_t(* | free_cookie )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Frees the given node cookie. | |
status_t(* | read )(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, void *buffer, size_t *length) |
Reads data from a file. | |
status_t(* | write )(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const void *buffer, size_t *length) |
Write data to a file. | |
Directory Operations | |
status_t(* | create_dir )(fs_volume *volume, fs_vnode *parent, const char *name, int perms) |
Create a new directory. | |
status_t(* | remove_dir )(fs_volume *volume, fs_vnode *parent, const char *name) |
Remove a directory. | |
status_t(* | open_dir )(fs_volume *volume, fs_vnode *vnode, void **_cookie) |
Opens the given directory node. | |
status_t(* | close_dir )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Closes the given directory cookie. | |
status_t(* | free_dir_cookie )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Frees the given directory cookie. | |
status_t(* | read_dir )(fs_volume *volume, fs_vnode *vnode, void *cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num) |
Reads the next one or more directory entries. | |
status_t(* | rewind_dir )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Resets the directory cookie to the first entry of the directory. | |
Attribute Directory Operations | |
status_t(* | open_attr_dir )(fs_volume *volume, fs_vnode *vnode, void **_cookie) |
Open a 'directory' of attributes for a vnode. | |
status_t(* | close_attr_dir )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Close a 'directory' of attributes for a vnode. | |
status_t(* | free_attr_dir_cookie )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Free the cookie to an attribute 'directory'. | |
status_t(* | read_attr_dir )(fs_volume *volume, fs_vnode *vnode, void *cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num) |
Read the next one or more attribute directory entries. | |
status_t(* | rewind_attr_dir )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Rewind the attribute directory iterator to the first entry. | |
Attribute Operations | |
status_t(* | create_attr )(fs_volume *volume, fs_vnode *vnode, const char *name, uint32 type, int openMode, void **_cookie) |
Create a new attribute. | |
status_t(* | open_attr )(fs_volume *volume, fs_vnode *vnode, const char *name, int openMode, void **_cookie) |
Open an existing attribute. | |
status_t(* | close_attr )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Close access to an attribute. | |
status_t(* | free_attr_cookie )(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Free the cookie of an attribute. | |
status_t(* | read_attr )(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, void *buffer, size_t *length) |
Read attribute data. | |
status_t(* | write_attr )(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const void *buffer, size_t *length) |
Write attribute data. | |
status_t(* | read_attr_stat )(fs_volume *volume, fs_vnode *vnode, void *cookie, struct stat *stat) |
Get the stats for an attribute. | |
status_t(* | write_attr_stat )(fs_volume *volume, fs_vnode *vnode, void *cookie, const struct stat *stat, int statMask) |
Update the stats of an attribute. | |
status_t(* | rename_attr )(fs_volume *volume, fs_vnode *fromVnode, const char *fromName, fs_vnode *toVnode, const char *toName) |
Rename and/or relocate an attribute. | |
status_t(* | remove_attr )(fs_volume *volume, fs_vnode *vnode, const char *name) |
Remove an attribute. | |
Node and FS Layers | |
status_t(* | create_special_node )(fs_volume *volume, fs_vnode *dir, const char *name, fs_vnode *subVnode, mode_t mode, uint32 flags, fs_vnode *_superVnode, ino_t *_nodeID) |
TODO: Document! | |
status_t(* | get_super_vnode )(fs_volume *volume, fs_vnode *vnode, fs_volume *superVolume, fs_vnode *superVnode) |
TODO: Document! | |
Operations vector for a node.
See the introduction to file system modules for an introduction to writing file systems.
status_t(* fs_vnode_ops::access)(fs_volume *volume, fs_vnode *vnode, int mode) |
Checks whether the current user is allowed to access the node in the specified way.
mode is a bitwise combination of:
R_OK:
Read access.W_OK:
Write access.X_OK:
Execution.If the current user does not have any of the access permissions represented by the set bits, the function shall return B_NOT_ALLOWED
. As a special case, if the volume is read-only and write access is requested, B_READ_ONLY_DEVICE
shall be returned. If the requested access mode complies with the user's access permissions, the function shall return B_OK
.
For most FSs the permissions a user has are defined by the st_mode
, st_uid
, and st_gid
fields of the node's stat data. As a special exception, the root user (geteuid() == 0
) does always have read and write permissions, execution permission only when at least one of the execution permission bits are set.
volume | The volume object. |
vnode | The node object. |
mode | The access mode mask. |
B_OK | The user has the permissions to access the node in the requested way. |
B_READ_ONLY_DEVICE | The volume is read-only, but the write access has been requested. |
B_NOT_ALLOWED | The user does not have all permissions to access the node in the requested way. |
bool(* fs_vnode_ops::can_page)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Deprecated.
status_t(* fs_vnode_ops::close)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Closes the given node cookie.
The hook is invoked, when closing the node has been requested. At this point other threads might still use the cookie, i.e. still execute hooks to which the cookie has been passed. If the FS supports blocking I/O operations, this hook should make sure to unblock all currently blocking threads performing an operation using the cookie, and mark the cookie such that no further threads will block using it.
For many FSs this hook is a no-op – it's mandatory to be exported, though.
volume | The volume object. |
vnode | The node object. |
cookie | The node cookie as returned by open(). |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::close_attr)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Close access to an attribute.
Note that you should not delete the cookie yet, you should do that when the VFS calls free_attr_cookie().
volume | The volume object. |
vnode | The node object. |
cookie | The cookie you associated with this attribute. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::close_attr_dir)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Close a 'directory' of attributes for a vnode.
Note that you should free the cookie in the free_attr_dir_cookie() call.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie associated with this 'directory'. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::close_dir)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Closes the given directory cookie.
Generally the situation is similar to the one described for close(). In practice it is a bit different, though, since directory cookies are exclusively used for directory iteration, and it normally doesn't make sense to have multiple threads read the same directory concurrently. Furthermore usually reading a directory will not block. Therefore for most FSs this hook is a no-op.
volume | The volume object. |
vnode | The node object. |
cookie | The directory cookie as returned by open_dir(). |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::create)(fs_volume *volume, fs_vnode *dir, const char *name, int openMode, int perms, void **_cookie, ino_t *_newVnodeID) |
Creates and opens a new file.
The hook is similar to open() , with the difference that, if an entry with the name name does not already exist in the given directory, a new file with that name is created first. If the entry does already exist and openMode specifies the O_EXCL
flag, the function shall fail with B_FILE_EXISTS
(aka EEXIST
).
volume | The volume object. | |
dir | The node object for the directory where the file should appear. | |
name | The name of the new file. | |
openMode | The mode associated to the file. | |
perms | The permissions the new file should have. | |
[out] | _cookie | In case of success, the storage where you can put your FS specific cookie for the open node. |
[out] | _newVnodeID | In case of success, you can store the new vnode id in this variable. |
B_OK
shall be returned and _cookie and _newVnodeID shall be set. Otherwise an error code shall be returned. status_t(* fs_vnode_ops::create_attr)(fs_volume *volume, fs_vnode *vnode, const char *name, uint32 type, int openMode, void **_cookie) |
Create a new attribute.
If the attribute already exists, you should open it in truncated mode.
volume | The volume object. | |
vnode | The node object. | |
name | The name of the attribute. | |
type | The type_code of the attribute. | |
openMode | The openMode of the associated attribute. | |
[out] | _cookie | A pointer where you can store an associated file system cookie. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::create_dir)(fs_volume *volume, fs_vnode *parent, const char *name, int perms) |
Create a new directory.
volume | The volume object. |
parent | The node object for the directory in which to create the new directory. |
name | The name the new directory should have. |
perms | The permissions the new directory should have. |
B_OK
if the directory was created successfully, an error code otherwise. status_t(* fs_vnode_ops::create_symlink)(fs_volume *volume, fs_vnode *dir, const char *name, const char *path, int mode) |
Create a new symbolic link.
volume | The volume object. |
dir | The node object for the directory the symbolic link should be created in. |
name | The name of the new symbolic link. |
path | The path the symbolic link should refer to. |
mode | The permissions for the newly created symbolic link. |
B_OK
if you succeeded, or an error code if you failed. status_t(* fs_vnode_ops::deselect)(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event, selectsync *sync) |
Deselects the specified vnode from a previous select() call.
This function is called by the VFS whenever a select() or poll() function exits that previously called file_system_module_info::select() on that vnode.
volume | The volume object. |
vnode | The node object. |
cookie | The file system provided cookie associated with the opened file. |
event | The event to be deselected. |
sync | Opaque pointer to be passed to notify_select_event(). |
B_OK
if the operation succeeded, or else an error code. status_t(* fs_vnode_ops::free_attr_cookie)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Free the cookie of an attribute.
The VFS calls this hook when all operations on the attribute have ceased.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie to the attribute that should be freed. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::free_attr_dir_cookie)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Free the cookie to an attribute 'directory'.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie associated that should be freed. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::free_cookie)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Frees the given node cookie.
The hook is invoked after close(), when no other thread uses or is going to use the cookie. All resources associated with the cookie must be freed.
volume | The volume object. |
vnode | The node object. |
cookie | The node cookie as returned by open(). |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::free_dir_cookie)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Frees the given directory cookie.
The hook is invoked after close_dir(), when no other thread uses or is going to use the cookie. All resources associated with the cookie must be freed.
volume | The volume object. |
vnode | The node object. |
cookie | The directory cookie as returned by open_dir(). |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::fsync)(fs_volume *volume, fs_vnode *vnode) |
Synchronize the buffers with the on disk data.
volume | The volume object. |
vnode | The node object. |
B_OK
if the operation succeeded, or else an error code. status_t(* fs_vnode_ops::get_file_map)(fs_volume *volume, fs_vnode *vnode, off_t offset, size_t size, struct file_io_vec *vecs, size_t *_count) |
Fills the vecs with the extents of the file data stream.
This function is called only when you are using the file cache, but if you use it, its implementation is mandatory.
TODO: complete me
status_t(* fs_vnode_ops::get_vnode_name)(fs_volume *volume, fs_vnode *vnode, char *buffer, size_t bufferSize) |
Return the file name of a directory vnode.
Normally file systems don't support hard links for directories, which means that a directory can be addressed by a unique path. This hook returns the name of the directory's entry in its parent directory.
Note that you don't have to implement this call if it can't be easily done; it's completely optional. If you don't implement it, you'll have to export a NULL pointer for this function in the module definition. In this case, the VFS will find the name by iterating over its parent directory.
If invoked for a non-directory node the hook is allowed to fail.
volume | The volume object. |
vnode | The node object. |
buffer | The buffer that the name can be copied into. |
bufferSize | The size of the buffer. |
B_OK | You successfully copied the file name into the buffer. |
other errors | There was some error looking up or copying the name. |
status_t(* fs_vnode_ops::ioctl)(fs_volume *volume, fs_vnode *vnode, void *cookie, ulong op, void *buffer, size_t length) |
Perform file system specific operations.
You can implement a customized API using this call. This can be extremely handy for debugging purposes. There are no obligatory operations for you to implement.
If you don't want to use this feature, you don't have to implement it.
volume | The volume object. |
vnode | The node object. |
cookie | The file system provided cookie associated with, for example, an open file (if applicable). |
op | The operation code. You will have to define them yourself. |
buffer | A buffer (if applicable). |
length | The size of the buffer. |
status_t(* fs_vnode_ops::link)(fs_volume *volume, fs_vnode *dir, const char *name, fs_vnode *vnode) |
Create a new hard link.
The virtual file system will request the creation of symbolic links with create_symlink().
If you don't implement this function, the VFS will return EROFS
when a hard link is requested. So, if you don't support hard links implement this hook and return an appropriate error code.
volume | The volume object. |
dir | The node object for the directory where the link should be created. |
name | The name the link should have. |
vnode | The vnode the new link should resolve to. |
B_OK | The hard link is properly created. |
B_NOT_ALLOWED | The user does not have the proper permissions. |
other errors | Another error occured. |
status_t(* fs_vnode_ops::lookup)(fs_volume *volume, fs_vnode *dir, const char *name, ino_t *_id) |
Looks up the node a directory entry refers to.
The VFS uses this hook to resolve path names to vnodes. It is used quite often and should be implemented efficiently.
If the parameter dir does not specify a directory, the function shall fail. It shall also fail, if it is a directory, but does not contain an entry with the given name name. Otherwise the function shall invoke get_vnode() for the node the entry refers to and pass back the ID of the node in _id.
Note that a directory must contain the special entries "."
and ".."
, referring to the same directory and the parent directory respectively. lookup() must resolve the nodes accordingly. ".."
for the root directory of the volume shall be resolved to the root directory itself.
volume | The volume object. |
dir | The node object for the directory. |
name | The name of the directory entry. |
_id | Pointer to a pre-allocated variable the ID of the found node shall be written to. |
B_OK | Everything went fine. |
B_NOT_A_DIRECTORY | The given node is not a directory. |
B_ENTRY_NOT_FOUND | The given directory does not contain an entry with the given name. |
status_t(* fs_vnode_ops::open)(fs_volume *volume, fs_vnode *vnode, int openMode, void **_cookie) |
Opens the given node.
The hook is invoked whenever a file is opened (e.g. via the open() POSIX function).
The hook can create a node cookie, and store it in the variable _cookie points to. The cookie will be passed to all hooks that operate on open files.
The open mode openMode is encoded in the same way as the parameter of the POSIX function open()
, i.e. it is either O_RDONLY
, O_WRONLY
, or O_RDWR
, bitwise or'ed with flags. The only relevant flags for this hook are O_TRUNC
and O_NONBLOCK
. You will normally want to store the open mode in the file cookie, since you'll have to check in read() and write() whether the the respective operation is allowed by the open mode.
volume | The volume object. |
vnode | The node object. |
openMode | The open mode. |
_cookie | Pointer to a pre-allocated variable the node cookie shall be written to. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::open_attr)(fs_volume *volume, fs_vnode *vnode, const char *name, int openMode, void **_cookie) |
Open an existing attribute.
volume | The volume object. | |
vnode | The node object. | |
name | The name of the attribute. | |
openMode | The mode in which you want to open the attribute data. | |
[out] | _cookie | A pointer where you can store an associated file system cookie. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::open_attr_dir)(fs_volume *volume, fs_vnode *vnode, void **_cookie) |
Open a 'directory' of attributes for a vnode.
See Generic Concepts on directories and iterators. Basically, the VFS uses the same way of traversing through attributes as it traverses through a directory.
volume | The volume object. | |
vnode | The node object. | |
[out] | _cookie | Pointer where the file system can store a directory cookie if the attribute directory is succesfully opened. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::open_dir)(fs_volume *volume, fs_vnode *vnode, void **_cookie) |
Opens the given directory node.
If the specified node is not a directory, the function shall fail. Otherwise it shall allocate a directory cookie and store it in the variable _cookie points to. A subsequent read_dir() using the cookie shall start reading the first entry of the directory.
volume | The volume object. |
vnode | The node object. |
_cookie | Pointer to a pre-allocated variable the directory cookie shall be written to. |
B_OK
if everything went fine, another error code otherwise. fn status_t(* fs_vnode_ops::put_vnode)(fs_volume *volume, fs_vnode *vnode, bool reenter) |
Deletes the private data handle associated with the specified node.
Invoked by the VFS when it deletes the vnode for the respective node and the node is not marked removed.
volume | The volume object. |
vnode | The node object. |
reenter | true if the hook invocation has been caused by the FS itself, e.g. by invoking put_vnode(). |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::read)(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, void *buffer, size_t *length) |
Reads data from a file.
This function should fail if
The number of bytes to be read is stored in the variable pointed to by length. If less data is available at file position pos, or if pos if greater than the size of the file, only as many data as available shall be read, the function shall store the number of bytes actually read into the variable pointed to by length, and return B_OK
.
volume | The volume object. |
vnode | The node object. |
cookie | The node cookie as returned by open(). |
pos | The file position where to start reading data. |
buffer | Pointer to a pre-allocated buffer the read data shall be written to. |
length | Pointer to a pre-allocated variable containing the size of the buffer when invoked, and into which the size of the data actually read shall be written. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::read_attr)(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, void *buffer, size_t *length) |
Read attribute data.
Read until the buffer with size length is full, or until you are out of data, in which case you should update length.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie you associated with this attribute. |
pos | The position to start reading from. |
buffer | The buffer the data should be copied in. |
length | The length of the buffer. Update this variable to the actual amount of bytes read. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::read_attr_dir)(fs_volume *volume, fs_vnode *vnode, void *cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num) |
Read the next one or more attribute directory entries.
This method should perform the same tasks as read_dir(), except that the '.' and '..' entries do not have to be present. Also, only the d_name
and d_reclen
fields have to be filled in.
status_t(* fs_vnode_ops::read_attr_stat)(fs_volume *volume, fs_vnode *vnode, void *cookie, struct stat *stat) |
Get the stats for an attribute.
Only the st_size
and st_type
fields need to be filled in.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie you associated with this attribute. |
stat | A pointer to a stat structure you should fill. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::read_dir)(fs_volume *volume, fs_vnode *vnode, void *cookie, struct dirent *buffer, size_t bufferSize, uint32 *_num) |
Reads the next one or more directory entries.
The number of entries to be read at maximum is stored in the variable _num points to.
Per read dirent
the following fields have to be filled in:
d_dev:
The volume ID.d_ino:
The ID of the node the entry refers to.d_name:
The null-terminated name of the entry.d_reclen:
The size of the dirent
structure in bytes, starting from the beginning of the structure, counting all bytes up to and including the null-termination char of the name stored in d_name
.If more than one entry is read, the corresponding dirent
structures are tightly packed, i.e. the second entry can begin directly after the end of the first one (i.e. d_reclen
bytes after the beginning of the first one). The file system should make sure that the dirents are 8-byte aligned, i.e. when another entry follows, d_reclen
of the previous one should be aligned. A FS doesn't have to read more than one entry at a time, but it is recommended to support that for performance reasons.
If the provided buffer is too small to contain even the single next entry, B_BUFFER_OVERFLOW
shall be returned. It shall not fail, if at least one entry has been read, and the buffer is just too small to hold as many entries as requested. When the function is invoked after the end of the directory has been reached, it shall set the variable _num points to 0
and return B_OK
. Usually the function is invoked repeatedly until then to get more entries. The cookie
parameter must be used to track the position in the directory.
Note that a directory is expected to contain the special entries "."
and ".."
, referring to the same directory and the parent directory respectively. The dirent
structure returned for the ".."
entry of the volume's root directory shall refer to the root node itself.
volume | The volume object. |
vnode | The node object. |
cookie | The directory cookie as returned by open_dir(). |
buffer | Pointer to a pre-allocated buffer the directory entries shall be written to. |
bufferSize | The size of buffer in bytes. |
_num | Pointer to a pre-allocated variable, when invoked, containing the number of directory entries to be read, and into which the number of entries actually read shall be written. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::read_pages)(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) |
Deprecated.
status_t(* fs_vnode_ops::read_stat)(fs_volume *volume, fs_vnode *vnode, struct stat *stat) |
Retrieves the stat data for a given node.
All values of the struct stat
save st_dev
, st_ino
, st_rdev
, and st_type
need to be filled in.
volume | The volume object. |
vnode | The node object. |
stat | Pointer to a pre-allocated variable the stat data shall be written to. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::read_symlink)(fs_volume *volume, fs_vnode *link, char *buffer, size_t *_bufferSize) |
Read the value of a symbolic link.
If the function is successful, the symlink string shall be written to the buffer. It does not need to be null-terminated. If the buffer is too small to hold the complete string, only the first *_bufferSize
bytes of the string shall be written to the buffer; the buffer shall not be null-terminated in this case. Furthermore the variable _bufferSize shall be set to the length of the symlink contents, even if the entire contents did not fit in the provided buffer.
volume | The volume object. |
link | The node object. |
buffer | Pointer to a pre-allocated buffer the link value shall be written to. |
_bufferSize | Pointer to a pre-allocated variable containing the size of the buffer supplied to the function. Upon successful completion the hook shall store the length of the symlink contents. |
B_OK | Everything went fine. |
B_BAD_VALUE | link does not identify a symbolic link. |
status_t(* fs_vnode_ops::remove_attr)(fs_volume *volume, fs_vnode *vnode, const char *name) |
Remove an attribute.
volume | The volume object. |
vnode | The node object. |
name | The name of the attribute. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::remove_dir)(fs_volume *volume, fs_vnode *parent, const char *name) |
Remove a directory.
The function shall fail, if the entry does not refer to a directory, or if it refers to a directory that is not empty.
volume | The volume object. |
parent | The node object for the parent directory containing the directory to be removed. |
name | The name of the directory that needs to be removed. |
B_OK | Operation succeeded. |
B_ENTRY_NOT_FOUND | There is no entry with this name. |
B_NOT_A_DIRECTORY | The entry is not a directory. |
B_DIRECTORY_NOT_EMPTY | The directory is not empty. The virtual file system expects directories to be emptied before they can be removed. |
other errors | Other errors occured. |
status_t(* fs_vnode_ops::remove_vnode)(fs_volume *volume, fs_vnode *vnode, bool reenter) |
Deletes the private data handle associated with the specified node.
Invoked by the VFS when it deletes the vnode for the respective node and the node has been marked removed by a call to remove_vnode().
volume | The volume object. |
vnode | The node object. |
reenter | true if the hook invocation has been caused by the FS itself, e.g. by invoking put_vnode(). |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::rename)(fs_volume *volume, fs_vnode *fromDir, const char *fromName, fs_vnode *toDir, const char *toName) |
Rename and/or relocate an entry.
The virtual file system merely relays the request, so make sure the user is not changing the file name to something like '.', '..' or anything starting with '/'.
This also means that it if the entry refers to a directory, that it should not be moved into one of its own children.
volume | The volume object. |
fromDir | The node object for the parent directory the entry should be moved from. |
fromName | The old entry name. |
toDir | The node object for the parent directory the entry should be moved to. |
toName | The new entry name. |
B_OK | The renaming and relocating succeeded. |
B_BAD_VALUE | One of the supplied parameters were invalid. |
B_NOT_ALLOWED | The user does not have the proper permissions. |
other errors | Another error condition was encountered. |
status_t(* fs_vnode_ops::rename_attr)(fs_volume *volume, fs_vnode *fromVnode, const char *fromName, fs_vnode *toVnode, const char *toName) |
Rename and/or relocate an attribute.
Currently there's no userland or kernel API moving an attribute from one node to another. So this hook is to allowed to only support the case where fromVnode and toVnode are equal and fail otherwise.
volume | The volume object. |
fromVnode | The node object for the vnode the attribute currently belongs to. |
fromName | The old name of the attribute. |
toVnode | The node object for the vnode the attribute should be moved to. This can be the same as fromVnode, in which case it only means the attribute should be renamed. |
toName | The new name of the attribute. This can be the same as fromName, in which case it only means the attribute should be relocated. |
B_OK | The renaming and/or relocating succeeded. |
B_BAD_VALUE | One of the supplied parameters were invalid. |
B_NOT_ALLOWED | The user does not have the proper permissions. |
other errors | Another error condition was encountered. |
status_t(* fs_vnode_ops::rewind_attr_dir)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Rewind the attribute directory iterator to the first entry.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie associated with this 'directory'. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::rewind_dir)(fs_volume *volume, fs_vnode *vnode, void *cookie) |
Resets the directory cookie to the first entry of the directory.
volume | The volume object. |
vnode | The node object. |
cookie | The directory cookie as returned by open_dir(). |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::select)(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event, selectsync *sync) |
Selects the specified vnode with the specified events.
This function is called by the VFS whenever select() or poll() is called on a file descriptor that points to your file system.
You have to check if the condition of the select() (ie. if there is data available if event is B_SELECT_READ) is already satisfied, and call notify_select_event() with the sync and ref arguments you retrieve here.
Additionally, when a vnode is selected this way, you have to call notify_select_event() whenever the condition becomes true until the vnode is deselected again via file_system_module_info::deselect().
This function is optional. If you don't export it, the default implementation in the VFS will call notify_select_event() directly which will be sufficient for most file systems.
Note that while select() and the corresponding deselect() are invoked by the same thread, notifications are usually generated by other threads. It is your responsibility to make sure that notify_select_event() is never called for a selectsync object for which deselect() has already returned. This is commonly done by holding the same lock when invoking notify_select_event() and when removing the selectsync object from the cookie in deselect(). Such a lock can be any lock, usually one that is associated with the node or the volume.
volume | The volume object. |
vnode | The node object. |
cookie | The file system provided cookie associated with the opened file. |
event | The event to be selected. One of:
|
sync | Opaque pointer to be passed to notify_select_event(). |
B_OK
if the operation succeeded, or else an error code. status_t(* fs_vnode_ops::set_flags)(fs_volume *volume, fs_vnode *vnode, void *cookie, int flags) |
Set the open mode flags for an opened file.
This function should change the open flags for an opened file.
volume | The volume object. |
vnode | The node object. |
cookie | The file system provided cookie associated with the opened file. |
flags | The new flags. |
B_OK
if the operation succeeded, or else an error code. status_t(* fs_vnode_ops::unlink)(fs_volume *volume, fs_vnode *dir, const char *name) |
Remove a non-directory entry.
Remove an entry that does refer to a non-directory node. For removing directories the remove_dir() hook is used. If invoked on a directory, this hook shall fail.
volume | The volume object. |
dir | The node object for the directory containing the entry to be removed. |
name | The name of the entry that should be removed. |
B_OK | Removal succeeded. |
B_ENTRY_NOT_FOUND | The entry does not exist. |
B_NOT_ALLOWED | The user does not have the proper permissions. |
B_IS_A_DIRECTORY | The entry refers to a directory. |
other errors | Another error occured. |
status_t(* fs_vnode_ops::write)(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const void *buffer, size_t *length) |
Write data to a file.
This function should fail if
The number of bytes to be written is stored in the variable pointed to by length. If not all bytes could be written, that variable must be updated to reflect the amount of actually written bytes. If any bytes have been written, the function shall not fail, if an error prevents you from writing the full amount. Only when the error prevented you from writing any data at all an error shall be returned.
volume | The volume object. |
vnode | The node object. |
cookie | The file system provided cookie associated with the file. |
pos | The position to start writing. |
buffer | The buffer that contains the data that will need to be written. |
length | The length of the data that needs to be written. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::write_attr)(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const void *buffer, size_t *length) |
Write attribute data.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie you associated with this attribute. |
pos | The position to start writing to. |
buffer | The buffer the data should be copied from. |
length | The size of the buffer. Update this variable to the actual amount of bytes written. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::write_attr_stat)(fs_volume *volume, fs_vnode *vnode, void *cookie, const struct stat *stat, int statMask) |
Update the stats of an attribute.
Currently on the attribute size (B_STAT_SIZE) can be set.
volume | The volume object. |
vnode | The node object. |
cookie | The cookie you associated with this attribute. |
stat | A pointer to the new stats you should write. |
statMask | One or more of the values of write_stat_mask that tell you which fields of stat are to be updated. |
B_OK
if everything went fine, another error code otherwise. status_t(* fs_vnode_ops::write_pages)(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) |
Deprecated.
status_t(* fs_vnode_ops::write_stat)(fs_volume *volume, fs_vnode *vnode, const struct stat *stat, uint32 statMask) |
Update the stats for a vnode.
You should make sure that the new values are valid.
volume | The volume object. |
vnode | The node object. |
stat | The structure with the updated values. |
statMask | A bitwise combination of one or more of the following, specifying which stat field shall be set:
|
B_OK | The update succeeded. |
B_NOT_ALLOWED | The user does not have the proper permissions. |
other errors | Another error condition occured. |