📄 sys_ppc32.c
字号:
}struct dqblk32 { __u32 dqb_bhardlimit; __u32 dqb_bsoftlimit; __u32 dqb_curblocks; __u32 dqb_ihardlimit; __u32 dqb_isoftlimit; __u32 dqb_curinodes; __kernel_time_t32 dqb_btime; __kernel_time_t32 dqb_itime;}; extern asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr);/* Note: it is necessary to treat cmd and id as unsigned ints, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * and the register representation of a signed int (msr in 64-bit mode) is performed. */asmlinkage long sys32_quotactl(u32 cmd_parm, const char *special, u32 id_parm, unsigned long addr){ int cmd = (int)cmd_parm; int id = (int)id_parm; int cmds = cmd >> SUBCMDSHIFT; int err; struct dqblk d; mm_segment_t old_fs; char *spec; PPCDBG(PPCDBG_SYS32, "sys32_quotactl - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); switch (cmds) { case Q_GETQUOTA: break; case Q_SETQUOTA: case Q_SETUSE: case Q_SETQLIM: if (copy_from_user (&d, (struct dqblk32 *)addr, sizeof (struct dqblk32))) return -EFAULT; d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; break; default: return sys_quotactl(cmd, special, id, (caddr_t)addr); } spec = getname32 (special); err = PTR_ERR(spec); if (IS_ERR(spec)) return err; old_fs = get_fs (); set_fs (KERNEL_DS); err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d); set_fs (old_fs); putname (spec); if (cmds == Q_GETQUOTA) { __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; ((struct dqblk32 *)&d)->dqb_itime = i; ((struct dqblk32 *)&d)->dqb_btime = b; if (copy_to_user ((struct dqblk32 *)addr, &d, sizeof (struct dqblk32))) return -EFAULT; } PPCDBG(PPCDBG_SYS32, "sys32_quotactl - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); return err;}/* 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; /* unsigned char d_type; */ 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, (filldir_t)fillonedir, &buf); if (error < 0) goto out_putf; error = buf.count;out_putf: fput(file);out: return error;}#if 0struct linux_dirent32 { u32 d_ino; u32 d_off; unsigned short d_reclen; char d_name[1];};#elsestruct linux_dirent32 { u32 d_ino; u32 d_off; unsigned short d_reclen; /* unsigned char d_type; */ char d_name[256];};#endifstruct getdents_callback32 { struct linux_dirent32 * current_dir; struct linux_dirent32 * previous; int count; int error;};static intfilldir(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); /* put_user(d_type, &dirent->d_type); */ 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 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; PPCDBG(PPCDBG_SYS32NI, "sys32_getdents - running - fd=%x, pid=%ld, comm=%s \n", fd, current->pid, current->comm); 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_t)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 *//* 32-bit timeval and related flotsam. */struct timeval32{ int tv_sec, tv_usec;};struct itimerval32{ struct timeval32 it_interval; struct timeval32 it_value;};/* * 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 long 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; PPCDBG(PPCDBG_SYS32X, "sys32_select - entered - n=%x, inp=%p, outp=%p - pid=%ld comm=%s \n", n, inp, outp, current->pid, current->comm); 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: PPCDBG(PPCDBG_SYS32X, "sys32_select - exited - pid=%ld, comm=%s \n", current->pid, current->comm); return ret;}/* * Due to some executables calling the wrong select we sometimes * get wrong args. This determines how the args are being passed * (a single ptr to them all args passed) then calls * sys_select() with the appropriate args. -- Cort *//* Note: it is necessary to treat n as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * and the register representation of a signed int (msr in 64-bit mode) is performed. */asmlinkage int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x){ if ((unsigned int)n >= 4096) panic("ppc32_select - wrong arguments were passed in \n"); return sys32_select((int)n, inp, outp, exp, tvp_x);}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; blksize = inode->i_blksize; blocks = inode->i_blocks; err = put_user(kdev_t_to_nr(dev), &statbuf->st_dev); err |= put_user(ino, &statbuf->st_ino); err |= put_user(mode, &statbuf->st_mode); err |= put_user(nlink, &statbuf->st_nlink); err |= put_user(uid, &statbuf->st_uid); err |= put_user(gid, &statbuf->st_gid); err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev); err |= put_user(size, &statbuf->st_size); err |= put_user(atime, &statbuf->st_atime); err |= put_user(0, &statbuf->__unused1); err |= put_user(mtime, &statbuf->st_mtime); err |= put_user(0, &statbuf->__unused2); err |= put_user(ctime, &statbuf->st_ctime); err |= put_user(0, &statbuf->__unused3); if (blksize) { err |= put_user(blksize, &statbuf->st_blksize); err |= put_user(blocks, &statbuf->st_blocks); } else { unsigned int tmp_blocks;#define D_B 7#define I_B (BLOCK_SIZE / sizeof(unsigned short)) tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE; if (tmp_blocks > D_B) { unsigned int indirect; indirect = (tmp_blocks - D_B + I_B - 1) / I_B; tmp_blocks += indirect; if (indirect > 1) { indirect = (indirect - 1 + I_B - 1) / I_B; tmp_blocks += indirect; if (indirect > 1) tmp_blocks++; } } err |= put_user(BLOCK_SIZE, &statbuf->st_blksize); err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);#undef D_B#undef I_B } err |= put_user(0, &statbuf->__unused4[0]); err |= put_user(0, &statbuf->__unused4[1]); return err;}static __inline__ intdo_revalidate(struct dentry *dentry){ struct inode * inode = dentry->d_inode; if (inode->i_op && inode->i_op->revalidate) return inode->i_op->revalidate(dentry); return 0;}asmlinkage long sys32_newstat(char* filename, struct stat32* statbuf){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -