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

📄 sys_ia32.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on *             sys_sparc32  * * Copyright (C) 2000		VA Linux Co * Copyright (C) 2000		Don Dugger <n0ano@valinux.com> * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com> * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 2000		Hewlett-Packard Co. * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 2000,2001,2002	Andi Kleen, SuSE Labs (x86-64 port)  * * These routines maintain argument size conversion between 32bit and 64bit * environment. In 2.5 most of this should be moved to a generic directory.  * * This file assumes that there is a hole at the end of user address space. * * $Id: sys_ia32.c,v 1.54 2003/03/24 09:28:26 ak Exp $ */#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h> #include <linux/file.h> #include <linux/signal.h>#include <linux/utime.h>#include <linux/resource.h>#include <linux/times.h>#include <linux/utsname.h>#include <linux/timex.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/sem.h>#include <linux/msg.h>#include <linux/mm.h>#include <linux/shm.h>#include <linux/slab.h>#include <linux/uio.h>#include <linux/nfs_fs.h>#include <linux/smb_fs.h>#include <linux/smb_mount.h>#include <linux/ncp_fs.h>#include <linux/quota.h>#include <linux/module.h>#include <linux/sunrpc/svc.h>#include <linux/nfsd/nfsd.h>#include <linux/nfsd/cache.h>#include <linux/nfsd/xdr.h>#include <linux/nfsd/syscall.h>#include <linux/poll.h>#include <linux/personality.h>#include <linux/stat.h>#include <linux/ipc.h>#include <linux/rwsem.h>#include <linux/binfmts.h>#include <linux/init.h>#include <asm/mman.h>#include <asm/types.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include <asm/ipc.h>#include <asm/atomic.h>#include <asm/ldt.h>#include <net/scm.h>#include <net/sock.h>#include <asm/ia32.h>#define A(__x)		((unsigned long)(__x))#define AA(__x)		((unsigned long)(__x))#define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))#undef high2lowuid#undef high2lowgid#undef low2highuid#undef low2highgid#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)extern int overflowuid,overflowgid; static intputstat(struct stat32 *ubuf, struct stat *kbuf){	if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct stat32)) ||	    __put_user (kbuf->st_dev, &ubuf->st_dev) ||	    __put_user (kbuf->st_ino, &ubuf->st_ino) ||	    __put_user (kbuf->st_mode, &ubuf->st_mode) ||	    __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||	    __put_user (kbuf->st_uid, &ubuf->st_uid) ||	    __put_user (kbuf->st_gid, &ubuf->st_gid) ||	    __put_user (kbuf->st_rdev, &ubuf->st_rdev) ||	    __put_user (kbuf->st_size, &ubuf->st_size) ||	    __put_user (kbuf->st_atime, &ubuf->st_atime) ||	    __put_user (kbuf->st_mtime, &ubuf->st_mtime) ||	    __put_user (kbuf->st_ctime, &ubuf->st_ctime) ||	    __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||	    __put_user (kbuf->st_blocks, &ubuf->st_blocks))		return -EFAULT;	return 0;}extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);asmlinkage longsys32_newstat(char * filename, struct stat32 *statbuf){	int ret;	struct stat s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_newstat(filename, &s);	set_fs (old_fs);	if (putstat (statbuf, &s))		return -EFAULT;	return ret;}extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);asmlinkage longsys32_newlstat(char * filename, struct stat32 *statbuf){	int ret;	struct stat s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_newlstat(filename, &s);	set_fs (old_fs);	if (putstat (statbuf, &s))		return -EFAULT;	return ret;}extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);asmlinkage longsys32_newfstat(unsigned int fd, struct stat32 *statbuf){	int ret;	struct stat s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_newfstat(fd, &s);	set_fs (old_fs);	if (putstat (statbuf, &s))		return -EFAULT;	return ret;}/* Another set for IA32/LFS -- x86_64 struct stat is different due to    support for 64bit inode numbers. */static intputstat64(struct stat64 *ubuf, struct stat *kbuf){	if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct stat64)) ||	    __put_user (kbuf->st_dev, &ubuf->st_dev) ||	    __put_user (kbuf->st_ino, &ubuf->__st_ino) ||	    __put_user (kbuf->st_ino, &ubuf->st_ino) ||	    __put_user (kbuf->st_mode, &ubuf->st_mode) ||	    __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||	    __put_user (kbuf->st_uid, &ubuf->st_uid) ||	    __put_user (kbuf->st_gid, &ubuf->st_gid) ||	    __put_user (kbuf->st_rdev, &ubuf->st_rdev) ||	    __put_user (kbuf->st_size, &ubuf->st_size) ||	    __put_user (kbuf->st_atime, &ubuf->st_atime) ||	    __put_user (kbuf->st_mtime, &ubuf->st_mtime) ||	    __put_user (kbuf->st_ctime, &ubuf->st_ctime) ||	    __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||	    __put_user (kbuf->st_blocks, &ubuf->st_blocks))		return -EFAULT;	return 0;}asmlinkage longsys32_stat64(char * filename, struct stat64 *statbuf){	int ret;	struct stat s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_newstat(filename, &s);	set_fs (old_fs);	if (putstat64 (statbuf, &s))		return -EFAULT;	return ret;}asmlinkage longsys32_lstat64(char * filename, struct stat64 *statbuf){	int ret;	struct stat s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_newlstat(filename, &s);	set_fs (old_fs);	if (putstat64 (statbuf, &s))		return -EFAULT;	return ret;}asmlinkage longsys32_fstat64(unsigned int fd, struct stat64 *statbuf){	int ret;	struct stat s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_newfstat(fd, &s);	set_fs (old_fs);	if (putstat64 (statbuf, &s))		return -EFAULT;	return ret;}/* Don't set O_LARGEFILE implicitely. */asmlinkage long sys32_open(const char * filename, int flags, int mode){	char * tmp;	int fd, error;	tmp = getname(filename);	fd = PTR_ERR(tmp);	if (!IS_ERR(tmp)) {		fd = get_unused_fd();		if (fd >= 0) {			struct file *f = filp_open(tmp, flags, mode);			error = PTR_ERR(f);			if (IS_ERR(f))				goto out_error;			fd_install(fd, f);		}out:		putname(tmp);	}	return fd;out_error:	put_unused_fd(fd);	fd = error;	goto out;}/* * Linux/i386 didn't use to be able to handle more than * 4 system call parameters, so these system calls used a memory * block for parameter passing.. */struct mmap_arg_struct {	unsigned int addr;	unsigned int len;	unsigned int prot;	unsigned int flags;	unsigned int fd;	unsigned int offset;};asmlinkage longsys32_mmap(struct mmap_arg_struct *arg){	struct mmap_arg_struct a;	struct file *file = NULL;	unsigned long retval;	struct mm_struct *mm ;	if (copy_from_user(&a, arg, sizeof(a)))		return -EFAULT;	if (a.offset & ~PAGE_MASK)		return -EINVAL; 	if (!(a.flags & MAP_ANONYMOUS)) {		file = fget(a.fd);		if (!file)			return -EBADF;	}		if (a.prot & PROT_READ) 		a.prot |= PROT_EXEC; 	mm = current->mm; 	down_write(&mm->mmap_sem); 	retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT);	if (file)		fput(file);	up_write(&mm->mmap_sem); 	return retval;}extern asmlinkage long sys_mprotect(unsigned long start,size_t len,unsigned long prot);asmlinkage long sys32_mprotect(unsigned long start, size_t len, unsigned long prot){	if (prot & PROT_READ) 		prot |= PROT_EXEC; 	return sys_mprotect(start,len,prot); }asmlinkage longsys32_pipe(int *fd){	int retval;	int fds[2];	retval = do_pipe(fds);	if (retval)		goto out;	if (copy_to_user(fd, fds, sizeof(fds)))		retval = -EFAULT;  out:	return retval;}asmlinkage longsys32_rt_sigaction(int sig, struct sigaction32 *act,		   struct sigaction32 *oact,  unsigned int sigsetsize){	struct k_sigaction new_ka, old_ka;	int ret;	sigset32_t set32;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset32_t))		return -EINVAL;	if (act) {		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||		    __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||		    __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer)||		    __copy_from_user(&set32, &act->sa_mask, sizeof(sigset32_t)))			return -EFAULT;		/* FIXME: here we rely on _IA32_NSIG_WORS to be >= than _NSIG_WORDS << 1 */		switch (_NSIG_WORDS) {		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]				| (((long)set32.sig[7]) << 32);		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]				| (((long)set32.sig[5]) << 32);		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]				| (((long)set32.sig[3]) << 32);		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]				| (((long)set32.sig[1]) << 32);		}	}	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		/* FIXME: here we rely on _IA32_NSIG_WORS to be >= than _NSIG_WORDS << 1 */		switch (_NSIG_WORDS) {		case 4:			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);			set32.sig[6] = old_ka.sa.sa_mask.sig[3];		case 3:			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);			set32.sig[4] = old_ka.sa.sa_mask.sig[2];		case 2:			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);			set32.sig[2] = old_ka.sa.sa_mask.sig[1];		case 1:			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);			set32.sig[0] = old_ka.sa.sa_mask.sig[0];		}		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||		    __put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) ||		    __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) ||		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||		    __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset32_t)))			return -EFAULT;	}	return ret;}asmlinkage longsys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact){        struct k_sigaction new_ka, old_ka;        int ret;        if (act) {		old_sigset32_t mask;		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||		    __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||		    __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer) ||		    __get_user(mask, &act->sa_mask))			return -EFAULT;		siginitset(&new_ka.sa.sa_mask, mask);        }        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||		    __put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) ||		    __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) ||		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))			return -EFAULT;        }	return ret;}extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,					  size_t sigsetsize);asmlinkage longsys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,		     unsigned int sigsetsize){	sigset_t s;	sigset32_t s32;	int ret;	mm_segment_t old_fs = get_fs();		if (set) {		if (copy_from_user (&s32, set, sizeof(sigset32_t)))			return -EFAULT;		switch (_NSIG_WORDS) {		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);		}	}	set_fs (KERNEL_DS);	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,				 sigsetsize); 	set_fs (old_fs);	if (ret) return ret;	if (oset) {		switch (_NSIG_WORDS) {		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];		}		if (copy_to_user (oset, &s32, sizeof(sigset32_t)))			return -EFAULT;	}	return 0;}static intput_statfs (struct statfs32 *ubuf, struct statfs *kbuf){	if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct statfs32)) ||	    __put_user (kbuf->f_type, &ubuf->f_type) ||	    __put_user (kbuf->f_bsize, &ubuf->f_bsize) ||	    __put_user (kbuf->f_blocks, &ubuf->f_blocks) ||	    __put_user (kbuf->f_bfree, &ubuf->f_bfree) ||	    __put_user (kbuf->f_bavail, &ubuf->f_bavail) ||	    __put_user (kbuf->f_files, &ubuf->f_files) ||	    __put_user (kbuf->f_ffree, &ubuf->f_ffree) ||	    __put_user (kbuf->f_namelen, &ubuf->f_namelen) ||	    __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||	    __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]))		return -EFAULT;	return 0;}extern asmlinkage long sys_statfs(const char * path, struct statfs * buf);asmlinkage longsys32_statfs(const char * path, struct statfs32 *buf){	int ret;	struct statfs s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_statfs((const char *)path, &s);	set_fs (old_fs);	if (put_statfs(buf, &s))		return -EFAULT;	return ret;}extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);asmlinkage longsys32_fstatfs(unsigned int fd, struct statfs32 *buf){	int ret;	struct statfs s;	mm_segment_t old_fs = get_fs();		set_fs (KERNEL_DS);	ret = sys_fstatfs(fd, &s);	set_fs (old_fs);	if (put_statfs(buf, &s))		return -EFAULT;

⌨️ 快捷键说明

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