Import 2.3.12pre9
[davej-history.git] / fs / fcntl.c
blob95ed3e9f48df7e1823f4b3401c6e9761f1b65a8e
1 /*
2 * linux/fs/fcntl.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/mm.h>
8 #include <linux/file.h>
9 #include <linux/smp_lock.h>
11 #include <asm/uaccess.h>
13 extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
16 * locate_fd finds a free file descriptor in the open_fds fdset,
17 * expanding the fd arrays if necessary. The files write lock will be
18 * held on exit to ensure that the fd can be entered atomically.
21 static inline int locate_fd(struct files_struct *files,
22 struct file *file, int start)
24 unsigned int newfd;
25 int error;
27 write_lock(&files->file_lock);
29 repeat:
30 error = -EMFILE;
31 if (start < files->next_fd)
32 start = files->next_fd;
33 if (start >= files->max_fdset) {
34 expand:
35 error = expand_files(files, start);
36 if (error < 0)
37 goto out;
38 goto repeat;
41 newfd = find_next_zero_bit(files->open_fds->fds_bits,
42 files->max_fdset, start);
44 error = -EMFILE;
45 if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
46 goto out;
47 if (newfd >= files->max_fdset)
48 goto expand;
50 error = expand_files(files, newfd);
51 if (error < 0)
52 goto out;
53 if (error) /* If we might have blocked, try again. */
54 goto repeat;
56 if (start <= files->next_fd)
57 files->next_fd = newfd + 1;
59 error = newfd;
61 out:
62 return error;
65 static inline void allocate_fd(struct files_struct *files,
66 struct file *file, int fd)
68 FD_SET(fd, files->open_fds);
69 FD_CLR(fd, files->close_on_exec);
70 write_unlock(&files->file_lock);
71 fd_install(fd, file);
74 static int dupfd(struct file *file, int start)
76 struct files_struct * files = current->files;
77 int ret;
79 ret = locate_fd(files, file, start);
80 if (ret < 0)
81 goto out_putf;
82 allocate_fd(files, file, ret);
83 return ret;
85 out_putf:
86 write_unlock(&files->file_lock);
87 fput(file);
88 return ret;
91 asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
93 int err = -EBADF;
94 struct file * file;
95 struct files_struct * files = current->files;
97 write_lock(&current->files->file_lock);
98 if (!(file = fcheck(oldfd)))
99 goto out_unlock;
100 err = newfd;
101 if (newfd == oldfd)
102 goto out_unlock;
103 err = -EBADF;
104 if (newfd >= NR_OPEN)
105 goto out_unlock; /* following POSIX.1 6.2.1 */
106 get_file(file); /* We are now finished with oldfd */
108 err = expand_files(files, newfd);
109 if (err < 0) {
110 write_unlock(&files->file_lock);
111 fput(file);
112 goto out;
115 /* To avoid races with open() and dup(), we will mark the fd as
116 * in-use in the open-file bitmap throughout the entire dup2()
117 * process. This is quite safe: do_close() uses the fd array
118 * entry, not the bitmap, to decide what work needs to be
119 * done. --sct */
120 FD_SET(newfd, files->open_fds);
121 write_unlock(&files->file_lock);
123 do_close(newfd, 0);
125 write_lock(&files->file_lock);
126 allocate_fd(files, file, newfd);
127 err = newfd;
129 out:
130 return err;
131 out_unlock:
132 write_unlock(&current->files->file_lock);
133 goto out;
136 asmlinkage int sys_dup(unsigned int fildes)
138 int ret = -EBADF;
139 struct file * file = fget(fildes);
141 if (file)
142 ret = dupfd(file, 0);
143 return ret;
146 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)
148 static int setfl(int fd, struct file * filp, unsigned long arg)
150 struct inode * inode = filp->f_dentry->d_inode;
153 * In the case of an append-only file, O_APPEND
154 * cannot be cleared
156 if (!(arg & O_APPEND) && IS_APPEND(inode))
157 return -EPERM;
159 /* Did FASYNC state change? */
160 if ((arg ^ filp->f_flags) & FASYNC) {
161 if (filp->f_op && filp->f_op->fasync)
162 filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
165 /* required for strict SunOS emulation */
166 if (O_NONBLOCK != O_NDELAY)
167 if (arg & O_NDELAY)
168 arg |= O_NONBLOCK;
170 filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
171 return 0;
174 asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
176 struct file * filp;
177 long err = -EBADF;
179 filp = fget(fd);
180 if (!filp)
181 goto out;
182 err = 0;
183 lock_kernel();
184 switch (cmd) {
185 case F_DUPFD:
186 err = -EINVAL;
187 if (arg < NR_OPEN) {
188 get_file(filp);
189 err = dupfd(filp, arg);
191 break;
192 case F_GETFD:
193 err = FD_ISSET(fd, current->files->close_on_exec);
194 break;
195 case F_SETFD:
196 if (arg&1)
197 FD_SET(fd, current->files->close_on_exec);
198 else
199 FD_CLR(fd, current->files->close_on_exec);
200 break;
201 case F_GETFL:
202 err = filp->f_flags;
203 break;
204 case F_SETFL:
205 err = setfl(fd, filp, arg);
206 break;
207 case F_GETLK:
208 err = fcntl_getlk(fd, (struct flock *) arg);
209 break;
210 case F_SETLK:
211 err = fcntl_setlk(fd, cmd, (struct flock *) arg);
212 break;
213 case F_SETLKW:
214 err = fcntl_setlk(fd, cmd, (struct flock *) arg);
215 break;
216 case F_GETOWN:
218 * XXX If f_owner is a process group, the
219 * negative return value will get converted
220 * into an error. Oops. If we keep the
221 * current syscall conventions, the only way
222 * to fix this will be in libc.
224 err = filp->f_owner.pid;
225 break;
226 case F_SETOWN:
227 filp->f_owner.pid = arg;
228 filp->f_owner.uid = current->uid;
229 filp->f_owner.euid = current->euid;
230 if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
231 err = sock_fcntl (filp, F_SETOWN, arg);
232 break;
233 case F_GETSIG:
234 err = filp->f_owner.signum;
235 break;
236 case F_SETSIG:
237 if (arg <= 0 || arg > _NSIG) {
238 err = -EINVAL;
239 break;
241 err = 0;
242 filp->f_owner.signum = arg;
243 break;
244 default:
245 /* sockets need a few special fcntls. */
246 err = -EINVAL;
247 if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
248 err = sock_fcntl (filp, cmd, arg);
249 break;
251 fput(filp);
252 unlock_kernel();
253 out:
254 return err;
257 static void send_sigio_to_task(struct task_struct *p,
258 struct fown_struct *fown, struct fasync_struct *fa)
260 if ((fown->euid != 0) &&
261 (fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
262 (fown->uid ^ p->suid) && (fown->uid ^ p->uid))
263 return;
264 switch (fown->signum) {
265 siginfo_t si;
266 default:
267 /* Queue a rt signal with the appropriate fd as its
268 value. We use SI_SIGIO as the source, not
269 SI_KERNEL, since kernel signals always get
270 delivered even if we can't queue. Failure to
271 queue in this case _should_ be reported; we fall
272 back to SIGIO in that case. --sct */
273 si.si_signo = fown->signum;
274 si.si_errno = 0;
275 si.si_code = SI_SIGIO;
276 si.si_pid = fown->pid;
277 si.si_uid = fown->uid;
278 si.si_fd = fa->fa_fd;
279 if (!send_sig_info(fown->signum, &si, p))
280 break;
281 /* fall-through: fall back on the old plain SIGIO signal */
282 case 0:
283 send_sig(SIGIO, p, 1);
287 static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa)
289 struct task_struct * p;
290 int pid = fown->pid;
292 read_lock(&tasklist_lock);
293 if ( (pid > 0) && (p = find_task_by_pid(pid)) ) {
294 send_sigio_to_task(p, fown, fa);
295 goto out;
297 for_each_task(p) {
298 int match = p->pid;
299 if (pid < 0)
300 match = -p->pgrp;
301 if (pid != match)
302 continue;
303 send_sigio_to_task(p, fown, fa);
305 out:
306 read_unlock(&tasklist_lock);
309 void kill_fasync(struct fasync_struct *fa, int sig)
311 while (fa) {
312 struct fown_struct * fown;
313 if (fa->magic != FASYNC_MAGIC) {
314 printk("kill_fasync: bad magic number in "
315 "fasync_struct!\n");
316 return;
318 fown = &fa->fa_file->f_owner;
319 if (fown->pid)
320 send_sigio(fown, fa);
321 fa = fa->fa_next;