Created
December 3, 2020 11:13
-
-
Save apselon/08446fca7ea48c2c01cce5e1c2374daf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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