diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-05-16 17:14:40 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-05-16 17:14:40 +0000 |
commit | d081888ede32893d5dfa6a13f09405aa730c9092 (patch) | |
tree | df2c5452e4612103cc5e3b507980de79f926318b /sys/compat/common/kern_ipc_23.c | |
parent | a298e9ff9d4b9418b1b5b64c70a04ed9774e676d (diff) |
Create COMPAT_25 and move ogetfsstat, ostatfs and ostatfs into it.
Create COMPAT_23 and move __osemctl, omsgctl, oshmctl there.
Diffstat (limited to 'sys/compat/common/kern_ipc_23.c')
-rw-r--r-- | sys/compat/common/kern_ipc_23.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/sys/compat/common/kern_ipc_23.c b/sys/compat/common/kern_ipc_23.c new file mode 100644 index 00000000000..171154d4b9a --- /dev/null +++ b/sys/compat/common/kern_ipc_23.c @@ -0,0 +1,449 @@ +/* $OpenBSD: kern_ipc_23.c,v 1.1 2001/05/16 17:14:38 millert Exp $ */ + +/* + * Implementation of SVID semaphores + * + * Author: Daniel Boulet + * + * This software is provided ``AS IS'' without any warranties of any kind. + */ +/* + * Implementation of SVID messages + * + * Author: Daniel Boulet + * + * Copyright 1993 Daniel Boulet and RTMX Inc. + * + * This system call was implemented by Daniel Boulet under contract from RTMX. + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + */ +/* + * Copyright (c) 1994 Adam Glass and Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass and Charles M. + * Hannum. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <sys/msg.h> +#include <sys/sem.h> +#include <sys/shm.h> +#include <sys/malloc.h> + +#include <sys/mount.h> +#include <sys/syscallargs.h> + +#ifdef SYSVMSG + +void msg_freehdr __P((struct msg *)); + +int +compat_23_sys_msgctl(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_23_sys_msgctl_args /* { + syscallarg(int) msqid; + syscallarg(int) cmd; + syscallarg(struct msqid_ds *) buf; + } */ *uap = v; + int msqid = SCARG(uap, msqid); + int cmd = SCARG(uap, cmd); + struct omsqid_ds *user_msqptr = SCARG(uap, buf); + struct ucred *cred = p->p_ucred; + int rval, eval; + struct omsqid_ds omsqbuf; + register struct msqid_ds *msqptr; + +#ifdef MSG_DEBUG_OK + printf("call to msgctl(%d, %d, %p)\n", msqid, cmd, user_msqptr); +#endif + + msqid = IPCID_TO_IX(msqid); + + if (msqid < 0 || msqid >= msginfo.msgmni) { +#ifdef MSG_DEBUG_OK + printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, + msginfo.msgmni); +#endif + return(EINVAL); + } + + msqptr = &msqids[msqid]; + + if (msqptr->msg_qbytes == 0) { +#ifdef MSG_DEBUG_OK + printf("no such msqid\n"); +#endif + return(EINVAL); + } + if (msqptr->msg_perm.seq != IPCID_TO_SEQ(SCARG(uap, msqid))) { +#ifdef MSG_DEBUG_OK + printf("wrong sequence number\n"); +#endif + return(EINVAL); + } + + eval = 0; + rval = 0; + + switch (cmd) { + + case IPC_RMID: + { + struct msg *msghdr; + if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_M)) != 0) + return(eval); + /* Free the message headers */ + msghdr = msqptr->msg_first; + while (msghdr != NULL) { + struct msg *msghdr_tmp; + + /* Free the segments of each message */ + msqptr->msg_cbytes -= msghdr->msg_ts; + msqptr->msg_qnum--; + msghdr_tmp = msghdr; + msghdr = msghdr->msg_next; + msg_freehdr(msghdr_tmp); + } + +#ifdef DIAGNOSTIC + if (msqptr->msg_cbytes != 0) + panic("sys_omsgctl: msg_cbytes is screwed up"); + if (msqptr->msg_qnum != 0) + panic("sys_omsgctl: msg_qnum is screwed up"); +#endif + + msqptr->msg_qbytes = 0; /* Mark it as free */ + + wakeup((caddr_t)msqptr); + } + + break; + + case IPC_SET: + if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_M))) + return(eval); + if ((eval = copyin(user_msqptr, &omsqbuf, sizeof(omsqbuf))) != 0) + return(eval); + if (omsqbuf.msg_qbytes > msqptr->msg_qbytes && cred->cr_uid != 0) + return(EPERM); + if (omsqbuf.msg_qbytes > msginfo.msgmnb) { +#ifdef MSG_DEBUG_OK + printf("can't increase msg_qbytes beyond %d (truncating)\n", + msginfo.msgmnb); +#endif + omsqbuf.msg_qbytes = msginfo.msgmnb; /* silently restrict qbytes to system limit */ + } + if (omsqbuf.msg_qbytes == 0) { +#ifdef MSG_DEBUG_OK + printf("can't reduce msg_qbytes to 0\n"); +#endif + return(EINVAL); /* non-standard errno! */ + } + msqptr->msg_perm.uid = omsqbuf.msg_perm.uid; /* change the owner */ + msqptr->msg_perm.gid = omsqbuf.msg_perm.gid; /* change the owner */ + msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) | + (omsqbuf.msg_perm.mode & 0777); + msqptr->msg_qbytes = omsqbuf.msg_qbytes; + msqptr->msg_ctime = time.tv_sec; + break; + + case IPC_STAT: + if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_R))) { +#ifdef MSG_DEBUG_OK + printf("requester doesn't have read access\n"); +#endif + return(eval); + } + msqid_n2o(msqptr, &omsqbuf); + eval = copyout((caddr_t)&omsqbuf, user_msqptr, sizeof omsqbuf); + break; + + default: +#ifdef MSG_DEBUG_OK + printf("invalid command %d\n", cmd); +#endif + return(EINVAL); + } + + if (eval == 0) + *retval = rval; + return(eval); +} +#endif /* SYSVMSG */ + +#ifdef SYSVSHM + +struct shmid_ds *shm_find_segment_by_shmid __P((int)); +void shm_deallocate_segment __P((struct shmid_ds *)); + +#define SHMSEG_REMOVED 0x0400 /* XXX */ + +int +compat_23_sys_shmctl(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct compat_23_sys_shmctl_args /* { + syscallarg(int) shmid; + syscallarg(int) cmd; + syscallarg(struct shmid_ds *) buf; + } */ *uap = v; + int error; + struct ucred *cred = p->p_ucred; + struct oshmid_ds oinbuf; + struct shmid_ds *shmseg; + extern int shm_last_free; + + shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid)); + if (shmseg == NULL) + return EINVAL; + switch (SCARG(uap, cmd)) { + case IPC_STAT: + if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_R)) != 0) + return error; + shmid_n2o(shmseg, &oinbuf); + error = copyout((caddr_t)&oinbuf, SCARG(uap, buf), + sizeof(oinbuf)); + if (error) + return error; + break; + case IPC_SET: + if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) + return error; + error = copyin(SCARG(uap, buf), (caddr_t)&oinbuf, + sizeof(oinbuf)); + if (error) + return error; + shmseg->shm_perm.uid = oinbuf.shm_perm.uid; + shmseg->shm_perm.gid = oinbuf.shm_perm.gid; + shmseg->shm_perm.mode = + (shmseg->shm_perm.mode & ~ACCESSPERMS) | + (oinbuf.shm_perm.mode & ACCESSPERMS); + shmseg->shm_ctime = time.tv_sec; + break; + case IPC_RMID: + if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) + return error; + shmseg->shm_perm.key = IPC_PRIVATE; + shmseg->shm_perm.mode |= SHMSEG_REMOVED; + if (shmseg->shm_nattch <= 0) { + shm_deallocate_segment(shmseg); + shm_last_free = IPCID_TO_IX(SCARG(uap, shmid)); + } + break; + case SHM_LOCK: + case SHM_UNLOCK: + default: + return EINVAL; + } + return 0; +} +#endif /* SYSVSHM */ + +#ifdef SYSVSEM + +void semundo_clear __P((int, int)); + +int +compat_23_sys___semctl(p, v, retval) + struct proc *p; + register void *v; + register_t *retval; +{ + register struct compat_23_sys___semctl_args /* { + syscallarg(int) semid; + syscallarg(int) semnum; + syscallarg(int) cmd; + syscallarg(union semun *) arg; + } */ *uap = v; + int semid = SCARG(uap, semid); + int semnum = SCARG(uap, semnum); + int cmd = SCARG(uap, cmd); + union semun *arg = SCARG(uap, arg); + union semun real_arg; + struct ucred *cred = p->p_ucred; + int i, rval, eval; + struct semid_ds *semaptr; + struct osemid_ds osbuf; + extern int semtot; + +#ifdef SEM_DEBUG + printf("call to semctl(%d, %d, %d, %p)\n", semid, semnum, cmd, arg); +#endif + + semid = IPCID_TO_IX(semid); + if (semid < 0 || semid >= seminfo.semmsl) + return(EINVAL); + + semaptr = &sema[semid]; + if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || + semaptr->sem_perm.seq != IPCID_TO_SEQ(SCARG(uap, semid))) + return(EINVAL); + + eval = 0; + rval = 0; + + switch (cmd) { + case IPC_RMID: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M)) != 0) + return(eval); + semaptr->sem_perm.cuid = cred->cr_uid; + semaptr->sem_perm.uid = cred->cr_uid; + semtot -= semaptr->sem_nsems; + for (i = semaptr->sem_base - sem; i < semtot; i++) + sem[i] = sem[i + semaptr->sem_nsems]; + for (i = 0; i < seminfo.semmni; i++) { + if ((sema[i].sem_perm.mode & SEM_ALLOC) && + sema[i].sem_base > semaptr->sem_base) + sema[i].sem_base -= semaptr->sem_nsems; + } + semaptr->sem_perm.mode = 0; + semundo_clear(semid, -1); + wakeup((caddr_t)semaptr); + break; + + case IPC_SET: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M))) + return(eval); + if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + return(eval); + if ((eval = copyin(real_arg.buf, (caddr_t)&osbuf, + sizeof(osbuf))) != 0) + return(eval); + semaptr->sem_perm.uid = osbuf.sem_perm.uid; + semaptr->sem_perm.gid = osbuf.sem_perm.gid; + semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) | + (osbuf.sem_perm.mode & 0777); + semaptr->sem_ctime = time.tv_sec; + break; + + case IPC_STAT: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) + return(eval); + if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + return(eval); + semid_n2o(semaptr, &osbuf); + eval = copyout((caddr_t)&osbuf, real_arg.buf, sizeof osbuf); + break; + + case GETNCNT: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) + return(eval); + if (semnum < 0 || semnum >= semaptr->sem_nsems) + return(EINVAL); + rval = semaptr->sem_base[semnum].semncnt; + break; + + case GETPID: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) + return(eval); + if (semnum < 0 || semnum >= semaptr->sem_nsems) + return(EINVAL); + rval = semaptr->sem_base[semnum].sempid; + break; + + case GETVAL: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) + return(eval); + if (semnum < 0 || semnum >= semaptr->sem_nsems) + return(EINVAL); + rval = semaptr->sem_base[semnum].semval; + break; + + case GETALL: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) + return(eval); + if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + return(eval); + for (i = 0; i < semaptr->sem_nsems; i++) { + eval = copyout((caddr_t)&semaptr->sem_base[i].semval, + &real_arg.array[i], sizeof(real_arg.array[0])); + if (eval != 0) + break; + } + break; + + case GETZCNT: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) + return(eval); + if (semnum < 0 || semnum >= semaptr->sem_nsems) + return(EINVAL); + rval = semaptr->sem_base[semnum].semzcnt; + break; + + case SETVAL: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W))) + return(eval); + if (semnum < 0 || semnum >= semaptr->sem_nsems) + return(EINVAL); + if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + return(eval); + semaptr->sem_base[semnum].semval = real_arg.val; + semundo_clear(semid, semnum); + wakeup((caddr_t)semaptr); + break; + + case SETALL: + if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W))) + return(eval); + if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + return(eval); + for (i = 0; i < semaptr->sem_nsems; i++) { + eval = copyin(&real_arg.array[i], + (caddr_t)&semaptr->sem_base[i].semval, + sizeof(real_arg.array[0])); + if (eval != 0) + break; + } + semundo_clear(semid, -1); + wakeup((caddr_t)semaptr); + break; + + default: + return(EINVAL); + } + + if (eval == 0) + *retval = rval; + return(eval); +} +#endif /* SYSVSEM */ |