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

📄 osf_sys.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 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/unistd.h>#include <linux/ptrace.h>#include <linux/malloc.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 <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 *);extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);extern asmlinkage unsigned long sys_brk(unsigned long);/* * 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;	printk("set_program_attributes(%lx %lx %lx %lx)\n",		text_start, text_len, bss_start, bss_len);	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(de) ((int) ((de)->d_name - (char *) (de)))#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 *dirent;	long *basep;	int count;	int error;};static int osf_filldir(void *__buf, const char *name, int namlen, off_t offset,		       ino_t ino, unsigned int d_type){	struct osf_dirent *dirent;	struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);	buf->error = -EINVAL;	/* only used if we fail */	if (reclen > buf->count)		return -EINVAL;	if (buf->basep) {		put_user(offset, buf->basep);		buf->basep = NULL;	}	dirent = buf->dirent;	put_user(ino, &dirent->d_ino);	put_user(namlen, &dirent->d_namlen);	put_user(reclen, &dirent->d_reclen);	copy_to_user(dirent->d_name, name, namlen);	put_user(0, dirent->d_name + namlen);	((char *) dirent) += reclen;	buf->dirent = dirent;	buf->count -= reclen;	return 0;}asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,				 unsigned int count, long *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/* * Alpha syscall convention has no problem returning negative * values: */asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4,			       int a5, struct pt_regs regs){	extern int sys_getpriority(int, int);	int prio;	/*	 * We don't need to acquire the kernel lock here, because	 * all of these operations are local. sys_getpriority	 * will get the lock as required..	 */	prio = sys_getpriority(which, who);	if (prio >= 0) {		regs.r0 = 0;		/* special return: no errors */		prio = 20 - prio;	}	return prio;}/* * No need to acquire the kernel lock, we're local.. */asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4,				     int a5, struct pt_regs regs){	struct task_struct * tsk = current;	(&regs)->r20 = tsk->euid;	return tsk->uid;}asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4,				     int a5, struct pt_regs regs){	struct task_struct * tsk = current;	(&regs)->r20 = tsk->egid;	return tsk->gid;}asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4,				     int a5, struct pt_regs regs){	struct task_struct *tsk = current;	/* 	 * This isn't strictly "local" any more and we should actually	 * acquire the kernel lock. The "p_opptr" pointer might change	 * if the parent goes away (or due to ptrace). But any race	 * isn't actually going to matter, as if the parent happens	 * to change we can happily return either of the pids.	 */	(&regs)->r20 = tsk->p_opptr->pid;	return tsk->pid;}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;	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(&current->mm->mmap_sem);	ret = do_mmap(file, addr, len, prot, flags, off);	up(&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;} *osf_stat;static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *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 */	/* Linux doesn't provide a "fundamental filesystem block size": */	tmp_stat.f_fsize = linux_stat->f_bsize;	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 int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsigned long bufsiz){	struct statfs 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 int osf_statfs(char *path, struct osf_statfs *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 int osf_fstatfs(unsigned long fd, struct osf_statfs *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 *devname;	int flags;	uid_t exroot;};struct cdfs_args {	char *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 *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 int osf_ufs_mount(char *dirname, struct ufs_args *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 int osf_cdfs_mount(char *dirname, struct cdfs_args *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 int osf_procfs_mount(char *dirname, struct procfs_args *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 int osf_mount(unsigned long typenr, char *path, int flag, void *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, (struct ufs_args *) data, flag);		break;	case 6:		retval = osf_cdfs_mount(name, (struct cdfs_args *) data, flag);		break;	case 9:		retval = osf_procfs_mount(name, (struct procfs_args *) data, flag);		break;	default:		printk("osf_mount(%ld, %x)\n", typenr, flag);	}	putname(name);out:	unlock_kernel();	return retval;}asmlinkage int osf_utsname(char *name){	int error;

⌨️ 快捷键说明

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