Files
nt-lite/code/kernel/io_file.c
T
2026-04-30 23:52:46 +02:00

114 lines
4.0 KiB
C

// io_file.c - VFS dispatch layer
#include "ke_list.h"
#include "io_file.h"
#include "mm_virt.h"
#include "ob_object.h"
#include <string.h>
#define MAX_DRIVES 8
typedef struct {
IO_FILESYSTEM *Fs;
IO_VOLUME_PARAMS Vol;
} VOLUME_ENTRY;
static VOLUME_ENTRY gVolumes[MAX_DRIVES];
// ---------------------------------------------------------------------------
// Registration
// ---------------------------------------------------------------------------
KSTATUS IoRegisterFilesystem(uint8_t volumeIndex,
IO_FILESYSTEM *fs,
const IO_VOLUME_PARAMS *vol) {
if (volumeIndex >= MAX_DRIVES || !fs || !vol)
return STATUS_INVALID_PARAMETER;
if (gVolumes[volumeIndex].Fs)
return STATUS_ALREADY_EXISTS;
gVolumes[volumeIndex].Fs = fs;
gVolumes[volumeIndex].Vol = *vol;
return STATUS_SUCCESS;
}
// ---------------------------------------------------------------------------
// Path parsing - "0:\apps\shell.exe" or just "apps\shell.exe" (drive 0)
// ---------------------------------------------------------------------------
static uint8_t ParseDrive(const char* path, const char **pathOut) {
// Accept "N:\..." prefix, otherwise default to drive 0.
if (path[0] >= '0' && path[0] <= '7' &&
path[1] == ':' && (path[2] == '\\' || path[2] == '/')) {
*pathOut = path + 3;
return (uint8_t)(path[0] - '0');
}
*pathOut = path;
return 0;
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
static void FileDestroy(OBJECT* obj) {
FILE_OBJECT* f = CONTAINING_RECORD(obj, FILE_OBJECT, Header);
if (f->Fs && f->FileCtx) f->Fs->Close(f->Fs, f->FileCtx);
}
// ---------------------------------------------------------------------------
// IoOpenFile
// ---------------------------------------------------------------------------
KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) {
if (!path || !out) return STATUS_INVALID_PARAMETER;
const char* relPath;
uint8_t drive = ParseDrive(path, &relPath);
IO_FILESYSTEM* fs = gVolumes[drive].Fs;
if (!fs) return STATUS_NOT_FOUND;
void* fileCtx;
KSTATUS s = fs->Open(fs, relPath, &fileCtx);
if (!KSUCCESS(s)) return s;
FILE_OBJECT* f = (FILE_OBJECT *)ObAllocateObject(ObjectTypeFile /* reuse slot */,
sizeof(FILE_OBJECT));
if (!f) { fs->Close(fs, fileCtx); return STATUS_NO_MEMORY; }
f->Header.Destroy = FileDestroy;
f->Fs = fs;
f->FileCtx = fileCtx;
f->Size = fs->GetSize(fs, fileCtx);
f->Offset = 0;
*out = f;
return STATUS_SUCCESS;
}
// ---------------------------------------------------------------------------
// IoReadFile - sequential read at current offset
// ---------------------------------------------------------------------------
KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) {
if (!file || !buf) return STATUS_INVALID_PARAMETER;
if (file->Offset >= file->Size) { *bytesRead = 0; return STATUS_SUCCESS; }
// Clamp to remaining bytes.
size_t remaining = (size_t)(file->Size - file->Offset);
if (size > remaining) size = remaining;
KSTATUS s = file->Fs->Read(file->Fs, file->FileCtx,
file->Offset, buf, size, bytesRead);
if (KSUCCESS(s)) file->Offset += *bytesRead;
return s;
}
// ---------------------------------------------------------------------------
KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) {
if (!file) return STATUS_INVALID_PARAMETER;
file->Offset = offset;
return STATUS_SUCCESS;
}
uint64_t IoGetFileSize(FILE_OBJECT* file) {
return file ? file->Size : 0;
}
void IoCloseFile(FILE_OBJECT* file) {
if (file) ObDereferenceObject(&file->Header);
}