Files
KirkOS/src/fs/ext2.h
T
kaguya ef14a52b49 rand: Add ChaCha20-based CSPRNG, among other things
We now have RNG!

- Implement ChaCha20-based cryptographically secure random number generator (CSPRNG) in `src/drivers/rand/random.c` and its header in `src/drivers/rand/random.h`.
- Modify VFS to support directory operations, including opening directories and reading directory entries.
- Update syscall interface to include new syscalls for directory handling: `SYS_OPEN_DIR` and `SYS_READ_ENTRIES`.
- Enhance file creation in EXT2 to allow specifying file modes.
- Refactor VFS file handling to accommodate new flags and modes.
- Update user-space application in `user/include/mlibc/helloworld.c` to demonstrate file operations including `touch`, `ls`, and `cat`.
- Clean up debug print statements in EXT2 file system code.
- Worked on proper error handling and return codes across VFS and syscall implementations.

It's only a small step but we're getting closer to making error codes standardized

We also setup SSE exactly as we should've the first time we introduced it in commit 9a9b91c

We have added it correctly to the user stack trampoline (hopefully), so there shouldn't be any issues now.

Signed-off-by: kaguya <vpshinomiya@protonmail.com>
2026-05-03 00:46:59 -04:00

220 lines
10 KiB
C

#pragma once
#include <stdint.h>
#include <stdbool.h>
#define EXT2_SUPERBLOCK_OFFSET 1024
#define EXT2_SUPERBLOCK_SIZE 1024
#define EXT2_MAGIC 0xEF53
#define EXT2_NAME_LEN 255
typedef struct ext2_superblock {
unsigned int s_inodes_count; /* Inodes count */
unsigned int s_blocks_count; /* Blocks count */
unsigned int s_r_blocks_count; /* Reserved blocks count */
unsigned int s_free_blocks_count; /* Free blocks count */
unsigned int s_free_inodes_count; /* Free inodes count */
unsigned int s_first_data_block; /* First Data Block */
unsigned int s_log_block_size; /* Block size */
unsigned int s_log_frag_size; /* Fragment size */
unsigned int s_blocks_per_group; /* # Blocks per group */
unsigned int s_frags_per_group; /* # Fragments per group */
unsigned int s_inodes_per_group; /* # Inodes per group */
unsigned int s_mtime; /* Mount time */
unsigned int s_wtime; /* Write time */
unsigned short s_mnt_count; /* Mount count */
unsigned short s_max_mnt_count; /* Maximal mount count */
unsigned short s_magic; /* Magic signature */
unsigned short s_state; /* File system state */
unsigned short s_errors; /* Behaviour when detecting errors */
unsigned short s_minor_rev_level; /* minor revision level */
unsigned int s_lastcheck; /* time of last check */
unsigned int s_checkinterval; /* max. time between checks */
unsigned int s_creator_os; /* OS */
unsigned int s_rev_level; /* Revision level */
unsigned short s_def_resuid; /* Default uid for reserved blocks */
unsigned short s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
unsigned int s_first_ino; /* First non-reserved inode */
unsigned short s_inode_size; /* size of inode structure */
unsigned short s_block_group_nr; /* block group # of this superblock */
unsigned int s_feature_compat; /* compatible feature set */
unsigned int s_feature_incompat; /* incompatible feature set */
unsigned int s_feature_ro_compat; /* readonly-compatible feature set */
unsigned char s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
unsigned int s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_COMPAT_PREALLOC flag is on.
*/
unsigned char s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
unsigned char s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
unsigned short s_padding1;
/*
* Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
*/
unsigned char s_journal_uuid[16]; /* uuid of journal superblock */
unsigned int s_journal_inum; /* inode number of journal file */
unsigned int s_journal_dev; /* device number of journal file */
unsigned int s_last_orphan; /* start of list of inodes to delete */
unsigned int s_hash_seed[4]; /* HTREE hash seed */
unsigned char s_def_hash_version; /* Default hash version to use */
unsigned char s_reserved_char_pad;
unsigned short s_reserved_word_pad;
unsigned int s_default_mount_opts;
unsigned int s_first_meta_bg; /* First metablock block group */
unsigned int s_reserved[190]; /* Padding to the end of the block */
} __attribute__((packed)) ext2_superblock_t;
typedef struct ext2_group_desc {
unsigned int bg_block_bitmap; /* Blocks bitmap block */
unsigned int bg_inode_bitmap; /* Inodes bitmap block */
unsigned int bg_inode_table; /* Inodes table block */
unsigned short bg_free_blocks_count; /* Free blocks count */
unsigned short bg_free_inodes_count; /* Free inodes count */
unsigned short bg_used_dirs_count; /* Directories count */
unsigned short bg_pad;
unsigned int bg_reserved[3];
} __attribute__((packed)) ext2_group_desc_t;
typedef struct ext2_inode {
unsigned short i_mode; /* File mode */
unsigned short i_uid; /* Low 16 bits of Owner Uid */
unsigned int i_size; /* Size in bytes */
unsigned int i_atime; /* Access time */
unsigned int i_ctime; /* Creation time */
unsigned int i_mtime; /* Modification time */
unsigned int i_dtime; /* Deletion Time */
unsigned short i_gid; /* Low 16 bits of Group Id */
unsigned short i_links_count; /* Links count */
unsigned int i_blocks; /* Blocks count IN DISK SECTORS*/
unsigned int i_flags; /* File flags */
unsigned int osd1; /* OS dependent 1 */
unsigned int i_block[15]; /* Pointers to blocks */
unsigned int i_generation; /* File version (for NFS) */
unsigned int i_file_acl; /* File ACL */
unsigned int i_dir_acl; /* Directory ACL */
unsigned int i_faddr; /* Fragment address */
unsigned int extra[3];
} __attribute__((packed)) ext2_inode_t;
typedef struct ext2_dir_entry {
unsigned int inode; /* Inode number */
unsigned short rec_len; /* Directory entry length */
unsigned char name_len; /* Name length */
unsigned char file_type;
char name[]; /* File name, up to EXT2_NAME_LEN */
} __attribute__((packed)) ext2_dir_entry_t;
typedef struct {
uint32_t ino;
uint16_t mode;
uint16_t uid;
uint16_t gid;
uint32_t size;
uint32_t atime;
uint32_t mtime;
uint32_t ctime;
uint32_t nlink;
uint32_t blocks;
} ext2_stat_t;
typedef enum {
EXT2_WRITE_OVERWRITE,
EXT2_WRITE_APPEND,
} ext2_write_mode_t;
// Inode type and permissions
#define EXT2_S_IFIFO 0x1000
#define EXT2_S_IFCHR 0x2000
#define EXT2_S_IFDIR 0x4000
#define EXT2_S_IFBLK 0x6000
#define EXT2_S_IFREG 0x8000
#define EXT2_S_IFLNK 0xA000
#define EXT2_S_IFSOCK 0xC000
#define EXT2_S_IRUSR 0x0100
#define EXT2_S_IWUSR 0x0080
#define EXT2_S_IXUSR 0x0040
#define EXT2_S_IRGRP 0x0020
#define EXT2_S_IWGRP 0x0010
#define EXT2_S_IXGRP 0x0008
#define EXT2_S_IROTH 0x0004
#define EXT2_S_IWOTH 0x0002
#define EXT2_S_IXOTH 0x0001
// File types for directory entries
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_REG_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHRDEV 3
#define EXT2_FT_BLKDEV 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
// ── init ──────────────────────────────────────────────────────────────────────
bool ext2_read_superblock(void);
bool ext2_read_group_desc_table(void);
// ── low-level ────────────────────────────────────────────────────────────────
bool ext2_read_block(uint32_t block_num, void* buf);
bool ext2_write_block(uint32_t block_num, const void* buf);
bool ext2_read_inode(uint32_t inode_num, ext2_inode_t* out);
bool ext2_write_inode(uint32_t inode_num, ext2_inode_t* inode);
// ── path / directory ─────────────────────────────────────────────────────────
uint32_t ext2_resolve_path(const char* path); // returns inode num, 0 = not found
bool ext2_find_in_dir(ext2_inode_t* dir, const char* name, uint32_t* out_inum);
bool ext2_read_dir(ext2_inode_t* dir);
bool ext2_read_root_dir(void);
// ── file I/O ─────────────────────────────────────────────────────────────────
bool ext2_read_file(ext2_inode_t* inode, uint8_t* buf);
bool ext2_write_file(ext2_inode_t* inode, uint32_t inode_num,
const uint8_t* data, uint32_t size, ext2_write_mode_t mode);
bool ext2_truncate(ext2_inode_t* inode, uint32_t inode_num, uint32_t new_size);
// ── high-level (operate from a path string) ───────────────────────────────────
bool ext2_read_file_from_root(const char* name, uint8_t* buf, uint32_t* size);
bool ext2_write_file_from_root(const char* name, const uint8_t* data,
uint32_t size, ext2_write_mode_t mode);
// ── create / delete ───────────────────────────────────────────────────────────
bool ext2_create_file(ext2_inode_t* dir, uint32_t dir_inum,
const char* name, uint16_t mode, uint32_t* out_inum);
bool ext2_mkdir(ext2_inode_t* parent, uint32_t parent_inum,
const char* name, uint32_t* out_inum);
bool ext2_unlink(ext2_inode_t* dir, uint32_t dir_inum, const char* name);
bool ext2_rmdir(ext2_inode_t* parent, uint32_t parent_inum, const char* name);
bool ext2_rename(ext2_inode_t* src_dir, uint32_t src_inum,
ext2_inode_t* dst_dir, uint32_t dst_inum,
const char* old_name, const char* new_name);
// ── symlinks ──────────────────────────────────────────────────────────────────
bool ext2_symlink(ext2_inode_t* dir, uint32_t dir_inum,
const char* name, const char* target);
bool ext2_readlink(uint32_t inode_num, char* buf, uint32_t buf_size);
// ── metadata ─────────────────────────────────────────────────────────────────
bool ext2_stat(uint32_t inode_num, ext2_stat_t* st);
bool ext2_chmod(uint32_t inode_num, uint16_t mode);
bool ext2_chown(uint32_t inode_num, uint16_t uid, uint16_t gid);
const char* ext2_file_type_string(uint8_t type);