sys_sparc32.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,739 行 · 第 1/4 页

C
1,739
字号
{	int err;	if (stat->size > MAX_NON_LFS || !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(0, &statbuf->__unused1);	err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);	err |= put_user(0, &statbuf->__unused2);	err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);	err |= put_user(0, &statbuf->__unused3);	err |= put_user(stat->blksize, &statbuf->st_blksize);	err |= put_user(stat->blocks, &statbuf->st_blocks);	err |= put_user(0, &statbuf->__unused4[0]);	err |= put_user(0, &statbuf->__unused4[1]);	return err;}asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2){	return sys_sysfs(option, arg1, arg2);}struct sysinfo32 {        s32 uptime;        u32 loads[3];        u32 totalram;        u32 freeram;        u32 sharedram;        u32 bufferram;        u32 totalswap;        u32 freeswap;        unsigned short procs;	unsigned short pad;	u32 totalhigh;	u32 freehigh;	u32 mem_unit;	char _f[20-2*sizeof(int)-sizeof(int)];};asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info){	struct sysinfo s;	int ret, err;	int bitcount = 0;	mm_segment_t old_fs = get_fs ();		set_fs(KERNEL_DS);	ret = sys_sysinfo((struct sysinfo __user *) &s);	set_fs(old_fs);	/* Check to see if any memory value is too large for 32-bit and         * scale down if needed.         */	if ((s.totalram >> 32) || (s.totalswap >> 32)) {		while (s.mem_unit < PAGE_SIZE) {			s.mem_unit <<= 1;			bitcount++;		}		s.totalram >>= bitcount;		s.freeram >>= bitcount;		s.sharedram >>= bitcount;		s.bufferram >>= bitcount;		s.totalswap >>= bitcount;		s.freeswap >>= bitcount;		s.totalhigh >>= bitcount;		s.freehigh >>= bitcount;	}	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 compat_sys_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, (struct timespec __user *) &t);	set_fs (old_fs);	if (put_compat_timespec(&t, interval))		return -EFAULT;	return ret;}asmlinkage long compat_sys_rt_sigprocmask(int how,					  compat_sigset_t __user *set,					  compat_sigset_t __user *oset,					  compat_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 ? (sigset_t __user *) &s : NULL,				 oset ? (sigset_t __user *) &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,				    compat_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((sigset_t __user *) &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;}asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,				      siginfo_t32 __user *uinfo,				      struct compat_timespec __user *uts,				      compat_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) {		timeout = MAX_SCHEDULE_TIMEOUT;		if (uts)			timeout = (timespec_to_jiffies(&ts)				   + (ts.tv_sec || ts.tv_nsec));		if (timeout) {			/* None ready -- temporarily unblock those we're			 * interested while we are sleeping 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);			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 long compat_sys_rt_sigqueueinfo(int pid, int sig,					   siginfo_t32 __user *uinfo){	siginfo_t info;	int ret;	mm_segment_t old_fs = get_fs();		if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))		return -EFAULT;	set_fs (KERNEL_DS);	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);	set_fs (old_fs);	return ret;}asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,				     struct old_sigaction32 __user *oact){        struct k_sigaction new_ka, old_ka;        int ret;	if (sig < 0) {		set_thread_flag(TIF_NEWSIGNALS);		sig = -sig;	}        if (act) {		compat_old_sigset_t mask;		u32 u_handler, u_restorer;				ret = get_user(u_handler, &act->sa_handler);		new_ka.sa.sa_handler =  compat_ptr(u_handler);		ret |= __get_user(u_restorer, &act->sa_restorer);		new_ka.sa.sa_restorer = compat_ptr(u_restorer);		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);		ret |= __get_user(mask, &act->sa_mask);		if (ret)			return ret;		new_ka.ka_restorer = NULL;		siginitset(&new_ka.sa.sa_mask, mask);        }        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);		ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);		ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);        }	return ret;}asmlinkage long compat_sys_rt_sigaction(int sig,					struct sigaction32 __user *act,					struct sigaction32 __user *oact,					void __user *restorer,					compat_size_t sigsetsize){        struct k_sigaction new_ka, old_ka;        int ret;	compat_sigset_t set32;        /* XXX: Don't preclude handling different sized sigset_t's.  */        if (sigsetsize != sizeof(compat_sigset_t))                return -EINVAL;	/* All tasks which use RT signals (effectively) use	 * new style signals.	 */	set_thread_flag(TIF_NEWSIGNALS);        if (act) {		u32 u_handler, u_restorer;		new_ka.ka_restorer = restorer;		ret = get_user(u_handler, &act->sa_handler);		new_ka.sa.sa_handler =  compat_ptr(u_handler);		ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));		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 |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);		ret |= __get_user(u_restorer, &act->sa_restorer);		new_ka.sa.sa_restorer = compat_ptr(u_restorer);                if (ret)                	return -EFAULT;	}	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		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];		}		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);		ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);		ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);		if (ret)			ret = -EFAULT;        }        return ret;}/* * sparc32_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 long sparc32_execve(struct pt_regs *regs){	int error, base = 0;	char *filename;	/* User register window flush is done by entry.S */	/* Check for indirect call. */	if ((u32)regs->u_regs[UREG_G1] == 0)		base = 1;	filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));	error = PTR_ERR(filename);	if (IS_ERR(filename))		goto out;	error = compat_do_execve(filename,				 compat_ptr(regs->u_regs[base + UREG_I1]),				 compat_ptr(regs->u_regs[base + UREG_I2]), regs);	putname(filename);	if (!error) {		fprs_write(0);		current_thread_info()->xfsr[0] = 0;		current_thread_info()->fpsaved[0] = 0;		regs->tstate &= ~TSTATE_PEF;		current->ptrace &= ~PT_DTRACE;	}out:	return error;}#ifdef CONFIG_MODULESasmlinkage long sys32_init_module(void __user *umod, u32 len,				  const char __user *uargs){	return sys_init_module(umod, len, uargs);}asmlinkage long sys32_delete_module(const char __user *name_user,				    unsigned int flags){	return sys_delete_module(name_user, flags);}#else /* CONFIG_MODULES */asmlinkage long sys32_init_module(const char __user *name_user,				  struct module __user *mod_user){	return -ENOSYS;}asmlinkage long sys32_delete_module(const char __user *name_user)

⌨️ 快捷键说明

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