From a935148f607e3dc18dfacd22999792cb6ee0a1ea Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Tue, 21 Jan 2014 00:53:18 +0100 Subject: [PATCH] Add statvfs(2), fstatvfs(2) and fstatvfsat(2). --- kernel/descriptor.cpp | 9 ++- kernel/fs/user.cpp | 22 +++++++- kernel/include/sortix/kernel/descriptor.h | 4 +- kernel/include/sortix/kernel/inode.h | 5 +- kernel/include/sortix/kernel/vnode.h | 4 +- kernel/include/sortix/statvfs.h | 69 +++++++++++++++++++++++ kernel/include/sortix/syscallnum.h | 4 +- kernel/inode.cpp | 28 ++++++++- kernel/io.cpp | 33 ++++++++++- kernel/vnode.cpp | 7 ++- libc/Makefile | 3 + libc/include/fsmarshall-msg.h | 15 ++++- libc/include/sys/statvfs.h | 42 ++++++++++++++ libc/sys/statvfs/fstatvfs.cpp | 33 +++++++++++ libc/sys/statvfs/fstatvfsat.cpp | 37 ++++++++++++ libc/sys/statvfs/statvfs.cpp | 33 +++++++++++ 16 files changed, 338 insertions(+), 10 deletions(-) create mode 100644 kernel/include/sortix/statvfs.h create mode 100644 libc/include/sys/statvfs.h create mode 100644 libc/sys/statvfs/fstatvfs.cpp create mode 100644 libc/sys/statvfs/fstatvfsat.cpp create mode 100644 libc/sys/statvfs/statvfs.cpp diff --git a/kernel/descriptor.cpp b/kernel/descriptor.cpp index 5f65006b..9d22da1b 100644 --- a/kernel/descriptor.cpp +++ b/kernel/descriptor.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of Sortix. @@ -170,6 +170,13 @@ int Descriptor::stat(ioctx_t* ctx, struct stat* st) return vnode->stat(ctx, st); } +int Descriptor::statvfs(ioctx_t* ctx, struct statvfs* stvfs) +{ + // TODO: Possible information leak if not O_READ | O_WRITE and the caller + // is told about the file size. + return vnode->statvfs(ctx, stvfs); +} + int Descriptor::chmod(ioctx_t* ctx, mode_t mode) { return vnode->chmod(ctx, mode); diff --git a/kernel/fs/user.cpp b/kernel/fs/user.cpp index b9c334a1..31ef304b 100644 --- a/kernel/fs/user.cpp +++ b/kernel/fs/user.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of Sortix. @@ -184,6 +184,7 @@ public: virtual void unlinked(); virtual int sync(ioctx_t* ctx); virtual int stat(ioctx_t* ctx, struct stat* st); + virtual int statvfs(ioctx_t* ctx, struct statvfs* stvfs); virtual int chmod(ioctx_t* ctx, mode_t mode); virtual int chown(ioctx_t* ctx, uid_t owner, gid_t group); virtual int truncate(ioctx_t* ctx, off_t length); @@ -706,6 +707,25 @@ int Unode::stat(ioctx_t* ctx, struct stat* st) return ret; } +int Unode::statvfs(ioctx_t* ctx, struct statvfs* stvfs) +{ + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + int ret = -1; + struct fsm_req_statvfs msg; + struct fsm_resp_statvfs resp; + msg.ino = ino; + if ( SendMessage(channel, FSM_REQ_STATVFS, &msg, sizeof(msg)) && + RecvMessage(channel, FSM_RESP_STATVFS, &resp, sizeof(resp)) && + (resp.stvfs.f_fsid = (dev_t) server, true) && + (resp.stvfs.f_flag |= ST_NOSUID, true) && + ctx->copy_to_dest(stvfs, &resp.stvfs, sizeof(*stvfs)) ) + ret = 0; + channel->KernelClose(); + return ret; +} + int Unode::chmod(ioctx_t* /*ctx*/, mode_t mode) { Channel* channel = server->Connect(); diff --git a/kernel/include/sortix/kernel/descriptor.h b/kernel/include/sortix/kernel/descriptor.h index 9d89b831..ffab1594 100644 --- a/kernel/include/sortix/kernel/descriptor.h +++ b/kernel/include/sortix/kernel/descriptor.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of Sortix. @@ -35,6 +35,7 @@ #include struct stat; +struct statvfs; struct wincurpos; struct winsize; struct kernel_dirent; @@ -57,6 +58,7 @@ public: int GetFlags(); int sync(ioctx_t* ctx); int stat(ioctx_t* ctx, struct stat* st); + int statvfs(ioctx_t* ctx, struct statvfs* stvfs); int chmod(ioctx_t* ctx, mode_t mode); int chown(ioctx_t* ctx, uid_t owner, gid_t group); int truncate(ioctx_t* ctx, off_t length); diff --git a/kernel/include/sortix/kernel/inode.h b/kernel/include/sortix/kernel/inode.h index 38f1bdfb..a79fe82b 100644 --- a/kernel/include/sortix/kernel/inode.h +++ b/kernel/include/sortix/kernel/inode.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of Sortix. @@ -35,6 +35,7 @@ #include struct stat; +struct statvfs; struct wincurpos; struct winsize; struct kernel_dirent; @@ -59,6 +60,7 @@ public: virtual void unlinked() = 0; virtual int sync(ioctx_t* ctx) = 0; virtual int stat(ioctx_t* ctx, struct stat* st) = 0; + virtual int statvfs(ioctx_t* ctx, struct statvfs* stvfs) = 0; virtual int chmod(ioctx_t* ctx, mode_t mode) = 0; virtual int chown(ioctx_t* ctx, uid_t owner, gid_t group) = 0; virtual int truncate(ioctx_t* ctx, off_t length) = 0; @@ -139,6 +141,7 @@ public: virtual void unlinked(); virtual int sync(ioctx_t* ctx); virtual int stat(ioctx_t* ctx, struct stat* st); + virtual int statvfs(ioctx_t* ctx, struct statvfs* stvfs); virtual int chmod(ioctx_t* ctx, mode_t mode); virtual int chown(ioctx_t* ctx, uid_t owner, gid_t group); virtual int truncate(ioctx_t* ctx, off_t length); diff --git a/kernel/include/sortix/kernel/vnode.h b/kernel/include/sortix/kernel/vnode.h index f262a262..7d1acfb5 100644 --- a/kernel/include/sortix/kernel/vnode.h +++ b/kernel/include/sortix/kernel/vnode.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of Sortix. @@ -34,6 +34,7 @@ #include struct stat; +struct statvfs; struct wincurpos; struct winsize; struct kernel_dirent; @@ -58,6 +59,7 @@ public: virtual ~Vnode(); int sync(ioctx_t* ctx); int stat(ioctx_t* ctx, struct stat* st); + int statvfs(ioctx_t* ctx, struct statvfs* stvfs); int chmod(ioctx_t* ctx, mode_t mode); int chown(ioctx_t* ctx, uid_t owner, gid_t group); int truncate(ioctx_t* ctx, off_t length); diff --git a/kernel/include/sortix/statvfs.h b/kernel/include/sortix/statvfs.h new file mode 100644 index 00000000..6fe77094 --- /dev/null +++ b/kernel/include/sortix/statvfs.h @@ -0,0 +1,69 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + sortix/statvfs.h + Virtual filesystem information structure. + +*******************************************************************************/ + +#ifndef INCLUDE_SORTIX_STATVFS_H +#define INCLUDE_SORTIX_STATVFS_H + +#include + +#include + +__BEGIN_DECLS + +#ifndef __dev_t_defined +#define __dev_t_defined +typedef __dev_t dev_t; +#endif + +#ifndef __fsblkcnt_t_defined +#define __fsblkcnt_t_defined +typedef __fsblkcnt_t fsblkcnt_t; +#endif + +#ifndef __fsfilcnt_t_defined +#define __fsfilcnt_t_defined +typedef __fsfilcnt_t fsfilcnt_t; +#endif + +struct statvfs +{ + unsigned long f_bsize; + unsigned long f_frsize; + fsblkcnt_t f_blocks; + fsblkcnt_t f_bfree; + fsblkcnt_t f_bavail; + fsfilcnt_t f_files; + fsfilcnt_t f_ffree; + fsfilcnt_t f_favail; + dev_t f_fsid; + unsigned long f_flag; + unsigned long f_namemax; +}; + +#define ST_RDONLY (1 << 0) +#define ST_NOSUID (1 << 1) + +__END_DECLS + +#endif diff --git a/kernel/include/sortix/syscallnum.h b/kernel/include/sortix/syscallnum.h index 046891e7..56b3e986 100644 --- a/kernel/include/sortix/syscallnum.h +++ b/kernel/include/sortix/syscallnum.h @@ -148,6 +148,8 @@ #define SYSCALL_TCGETWINCURPOS 124 #define SYSCALL_PIPE2 125 #define SYSCALL_GETUMASK 126 -#define SYSCALL_MAX_NUM 127 /* index of highest constant + 1 */ +#define SYSCALL_FSTATVFS 127 +#define SYSCALL_FSTATVFSAT 128 +#define SYSCALL_MAX_NUM 129 /* index of highest constant + 1 */ #endif diff --git a/kernel/inode.cpp b/kernel/inode.cpp index d929da3c..4525a527 100644 --- a/kernel/inode.cpp +++ b/kernel/inode.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of Sortix. @@ -23,10 +23,12 @@ *******************************************************************************/ #include +#include #include #include #include +#include #include #include @@ -96,6 +98,30 @@ int AbstractInode::stat(ioctx_t* ctx, struct stat* st) return 0; } +// TODO: Provide an easier mechanism for letting subclasses give this +// information than overriding this method. Additionally, what should be +// done in abstract kernel objects where this call doesn't make that much +// sense? +int AbstractInode::statvfs(ioctx_t* ctx, struct statvfs* stvfs) +{ + struct statvfs retstvfs; + ScopedLock lock(&metalock); + memset(&retstvfs, 0, sizeof(retstvfs)); + retstvfs.f_bsize = 0; + retstvfs.f_frsize = 0; + retstvfs.f_blocks = 0; + retstvfs.f_bfree = 0; + retstvfs.f_bavail = 0; + retstvfs.f_files = 0; + retstvfs.f_ffree = 0; + retstvfs.f_fsid = (dev_t) dev; + retstvfs.f_flag = ST_NOSUID; + retstvfs.f_namemax = ULONG_MAX; + if ( !ctx->copy_to_dest(stvfs, &retstvfs, sizeof(retstvfs)) ) + return -1; + return 0; +} + int AbstractInode::chmod(ioctx_t* /*ctx*/, mode_t mode) { ScopedLock lock(&metalock); diff --git a/kernel/io.cpp b/kernel/io.cpp index 23a82f78..e9159ac5 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. This file is part of Sortix. @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -324,6 +325,34 @@ static int sys_fstat(int fd, struct stat* st) return desc->stat(&ctx, st); } +static int sys_fstatvfs(int fd, struct statvfs* stvfs) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + ioctx_t ctx; SetupUserIOCtx(&ctx); + return desc->statvfs(&ctx, stvfs); +} + +static int sys_fstatvfsat(int dirfd, const char* path, struct statvfs* stvfs, int flags) +{ + if ( flags & ~(AT_SYMLINK_NOFOLLOW) ) + return errno = EINVAL; + char* pathcopy = GetStringFromUser(path); + if ( !pathcopy ) + return -1; + ioctx_t ctx; SetupUserIOCtx(&ctx); + const char* relpath = pathcopy; + Ref from = PrepareLookup(&relpath, dirfd); + if ( !from ) { delete[] pathcopy; return -1; } + int open_flags = O_READ | (flags & AT_SYMLINK_NOFOLLOW ? O_SYMLINK_NOFOLLOW : 0); + Ref desc = from->open(&ctx, relpath, open_flags); + delete[] pathcopy; + if ( !desc ) + return -1; + return desc->statvfs(&ctx, stvfs); +} + static int sys_fcntl(int fd, int cmd, uintptr_t arg) { // Operations on the descriptor table. @@ -1029,6 +1058,8 @@ void Init() Syscall::Register(SYSCALL_FCHROOT, (void*) sys_fchroot); Syscall::Register(SYSCALL_FCNTL, (void*) sys_fcntl); Syscall::Register(SYSCALL_FSTATAT, (void*) sys_fstatat); + Syscall::Register(SYSCALL_FSTATVFSAT, (void*) sys_fstatvfsat); + Syscall::Register(SYSCALL_FSTATVFS, (void*) sys_fstatvfs); Syscall::Register(SYSCALL_FSTAT, (void*) sys_fstat); Syscall::Register(SYSCALL_FSYNC, (void*) sys_fsync); Syscall::Register(SYSCALL_FTRUNCATE, (void*) sys_ftruncate); diff --git a/kernel/vnode.cpp b/kernel/vnode.cpp index 3ecc12e7..c2e3f47c 100644 --- a/kernel/vnode.cpp +++ b/kernel/vnode.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of Sortix. @@ -116,6 +116,11 @@ int Vnode::stat(ioctx_t* ctx, struct stat* st) return inode->stat(ctx, st); } +int Vnode::statvfs(ioctx_t* ctx, struct statvfs* stvfs) +{ + return inode->statvfs(ctx, stvfs); +} + int Vnode::chmod(ioctx_t* ctx, mode_t mode) { return inode->chmod(ctx, mode); diff --git a/libc/Makefile b/libc/Makefile index d6f8cda9..c65862d0 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -439,6 +439,9 @@ sys/stat/stat.o \ sys/stat/umask.o \ sys/stat/utimensat.o \ sys/stat/utimens.o \ +sys/statvfs/fstatvfsat.o \ +sys/statvfs/fstatvfs.o \ +sys/statvfs/statvfs.o \ sys/termmode/gettermmode.o \ sys/termmode/settermmode.o \ sys/time/gettimeofday.o \ diff --git a/libc/include/fsmarshall-msg.h b/libc/include/fsmarshall-msg.h index 6b4468ba..99817878 100644 --- a/libc/include/fsmarshall-msg.h +++ b/libc/include/fsmarshall-msg.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2013. + Copyright(C) Jonas 'Sortie' Termansen 2013, 2014. This file is part of the Sortix C Library. @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -355,6 +356,18 @@ struct fsm_resp_tcgetwincurpos struct wincurpos pos; }; +#define FSM_REQ_STATVFS 44 +struct fsm_req_statvfs +{ + ino_t ino; +}; + +#define FSM_RESP_STATVFS 45 +struct fsm_resp_statvfs +{ + struct statvfs stvfs; +}; + #define FSM_MSG_NUM 45 #if defined(__cplusplus) diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h new file mode 100644 index 00000000..81fb0a55 --- /dev/null +++ b/libc/include/sys/statvfs.h @@ -0,0 +1,42 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/statvfs.h + Virtual filesystem information structure. + +*******************************************************************************/ + +#ifndef INCLUDE_SYS_STATVFS_H +#define INCLUDE_SYS_STATVFS_H + +#include + +#include + +#include + +__BEGIN_DECLS + +int fstatvfs(int, struct statvfs*); +int fstatvfsat(int, const char* __restrict, struct statvfs* __restrict, int); +int statvfs(const char* __restrict, struct statvfs* __restrict); + +__END_DECLS + +#endif diff --git a/libc/sys/statvfs/fstatvfs.cpp b/libc/sys/statvfs/fstatvfs.cpp new file mode 100644 index 00000000..19fab561 --- /dev/null +++ b/libc/sys/statvfs/fstatvfs.cpp @@ -0,0 +1,33 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/statvfs/fstatvfs.cpp + Get virtual filesystem information. + +*******************************************************************************/ + +#include +#include + +DEFN_SYSCALL2(int, sys_fstatvfs, SYSCALL_FSTATVFS, int, struct statvfs*); + +extern "C" int fstatvfs(int fd, struct statvfs* stvfs) +{ + return sys_fstatvfs(fd, stvfs); +} diff --git a/libc/sys/statvfs/fstatvfsat.cpp b/libc/sys/statvfs/fstatvfsat.cpp new file mode 100644 index 00000000..a551cb8d --- /dev/null +++ b/libc/sys/statvfs/fstatvfsat.cpp @@ -0,0 +1,37 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/statvfs/fstatvfsat.cpp + Get virtual filesystem information. + +*******************************************************************************/ + +#include +#include + +DEFN_SYSCALL4(int, sys_fstatvfsat, SYSCALL_FSTATVFSAT, int, const char*, struct statvfs*, int); + +extern "C" +int fstatvfsat(int dirfd, + const char* restrict path, + struct statvfs* restrict stvfs, + int flags) +{ + return sys_fstatvfsat(dirfd, path, stvfs, flags); +} diff --git a/libc/sys/statvfs/statvfs.cpp b/libc/sys/statvfs/statvfs.cpp new file mode 100644 index 00000000..909f024a --- /dev/null +++ b/libc/sys/statvfs/statvfs.cpp @@ -0,0 +1,33 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/statvfs/statvfs.cpp + Get virtual filesystem information. + +*******************************************************************************/ + +#include + +#include + +extern "C" +int statvfs(const char* restrict path, struct statvfs* restrict stvfs) +{ + return fstatvfsat(AT_FDCWD, path, stvfs, 0); +}