From 00b47117b0842913da8da38e5cc2f597a9da1666 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Thu, 22 May 2008 11:21:27 +0000 Subject: [PATCH] Added sys_stat, sys_fstat and their libposix glue. --- tasks/fs0/include/stat.h | 17 +++ tasks/fs0/include/task.h | 4 +- tasks/fs0/src/syscalls.c | 81 +++++++++++++- tasks/fs0/src/task.c | 2 +- tasks/libl4/include/l4lib/ipcdefs.h | 3 + tasks/libl4/include/l4lib/os/posix/kstat.h | 23 ++++ tasks/libposix/stat.c | 122 +++++++++++++++++++++ 7 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 tasks/libl4/include/l4lib/os/posix/kstat.h create mode 100644 tasks/libposix/stat.c diff --git a/tasks/fs0/include/stat.h b/tasks/fs0/include/stat.h index b930791..ee7225e 100644 --- a/tasks/fs0/include/stat.h +++ b/tasks/fs0/include/stat.h @@ -62,4 +62,21 @@ #define O_NOATIME 01000000 #define O_NDELAY O_NONBLOCK +/* + * Internal codezero-specific stat structure. + * This is converted to posix stat in userspace + */ +struct kstat { + u64 vnum; + u32 mode; + int links; + u16 uid; + u16 gid; + u64 size; + int blksize; + u64 atime; + u64 mtime; + u64 ctime; +}; + #endif /* __FS0_STAT_H__ */ diff --git a/tasks/fs0/include/task.h b/tasks/fs0/include/task.h index 453101e..c82b527 100644 --- a/tasks/fs0/include/task.h +++ b/tasks/fs0/include/task.h @@ -10,7 +10,7 @@ #define __TASKNAME__ __VFSNAME__ -#define TASK_OFILES_MAX 32 +#define TASK_FILES_MAX 32 /* Thread control block, fs0 portion */ struct tcb { @@ -18,7 +18,7 @@ struct tcb { unsigned long utcb_address; int utcb_mapped; /* Set if we mapped their utcb */ struct list_head list; - int fd[TASK_OFILES_MAX]; + int fd[TASK_FILES_MAX]; struct id_pool *fdpool; struct vnode *curdir; struct vnode *rootdir; diff --git a/tasks/fs0/src/syscalls.c b/tasks/fs0/src/syscalls.c index 447c8b8..00deda3 100644 --- a/tasks/fs0/src/syscalls.c +++ b/tasks/fs0/src/syscalls.c @@ -221,6 +221,85 @@ int sys_chdir(l4id_t sender, const char *pathname) return 0; } +void fill_kstat(struct vnode *v, struct kstat *ks) +{ + ks->vnum = (u64)v->vnum; + ks->mode = v->mode; + ks->links = v->links; + ks->uid = v->owner & 0xFFFF; + ks->gid = (v->owner >> 16) & 0xFFFF; + ks->size = v->size; + ks->blksize = v->sb->blocksize; + ks->atime = v->atime; + ks->mtime = v->mtime; + ks->ctime = v->ctime; +} + +int sys_fstat(l4id_t sender, int fd, void *statbuf) +{ + struct vnode *v; + struct tcb *task; + unsigned long vnum; + int retval; + + /* Get the task */ + BUG_ON(!(task = find_task(sender))); + + /* Get the vnum */ + if (fd < 0 || fd > TASK_FILES_MAX) { + l4_ipc_return(-EINVAL); + return 0; + } + vnum = task->fd[fd]; + + /* Lookup vnode */ + if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum))) { + retval = -EINVAL; /* No such vnode */ + return 0; + } + + /* Fill in the c0-style stat structure */ + fill_kstat(v, statbuf); + + l4_ipc_return(0); + return 0; +} + +/* + * Returns codezero-style stat structure which in turn is + * converted to posix style stat structure via the libposix + * library in userspace. + */ +int sys_stat(l4id_t sender, const char *pathname, void *statbuf) +{ + struct vnode *v; + struct tcb *task; + struct pathdata *pdata; + + /* Get the task */ + BUG_ON(!(task = find_task(sender))); + + /* Parse path data */ + if (IS_ERR(pdata = pathdata_parse(pathname, + alloca(strlen(pathname) + 1), + task))) { + l4_ipc_return((int)pdata); + return 0; + } + + /* Get the vnode */ + if (IS_ERR(v = vfs_lookup_bypath(pdata))) { + l4_ipc_return((int)v); + return 0; + } + + /* Fill in the c0-style stat structure */ + fill_kstat(v, statbuf); + + l4_ipc_return(0); + return 0; +} + /* * Note this can be solely called by the pager and is not the posix read call. * That call is in the pager. This merely supplies the pages the pager needs @@ -387,7 +466,7 @@ int sys_readdir(l4id_t sender, int fd, void *buf, int count) return 0; } - if (fd < 0 || fd > TASK_OFILES_MAX) { + if (fd < 0 || fd > TASK_FILES_MAX) { l4_ipc_return(-EBADF); return 0; } diff --git a/tasks/fs0/src/task.c b/tasks/fs0/src/task.c index 33582d4..e3415a3 100644 --- a/tasks/fs0/src/task.c +++ b/tasks/fs0/src/task.c @@ -115,7 +115,7 @@ struct tcb *create_tcb(void) if (!(t = kmalloc(sizeof(*t)))) return PTR_ERR(-ENOMEM); - t->fdpool = id_pool_new_init(TASK_OFILES_MAX); + t->fdpool = id_pool_new_init(TASK_FILES_MAX); INIT_LIST_HEAD(&t->list); list_add_tail(&t->list, &tcb_head.list); tcb_head.total++; diff --git a/tasks/libl4/include/l4lib/ipcdefs.h b/tasks/libl4/include/l4lib/ipcdefs.h index d0573de..379769c 100644 --- a/tasks/libl4/include/l4lib/ipcdefs.h +++ b/tasks/libl4/include/l4lib/ipcdefs.h @@ -43,6 +43,9 @@ #define L4_IPC_TAG_MMAP2 20 #define L4_IPC_TAG_CHDIR 21 #define L4_IPC_TAG_FORK 22 +#define L4_IPC_TAG_STAT 23 +#define L4_IPC_TAG_FSTAT 24 + /* Tags for ipc between fs0 and mm0 */ #define L4_IPC_TAG_TASKDATA 25 diff --git a/tasks/libl4/include/l4lib/os/posix/kstat.h b/tasks/libl4/include/l4lib/os/posix/kstat.h new file mode 100644 index 0000000..89b0467 --- /dev/null +++ b/tasks/libl4/include/l4lib/os/posix/kstat.h @@ -0,0 +1,23 @@ +#ifndef __OS_KSTAT_H__ +#define __OS_KSTAT_H__ + +#include + +/* + * Internal codezero-specific stat structure. + * This is converted to posix stat in userspace + */ +struct kstat { + u64 vnum; + u32 mode; + int links; + u16 uid; + u16 gid; + u64 size; + int blksize; + u64 atime; + u64 mtime; + u64 ctime; +}; + +#endif diff --git a/tasks/libposix/stat.c b/tasks/libposix/stat.c new file mode 100644 index 0000000..defb442 --- /dev/null +++ b/tasks/libposix/stat.c @@ -0,0 +1,122 @@ +/* + * l4/posix glue for open() + * + * Copyright (C) 2007 Bahadir Balban + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include INC_GLUE(memory.h) + +static inline int l4_fstat(int fd, void *buffer) +{ + int err; + + /* Pathname address on utcb page */ + write_mr(L4SYS_ARG0, fd); + write_mr(L4SYS_ARG1, (unsigned long)buffer); + + /* Call pager with open() request. Check ipc error. */ + if ((err = l4_sendrecv(VFS_TID, VFS_TID, L4_IPC_TAG_FSTAT)) < 0) { + printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err); + return err; + } + /* Check if syscall itself was successful */ + if ((err = l4_get_retval()) < 0) { + printf("%s: FSTAT Error: %d.\n", __FUNCTION__, err); + return err; + } + return err; +} + +int kstat_to_stat(struct kstat *ks, struct stat *s) +{ + s->st_dev = 0; + s->st_ino = ks->vnum; + s->st_mode = ks->mode; + s->st_nlink = ks->links; + s->st_uid = ks->uid; + s->st_gid = ks->gid; + s->st_rdev = 0; + s->st_size = ks->size; + s->st_blksize = ks->blksize; + s->st_blocks = ks->size / ks->blksize; + s->st_atime = ks->atime; + s->st_mtime = ks->mtime; + s->st_ctime = ks->ctime; +} + +static inline int l4_stat(const char *pathname, void *buffer) +{ + int err; + struct kstat ks; + + copy_to_utcb((void *)pathname, 0, strlen(pathname) + 1); + + /* Pathname address on utcb page */ + write_mr(L4SYS_ARG0, (unsigned long)utcb_page); + + /* Pass on buffer that should receive stat */ + write_mr(L4SYS_ARG1, (unsigned long)&ks); + + /* Call vfs with stat() request. Check ipc error. */ + if ((err = l4_sendrecv(VFS_TID, VFS_TID, L4_IPC_TAG_STAT)) < 0) { + printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err); + return err; + } + + /* Check if syscall itself was successful */ + if ((err = l4_get_retval()) < 0) { + printf("%s: STAT Error: %d.\n", __FUNCTION__, err); + return err; + } + + /* Convert c0-style stat structure to posix stat */ + kstat_to_stat(&ks, buffer); + + return err; +} + +int fstat(int fd, struct stat *buffer) +{ + int ret; + + ret = l4_fstat(fd, buffer); + + /* If error, return positive error code */ + if (ret < 0) { + errno = -ret; + return -1; + } + /* else return value */ + return ret; + +} + +int stat(const char *pathname, struct stat *buffer) +{ + int ret; + + ret = l4_stat(pathname, buffer); + + /* If error, return positive error code */ + if (ret < 0) { + errno = -ret; + return -1; + } + /* else return value */ + return ret; + +} +