99261380ca
This commit adds operations for appending directories and top-level lookups. Signed-off-by: Chloe M. <chloe@mensia.org>
187 lines
3.9 KiB
C
187 lines
3.9 KiB
C
/*
|
|
* Copyright (c) 2026, Chloe M.
|
|
* Provided under the BSD-3 clause.
|
|
*
|
|
* Description: Object manager
|
|
* Author: Chloe M.
|
|
*/
|
|
|
|
#include <ob/object.h>
|
|
#include <ex/pool.h>
|
|
#include <ob/cache.h>
|
|
#include <string.h>
|
|
#include <atomic.h>
|
|
|
|
ST_STATUS
|
|
ObCreateDirectory(const CHAR *Name, ST_OBJECT **Result)
|
|
{
|
|
ST_STATUS Status;
|
|
ST_OBJECT *DirecObj;
|
|
OBJECT_DIRECTORY *Direc;
|
|
|
|
if (Name == NULL || Result == NULL) {
|
|
return STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
Status = ObCreateObject(
|
|
Name,
|
|
OBJECT_TYPE_DIRECTORY,
|
|
NULL,
|
|
&DirecObj
|
|
);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
Direc = ExAllocatePoolWithTag(
|
|
POOL_NON_PAGED,
|
|
sizeof(*Direc),
|
|
OBJECT_POOL_TAG
|
|
);
|
|
|
|
if (Direc == NULL) {
|
|
ObReclaimObject(DirecObj);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
RtlMemSet(Direc, 0, sizeof(*Direc));
|
|
DirecObj->Data = Direc;
|
|
*Result = DirecObj;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ST_STATUS
|
|
ObCreateObject(const CHAR *Name, OBJECT_TYPE Type, VOID *Data, ST_OBJECT **Result)
|
|
{
|
|
ST_OBJECT *Object;
|
|
USIZE NameLen;
|
|
|
|
if (Name == NULL || Result == NULL) {
|
|
return STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
NameLen = RtlStrLen(Name);
|
|
if (NameLen >= OBJECT_NAMESZ - 1) {
|
|
return STATUS_NAME_TOO_LONG;
|
|
}
|
|
|
|
/*
|
|
* Try to pull an object from the cache, if there are not
|
|
* objects to pull then we'll allocate one.
|
|
*/
|
|
Object = ObPopFromCache(&gObCache);
|
|
if (Object == NULL) {
|
|
Object = ExAllocatePoolWithTag(
|
|
POOL_NON_PAGED,
|
|
sizeof(*Object),
|
|
OBJECT_POOL_TAG
|
|
);
|
|
|
|
if (Object == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
RtlMemSet(Object, 0, sizeof(*Object));
|
|
RtlMemCpy(Object->Name, Name, NameLen);
|
|
|
|
Object->Name[NameLen] = '\0';
|
|
Object->RefCount = 1;
|
|
Object->Type = Type;
|
|
Object->Data = Data;
|
|
*Result = Object;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
ObReclaimObject(ST_OBJECT *Object)
|
|
{
|
|
if (Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (AtomicDecLong(&Object->RefCount) == 0) {
|
|
ObReclaimToCache(&gObCache, Object);
|
|
}
|
|
}
|
|
|
|
ST_STATUS
|
|
ObAppendDirectory(ST_OBJECT *DirecParent, ST_OBJECT *Object)
|
|
{
|
|
OBJECT_DIRECTORY *Directory;
|
|
ST_OBJECT *Last;
|
|
|
|
if (DirecParent == NULL || Object == NULL) {
|
|
return STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if (DirecParent->Type != OBJECT_TYPE_DIRECTORY) {
|
|
return STATUS_NOT_DIRECTORY;
|
|
}
|
|
|
|
Directory = DirecParent->Data;
|
|
if (Directory == NULL) {
|
|
return STATUS_IO_ERROR;
|
|
}
|
|
|
|
/* TODO: Place lock here */
|
|
if (Directory->First == NULL || Directory->Last == NULL) {
|
|
Directory->First = Object;
|
|
Directory->Last = Object;
|
|
} else {
|
|
Last = Directory->Last;
|
|
Last->DirecNext = Object;
|
|
Directory->Last = Object;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ST_STATUS
|
|
ObLookupFromTop(ST_OBJECT *Parent, const CHAR *Name, ST_OBJECT **Result)
|
|
{
|
|
ST_OBJECT *Entry;
|
|
OBJECT_DIRECTORY *ParentDirec;
|
|
USIZE NameLen;
|
|
|
|
if (Parent == NULL || Name == NULL) {
|
|
return STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if (Result == NULL) {
|
|
return STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* Must be a directory */
|
|
if (Parent->Type != OBJECT_TYPE_DIRECTORY) {
|
|
return STATUS_NOT_DIRECTORY;
|
|
}
|
|
|
|
ParentDirec = Parent->Data;
|
|
if (ParentDirec == NULL) {
|
|
return STATUS_IO_ERROR;
|
|
}
|
|
|
|
Entry = ParentDirec->First;
|
|
NameLen = RtlStrLen(Name);
|
|
if (NameLen >= OBJECT_NAMESZ - 1) {
|
|
return STATUS_NAME_TOO_LONG;
|
|
}
|
|
|
|
while (Entry != NULL) {
|
|
if (*Entry->Name != *Name) {
|
|
Entry = Entry->DirecNext;
|
|
continue;
|
|
}
|
|
|
|
if (RtlMemCmp(Entry->Name, Name, NameLen) == 0) {
|
|
*Result = Entry;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
Entry = Entry->DirecNext;
|
|
}
|
|
|
|
return STATUS_NOT_FOUND;
|
|
}
|