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

📄 compat_linux.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		task_unlock(current);		current->thread.fp_regs.fpc=0;		__asm__ __volatile__		        ("sr  0,0\n\t"		         "sfpc 0,0\n\t"			 : : :"0");	}        putname(filename);out:        return error;}#ifdef CONFIG_MODULESasmlinkage longsys32_init_module(void __user *umod, unsigned long len,		const char __user *uargs){	return sys_init_module(umod, len, uargs);}asmlinkage longsys32_delete_module(const char __user *name_user, unsigned int flags){	return sys_delete_module(name_user, flags);}#else /* CONFIG_MODULES */asmlinkage longsys32_init_module(void __user *umod, unsigned long len,		const char __user *uargs){	return -ENOSYS;}asmlinkage longsys32_delete_module(const char __user *name_user, unsigned int flags){	return -ENOSYS;}#endif  /* CONFIG_MODULES *//* Translations due to time_t size differences.  Which affects all   sorts of things, like timeval and itimerval.  */extern struct timezone sys_tz;asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz){	if (tv) {		struct timeval ktv;		do_gettimeofday(&ktv);		if (put_tv32(tv, &ktv))			return -EFAULT;	}	if (tz) {		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))			return -EFAULT;	}	return 0;}static inline long get_ts32(struct timespec *o, struct compat_timeval *i){	long usec;	if (!access_ok(VERIFY_READ, i, sizeof(*i)))		return -EFAULT;	if (__get_user(o->tv_sec, &i->tv_sec))		return -EFAULT;	if (__get_user(usec, &i->tv_usec))		return -EFAULT;	o->tv_nsec = usec * 1000;	return 0;}asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz){	struct timespec kts;	struct timezone ktz; 	if (tv) {		if (get_ts32(&kts, tv))			return -EFAULT;	}	if (tz) {		if (copy_from_user(&ktz, tz, sizeof(ktz)))			return -EFAULT;	}	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);}/* These are here just in case some old sparc32 binary calls it. */asmlinkage long sys32_pause(void){	current->state = TASK_INTERRUPTIBLE;	schedule();	return -ERESTARTNOHAND;}asmlinkage long sys32_pread64(unsigned int fd, char *ubuf,				size_t count, u32 poshi, u32 poslo){	if ((compat_ssize_t) count < 0)		return -EINVAL;	return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));}asmlinkage long sys32_pwrite64(unsigned int fd, const char *ubuf,				size_t count, u32 poshi, u32 poslo){	if ((compat_ssize_t) count < 0)		return -EINVAL;	return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));}asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count){	return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);}asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size_t count){	mm_segment_t old_fs = get_fs();	int ret;	off_t of;		if (offset && get_user(of, offset))		return -EFAULT;			set_fs(KERNEL_DS);	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);	set_fs(old_fs);		if (offset && put_user(of, offset))		return -EFAULT;			return ret;}asmlinkage long sys32_sendfile64(int out_fd, int in_fd,				compat_loff_t *offset, s32 count){	mm_segment_t old_fs = get_fs();	int ret;	loff_t lof;		if (offset && get_user(lof, offset))		return -EFAULT;			set_fs(KERNEL_DS);	ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count);	set_fs(old_fs);		if (offset && put_user(lof, offset))		return -EFAULT;			return ret;}/* Handle adjtimex compatibility. */struct timex32 {	u32 modes;	s32 offset, freq, maxerror, esterror;	s32 status, constant, precision, tolerance;	struct compat_timeval time;	s32 tick;	s32 ppsfreq, jitter, shift, stabil;	s32 jitcnt, calcnt, errcnt, stbcnt;	s32  :32; s32  :32; s32  :32; s32  :32;	s32  :32; s32  :32; s32  :32; s32  :32;	s32  :32; s32  :32; s32  :32; s32  :32;};extern int do_adjtimex(struct timex *);asmlinkage long sys32_adjtimex(struct timex32 *utp){	struct timex txc;	int ret;	memset(&txc, 0, sizeof(struct timex));	if(get_user(txc.modes, &utp->modes) ||	   __get_user(txc.offset, &utp->offset) ||	   __get_user(txc.freq, &utp->freq) ||	   __get_user(txc.maxerror, &utp->maxerror) ||	   __get_user(txc.esterror, &utp->esterror) ||	   __get_user(txc.status, &utp->status) ||	   __get_user(txc.constant, &utp->constant) ||	   __get_user(txc.precision, &utp->precision) ||	   __get_user(txc.tolerance, &utp->tolerance) ||	   __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||	   __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||	   __get_user(txc.tick, &utp->tick) ||	   __get_user(txc.ppsfreq, &utp->ppsfreq) ||	   __get_user(txc.jitter, &utp->jitter) ||	   __get_user(txc.shift, &utp->shift) ||	   __get_user(txc.stabil, &utp->stabil) ||	   __get_user(txc.jitcnt, &utp->jitcnt) ||	   __get_user(txc.calcnt, &utp->calcnt) ||	   __get_user(txc.errcnt, &utp->errcnt) ||	   __get_user(txc.stbcnt, &utp->stbcnt))		return -EFAULT;	ret = do_adjtimex(&txc);	if(put_user(txc.modes, &utp->modes) ||	   __put_user(txc.offset, &utp->offset) ||	   __put_user(txc.freq, &utp->freq) ||	   __put_user(txc.maxerror, &utp->maxerror) ||	   __put_user(txc.esterror, &utp->esterror) ||	   __put_user(txc.status, &utp->status) ||	   __put_user(txc.constant, &utp->constant) ||	   __put_user(txc.precision, &utp->precision) ||	   __put_user(txc.tolerance, &utp->tolerance) ||	   __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||	   __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||	   __put_user(txc.tick, &utp->tick) ||	   __put_user(txc.ppsfreq, &utp->ppsfreq) ||	   __put_user(txc.jitter, &utp->jitter) ||	   __put_user(txc.shift, &utp->shift) ||	   __put_user(txc.stabil, &utp->stabil) ||	   __put_user(txc.jitcnt, &utp->jitcnt) ||	   __put_user(txc.calcnt, &utp->calcnt) ||	   __put_user(txc.errcnt, &utp->errcnt) ||	   __put_user(txc.stbcnt, &utp->stbcnt))		ret = -EFAULT;	return ret;}#ifdef CONFIG_SYSCTLstruct __sysctl_args32 {	u32 name;	int nlen;	u32 oldval;	u32 oldlenp;	u32 newval;	u32 newlen;	u32 __unused[4];};asmlinkage long sys32_sysctl(struct __sysctl_args32 *args){	struct __sysctl_args32 tmp;	int error;	size_t oldlen, *oldlenp = NULL;	unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;	if (copy_from_user(&tmp, args, sizeof(tmp)))		return -EFAULT;	if (tmp.oldval && tmp.oldlenp) {		/* Duh, this is ugly and might not work if sysctl_args		   is in read-only memory, but do_sysctl does indirectly		   a lot of uaccess in both directions and we'd have to		   basically copy the whole sysctl.c here, and		   glibc's __sysctl uses rw memory for the structure		   anyway.  */		if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||		    put_user(oldlen, (size_t *)addr))			return -EFAULT;		oldlenp = (size_t *)addr;	}	lock_kernel();	error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),			  oldlenp, (void *)A(tmp.newval), tmp.newlen);	unlock_kernel();	if (oldlenp) {		if (!error) {			if (get_user(oldlen, (size_t *)addr) ||			    put_user(oldlen, (u32 *)A(tmp.oldlenp)))				error = -EFAULT;		}		copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));	}	return error;}#endifstruct stat64_emu31 {	unsigned long long  st_dev;	unsigned int    __pad1;#define STAT64_HAS_BROKEN_ST_INO        1	u32             __st_ino;	unsigned int    st_mode;	unsigned int    st_nlink;	u32             st_uid;	u32             st_gid;	unsigned long long  st_rdev;	unsigned int    __pad3;	long            st_size;	u32             st_blksize;	unsigned char   __pad4[4];	u32             __pad5;     /* future possible st_blocks high bits */	u32             st_blocks;  /* Number 512-byte blocks allocated. */	u32             st_atime;	u32             __pad6;	u32             st_mtime;	u32             __pad7;	u32             st_ctime;	u32             __pad8;     /* will be high 32 bits of ctime someday */	unsigned long   st_ino;};	static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat){	struct stat64_emu31 tmp;	memset(&tmp, 0, sizeof(tmp));	tmp.st_dev = huge_encode_dev(stat->dev);	tmp.st_ino = stat->ino;	tmp.__st_ino = (u32)stat->ino;	tmp.st_mode = stat->mode;	tmp.st_nlink = (unsigned int)stat->nlink;	tmp.st_uid = stat->uid;	tmp.st_gid = stat->gid;	tmp.st_rdev = huge_encode_dev(stat->rdev);	tmp.st_size = stat->size;	tmp.st_blksize = (u32)stat->blksize;	tmp.st_blocks = (u32)stat->blocks;	tmp.st_atime = (u32)stat->atime.tv_sec;	tmp.st_mtime = (u32)stat->mtime.tv_sec;	tmp.st_ctime = (u32)stat->ctime.tv_sec;	return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; }asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf){	struct kstat stat;	int ret = vfs_stat(filename, &stat);	if (!ret)		ret = cp_stat64(statbuf, &stat);	return ret;}asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf){	struct kstat stat;	int ret = vfs_lstat(filename, &stat);	if (!ret)		ret = cp_stat64(statbuf, &stat);	return ret;}asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf){	struct kstat stat;	int ret = vfs_fstat(fd, &stat);	if (!ret)		ret = cp_stat64(statbuf, &stat);	return ret;}/* * 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_emu31 {	u32	addr;	u32	len;	u32	prot;	u32	flags;	u32	fd;	u32	offset;};/* common code for old and new mmaps */static inline long do_mmap2(	unsigned long addr, unsigned long len,	unsigned long prot, unsigned long flags,	unsigned long fd, unsigned long pgoff){	struct file * file = NULL;	unsigned long error = -EBADF;	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);	if (!(flags & MAP_ANONYMOUS)) {		file = fget(fd);		if (!file)			goto out;	}	down_write(&current->mm->mmap_sem);	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);	if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) {		/* Result is out of bounds.  */		do_munmap(current->mm, addr, len);		error = -ENOMEM;	}	up_write(&current->mm->mmap_sem);	if (file)		fput(file);out:    	return error;}asmlinkage unsigned longold32_mmap(struct mmap_arg_struct_emu31 *arg){	struct mmap_arg_struct_emu31 a;	int error = -EFAULT;	if (copy_from_user(&a, arg, sizeof(a)))		goto out;	error = -EINVAL;	if (a.offset & ~PAGE_MASK)		goto out;	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out:	return error;}asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 *arg){	struct mmap_arg_struct_emu31 a;	int error = -EFAULT;	if (copy_from_user(&a, arg, sizeof(a)))		goto out;	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);out:	return error;}asmlinkage long sys32_read(unsigned int fd, char * buf, size_t count){	if ((compat_ssize_t) count < 0)		return -EINVAL; 	return sys_read(fd, buf, count);}asmlinkage long sys32_write(unsigned int fd, char * buf, size_t count){	if ((compat_ssize_t) count < 0)		return -EINVAL; 	return sys_write(fd, buf, count);}asmlinkage long sys32_clone(struct pt_regs regs){        unsigned long clone_flags;        unsigned long newsp;	int *parent_tidptr, *child_tidptr;        clone_flags = regs.gprs[3] & 0xffffffffUL;        newsp = regs.orig_gpr2 & 0x7fffffffUL;	parent_tidptr = (int *) (regs.gprs[4] & 0x7fffffffUL);	child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL);        if (!newsp)                newsp = regs.gprs[15];        return do_fork(clone_flags, newsp, &regs, 0,		       parent_tidptr, child_tidptr);}/* * Wrapper function for sys_timer_create. */extern asmlinkage longsys_timer_create(clockid_t, struct sigevent *, timer_t *);asmlinkage longsys32_timer_create(clockid_t which_clock, struct compat_sigevent *se32,		timer_t *timer_id){	struct sigevent se;	timer_t ktimer_id;	mm_segment_t old_fs;	long ret;	if (se32 == NULL)		return sys_timer_create(which_clock, NULL, timer_id);	if (get_compat_sigevent(&se, se32))		return -EFAULT;	old_fs = get_fs();	set_fs(KERNEL_DS);	ret = sys_timer_create(which_clock, &se, &ktimer_id);	set_fs(old_fs);	if (!ret)		ret = put_user (ktimer_id, timer_id);	return ret;}/* * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} * because the 31 bit values differ from the 64 bit values. */asmlinkage longsys32_fadvise64(int fd, loff_t offset, size_t len, int advise){	if (advise == 4)		advise = POSIX_FADV_DONTNEED;	else if (advise == 5)		advise = POSIX_FADV_NOREUSE;	return sys_fadvise64(fd, offset, len, advise);}struct fadvise64_64_args {	int fd;	long long offset;	long long len;	int advice;};asmlinkage longsys32_fadvise64_64(struct fadvise64_64_args __user *args){	struct fadvise64_64_args a;	if ( copy_from_user(&a, args, sizeof(a)) )		return -EFAULT;	if (a.advice == 4)		a.advice = POSIX_FADV_DONTNEED;	else if (a.advice == 5)		a.advice = POSIX_FADV_NOREUSE;	return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);}

⌨️ 快捷键说明

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