rm unneeded proc flags; set up for cpu_fork to relocate kernel stack;
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
da7c5cc6 1/*
7ddc4f96 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
c4ec2128 3 * All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
c4ec2128 6 *
208eb71b 7 * @(#)kern_descrip.c 7.23 (Berkeley) %G%
da7c5cc6 8 */
40056b21 9
94368568
JB
10#include "param.h"
11#include "systm.h"
5e00df3b 12#include "filedesc.h"
94368568 13#include "kernel.h"
c4ec2128 14#include "vnode.h"
94368568 15#include "proc.h"
94368568
JB
16#include "file.h"
17#include "socket.h"
18#include "socketvar.h"
94368568 19#include "stat.h"
94368568 20#include "ioctl.h"
a4128336 21#include "fcntl.h"
5e00df3b
KM
22#include "malloc.h"
23#include "syslog.h"
7ddc4f96 24#include "resourcevar.h"
4147b3f6
BJ
25
26/*
27 * Descriptor management.
28 */
29
40056b21 30/*
4147b3f6 31 * System calls on descriptors.
40056b21 32 */
a53a698b
KM
33/* ARGSUSED */
34getdtablesize(p, uap, retval)
35 struct proc *p;
36 struct args *uap;
37 int *retval;
4147b3f6
BJ
38{
39
8429d022 40 *retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
d9c2f47f 41 return (0);
4147b3f6
BJ
42}
43
a53a698b
KM
44/*
45 * Duplicate a file descriptor.
46 */
47/* ARGSUSED */
48dup(p, uap, retval)
49 struct proc *p;
50 struct args {
4147b3f6 51 int i;
a53a698b
KM
52 } *uap;
53 int *retval;
54{
5e00df3b 55 register struct filedesc *fdp = p->p_fd;
a81e9a81 56 struct file *fp;
a53a698b 57 int fd, error;
4147b3f6 58
a53a698b
KM
59 /*
60 * XXX Compatibility
61 */
d9c2f47f 62 if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); }
4147b3f6 63
8429d022 64 if ((unsigned)uap->i >= fdp->fd_nfiles ||
7ddc4f96 65 (fp = fdp->fd_ofiles[uap->i]) == NULL)
d9c2f47f 66 return (EBADF);
8429d022 67 if (error = fdalloc(p, 0, &fd))
d9c2f47f 68 return (error);
7ddc4f96
MK
69 fdp->fd_ofiles[fd] = fp;
70 fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE;
a53a698b 71 fp->f_count++;
5e00df3b
KM
72 if (fd > fdp->fd_lastfile)
73 fdp->fd_lastfile = fd;
a53a698b 74 *retval = fd;
d9c2f47f 75 return (0);
4147b3f6
BJ
76}
77
a53a698b
KM
78/*
79 * Duplicate a file descriptor to a particular value.
80 */
81/* ARGSUSED */
82dup2(p, uap, retval)
83 struct proc *p;
7ddc4f96
MK
84 struct args {
85 u_int from;
86 u_int to;
a53a698b
KM
87 } *uap;
88 int *retval;
4147b3f6 89{
5e00df3b 90 register struct filedesc *fdp = p->p_fd;
4147b3f6 91 register struct file *fp;
7ddc4f96 92 register u_int old = uap->from, new = uap->to;
5e00df3b 93 int i, error;
40056b21 94
7ddc4f96
MK
95 if (old >= fdp->fd_nfiles ||
96 (fp = fdp->fd_ofiles[old]) == NULL ||
97 new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
d9c2f47f 98 return (EBADF);
7ddc4f96
MK
99 *retval = new;
100 if (old == new)
d9c2f47f 101 return (0);
7ddc4f96
MK
102 if (new >= fdp->fd_nfiles) {
103 if (error = fdalloc(p, new, &i))
5e00df3b 104 return (error);
7ddc4f96 105 if (new != i)
8429d022 106 panic("dup2: fdalloc");
7ddc4f96
MK
107 } else if (fdp->fd_ofiles[new]) {
108 if (fdp->fd_ofileflags[new] & UF_MAPPED)
109 (void) munmapfd(p, new);
110 /*
111 * dup2() must succeed even if the close has an error.
112 */
113 (void) closef(fdp->fd_ofiles[new], p);
4147b3f6 114 }
7ddc4f96
MK
115 fdp->fd_ofiles[new] = fp;
116 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
a53a698b 117 fp->f_count++;
7ddc4f96
MK
118 if (new > fdp->fd_lastfile)
119 fdp->fd_lastfile = new;
120 return (0);
a81e9a81
SL
121}
122
88a7a62a
SL
123/*
124 * The file control system call.
125 */
a53a698b
KM
126/* ARGSUSED */
127fcntl(p, uap, retval)
128 struct proc *p;
129 register struct args {
8429d022 130 int fd;
88a7a62a
SL
131 int cmd;
132 int arg;
a53a698b
KM
133 } *uap;
134 int *retval;
135{
5e00df3b 136 register struct filedesc *fdp = p->p_fd;
a53a698b 137 register struct file *fp;
88a7a62a 138 register char *pop;
a4128336 139 struct vnode *vp;
208eb71b 140 int i, tmp, error, flg = F_POSIX;
a4128336 141 struct flock fl;
4147b3f6 142
8429d022 143 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
7ddc4f96 144 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
d9c2f47f 145 return (EBADF);
7ddc4f96 146 pop = &fdp->fd_ofileflags[uap->fd];
88a7a62a 147 switch(uap->cmd) {
85f01bd4 148 case F_DUPFD:
8429d022 149 if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
d9c2f47f 150 return (EINVAL);
8429d022 151 if (error = fdalloc(p, uap->arg, &i))
d9c2f47f 152 return (error);
7ddc4f96
MK
153 fdp->fd_ofiles[i] = fp;
154 fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE;
a53a698b 155 fp->f_count++;
5e00df3b
KM
156 if (i > fdp->fd_lastfile)
157 fdp->fd_lastfile = i;
a53a698b 158 *retval = i;
d9c2f47f 159 return (0);
12438177 160
85f01bd4 161 case F_GETFD:
a53a698b 162 *retval = *pop & 1;
d9c2f47f 163 return (0);
40056b21 164
85f01bd4 165 case F_SETFD:
88a7a62a 166 *pop = (*pop &~ 1) | (uap->arg & 1);
d9c2f47f 167 return (0);
12438177 168
85f01bd4 169 case F_GETFL:
f474c4c6 170 *retval = OFLAGS(fp->f_flag);
d9c2f47f 171 return (0);
12438177 172
85f01bd4 173 case F_SETFL:
f474c4c6
MK
174 fp->f_flag &= ~FCNTLFLAGS;
175 fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
208eb71b
KM
176 if (tmp = (fp->f_flag & FNDELAY))
177 fp->f_flag |= FNDELAY;
178 else
179 fp->f_flag &= ~FNDELAY;
180 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
181 if (error)
d9c2f47f 182 return (error);
208eb71b
KM
183 if (tmp = (fp->f_flag & FASYNC))
184 fp->f_flag |= FASYNC;
185 else
186 fp->f_flag &= ~FASYNC;
187 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
188 if (!error)
189 return (0);
190 fp->f_flag &= ~FNDELAY;
191 tmp = 0;
192 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
d9c2f47f 193 return (error);
88a7a62a 194
85f01bd4 195 case F_GETOWN:
208eb71b
KM
196 if (fp->f_type == DTYPE_SOCKET) {
197 *retval = ((struct socket *)fp->f_data)->so_pgid;
198 return (0);
199 }
200 error = (*fp->f_ops->fo_ioctl)
201 (fp, (int)TIOCGPGRP, (caddr_t)retval, p);
202 *retval = -*retval;
203 return (error);
88a7a62a 204
85f01bd4 205 case F_SETOWN:
208eb71b
KM
206 if (fp->f_type == DTYPE_SOCKET) {
207 ((struct socket *)fp->f_data)->so_pgid = uap->arg;
208 return (0);
209 }
210 if (uap->arg <= 0) {
211 uap->arg = -uap->arg;
212 } else {
213 struct proc *p1 = pfind(uap->arg);
214 if (p1 == 0)
215 return (ESRCH);
216 uap->arg = p1->p_pgrp->pg_id;
217 }
218 return ((*fp->f_ops->fo_ioctl)
219 (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
88a7a62a 220
a4128336 221 case F_SETLKW:
208eb71b 222 flg |= F_WAIT;
a4128336
KM
223 /* Fall into F_SETLK */
224
225 case F_SETLK:
226 if (fp->f_type != DTYPE_VNODE)
227 return (EBADF);
228 vp = (struct vnode *)fp->f_data;
229 /* Copy in the lock structure */
230 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
231 if (error)
232 return (error);
233 if (fl.l_whence == SEEK_CUR)
234 fl.l_start += fp->f_offset;
235 switch (fl.l_type) {
236
237 case F_RDLCK:
238 if ((fp->f_flag & FREAD) == 0)
239 return (EBADF);
208eb71b 240 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
a4128336
KM
241
242 case F_WRLCK:
243 if ((fp->f_flag & FWRITE) == 0)
244 return (EBADF);
208eb71b 245 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
a4128336
KM
246
247 case F_UNLCK:
208eb71b
KM
248 return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
249 F_POSIX));
a4128336
KM
250
251 default:
252 return (EINVAL);
253 }
254
255 case F_GETLK:
256 if (fp->f_type != DTYPE_VNODE)
257 return (EBADF);
258 vp = (struct vnode *)fp->f_data;
259 /* Copy in the lock structure */
260 error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
261 if (error)
262 return (error);
2975e814
KM
263 if (fl.l_whence == SEEK_CUR)
264 fl.l_start += fp->f_offset;
208eb71b 265 if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
a4128336
KM
266 return (error);
267 return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
268
88a7a62a 269 default:
d9c2f47f 270 return (EINVAL);
40056b21 271 }
a53a698b 272 /* NOTREACHED */
40056b21
BJ
273}
274
a53a698b
KM
275/*
276 * Close a file descriptor.
277 */
278/* ARGSUSED */
279close(p, uap, retval)
280 struct proc *p;
281 struct args {
8429d022 282 int fd;
a53a698b
KM
283 } *uap;
284 int *retval;
285{
5e00df3b 286 register struct filedesc *fdp = p->p_fd;
88a7a62a 287 register struct file *fp;
8429d022 288 register int fd = uap->fd;
92438dfc 289 register u_char *pf;
3ebb7a40 290
8429d022 291 if ((unsigned)fd >= fdp->fd_nfiles ||
7ddc4f96 292 (fp = fdp->fd_ofiles[fd]) == NULL)
d9c2f47f 293 return (EBADF);
7ddc4f96 294 pf = (u_char *)&fdp->fd_ofileflags[fd];
92438dfc 295 if (*pf & UF_MAPPED)
8429d022 296 (void) munmapfd(p, fd);
7ddc4f96
MK
297 fdp->fd_ofiles[fd] = NULL;
298 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
5e00df3b 299 fdp->fd_lastfile--;
8429d022
MK
300 if (fd < fdp->fd_freefile)
301 fdp->fd_freefile = fd;
92438dfc 302 *pf = 0;
8429d022 303 return (closef(fp, p));
92438dfc
SL
304}
305
a53a698b
KM
306/*
307 * Return status information about a file descriptor.
308 */
309/* ARGSUSED */
310fstat(p, uap, retval)
311 struct proc *p;
312 register struct args {
8429d022 313 int fd;
92438dfc 314 struct stat *sb;
a53a698b
KM
315 } *uap;
316 int *retval;
317{
5e00df3b 318 register struct filedesc *fdp = p->p_fd;
a53a698b 319 register struct file *fp;
92438dfc 320 struct stat ub;
a53a698b 321 int error;
92438dfc 322
8429d022 323 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
7ddc4f96 324 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
d9c2f47f 325 return (EBADF);
92438dfc
SL
326 switch (fp->f_type) {
327
c4ec2128 328 case DTYPE_VNODE:
208eb71b 329 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
92438dfc
SL
330 break;
331
332 case DTYPE_SOCKET:
a53a698b 333 error = soo_stat((struct socket *)fp->f_data, &ub);
92438dfc
SL
334 break;
335
336 default:
337 panic("fstat");
338 /*NOTREACHED*/
339 }
a53a698b
KM
340 if (error == 0)
341 error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
d9c2f47f 342 return (error);
3ebb7a40
BJ
343}
344
40056b21 345/*
8429d022 346 * Allocate a file descriptor for the process.
40056b21 347 */
8429d022 348int fdexpand;
5e00df3b 349
8429d022
MK
350fdalloc(p, want, result)
351 struct proc *p;
352 int want;
c4ec2128 353 int *result;
4147b3f6 354{
8429d022
MK
355 register struct filedesc *fdp = p->p_fd;
356 register int i;
357 int lim, last, nfiles;
5e00df3b
KM
358 struct file **newofile;
359 char *newofileflags;
360
8429d022
MK
361 /*
362 * Search for a free descriptor starting at the higher
363 * of want or fd_freefile. If that fails, consider
364 * expanding the ofile array.
365 */
366 lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
5e00df3b 367 for (;;) {
8429d022
MK
368 last = min(fdp->fd_nfiles, lim);
369 if ((i = want) < fdp->fd_freefile)
370 i = fdp->fd_freefile;
371 for (; i < last; i++) {
7ddc4f96
MK
372 if (fdp->fd_ofiles[i] == NULL) {
373 fdp->fd_ofileflags[i] = 0;
8429d022
MK
374 if (i > fdp->fd_lastfile)
375 fdp->fd_lastfile = i;
7ddc4f96 376 if (want <= fdp->fd_freefile)
8429d022
MK
377 fdp->fd_freefile = i;
378 *result = i;
5e00df3b
KM
379 return (0);
380 }
381 }
8429d022
MK
382
383 /*
384 * No space in current array. Expand?
385 */
386 if (fdp->fd_nfiles >= lim)
5e00df3b 387 return (EMFILE);
7ddc4f96
MK
388 if (fdp->fd_nfiles < NDEXTENT)
389 nfiles = NDEXTENT;
390 else
391 nfiles = 2 * fdp->fd_nfiles;
8429d022
MK
392 MALLOC(newofile, struct file **, nfiles * OFILESIZE,
393 M_FILEDESC, M_WAITOK);
394 newofileflags = (char *) &newofile[nfiles];
395 /*
396 * Copy the existing ofile and ofileflags arrays
397 * and zero the new portion of each array.
398 */
399 bcopy(fdp->fd_ofiles, newofile,
400 (i = sizeof(struct file *) * fdp->fd_nfiles));
401 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
402 bcopy(fdp->fd_ofileflags, newofileflags,
403 (i = sizeof(char) * fdp->fd_nfiles));
404 bzero(newofileflags + i, nfiles * sizeof(char) - i);
7ddc4f96
MK
405 if (fdp->fd_nfiles > NDFILE)
406 FREE(fdp->fd_ofiles, M_FILEDESC);
8429d022
MK
407 fdp->fd_ofiles = newofile;
408 fdp->fd_ofileflags = newofileflags;
409 fdp->fd_nfiles = nfiles;
410 fdexpand++;
06b22f9b 411 }
4147b3f6
BJ
412}
413
a53a698b 414/*
7ddc4f96
MK
415 * Check to see whether n user file descriptors
416 * are available to the process p.
a53a698b 417 */
8429d022
MK
418fdavail(p, n)
419 struct proc *p;
420 register int n;
88a7a62a 421{
8429d022 422 register struct filedesc *fdp = p->p_fd;
7ddc4f96 423 register struct file **fpp;
8429d022 424 register int i;
88a7a62a 425
8429d022
MK
426 if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 &&
427 (n -= i) <= 0)
428 return (1);
7ddc4f96
MK
429 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
430 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
431 if (*fpp == NULL && --n <= 0)
8429d022
MK
432 return (1);
433 return (0);
88a7a62a
SL
434}
435
4147b3f6
BJ
436struct file *lastf;
437/*
8429d022
MK
438 * Create a new open file structure and allocate
439 * a file decriptor for the process that refers to it.
4147b3f6 440 */
5e00df3b
KM
441falloc(p, resultfp, resultfd)
442 register struct proc *p;
c4ec2128
KM
443 struct file **resultfp;
444 int *resultfd;
4147b3f6
BJ
445{
446 register struct file *fp;
c4ec2128 447 int error, i;
4147b3f6 448
8429d022 449 if (error = fdalloc(p, 0, &i))
c4ec2128 450 return (error);
4147b3f6
BJ
451 if (lastf == 0)
452 lastf = file;
453 for (fp = lastf; fp < fileNFILE; fp++)
454 if (fp->f_count == 0)
455 goto slot;
456 for (fp = file; fp < lastf; fp++)
457 if (fp->f_count == 0)
458 goto slot;
459 tablefull("file");
c4ec2128 460 return (ENFILE);
4147b3f6 461slot:
7ddc4f96 462 p->p_fd->fd_ofiles[i] = fp;
88a7a62a
SL
463 fp->f_count = 1;
464 fp->f_data = 0;
4147b3f6 465 fp->f_offset = 0;
8429d022 466 fp->f_cred = p->p_ucred;
c4ec2128 467 crhold(fp->f_cred);
4147b3f6 468 lastf = fp + 1;
c4ec2128
KM
469 if (resultfp)
470 *resultfp = fp;
471 if (resultfd)
472 *resultfd = i;
473 return (0);
4147b3f6
BJ
474}
475
5e00df3b 476/*
8429d022 477 * Copy a filedesc structure.
5e00df3b
KM
478 */
479struct filedesc *
8429d022
MK
480fdcopy(p)
481 struct proc *p;
5e00df3b 482{
7ddc4f96
MK
483 register struct filedesc *newfdp, *fdp = p->p_fd;
484 register struct file **fpp;
5e00df3b 485 register int i;
5e00df3b 486
7ddc4f96
MK
487 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
488 M_FILEDESC, M_WAITOK);
489 bcopy(fdp, newfdp, sizeof(struct filedesc));
5e00df3b
KM
490 VREF(newfdp->fd_cdir);
491 if (newfdp->fd_rdir)
492 VREF(newfdp->fd_rdir);
493 newfdp->fd_refcnt = 1;
8429d022
MK
494
495 /*
7ddc4f96
MK
496 * If the number of open files fits in the internal arrays
497 * of the open file structure, use them, otherwise allocate
498 * additional memory for the number of descriptors currently
499 * in use.
8429d022 500 */
7ddc4f96
MK
501 if (newfdp->fd_lastfile < NDFILE) {
502 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
503 newfdp->fd_ofileflags =
504 ((struct filedesc0 *) newfdp)->fd_dfileflags;
505 i = NDFILE;
506 } else {
507 /*
508 * Compute the smallest multiple of NDEXTENT needed
509 * for the file descriptors currently in use,
510 * allowing the table to shrink.
511 */
512 i = newfdp->fd_nfiles;
513 while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
514 i /= 2;
515 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
516 M_FILEDESC, M_WAITOK);
517 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
518 }
8429d022 519 newfdp->fd_nfiles = i;
8429d022
MK
520 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
521 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
7ddc4f96
MK
522 fpp = newfdp->fd_ofiles;
523 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
524 if (*fpp != NULL)
525 (*fpp)->f_count++;
5e00df3b
KM
526 return (newfdp);
527}
528
529/*
530 * Release a filedesc structure.
531 */
7ddc4f96 532void
8429d022
MK
533fdfree(p)
534 struct proc *p;
5e00df3b 535{
8429d022 536 register struct filedesc *fdp = p->p_fd;
7ddc4f96 537 struct file **fpp;
5e00df3b
KM
538 register int i;
539
8429d022 540 if (--fdp->fd_refcnt > 0)
5e00df3b 541 return;
7ddc4f96
MK
542 fpp = fdp->fd_ofiles;
543 for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
544 if (*fpp)
545 (void) closef(*fpp, p);
546 if (fdp->fd_nfiles > NDFILE)
547 FREE(fdp->fd_ofiles, M_FILEDESC);
5e00df3b
KM
548 vrele(fdp->fd_cdir);
549 if (fdp->fd_rdir)
550 vrele(fdp->fd_rdir);
8429d022 551 FREE(fdp, M_FILEDESC);
5e00df3b
KM
552}
553
4147b3f6
BJ
554/*
555 * Internal form of close.
88a7a62a 556 * Decrement reference count on file structure.
4147b3f6 557 */
8429d022 558closef(fp, p)
4147b3f6 559 register struct file *fp;
8429d022 560 struct proc *p;
4147b3f6 561{
a4128336
KM
562 struct vnode *vp;
563 struct flock lf;
f9934296 564 int error;
4147b3f6 565
40056b21 566 if (fp == NULL)
f9934296 567 return (0);
a4128336
KM
568 /*
569 * POSIX record locking dictates that any close releases ALL
570 * locks owned by this process. This is handled by setting
571 * a flag in the unlock to free ONLY locks obeying POSIX
572 * semantics, and not to free BSD-style file locks.
573 */
574 if (fp->f_type == DTYPE_VNODE) {
575 lf.l_whence = SEEK_SET;
576 lf.l_start = 0;
577 lf.l_len = 0;
578 lf.l_type = F_UNLCK;
579 vp = (struct vnode *)fp->f_data;
208eb71b 580 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
a4128336 581 }
8429d022 582 if (--fp->f_count > 0)
f9934296 583 return (0);
8429d022
MK
584 if (fp->f_count < 0)
585 panic("closef: count < 0");
a4128336 586 if (fp->f_type == DTYPE_VNODE)
208eb71b
KM
587 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
588 error = (*fp->f_ops->fo_close)(fp, p);
c4ec2128 589 crfree(fp->f_cred);
4147b3f6 590 fp->f_count = 0;
f9934296 591 return (error);
8d528261 592}
92438dfc
SL
593
594/*
595 * Apply an advisory lock on a file descriptor.
a4128336
KM
596 *
597 * Just attempt to get a record lock of the requested type on
598 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
92438dfc 599 */
a4128336 600
a53a698b
KM
601/* ARGSUSED */
602flock(p, uap, retval)
603 struct proc *p;
604 register struct args {
8429d022 605 int fd;
92438dfc 606 int how;
a53a698b
KM
607 } *uap;
608 int *retval;
609{
5e00df3b 610 register struct filedesc *fdp = p->p_fd;
92438dfc 611 register struct file *fp;
a4128336
KM
612 struct vnode *vp;
613 struct flock lf;
614 int error;
92438dfc 615
8429d022 616 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
7ddc4f96 617 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
d9c2f47f 618 return (EBADF);
a53a698b 619 if (fp->f_type != DTYPE_VNODE)
d9c2f47f 620 return (EOPNOTSUPP);
a4128336
KM
621 vp = (struct vnode *)fp->f_data;
622 lf.l_whence = SEEK_SET;
623 lf.l_start = 0;
624 lf.l_len = 0;
55dfda24 625 if (uap->how & LOCK_UN) {
a4128336 626 lf.l_type = F_UNLCK;
208eb71b 627 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
92438dfc 628 }
742253b3 629 if (uap->how & LOCK_EX)
a4128336
KM
630 lf.l_type = F_WRLCK;
631 else if (uap->how & LOCK_SH)
632 lf.l_type = F_RDLCK;
633 else
634 return (EBADF);
635 if (uap->how & LOCK_NB)
208eb71b
KM
636 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
637 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
92438dfc 638}
75ebd8c9
MT
639
640/*
641 * File Descriptor pseudo-device driver (/dev/fd/).
642 *
75ebd8c9
MT
643 * Opening minor device N dup()s the file (if any) connected to file
644 * descriptor N belonging to the calling process. Note that this driver
645 * consists of only the ``open()'' routine, because all subsequent
646 * references to this file will be direct to the other driver.
647 */
c4ec2128
KM
648/* ARGSUSED */
649fdopen(dev, mode, type)
75ebd8c9 650 dev_t dev;
c4ec2128 651 int mode, type;
75ebd8c9 652{
75ebd8c9
MT
653
654 /*
8429d022 655 * XXX Kludge: set curproc->p_dupfd to contain the value of the
1105efe2
KM
656 * the file descriptor being sought for duplication. The error
657 * return ensures that the vnode for this device will be released
658 * by vn_open. Open will detect this special error and take the
659 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
660 * will simply report the error.
75ebd8c9 661 */
8429d022 662 curproc->p_dupfd = minor(dev); /* XXX */
1105efe2
KM
663 return (ENODEV);
664}
e99d5db8 665
1105efe2
KM
666/*
667 * Duplicate the specified descriptor to a free descriptor.
668 */
5e00df3b
KM
669dupfdopen(fdp, indx, dfd, mode)
670 register struct filedesc *fdp;
1105efe2
KM
671 register int indx, dfd;
672 int mode;
673{
674 register struct file *wfp;
675 struct file *fp;
676
75ebd8c9 677 /*
1105efe2
KM
678 * If the to-be-dup'd fd number is greater than the allowed number
679 * of file descriptors, or the fd to be dup'd has already been
680 * closed, reject. Note, check for new == old is necessary as
681 * falloc could allocate an already closed to-be-dup'd descriptor
682 * as the new descriptor.
75ebd8c9 683 */
7ddc4f96
MK
684 fp = fdp->fd_ofiles[indx];
685 if ((u_int)dfd >= fdp->fd_nfiles ||
686 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
75ebd8c9 687 return (EBADF);
e99d5db8 688
75ebd8c9 689 /*
e99d5db8
KB
690 * Check that the mode the file is being opened for is a subset
691 * of the mode of the existing descriptor.
75ebd8c9 692 */
1105efe2 693 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
75ebd8c9 694 return (EACCES);
7ddc4f96
MK
695 fdp->fd_ofiles[indx] = wfp;
696 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
a53a698b 697 wfp->f_count++;
5e00df3b
KM
698 if (indx > fdp->fd_lastfile)
699 fdp->fd_lastfile = indx;
1105efe2 700 return (0);
75ebd8c9 701}