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