|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1989, 1991, 1993
28: * The Regents of the University of California. All rights reserved.
29: * (c) UNIX System Laboratories, Inc.
30: * All or some portions of this file are derived from material licensed
31: * to the University of California by American Telephone and Telegraph
32: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
33: * the permission of UNIX System Laboratories, Inc.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * 4. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: *
63: * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
64: *
65: * History:
66: * CHW 8/5/98 Added F_SETSIZE command to truncate without
67: * zero filling space
68: * CHW 7/6/98 Updated Preallocate command to take a structure
69: * and return output.
70: * CHW 6/25/98 Fixed a bug in the lock call in fcntl
71: * Preallocate command
72: */
73:
74: #include <sys/param.h>
75: #include <sys/systm.h>
76: #include <sys/filedesc.h>
77: #include <sys/kernel.h>
78: #include <sys/vnode.h>
79: #include <sys/proc.h>
80: #include <sys/file.h>
81: #include <sys/socket.h>
82: #include <sys/socketvar.h>
83: #include <sys/stat.h>
84: #include <sys/ioctl.h>
85: #include <sys/fcntl.h>
86: #include <sys/malloc.h>
87: #include <sys/syslog.h>
88: #include <sys/unistd.h>
89: #include <sys/resourcevar.h>
90:
91: #include <sys/mount.h>
92:
93: /*
94: * Descriptor management.
95: */
96: struct filelist filehead; /* head of list of open files */
97: int nfiles; /* actual number of open files */
98:
99: /*
100: * System calls on descriptors.
101: */
102: /* ARGSUSED */
103: int
104: getdtablesize(p, uap, retval)
105: struct proc *p;
106: void *uap;
107: register_t *retval;
108: {
109:
110: *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
111: return (0);
112: }
113:
114: /* ARGSUSED */
115: int
116: ogetdtablesize(p, uap, retval)
117: struct proc *p;
118: void *uap;
119: register_t *retval;
120: {
121:
122: *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, NOFILE);
123: return (0);
124: }
125:
126: static __inline__
127: void _fdrelse(fdp, fd)
128: register struct filedesc *fdp;
129: register int fd;
130: {
131: if (fd < fdp->fd_freefile)
132: fdp->fd_freefile = fd;
133: #if DIAGNOSTIC
134: if (fd > fdp->fd_lastfile)
135: panic("fdrelse: fd_lastfile inconsistent");
136: #endif
137: fdp->fd_ofiles[fd] = NULL;
138: fdp->fd_ofileflags[fd] = 0;
139: while ((fd = fdp->fd_lastfile) > 0 &&
140: fdp->fd_ofiles[fd] == NULL &&
141: !(fdp->fd_ofileflags[fd] & UF_RESERVED))
142: fdp->fd_lastfile--;
143: }
144:
145: /*
146: * Duplicate a file descriptor.
147: */
148: struct dup_args {
149: u_int fd;
150: };
151: /* ARGSUSED */
152: int
153: dup(p, uap, retval)
154: struct proc *p;
155: struct dup_args *uap;
156: register_t *retval;
157: {
158: register struct filedesc *fdp = p->p_fd;
159: register int old = uap->fd;
160: int new, error;
161:
162: if ((u_int)old >= fdp->fd_nfiles ||
163: fdp->fd_ofiles[old] == NULL ||
164: (fdp->fd_ofileflags[old] & UF_RESERVED))
165: return (EBADF);
166: if (error = fdalloc(p, 0, &new))
167: return (error);
168: return (finishdup(fdp, old, new, retval));
169: }
170:
171: /*
172: * Duplicate a file descriptor to a particular value.
173: */
174: struct dup2_args {
175: u_int from;
176: u_int to;
177: };
178: /* ARGSUSED */
179: int
180: dup2(p, uap, retval)
181: struct proc *p;
182: struct dup2_args *uap;
183: register_t *retval;
184: {
185: register struct filedesc *fdp = p->p_fd;
186: register int old = uap->from, new = uap->to;
187: int i, error;
188:
189: if ((u_int)old >= fdp->fd_nfiles ||
190: fdp->fd_ofiles[old] == NULL ||
191: (fdp->fd_ofileflags[old] & UF_RESERVED) ||
192: (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
193: (u_int)new >= maxfiles)
194: return (EBADF);
195: if (old == new) {
196: *retval = new;
197: return (0);
198: }
199: if ((u_int)new >= fdp->fd_nfiles) {
200: if (error = fdalloc(p, new, &i))
201: return (error);
202: if (new != i) {
203: _fdrelse(fdp, i);
204: goto closeit;
205: }
206: }
207: else {
208: struct file **fpp;
209: char flags;
210: closeit:
211: if ((flags = fdp->fd_ofileflags[new]) & UF_RESERVED)
212: return (EBADF);
213: fdp->fd_ofileflags[new] = (flags & ~UF_MAPPED) | UF_RESERVED;
214: /*
215: * dup2() must succeed even if the close has an error.
216: */
217: if (*(fpp = &fdp->fd_ofiles[new])) {
218: struct file *fp = *fpp;
219:
220: *fpp = NULL; (void) closef(fp, p);
221: }
222: }
223: return (finishdup(fdp, old, new, retval));
224: }
225:
226: /*
227: * The file control system call.
228: */
229: struct fcntl_args {
230: int fd;
231: int cmd;
232: int arg;
233: };
234: /* ARGSUSED */
235: int
236: fcntl(p, uap, retval)
237: struct proc *p;
238: register struct fcntl_args *uap;
239: register_t *retval;
240: {
241: int fd = uap->fd;
242: register struct filedesc *fdp = p->p_fd;
243: register struct file *fp;
244: register char *pop;
245: struct vnode *vp;
246: int i, tmp, error, error2, flg = F_POSIX;
247: struct flock fl;
248: fstore_t alloc_struct; /* structure for allocate command */
249: u_int32_t alloc_flags = 0;
250: off_t offset; /* used for F_SETSIZE */
251: int newmin;
252: struct radvisory ra_struct;
253: fbootstraptransfer_t fbt_struct; /* for F_READBOOTSTRAP and F_WRITEBOOTSTRAP */
254:
255: if ((u_int)fd >= fdp->fd_nfiles ||
256: (fp = fdp->fd_ofiles[fd]) == NULL ||
257: (fdp->fd_ofileflags[fd] & UF_RESERVED))
258: return (EBADF);
259: pop = &fdp->fd_ofileflags[fd];
260: switch (uap->cmd) {
261:
262: case F_DUPFD:
263: newmin = (long)uap->arg;
264: if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
265: (u_int)newmin >= maxfiles)
266: return (EINVAL);
267: if (error = fdalloc(p, newmin, &i))
268: return (error);
269: return (finishdup(fdp, fd, i, retval));
270:
271: case F_GETFD:
272: *retval = (*pop & UF_EXCLOSE)? 1 : 0;
273: return (0);
274:
275: case F_SETFD:
276: *pop = (*pop &~ UF_EXCLOSE) |
277: ((long)(uap->arg) & 1)? UF_EXCLOSE : 0;
278: return (0);
279:
280: case F_GETFL:
281: *retval = OFLAGS(fp->f_flag);
282: return (0);
283:
284: case F_SETFL:
285: fp->f_flag &= ~FCNTLFLAGS;
286: fp->f_flag |= FFLAGS((long)uap->arg) & FCNTLFLAGS;
287: tmp = fp->f_flag & FNONBLOCK;
288: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
289: if (error)
290: return (error);
291: tmp = fp->f_flag & FASYNC;
292: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
293: if (!error)
294: return (0);
295: fp->f_flag &= ~FNONBLOCK;
296: tmp = 0;
297: (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
298: return (error);
299:
300: case F_GETOWN:
301: if (fp->f_type == DTYPE_SOCKET) {
302: *retval = ((struct socket *)fp->f_data)->so_pgid;
303: return (0);
304: }
305: error = (*fp->f_ops->fo_ioctl)
306: (fp, (int)TIOCGPGRP, (caddr_t)retval, p);
307: *retval = -*retval;
308: return (error);
309:
310: case F_SETOWN:
311: if (fp->f_type == DTYPE_SOCKET) {
312: ((struct socket *)fp->f_data)->so_pgid =
313: (long)uap->arg;
314: return (0);
315: }
316: if ((long)uap->arg <= 0) {
317: uap->arg = (void *)(-(long)(uap->arg));
318: } else {
319: struct proc *p1 = pfind((long)uap->arg);
320: if (p1 == 0)
321: return (ESRCH);
322: uap->arg = (void *)(long)p1->p_pgrp->pg_id;
323: }
324: return ((*fp->f_ops->fo_ioctl)
325: (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
326:
327: case F_SETLKW:
328: flg |= F_WAIT;
329: /* Fall into F_SETLK */
330:
331: case F_SETLK:
332: if (fp->f_type != DTYPE_VNODE)
333: return (EBADF);
334: vp = (struct vnode *)fp->f_data;
335: /* Copy in the lock structure */
336: error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
337: sizeof (fl));
338: if (error)
339: return (error);
340: if (fl.l_whence == SEEK_CUR)
341: fl.l_start += fp->f_offset;
342: switch (fl.l_type) {
343:
344: case F_RDLCK:
345: if ((fp->f_flag & FREAD) == 0)
346: return (EBADF);
347: p->p_flag |= P_ADVLOCK;
348: return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
349:
350: case F_WRLCK:
351: if ((fp->f_flag & FWRITE) == 0)
352: return (EBADF);
353: p->p_flag |= P_ADVLOCK;
354: return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
355:
356: case F_UNLCK:
357: return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
358: F_POSIX));
359:
360: default:
361: return (EINVAL);
362: }
363:
364: case F_GETLK:
365: if (fp->f_type != DTYPE_VNODE)
366: return (EBADF);
367: vp = (struct vnode *)fp->f_data;
368: /* Copy in the lock structure */
369: error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
370: sizeof (fl));
371: if (error)
372: return (error);
373: if (fl.l_whence == SEEK_CUR)
374: fl.l_start += fp->f_offset;
375: if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
376: return (error);
377: return (copyout((caddr_t)&fl, (caddr_t)uap->arg,
378: sizeof (fl)));
379:
380: case F_PREALLOCATE:
381:
382: /* Copy in the structure */
383:
384: error = copyin((caddr_t)uap->arg, (caddr_t)&alloc_struct,
385: sizeof (alloc_struct));
386:
387: if (error)
388: return (error);
389:
390: /* now set the space allocated to 0 and pass it out in
391: case we get a parameter checking error */
392:
393: alloc_struct.fst_bytesalloc = 0;
394:
395: error = copyout((caddr_t)&alloc_struct, (caddr_t)uap->arg,
396: sizeof (alloc_struct));
397:
398: if (error)
399: return(error);
400:
401: /* First make sure that we have write permission */
402:
403: if ((fp->f_flag & FWRITE) == 0)
404: return (EBADF);
405:
406:
407: /* Do some simple parameter checking */
408:
409:
410: /* set up the flags */
411:
412: alloc_flags |= PREALLOCATE;
413:
414: if (alloc_struct.fst_flags & F_ALLOCATECONTIG) {
415: alloc_flags |= ALLOCATECONTIG;
416: }
417:
418: if (alloc_struct.fst_flags & F_ALLOCATEALL) {
419: alloc_flags |= ALLOCATEALL;
420: }
421:
422: /* Do any position mode specific stuff. The only */
423: /* position mode supported now is PEOFPOSMODE */
424:
425: switch (alloc_struct.fst_posmode) {
426:
427: case F_PEOFPOSMODE:
428:
429: if ((alloc_struct.fst_offset != 0) ||
430: (alloc_struct.fst_length < 0))
431: return (EINVAL);
432:
433: alloc_flags |= ALLOCATEFROMPEOF;
434: break;
435:
436: default:
437:
438: return(EINVAL);
439:
440: }
441:
442:
443: /* Now lock the vnode and call allocate to get the space */
444:
445: vp = (struct vnode *)fp->f_data;
446:
447: VOP_LOCK(vp,LK_EXCLUSIVE,p);
448: error = VOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
449: &alloc_struct.fst_bytesalloc,fp->f_cred,p);
450: VOP_UNLOCK(vp,0,p);
451:
452: if (error2 = (copyout((caddr_t)&alloc_struct, (caddr_t)uap->arg,
453: sizeof (alloc_struct)))) {
454: if (error) {
455: return(error);
456: } else {
457: return(error2);
458: }
459: }
460:
461: return(error);
462:
463: case F_SETSIZE:
464:
465: /* Copy in the structure */
466:
467: error = copyin((caddr_t)uap->arg, (caddr_t)&offset,
468: sizeof (off_t));
469:
470: if (error)
471: return (error);
472:
473:
474: /* First make sure that we are root. Growing a file */
475: /* without zero filling the data is a security hole */
476: /* root would have access anyway so we'll allow it */
477:
478: if (!is_suser()) {
479: return (EACCES);
480: }
481:
482: /* Now lock the vnode and call allocate to get the space */
483:
484: vp = (struct vnode *)fp->f_data;
485:
486: VOP_LOCK(vp,LK_EXCLUSIVE,p);
487: error = VOP_TRUNCATE(vp,offset,IO_NOZEROFILL,fp->f_cred,p);
488: VOP_UNLOCK(vp,0,p);
489:
490: return(error);
491:
492: case F_RDAHEAD:
493: vp = (struct vnode *)fp->f_data;
494:
495: simple_lock(&vp->v_interlock);
496: if (uap->arg)
497: vp->v_flag &= ~VRAOFF;
498: else
499: vp->v_flag |= VRAOFF;
500: simple_unlock(&vp->v_interlock);
501:
502: return (0);
503:
504: case F_RDADVISE:
505: vp = (struct vnode *)fp->f_data;
506:
507: if (error = copyin((caddr_t)uap->arg, (caddr_t)&ra_struct, sizeof (ra_struct)))
508: return(error);
509: return (VOP_IOCTL(vp, 1, &ra_struct, 0, fp->f_cred, p));
510:
511: case F_READBOOTSTRAP:
512: case F_WRITEBOOTSTRAP:
513:
514: /* Copy in the structure */
515:
516: error = copyin((caddr_t)uap->arg, (caddr_t)&fbt_struct,
517: sizeof (fbt_struct));
518:
519: if (error)
520: return (error);
521:
522:
523: if (uap->cmd == F_WRITEBOOTSTRAP) {
524: /* First make sure that we are root. Updating the */
525: /* bootstrap on a disk could be a security hole */
526:
527: if (!is_suser()) {
528: return (EACCES);
529: }
530: };
531:
532: /* Now lock the vnode and call VOP_IOCTL to handle the I/O: */
533:
534: vp = (struct vnode *)fp->f_data;
535: if (vp->v_tag != VT_HFS) {
536: error = EINVAL;
537: } else {
538: VOP_LOCK(vp,LK_EXCLUSIVE,p);
539: error = VOP_IOCTL(vp, (uap->cmd == F_WRITEBOOTSTRAP) ? 3 : 2, &fbt_struct, 0, fp->f_cred, p);
540: VOP_UNLOCK(vp,0,p);
541: };
542:
543: return(error);
544:
545:
546: default:
547: return (EINVAL);
548: }
549: /* NOTREACHED */
550: }
551:
552: /*
553: * Common code for dup, dup2, and fcntl(F_DUPFD).
554: */
555: int
556: finishdup(fdp, old, new, retval)
557: register struct filedesc *fdp;
558: register int old, new;
559: register_t *retval;
560: {
561: register struct file *fp;
562:
563: if ((fp = fdp->fd_ofiles[old]) == NULL ||
564: (fdp->fd_ofileflags[old] & UF_RESERVED)) {
565: _fdrelse(fdp, new);
566: return (EBADF);
567: }
568: fdp->fd_ofiles[new] = fp;
569: fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
1.1.1.2 ! root 570: if (++fp->f_count <= 0)
! 571: panic("finishdup f_count");
1.1 root 572: if (new > fdp->fd_lastfile)
573: fdp->fd_lastfile = new;
574: *retval = new;
575: return (0);
576: }
577:
578: /*
579: * Close a file descriptor.
580: */
581: struct close_args {
582: int fd;
583: };
584: /* ARGSUSED */
585: int
586: close(p, uap, retval)
587: struct proc *p;
588: struct close_args *uap;
589: register_t *retval;
590: {
591: int fd = uap->fd;
592: register struct filedesc *fdp = p->p_fd;
593: register struct file *fp;
594:
595: if ((u_int)fd >= fdp->fd_nfiles ||
596: (fp = fdp->fd_ofiles[fd]) == NULL ||
597: (fdp->fd_ofileflags[fd] & UF_RESERVED))
598: return (EBADF);
599: _fdrelse(fdp, fd);
600: return (closef(fp, p));
601: }
602:
603: /*
604: * Return status information about a file descriptor.
605: */
606: struct fstat_args {
607: int fd;
608: struct stat *sb;
609: };
610: /* ARGSUSED */
611: int
612: fstat(p, uap, retval)
613: struct proc *p;
614: register struct fstat_args *uap;
615: register_t *retval;
616: {
617: int fd = uap->fd;
618: register struct filedesc *fdp = p->p_fd;
619: register struct file *fp;
620: struct stat ub;
621: int error;
622:
623: if ((u_int)fd >= fdp->fd_nfiles ||
624: (fp = fdp->fd_ofiles[fd]) == NULL ||
625: (fdp->fd_ofileflags[fd] & UF_RESERVED))
626: return (EBADF);
627: switch (fp->f_type) {
628:
629: case DTYPE_VNODE:
630: error = vn_stat((struct vnode *)fp->f_data, &ub, p);
631: break;
632:
633: case DTYPE_SOCKET:
634: error = soo_stat((struct socket *)fp->f_data, &ub);
635: break;
636:
637: default:
638: panic("fstat");
639: /*NOTREACHED*/
640: }
641: if (error == 0)
642: error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
643: sizeof (ub));
644: return (error);
645: }
646:
647: #if COMPAT_43
648: /*
649: * Return status information about a file descriptor.
650: */
651: struct ofstat_args {
652: int fd;
653: struct ostat *sb;
654: };
655: /* ARGSUSED */
656: ofstat(p, uap, retval)
657: struct proc *p;
658: register struct ofstat_args *uap;
659: register_t *retval;
660: {
661: int fd = uap->fd;
662: register struct filedesc *fdp = p->p_fd;
663: register struct file *fp;
664: struct stat ub;
665: struct ostat oub;
666: int error;
667:
668: if ((u_int)fd >= fdp->fd_nfiles ||
669: (fp = fdp->fd_ofiles[fd]) == NULL ||
670: (fdp->fd_ofileflags[fd] & UF_RESERVED))
671: return (EBADF);
672: switch (fp->f_type) {
673:
674: case DTYPE_VNODE:
675: error = vn_stat((struct vnode *)fp->f_data, &ub, p);
676: break;
677:
678: case DTYPE_SOCKET:
679: error = soo_stat((struct socket *)fp->f_data, &ub);
680: break;
681:
682: default:
683: panic("ofstat");
684: /*NOTREACHED*/
685: }
686: cvtstat(&ub, &oub);
687: if (error == 0)
688: error = copyout((caddr_t)&oub, (caddr_t)uap->sb,
689: sizeof (oub));
690: return (error);
691: }
692: #endif /* COMPAT_43 */
693:
694: /*
695: * Return pathconf information about a file descriptor.
696: */
697: struct fpathconf_args {
698: int fd;
699: int name;
700: };
701: /* ARGSUSED */
702: fpathconf(p, uap, retval)
703: struct proc *p;
704: register struct fpathconf_args *uap;
705: register_t *retval;
706: {
707: int fd = uap->fd;
708: struct filedesc *fdp = p->p_fd;
709: struct file *fp;
710: struct vnode *vp;
711:
712: if ((u_int)fd >= fdp->fd_nfiles ||
713: (fp = fdp->fd_ofiles[fd]) == NULL ||
714: (fdp->fd_ofileflags[fd] & UF_RESERVED))
715: return (EBADF);
716: switch (fp->f_type) {
717:
718: case DTYPE_SOCKET:
719: if (uap->name != _PC_PIPE_BUF)
720: return (EINVAL);
721: *retval = PIPE_BUF;
722: return (0);
723:
724: case DTYPE_VNODE:
725: vp = (struct vnode *)fp->f_data;
726: return (VOP_PATHCONF(vp, uap->name, retval));
727:
728: default:
729: panic("fpathconf");
730: }
731: /*NOTREACHED*/
732: }
733:
734: /*
735: * Allocate a file descriptor for the process.
736: */
737: int fdexpand;
738:
739: int
740: fdalloc(p, want, result)
741: struct proc *p;
742: int want;
743: int *result;
744: {
745: register struct filedesc *fdp = p->p_fd;
746: register int i;
747: int lim, last, nfiles, oldnfiles;
748: struct file **newofiles, **ofiles;
749: char *newofileflags, *ofileflags;
750:
751: /*
752: * Search for a free descriptor starting at the higher
753: * of want or fd_freefile. If that fails, consider
754: * expanding the ofile array.
755: */
756: lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
757: for (;;) {
758: last = min(fdp->fd_nfiles, lim);
759: if ((i = want) < fdp->fd_freefile)
760: i = fdp->fd_freefile;
761: ofiles = &fdp->fd_ofiles[i];
762: ofileflags = &fdp->fd_ofileflags[i];
763: for (; i < last; i++) {
764: if (*ofiles == NULL && !(*ofileflags & UF_RESERVED)) {
765: *ofileflags = UF_RESERVED;
766: if (i > fdp->fd_lastfile)
767: fdp->fd_lastfile = i;
768: if (want <= fdp->fd_freefile)
769: fdp->fd_freefile = i;
770: *result = i;
771: return (0);
772: }
773: ofiles++; ofileflags++;
774: }
775:
776: /*
777: * No space in current array. Expand?
778: */
779: if (fdp->fd_nfiles >= lim)
780: return (EMFILE);
781: if (fdp->fd_nfiles < NDEXTENT)
782: nfiles = NDEXTENT;
783: else
784: nfiles = 2 * fdp->fd_nfiles;
785: /* Enforce lim */
786: if (nfiles > lim)
787: nfiles = lim;
788: MALLOC_ZONE(newofiles, struct file **,
789: nfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
790: if (fdp->fd_nfiles >= nfiles) {
791: FREE_ZONE(newofiles, nfiles * OFILESIZE, M_OFILETABL);
792: continue;
793: }
794: newofileflags = (char *) &newofiles[nfiles];
795: /*
796: * Copy the existing ofile and ofileflags arrays
797: * and zero the new portion of each array.
798: */
799: oldnfiles = fdp->fd_nfiles;
800: (void) memcpy(newofiles, fdp->fd_ofiles,
801: oldnfiles * sizeof *fdp->fd_ofiles);
802: (void) memset(&newofiles[oldnfiles], 0,
803: (nfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
804:
805: (void) memcpy(newofileflags, fdp->fd_ofileflags,
806: oldnfiles * sizeof *fdp->fd_ofileflags);
807: (void) memset(&newofileflags[oldnfiles], 0,
808: (nfiles - oldnfiles) *
809: sizeof *fdp->fd_ofileflags);
810: ofiles = fdp->fd_ofiles;
811: fdp->fd_ofiles = newofiles;
812: fdp->fd_ofileflags = newofileflags;
813: fdp->fd_nfiles = nfiles;
814: FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
815: fdexpand++;
816: }
817: }
818:
819: /*
820: * Check to see whether n user file descriptors
821: * are available to the process p.
822: */
823: int
824: fdavail(p, n)
825: struct proc *p;
826: register int n;
827: {
828: register struct filedesc *fdp = p->p_fd;
829: register struct file **fpp;
830: register char *flags;
831: register int i, lim;
832:
833: lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
834: if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
835: return (1);
836: fpp = &fdp->fd_ofiles[fdp->fd_freefile];
837: flags = &fdp->fd_ofileflags[fdp->fd_freefile];
838: for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
839: if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
840: return (1);
841: return (0);
842: }
843:
844: void
845: fdrelse(p, fd)
846: struct proc *p;
847: int fd;
848: {
849: _fdrelse(p->p_fd, fd);
850: }
851:
852: int
853: fdgetf(p, fd, resultfp)
854: register struct proc *p;
855: register int fd;
856: struct file **resultfp;
857: {
858: register struct filedesc *fdp = p->p_fd;
859: struct file *fp;
860:
861: if ((u_int)fd >= fdp->fd_nfiles ||
862: (fp = fdp->fd_ofiles[fd]) == NULL ||
863: (fdp->fd_ofileflags[fd] & UF_RESERVED))
864: return (EBADF);
865:
866: if (resultfp)
867: *resultfp = fp;
868: return (0);
869: }
870:
871: /*
872: * Create a new open file structure and allocate
873: * a file decriptor for the process that refers to it.
874: */
875: int
876: falloc(p, resultfp, resultfd)
877: register struct proc *p;
878: struct file **resultfp;
879: int *resultfd;
880: {
881: register struct file *fp, *fq;
882: int error, i;
883:
884: if (error = fdalloc(p, 0, &i))
885: return (error);
886: if (nfiles >= maxfiles) {
887: tablefull("file");
888: return (ENFILE);
889: }
890: /*
891: * Allocate a new file descriptor.
892: * If the process has file descriptor zero open, add to the list
893: * of open files at that point, otherwise put it at the front of
894: * the list of open files.
895: */
896: nfiles++;
897: MALLOC_ZONE(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
898: bzero(fp, sizeof(struct file));
899: if (fq = p->p_fd->fd_ofiles[0]) {
900: LIST_INSERT_AFTER(fq, fp, f_list);
901: } else {
902: LIST_INSERT_HEAD(&filehead, fp, f_list);
903: }
904: p->p_fd->fd_ofiles[i] = fp;
905: fp->f_count = 1;
906: fp->f_cred = p->p_ucred;
907: crhold(fp->f_cred);
908: if (resultfp)
909: *resultfp = fp;
910: if (resultfd)
911: *resultfd = i;
912: return (0);
913: }
914:
915: /*
916: * Free a file structure.
917: */
918: void
919: ffree(fp)
920: register struct file *fp;
921: {
922: register struct file *fq;
1.1.1.2 ! root 923: struct ucred *cred;
1.1 root 924:
925: LIST_REMOVE(fp, f_list);
1.1.1.2 ! root 926: cred = fp->f_cred;
! 927: if (cred != NOCRED) {
! 928: fp->f_cred = NOCRED;
! 929: crfree(cred);
! 930: }
1.1 root 931: #if DIAGNOSTIC
932: fp->f_count = 0;
933: #endif
934: nfiles--;
935: FREE_ZONE(fp, sizeof *fp, M_FILE);
936: }
937:
938: void
939: fdexec(p)
940: struct proc *p;
941: {
942: register struct filedesc *fdp = p->p_fd;
943: register int i = fdp->fd_lastfile;
944: register struct file **fpp = &fdp->fd_ofiles[i];
945: register char *flags = &fdp->fd_ofileflags[i];
946:
947: while (i >= 0) {
948: if ((*flags & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
949: register struct file *fp = *fpp;
950:
951: *fpp = NULL; *flags = 0;
952: if (i == fdp->fd_lastfile && i > 0)
953: fdp->fd_lastfile--;
954: closef(fp, p);
955: }
956: else
957: *flags &= ~UF_MAPPED;
958:
959: i--; fpp--; flags--;
960: }
961: }
962:
963: /*
964: * Copy a filedesc structure.
965: */
966: struct filedesc *
967: fdcopy(p)
968: struct proc *p;
969: {
970: register struct filedesc *newfdp, *fdp = p->p_fd;
971: register int i;
972:
973: MALLOC_ZONE(newfdp, struct filedesc *,
974: sizeof *newfdp, M_FILEDESC, M_WAITOK);
975: (void) memcpy(newfdp, fdp, sizeof *newfdp);
976: VREF(newfdp->fd_cdir);
977: if (newfdp->fd_rdir)
978: VREF(newfdp->fd_rdir);
979: newfdp->fd_refcnt = 1;
980:
981: /*
982: * If the number of open files fits in the internal arrays
983: * of the open file structure, use them, otherwise allocate
984: * additional memory for the number of descriptors currently
985: * in use.
986: */
987: if (newfdp->fd_lastfile < NDFILE)
988: i = NDFILE;
989: else {
990: /*
991: * Compute the smallest multiple of NDEXTENT needed
992: * for the file descriptors currently in use,
993: * allowing the table to shrink.
994: */
995: i = newfdp->fd_nfiles;
996: while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
997: i /= 2;
998: }
999: MALLOC_ZONE(newfdp->fd_ofiles, struct file **,
1000: i * OFILESIZE, M_OFILETABL, M_WAITOK);
1001: newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
1002: newfdp->fd_nfiles = i;
1003: if (fdp->fd_nfiles > 0) {
1004: register struct file **fpp;
1005: register char *flags;
1006:
1007: (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
1008: i * sizeof *fdp->fd_ofiles);
1009: (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
1010: i * sizeof *fdp->fd_ofileflags);
1011:
1012: fpp = newfdp->fd_ofiles;
1013: flags = newfdp->fd_ofileflags;
1014: for (i = newfdp->fd_lastfile; i-- >= 0; fpp++, flags++)
1.1.1.2 ! root 1015: if (*fpp != NULL && !(*flags & UF_RESERVED)) {
! 1016: if (++(*fpp)->f_count <= 0)
! 1017: panic("fdcopy f_count");
! 1018: } else {
1.1 root 1019: *fpp = NULL; *flags = 0;
1020: }
1021: }
1022: else
1023: (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
1024:
1025: return (newfdp);
1026: }
1027:
1028: /*
1029: * Release a filedesc structure.
1030: */
1031: void
1032: fdfree(p)
1033: struct proc *p;
1034: {
1035: register struct filedesc *fdp;
1036: register struct file **fpp;
1037: register int i;
1038:
1039: if ((fdp = p->p_fd) == NULL)
1040: return;
1041: if (--fdp->fd_refcnt > 0)
1042: return;
1043: p->p_fd = NULL;
1044: if (fdp->fd_nfiles > 0) {
1045: fpp = fdp->fd_ofiles;
1046: for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
1047: if (*fpp)
1048: (void) closef(*fpp, p);
1049: FREE_ZONE(fdp->fd_ofiles,
1050: fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
1051: }
1052: vrele(fdp->fd_cdir);
1053: if (fdp->fd_rdir)
1054: vrele(fdp->fd_rdir);
1055: FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
1056: }
1057:
1058: /*
1059: * Internal form of close.
1060: * Decrement reference count on file structure.
1061: * Note: p may be NULL when closing a file
1062: * that was being passed in a message.
1063: */
1064: int
1065: closef(fp, p)
1066: register struct file *fp;
1067: register struct proc *p;
1068: {
1069: struct vnode *vp;
1070: struct flock lf;
1071: int error;
1072:
1073: if (fp == NULL)
1074: return (0);
1075: /*
1076: * POSIX record locking dictates that any close releases ALL
1077: * locks owned by this process. This is handled by setting
1078: * a flag in the unlock to free ONLY locks obeying POSIX
1079: * semantics, and not to free BSD-style file locks.
1080: * If the descriptor was in a message, POSIX-style locks
1081: * aren't passed with the descriptor.
1082: */
1083: if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
1084: lf.l_whence = SEEK_SET;
1085: lf.l_start = 0;
1086: lf.l_len = 0;
1087: lf.l_type = F_UNLCK;
1088: vp = (struct vnode *)fp->f_data;
1089: (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1090: }
1091: if (--fp->f_count > 0)
1092: return (0);
1093: if (fp->f_count < 0)
1094: panic("closef: count < 0");
1095: if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1096: lf.l_whence = SEEK_SET;
1097: lf.l_start = 0;
1098: lf.l_len = 0;
1099: lf.l_type = F_UNLCK;
1100: vp = (struct vnode *)fp->f_data;
1101: (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1102: }
1103: if (fp->f_ops)
1104: error = (*fp->f_ops->fo_close)(fp, p);
1105: else
1106: error = 0;
1107: ffree(fp);
1108: return (error);
1109: }
1110:
1111: /*
1112: * Apply an advisory lock on a file descriptor.
1113: *
1114: * Just attempt to get a record lock of the requested type on
1115: * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1116: */
1117: struct flock_args {
1118: int fd;
1119: int how;
1120: };
1121: /* ARGSUSED */
1122: int
1123: flock(p, uap, retval)
1124: struct proc *p;
1125: register struct flock_args *uap;
1126: register_t *retval;
1127: {
1128: int fd = uap->fd;
1129: int how = uap->how;
1130: register struct filedesc *fdp = p->p_fd;
1131: register struct file *fp;
1132: struct vnode *vp;
1133: struct flock lf;
1134:
1135: if ((u_int)fd >= fdp->fd_nfiles ||
1136: (fp = fdp->fd_ofiles[fd]) == NULL ||
1137: (fdp->fd_ofileflags[fd] & UF_RESERVED))
1138: return (EBADF);
1139: if (fp->f_type != DTYPE_VNODE)
1140: return (EOPNOTSUPP);
1141: vp = (struct vnode *)fp->f_data;
1142: lf.l_whence = SEEK_SET;
1143: lf.l_start = 0;
1144: lf.l_len = 0;
1145: if (how & LOCK_UN) {
1146: lf.l_type = F_UNLCK;
1147: fp->f_flag &= ~FHASLOCK;
1148: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
1149: }
1150: if (how & LOCK_EX)
1151: lf.l_type = F_WRLCK;
1152: else if (how & LOCK_SH)
1153: lf.l_type = F_RDLCK;
1154: else
1155: return (EBADF);
1156: fp->f_flag |= FHASLOCK;
1157: if (how & LOCK_NB)
1158: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
1159: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
1160: }
1161:
1162: /*
1163: * File Descriptor pseudo-device driver (/dev/fd/).
1164: *
1165: * Opening minor device N dup()s the file (if any) connected to file
1166: * descriptor N belonging to the calling process. Note that this driver
1167: * consists of only the ``open()'' routine, because all subsequent
1168: * references to this file will be direct to the other driver.
1169: */
1170: /* ARGSUSED */
1171: int
1172: fdopen(dev, mode, type, p)
1173: dev_t dev;
1174: int mode, type;
1175: struct proc *p;
1176: {
1177:
1178: /*
1179: * XXX Kludge: set curproc->p_dupfd to contain the value of the
1180: * the file descriptor being sought for duplication. The error
1181: * return ensures that the vnode for this device will be released
1182: * by vn_open. Open will detect this special error and take the
1183: * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1184: * will simply report the error.
1185: */
1186: p->p_dupfd = minor(dev);
1187: return (ENODEV);
1188: }
1189:
1190: /*
1191: * Duplicate the specified descriptor to a free descriptor.
1192: */
1193: int
1194: dupfdopen(fdp, indx, dfd, mode, error)
1195: register struct filedesc *fdp;
1196: register int indx, dfd;
1197: int mode;
1198: int error;
1199: {
1200: register struct file *wfp;
1201: struct file *fp;
1202:
1203: /*
1204: * If the to-be-dup'd fd number is greater than the allowed number
1205: * of file descriptors, or the fd to be dup'd has already been
1206: * closed, reject. Note, check for new == old is necessary as
1207: * falloc could allocate an already closed to-be-dup'd descriptor
1208: * as the new descriptor.
1209: */
1210: fp = fdp->fd_ofiles[indx];
1211: if ((u_int)dfd >= fdp->fd_nfiles ||
1212: (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
1213: (fdp->fd_ofileflags[dfd] & UF_RESERVED))
1214: return (EBADF);
1215:
1216: /*
1217: * There are two cases of interest here.
1218: *
1219: * For ENODEV simply dup (dfd) to file descriptor
1220: * (indx) and return.
1221: *
1222: * For ENXIO steal away the file structure from (dfd) and
1223: * store it in (indx). (dfd) is effectively closed by
1224: * this operation.
1225: *
1226: * Any other error code is just returned.
1227: */
1228: switch (error) {
1229: case ENODEV:
1230: /*
1231: * Check that the mode the file is being opened for is a
1232: * subset of the mode of the existing descriptor.
1233: */
1234: if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1235: return (EACCES);
1.1.1.2 ! root 1236: if (++wfp->f_count <= 0)
! 1237: panic("dupfdopen f_count");
1.1 root 1238: if (indx > fdp->fd_lastfile)
1239: fdp->fd_lastfile = indx;;
1240: fdp->fd_ofiles[indx] = wfp;
1241: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1242: return (0);
1243:
1244: case ENXIO:
1245: /*
1246: * Steal away the file pointer from dfd, and stuff it into indx.
1247: */
1248: if (indx > fdp->fd_lastfile)
1249: fdp->fd_lastfile = indx;;
1250: fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
1251: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1252: _fdrelse(fdp, dfd);
1253: return (0);
1254:
1255: default:
1256: return (error);
1257: }
1258: /* NOTREACHED */
1259: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.