linux_ipc.c revision 64906
110015Speter/*-
212496Speter * Copyright (c) 1994-1995 S�ren Schmidt
310015Speter * All rights reserved.
410015Speter *
510015Speter * Redistribution and use in source and binary forms, with or without
610015Speter * modification, are permitted provided that the following conditions
710015Speter * are met:
810015Speter * 1. Redistributions of source code must retain the above copyright
910015Speter *    notice, this list of conditions and the following disclaimer
1010015Speter *    in this position and unchanged.
1110015Speter * 2. Redistributions in binary form must reproduce the above copyright
1210015Speter *    notice, this list of conditions and the following disclaimer in the
1310015Speter *    documentation and/or other materials provided with the distribution.
1410015Speter * 3. The name of the author may not be used to endorse or promote products
1510015Speter *    derived from this software withough specific prior written permission
1610015Speter *
1710015Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1810015Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1910015Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2010015Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2110015Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2210015Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310015Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410015Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510015Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2610015Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710015Speter *
2810015Speter * $FreeBSD: head/sys/compat/linux/linux_ipc.c 64906 2000-08-22 01:31:23Z marcel $
2910015Speter */
3010015Speter
3110015Speter#include <sys/param.h>
3210015Speter#include <sys/systm.h>
3329677Sgibbs#include <sys/sysproto.h>
3410015Speter#include <sys/proc.h>
3510015Speter#include <sys/sem.h>
3610015Speter#include <sys/shm.h>
3716322Sgpalmer
3816322Sgpalmer#include <machine/../linux/linux.h>
3916322Sgpalmer#include <machine/../linux/linux_proto.h>
4010015Speter#include <compat/linux/linux_ipc.h>
4110015Speter#include <compat/linux/linux_util.h>
4210015Speter
4310015Speterstruct linux_ipc_perm {
4424207Sbde    linux_key_t key;
4524207Sbde    unsigned short uid;
4624207Sbde    unsigned short gid;
4710015Speter    unsigned short cuid;
4810015Speter    unsigned short cgid;
4910015Speter    unsigned short mode;
5024131Sbde    unsigned short seq;
5110015Speter};
5210015Speter
5310015Speterstatic void
5415683Speterlinux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
5512675Sjulian{
5612675Sjulian    bpp->key = lpp->key;
5712675Sjulian    bpp->uid = lpp->uid;
5810015Speter    bpp->gid = lpp->gid;
5910015Speter    bpp->cuid = lpp->cuid;
6010015Speter    bpp->cgid = lpp->cgid;
6112659Sbde    bpp->mode = lpp->mode;
6212662Sdg    bpp->seq = lpp->seq;
6312659Sbde}
6410015Speter
6510015Speter
6610015Speterstatic void
6710015Speterbsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
6810015Speter{
6910015Speter    lpp->key = bpp->key;
7013353Speter    lpp->uid = bpp->uid;
7110015Speter    lpp->gid = bpp->gid;
7210015Speter    lpp->cuid = bpp->cuid;
7310015Speter    lpp->cgid = bpp->cgid;
7410015Speter    lpp->mode = bpp->mode;
7510015Speter    lpp->seq = bpp->seq;
7612496Speter}
7710015Speter
7810015Speterstruct linux_semid_ds {
7910015Speter	struct linux_ipc_perm	sem_perm;
8010015Speter	linux_time_t		sem_otime;
8110015Speter	linux_time_t		sem_ctime;
8217547Speter	void			*sem_base;
8317547Speter	void			*sem_pending;
8417547Speter	void			*sem_pending_last;
8510047Speter	void			*undo;
8612496Speter	ushort			sem_nsems;
8715639Speter};
8815639Speter
8910015Speterstruct linux_shmid_ds {
9010015Speter    struct linux_ipc_perm shm_perm;
9110015Speter    int shm_segsz;
9210015Speter    linux_time_t shm_atime;
9310015Speter    linux_time_t shm_dtime;
9410015Speter    linux_time_t shm_ctime;
9510015Speter    ushort shm_cpid;
9610015Speter    ushort shm_lpid;
9725047Sbde    short shm_nattch;
9810015Speter    ushort private1;
9910015Speter    void *private2;
10010015Speter    void *private3;
10110015Speter};
10210015Speter
10312724Sphkstatic void
10410015Speterlinux_to_bsd_semid_ds(struct linux_semid_ds *lsp, struct semid_ds *bsp)
10512724Sphk{
10612724Sphk    linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
10710708Speter    bsp->sem_otime = lsp->sem_otime;
10810708Speter    bsp->sem_ctime = lsp->sem_ctime;
10912675Sjulian    bsp->sem_nsems = lsp->sem_nsems;
11012675Sjulian    bsp->sem_base = lsp->sem_base;
11112675Sjulian}
11212675Sjulian
11312675Sjulianstatic void
11412675Sjulianbsd_to_linux_semid_ds(struct semid_ds *bsp, struct linux_semid_ds *lsp)
11512675Sjulian{
11612675Sjulian	bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
11712675Sjulian	lsp->sem_otime = bsp->sem_otime;
11812675Sjulian	lsp->sem_ctime = bsp->sem_ctime;
11912731Sbde	lsp->sem_nsems = bsp->sem_nsems;
12012675Sjulian	lsp->sem_base = bsp->sem_base;
12112675Sjulian}
12212678Sphk
12312675Sjulianstatic void
12412743Sbdelinux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
12529368Speter{
12612675Sjulian    linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
12712675Sjulian    bsp->shm_segsz = lsp->shm_segsz;
12812174Speter    bsp->shm_lpid = lsp->shm_lpid;
12913353Speter    bsp->shm_cpid = lsp->shm_cpid;
13013353Speter    bsp->shm_nattch = lsp->shm_nattch;
13113353Speter    bsp->shm_atime = lsp->shm_atime;
13210708Speter    bsp->shm_dtime = lsp->shm_dtime;
13313353Speter    bsp->shm_ctime = lsp->shm_ctime;
13410708Speter    bsp->shm_internal = lsp->private3;	/* this goes (yet) SOS */
13513353Speter}
13610708Speter
13710708Speterstatic void
13810708Speterbsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
13910708Speter{
14010962Speter    bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
14110962Speter    lsp->shm_segsz = bsp->shm_segsz;
14210962Speter    lsp->shm_lpid = bsp->shm_lpid;
14310015Speter    lsp->shm_cpid = bsp->shm_cpid;
14410962Speter    lsp->shm_nattch = bsp->shm_nattch;
14510962Speter    lsp->shm_atime = bsp->shm_atime;
14612174Speter    lsp->shm_dtime = bsp->shm_dtime;
14710015Speter    lsp->shm_ctime = bsp->shm_ctime;
14810015Speter    lsp->private3 = bsp->shm_internal;	/* this goes (yet) SOS */
14910015Speter}
15010044Speter
15110044Speterint
15210044Speterlinux_semop(struct proc *p, struct linux_ipc_args *args)
15310044Speter{
15410044Speter	struct semop_args /* {
15510044Speter	int	semid;
15610044Speter	struct	sembuf *sops;
15710044Speter	int		nsops;
15810044Speter	} */ bsd_args;
15910044Speter
16010044Speter	bsd_args.semid = args->arg1;
16110044Speter	bsd_args.sops = (struct sembuf *)args->ptr;
16212675Sjulian	bsd_args.nsops = args->arg2;
16312675Sjulian	return semop(p, &bsd_args);
16412675Sjulian}
16512826Speter
16612675Sjulianint
16712675Sjulianlinux_semget(struct proc *p, struct linux_ipc_args *args)
16812675Sjulian{
16913165Speter	struct semget_args /* {
17012675Sjulian	key_t	key;
17110044Speter	int		nsems;
17212724Sphk	int		semflg;
17310044Speter	} */ bsd_args;
17412174Speter
17510015Speter	bsd_args.key = args->arg1;
17610015Speter	bsd_args.nsems = args->arg2;
17710015Speter	bsd_args.semflg = args->arg3;
17810015Speter	return semget(p, &bsd_args);
17910015Speter}
18010015Speter
18110015Speterint
18210015Speterlinux_semctl(struct proc *p, struct linux_ipc_args *args)
18310015Speter{
18410015Speter	struct linux_semid_ds	linux_semid;
18510015Speter	struct semid_ds	bsd_semid;
18610015Speter	struct __semctl_args /* {
18710015Speter	int		semid;
18810015Speter	int		semnum;
18910015Speter	int		cmd;
19010015Speter	union	semun *arg;
19110015Speter	} */ bsd_args;
19210015Speter	int	error;
19310015Speter	caddr_t sg, unptr, dsp, ldsp;
19410015Speter
19510015Speter	sg = stackgap_init();
19610015Speter	bsd_args.semid = args->arg1;
19710015Speter	bsd_args.semnum = args->arg2;
19810015Speter	bsd_args.cmd = args->arg3;
19910015Speter	bsd_args.arg = (union semun *)args->ptr;
20010015Speter
20110015Speter	switch (args->arg3) {
20210015Speter	case LINUX_IPC_RMID:
20310015Speter		bsd_args.cmd = IPC_RMID;
20410015Speter		break;
20510015Speter	case LINUX_GETNCNT:
20610015Speter		bsd_args.cmd = GETNCNT;
20710015Speter		break;
20810015Speter	case LINUX_GETPID:
20910015Speter		bsd_args.cmd = GETPID;
21010015Speter		break;
21110015Speter	case LINUX_GETVAL:
21210015Speter		bsd_args.cmd = GETVAL;
21310015Speter		break;
21410015Speter	case LINUX_GETZCNT:
21510015Speter		bsd_args.cmd = GETZCNT;
21610015Speter		break;
21710015Speter	case LINUX_SETVAL:
21810047Speter		bsd_args.cmd = SETVAL;
21910047Speter		break;
22010047Speter	case LINUX_IPC_SET:
22110047Speter		bsd_args.cmd = IPC_SET;
22210047Speter		error = copyin(args->ptr, &ldsp, sizeof(ldsp));
22310047Speter		if (error)
22410047Speter			return error;
22510047Speter		error = copyin(ldsp, (caddr_t)&linux_semid, sizeof(linux_semid));
22610047Speter		if (error)
22710047Speter			return error;
22810015Speter		linux_to_bsd_semid_ds(&linux_semid, &bsd_semid);
22915683Speter		unptr = stackgap_alloc(&sg, sizeof(union semun));
23017547Speter		dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
23115639Speter		error = copyout((caddr_t)&bsd_semid, dsp, sizeof(bsd_semid));
23216403Speter		if (error)
23317547Speter			return error;
23415639Speter		error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
23510015Speter		if (error)
23610015Speter			return error;
23710015Speter		bsd_args.arg = (union semun *)unptr;
23810015Speter		return __semctl(p, &bsd_args);
23910015Speter	case LINUX_IPC_STAT:
24010015Speter		bsd_args.cmd = IPC_STAT;
24110015Speter		unptr = stackgap_alloc(&sg, sizeof(union semun *));
24210015Speter		dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
24310015Speter		error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
24410015Speter		if (error)
24510015Speter			return error;
24610015Speter		bsd_args.arg = (union semun *)unptr;
24710015Speter		error = __semctl(p, &bsd_args);
24810015Speter		if (error)
24910015Speter			return error;
25010015Speter		error = copyin(dsp, (caddr_t)&bsd_semid, sizeof(bsd_semid));
25110015Speter		if (error)
25212724Sphk			return error;
25310015Speter		bsd_to_linux_semid_ds(&bsd_semid, &linux_semid);
25410015Speter		error = copyin(args->ptr, &ldsp, sizeof(ldsp));
25510015Speter		if (error)
25610015Speter			return error;
25710015Speter		return copyout((caddr_t)&linux_semid, ldsp, sizeof(linux_semid));
25810015Speter	case LINUX_GETALL:
25910015Speter		/* FALLTHROUGH */
26010015Speter	case LINUX_SETALL:
26110015Speter		/* FALLTHROUGH */
26210015Speter	default:
26317547Speter		uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
26417547Speter		return EINVAL;
26517547Speter	}
26617547Speter	return __semctl(p, &bsd_args);
26715683Speter}
26810015Speter
26910015Speterint
27010015Speterlinux_msgsnd(struct proc *p, struct linux_ipc_args *args)
27112496Speter{
27212496Speter    struct msgsnd_args /* {
27310015Speter	int     msqid;
27410015Speter	void    *msgp;
27510015Speter	size_t  msgsz;
27610015Speter	int     msgflg;
27710015Speter    } */ bsd_args;
27810015Speter
27910015Speter    bsd_args.msqid = args->arg1;
28012174Speter    bsd_args.msgp = args->ptr;
28112174Speter    bsd_args.msgsz = args->arg2;
28210015Speter    bsd_args.msgflg = args->arg3;
28310015Speter    return msgsnd(p, &bsd_args);
28410015Speter}
28510015Speter
28610015Speterint
28710015Speterlinux_msgrcv(struct proc *p, struct linux_ipc_args *args)
28810015Speter{
28910015Speter    struct msgrcv_args /* {
29010015Speter        int 	msqid;
29110015Speter	void	*msgp;
29210015Speter	size_t	msgsz;
29310015Speter	long	msgtyp;
29410015Speter	int	msgflg;
29510015Speter    } */ bsd_args;
29610015Speter
29710015Speter    bsd_args.msqid = args->arg1;
29810015Speter    bsd_args.msgp = args->ptr;
29910015Speter    bsd_args.msgsz = args->arg2;
30010015Speter    bsd_args.msgtyp = 0;
30110015Speter    bsd_args.msgflg = args->arg3;
30210015Speter    return msgrcv(p, &bsd_args);
30310015Speter}
30410015Speter
30510015Speterint
30610015Speterlinux_msgget(struct proc *p, struct linux_ipc_args *args)
30710015Speter{
30810015Speter    struct msgget_args /* {
30910015Speter	key_t	key;
31010015Speter        int 	msgflg;
31110015Speter    } */ bsd_args;
31210015Speter
31310015Speter    bsd_args.key = args->arg1;
31410015Speter    bsd_args.msgflg = args->arg2;
31510015Speter    return msgget(p, &bsd_args);
31610015Speter}
31710015Speter
31810015Speterint
31910015Speterlinux_msgctl(struct proc *p, struct linux_ipc_args *args)
32010015Speter{
32110015Speter    struct msgctl_args /* {
32210015Speter	int     msqid;
32312496Speter	int     cmd;
32410015Speter	struct	msqid_ds *buf;
32510015Speter    } */ bsd_args;
32610015Speter    int error;
32710015Speter
32810015Speter    bsd_args.msqid = args->arg1;
32910015Speter    bsd_args.cmd = args->arg2;
33010015Speter    bsd_args.buf = (struct msqid_ds *)args->ptr;
33110015Speter    error = msgctl(p, &bsd_args);
33210015Speter    return ((args->arg2 == LINUX_IPC_RMID && error == EINVAL) ? 0 : error);
33310015Speter}
33410015Speter
33510015Speterint
33610015Speterlinux_shmat(struct proc *p, struct linux_ipc_args *args)
33710015Speter{
33810015Speter    struct shmat_args /* {
33910015Speter	int shmid;
34010015Speter	void *shmaddr;
34110015Speter	int shmflg;
34210015Speter    } */ bsd_args;
34310015Speter    int error;
34410015Speter
34510015Speter    bsd_args.shmid = args->arg1;
34610015Speter    bsd_args.shmaddr = args->ptr;
34710015Speter    bsd_args.shmflg = args->arg2;
34810015Speter    if ((error = shmat(p, &bsd_args)))
34910015Speter	return error;
35010015Speter    if ((error = copyout(p->p_retval, (caddr_t)args->arg3, sizeof(int))))
35110015Speter	return error;
35210015Speter    p->p_retval[0] = 0;
35310015Speter    return 0;
35410015Speter}
35510015Speter
35610015Speterint
35710015Speterlinux_shmdt(struct proc *p, struct linux_ipc_args *args)
35810015Speter{
35910015Speter    struct shmdt_args /* {
36010015Speter	void *shmaddr;
36110015Speter    } */ bsd_args;
36210015Speter
36310015Speter    bsd_args.shmaddr = args->ptr;
36410015Speter    return shmdt(p, &bsd_args);
36510015Speter}
36610015Speter
36710015Speterint
36810015Speterlinux_shmget(struct proc *p, struct linux_ipc_args *args)
36910015Speter{
37010015Speter    struct shmget_args /* {
37110015Speter	key_t key;
37210015Speter	int size;
37310015Speter	int shmflg;
37410015Speter    } */ bsd_args;
37510015Speter
37610015Speter    bsd_args.key = args->arg1;
37710015Speter    bsd_args.size = args->arg2;
37810015Speter    bsd_args.shmflg = args->arg3;
37910015Speter    return shmget(p, &bsd_args);
38010015Speter}
38110015Speter
38210015Speterint
38310015Speterlinux_shmctl(struct proc *p, struct linux_ipc_args *args)
38410015Speter{
38510015Speter    struct shmid_ds bsd_shmid;
38610015Speter    struct linux_shmid_ds linux_shmid;
38710015Speter    struct shmctl_args /* {
38810015Speter	int shmid;
38912496Speter	int cmd;
39012496Speter	struct shmid_ds *buf;
39110015Speter    } */ bsd_args;
39218515Speter    int error;
39310015Speter    caddr_t sg = stackgap_init();
39410015Speter
39518515Speter    switch (args->arg2) {
39610015Speter    case LINUX_IPC_STAT:
39710015Speter	bsd_args.shmid = args->arg1;
39810015Speter	bsd_args.cmd = IPC_STAT;
39912174Speter	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
40010015Speter	if ((error = shmctl(p, &bsd_args)))
40110015Speter	    return error;
40210015Speter	if ((error = copyin((caddr_t)bsd_args.buf, (caddr_t)&bsd_shmid,
40310015Speter		    	    sizeof(struct shmid_ds))))
40410015Speter	    return error;
40510015Speter	bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
40618515Speter	return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
40710015Speter
40810015Speter    case LINUX_IPC_SET:
40918515Speter	if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
41010015Speter		    	    sizeof(linux_shmid))))
41110015Speter	    return error;
41210015Speter	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
41312174Speter	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
41410015Speter	if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
41510015Speter		     	     sizeof(struct shmid_ds))))
41610015Speter	    return error;
41710015Speter	bsd_args.shmid = args->arg1;
41810015Speter	bsd_args.cmd = IPC_SET;
41910015Speter	return shmctl(p, &bsd_args);
42010015Speter
42110015Speter    case LINUX_IPC_RMID:
42210015Speter	bsd_args.shmid = args->arg1;
42310015Speter	bsd_args.cmd = IPC_RMID;
42410015Speter	if (NULL == args->ptr)
42510015Speter	    bsd_args.buf = NULL;
42610015Speter	else {
42710015Speter	    if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
42810015Speter		    		sizeof(linux_shmid))))
42910015Speter		return error;
43010015Speter	    linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
43110015Speter	    bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
43210015Speter	    if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
43310015Speter		     		 sizeof(struct shmid_ds))))
43410015Speter		return error;
43510015Speter	}
43610015Speter	return shmctl(p, &bsd_args);
43710015Speter
43810015Speter    case LINUX_IPC_INFO:
43910015Speter    case LINUX_SHM_STAT:
44010015Speter    case LINUX_SHM_INFO:
44110015Speter    case LINUX_SHM_LOCK:
44210015Speter    case LINUX_SHM_UNLOCK:
44310015Speter    default:
44410015Speter	uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
44510015Speter	return EINVAL;
44610015Speter    }
44710015Speter}
44810015Speter