summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_vnops.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-07-03 20:40:26 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-07-03 20:40:26 +0000
commit7172f60910c3353e8a649d297b80d3bcab9cabfe (patch)
treeda1b4649fcf0d17b6d56cff207990e21be67cd8e /sys/kern/vfs_vnops.c
parent9decf10757b69d8f3d9fc71615993eb79208ce45 (diff)
Add a new so_seek member to "struct file" such that we can have seekable
files that aren't vnodes. Move the vnode-specific code into its own function. Add an implementation for the "DMA buffers" that can be used by DRI3/prime code to find out the size of the graphics buffer. This implementation is very limited and only supports offset 0 and only for SEEK_SET and SEEK_END. This doesn't really make sense; implementing stat(2) would be a more obvious choice. But this is what Linux does. ok guenther@, visa@
Diffstat (limited to 'sys/kern/vfs_vnops.c')
-rw-r--r--sys/kern/vfs_vnops.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 2dbc93adba4..c20982e0308 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.94 2018/07/03 12:58:18 anton Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.95 2018/07/03 20:40:25 kettenis Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -64,6 +64,7 @@ int vn_write(struct file *, off_t *, struct uio *, struct ucred *);
int vn_poll(struct file *, int, struct proc *);
int vn_kqfilter(struct file *, struct knote *);
int vn_closefile(struct file *, struct proc *);
+int vn_seek(struct file *, off_t *, int, struct proc *);
struct fileops vnops = {
.fo_read = vn_read,
@@ -72,7 +73,8 @@ struct fileops vnops = {
.fo_poll = vn_poll,
.fo_kqfilter = vn_kqfilter,
.fo_stat = vn_statfile,
- .fo_close = vn_closefile
+ .fo_close = vn_closefile,
+ .fo_seek = vn_seek,
};
/*
@@ -561,6 +563,46 @@ vn_kqfilter(struct file *fp, struct knote *kn)
return (VOP_KQFILTER(fp->f_data, kn));
}
+int
+vn_seek(struct file *fp, off_t *offset, int whence, struct proc *p)
+{
+ struct ucred *cred = p->p_ucred;
+ struct vnode *vp = fp->f_data;
+ struct vattr vattr;
+ off_t newoff;
+ int error, special;
+
+ if (vp->v_type == VFIFO)
+ return (ESPIPE);
+ if (vp->v_type == VCHR)
+ special = 1;
+ else
+ special = 0;
+
+ switch (whence) {
+ case SEEK_CUR:
+ newoff = fp->f_offset + *offset;
+ break;
+ case SEEK_END:
+ error = VOP_GETATTR(vp, &vattr, cred, p);
+ if (error)
+ return (error);
+ newoff = *offset + (off_t)vattr.va_size;
+ break;
+ case SEEK_SET:
+ newoff = *offset;
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (!special) {
+ if (newoff < 0)
+ return(EINVAL);
+ }
+ fp->f_offset = *offset = newoff;
+ return (0);
+}
+
/*
* Common code for vnode access operations.
*/