patch-2.1.129 linux/arch/sparc64/solaris/misc.c
Next file: linux/arch/sparc64/solaris/socket.c
Previous file: linux/arch/sparc64/solaris/fs.c
Back to the patch index
Back to the overall index
- Lines: 391
- Date:
Mon Nov 16 10:37:28 1998
- Orig file:
v2.1.128/linux/arch/sparc64/solaris/misc.c
- Orig date:
Thu Aug 6 14:06:31 1998
diff -u --recursive --new-file v2.1.128/linux/arch/sparc64/solaris/misc.c linux/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 @@
/* 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_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;
@@ -376,6 +461,257 @@
(int (*)(struct timeval *, struct timezone *))SYS(gettimeofday);
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)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov