extractedLnx/linux/arch/sparc64/kernel/sys_sparc32.c_sys32_ipc.c
asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{
int version, err;
lock_kernel();
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
if (call <= SEMCTL)
switch (call) {
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
err = sys_semop (first, (struct sembuf *)A(ptr), second);
goto out;
case SEMGET:
err = sys_semget (first, second, third);
goto out;
case SEMCTL: {
union semun fourth;
void *pad;
mm_segment_t old_fs;
struct semid_ds s;
err = -EINVAL;
if (!ptr)
goto out;
err = -EFAULT;
if(get_user(pad, (void **)A(ptr)))
goto out;
fourth.__pad = pad;
switch (third) {
case IPC_INFO:
case SEM_INFO:
case GETVAL:
case GETPID:
case GETNCNT:
case GETZCNT:
case GETALL:
case SETALL:
case IPC_RMID:
err = sys_semctl (first, second, third, fourth);
goto out;
case IPC_SET:
if (get_user (s.sem_perm.uid, &(((struct semid_ds32 *)A(pad))->sem_perm.uid)) ||
__get_user (s.sem_perm.gid, &(((struct semid_ds32 *)A(pad))->sem_perm.gid)) ||
__get_user (s.sem_perm.mode, &(((struct semid_ds32 *)A(pad))->sem_perm.mode))) {
err = -EFAULT;
goto out;
}
/* Fall through */
case SEM_STAT:
case IPC_STAT:
fourth.__pad = &s;
break;
}
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_semctl (first, second, third, fourth);
set_fs (old_fs);
switch (third) {
case SEM_STAT:
case IPC_STAT:
if (put_user (s.sem_perm.key, &(((struct semid_ds32 *)A(pad))->sem_perm.key)) ||
__put_user (s.sem_perm.uid, &(((struct semid_ds32 *)A(pad))->sem_perm.uid)) ||
__put_user (s.sem_perm.gid, &(((struct semid_ds32 *)A(pad))->sem_perm.gid)) ||
__put_user (s.sem_perm.cuid, &(((struct semid_ds32 *)A(pad))->sem_perm.cuid)) ||
__put_user (s.sem_perm.cgid, &(((struct semid_ds32 *)A(pad))->sem_perm.cgid)) ||
__put_user (s.sem_perm.mode, &(((struct semid_ds32 *)A(pad))->sem_perm.mode)) ||
__put_user (s.sem_perm.seq, &(((struct semid_ds32 *)A(pad))->sem_perm.seq)) ||
__put_user (s.sem_otime, &(((struct semid_ds32 *)A(pad))->sem_otime)) ||
__put_user (s.sem_ctime, &(((struct semid_ds32 *)A(pad))->sem_ctime)) ||
__put_user (s.sem_nsems, &(((struct semid_ds32 *)A(pad))->sem_nsems)))
err = -EFAULT;
}
goto out;
}
default:
err = -EINVAL;
goto out;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
{
struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_KERNEL);
if (!p) err = -ENOMEM;
else {
err = 0;
if (first == kerneld_msqid) {
*(int *)p->mtext = 0;
if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
__copy_from_user(&p->mtext[4], &(((struct msgbuf32 *)A(ptr))->mtext[0]), 4) ||
__copy_from_user(&p->mtext[8], &(((struct msgbuf32 *)A(ptr))->mtext[4]), second-4))
err = -EFAULT;
else
second += 4;
} else {
if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
__copy_from_user(p->mtext, &(((struct msgbuf32 *)A(ptr))->mtext), second))
err = -EFAULT;
}
if (!err) {
mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_msgsnd (first, p, second, third);
set_fs (old_fs);
}
kfree (p);
}
}
goto out;
case MSGRCV:
{
struct msgbuf *p;
mm_segment_t old_fs;
long msgtyp = fifth;
if (!version) {
struct ipc_kludge tmp;
err = -EINVAL;
if (!ptr)
goto out;
err = -EFAULT;
if(copy_from_user(&tmp,(struct ipc_kludge *)A(ptr), sizeof (tmp)))
goto out;
ptr = tmp.msgp;
msgtyp = tmp.msgtyp;
}
p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_KERNEL);
if (!p) {
err = -EFAULT;
goto out;
}
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_msgrcv (first, p, second + 4, msgtyp, third);
set_fs (old_fs);
if (err < 0)
goto out;
if (first == kerneld_msqid) {
if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
__copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext[0]), &p->mtext[4], 4) ||
__copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext[4]), &p->mtext[8], err-8))
err = -EFAULT;
else
err -= 4;
} else {
if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
__copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext), p->mtext, err))
err = -EFAULT;
}
kfree (p);
goto out;
}
case MSGGET:
err = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL:
{
struct msqid_ds m;
mm_segment_t old_fs;
switch (second) {
case IPC_INFO:
case MSG_INFO:
/* struct msginfo is the same */
case IPC_RMID:
/* and this doesn't care about ptr */
err = sys_msgctl (first, second, (struct msqid_ds *)A(ptr));
goto out;
case IPC_SET:
if (get_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
__get_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
__get_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
__get_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes))) {
err = -EFAULT;
goto out;
}
default:
break;
}
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_msgctl (first, second, &m);
set_fs (old_fs);
switch (second) {
case MSG_STAT:
case IPC_STAT:
if (put_user (m.msg_perm.key, &(((struct msqid_ds32 *)A(ptr))->msg_perm.key)) ||
__put_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
__put_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
__put_user (m.msg_perm.cuid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cuid)) ||
__put_user (m.msg_perm.cgid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cgid)) ||
__put_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
__put_user (m.msg_perm.seq, &(((struct msqid_ds32 *)A(ptr))->msg_perm.seq)) ||
__put_user (m.msg_stime, &(((struct msqid_ds32 *)A(ptr))->msg_stime)) ||
__put_user (m.msg_rtime, &(((struct msqid_ds32 *)A(ptr))->msg_rtime)) ||
__put_user (m.msg_ctime, &(((struct msqid_ds32 *)A(ptr))->msg_ctime)) ||
__put_user (m.msg_cbytes, &(((struct msqid_ds32 *)A(ptr))->msg_cbytes)) ||
__put_user (m.msg_qnum, &(((struct msqid_ds32 *)A(ptr))->msg_qnum)) ||
__put_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes)) ||
__put_user (m.msg_lspid, &(((struct msqid_ds32 *)A(ptr))->msg_lspid)) ||
__put_user (m.msg_lrpid, &(((struct msqid_ds32 *)A(ptr))->msg_lrpid)))
err = -EFAULT;
break;
default:
break;
}
}
goto out;
default:
err = -EINVAL;
goto out;
}
if (call <= SHMCTL)
switch (call) {
case SHMAT:
switch (version) {
case 0: default: {
unsigned long raddr;
u32 *uptr = (u32 *) A(((u32)third));
err = sys_shmat (first, (char *)A(ptr), second, &raddr);
if (err)
goto out;
err = -EFAULT;
if(put_user (raddr, uptr))
goto out;
err = 0;
goto out;
}
case 1: /* If iBCS2 should ever run, then for sure in 64bit mode, not 32bit... */
err = -EINVAL;
goto out;
}
case SHMDT:
err = sys_shmdt ((char *)A(ptr));
goto out;
case SHMGET:
err = sys_shmget (first, second, third);
goto out;
case SHMCTL:
{
struct shmid_ds s;
mm_segment_t old_fs;
switch (second) {
case IPC_INFO:
/* struct shminfo is the same */
case SHM_LOCK:
case SHM_UNLOCK:
case IPC_RMID:
/* and these three aren't using ptr at all */
err = sys_shmctl (first, second, (struct shmid_ds *)A(ptr));
goto out;
case IPC_SET:
if (get_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
__get_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
__get_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode))) {
err = -EFAULT;
goto out;
}
default:
break;
}
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_shmctl (first, second, &s);
set_fs (old_fs);
switch (second) {
case SHM_INFO:
{
struct shm_info32 { int used_ids; u32 shm_tot; u32 shm_rss; u32 shm_swp; u32 swap_attempts; u32 swap_successes; };
struct shm_info *si = (struct shm_info *)&s;
if (put_user (si->used_ids, &(((struct shm_info32 *)A(ptr))->used_ids)) ||
__put_user (si->shm_tot, &(((struct shm_info32 *)A(ptr))->shm_tot)) ||
__put_user (si->shm_rss, &(((struct shm_info32 *)A(ptr))->shm_rss)) ||
__put_user (si->shm_swp, &(((struct shm_info32 *)A(ptr))->shm_swp)) ||
__put_user (si->swap_attempts, &(((struct shm_info32 *)A(ptr))->swap_attempts)) ||
__put_user (si->swap_successes, &(((struct shm_info32 *)A(ptr))->swap_successes)))
err = -EFAULT;
}
break;
case SHM_STAT:
case IPC_STAT:
if (put_user (s.shm_perm.key, &(((struct shmid_ds32 *)A(ptr))->shm_perm.key)) ||
__put_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
__put_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
__put_user (s.shm_perm.cuid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cuid)) ||
__put_user (s.shm_perm.cgid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cgid)) ||
__put_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode)) ||
__put_user (s.shm_perm.seq, &(((struct shmid_ds32 *)A(ptr))->shm_perm.seq)) ||
__put_user (s.shm_atime, &(((struct shmid_ds32 *)A(ptr))->shm_atime)) ||
__put_user (s.shm_dtime, &(((struct shmid_ds32 *)A(ptr))->shm_dtime)) ||
__put_user (s.shm_ctime, &(((struct shmid_ds32 *)A(ptr))->shm_ctime)) ||
__put_user (s.shm_segsz, &(((struct shmid_ds32 *)A(ptr))->shm_segsz)) ||
__put_user (s.shm_nattch, &(((struct shmid_ds32 *)A(ptr))->shm_nattch)) ||
__put_user (s.shm_lpid, &(((struct shmid_ds32 *)A(ptr))->shm_cpid)) ||
__put_user (s.shm_cpid, &(((struct shmid_ds32 *)A(ptr))->shm_lpid)))
err = -EFAULT;
break;
default:
break;
}
}
goto out;
default:
err = -EINVAL;
goto out;
}
err = -EINVAL;
out:
unlock_kernel();
return err;
}
Generated by GNU enscript 1.6.4.