BarryServer : Git

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

// Related

Orion

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