agendafs
A filesystem for your calendar.
git clone git://mccd.space/agendafscommit 1c1a7b02588e34e81036a31fc12e8f1bac9bd3d8
parent 84c07426a0268fe5b2b10d3c2cda34501c537887
Author: Marc Coquand <marc@coquand.email>
Date: Sun, 1 Jun 2025 16:01:29 +0100
Cleanup
Diffstat:
| M | main.c | | | 128 | +++++++++++++++++++++++++++---------------------------------------------------- |
1 file changed, 43 insertions(+), 85 deletions(-)
diff --git a/main.c b/main.c
@@ -32,7 +32,7 @@ typedef struct {
char *summary;
char *description;
char *uid;
- time_t timestamp;
+ time_t modified_at;
time_t created_at;
} journal_entry;
@@ -68,7 +68,7 @@ static time_t parse_datetime(const char *datetime)
-1; // Let mktime determine if daylight savings is needed
return mktime(&tm);
}
- return -1;
+ return INVALID_TIME;
}
// Folds are [\r]\n followed by ' ' or '\t'
@@ -276,11 +276,7 @@ static int parse_ics_file(const char *file_path, journal_entry *entry)
fseek(file, 0, SEEK_SET);
char *file_content = calloc(file_size + 1, sizeof(char));
- if (!file_content) {
- perror("Memory allocation failed");
- fclose(file);
- return -1;
- }
+
fread(file_content, 1, file_size, file);
file_content[file_size] = '\0'; // Null-terminate the string
fclose(file);
@@ -291,7 +287,8 @@ static int parse_ics_file(const char *file_path, journal_entry *entry)
entry->summary = extract_ical_field(file_content, "SUMMARY");
if (!entry->summary) {
fprintf(stderr, "SUMMARY field not found in: %s\n", file_path);
- goto cleanup;
+ free_journal_entry(entry);
+ return -1;
}
unescape_text(entry->summary);
@@ -299,7 +296,8 @@ static int parse_ics_file(const char *file_path, journal_entry *entry)
entry->uid = extract_ical_field(file_content, "UID");
if (!entry->uid) {
fprintf(stderr, "UID field not found in: %s\n", file_path);
- goto cleanup;
+ free_journal_entry(entry);
+ return -1;
}
unescape_text(entry->uid);
@@ -308,7 +306,9 @@ static int parse_ics_file(const char *file_path, journal_entry *entry)
if (!entry->description) {
fprintf(stderr, "DESCRIPTION field not found in: %s\n",
file_path);
- goto cleanup;
+
+ free_journal_entry(entry);
+ return -1;
}
unescape_text(entry->description);
@@ -317,16 +317,14 @@ static int parse_ics_file(const char *file_path, journal_entry *entry)
if (regexec(®ex_dtstamp, file_content, 2, matches_dtstamp, 0) == 0) {
char *dtstamp_str =
extract_match(file_content, matches_dtstamp[1]);
- if (!dtstamp_str) {
- perror("Memory allocation failed for DTSTAMP");
- goto cleanup;
- }
entry->created_at = parse_datetime(dtstamp_str);
free(dtstamp_str);
- if (entry->created_at == -1) {
+ if (entry->created_at == INVALID_TIME) {
fprintf(stderr, "Failed to parse DTSTAMP in: %s\n",
file_path);
- goto cleanup;
+
+ free_journal_entry(entry);
+ return -1;
}
}
else {
@@ -337,37 +335,23 @@ static int parse_ics_file(const char *file_path, journal_entry *entry)
if (regexec(®ex_lastmod, file_content, 2, matches_lastmod, 0) == 0) {
char *lastmod_str =
extract_match(file_content, matches_lastmod[1]);
- if (!lastmod_str) {
- perror("Memory allocation failed for LAST-MODIFIED");
- goto cleanup;
- }
- entry->timestamp = parse_datetime(lastmod_str);
+ entry->modified_at = parse_datetime(lastmod_str);
free(lastmod_str);
- if (entry->timestamp == -1) {
+ if (entry->modified_at == INVALID_TIME) {
fprintf(stderr,
"Failed to parse LAST-MODIFIED in: %s\n",
file_path);
- goto cleanup;
+
+ free_journal_entry(entry);
+ return -1;
}
}
else {
- entry->timestamp = entry->created_at;
+ entry->modified_at = entry->created_at;
}
- // Success
-
free(file_content);
return 0;
-
-cleanup:
- if (entry->summary)
- free(entry->summary);
- if (entry->description)
- free(entry->description);
- if (entry->uid)
- free(entry->uid);
- free(file_content);
- return -1;
}
// Dynamically create a time string using format
@@ -378,18 +362,11 @@ char *time_string(time_t time_val, const char *format)
return NULL;
}
- // Allocate a reasonably large buffer
size_t buf_size = 64;
char *buffer = malloc(buf_size);
- if (!buffer)
- return NULL;
size_t len = strftime(buffer, buf_size, format, &tm_info);
- if (len == 0) {
- free(buffer);
- return NULL; // Formatting failed (buffer too small)
- }
- return buffer; // caller must free this
+ return buffer;
}
// Uses created_at as filename.
@@ -427,6 +404,10 @@ char *get_unique_filename(time_t created_at, struct hashmap *entries_map)
return strdup(unique_filename);
}
+// Initializes
+// entries_original_key
+// entries_fuse_key
+// Should only be run once
static void load_journal_entries()
{
pthread_mutex_lock(&entries_mutex);
@@ -543,14 +524,13 @@ int journal_getattr(const char *path, struct stat *stbuf,
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
- // Write to nothing and get the size
int size = get_entry_content_size(entry);
stbuf->st_size = (off_t)size;
LOG("Entry found %s, %s", entry->filename, entry->description);
- stbuf->st_mtime = entry->timestamp;
- stbuf->st_ctime = entry->timestamp;
+ stbuf->st_mtime = entry->modified_at;
+ stbuf->st_ctime = entry->modified_at;
stbuf->st_atime = time(NULL);
ret_code = 0;
@@ -612,7 +592,6 @@ static int journal_read(const char *path, char *buf, size_t size, off_t offset,
int needed_len = get_entry_content_size(entry);
char *full_content = calloc(needed_len + 1, sizeof(char));
-
write_entry_content(full_content, needed_len + 1, entry);
if (offset >= needed_len) {
@@ -625,9 +604,10 @@ static int journal_read(const char *path, char *buf, size_t size, off_t offset,
if (offset + size > (size_t)needed_len)
size = needed_len - offset;
+ // Write to read buffer only the requested amount
memcpy(buf, full_content + offset, size);
-
free(full_content);
+
ret_code = size;
unlock_and_return:
@@ -640,17 +620,10 @@ char *journal_entry_to_ical(const journal_entry *entry)
char *escaped_summary = escape_text(entry->summary);
char *escaped_description = escape_text(entry->description);
- if (!escaped_summary || !escaped_description) {
- free(escaped_summary);
- free(escaped_description);
- LOG("FAILED TO ESCAPE");
- return NULL;
- }
-
// Format timestamps
struct tm created_tm, modified_tm;
gmtime_r(&entry->created_at, &created_tm);
- gmtime_r(&entry->timestamp, &modified_tm);
+ gmtime_r(&entry->modified_at, &modified_tm);
char dtstamp[32], lastmod[32];
strftime(dtstamp, sizeof(dtstamp), "%Y%m%dT%H%M%SZ", &created_tm);
@@ -659,15 +632,9 @@ char *journal_entry_to_ical(const journal_entry *entry)
// Estimate total size (safe upper bound)
size_t total_size = strlen(escaped_summary) +
strlen(escaped_description) + strlen(entry->uid) +
- strlen(dtstamp) + strlen(lastmod) +
- 512; // Extra for formatting
+ strlen(dtstamp) + strlen(lastmod) + 512;
- char *ical = malloc(total_size);
- if (!ical) {
- free(escaped_summary);
- free(escaped_description);
- return NULL;
- }
+ char *ical = calloc(total_size, sizeof(char));
snprintf(ical, total_size,
"BEGIN:VCALENDAR\n"
@@ -691,15 +658,14 @@ char *journal_entry_to_ical(const journal_entry *entry)
int parse_entry_content(journal_entry *entry, const char *buf, size_t size)
{
char *copy = strndup(buf, size);
- if (!copy)
- return -ENOMEM;
char *summary = NULL, *description = NULL;
char *sep = strstr(copy, "\n---\n");
+ // Malformed input
if (!sep) {
free(copy);
- return -EINVAL; // Malformed input
+ return -EINVAL;
}
*sep = '\0';
@@ -712,18 +678,13 @@ int parse_entry_content(journal_entry *entry, const char *buf, size_t size)
}
summary = strdup(summary_line);
- if (!summary) {
- free(copy);
- return -ENOMEM;
- }
// Clean up old values
free(entry->summary);
free(entry->description);
entry->summary = summary;
- entry->description = strdup(description ? description : "");
-
- entry->timestamp = time(NULL); // Update modified time
+ entry->description = strdup(description);
+ entry->modified_at = time(NULL);
free(copy);
return 0;
@@ -732,9 +693,6 @@ int parse_entry_content(journal_entry *entry, const char *buf, size_t size)
int write_entry_to_ical_file(const journal_entry *entry, const char *filepath)
{
char *ical_str = journal_entry_to_ical(entry);
- if (!ical_str) {
- return -EIO;
- }
FILE *f = fopen(filepath, "w");
if (!f) {
@@ -750,7 +708,7 @@ int write_entry_to_ical_file(const journal_entry *entry, const char *filepath)
return 0;
}
-// Full filepath
+// Full filepath of original ics file
char *get_original_filepath(const journal_entry *entry)
{
size_t needed =
@@ -779,7 +737,6 @@ static int journal_write(const char *path, const char *buf, size_t size,
}
char *filepath = get_original_filepath(entry);
-
if (write_entry_to_ical_file(entry, filepath) != 0) {
pthread_mutex_unlock(&entries_mutex);
return -EIO;
@@ -798,7 +755,7 @@ journal_entry *copy_journal_entry(const journal_entry *src)
copy->description = strdup(src->description);
copy->uid = strdup(src->uid);
- copy->timestamp = src->timestamp;
+ copy->modified_at = src->modified_at;
copy->created_at = src->created_at;
return copy;
@@ -863,14 +820,14 @@ static int do_journal_entry_rename(time_t new_created_at, const char *old,
}
journal_entry *new_entry = copy_journal_entry(old_entry);
-
- hashmap_remove(entries_original_key, old_entry->filename_original);
- hashmap_remove(entries_fuse_key, old_entry->filename);
-
free(new_entry->filename);
new_entry->filename = strdup(new_basename);
new_entry->created_at = new_created_at;
+ // hashmap frees old_entry
+ hashmap_remove(entries_original_key, old_entry->filename_original);
+ hashmap_remove(entries_fuse_key, old_entry->filename);
+
hashmap_insert(entries_original_key, new_entry->filename_original,
new_entry);
hashmap_insert(entries_fuse_key, new_entry->filename, new_entry);
@@ -1009,6 +966,7 @@ void *watch_ics_dir(void *arg)
close(fd);
return NULL;
}
+
int journal_create(const char *file_name, mode_t mode,
struct fuse_file_info *info)
{