Files
Chloe M. 99261380ca stos: ob: Add directory object operations
This commit adds operations for appending directories and top-level
lookups.

Signed-off-by: Chloe M. <chloe@mensia.org>
2026-06-25 23:26:54 +00:00

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