Skip to content

Commit

Permalink
Implement the stat system call
Browse files Browse the repository at this point in the history
A certain four-letters nineties game requires it.
  • Loading branch information
29jm committed Dec 8, 2020
1 parent 5b729d3 commit b5a6f09
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 7 deletions.
7 changes: 5 additions & 2 deletions kernel/include/kernel/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ typedef struct fs_t {
/* TODO: require null termination of entries */
sos_directory_entry_t* (*readdir)(struct fs_t*, uint32_t, uint32_t);
inode_t* (*get_fs_inode)(struct fs_t*, uint32_t);
int32_t (*close)(fs_t*, uint32_t)
int32_t (*close)(fs_t*, uint32_t);
int32_t (*stat)(fs_t*, uint32_t, stat_t*);
} fs_t;

typedef inode_t* (*fs_get_fs_inode_t)(struct fs_t*, uint32_t);
Expand All @@ -56,6 +57,7 @@ typedef int32_t (*fs_unlink_t)(struct fs_t*, uint32_t, uint32_t);
typedef int32_t (*fs_rename_t)(struct fs_t*, uint32_t, uint32_t, uint32_t);
typedef uint32_t (*fs_create_t)(struct fs_t*, const char*, uint32_t, uint32_t);
typedef int32_t (*fs_close_t)(struct fs_t*, uint32_t);
typedef int32_t (*fs_stat_t)(struct fs_t*, uint32_t, stat_t*);

void init_fs(fs_t* fs);
void fs_mount(const char* mount_point, fs_t* fs);
Expand All @@ -67,4 +69,5 @@ int32_t fs_rename(const char* oldp, const char* newp);
int32_t fs_close(inode_t* in);
uint32_t fs_read(inode_t* in, uint32_t offset, uint8_t* buf, uint32_t size);
uint32_t fs_write(inode_t* in, uint8_t* buf, uint32_t size);
uint32_t fs_readdir(inode_t* in, uint32_t offset, sos_directory_entry_t* d_ent, uint32_t size);
uint32_t fs_readdir(inode_t* in, uint32_t offset, sos_directory_entry_t* d_ent, uint32_t size);
int32_t fs_stat(const char* path, stat_t* buf);
10 changes: 9 additions & 1 deletion kernel/include/kernel/uapi/uapi_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,12 @@ typedef struct {
uint8_t name_len_low;
uint8_t type;
char name[];
} sos_directory_entry_t;
} sos_directory_entry_t;

typedef struct stat_t {
uint32_t st_dev;
uint32_t st_ino;
uint32_t st_mode;
uint32_t st_nlink;
uint32_t st_size;
} stat_t;
3 changes: 2 additions & 1 deletion kernel/include/kernel/uapi/uapi_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
#define SYS_UNLINK 19
#define SYS_RENAME 20
#define SYS_MAKETTY 21
#define SYS_MAX 22 // First invalid syscall number
#define SYS_STAT 22
#define SYS_MAX 23 // First invalid syscall number

#define SYS_INFO_UPTIME 1
#define SYS_INFO_MEMORY 2
Expand Down
22 changes: 20 additions & 2 deletions kernel/src/misc/ext2.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ uint32_t ext2_read(ext2_fs_t* fs, uint32_t inode, uint32_t offset, uint8_t* buf,
uint32_t ext2_append(ext2_fs_t* fs, uint32_t inode, uint8_t* data, uint32_t size);
sos_directory_entry_t* ext2_readdir(ext2_fs_t* fs, uint32_t inode, uint32_t offset);
inode_t* ext2_get_fs_inode(ext2_fs_t* fs, uint32_t inode);
int32_t ext2_close(fs_t* fs, uint32_t ino);
int32_t ext2_close(ext2_fs_t* fs, uint32_t ino);
int32_t ext2_stat(ext2_fs_t* fs, uint32_t ino, stat_t* stat);

static void read_block(ext2_fs_t* fs, uint32_t block, uint8_t* buf);
static void write_block(ext2_fs_t* fs, uint32_t block, uint8_t* buf);
Expand Down Expand Up @@ -212,6 +213,7 @@ fs_t* init_ext2(uint8_t* data, uint32_t len) {
e2fs->fs.readdir = (fs_readdir_t) ext2_readdir;
e2fs->fs.unlink = (fs_unlink_t) ext2_unlink;
e2fs->fs.close = (fs_close_t) ext2_close;
e2fs->fs.stat = (fs_stat_t) ext2_stat;

e2fs->fs.uid = e2fs->sb->id[0];
e2fs->fs.root = (folder_inode_t*) ext2_get_fs_inode(e2fs, EXT2_ROOT_INODE);
Expand Down Expand Up @@ -463,13 +465,29 @@ inode_t* ext2_get_fs_inode(ext2_fs_t* fs, uint32_t inode) {
return fs_in;
}

int32_t ext2_close(fs_t* fs, uint32_t ino) {
int32_t ext2_close(ext2_fs_t* fs, uint32_t ino) {
UNUSED(fs);
UNUSED(ino);

return 0;
}

int32_t ext2_stat(ext2_fs_t* fs, uint32_t ino, stat_t* stat) {
ext2_inode_t* in = get_inode(fs, ino);

if (!in) {
return -1;
}

stat->st_dev = fs->fs.uid;
stat->st_ino = ino;
stat->st_mode = in->type_perms;
stat->st_nlink = in->hardlinks_count;
stat->st_size = in->size_lower;

return 0;
}

/* Utility functions */

/* Reads the content of the given block.
Expand Down
11 changes: 11 additions & 0 deletions kernel/src/misc/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,17 @@ int32_t fs_rename(const char* oldp, const char* newp) {
return 0;
}

int32_t fs_stat(const char* path, stat_t* buf) {
printk("stat: %s", path);
inode_t* in = fs_open(path, O_RDONLY);

if (!in) {
return -1;
}

return FS(in)->stat(FS(in), in->inode_no, buf);
}

/* A process has released its grip on a file: notify the fs.
*/
int32_t fs_close(inode_t* in) {
Expand Down
9 changes: 9 additions & 0 deletions kernel/src/sys/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static void syscall_getcwd(registers_t* regs);
static void syscall_unlink(registers_t* regs);
static void syscall_rename(registers_t* regs);
static void syscall_maketty(registers_t* regs);
static void syscall_stat(registers_t* regs);

handler_t syscall_handlers[SYSCALL_NUM] = { 0 };

Expand Down Expand Up @@ -65,6 +66,7 @@ void init_syscall() {
syscall_handlers[SYS_UNLINK] = syscall_unlink;
syscall_handlers[SYS_RENAME] = syscall_rename;
syscall_handlers[SYS_MAKETTY] = syscall_maketty;
syscall_handlers[SYS_STAT] = syscall_stat;
}

static void syscall_handler(registers_t* regs) {
Expand Down Expand Up @@ -275,4 +277,11 @@ static void syscall_maketty(registers_t* regs) {
proc_add_fd(entry);

regs->eax = 0;
}

static void syscall_stat(registers_t* regs) {
const char* path = (const char*) regs->ebx;
stat_t* buf = (stat_t*) regs->ecx;

regs->eax = fs_stat(path, buf);
}
9 changes: 9 additions & 0 deletions libc/include/sys/stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@

typedef uint32_t mode_t;

struct stat {
uint32_t st_dev;
uint32_t st_ino;
uint32_t st_mode;
uint32_t st_nlink;
uint32_t st_size;
};

#ifndef _KERNEL_
int mkdir(const char* pathname, mode_t mode);
int stat(const char* path, struct stat* buf);
#endif
3 changes: 2 additions & 1 deletion libc/include/unistd.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once

#include <stddef.h>
#include <kernel/uapi/uapi_fs.h>

#include <stddef.h>

#define STDOUT_FILENO FS_STDOUT_FILENO

#ifndef _KERNEL_
Expand Down
17 changes: 17 additions & 0 deletions libc/src/unix/stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,21 @@ int unlink(const char* path) {
return syscall1(SYS_UNLINK, (uintptr_t) path);
}

int stat(const char* path, struct stat* buf) {
stat_t statbuf;
int ret = syscall2(SYS_STAT, (uintptr_t) path, (uintptr_t) &statbuf);

if (ret) {
return ret;
}

buf->st_dev = statbuf.st_dev;
buf->st_ino = statbuf.st_ino;
buf->st_mode = statbuf.st_mode;
buf->st_nlink = statbuf.st_nlink;
buf->st_size = statbuf.st_size;

return 0;
}

#endif

0 comments on commit b5a6f09

Please sign in to comment.