]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - fs/ioctl.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
7 #include <linux/syscalls.h>
9 #include <linux/smp_lock.h>
10 #include <linux/capability.h>
11 #include <linux/file.h>
13 #include <linux/security.h>
14 #include <linux/module.h>
15 #include <linux/uaccess.h>
17 #include <asm/ioctls.h>
20 * vfs_ioctl - call filesystem specific ioctl methods
21 * @filp: open file to invoke ioctl method on
22 * @cmd: ioctl command to execute
23 * @arg: command-specific argument for ioctl
25 * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
26 * invokes filesystem specific ->ioctl method. If neither method exists,
29 * Returns 0 on success, -errno on error.
31 static long vfs_ioctl(struct file
*filp
, unsigned int cmd
,
39 if (filp
->f_op
->unlocked_ioctl
) {
40 error
= filp
->f_op
->unlocked_ioctl(filp
, cmd
, arg
);
41 if (error
== -ENOIOCTLCMD
)
44 } else if (filp
->f_op
->ioctl
) {
46 error
= filp
->f_op
->ioctl(filp
->f_path
.dentry
->d_inode
,
55 static int ioctl_fibmap(struct file
*filp
, int __user
*p
)
57 struct address_space
*mapping
= filp
->f_mapping
;
60 /* do we support this mess? */
61 if (!mapping
->a_ops
->bmap
)
63 if (!capable(CAP_SYS_RAWIO
))
65 res
= get_user(block
, p
);
69 res
= mapping
->a_ops
->bmap(mapping
, block
);
71 return put_user(res
, p
);
74 static int file_ioctl(struct file
*filp
, unsigned int cmd
,
77 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
78 int __user
*p
= (int __user
*)arg
;
82 return ioctl_fibmap(filp
, p
);
84 return put_user(inode
->i_sb
->s_blocksize
, p
);
86 return put_user(i_size_read(inode
) - filp
->f_pos
, p
);
89 return vfs_ioctl(filp
, cmd
, arg
);
92 static int ioctl_fionbio(struct file
*filp
, int __user
*argp
)
97 error
= get_user(on
, argp
);
102 /* SunOS compatibility item. */
103 if (O_NONBLOCK
!= O_NDELAY
)
107 filp
->f_flags
|= flag
;
109 filp
->f_flags
&= ~flag
;
113 static int ioctl_fioasync(unsigned int fd
, struct file
*filp
,
119 error
= get_user(on
, argp
);
122 flag
= on
? FASYNC
: 0;
124 /* Did FASYNC state change ? */
125 if ((flag
^ filp
->f_flags
) & FASYNC
) {
126 if (filp
->f_op
&& filp
->f_op
->fasync
) {
128 error
= filp
->f_op
->fasync(fd
, filp
, on
);
137 filp
->f_flags
|= FASYNC
;
139 filp
->f_flags
&= ~FASYNC
;
144 * When you add any new common ioctls to the switches above and below
145 * please update compat_sys_ioctl() too.
147 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
148 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
150 int do_vfs_ioctl(struct file
*filp
, unsigned int fd
, unsigned int cmd
,
154 int __user
*argp
= (int __user
*)arg
;
158 set_close_on_exec(fd
, 1);
162 set_close_on_exec(fd
, 0);
166 error
= ioctl_fionbio(filp
, argp
);
170 error
= ioctl_fioasync(fd
, filp
, argp
);
174 if (S_ISDIR(filp
->f_path
.dentry
->d_inode
->i_mode
) ||
175 S_ISREG(filp
->f_path
.dentry
->d_inode
->i_mode
) ||
176 S_ISLNK(filp
->f_path
.dentry
->d_inode
->i_mode
)) {
178 inode_get_bytes(filp
->f_path
.dentry
->d_inode
);
179 error
= copy_to_user((loff_t __user
*)arg
, &res
,
180 sizeof(res
)) ? -EFAULT
: 0;
185 if (S_ISREG(filp
->f_path
.dentry
->d_inode
->i_mode
))
186 error
= file_ioctl(filp
, cmd
, arg
);
188 error
= vfs_ioctl(filp
, cmd
, arg
);
194 asmlinkage
long sys_ioctl(unsigned int fd
, unsigned int cmd
, unsigned long arg
)
200 filp
= fget_light(fd
, &fput_needed
);
204 error
= security_file_ioctl(filp
, cmd
, arg
);
208 error
= do_vfs_ioctl(filp
, fd
, cmd
, arg
);
210 fput_light(filp
, fput_needed
);