File: /usr/src/linux/fs/ioctl.c

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