BSD 4_4 release
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
da7c5cc6 1/*
ad787160
C
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
da7c5cc6 4 *
ad787160
C
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
c4ec2128 20 *
ad787160
C
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)kern_descrip.c 8.1 (Berkeley) 6/10/93
da7c5cc6 34 */
40056b21 35
38a01dbe
KB
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/filedesc.h>
39#include <sys/kernel.h>
40#include <sys/vnode.h>
41#include <sys/proc.h>
42#include <sys/file.h>
43#include <sys/socket.h>
44#include <sys/socketvar.h>
45#include <sys/stat.h>
46#include <sys/ioctl.h>
47#include <sys/fcntl.h>
48#include <sys/malloc.h>
49#include <sys/syslog.h>
cece3911 50#include <sys/unistd.h>
38a01dbe 51#include <sys/resourcevar.h>
4147b3f6
BJ
52
53/*
54 * Descriptor management.
55 */
c753a490
KM
56struct file *filehead; /* head of list of open files */
57int nfiles; /* actual number of open files */
4147b3f6 58
40056b21 59/*
4147b3f6 60 * System calls on descriptors.
40056b21 61 */
d5820a3c
CT
62struct getdtablesize_args {
63 int dummy;
64};
a53a698b
KM
65/* ARGSUSED */
66getdtablesize(p, uap, retval)
67 struct proc *p;
d5820a3c 68 struct getdtablesize_args *uap;
a53a698b 69 int *retval;
4147b3f6
BJ
70{
71
e0ed5a07 72 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
d9c2f47f 73 return (0);
4147b3f6
BJ
74}
75
a53a698b
KM
76/*
77 * Duplicate a file descriptor.
78 */
d5820a3c 79struct dup_args {
e0ed5a07 80 u_int fd;
d5820a3c 81};
a53a698b
KM
82/* ARGSUSED */
83dup(p, uap, retval)
84 struct proc *p;
d5820a3c 85 struct dup_args *uap;
a53a698b
KM
86 int *retval;
87{
e0ed5a07
KM
88 register struct filedesc *fdp;
89 u_int old;
90 int new, error;
4147b3f6 91
e0ed5a07 92 old = uap->fd;
a53a698b
KM
93 /*
94 * XXX Compatibility
95 */
e0ed5a07 96 if (old &~ 077) { uap->fd &= 077; return (dup2(p, uap, retval)); }
4147b3f6 97
e0ed5a07
KM
98 fdp = p->p_fd;
99 if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL)
d9c2f47f 100 return (EBADF);
e0ed5a07 101 if (error = fdalloc(p, 0, &new))
d9c2f47f 102 return (error);
e0ed5a07 103 return (finishdup(fdp, (int)old, new, retval));
4147b3f6
BJ
104}
105
a53a698b
KM
106/*
107 * Duplicate a file descriptor to a particular value.
108 */
d5820a3c
CT
109struct dup2_args {
110 u_int from;
111 u_int to;
112};
a53a698b
KM
113/* ARGSUSED */
114dup2(p, uap, retval)
115 struct proc *p;
d5820a3c 116 struct dup2_args *uap;
a53a698b 117 int *retval;
4147b3f6 118{
5e00df3b 119 register struct filedesc *fdp = p->p_fd;
7ddc4f96 120 register u_int old = uap->from, new = uap->to;
5e00df3b 121 int i, error;
40056b21 122
7ddc4f96 123 if (old >= fdp->fd_nfiles ||
e0ed5a07 124 fdp->fd_ofiles[old] == NULL ||
271cfd89 125 new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
e0ed5a07 126 new >= maxfiles)
d9c2f47f 127 return (EBADF);
e0ed5a07
KM
128 if (old == new) {
129 *retval = new;
d9c2f47f 130 return (0);
e0ed5a07 131 }
7ddc4f96
MK
132 if (new >= fdp->fd_nfiles) {
133 if (error = fdalloc(p, new, &i))
5e00df3b 134 return (error);
7ddc4f96 135 if (new != i)
8429d022 136 panic("dup2: fdalloc");
7ddc4f96
MK
137 } else if (fdp->fd_ofiles[new]) {
138 if (fdp->fd_ofileflags[new] & UF_MAPPED)
139 (void) munmapfd(p, new);
140 /*
141 * dup2() must succeed even if the close has an error.
142 */
143 (void) closef(fdp->fd_ofiles[new], p);
4147b3f6 144 }
e0ed5a07 145 return (finishdup(fdp, (int)old, (int)new, retval));
a81e9a81
SL
146}
147
88a7a62a
SL
148/*
149 * The file control system call.
150 */
d5820a3c
CT
151struct fcntl_args {
152 int fd;
153 int cmd;
154 int arg;
155};
a53a698b
KM
156/* ARGSUSED */
157fcntl(p, uap, retval)
158 struct proc *p;
d5820a3c 159 register struct fcntl_args *uap;
a53a698b
KM
160 int *retval;
161{
5e00df3b 162 register struct filedesc *fdp = p->p_fd;
a53a698b 163 register struct file *fp;
88a7a62a 164 register char *pop;
a4128336 165 struct vnode *vp;
208eb71b 166 int i, tmp, error, flg = F_POSIX;
a4128336 167 struct flock fl;
e0ed5a07 168 u_int newmin;
4147b3f6 169
8429d022 170 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
7ddc4f96 171 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
d9c2f47f 172 return (EBADF);
7ddc4f96 173 pop = &fdp->fd_ofileflags[uap->fd];
e0ed5a07
KM
174 switch (uap->cmd) {
175
85f01bd4 176 case F_DUPFD:
e0ed5a07
KM
177 newmin = uap->arg;
178 if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
179 newmin >= maxfiles)
d9c2f47f 180 return (EINVAL);
e0ed5a07 181 if (error = fdalloc(p, newmin, &i))
d9c2f47f 182 return (error);
e0ed5a07 183 return (finishdup(fdp, uap->fd, i, retval));
12438177 184
85f01bd4 185 case F_GETFD:
a53a698b 186 *retval = *pop & 1;
d9c2f47f 187 return (0);
40056b21 188
85f01bd4 189 case F_SETFD:
88a7a62a 190 *pop = (*pop &~ 1) | (uap->arg & 1);
d9c2f47f 191 return (0);
12438177 192
85f01bd4 193 case F_GETFL:
f474c4c6 194 *retval = OFLAGS(fp->f_flag);
d9c2f47f 195 return (0);
12438177 196
85f01bd4 197 case F_SETFL:
f474c4c6
MK
198 fp->f_flag &= ~FCNTLFLAGS;
199 fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
ff0803f0 200 tmp = fp->f_flag & FNONBLOCK;
208eb71b
KM
201 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
202 if (error)
d9c2f47f 203 return (error);
ff0803f0 204 tmp = fp->f_flag & FASYNC;
208eb71b
KM
205 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
206 if (!error)
207 return (0);
ff0803f0 208 fp->f_flag &= ~FNONBLOCK;
208eb71b
KM
209 tmp = 0;
210 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
d9c2f47f 211 return (error);
88a7a62a 212
85f01bd4 213 case F_GETOWN:
208eb71b
KM
214 if (fp->f_type == DTYPE_SOCKET) {
215 *retval = ((struct socket *)fp->f_data)->so_pgid;
216 return (0);
217 }
218 error = (*fp->f_ops->fo_ioctl)
219 (fp, (int)TIOCGPGRP, (caddr_t)retval, p);
220 *retval = -*retval;
221 return (error);
88a7a62a 222
85f01bd4 223 case F_SETOWN:
208eb71b
KM
224 if (fp->f_type == DTYPE_SOCKET) {
225 ((struct socket *)fp->f_data)->so_pgid = uap->arg;
226 return (0);
227 }
228 if (uap->arg <= 0) {
229 uap->arg = -uap->arg;
230 } else {
231 struct proc *p1 = pfind(uap->arg);
232 if (p1 == 0)
233 return (ESRCH);
234 uap->arg = p1->p_pgrp->pg_id;
235 }
236 return ((*fp->f_ops->fo_ioctl)
237 (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
88a7a62a 238
a4128336 239 case F_SETLKW:
208eb71b 240 flg |= F_WAIT;
a4128336
KM
241 /* Fall into F_SETLK */
242
243 case F_SETLK:
244 if (fp->f_type != DTYPE_VNODE)
245 return (EBADF);
246 vp = (struct vnode *)fp->f_data;
247 /* Copy in the lock structure */
248 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
249 if (error)
250 return (error);
251 if (fl.l_whence == SEEK_CUR)
252 fl.l_start += fp->f_offset;
253 switch (fl.l_type) {
254
255 case F_RDLCK:
256 if ((fp->f_flag & FREAD) == 0)
257 return (EBADF);
9bd5ee04 258 p->p_flag |= SADVLCK;
208eb71b 259 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
a4128336
KM
260
261 case F_WRLCK:
262 if ((fp->f_flag & FWRITE) == 0)
263 return (EBADF);
9bd5ee04 264 p->p_flag |= SADVLCK;
208eb71b 265 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
a4128336
KM
266
267 case F_UNLCK:
208eb71b
KM
268 return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
269 F_POSIX));
a4128336
KM
270
271 default:
272 return (EINVAL);
273 }
274
275 case F_GETLK:
276 if (fp->f_type != DTYPE_VNODE)
277 return (EBADF);
278 vp = (struct vnode *)fp->f_data;
279 /* Copy in the lock structure */
280 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
281 if (error)
282 return (error);
2975e814
KM
283 if (fl.l_whence == SEEK_CUR)
284 fl.l_start += fp->f_offset;
208eb71b 285 if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
a4128336
KM
286 return (error);
287 return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
288
88a7a62a 289 default:
d9c2f47f 290 return (EINVAL);
40056b21 291 }
a53a698b 292 /* NOTREACHED */
40056b21
BJ
293}
294
e0ed5a07
KM
295/*
296 * Common code for dup, dup2, and fcntl(F_DUPFD).
297 */
298int
299finishdup(fdp, old, new, retval)
300 register struct filedesc *fdp;
301 register int old, new, *retval;
302{
303 register struct file *fp;
304
305 fp = fdp->fd_ofiles[old];
306 fdp->fd_ofiles[new] = fp;
307 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
308 fp->f_count++;
309 if (new > fdp->fd_lastfile)
310 fdp->fd_lastfile = new;
311 *retval = new;
312 return (0);
313}
314
a53a698b
KM
315/*
316 * Close a file descriptor.
317 */
d5820a3c
CT
318struct close_args {
319 int fd;
320};
a53a698b
KM
321/* ARGSUSED */
322close(p, uap, retval)
323 struct proc *p;
d5820a3c 324 struct close_args *uap;
a53a698b
KM
325 int *retval;
326{
5e00df3b 327 register struct filedesc *fdp = p->p_fd;
88a7a62a 328 register struct file *fp;
8429d022 329 register int fd = uap->fd;
92438dfc 330 register u_char *pf;
3ebb7a40 331
8429d022 332 if ((unsigned)fd >= fdp->fd_nfiles ||
7ddc4f96 333 (fp = fdp->fd_ofiles[fd]) == NULL)
d9c2f47f 334 return (EBADF);
7ddc4f96 335 pf = (u_char *)&fdp->fd_ofileflags[fd];
92438dfc 336 if (*pf & UF_MAPPED)
8429d022 337 (void) munmapfd(p, fd);
7ddc4f96
MK
338 fdp->fd_ofiles[fd] = NULL;
339 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
5e00df3b 340 fdp->fd_lastfile--;
8429d022
MK
341 if (fd < fdp->fd_freefile)
342 fdp->fd_freefile = fd;
92438dfc 343 *pf = 0;
8429d022 344 return (closef(fp, p));
92438dfc
SL
345}
346
0c1cfb60 347#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
a53a698b
KM
348/*
349 * Return status information about a file descriptor.
350 */
d5820a3c
CT
351struct ofstat_args {
352 int fd;
353 struct ostat *sb;
354};
a53a698b 355/* ARGSUSED */
a5bec772 356ofstat(p, uap, retval)
6150798f 357 struct proc *p;
d5820a3c 358 register struct ofstat_args *uap;
6150798f
KM
359 int *retval;
360{
361 register struct filedesc *fdp = p->p_fd;
362 register struct file *fp;
363 struct stat ub;
364 struct ostat oub;
365 int error;
366
367 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
368 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
369 return (EBADF);
370 switch (fp->f_type) {
371
372 case DTYPE_VNODE:
373 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
374 break;
375
376 case DTYPE_SOCKET:
377 error = soo_stat((struct socket *)fp->f_data, &ub);
378 break;
379
380 default:
0c1cfb60 381 panic("ofstat");
6150798f
KM
382 /*NOTREACHED*/
383 }
384 cvtstat(&ub, &oub);
385 if (error == 0)
386 error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub));
387 return (error);
388}
0c1cfb60 389#endif /* COMPAT_43 || COMPAT_SUNOS */
6150798f
KM
390
391/*
392 * Return status information about a file descriptor.
393 */
d5820a3c
CT
394struct fstat_args {
395 int fd;
396 struct stat *sb;
397};
6150798f 398/* ARGSUSED */
a5bec772 399fstat(p, uap, retval)
a53a698b 400 struct proc *p;
d5820a3c 401 register struct fstat_args *uap;
a53a698b
KM
402 int *retval;
403{
5e00df3b 404 register struct filedesc *fdp = p->p_fd;
a53a698b 405 register struct file *fp;
92438dfc 406 struct stat ub;
a53a698b 407 int error;
92438dfc 408
8429d022 409 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
7ddc4f96 410 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
d9c2f47f 411 return (EBADF);
92438dfc
SL
412 switch (fp->f_type) {
413
c4ec2128 414 case DTYPE_VNODE:
208eb71b 415 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
92438dfc
SL
416 break;
417
418 case DTYPE_SOCKET:
a53a698b 419 error = soo_stat((struct socket *)fp->f_data, &ub);
92438dfc
SL
420 break;
421
422 default:
423 panic("fstat");
424 /*NOTREACHED*/
425 }
a53a698b
KM
426 if (error == 0)
427 error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
d9c2f47f 428 return (error);
3ebb7a40
BJ
429}
430
cece3911
KM
431/*
432 * Return pathconf information about a file descriptor.
433 */
434struct fpathconf_args {
435 int fd;
436 int name;
437};
438/* ARGSUSED */
439fpathconf(p, uap, retval)
440 struct proc *p;
441 register struct fpathconf_args *uap;
442 int *retval;
443{
444 struct filedesc *fdp = p->p_fd;
445 struct file *fp;
446 struct vnode *vp;
447
448 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
449 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
450 return (EBADF);
451 switch (fp->f_type) {
452
453 case DTYPE_SOCKET:
454 if (uap->name != _PC_PIPE_BUF)
455 return (EINVAL);
456 *retval = PIPE_BUF;
457 return (0);
458
459 case DTYPE_VNODE:
460 vp = (struct vnode *)fp->f_data;
461 return (VOP_PATHCONF(vp, uap->name, retval));
462
463 default:
464 panic("fpathconf");
465 }
466 /*NOTREACHED*/
467}
468
40056b21 469/*
8429d022 470 * Allocate a file descriptor for the process.
40056b21 471 */
8429d022 472int fdexpand;
5e00df3b 473
8429d022
MK
474fdalloc(p, want, result)
475 struct proc *p;
476 int want;
c4ec2128 477 int *result;
4147b3f6 478{
8429d022
MK
479 register struct filedesc *fdp = p->p_fd;
480 register int i;
481 int lim, last, nfiles;
5e00df3b
KM
482 struct file **newofile;
483 char *newofileflags;
484
8429d022
MK
485 /*
486 * Search for a free descriptor starting at the higher
487 * of want or fd_freefile. If that fails, consider
488 * expanding the ofile array.
489 */
e0ed5a07 490 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
5e00df3b 491 for (;;) {
8429d022
MK
492 last = min(fdp->fd_nfiles, lim);
493 if ((i = want) < fdp->fd_freefile)
494 i = fdp->fd_freefile;
495 for (; i < last; i++) {
7ddc4f96
MK
496 if (fdp->fd_ofiles[i] == NULL) {
497 fdp->fd_ofileflags[i] = 0;
8429d022
MK
498 if (i > fdp->fd_lastfile)
499 fdp->fd_lastfile = i;
7ddc4f96 500 if (want <= fdp->fd_freefile)
8429d022
MK
501 fdp->fd_freefile = i;
502 *result = i;
5e00df3b
KM
503 return (0);
504 }
505 }
8429d022
MK
506
507 /*
508 * No space in current array. Expand?
509 */
510 if (fdp->fd_nfiles >= lim)
5e00df3b 511 return (EMFILE);
7ddc4f96
MK
512 if (fdp->fd_nfiles < NDEXTENT)
513 nfiles = NDEXTENT;
514 else
515 nfiles = 2 * fdp->fd_nfiles;
8429d022
MK
516 MALLOC(newofile, struct file **, nfiles * OFILESIZE,
517 M_FILEDESC, M_WAITOK);
518 newofileflags = (char *) &newofile[nfiles];
519 /*
520 * Copy the existing ofile and ofileflags arrays
521 * and zero the new portion of each array.
522 */
523 bcopy(fdp->fd_ofiles, newofile,
524 (i = sizeof(struct file *) * fdp->fd_nfiles));
525 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
526 bcopy(fdp->fd_ofileflags, newofileflags,
527 (i = sizeof(char) * fdp->fd_nfiles));
528 bzero(newofileflags + i, nfiles * sizeof(char) - i);
7ddc4f96
MK
529 if (fdp->fd_nfiles > NDFILE)
530 FREE(fdp->fd_ofiles, M_FILEDESC);
8429d022
MK
531 fdp->fd_ofiles = newofile;
532 fdp->fd_ofileflags = newofileflags;
533 fdp->fd_nfiles = nfiles;
534 fdexpand++;
06b22f9b 535 }
4147b3f6
BJ
536}
537
a53a698b 538/*
7ddc4f96
MK
539 * Check to see whether n user file descriptors
540 * are available to the process p.
a53a698b 541 */
8429d022
MK
542fdavail(p, n)
543 struct proc *p;
544 register int n;
88a7a62a 545{
8429d022 546 register struct filedesc *fdp = p->p_fd;
7ddc4f96 547 register struct file **fpp;
e0ed5a07 548 register int i, lim;
88a7a62a 549
e0ed5a07
KM
550 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
551 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
8429d022 552 return (1);
7ddc4f96
MK
553 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
554 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
555 if (*fpp == NULL && --n <= 0)
8429d022
MK
556 return (1);
557 return (0);
88a7a62a
SL
558}
559
4147b3f6 560/*
8429d022
MK
561 * Create a new open file structure and allocate
562 * a file decriptor for the process that refers to it.
4147b3f6 563 */
5e00df3b
KM
564falloc(p, resultfp, resultfd)
565 register struct proc *p;
c4ec2128
KM
566 struct file **resultfp;
567 int *resultfd;
4147b3f6 568{
c753a490 569 register struct file *fp, *fq, **fpp;
c4ec2128 570 int error, i;
4147b3f6 571
8429d022 572 if (error = fdalloc(p, 0, &i))
c4ec2128 573 return (error);
c753a490
KM
574 if (nfiles >= maxfiles) {
575 tablefull("file");
576 return (ENFILE);
577 }
578 /*
579 * Allocate a new file descriptor.
580 * If the process has file descriptor zero open, add to the list
581 * of open files at that point, otherwise put it at the front of
582 * the list of open files.
583 */
584 nfiles++;
585 MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
c753a490
KM
586 if (fq = p->p_fd->fd_ofiles[0])
587 fpp = &fq->f_filef;
588 else
589 fpp = &filehead;
c1884703 590 p->p_fd->fd_ofiles[i] = fp;
c753a490
KM
591 if (fq = *fpp)
592 fq->f_fileb = &fp->f_filef;
593 fp->f_filef = fq;
594 fp->f_fileb = fpp;
595 *fpp = fp;
88a7a62a 596 fp->f_count = 1;
c753a490 597 fp->f_msgcount = 0;
4147b3f6 598 fp->f_offset = 0;
8429d022 599 fp->f_cred = p->p_ucred;
c4ec2128 600 crhold(fp->f_cred);
c4ec2128
KM
601 if (resultfp)
602 *resultfp = fp;
603 if (resultfd)
604 *resultfd = i;
605 return (0);
4147b3f6
BJ
606}
607
c753a490
KM
608/*
609 * Free a file descriptor.
610 */
611ffree(fp)
612 register struct file *fp;
613{
614 register struct file *fq;
615
616 if (fq = fp->f_filef)
617 fq->f_fileb = fp->f_fileb;
618 *fp->f_fileb = fq;
619 crfree(fp->f_cred);
620#ifdef DIAGNOSTIC
621 fp->f_filef = NULL;
622 fp->f_fileb = NULL;
623 fp->f_count = 0;
624#endif
625 nfiles--;
626 FREE(fp, M_FILE);
627}
628
5e00df3b 629/*
8429d022 630 * Copy a filedesc structure.
5e00df3b
KM
631 */
632struct filedesc *
8429d022
MK
633fdcopy(p)
634 struct proc *p;
5e00df3b 635{
7ddc4f96
MK
636 register struct filedesc *newfdp, *fdp = p->p_fd;
637 register struct file **fpp;
5e00df3b 638 register int i;
5e00df3b 639
7ddc4f96
MK
640 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
641 M_FILEDESC, M_WAITOK);
642 bcopy(fdp, newfdp, sizeof(struct filedesc));
5e00df3b
KM
643 VREF(newfdp->fd_cdir);
644 if (newfdp->fd_rdir)
645 VREF(newfdp->fd_rdir);
646 newfdp->fd_refcnt = 1;
8429d022
MK
647
648 /*
7ddc4f96
MK
649 * If the number of open files fits in the internal arrays
650 * of the open file structure, use them, otherwise allocate
651 * additional memory for the number of descriptors currently
652 * in use.
8429d022 653 */
7ddc4f96
MK
654 if (newfdp->fd_lastfile < NDFILE) {
655 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
656 newfdp->fd_ofileflags =
657 ((struct filedesc0 *) newfdp)->fd_dfileflags;
658 i = NDFILE;
659 } else {
660 /*
661 * Compute the smallest multiple of NDEXTENT needed
662 * for the file descriptors currently in use,
663 * allowing the table to shrink.
664 */
665 i = newfdp->fd_nfiles;
666 while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
667 i /= 2;
668 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
669 M_FILEDESC, M_WAITOK);
670 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
671 }
8429d022 672 newfdp->fd_nfiles = i;
8429d022
MK
673 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
674 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
7ddc4f96
MK
675 fpp = newfdp->fd_ofiles;
676 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
677 if (*fpp != NULL)
678 (*fpp)->f_count++;
5e00df3b
KM
679 return (newfdp);
680}
681
682/*
683 * Release a filedesc structure.
684 */
7ddc4f96 685void
8429d022
MK
686fdfree(p)
687 struct proc *p;
5e00df3b 688{
8429d022 689 register struct filedesc *fdp = p->p_fd;
7ddc4f96 690 struct file **fpp;
5e00df3b
KM
691 register int i;
692
8429d022 693 if (--fdp->fd_refcnt > 0)
5e00df3b 694 return;
7ddc4f96
MK
695 fpp = fdp->fd_ofiles;
696 for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
697 if (*fpp)
698 (void) closef(*fpp, p);
699 if (fdp->fd_nfiles > NDFILE)
700 FREE(fdp->fd_ofiles, M_FILEDESC);
5e00df3b
KM
701 vrele(fdp->fd_cdir);
702 if (fdp->fd_rdir)
703 vrele(fdp->fd_rdir);
8429d022 704 FREE(fdp, M_FILEDESC);
5e00df3b
KM
705}
706
4147b3f6
BJ
707/*
708 * Internal form of close.
88a7a62a 709 * Decrement reference count on file structure.
93ca0e50
MK
710 * Note: p may be NULL when closing a file
711 * that was being passed in a message.
4147b3f6 712 */
8429d022 713closef(fp, p)
4147b3f6 714 register struct file *fp;
c753a490 715 register struct proc *p;
4147b3f6 716{
a4128336
KM
717 struct vnode *vp;
718 struct flock lf;
f9934296 719 int error;
4147b3f6 720
40056b21 721 if (fp == NULL)
f9934296 722 return (0);
a4128336
KM
723 /*
724 * POSIX record locking dictates that any close releases ALL
725 * locks owned by this process. This is handled by setting
726 * a flag in the unlock to free ONLY locks obeying POSIX
727 * semantics, and not to free BSD-style file locks.
93ca0e50
MK
728 * If the descriptor was in a message, POSIX-style locks
729 * aren't passed with the descriptor.
a4128336 730 */
93ca0e50 731 if (p && (p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) {
a4128336
KM
732 lf.l_whence = SEEK_SET;
733 lf.l_start = 0;
734 lf.l_len = 0;
735 lf.l_type = F_UNLCK;
736 vp = (struct vnode *)fp->f_data;
208eb71b 737 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
a4128336 738 }
8429d022 739 if (--fp->f_count > 0)
f9934296 740 return (0);
8429d022
MK
741 if (fp->f_count < 0)
742 panic("closef: count < 0");
9bd5ee04
KM
743 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
744 lf.l_whence = SEEK_SET;
745 lf.l_start = 0;
746 lf.l_len = 0;
747 lf.l_type = F_UNLCK;
748 vp = (struct vnode *)fp->f_data;
208eb71b 749 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
9bd5ee04 750 }
208eb71b 751 error = (*fp->f_ops->fo_close)(fp, p);
c753a490 752 ffree(fp);
f9934296 753 return (error);
8d528261 754}
92438dfc
SL
755
756/*
757 * Apply an advisory lock on a file descriptor.
a4128336
KM
758 *
759 * Just attempt to get a record lock of the requested type on
760 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
92438dfc 761 */
d5820a3c
CT
762struct flock_args {
763 int fd;
764 int how;
765};
a53a698b
KM
766/* ARGSUSED */
767flock(p, uap, retval)
768 struct proc *p;
d5820a3c 769 register struct flock_args *uap;
a53a698b
KM
770 int *retval;
771{
5e00df3b 772 register struct filedesc *fdp = p->p_fd;
92438dfc 773 register struct file *fp;
a4128336
KM
774 struct vnode *vp;
775 struct flock lf;
776 int error;
92438dfc 777
8429d022 778 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
7ddc4f96 779 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
d9c2f47f 780 return (EBADF);
a53a698b 781 if (fp->f_type != DTYPE_VNODE)
d9c2f47f 782 return (EOPNOTSUPP);
a4128336
KM
783 vp = (struct vnode *)fp->f_data;
784 lf.l_whence = SEEK_SET;
785 lf.l_start = 0;
786 lf.l_len = 0;
55dfda24 787 if (uap->how & LOCK_UN) {
a4128336 788 lf.l_type = F_UNLCK;
9bd5ee04 789 fp->f_flag &= ~FHASLOCK;
208eb71b 790 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
92438dfc 791 }
742253b3 792 if (uap->how & LOCK_EX)
a4128336
KM
793 lf.l_type = F_WRLCK;
794 else if (uap->how & LOCK_SH)
795 lf.l_type = F_RDLCK;
796 else
797 return (EBADF);
9bd5ee04 798 fp->f_flag |= FHASLOCK;
a4128336 799 if (uap->how & LOCK_NB)
208eb71b
KM
800 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
801 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
92438dfc 802}
75ebd8c9
MT
803
804/*
805 * File Descriptor pseudo-device driver (/dev/fd/).
806 *
75ebd8c9
MT
807 * Opening minor device N dup()s the file (if any) connected to file
808 * descriptor N belonging to the calling process. Note that this driver
809 * consists of only the ``open()'' routine, because all subsequent
810 * references to this file will be direct to the other driver.
811 */
c4ec2128 812/* ARGSUSED */
b640277d 813fdopen(dev, mode, type, p)
75ebd8c9 814 dev_t dev;
c4ec2128 815 int mode, type;
b640277d 816 struct proc *p;
75ebd8c9 817{
75ebd8c9
MT
818
819 /*
8429d022 820 * XXX Kludge: set curproc->p_dupfd to contain the value of the
1105efe2
KM
821 * the file descriptor being sought for duplication. The error
822 * return ensures that the vnode for this device will be released
823 * by vn_open. Open will detect this special error and take the
824 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
825 * will simply report the error.
75ebd8c9 826 */
b640277d 827 p->p_dupfd = minor(dev);
1105efe2
KM
828 return (ENODEV);
829}
e99d5db8 830
1105efe2
KM
831/*
832 * Duplicate the specified descriptor to a free descriptor.
833 */
d1c3140e 834dupfdopen(fdp, indx, dfd, mode, error)
5e00df3b 835 register struct filedesc *fdp;
1105efe2
KM
836 register int indx, dfd;
837 int mode;
d1c3140e 838 int error;
1105efe2
KM
839{
840 register struct file *wfp;
841 struct file *fp;
842
75ebd8c9 843 /*
1105efe2
KM
844 * If the to-be-dup'd fd number is greater than the allowed number
845 * of file descriptors, or the fd to be dup'd has already been
846 * closed, reject. Note, check for new == old is necessary as
847 * falloc could allocate an already closed to-be-dup'd descriptor
848 * as the new descriptor.
75ebd8c9 849 */
7ddc4f96
MK
850 fp = fdp->fd_ofiles[indx];
851 if ((u_int)dfd >= fdp->fd_nfiles ||
852 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
75ebd8c9 853 return (EBADF);
e99d5db8 854
75ebd8c9 855 /*
d1c3140e
JSP
856 * There are two cases of interest here.
857 *
858 * For ENODEV simply dup (dfd) to file descriptor
859 * (indx) and return.
860 *
861 * For ENXIO steal away the file structure from (dfd) and
862 * store it in (indx). (dfd) is effectively closed by
863 * this operation.
864 *
865 * Any other error code is just returned.
75ebd8c9 866 */
d1c3140e
JSP
867 switch (error) {
868 case ENODEV:
869 /*
870 * Check that the mode the file is being opened for is a
871 * subset of the mode of the existing descriptor.
872 */
873 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
874 return (EACCES);
875 fdp->fd_ofiles[indx] = wfp;
876 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
877 wfp->f_count++;
878 if (indx > fdp->fd_lastfile)
879 fdp->fd_lastfile = indx;
880 return (0);
881
882 case ENXIO:
883 /*
884 * Steal away the file pointer from dfd, and stuff it into indx.
885 */
886 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
887 fdp->fd_ofiles[dfd] = NULL;
888 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
889 fdp->fd_ofileflags[dfd] = 0;
890 /*
891 * Complete the clean up of the filedesc structure by
892 * recomputing the various hints.
893 */
894 if (indx > fdp->fd_lastfile)
895 fdp->fd_lastfile = indx;
896 else
897 while (fdp->fd_lastfile > 0 &&
898 fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
899 fdp->fd_lastfile--;
900 if (dfd < fdp->fd_freefile)
901 fdp->fd_freefile = dfd;
902 return (0);
903
904 default:
905 return (error);
906 }
907 /* NOTREACHED */
75ebd8c9 908}