Module luafs

Lets users write filesystems in Lua.

Please see the user guide for explanation on creating filesystems.

This document describes not functions you can call but functions your filesystem objects should implement.

This document uses the terms “functions”, “operations” and “operators” interchangeably.

Signaling errors

An operator may signal an error by returning a pair or a triad: first a nil, then an Operating System’s error code (either in the second or third place; this “fuzziness” is for compatibility with the standard Lua OS functions, which by convention return a triad).

You can get by, however, by just returning nothing (or a nil): an appropriate error code will be deduced for you.

For example, if a stat operator returns nothing, it’s as if a ENOENT pair (“No such file or directory”) was returned:

function MyFS:stat(pathname)
  if pathname == "one.txt" then
    return { type="regular", size=1000 }
  elseif pathname == "extra" then
    return { type="directory" }
  end
  -- implicitly return (nil, ENOENT) for any other pathanme.
end

As another example, an implementation of a mirror filesystem that just forwards calls to another one is trivial: due to the way Lua’s “return” preserves multiple values (the triads, in our case), the errors are propagated, as desired, without special effort on our part.

Functions

chdir(session, path) Enters a directory.
chmod(session, path, mode) Changes the permission bits of a file.
chown(session, path, owner, group) Changes the ownership of a file.
close(session, filehandle) Closes a file.
close_session(session) Cleans up after a session.
file(session, pathname, mode, info) Returns a file.
flush(session, path) Flushes a directory index.
get_name(session) Returns a path representing the session.
is_same_session(session, vpath) Determines whether a path belongs to this session.
link(session, path1, path2) Creates a hard link.
lstat(session, pathname) Returns stat information about a file.
mkdir(session, path) Creates a directory.
mknod(session, path, mode, dev) Creates a special (or ordinary) file.
open(session, pathname, mode, info) Opens a file.
open_session(session) Initializes a session.
read(session, filehandle, count) Reads from a file.
readdir(session, dir) Returns a directory’s contents.
readlink(session, path) Reads the contents of a symbolic links.
rename(session, path1, path2) Renames a file.
rmdir(session, path) Deletes a directory.
run(session, path) Runs a program.
seek(session, filehandle, whence, offs) Seeks in a file.
stat(session, pathname) Returns stat information about a file.
symlink(session, path1, path2) Creates a symbolic link.
unlink(session, path) Deletes a file.
utime(session, path, modtime, actime) Changes file last access and modification times.
write(session, filehandle, buf) Writes to a file.

Properties

prefix The filesystem’s ID, or “URL scheme”.

Panel-integration properties

glob Determine panel integration by a glob pattern.
iglob Determine panel integration by case-insensitive glob pattern.
iregex Determine panel integration by case-insensitive Perl-compatible regex.
regex Determine panel integration by Perl-compatible regex.


Functions

chdir(session, path)
Enters a directory.

If not implemented, true (meaning: success) is returned.

If nothing is returned it’s as if an EACCES triad was returned (“Permission denied”).

chmod(session, path, mode)
Changes the permission bits of a file.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

chown(session, path, owner, group)
Changes the ownership of a file.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

close(session, filehandle)
Closes a file.

To signal success, the function should return some truth value. Remember to do this, because, although many programmers neglect to check the return value of close(), proper code does, and if you don’t signal success the code will fail.

If the function returns nothing, it’s as if an EIO triad was returned (“Input/output error”).

Parameters:

  • session
  • filehandle Whatever open previously returned.
close_session(session)
Cleans up after a session.

You may use this operator to delete temporary files you created or close a socket.

See discussion in the user guide.

file(session, pathname, mode, info)

Returns a file.

Implementing the file() operator is an easy alternative to implementing open/read/write/seek/close.

The file() operator gets exactly the same arguments open gets. The difference is that ‘file’ may not return any arbitrary object but either of:

  • A string, which stands for the whole contents of the file. In this case the file can only be opened for reading. If it’s opened for writing, a “Read-only file system” error will be generated.

  • A file object (e.g., the result of fs.open, io.open or io.popen (though the latter may cause trouble for tasks that wish to seek in the file, like MC’s editor)).

(or, it may return a triad, or nothing; same as open.)

function MyFS:file(pathname)
  if pathname == "a.txt" then
    return "contents of a.txt"
  end
end
flush(session, path)
Flushes a directory index.

When you reload a panel (e.g. by pressing C-r) this operation is invoked. You may use it to invalidate a cached directory index.

Parameters:

  • session
  • path The directory to flush, for granular control. You may of course ignore this and flush your whole cache.
get_name(session)
Returns a path representing the session.

This path is shown in the “Active VFS” dialog of MC.

is_same_session(session, vpath)
Determines whether a path belongs to this session.

When a path is accessed, every session is asked whether this path is under its control. The first session that answer true is used to serve the request. If the path belongs to no session, a new session is created (see open_session).

If this operator isn’t implemented, the following default implementation will take place:

function FileSystem:is_same_session(vpath)
   return self.parent_path.str == vpath:parent().str
end

(This default logic favors archive-style filesystems and is explained in the user guide. For non-archives, simply make this operator return 'true'.)

Parameters:

  • session
  • vpath The path to test. (A fs.VPath is used, instead of a string, for easier access to parsed elements such as username and password.)
link(session, path1, path2)
Creates a hard link.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

See also symlink.

Parameters:

  • session
  • path1 Source.
  • path2 Destination.
lstat(session, pathname)
Returns stat information about a file.

Like stat but doesn’t dereference symbolic links.

If not implemented, the stat function will be used instead.

Parameters:

  • session
  • pathname The pathname to the file (or directory).
mkdir(session, path)
Creates a directory.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

mknod(session, path, mode, dev)
Creates a special (or ordinary) file.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

open(session, pathname, mode, info)

Opens a file.

This function should return some “file handle”, which is whatever Lua value you wish it to be. MC donesn’t look inside this value: it’s passed as-is to the other operators (read, write, seek, close).

If the function returns nothing, it’s as if the the triad ENOENT (“No such file or directory”), when reading, or EROFS (“Read-only file system”), when writing, was returned.

The argument this operator gets:

  • session – The session.

  • pathname – The pathname of the file.

  • mode – Open mode. One of: “r”, “w”, “a”, “r+”, “w+”, “a+”. (This is an approximate translation of info.posix_flags (see next).)

  • info – A table with:

- posix_flags - The open mode given in numeric code. A bitwise-or of
  O_RDONLY, O_WRONLY, O_RDWR, etc.
- creation_mode - When creating a file, the permission bits to use.
- mc_flags - The same as posix_flags, except that it may include the
  MC-specific flag O_LINEAR.
open_session(session)
Initializes a session.

See discussion in the user guide and at is_same_session.

You're free to modify the session object, but make sure not to touch the few internal variables already stored there. Among the variables already there:

  • parent_path: points to the path containing our session. E.g., when accessing "/outer/path/myfs://inner/path", parent_path is "/outer/path".

You're allowed to throw an exception from open_session. For example, you may want to do that if an external program you're dependent on isn’t installed. See examples in mysql.lua and sqlite.lua.

read(session, filehandle, count)
Reads from a file.

Must return a triad on error.

On success, the string read should be returned. On EOF, the function may return either an empty string or nothing (therefore a triad must be returned on real error).

If the function is not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

Parameters:

  • session
  • filehandle Whatever open previously returned.
  • count The number of bytes to read.
readdir(session, dir)
Returns a directory’s contents.

Returns a list of all files in a directory.

Each entry is a string, which is the filename (the basename only; don’t use slashes). Or an entry may be a list whose first element is a string and the second a number denoting the inode.

If the function returns nothing, it’s as if an ENOENT triad was returned (“No such file or directory”).

function MyFS:readdir(dir)
  if dir == "" then  -- the top directory.
    return {"one.txt","two.txt","three.txt"}
  end
end

By default, each file is considered a regular file having zero size. If you want to override this, implement stat.

If the function is not implemented, it’s as if the filesystem contains an empty top directory.

Parameters:

  • session
  • dir The directory. The top directory is “” (an empty string).
readlink(session, path)
Reads the contents of a symbolic links.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

rename(session, path1, path2)
Renames a file.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

Parameters:

  • session
  • path1 Source.
  • path2 Destination.
rmdir(session, path)
Deletes a directory.

(This is a low-level function; The directory must be empty.)

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

run(session, path)
Runs a program.

Invoked when you press ENTER over an executable. If not implemented, nothing then happens.

seek(session, filehandle, whence, offs)
Seeks in a file.

Parameters:

  • session
  • filehandle Whatever open previously returned.
  • whence One of “set”, “cur”, “end”.
  • offs A number.
stat(session, pathname)

Returns stat information about a file.

Optional. If you don’t implement this, all files will be regarded a regular files having zero size.

Returns either a fs.StatBuf or a table to be passed to its constructor. As a convenience, if you provide a table, the timestamps, if missing, will be initialized to the time the session was opened.

If the function returns nothing, it’s as if an ENOENT triad was returned (“No such file or directory”).

If the function is not implemented, every pathname queried will be reported as existing (and being a regular file of zero size).

function MyFS:stat(pathname)
  if pathname == "one.txt" or pathname == "two.txt" then
    return { size = 1000 }
  elseif pathname == "three" then
    return { type = "directory" }
  else
end

Parameters:

  • session
  • pathname The pathname to the file (or directory).
symlink(session, path1, path2)
Creates a symbolic link.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

Parameters:

  • session
  • path1 Source.
  • path2 Destination.
unlink(session, path)
Deletes a file.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

utime(session, path, modtime, actime)
Changes file last access and modification times.

If not implemented, it’s as if an E_NOTSUPP triad was returned (“Function not implemented”).

write(session, filehandle, buf)
Writes to a file.

To signal success, the function should return some truth value. It may return the number of bytes written (if it doesn’t, this number will be assumed to be the written strings' length.)

If the function returns nothing, it’s as if an EIO triad was returned (“Input/output error”).

If the function is not implemented, it’s as if an EROFS triad was returned (“Read-only file system”).

Parameters:

  • session
  • filehandle Whatever open previously returned.
  • buf The string to write.

Properties

prefix
The filesystem’s ID, or “URL scheme”.

The prefix property, when embedded in a path, identifies the path (whole or part of it) as belonging to a certain filesystem.

for example, given a filesystem that handles ZIP files,

ZipFS = {
  prefix = "zip",
  ...
}

then typing a path like /home/john/book.7z/zip://text/chapter1.txt will access the file text/chapter1.txt within the ZIP archive book.7z.

For filesystems that represent archives, the prefix doesn’t have to equal the archive’s suffix. We could just as well have chosen the prefix “doodle” for our ZipFS filesystem.

As another example, given a filesystem that displays your MySQL databases,

MysqlFS = {
  prefix = "mysql",
  ...
}

then doing cd mysql:// will navigate to a directory listing the databases.

Panel-integration properties

These properties determine whether pressing ENTER on a file will cause MC to cd into it.

For example, when given the following filesystem,

local MarkdownFS = {
  prefix = "markdown",
  glob = "*.md",
  ...
}

then standing over the file “cheats.md” and pressing ENTER will cd you to “cheats.md/markdown://”.

This is a convenience feature only. You can always cd “by hand” (or by instructing MC to do so in your extension file).

glob
Determine panel integration by a glob pattern.

See example at iglob.

iglob

Determine panel integration by case-insensitive glob pattern.

Example:

local MarkdownFS = {
  prefix = "markdown",
  iglob = "*.{md,mkd,mdown}",
  ...
}
iregex

Determine panel integration by case-insensitive Perl-compatible regex.

Example:

local MarkdownFS = {
  prefix = "markdown",
  iregex = [[\.(md|mkd|mdown)$]],
  ...
}
regex
Determine panel integration by Perl-compatible regex.

See example at iregex.

generated by LDoc 1.4.3 Last updated 2016-08-23 17:29:40