agendafs

A filesystem for your calendar.

git clone git://mccd.space/agendafs
commit 4239a40bb845ddb32657a7403b90a2cb9ddc1a41
parent 15fee8c7819f82aaf530f105a20bb85912c88c17
Author: Marc Coquand <marc@coquand.email>
Date:   Sun,  1 Jun 2025 20:04:27 +0100

bugfixes and cleanup

Diffstat:
Mmain.c | 83+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 49 insertions(+), 34 deletions(-)
diff --git a/main.c b/main.c
@@ -366,7 +366,6 @@ parse_ics_file(const char *file_path, journal_entry *entry)
 }
 
 // Dynamically create a time string using format
-// Needs to be freed after use
 char *
 time_string(time_t time_val, const char *format)
 {
@@ -509,18 +508,29 @@ load_journal_entries()
 	pthread_mutex_unlock(&entries_mutex);
 }
 
-int
-write_entry_content(char *buf, size_t max_len, journal_entry *entry)
+size_t
+write_entry_content(char *buf, journal_entry *entry)
 {
-	int size = snprintf(buf, max_len, "%s\n---\n%s", entry->summary,
-			    entry->description);
+	// Allocate memory for the content
+	size_t size =
+	    asprintf(&buf, "%s\n---\n%s", entry->summary, entry->description);
+	if (size == -1) {
+		LOG("Out of memory");
+		exit(1); // Handle out of memory by terminating the program
+	}
 	return size;
 }
 
-int
+size_t
 get_entry_content_size(journal_entry *entry)
 {
-	return write_entry_content(NULL, 0, entry);
+	size_t size = snprintf(NULL, 0, "%s\n---\n%s", entry->summary,
+			       entry->description);
+	if (size == -1) {
+		LOG("Out of mem");
+		exit(1);
+	}
+	return size;
 }
 
 int
@@ -615,10 +625,13 @@ journal_read(const char *path, char *buf, size_t size, off_t offset,
 	LOG("Got entry %s", entry->summary);
 
 	// Calculate required length for full content
-	int needed_len = get_entry_content_size(entry);
-
-	char *full_content = xcalloc(needed_len + 1, sizeof(char));
-	write_entry_content(full_content, needed_len + 1, entry);
+	char *full_content = NULL;
+	size_t needed_len = asprintf(&full_content, "%s\n---\n%s",
+				     entry->summary, entry->description);
+	if (needed_len == -1) {
+		LOG("Out of memory");
+		exit(1); // Handle out of memory by terminating the program
+	}
 
 	if (offset >= needed_len) {
 		// EOF
@@ -656,14 +669,9 @@ journal_entry_to_ical(const journal_entry *entry)
 	strftime(dtstamp, sizeof(dtstamp), "%Y%m%dT%H%M%SZ", &created_tm);
 	strftime(lastmod, sizeof(lastmod), "%Y%m%dT%H%M%SZ", &modified_tm);
 
-	// Estimate total size (safe upper bound)
-	size_t total_size = strlen(escaped_summary) +
-			    strlen(escaped_description) + strlen(entry->uid) +
-			    strlen(dtstamp) + strlen(lastmod) + 512;
+	char *ical = NULL;
 
-	char *ical = xcalloc(total_size, sizeof(char));
-
-	snprintf(ical, total_size,
+	asprintf(&ical,
 		 "BEGIN:VCALENDAR\n"
 		 "PRODID:caldavfs\n"
 		 "BEGIN:VJOURNAL\n"
@@ -741,11 +749,8 @@ write_entry_to_ical_file(const journal_entry *entry, const char *filepath)
 char *
 get_original_filepath(const journal_entry *entry)
 {
-	size_t needed =
-	    snprintf(NULL, 0, "%s/%s", ICS_DIR, entry->filename_original);
-	char *filepath = xcalloc(needed + 1, sizeof(char));
-	snprintf(filepath, needed + 1, "%s/%s", ICS_DIR,
-		 entry->filename_original);
+	char *filepath = NULL;
+	asprintf(&filepath, "%s/%s", ICS_DIR, entry->filename_original);
 	return filepath;
 }
 
@@ -769,9 +774,11 @@ journal_write(const char *path, const char *buf, size_t size, off_t offset,
 
 	char *filepath = get_original_filepath(entry);
 	if (write_entry_to_ical_file(entry, filepath) != 0) {
+		free(filepath);
 		pthread_mutex_unlock(&entries_mutex);
 		return -EIO;
 	}
+	free(filepath);
 	pthread_mutex_unlock(&entries_mutex);
 	return size;
 }
@@ -797,9 +804,17 @@ time_t
 timestamp_from_filename(const char *filename)
 {
 
+	const char *basename = strrchr(filename, '/');
+	if (basename != NULL) {
+		basename++; // Skip the '/' to get the actual filename
+	}
+	else {
+		basename = filename; // No path, use the original filename
+	}
+
 	regmatch_t matches[4];
 
-	int ret = regexec(&regex_fuse_file, filename, 4, matches, 0);
+	int ret = regexec(&regex_fuse_file, basename, 4, matches, 0);
 	if (ret != 0)
 		return INVALID_TIME;
 
@@ -813,8 +828,8 @@ timestamp_from_filename(const char *filename)
 	if (len_date != 8 || len_time != 5)
 		return (time_t)-1;
 
-	strncpy(date_str, filename + matches[1].rm_so, len_date);
-	strncpy(time_str, filename + matches[2].rm_so, len_time);
+	strncpy(date_str, basename + matches[1].rm_so, len_date);
+	strncpy(time_str, basename + matches[2].rm_so, len_time);
 
 	int year, month, day, hour, minute;
 
@@ -889,6 +904,7 @@ journal_rename(const char *old, const char *new, unsigned int flags)
 
 	if (new_created_at == INVALID_TIME) {
 		LOG("Invalid filename format: %s", new_basename);
+		pthread_mutex_unlock(&entries_mutex);
 		return -EINVAL;
 	}
 
@@ -968,6 +984,7 @@ watch_ics_dir(void *arg)
 		ssize_t length = read(fd, buffer, EVENT_BUF_LEN);
 		if (length < 0) {
 			if (errno == EAGAIN || errno == EINTR) {
+				usleep(100000);
 				continue;
 			}
 			perror("read");
@@ -979,19 +996,17 @@ watch_ics_dir(void *arg)
 			struct inotify_event *event =
 			    (struct inotify_event *)&buffer[i];
 
-			char full_path[1024]; // Adjust size based on your max
-					      // path length
-			snprintf(full_path, sizeof(full_path), "%s/%s", ICS_DIR,
-				 event->name);
+			char *full_path = NULL;
+			asprintf(&full_path, "%s/%s", ICS_DIR, event->name);
 
 			if (event->len && strstr(event->name, ".ics")) {
 				LOG("Detected change in ICS file: %s\n",
 				    event->name);
-				update_fuse_entry_from_original(
-				    full_path); // Reload entries on any
-						// change
-				break;
+
+				// Reload entries on any change
+				update_fuse_entry_from_original(full_path);
 			}
+			free(full_path);
 
 			i += sizeof(struct inotify_event) + event->len;
 		}