syscalls: implement stat and fstat syscalls
This commit is contained in:
@@ -69,6 +69,12 @@ iso:
|
|||||||
cp grubshit/zsh katauos/katau/zsh
|
cp grubshit/zsh katauos/katau/zsh
|
||||||
cp grubshit/ksh katauos/katau/ksh
|
cp grubshit/ksh katauos/katau/ksh
|
||||||
|
|
||||||
|
cp grubshit/ls katauos/katau/ls
|
||||||
|
cp grubshit/stat katauos/katau/stat
|
||||||
|
cp grubshit/stat.c katauos/katau/stat.c
|
||||||
|
cp grubshit/main katauos/main
|
||||||
|
cp grubshit/video.dat katauos/katau/video.dat
|
||||||
|
|
||||||
sudo umount tmp/
|
sudo umount tmp/
|
||||||
grub-mkrescue -o boot.iso katauos/
|
grub-mkrescue -o boot.iso katauos/
|
||||||
|
|
||||||
|
|||||||
@@ -12,5 +12,6 @@ char *strcat(char *dest, const char *src);
|
|||||||
char *strcpy(char *dest, const char *src);
|
char *strcpy(char *dest, const char *src);
|
||||||
char *strtok(char *str, const char *delim);
|
char *strtok(char *str, const char *delim);
|
||||||
char *strrchr(const char *s, int c);
|
char *strrchr(const char *s, int c);
|
||||||
|
int strcmp(const char* s1, const char* s2);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+198
-19
@@ -102,6 +102,8 @@ int sys_fork(TrapFrame *tf)
|
|||||||
child->state = Ready;
|
child->state = Ready;
|
||||||
child->ring = current->ring;
|
child->ring = current->ring;
|
||||||
child->pagedir = new_pd;
|
child->pagedir = new_pd;
|
||||||
|
child->cwd = malloc(sizeof(l9660_dir));
|
||||||
|
memcpy(child->cwd, current->cwd, sizeof(l9660_dir));
|
||||||
|
|
||||||
void *kstack_physical = alloc_page();
|
void *kstack_physical = alloc_page();
|
||||||
if (!kstack_physical) {
|
if (!kstack_physical) {
|
||||||
@@ -281,30 +283,27 @@ int sys_open(TrapFrame *tf)
|
|||||||
int flags = tf->ecx;
|
int flags = tf->ecx;
|
||||||
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
const char* mode_str = flags_to_mode_str(flags);
|
for(int i = 3; i < MAX_OPEN_FILES; i++) {
|
||||||
|
if(current->file_descriptors[i] == NULL) {
|
||||||
//debug_log("\n====filename: %s\n", filename);
|
|
||||||
//debug_log("\n====mode_str: %s\n", mode_str);
|
|
||||||
|
|
||||||
for(int i = 3; i < MAX_OPEN_FILES; i++)
|
|
||||||
{
|
|
||||||
//debug_log("\n====i: %X\n", i);
|
|
||||||
if(current->file_descriptors[i] == NULL)
|
|
||||||
{
|
|
||||||
current->file_descriptors[i] = (l9660_file*)malloc(sizeof(l9660_file)); // Kernel malloc
|
|
||||||
l9660_openat(current->file_descriptors[i], root_dir, filename);
|
|
||||||
//debug_log("\n====FILE_DESCRIPTOR: %X\n", i);
|
|
||||||
int result = 0;//fat_fopen(current->file_descriptors[i], filename, mode_str);
|
|
||||||
if (result < 0) {
|
|
||||||
free(current->file_descriptors[i]); // Free on failure
|
|
||||||
current->file_descriptors[i] = NULL;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
fd = i;
|
fd = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fd == -1) return -23; // -ENFILE
|
||||||
|
|
||||||
|
l9660_file* file = (l9660_file*)malloc(sizeof(l9660_file));
|
||||||
|
if (!file) return -12; // -ENOMEM
|
||||||
|
|
||||||
|
l9660_dir temp_dir = *current->cwd;
|
||||||
|
l9660_seekdir(&temp_dir, 0);
|
||||||
|
int status = follow_path(filename, file, &temp_dir);
|
||||||
|
|
||||||
|
if (status != L9660_OK) {
|
||||||
|
free(file);
|
||||||
|
return -2; // -ENOENT
|
||||||
|
}
|
||||||
|
|
||||||
|
current->file_descriptors[fd] = file;
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,6 +660,178 @@ uint32_t sys_nanosleep(TrapFrame *tf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct stat {
|
||||||
|
uint32_t st_dev;
|
||||||
|
uint32_t st_ino;
|
||||||
|
uint16_t st_mode; /* mode is 16-bit in standard 32-bit ABI */
|
||||||
|
uint16_t st_nlink; /* nlink is 16-bit */
|
||||||
|
uint16_t st_uid; /* uid is 16-bit */
|
||||||
|
uint16_t st_gid; /* gid is 16-bit */
|
||||||
|
uint32_t st_rdev;
|
||||||
|
uint32_t st_size;
|
||||||
|
uint32_t st_blksize;
|
||||||
|
uint32_t st_blocks;
|
||||||
|
uint32_t st_atime;
|
||||||
|
uint32_t st_atime_nsec;
|
||||||
|
uint32_t st_mtime;
|
||||||
|
uint32_t st_mtime_nsec;
|
||||||
|
uint32_t st_ctime;
|
||||||
|
uint32_t st_ctime_nsec;
|
||||||
|
uint32_t __unused4;
|
||||||
|
uint32_t __unused5;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* File type flags (st_mode) */
|
||||||
|
#define S_IFMT 0xF000 /* Format mask */
|
||||||
|
#define S_IFSOCK 0xC000 /* Socket */
|
||||||
|
#define S_IFLNK 0xA000 /* Symbolic link */
|
||||||
|
#define S_IFREG 0x8000 /* Regular file */
|
||||||
|
#define S_IFBLK 0x6000 /* Block device */
|
||||||
|
#define S_IFDIR 0x4000 /* Directory */
|
||||||
|
#define S_IFCHR 0x2000 /* Character device */
|
||||||
|
#define S_IFIFO 0x1000 /* FIFO */
|
||||||
|
|
||||||
|
/* Permissions (simplified) */
|
||||||
|
#define S_IRWXU 00700 /* User rwx */
|
||||||
|
#define S_IRUSR 00400 /* User read */
|
||||||
|
#define S_IWUSR 00200 /* User write */
|
||||||
|
#define S_IXUSR 00100 /* User execute */
|
||||||
|
|
||||||
|
#ifdef L9660_BIG_ENDIAN
|
||||||
|
#define READ32(v) (((v).be[3]) | ((v).be[2] << 8) | ((v).be[1]) << 16 | ((v).be[0] << 24))
|
||||||
|
#else
|
||||||
|
#define READ32(v) (((v).le[0]) | ((v).le[1] << 8) | ((v).le[2]) << 16 | ((v).le[3] << 24))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int find_entry_info(l9660_dir* parent, const char* name, uint32_t* sector, uint32_t* size) {
|
||||||
|
l9660_dirent* dent;
|
||||||
|
l9660_status status;
|
||||||
|
|
||||||
|
// Rewind directory to start
|
||||||
|
l9660_seekdir(parent, 0);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
status = l9660_readdir(parent, &dent);
|
||||||
|
if (status != L9660_OK || dent == NULL) break;
|
||||||
|
|
||||||
|
// Compare names (dent->name is NOT null-terminated)
|
||||||
|
size_t name_len = strlen(name);
|
||||||
|
if (name_len == dent->name_len && memcmp(dent->name, name, name_len) == 0) {
|
||||||
|
*sector = READ32(dent->sector);
|
||||||
|
*size = READ32(dent->size);
|
||||||
|
return 0; // Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1; // Not found
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_fstat(TrapFrame *tf)
|
||||||
|
{
|
||||||
|
int fd = tf->ebx;
|
||||||
|
struct stat *st = (struct stat*)tf->ecx;
|
||||||
|
|
||||||
|
if (!st) return -14; // -EFAULT
|
||||||
|
memset(st, 0, sizeof(struct stat));
|
||||||
|
|
||||||
|
//if stdin, stdout or stderr
|
||||||
|
if (fd >= 0 && fd < 3) {
|
||||||
|
st->st_mode = S_IFCHR | 0666; // Character device
|
||||||
|
st->st_rdev = fd;
|
||||||
|
st->st_nlink = 1;
|
||||||
|
st->st_blksize = 1024;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd >= MAX_OPEN_FILES || current->file_descriptors[fd] == NULL) {
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
l9660_file* file = current->file_descriptors[fd];
|
||||||
|
|
||||||
|
st->st_dev = 0;
|
||||||
|
st->st_ino = file->first_sector;//use first sector as inode
|
||||||
|
st->st_mode = S_IFREG | 0777; // Regular file
|
||||||
|
st->st_nlink = 1;
|
||||||
|
|
||||||
|
//get size properly
|
||||||
|
uint32_t old_pos = l9660_tell(file);
|
||||||
|
l9660_seek(file, L9660_SEEK_END, 0);
|
||||||
|
st->st_size = l9660_tell(file);
|
||||||
|
l9660_seek(file, L9660_SEEK_SET, old_pos);
|
||||||
|
|
||||||
|
st->st_blksize = 2048;
|
||||||
|
st->st_blocks = DivRoundUp(st->st_size, 512);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_stat(TrapFrame *tf)
|
||||||
|
{
|
||||||
|
const char* path = (const char*)tf->ebx;
|
||||||
|
struct stat *st = (struct stat*)tf->ecx;
|
||||||
|
|
||||||
|
if (!path || !st) return -14; // -EFAULT
|
||||||
|
memset(st, 0, sizeof(struct stat));
|
||||||
|
|
||||||
|
if (strcmp(path, "/") == 0) {
|
||||||
|
st->st_mode = S_IFDIR | 0755;
|
||||||
|
st->st_ino = root_dir->file.first_sector;
|
||||||
|
st->st_size = 2048;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
l9660_file file;
|
||||||
|
l9660_dir parent_dir = *current->cwd;
|
||||||
|
|
||||||
|
int status = follow_path(path, &file, &parent_dir);
|
||||||
|
|
||||||
|
if (status == L9660_OK) {
|
||||||
|
// It is a FILE
|
||||||
|
st->st_mode = S_IFREG | 0777;
|
||||||
|
st->st_ino = file.first_sector;
|
||||||
|
|
||||||
|
l9660_seek(&file, L9660_SEEK_END, 0);
|
||||||
|
st->st_size = l9660_tell(&file);
|
||||||
|
}
|
||||||
|
else if (status == L9660_ENOTFILE) {
|
||||||
|
// It is likely a DIRECTORY
|
||||||
|
// follow_path failed because the last component was a dir, not a file.
|
||||||
|
// 'parent_dir' now points to the directory CONTAINING the target.
|
||||||
|
|
||||||
|
// We need to extract the target name from the path.
|
||||||
|
// e.g., "/boot/grub" -> parent is "/boot", target name is "grub"
|
||||||
|
const char* name = strrchr(path, '/');
|
||||||
|
if (name) name++; // Skip slash
|
||||||
|
else name = path; // No slash, just name
|
||||||
|
|
||||||
|
// Handle trailing slash (e.g. "boot/")
|
||||||
|
char name_buf[64];
|
||||||
|
if (*name == '\0') {
|
||||||
|
// This is tricky without modifying the string.
|
||||||
|
// Simplification: assume path didn't end in slash or handle separately.
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t sector = 0, size = 0;
|
||||||
|
if (find_entry_info(&parent_dir, name, §or, &size) == 0) {
|
||||||
|
st->st_mode = S_IFDIR | 0755;
|
||||||
|
st->st_ino = sector;
|
||||||
|
st->st_size = size;
|
||||||
|
} else {
|
||||||
|
return -2; // -ENOENT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -2; // -ENOENT
|
||||||
|
}
|
||||||
|
|
||||||
|
st->st_nlink = 1;
|
||||||
|
st->st_blksize = 2048;
|
||||||
|
st->st_blocks = DivRoundUp(st->st_size, 512);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void handle_syscall(TrapFrame *tf)
|
void handle_syscall(TrapFrame *tf)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -725,6 +896,14 @@ void handle_syscall(TrapFrame *tf)
|
|||||||
tf->eax = sys_nanosleep(tf);
|
tf->eax = sys_nanosleep(tf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x6a://stat
|
||||||
|
tf->eax = sys_stat(tf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x6c://fstat
|
||||||
|
tf->eax = sys_fstat(tf);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debug_log("unknown syscall: %X\n", tf->eax);
|
debug_log("unknown syscall: %X\n", tf->eax);
|
||||||
tf->eax = -38;//-ENOSYS
|
tf->eax = -38;//-ENOSYS
|
||||||
|
|||||||
@@ -160,4 +160,14 @@ char *strrchr(const char *s, int c) {
|
|||||||
if (*s++ == '\0')
|
if (*s++ == '\0')
|
||||||
return (char *)p;
|
return (char *)p;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
while(*s1 && (*s1 == *s2))
|
||||||
|
{
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user