httpdirfs/src/fuse_local.c

176 lines
4.3 KiB
C
Raw Normal View History

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
}
/** \brief release an opened file */
static int fs_release(const char *path, struct fuse_file_info *fi)
{
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;
}
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:18:39 +02:00
}
stbuf->st_uid = getuid();
stbuf->st_gid = getgid();
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,
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)
{
lprintf(info, "%s\n", path);
2021-08-31 12:18:39 +02:00
Link *link = path_to_Link(path);
if (!link) {
return -ENOENT;
}
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) {
return -ENOENT;
2021-08-31 12:18:39 +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,
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;
linktbl = path_to_Link_LinkTable_new(path);
if (!linktbl) {
return -ENOENT;
2021-08-31 12:18:39 +02:00
}
2021-08-31 12:18:39 +02:00
/*
* start adding the links
*/
dir_add(buf, ".", NULL, 0);
dir_add(buf, "..", NULL, 0);
/* 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:18:39 +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
}