sys_sparc32.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,739 行 · 第 1/4 页
C
1,739 行
{ 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 __user *tv, struct timezone __user *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 __user *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 __user *tv, struct timezone __user *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);}asmlinkage long sys32_utimes(char __user *filename, struct compat_timeval __user *tvs){ struct timeval ktvs[2]; if (tvs) { if (get_tv32(&ktvs[0], tvs) || get_tv32(&ktvs[1], 1+tvs)) return -EFAULT; } return do_utimes(filename, (tvs ? &ktvs[0] : 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 compat_ssize_t sys32_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, unsigned long poshi, unsigned long poslo){ return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo);}asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count, unsigned long poshi, unsigned long poslo){ return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo);}asmlinkage long compat_sys_readahead(int fd, unsigned long offhi, unsigned long offlo, compat_size_t count){ return sys_readahead(fd, (offhi << 32) | offlo, count);}long compat_sys_fadvise64(int fd, unsigned long offhi, unsigned long offlo, compat_size_t len, int advice){ return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice);}long compat_sys_fadvise64_64(int fd, unsigned long offhi, unsigned long offlo, unsigned long lenhi, unsigned long lenlo, int advice){ return sys_fadvise64_64(fd, (offhi << 32) | offlo, (lenhi << 32) | lenlo, advice);}asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, compat_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 ? (off_t __user *) &of : NULL, count); set_fs(old_fs); if (offset && put_user(of, offset)) return -EFAULT; return ret;}asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, compat_size_t 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 ? (loff_t __user *) &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 __user *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;}/* This is just a version for 32-bit applications which does * not force O_LARGEFILE on. */asmlinkage long sparc32_open(const char __user *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;}extern unsigned long do_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr); asmlinkage unsigned long sys32_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, u32 __new_addr){ struct vm_area_struct *vma; unsigned long ret = -EINVAL; unsigned long new_addr = __new_addr; if (old_len > 0xf0000000UL || new_len > 0xf0000000UL) goto out; if (addr > 0xf0000000UL - old_len) goto out; down_write(¤t->mm->mmap_sem); if (flags & MREMAP_FIXED) { if (new_addr > 0xf0000000UL - new_len) goto out_sem; } else if (addr > 0xf0000000UL - new_len) { unsigned long map_flags = 0; struct file *file = NULL; ret = -ENOMEM; if (!(flags & MREMAP_MAYMOVE)) goto out_sem; vma = find_vma(current->mm, addr); if (vma) { if (vma->vm_flags & VM_SHARED) map_flags |= MAP_SHARED; file = vma->vm_file; } /* MREMAP_FIXED checked above. */ new_addr = get_unmapped_area(file, addr, new_len, vma ? vma->vm_pgoff : 0, map_flags); ret = new_addr; if (new_addr & ~PAGE_MASK) goto out_sem; flags |= MREMAP_FIXED; } ret = do_mremap(addr, old_len, new_len, flags, new_addr);out_sem: up_write(¤t->mm->mmap_sem);out: return ret; }struct __sysctl_args32 { u32 name; int nlen; u32 oldval; u32 oldlenp; u32 newval; u32 newlen; u32 __unused[4];};asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args){#ifndef CONFIG_SYSCTL return -ENOSYS;#else struct __sysctl_args32 tmp; int error; size_t oldlen, __user *oldlenp = NULL; unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL; 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 __user *)(unsigned long)tmp.oldlenp) || put_user(oldlen, (size_t __user *)addr)) return -EFAULT; oldlenp = (size_t __user *)addr; } lock_kernel(); error = do_sysctl((int __user *)(unsigned long) tmp.name, tmp.nlen, (void __user *)(unsigned long) tmp.oldval, oldlenp, (void __user *)(unsigned long) tmp.newval, tmp.newlen); unlock_kernel(); if (oldlenp) { if (!error) { if (get_user(oldlen, (size_t __user *)addr) || put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp)) error = -EFAULT; } copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); } return error;#endif}long sys32_lookup_dcookie(unsigned long cookie_high, unsigned long cookie_low, char __user *buf, size_t len){ return sys_lookup_dcookie((cookie_high << 32) | cookie_low, buf, len);}extern asmlinkage longsys_timer_create(clockid_t which_clock, struct sigevent __user *timer_event_spec, timer_t __user *created_timer_id);longsys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id){ struct sigevent se; mm_segment_t oldfs; timer_t t; long err; if (se32 == NULL) return sys_timer_create(clock, NULL, timer_id); memset(&se, 0, sizeof(struct sigevent)); if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) || __get_user(se.sigev_signo, &se32->sigev_signo) || __get_user(se.sigev_notify, &se32->sigev_notify) || __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad, sizeof(se._sigev_un._pad))) return -EFAULT; if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) return -EFAULT; oldfs = get_fs(); set_fs(KERNEL_DS); err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t); set_fs(oldfs); if (!err) err = __put_user (t, timer_id); return err;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?