agendafs
A filesystem for your calendar.
git clone git://mccd.space/agendafscommit ca0f85fa935595c580f5bbedb12c667cc8741eb6
parent 6dcea2c4b6dacd4bc260d6f54de9487adbddc7a1
Author: Marc Coquand <marc@coquand.email>
Date: Sun, 13 Jul 2025 16:45:37 +0200
Refactor path functionality
Diffstat:
7 files changed, 137 insertions(+), 89 deletions(-)
diff --git a/Makefile b/Makefile
@@ -5,10 +5,10 @@ LIBS = `pkg-config uuid fuse3 libical --cflags --libs`
all: agendafs
-agendafs: main.c util.c hashmap.c journal_entry.c tree.c
+agendafs: main.c path.c util.c hashmap.c journal_entry.c tree.c
$(CC) $(CFLAGS) *.c -o mount_agendafs $(LIBS)
-debug: main.c util.c hashmap.c journal_entry.c tree.c
+debug: main.c path.c util.c hashmap.c journal_entry.c tree.c
$(CC) $(CFLAGS_DEBUG) $(DEBUG_FLAGS) *.c -o mount_agendafs-debug $(LIBS)
clean:
diff --git a/journal_entry.c b/journal_entry.c
@@ -1,6 +1,7 @@
#include "journal_entry.h"
#include "hashmap.h"
+#include "path.h"
#include "tree.h"
#include "util.h"
#include <dirent.h>
@@ -63,30 +64,6 @@ get_node_component(const struct tree_node *node)
return entry->component;
}
-int
-get_parent_path(const char *path, char **buffer)
-{
- char *path_copy = strdup(path);
-
- char *last_slash = strrchr(path_copy, '/');
- if (last_slash == NULL) {
- free(path_copy);
- return 0;
- }
-
- // If they are the same, it means the parent is root
- if (strcmp(last_slash, path_copy) == 0) {
- int result = asprintf(buffer, "/");
- free(path_copy);
- return result;
- }
- *last_slash = '\0';
- int result = asprintf(buffer, "%s", path_copy);
- free(path_copy);
-
- return result;
-}
-
struct tree_node **
get_node_children(const struct tree_node *node)
{
@@ -143,28 +120,6 @@ is_root_node(const struct tree_node *node)
return false;
}
-char **
-split_path(const char *path, size_t *count_out)
-{
- char *path_copy = strdup(path);
- if (!path_copy)
- return NULL;
-
- size_t count = 0;
- char **segments = NULL;
-
- char *token = strtok(path_copy, "/");
- while (token) {
- segments = xreallocarray(segments, sizeof(char *), (count + 1));
- segments[count++] = strdup(token);
- token = strtok(NULL, "/");
- }
- free(path_copy);
-
- *count_out = count;
- return segments;
-}
-
void
set_parent_child_relationship_to_component(icalcomponent *parent,
icalcomponent *child)
@@ -232,14 +187,6 @@ add_child_to_node(struct tree_node *parent, struct tree_node *child)
}
}
-void
-free_segments(char **segments, size_t count)
-{
- for (size_t i = 0; i < count; ++i)
- free(segments[i]);
- free(segments);
-}
-
struct tree_node *
get_node_by_path(const char *path)
{
@@ -248,8 +195,8 @@ get_node_by_path(const char *path)
return fuse_tree_root;
}
- size_t count;
- char **segments = split_path(path, &count);
+ char **segments = NULL;
+ size_t count = split_path(path, segments);
if (!segments)
return fuse_tree_root;
LOG("Segments are defined");
@@ -280,9 +227,7 @@ get_node_by_path(const char *path)
char *
get_original_filepath(const struct journal_entry *entry)
{
- char *filepath = NULL;
- asprintf(&filepath, "%s/%s", ICS_DIR, entry->filename_original);
- return filepath;
+ return append_path(ICS_DIR, entry->filename_original);
}
icaltimetype
@@ -307,15 +252,6 @@ free_journal_entry(void *val)
free(entry);
}
-char *
-get_filename(const char *full_path)
-{
- char *base_name = strrchr(full_path, '/');
- if (!base_name)
- return (char *)full_path;
- return base_name + 1;
-}
-
struct journal_entry *
get_entry_from_fuse_path(const char *path)
{
@@ -991,6 +927,7 @@ write_entry_to_ical_file(const struct journal_entry *entry)
return 0;
}
+
size_t
load_agendafs_environment(char *ics_dir_env)
{
@@ -1148,7 +1085,6 @@ create_vjournal_directory(char *summary)
icalcomponent_add_property(calendar,
icalproperty_new_prodid("-//caldavfs//EN"));
- // Step 2: Create a VJOURNAL entry
icalcomponent *journal = icalcomponent_new_vjournal();
char *id = create_new_unique_ics_uid();
@@ -1171,18 +1107,6 @@ create_vjournal_directory(char *summary)
return calendar;
}
-void
-remove_file_extension(char *path)
-{
- char *last_dot = strrchr(path, '.');
- char *last_slash = strrchr(path, '/');
-
- // Only remove the extension if dot is after last slash
- if (last_dot && (!last_slash || last_dot > last_slash)) {
- *last_dot = '\0';
- }
-}
-
bool
match_by_uid(icalcomponent *component, const char *target_uuid)
{
@@ -1202,8 +1126,7 @@ create_entry_from_fuse(const char *fuse_path)
char *new_basename = strrchr(fuse_path, '/');
new_basename++;
- char *without_extension = strdup(new_basename);
- remove_file_extension(without_extension);
+ path *without_extension = remove_file_extension(new_basename);
struct journal_entry *new_entry =
xcalloc(1, sizeof(struct journal_entry));
diff --git a/journal_entry.h b/journal_entry.h
@@ -179,9 +179,6 @@ gid_t
get_node_gid(const struct tree_node *node);
void
-remove_file_extension(char *path);
-
-void
update_or_create_fuse_entry_from_original(const char *filename);
int
diff --git a/path.c b/path.c
@@ -0,0 +1,92 @@
+#include "path.h"
+#include "util.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+path *
+remove_file_extension(const path *p)
+{
+ char *cpy = xstrdup(p);
+ char *last_dot = strrchr(cpy, '.');
+ char *last_slash = strrchr(cpy, '/');
+
+ // Only remove the extension if dot is after last slash
+ if (last_dot && (!last_slash || last_dot > last_slash)) {
+ *last_dot = '\0';
+ }
+
+ return cpy;
+}
+
+void
+free_segments(char **segments, size_t count)
+{
+ for (size_t i = 0; i < count; ++i)
+ free(segments[i]);
+ free(segments);
+}
+
+path *
+append_path(path *parentp, char *childp)
+{
+ char *filepath = NULL;
+ if (asprintf(&filepath, "%s/%s", parentp, childp) == -1) {
+ LOG("Memory alloc failed");
+ exit(1);
+ }
+ return filepath;
+}
+
+path *
+get_filename(const char *full_path)
+{
+ char *base_name = strrchr(full_path, '/');
+ if (!base_name)
+ return (char *)full_path;
+ return base_name + 1;
+}
+
+size_t
+get_parent_path(const char *path, char **buffer)
+{
+ char *path_copy = strdup(path);
+
+ char *last_slash = strrchr(path_copy, '/');
+ if (last_slash == NULL) {
+ free(path_copy);
+ return 0;
+ }
+
+ // If they are the same, it means the parent is root
+ if (strcmp(last_slash, path_copy) == 0) {
+ int result = asprintf(buffer, "/");
+ free(path_copy);
+ return result;
+ }
+ *last_slash = '\0';
+ int result = asprintf(buffer, "%s", path_copy);
+ free(path_copy);
+
+ return result;
+}
+
+size_t
+split_path(const path *p, char **segments)
+{
+ char *path_copy = xstrdup(p);
+
+ size_t count = 0;
+ char *segment;
+
+ char *saveptr;
+ segment = strtok_r(path_copy, "/", &saveptr);
+ while (segment) {
+ segments[count++] = strdup(segment);
+ segment = strtok_r(NULL, "/", &saveptr);
+ }
+ free(path_copy);
+
+ return count;
+}
+
diff --git a/path.h b/path.h
@@ -0,0 +1,26 @@
+#ifndef path_h_INCLUDED
+#define path_h_INCLUDED
+#include "util.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef char path;
+
+path *
+remove_file_extension(const path *);
+
+void
+free_segments(path **, size_t);
+
+path *
+append_path(path *, char *);
+
+path *
+get_filename(const path *);
+
+size_t
+get_parent_path(const char *, char **);
+size_t
+split_path(const path *, char **);
+#endif // path_h_INCLUDED
diff --git a/util.c b/util.c
@@ -33,6 +33,15 @@ xcalloc(size_t memb, size_t s)
return buf;
}
+char *
+xstrdup(const char *s)
+{
+ char *cpy = strdup(s);
+ if (!cpy)
+ exit(1);
+ return cpy;
+}
+
void *
reallocarray(void *buf, size_t n, size_t m)
{
diff --git a/util.h b/util.h
@@ -14,5 +14,6 @@ void *
xmalloc(size_t);
void *
xcalloc(size_t, size_t);
-
+char *
+xstrdup(const char *s);
#endif