summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_generic.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-01-07 20:05:19 +0000
committerjhb <jhb@FreeBSD.org>2008-01-07 20:05:19 +0000
commitf8a246b9791d1450cf4945cc7b38f651a3a456ee (patch)
tree4cf9280569e048ce55d457d60918586c5cf023e5 /sys/kern/sys_generic.c
parent1b130ab3271ae64d5c2979889a661e27bbe422d9 (diff)
downloadFreeBSD-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.c67
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;
OpenPOWER on IntegriCloud