agendafs
A filesystem for your calendar.
git clone git://mccd.space/agendafs| Log | Files | Refs | README | LICENSE | Mail | Website |
fuse_node_store.c (3389B)
1 #include "agenda_entry.h"
2 #include "hashmap.h"
3 #include "path.h"
4 #include "tree.h"
5 #include "util.h"
6 #include <stddef.h>
7 #include <stdlib.h>
8 #include <string.h>
9 char VDIR[256];
10
11 char FILE_EXTENSION[256] = "";
12
13 // A structure of the current root
14 struct tree_node *fuse_root = NULL;
15 // ics entries, keys are the filename as stored in ICS_DIR
16 // I.E. bcb4c14b-8f3f-4a53-ad33-1f4499071a9m-caldavfs.ics
17 struct hashmap *entries_vdir = NULL;
18
19 // Copies vdir
20 void
21 set_vdir(const char *expanded_path)
22 {
23 strlcpy(VDIR, expanded_path, sizeof(VDIR));
24 }
25
26 const char *
27 get_default_file_extension()
28 {
29 return FILE_EXTENSION;
30 }
31
32 int
33 set_file_extension(const char *extension)
34 {
35 if (extension[0] == '.') {
36 return -1;
37 }
38
39 if (strlen(extension) > 256) {
40 return -2;
41 }
42
43 strlcpy(FILE_EXTENSION, extension, sizeof(FILE_EXTENSION));
44 return 0;
45 }
46
47 int
48 set_node_filename(struct tree_node *node, const char *filename)
49 {
50 struct agenda_entry *entry = node->data;
51 free(entry->filename);
52 entry->filename = xstrdup(filename);
53 return 0;
54 }
55
56 struct tree_node *
57 get_fuse_node_from_vdir_name(const char *vdir_name)
58 {
59 return hashmap_get(entries_vdir, vdir_name);
60 }
61
62 const struct agenda_entry *
63 get_entry(const struct tree_node *node)
64 {
65 return node->data;
66 }
67
68 bool
69 is_root_node(const struct tree_node *node)
70 {
71 // Root node is the only item without an agenda_entry
72 return !node->data;
73 }
74
75 const char *
76 get_node_filename(const struct tree_node *node)
77 {
78 struct agenda_entry *entry = node->data;
79 if (entry == NULL)
80 return "";
81 return entry->filename;
82 }
83
84 const char *
85 get_vdir_filepath(arena *ar, const struct tree_node *node)
86 {
87 const struct agenda_entry *entry = get_entry(node);
88 return append_path(ar, VDIR, entry->filename_vdir);
89 }
90
91 void
92 delete_fuse_node(struct tree_node *node)
93 {
94 const struct agenda_entry *e = get_entry(node);
95 hashmap_remove(entries_vdir, e->filename_vdir);
96 detach_tree_node(node);
97 free_tree(node);
98 }
99
100 // Copies agenda_entry
101 struct tree_node *
102 create_fuse_node(const struct agenda_entry *entry)
103 {
104 struct agenda_entry *cpy = copy_agenda_entry(entry);
105
106 struct tree_node *new_node =
107 create_tree_node(cpy, (void *)free_agenda_entry);
108
109 hashmap_insert(entries_vdir, cpy->filename_vdir, new_node);
110
111 return new_node;
112 }
113
114 struct tree_node *
115 upsert_fuse_node(const struct agenda_entry *entry)
116 {
117 struct tree_node *node =
118 hashmap_get(entries_vdir, entry->filename_vdir);
119 if (node) {
120 set_node_filename(node, entry->filename);
121 }
122 else {
123 node = create_fuse_node(entry);
124 }
125
126 return node;
127 }
128
129 // Add fuse child to node.
130 // OBS: Modifies filename if not unique!
131 size_t
132 add_fuse_child(struct tree_node *parent, struct tree_node *child)
133 {
134 const char *filename = get_node_filename(child);
135
136 char *new_filename = xstrdup(filename);
137
138 size_t conflict_count = 1;
139
140 while (true) {
141 bool is_unique = true;
142 for (size_t i = 0; i < parent->child_count; i++) {
143 const char *sibling_filename =
144 get_node_filename(parent->children[i]);
145
146 if (strcmp(new_filename, sibling_filename) == 0) {
147 is_unique = false;
148 break;
149 }
150 }
151
152 if (is_unique) {
153 break;
154 }
155
156 free(new_filename);
157 new_filename = filename_numbered(filename, conflict_count++);
158 }
159
160 set_node_filename(child, new_filename);
161
162 return add_child(parent, child);
163 }
164
165 size_t
166 move_fuse_node(struct tree_node *new_parent, struct tree_node *child)
167 {
168 detach_tree_node(child);
169 return add_fuse_child(new_parent, child);
170 }