⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osf_sys.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  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 longosf_brk(unsigned long brk){	unsigned long retval = sys_brk(brk);	if (brk && brk != retval)		retval = -ENOMEM;	return retval;} /* * This is pure guess-work.. */asmlinkage intosf_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 intosf_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 intosf_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_OFFSETasmlinkage unsigned longosf_mmap(unsigned long addr, unsigned long len, unsigned long prot,	 unsigned long flags, unsigned long fd, unsigned long off){	struct file *file = NULL;	unsigned long ret = -EBADF;#if 0	if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))		printk("%s: unimplemented OSF mmap flags %04lx\n", 			current->comm, flags);#endif	if (!(flags & MAP_ANONYMOUS)) {		file = fget(fd);		if (!file)			goto out;	}	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);	down_write(&current->mm->mmap_sem);	ret = do_mmap(file, addr, len, prot, flags, off);	up_write(&current->mm->mmap_sem);	if (file)		fput(file); out:	return ret;}/* * The OSF/1 statfs structure is much larger, but this should * match the beginning, at least. */struct osf_statfs {	short f_type;	short f_flags;	int f_fsize;	int f_bsize;	int f_blocks;	int f_bfree;	int f_bavail;	int f_files;	int f_ffree;	__kernel_fsid_t f_fsid;};static intlinux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_stat,		    unsigned long bufsiz){	struct osf_statfs tmp_stat;	tmp_stat.f_type = linux_stat->f_type;	tmp_stat.f_flags = 0;	/* mount flags */	tmp_stat.f_fsize = linux_stat->f_frsize;	tmp_stat.f_bsize = linux_stat->f_bsize;	tmp_stat.f_blocks = linux_stat->f_blocks;	tmp_stat.f_bfree = linux_stat->f_bfree;	tmp_stat.f_bavail = linux_stat->f_bavail;	tmp_stat.f_files = linux_stat->f_files;	tmp_stat.f_ffree = linux_stat->f_ffree;	tmp_stat.f_fsid = linux_stat->f_fsid;	if (bufsiz > sizeof(tmp_stat))		bufsiz = sizeof(tmp_stat);	return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;}static intdo_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,	      unsigned long bufsiz){	struct kstatfs linux_stat;	int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat);	if (!error)		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);	return error;	}asmlinkage intosf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bufsiz){	struct nameidata nd;	int retval;	retval = user_path_walk(path, &nd);	if (!retval) {		retval = do_osf_statfs(nd.dentry, buffer, bufsiz);		path_release(&nd);	}	return retval;}asmlinkage intosf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bufsiz){	struct file *file;	int retval;	retval = -EBADF;	file = fget(fd);	if (file) {		retval = do_osf_statfs(file->f_dentry, buffer, bufsiz);		fput(file);	}	return retval;}/* * Uhh.. OSF/1 mount parameters aren't exactly obvious.. * * Although to be frank, neither are the native Linux/i386 ones.. */struct ufs_args {	char __user *devname;	int flags;	uid_t exroot;};struct cdfs_args {	char __user *devname;	int flags;	uid_t exroot;	/* This has lots more here, which Linux handles with the option block	   but I'm too lazy to do the translation into ASCII.  */};struct procfs_args {	char __user *devname;	int flags;	uid_t exroot;};/* * We can't actually handle ufs yet, so we translate UFS mounts to * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS * layout is so braindead it's a major headache doing it. * * Just how long ago was it written? OTOH our UFS driver may be still * unhappy with OSF UFS. [CHECKME] */static intosf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags){	int retval;	struct cdfs_args tmp;	char *devname;	retval = -EFAULT;	if (copy_from_user(&tmp, args, sizeof(tmp)))		goto out;	devname = getname(tmp.devname);	retval = PTR_ERR(devname);	if (IS_ERR(devname))		goto out;	retval = do_mount(devname, dirname, "ext2", flags, NULL);	putname(devname); out:	return retval;}static intosf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags){	int retval;	struct cdfs_args tmp;	char *devname;	retval = -EFAULT;	if (copy_from_user(&tmp, args, sizeof(tmp)))		goto out;	devname = getname(tmp.devname);	retval = PTR_ERR(devname);	if (IS_ERR(devname))		goto out;	retval = do_mount(devname, dirname, "iso9660", flags, NULL);	putname(devname); out:	return retval;}static intosf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags){	struct procfs_args tmp;	if (copy_from_user(&tmp, args, sizeof(tmp)))		return -EFAULT;	return do_mount("", dirname, "proc", flags, NULL);}asmlinkage intosf_mount(unsigned long typenr, char __user *path, int flag, void __user *data){	int retval = -EINVAL;	char *name;	lock_kernel();	name = getname(path);	retval = PTR_ERR(name);	if (IS_ERR(name))		goto out;	switch (typenr) {	case 1:		retval = osf_ufs_mount(name, data, flag);		break;	case 6:		retval = osf_cdfs_mount(name, data, flag);		break;	case 9:		retval = osf_procfs_mount(name, data, flag);		break;	default:		printk("osf_mount(%ld, %x)\n", typenr, flag);	}	putname(name); out:	unlock_kernel();	return retval;}asmlinkage intosf_utsname(char __user *name){	int error;	down_read(&uts_sem);	error = -EFAULT;	if (copy_to_user(name + 0, system_utsname.sysname, 32))		goto out;	if (copy_to_user(name + 32, system_utsname.nodename, 32))		goto out;	if (copy_to_user(name + 64, system_utsname.release, 32))		goto out;	if (copy_to_user(name + 96, system_utsname.version, 32))		goto out;	if (copy_to_user(name + 128, system_utsname.machine, 32))		goto out;	error = 0; out:	up_read(&uts_sem);		return error;}asmlinkage unsigned longsys_getpagesize(void){	return PAGE_SIZE;}asmlinkage unsigned longsys_getdtablesize(void){	return NR_OPEN;}/* * For compatibility with OSF/1 only.  Use utsname(2) instead. */asmlinkage intosf_getdomainname(char __user *name, int namelen){	unsigned len;	int i;	if (!access_ok(VERIFY_WRITE, name, namelen))		return -EFAULT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -