patch-2.1.38 linux/arch/sparc64/kernel/sys_sparc32.c
Next file: linux/arch/sparc64/lib/checksum.S
Previous file: linux/arch/sparc64/kernel/sparcelf32.c
Back to the patch index
Back to the overall index
- Lines: 390
- Date:
Wed May 14 15:01:21 1997
- Orig file:
v2.1.37/linux/arch/sparc64/kernel/sys_sparc32.c
- Orig date:
Wed Apr 23 19:01:16 1997
diff -u --recursive --new-file v2.1.37/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.9 1997/04/21 08:34:24 jj Exp $
+/* $Id: sys_sparc32.c,v 1.12 1997/05/14 14:50:58 jj Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -27,6 +27,7 @@
#include <linux/nfs_fs.h>
#include <linux/smb_fs.h>
#include <linux/ncp_fs.h>
+#include <linux/quota.h>
#include <asm/types.h>
#include <asm/poll.h>
@@ -138,6 +139,10 @@
extern asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags);
extern asmlinkage int sys_socketcall(int call, unsigned long *args);
extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp);
+extern asmlinkage int sys_listen(int fd, int backlog);
+extern asmlinkage int sys_socket(int family, int type, int protocol);
+extern asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2]);
+extern asmlinkage int sys_shutdown(int fd, int how);
asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
{
@@ -157,6 +162,17 @@
unsigned short seq;
};
+struct semid_ds32 {
+ struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */
+ __kernel_time_t32 sem_otime; /* last semop time */
+ __kernel_time_t32 sem_ctime; /* last change time */
+ u32 sem_base; /* ptr to first semaphore in array */
+ u32 sem_pending; /* pending operations to be processed */
+ u32 sem_pending_last; /* last pending operation */
+ u32 undo; /* undo requests on this array */
+ unsigned short sem_nsems; /* no. of semaphores in array */
+};
+
struct msqid_ds32
{
struct ipc_perm32 msg_perm;
@@ -212,15 +228,62 @@
err = sys_semget (first, second, third);
goto out;
case SEMCTL: {
- /* XXX union semun32 to union semun64 and back conversion */
union semun fourth;
+ void *pad;
+ unsigned long old_fs;
+ struct semid_ds s;
+
err = -EINVAL;
if (!ptr)
goto out;
err = -EFAULT;
- if(get_user(fourth.__pad, (void **)A(ptr)))
+ 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:
@@ -534,10 +597,50 @@
return sys_rename((const char *)A(oldname), (const char *)A(newname));
}
-/* XXX: Play with the addr, it will be ugly :(( */
+struct dqblk32 {
+ __u32 dqb_bhardlimit;
+ __u32 dqb_bsoftlimit;
+ __u32 dqb_curblocks;
+ __u32 dqb_ihardlimit;
+ __u32 dqb_isoftlimit;
+ __u32 dqb_curinodes;
+ __kernel_time_t32 dqb_btime;
+ __kernel_time_t32 dqb_itime;
+};
+
asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr)
{
- return sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr));
+ int cmds = cmd >> SUBCMDSHIFT;
+ int err;
+ struct dqblk d;
+ unsigned long old_fs;
+
+ switch (cmds) {
+ case Q_GETQUOTA:
+ break;
+ case Q_SETQUOTA:
+ case Q_SETUSE:
+ case Q_SETQLIM:
+ if (copy_from_user (&d, (struct dqblk32 *)A(addr), sizeof (struct dqblk32)))
+ return -EFAULT;
+ d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
+ d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
+ break;
+ default:
+ return sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr));
+ }
+ old_fs = get_fs ();
+ set_fs (KERNEL_DS);
+ err = sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr));
+ set_fs (old_fs);
+ if (cmds == Q_GETQUOTA) {
+ __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
+ ((struct dqblk32 *)&d)->dqb_itime = i;
+ ((struct dqblk32 *)&d)->dqb_btime = b;
+ if (copy_to_user ((struct dqblk32 *)A(addr), &d, sizeof (struct dqblk32)))
+ return -EFAULT;
+ }
+ return err;
}
static int put_statfs (u32 buf, struct statfs *s)
@@ -1599,20 +1702,224 @@
return sys_getsockopt(fd, level, optname, (char *)A(optval), (int *)A(optlen));
}
-/* Continue here */
+struct msghdr32 {
+ u32 msg_name;
+ int msg_namelen;
+ u32 msg_iov;
+ __kernel_size_t32 msg_iovlen;
+ u32 msg_control;
+ __kernel_size_t32 msg_controllen;
+ unsigned msg_flags;
+};
+
+struct cmsghdr32 {
+ __kernel_size_t32 cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+ unsigned char cmsg_data[0];
+};
+
asmlinkage int sys32_sendmsg(int fd, u32 msg, unsigned flags)
{
- return sys_sendmsg(fd, (struct msghdr *)A(msg), flags);
+ struct msghdr m;
+ int count;
+ struct iovec *v;
+ struct iovec vf[UIO_FASTIOV];
+ u32 i, vector;
+ long ret;
+ unsigned long old_fs;
+
+ if (get_user ((long)m.msg_name, &(((struct msghdr32 *)A(msg))->msg_name)) ||
+ __get_user (m.msg_namelen, &(((struct msghdr32 *)A(msg))->msg_namelen)) ||
+ __get_user (vector, &(((struct msghdr32 *)A(msg))->msg_iov)) ||
+ __get_user (m.msg_iovlen, &(((struct msghdr32 *)A(msg))->msg_iovlen)) ||
+ __get_user ((long)m.msg_control, &(((struct msghdr32 *)A(msg))->msg_control)) ||
+ __get_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)) ||
+ __get_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags)))
+ return -EFAULT;
+
+ count = m.msg_iovlen;
+ if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
+ if (count <= UIO_FASTIOV)
+ v = vf;
+ else {
+ lock_kernel ();
+ v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
+ if (!v) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
+ __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+
+ m.msg_iov = v;
+
+ if (m.msg_controllen) {
+ /* XXX Handle msg_control stuff... Or should that go into ip_sockglue.c etc.? */
+ }
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ ret = sys_sendmsg(fd, &m, flags);
+ set_fs (old_fs);
+out:
+ if (count > UIO_FASTIOV) {
+ kfree (v);
+ unlock_kernel ();
+ }
+ return ret;
}
asmlinkage int sys32_recvmsg(int fd, u32 msg, unsigned int flags)
{
- return sys_recvmsg(fd, (struct msghdr *)A(msg), flags);
+ struct msghdr m;
+ int count;
+ struct iovec *v;
+ struct iovec vf[UIO_FASTIOV];
+ u32 i, vector;
+ long ret;
+ unsigned long old_fs;
+
+ if (get_user ((long)m.msg_name, &(((struct msghdr32 *)A(msg))->msg_name)) ||
+ __get_user (m.msg_namelen, &(((struct msghdr32 *)A(msg))->msg_namelen)) ||
+ __get_user (vector, &(((struct msghdr32 *)A(msg))->msg_iov)) ||
+ __get_user (m.msg_iovlen, &(((struct msghdr32 *)A(msg))->msg_iovlen)) ||
+ __get_user ((long)m.msg_control, &(((struct msghdr32 *)A(msg))->msg_control)) ||
+ __get_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)) ||
+ __get_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags)))
+ return -EFAULT;
+
+ count = m.msg_iovlen;
+ if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
+ if (count <= UIO_FASTIOV)
+ v = vf;
+ else {
+ lock_kernel ();
+ v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
+ if (!v) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
+ __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+
+ m.msg_iov = v;
+
+ if (m.msg_controllen) {
+ /* XXX Handle msg_control stuff... Or should that go into ip_sockglue.c etc.? */
+ }
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ ret = sys_recvmsg(fd, &m, flags);
+ set_fs (old_fs);
+ if (ret >= 0) {
+ /* XXX Handle msg_control stuff... */
+ if (put_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags)) ||
+ __put_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)))
+ return -EFAULT;
+ }
+out:
+ if (count > UIO_FASTIOV) {
+ kfree (v);
+ unlock_kernel ();
+ }
+ return ret;
}
asmlinkage int sys32_socketcall(int call, u32 args)
{
- return sys_socketcall(call, (unsigned long *)A(args));
+ static unsigned char nargs[18]={0,3,3,3,2,3,3,3,
+ 4,4,4,6,6,2,5,5,3,3};
+ u32 a[6];
+ u32 a0,a1;
+ int err = -EINVAL;
+ int i;
+
+ lock_kernel();
+ if(call<1||call>SYS_RECVMSG)
+ goto out;
+ err = -EFAULT;
+
+ for (i = 0; i < nargs[call]; i++, args += sizeof (u32))
+ if (get_user(a[i], (u32 *)A(args)))
+ goto out;
+
+ a0=a[0];
+ a1=a[1];
+
+ switch(call)
+ {
+ case SYS_SOCKET:
+ err = sys_socket(a0, a1, a[2]);
+ break;
+ case SYS_BIND:
+ err = sys32_bind(a0, a1, a[2]);
+ break;
+ case SYS_CONNECT:
+ err = sys32_connect(a0, a1, a[2]);
+ break;
+ case SYS_LISTEN:
+ err = sys_listen(a0, a1);
+ break;
+ case SYS_ACCEPT:
+ err = sys32_accept(a0, a1, a[2]);
+ break;
+ case SYS_GETSOCKNAME:
+ err = sys32_getsockname(a0, a1, a[2]);
+ break;
+ case SYS_GETPEERNAME:
+ err = sys32_getpeername(a0, a1, a[2]);
+ break;
+ case SYS_SOCKETPAIR:
+ err = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+ break;
+ case SYS_SEND:
+ err = sys32_send(a0, a1, a[2], a[3]);
+ break;
+ case SYS_SENDTO:
+ err = sys32_sendto(a0, a1, a[2], a[3], a[4], a[5]);
+ break;
+ case SYS_RECV:
+ err = sys32_recv(a0, a1, a[2], a[3]);
+ break;
+ case SYS_RECVFROM:
+ err = sys32_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
+ break;
+ case SYS_SHUTDOWN:
+ err = sys_shutdown(a0,a1);
+ break;
+ case SYS_SETSOCKOPT:
+ err = sys32_setsockopt(a0, a1, a[2], a[3], a[4]);
+ break;
+ case SYS_GETSOCKOPT:
+ err = sys32_getsockopt(a0, a1, a[2], a[3], a[4]);
+ break;
+ case SYS_SENDMSG:
+ err = sys32_sendmsg(a0, a1, a[2]);
+ break;
+ case SYS_RECVMSG:
+ err = sys32_recvmsg(a0, a1, a[2]);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+out:
+ unlock_kernel();
+ return err;
}
extern void check_pending(int signum);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov