6fs is a FUSE file system that stores all data in six files on an existing file system. These six files grow and shrink dynamically, and therefore always use only little more space than the data you store in 6fs.
6fs is useful for storing encrypted copies or backups of files on file systems that do not provide the full set of Linux/UNIX file systems features, e.g. an external USB device formatted with exfat, or a file server providing only SMB.
- Stores all data in six dynamically growing and shrinking files
- Supports encryption, including metadata and directory structures
- Supports all standard UNIX file system features such as permissions, ownership, time stamps, device files, sockets, named pipes, symbolic links and so on
- Can also be used as a RAM disk, using six growing/shrinking arrays in memory
6fs requires libfuse and libsodium.
It is based on autotools: use the typical autoreconf -fi; ./configure; make; make install
sequence to install it.
Usage: 6fs [options] <mountpoint>
Options:
--dir=<dir>
: The directory containing the six 6fs files. They will be automatically created if they do not exist yet. An empty argument will create a RAM disk instead.--max-size=<size>
: Set a maximum size for the 6fs file system. Suffixes K, M, G, T are supported. Note that this limit is only approximate for performance reasons. Recommended for RAM disks.--key=<keyfile>
: Activate encryption and read the 40-byte encryption key from the specified file. The key file should of course not be stored on the same medium as the 6fs files.--log=<logfile>
: Set a file to send log messages to. If the file name is empty, log messages are sent to syslog.--log-level=<level>
: Set a minimum level for log messages (debug, info, warning, error). Default is warning.--punch-holes=0|1
: Punch holes for unused blocks into the block data file to save disk space. Does not work on all file systems and costs performance. Disabled by default.
Example without encryption:
# Create mount point for 6fs
mkdir /mnt/6fs
# Mount 6fs, with its six data files residing in /mnt/usbdrive/6fs
6fs --dir=/mnt/usbdrive/6fs /mnt/6fs
# Use rsync to copy something into 6fs (just an example)
rsync -av /stuff/to/copy /mnt/6fs
# Unmount 6fs
fusermount -u /mnt/6fs
Example with encryption:
# Create random 40-byte key
dd if=/dev/urandom of=6fs-key bs=1 count=40
# Mount 6fs with encryption
6fs --dir=/mnt/usbdrive/6fs --key=6fs-key /mnt/6fs
The six files that 6fs is based on are the following:
inodemap.6fs
: bit map to manage inodesinodedat.6fs
: inode datadirenmap.6fs
: bit map to manage directory entriesdirendat.6fs
: directory entry datablockmap.6fs
: bit map to manage data blocksblockdat.6fs
: blocks of data, each containing 4096 bytes
The bit maps indicate with each bit (one or zero) whether the corresponding inode / directory entry / data block is currently used (one) or free (zero).
The data files are simple one-dimensional arrays of inode, directory entry, or block data.
Unused bits or array entries at the end of each file are removed so that the
files do not occupy more space than necessary. Moreover, with --punch-holes=1
unused data block entries are deallocated from the underlying file system if
that file system supports the fallocate
flag FALLOC_FL_PUNCH_HOLE
, so that
even unused data blocks in the middle of the array do not occupy disk space.
Each inode stores an index to the data associated with that inode (directory entries or data blocks). That index uses multilevel indirection to support up to 68853957121 entries, resulting in a maximum file size of 256.5 TiB.
Encryption is applied to the three array files, but not to the bit map files. Each array entry is encrypted using the libsodium secretbox-easy interface, and the nonce and authentication tag is stored together with the encrypted data.
An attacker that can read the 6fs files can see how many inodes, directory entries and data blocks your file system uses, but cannot see directory hierarchies, file names and other metadata, or file contents. An attacker that additionally has write access to the 6fs files can of course corrupt or delete them, but cannot modify encrypted data without being detected, and cannot manipulate the data in a way that will reveal the key.