Files
aios/kernel/src/filesystem.rs
2025-07-05 17:21:10 +09:00

196 lines
4.9 KiB
Rust

//! Simple File System for Aios
//!
//! Provides basic file operations for package installation and management
#![allow(dead_code)]
/// Simple file entry
#[derive(Debug, Clone, Copy)]
pub struct FileEntry {
pub name: [u8; 32],
pub size: usize,
pub file_type: FileType,
pub data_offset: usize,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FileType {
Regular,
Directory,
Executable,
}
/// Simple in-memory file system
pub struct SimpleFS {
files: [Option<FileEntry>; 64],
file_count: usize,
data_storage: [u8; 2048], // 2KB storage (reduced from 8KB)
data_used: usize,
}
impl SimpleFS {
pub fn new() -> Self {
SimpleFS {
files: [None; 64],
file_count: 0,
data_storage: [0; 2048],
data_used: 0,
}
}
/// Create a file
pub fn create_file(&mut self, name: &str, content: &[u8], file_type: FileType) -> Result<(), &'static str> {
if self.file_count >= 64 {
return Err("File system full");
}
if name.len() > 31 {
return Err("Filename too long");
}
if self.data_used + content.len() > self.data_storage.len() {
return Err("Not enough storage space");
}
// Check if file already exists
if self.find_file(name).is_some() {
return Err("File already exists");
}
// Create file entry
let mut file_name = [0u8; 32];
let name_bytes = name.as_bytes();
for i in 0..name_bytes.len() {
file_name[i] = name_bytes[i];
}
let file_entry = FileEntry {
name: file_name,
size: content.len(),
file_type,
data_offset: self.data_used,
};
// Store file data
for i in 0..content.len() {
self.data_storage[self.data_used + i] = content[i];
}
self.data_used += content.len();
// Add file entry
self.files[self.file_count] = Some(file_entry);
self.file_count += 1;
Ok(())
}
/// Find a file by name
pub fn find_file(&self, name: &str) -> Option<&FileEntry> {
for i in 0..self.file_count {
if let Some(file) = &self.files[i] {
if self.str_eq(&file.name, name) {
return Some(file);
}
}
}
None
}
/// List all files
pub fn list_files(&self) -> &[Option<FileEntry>] {
&self.files[..self.file_count]
}
/// Read file content
pub fn read_file(&self, name: &str) -> Option<&[u8]> {
if let Some(file) = self.find_file(name) {
let start = file.data_offset;
let end = start + file.size;
Some(&self.data_storage[start..end])
} else {
None
}
}
/// Delete a file
pub fn delete_file(&mut self, name: &str) -> Result<(), &'static str> {
let mut found_index = None;
for i in 0..self.file_count {
if let Some(file) = &self.files[i] {
if self.str_eq(&file.name, name) {
found_index = Some(i);
break;
}
}
}
if let Some(index) = found_index {
// Remove file by shifting array
for i in index..self.file_count.saturating_sub(1) {
self.files[i] = self.files[i + 1];
}
self.files[self.file_count - 1] = None;
self.file_count -= 1;
Ok(())
} else {
Err("File not found")
}
}
/// Get file count
pub fn file_count(&self) -> usize {
self.file_count
}
/// Helper function to compare string with byte array
fn str_eq(&self, arr: &[u8; 32], s: &str) -> bool {
let s_bytes = s.as_bytes();
if s_bytes.len() > 32 {
return false;
}
// Find the end of the string in the array (null terminator)
let mut arr_len = 0;
for i in 0..32 {
if arr[i] == 0 {
break;
}
arr_len += 1;
}
if arr_len != s_bytes.len() {
return false;
}
for i in 0..arr_len {
if arr[i] != s_bytes[i] {
return false;
}
}
true
}
/// Get filename as string
pub fn filename_str(file: &FileEntry) -> &str {
let mut len = 0;
for i in 0..32 {
if file.name[i] == 0 {
break;
}
len += 1;
}
core::str::from_utf8(&file.name[..len]).unwrap_or("")
}
}
impl FileType {
pub fn as_str(&self) -> &'static str {
match self {
FileType::Regular => "file",
FileType::Directory => "dir",
FileType::Executable => "exec",
}
}
}