Annotation of src/sys/kern/kern_descrip.c, Revision 1.124
1.124 ! yamt 1: /* $NetBSD: kern_descrip.c,v 1.123 2004/01/07 09:26:29 jdolecek Exp $ */
1.22 cgd 2:
1.16 cgd 3: /*
1.17 cgd 4: * Copyright (c) 1982, 1986, 1989, 1991, 1993
5: * The Regents of the University of California. All rights reserved.
1.16 cgd 6: * (c) UNIX System Laboratories, Inc.
7: * All or some portions of this file are derived from material licensed
8: * to the University of California by American Telephone and Telegraph
9: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10: * the permission of UNIX System Laboratories, Inc.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
1.111 agc 20: * 3. Neither the name of the University nor the names of its contributors
1.16 cgd 21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
1.51 fvdl 36: * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
1.16 cgd 37: */
1.81 lukem 38:
39: #include <sys/cdefs.h>
1.124 ! yamt 40: __KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.123 2004/01/07 09:26:29 jdolecek Exp $");
1.50 mrg 41:
1.16 cgd 42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/filedesc.h>
45: #include <sys/kernel.h>
46: #include <sys/vnode.h>
47: #include <sys/proc.h>
48: #include <sys/file.h>
1.86 christos 49: #include <sys/namei.h>
1.16 cgd 50: #include <sys/socket.h>
51: #include <sys/socketvar.h>
52: #include <sys/stat.h>
53: #include <sys/ioctl.h>
54: #include <sys/fcntl.h>
55: #include <sys/malloc.h>
1.55 thorpej 56: #include <sys/pool.h>
1.16 cgd 57: #include <sys/syslog.h>
1.17 cgd 58: #include <sys/unistd.h>
1.16 cgd 59: #include <sys/resourcevar.h>
1.42 christos 60: #include <sys/conf.h>
1.96 jdolecek 61: #include <sys/event.h>
1.16 cgd 62:
1.25 cgd 63: #include <sys/mount.h>
1.99 thorpej 64: #include <sys/sa.h>
1.25 cgd 65: #include <sys/syscallargs.h>
1.38 christos 66:
1.16 cgd 67: /*
68: * Descriptor management.
69: */
1.72 lukem 70: struct filelist filehead; /* head of list of open files */
71: int nfiles; /* actual number of open files */
72: struct pool file_pool; /* memory pool for file structures */
73: struct pool cwdi_pool; /* memory pool for cwdinfo structures */
74: struct pool filedesc0_pool; /* memory pool for filedesc0 structures */
1.101 thorpej 75:
1.102 pk 76: /* Global file list lock */
77: static struct simplelock filelist_slock = SIMPLELOCK_INITIALIZER;
78:
1.101 thorpej 79: MALLOC_DEFINE(M_FILE, "file", "Open file structure");
80: MALLOC_DEFINE(M_FILEDESC, "file desc", "Open file descriptor table");
81: MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
1.72 lukem 82:
83: static __inline void fd_used(struct filedesc *, int);
84: static __inline void fd_unused(struct filedesc *, int);
1.115 provos 85: static __inline int find_next_zero(uint32_t *, int, u_int);
1.110 fvdl 86: int finishdup(struct proc *, int, int, register_t *);
1.115 provos 87: int find_last_set(struct filedesc *, int);
1.110 fvdl 88: int fcntl_forfs(int, struct proc *, int, void *);
1.94 gehenna 89:
90: dev_type_open(filedescopen);
91:
92: const struct cdevsw filedesc_cdevsw = {
93: filedescopen, noclose, noread, nowrite, noioctl,
1.96 jdolecek 94: nostop, notty, nopoll, nommap, nokqfilter,
1.94 gehenna 95: };
1.38 christos 96:
1.115 provos 97: static __inline int
98: find_next_zero(uint32_t *bitmap, int want, u_int bits)
99: {
100: int i, off, maxoff;
101: uint32_t sub;
102:
103: if (want > bits)
104: return -1;
105:
106: off = want >> NDENTRYSHIFT;
107: i = want & NDENTRYMASK;
108: if (i) {
109: sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i));
110: if (sub != ~0)
111: goto found;
112: off++;
113: }
114:
115: maxoff = NDLOSLOTS(bits);
116: while (off < maxoff) {
117: if ((sub = bitmap[off]) != ~0)
118: goto found;
119: off++;
120: }
121:
122: return (-1);
123:
124: found:
125: return (off << NDENTRYSHIFT) + ffs(~sub) - 1;
126: }
127:
128: int
129: find_last_set(struct filedesc *fd, int last)
130: {
131: int off, i;
132: struct file **ofiles = fd->fd_ofiles;
133: uint32_t *bitmap = fd->fd_lomap;
134:
135: off = (last - 1) >> NDENTRYSHIFT;
136:
1.121 provos 137: while (off >= 0 && !bitmap[off])
1.115 provos 138: off--;
139:
140: if (off < 0)
141: return (0);
142:
143: i = ((off + 1) << NDENTRYSHIFT) - 1;
144: if (i >= last)
145: i = last - 1;
146:
147: while (i > 0 && ofiles[i] == NULL)
148: i--;
149:
150: return (i);
151: }
152:
1.38 christos 153: static __inline void
1.72 lukem 154: fd_used(struct filedesc *fdp, int fd)
1.27 mycroft 155: {
1.115 provos 156: u_int off = fd >> NDENTRYSHIFT;
157:
1.124 ! yamt 158: KDASSERT((fdp->fd_lomap[off] & (1 << (fd & NDENTRYMASK))) == 0);
! 159:
1.115 provos 160: fdp->fd_lomap[off] |= 1 << (fd & NDENTRYMASK);
1.124 ! yamt 161: if (fdp->fd_lomap[off] == ~0) {
! 162: KDASSERT((fdp->fd_himap[off >> NDENTRYSHIFT] &
! 163: (1 << (off & NDENTRYMASK))) == 0);
1.115 provos 164: fdp->fd_himap[off >> NDENTRYSHIFT] |= 1 << (off & NDENTRYMASK);
1.124 ! yamt 165: }
1.27 mycroft 166:
167: if (fd > fdp->fd_lastfile)
168: fdp->fd_lastfile = fd;
169: }
170:
1.38 christos 171: static __inline void
1.72 lukem 172: fd_unused(struct filedesc *fdp, int fd)
1.27 mycroft 173: {
1.115 provos 174: u_int off = fd >> NDENTRYSHIFT;
1.27 mycroft 175:
176: if (fd < fdp->fd_freefile)
177: fdp->fd_freefile = fd;
1.115 provos 178:
1.124 ! yamt 179: if (fdp->fd_lomap[off] == ~0) {
! 180: KDASSERT((fdp->fd_himap[off >> NDENTRYSHIFT] &
! 181: (1 << (off & NDENTRYMASK))) != 0);
! 182: fdp->fd_himap[off >> NDENTRYSHIFT] &=
! 183: ~(1 << (off & NDENTRYMASK));
! 184: }
! 185: KDASSERT((fdp->fd_lomap[off] & (1 << (fd & NDENTRYMASK))) != 0);
1.115 provos 186: fdp->fd_lomap[off] &= ~(1 << (fd & NDENTRYMASK));
187:
1.27 mycroft 188: #ifdef DIAGNOSTIC
189: if (fd > fdp->fd_lastfile)
190: panic("fd_unused: fd_lastfile inconsistent");
191: #endif
1.115 provos 192: if (fd == fdp->fd_lastfile)
193: fdp->fd_lastfile = find_last_set(fdp, fd);
1.27 mycroft 194: }
195:
1.103 pk 196: /*
197: * Lookup the file structure corresponding to a file descriptor
198: * and return it locked.
199: * Note: typical usage is: `fp = fd_getfile(..); FILE_USE(fp);'
200: * The locking strategy has been optimised for this case, i.e.
201: * fd_getfile() returns the file locked while FILE_USE() will increment
202: * the file's use count and unlock.
203: */
1.77 thorpej 204: struct file *
205: fd_getfile(struct filedesc *fdp, int fd)
206: {
207: struct file *fp;
208:
209: if ((u_int) fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
210: return (NULL);
211:
1.103 pk 212: simple_lock(&fp->f_slock);
213: if (FILE_IS_USABLE(fp) == 0) {
214: simple_unlock(&fp->f_slock);
1.77 thorpej 215: return (NULL);
1.103 pk 216: }
1.77 thorpej 217:
218: return (fp);
219: }
220:
1.16 cgd 221: /*
222: * System calls on descriptors.
223: */
1.18 cgd 224:
1.16 cgd 225: /*
226: * Duplicate a file descriptor.
227: */
228: /* ARGSUSED */
1.38 christos 229: int
1.99 thorpej 230: sys_dup(struct lwp *l, void *v, register_t *retval)
1.36 thorpej 231: {
1.37 mycroft 232: struct sys_dup_args /* {
1.72 lukem 233: syscallarg(int) fd;
1.36 thorpej 234: } */ *uap = v;
1.72 lukem 235: struct file *fp;
236: struct filedesc *fdp;
1.99 thorpej 237: struct proc *p;
1.72 lukem 238: int old, new, error;
239:
1.99 thorpej 240: p = l->l_proc;
1.72 lukem 241: fdp = p->p_fd;
242: old = SCARG(uap, fd);
1.16 cgd 243:
1.75 thorpej 244: restart:
1.77 thorpej 245: if ((fp = fd_getfile(fdp, old)) == NULL)
1.16 cgd 246: return (EBADF);
1.59 thorpej 247:
248: FILE_USE(fp);
249:
250: if ((error = fdalloc(p, 0, &new)) != 0) {
1.76 thorpej 251: if (error == ENOSPC) {
252: fdexpand(p);
1.110 fvdl 253: FILE_UNUSE(fp, p);
1.76 thorpej 254: goto restart;
255: }
1.110 fvdl 256: FILE_UNUSE(fp, p);
1.16 cgd 257: return (error);
1.59 thorpej 258: }
259:
260: /* finishdup() will unuse the descriptors for us */
1.110 fvdl 261: return (finishdup(p, old, new, retval));
1.16 cgd 262: }
263:
264: /*
265: * Duplicate a file descriptor to a particular value.
266: */
267: /* ARGSUSED */
1.38 christos 268: int
1.99 thorpej 269: sys_dup2(struct lwp *l, void *v, register_t *retval)
1.36 thorpej 270: {
1.37 mycroft 271: struct sys_dup2_args /* {
1.72 lukem 272: syscallarg(int) from;
273: syscallarg(int) to;
1.36 thorpej 274: } */ *uap = v;
1.72 lukem 275: struct file *fp;
276: struct filedesc *fdp;
1.99 thorpej 277: struct proc *p;
1.72 lukem 278: int old, new, i, error;
279:
1.99 thorpej 280: p = l->l_proc;
1.72 lukem 281: fdp = p->p_fd;
282: old = SCARG(uap, from);
283: new = SCARG(uap, to);
1.16 cgd 284:
1.75 thorpej 285: restart:
1.77 thorpej 286: if ((fp = fd_getfile(fdp, old)) == NULL)
287: return (EBADF);
288:
289: if ((u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
1.103 pk 290: (u_int)new >= maxfiles) {
291: simple_unlock(&fp->f_slock);
1.16 cgd 292: return (EBADF);
1.103 pk 293: }
1.77 thorpej 294:
1.17 cgd 295: if (old == new) {
1.103 pk 296: simple_unlock(&fp->f_slock);
1.17 cgd 297: *retval = new;
1.16 cgd 298: return (0);
1.17 cgd 299: }
1.59 thorpej 300:
301: FILE_USE(fp);
302:
1.16 cgd 303: if (new >= fdp->fd_nfiles) {
1.59 thorpej 304: if ((error = fdalloc(p, new, &i)) != 0) {
1.76 thorpej 305: if (error == ENOSPC) {
306: fdexpand(p);
1.110 fvdl 307: FILE_UNUSE(fp, p);
1.76 thorpej 308: goto restart;
309: }
1.110 fvdl 310: FILE_UNUSE(fp, p);
1.16 cgd 311: return (error);
1.59 thorpej 312: }
1.16 cgd 313: if (new != i)
314: panic("dup2: fdalloc");
1.117 yamt 315: } else if (fdp->fd_ofiles[new] == NULL) {
316: /*
317: * Mark `new' slot "used" only if it was empty.
318: */
319: fd_used(fdp, new);
1.16 cgd 320: }
1.59 thorpej 321:
1.75 thorpej 322: /*
323: * finishdup() will close the file that's in the `new'
324: * slot, if there's one there.
325: */
326:
1.59 thorpej 327: /* finishdup() will unuse the descriptors for us */
1.110 fvdl 328: return (finishdup(p, old, new, retval));
1.16 cgd 329: }
330:
331: /*
332: * The file control system call.
333: */
334: /* ARGSUSED */
1.38 christos 335: int
1.99 thorpej 336: sys_fcntl(struct lwp *l, void *v, register_t *retval)
1.36 thorpej 337: {
1.66 augustss 338: struct sys_fcntl_args /* {
1.72 lukem 339: syscallarg(int) fd;
340: syscallarg(int) cmd;
341: syscallarg(void *) arg;
1.36 thorpej 342: } */ *uap = v;
1.72 lukem 343: struct filedesc *fdp;
344: struct file *fp;
1.99 thorpej 345: struct proc *p;
1.72 lukem 346: struct vnode *vp;
347: int fd, i, tmp, error, flg, cmd, newmin;
348: struct flock fl;
349:
1.99 thorpej 350: p = l->l_proc;
1.72 lukem 351: fd = SCARG(uap, fd);
1.122 christos 352: cmd = SCARG(uap, cmd);
1.72 lukem 353: fdp = p->p_fd;
354: error = 0;
355: flg = F_POSIX;
1.16 cgd 356:
1.122 christos 357: switch (cmd) {
358: case F_CLOSEM:
359: if (fd < 0)
360: return EBADF;
361: while (fdp->fd_lastfile >= fd)
362: fdrelease(p, fdp->fd_lastfile);
363: return 0;
364:
365: case F_MAXFD:
1.123 jdolecek 366: *retval = fdp->fd_lastfile;
367: return 0;
1.122 christos 368:
369: default:
370: /* Handled below */
371: break;
372: }
373:
1.75 thorpej 374: restart:
1.77 thorpej 375: if ((fp = fd_getfile(fdp, fd)) == NULL)
1.16 cgd 376: return (EBADF);
1.59 thorpej 377:
378: FILE_USE(fp);
379:
1.61 wrstuden 380: if ((cmd & F_FSCTL)) {
1.110 fvdl 381: error = fcntl_forfs(fd, p, cmd, SCARG(uap, arg));
1.61 wrstuden 382: goto out;
383: }
384:
385: switch (cmd) {
1.17 cgd 386:
1.16 cgd 387: case F_DUPFD:
1.30 cgd 388: newmin = (long)SCARG(uap, arg);
1.27 mycroft 389: if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
1.59 thorpej 390: (u_int)newmin >= maxfiles) {
391: error = EINVAL;
392: goto out;
393: }
1.75 thorpej 394: if ((error = fdalloc(p, newmin, &i)) != 0) {
1.76 thorpej 395: if (error == ENOSPC) {
396: fdexpand(p);
1.110 fvdl 397: FILE_UNUSE(fp, p);
1.75 thorpej 398: goto restart;
399: }
1.59 thorpej 400: goto out;
1.75 thorpej 401: }
1.59 thorpej 402:
403: /* finishdup() will unuse the descriptors for us */
1.110 fvdl 404: return (finishdup(p, fd, i, retval));
1.16 cgd 405:
406: case F_GETFD:
1.27 mycroft 407: *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
1.59 thorpej 408: break;
1.16 cgd 409:
410: case F_SETFD:
1.27 mycroft 411: if ((long)SCARG(uap, arg) & 1)
412: fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
413: else
414: fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
1.59 thorpej 415: break;
1.16 cgd 416:
417: case F_GETFL:
418: *retval = OFLAGS(fp->f_flag);
1.59 thorpej 419: break;
1.16 cgd 420:
421: case F_SETFL:
1.61 wrstuden 422: tmp = FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
1.110 fvdl 423: error = (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &tmp, p);
1.61 wrstuden 424: if (error)
1.107 dsl 425: break;
426: i = tmp ^ fp->f_flag;
427: if (i & FNONBLOCK) {
428: int fl = tmp & FNONBLOCK;
1.110 fvdl 429: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, &fl, p);
1.107 dsl 430: if (error)
431: goto reset_fcntl;
432: }
433: if (i & FASYNC) {
434: int fl = tmp & FASYNC;
1.110 fvdl 435: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, &fl, p);
1.107 dsl 436: if (error) {
437: if (i & FNONBLOCK) {
438: tmp = fp->f_flag & FNONBLOCK;
439: (void)(*fp->f_ops->fo_ioctl)(fp,
1.110 fvdl 440: FIONBIO, &tmp, p);
1.107 dsl 441: }
442: goto reset_fcntl;
443: }
444: }
445: fp->f_flag = (fp->f_flag & ~FCNTLFLAGS) | tmp;
446: break;
447: reset_fcntl:
1.110 fvdl 448: (void)(*fp->f_ops->fo_fcntl)(fp, F_SETFL, &fp->f_flag, p);
1.59 thorpej 449: break;
1.16 cgd 450:
451: case F_GETOWN:
1.113 jdolecek 452: error = (*fp->f_ops->fo_ioctl)(fp, FIOGETOWN, retval, p);
1.59 thorpej 453: break;
1.16 cgd 454:
455: case F_SETOWN:
1.113 jdolecek 456: tmp = (int)(intptr_t) SCARG(uap, arg);
457: error = (*fp->f_ops->fo_ioctl)(fp, FIOSETOWN, &tmp, p);
1.59 thorpej 458: break;
1.16 cgd 459:
460: case F_SETLKW:
461: flg |= F_WAIT;
462: /* Fall into F_SETLK */
463:
464: case F_SETLK:
1.59 thorpej 465: if (fp->f_type != DTYPE_VNODE) {
466: error = EINVAL;
467: goto out;
468: }
1.16 cgd 469: vp = (struct vnode *)fp->f_data;
470: /* Copy in the lock structure */
1.106 dsl 471: error = copyin(SCARG(uap, arg), &fl, sizeof(fl));
1.16 cgd 472: if (error)
1.59 thorpej 473: goto out;
1.16 cgd 474: if (fl.l_whence == SEEK_CUR)
475: fl.l_start += fp->f_offset;
476: switch (fl.l_type) {
477: case F_RDLCK:
1.59 thorpej 478: if ((fp->f_flag & FREAD) == 0) {
479: error = EBADF;
480: goto out;
481: }
1.16 cgd 482: p->p_flag |= P_ADVLOCK;
1.106 dsl 483: error = VOP_ADVLOCK(vp, p, F_SETLK, &fl, flg);
1.59 thorpej 484: goto out;
1.16 cgd 485:
486: case F_WRLCK:
1.59 thorpej 487: if ((fp->f_flag & FWRITE) == 0) {
488: error = EBADF;
489: goto out;
490: }
1.16 cgd 491: p->p_flag |= P_ADVLOCK;
1.106 dsl 492: error = VOP_ADVLOCK(vp, p, F_SETLK, &fl, flg);
1.59 thorpej 493: goto out;
1.16 cgd 494:
495: case F_UNLCK:
1.106 dsl 496: error = VOP_ADVLOCK(vp, p, F_UNLCK, &fl, F_POSIX);
1.59 thorpej 497: goto out;
1.16 cgd 498:
499: default:
1.59 thorpej 500: error = EINVAL;
501: goto out;
1.16 cgd 502: }
503:
504: case F_GETLK:
1.59 thorpej 505: if (fp->f_type != DTYPE_VNODE) {
506: error = EINVAL;
507: goto out;
508: }
1.16 cgd 509: vp = (struct vnode *)fp->f_data;
510: /* Copy in the lock structure */
1.106 dsl 511: error = copyin(SCARG(uap, arg), &fl, sizeof(fl));
1.16 cgd 512: if (error)
1.59 thorpej 513: goto out;
1.16 cgd 514: if (fl.l_whence == SEEK_CUR)
515: fl.l_start += fp->f_offset;
1.43 kleink 516: if (fl.l_type != F_RDLCK &&
517: fl.l_type != F_WRLCK &&
1.59 thorpej 518: fl.l_type != F_UNLCK) {
519: error = EINVAL;
520: goto out;
521: }
1.106 dsl 522: error = VOP_ADVLOCK(vp, p, F_GETLK, &fl, F_POSIX);
1.38 christos 523: if (error)
1.59 thorpej 524: goto out;
1.106 dsl 525: error = copyout(&fl, SCARG(uap, arg), sizeof(fl));
1.59 thorpej 526: break;
1.16 cgd 527:
528: default:
1.59 thorpej 529: error = EINVAL;
1.16 cgd 530: }
1.59 thorpej 531:
532: out:
1.110 fvdl 533: FILE_UNUSE(fp, p);
1.59 thorpej 534: return (error);
1.16 cgd 535: }
536:
537: /*
1.17 cgd 538: * Common code for dup, dup2, and fcntl(F_DUPFD).
539: */
540: int
1.110 fvdl 541: finishdup(struct proc *p, int old, int new, register_t *retval)
1.17 cgd 542: {
1.72 lukem 543: struct filedesc *fdp;
1.110 fvdl 544: struct file *fp, *delfp;
1.72 lukem 545:
546: fdp = p->p_fd;
1.59 thorpej 547:
548: /*
1.75 thorpej 549: * If there is a file in the new slot, remember it so we
550: * can close it after we've finished the dup. We need
551: * to do it after the dup is finished, since closing
552: * the file may block.
553: *
1.59 thorpej 554: * Note: `old' is already used for us.
1.117 yamt 555: * Note: Caller already marked `new' slot "used".
1.59 thorpej 556: */
1.75 thorpej 557: delfp = fdp->fd_ofiles[new];
1.17 cgd 558:
559: fp = fdp->fd_ofiles[old];
1.124 ! yamt 560: KDASSERT(fp != NULL);
1.17 cgd 561: fdp->fd_ofiles[new] = fp;
562: fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
563: fp->f_count++;
564: *retval = new;
1.110 fvdl 565: FILE_UNUSE(fp, p);
1.75 thorpej 566:
567: if (delfp != NULL) {
1.103 pk 568: simple_lock(&delfp->f_slock);
1.75 thorpej 569: FILE_USE(delfp);
1.96 jdolecek 570: if (new < fdp->fd_knlistsize)
1.110 fvdl 571: knote_fdclose(p, new);
572: (void) closef(delfp, p);
1.75 thorpej 573: }
1.17 cgd 574: return (0);
1.65 thorpej 575: }
576:
577: void
1.72 lukem 578: fdremove(struct filedesc *fdp, int fd)
1.65 thorpej 579: {
580:
581: fdp->fd_ofiles[fd] = NULL;
582: fd_unused(fdp, fd);
1.17 cgd 583: }
584:
1.27 mycroft 585: int
1.110 fvdl 586: fdrelease(struct proc *p, int fd)
1.72 lukem 587: {
588: struct filedesc *fdp;
1.110 fvdl 589: struct file **fpp, *fp;
1.27 mycroft 590:
1.72 lukem 591: fdp = p->p_fd;
1.27 mycroft 592: fpp = &fdp->fd_ofiles[fd];
593: fp = *fpp;
594: if (fp == NULL)
595: return (EBADF);
1.59 thorpej 596:
1.103 pk 597: simple_lock(&fp->f_slock);
598: if (!FILE_IS_USABLE(fp)) {
599: simple_unlock(&fp->f_slock);
600: return (EBADF);
601: }
602:
1.59 thorpej 603: FILE_USE(fp);
604:
1.27 mycroft 605: *fpp = NULL;
1.75 thorpej 606: fdp->fd_ofileflags[fd] = 0;
1.96 jdolecek 607: if (fd < fdp->fd_knlistsize)
1.110 fvdl 608: knote_fdclose(p, fd);
1.27 mycroft 609: fd_unused(fdp, fd);
1.110 fvdl 610: return (closef(fp, p));
1.27 mycroft 611: }
612:
1.17 cgd 613: /*
1.16 cgd 614: * Close a file descriptor.
615: */
616: /* ARGSUSED */
1.38 christos 617: int
1.99 thorpej 618: sys_close(struct lwp *l, void *v, register_t *retval)
1.36 thorpej 619: {
1.37 mycroft 620: struct sys_close_args /* {
1.72 lukem 621: syscallarg(int) fd;
1.36 thorpej 622: } */ *uap = v;
1.72 lukem 623: int fd;
624: struct filedesc *fdp;
1.99 thorpej 625: struct proc *p;
1.16 cgd 626:
1.99 thorpej 627: p = l->l_proc;
1.72 lukem 628: fd = SCARG(uap, fd);
629: fdp = p->p_fd;
1.79 thorpej 630:
1.103 pk 631: if ((u_int) fd >= fdp->fd_nfiles)
1.105 martin 632: return (EBADF);
1.103 pk 633: #if 0
1.100 simonb 634: if (fd_getfile(fdp, fd) == NULL)
1.16 cgd 635: return (EBADF);
1.103 pk 636: #endif
1.79 thorpej 637:
1.110 fvdl 638: return (fdrelease(p, fd));
1.16 cgd 639: }
640:
1.17 cgd 641: /*
642: * Return status information about a file descriptor.
643: */
1.16 cgd 644: /* ARGSUSED */
1.38 christos 645: int
1.99 thorpej 646: sys___fstat13(struct lwp *l, void *v, register_t *retval)
1.36 thorpej 647: {
1.66 augustss 648: struct sys___fstat13_args /* {
1.72 lukem 649: syscallarg(int) fd;
650: syscallarg(struct stat *) sb;
1.36 thorpej 651: } */ *uap = v;
1.72 lukem 652: int fd;
653: struct filedesc *fdp;
654: struct file *fp;
1.99 thorpej 655: struct proc *p;
1.72 lukem 656: struct stat ub;
657: int error;
1.16 cgd 658:
1.99 thorpej 659: p = l->l_proc;
1.72 lukem 660: fd = SCARG(uap, fd);
661: fdp = p->p_fd;
1.77 thorpej 662:
663: if ((fp = fd_getfile(fdp, fd)) == NULL)
1.16 cgd 664: return (EBADF);
1.59 thorpej 665:
666: FILE_USE(fp);
1.110 fvdl 667: error = (*fp->f_ops->fo_stat)(fp, &ub, p);
668: FILE_UNUSE(fp, p);
1.59 thorpej 669:
1.16 cgd 670: if (error == 0)
1.52 perry 671: error = copyout(&ub, SCARG(uap, sb), sizeof(ub));
1.73 jdolecek 672:
1.16 cgd 673: return (error);
674: }
675:
676: /*
677: * Return pathconf information about a file descriptor.
678: */
679: /* ARGSUSED */
1.38 christos 680: int
1.99 thorpej 681: sys_fpathconf(struct lwp *l, void *v, register_t *retval)
1.36 thorpej 682: {
1.66 augustss 683: struct sys_fpathconf_args /* {
1.72 lukem 684: syscallarg(int) fd;
685: syscallarg(int) name;
1.36 thorpej 686: } */ *uap = v;
1.72 lukem 687: int fd;
688: struct filedesc *fdp;
689: struct file *fp;
1.99 thorpej 690: struct proc *p;
1.72 lukem 691: struct vnode *vp;
692: int error;
693:
1.99 thorpej 694: p = l->l_proc;
1.72 lukem 695: fd = SCARG(uap, fd);
696: fdp = p->p_fd;
697: error = 0;
1.17 cgd 698:
1.77 thorpej 699: if ((fp = fd_getfile(fdp, fd)) == NULL)
1.17 cgd 700: return (EBADF);
1.59 thorpej 701:
702: FILE_USE(fp);
703:
1.17 cgd 704: switch (fp->f_type) {
1.16 cgd 705:
1.17 cgd 706: case DTYPE_SOCKET:
1.78 jdolecek 707: case DTYPE_PIPE:
1.25 cgd 708: if (SCARG(uap, name) != _PC_PIPE_BUF)
1.59 thorpej 709: error = EINVAL;
710: else
711: *retval = PIPE_BUF;
712: break;
1.17 cgd 713:
714: case DTYPE_VNODE:
715: vp = (struct vnode *)fp->f_data;
1.59 thorpej 716: error = VOP_PATHCONF(vp, SCARG(uap, name), retval);
717: break;
1.17 cgd 718:
1.96 jdolecek 719: case DTYPE_KQUEUE:
720: error = EINVAL;
721: break;
722:
1.17 cgd 723: default:
1.93 thorpej 724: error = EOPNOTSUPP;
725: break;
1.17 cgd 726: }
1.59 thorpej 727:
1.110 fvdl 728: FILE_UNUSE(fp, p);
1.59 thorpej 729: return (error);
1.16 cgd 730: }
731:
732: /*
733: * Allocate a file descriptor for the process.
734: */
1.76 thorpej 735: int fdexpanded; /* XXX: what else uses this? */
1.16 cgd 736:
1.38 christos 737: int
1.72 lukem 738: fdalloc(struct proc *p, int want, int *result)
739: {
740: struct filedesc *fdp;
1.76 thorpej 741: int i, lim, last;
1.115 provos 742: u_int off, new;
1.72 lukem 743:
744: fdp = p->p_fd;
1.16 cgd 745:
746: /*
747: * Search for a free descriptor starting at the higher
748: * of want or fd_freefile. If that fails, consider
749: * expanding the ofile array.
750: */
1.17 cgd 751: lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1.90 enami 752: last = min(fdp->fd_nfiles, lim);
1.115 provos 753: again:
1.90 enami 754: if ((i = want) < fdp->fd_freefile)
755: i = fdp->fd_freefile;
1.115 provos 756: off = i >> NDENTRYSHIFT;
757: new = find_next_zero(fdp->fd_himap, off,
758: (last + NDENTRIES - 1) >> NDENTRYSHIFT);
759: if (new != -1) {
760: i = find_next_zero(&fdp->fd_lomap[new],
761: new > off ? 0 : i & NDENTRYMASK, NDENTRIES);
762: if (i == -1) {
763: /*
764: * free file descriptor in this block was
765: * below want, try again with higher want.
766: */
767: want = (new + 1) << NDENTRYSHIFT;
768: goto again;
769: }
770: i += (new << NDENTRYSHIFT);
771: if (i < last) {
772: if (fdp->fd_ofiles[i] == NULL) {
773: fd_used(fdp, i);
774: if (want <= fdp->fd_freefile)
775: fdp->fd_freefile = i;
776: *result = i;
777: return (0);
778: }
1.16 cgd 779: }
1.90 enami 780: }
1.16 cgd 781:
1.90 enami 782: /* No space in current array. Expand? */
783: if (fdp->fd_nfiles >= lim)
784: return (EMFILE);
1.76 thorpej 785:
1.90 enami 786: /* Let the caller do it. */
787: return (ENOSPC);
1.16 cgd 788: }
789:
1.76 thorpej 790: void
791: fdexpand(struct proc *p)
792: {
793: struct filedesc *fdp;
794: int i, nfiles;
795: struct file **newofile;
796: char *newofileflags;
1.115 provos 797: uint32_t *newhimap, *newlomap;
1.76 thorpej 798:
799: fdp = p->p_fd;
800:
801: if (fdp->fd_nfiles < NDEXTENT)
802: nfiles = NDEXTENT;
803: else
804: nfiles = 2 * fdp->fd_nfiles;
805: newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK);
806: newofileflags = (char *) &newofile[nfiles];
807: /*
808: * Copy the existing ofile and ofileflags arrays
809: * and zero the new portion of each array.
810: */
811: memcpy(newofile, fdp->fd_ofiles,
1.89 enami 812: (i = sizeof(struct file *) * fdp->fd_nfiles));
1.76 thorpej 813: memset((char *)newofile + i, 0,
814: nfiles * sizeof(struct file *) - i);
815: memcpy(newofileflags, fdp->fd_ofileflags,
816: (i = sizeof(char) * fdp->fd_nfiles));
817: memset(newofileflags + i, 0, nfiles * sizeof(char) - i);
818: if (fdp->fd_nfiles > NDFILE)
819: free(fdp->fd_ofiles, M_FILEDESC);
1.115 provos 820:
821: if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
822: newhimap = malloc(NDHISLOTS(nfiles) * sizeof(uint32_t),
823: M_FILEDESC, M_WAITOK);
824: newlomap = malloc(NDLOSLOTS(nfiles) * sizeof(uint32_t),
825: M_FILEDESC, M_WAITOK);
826:
827: memcpy(newhimap, fdp->fd_himap,
828: (i = NDHISLOTS(fdp->fd_nfiles) * sizeof(uint32_t)));
829: memset((char *)newhimap + i, 0,
830: NDHISLOTS(nfiles) * sizeof(uint32_t) - i);
831:
832: memcpy(newlomap, fdp->fd_lomap,
833: (i = NDLOSLOTS(fdp->fd_nfiles) * sizeof(uint32_t)));
834: memset((char *)newlomap + i, 0,
835: NDLOSLOTS(nfiles) * sizeof(uint32_t) - i);
836:
837: if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
838: free(fdp->fd_himap, M_FILEDESC);
839: free(fdp->fd_lomap, M_FILEDESC);
840: }
841: fdp->fd_himap = newhimap;
842: fdp->fd_lomap = newlomap;
843: }
844:
1.76 thorpej 845: fdp->fd_ofiles = newofile;
846: fdp->fd_ofileflags = newofileflags;
847: fdp->fd_nfiles = nfiles;
848: fdexpanded++;
849: }
850:
1.16 cgd 851: /*
852: * Check to see whether n user file descriptors
853: * are available to the process p.
854: */
1.38 christos 855: int
1.72 lukem 856: fdavail(struct proc *p, int n)
857: {
858: struct filedesc *fdp;
859: struct file **fpp;
860: int i, lim;
1.16 cgd 861:
1.72 lukem 862: fdp = p->p_fd;
1.17 cgd 863: lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
864: if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
1.16 cgd 865: return (1);
866: fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1.56 sommerfe 867: for (i = min(lim,fdp->fd_nfiles) - fdp->fd_freefile; --i >= 0; fpp++)
1.16 cgd 868: if (*fpp == NULL && --n <= 0)
869: return (1);
870: return (0);
871: }
872:
873: /*
1.55 thorpej 874: * Initialize the data structures necessary for managing files.
875: */
876: void
1.72 lukem 877: finit(void)
1.55 thorpej 878: {
879:
880: pool_init(&file_pool, sizeof(struct file), 0, 0, 0, "filepl",
1.85 thorpej 881: &pool_allocator_nointr);
1.58 thorpej 882: pool_init(&cwdi_pool, sizeof(struct cwdinfo), 0, 0, 0, "cwdipl",
1.85 thorpej 883: &pool_allocator_nointr);
1.64 thorpej 884: pool_init(&filedesc0_pool, sizeof(struct filedesc0), 0, 0, 0, "fdescpl",
1.85 thorpej 885: &pool_allocator_nointr);
1.55 thorpej 886: }
887:
888: /*
1.16 cgd 889: * Create a new open file structure and allocate
1.98 wiz 890: * a file descriptor for the process that refers to it.
1.16 cgd 891: */
1.38 christos 892: int
1.72 lukem 893: falloc(struct proc *p, struct file **resultfp, int *resultfd)
1.16 cgd 894: {
1.72 lukem 895: struct file *fp, *fq;
896: int error, i;
1.16 cgd 897:
1.75 thorpej 898: restart:
899: if ((error = fdalloc(p, 0, &i)) != 0) {
1.76 thorpej 900: if (error == ENOSPC) {
901: fdexpand(p);
1.75 thorpej 902: goto restart;
1.76 thorpej 903: }
1.16 cgd 904: return (error);
1.75 thorpej 905: }
1.102 pk 906:
907: fp = pool_get(&file_pool, PR_WAITOK);
908: simple_lock(&filelist_slock);
1.16 cgd 909: if (nfiles >= maxfiles) {
1.69 jdolecek 910: tablefull("file", "increase kern.maxfiles or MAXFILES");
1.102 pk 911: simple_unlock(&filelist_slock);
1.115 provos 912: fd_unused(p->p_fd, i);
1.102 pk 913: pool_put(&file_pool, fp);
1.16 cgd 914: return (ENFILE);
915: }
916: /*
917: * Allocate a new file descriptor.
918: * If the process has file descriptor zero open, add to the list
919: * of open files at that point, otherwise put it at the front of
920: * the list of open files.
921: */
922: nfiles++;
1.53 perry 923: memset(fp, 0, sizeof(struct file));
1.83 jdolecek 924: fp->f_iflags = FIF_LARVAL;
1.38 christos 925: if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
1.24 mycroft 926: LIST_INSERT_AFTER(fq, fp, f_list);
927: } else {
928: LIST_INSERT_HEAD(&filehead, fp, f_list);
929: }
1.102 pk 930: simple_unlock(&filelist_slock);
1.124 ! yamt 931: KDASSERT(p->p_fd->fd_ofiles[i] == NULL);
1.16 cgd 932: p->p_fd->fd_ofiles[i] = fp;
1.103 pk 933: simple_lock_init(&fp->f_slock);
1.16 cgd 934: fp->f_count = 1;
935: fp->f_cred = p->p_ucred;
936: crhold(fp->f_cred);
1.59 thorpej 937: if (resultfp) {
1.103 pk 938: fp->f_usecount = 1;
1.16 cgd 939: *resultfp = fp;
1.59 thorpej 940: }
1.16 cgd 941: if (resultfd)
942: *resultfd = i;
943: return (0);
944: }
945:
946: /*
947: * Free a file descriptor.
948: */
1.38 christos 949: void
1.72 lukem 950: ffree(struct file *fp)
1.16 cgd 951: {
1.59 thorpej 952:
953: #ifdef DIAGNOSTIC
954: if (fp->f_usecount)
955: panic("ffree");
956: #endif
957:
1.102 pk 958: simple_lock(&filelist_slock);
1.24 mycroft 959: LIST_REMOVE(fp, f_list);
1.16 cgd 960: crfree(fp->f_cred);
961: #ifdef DIAGNOSTIC
1.103 pk 962: fp->f_count = 0; /* What's the point? */
1.16 cgd 963: #endif
964: nfiles--;
1.102 pk 965: simple_unlock(&filelist_slock);
1.55 thorpej 966: pool_put(&file_pool, fp);
1.48 thorpej 967: }
968:
969: /*
1.58 thorpej 970: * Create an initial cwdinfo structure, using the same current and root
971: * directories as p.
972: */
973: struct cwdinfo *
1.72 lukem 974: cwdinit(struct proc *p)
1.58 thorpej 975: {
976: struct cwdinfo *cwdi;
977:
978: cwdi = pool_get(&cwdi_pool, PR_WAITOK);
979:
980: cwdi->cwdi_cdir = p->p_cwdi->cwdi_cdir;
1.63 thorpej 981: if (cwdi->cwdi_cdir)
982: VREF(cwdi->cwdi_cdir);
1.58 thorpej 983: cwdi->cwdi_rdir = p->p_cwdi->cwdi_rdir;
984: if (cwdi->cwdi_rdir)
985: VREF(cwdi->cwdi_rdir);
1.60 christos 986: cwdi->cwdi_cmask = p->p_cwdi->cwdi_cmask;
1.58 thorpej 987: cwdi->cwdi_refcnt = 1;
988:
989: return (cwdi);
990: }
991:
992: /*
993: * Make p2 share p1's cwdinfo.
994: */
995: void
1.72 lukem 996: cwdshare(struct proc *p1, struct proc *p2)
1.58 thorpej 997: {
998:
999: p2->p_cwdi = p1->p_cwdi;
1000: p1->p_cwdi->cwdi_refcnt++;
1001: }
1002:
1003: /*
1004: * Make this process not share its cwdinfo structure, maintaining
1005: * all cwdinfo state.
1006: */
1007: void
1.72 lukem 1008: cwdunshare(struct proc *p)
1.58 thorpej 1009: {
1010: struct cwdinfo *newcwdi;
1011:
1012: if (p->p_cwdi->cwdi_refcnt == 1)
1013: return;
1014:
1015: newcwdi = cwdinit(p);
1016: cwdfree(p);
1017: p->p_cwdi = newcwdi;
1018: }
1019:
1020: /*
1021: * Release a cwdinfo structure.
1022: */
1023: void
1.72 lukem 1024: cwdfree(struct proc *p)
1.58 thorpej 1025: {
1.72 lukem 1026: struct cwdinfo *cwdi;
1.58 thorpej 1027:
1.72 lukem 1028: cwdi = p->p_cwdi;
1.58 thorpej 1029: if (--cwdi->cwdi_refcnt > 0)
1030: return;
1031:
1032: p->p_cwdi = NULL;
1033:
1034: vrele(cwdi->cwdi_cdir);
1035: if (cwdi->cwdi_rdir)
1036: vrele(cwdi->cwdi_rdir);
1037: pool_put(&cwdi_pool, cwdi);
1038: }
1039:
1040: /*
1.48 thorpej 1041: * Create an initial filedesc structure, using the same current and root
1042: * directories as p.
1043: */
1044: struct filedesc *
1.72 lukem 1045: fdinit(struct proc *p)
1.48 thorpej 1046: {
1047: struct filedesc0 *newfdp;
1048:
1.64 thorpej 1049: newfdp = pool_get(&filedesc0_pool, PR_WAITOK);
1.53 perry 1050: memset(newfdp, 0, sizeof(struct filedesc0));
1.48 thorpej 1051:
1052: fdinit1(newfdp);
1053:
1054: return (&newfdp->fd_fd);
1055: }
1056:
1057: /*
1058: * Initialize a file descriptor table.
1059: */
1060: void
1.72 lukem 1061: fdinit1(struct filedesc0 *newfdp)
1.48 thorpej 1062: {
1063:
1064: newfdp->fd_fd.fd_refcnt = 1;
1065: newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
1066: newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
1067: newfdp->fd_fd.fd_nfiles = NDFILE;
1.96 jdolecek 1068: newfdp->fd_fd.fd_knlistsize = -1;
1.115 provos 1069: newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
1070: newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
1.48 thorpej 1071: }
1072:
1073: /*
1074: * Make p2 share p1's filedesc structure.
1075: */
1076: void
1.72 lukem 1077: fdshare(struct proc *p1, struct proc *p2)
1.48 thorpej 1078: {
1079:
1080: p2->p_fd = p1->p_fd;
1081: p1->p_fd->fd_refcnt++;
1082: }
1083:
1084: /*
1085: * Make this process not share its filedesc structure, maintaining
1086: * all file descriptor state.
1087: */
1088: void
1.110 fvdl 1089: fdunshare(struct proc *p)
1.48 thorpej 1090: {
1091: struct filedesc *newfd;
1092:
1093: if (p->p_fd->fd_refcnt == 1)
1094: return;
1095:
1096: newfd = fdcopy(p);
1.110 fvdl 1097: fdfree(p);
1.48 thorpej 1098: p->p_fd = newfd;
1099: }
1100:
1101: /*
1102: * Clear a process's fd table.
1103: */
1104: void
1.110 fvdl 1105: fdclear(struct proc *p)
1.48 thorpej 1106: {
1107: struct filedesc *newfd;
1108:
1109: newfd = fdinit(p);
1.110 fvdl 1110: fdfree(p);
1.48 thorpej 1111: p->p_fd = newfd;
1.16 cgd 1112: }
1113:
1114: /*
1115: * Copy a filedesc structure.
1116: */
1117: struct filedesc *
1.72 lukem 1118: fdcopy(struct proc *p)
1.16 cgd 1119: {
1.72 lukem 1120: struct filedesc *newfdp, *fdp;
1121: struct file **fpp;
1122: int i;
1.16 cgd 1123:
1.72 lukem 1124: fdp = p->p_fd;
1.64 thorpej 1125: newfdp = pool_get(&filedesc0_pool, PR_WAITOK);
1.53 perry 1126: memcpy(newfdp, fdp, sizeof(struct filedesc));
1.16 cgd 1127: newfdp->fd_refcnt = 1;
1128:
1129: /*
1130: * If the number of open files fits in the internal arrays
1131: * of the open file structure, use them, otherwise allocate
1132: * additional memory for the number of descriptors currently
1133: * in use.
1134: */
1135: if (newfdp->fd_lastfile < NDFILE) {
1136: newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
1137: newfdp->fd_ofileflags =
1138: ((struct filedesc0 *) newfdp)->fd_dfileflags;
1139: i = NDFILE;
1140: } else {
1141: /*
1142: * Compute the smallest multiple of NDEXTENT needed
1143: * for the file descriptors currently in use,
1144: * allowing the table to shrink.
1145: */
1146: i = newfdp->fd_nfiles;
1.27 mycroft 1147: while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
1.16 cgd 1148: i /= 2;
1.64 thorpej 1149: newfdp->fd_ofiles = malloc(i * OFILESIZE, M_FILEDESC, M_WAITOK);
1.16 cgd 1150: newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
1151: }
1.115 provos 1152: if (NDHISLOTS(i) <= NDHISLOTS(NDFILE)) {
1153: newfdp->fd_himap =
1154: ((struct filedesc0 *) newfdp)->fd_dhimap;
1155: newfdp->fd_lomap =
1156: ((struct filedesc0 *) newfdp)->fd_dlomap;
1157: } else {
1158: newfdp->fd_himap = malloc(NDHISLOTS(i) * sizeof(uint32_t),
1159: M_FILEDESC, M_WAITOK);
1160: newfdp->fd_lomap = malloc(NDLOSLOTS(i) * sizeof(uint32_t),
1161: M_FILEDESC, M_WAITOK);
1162: }
1163:
1.16 cgd 1164: newfdp->fd_nfiles = i;
1.53 perry 1165: memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file **));
1166: memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char));
1.120 yamt 1167: if (i < NDENTRIES * NDENTRIES)
1168: i = NDENTRIES * NDENTRIES; /* size of inlined bitmaps */
1.115 provos 1169: memcpy(newfdp->fd_himap, fdp->fd_himap, NDHISLOTS(i)*sizeof(uint32_t));
1170: memcpy(newfdp->fd_lomap, fdp->fd_lomap, NDLOSLOTS(i)*sizeof(uint32_t));
1.96 jdolecek 1171: /*
1172: * kq descriptors cannot be copied.
1173: */
1174: if (newfdp->fd_knlistsize != -1) {
1175: fpp = newfdp->fd_ofiles;
1.116 provos 1176: for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++) {
1.96 jdolecek 1177: if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
1.116 provos 1178: fdremove(newfdp, i);
1.96 jdolecek 1179: }
1180: newfdp->fd_knlist = NULL;
1181: newfdp->fd_knlistsize = -1;
1182: newfdp->fd_knhash = NULL;
1183: newfdp->fd_knhashmask = 0;
1184: }
1.16 cgd 1185: fpp = newfdp->fd_ofiles;
1.27 mycroft 1186: for (i = newfdp->fd_lastfile; i >= 0; i--, fpp++)
1.16 cgd 1187: if (*fpp != NULL)
1188: (*fpp)->f_count++;
1189: return (newfdp);
1190: }
1191:
1192: /*
1193: * Release a filedesc structure.
1194: */
1195: void
1.110 fvdl 1196: fdfree(struct proc *p)
1.16 cgd 1197: {
1.72 lukem 1198: struct filedesc *fdp;
1199: struct file **fpp, *fp;
1200: int i;
1.16 cgd 1201:
1.72 lukem 1202: fdp = p->p_fd;
1.16 cgd 1203: if (--fdp->fd_refcnt > 0)
1204: return;
1205: fpp = fdp->fd_ofiles;
1.32 mycroft 1206: for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
1207: fp = *fpp;
1208: if (fp != NULL) {
1209: *fpp = NULL;
1.103 pk 1210: simple_lock(&fp->f_slock);
1.59 thorpej 1211: FILE_USE(fp);
1.96 jdolecek 1212: if (i < fdp->fd_knlistsize)
1.110 fvdl 1213: knote_fdclose(p, fdp->fd_lastfile - i);
1214: (void) closef(fp, p);
1.32 mycroft 1215: }
1216: }
1217: p->p_fd = NULL;
1.16 cgd 1218: if (fdp->fd_nfiles > NDFILE)
1.64 thorpej 1219: free(fdp->fd_ofiles, M_FILEDESC);
1.115 provos 1220: if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
1221: free(fdp->fd_himap, M_FILEDESC);
1222: free(fdp->fd_lomap, M_FILEDESC);
1223: }
1.96 jdolecek 1224: if (fdp->fd_knlist)
1225: free(fdp->fd_knlist, M_KEVENT);
1226: if (fdp->fd_knhash)
1227: hashdone(fdp->fd_knhash, M_KEVENT);
1.64 thorpej 1228: pool_put(&filedesc0_pool, fdp);
1.16 cgd 1229: }
1230:
1231: /*
1232: * Internal form of close.
1233: * Decrement reference count on file structure.
1.17 cgd 1234: * Note: p may be NULL when closing a file
1235: * that was being passed in a message.
1.59 thorpej 1236: *
1237: * Note: we expect the caller is holding a usecount, and expects us
1238: * to drop it (the caller thinks the file is going away forever).
1.16 cgd 1239: */
1.38 christos 1240: int
1.110 fvdl 1241: closef(struct file *fp, struct proc *p)
1.72 lukem 1242: {
1243: struct vnode *vp;
1244: struct flock lf;
1245: int error;
1.16 cgd 1246:
1247: if (fp == NULL)
1248: return (0);
1.59 thorpej 1249:
1.16 cgd 1250: /*
1251: * POSIX record locking dictates that any close releases ALL
1252: * locks owned by this process. This is handled by setting
1253: * a flag in the unlock to free ONLY locks obeying POSIX
1254: * semantics, and not to free BSD-style file locks.
1.17 cgd 1255: * If the descriptor was in a message, POSIX-style locks
1256: * aren't passed with the descriptor.
1.16 cgd 1257: */
1258: if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
1259: lf.l_whence = SEEK_SET;
1260: lf.l_start = 0;
1261: lf.l_len = 0;
1262: lf.l_type = F_UNLCK;
1263: vp = (struct vnode *)fp->f_data;
1.106 dsl 1264: (void) VOP_ADVLOCK(vp, p, F_UNLCK, &lf, F_POSIX);
1.16 cgd 1265: }
1.59 thorpej 1266:
1267: /*
1268: * If WANTCLOSE is set, then the reference count on the file
1269: * is 0, but there were multiple users of the file. This can
1270: * happen if a filedesc structure is shared by multiple
1271: * processes.
1272: */
1.103 pk 1273: simple_lock(&fp->f_slock);
1.83 jdolecek 1274: if (fp->f_iflags & FIF_WANTCLOSE) {
1.59 thorpej 1275: /*
1276: * Another user of the file is already closing, and is
1277: * simply waiting for other users of the file to drain.
1278: * Release our usecount, and wake up the closer if it
1279: * is the only remaining use.
1280: */
1281: #ifdef DIAGNOSTIC
1282: if (fp->f_count != 0)
1283: panic("closef: wantclose and count != 0");
1284: if (fp->f_usecount < 2)
1285: panic("closef: wantclose and usecount < 2");
1286: #endif
1287: if (--fp->f_usecount == 1)
1288: wakeup(&fp->f_usecount);
1.103 pk 1289: simple_unlock(&fp->f_slock);
1.16 cgd 1290: return (0);
1.59 thorpej 1291: } else {
1292: /*
1293: * Decrement the reference count. If we were not the
1294: * last reference, then release our use and just
1295: * return.
1296: */
1297: if (--fp->f_count > 0) {
1298: #ifdef DIAGNOSTIC
1299: if (fp->f_usecount < 1)
1300: panic("closef: no wantclose and usecount < 1");
1301: #endif
1302: fp->f_usecount--;
1.103 pk 1303: simple_unlock(&fp->f_slock);
1.59 thorpej 1304: return (0);
1305: }
1306: }
1307:
1308: /*
1309: * The reference count is now 0. However, there may be
1310: * multiple potential users of this file. This can happen
1311: * if multiple processes shared a single filedesc structure.
1312: *
1313: * Notify these potential users that the file is closing.
1314: * This will prevent them from adding additional uses to
1315: * the file.
1316: */
1.83 jdolecek 1317: fp->f_iflags |= FIF_WANTCLOSE;
1.59 thorpej 1318:
1319: /*
1320: * We expect the caller to add a use to the file. So, if we
1321: * are the last user, usecount will be 1. If it is not, we
1322: * must wait for the usecount to drain. When it drains back
1323: * to 1, we will be awakened so that we may proceed with the
1324: * close.
1325: */
1326: #ifdef DIAGNOSTIC
1327: if (fp->f_usecount < 1)
1328: panic("closef: usecount < 1");
1329: #endif
1330: while (fp->f_usecount > 1)
1.103 pk 1331: (void) ltsleep(&fp->f_usecount, PRIBIO, "closef", 0,
1332: &fp->f_slock);
1.59 thorpej 1333: #ifdef DIAGNOSTIC
1334: if (fp->f_usecount != 1)
1335: panic("closef: usecount != 1");
1336: #endif
1337:
1.103 pk 1338: simple_unlock(&fp->f_slock);
1.16 cgd 1339: if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1340: lf.l_whence = SEEK_SET;
1341: lf.l_start = 0;
1342: lf.l_len = 0;
1343: lf.l_type = F_UNLCK;
1344: vp = (struct vnode *)fp->f_data;
1.106 dsl 1345: (void) VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
1.16 cgd 1346: }
1.17 cgd 1347: if (fp->f_ops)
1.110 fvdl 1348: error = (*fp->f_ops->fo_close)(fp, p);
1.17 cgd 1349: else
1350: error = 0;
1.59 thorpej 1351:
1352: /* Nothing references the file now, drop the final use (us). */
1353: fp->f_usecount--;
1354:
1.16 cgd 1355: ffree(fp);
1356: return (error);
1357: }
1358:
1359: /*
1360: * Apply an advisory lock on a file descriptor.
1361: *
1362: * Just attempt to get a record lock of the requested type on
1363: * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1364: */
1365: /* ARGSUSED */
1.38 christos 1366: int
1.99 thorpej 1367: sys_flock(struct lwp *l, void *v, register_t *retval)
1.36 thorpej 1368: {
1.66 augustss 1369: struct sys_flock_args /* {
1.72 lukem 1370: syscallarg(int) fd;
1371: syscallarg(int) how;
1.36 thorpej 1372: } */ *uap = v;
1.72 lukem 1373: int fd, how, error;
1.99 thorpej 1374: struct proc *p;
1.72 lukem 1375: struct filedesc *fdp;
1376: struct file *fp;
1377: struct vnode *vp;
1378: struct flock lf;
1.16 cgd 1379:
1.99 thorpej 1380: p = l->l_proc;
1.72 lukem 1381: fd = SCARG(uap, fd);
1382: how = SCARG(uap, how);
1383: fdp = p->p_fd;
1384: error = 0;
1.77 thorpej 1385:
1386: if ((fp = fd_getfile(fdp, fd)) == NULL)
1.16 cgd 1387: return (EBADF);
1.59 thorpej 1388:
1389: FILE_USE(fp);
1390:
1391: if (fp->f_type != DTYPE_VNODE) {
1392: error = EOPNOTSUPP;
1393: goto out;
1394: }
1395:
1.16 cgd 1396: vp = (struct vnode *)fp->f_data;
1397: lf.l_whence = SEEK_SET;
1398: lf.l_start = 0;
1399: lf.l_len = 0;
1.27 mycroft 1400: if (how & LOCK_UN) {
1.16 cgd 1401: lf.l_type = F_UNLCK;
1402: fp->f_flag &= ~FHASLOCK;
1.106 dsl 1403: error = VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
1.59 thorpej 1404: goto out;
1.16 cgd 1405: }
1.27 mycroft 1406: if (how & LOCK_EX)
1.16 cgd 1407: lf.l_type = F_WRLCK;
1.27 mycroft 1408: else if (how & LOCK_SH)
1.16 cgd 1409: lf.l_type = F_RDLCK;
1.59 thorpej 1410: else {
1411: error = EINVAL;
1412: goto out;
1413: }
1.16 cgd 1414: fp->f_flag |= FHASLOCK;
1.27 mycroft 1415: if (how & LOCK_NB)
1.106 dsl 1416: error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK);
1.59 thorpej 1417: else
1.106 dsl 1418: error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf,
1.59 thorpej 1419: F_FLOCK|F_WAIT);
1420: out:
1.110 fvdl 1421: FILE_UNUSE(fp, p);
1.59 thorpej 1422: return (error);
1.16 cgd 1423: }
1424:
1425: /*
1426: * File Descriptor pseudo-device driver (/dev/fd/).
1427: *
1428: * Opening minor device N dup()s the file (if any) connected to file
1429: * descriptor N belonging to the calling process. Note that this driver
1430: * consists of only the ``open()'' routine, because all subsequent
1431: * references to this file will be direct to the other driver.
1432: */
1433: /* ARGSUSED */
1.28 mycroft 1434: int
1.110 fvdl 1435: filedescopen(dev_t dev, int mode, int type, struct proc *p)
1.16 cgd 1436: {
1437:
1.28 mycroft 1438: /*
1.112 jdolecek 1439: * XXX Kludge: set dupfd to contain the value of the
1.89 enami 1440: * the file descriptor being sought for duplication. The error
1.28 mycroft 1441: * return ensures that the vnode for this device will be released
1442: * by vn_open. Open will detect this special error and take the
1443: * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1444: * will simply report the error.
1445: */
1.112 jdolecek 1446: curlwp->l_dupfd = minor(dev); /* XXX */
1.28 mycroft 1447: return (ENODEV);
1.27 mycroft 1448: }
1449:
1.28 mycroft 1450: /*
1451: * Duplicate the specified descriptor to a free descriptor.
1.118 yamt 1452: *
1453: * 'indx' has been fdalloc'ed (and will be fdremove'ed on error) by the caller.
1.28 mycroft 1454: */
1.27 mycroft 1455: int
1.110 fvdl 1456: dupfdopen(struct proc *p, int indx, int dfd, int mode, int error)
1.72 lukem 1457: {
1.110 fvdl 1458: struct filedesc *fdp;
1.118 yamt 1459: struct file *wfp;
1.27 mycroft 1460:
1.72 lukem 1461: fdp = p->p_fd;
1.118 yamt 1462:
1463: /* should be cleared by the caller */
1464: KASSERT(fdp->fd_ofiles[indx] == NULL);
1465:
1.27 mycroft 1466: /*
1467: * If the to-be-dup'd fd number is greater than the allowed number
1468: * of file descriptors, or the fd to be dup'd has already been
1.118 yamt 1469: * closed, reject.
1.27 mycroft 1470: */
1.77 thorpej 1471:
1.118 yamt 1472: /*
1473: * Note, in the case of indx == dfd, fd_getfile below returns NULL.
1474: */
1.77 thorpej 1475: if ((wfp = fd_getfile(fdp, dfd)) == NULL)
1476: return (EBADF);
1477:
1.59 thorpej 1478: FILE_USE(wfp);
1479:
1.27 mycroft 1480: /*
1.28 mycroft 1481: * There are two cases of interest here.
1482: *
1483: * For ENODEV simply dup (dfd) to file descriptor
1484: * (indx) and return.
1485: *
1486: * For ENXIO steal away the file structure from (dfd) and
1487: * store it in (indx). (dfd) is effectively closed by
1488: * this operation.
1489: *
1490: * Any other error code is just returned.
1.27 mycroft 1491: */
1.28 mycroft 1492: switch (error) {
1493: case ENODEV:
1494: /*
1495: * Check that the mode the file is being opened for is a
1496: * subset of the mode of the existing descriptor.
1497: */
1.59 thorpej 1498: if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
1.110 fvdl 1499: FILE_UNUSE(wfp, p);
1.28 mycroft 1500: return (EACCES);
1.59 thorpej 1501: }
1.28 mycroft 1502: fdp->fd_ofiles[indx] = wfp;
1503: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1504: wfp->f_count++;
1.119 yamt 1505: /* 'indx' has been fd_used'ed by caller */
1.110 fvdl 1506: FILE_UNUSE(wfp, p);
1.28 mycroft 1507: return (0);
1.27 mycroft 1508:
1.28 mycroft 1509: case ENXIO:
1510: /*
1511: * Steal away the file pointer from dfd, and stuff it into indx.
1512: */
1513: fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
1514: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1515: fdp->fd_ofiles[dfd] = NULL;
1516: fdp->fd_ofileflags[dfd] = 0;
1517: /*
1518: * Complete the clean up of the filedesc structure by
1519: * recomputing the various hints.
1520: */
1.119 yamt 1521: /* 'indx' has been fd_used'ed by caller */
1.28 mycroft 1522: fd_unused(fdp, dfd);
1.110 fvdl 1523: FILE_UNUSE(wfp, p);
1.28 mycroft 1524: return (0);
1.16 cgd 1525:
1.28 mycroft 1526: default:
1.110 fvdl 1527: FILE_UNUSE(wfp, p);
1.28 mycroft 1528: return (error);
1529: }
1530: /* NOTREACHED */
1.61 wrstuden 1531: }
1532:
1533: /*
1534: * fcntl call which is being passed to the file's fs.
1535: */
1536: int
1.110 fvdl 1537: fcntl_forfs(int fd, struct proc *p, int cmd, void *arg)
1.61 wrstuden 1538: {
1.72 lukem 1539: struct file *fp;
1540: struct filedesc *fdp;
1541: int error;
1542: u_int size;
1.106 dsl 1543: void *data, *memp;
1.61 wrstuden 1544: #define STK_PARAMS 128
1.72 lukem 1545: char stkbuf[STK_PARAMS];
1.61 wrstuden 1546:
1547: /* fd's value was validated in sys_fcntl before calling this routine */
1548: fdp = p->p_fd;
1549: fp = fdp->fd_ofiles[fd];
1550:
1551: if ((fp->f_flag & (FREAD | FWRITE)) == 0)
1552: return (EBADF);
1553:
1554: /*
1555: * Interpret high order word to find amount of data to be
1556: * copied to/from the user's address space.
1557: */
1558: size = (size_t)F_PARAM_LEN(cmd);
1559: if (size > F_PARAM_MAX)
1560: return (EINVAL);
1561: memp = NULL;
1562: if (size > sizeof(stkbuf)) {
1.106 dsl 1563: memp = malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
1.61 wrstuden 1564: data = memp;
1565: } else
1566: data = stkbuf;
1567: if (cmd & F_FSIN) {
1568: if (size) {
1569: error = copyin(arg, data, size);
1570: if (error) {
1571: if (memp)
1572: free(memp, M_IOCTLOPS);
1573: return (error);
1574: }
1575: } else
1.106 dsl 1576: *(void **)data = arg;
1.61 wrstuden 1577: } else if ((cmd & F_FSOUT) && size)
1578: /*
1579: * Zero the buffer so the user always
1580: * gets back something deterministic.
1581: */
1582: memset(data, 0, size);
1583: else if (cmd & F_FSVOID)
1.106 dsl 1584: *(void **)data = arg;
1.61 wrstuden 1585:
1586:
1.110 fvdl 1587: error = (*fp->f_ops->fo_fcntl)(fp, cmd, data, p);
1.61 wrstuden 1588:
1589: /*
1590: * Copy any data to user, size was
1591: * already set and checked above.
1592: */
1593: if (error == 0 && (cmd & F_FSOUT) && size)
1594: error = copyout(data, arg, size);
1595: if (memp)
1596: free(memp, M_IOCTLOPS);
1597: return (error);
1.27 mycroft 1598: }
1.16 cgd 1599:
1.27 mycroft 1600: /*
1601: * Close any files on exec?
1602: */
1603: void
1.110 fvdl 1604: fdcloseexec(struct proc *p)
1.27 mycroft 1605: {
1.110 fvdl 1606: struct filedesc *fdp;
1.72 lukem 1607: int fd;
1.80 thorpej 1608:
1.110 fvdl 1609: fdunshare(p);
1.80 thorpej 1610: cwdunshare(p);
1.16 cgd 1611:
1.72 lukem 1612: fdp = p->p_fd;
1.27 mycroft 1613: for (fd = 0; fd <= fdp->fd_lastfile; fd++)
1614: if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
1.110 fvdl 1615: (void) fdrelease(p, fd);
1.86 christos 1616: }
1617:
1618: /*
1619: * It is unsafe for set[ug]id processes to be started with file
1620: * descriptors 0..2 closed, as these descriptors are given implicit
1621: * significance in the Standard C library. fdcheckstd() will create a
1622: * descriptor referencing /dev/null for each of stdin, stdout, and
1623: * stderr that is not already open.
1624: */
1.92 atatat 1625: #define CHECK_UPTO 3
1.86 christos 1626: int
1.110 fvdl 1627: fdcheckstd(p)
1628: struct proc *p;
1.109 darrenr 1629: {
1.86 christos 1630: struct nameidata nd;
1631: struct filedesc *fdp;
1632: struct file *fp;
1.97 scw 1633: struct file *devnullfp = NULL; /* Quell compiler warning */
1.91 enami 1634: struct proc *pp;
1.86 christos 1635: register_t retval;
1.92 atatat 1636: int fd, i, error, flags = FREAD|FWRITE, devnull = -1;
1637: char closed[CHECK_UPTO * 3 + 1], which[3 + 1];
1.86 christos 1638:
1.92 atatat 1639: closed[0] = '\0';
1.86 christos 1640: if ((fdp = p->p_fd) == NULL)
1.89 enami 1641: return (0);
1.92 atatat 1642: for (i = 0; i < CHECK_UPTO; i++) {
1.86 christos 1643: if (fdp->fd_ofiles[i] != NULL)
1644: continue;
1.92 atatat 1645: snprintf(which, sizeof(which), ",%d", i);
1.108 itojun 1646: strlcat(closed, which, sizeof(closed));
1.86 christos 1647: if (devnull < 0) {
1648: if ((error = falloc(p, &fp, &fd)) != 0)
1.89 enami 1649: return (error);
1.86 christos 1650: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null",
1.110 fvdl 1651: p);
1.86 christos 1652: if ((error = vn_open(&nd, flags, 0)) != 0) {
1.110 fvdl 1653: FILE_UNUSE(fp, p);
1.86 christos 1654: ffree(fp);
1655: fdremove(p->p_fd, fd);
1.89 enami 1656: return (error);
1.86 christos 1657: }
1.106 dsl 1658: fp->f_data = nd.ni_vp;
1.86 christos 1659: fp->f_flag = flags;
1660: fp->f_ops = &vnops;
1661: fp->f_type = DTYPE_VNODE;
1662: VOP_UNLOCK(nd.ni_vp, 0);
1663: devnull = fd;
1.88 christos 1664: devnullfp = fp;
1.87 christos 1665: FILE_SET_MATURE(fp);
1.86 christos 1666: } else {
1667: restart:
1668: if ((error = fdalloc(p, 0, &fd)) != 0) {
1669: if (error == ENOSPC) {
1670: fdexpand(p);
1671: goto restart;
1672: }
1.89 enami 1673: return (error);
1.86 christos 1674: }
1.88 christos 1675:
1.104 yamt 1676: simple_lock(&devnullfp->f_slock);
1.88 christos 1677: FILE_USE(devnullfp);
1678: /* finishdup() will unuse the descriptors for us */
1.110 fvdl 1679: if ((error = finishdup(p, devnull, fd, &retval)) != 0)
1.89 enami 1680: return (error);
1.86 christos 1681: }
1682: }
1.104 yamt 1683: if (devnullfp)
1.110 fvdl 1684: FILE_UNUSE(devnullfp, p);
1.92 atatat 1685: if (closed[0] != '\0') {
1686: pp = p->p_pptr;
1687: log(LOG_WARNING, "set{u,g}id pid %d (%s) "
1688: "was invoked by uid %d ppid %d (%s) "
1689: "with fd %s closed\n",
1690: p->p_pid, p->p_comm, pp->p_ucred->cr_uid,
1691: pp->p_pid, pp->p_comm, &closed[1]);
1692: }
1.89 enami 1693: return (0);
1.16 cgd 1694: }
1.92 atatat 1695: #undef CHECK_UPTO
1.113 jdolecek 1696:
1697: /*
1698: * Sets descriptor owner. If the owner is a process, 'pgid'
1699: * is set to positive value, process ID. If the owner is process group,
1700: * 'pgid' is set to -pg_id.
1701: */
1702: int
1703: fsetown(struct proc *p, pid_t *pgid, int cmd, const void *data)
1704: {
1705: int id = *(int *)data;
1706: int error;
1707:
1708: switch (cmd) {
1709: case TIOCSPGRP:
1710: if (id < 0)
1711: return (EINVAL);
1712: id = -id;
1713: break;
1714: default:
1715: break;
1716: }
1717:
1718: if (id > 0 && !pfind(id))
1719: return (ESRCH);
1720: else if (id < 0 && (error = pgid_in_session(p, -id)))
1721: return (error);
1722:
1723: *pgid = id;
1724: return (0);
1725: }
1726:
1727: /*
1728: * Return descriptor owner information. If the value is positive,
1729: * it's process ID. If it's negative, it's process group ID and
1730: * needs the sign removed before use.
1731: */
1732: int
1733: fgetown(struct proc *p, pid_t pgid, int cmd, void *data)
1734: {
1735: switch (cmd) {
1736: case TIOCGPGRP:
1737: *(int *)data = -pgid;
1738: break;
1739: default:
1740: *(int *)data = pgid;
1741: break;
1742: }
1743: return (0);
1744: }
1745:
1746: /*
1747: * Send signal to descriptor owner, either process or process group.
1748: */
1749: void
1.114 christos 1750: fownsignal(pid_t pgid, int signo, int code, int band, void *fdescdata)
1.113 jdolecek 1751: {
1752: struct proc *p1;
1753: ksiginfo_t ksi;
1754:
1755: memset(&ksi, 0, sizeof(ksi));
1.114 christos 1756: ksi.ksi_signo = signo;
1.113 jdolecek 1757: ksi.ksi_code = code;
1758: ksi.ksi_band = band;
1759:
1760: if (pgid > 0 && (p1 = pfind(pgid)))
1761: kpsignal(p1, &ksi, fdescdata);
1762: else if (pgid < 0)
1763: kgsignal(-pgid, &ksi, fdescdata);
1764: }
CVSweb <webmaster@jp.NetBSD.org>