agendafs
A filesystem for your calendar.
git clone git://mccd.space/agendafscommit 3d7e628aadcc9df41ec48687bd6aa4762faa64d2
parent 29e47888b538a412d4a23347cdad3b93a5023d96
Author: Marc Coquand <marc@coquand.email>
Date: Tue, 29 Jul 2025 11:52:51 +0200
Add macro for resource initialization
I typically avoid macros and don't like them, but since C
lacks closures, the options are:
- Repeat the code everywhere (error prone, makes it hard to modify)
- Use gcc specific RAII features (non-standard)
- Use macros (bad tooling support, increases complexity of learning
the code)
Since I want to avoid RAII features, I think macros are the least
bad option here.
Diffstat:
| M | main.c | | | 225 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
1 file changed, 102 insertions(+), 123 deletions(-)
diff --git a/main.c b/main.c
@@ -30,14 +30,35 @@
#define EVENT_BUF_LEN (1024 * (sizeof(struct inotify_event) + 16))
static pthread_rwlock_t entries_lock = PTHREAD_RWLOCK_INITIALIZER;
+#define FUSE_WRITE_BEGIN \
+ LOG("%s", __func__); \
+ pthread_rwlock_wrlock(&entries_lock); \
+ memory_region *mreg = create_region(); \
+ int status = 0; \
+ if (!mreg) { \
+ pthread_rwlock_unlock(&entries_lock); \
+ return -ENOMEM; \
+ }
+
+#define FUSE_READ_BEGIN \
+ LOG("%s", __func__); \
+ pthread_rwlock_rdlock(&entries_lock); \
+ memory_region *mreg = create_region(); \
+ int status = 0; \
+ if (!mreg) { \
+ pthread_rwlock_unlock(&entries_lock); \
+ return -ENOMEM; \
+ }
+
+#define FUSE_CLEANUP \
+ pthread_rwlock_unlock(&entries_lock); \
+ rfree_all(mreg);
+
static int
fuse_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
{
- LOG("STAT %s", path);
-
- pthread_rwlock_rdlock(&entries_lock);
- memory_region *mreg = create_region();
- int ret_code = 0;
+ FUSE_READ_BEGIN;
+ LOG("%s", path);
memset(stbuf, 0, sizeof(struct stat));
@@ -55,7 +76,7 @@ fuse_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
const struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
LOG("Entry not found");
- ret_code = -ENOENT;
+ status = -ENOENT;
goto cleanup_return;
}
@@ -68,9 +89,8 @@ fuse_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
stbuf->st_atime = time(NULL);
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
- return ret_code;
+ FUSE_CLEANUP;
+ return status;
}
static int
@@ -86,10 +106,8 @@ fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
struct fuse_file_info *fi, enum fuse_readdir_flags flags)
{
- LOG("READDIR %s", path);
- pthread_rwlock_rdlock(&entries_lock);
- memory_region *mreg = create_region();
- int status = 0;
+ FUSE_READ_BEGIN;
+ LOG("%s", path);
filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0, 0);
@@ -114,19 +132,15 @@ fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
}
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
+ FUSE_CLEANUP;
return status;
}
static int
fuse_open(const char *path, struct fuse_file_info *fi)
{
- LOG("OPEN %s", path);
-
- memory_region *mreg = create_region();
- pthread_rwlock_rdlock(&entries_lock);
- int status = 0;
+ FUSE_READ_BEGIN;
+ LOG("%s", path);
const struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
@@ -134,25 +148,18 @@ fuse_open(const char *path, struct fuse_file_info *fi)
status = -ENOENT;
}
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
-
+ FUSE_CLEANUP;
return status;
}
static int
fuse_mkdir(const char *path, mode_t mode)
{
- LOG("MKDIR %s", path);
-
- memory_region *mreg = create_region();
- pthread_rwlock_wrlock(&entries_lock);
- int status = 0;
+ FUSE_WRITE_BEGIN;
status = create_entry_from_fuse(mreg, path, ENTRY_DIRECTORY);
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
+ FUSE_CLEANUP;
return status;
}
@@ -160,19 +167,18 @@ static int
fuse_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
- LOG("READ called: offset=%ld, size=%zu", offset, size);
- memory_region *mreg = create_region();
- pthread_rwlock_rdlock(&entries_lock);
- int ret_i = 0;
+ FUSE_READ_BEGIN;
+
+ LOG("READ: offset=%ld, size=%zu", offset, size);
const struct tree_node *n = get_node_by_path(mreg, path);
if (!n) {
- ret_i = -ENOENT;
+ status = -ENOENT;
goto cleanup_return;
}
icalcomponent *ic = get_icalcomponent_from_node(mreg, n);
if (!ic) {
- ret_i = -EIO;
+ status = -EIO;
goto cleanup_return;
}
@@ -195,12 +201,11 @@ fuse_read(const char *path, char *buf, size_t size, off_t offset,
memcpy(buf, description + offset, bytes_to_read);
}
- ret_i = bytes_to_read;
+ status = bytes_to_read;
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
- return ret_i;
+ FUSE_CLEANUP;
+ return status;
}
static int
@@ -208,20 +213,17 @@ fuse_write(const char *path, const char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
- LOG("WRITE %s, %zu, %zu", buf, size, offset);
-
- memory_region *mreg = create_region();
- pthread_rwlock_wrlock(&entries_lock);
- int ret_i = 0;
+ FUSE_WRITE_BEGIN;
+ LOG("%s, %zu, %zu", buf, size, offset);
if (pathIsHidden(path)) {
- ret_i = -EPERM;
+ status = -EPERM;
goto cleanup_return;
}
const struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
- ret_i = -ENONET;
+ status = -ENONET;
goto cleanup_return;
}
@@ -232,118 +234,103 @@ fuse_write(const char *path, const char *buf, size_t size, off_t offset,
icalcomponent_insert_description(mreg, ic, buf, size, offset);
- ret_i = write_ical_file(mreg, node, ic);
+ status = write_ical_file(mreg, node, ic);
- ret_i = ret_i >= 0 ? size : ret_i;
+ status = status >= 0 ? size : status;
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
- return ret_i;
+ FUSE_CLEANUP;
+ return status;
}
// Aka remove or delete
static int
fuse_unlink(const char *file)
{
- LOG("DELETE %s", file);
-
- memory_region *mreg = create_region();
- pthread_rwlock_wrlock(&entries_lock);
- int res = 0;
+ FUSE_WRITE_BEGIN;
+ LOG("%s", file);
struct tree_node *node = get_node_by_path(mreg, file);
if (!node) {
- res = -ENOENT;
+ status = -ENOENT;
goto cleanup_return;
}
icalcomponent *node_ics = get_icalcomponent_from_node(mreg, node);
if (node_is_directory(mreg, node, node_ics)) {
- res = -EISDIR;
+ status = -EISDIR;
goto cleanup_return;
}
- res = delete_vdir_entry(mreg, node);
+ status = delete_vdir_entry(mreg, node);
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
- return res;
+ FUSE_CLEANUP;
+ return status;
}
static int
fuse_rmdir(const char *filepath)
{
- LOG("DELETE %s", filepath);
-
- memory_region *mreg = create_region();
- pthread_rwlock_wrlock(&entries_lock);
- int res = 0;
+ FUSE_WRITE_BEGIN;
+ LOG("%s", filepath);
struct tree_node *node = get_node_by_path(mreg, filepath);
if (!node) {
- res = -ENOENT;
+ status = -ENOENT;
goto cleanup_return;
}
icalcomponent *node_ics = get_icalcomponent_from_node(mreg, node);
if (!node_is_directory(mreg, node, node_ics)) {
- res = -ENOTDIR;
+ status = -ENOTDIR;
goto cleanup_return;
}
if (node->child_count > 0) {
- res = -ENOTEMPTY;
+ status = -ENOTEMPTY;
goto cleanup_return;
}
- res = delete_vdir_entry(mreg, node);
+ status = delete_vdir_entry(mreg, node);
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
- return res;
+ FUSE_CLEANUP;
+ return status;
}
static int
fuse_rename(const char *old, const char *new, unsigned int flags)
{
- memory_region *mreg = create_region();
- pthread_rwlock_wrlock(&entries_lock);
- LOG("RENAME %s -> %s", old, new);
- int res = 0;
+ FUSE_WRITE_BEGIN;
+ LOG("%s -> %s", old, new);
struct tree_node *existing_node = get_node_by_path(mreg, new);
if (existing_node) {
if (node_has_children(existing_node)) {
- res = -ENOTEMPTY;
+ status = -ENOTEMPTY;
goto cleanup_return;
}
if (delete_vdir_entry(mreg, existing_node) != 0) {
- res = -EIO;
+ status = -EIO;
goto cleanup_return;
}
}
- res = do_agenda_rename(mreg, old, new);
+ status = do_agenda_rename(mreg, old, new);
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
- return res;
+ FUSE_CLEANUP;
+ return status;
}
static int
fuse_create(const char *filepath, mode_t mode, struct fuse_file_info *info)
{
- memory_region *mreg = create_region();
- pthread_rwlock_wrlock(&entries_lock);
- LOG("CREATE %s", filepath);
-
- int status = 0;
+ FUSE_WRITE_BEGIN;
+ LOG("%s", filepath);
// Reserved
if (pathIsHidden(filepath)) {
@@ -361,18 +348,16 @@ fuse_create(const char *filepath, mode_t mode, struct fuse_file_info *info)
create_entry_from_fuse(mreg, filepath, ENTRY_FILE);
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
+ FUSE_CLEANUP;
return status;
}
static int
fuse_removexattr(const char *path, const char *attribute)
{
- LOG("REMOVEXATTR '%s' '%s'", path, attribute);
- memory_region *mreg = create_region();
- int status = -EINVAL;
- pthread_rwlock_wrlock(&entries_lock);
+ FUSE_WRITE_BEGIN;
+ LOG("'%s' '%s'", path, attribute);
+
struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
status = -ENONET;
@@ -395,10 +380,13 @@ fuse_removexattr(const char *path, const char *attribute)
status = write_ical_file(mreg, node, ic);
goto cleanup_return;
}
+ else {
+ status = -EINVAL;
+ goto cleanup_return;
+ }
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
+ FUSE_CLEANUP;
return status;
}
@@ -406,11 +394,9 @@ static int
fuse_setxattr(const char *path, const char *attribute, const char *value,
size_t s, int flags)
{
- LOG("SETXATTR '%s' '%s' '%zu' '%s' '%d'", path, attribute, s, attribute,
- flags);
- memory_region *mreg = create_region();
- pthread_rwlock_wrlock(&entries_lock);
- int status = 0;
+
+ FUSE_WRITE_BEGIN;
+ LOG("'%s' '%s' '%zu' '%s' '%d'", path, attribute, s, attribute, flags);
// Limit imposed in xattr(7)
if (strlen(attribute) >= 256) {
@@ -454,18 +440,15 @@ fuse_setxattr(const char *path, const char *attribute, const char *value,
}
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
+ FUSE_CLEANUP;
return status;
}
static int
fuse_listxattr(const char *path, char *list, size_t size)
{
- LOG("LISTXATTR %s %zu", list, size);
- memory_region *mreg = create_region();
- pthread_rwlock_rdlock(&entries_lock);
- int return_i = 0;
+ FUSE_READ_BEGIN;
+ LOG("%s %zu", list, size);
FILE *stream;
char *membuffer = NULL;
@@ -473,12 +456,12 @@ fuse_listxattr(const char *path, char *list, size_t size)
struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
- return_i = -ENONET;
+ status = -ENONET;
goto cleanup_return_2;
}
if (is_root_node(node)) {
- return_i = -EPERM;
+ status = -EPERM;
goto cleanup_return_2;
}
@@ -487,7 +470,7 @@ fuse_listxattr(const char *path, char *list, size_t size)
stream = open_memstream(&membuffer, &membuffer_len);
if (stream == NULL) {
- return_i = -EIO;
+ status = -EIO;
goto cleanup_return_2;
}
@@ -506,7 +489,7 @@ fuse_listxattr(const char *path, char *list, size_t size)
icalcomponent_write_x_props(stream, comp);
if (fclose(stream) != 0) {
- return_i = -EIO;
+ status = -EIO;
goto cleanup_return;
}
@@ -519,23 +502,20 @@ fuse_listxattr(const char *path, char *list, size_t size)
list[size - 1] = '\0';
}
}
- return_i = membuffer_len;
+ status = membuffer_len;
cleanup_return:
free(membuffer);
cleanup_return_2:
- rfree_all(mreg);
- pthread_rwlock_unlock(&entries_lock);
- return return_i;
+ FUSE_CLEANUP;
+ return status;
}
static int
fuse_getxattr(const char *path, const char *attribute, char *buf, size_t s)
{
- LOG("GETXATTR '%s' '%s' '%zu'\n", path, attribute, s);
- pthread_rwlock_rdlock(&entries_lock);
- memory_region *mreg = create_region();
- int status = 0;
+ FUSE_READ_BEGIN;
+ LOG("'%s' '%s' '%zu'\n", path, attribute, s);
struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
@@ -600,8 +580,7 @@ fuse_getxattr(const char *path, const char *attribute, char *buf, size_t s)
}
cleanup_return:
- pthread_rwlock_unlock(&entries_lock);
- rfree_all(mreg);
+ FUSE_CLEANUP;
return status;
}