3
1
Implement a FUSE filesystem in minimum bytes.
Your program must do three things:
- Mounting the virtual filesystem to a directory
- Handling requests to enumerate files in that directory (showing one file)
- Handling requests to read the file in that directory
Rules:
ls
(a system program, you don't need to implement it) must showhello.txt
file (other unrelated files can also be visible, as well as errors may be printed).hello.txt
must be exact,68 65 6c 6c 6f 2e 74 78 74
in hex).cat
(a system program) pointed to the file should outputHello, world.
(punctuation, case and end of lines may differ. A bunch of zero bytes can also slip unnoticed). It can also becat m/hello.txt; echo
if there is no trailing newline.- It must be actual FUSE filesystem, not just a regular file created by your program. For example, freezing your program should freeze the
hello.txt
file (cat
andls
would hang). Creating a socket instead of mounting FUSE filesystem isn't an allowed workaround. Your mounted filesystem should be visible in/proc/mounts
(or platform analogue). - For 200 bytes penalty, you may depend on libfuse or use it's header files (or depend on the appropriate FUSE binding in some other language)
- Detaching is optional
- You program may be platform-specific. Somebody else on that platform should check and write a comment that it works (or not)
- Your program can't be a kernel module (
fuse.ko
is the involved kernel module on Linux and is considered a part of environtment, not your program) - Your program can access
/dev/fuse
(or platform analogue) directly. It may require root access (or changing permissions) for it if needed. It can also rely onfusermount
for the mounting step (like the example below). Whether usingfusermount
for mounting carry penalty or not I have not decided yet (because of I don't know implementation details enough): if the rest feels like talking to kernel directly then it should not be a problem. - Additional compilation and invocation parameters are added to the score. A directory to be mounted may be specified as a free (non-penalty) parameter or may be just hardcoded (like
m
)
Example (directly based on official hello.c):
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
static const char *hello_str = "Hello, world\n";
static const char *hello_path = "/hello.txt";
static int hello_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else if (strcmp(path, hello_path) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = strlen(hello_str);
}
return res;
}
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
filler(buf, hello_path + 1, NULL, 0);
return 0;
}
static int hello_open(const char *path, struct fuse_file_info *fi)
{
return 0;
}
static int hello_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
size_t len;
(void) fi;
if(strcmp(path, hello_path) != 0)
return -ENOENT;
len = strlen(hello_str);
if (offset < len) {
if (offset + size > len)
size = len - offset;
memcpy(buf, hello_str + offset, size);
} else
size = 0;
return size;
}
static struct fuse_operations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &hello_oper, NULL);
}
$ gcc -D_FILE_OFFSET_BITS=64 golffs.c -lfuse -o golffs
$ ./golffs m # uses fusermount under the hood
$ ls m
hello.txt
$ cat m/hello.txt
Hello, world
$ fusermount -u m
Score of the example: 1974 + 29 (compilation parameters) + 0 (invocation parameters) + 200 (penalty) = 2203
1"hello.txt must be exactly this hex" seems to collide with the next line "cat should output Hello, world. **punctuation, EOL and case may differ**" – cat – 2015-11-29T20:56:23.733
1The first is about the virtual file name, the second is about virtual file content. The former is exact, the latter should match
/^hello,?\s?world[.!;?]?\r?\n$?/im
(for example). – Vi. – 2015-11-29T20:58:00.2101Ohh, okay. I like this challenge because it gives real, non-golfing languages a chance; it will be a while before I have something that works. – cat – 2015-11-29T20:59:53.717
Wait, why are
cat
andls
builtins for the filesystem? shouldn't they be standalone binaries? – cat – 2015-11-29T21:00:55.9101
cat
andls
are assumed to be system binaries. They are used to test the filesystem. They are clarified because of for poorly behaving filesystems, using other programs (likedd
andfind
) can lead to different results (due to different syscalls or reaction to them). – Vi. – 2015-11-29T21:02:16.1871So we get a 200 byte penalty if we use the actual library, which is a kernel module (because in order for a filesystem to show up in
/proc/mounts
or haveudev
even sneeze at it, it needs to have some sort of kernel bus, specifically a module) but we also aren't allowed to make a kernel module, so we have to use the existing library ( on *ix, at least ) which means for Mac and GNU/Linux the 200 byte penalty is unavoidable. – cat – 2015-11-29T21:11:04.0631The
fuse.ko
kernel module is considered part of the system (like kernel or C library). Thelibfuse.so
library is considered part of your program. To avoid penalty, you should implement it on low level (on the level thelibfuse.so
itself is implemented), i.e. open/dev/fuse
and use it.fusermount
program may be used to get access to/dev/fuse
without requiring administrator access (assuming it does not take part in filesystem activity after starting up). – Vi. – 2015-11-29T21:14:47.487