Filesystems in Lua Userspace
Here you can find a list of the functions present in the module and how to use them. Flu main module follows Lua package system, see the Lua 5.1 manual or Lua 5.2 manual for further explanations.
Quick links:
The flu
module has very few functions, most of the magic happens inside the fs
table passed to flu.main
.
flu.main (argv, fs)
Starts a new filesystem daemon. argv
is an array containing additionnal parameters to pass to the FUSE library. fs
is a table (or any indexable object) containing methods of the FUSE filesystem you are trying to create.
local luafs = {}
function luafs.getattr(path, stat)
error(flu.errno.ENOSYS)
end
local argv = {"luafs", select(2, ...)}
flu.main(argv, luafs)
flu.get_context ([tbl])
Obtain information about the context of the current FUSE request. A table is returned containing fields uid
, gid
and pid
(user, group and thread id of the calling process, respectively). If no arguments are given, a new table is created. If a table is passed as an argument, it is reused and fields are set in it instead.
These methods may be present in the fs
object passed to flu.main
. They are all optional, though without them your filesystem may not work properly. See example filesystems available in Flu packages for minimal requirements.
Below each functon is described with the parameters they are called with, and the expected return values on normal operation. Most functions though have no return value. To express error conditions, regular Lua error should be thrown with error
. The thrown error though have to be errno userdata values as found in the flu.errno table. For example:
error(flu.errno.EINVAL)
They are named methods here, but they are called as Lua function, without a self parameter. To maintain state, use upvalues.
As of FUSE 2.6, there are six FUSE methods that are not bound by Flu: and init
, destroy
, lock
and bmap
which I haven't used yet and are a bit complicated to bind, and getdir
and utime
which are obsolete.
stat = fs.getattr (path)
Get file attributes. stat
should be a table, with some of the following fields set:
dev
, number, ID of device containing fileino
, number, inode numbermode
, a set or a string, file type and permissions. If mode is a set, it's made of the recognized mode flags listed below. If it's a string, it's one of the predefined modes described below.nlink
, number, number of hard linksuid
, number, user ID of ownergid
, number, group ID of ownerrdev
, number, device ID (if special file)access
, number, time of last accessmodification
, number, time of last modificationchange
, number, time of last status changesize
, number, total size, in bytesblocks
, number, number of blocks allocatedblksize
, number, blocksize for filesystem I/OThis table is compatible with LuaFileSystem, though the default access rights for mode
strings (as described below) may not suit you.
The dev
and blksize
fields are ignored. The ino
field is ignored except if the use_ino
mount option is given.
Note that for the find command line utility to work in your filesystem, the nlink
field must be properly filled. See this FUSE FAQ entry for more details.
Mode flags:
blk
, the file is a block devicechr
, the file is a character devicefifo
, the file is a FIFOreg
, the file is a regular filedir
, the file is a directorylnk
, the file is a symbolic linksock
, the file is a socketrusr
, owner has read permissionwusr
, owner has write permissionxusr
, owner has execute permissionrgrp
, group has read permissionwgrp
, group has write permissionxgrp
, group has execute permissionroth
, others have read permissionwoth
, others have write permissionxoth
, others have execute permissionsuid
, set UID bitsgid
, set-group-ID bitsvtx
, sticky bitPredefined modes:
'file'
, equivalent to reg
, rusr
, wusr
, rgrp
and wgrp
'directory'
, equivalent to dir
, rusr
, wusr
, xusr
, rgrp
, wgrp
and xgrp
'link'
, equivalent to lnk
, rusr
, wusr
, rgrp
and wgrp
'socket'
, equivalent to sock
, rusr
, wusr
, rgrp
and wgrp
'named pipe'
, equivalent to fifo
, rusr
, wusr
, rgrp
and wgrp
'char device'
, equivalent to chr
, rusr
, wusr
, rgrp
and wgrp
'block device'
, equivalent to blk
, rusr
, wusr
, rgrp
and wgrp
'other'
, equivalent to an empty settarget = fs.readlink (path, size)
Read the target of a symbolic link. The target should be returned as a string, which size should not exceed size
.
function luafs.readlink(path, size)
return "/foo/"..path
end
fs.mknod (path, mode, rdev)
Create a file node. This is called for creation of all non-directory, non-symlink nodes. If the filesystem defines a create
method, then for regular files that will be called instead. mode
is a set, see fs.getattr
for a description of the recognized flags.
fs.mkdir (path, mode)
Create a directory. mode
is a set, see fs.getattr
for a description of the recognized flags.
fs.unlink (path)
Remove a file.
fs.rmdir (path)
Remove a directory.
fs.symlink (linkname, path)
Create a symbolic link. path
is the name of the link itself in the Flu filesystem, linkname
is the linked file.
fs.rename (oldpath, newpath)
Rename a file.
fs.link (oldpath, newpath)
Create a hard link to a file.
fs.chmod (path, mode)
Change the permission bits of a file. mode
is a set, see fs.getattr
for a description of the recognized flags.
fs.chown (path, uid, gid)
Change the owner and group of a file. uid
and gid
are numbers.
fs.truncate (path, size)
Change the size of a file.
fs.open (path, fi)
File open operation. fi
is a fuse_file_info
structure (see below). No creation, or truncation flags (creat
, excl
, trunc
) will be passed to fs.open
. Open should check if the operation is permitted for the given flags. Optionally open may also return an arbitrary file handle in the fh
field of the fuse_file_info
structure, which will be passed to all subsequent operations on that file.
The fuse_file_info
structure has the following members:
flags
, set, with the following flags recognized: append
, async
, creat
, direct
, directory
, excl
, largefile
, noatime
, noctty
, nofollow
, nonblock
, ndelay
, sync
, trunc
, rdwr
, rdonly
, wronly
writepage
, numberdirect_io
, booleankeep_cache
, booleanflush
, booleanfh
, number, the file handle that the filesystem can write tolock_owner
, numberdata = fs.read (path, size, offset, fi)
Read data from an open file. size
is the amount of data required in bytes. offset
is a position inside the file. See fs.open
for a description of fi
.
Read should return a string of size
length exactly except on end of file or on error, otherwise the rest of the data will be substituted with zeroes. An exception to this is when the direct_io
mount option is specified, in which case the return value of the read system call will reflect the return value of this operation.
fs.write (path, buf, offset, fi)
Write data to an open file. buf
is a string containing the written data. offset
is a position inside the file. See fs.open
for a description of fi
.
Write should return exactly the number of bytes requested except on error. An exception to this is when the direct_io
mount option is specified (see read operation).
stat = fs.statfs (path)
Get file system statistics. stat
should be a table, with some of the following fields set:
bsize
, number, file system block sizefrsize
, number, fragment sizeblocks
, number, size of fs in frsize unitsbfree
, number, # free blocksbavail
, number, # free blocks for non-rootfiles
, number, # inodesffree
, number, # free inodesfavail
, number, # free inodes for non-rootfsid
, number, file system IDflag
, table, mount flags as a Lua set, with the following recognized flags: rdonly
, nosuid
.namemax
, number, maximum filename lengthThe frsize
, favail
, fsid
and flag
fields are ignored.
fs.flush (path, fi)
Possibly flush cached data. See fs.open
for a description of fi
.
BIG NOTE: This is not equivalent to fsync(). It's not a request to sync dirty data.
Flush is called on each fs.close
of a file descriptor. So if a filesystem wants to return write errors in fs.close
and the file has cached dirty data, this is a good place to write back data and raise any errors. Since many applications ignore fs.close
errors this is not always useful.
NOTE: The fs.flush
method may be called more than once for each fs.open
. This happens if more than one file descriptor refers to an opened file due to dup(), dup2() or fork() calls. It is not possible to determine if a flush is final, so each flush should be treated equally. Multiple write-flush sequences are relatively rare, so this shouldn't be a problem.
Filesystems shouldn't assume that fs.flush
will always be called after some writes, or that it will be called at all.
fs.release (path, fi)
Release an open file. See fs.open
for a description of fi
.
Release is called when there are no more references to an open file: all file descriptors are closed and all memory mappings are unmapped.
For every open() call there will be exactly one release() call with the same flags and file descriptor. It is possible to have a file opened more than once, in which case only the last release will mean, that no more reads/writes will happen on the file. Errors in release are ignored.
fs.fsync (path, datasync, fi)
Synchronize file contents. If the datasync
parameter is true
, then only the user data should be flushed, not the meta data. See fs.open
for a description of fi
.
fs.setxattr (path, name, value, flags)
Set an extended attribute on the file. flags
is a set with the following recognized flags: create
, replace
. If create
is set the method should throw an error if the attribute exists. If replace
the method should throw when the attribute doesn't exist.
value = fs.getxattr (path, name)
Get an extended attribute. If the attribute doesn't exist ENODATA
should be thrown.
list = fs.listxattr (path)
Return a list of extended attribute names. list
should be an array of strings.
fs.removexattr (path, name)
Remove an extended attribute. If the attribute doesn't exist ENODATA
should be thrown.
fs.opendir (path, fi)
Open directory. This method should check if the open operation is permitted for this directory. See fs.open
for a description of fi
.
fs.readdir (path, filler, fi)
Read directory. filler
is a function with the prototype filler(name)
that must be called for each directory entry, and that will return false
when the output buffer is full, true
otherwise. See fs.open
for a description of fi
.
fs.releasedir (path, fi)
Release a directory. See fs.open
for a description of fi
.
fs.fsyncdir (path, datasync, fi)
Synchronize directory contents. If the datasync
parameter is true
, then only the user data should be flushed, not the meta data. See fs.open
for a description of fi
.
fs.access (path, mask)
Check file access permissions. This will be called for the access()
system call. If the 'default_permissions'
mount option is given, this method is not called.
This method is not called under Linux kernel versions 2.4.x.
fs.create (path, mode, fi)
Create and open a file. mode
is a set, see fs.getattr
for a description of the recognized flags. See fs.open
for a description of fi
.
If the file does not exist, first create it with the specified mode
, and then open it.
If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the mknod() and open() methods will be called instead.
fs.ftruncate (path, size, fi)
Change the size of an open file. See fs.open
for a description of fi
.
This method is called instead of the fs.truncate
method if the truncation was invoked from an ftruncate()
system call.
If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the fs.truncate
method will be called instead.
fs.fgetattr (path, st, fi)
Get attributes from an open file.
This method is called instead of the fs.getattr
method if the file information is available.
Currently this is only called after the fs.create
method if that is implemented (see above). Later it may be called for invocations of fstat()
too.
fs.utimens (path, access, modification)
Change the access and modification times of a file with nanosecond resolution. access
and modification
are Lua tables with two fields each:
sec
, number, time in secondsnsec
, number, the sub-second portion of the time, in nanoseconds