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

📄 compat_linux.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
struct getdents_callback32 {	struct linux_dirent32 * current_dir;	struct linux_dirent32 * previous;	int count;	int error;};static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,		   unsigned int d_type){	struct linux_dirent32 * dirent;	struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);	buf->error = -EINVAL;	/* only used if we fail.. */	if (reclen > buf->count)		return -EINVAL;	dirent = buf->previous;	if (dirent)		put_user(offset, &dirent->d_off);	dirent = buf->current_dir;	buf->previous = dirent;	put_user(ino, &dirent->d_ino);	put_user(reclen, &dirent->d_reclen);	copy_to_user(dirent->d_name, name, namlen);	put_user(0, dirent->d_name + namlen);	buf->current_dir = ((void *)dirent) + reclen;	buf->count -= reclen;	return 0;}asmlinkage long sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count){	struct file * file;	struct linux_dirent32 * lastdirent;	struct getdents_callback32 buf;	int error = -EBADF;	file = fget(fd);	if (!file)		goto out;	buf.current_dir = dirent;	buf.previous = NULL;	buf.count = count;	buf.error = 0;	error = vfs_readdir(file, filldir, &buf);	if (error < 0)		goto out_putf;	lastdirent = buf.previous;	error = buf.error;	if(lastdirent) {		put_user(file->f_pos, &lastdirent->d_off);		error = count - buf.count;	}out_putf:	fput(file);out:	return error;}/* end of readdir & getdents */int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf){	int err;	if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))		return -EOVERFLOW;	err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);	err |= put_user(stat->ino, &statbuf->st_ino);	err |= put_user(stat->mode, &statbuf->st_mode);	err |= put_user(stat->nlink, &statbuf->st_nlink);	err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);	err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);	err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);	err |= put_user(stat->size, &statbuf->st_size);	err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);	err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);	err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);	err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);	err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);	err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);	err |= put_user(stat->blksize, &statbuf->st_blksize);	err |= put_user(stat->blocks, &statbuf->st_blocks);/* fixme	err |= put_user(0, &statbuf->__unused4[0]);	err |= put_user(0, &statbuf->__unused4[1]);*/	return err;}struct sysinfo32 {        s32 uptime;        u32 loads[3];        u32 totalram;        u32 freeram;        u32 sharedram;        u32 bufferram;        u32 totalswap;        u32 freeswap;        unsigned short procs;	unsigned short pads;	u32 totalhigh;	u32 freehigh;	unsigned int mem_unit;        char _f[8];};asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info){	struct sysinfo s;	int ret, err;	mm_segment_t old_fs = get_fs ();		set_fs (KERNEL_DS);	ret = sys_sysinfo(&s);	set_fs (old_fs);	err = put_user (s.uptime, &info->uptime);	err |= __put_user (s.loads[0], &info->loads[0]);	err |= __put_user (s.loads[1], &info->loads[1]);	err |= __put_user (s.loads[2], &info->loads[2]);	err |= __put_user (s.totalram, &info->totalram);	err |= __put_user (s.freeram, &info->freeram);	err |= __put_user (s.sharedram, &info->sharedram);	err |= __put_user (s.bufferram, &info->bufferram);	err |= __put_user (s.totalswap, &info->totalswap);	err |= __put_user (s.freeswap, &info->freeswap);	err |= __put_user (s.procs, &info->procs);	err |= __put_user (s.totalhigh, &info->totalhigh);	err |= __put_user (s.freehigh, &info->freehigh);	err |= __put_user (s.mem_unit, &info->mem_unit);	if (err)		return -EFAULT;	return ret;}asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,				struct compat_timespec __user *interval){	struct timespec t;	int ret;	mm_segment_t old_fs = get_fs ();		set_fs (KERNEL_DS);	ret = sys_sched_rr_get_interval(pid, &t);	set_fs (old_fs);	if (put_compat_timespec(&t, interval))		return -EFAULT;	return ret;}asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,			compat_sigset_t __user *oset, size_t sigsetsize){	sigset_t s;	compat_sigset_t s32;	int ret;	mm_segment_t old_fs = get_fs();		if (set) {		if (copy_from_user (&s32, set, sizeof(compat_sigset_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(compat_sigset_t)))			return -EFAULT;	}	return 0;}asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,				size_t sigsetsize){	sigset_t s;	compat_sigset_t s32;	int ret;	mm_segment_t old_fs = get_fs();			set_fs (KERNEL_DS);	ret = sys_rt_sigpending(&s, sigsetsize);	set_fs (old_fs);	if (!ret) {		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 (set, &s32, sizeof(compat_sigset_t)))			return -EFAULT;	}	return ret;}extern intcopy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);asmlinkage longsys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,		      struct compat_timespec *uts, size_t sigsetsize){	int ret, sig;	sigset_t these;	compat_sigset_t these32;	struct timespec ts;	siginfo_t info;	long timeout = 0;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset_t))		return -EINVAL;	if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))		return -EFAULT;	switch (_NSIG_WORDS) {	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);	}			/*	 * Invert the set of allowed signals to get those we	 * want to block.	 */	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));	signotset(&these);	if (uts) {		if (get_compat_timespec(&ts, uts))			return -EINVAL;		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0		    || ts.tv_sec < 0)			return -EINVAL;	}	spin_lock_irq(&current->sighand->siglock);	sig = dequeue_signal(current, &these, &info);	if (!sig) {		/* None ready -- temporarily unblock those we're interested		   in so that we'll be awakened when they arrive.  */		current->real_blocked = current->blocked;		sigandsets(&current->blocked, &current->blocked, &these);		recalc_sigpending();		spin_unlock_irq(&current->sighand->siglock);		timeout = MAX_SCHEDULE_TIMEOUT;		if (uts)			timeout = (timespec_to_jiffies(&ts)				   + (ts.tv_sec || ts.tv_nsec));		current->state = TASK_INTERRUPTIBLE;		timeout = schedule_timeout(timeout);		spin_lock_irq(&current->sighand->siglock);		sig = dequeue_signal(current, &these, &info);		current->blocked = current->real_blocked;		siginitset(&current->real_blocked, 0);		recalc_sigpending();	}	spin_unlock_irq(&current->sighand->siglock);	if (sig) {		ret = sig;		if (uinfo) {			if (copy_siginfo_to_user32(uinfo, &info))				ret = -EFAULT;		}	} else {		ret = -EAGAIN;		if (timeout)			ret = -EINTR;	}	return ret;}asmlinkage longsys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo){	siginfo_t info;	int ret;	mm_segment_t old_fs = get_fs();		if (copy_siginfo_from_user32(&info, uinfo))		return -EFAULT;	set_fs (KERNEL_DS);	ret = sys_rt_sigqueueinfo(pid, sig, &info);	set_fs (old_fs);	return ret;}/* * sys32_execve() executes a new program after the asm stub has set * things up for us.  This should basically do what I want it to. */asmlinkage longsys32_execve(struct pt_regs regs){        int error;        char * filename;        filename = getname(compat_ptr(regs.orig_gpr2));        error = PTR_ERR(filename);        if (IS_ERR(filename))                goto out;        error = compat_do_execve(filename, compat_ptr(regs.gprs[3]),				 compat_ptr(regs.gprs[4]), &regs);	if (error == 0)	{		current->ptrace &= ~PT_DTRACE;		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;

⌨️ 快捷键说明

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