4 * Copyright (C) 1991, 1992 Linus Torvalds
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
);
15 static inline int dupfd(unsigned int fd
, unsigned int arg
)
17 struct files_struct
* files
= current
->files
;
31 arg
= find_next_zero_bit(&files
->open_fds
, NR_OPEN
, arg
);
32 if (arg
>= current
->rlim
[RLIMIT_NOFILE
].rlim_cur
)
34 FD_SET(arg
, &files
->open_fds
);
35 FD_CLR(arg
, &files
->close_on_exec
);
36 fd_install(arg
, file
);
46 asmlinkage
int sys_dup2(unsigned int oldfd
, unsigned int newfd
)
58 goto out
; /* following POSIX.1 6.2.1 */
61 err
= dupfd(oldfd
, newfd
);
67 asmlinkage
int sys_dup(unsigned int fildes
)
72 ret
= dupfd(fildes
, 0);
77 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)
79 static int setfl(int fd
, struct file
* filp
, unsigned long arg
)
81 struct inode
* inode
= filp
->f_dentry
->d_inode
;
84 * In the case of an append-only file, O_APPEND
87 if (!(arg
& O_APPEND
) && IS_APPEND(inode
))
90 /* Did FASYNC state change? */
91 if ((arg
^ filp
->f_flags
) & FASYNC
) {
92 if (filp
->f_op
&& filp
->f_op
->fasync
)
93 filp
->f_op
->fasync(fd
, filp
, (arg
& FASYNC
) != 0);
96 /* required for strict SunOS emulation */
97 if (O_NONBLOCK
!= O_NDELAY
)
101 filp
->f_flags
= (arg
& SETFL_MASK
) | (filp
->f_flags
& ~SETFL_MASK
);
105 asmlinkage
long sys_fcntl(unsigned int fd
, unsigned int cmd
, unsigned long arg
)
117 err
= dupfd(fd
, arg
);
120 err
= FD_ISSET(fd
, ¤t
->files
->close_on_exec
);
124 FD_SET(fd
, ¤t
->files
->close_on_exec
);
126 FD_CLR(fd
, ¤t
->files
->close_on_exec
);
132 err
= setfl(fd
, filp
, arg
);
135 err
= fcntl_getlk(fd
, (struct flock
*) arg
);
138 err
= fcntl_setlk(fd
, cmd
, (struct flock
*) arg
);
141 err
= fcntl_setlk(fd
, cmd
, (struct flock
*) arg
);
145 * XXX If f_owner is a process group, the
146 * negative return value will get converted
147 * into an error. Oops. If we keep the
148 * current syscall conventions, the only way
149 * to fix this will be in libc.
151 err
= filp
->f_owner
.pid
;
155 filp
->f_owner
.pid
= arg
;
156 filp
->f_owner
.uid
= current
->uid
;
157 filp
->f_owner
.euid
= current
->euid
;
158 if (S_ISSOCK (filp
->f_dentry
->d_inode
->i_mode
))
159 err
= sock_fcntl (filp
, F_SETOWN
, arg
);
162 err
= filp
->f_owner
.signum
;
165 if (arg
<= 0 || arg
> _NSIG
) {
170 filp
->f_owner
.signum
= arg
;
173 /* sockets need a few special fcntls. */
174 if (S_ISSOCK (filp
->f_dentry
->d_inode
->i_mode
))
175 err
= sock_fcntl (filp
, cmd
, arg
);
186 static void send_sigio_to_task(struct task_struct
*p
,
187 struct fown_struct
*fown
, struct fasync_struct
*fa
)
189 if ((fown
->euid
!= 0) &&
190 (fown
->euid
^ p
->suid
) && (fown
->euid
^ p
->uid
) &&
191 (fown
->uid
^ p
->suid
) && (fown
->uid
^ p
->uid
))
193 switch (fown
->signum
) {
196 /* Queue a rt signal with the appropriate fd as its
197 value. We use SI_SIGIO as the source, not
198 SI_KERNEL, since kernel signals always get
199 delivered even if we can't queue. Failure to
200 queue in this case _should_ be reported; we fall
201 back to SIGIO in that case. --sct */
202 si
.si_signo
= fown
->signum
;
204 si
.si_code
= SI_SIGIO
;
205 si
.si_pid
= fown
->pid
;
206 si
.si_uid
= fown
->uid
;
207 si
.si_fd
= fa
->fa_fd
;
208 if (!send_sig_info(fown
->signum
, &si
, p
))
210 /* fall-through: fall back on the old plain SIGIO signal */
212 send_sig(SIGIO
, p
, 1);
216 static void send_sigio(struct fown_struct
*fown
, struct fasync_struct
*fa
)
218 struct task_struct
* p
;
221 read_lock(&tasklist_lock
);
222 if ( (pid
> 0) && (p
= find_task_by_pid(pid
)) ) {
223 send_sigio_to_task(p
, fown
, fa
);
232 send_sigio_to_task(p
, fown
, fa
);
235 read_unlock(&tasklist_lock
);
238 void kill_fasync(struct fasync_struct
*fa
, int sig
)
241 struct fown_struct
* fown
;
242 if (fa
->magic
!= FASYNC_MAGIC
) {
243 printk("kill_fasync: bad magic number in "
247 fown
= &fa
->fa_file
->f_owner
;
249 send_sigio(fown
, fa
);