Date: Wed, 15 Aug 2001 12:52:48 +0400 From: "Andrey A. Chernov" <ache@nagual.pp.ru> To: arch@freebsd.org, current@freebsd.org Subject: CFR: lseek() POSIXed patch Message-ID: <20010815125248.A2588@nagual.pp.ru>
next in thread | raw e-mail | index | archive | help
Here it is what POSIX says about lseek(): [EINVAL] The whence argument is not a proper value, or the resulting file offset would be negative for a regular file, block special file, or directory. [EOVERFLOW] The resulting file offset would be a value which cannot be represented correctly in an object of type off_t. The patch below adds both cases, i.e. disallow negative seeks for VREG, VDIR, VBLK and add off_t overflow checks. I plan to commit this, please review. --- vfs_syscalls.c.old Wed Aug 15 04:45:30 2001 +++ vfs_syscalls.c Wed Aug 15 12:46:12 2001 @@ -1614,29 +1614,44 @@ register struct filedesc *fdp = p->p_fd; register struct file *fp; struct vattr vattr; - int error; + off_t offset; + int error, no_neg_seek; 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); + error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); + no_neg_seek = (!error && + (vattr.va_type == VREG || + vattr.va_type == VDIR || + vattr.va_type == VBLK)); + offset = SCARG(uap, offset); switch (SCARG(uap, whence)) { case L_INCR: - fp->f_offset += SCARG(uap, offset); + if ((fp->f_offset > 0 && offset > 0 && + offset + fp->f_offset < 0) || + (fp->f_offset < 0 && offset < 0 && + offset + fp->f_offset > 0)) + return (EOVERFLOW); + offset += fp->f_offset; break; case L_XTND: - error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); if (error) return (error); - fp->f_offset = SCARG(uap, offset) + vattr.va_size; + if (offset > 0 && (off_t)(offset + vattr.va_size) < 0) + return (EOVERFLOW); + offset += vattr.va_size; break; case L_SET: - fp->f_offset = SCARG(uap, offset); break; default: return (EINVAL); } + if (no_neg_seek && offset < 0) + return (EINVAL); + fp->f_offset = offset; *(off_t *)(p->p_retval) = fp->f_offset; return (0); } -- Andrey A. Chernov http://ache.pp.ru/ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010815125248.A2588>