summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/solaris
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
commit78c388aed2b7184182c08428db1de6c872d815f5 (patch)
tree4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /arch/sparc64/solaris
parenteb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff)
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'arch/sparc64/solaris')
-rw-r--r--arch/sparc64/solaris/Makefile6
-rw-r--r--arch/sparc64/solaris/conv.h17
-rw-r--r--arch/sparc64/solaris/fs.c299
-rw-r--r--arch/sparc64/solaris/misc.c354
-rw-r--r--arch/sparc64/solaris/socket.c463
-rw-r--r--arch/sparc64/solaris/socksys.c2
-rw-r--r--arch/sparc64/solaris/systbl.S76
7 files changed, 1087 insertions, 130 deletions
diff --git a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile
index 691601a3e..5e5a6aff8 100644
--- a/arch/sparc64/solaris/Makefile
+++ b/arch/sparc64/solaris/Makefile
@@ -8,17 +8,17 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := solaris.o
-O_OBJS := entry64.o fs.o misc.o signal.o systbl.o ioctl.o ipc.o socksys.o timod.o
+O_OBJS := entry64.o fs.o misc.o signal.o systbl.o socket.o ioctl.o ipc.o socksys.o timod.o
ifeq ($(CONFIG_SOLARIS_EMUL),m)
M_OBJS := $(O_TARGET)
CPPFLAGS = $(MODFLAGS)
endif
.S.s:
- $(CPP) -D__ASSEMBLY__ $(CPPFLAGS) -ansi $< -o $*.s
+ $(CPP) -D__ASSEMBLY__ $(AFLAGS) $(CPPFLAGS) -ansi $< -o $*.s
.S.o:
- $(CC) -D__ASSEMBLY__ $(CPPFLAGS) -ansi -c $< -o $*.o
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) $(CPPFLAGS) -ansi -c $< -o $*.o
ifneq ($(CONFIG_SOLARIS_EMUL),y)
do_it_all:
diff --git a/arch/sparc64/solaris/conv.h b/arch/sparc64/solaris/conv.h
index fa716f595..1cb3c9018 100644
--- a/arch/sparc64/solaris/conv.h
+++ b/arch/sparc64/solaris/conv.h
@@ -1,4 +1,4 @@
-/* $Id: conv.h,v 1.3 1998/03/26 08:46:13 jj Exp $
+/* $Id: conv.h,v 1.4 1998/08/15 20:42:51 davem Exp $
* conv.h: Utility macros for Solaris emulation
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -11,13 +11,14 @@
#include <asm/unistd.h>
-/* As gcc will warn about casting u32 to some ptr, we have to cast it to
- * unsigned long first, and that's what is A() for.
- * You just do (void *)A(x), instead of having to
- * type (void *)((unsigned long)x) or instead of just (void *)x, which will
- * produce warnings.
- */
-#define A(x) ((unsigned long)x)
+/* Use this to get at 32-bit user passed pointers. */
+#define A(__x) \
+({ unsigned long __ret; \
+ __asm__ ("srl %0, 0, %0" \
+ : "=r" (__ret) \
+ : "0" (__x)); \
+ __ret; \
+})
extern unsigned sys_call_table[];
extern unsigned sys_call_table32[];
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 3980f1d67..3631d43b2 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -1,7 +1,7 @@
-/* $Id: fs.c,v 1.10 1998/05/09 06:15:45 davem Exp $
+/* $Id: fs.c,v 1.11 1998/10/28 08:12:04 jj Exp $
* fs.c: fs related syscall emulation for Solaris
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
#include <linux/types.h>
@@ -55,6 +55,26 @@ struct sol_stat {
s32 st_pad4[8]; /* expansion area */
};
+struct sol_stat64 {
+ u32 st_dev;
+ s32 st_pad1[3]; /* network id */
+ u64 st_ino;
+ u32 st_mode;
+ u32 st_nlink;
+ u32 st_uid;
+ u32 st_gid;
+ u32 st_rdev;
+ s32 st_pad2[2];
+ s64 st_size;
+ timestruct_t st_atime;
+ timestruct_t st_mtime;
+ timestruct_t st_ctime;
+ s64 st_blksize;
+ s32 st_blocks;
+ char st_fstype[16];
+ s32 st_pad4[4]; /* expansion area */
+};
+
#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
@@ -80,6 +100,29 @@ static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
return 0;
}
+static inline int putstat64(struct sol_stat64 *ubuf, struct stat *kbuf)
+{
+ if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev) ||
+ __put_user (kbuf->st_ino, &ubuf->st_ino) ||
+ __put_user (kbuf->st_mode, &ubuf->st_mode) ||
+ __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
+ __put_user (kbuf->st_uid, &ubuf->st_uid) ||
+ __put_user (kbuf->st_gid, &ubuf->st_gid) ||
+ __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev) ||
+ __put_user (kbuf->st_size, &ubuf->st_size) ||
+ __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
+ __put_user (0, &ubuf->st_atime.tv_nsec) ||
+ __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
+ __put_user (0, &ubuf->st_mtime.tv_nsec) ||
+ __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
+ __put_user (0, &ubuf->st_ctime.tv_nsec) ||
+ __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
+ __put_user (kbuf->st_blocks, &ubuf->st_blocks) ||
+ __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
+ return -EFAULT;
+ return 0;
+}
+
asmlinkage int solaris_stat(u32 filename, u32 statbuf)
{
int ret;
@@ -108,6 +151,28 @@ asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf)
return solaris_stat(filename, statbuf);
}
+asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ char *filenam;
+ mm_segment_t old_fs = get_fs();
+ int (*sys_newstat)(char *,struct stat *) =
+ (int (*)(char *,struct stat *))SYS(stat);
+
+ filenam = getname32 (filename);
+ ret = PTR_ERR(filenam);
+ if (!IS_ERR(filenam)) {
+ set_fs (KERNEL_DS);
+ ret = sys_newstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
+ return -EFAULT;
+ }
+ return ret;
+}
+
asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
{
int ret;
@@ -135,6 +200,28 @@ asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf)
return solaris_lstat(filename, statbuf);
}
+asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ char *filenam;
+ mm_segment_t old_fs = get_fs();
+ int (*sys_newlstat)(char *,struct stat *) =
+ (int (*)(char *,struct stat *))SYS(lstat);
+
+ filenam = getname32 (filename);
+ ret = PTR_ERR(filenam);
+ if (!IS_ERR(filenam)) {
+ set_fs (KERNEL_DS);
+ ret = sys_newlstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
+ return -EFAULT;
+ }
+ return ret;
+}
+
asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
{
int ret;
@@ -156,6 +243,22 @@ asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf)
return solaris_fstat(fd, statbuf);
}
+asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ mm_segment_t old_fs = get_fs();
+ int (*sys_newfstat)(unsigned,struct stat *) =
+ (int (*)(unsigned,struct stat *))SYS(fstat);
+
+ set_fs (KERNEL_DS);
+ ret = sys_newfstat(fd, &s);
+ set_fs (old_fs);
+ if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
+ return -EFAULT;
+ return ret;
+}
+
asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev)
{
int (*sys_mknod)(const char *,int,dev_t) =
@@ -172,6 +275,14 @@ asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev)
return solaris_mknod(path, mode, dev);
}
+asmlinkage int solaris_getdents64(unsigned int fd, void *dirent, unsigned int count)
+{
+ int (*sys_getdents)(unsigned int, void *, unsigned int) =
+ (int (*)(unsigned int, void *, unsigned int))SYS(getdents);
+
+ return sys_getdents(fd, dirent, count);
+}
+
/* This statfs thingie probably will go in the near future, but... */
struct sol_statfs {
@@ -276,6 +387,23 @@ struct sol_statvfs {
u32 f_filler[16];
};
+struct sol_statvfs64 {
+ u32 f_bsize;
+ u32 f_frsize;
+ u64 f_blocks;
+ u64 f_bfree;
+ u64 f_bavail;
+ u64 f_files;
+ u64 f_ffree;
+ u64 f_favail;
+ u32 f_fsid;
+ char f_basetype[16];
+ u32 f_flag;
+ u32 f_namemax;
+ char f_fstr[32];
+ u32 f_filler[16];
+};
+
static int report_statvfs(struct inode *inode, u32 buf)
{
struct statfs s;
@@ -313,6 +441,43 @@ static int report_statvfs(struct inode *inode, u32 buf)
return error;
}
+static int report_statvfs64(struct inode *inode, u32 buf)
+{
+ struct statfs s;
+ mm_segment_t old_fs = get_fs();
+ int error;
+ struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf);
+
+ set_fs (KERNEL_DS);
+ error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs));
+ set_fs (old_fs);
+ if (!error) {
+ const char *p = inode->i_sb->s_type->name;
+ int i = 0;
+ int j = strlen (p);
+
+ if (j > 15) j = 15;
+ if (IS_RDONLY(inode)) i = 1;
+ if (IS_NOSUID(inode)) i |= 2;
+ if (put_user (s.f_bsize, &ss->f_bsize) ||
+ __put_user (0, &ss->f_frsize) ||
+ __put_user (s.f_blocks, &ss->f_blocks) ||
+ __put_user (s.f_bfree, &ss->f_bfree) ||
+ __put_user (s.f_bavail, &ss->f_bavail) ||
+ __put_user (s.f_files, &ss->f_files) ||
+ __put_user (s.f_ffree, &ss->f_ffree) ||
+ __put_user (s.f_ffree, &ss->f_favail) ||
+ __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
+ __copy_to_user (ss->f_basetype,p,j) ||
+ __put_user (0, (char *)&ss->f_basetype[j]) ||
+ __put_user (s.f_namelen, &ss->f_namemax) ||
+ __put_user (i, &ss->f_flag) ||
+ __clear_user (&ss->f_fstr, 32))
+ return -EFAULT;
+ }
+ return error;
+}
+
asmlinkage int solaris_statvfs(u32 path, u32 buf)
{
struct dentry * dentry;
@@ -362,12 +527,62 @@ out:
return error;
}
+asmlinkage int solaris_statvfs64(u32 path, u32 buf)
+{
+ struct dentry * dentry;
+ int error;
+
+ lock_kernel();
+ dentry = namei((const char *)A(path));
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+
+ error = -ENOSYS;
+ if (inode->i_sb->s_op->statfs)
+ error = report_statvfs64(inode, buf);
+ dput(dentry);
+ }
+ unlock_kernel();
+ return error;
+}
+
+asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
+{
+ struct inode * inode;
+ struct dentry * dentry;
+ struct file * file;
+ int error;
+
+ lock_kernel();
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ if (!(dentry = file->f_dentry))
+ error = -ENOENT;
+ else if (!(inode = dentry->d_inode))
+ error = -ENOENT;
+ else if (!inode->i_sb)
+ error = -ENODEV;
+ else if (!inode->i_sb->s_op->statfs)
+ error = -ENOSYS;
+ else
+ error = report_statvfs64(inode, buf);
+ fput(file);
+out:
+ unlock_kernel();
+ return error;
+}
+
asmlinkage int solaris_open(u32 filename, int flags, u32 mode)
{
int (*sys_open)(const char *,int,int) =
(int (*)(const char *,int,int))SYS(open);
int fl = flags & 0xf;
-
+
+/* if (flags & 0x2000) - allow LFS */
if (flags & 0x8050) fl |= O_SYNC;
if (flags & 0x80) fl |= O_NONBLOCK;
if (flags & 0x100) fl |= O_CREAT;
@@ -558,78 +773,20 @@ asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp)
return -ENOSYS;
}
-asmlinkage int solaris_pread(int fd, u32 buf, u32 nbyte, s32 offset)
+asmlinkage int solaris_pread(unsigned int fd, char *buf, u32 count, u32 pos)
{
- off_t temp;
- int retval;
- struct file * file;
- long (*sys_read)(unsigned int, char *, unsigned long) =
- (long (*)(unsigned int, char *, unsigned long))SYS(read);
- long (*sys_lseek)(unsigned int, off_t, unsigned int) =
- (long (*)(unsigned int, off_t, unsigned int))SYS(lseek);
-
- lock_kernel();
- retval = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad;
-
- temp = file->f_pos;
- if (temp != offset) {
- retval = sys_lseek(fd, offset, 0);
- if (retval < 0)
- goto out_putf;
- }
- retval = sys_read(fd, (char *)A(buf), nbyte);
- if (file->f_pos != temp) {
- if (!retval)
- retval = sys_lseek(fd, temp, 0);
- else
- sys_lseek(fd, temp, 0);
- }
-
-out_putf:
- fput(file);
-bad:
- unlock_kernel();
- return retval;
+ ssize_t (*sys_pread)(unsigned int, char *, size_t, loff_t) =
+ (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pread);
+
+ return sys_pread(fd, buf, count, (loff_t)pos);
}
-asmlinkage int solaris_pwrite(int fd, u32 buf, u32 nbyte, s32 offset)
+asmlinkage int solaris_pwrite(unsigned int fd, char *buf, u32 count, u32 pos)
{
- off_t temp;
- int retval;
- struct file * file;
- long (*sys_write)(unsigned int, char *, unsigned long) =
- (long (*)(unsigned int, char *, unsigned long))SYS(read);
- long (*sys_lseek)(unsigned int, off_t, unsigned int) =
- (long (*)(unsigned int, off_t, unsigned int))SYS(lseek);
-
- lock_kernel();
- retval = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad;
-
- temp = file->f_pos;
- if (temp != offset) {
- retval = sys_lseek(fd, offset, 0);
- if (retval < 0)
- goto out_putf;
- }
- retval = sys_write(fd, (char *)A(buf), nbyte);
- if (file->f_pos != temp) {
- if (!retval)
- retval = sys_lseek(fd, temp, 0);
- else
- sys_lseek(fd, temp, 0);
- }
-
-out_putf:
- fput(file);
-bad:
- unlock_kernel();
- return retval;
+ ssize_t (*sys_pwrite)(unsigned int, char *, size_t, loff_t) =
+ (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pwrite);
+
+ return sys_pwrite(fd, buf, count, (loff_t)pos);
}
/* POSIX.1 names */
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 8e0ce81da..c29b79f68 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -1,7 +1,7 @@
-/* $Id: misc.c,v 1.12 1998/06/16 04:37:08 davem Exp $
+/* $Id: misc.c,v 1.13 1998/10/28 08:11:58 jj Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
#include <linux/module.h>
@@ -11,6 +11,9 @@
#include <linux/limits.h>
#include <linux/mm.h>
#include <linux/smp.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/timex.h>
#include <asm/uaccess.h>
#include <asm/string.h>
@@ -43,16 +46,86 @@ int solaris_err_table[] = {
/* 120 */ 22, 22, 88, 86, 85, 22, 22,
};
+#define SOLARIS_NR_OPEN 256
+
+static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off)
+{
+ struct file *file = NULL;
+ unsigned long retval, ret_type;
+
+ lock_kernel();
+ current->personality |= PER_SVR4;
+ if (flags & MAP_NORESERVE) {
+ static int cnt = 0;
+
+ if (cnt < 5) {
+ printk("%s: unimplemented Solaris MAP_NORESERVE mmap() flag\n",
+ current->comm);
+ cnt++;
+ }
+ flags &= ~MAP_NORESERVE;
+ }
+ retval = -EBADF;
+ if(!(flags & MAP_ANONYMOUS)) {
+ if(fd >= SOLARIS_NR_OPEN)
+ goto out;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ if (file->f_dentry && file->f_dentry->d_inode) {
+ struct inode * inode = file->f_dentry->d_inode;
+ if(MAJOR(inode->i_rdev) == MEM_MAJOR &&
+ MINOR(inode->i_rdev) == 5) {
+ flags |= MAP_ANONYMOUS;
+ fput(file);
+ file = NULL;
+ }
+ }
+ }
+
+ retval = -ENOMEM;
+ if(!(flags & MAP_FIXED) && !addr) {
+ unsigned long attempt = get_unmapped_area(addr, len);
+ if(!attempt || (attempt >= 0xf0000000UL))
+ goto out_putf;
+ addr = (u32) attempt;
+ }
+ if(!(flags & MAP_FIXED))
+ addr = 0;
+ ret_type = flags & _MAP_NEW;
+ flags &= ~_MAP_NEW;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ retval = do_mmap(file,
+ (unsigned long) addr, (unsigned long) len,
+ (unsigned long) prot, (unsigned long) flags, off);
+ if(!ret_type)
+ retval = ((retval < 0xf0000000) ? 0 : retval);
+out_putf:
+ if (file)
+ fput(file);
+out:
+ unlock_kernel();
+ return (u32) retval;
+}
+
asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
{
- u32 (*sunos_mmap)(u32,u32,u32,u32,u32,u32) =
- (u32 (*)(u32,u32,u32,u32,u32,u32))SUNOS(71);
- u32 ret;
+ return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off);
+}
+
+asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi)
+{
+ u32 offlo;
- ret = sunos_mmap(addr,len,prot,flags,fd,off);
- /* sunos_mmap sets personality to PER_BSD */
- current->personality = PER_SVR4;
- return ret;
+ if (regs->u_regs[UREG_G1]) {
+ if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
+ return -EFAULT;
+ } else {
+ if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x60)))
+ return -EFAULT;
+ }
+ return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo);
}
asmlinkage int solaris_brk(u32 brk)
@@ -326,6 +399,18 @@ asmlinkage int solaris_sysconf(int id)
}
}
+asmlinkage int solaris_setreuid(s32 ruid, s32 euid)
+{
+ int (*sys_setreuid)(uid_t, uid_t) = (int (*)(uid_t, uid_t))SYS(setreuid);
+ return sys_setreuid(ruid, euid);
+}
+
+asmlinkage int solaris_setregid(s32 rgid, s32 egid)
+{
+ int (*sys_setregid)(gid_t, gid_t) = (int (*)(gid_t, gid_t))SYS(setregid);
+ return sys_setregid(rgid, egid);
+}
+
asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
{
int ret;
@@ -378,6 +463,257 @@ asmlinkage int solaris_gettimeofday(u32 tim)
return sys_gettimeofday((struct timeval *)(u64)tim, NULL);
}
+#define RLIM_SOL_INFINITY32 0x7fffffff
+#define RLIM_SOL_SAVED_MAX32 0x7ffffffe
+#define RLIM_SOL_SAVED_CUR32 0x7ffffffd
+#define RLIM_SOL_INFINITY ((u64)-3)
+#define RLIM_SOL_SAVED_MAX ((u64)-2)
+#define RLIM_SOL_SAVED_CUR ((u64)-1)
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+#define RLIMIT_SOL_NOFILE 5
+#define RLIMIT_SOL_VMEM 6
+
+struct rlimit32 {
+ s32 rlim_cur;
+ s32 rlim_max;
+};
+
+asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+ struct rlimit r;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &r);
+ set_fs (old_fs);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_INFINITY)
+ r.rlim_cur = RLIM_SOL_INFINITY32;
+ else if ((u64)r.rlim_cur > RLIM_SOL_INFINITY32)
+ r.rlim_cur = RLIM_SOL_SAVED_CUR32;
+ if (r.rlim_max == RLIM_INFINITY)
+ r.rlim_max = RLIM_SOL_INFINITY32;
+ else if ((u64)r.rlim_max > RLIM_SOL_INFINITY32)
+ r.rlim_max = RLIM_SOL_SAVED_MAX32;
+ ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+ ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+ }
+ return ret;
+}
+
+asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+ struct rlimit r, rold;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+ int (*sys_setrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+ __get_user (r.rlim_max, &rlim->rlim_max))
+ return -EFAULT;
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &rold);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_SOL_INFINITY32)
+ r.rlim_cur = RLIM_INFINITY;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_CUR32)
+ r.rlim_cur = rold.rlim_cur;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_MAX32)
+ r.rlim_cur = rold.rlim_max;
+ if (r.rlim_max == RLIM_SOL_INFINITY32)
+ r.rlim_max = RLIM_INFINITY;
+ else if (r.rlim_max == RLIM_SOL_SAVED_CUR32)
+ r.rlim_max = rold.rlim_cur;
+ else if (r.rlim_max == RLIM_SOL_SAVED_MAX32)
+ r.rlim_max = rold.rlim_max;
+ ret = sys_setrlimit(resource, &r);
+ }
+ set_fs (old_fs);
+ return ret;
+}
+
+asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit *rlim)
+{
+ struct rlimit r;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &r);
+ set_fs (old_fs);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_INFINITY)
+ r.rlim_cur = RLIM_SOL_INFINITY;
+ if (r.rlim_max == RLIM_INFINITY)
+ r.rlim_max = RLIM_SOL_INFINITY;
+ ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+ ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+ }
+ return ret;
+}
+
+asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit *rlim)
+{
+ struct rlimit r, rold;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+ int (*sys_setrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+ __get_user (r.rlim_max, &rlim->rlim_max))
+ return -EFAULT;
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &rold);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_SOL_INFINITY)
+ r.rlim_cur = RLIM_INFINITY;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_CUR)
+ r.rlim_cur = rold.rlim_cur;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_MAX)
+ r.rlim_cur = rold.rlim_max;
+ if (r.rlim_max == RLIM_SOL_INFINITY)
+ r.rlim_max = RLIM_INFINITY;
+ else if (r.rlim_max == RLIM_SOL_SAVED_CUR)
+ r.rlim_max = rold.rlim_cur;
+ else if (r.rlim_max == RLIM_SOL_SAVED_MAX)
+ r.rlim_max = rold.rlim_max;
+ ret = sys_setrlimit(resource, &r);
+ }
+ set_fs (old_fs);
+ return ret;
+}
+
+struct timeval32 {
+ int tv_sec, tv_usec;
+};
+
+struct sol_ntptimeval {
+ struct timeval32 time;
+ s32 maxerror;
+ s32 esterror;
+};
+
+struct sol_timex {
+ u32 modes;
+ s32 offset;
+ s32 freq;
+ s32 maxerror;
+ s32 esterror;
+ s32 status;
+ s32 constant;
+ s32 precision;
+ s32 tolerance;
+ s32 ppsfreq;
+ s32 jitter;
+ s32 shift;
+ s32 stabil;
+ s32 jitcnt;
+ s32 calcnt;
+ s32 errcnt;
+ s32 stbcnt;
+};
+
+asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval *ntp)
+{
+ int (*sys_adjtimex)(struct timex *) =
+ (int (*)(struct timex *))SYS(adjtimex);
+ struct timex t;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ t.modes = 0;
+ ret = sys_adjtimex(&t);
+ set_fs(old_fs);
+ if (ret < 0)
+ return ret;
+ ret = put_user (t.time.tv_sec, &ntp->time.tv_sec);
+ ret |= __put_user (t.time.tv_usec, &ntp->time.tv_usec);
+ ret |= __put_user (t.maxerror, &ntp->maxerror);
+ ret |= __put_user (t.esterror, &ntp->esterror);
+ return ret;
+}
+
+asmlinkage int solaris_ntp_adjtime(struct sol_timex *txp)
+{
+ int (*sys_adjtimex)(struct timex *) =
+ (int (*)(struct timex *))SYS(adjtimex);
+ struct timex t;
+ int ret, err;
+ mm_segment_t old_fs = get_fs();
+
+ ret = get_user (t.modes, &txp->modes);
+ ret |= __get_user (t.offset, &txp->offset);
+ ret |= __get_user (t.freq, &txp->freq);
+ ret |= __get_user (t.maxerror, &txp->maxerror);
+ ret |= __get_user (t.esterror, &txp->esterror);
+ ret |= __get_user (t.status, &txp->status);
+ ret |= __get_user (t.constant, &txp->constant);
+ set_fs(KERNEL_DS);
+ ret = sys_adjtimex(&t);
+ set_fs(old_fs);
+ if (ret < 0)
+ return ret;
+ err = put_user (t.offset, &txp->offset);
+ err |= __put_user (t.freq, &txp->freq);
+ err |= __put_user (t.maxerror, &txp->maxerror);
+ err |= __put_user (t.esterror, &txp->esterror);
+ err |= __put_user (t.status, &txp->status);
+ err |= __put_user (t.constant, &txp->constant);
+ err |= __put_user (t.precision, &txp->precision);
+ err |= __put_user (t.tolerance, &txp->tolerance);
+ err |= __put_user (t.ppsfreq, &txp->ppsfreq);
+ err |= __put_user (t.jitter, &txp->jitter);
+ err |= __put_user (t.shift, &txp->shift);
+ err |= __put_user (t.stabil, &txp->stabil);
+ err |= __put_user (t.jitcnt, &txp->jitcnt);
+ err |= __put_user (t.calcnt, &txp->calcnt);
+ err |= __put_user (t.errcnt, &txp->errcnt);
+ err |= __put_user (t.stbcnt, &txp->stbcnt);
+ if (err)
+ return -EFAULT;
+ return ret;
+}
+
asmlinkage int do_sol_unimplemented(struct pt_regs *regs)
{
printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n",
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
new file mode 100644
index 000000000..4b3f18fc1
--- /dev/null
+++ b/arch/sparc64/solaris/socket.c
@@ -0,0 +1,463 @@
+/* $Id: socket.c,v 1.1 1998/10/28 08:12:11 jj Exp $
+ * socket.c: Socket syscall emulation for Solaris 2.6+
+ *
+ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <linux/types.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/socket.h>
+#include <linux/file.h>
+
+#include <asm/uaccess.h>
+#include <asm/string.h>
+#include <asm/oplib.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+
+#include "conv.h"
+
+#define SOCK_SOL_STREAM 2
+#define SOCK_SOL_DGRAM 1
+#define SOCK_SOL_RAW 4
+#define SOCK_SOL_RDM 5
+#define SOCK_SOL_SEQPACKET 6
+
+static int socket_check(int family, int type)
+{
+ if (family != PF_UNIX && family != PF_INET)
+ return -ESOCKTNOSUPPORT;
+ switch (type) {
+ case SOCK_SOL_STREAM: type = SOCK_STREAM; break;
+ case SOCK_SOL_DGRAM: type = SOCK_DGRAM; break;
+ case SOCK_SOL_RAW: type = SOCK_RAW; break;
+ case SOCK_SOL_RDM: type = SOCK_RDM; break;
+ case SOCK_SOL_SEQPACKET: type = SOCK_SEQPACKET; break;
+ default: return -EINVAL;
+ }
+ return type;
+}
+
+asmlinkage int solaris_socket(int family, int type, int protocol)
+{
+ int (*sys_socket)(int, int, int) =
+ (int (*)(int, int, int))SYS(socket);
+
+ type = socket_check (family, type);
+ if (type < 0) return type;
+ return sys_socket(family, type, protocol);
+}
+
+asmlinkage int solaris_socketpair(int family, int type, int protocol, int *usockvec)
+{
+ int (*sys_socketpair)(int, int, int, int *) =
+ (int (*)(int, int, int, int *))SYS(socketpair);
+
+ type = socket_check (family, type);
+ if (type < 0) return type;
+ return sys_socketpair(family, type, protocol, usockvec);
+}
+
+asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen)
+{
+ int (*sys_bind)(int, struct sockaddr *, int) =
+ (int (*)(int, struct sockaddr *, int))SUNOS(104);
+
+ return sys_bind(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int optlen)
+{
+ int (*sunos_setsockopt)(int, int, int, u32, int) =
+ (int (*)(int, int, int, u32, int))SUNOS(105);
+
+ return sunos_setsockopt(fd, level, optname, optval, optlen);
+}
+
+asmlinkage int solaris_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen)
+{
+ int (*sunos_getsockopt)(int, int, int, u32, u32) =
+ (int (*)(int, int, int, u32, u32))SUNOS(118);
+
+ return sunos_getsockopt(fd, level, optname, optval, optlen);
+}
+
+asmlinkage int solaris_connect(int fd, struct sockaddr *addr, int addrlen)
+{
+ int (*sys_connect)(int, struct sockaddr *, int) =
+ (int (*)(int, struct sockaddr *, int))SYS(connect);
+
+ return sys_connect(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_accept(int fd, struct sockaddr *addr, int *addrlen)
+{
+ int (*sys_accept)(int, struct sockaddr *, int *) =
+ (int (*)(int, struct sockaddr *, int *))SYS(accept);
+
+ return sys_accept(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_listen(int fd, int backlog)
+{
+ int (*sys_listen)(int, int) =
+ (int (*)(int, int))SUNOS(106);
+
+ return sys_listen(fd, backlog);
+}
+
+asmlinkage int solaris_shutdown(int fd, int how)
+{
+ int (*sys_shutdown)(int, int) =
+ (int (*)(int, int))SYS(shutdown);
+
+ return sys_shutdown(fd, how);
+}
+
+#define MSG_SOL_OOB 0x1
+#define MSG_SOL_PEEK 0x2
+#define MSG_SOL_DONTROUTE 0x4
+#define MSG_SOL_EOR 0x8
+#define MSG_SOL_CTRUNC 0x10
+#define MSG_SOL_TRUNC 0x20
+#define MSG_SOL_WAITALL 0x40
+#define MSG_SOL_DONTWAIT 0x80
+
+static int solaris_to_linux_msgflags(int flags)
+{
+ int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+
+ if (flags & MSG_SOL_EOR) fl |= MSG_EOR;
+ if (flags & MSG_SOL_CTRUNC) fl |= MSG_CTRUNC;
+ if (flags & MSG_SOL_TRUNC) fl |= MSG_TRUNC;
+ if (flags & MSG_SOL_WAITALL) fl |= MSG_WAITALL;
+ if (flags & MSG_SOL_DONTWAIT) fl |= MSG_DONTWAIT;
+ return fl;
+}
+
+static int linux_to_solaris_msgflags(int flags)
+{
+ int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+
+ if (flags & MSG_EOR) fl |= MSG_SOL_EOR;
+ if (flags & MSG_CTRUNC) fl |= MSG_SOL_CTRUNC;
+ if (flags & MSG_TRUNC) fl |= MSG_SOL_TRUNC;
+ if (flags & MSG_WAITALL) fl |= MSG_SOL_WAITALL;
+ if (flags & MSG_DONTWAIT) fl |= MSG_SOL_DONTWAIT;
+ return fl;
+}
+
+asmlinkage int solaris_recvfrom(int s, char *buf, int len, int flags, u32 from, u32 fromlen)
+{
+ int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);
+
+ return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), (struct sockaddr *)A(from), (int *)A(fromlen));
+}
+
+asmlinkage int solaris_recv(int s, char *buf, int len, int flags)
+{
+ int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);
+
+ return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+}
+
+asmlinkage int solaris_sendto(int s, char *buf, int len, int flags, u32 to, u32 tolen)
+{
+ int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto);
+
+ return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), (struct sockaddr *)A(to), (int *)A(tolen));
+}
+
+asmlinkage int solaris_send(int s, char *buf, int len, int flags)
+{
+ int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto);
+
+ return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+}
+
+asmlinkage int solaris_getpeername(int fd, struct sockaddr *addr, int *addrlen)
+{
+ int (*sys_getpeername)(int, struct sockaddr *, int *) =
+ (int (*)(int, struct sockaddr *, int *))SYS(getpeername);
+
+ return sys_getpeername(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_getsockname(int fd, struct sockaddr *addr, int *addrlen)
+{
+ int (*sys_getsockname)(int, struct sockaddr *, int *) =
+ (int (*)(int, struct sockaddr *, int *))SYS(getsockname);
+
+ return sys_getsockname(fd, addr, addrlen);
+}
+
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
+ 16 for IP, 16 for IPX,
+ 24 for IPv6,
+ about 80 for AX.25 */
+
+/* XXX These as well... */
+extern __inline__ struct socket *socki_lookup(struct inode *inode)
+{
+ return &inode->u.socket_i;
+}
+
+extern __inline__ struct socket *sockfd_lookup(int fd, int *err)
+{
+ struct file *file;
+ struct inode *inode;
+
+ if (!(file = fget(fd))) {
+ *err = -EBADF;
+ return NULL;
+ }
+
+ inode = file->f_dentry->d_inode;
+ if (!inode || !inode->i_sock || !socki_lookup(inode)) {
+ *err = -ENOTSOCK;
+ fput(file);
+ return NULL;
+ }
+
+ return socki_lookup(inode);
+}
+
+extern __inline__ void sockfd_put(struct socket *sock)
+{
+ fput(sock->file);
+}
+
+struct sol_nmsghdr {
+ u32 msg_name;
+ int msg_namelen;
+ u32 msg_iov;
+ u32 msg_iovlen;
+ u32 msg_control;
+ u32 msg_controllen;
+ u32 msg_flags;
+};
+
+struct sol_cmsghdr {
+ u32 cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+ unsigned char cmsg_data[0];
+};
+
+struct iovec32 {
+ u32 iov_base;
+ u32 iov_len;
+};
+
+static inline int iov_from_user32_to_kern(struct iovec *kiov,
+ struct iovec32 *uiov32,
+ int niov)
+{
+ int tot_len = 0;
+
+ while(niov > 0) {
+ u32 len, buf;
+
+ if(get_user(len, &uiov32->iov_len) ||
+ get_user(buf, &uiov32->iov_base)) {
+ tot_len = -EFAULT;
+ break;
+ }
+ tot_len += len;
+ kiov->iov_base = (void *)A(buf);
+ kiov->iov_len = (__kernel_size_t) len;
+ uiov32++;
+ kiov++;
+ niov--;
+ }
+ return tot_len;
+}
+
+static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
+ struct sol_nmsghdr *umsg)
+{
+ u32 tmp1, tmp2, tmp3;
+ int err;
+
+ err = get_user(tmp1, &umsg->msg_name);
+ err |= __get_user(tmp2, &umsg->msg_iov);
+ err |= __get_user(tmp3, &umsg->msg_control);
+ if (err)
+ return -EFAULT;
+
+ kmsg->msg_name = (void *)A(tmp1);
+ kmsg->msg_iov = (struct iovec *)A(tmp2);
+ kmsg->msg_control = (void *)A(tmp3);
+
+ err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+ err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+ err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+
+ kmsg->msg_flags = solaris_to_linux_msgflags(kmsg->msg_flags);
+
+ return err;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
+ char *kern_address, int mode)
+{
+ int tot_len;
+
+ if(kern_msg->msg_namelen) {
+ if(mode==VERIFY_READ) {
+ int err = move_addr_to_kernel(kern_msg->msg_name,
+ kern_msg->msg_namelen,
+ kern_address);
+ if(err < 0)
+ return err;
+ }
+ kern_msg->msg_name = kern_address;
+ } else
+ kern_msg->msg_name = NULL;
+
+ if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+ kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+ GFP_KERNEL);
+ if(!kern_iov)
+ return -ENOMEM;
+ }
+
+ tot_len = iov_from_user32_to_kern(kern_iov,
+ (struct iovec32 *)kern_msg->msg_iov,
+ kern_msg->msg_iovlen);
+ if(tot_len >= 0)
+ kern_msg->msg_iov = kern_iov;
+ else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+ kfree(kern_iov);
+
+ return tot_len;
+}
+
+asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned user_flags)
+{
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ struct iovec iov[UIO_FASTIOV];
+ unsigned char ctl[sizeof(struct cmsghdr) + 20];
+ unsigned char *ctl_buf = ctl;
+ struct msghdr kern_msg;
+ int err, total_len;
+
+ if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+ return -EFAULT;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;
+ err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+ if (err < 0)
+ goto out;
+ total_len = err;
+
+ if(kern_msg.msg_controllen) {
+ struct sol_cmsghdr *ucmsg = (struct sol_cmsghdr *)kern_msg.msg_control;
+ unsigned long *kcmsg;
+ __kernel_size_t32 cmlen;
+
+ if(kern_msg.msg_controllen > sizeof(ctl) &&
+ kern_msg.msg_controllen <= 256) {
+ err = -ENOBUFS;
+ ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
+ if(!ctl_buf)
+ goto out_freeiov;
+ }
+ __get_user(cmlen, &ucmsg->cmsg_len);
+ kcmsg = (unsigned long *) ctl_buf;
+ *kcmsg++ = (unsigned long)cmlen;
+ err = -EFAULT;
+ if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
+ kern_msg.msg_controllen - sizeof(__kernel_size_t32)))
+ goto out_freectl;
+ kern_msg.msg_control = ctl_buf;
+ }
+ kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags);
+
+ lock_kernel();
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ if (sock->file->f_flags & O_NONBLOCK)
+ kern_msg.msg_flags |= MSG_DONTWAIT;
+ err = sock_sendmsg(sock, &kern_msg, total_len);
+ sockfd_put(sock);
+ }
+ unlock_kernel();
+
+out_freectl:
+ /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
+ if(ctl_buf != ctl)
+ kfree(ctl_buf);
+out_freeiov:
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+out:
+ return err;
+}
+
+asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr *user_msg, unsigned int user_flags)
+{
+ struct iovec iovstack[UIO_FASTIOV];
+ struct msghdr kern_msg;
+ char addr[MAX_SOCK_ADDR];
+ struct socket *sock;
+ struct iovec *iov = iovstack;
+ struct sockaddr *uaddr;
+ int *uaddr_len;
+ unsigned long cmsg_ptr;
+ int err, total_len, len = 0;
+
+ if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+ return -EFAULT;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;
+
+ uaddr = kern_msg.msg_name;
+ uaddr_len = &user_msg->msg_namelen;
+ err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+ if (err < 0)
+ goto out;
+ total_len = err;
+
+ cmsg_ptr = (unsigned long) kern_msg.msg_control;
+ kern_msg.msg_flags = 0;
+
+ lock_kernel();
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ if (sock->file->f_flags & O_NONBLOCK)
+ user_flags |= MSG_DONTWAIT;
+ err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
+ if(err >= 0)
+ len = err;
+ sockfd_put(sock);
+ }
+ unlock_kernel();
+
+ if(uaddr != NULL && err >= 0)
+ err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
+ if(err >= 0) {
+ err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags);
+ if(!err) {
+ /* XXX Convert cmsg back into userspace 32-bit format... */
+ err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
+ &user_msg->msg_controllen);
+ }
+ }
+
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+out:
+ if(err < 0)
+ return err;
+ return len;
+}
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index dce7927d8..dbdbcd1a2 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.7 1998/03/29 10:11:04 davem Exp $
+/* $Id: socksys.c,v 1.8 1998/08/26 10:28:28 davem Exp $
* socksys.c: /dev/inet/ stuff for Solaris emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S
index bb18807f1..f47470e4c 100644
--- a/arch/sparc64/solaris/systbl.S
+++ b/arch/sparc64/solaris/systbl.S
@@ -1,7 +1,7 @@
-/* $Id: systbl.S,v 1.6 1998/03/26 08:46:08 jj Exp $
+/* $Id: systbl.S,v 1.7 1998/10/28 08:11:49 jj Exp $
* systbl.S: System call entry point table for Solaris compatibility.
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
*/
@@ -156,8 +156,8 @@ solaris_sys_table:
.word solaris_fxstat /* fxstat ddx 125 */
.word solaris_xmknod /* xmknod dsox 126 */
.word solaris_unimplemented /* syslocal d 127 */
- .word solaris_unimplemented /* setrlimit 128 */
- .word solaris_unimplemented /* getrlimit 129 */
+ .word solaris_setrlimit /* setrlimit dp 128 */
+ .word solaris_getrlimit /* getrlimit dp 129 */
.word CHAIN(chown) /* lchown sdd 130 */
.word solaris_unimplemented /* memcntl 131 */
.word solaris_getpmsg /* getpmsg dxxxx 132 */
@@ -230,8 +230,8 @@ solaris_sys_table:
.word CHAIN(nanosleep) /* nanosleep dd 199 */
.word solaris_facl /* facl dddp 200 */
.word solaris_unimplemented /* 201 */
- .word solaris_unimplemented /* 202 */
- .word solaris_unimplemented /* 203 */
+ .word solaris_setreuid /* setreuid dd 202 */
+ .word solaris_setregid /* setregid dd 203 */
.word solaris_unimplemented /* 204 */
.word solaris_unimplemented /* 205 */
.word solaris_unimplemented /* 206 */
@@ -241,43 +241,43 @@ solaris_sys_table:
.word solaris_unimplemented /* 210 */
.word solaris_unimplemented /* 211 */
.word solaris_unimplemented /* 212 */
- .word solaris_unimplemented /* 213 */
- .word solaris_unimplemented /* 214 */
- .word solaris_unimplemented /* 215 */
- .word solaris_unimplemented /* 216 */
- .word solaris_unimplemented /* 217 */
- .word solaris_unimplemented /* 218 */
- .word solaris_unimplemented /* 219 */
- .word solaris_unimplemented /* 220 */
- .word solaris_unimplemented /* 221 */
- .word solaris_unimplemented /* 222 */
- .word solaris_unimplemented /* 223 */
- .word solaris_unimplemented /* 224 */
- .word solaris_unimplemented /* 225 */
+ .word solaris_getdents64 /* getdents64 dpd 213 */
+ .word REGS(solaris_mmap64) /* mmap64 xxxxdX 214 */
+ .word solaris_stat64 /* stat64 sP 215 */
+ .word solaris_lstat64 /* lstat64 sP 216 */
+ .word solaris_fstat64 /* fstat64 dP 217 */
+ .word solaris_statvfs64 /* statvfs64 sP 218 */
+ .word solaris_fstatvfs64 /* fstatvfs64 dP 219 */
+ .word solaris_setrlimit64 /* setrlimit64 dP 220 */
+ .word solaris_getrlimit64 /* getrlimit64 dP 221 */
+ .word CHAIN(pread) /* pread64 dpdD 222 */
+ .word CHAIN(pwrite) /* pwrite64 dpdD 223 */
+ .word CHAIN(creat) /* creat64 so 224 */
+ .word solaris_open /* open64 soo 225 */
.word solaris_unimplemented /* 226 */
.word solaris_unimplemented /* 227 */
.word solaris_unimplemented /* 228 */
.word solaris_unimplemented /* 229 */
- .word solaris_unimplemented /* 230 */
- .word solaris_unimplemented /* 231 */
- .word solaris_unimplemented /* 232 */
- .word solaris_unimplemented /* 233 */
- .word solaris_unimplemented /* 234 */
- .word solaris_unimplemented /* 235 */
- .word solaris_unimplemented /* 236 */
- .word solaris_unimplemented /* 237 */
- .word solaris_unimplemented /* 238 */
- .word solaris_unimplemented /* 239 */
- .word solaris_unimplemented /* 240 */
- .word solaris_unimplemented /* 241 */
- .word solaris_unimplemented /* 242 */
- .word solaris_unimplemented /* 243 */
- .word solaris_unimplemented /* 244 */
- .word solaris_unimplemented /* 245 */
- .word solaris_unimplemented /* 246 */
+ .word solaris_socket /* socket ddd 230 */
+ .word solaris_socketpair /* socketpair dddp 231 */
+ .word solaris_bind /* bind dpd 232 */
+ .word solaris_listen /* listen dd 233 */
+ .word solaris_accept /* accept dpp 234 */
+ .word solaris_connect /* connect dpd 235 */
+ .word solaris_shutdown /* shutdown dd 236 */
+ .word solaris_recv /* recv dpdd 237 */
+ .word solaris_recvfrom /* recvfrom dpddpp 238 */
+ .word solaris_recvmsg /* recvmsg dpd 239 */
+ .word solaris_send /* send dpdd 240 */
+ .word solaris_sendmsg /* sendmsg dpd 241 */
+ .word solaris_sendto /* sendto dpddpd 242 */
+ .word solaris_getpeername /* getpeername dpp 243 */
+ .word solaris_getsockname /* getsockname dpp 244 */
+ .word solaris_getsockopt /* getsockopt dddpp 245 */
+ .word solaris_setsockopt /* setsockopt dddpp 246 */
.word solaris_unimplemented /* 247 */
- .word solaris_unimplemented /* 248 */
- .word solaris_unimplemented /* 249 */
+ .word solaris_ntp_gettime /* ntp_gettime p 248 */
+ .word solaris_ntp_adjtime /* ntp_adjtime p 249 */
.word solaris_unimplemented /* 250 */
.word solaris_unimplemented /* 251 */
.word solaris_unimplemented /* 252 */