|
| fs_handle (const fs_handle &)=delete |
| No copy construction (use clone() )
|
|
fs_handle & | operator= (const fs_handle &o)=delete |
| No copy assignment.
|
|
dev_t | st_dev () const noexcept |
| Unless flag::disable_safety_unlinks is set, the device id of the file when opened.
|
|
ino_t | st_ino () const noexcept |
| Unless flag::disable_safety_unlinks is set, the inode of the file when opened. When combined with st_dev(), forms a unique identifer on this system.
|
|
unique_id_type | unique_id () const noexcept |
| A unique identifier for this handle across the entire system. Can be used in hash tables etc.
|
|
virtual result< path_handle > | parent_path_handle (deadline d=std::chrono::seconds(30)) const noexcept |
| Obtain a handle to the path currently containing this handle's file entry. More...
|
|
template<class... Args> |
bool | try_parent_path_handle (Args &&... args) noexcept |
|
template<class... Args, class Rep , class Period > |
bool | try_parent_path_handle_for (Args &&... args, const std::chrono::duration< Rep, Period > &duration) noexcept |
|
template<class... Args, class Clock , class Duration > |
bool | try_parent_path_handle_until (Args &&... args, const std::chrono::time_point< Clock, Duration > &timeout) noexcept |
|
virtual result< void > | relink (const path_handle &base, path_view_type path, bool atomic_replace=true, deadline d=std::chrono::seconds(30)) noexcept |
| Relinks the current path of this open handle to the new path specified. If atomic_replace is true, the relink atomically and silently replaces any item at the new path specified. This operation is both atomic and matching POSIX behaviour even on Microsoft Windows where no Win32 API can match POSIX semantics. More...
|
|
template<class... Args> |
bool | try_relink (Args &&... args) noexcept |
|
template<class... Args, class Rep , class Period > |
bool | try_relink_for (Args &&... args, const std::chrono::duration< Rep, Period > &duration) noexcept |
|
template<class... Args, class Clock , class Duration > |
bool | try_relink_until (Args &&... args, const std::chrono::time_point< Clock, Duration > &timeout) noexcept |
|
virtual result< void > | link (const path_handle &base, path_view_type path, deadline d=std::chrono::seconds(30)) noexcept |
| Links the inode referred to by this open handle to the path specified. The current path of this open handle is not changed, unless it has no current path due to being unlinked. More...
|
|
template<class... Args> |
bool | try_link (Args &&... args) noexcept |
|
template<class... Args, class Rep , class Period > |
bool | try_link_for (Args &&... args, const std::chrono::duration< Rep, Period > &duration) noexcept |
|
template<class... Args, class Clock , class Duration > |
bool | try_link_until (Args &&... args, const std::chrono::time_point< Clock, Duration > &timeout) noexcept |
|
virtual result< void > | unlink (deadline d=std::chrono::seconds(30)) noexcept |
| Unlinks the current path of this open handle, causing its entry to immediately disappear from the filing system. More...
|
|
template<class... Args> |
bool | try_unlink (Args &&... args) noexcept |
|
template<class... Args, class Rep , class Period > |
bool | try_unlink_for (Args &&... args, const std::chrono::duration< Rep, Period > &duration) noexcept |
|
template<class... Args, class Clock , class Duration > |
bool | try_unlink_until (Args &&... args, const std::chrono::time_point< Clock, Duration > &timeout) noexcept |
|
virtual result< span< path_view_component > > | list_extended_attributes (span< byte > tofill) const noexcept |
| Fill the supplied buffer with the names of all extended attributes set on this file or directory, returning a span of path view components. More...
|
|
virtual result< span< byte > > | get_extended_attribute (span< byte > tofill, path_view_component name) const noexcept |
| Retrieve the value of an extended attribute set on this file or directory. More...
|
|
virtual result< void > | set_extended_attribute (path_view_component name, span< const byte > value) noexcept |
| Sets the value of an extended attribute on this file or directory. More...
|
|
virtual result< void > | remove_extended_attribute (path_view_component) noexcept |
| Removes the extended attribute set on this file or directory. More...
|
|
result< size_t > | copy_extended_attributes (const fs_handle &src, bool replace_all_local_attributes=false) noexcept |
| Copies the extended attributes from one entity to another, optionally replacing all the extended attributes on the destination. More...
|
|
A handle to something with a device and inode number.
- See also
algorithm::cached_parent_handle_adapter<T>
virtual result<void> llfio_v2_xxx::fs_handle::relink |
( |
const path_handle & |
base, |
|
|
path_view_type |
path, |
|
|
bool |
atomic_replace = true , |
|
|
deadline |
d = std::chrono::seconds(30) |
|
) |
| |
|
inlinevirtualnoexcept |
Relinks the current path of this open handle to the new path specified. If atomic_replace
is true, the relink atomically and silently replaces any item at the new path specified. This operation is both atomic and matching POSIX behaviour even on Microsoft Windows where no Win32 API can match POSIX semantics.
Note that if atomic_replace
is false, the operation may be implemented as creating a hard link to the destination (which fails if the destination exists), opening a new file descriptor to the destination, closing the existing file descriptor, replacing the existing file descriptor with the new one (this is to ensure path tracking continues to work), then unlinking the previous link. Thus native_handle()
's value may change. This is not the case on Microsoft Windows nor Linux, both of which provide syscalls capable of refusing to rename if the destination exists.
If the handle refers to a pipe, on Microsoft Windows the base path handle is ignored as there is a single global named pipe namespace. Unless the path fragment begins with \
, the string \??\
is prefixed to the name before passing it to the NT kernel API which performs the rename. This is because \\.\
in Win32 maps onto \??\
in the NT kernel.
- Warning
- Some operating systems provide a race free syscall for renaming an open handle (Windows). On all other operating systems this call is racy and can result in the wrong file entry being relinked. Note that unless
flag::disable_safety_unlinks
is set, this implementation opens a path_handle
to the source containing directory first, then checks before relinking that the item about to be relinked has the same inode as the open file handle. It will retry this matching until success until the deadline given. This should prevent most unmalicious accidental loss of data.
- Parameters
-
base | Base for any relative path. |
path | The relative or absolute new path to relink to. |
atomic_replace | Atomically replace the destination if a file entry already is present there. Choosing false for this will fail if a file entry is already present at the destination, and may not be an atomic operation on some platforms (i.e. both the old and new names may be linked to the same inode for a very short period of time). Windows and recent Linuxes are always atomic. |
d | The deadline by which the matching of the containing directory to the open handle's inode must succeed, else errc::timed_out will be returned. |
- Memory Allocations\n Except on platforms with race free syscalls for renaming open handles (Windows), calls
current_path()
via parent_path_handle()
and thus is both expensive and calls malloc many times.
Reimplemented in llfio_v2_xxx::symlink_handle, and llfio_v2_xxx::mapped_file_handle.
virtual result<void> llfio_v2_xxx::fs_handle::set_extended_attribute |
( |
path_view_component |
name, |
|
|
span< const byte > |
value |
|
) |
| |
|
inlinevirtualnoexcept |
Sets the value of an extended attribute on this file or directory.
To prevent collision in a globally visible resource, there is a convention whereby you ought to namespace the names of your values as namespace.attribute
e.g. appname.setting
to prevent unintentional collision with other programs. Obviously, do choose a unique appname
if there is any chance another program might use the same namespace name.
On POSIX, there are additional namespacing requirements: before your value name, you need to prefix one of user
or system
, so the actual name you might set would be user.appname.propname
. Windows does not have the user
/system
prefix requirement, but it does no harm to do the exact same on Windows as on POSIX.
The host OS and target filing system choose the limits on value size, and will fail accordingly. Some impose a maximum of 64Kb for all names and values per inode, others have a 4Kb maximum value size, there are lots of combinations. You are probably safest not setting many names, and keep the values short.
- Warning
- Extended attributes are 'brittle' because they can get silently wiped at any moment. Never store anything in extended attributes which cannot be recalculated if missing. The ideal use case for extended attributes is as a cache of additional metadata about a file or directory e.g. "I last checked this directory at timestamp X", or "the MD5 hash at last modified
timestamp X for this file was Y". Also remember that other processes can and do arbitrarily modify extended attributes concurrent to you.
Windows only
This API is implemented as file alternate data streams, rather than the Extended Attributes API as accessed via NtSetEaFile()
and NtQueryEaFile()
(which actually modify the file alternate data stream $EA
in any case).
The reason why is that NtSetEaFile()
can only append new records to EA storage. It cannot deallocate any existing EA records, if you try to do so you will get STATUS_EA_CORRUPT_ERROR
. You can append setting the same name to a different value, which can include a null value which then appears as if the name is no longer there. But there is a cap of 64kB for the EA record, and once it is consumed, it is gone forever for that inode.
Obviously that doesn't map at all well onto POSIX extended attributes, where you can set the value of an attribute as frequently as you like. The closest equivalent on Windows is therefore file alternate data streams, even though the attribute's value is then worked with as a whole proper file with all the attendant performance consequences.
As a result, name
must be a valid filename and not contain any characters not permitted in a filename. We use the NT API here, so the character restrictions are far fewer than for the Win32 API e.g. single character names do NOT cause misoperation like on Win32.