Documentation
¶
Overview ¶
Package mountfs is the filesystem behind `filex mount` — a remote filex server, seen as a folder on the machine that runs the command.
Why this exists when NFS and SFTP already do ¶
Both of those need something on the other end that filex does not control: NFSv3 has no encryption and belongs on a LAN, and an SFTP mount needs sshfs or WinFsp installed and configured. `filex mount` is the one that works from anywhere over the same HTTPS the web app uses, with the same session token, through whatever proxy or tunnel is already between the two — because it is just the REST API with a filesystem in front of it.
What it is not ¶
It is not a sync. Nothing is copied to the machine except a bounded read cache; closing the mount leaves nothing behind. `filex sync` is still the answer for "keep a folder on my laptop", and this is the answer for "open one file out of a hundred thousand without downloading the other 99,999".
The shape, and the reason for it ¶
Reads are cached in fixed blocks. A mounted filesystem gets asked for 128 KiB at arbitrary offsets by whatever program the user opened, and answering each one with its own HTTPS request would make a video unplayable; a block cache turns a sequential read into a handful of large requests and a random seek into one.
Writes are spooled whole and uploaded on close. That is not laziness: the REST API takes a complete file, there is no ranged write on the wire, and a partial upload committed under the real name would replace a good file with a torn one. The cost is that a 4 GB write needs 4 GB of scratch space, which is bounded and stated rather than discovered.
Index ¶
- Variables
- type Config
- type ErrKind
- type FS
- func (f *FS) Describe() string
- func (f *FS) Forget(p string)
- func (f *FS) MaxSpool() int64
- func (f *FS) Mkdir(ctx context.Context, p string) error
- func (f *FS) ReadAt(ctx context.Context, mountPath string, dst []byte, off int64, size int64) (int, error)
- func (f *FS) ReadDir(ctx context.Context, p string) ([]*cliclient.Stat, error)
- func (f *FS) ReadOnly() bool
- func (f *FS) Remove(ctx context.Context, p string) error
- func (f *FS) Rename(ctx context.Context, oldPath, newPath string) error
- func (f *FS) SpoolPath() (*os.File, error)
- func (f *FS) Stat(ctx context.Context, p string) (*cliclient.Stat, error)
- func (f *FS) Upload(ctx context.Context, mountPath, localPath string) error
- type Server
Constants ¶
This section is empty.
Variables ¶
var ( // ErrMountFailed — the driver refused. Almost always a mountpoint that is // in use, or a drive letter that is taken. ErrMountFailed = errors.New( "the filesystem driver refused to mount (is the drive letter or folder already in use?)") // ErrMountTimeout — it neither failed nor came up. On Windows this is // usually WinFsp missing: the DLL loads, the mount never registers. ErrMountTimeout = errors.New( "the mount did not come up (on Windows, check that WinFsp is installed - https://winfsp.dev)") // ErrUnmountFailed — the driver would not let go. ErrUnmountFailed = errors.New("could not unmount") )
Mount failures, shared so a caller can tell them apart on any platform.
var ErrTooLarge = errors.New("mountfs: file is larger than the write spool allows")
ErrTooLarge is a file bigger than the write spool allows.
var ErrUnsupported = errors.New(
"filex mount needs a filesystem driver, and on this platform there is none " +
"it can use. Linux needs nothing (FUSE is in the kernel) and Windows " +
"needs WinFsp, a free separate install - https://winfsp.dev. macOS is " +
"not supported: it needs macFUSE, whose licence forbids a commercial " +
"program from installing it and whose Go binding needs a C toolchain " +
"filex deliberately does not use. There, use `filex sync` for a folder, " +
"or the desktop app")
ErrUnsupported is what Mount returns where there is no FUSE driver.
⚠ Declared HERE rather than in the platform file so a caller can test for it on every OS — a Linux build that cannot see the sentinel would print a raw error instead of the sentence that tells somebody what to install.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Client talks to the remote filex. Required.
Client *cliclient.Client
// Remote is what to mount: "" for every storage the account can see,
// "docs://" for one storage, "docs://projects/acme" for a subtree.
Remote string
// ReadOnly refuses every write. The safe default for a mount somebody
// pointed at a production server to look at something.
ReadOnly bool
// BlockSize is the read granularity. 0 uses defaultBlockSize.
BlockSize int64
// CacheBlocks bounds the read cache, in blocks. 0 uses the default.
CacheBlocks int
// SpoolDir is where writes are spooled. Empty uses the OS temp dir.
SpoolDir string
// MaxSpool caps one write. 0 uses the default.
MaxSpool int64
// AttrTTL is how long a listing or a stat is trusted.
//
// ⚠ Not zero. A filesystem call that always goes to the network makes `ls`
// on a large folder take seconds and a shell tab-completion feel broken;
// but a long TTL means somebody else's upload is invisible for that long.
// A few seconds is the honest middle, and it is a knob rather than a
// constant because the right answer differs between a laptop and a build
// machine.
AttrTTL time.Duration
}
Config wires the filesystem to a remote server.
type ErrKind ¶
type ErrKind int
ErrKind is what went wrong, in terms a filesystem can express.
const ( // ErrNone is success. ErrNone ErrKind = iota // ErrIO is the fallback: something failed and nothing more precise fits. ErrIO // ErrNotFound — the path is not there. ErrNotFound // ErrDenied — the caller may not do this. ErrDenied // ErrExists — something is already there. ErrExists // ErrReadOnlyFS — the mount, or the storage behind it, refuses writes. ErrReadOnlyFS // ErrNoSpace — a quota or a disk said no. ⚠ Distinct from ErrDenied on // purpose: "you are out of space" is a thing the user can act on, and // every file manager on both platforms shows it differently. ErrNoSpace // ErrTooBig — the file is larger than the write spool allows. ErrTooBig )
type FS ¶
type FS struct {
// contains filtered or unexported fields
}
FS is the remote filesystem.
func (*FS) Forget ¶
Forget drops cached metadata for a path and its parent.
⚠ The PARENT too, and that is the half people forget: after a create or a delete the parent's LISTING is what is wrong, and a stale listing is how a file the user just made does not appear in `ls`.
func (*FS) ReadAt ¶
func (f *FS) ReadAt(ctx context.Context, mountPath string, dst []byte, off int64, size int64) (int, error)
ReadAt fills p from the remote file at off, through the block cache.
func (*FS) Remove ¶
Remove deletes a file or directory.
⚠ It goes to the filex TRASH, like every other surface — the server decides that, not this client. Worth knowing when a user "deletes" from a mount and expects the space back immediately.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a live mount.
func (*Server) Mountpoint ¶
Mountpoint is where it is attached.