Orion
Barry Importing existing Orion kernel d41a53c (3 years, 2 months ago)
diff --git a/vfs/custody.c b/vfs/custody.c
new file mode 100644
index 0000000..1200f59
--- /dev/null
+++ b/vfs/custody.c
@@ -0,0 +1,117 @@
+/*
+ * This file handles chains of custody for files. It implements a generic set
+ * of operations for acting on CustodyChain objects. A CustodyChain holds a
+ * linked list of Custody objects, each of which refers to a directory entry.
+ * With this chain, the VFS is able to find what path was used to access a
+ * resources and go back up the chain (for implementing ..) and avoid going
+ * beyond the root.
+ */
+
+#include <string.h>
+#include "vfs.h"
+#include "cache.h"
+#include "../mem/heap.h"
+
+/* Initialise a custody chain */
+void
+init_custody_chain(CustodyChain *chain)
+{
+ Custody *root = kmalloc(sizeof(Custody));
+ chain->start = chain->end = root;
+ chain->size = 0;
+ init_lock(&chain->lock);
+ root->prev = root->next = NULL;
+ root->chain = chain;
+ root->entry = NULL;
+}
+
+/* Create a new custody chain */
+CustodyChain *
+create_custody_chain(void)
+{
+ CustodyChain *chain = kmalloc(sizeof(CustodyChain));
+ init_custody_chain(chain);
+ return chain;
+}
+
+/* Clean a custody chain */
+void
+clean_custody_chain(CustodyChain *chain)
+{
+ acquire(&chain->lock);
+ while (chain->size)
+ remove_custody(chain);
+ kfree(chain->start);
+ release(&chain->lock);
+}
+
+/* Destroy a custody chain */
+void
+destroy_custody_chain(CustodyChain *chain)
+{
+ clean_custody_chain(chain);
+ kfree(chain);
+}
+
+/* Copy custody chain */
+void
+copy_custody_chain(CustodyChain *chain, CustodyChain *newchain)
+{
+ acquire(&chain->lock);
+ acquire(&newchain->lock);
+ Custody *c;
+ for (c = chain->start->next; c; c = c->next)
+ add_custody(newchain, c->entry);
+ release(&newchain->lock);
+ release(&chain->lock);
+}
+
+/* Add entry */
+void
+add_custody(CustodyChain *chain, DirEntry *entry)
+{
+ acquire(&chain->lock);
+ chain->end->next = kmalloc(sizeof(Custody));
+ chain->end->next->prev= chain->end;
+ chain->end = chain->end->next;
+ chain->end->chain = chain;
+ chain->end->entry = entry_get(entry);
+ chain->size++;
+ release(&chain->lock);
+}
+
+/* Remove an entry */
+DirEntry *
+remove_custody(CustodyChain *chain)
+{
+ if (!chain->size)
+ return NULL;
+ acquire(&chain->lock);
+ entry_put(chain->end->entry);
+ chain->end = chain->end->prev;
+ kfree(chain->end->next);
+ chain->end->next = NULL;
+ chain->size--;
+ release(&chain->lock);
+ return chain->end->entry;
+}
+
+/* Convert a chain to a path string */
+char *
+custody_path(CustodyChain *chain, char *buf, size_t size)
+{
+ char *ptr = buf;
+ Custody *curr;
+ if (!chain->start->next) {
+ *ptr++ = '/';
+ *ptr = '\0';
+ return buf;
+ }
+ for (curr = chain->start->next; curr; curr = curr->next) {
+ *ptr++ = '/';
+ strcpy(ptr, curr->entry->name);
+ ptr += strlen(curr->entry->name);
+ }
+ *ptr = '\0';
+ return buf;
+}