agendafs

A filesystem for your calendar.

git clone git://mccd.space/agendafs
commit ea7015dde9e3f6ed3e2bb9b5ff78b957707c7eba
parent 5ab7d85d4dd5716272de8231de8f0ce5e2a3666e
Author: Marc Coquand <marc@coquand.email>
Date:   Wed, 23 Jul 2025 20:40:34 +0200

Code cleanup

Diffstat:
Mmain.c | 82++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 44 insertions(+), 38 deletions(-)
diff --git a/main.c b/main.c
@@ -32,16 +32,14 @@ static pthread_mutex_t entries_mutex = PTHREAD_MUTEX_INITIALIZER;
 static int
 agenda_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
 {
+	LOG("STAT %s", path);
+
 	pthread_mutex_lock(&entries_mutex);
 	memory_region *mreg = create_region();
-	LOG("STAT %s", path);
+	int ret_code = 0;
 
-	LOG("memset");
 	memset(stbuf, 0, sizeof(struct stat));
 
-	int ret_code = 0;
-
-	LOG("strcmp");
 	if (strcmp(path, "/") == 0) {
 		stbuf->st_mode = S_IFDIR | 0444;
 		stbuf->st_nlink = 2;
@@ -53,7 +51,6 @@ agenda_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
 		goto cleanup_return;
 	}
 
-	LOG("Getting node");
 	const struct tree_node *node = get_node_by_path(mreg, path);
 	if (!node) {
 		LOG("Entry not found");
@@ -61,7 +58,6 @@ agenda_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
 		goto cleanup_return;
 	}
 
-	LOG("icalcomponent from node");
 	icalcomponent *ic = get_icalcomponent_from_node(mreg, node);
 	stbuf->st_uid = get_node_uid(node);
 	stbuf->st_gid = get_node_gid(node);
@@ -79,11 +75,11 @@ agenda_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
 		stbuf->st_nlink = 1;
 	}
 
-	char *full_disk_path = get_vdir_filepath(mreg, node);
-	struct stat disk_stat;
-	if (stat(full_disk_path, &disk_stat) == 0) {
-		stbuf->st_mtime = disk_stat.st_mtime;
-		stbuf->st_ctime = disk_stat.st_ctime;
+	char *vdir_path = get_vdir_filepath(mreg, node);
+	struct stat vdir_file_stat;
+	if (stat(vdir_path, &vdir_file_stat) == 0) {
+		stbuf->st_mtime = vdir_file_stat.st_mtime;
+		stbuf->st_ctime = vdir_file_stat.st_ctime;
 	}
 	else {
 		icaltimetype ical_last_modified = get_last_modified(ic);
@@ -97,8 +93,6 @@ agenda_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
 
 	stbuf->st_atime = time(NULL);
 
-	ret_code = 0;
-
 cleanup_return:
 	pthread_mutex_unlock(&entries_mutex);
 	rfree_all(mreg);
@@ -108,6 +102,7 @@ cleanup_return:
 static int
 agenda_readlink(const char *path, char *buf, size_t size)
 {
+	// TODO: Implement
 	LOG("READLINK path: %s", path);
 	return -ENOENT;
 }
@@ -118,11 +113,11 @@ agenda_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 	       enum fuse_readdir_flags flags)
 {
 
+	LOG("READDIR %s", path);
 	pthread_mutex_lock(&entries_mutex);
 	memory_region *mreg = create_region();
 	int status = 0;
 
-	LOG("READDIR %s", path);
 	filler(buf, ".", NULL, 0, 0);
 	filler(buf, "..", NULL, 0, 0);
 
@@ -131,13 +126,14 @@ agenda_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 		status = -ENOENT;
 		goto cleanup_return;
 	}
+
 	for (size_t i = 0; i < node->child_count; i++) {
 		const struct tree_node *child = node->children[i];
 		icalcomponent *ic = get_icalcomponent_from_node(mreg, child);
 		assert(ic);
 
 		struct stat st = {0};
-		// TODO: Fix
+		// TODO: Correct perms
 		st.st_mode = S_IFREG | 0744;
 
 		st.st_uid = get_node_uid(child);
@@ -162,8 +158,10 @@ agenda_open(const char *path, struct fuse_file_info *fi)
 {
 	memory_region *mreg = create_region();
 	pthread_mutex_lock(&entries_mutex);
+
 	LOG("Opening journal for %s", path);
 	const struct tree_node *node = get_node_by_path(mreg, path);
+
 	pthread_mutex_unlock(&entries_mutex);
 	rfree_all(mreg);
 	return node ? 0 : -ENOENT;
@@ -176,8 +174,10 @@ agenda_mkdir(const char *path, mode_t mode)
 	memory_region *mreg = create_region();
 	pthread_mutex_lock(&entries_mutex);
 	int status = 0;
+
 	LOG("MKDIR %s", path);
 	status = create_directory_from_fuse_path(mreg, path);
+
 	pthread_mutex_unlock(&entries_mutex);
 	rfree_all(mreg);
 	return status;
@@ -187,11 +187,11 @@ static int
 agenda_read(const char *path, char *buf, size_t size, off_t offset,
 	    struct fuse_file_info *fi)
 {
-	int ret_code = 0;
+	LOG("READ on path %s", path);
 
 	memory_region *mreg = create_region();
 	pthread_mutex_lock(&entries_mutex);
-	LOG("READ on path %s", path);
+	int ret_code = 0;
 
 	const struct tree_node *n = get_node_by_path(mreg, path);
 	if (!n) {
@@ -208,7 +208,7 @@ agenda_read(const char *path, char *buf, size_t size, off_t offset,
 	const char *content = description;
 	size_t content_len = strlen(content);
 
-	if ((size_t)offset >= content_len) {
+	if (offset >= content_len) {
 		ret_code = 0;
 		goto cleanup_return;
 	}
@@ -236,9 +236,11 @@ agenda_write(const char *path, const char *buf, size_t size, off_t offset,
 {
 
 	LOG("WRITE %s, %zu, %zu", buf, size, offset);
+
 	memory_region *mreg = create_region();
-	int ret_i = 0;
 	pthread_mutex_lock(&entries_mutex);
+	int ret_i = 0;
+
 	const struct tree_node *node = get_node_by_path(mreg, path);
 	if (!node) {
 		ret_i = -ENONET;
@@ -253,12 +255,9 @@ agenda_write(const char *path, const char *buf, size_t size, off_t offset,
 	char *new_desc = rstrins(mreg, old_desc, offset, buf, size);
 	icalcomponent_set_description(ic, new_desc);
 
-	if (write_ical_file(mreg, node, ic) != 0) {
-		ret_i = -EIO;
-		goto cleanup_return;
-	}
+	ret_i = write_ical_file(mreg, node, ic);
 
-	ret_i = size;
+	ret_i = ret_i >= 0 ? size : ret_i;
 
 cleanup_return:
 	pthread_mutex_unlock(&entries_mutex);
@@ -270,13 +269,14 @@ cleanup_return:
 static int
 agenda_unlink(const char *file)
 {
+	LOG("DELETE %s", file);
+
 	memory_region *mreg = create_region();
 	pthread_mutex_lock(&entries_mutex);
-	LOG("DELETE %s", file);
 	int res = 0;
 
 	res = delete_from_fuse_path(mreg, file);
-	LOG("Delete");
+
 	pthread_mutex_unlock(&entries_mutex);
 	rfree_all(mreg);
 	return res;
@@ -285,14 +285,14 @@ agenda_unlink(const char *file)
 static int
 agenda_rmdir(const char *file)
 {
+	LOG("DELETE %s", file);
+
 	memory_region *mreg = create_region();
 	pthread_mutex_lock(&entries_mutex);
-	LOG("DELETE %s", file);
 	int res = 0;
 
 	res = delete_dir_from_fuse_path(mreg, file);
 
-	LOG("Delete successful");
 	pthread_mutex_unlock(&entries_mutex);
 	rfree_all(mreg);
 	return res;
@@ -369,8 +369,8 @@ agenda_setxattr(const char *path, const char *header,
 	LOG("SETXATTR '%s' '%s' '%zu' '%s' '%d'", path, header, s,
 	    new_attributes, flags);
 	memory_region *mreg = create_region();
-	int status = -EINVAL;
 	pthread_mutex_lock(&entries_mutex);
+	int status = 0;
 
 	if (strcmp(header, "user.categories") == 0) {
 		struct tree_node *node = get_node_by_path(mreg, path);
@@ -400,6 +400,9 @@ agenda_setxattr(const char *path, const char *header,
 		status = set_node_class(mreg, node, iclass);
 		goto cleanup_return;
 	}
+	else {
+		status = -EINVAL;
+	}
 
 cleanup_return:
 	pthread_mutex_unlock(&entries_mutex);
@@ -411,12 +414,13 @@ static int
 agenda_listxattr(const char *path, char *list, size_t size)
 {
 	LOG("LISTXATTR %s %zu", list, size);
+	memory_region *mreg = create_region();
+	pthread_mutex_lock(&entries_mutex);
+	int return_i = 0;
+
 	FILE *stream;
 	char *membuffer = NULL;
-	int return_i = 0;
 	size_t membuffer_len = 0;
-	memory_region *mreg = create_region();
-	pthread_mutex_lock(&entries_mutex);
 
 	struct tree_node *node = get_node_by_path(mreg, path);
 	if (!node) {
@@ -429,12 +433,12 @@ agenda_listxattr(const char *path, char *list, size_t size)
 		return_i = -EIO;
 		goto cleanup_return;
 	}
+
 	char *cats = get_node_categories(mreg, node);
 	if (cats != NULL && strcmp("", cats) != 0) {
 		fprintf(stream, "user.categories");
 		fputc('\0', stream);
 	}
-	free(cats);
 
 	const char *iclass = get_node_class(mreg, node);
 	if (iclass != NULL && strcmp("", iclass) != 0) {
@@ -528,13 +532,14 @@ cleanup_return:
 }
 
 static void
-handle_ics_event(struct inotify_event *event)
+handle_vdir_event(struct inotify_event *event)
 {
 	if (!event->len || !strstr(event->name, ".ics"))
 		return;
 
 	memory_region *mreg = create_region();
 	pthread_mutex_lock(&entries_mutex);
+
 	LOG("Detected change in ICS file: %s\n", event->name);
 
 	char *full_path = NULL;
@@ -557,7 +562,7 @@ handle_ics_event(struct inotify_event *event)
 }
 
 static void *
-watch_ics_dir(void *arg)
+watch_vdir_changes(void *arg)
 {
 	int fd = inotify_init1(IN_NONBLOCK);
 	assert(fd >= 0);
@@ -581,7 +586,7 @@ watch_ics_dir(void *arg)
 		while (i < length) {
 			struct inotify_event *event =
 			    (struct inotify_event *)&buffer[i];
-			handle_ics_event(event);
+			handle_vdir_event(event);
 			size_t event_size =
 			    sizeof(struct inotify_event) + event->len;
 
@@ -690,7 +695,8 @@ main(int argc, char *argv[])
 
 	LOG("LOADED ICS DIR");
 
-	if (pthread_create(&watcher_thread, NULL, watch_ics_dir, NULL) != 0) {
+	if (pthread_create(&watcher_thread, NULL, watch_vdir_changes, NULL) !=
+	    0) {
 		perror("Failed to create inotify watcher thread");
 		return 1;
 	}