mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 10:26:59 +00:00
FEAT: VFS overhaul
This commit is contained in:
290
src/fs/procfs.c
Normal file
290
src/fs/procfs.c
Normal file
@@ -0,0 +1,290 @@
|
||||
#include "vfs.h"
|
||||
#include "../sys/process.h"
|
||||
#include "../sys/syscall.h"
|
||||
#include "../dev/disk.h"
|
||||
#include "memory_manager.h"
|
||||
#include "core/kutils.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t pid;
|
||||
char type[32];
|
||||
int offset;
|
||||
bool is_root;
|
||||
} procfs_handle_t;
|
||||
|
||||
void* procfs_open(void *fs_private, const char *path, const char *mode) {
|
||||
if (path[0] == '/') path++;
|
||||
|
||||
procfs_handle_t *h = (procfs_handle_t*)kmalloc(sizeof(procfs_handle_t));
|
||||
k_memset(h, 0, sizeof(procfs_handle_t));
|
||||
h->offset = 0;
|
||||
|
||||
if (path[0] == '\0') {
|
||||
h->is_root = true;
|
||||
return h;
|
||||
}
|
||||
|
||||
if (path[0] >= '0' && path[0] <= '9') {
|
||||
char pid_str[16];
|
||||
int i = 0;
|
||||
while (path[i] && path[i] != '/' && i < 15) {
|
||||
pid_str[i] = path[i];
|
||||
i++;
|
||||
}
|
||||
pid_str[i] = 0;
|
||||
h->pid = k_atoi(pid_str);
|
||||
|
||||
if (path[i] == '/') {
|
||||
k_strcpy(h->type, path + i + 1);
|
||||
} else {
|
||||
h->type[0] = 0;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
h->pid = 0xFFFFFFFF;
|
||||
k_strcpy(h->type, path);
|
||||
return h;
|
||||
}
|
||||
|
||||
void procfs_close(void *fs_private, void *handle) {
|
||||
if (handle) kfree(handle);
|
||||
}
|
||||
|
||||
int procfs_read(void *fs_private, void *handle, void *buf, int size) {
|
||||
procfs_handle_t *h = (procfs_handle_t*)handle;
|
||||
if (!h) return -1;
|
||||
|
||||
char out[1024];
|
||||
out[0] = 0;
|
||||
|
||||
if (h->pid == 0xFFFFFFFF) {
|
||||
if (k_strcmp(h->type, "version") == 0) {
|
||||
extern void get_os_info(os_info_t *info);
|
||||
os_info_t info;
|
||||
get_os_info(&info);
|
||||
k_strcpy(out, info.os_name);
|
||||
k_strcpy(out + k_strlen(out), " [");
|
||||
k_strcpy(out + k_strlen(out), info.os_codename);
|
||||
k_strcpy(out + k_strlen(out), "] Version ");
|
||||
k_strcpy(out + k_strlen(out), info.os_version);
|
||||
k_strcpy(out + k_strlen(out), "\nKernel: ");
|
||||
k_strcpy(out + k_strlen(out), info.kernel_name);
|
||||
k_strcpy(out + k_strlen(out), " ");
|
||||
k_strcpy(out + k_strlen(out), info.kernel_version);
|
||||
k_strcpy(out + k_strlen(out), "\nBuild: ");
|
||||
k_strcpy(out + k_strlen(out), info.build_date);
|
||||
k_strcpy(out + k_strlen(out), " ");
|
||||
k_strcpy(out + k_strlen(out), info.build_time);
|
||||
k_strcpy(out + k_strlen(out), "\n");
|
||||
} else if (k_strcmp(h->type, "uptime") == 0) {
|
||||
extern uint32_t wm_get_ticks(void);
|
||||
uint32_t ticks = wm_get_ticks();
|
||||
k_itoa(ticks / 60, out);
|
||||
k_strcpy(out + k_strlen(out), " seconds\nRaw_Ticks:");
|
||||
char t_s[16]; k_itoa(ticks, t_s);
|
||||
k_strcpy(out + k_strlen(out), t_s);
|
||||
k_strcpy(out + k_strlen(out), "\n");
|
||||
} else if (k_strcmp(h->type, "cpuinfo") == 0) {
|
||||
extern uint32_t smp_cpu_count(void);
|
||||
extern void platform_get_cpu_model(char *model);
|
||||
char model[64];
|
||||
platform_get_cpu_model(model);
|
||||
|
||||
k_strcpy(out, "Processor: ");
|
||||
k_strcpy(out + k_strlen(out), model);
|
||||
k_strcpy(out + k_strlen(out), "\nCores: ");
|
||||
char c_s[16]; k_itoa(smp_cpu_count(), c_s);
|
||||
k_strcpy(out + k_strlen(out), c_s);
|
||||
k_strcpy(out + k_strlen(out), "\nArchitecture: x86_64\n");
|
||||
} else if (k_strcmp(h->type, "meminfo") == 0) {
|
||||
extern MemStats memory_get_stats(void);
|
||||
MemStats stats = memory_get_stats();
|
||||
k_strcpy(out, "MemTotal: ");
|
||||
char m_s[32]; k_itoa(stats.total_memory / 1024, m_s);
|
||||
k_strcpy(out + k_strlen(out), m_s);
|
||||
k_strcpy(out + k_strlen(out), " kB\nMemFree: ");
|
||||
k_itoa(stats.available_memory / 1024, m_s);
|
||||
k_strcpy(out + k_strlen(out), m_s);
|
||||
k_strcpy(out + k_strlen(out), " kB\nMemUsed: ");
|
||||
k_itoa(stats.used_memory / 1024, m_s);
|
||||
k_strcpy(out + k_strlen(out), m_s);
|
||||
k_strcpy(out + k_strlen(out), " kB\nPeak: ");
|
||||
k_itoa(stats.peak_memory_used / 1024, m_s);
|
||||
k_strcpy(out + k_strlen(out), m_s);
|
||||
k_strcpy(out + k_strlen(out), " kB\nBlocks: ");
|
||||
k_itoa(stats.allocated_blocks, m_s);
|
||||
k_strcpy(out + k_strlen(out), m_s);
|
||||
k_strcpy(out + k_strlen(out), "\nFragmentation: ");
|
||||
k_itoa(stats.fragmentation_percent, m_s);
|
||||
k_strcpy(out + k_strlen(out), m_s);
|
||||
k_strcpy(out + k_strlen(out), "%\n");
|
||||
} else if (k_strcmp(h->type, "devices") == 0) {
|
||||
extern int disk_get_count(void);
|
||||
extern Disk* disk_get_by_index(int index);
|
||||
int dcount = disk_get_count();
|
||||
k_strcpy(out, "Block Devices:\n");
|
||||
for (int i = 0; i < dcount; i++) {
|
||||
Disk *d = disk_get_by_index(i);
|
||||
if (d) {
|
||||
k_strcpy(out + k_strlen(out), " - ");
|
||||
k_strcpy(out + k_strlen(out), d->devname);
|
||||
k_strcpy(out + k_strlen(out), "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
process_t *proc = process_get_by_pid(h->pid);
|
||||
if (!proc) return -1;
|
||||
|
||||
if (k_strcmp(h->type, "name") == 0 || k_strcmp(h->type, "cmdline") == 0) {
|
||||
k_strcpy(out, proc->name);
|
||||
k_strcpy(out + k_strlen(out), "\n");
|
||||
} else if (k_strcmp(h->type, "status") == 0) {
|
||||
k_strcpy(out, "Name: ");
|
||||
k_strcpy(out + k_strlen(out), proc->name);
|
||||
k_strcpy(out + k_strlen(out), "\nPID: ");
|
||||
char pid_s[16]; k_itoa(proc->pid, pid_s);
|
||||
k_strcpy(out + k_strlen(out), pid_s);
|
||||
k_strcpy(out + k_strlen(out), "\nState: RUNNING\nMemory: ");
|
||||
uint64_t mem_val = proc->used_memory;
|
||||
if (h->pid == 0) {
|
||||
extern MemStats memory_get_stats(void);
|
||||
mem_val = memory_get_stats().used_memory;
|
||||
}
|
||||
char mem_s[32]; k_itoa(mem_val / 1024, mem_s);
|
||||
k_strcpy(out + k_strlen(out), mem_s);
|
||||
k_strcpy(out + k_strlen(out), " KB\nTicks: ");
|
||||
char tick_s[32]; k_itoa(proc->ticks, tick_s);
|
||||
k_strcpy(out + k_strlen(out), tick_s);
|
||||
k_strcpy(out + k_strlen(out), "\nIdle: ");
|
||||
k_strcpy(out + k_strlen(out), proc->is_idle ? "1" : "0");
|
||||
k_strcpy(out + k_strlen(out), "\n");
|
||||
}
|
||||
}
|
||||
|
||||
int len = k_strlen(out);
|
||||
if (h->offset >= len) return 0;
|
||||
|
||||
int to_copy = len - h->offset;
|
||||
if (to_copy > size) to_copy = size;
|
||||
|
||||
k_memcpy(buf, out + h->offset, to_copy);
|
||||
h->offset += to_copy;
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
int procfs_write(void *fs_private, void *handle, const void *buf, int size) {
|
||||
procfs_handle_t *h = (procfs_handle_t*)handle;
|
||||
if (!h || h->pid == 0xFFFFFFFF) return -1;
|
||||
|
||||
if (k_strcmp(h->type, "signal") == 0) {
|
||||
char cmd[16];
|
||||
int to_copy = size < 15 ? size : 15;
|
||||
k_memcpy(cmd, buf, to_copy);
|
||||
cmd[to_copy] = 0;
|
||||
|
||||
if (k_strcmp(cmd, "9") == 0 || k_strcmp(cmd, "kill") == 0) {
|
||||
process_t *proc = process_get_by_pid(h->pid);
|
||||
if (proc && proc->pid != 0) {
|
||||
process_terminate(proc);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int procfs_readdir(void *fs_private, const char *path, vfs_dirent_t *entries, int max) {
|
||||
if (path[0] == '/') path++;
|
||||
|
||||
if (path[0] == '\0') {
|
||||
int out = 0;
|
||||
k_strcpy(entries[out++].name, "version");
|
||||
entries[out-1].is_directory = 0;
|
||||
k_strcpy(entries[out++].name, "uptime");
|
||||
entries[out-1].is_directory = 0;
|
||||
k_strcpy(entries[out++].name, "cpuinfo");
|
||||
entries[out-1].is_directory = 0;
|
||||
k_strcpy(entries[out++].name, "meminfo");
|
||||
entries[out-1].is_directory = 0;
|
||||
k_strcpy(entries[out++].name, "devices");
|
||||
entries[out-1].is_directory = 0;
|
||||
|
||||
extern process_t processes[];
|
||||
for (int i = 0; i < 16 && out < max; i++) {
|
||||
if (processes[i].pid != 0xFFFFFFFF) {
|
||||
k_itoa(processes[i].pid, entries[out].name);
|
||||
entries[out].is_directory = 1;
|
||||
entries[out].size = 0;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
if (path[0] >= '0' && path[0] <= '9') {
|
||||
int out = 0;
|
||||
k_strcpy(entries[out++].name, "name");
|
||||
k_strcpy(entries[out++].name, "status");
|
||||
k_strcpy(entries[out++].name, "cmdline");
|
||||
k_strcpy(entries[out++].name, "signal");
|
||||
for(int i=0; i<out; i++) entries[i].is_directory = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool procfs_exists(void *fs_private, const char *path) {
|
||||
if (path[0] == '/') path++;
|
||||
if (path[0] == '\0') return true;
|
||||
|
||||
if (path[0] >= '0' && path[0] <= '9') {
|
||||
char pid_str[16];
|
||||
int i = 0;
|
||||
while (path[i] && path[i] != '/' && i < 15) {
|
||||
pid_str[i] = path[i];
|
||||
i++;
|
||||
}
|
||||
pid_str[i] = 0;
|
||||
uint32_t pid = k_atoi(pid_str);
|
||||
if (process_get_by_pid(pid)) return true;
|
||||
}
|
||||
|
||||
if (k_strcmp(path, "version") == 0 || k_strcmp(path, "uptime") == 0) return true;
|
||||
if (k_strcmp(path, "cpuinfo") == 0 || k_strcmp(path, "meminfo") == 0) return true;
|
||||
if (k_strcmp(path, "devices") == 0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool procfs_is_dir(void *fs_private, const char *path) {
|
||||
if (path[0] == '/') path++;
|
||||
if (path[0] == '\0') return true;
|
||||
|
||||
if (path[0] >= '0' && path[0] <= '9') {
|
||||
int i = 0;
|
||||
while (path[i] && path[i] != '/') i++;
|
||||
if (path[i] == '\0') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs_fs_ops_t procfs_ops = {
|
||||
.open = procfs_open,
|
||||
.close = procfs_close,
|
||||
.read = procfs_read,
|
||||
.write = procfs_write,
|
||||
.readdir = procfs_readdir,
|
||||
.exists = procfs_exists,
|
||||
.is_dir = procfs_is_dir
|
||||
};
|
||||
|
||||
vfs_fs_ops_t* procfs_get_ops(void) {
|
||||
return &procfs_ops;
|
||||
}
|
||||
Reference in New Issue
Block a user