aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
authorAndrey A. Chernov <ache@FreeBSD.org>2001-08-21 21:20:42 +0000
committerAndrey A. Chernov <ache@FreeBSD.org>2001-08-21 21:20:42 +0000
commit383f169d4a7b378b69285f74d294ca502c0bdba3 (patch)
tree6c7fa56dc163bc97276370c1a686ab89b15937c0 /sys/kern/vfs_syscalls.c
parent161778121a065368a01625f70f6b2380425c1908 (diff)
downloadsrc-383f169d4a7b378b69285f74d294ca502c0bdba3.tar.gz
src-383f169d4a7b378b69285f74d294ca502c0bdba3.zip
Make lseek() POSIXed: for non character special files
1) handle off_t overflow with EOVERFLOW 2) handle negative offsets with EINVAL Reviewed by: arch discussion
Notes
Notes: svn path=/head/; revision=82098
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 086fd167ae24..06f70d8706af 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1615,29 +1615,44 @@ lseek(p, uap)
register struct filedesc *fdp = p->p_fd;
register struct file *fp;
struct vattr vattr;
- int error;
+ struct vnode *vp;
+ off_t offset;
+ int error, noneg;
if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
(fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
return (EBADF);
if (fp->f_type != DTYPE_VNODE)
return (ESPIPE);
+ vp = (struct vnode *)fp->f_data;
+ noneg = (vp->v_type != VCHR);
+ offset = SCARG(uap, offset);
switch (SCARG(uap, whence)) {
case L_INCR:
- fp->f_offset += SCARG(uap, offset);
+ if (noneg &&
+ ((offset > 0 && fp->f_offset > OFF_MAX - offset) ||
+ (offset < 0 && fp->f_offset < OFF_MIN - offset)))
+ return (EOVERFLOW);
+ offset += fp->f_offset;
break;
case L_XTND:
- error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
+ error = VOP_GETATTR(vp, &vattr, cred, p);
if (error)
return (error);
- fp->f_offset = SCARG(uap, offset) + vattr.va_size;
+ if (noneg &&
+ ((offset > 0 && vattr.va_size > OFF_MAX - offset) ||
+ (offset < 0 && vattr.va_size < OFF_MIN - offset)))
+ return (EOVERFLOW);
+ offset += vattr.va_size;
break;
case L_SET:
- fp->f_offset = SCARG(uap, offset);
break;
default:
return (EINVAL);
}
+ if (noneg && offset < 0)
+ return (EINVAL);
+ fp->f_offset = offset;
*(off_t *)(p->p_retval) = fp->f_offset;
return (0);
}