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(struct file
*file
, unsigned int arg
)
17 struct files_struct
* files
= current
->files
;
21 write_lock(&files
->file_lock
);
22 arg
= find_next_zero_bit(&files
->open_fds
, NR_OPEN
, arg
);
23 if (arg
>= current
->rlim
[RLIMIT_NOFILE
].rlim_cur
)
25 FD_SET(arg
, &files
->open_fds
);
26 FD_CLR(arg
, &files
->close_on_exec
);
27 write_unlock(&files
->file_lock
);
28 fd_install(arg
, file
);
34 write_unlock(&files
->file_lock
);
39 asmlinkage
int sys_dup2(unsigned int oldfd
, unsigned int newfd
)
44 read_lock(¤t
->files
->file_lock
);
45 if (!(file
= fcheck(oldfd
)))
52 goto out_unlock
; /* following POSIX.1 6.2.1 */
54 read_unlock(¤t
->files
->file_lock
);
57 err
= dupfd(file
, newfd
);
61 read_unlock(¤t
->files
->file_lock
);
65 asmlinkage
int sys_dup(unsigned int fildes
)
68 struct file
* file
= fget(fildes
);
74 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)
76 static int setfl(int fd
, struct file
* filp
, unsigned long arg
)
78 struct inode
* inode
= filp
->f_dentry
->d_inode
;
81 * In the case of an append-only file, O_APPEND
84 if (!(arg
& O_APPEND
) && IS_APPEND(inode
))
87 /* Did FASYNC state change? */
88 if ((arg
^ filp
->f_flags
) & FASYNC
) {
89 if (filp
->f_op
&& filp
->f_op
->fasync
)
90 filp
->f_op
->fasync(fd
, filp
, (arg
& FASYNC
) != 0);
93 /* required for strict SunOS emulation */
94 if (O_NONBLOCK
!= O_NDELAY
)
98 filp
->f_flags
= (arg
& SETFL_MASK
) | (filp
->f_flags
& ~SETFL_MASK
);
102 asmlinkage
long sys_fcntl(unsigned int fd
, unsigned int cmd
, unsigned long arg
)
117 err
= dupfd(filp
, arg
);
121 err
= FD_ISSET(fd
, ¤t
->files
->close_on_exec
);
125 FD_SET(fd
, ¤t
->files
->close_on_exec
);
127 FD_CLR(fd
, ¤t
->files
->close_on_exec
);
133 err
= setfl(fd
, filp
, arg
);
136 err
= fcntl_getlk(fd
, (struct flock
*) arg
);
139 err
= fcntl_setlk(fd
, cmd
, (struct flock
*) arg
);
142 err
= fcntl_setlk(fd
, cmd
, (struct flock
*) arg
);
146 * XXX If f_owner is a process group, the
147 * negative return value will get converted
148 * into an error. Oops. If we keep the
149 * current syscall conventions, the only way
150 * to fix this will be in libc.
152 err
= filp
->f_owner
.pid
;
156 filp
->f_owner
.pid
= arg
;
157 filp
->f_owner
.uid
= current
->uid
;
158 filp
->f_owner
.euid
= current
->euid
;
159 if (S_ISSOCK (filp
->f_dentry
->d_inode
->i_mode
))
160 err
= sock_fcntl (filp
, F_SETOWN
, arg
);
163 err
= filp
->f_owner
.signum
;
166 if (arg
<= 0 || arg
> _NSIG
) {
171 filp
->f_owner
.signum
= arg
;
174 /* sockets need a few special fcntls. */
175 if (S_ISSOCK (filp
->f_dentry
->d_inode
->i_mode
))
176 err
= sock_fcntl (filp
, cmd
, arg
);
187 static void send_sigio_to_task(struct task_struct
*p
,
188 struct fown_struct
*fown
, struct fasync_struct
*fa
)
190 if ((fown
->euid
!= 0) &&
191 (fown
->euid
^ p
->suid
) && (fown
->euid
^ p
->uid
) &&
192 (fown
->uid
^ p
->suid
) && (fown
->uid
^ p
->uid
))
194 switch (fown
->signum
) {
197 /* Queue a rt signal with the appropriate fd as its
198 value. We use SI_SIGIO as the source, not
199 SI_KERNEL, since kernel signals always get
200 delivered even if we can't queue. Failure to
201 queue in this case _should_ be reported; we fall
202 back to SIGIO in that case. --sct */
203 si
.si_signo
= fown
->signum
;
205 si
.si_code
= SI_SIGIO
;
206 si
.si_pid
= fown
->pid
;
207 si
.si_uid
= fown
->uid
;
208 si
.si_fd
= fa
->fa_fd
;
209 if (!send_sig_info(fown
->signum
, &si
, p
))
211 /* fall-through: fall back on the old plain SIGIO signal */
213 send_sig(SIGIO
, p
, 1);
217 static void send_sigio(struct fown_struct
*fown
, struct fasync_struct
*fa
)
219 struct task_struct
* p
;
222 read_lock(&tasklist_lock
);
223 if ( (pid
> 0) && (p
= find_task_by_pid(pid
)) ) {
224 send_sigio_to_task(p
, fown
, fa
);
233 send_sigio_to_task(p
, fown
, fa
);
236 read_unlock(&tasklist_lock
);
239 void kill_fasync(struct fasync_struct
*fa
, int sig
)
242 struct fown_struct
* fown
;
243 if (fa
->magic
!= FASYNC_MAGIC
) {
244 printk("kill_fasync: bad magic number in "
248 fown
= &fa
->fa_file
->f_owner
;
250 send_sigio(fown
, fa
);