BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / commit / d41a53cbc7d055b1c00cf0a339dbed6925f4f02c / vfs / custody.c

// Related

Orion

Barry Importing existing Orion kernel d41a53c (2 years, 4 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;
+}