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; +}