root/fs/ioctl.c

Revision 27, 3.5 kB (checked in by dkaplan1, 6 years ago)

Changed calldriver arguments and references. Now includes size and flags
Added map_pages function to map full pages
Added linked lists of mappings
Added linked lists of usage counts
Modified map_struct to look in list for cached mapping
NO UNMAPPING CODE (yet)

Line 
1 /*
2  *  linux/fs/ioctl.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6
7 #include <linux/mm.h>
8 #include <linux/smp_lock.h>
9 #include <linux/file.h>
10 #include <linux/fs.h>
11 #include <linux/security.h>
12
13 #include <asm/uaccess.h>
14 #include <asm/ioctls.h>
15 #include <asm/callgate.h>
16
17 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
18 {
19         int error;
20         int block;
21         struct inode * inode = filp->f_dentry->d_inode;
22         int __user *p = (int __user *)arg;
23
24         switch (cmd) {
25                 case FIBMAP:
26                 {
27                         struct address_space *mapping = filp->f_mapping;
28                         int res;
29                         /* do we support this mess? */
30                         if (!mapping->a_ops->bmap)
31                                 return -EINVAL;
32                         if (!capable(CAP_SYS_RAWIO))
33                                 return -EPERM;
34                         if ((error = get_user(block, p)) != 0)
35                                 return error;
36
37                         res = mapping->a_ops->bmap(mapping, block);
38                         return put_user(res, p);
39                 }
40                 case FIGETBSZ:
41                         if (inode->i_sb == NULL)
42                                 return -EBADF;
43                         return put_user(inode->i_sb->s_blocksize, p);
44                 case FIONREAD:
45                         return put_user(i_size_read(inode) - filp->f_pos, p);
46         }
47         if (filp->f_op && filp->f_op->ioctl) {
48       if ((unsigned long) filp->f_op->ioctl > PAGE_OFFSET)
49           return filp->f_op->ioctl(inode, filp, cmd, arg);
50       else {
51           CALLDRIVER_PREP4(ioctl, inode, filp, cmd, arg)
52           return calldriver((unsigned long) filp->f_op->ioctl, ioctl_args, ioctl_sizes, 4, current->mm, 3, 0);
53       }
54   }
55         return -ENOTTY;
56 }
57
58
59 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
60 {      
61         struct file * filp;
62         unsigned int flag;
63         int on, error = -EBADF;
64
65         filp = fget(fd);
66         if (!filp)
67                 goto out;
68
69         error = security_file_ioctl(filp, cmd, arg);
70         if (error) {
71                 fput(filp);
72                 goto out;
73         }
74
75         lock_kernel();
76         switch (cmd) {
77                 case FIOCLEX:
78                         set_close_on_exec(fd, 1);
79                         break;
80
81                 case FIONCLEX:
82                         set_close_on_exec(fd, 0);
83                         break;
84
85                 case FIONBIO:
86                         if ((error = get_user(on, (int __user *)arg)) != 0)
87                                 break;
88                         flag = O_NONBLOCK;
89 #ifdef __sparc__
90                         /* SunOS compatibility item. */
91                         if(O_NONBLOCK != O_NDELAY)
92                                 flag |= O_NDELAY;
93 #endif
94                         if (on)
95                                 filp->f_flags |= flag;
96                         else
97                                 filp->f_flags &= ~flag;
98                         break;
99
100                 case FIOASYNC:
101                         if ((error = get_user(on, (int __user *)arg)) != 0)
102                                 break;
103                         flag = on ? FASYNC : 0;
104
105                         /* Did FASYNC state change ? */
106                         if ((flag ^ filp->f_flags) & FASYNC) {
107                                 if (filp->f_op && filp->f_op->fasync)
108                                         error = filp->f_op->fasync(fd, filp, on);
109                                 else error = -ENOTTY;
110                         }
111                         if (error != 0)
112                                 break;
113
114                         if (on)
115                                 filp->f_flags |= FASYNC;
116                         else
117                                 filp->f_flags &= ~FASYNC;
118                         break;
119
120                 case FIOQSIZE:
121                         if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
122                             S_ISREG(filp->f_dentry->d_inode->i_mode) ||
123                             S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
124                                 loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
125                                 error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
126                         }
127                         else
128                                 error = -ENOTTY;
129                         break;
130                 default:
131                         error = -ENOTTY;
132                         if (S_ISREG(filp->f_dentry->d_inode->i_mode))
133                                 error = file_ioctl(filp, cmd, arg);
134                         else if (filp->f_op && filp->f_op->ioctl) {
135           if ((unsigned long) filp->f_op->ioctl > PAGE_OFFSET)
136               error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
137           else {
138               CALLDRIVER_PREP4(ioctl, filp->f_dentry->d_inode, filp, cmd, arg)
139               error=calldriver((unsigned long) filp->f_op->ioctl, ioctl_args, ioctl_sizes, 4, current->mm, 3, 0);
140           }
141       }
142              
143         }
144         unlock_kernel();
145         fput(filp);
146
147 out:
148         return error;
149 }
Note: See TracBrowser for help on using the browser.