Orion
Barry Importing existing Orion kernel d41a53c (3 years, 1 month ago)
/*
* 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;
}