Support opening, reading and stating files from userlevel

This commit is contained in:
Ali Mashtizadeh 2014-12-05 00:25:20 -08:00
parent 0e44a1a696
commit 39562233bf
16 changed files with 296 additions and 3 deletions

View File

@ -8,6 +8,7 @@
#define EFAULT 0xBAD4
#define ENOMEM 0xBAD5
#define ENOENT 0xBAD6
#define ENOTDIR 0xBAD7
#endif /* __ERRNO_H__ */

View File

@ -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);

View File

@ -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)
{

View File

@ -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",

View File

@ -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;
}

View File

@ -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
View 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__ */

View File

@ -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
View 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__ */

View File

@ -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

View File

@ -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__ */

View File

@ -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
View 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__ */

View File

@ -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:

View File

@ -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
View 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;
}