2018-07-26 11:01:47 +02:00
|
|
|
#include "fuse_local.h"
|
|
|
|
|
2021-09-03 22:23:52 +02:00
|
|
|
#include "link.h"
|
2021-08-31 12:50:59 +02:00
|
|
|
#include "log.h"
|
2019-04-24 00:48:08 +02:00
|
|
|
|
2021-08-30 12:24:32 +02:00
|
|
|
/*
|
|
|
|
* must be included before including <fuse.h>
|
|
|
|
*/
|
2019-04-24 00:48:08 +02:00
|
|
|
#define FUSE_USE_VERSION 26
|
|
|
|
#include <fuse.h>
|
2018-07-26 11:01:47 +02:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
static void *fs_init(struct fuse_conn_info *conn)
|
|
|
|
{
|
2021-08-31 12:18:39 +02:00
|
|
|
(void) conn;
|
|
|
|
return NULL;
|
2018-07-26 11:01:47 +02:00
|
|
|
}
|
|
|
|
|
2019-04-22 02:50:05 +02:00
|
|
|
/** \brief release an opened file */
|
|
|
|
static int fs_release(const char *path, struct fuse_file_info *fi)
|
|
|
|
{
|
2021-08-31 19:49:49 +02:00
|
|
|
lprintf(info, "%s\n", path);
|
2021-08-31 12:18:39 +02:00
|
|
|
(void) path;
|
|
|
|
if (CACHE_SYSTEM_INIT) {
|
|
|
|
Cache_close((Cache *) fi->fh);
|
|
|
|
}
|
|
|
|
return 0;
|
2019-04-22 02:50:05 +02:00
|
|
|
}
|
|
|
|
|
2018-07-26 11:01:47 +02:00
|
|
|
/** \brief return the attributes for a single file indicated by path */
|
|
|
|
static int fs_getattr(const char *path, struct stat *stbuf)
|
|
|
|
{
|
2021-08-31 12:18:39 +02:00
|
|
|
int res = 0;
|
|
|
|
memset(stbuf, 0, sizeof(struct stat));
|
|
|
|
|
|
|
|
if (!strcmp(path, "/")) {
|
|
|
|
stbuf->st_mode = S_IFDIR | 0755;
|
|
|
|
stbuf->st_nlink = 1;
|
|
|
|
} else {
|
|
|
|
Link *link = path_to_Link(path);
|
|
|
|
if (!link) {
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
2023-07-26 01:45:41 +02:00
|
|
|
struct timespec spec = { 0 };
|
2021-08-31 12:18:39 +02:00
|
|
|
spec.tv_sec = link->time;
|
2021-05-27 20:49:51 +02:00
|
|
|
#if defined(__APPLE__) && defined(__MACH__)
|
2021-08-31 12:18:39 +02:00
|
|
|
stbuf->st_mtimespec = spec;
|
2021-05-27 20:49:51 +02:00
|
|
|
#else
|
2021-08-31 12:18:39 +02:00
|
|
|
stbuf->st_mtim = spec;
|
2021-05-27 20:49:51 +02:00
|
|
|
#endif
|
2021-08-31 12:18:39 +02:00
|
|
|
switch (link->type) {
|
|
|
|
case LINK_DIR:
|
|
|
|
stbuf->st_mode = S_IFDIR | 0755;
|
|
|
|
stbuf->st_nlink = 1;
|
|
|
|
break;
|
|
|
|
case LINK_FILE:
|
|
|
|
stbuf->st_mode = S_IFREG | 0444;
|
|
|
|
stbuf->st_nlink = 1;
|
|
|
|
stbuf->st_size = link->content_length;
|
|
|
|
stbuf->st_blksize = 128 * 1024;
|
|
|
|
stbuf->st_blocks = (link->content_length) / 512;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -ENOENT;
|
2021-08-31 12:15:00 +02:00
|
|
|
}
|
2021-08-31 12:18:39 +02:00
|
|
|
}
|
|
|
|
stbuf->st_uid = getuid();
|
|
|
|
stbuf->st_gid = getgid();
|
2021-08-31 12:15:00 +02:00
|
|
|
|
2021-08-31 12:18:39 +02:00
|
|
|
return res;
|
2018-07-26 11:01:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief read a file */
|
2021-08-30 12:24:32 +02:00
|
|
|
static int
|
|
|
|
fs_read(const char *path, char *buf, size_t size, off_t offset,
|
2021-08-31 12:15:00 +02:00
|
|
|
struct fuse_file_info *fi)
|
2018-07-26 11:01:47 +02:00
|
|
|
{
|
2021-08-31 12:18:39 +02:00
|
|
|
long received;
|
|
|
|
if (CACHE_SYSTEM_INIT) {
|
|
|
|
received = Cache_read((Cache *) fi->fh, buf, size, offset);
|
|
|
|
} else {
|
|
|
|
received = path_download(path, buf, size, offset);
|
|
|
|
}
|
|
|
|
return received;
|
2018-07-26 11:01:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief open a file indicated by the path */
|
|
|
|
static int fs_open(const char *path, struct fuse_file_info *fi)
|
|
|
|
{
|
2021-08-31 19:49:49 +02:00
|
|
|
lprintf(info, "%s\n", path);
|
2021-08-31 12:18:39 +02:00
|
|
|
Link *link = path_to_Link(path);
|
|
|
|
if (!link) {
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
2022-06-28 15:54:51 +02:00
|
|
|
if ((fi->flags & O_RDWR) != O_RDONLY) {
|
|
|
|
return -EROFS;
|
2021-08-31 12:18:39 +02:00
|
|
|
}
|
|
|
|
if (CACHE_SYSTEM_INIT) {
|
|
|
|
fi->fh = (uint64_t) Cache_open(path);
|
|
|
|
if (!fi->fh) {
|
|
|
|
/*
|
|
|
|
* The link clearly exists, the cache cannot be opened, attempt
|
|
|
|
* cache creation
|
|
|
|
*/
|
|
|
|
Cache_delete(path);
|
|
|
|
Cache_create(path);
|
|
|
|
fi->fh = (uint64_t) Cache_open(path);
|
|
|
|
/*
|
|
|
|
* The cache definitely cannot be opened for some reason.
|
|
|
|
*/
|
|
|
|
if (!fi->fh) {
|
2021-08-31 12:15:00 +02:00
|
|
|
return -ENOENT;
|
2021-08-31 12:18:39 +02:00
|
|
|
}
|
2021-08-31 12:15:00 +02:00
|
|
|
}
|
2021-08-31 12:18:39 +02:00
|
|
|
}
|
|
|
|
return 0;
|
2018-07-26 11:01:47 +02:00
|
|
|
}
|
|
|
|
|
2021-08-08 16:50:35 +02:00
|
|
|
/**
|
|
|
|
* \brief read the directory indicated by the path
|
|
|
|
* \note
|
|
|
|
* - releasedir() is not implemented, because I don't see why anybody want
|
|
|
|
* the LinkTables to be evicted from the memory during the runtime of this
|
|
|
|
* program. If you want to evict LinkTables, just unmount the filesystem.
|
|
|
|
* - There is no real need to associate the LinkTable with the fi of each
|
|
|
|
* directory data structure. If you want a deep level directory, you need to
|
|
|
|
* generate the LinkTables for previous level directories. We might
|
|
|
|
* as well maintain our own tree structure.
|
|
|
|
*/
|
2021-08-30 12:24:32 +02:00
|
|
|
static int
|
|
|
|
fs_readdir(const char *path, void *buf, fuse_fill_dir_t dir_add,
|
2021-08-31 12:15:00 +02:00
|
|
|
off_t offset, struct fuse_file_info *fi)
|
2018-07-26 11:01:47 +02:00
|
|
|
{
|
2021-08-31 12:18:39 +02:00
|
|
|
(void) offset;
|
|
|
|
(void) fi;
|
|
|
|
LinkTable *linktbl;
|
2021-08-31 12:15:00 +02:00
|
|
|
|
2023-03-31 14:26:15 +02:00
|
|
|
linktbl = path_to_Link_LinkTable_new(path);
|
|
|
|
if (!linktbl) {
|
|
|
|
return -ENOENT;
|
2021-08-31 12:18:39 +02:00
|
|
|
}
|
|
|
|
|
2023-03-31 14:26:15 +02:00
|
|
|
|
2021-08-31 12:18:39 +02:00
|
|
|
/*
|
|
|
|
* start adding the links
|
|
|
|
*/
|
|
|
|
dir_add(buf, ".", NULL, 0);
|
|
|
|
dir_add(buf, "..", NULL, 0);
|
2021-08-31 14:52:25 +02:00
|
|
|
/* We skip the head link */
|
2021-08-31 12:18:39 +02:00
|
|
|
for (int i = 1; i < linktbl->num; i++) {
|
|
|
|
Link *link = linktbl->links[i];
|
|
|
|
if (link->type != LINK_INVALID) {
|
|
|
|
dir_add(buf, link->linkname, NULL, 0);
|
2021-08-31 12:15:00 +02:00
|
|
|
}
|
2021-08-31 12:18:39 +02:00
|
|
|
}
|
2021-08-31 12:15:00 +02:00
|
|
|
|
2021-08-31 12:18:39 +02:00
|
|
|
return 0;
|
2018-07-26 11:01:47 +02:00
|
|
|
}
|
2019-04-22 14:32:15 +02:00
|
|
|
|
|
|
|
static struct fuse_operations fs_oper = {
|
2021-08-31 12:18:39 +02:00
|
|
|
.getattr = fs_getattr,
|
|
|
|
.readdir = fs_readdir,
|
|
|
|
.open = fs_open,
|
|
|
|
.read = fs_read,
|
|
|
|
.init = fs_init,
|
|
|
|
.release = fs_release
|
2019-04-22 14:32:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
int fuse_local_init(int argc, char **argv)
|
|
|
|
{
|
2021-08-31 12:18:39 +02:00
|
|
|
return fuse_main(argc, argv, &fs_oper, NULL);
|
2019-04-22 14:32:15 +02:00
|
|
|
}
|