summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2006-03-30 07:42:32 +0000
committerps <ps@FreeBSD.org>2006-03-30 07:42:32 +0000
commit82f0faf08691e602d759d4e2455cfcfef9fe2cbe (patch)
tree048c7e74fc0cae58e8a30c0ef3db1df5a4d347f9
parent469f432d987f41f5538a5ec954b5570ed1c23a48 (diff)
downloadFreeBSD-src-82f0faf08691e602d759d4e2455cfcfef9fe2cbe.zip
FreeBSD-src-82f0faf08691e602d759d4e2455cfcfef9fe2cbe.tar.gz
Properly support for FreeBSD 4 32bit System V shared memory.
Submitted by: peter Obtained from: Yahoo! MFC after: 3 weeks
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c170
-rw-r--r--sys/compat/freebsd32/syscalls.master6
-rw-r--r--sys/kern/sysv_shm.c10
3 files changed, 179 insertions, 7 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 472ef24..ce6ab69 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -69,6 +69,8 @@ __FBSDID("$FreeBSD$");
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
@@ -1365,10 +1367,170 @@ freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
int
freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
{
- /*
- * Vector through to shmsys if it is loaded.
- */
- return sysent[SYS_shmsys].sy_call(td, uap);
+
+ switch (uap->which) {
+ case 0: { /* shmat */
+ struct shmat_args ap;
+
+ ap.shmid = uap->a2;
+ ap.shmaddr = PTRIN(uap->a3);
+ ap.shmflg = uap->a4;
+ return (sysent[SYS_shmat].sy_call(td, &ap));
+ }
+ case 2: { /* shmdt */
+ struct shmdt_args ap;
+
+ ap.shmaddr = PTRIN(uap->a2);
+ return (sysent[SYS_shmdt].sy_call(td, &ap));
+ }
+ case 3: { /* shmget */
+ struct shmget_args ap;
+
+ ap.key = uap->a2;
+ ap.size = uap->a3;
+ ap.shmflg = uap->a4;
+ return (sysent[SYS_shmget].sy_call(td, &ap));
+ }
+ case 4: { /* shmctl */
+ struct freebsd32_shmctl_args ap;
+
+ ap.shmid = uap->a2;
+ ap.cmd = uap->a3;
+ ap.buf = PTRIN(uap->a4);
+ return (freebsd32_shmctl(td, &ap));
+ }
+ case 1: /* oshmctl */
+ default:
+ return (EINVAL);
+ }
+}
+
+struct ipc_perm32 {
+ uint16_t cuid;
+ uint16_t cgid;
+ uint16_t uid;
+ uint16_t gid;
+ uint16_t mode;
+ uint16_t seq;
+ uint32_t key;
+};
+struct shmid_ds32 {
+ struct ipc_perm32 shm_perm;
+ int32_t shm_segsz;
+ int32_t shm_lpid;
+ int32_t shm_cpid;
+ int16_t shm_nattch;
+ int32_t shm_atime;
+ int32_t shm_dtime;
+ int32_t shm_ctime;
+ uint32_t shm_internal;
+};
+struct shm_info32 {
+ int32_t used_ids;
+ uint32_t shm_tot;
+ uint32_t shm_rss;
+ uint32_t shm_swp;
+ uint32_t swap_attempts;
+ uint32_t swap_successes;
+};
+struct shminfo32 {
+ uint32_t shmmax;
+ uint32_t shmmin;
+ uint32_t shmmni;
+ uint32_t shmseg;
+ uint32_t shmall;
+};
+
+int
+freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
+{
+ int error = 0;
+ union {
+ struct shmid_ds shmid_ds;
+ struct shm_info shm_info;
+ struct shminfo shminfo;
+ } u;
+ union {
+ struct shmid_ds32 shmid_ds32;
+ struct shm_info32 shm_info32;
+ struct shminfo32 shminfo32;
+ } u32;
+ size_t sz;
+
+ if (uap->cmd == IPC_SET) {
+ if ((error = copyin(uap->buf, &u32.shmid_ds32,
+ sizeof(u32.shmid_ds32))))
+ goto done;
+ CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
+ PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
+ }
+
+ error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
+ if (error)
+ goto done;
+
+ /* Cases in which we need to copyout */
+ switch (uap->cmd) {
+ case IPC_INFO:
+ CP(u.shminfo, u32.shminfo32, shmmax);
+ CP(u.shminfo, u32.shminfo32, shmmin);
+ CP(u.shminfo, u32.shminfo32, shmmni);
+ CP(u.shminfo, u32.shminfo32, shmseg);
+ CP(u.shminfo, u32.shminfo32, shmall);
+ error = copyout(&u32.shminfo32, uap->buf,
+ sizeof(u32.shminfo32));
+ break;
+ case SHM_INFO:
+ CP(u.shm_info, u32.shm_info32, used_ids);
+ CP(u.shm_info, u32.shm_info32, shm_rss);
+ CP(u.shm_info, u32.shm_info32, shm_tot);
+ CP(u.shm_info, u32.shm_info32, shm_swp);
+ CP(u.shm_info, u32.shm_info32, swap_attempts);
+ CP(u.shm_info, u32.shm_info32, swap_successes);
+ error = copyout(&u32.shm_info32, uap->buf,
+ sizeof(u32.shm_info32));
+ break;
+ case SHM_STAT:
+ case IPC_STAT:
+ CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
+ PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
+ error = copyout(&u32.shmid_ds32, uap->buf,
+ sizeof(u32.shmid_ds32));
+ break;
+ }
+
+done:
+ if (error) {
+ /* Invalidate the return value */
+ td->td_retval[0] = -1;
+ }
+ return (error);
}
int
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index d6797c2..a39e38c 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -305,8 +305,8 @@
int a3, int a4, int a5); }
170 AUE_MSGSYS MSTD { int freebsd32_msgsys(int which, int a2, \
int a3, int a4, int a5, int a6); }
-171 AUE_SHMSYS MSTD { int freebsd32_shmsys(int which, int a2, \
- int a3, int a4); }
+171 AUE_SHMSYS MSTD { int freebsd32_shmsys(uint32_t which, uint32_t a2, \
+ uint32_t a3, uint32_t a4); }
172 AUE_NULL UNIMPL nosys
173 AUE_PREAD MSTD { ssize_t freebsd32_pread(int fd, void *buf, \
size_t nbyte, int pad, \
@@ -415,7 +415,7 @@
size_t msgsz, long msgtyp, int msgflg); }
228 AUE_SHMAT MNOPROTO { int shmat(int shmid, void *shmaddr, \
int shmflg); }
-229 AUE_SHMCTL MNOPROTO { int shmctl(int shmid, int cmd, \
+229 AUE_SHMCTL MSTD { int freebsd32_shmctl(int shmid, int cmd, \
struct shmid_ds *buf); }
230 AUE_SHMDT MNOPROTO { int shmdt(void *shmaddr); }
231 AUE_SHMGET MNOPROTO { int shmget(key_t key, int size, \
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index c52f79d..d785891 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -102,20 +102,24 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_SHM, "shm", "SVID compatible shared memory segments");
+#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43))
struct oshmctl_args;
static int oshmctl(struct thread *td, struct oshmctl_args *uap);
+#endif
static int shmget_allocate_segment(struct thread *td,
struct shmget_args *uap, int mode);
static int shmget_existing(struct thread *td, struct shmget_args *uap,
int mode, int segnum);
+#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43))
/* XXX casting to (sy_call_t *) is bogus, as usual. */
static sy_call_t *shmcalls[] = {
(sy_call_t *)shmat, (sy_call_t *)oshmctl,
(sy_call_t *)shmdt, (sy_call_t *)shmget,
(sy_call_t *)shmctl
};
+#endif
#define SHMSEG_FREE 0x0200
#define SHMSEG_REMOVED 0x0400
@@ -464,6 +468,7 @@ shmat(td, uap)
return kern_shmat(td, uap->shmid, uap->shmaddr, uap->shmflg);
}
+#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43))
struct oshmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
@@ -540,6 +545,7 @@ done2:
return (EINVAL);
#endif
}
+#endif
#ifndef _SYS_SYSPROTO_H_
struct shmctl_args {
@@ -876,6 +882,7 @@ shmsys(td, uap)
int a4;
} */ *uap;
{
+#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43))
int error;
if (!jail_sysvipc_allowed && jailed(td->td_ucred))
@@ -887,6 +894,9 @@ shmsys(td, uap)
error = (*shmcalls[uap->which])(td, &uap->a2);
mtx_unlock(&Giant);
return (error);
+#else
+ return (nosys(td, NULL));
+#endif
}
static void
OpenPOWER on IntegriCloud