summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-07-08 20:12:14 +0000
committerjhb <jhb@FreeBSD.org>2006-07-08 20:12:14 +0000
commit094306d69d41989862ff128380df0e7e2bdbe80d (patch)
tree08f1122008ef638646627d52e5fc05db3ffc64ba
parent28bb163264ff66e4b22bed304a675e7ab2ca723a (diff)
downloadFreeBSD-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.c17
-rw-r--r--sys/i386/ibcs2/syscalls.xenix2
-rw-r--r--sys/kern/sys_generic.c81
-rw-r--r--sys/sys/syscallsubr.h1
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);
OpenPOWER on IntegriCloud