diff options
author | jhb <jhb@FreeBSD.org> | 2008-01-07 20:05:19 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-01-07 20:05:19 +0000 |
commit | f8a246b9791d1450cf4945cc7b38f651a3a456ee (patch) | |
tree | 4cf9280569e048ce55d457d60918586c5cf023e5 /sys/kern/sys_generic.c | |
parent | 1b130ab3271ae64d5c2979889a661e27bbe422d9 (diff) | |
download | FreeBSD-src-f8a246b9791d1450cf4945cc7b38f651a3a456ee.zip FreeBSD-src-f8a246b9791d1450cf4945cc7b38f651a3a456ee.tar.gz |
Make ftruncate a 'struct file' operation rather than a vnode operation.
This makes it possible to support ftruncate() on non-vnode file types in
the future.
- 'struct fileops' grows a 'fo_truncate' method to handle an ftruncate() on
a given file descriptor.
- ftruncate() moves to kern/sys_generic.c and now just fetches a file
object and invokes fo_truncate().
- The vnode-specific portions of ftruncate() move to vn_truncate() in
vfs_vnops.c which implements fo_truncate() for vnode file types.
- Non-vnode file types return EINVAL in their fo_truncate() method.
Submitted by: rwatson
Diffstat (limited to 'sys/kern/sys_generic.c')
-rw-r--r-- | sys/kern/sys_generic.c | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 9c800f3..90946ea 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/socketvar.h> #include <sys/uio.h> #include <sys/kernel.h> +#include <sys/ktr.h> #include <sys/limits.h> #include <sys/malloc.h> #include <sys/poll.h> @@ -69,7 +70,7 @@ __FBSDID("$FreeBSD$"); #include <sys/ktrace.h> #endif -#include <sys/ktr.h> +#include <security/audit/audit.h> static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer"); static MALLOC_DEFINE(M_SELECT, "select", "select() buffer"); @@ -544,6 +545,70 @@ dofilewrite(td, fd, fp, auio, offset, flags) return (error); } +/* + * Truncate a file given a file descriptor. + * + * Can't use fget_write() here, since must return EINVAL and not EBADF if the + * descriptor isn't writable. + */ +int +kern_ftruncate(td, fd, length) + struct thread *td; + int fd; + off_t length; +{ + struct file *fp; + int error; + + AUDIT_ARG(fd, fd); + if (length < 0) + return (EINVAL); + error = fget(td, fd, &fp); + if (error) + return (error); + AUDIT_ARG(file, td->td_proc, fp); + if (!(fp->f_flag & FWRITE)) { + fdrop(fp, td); + return (EINVAL); + } + error = fo_truncate(fp, length, td->td_ucred, td); + fdrop(fp, td); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct ftruncate_args { + int fd; + int pad; + off_t length; +}; +#endif +int +ftruncate(td, uap) + struct thread *td; + struct ftruncate_args *uap; +{ + + return (kern_ftruncate(td, uap->fd, uap->length)); +} + +#if defined(COMPAT_43) +#ifndef _SYS_SYSPROTO_H_ +struct oftruncate_args { + int fd; + long length; +}; +#endif +int +oftruncate(td, uap) + struct thread *td; + struct oftruncate_args *uap; +{ + + return (kern_ftruncate(td, uap->fd, uap->length)); +} +#endif /* COMPAT_43 */ + #ifndef _SYS_SYSPROTO_H_ struct ioctl_args { int fd; |