diff options
author | jhb <jhb@FreeBSD.org> | 2006-07-08 20:12:14 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2006-07-08 20:12:14 +0000 |
commit | 094306d69d41989862ff128380df0e7e2bdbe80d (patch) | |
tree | 08f1122008ef638646627d52e5fc05db3ffc64ba | |
parent | 28bb163264ff66e4b22bed304a675e7ab2ca723a (diff) | |
download | FreeBSD-src-094306d69d41989862ff128380df0e7e2bdbe80d.zip FreeBSD-src-094306d69d41989862ff128380df0e7e2bdbe80d.tar.gz |
- Split ioctl() up into ioctl() and kern_ioctl(). The kern_ioctl() assumes
that the 'data' pointer is already setup to point to a valid KVM buffer
or contains the copied-in data from userland as appropriate (ioctl(2)
still does this). kern_ioctl() takes care of looking up a file pointer,
implementing FIONCLEX and FIOCLEX, and calling fi_ioctl().
- Use kern_ioctl() to implement xenix_rdchk() instead of using the stackgap
and mark xenix_rdchk() MPSAFE.
-rw-r--r-- | sys/i386/ibcs2/ibcs2_xenix.c | 17 | ||||
-rw-r--r-- | sys/i386/ibcs2/syscalls.xenix | 2 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 81 | ||||
-rw-r--r-- | sys/sys/syscallsubr.h | 1 |
4 files changed, 53 insertions, 48 deletions
diff --git a/sys/i386/ibcs2/ibcs2_xenix.c b/sys/i386/ibcs2/ibcs2_xenix.c index faa9d7c..e3fbc04 100644 --- a/sys/i386/ibcs2/ibcs2_xenix.c +++ b/sys/i386/ibcs2/ibcs2_xenix.c @@ -84,18 +84,15 @@ xenix_rdchk(td, uap) struct thread *td; struct xenix_rdchk_args *uap; { - int error; - struct ioctl_args sa; - caddr_t sg = stackgap_init(); + int data, error; DPRINTF(("IBCS2: 'xenix rdchk'\n")); - sa.fd = uap->fd; - sa.com = FIONREAD; - sa.data = stackgap_alloc(&sg, sizeof(int)); - if ((error = ioctl(td, &sa)) != 0) - return error; - td->td_retval[0] = (*((int*)sa.data)) ? 1 : 0; - return 0; + + error = kern_ioctl(td, uap->fd, FIONREAD, (caddr_t)&data); + if (error) + return (error); + td->td_retval[0] = data ? 1 : 0; + return (0); } int diff --git a/sys/i386/ibcs2/syscalls.xenix b/sys/i386/ibcs2/syscalls.xenix index 8b9b84a..2fc1838 100644 --- a/sys/i386/ibcs2/syscalls.xenix +++ b/sys/i386/ibcs2/syscalls.xenix @@ -14,7 +14,7 @@ 4 AUE_NULL UNIMPL xenix_sigsem 5 AUE_NULL UNIMPL xenix_waitsem 6 AUE_NULL UNIMPL xenix_nbwaitsem -7 AUE_NULL STD { int xenix_rdchk(int fd); } +7 AUE_NULL MSTD { int xenix_rdchk(int fd); } 8 AUE_NULL UNIMPL nosys 9 AUE_NULL UNIMPL nosys 10 AUE_FTRUNCATE MSTD { int xenix_chsize(int fd, long size); } diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index e8cb5e9..13387ec 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -523,13 +523,10 @@ struct ioctl_args { int ioctl(struct thread *td, struct ioctl_args *uap) { - struct file *fp; - struct filedesc *fdp; u_long com; - int error = 0; + int error; u_int size; caddr_t data, memp; - int tmp; if (uap->com > 0xffffffff) { printf( @@ -537,27 +534,7 @@ ioctl(struct thread *td, struct ioctl_args *uap) td->td_proc->p_pid, td->td_proc->p_comm, uap->com); uap->com &= 0xffffffff; } - if ((error = fget(td, uap->fd, &fp)) != 0) - return (error); - if ((fp->f_flag & (FREAD | FWRITE)) == 0) { - fdrop(fp, td); - return (EBADF); - } - fdp = td->td_proc->p_fd; - switch (com = uap->com) { - case FIONCLEX: - FILEDESC_LOCK_FAST(fdp); - fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; - FILEDESC_UNLOCK_FAST(fdp); - fdrop(fp, td); - return (0); - case FIOCLEX: - FILEDESC_LOCK_FAST(fdp); - fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; - FILEDESC_UNLOCK_FAST(fdp); - fdrop(fp, td); - return (0); - } + com = uap->com; /* * Interpret high order word to find amount of data to be @@ -571,10 +548,8 @@ ioctl(struct thread *td, struct ioctl_args *uap) #else ((com & (IOC_IN | IOC_OUT)) && size == 0) || #endif - ((com & IOC_VOID) && size > 0)) { - fdrop(fp, td); + ((com & IOC_VOID) && size > 0)) return (ENOTTY); - } if (size > 0) { memp = malloc((u_long)size, M_IOCTLOPS, M_WAITOK); @@ -587,7 +562,6 @@ ioctl(struct thread *td, struct ioctl_args *uap) error = copyin(uap->data, data, (u_int)size); if (error) { free(memp, M_IOCTLOPS); - fdrop(fp, td); return (error); } } else if (com & IOC_OUT) { @@ -598,7 +572,43 @@ ioctl(struct thread *td, struct ioctl_args *uap) bzero(data, size); } - if (com == FIONBIO) { + error = kern_ioctl(td, uap->fd, com, data); + + if (error == 0 && (com & IOC_OUT)) + error = copyout(data, uap->data, (u_int)size); + + if (memp != NULL) + free(memp, M_IOCTLOPS); + return (error); +} + +int +kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data) +{ + struct file *fp; + struct filedesc *fdp; + int error; + int tmp; + + if ((error = fget(td, fd, &fp)) != 0) + return (error); + if ((fp->f_flag & (FREAD | FWRITE)) == 0) { + fdrop(fp, td); + return (EBADF); + } + fdp = td->td_proc->p_fd; + switch (com) { + case FIONCLEX: + FILEDESC_LOCK_FAST(fdp); + fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE; + FILEDESC_UNLOCK_FAST(fdp); + goto out; + case FIOCLEX: + FILEDESC_LOCK_FAST(fdp); + fdp->fd_ofileflags[fd] |= UF_EXCLOSE; + FILEDESC_UNLOCK_FAST(fdp); + goto out; + case FIONBIO: FILE_LOCK(fp); if ((tmp = *(int *)data)) fp->f_flag |= FNONBLOCK; @@ -606,7 +616,8 @@ ioctl(struct thread *td, struct ioctl_args *uap) fp->f_flag &= ~FNONBLOCK; FILE_UNLOCK(fp); data = (void *)&tmp; - } else if (com == FIOASYNC) { + break; + case FIOASYNC: FILE_LOCK(fp); if ((tmp = *(int *)data)) fp->f_flag |= FASYNC; @@ -614,15 +625,11 @@ ioctl(struct thread *td, struct ioctl_args *uap) fp->f_flag &= ~FASYNC; FILE_UNLOCK(fp); data = (void *)&tmp; + break; } error = fo_ioctl(fp, com, data, td->td_ucred, td); - - if (error == 0 && (com & IOC_OUT)) - error = copyout(data, uap->data, (u_int)size); - - if (memp != NULL) - free(memp, M_IOCTLOPS); +out: fdrop(fp, td); return (error); } diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index c98b0cf..e9bf9e2 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -87,6 +87,7 @@ int kern_getitimer(struct thread *, u_int, struct itimerval *); int kern_getrusage(struct thread *td, int who, struct rusage *rup); int kern_getsockopt(struct thread *td, int s, int level, int name, void *optval, enum uio_seg valseg, socklen_t *valsize); +int kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data); int kern_kevent(struct thread *td, int fd, int nchanges, int nevents, struct kevent_copyops *k_ops, const struct timespec *timeout); int kern_kldload(struct thread *td, const char *file, int *fileid); |