/*
* linux/arch/alpha/kernel/osf_sys.c
*
* Copyright (C) 1995 Linus Torvalds
*/
/*
* This file handles some of the stranger OSF/1 system call interfaces.
* Some of the system calls expect a non-C calling standard, others have
* special parameter blocks..
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/utsname.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/shm.h>
#include <linux/poll.h>
#include <linux/file.h>
#include <linux/types.h>
#include <linux/ipc.h>
#include <linux/namei.h>
#include <linux/uio.h>
#include <linux/vfs.h>
#include <linux/rcupdate.h>
#include <asm/fpu.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/sysinfo.h>
#include <asm/hwrpb.h>
#include <asm/processor.h>
extern int do_pipe(int *);
/*
* Brk needs to return an error. Still support Linux's brk(0) query idiom,
* which OSF programs just shouldn't be doing. We're still not quite
* identical to OSF as we don't return 0 on success, but doing otherwise
* would require changes to libc. Hopefully this is good enough.
*/
asmlinkage unsigned long
osf_brk(unsigned long brk)
{
unsigned long retval = sys_brk(brk);
if (brk && brk != retval)
retval = -ENOMEM;
return retval;
}
/*
* This is pure guess-work..
*/
asmlinkage int
osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
unsigned long bss_start, unsigned long bss_len)
{
struct mm_struct *mm;
lock_kernel();
mm = current->mm;
mm->end_code = bss_start + bss_len;
mm->brk = bss_start + bss_len;
#if 0
printk("set_program_attributes(%lx %lx %lx %lx)\n",
text_start, text_len, bss_start, bss_len);
#endif
unlock_kernel();
return 0;
}
/*
* OSF/1 directory handling functions...
*
* The "getdents()" interface is much more sane: the "basep" stuff is
* braindamage (it can't really handle filesystems where the directory
* offset differences aren't the same as "d_reclen").
*/
#define NAME_OFFSET offsetof (struct osf_dirent, d_name)
#define ROUND_UP(x) (((x)+3) & ~3)
struct osf_dirent {
unsigned int d_ino;
unsigned short d_reclen;
unsigned short d_namlen;
char d_name[1];
};
struct osf_dirent_callback {
struct osf_dirent __user *dirent;
long __user *basep;
unsigned int count;
int error;
};
static int
osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
ino_t ino, unsigned int d_type)
{
struct osf_dirent __user *dirent;
struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1);
buf->error = -EINVAL; /* only used if we fail */
if (reclen > buf->count)
return -EINVAL;
if (buf->basep) {
if (put_user(offset, buf->basep))
return -EFAULT;
buf->basep = NULL;
}
dirent = buf->dirent;
put_user(ino, &dirent->d_ino);
put_user(namlen, &dirent->d_namlen);
put_user(reclen, &dirent->d_reclen);
if (copy_to_user(dirent->d_name, name, namlen) ||
put_user(0, dirent->d_name + namlen))
return -EFAULT;
dirent = (void __user *)dirent + reclen;
buf->dirent = dirent;
buf->count -= reclen;
return 0;
}
asmlinkage int
osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
unsigned int count, long __user *basep)
{
int error;
struct file *file;
struct osf_dirent_callback buf;
error = -EBADF;
file = fget(fd);
if (!file)
goto out;
buf.dirent = dirent;
buf.basep = basep;
buf.count = count;
buf.error = 0;
error = vfs_readdir(file, osf_filldir, &buf);
if (error < 0)
goto out_putf;
error = buf.error;
if (count != buf.count)
error = count - buf.count;
out_putf:
fput(file);
out:
return error;
}
#undef ROUND_UP
#undef NAME_OFFSET
asmlinkage unsigned long
osf_mmap(unsigned long addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long fd, unsigned long off)
{
struct file *file = NULL;
|