📄 sys_sparc32.c
字号:
set_fs (KERNEL_DS); ret = sys_fstatfs(fd, &s); set_fs (old_fs); if (put_statfs(buf, &s)) return -EFAULT; return ret;}extern asmlinkage long sys_truncate(const char * path, unsigned long length);extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low){ if ((int)high < 0) return -EINVAL; else return sys_truncate(path, (high << 32) | low);}asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low){ if ((int)high < 0) return -EINVAL; else return sys_ftruncate(fd, (high << 32) | low);}extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);struct utimbuf32 { __kernel_time_t32 actime, modtime;};asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times){ struct utimbuf t; mm_segment_t old_fs; int ret; char *filenam; if (!times) return sys_utime(filename, NULL); if (get_user (t.actime, ×->actime) || __get_user (t.modtime, ×->modtime)) return -EFAULT; filenam = getname (filename); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_utime(filenam, &t); set_fs (old_fs); putname (filenam); } return ret;}struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);static long do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, u32 count){ unsigned long tot_len; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack, *ivp; struct inode *inode; long retval, i; io_fn_t fn; iov_fn_t fnv; /* First get the "struct iovec" from user memory and * verify all the pointers */ if (!count) return 0; if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; if (count > UIO_FASTIOV) { iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); if (!iov) return -ENOMEM; } tot_len = 0; i = count; ivp = iov; while(i > 0) { u32 len; u32 buf; __get_user(len, &vector->iov_len); __get_user(buf, &vector->iov_base); tot_len += len; ivp->iov_base = (void *)A(buf); ivp->iov_len = (__kernel_size_t) len; vector++; ivp++; i--; } inode = file->f_dentry->d_inode; /* VERIFY_WRITE actually means a read, as we write to user space */ retval = locks_verify_area((type == VERIFY_WRITE ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), inode, file, file->f_pos, tot_len); if (retval) goto out; /* VERIFY_WRITE actually means a read, as we write to user space */ fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev); if (fnv) { retval = fnv(file, iov, count, &file->f_pos); goto out; } fn = (type == VERIFY_WRITE ? file->f_op->read : (io_fn_t) file->f_op->write); ivp = iov; while (count > 0) { void * base; int len, nr; base = ivp->iov_base; len = ivp->iov_len; ivp++; count--; nr = fn(file, base, len, &file->f_pos); if (nr < 0) { if (!retval) retval = nr; break; } retval += nr; if (nr != len) break; }out: if (iov != iovstack) kfree(iov); return retval;}asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count){ struct file *file; long ret = -EBADF; file = fget(fd); if(!file) goto bad_file; if (file->f_op && (file->f_mode & FMODE_READ) && (file->f_op->readv || file->f_op->read)) ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); fput(file);bad_file: return ret;}asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count){ struct file *file; int ret = -EBADF; file = fget(fd); if(!file) goto bad_file; if (file->f_op && (file->f_mode & FMODE_WRITE) && (file->f_op->writev || file->f_op->write)) ret = do_readv_writev32(VERIFY_READ, file, vector, count); fput(file);bad_file: return ret;}/* readdir & getdents */#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))struct old_linux_dirent32 { u32 d_ino; u32 d_offset; unsigned short d_namlen; char d_name[1];};struct readdir_callback32 { struct old_linux_dirent32 * dirent; int count;};static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino, unsigned int d_type){ struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf; struct old_linux_dirent32 * dirent; if (buf->count) return -EINVAL; buf->count++; dirent = buf->dirent; put_user(ino, &dirent->d_ino); put_user(offset, &dirent->d_offset); put_user(namlen, &dirent->d_namlen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); return 0;}asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count){ int error = -EBADF; struct file * file; struct readdir_callback32 buf; file = fget(fd); if (!file) goto out; buf.count = 0; buf.dirent = dirent; error = vfs_readdir(file, fillonedir, &buf); if (error < 0) goto out_putf; error = buf.count;out_putf: fput(file);out: return error;}struct linux_dirent32 { u32 d_ino; u32 d_off; unsigned short d_reclen; char d_name[1];};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, off_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); ((char *) dirent) += reclen; buf->current_dir = dirent; buf->count -= reclen; return 0;}asmlinkage int 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 *//* * Ooo, nasty. We need here to frob 32-bit unsigned longs to * 64-bit unsigned longs. */static inline intget_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset){ if (ufdset) { unsigned long odd; if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32))) return -EFAULT; odd = n & 1UL; n &= ~1UL; while (n) { unsigned long h, l; __get_user(l, ufdset); __get_user(h, ufdset+1); ufdset += 2; *fdset++ = h << 32 | l; n -= 2; } if (odd) __get_user(*fdset, ufdset); } else { /* Tricky, must clear full unsigned long in the * kernel fdset at the end, this makes sure that * actually happens. */ memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); } return 0;}static inline voidset_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset){ unsigned long odd; if (!ufdset) return; odd = n & 1UL; n &= ~1UL; while (n) { unsigned long h, l; l = *fdset++; h = l >> 32; __put_user(l, ufdset); __put_user(h, ufdset+1); ufdset += 2; n -= 2; } if (odd) __put_user(*fdset, ufdset);}#define MAX_SELECT_SECONDS \ ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x){ fd_set_bits fds; struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x); char *bits; unsigned long nn; long timeout; int ret, size; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { time_t sec, usec; if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) || (ret = __get_user(sec, &tvp->tv_sec)) || (ret = __get_user(usec, &tvp->tv_usec))) goto out_nofds; ret = -EINVAL; if(sec < 0 || usec < 0) goto out_nofds; if ((unsigned long) sec < MAX_SELECT_SECONDS) { timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); timeout += sec * (unsigned long) HZ; } } ret = -EINVAL; if (n < 0) goto out_nofds; if (n > current->files->max_fdset) n = current->files->max_fdset; /* * We need 6 bitmaps (in/out/ex for both incoming and outgoing), * since we used fdset we need to allocate memory in units of * long-words. */ ret = -ENOMEM; size = FDS_BYTES(n); bits = kmalloc(6 * size, GFP_KERNEL); if (!bits) goto out_nofds; fds.in = (unsigned long *) bits; fds.out = (unsigned long *) (bits + size); fds.ex = (unsigned long *) (bits + 2*size); fds.res_in = (unsigned long *) (bits + 3*size); fds.res_out = (unsigned long *) (bits + 4*size); fds.res_ex = (unsigned long *) (bits + 5*size); nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); if ((ret = get_fd_set32(nn, fds.in, inp)) || (ret = get_fd_set32(nn, fds.out, outp)) || (ret = get_fd_set32(nn, fds.ex, exp))) goto out; zero_fd_set(n, fds.res_in); zero_fd_set(n, fds.res_out); zero_fd_set(n, fds.res_ex); ret = do_select(n, &fds, &timeout); if (tvp && !(current->personality & STICKY_TIMEOUTS)) { time_t sec = 0, usec = 0; if (timeout) { sec = timeout / HZ; usec = timeout % HZ; usec *= (1000000/HZ); } put_user(sec, &tvp->tv_sec); put_user(usec, &tvp->tv_usec); } if (ret < 0) goto out; if (!ret) { ret = -ERESTARTNOHAND; if (signal_pending(current)) goto out; ret = 0; } set_fd_set32(nn, inp, fds.res_in); set_fd_set32(nn, outp, fds.res_out); set_fd_set32(nn, exp, fds.res_ex);out: kfree(bits);out_nofds: return ret;}static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf){ unsigned long ino, blksize, blocks; kdev_t dev, rdev; umode_t mode; nlink_t nlink; uid_t uid; gid_t gid; off_t size; time_t atime, mtime, ctime; int err; /* Stream the loads of inode data into the load buffer, * then we push it all into the store buffer below. This * should give optimal cache performance. */ ino = inode->i_ino; dev = inode->i_dev; mode = inode->i_mode; nlink = inode->i_nlink; uid = inode->i_uid; gid = inode->i_gid; rdev = inode->i_rdev; size = inode->i_size; atime = inode->i_atime; mtime = inode->i_mtime; ctime = inode->i_ctime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -