Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | /* * linux/fs/ioctl.c * * Copyright (C) 1991, 1992 Linus Torvalds */ #include <linux/mm.h> #include <linux/smp_lock.h> #include <linux/file.h> #include <asm/uaccess.h> static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) { int error; int block; struct inode * inode = filp->f_dentry->d_inode; switch (cmd) { case FIBMAP: if (!capable(CAP_SYS_RAWIO)) return -EPERM; if (inode->i_op == NULL) return -EBADF; if (inode->i_op->bmap == NULL) return -EINVAL; if ((error = get_user(block, (int *) arg)) != 0) return error; block = inode->i_op->bmap(inode,block); return put_user(block, (int *) arg); case FIGETBSZ: if (inode->i_sb == NULL) return -EBADF; return put_user(inode->i_sb->s_blocksize, (int *) arg); case FIONREAD: return put_user(inode->i_size - filp->f_pos, (int *) arg); } if (filp->f_op && filp->f_op->ioctl) return filp->f_op->ioctl(inode, filp, cmd, arg); return -ENOTTY; } asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; unsigned int flag; int on, error = -EBADF; lock_kernel(); filp = fget(fd); if (!filp) goto out; error = 0; switch (cmd) { case FIOCLEX: FD_SET(fd, current->files->close_on_exec); break; case FIONCLEX: FD_CLR(fd, current->files->close_on_exec); break; case FIONBIO: if ((error = get_user(on, (int *)arg)) != 0) break; flag = O_NONBLOCK; #ifdef __sparc__ /* SunOS compatibility item. */ if(O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif if (on) filp->f_flags |= flag; else filp->f_flags &= ~flag; break; case FIOASYNC: if ((error = get_user(on, (int *)arg)) != 0) break; flag = on ? FASYNC : 0; /* Did FASYNC state change ? */ if ((flag ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) filp->f_op->fasync(fd, filp, on); } if (on) filp->f_flags |= FASYNC; else filp->f_flags &= ~FASYNC; break; default: error = -ENOTTY; if (!filp->f_dentry || !filp->f_dentry->d_inode) error = -ENOENT; else if (S_ISREG(filp->f_dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else if (filp->f_op && filp->f_op->ioctl) error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); } fput(filp); out: unlock_kernel(); return error; } |