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(¤t->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(¤t->blocked, ¤t->blocked, &these); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); current->state = TASK_INTERRUPTIBLE; timeout = schedule_timeout(timeout); spin_lock_irq(¤t->sighand->siglock); sig = dequeue_signal(current, &these, &info); current->blocked = current->real_blocked; siginitset(¤t->real_blocked, 0); recalc_sigpending(); } } spin_unlock_irq(¤t->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 + -
显示快捷键?