134 lines
3.0 KiB
C
134 lines
3.0 KiB
C
|
#include "alloc.h"
|
||
|
#include "assert.h"
|
||
|
#include "fsEntry.h"
|
||
|
#include "errno.h"
|
||
|
#include "list.h"
|
||
|
#include "mem.h"
|
||
|
#include "stdint.h"
|
||
|
|
||
|
bool_t pstringSplipPath(struct pstr *path, struct pstr *upper, struct pstr *lower)
|
||
|
{
|
||
|
typeof(path->name) curPos = path->name;
|
||
|
typeof(path->len) curLen = path->len;
|
||
|
typeof(path->len) upperLen = 0;
|
||
|
|
||
|
// Skip leading /
|
||
|
while (curLen > 0 && curPos[0] == '/') {
|
||
|
curPos++;
|
||
|
curLen--;
|
||
|
}
|
||
|
|
||
|
upper->name = curPos;
|
||
|
|
||
|
// Find first non /
|
||
|
while (curLen > 0 && curPos[0] != '/') {
|
||
|
upperLen++;
|
||
|
curLen--;
|
||
|
curPos++;
|
||
|
}
|
||
|
upper->len = upperLen;
|
||
|
|
||
|
while (curLen > 0 && curPos[0] == '/') {
|
||
|
curPos++;
|
||
|
curLen--;
|
||
|
}
|
||
|
lower->name = curPos;
|
||
|
lower->len = path->len - (lower->name - path->name);
|
||
|
|
||
|
return lower->len > 0;
|
||
|
}
|
||
|
|
||
|
bool_t pstringIsEq(struct pstr *p1, struct pstr *p2)
|
||
|
{
|
||
|
return p1->len == p2->len && (memcmp(p1, p2, p1->len) == 0);
|
||
|
}
|
||
|
|
||
|
int fsEntryRef(struct fsEntry *entry)
|
||
|
{
|
||
|
entry->ref++;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int fsEntryUnref(struct fsEntry **entry)
|
||
|
{
|
||
|
struct fsEntry *toDelete = NULL, *entryTmp;
|
||
|
|
||
|
entryTmp = *entry;
|
||
|
*entry = NULL;
|
||
|
|
||
|
while (entryTmp) {
|
||
|
assert(entryTmp->ref > 0);
|
||
|
entryTmp->ref--;
|
||
|
|
||
|
if (entryTmp->ref > 0)
|
||
|
break;
|
||
|
|
||
|
if (entryTmp == *entry)
|
||
|
entry = NULL;
|
||
|
|
||
|
if (entryTmp->parent) {
|
||
|
struct fsEntry *parent = entryTmp->parent;
|
||
|
|
||
|
assert(entryTmp->parent->ref >= 1);
|
||
|
|
||
|
list_delete_named(parent->childs, entryTmp, prevSiblings, nextSiblings);
|
||
|
// At next iteration we will decrement parent's ref cnt
|
||
|
}
|
||
|
|
||
|
// Avoid recursivity in kernel by using a list of entry to suppress
|
||
|
list_add_tail_named(toDelete, entryTmp, prevSiblings, nextSiblings);
|
||
|
|
||
|
// now, unref parent
|
||
|
entryTmp = entryTmp->parent;
|
||
|
}
|
||
|
|
||
|
// free 0 ref entries
|
||
|
while (!list_is_empty_named(toDelete, prevSiblings, nextSiblings)) {
|
||
|
entryTmp = list_pop_head_named(toDelete, prevSiblings, nextSiblings);
|
||
|
fsInodeUnref(entryTmp->node);
|
||
|
free(entryTmp);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int fsEntryNewChild(struct fsEntry *parent, const struct pstr *name, struct inode *inode,
|
||
|
struct fsEntry **result)
|
||
|
{
|
||
|
struct fsEntry *entry = malloc(sizeof(struct fsEntry));
|
||
|
|
||
|
if (!entry)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
if (name && name->len > 0) {
|
||
|
char *allocName = malloc(name->len);
|
||
|
|
||
|
if (!allocName) {
|
||
|
free(entry);
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
memcpy(allocName, name->name, name->len);
|
||
|
entry->name.len = name->len;
|
||
|
entry->name.name = allocName;
|
||
|
}
|
||
|
|
||
|
entry->ref = 1;
|
||
|
entry->node = inode;
|
||
|
entry->parent = parent;
|
||
|
|
||
|
fsInodeRef(inode);
|
||
|
if (parent) {
|
||
|
fsEntryRef(parent);
|
||
|
list_add_head_named(parent->childs, entry, prevSiblings, nextSiblings);
|
||
|
}
|
||
|
|
||
|
*result = entry;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int fsEntrySetup(void){
|
||
|
return allocBookSlab(sizeof(struct fsEntry), PAGE_SIZE, 0, 0);
|
||
|
}
|