diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-07-03 20:40:26 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-07-03 20:40:26 +0000 |
commit | 7172f60910c3353e8a649d297b80d3bcab9cabfe (patch) | |
tree | da1b4649fcf0d17b6d56cff207990e21be67cd8e /sys/kern/vfs_vnops.c | |
parent | 9decf10757b69d8f3d9fc71615993eb79208ce45 (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.c | 46 |
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. */ |