Skip to content

Instantly share code, notes, and snippets.

@apselon
Created December 3, 2020 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apselon/08446fca7ea48c2c01cce5e1c2374daf to your computer and use it in GitHub Desktop.
Save apselon/08446fca7ea48c2c01cce5e1c2374daf to your computer and use it in GitHub Desktop.
#define FUSE_USE_VERSION 30
#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <fuse3/fuse.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
enum ErrorCodes {
SUCCESS,
};
enum { MAX_SIZE = 1 << 20 };
struct FileSystem {
char data[MAX_SIZE];
char* files_start;
size_t numfiles;
size_t file_sizes[MAX_SIZE];
const char* file_names[MAX_SIZE];
} aifs = {};
int my_open(const char* path, struct fuse_file_info* fi)
{
++path;
int cur_file = -1;
for (size_t i = 0; i < aifs.numfiles; ++i) {
if (strcmp(aifs.file_names[i], path) == 0) {
cur_file = i;
break;
}
}
if (-1 == cur_file) {
return -ENOENT;
}
if (O_RDONLY != (fi->flags & O_ACCMODE)) {
return -EACCES;
}
return 0;
}
int my_read(
const char* path,
char* buf,
size_t size,
off_t off,
struct fuse_file_info* fi)
{
++path;
int cur_file = -1;
for (size_t i = 0; i < aifs.numfiles; ++i) {
if (strcmp(aifs.file_names[i], path) == 0) {
cur_file = i;
break;
}
}
if (-1 == cur_file) {
return -ENOENT;
}
size_t file_size = aifs.file_sizes[cur_file];
if (off > file_size) {
return 0;
}
if (off + size > file_size) {
size = file_size - off;
}
memcpy(buf, aifs.files_start + off, size);
return size;
}
int my_stat(const char* path, struct stat* st, struct fuse_file_info* fi)
{
if (0 == strcmp("/", path)) {
st->st_mode = 0555 | S_IFDIR;
st->st_nlink = 2;
return 0;
}
++path;
int cur_file = -1;
for (size_t i = 0; i < aifs.numfiles; ++i) {
if (strcmp(aifs.file_names[i], path) == 0) {
cur_file = i;
break;
}
}
if (-1 == cur_file) {
return -ENOENT;
}
st->st_mode = S_IFREG | 0444;
st->st_nlink = 1;
st->st_size = aifs.file_sizes[cur_file];
return 0;
}
/*
int my_opendir(const char* path, struct fuse_file_info* fi)
{
printf("IN OPENDIR: <<<%s>>>", path);
return (0);
}
*/
int my_readdir(
const char* path,
void* buf,
fuse_fill_dir_t filler,
off_t offset,
struct fuse_file_info* fi,
enum fuse_readdir_flags flags)
{
if (0 != strcmp(path, "/")) {
return -ENOENT;
}
filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0, 0);
for (size_t i = 0; i < aifs.numfiles; ++i) {
filler(buf, aifs.file_names[i], NULL, 0, 0);
}
return SUCCESS;
}
static struct fuse_operations operations = {
.open = my_open,
.read = my_read,
.readdir = my_readdir,
.getattr = my_stat,
};
int open_filesystem(const char* image_name)
{
FILE* image_f = NULL;
int ret_val = 0;
if (NULL == (image_f = fopen(image_name, "r"))) {
ret_val = 1;
goto finally;
}
fread(aifs.data, sizeof(aifs.data), sizeof(*(aifs.data)), image_f);
char* data_ptr = aifs.data;
int offset = 0;
size_t numfiles = 0;
sscanf(data_ptr, "%zu\n%n", &numfiles, &offset);
data_ptr += offset;
aifs.numfiles = numfiles;
for (size_t i = 0; i < numfiles; ++i) {
aifs.file_names[i] = data_ptr;
sscanf(data_ptr, "%*s%n", &offset);
data_ptr += offset;
*data_ptr = '\0';
++data_ptr;
sscanf(data_ptr, "%zu\n%n", &aifs.file_sizes[i], &offset);
data_ptr += offset;
}
aifs.files_start = data_ptr;
finally:
fclose(image_f);
return ret_val;
}
int main(int argc, char* argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
typedef struct {
char* src;
} my_options_t;
my_options_t opt = {};
struct fuse_opt opt_specs[] = {{"--src %s", offsetof(my_options_t, src), 0},
{NULL, 0, 0}};
fuse_opt_parse(&args, &opt, opt_specs, NULL);
if (NULL != opt.src) {
open_filesystem(opt.src);
}
int ret = fuse_main(args.argc, args.argv, &operations, NULL);
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment