2.0 is finally here! The main reason for a semver-major release is that a lot of cleanup was needed that involved breaking changes (like removing deprecated APIs). This release does include some big features though!
How many downloads?
Before getting into the details of this release, I wanted to thank the users of ZenFS. ZenFS and Utilium have now received over 1,000,000 downloads (yes, one million). I'm proud of what ZenFS has matured into, and I couldn't have done this without the community. So, thank you all for supporting the project, even if just by downloading it.
Extended attributes / xattr
This release adds full support for extended attributes (a.k.a xattr), which behave the same as on Linux. Node.js doesn't even have an API for this yet! This allows you to store arbitrary metadata on files, though a limit of 1 KiB per attribute value is imposed for performance and sanity. Like Linux, xattr names are namespaced— you will need to use the user namespace. See #189 for the initial issue.
ioctl and inode flags
With the new ioctl and ioctlSync functions, you can do a few cool things:
1. Inode flags
Using the IOC.GetFlags and IOC.SetFlags commands, the flags on an file can be changed. At the moment, these are the flags that affect VFS behavior:
NoAtime: When set, theatimeof files will not be updated. This replaces the experimentaldisableUpdateOnReadconfiguration flag.Sync: When set, files will be synced to the file system immediately following any changes. This is off by default, meaning any changes will only be synced once the file is closed. This replaces the experimentalonlySyncOnCloseconfiguration flag.
These flags are currently only available on a per-file basis, though support for FS-wide flags will likely be added to mount in a minor release in the near future.
2. File "versions"
IOC.GetVersion and IOC.SetVersion manipulate the version field of inodes. While this field isn't used internally, it could be useful for some use cases— go crazy!
3. File system commands
Note
Other than IOC.GetLabel/IOC.SetLabel, the FS-level ioctl commands only exist for completeness and should not be used.
IOC.GetLabelandIOC.SetLabelcan be used to read and write the label of a file system.IOC.GetUUIDwill retrieve the UUID of a file system. At the moment, each file system instance is assigned a random UUID when instantiated. OnlySingleBufferpersists the UUID.IOC.GetSysfsPathjust gives you/sys/fs/${fs.name}/${fs.uuid}.sysfsis very complicated and has not be implemented.IOC.GetXattr/IOC.SetXattrare not related to extend attributes. These are for working with astruct fsxattr. This structure has not been fully implemented, you should not use it.
As of this release, there is not mechanism for file systems to register ioctl command handlers. This is planned for a future minor release.
Contexts
This release makes contexts more powerful by introducing context ids, parent/children tracking, context-dependent working directories, and context-dependent file descriptors. The exported boundContexts Map can be used to access all of the bound contexts (a notable use case is /proc). You can create a child of a BoundContext using its bind method.
Also, this release fixed CredentialsInit not being plural, improves the types of BoundContext, and changes chroot to always be in-place and perform more anti-escape checks. mounts is no longer accessible on the fs namespace export, since this could be used to escape a context.
Internally, a "default" context is used for unbound operations. This absorbs the old "default"/unbound credentials.
Internal API changes: metadata, synchronization, and files
This release significantly improves how metadata and synchronization is handled internally.
- The internal
Fileclass has been completely absorbed into the VFS. This comes with some nice performance and maintainability benefits. You can look atSyncHandlefor the synchronous logic fromFile. - The
idproperty ofFileSystemhas been renamed totype, since it is used to identify the class rather than the instance, which was ambiguous. - A new
touchmethod has been added toFileSystem.touchonly updates metadata. All of the internal metadata updates now go through this new method. FileSystem.syncno longer takes any parameters. It is a no-op for current backends, though it can likely be used as a barrier for asynchronous operations in the future.- All of the internal APIs for passing around metadata now use
InodeLikeorInodeinstead ofStatsLike. - Whenever an inode is updated, its
ctimeis now changed automatically. - The upgrade path for format 1-3 inodes has been completely removed. These are from much older versions of ZenFS, if you are using one of these versions, please upgrade to 1.11 first.
- The
createFileandmkdirmethods ofFileSystemhave had theirmodeparameter merged intoCreationOptions. (PureCreationOptionshas been removed). - File open flags are now represented using numbers instead of strings internally, which improved performance and simplified some checks and imports.
- Added an internal
hasAccessfunction, so permissions can be checked without copying an inode and creating a newStatsinstance, significantly improving performance.
Configuration and logging
- Passing a boolean-returning function for the
typeof an option is now supported. - The
MountConfigurationused for a backend is now passed to that backend'sisAvailablefunction. (#196) - Improved backend options
type. Configuration.logis no longer experimental.- The built-in log formatting has been overhauled. Read the documentation on
log.fancyfor more information. - The error thrown when sync preloading is disabled is no longer written to the log.
- Logging in tests has been improved.
Other changes
- The
readLinesmethod ofFileHandlehas finally been implemented. This actually involved implementing most of thenode:readlinemodule, which can be imported from@zenfs/core/readline.js. src/vfs/path.tshas been moved tosrc/path.ts. You can import from@zenfs/core/path.js.- Added support for opening files with the synchronous flag (
s). - File descriptor numbers now start at 4.
- Access Control Lists (ACLs) have been implemented, though they are not checked for now. (#194)
Deviceinode data can now be customized by the device driver.- Fixed device reads and writes not working correctly with device sizes.
- Fixed multiple problems with
ReadStream. (#193) - All of the code for the
Portbackend has been consolidated intosrc/backends/port.ts. - The prefix in
Passthroughis no longer normalized. (#203) - Refactored
vfs/config.tsfor performance. - Fixed the metadata offset not being set on fresh super blocks for
SingleBuffer. (#205, thanks @tbrockman) - Fixed streaming methods not checking if the file was closed.
- Fixed
symlinkSyncnot closing the file it opened. - Fixed an access check missing in
statSync. - The RPC code used for
Porthas been refactored. - The
encode/decodeUTF8/Rawfunctions andConcretetype have been moved to Utilium.