patch-2.1.23 linux/arch/sparc/kernel/sys_sunos.c
Next file: linux/arch/sparc/kernel/systbls.S
Previous file: linux/arch/sparc/kernel/sys_sparc.c
Back to the patch index
Back to the overall index
- Lines: 1135
- Date:
Sun Jan 26 12:07:08 1997
- Orig file:
v2.1.22/linux/arch/sparc/kernel/sys_sunos.c
- Orig date:
Wed Jan 15 19:45:40 1997
diff -u --recursive --new-file v2.1.22/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.71 1996/12/29 20:46:02 davem Exp $
+/* $Id: sys_sunos.c,v 1.75 1997/01/26 07:12:31 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -8,22 +8,6 @@
*
* Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
*
- * The sunos_poll routine is based on iBCS2's poll routine, this
- * is the copyright message for that file:
- *
- * This file contains the procedures for the handling of poll.
- *
- * Copyright (C) 1994 Eric Youngdale
- *
- * Created for Linux based loosely upon linux select code, which
- * in turn is loosely based upon Mathius Lattner's minix
- * patches by Peter MacDonald. Heavily edited by Linus.
- *
- * Poll is used by SVr4 instead of select, and it has considerably
- * more functionality. Parts of it are related to STREAMS, and since
- * we do not have streams, we fake it. In fact, select() still exists
- * under SVr4, but libc turns it into a poll() call instead. We attempt
- * to do the inverse mapping.
*/
#include <linux/kernel.h>
@@ -46,6 +30,8 @@
#include <linux/malloc.h>
#include <linux/pagemap.h>
#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#ifndef KERNEL_DS
@@ -79,19 +65,22 @@
struct file * file = NULL;
unsigned long retval, ret_type;
+ lock_kernel();
current->personality |= PER_BSD;
if(flags & MAP_NORESERVE) {
printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
current->comm);
flags &= ~MAP_NORESERVE;
}
+ retval = -EBADF;
if(!(flags & MAP_ANONYMOUS))
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
+ goto out;
+ retval = -ENOMEM;
if(!(flags & MAP_FIXED) && !addr) {
addr = get_unmapped_area(addr, len);
if(!addr)
- return -ENOMEM;
+ goto out;
}
/* If this is ld.so or a shared library doing an mmap
* of /dev/zero, transform it into an anonymous mapping.
@@ -108,19 +97,23 @@
flags &= ~_MAP_NEW;
/* See asm-sparc/uaccess.h */
+ retval = -EINVAL;
if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
- return -EINVAL;
+ goto out;
if(sparc_cpu_model == sun4c) {
- if(((addr >= 0x20000000) && (addr < 0xe0000000)))
- return current->mm->brk;
+ if(((addr >= 0x20000000) && (addr < 0xe0000000))) {
+ retval = current->mm->brk;
+ goto out;
+ }
}
retval = do_mmap(file, addr, len, prot, flags, off);
- if(ret_type)
- return retval;
- else
- return ((retval < PAGE_OFFSET) ? 0 : retval);
+ if(!ret_type)
+ retval = ((retval < PAGE_OFFSET) ? 0 : retval);
+out:
+ unlock_kernel();
+ return retval;
}
/* lmbench calls this, just say "yeah, ok" */
@@ -135,23 +128,26 @@
*/
asmlinkage int sunos_brk(unsigned long brk)
{
- int freepages;
+ int freepages, retval = -ENOMEM;
unsigned long rlim;
unsigned long newbrk, oldbrk;
+ lock_kernel();
if(sparc_cpu_model == sun4c) {
- if(brk >= 0x20000000 && brk < 0xe0000000)
- return -ENOMEM;
+ if(brk >= 0x20000000 && brk < 0xe0000000) {
+ goto out;
+ }
}
if (brk < current->mm->end_code)
- return -ENOMEM;
+ goto out;
newbrk = PAGE_ALIGN(brk);
oldbrk = PAGE_ALIGN(current->mm->brk);
+ retval = 0;
if (oldbrk == newbrk) {
current->mm->brk = brk;
- return 0;
+ goto out;
}
/*
@@ -160,22 +156,23 @@
if (brk <= current->mm->brk) {
current->mm->brk = brk;
do_munmap(newbrk, oldbrk-newbrk);
- return 0;
+ goto out;
}
/*
* Check against rlimit and stack..
*/
+ retval = -ENOMEM;
rlim = current->rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY)
rlim = ~0;
if (brk - current->mm->end_code > rlim)
- return -ENOMEM;
+ goto out;
/*
* Check against existing mmap mappings.
*/
if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
- return -ENOMEM;
+ goto out;
/*
* stupid algorithm to decide if we have enough memory: while
@@ -190,7 +187,7 @@
freepages -= num_physpages >> 4;
freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
if (freepages < 0)
- return -ENOMEM;
+ goto out;
/*
* Ok, we have probably got enough memory - let it rip.
*/
@@ -198,20 +195,25 @@
do_mmap(NULL, oldbrk, newbrk-oldbrk,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- return 0;
+ retval = 0;
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage unsigned long sunos_sbrk(int increment)
{
int error;
- unsigned long oldbrk = current->mm->brk;
+ unsigned long oldbrk;
/* This should do it hopefully... */
+ lock_kernel();
+ oldbrk = current->mm->brk;
error = sunos_brk(((int) current->mm->brk) + increment);
- if(error)
- return error;
- else
- return oldbrk;
+ if(!error)
+ error = oldbrk;
+ unlock_kernel();
+ return error;
}
/* XXX Completely undocumented, and completely magic...
@@ -221,8 +223,10 @@
*/
asmlinkage unsigned long sunos_sstk(int increment)
{
+ lock_kernel();
printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
current->comm, increment);
+ unlock_kernel();
return -1;
}
@@ -243,10 +247,11 @@
asmlinkage void sunos_vadvise(unsigned long strategy)
{
/* I wanna see who uses this... */
+ lock_kernel();
printk("%s: Advises us to use %s paging strategy\n",
current->comm,
strategy <= 3 ? vstrings[strategy] : "BOGUS");
- return; /* We don't do diddly... */
+ unlock_kernel();
}
/* Same as vadvise, and just as bogus, but for a range of virtual
@@ -270,11 +275,12 @@
unsigned long strategy)
{
/* I wanna see who uses this... */
+ lock_kernel();
printk("%s: Advises us to use %s paging strategy for addr<%08lx> len<%08lx>\n",
current->comm,
strategy <= 4 ? mstrings[strategy] : "BOGUS",
address, len);
- return; /* We don't do diddly... */
+ unlock_kernel();
}
/* Places into character array, the status of all the pages in the passed
@@ -293,33 +299,39 @@
pmd_t *pmdp;
pte_t *ptep;
unsigned long limit;
- int num_pages, pnum;
+ int num_pages, pnum, retval = -EINVAL;
+ lock_kernel();
if(addr & ~(PAGE_MASK))
- return -EINVAL;
+ goto out;
num_pages = (len / PAGE_SIZE);
+ retval = -EFAULT;
if(verify_area(VERIFY_WRITE, array, num_pages))
- return -EFAULT;
+ goto out;
+ retval = -ENOMEM;
if((addr >= PAGE_OFFSET) || ((addr + len) > PAGE_OFFSET))
- return -ENOMEM; /* I'm sure you're curious about kernel mappings.. */
+ goto out; /* I'm sure you're curious about kernel mappings.. */
/* Wheee, go through pte's */
pnum = 0;
for(limit = addr + len; addr < limit; addr += PAGE_SIZE, pnum++) {
pgdp = pgd_offset(current->mm, addr);
if(pgd_none(*pgdp))
- return -ENOMEM; /* As per SunOS manpage */
+ goto out; /* As per SunOS manpage */
pmdp = pmd_offset(pgdp, addr);
if(pmd_none(*pmdp))
- return -ENOMEM; /* As per SunOS manpage */
+ goto out; /* As per SunOS manpage */
ptep = pte_offset(pmdp, addr);
if(pte_none(*ptep))
- return -ENOMEM; /* As per SunOS manpage */
+ goto out; /* As per SunOS manpage */
/* Page in core or Swapped page? */
__put_user((pte_present(*ptep) ? 1 : 0), &array[pnum]);
}
- return 0; /* Success... I think... */
+ retval = 0; /* Success... I think... */
+out:
+ unlock_kernel();
+ return retval;
}
/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
@@ -339,10 +351,12 @@
unsigned long flags;
unsigned long old;
+ lock_kernel();
save_and_cli(flags);
old = current->blocked;
current->blocked |= (blk_mask & _BLOCKABLE);
restore_flags(flags);
+ unlock_kernel();
return old;
}
@@ -351,10 +365,12 @@
unsigned long flags;
unsigned long retval;
+ lock_kernel();
save_and_cli(flags);
retval = current->blocked;
current->blocked = newmask & _BLOCKABLE;
restore_flags(flags);
+ unlock_kernel();
return retval;
}
@@ -410,14 +426,17 @@
struct file * file;
struct sunos_dirent * lastdirent;
struct sunos_dirent_callback buf;
- int error;
+ int error = -EBADF;
+ lock_kernel();
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
+ goto out;
+ error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- return -ENOTDIR;
+ goto out;
+ error = -EINVAL;
if(cnt < (sizeof(struct sunos_dirent) + 255))
- return -EINVAL;
+ goto out;
buf.curr = (struct sunos_dirent *) dirent;
buf.previous = NULL;
@@ -425,12 +444,17 @@
buf.error = 0;
error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldir);
if (error < 0)
- return error;
+ goto out;
lastdirent = buf.previous;
- if (!lastdirent)
- return buf.error;
- put_user(file->f_pos, &lastdirent->d_off);
- return cnt - buf.count;
+ if (!lastdirent) {
+ error = buf.error;
+ } else {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = cnt - buf.count;
+ }
+out:
+ unlock_kernel();
+ return error;
}
/* Old sunos getdirentries, severely broken compatibility stuff here. */
@@ -477,14 +501,17 @@
struct file * file;
struct sunos_direntry * lastdirent;
struct sunos_direntry_callback buf;
- int error;
+ int error = -EBADF;
+ lock_kernel();
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
+ goto out;
+ error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- return -ENOTDIR;
+ goto out;
+ error = -EINVAL;
if(cnt < (sizeof(struct sunos_direntry) + 255))
- return -EINVAL;
+ goto out;
buf.curr = (struct sunos_direntry *) dirent;
buf.previous = NULL;
@@ -492,26 +519,36 @@
buf.error = 0;
error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldirentry);
if (error < 0)
- return error;
+ goto out;
lastdirent = buf.previous;
- if (!lastdirent)
- return buf.error;
- put_user(file->f_pos, basep);
- return cnt - buf.count;
+ if (!lastdirent) {
+ error = buf.error;
+ } else {
+ put_user(file->f_pos, basep);
+ error = cnt - buf.count;
+ }
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int sunos_getdomainname(char *name, int len)
{
int nlen = strlen(system_utsname.domainname);
+ int ret = -EFAULT;
+ lock_kernel();
if (nlen < len)
len = nlen;
if(len > __NEW_UTS_LEN)
- return -EFAULT;
+ goto out;
if(copy_to_user(name, system_utsname.domainname, len))
- return -EFAULT;
- return 0;
+ goto out;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
struct sunos_utsname {
@@ -525,22 +562,29 @@
asmlinkage int sunos_uname(struct sunos_utsname *name)
{
+ int ret = -EFAULT;
+
+ lock_kernel();
if(!name)
- return -EFAULT;
+ goto out;
if(copy_to_user(&name->sname[0], &system_utsname.sysname[0], sizeof(name->sname) - 1))
- return -EFAULT;
+ goto out;
copy_to_user(&name->nname[0], &system_utsname.nodename[0], sizeof(name->nname) - 1);
put_user('\0', &name->nname[8]);
copy_to_user(&name->rel[0], &system_utsname.release[0], sizeof(name->rel) - 1);
copy_to_user(&name->ver[0], &system_utsname.version[0], sizeof(name->ver) - 1);
copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_nosys(void)
{
struct pt_regs *regs;
+ lock_kernel();
regs = current->tss.kregs;
current->tss.sig_address = regs->pc;
current->tss.sig_desc = regs->u_regs[UREG_G1];
@@ -548,6 +592,7 @@
printk("Process makes ni_syscall number %d, register dump:\n",
(int) regs->u_regs[UREG_G1]);
show_regs(regs);
+ unlock_kernel();
return -ENOSYS;
}
@@ -556,33 +601,51 @@
*/
asmlinkage int sunos_fpathconf(int fd, int name)
{
+ int ret;
+
+ lock_kernel();
switch(name) {
case _PCONF_LINK:
- return LINK_MAX;
+ ret = LINK_MAX;
+ break;
case _PCONF_CANON:
- return MAX_CANON;
+ ret = MAX_CANON;
+ break;
case _PCONF_INPUT:
- return MAX_INPUT;
+ ret = MAX_INPUT;
+ break;
case _PCONF_NAME:
- return NAME_MAX;
+ ret = NAME_MAX;
+ break;
case _PCONF_PATH:
- return PATH_MAX;
+ ret = PATH_MAX;
+ break;
case _PCONF_PIPE:
- return PIPE_BUF;
- case _PCONF_CHRESTRICT:
- return 1; /* XXX Investigate XXX */
- case _PCONF_NOTRUNC:
- return 0; /* XXX Investigate XXX */
+ ret = PIPE_BUF;
+ break;
+ case _PCONF_CHRESTRICT: /* XXX Investigate XXX */
+ ret = 1;
+ break;
+ case _PCONF_NOTRUNC: /* XXX Investigate XXX */
case _PCONF_VDISABLE:
- return 0;
+ ret = 0;
+ break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ break;
}
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_pathconf(char *path, int name)
{
- return sunos_fpathconf(0, name); /* XXX cheese XXX */
+ int ret;
+
+ lock_kernel();
+ ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
+ unlock_kernel();
+ return ret;
}
/* SunOS mount system call emulation */
@@ -591,9 +654,14 @@
asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
{
+ int ret;
+
/* SunOS binaries expect that select won't change the tvp contents */
+ lock_kernel();
current->personality |= STICKY_TIMEOUTS;
- return sys_select (width, inp, outp, exp, tvp);
+ ret = sys_select (width, inp, outp, exp, tvp);
+ unlock_kernel();
+ return ret;
}
asmlinkage void sunos_nop(void)
@@ -757,15 +825,17 @@
sunos_mount(char *type, char *dir, int flags, void *data)
{
int linux_flags = MS_MGC_MSK; /* new semantics */
+ int ret = -EINVAL;
char *dev_fname = 0;
+ lock_kernel();
/* We don't handle the integer fs type */
if ((flags & SMNT_NEWTYPE) == 0)
- return -EINVAL;
+ goto out;
/* Do not allow for those flags we don't support */
if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
- return -EINVAL;
+ goto out;
if(flags & SMNT_REMOUNT)
linux_flags |= MS_REMOUNT;
@@ -780,14 +850,20 @@
} else if(strcmp(type, "minix") == 0) {
dev_fname = (char *) data;
} else if(strcmp(type, "nfs") == 0) {
- return sunos_nfs_mount (dir, flags, data);
+ ret = sunos_nfs_mount (dir, flags, data);
+ goto out;
} else if(strcmp(type, "ufs") == 0) {
printk("Warning: UFS filesystem mounts unsupported.\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto out;
} else if(strcmp(type, "proc")) {
- return -ENODEV;
+ ret = -ENODEV;
+ goto out;
}
- return sys_mount(dev_fname, dir, type, linux_flags, NULL);
+ ret = sys_mount(dev_fname, dir, type, linux_flags, NULL);
+out:
+ unlock_kernel();
+ return ret;
}
extern asmlinkage int sys_setsid(void);
@@ -795,217 +871,102 @@
asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
{
+ int ret;
+
/* So stupid... */
+ lock_kernel();
if((!pid || pid == current->pid) &&
!pgid) {
sys_setsid();
- return 0;
+ ret = 0;
} else {
- return sys_setpgid(pid, pgid);
+ ret = sys_setpgid(pid, pgid);
}
+ unlock_kernel();
+ return ret;
}
/* So stupid... */
extern asmlinkage int sys_wait4(pid_t, unsigned int *, int, struct rusage *);
asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru)
{
- return sys_wait4((pid ? pid : -1), stat_addr, options, ru);
+ int ret;
+
+ lock_kernel();
+ ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru);
+ unlock_kernel();
+ return ret;
}
extern int kill_pg(int, int, int);
asmlinkage int sunos_killpg(int pgrp, int sig)
{
- return kill_pg(pgrp, sig, 0);
+ int ret;
+
+ lock_kernel();
+ ret = kill_pg(pgrp, sig, 0);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_audit(void)
{
+ lock_kernel();
printk ("sys_audit\n");
+ unlock_kernel();
return -1;
}
extern asmlinkage unsigned long sunos_gethostid(void)
{
- return ((unsigned long)idprom->id_machtype << 24) |
- (unsigned long)idprom->id_sernum;
+ unsigned long ret;
+
+ lock_kernel();
+ ret = ((unsigned long)idprom->id_machtype << 24) |
+ (unsigned long)idprom->id_sernum;
+ unlock_kernel();
+ return ret;
}
extern asmlinkage long sunos_sysconf (int name)
{
+ long ret;
+
+ lock_kernel();
switch (name){
case _SC_ARG_MAX:
- return ARG_MAX;
+ ret = ARG_MAX;
+ break;
case _SC_CHILD_MAX:
- return CHILD_MAX;
+ ret = CHILD_MAX;
+ break;
case _SC_CLK_TCK:
- return HZ;
+ ret = HZ;
+ break;
case _SC_NGROUPS_MAX:
- return NGROUPS_MAX;
+ ret = NGROUPS_MAX;
+ break;
case _SC_OPEN_MAX:
- return OPEN_MAX;
+ ret = OPEN_MAX;
+ break;
case _SC_JOB_CONTROL:
- return 1; /* yes, we do support job control */
+ ret = 1; /* yes, we do support job control */
+ break;
case _SC_SAVED_IDS:
- return 1; /* yes, we do support saved uids */
+ ret = 1; /* yes, we do support saved uids */
+ break;
case _SC_VERSION:
/* mhm, POSIX_VERSION is in /usr/include/unistd.h
* should it go on /usr/include/linux?
*/
- return 199009L;
- }
- return -1;
-}
-
-#define POLL_ROUND_UP(x,y) (((x)+(y)-1)/(y))
-
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#define POLLERR 8
-#define POLLHUP 16
-#define POLLNVAL 32
-#define POLLRDNORM 64
-#define POLLWRNORM POLLOUT
-#define POLLRDBAND 128
-#define POLLWRBAND 256
-
-#define LINUX_POLLIN (POLLRDNORM | POLLRDBAND | POLLIN)
-#define LINUX_POLLOUT (POLLWRBAND | POLLWRNORM | POLLOUT)
-#define LINUX_POLLERR (POLLERR)
-
-static inline void free_wait(select_table * p)
-{
- struct select_table_entry * entry = p->entry + p->nr;
-
- while (p->nr > 0) {
- p->nr--;
- entry--;
- remove_wait_queue(entry->wait_address,&entry->wait);
- }
-}
-
-
-/* Copied directly from fs/select.c */
-static int check(int flag, select_table * wait, struct file * file)
-{
- struct inode * inode;
- struct file_operations *fops;
- int (*select) (struct inode *, struct file *, int, select_table *);
-
- inode = file->f_inode;
- if ((fops = file->f_op) && (select = fops->select))
- return select(inode, file, flag, wait)
- || (wait && select(inode, file, flag, NULL));
- if (S_ISREG(inode->i_mode))
- return 1;
- return 0;
-}
-
-struct poll {
- int fd;
- short events;
- short revents;
-};
-
-int sunos_poll(struct poll * ufds, size_t nfds, int timeout)
-{
- int i,j, count, fdcount, retflag;
- struct poll * fdpnt;
- struct poll * fds, *fds1;
- select_table wait_table, *wait;
- struct select_table_entry *entry;
-
- if (nfds > NR_OPEN)
- return -EINVAL;
-
- if (!(entry = (struct select_table_entry*)__get_free_page(GFP_KERNEL))
- || !(fds = (struct poll *)kmalloc(nfds*sizeof(struct poll), GFP_KERNEL)))
- return -ENOMEM;
-
- if(copy_from_user(fds, ufds, nfds*sizeof(struct poll))) {
- free_page((unsigned long)entry);
- kfree(fds);
- return -EFAULT;
- }
-
- if (timeout < 0)
- current->timeout = 0x7fffffff;
- else {
- current->timeout = jiffies + POLL_ROUND_UP(timeout, (1000/HZ));
- if (current->timeout <= jiffies)
- current->timeout = 0;
- }
-
- count = 0;
- wait_table.nr = 0;
- wait_table.entry = entry;
- wait = &wait_table;
-
- for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) {
- i = fdpnt->fd;
- fdpnt->revents = 0;
- if (!current->files->fd[i] || !current->files->fd[i]->f_inode)
- fdpnt->revents = POLLNVAL;
- }
-repeat:
- current->state = TASK_INTERRUPTIBLE;
- for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) {
- i = fdpnt->fd;
-
- if(i < 0) continue;
- if (!current->files->fd[i] || !current->files->fd[i]->f_inode) continue;
-
- if ((fdpnt->events & LINUX_POLLIN)
- && check(SEL_IN, wait, current->files->fd[i])) {
- retflag = 0;
- if (fdpnt->events & POLLIN)
- retflag = POLLIN;
- if (fdpnt->events & POLLRDNORM)
- retflag = POLLRDNORM;
- fdpnt->revents |= retflag;
- count++;
- wait = NULL;
- }
-
- if ((fdpnt->events & LINUX_POLLOUT) &&
- check(SEL_OUT, wait, current->files->fd[i])) {
- fdpnt->revents |= (LINUX_POLLOUT & fdpnt->events);
- count++;
- wait = NULL;
- }
-
- if (check(SEL_EX, wait, current->files->fd[i])) {
- fdpnt->revents |= POLLHUP;
- count++;
- wait = NULL;
- }
- }
-
- if ((current->signal & (~current->blocked)))
- return -EINTR;
-
- wait = NULL;
- if (!count && current->timeout > jiffies) {
- schedule();
- goto repeat;
- }
-
- free_wait(&wait_table);
- free_page((unsigned long) entry);
-
- /* OK, now copy the revents fields back to user space. */
- fds1 = fds;
- fdcount = 0;
- for(i=0; i < (int)nfds; i++, ufds++, fds++) {
- if (fds->revents) {
- fdcount++;
- }
- __put_user(fds->revents, &ufds->revents);
- }
- kfree(fds1);
- current->timeout = 0;
- current->state = TASK_RUNNING;
- return fdcount;
+ ret = 199009L;
+ break;
+ default:
+ ret = -1;
+ break;
+ };
+ unlock_kernel();
+ return ret;
}
extern asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg);
@@ -1016,7 +977,9 @@
unsigned long arg3, void *ptr)
{
union semun arg4;
+ int ret;
+ lock_kernel();
switch (op) {
case 0:
/* Most arguments match on a 1:1 basis but cmd doesn't */
@@ -1038,16 +1001,22 @@
}
/* sys_semctl(): */
arg4.__pad=ptr; /* value to modify semaphore to */
- return sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4 );
+ ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4 );
+ break;
case 1:
/* sys_semget(): */
- return sys_semget((key_t)arg1, (int)arg2, (int)arg3);
+ ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
+ break;
case 2:
/* sys_semop(): */
- return sys_semop((int)arg1, (struct sembuf *)arg2, (unsigned)arg3);
+ ret = sys_semop((int)arg1, (struct sembuf *)arg2, (unsigned)arg3);
+ break;
default:
- return -EINVAL;
- }
+ ret = -EINVAL;
+ break;
+ };
+ unlock_kernel();
+ return ret;
}
extern asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
@@ -1061,32 +1030,43 @@
unsigned long raddr;
int rval;
+ lock_kernel();
switch(op) {
case 0:
/* sys_shmat(): attach a shared memory area */
rval = sys_shmat((int)arg1,(char *)arg2,(int)arg3,&raddr);
- if(rval != 0)
- return rval;
- return (int) raddr;
+ if(!rval)
+ rval = (int) raddr;
+ break;
case 1:
/* sys_shmctl(): modify shared memory area attr. */
rval = sys_shmctl((int)arg1,(int)arg2,(struct shmid_ds *)arg3);
- return (rval);
+ break;
case 2:
/* sys_shmdt(): detach a shared memory area */
- return sys_shmdt((char *)arg1);
+ rval = sys_shmdt((char *)arg1);
+ break;
case 3:
/* sys_shmget(): get a shared memory area */
- return sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
+ rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
+ break;
default:
- return -EINVAL;
- }
+ rval = -EINVAL;
+ break;
+ };
+ unlock_kernel();
+ return rval;
}
asmlinkage int sunos_open(const char *filename, int flags, int mode)
{
+ int ret;
+
+ lock_kernel();
current->personality |= PER_BSD;
- return sys_open (filename, flags, mode);
+ ret = sys_open (filename, flags, mode);
+ unlock_kernel();
+ return ret;
}
@@ -1115,37 +1095,72 @@
asmlinkage int sunos_read(unsigned int fd,char *buf,int count)
{
- return check_nonblock(sys_read(fd,buf,count),fd);
+ int ret;
+
+ lock_kernel();
+ ret = check_nonblock(sys_read(fd,buf,count),fd);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_readv(unsigned long fd, const struct iovec * vector, long count)
{
- return check_nonblock(sys_readv(fd,vector,count),fd);
+ int ret;
+
+ lock_kernel();
+ ret = check_nonblock(sys_readv(fd,vector,count),fd);
+ lock_kernel();
+ return ret;
}
asmlinkage int sunos_write(unsigned int fd,char *buf,int count)
{
- return check_nonblock(sys_write(fd,buf,count),fd);
+ int ret;
+
+ lock_kernel();
+ ret = check_nonblock(sys_write(fd,buf,count),fd);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_writev(unsigned long fd, const struct iovec * vector, long count)
{
- return check_nonblock(sys_writev(fd,vector,count),fd);
+ int ret;
+
+ lock_kernel();
+ ret = check_nonblock(sys_writev(fd,vector,count),fd);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_recv(int fd, void * ubuf, int size, unsigned flags)
{
- return check_nonblock(sys_recv(fd,ubuf,size,flags),fd);
+ int ret;
+
+ lock_kernel();
+ ret = check_nonblock(sys_recv(fd,ubuf,size,flags),fd);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_send(int fd, void * buff, int len, unsigned flags)
{
- return check_nonblock(sys_send(fd,buff,len,flags),fd);
+ int ret;
+
+ lock_kernel();
+ ret = check_nonblock(sys_send(fd,buff,len,flags),fd);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen)
{
- return check_nonblock(sys_accept(fd,sa,addrlen),fd);
+ int ret;
+
+ lock_kernel();
+ ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);
+ unlock_kernel();
+ return ret;
}
#define SUNOS_SV_INTERRUPT 2
@@ -1157,33 +1172,38 @@
{
struct sigaction new_sa, *p;
const int sigaction_size = sizeof (struct sigaction) - sizeof (void *);
- int err;
+ int err = -EINVAL;
+ lock_kernel();
current->personality |= PER_BSD;
if (signum<1 || signum>32)
- return -EINVAL;
+ goto out;
p = signum - 1 + current->sig->action;
if (action) {
+ err = -EFAULT;
if(copy_from_user(&new_sa, action, sigaction_size))
- return -EFAULT;
+ goto out;
+ err = -EINVAL;
if (signum==SIGKILL || signum==SIGSTOP)
- return -EINVAL;
+ goto out;
memset(&new_sa, 0, sizeof(struct sigaction));
+ err = -EFAULT;
if(copy_from_user(&new_sa, action, sigaction_size))
- return -EFAULT;
+ goto out;
if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
if (err)
- return err;
+ goto out;
}
new_sa.sa_flags ^= SUNOS_SV_INTERRUPT;
}
if (oldaction) {
+ err = -EFAULT;
if (copy_to_user(oldaction, p, sigaction_size))
- return -EFAULT;
+ goto out;
if (oldaction->sa_flags & SA_RESTART)
oldaction->sa_flags &= ~SA_RESTART;
else
@@ -1194,8 +1214,10 @@
*p = new_sa;
check_pending(signum);
}
-
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
@@ -1206,34 +1228,32 @@
int optlen)
{
int tr_opt = optname;
+ int ret;
- if (level == SOL_IP)
- {
- /*
- * Multicast socketopts (ttl, membership)
- */
+ lock_kernel();
+ if (level == SOL_IP) {
+ /* Multicast socketopts (ttl, membership) */
if (tr_opt >=2 && tr_opt <= 6)
- {
tr_opt += 30;
- }
}
- return sys_setsockopt(fd, level, tr_opt, optval, optlen);
+ ret = sys_setsockopt(fd, level, tr_opt, optval, optlen);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sunos_getsockopt(int fd, int level, int optname, char *optval,
int *optlen)
{
int tr_opt = optname;
+ int ret;
- if (level == SOL_IP)
- {
- /*
- * Multicast socketopts (ttl, membership)
- */
+ lock_kernel();
+ if (level == SOL_IP) {
+ /* Multicast socketopts (ttl, membership) */
if (tr_opt >=2 && tr_opt <= 6)
- {
tr_opt += 30;
- }
}
- return sys_getsockopt(fd, level, tr_opt, optval, optlen);
+ ret = sys_getsockopt(fd, level, tr_opt, optval, optlen);
+ unlock_kernel();
+ return ret;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov