ft: filesystem abstraction
intro⌗
ft
is a remote file browser, its function is to give any user(smartphone, raspberry pi, normal computer) the ability to transfer files to a number remote of storage units such as flash drives, phone and hard disks.
If that was the only intention with creating ft
then it wouldn’t be of much use really. ft
should support different file systems, such as network filesystems, filesystems for phones, cameras and other types aswell.
ft
’s server language, Go, provides a package in the standard library that defines clearly what a file system is. So, one must consider Go’s io/fs
as a good option in using it in this project, but there are several reasons why you shouldn’t.
go fs packages⌗
io/fs
simply isn’t flexible. The definition of a filesystem in io/fs
consists of a data structure with an Open
method.
Open(name string) (File, error)
Do note that the method essentially returns a read-only file, as file only implements io.Reader
, io.Closer
and Stat() (FileInfo, error)
. That’s literaly all.
That essentially means you cannot:
- Create Directories
- Remove files
- Create new files
- Create files with specific flags
- Modify already existing files
- Modify permissions and groups
Simply put, io/fs
is too abstract for a filesystem interface. There’s a slightly order and better package called afero
by user, spf13
who also made hugo. afero
, in contrast to io/fs
, is a lot better.
It has convenient abstractions that are implemented by the default os
package and pretty good data structures that allow for easier testing, see afero.NewMemMapFs()
.
But, while researching filesystem abstractions I thought: “Why go through all this trouble if this is not extensible”.
extensibility: an overview⌗
Extensibility is the capacity of being able to be extended. Extensibility can help a program stay secure and consistent while providing supreme usuability and power to the user.
One good case of this is the coreutils
defined by the POSIX standard. For those who do not know, the coreutils
are a collection of programs that are meant to do thing and doing it well.
A good example of using the coreutils
together is by wanting to search through a file. Normally, programs such as text-editors provide a feature like searching through a hot key such as CTRL+F
, where you could not only serach for word but also replace them.
In the coreutils
, it is much simple. First, you read all the contents of a file via a program named cat
. Second, you search for the word using the program grep
.
Via a process called piping, one program can read another program’s output. The practical application of this is as follows:
cat file.txt | grep "my word"
In essence, extensibility is a good trait to have. However, requiring the user to write a Go package to support their favorite file system was too much to gain extensibility.
Add to that the fact that these file system implementations some times need updates or have bugs in them, and you have a pretty high risk of making your software assiociated with unreliability and buggy behaivor.
In ft
’s situation, extensibility must come from outside and to that we can look forward to no abstraction but FUSE
.
fuse: filesystem in userspace⌗
Usually, filesystems must be implemented through a driver, similarly to how Microsoft Windows does in-order to support phones and cameras. But, this approach is rather inefficient as it required elevated privileges and bugs can crash a system.
fuse
is linux’s solution to mounting dynamic or otherwise ‘outsider’ filesystem. fuse
is a kernel module that defines an abstraction to mount file system as a normal user.
The pros of using fuse
for ft
are:
- Any programmer can implement, in their own language, a filesystem
ft
can later use that filesystem from an outside language such as C++- Performance, stability and reliability via using tested implementations.
conculsion⌗
While afero
provides a very good file system abstraction, it cannot compete with fuse
, not at the slightest. fuse
allows the end-user to customize how many directories are mounted at its root directory, allowing for pluggable phones, cameras, flash drives, and other sort of devices to co-exist in one space, making ft
extremely useful.
One thing I’d like to note is how useful afero
is in Go
packages. To test out internal packages, you do not have to depend on OS access but instead rely on afero
’s abstractions and using mock implementations. Definitely use afero
over io/fs
any time of the day since it is more developed and stable.