whiterose

linux unikernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/whiterose

commit 5037c5ea9bfbe83a460bce35cf30dcd26c6859f1
parent a1b9d55a388e9f42f85502f546f1c6c3540bf49e
Author: Louis Solofrizzo <lsolofrizzo@online.net>
Date:   Thu, 25 Apr 2019 11:25:45 +0200

ukl: Add stat and family

This patches introduces 4 new syscalls in the library:
- stat
- fstat
- lstat
- fstatat

Signed-off-by: Louis Solofrizzo <lsolofrizzo@online.net>

Diffstat:
Ainclude/ukl/sys/stat.h | 11+++++++++++
Mukl/Makefile | 2+-
Mukl/TO_PORT | 5-----
Aukl/stat/Makefile | 1+
Aukl/stat/stat.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 120 insertions(+), 6 deletions(-)

diff --git a/include/ukl/sys/stat.h b/include/ukl/sys/stat.h @@ -0,0 +1,11 @@ +#ifndef STAT_H +#define STAT_H + +#include <linux/stat.h> + +int stat(const char *, struct stat *); +int fstat(int, struct stat *); +int lstat(const char *, struct stat *); +int newfstatat(int, const char *, struct stat *, int); + +#endif /* STAT_H */ diff --git a/ukl/Makefile b/ukl/Makefile @@ -1,2 +1,2 @@ ukl-real-obj-m := $(addprefix ../../../../../../../..$(UKL)/,$(ukl-obj-m)) -obj-y := unistd/ fcntl/ stdio/ sys/ stdlib/ $(ukl-real-obj-m) +obj-y := unistd/ fcntl/ stdio/ sys/ stdlib/ stat/ $(ukl-real-obj-m) diff --git a/ukl/TO_PORT b/ukl/TO_PORT @@ -1,8 +1,5 @@ Syscalls to port: ================ -- stat -- fstat -- lstat - poll - mmap - mprotect @@ -11,7 +8,6 @@ Syscalls to port: - rt_sigaction - rt_sigprocmask - rt_sigreturn -- ioctl - pread64 - pwrite64 - access @@ -254,7 +250,6 @@ Syscalls to port: - mknodat - fchownat - futimesat -- newfstatat - unlinkat - renameat - linkat diff --git a/ukl/stat/Makefile b/ukl/stat/Makefile @@ -0,0 +1 @@ +obj-y := stat.o diff --git a/ukl/stat/stat.c b/ukl/stat/stat.c @@ -0,0 +1,107 @@ +#include <sys/stat.h> +#include <linux/kernel.h> +#include <linux/stat.h> +#include <linux/fs.h> +#include <linux/cred.h> + +#ifndef INIT_STRUCT_STAT_PADDING +#define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st)) +#endif /* INIT_STRUCT_STAT_PADDING */ + +#if BITS_PER_LONG == 32 +#define choose_32_64(a, b) a +#else +#define choose_32_64(a, b) b +#endif /* BITS_PER_LONG */ + +#define valid_dev(x) choose_32_64(old_valid_dev(x), true) +#define encode_dev(x) choose_32_64(old_encode_dev, new_encode_dev)(x) + +static int ukl_cp_new_stat(struct kstat *stat, struct stat *statbuf) +{ + struct stat tmp; + + if (!valid_dev(stat->dev) || !valid_dev(stat->rdev)) + return -EOVERFLOW; + +#if BITS_PER_LONG == 32 + if (stat->size > MAX_NON_LFS) + return -EOVERFLOW; +#endif + + INIT_STRUCT_STAT_PADDING(tmp); + tmp.st_dev = encode_dev(stat->dev); + tmp.st_ino = stat->ino; + + if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) + return -EOVERFLOW; + + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + + if (tmp.st_nlink != stat->nlink) + return -EOVERFLOW; + + SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid)); + SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid)); + tmp.st_rdev = encode_dev(stat->rdev); + tmp.st_size = stat->size; + tmp.st_atime = stat->atime.tv_sec; + tmp.st_mtime = stat->mtime.tv_sec; + tmp.st_ctime = stat->ctime.tv_sec; + +#ifdef STAT_HAVE_NSEC + tmp.st_atime_nsec = stat->atime.tv_nsec; + tmp.st_mtime_nsec = stat->mtime.tv_nsec; + tmp.st_ctime_nsec = stat->ctime.tv_nsec; +#endif + + tmp.st_blocks = stat->blocks; + tmp.st_blksize = stat->blksize; + memcpy(statbuf, &tmp, sizeof(tmp)); + return 0; +} + +int stat(const char *pathname, struct stat *statbuf) +{ + struct kstat stat; + int error = vfs_stat(pathname, &stat); + + if (error) + return error; + + return ukl_cp_new_stat(&stat, statbuf); +} + +int fstat(int fd, struct stat *statbuf) +{ + struct kstat stat; + int error = vfs_fstat(fd, &stat); + + if (error) + return error; + + return ukl_cp_new_stat(&stat, statbuf); +} + +int lstat(const char *pathname, struct stat *statbuf) +{ + struct kstat stat; + int error = vfs_lstat(pathname, &stat); + + if (error) + return error; + + return ukl_cp_new_stat(&stat, statbuf); +} + +int newfstatat(int dfd, const char *pathname, struct stat *statbuf, int flag) +{ + struct kstat stat; + int error = vfs_fstatat(dfd, pathname, &stat, flag); + + if (error) + return error; + + return ukl_cp_new_stat(&stat, statbuf); +}