Support opening, reading and stating files from userlevel
This commit is contained in:
parent
0e44a1a696
commit
39562233bf
@ -8,6 +8,7 @@
|
||||
#define EFAULT 0xBAD4
|
||||
#define ENOMEM 0xBAD5
|
||||
#define ENOENT 0xBAD6
|
||||
#define ENOTDIR 0xBAD7
|
||||
|
||||
#endif /* __ERRNO_H__ */
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#ifndef __SYSCALL_H__
|
||||
#define __SYSCALL_H__
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
uint64_t SystemTime();
|
||||
void SystemExit(int status);
|
||||
uint64_t SystemGetPID();
|
||||
@ -19,6 +21,10 @@ int SystemFlush(uint64_t fd);
|
||||
uint64_t SystemOpen(const char *path, uint64_t flags);
|
||||
int SystemClose(uint64_t fd);
|
||||
|
||||
// Directory
|
||||
int SystemStat(const char *path, struct stat *sb);
|
||||
int SystemReadDir(uint64_t fd, char *buf, size_t length, uint64_t *offset);
|
||||
|
||||
// Threads
|
||||
int SystemThreadSleep(uint64_t time);
|
||||
|
||||
|
@ -79,6 +79,18 @@ SystemClose(uint64_t fd)
|
||||
return syscall(SYSCALL_CLOSE, fd);
|
||||
}
|
||||
|
||||
int
|
||||
SystemStat(const char *path, struct stat *sb)
|
||||
{
|
||||
return syscall(SYSCALL_STAT, path, sb);
|
||||
}
|
||||
|
||||
int
|
||||
SystemReadDir(uint64_t fd, char *buf, size_t length, uint64_t *offset)
|
||||
{
|
||||
return syscall(SYSCALL_READDIR, fd, buf, length, offset);
|
||||
}
|
||||
|
||||
int
|
||||
SystemThreadSleep(uint64_t time)
|
||||
{
|
||||
|
@ -54,6 +54,7 @@ src_common = [
|
||||
"kern/sysctl.c",
|
||||
"kern/thread.c",
|
||||
"kern/vfs.c",
|
||||
"kern/vfsuio.c",
|
||||
"dev/ahci.c",
|
||||
"dev/console.c",
|
||||
"dev/pci.c",
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/kassert.h>
|
||||
#include <sys/kmem.h>
|
||||
@ -18,7 +19,10 @@ int O2FS_GetRoot(VFS *fs, VNode **dn);
|
||||
int O2FS_Lookup(VNode *dn, VNode **fn, const char *name);
|
||||
int O2FS_Open(VNode *fn);
|
||||
int O2FS_Close(VNode *fn);
|
||||
int O2FS_Stat(VNode *fn, struct stat *statinfo);
|
||||
int O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
||||
int O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
||||
int O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off);
|
||||
|
||||
static VFSOp O2FSOperations = {
|
||||
.unmount = O2FS_Unmount,
|
||||
@ -26,7 +30,10 @@ static VFSOp O2FSOperations = {
|
||||
.lookup = O2FS_Lookup,
|
||||
.open = O2FS_Open,
|
||||
.close = O2FS_Close,
|
||||
.stat = O2FS_Stat,
|
||||
.read = O2FS_Read,
|
||||
.write = O2FS_Write,
|
||||
.readdir = O2FS_ReadDir,
|
||||
};
|
||||
|
||||
VFS *
|
||||
@ -257,6 +264,23 @@ O2FS_Close(VNode *fn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
O2FS_Stat(VNode *fn, struct stat *statinfo)
|
||||
{
|
||||
VFS *vfs = fn->vfs;
|
||||
DiskCacheEntry *sbEntry = (DiskCacheEntry *)vfs->fsptr;
|
||||
SuperBlock *sb = sbEntry->buffer;
|
||||
DiskCacheEntry *fileEntry = (DiskCacheEntry *)fn->fsptr;
|
||||
BNode *fileBN = fileEntry->buffer;
|
||||
|
||||
statinfo->st_size = fileBN->size;
|
||||
// XXX: support other fields
|
||||
statinfo->st_blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
|
||||
statinfo->st_blksize = sb->blockSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
||||
{
|
||||
@ -310,3 +334,16 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
int
|
||||
O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
||||
{
|
||||
NOT_IMPLEMENTED();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int
|
||||
O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ typedef struct SuperBlock
|
||||
uint64_t blockCount;
|
||||
uint64_t blockSize;
|
||||
|
||||
uint64_t version; /* Snapshot version */
|
||||
ObjID root; /* Root Tree */
|
||||
|
||||
uint8_t hash[32];
|
||||
|
18
sys/include/dirent.h
Normal file
18
sys/include/dirent.h
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
#ifndef __SYS_DIRENT_H__
|
||||
#define __SYS_DIRENT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NAME_MAX 256
|
||||
|
||||
struct dirent {
|
||||
ino_t d_ino;
|
||||
uint16_t d_reclen;
|
||||
uint8_t d_type;
|
||||
uint8_t d_namlen;
|
||||
char d_name[NAME_MAX];
|
||||
};
|
||||
|
||||
#endif /* __SYS_DIRENT_H__ */
|
||||
|
@ -3,6 +3,8 @@
|
||||
#define __SYS_HANDLE_H__
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/vfs.h>
|
||||
|
||||
struct Handle;
|
||||
typedef struct Handle Handle;
|
||||
@ -14,6 +16,7 @@ typedef struct Handle {
|
||||
uint64_t fd; // FD Number
|
||||
uint64_t type; // Type
|
||||
uint64_t threadId; // Thread ID
|
||||
VNode *vnode; // File VNode
|
||||
TAILQ_ENTRY(Handle) handleList; // Hash table
|
||||
int (*read)(Handle *, void *, uint64_t, uint64_t); // Read
|
||||
int (*write)(Handle *, void *, uint64_t, uint64_t); // Write
|
||||
|
17
sys/include/stat.h
Normal file
17
sys/include/stat.h
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
#ifndef __SYS_STAT_H__
|
||||
#define __SYS_STAT_H__
|
||||
|
||||
struct stat {
|
||||
ino_t st_ino;
|
||||
// mode
|
||||
// uid
|
||||
// gid
|
||||
// timespec st_atim, st_mtim, st_ctim
|
||||
off_t st_size;
|
||||
size_t st_blocks;
|
||||
size_t st_blksize;
|
||||
};
|
||||
|
||||
#endif /* __SYS_STAT_H__ */
|
||||
|
@ -24,6 +24,8 @@
|
||||
#define SYSCALL_MOVE 0x1A
|
||||
#define SYSCALL_DELETE 0x1B
|
||||
#define SYSCALL_SETLENGTH 0x1C
|
||||
#define SYSCALL_STAT 0x1D
|
||||
#define SYSCALL_READDIR 0x1E
|
||||
|
||||
// Threading
|
||||
#define SYSCALL_THREADCREATE 0x30
|
||||
|
@ -20,6 +20,8 @@ typedef int64_t ssize_t;
|
||||
typedef int64_t off_t;
|
||||
typedef int64_t fpos_t;
|
||||
|
||||
typedef uint64_t ino_t;
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
#endif /* __SYS_TYPES_H__ */
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define __SYS_VFS_H__
|
||||
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
typedef struct VFSOp VFSOp;
|
||||
typedef struct VNode VNode;
|
||||
@ -40,15 +41,20 @@ typedef struct VFSOp {
|
||||
int (*lookup)(VNode *dn, VNode **fn, const char *name);
|
||||
int (*open)(VNode *fn);
|
||||
int (*close)(VNode *fn);
|
||||
int (*stat)(VNode *fn, struct stat *sb);
|
||||
int (*read)(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
||||
int (*write)(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
||||
int (*readdir)(VNode *fn, void *buf, uint64_t len, uint64_t *off);
|
||||
} VFSOp;
|
||||
|
||||
int VFS_MountRoot(Disk *root);
|
||||
VNode *VFS_Lookup(const char *path);
|
||||
// XXX: Release/Retain
|
||||
int VFS_Stat(const char *path, struct stat *sb);
|
||||
int VFS_Open(VNode *fn);
|
||||
int VFS_Close(VNode *fn);
|
||||
int VFS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len);
|
||||
|
||||
int VFS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off);
|
||||
|
||||
#endif /* __SYS_VFS_H__ */
|
||||
|
||||
|
10
sys/include/vfsuio.h
Normal file
10
sys/include/vfsuio.h
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
#ifndef __SYS_VFSUIO_H__
|
||||
#define __SYS_VFSUIO_H__
|
||||
|
||||
#include <sys/handle.h>
|
||||
|
||||
int VFSUIO_Open(const char *path, Handle **handle);
|
||||
|
||||
#endif /* __SYS_VFSUIO_H__ */
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/vfsuio.h>
|
||||
|
||||
Handle *Console_OpenHandle();
|
||||
|
||||
@ -198,10 +199,16 @@ Syscall_Open(uint64_t user_path, uint64_t flags)
|
||||
Handle *handle = Console_OpenHandle();
|
||||
return Handle_Add(cur, handle);
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
NOT_IMPLEMENTED();
|
||||
return 0;
|
||||
Handle *handle;
|
||||
status = VFSUIO_Open(path, &handle);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
return Handle_Add(cur, handle);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@ -216,6 +223,61 @@ Syscall_Close(uint64_t fd)
|
||||
return (handle->close)(handle);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Syscall_Stat(uint64_t user_path, uint64_t user_stat)
|
||||
{
|
||||
int status;
|
||||
char path[512];
|
||||
struct stat sb;
|
||||
|
||||
// XXX: Use CopyInStr
|
||||
status = CopyIn(user_path, &path, sizeof(path));
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// VFS_Stat
|
||||
status = VFS_Stat(path, &sb);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = CopyOut(&sb, user_stat, sizeof(struct stat));
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off)
|
||||
{
|
||||
int status;
|
||||
Thread *cur = Thread_Current();
|
||||
Handle *handle = Handle_Lookup(cur, fd);
|
||||
uint64_t offset;
|
||||
|
||||
if (handle == NULL)
|
||||
return -EBADF;
|
||||
|
||||
status = CopyIn(user_off, &offset, sizeof(offset));
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
if (handle->type != HANDLE_TYPE_FILE)
|
||||
return -ENOTDIR;
|
||||
status = VFS_ReadDir(handle->vnode, user_buf, len, &offset);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
status = CopyOut(&offset, user_off, sizeof(offset));
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Syscall_ThreadSleep(uint64_t time)
|
||||
{
|
||||
@ -258,6 +320,10 @@ Syscall_Entry(uint64_t syscall, uint64_t a1, uint64_t a2,
|
||||
return Syscall_Open(a1, a2);
|
||||
case SYSCALL_CLOSE:
|
||||
return Syscall_Close(a1);
|
||||
case SYSCALL_STAT:
|
||||
return Syscall_Stat(a1, a2);
|
||||
case SYSCALL_READDIR:
|
||||
return Syscall_ReadDir(a1, a2, a3, a4);
|
||||
case SYSCALL_THREADSLEEP:
|
||||
return Syscall_ThreadSleep(a1);
|
||||
default:
|
||||
|
@ -2,12 +2,14 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/kassert.h>
|
||||
#include <sys/kdebug.h>
|
||||
#include <sys/spinlock.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/handle.h>
|
||||
|
||||
extern VFS *O2FS_Mount(Disk *root);
|
||||
|
||||
@ -92,6 +94,18 @@ VFS_Lookup(const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
VFS_Stat(const char *path, struct stat *sb)
|
||||
{
|
||||
VNode *vn = VFS_Lookup(path);
|
||||
if (vn == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
vn->op->stat(vn, sb);
|
||||
|
||||
// Release
|
||||
}
|
||||
|
||||
int
|
||||
VFS_Open(VNode *fn)
|
||||
{
|
||||
@ -110,3 +124,15 @@ VFS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
||||
return fn->op->read(fn, buf, off, len);
|
||||
}
|
||||
|
||||
int
|
||||
VFS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len)
|
||||
{
|
||||
return fn->op->write(fn, buf, off, len);
|
||||
}
|
||||
|
||||
int
|
||||
VFS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
|
||||
{
|
||||
return fn->op->readdir(fn, buf, len, off);
|
||||
}
|
||||
|
||||
|
85
sys/kern/vfsuio.c
Normal file
85
sys/kern/vfsuio.c
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/kassert.h>
|
||||
#include <sys/kdebug.h>
|
||||
#include <sys/spinlock.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/handle.h>
|
||||
#include <sys/vfsuio.h>
|
||||
|
||||
static int
|
||||
VFSUIO_Read(Handle *handle, void *buf, uint64_t len, uint64_t off)
|
||||
{
|
||||
ASSERT(handle->type == HANDLE_TYPE_FILE);
|
||||
|
||||
// XXX: Need to pin memory
|
||||
|
||||
return VFS_Read(handle->vnode, buf, len, off);
|
||||
}
|
||||
|
||||
static int
|
||||
VFSUIO_Write(Handle *handle, void *buf, uint64_t len, uint64_t off)
|
||||
{
|
||||
ASSERT(handle->type == HANDLE_TYPE_FILE);
|
||||
|
||||
// XXX: Need to pin memory
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
VFSUIO_Flush(Handle *handle)
|
||||
{
|
||||
ASSERT(handle->type == HANDLE_TYPE_FILE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
VFSUIO_Close(Handle *handle)
|
||||
{
|
||||
int status;
|
||||
|
||||
ASSERT(handle->type == HANDLE_TYPE_FILE);
|
||||
|
||||
status = VFS_Close(handle->vnode);
|
||||
Handle_Free(handle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
VFSUIO_Open(const char *path, Handle **handle)
|
||||
{
|
||||
int status;
|
||||
|
||||
Handle *hdl = Handle_Alloc();
|
||||
if (!hdl) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
VNode *vn = VFS_Lookup(path);
|
||||
status = VFS_Open(vn);
|
||||
if (status != 0) {
|
||||
// XXX: Release VNode
|
||||
Handle_Free(hdl);
|
||||
return status;
|
||||
}
|
||||
|
||||
hdl->vnode = vn;
|
||||
hdl->type = HANDLE_TYPE_FILE;
|
||||
hdl->read = VFSUIO_Read;
|
||||
hdl->write = VFSUIO_Write;
|
||||
hdl->flush = VFSUIO_Flush;
|
||||
hdl->close = VFSUIO_Close;
|
||||
|
||||
*handle = hdl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user