Merge with Linux 2.4.0-test5-pre1. This works again on Origin UP.
[linux-2.6/linux-mips.git] / fs / ioctl.c
blobf02d766bd37882ee5bfb17895d8bf0d70475b97d
1 /*
2 * linux/fs/ioctl.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/mm.h>
8 #include <linux/smp_lock.h>
9 #include <linux/file.h>
11 #include <asm/uaccess.h>
13 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
15 int error;
16 int block;
17 struct inode * inode = filp->f_dentry->d_inode;
19 switch (cmd) {
20 case FIBMAP:
22 struct address_space *mapping = inode->i_mapping;
23 int res;
24 /* do we support this mess? */
25 if (!mapping->a_ops->bmap)
26 return -EINVAL;
27 if (!capable(CAP_SYS_RAWIO))
28 return -EPERM;
29 if ((error = get_user(block, (int *) arg)) != 0)
30 return error;
32 res = mapping->a_ops->bmap(mapping, block);
33 return put_user(res, (int *) arg);
35 case FIGETBSZ:
36 if (inode->i_sb == NULL)
37 return -EBADF;
38 return put_user(inode->i_sb->s_blocksize, (int *) arg);
39 case FIONREAD:
40 return put_user(inode->i_size - filp->f_pos, (int *) arg);
42 if (filp->f_op && filp->f_op->ioctl)
43 return filp->f_op->ioctl(inode, filp, cmd, arg);
44 return -ENOTTY;
48 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
50 struct file * filp;
51 unsigned int flag;
52 int on, error = -EBADF;
54 filp = fget(fd);
55 if (!filp)
56 goto out;
57 error = 0;
58 lock_kernel();
59 switch (cmd) {
60 case FIOCLEX:
61 FD_SET(fd, current->files->close_on_exec);
62 break;
64 case FIONCLEX:
65 FD_CLR(fd, current->files->close_on_exec);
66 break;
68 case FIONBIO:
69 if ((error = get_user(on, (int *)arg)) != 0)
70 break;
71 flag = O_NONBLOCK;
72 #ifdef __sparc__
73 /* SunOS compatibility item. */
74 if(O_NONBLOCK != O_NDELAY)
75 flag |= O_NDELAY;
76 #endif
77 if (on)
78 filp->f_flags |= flag;
79 else
80 filp->f_flags &= ~flag;
81 break;
83 case FIOASYNC:
84 if ((error = get_user(on, (int *)arg)) != 0)
85 break;
86 flag = on ? FASYNC : 0;
88 /* Did FASYNC state change ? */
89 if ((flag ^ filp->f_flags) & FASYNC) {
90 if (filp->f_op && filp->f_op->fasync)
91 error = filp->f_op->fasync(fd, filp, on);
92 else error = -ENOTTY;
94 if (error != 0)
95 break;
97 if (on)
98 filp->f_flags |= FASYNC;
99 else
100 filp->f_flags &= ~FASYNC;
101 break;
103 default:
104 error = -ENOTTY;
105 if (S_ISREG(filp->f_dentry->d_inode->i_mode))
106 error = file_ioctl(filp, cmd, arg);
107 else if (filp->f_op && filp->f_op->ioctl)
108 error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
110 unlock_kernel();
111 fput(filp);
113 out:
114 return error;