|
|
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;
570: fp->f_count++;
571: if (new > fdp->fd_lastfile)
572: fdp->fd_lastfile = new;
573: *retval = new;
574: return (0);
575: }
576:
577: /*
578: * Close a file descriptor.
579: */
580: struct close_args {
581: int fd;
582: };
583: /* ARGSUSED */
584: int
585: close(p, uap, retval)
586: struct proc *p;
587: struct close_args *uap;
588: register_t *retval;
589: {
590: int fd = uap->fd;
591: register struct filedesc *fdp = p->p_fd;
592: register struct file *fp;
593:
594: if ((u_int)fd >= fdp->fd_nfiles ||
595: (fp = fdp->fd_ofiles[fd]) == NULL ||
596: (fdp->fd_ofileflags[fd] & UF_RESERVED))
597: return (EBADF);
598: _fdrelse(fdp, fd);
599: return (closef(fp, p));
600: }
601:
602: /*
603: * Return status information about a file descriptor.
604: */
605: struct fstat_args {
606: int fd;
607: struct stat *sb;
608: };
609: /* ARGSUSED */
610: int
611: fstat(p, uap, retval)
612: struct proc *p;
613: register struct fstat_args *uap;
614: register_t *retval;
615: {
616: int fd = uap->fd;
617: register struct filedesc *fdp = p->p_fd;
618: register struct file *fp;
619: struct stat ub;
620: int error;
621:
622: if ((u_int)fd >= fdp->fd_nfiles ||
623: (fp = fdp->fd_ofiles[fd]) == NULL ||
624: (fdp->fd_ofileflags[fd] & UF_RESERVED))
625: return (EBADF);
626: switch (fp->f_type) {
627:
628: case DTYPE_VNODE:
629: error = vn_stat((struct vnode *)fp->f_data, &ub, p);
630: break;
631:
632: case DTYPE_SOCKET:
633: error = soo_stat((struct socket *)fp->f_data, &ub);
634: break;
635:
636: default:
637: panic("fstat");
638: /*NOTREACHED*/
639: }
640: if (error == 0)
641: error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
642: sizeof (ub));
643: return (error);
644: }
645:
646: #if COMPAT_43
647: /*
648: * Return status information about a file descriptor.
649: */
650: struct ofstat_args {
651: int fd;
652: struct ostat *sb;
653: };
654: /* ARGSUSED */
655: ofstat(p, uap, retval)
656: struct proc *p;
657: register struct ofstat_args *uap;
658: register_t *retval;
659: {
660: int fd = uap->fd;
661: register struct filedesc *fdp = p->p_fd;
662: register struct file *fp;
663: struct stat ub;
664: struct ostat oub;
665: int error;
666:
667: if ((u_int)fd >= fdp->fd_nfiles ||
668: (fp = fdp->fd_ofiles[fd]) == NULL ||
669: (fdp->fd_ofileflags[fd] & UF_RESERVED))
670: return (EBADF);
671: switch (fp->f_type) {
672:
673: case DTYPE_VNODE:
674: error = vn_stat((struct vnode *)fp->f_data, &ub, p);
675: break;
676:
677: case DTYPE_SOCKET:
678: error = soo_stat((struct socket *)fp->f_data, &ub);
679: break;
680:
681: default:
682: panic("ofstat");
683: /*NOTREACHED*/
684: }
685: cvtstat(&ub, &oub);
686: if (error == 0)
687: error = copyout((caddr_t)&oub, (caddr_t)uap->sb,
688: sizeof (oub));
689: return (error);
690: }
691: #endif /* COMPAT_43 */
692:
693: /*
694: * Return pathconf information about a file descriptor.
695: */
696: struct fpathconf_args {
697: int fd;
698: int name;
699: };
700: /* ARGSUSED */
701: fpathconf(p, uap, retval)
702: struct proc *p;
703: register struct fpathconf_args *uap;
704: register_t *retval;
705: {
706: int fd = uap->fd;
707: struct filedesc *fdp = p->p_fd;
708: struct file *fp;
709: struct vnode *vp;
710:
711: if ((u_int)fd >= fdp->fd_nfiles ||
712: (fp = fdp->fd_ofiles[fd]) == NULL ||
713: (fdp->fd_ofileflags[fd] & UF_RESERVED))
714: return (EBADF);
715: switch (fp->f_type) {
716:
717: case DTYPE_SOCKET:
718: if (uap->name != _PC_PIPE_BUF)
719: return (EINVAL);
720: *retval = PIPE_BUF;
721: return (0);
722:
723: case DTYPE_VNODE:
724: vp = (struct vnode *)fp->f_data;
725: return (VOP_PATHCONF(vp, uap->name, retval));
726:
727: default:
728: panic("fpathconf");
729: }
730: /*NOTREACHED*/
731: }
732:
733: /*
734: * Allocate a file descriptor for the process.
735: */
736: int fdexpand;
737:
738: int
739: fdalloc(p, want, result)
740: struct proc *p;
741: int want;
742: int *result;
743: {
744: register struct filedesc *fdp = p->p_fd;
745: register int i;
746: int lim, last, nfiles, oldnfiles;
747: struct file **newofiles, **ofiles;
748: char *newofileflags, *ofileflags;
749:
750: /*
751: * Search for a free descriptor starting at the higher
752: * of want or fd_freefile. If that fails, consider
753: * expanding the ofile array.
754: */
755: lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
756: for (;;) {
757: last = min(fdp->fd_nfiles, lim);
758: if ((i = want) < fdp->fd_freefile)
759: i = fdp->fd_freefile;
760: ofiles = &fdp->fd_ofiles[i];
761: ofileflags = &fdp->fd_ofileflags[i];
762: for (; i < last; i++) {
763: if (*ofiles == NULL && !(*ofileflags & UF_RESERVED)) {
764: *ofileflags = UF_RESERVED;
765: if (i > fdp->fd_lastfile)
766: fdp->fd_lastfile = i;
767: if (want <= fdp->fd_freefile)
768: fdp->fd_freefile = i;
769: *result = i;
770: return (0);
771: }
772: ofiles++; ofileflags++;
773: }
774:
775: /*
776: * No space in current array. Expand?
777: */
778: if (fdp->fd_nfiles >= lim)
779: return (EMFILE);
780: if (fdp->fd_nfiles < NDEXTENT)
781: nfiles = NDEXTENT;
782: else
783: nfiles = 2 * fdp->fd_nfiles;
784: /* Enforce lim */
785: if (nfiles > lim)
786: nfiles = lim;
787: MALLOC_ZONE(newofiles, struct file **,
788: nfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
789: if (fdp->fd_nfiles >= nfiles) {
790: FREE_ZONE(newofiles, nfiles * OFILESIZE, M_OFILETABL);
791: continue;
792: }
793: newofileflags = (char *) &newofiles[nfiles];
794: /*
795: * Copy the existing ofile and ofileflags arrays
796: * and zero the new portion of each array.
797: */
798: oldnfiles = fdp->fd_nfiles;
799: (void) memcpy(newofiles, fdp->fd_ofiles,
800: oldnfiles * sizeof *fdp->fd_ofiles);
801: (void) memset(&newofiles[oldnfiles], 0,
802: (nfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
803:
804: (void) memcpy(newofileflags, fdp->fd_ofileflags,
805: oldnfiles * sizeof *fdp->fd_ofileflags);
806: (void) memset(&newofileflags[oldnfiles], 0,
807: (nfiles - oldnfiles) *
808: sizeof *fdp->fd_ofileflags);
809: ofiles = fdp->fd_ofiles;
810: fdp->fd_ofiles = newofiles;
811: fdp->fd_ofileflags = newofileflags;
812: fdp->fd_nfiles = nfiles;
813: FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
814: fdexpand++;
815: }
816: }
817:
818: /*
819: * Check to see whether n user file descriptors
820: * are available to the process p.
821: */
822: int
823: fdavail(p, n)
824: struct proc *p;
825: register int n;
826: {
827: register struct filedesc *fdp = p->p_fd;
828: register struct file **fpp;
829: register char *flags;
830: register int i, lim;
831:
832: lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
833: if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
834: return (1);
835: fpp = &fdp->fd_ofiles[fdp->fd_freefile];
836: flags = &fdp->fd_ofileflags[fdp->fd_freefile];
837: for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
838: if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
839: return (1);
840: return (0);
841: }
842:
843: void
844: fdrelse(p, fd)
845: struct proc *p;
846: int fd;
847: {
848: _fdrelse(p->p_fd, fd);
849: }
850:
851: int
852: fdgetf(p, fd, resultfp)
853: register struct proc *p;
854: register int fd;
855: struct file **resultfp;
856: {
857: register struct filedesc *fdp = p->p_fd;
858: struct file *fp;
859:
860: if ((u_int)fd >= fdp->fd_nfiles ||
861: (fp = fdp->fd_ofiles[fd]) == NULL ||
862: (fdp->fd_ofileflags[fd] & UF_RESERVED))
863: return (EBADF);
864:
865: if (resultfp)
866: *resultfp = fp;
867: return (0);
868: }
869:
870: /*
871: * Create a new open file structure and allocate
872: * a file decriptor for the process that refers to it.
873: */
874: int
875: falloc(p, resultfp, resultfd)
876: register struct proc *p;
877: struct file **resultfp;
878: int *resultfd;
879: {
880: register struct file *fp, *fq;
881: int error, i;
882:
883: if (error = fdalloc(p, 0, &i))
884: return (error);
885: if (nfiles >= maxfiles) {
886: tablefull("file");
887: return (ENFILE);
888: }
889: /*
890: * Allocate a new file descriptor.
891: * If the process has file descriptor zero open, add to the list
892: * of open files at that point, otherwise put it at the front of
893: * the list of open files.
894: */
895: nfiles++;
896: MALLOC_ZONE(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
897: bzero(fp, sizeof(struct file));
898: if (fq = p->p_fd->fd_ofiles[0]) {
899: LIST_INSERT_AFTER(fq, fp, f_list);
900: } else {
901: LIST_INSERT_HEAD(&filehead, fp, f_list);
902: }
903: p->p_fd->fd_ofiles[i] = fp;
904: fp->f_count = 1;
905: fp->f_cred = p->p_ucred;
906: crhold(fp->f_cred);
907: if (resultfp)
908: *resultfp = fp;
909: if (resultfd)
910: *resultfd = i;
911: return (0);
912: }
913:
914: /*
915: * Free a file structure.
916: */
917: void
918: ffree(fp)
919: register struct file *fp;
920: {
921: register struct file *fq;
922:
923: LIST_REMOVE(fp, f_list);
924: crfree(fp->f_cred);
925: #if DIAGNOSTIC
926: fp->f_count = 0;
927: #endif
928: nfiles--;
929: FREE_ZONE(fp, sizeof *fp, M_FILE);
930: }
931:
932: void
933: fdexec(p)
934: struct proc *p;
935: {
936: register struct filedesc *fdp = p->p_fd;
937: register int i = fdp->fd_lastfile;
938: register struct file **fpp = &fdp->fd_ofiles[i];
939: register char *flags = &fdp->fd_ofileflags[i];
940:
941: while (i >= 0) {
942: if ((*flags & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
943: register struct file *fp = *fpp;
944:
945: *fpp = NULL; *flags = 0;
946: if (i == fdp->fd_lastfile && i > 0)
947: fdp->fd_lastfile--;
948: closef(fp, p);
949: }
950: else
951: *flags &= ~UF_MAPPED;
952:
953: i--; fpp--; flags--;
954: }
955: }
956:
957: /*
958: * Copy a filedesc structure.
959: */
960: struct filedesc *
961: fdcopy(p)
962: struct proc *p;
963: {
964: register struct filedesc *newfdp, *fdp = p->p_fd;
965: register int i;
966:
967: MALLOC_ZONE(newfdp, struct filedesc *,
968: sizeof *newfdp, M_FILEDESC, M_WAITOK);
969: (void) memcpy(newfdp, fdp, sizeof *newfdp);
970: VREF(newfdp->fd_cdir);
971: if (newfdp->fd_rdir)
972: VREF(newfdp->fd_rdir);
973: newfdp->fd_refcnt = 1;
974:
975: /*
976: * If the number of open files fits in the internal arrays
977: * of the open file structure, use them, otherwise allocate
978: * additional memory for the number of descriptors currently
979: * in use.
980: */
981: if (newfdp->fd_lastfile < NDFILE)
982: i = NDFILE;
983: else {
984: /*
985: * Compute the smallest multiple of NDEXTENT needed
986: * for the file descriptors currently in use,
987: * allowing the table to shrink.
988: */
989: i = newfdp->fd_nfiles;
990: while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
991: i /= 2;
992: }
993: MALLOC_ZONE(newfdp->fd_ofiles, struct file **,
994: i * OFILESIZE, M_OFILETABL, M_WAITOK);
995: newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
996: newfdp->fd_nfiles = i;
997: if (fdp->fd_nfiles > 0) {
998: register struct file **fpp;
999: register char *flags;
1000:
1001: (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
1002: i * sizeof *fdp->fd_ofiles);
1003: (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
1004: i * sizeof *fdp->fd_ofileflags);
1005:
1006: fpp = newfdp->fd_ofiles;
1007: flags = newfdp->fd_ofileflags;
1008: for (i = newfdp->fd_lastfile; i-- >= 0; fpp++, flags++)
1009: if (*fpp != NULL && !(*flags & UF_RESERVED))
1010: (*fpp)->f_count++;
1011: else {
1012: *fpp = NULL; *flags = 0;
1013: }
1014: }
1015: else
1016: (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
1017:
1018: return (newfdp);
1019: }
1020:
1021: /*
1022: * Release a filedesc structure.
1023: */
1024: void
1025: fdfree(p)
1026: struct proc *p;
1027: {
1028: register struct filedesc *fdp;
1029: register struct file **fpp;
1030: register int i;
1031:
1032: if ((fdp = p->p_fd) == NULL)
1033: return;
1034: if (--fdp->fd_refcnt > 0)
1035: return;
1036: p->p_fd = NULL;
1037: if (fdp->fd_nfiles > 0) {
1038: fpp = fdp->fd_ofiles;
1039: for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
1040: if (*fpp)
1041: (void) closef(*fpp, p);
1042: FREE_ZONE(fdp->fd_ofiles,
1043: fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
1044: }
1045: vrele(fdp->fd_cdir);
1046: if (fdp->fd_rdir)
1047: vrele(fdp->fd_rdir);
1048: FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
1049: }
1050:
1051: /*
1052: * Internal form of close.
1053: * Decrement reference count on file structure.
1054: * Note: p may be NULL when closing a file
1055: * that was being passed in a message.
1056: */
1057: int
1058: closef(fp, p)
1059: register struct file *fp;
1060: register struct proc *p;
1061: {
1062: struct vnode *vp;
1063: struct flock lf;
1064: int error;
1065:
1066: if (fp == NULL)
1067: return (0);
1068: /*
1069: * POSIX record locking dictates that any close releases ALL
1070: * locks owned by this process. This is handled by setting
1071: * a flag in the unlock to free ONLY locks obeying POSIX
1072: * semantics, and not to free BSD-style file locks.
1073: * If the descriptor was in a message, POSIX-style locks
1074: * aren't passed with the descriptor.
1075: */
1076: if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
1077: lf.l_whence = SEEK_SET;
1078: lf.l_start = 0;
1079: lf.l_len = 0;
1080: lf.l_type = F_UNLCK;
1081: vp = (struct vnode *)fp->f_data;
1082: (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1083: }
1084: if (--fp->f_count > 0)
1085: return (0);
1086: if (fp->f_count < 0)
1087: panic("closef: count < 0");
1088: if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1089: lf.l_whence = SEEK_SET;
1090: lf.l_start = 0;
1091: lf.l_len = 0;
1092: lf.l_type = F_UNLCK;
1093: vp = (struct vnode *)fp->f_data;
1094: (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1095: }
1096: if (fp->f_ops)
1097: error = (*fp->f_ops->fo_close)(fp, p);
1098: else
1099: error = 0;
1100: ffree(fp);
1101: return (error);
1102: }
1103:
1104: /*
1105: * Apply an advisory lock on a file descriptor.
1106: *
1107: * Just attempt to get a record lock of the requested type on
1108: * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1109: */
1110: struct flock_args {
1111: int fd;
1112: int how;
1113: };
1114: /* ARGSUSED */
1115: int
1116: flock(p, uap, retval)
1117: struct proc *p;
1118: register struct flock_args *uap;
1119: register_t *retval;
1120: {
1121: int fd = uap->fd;
1122: int how = uap->how;
1123: register struct filedesc *fdp = p->p_fd;
1124: register struct file *fp;
1125: struct vnode *vp;
1126: struct flock lf;
1127:
1128: if ((u_int)fd >= fdp->fd_nfiles ||
1129: (fp = fdp->fd_ofiles[fd]) == NULL ||
1130: (fdp->fd_ofileflags[fd] & UF_RESERVED))
1131: return (EBADF);
1132: if (fp->f_type != DTYPE_VNODE)
1133: return (EOPNOTSUPP);
1134: vp = (struct vnode *)fp->f_data;
1135: lf.l_whence = SEEK_SET;
1136: lf.l_start = 0;
1137: lf.l_len = 0;
1138: if (how & LOCK_UN) {
1139: lf.l_type = F_UNLCK;
1140: fp->f_flag &= ~FHASLOCK;
1141: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
1142: }
1143: if (how & LOCK_EX)
1144: lf.l_type = F_WRLCK;
1145: else if (how & LOCK_SH)
1146: lf.l_type = F_RDLCK;
1147: else
1148: return (EBADF);
1149: fp->f_flag |= FHASLOCK;
1150: if (how & LOCK_NB)
1151: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
1152: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
1153: }
1154:
1155: /*
1156: * File Descriptor pseudo-device driver (/dev/fd/).
1157: *
1158: * Opening minor device N dup()s the file (if any) connected to file
1159: * descriptor N belonging to the calling process. Note that this driver
1160: * consists of only the ``open()'' routine, because all subsequent
1161: * references to this file will be direct to the other driver.
1162: */
1163: /* ARGSUSED */
1164: int
1165: fdopen(dev, mode, type, p)
1166: dev_t dev;
1167: int mode, type;
1168: struct proc *p;
1169: {
1170:
1171: /*
1172: * XXX Kludge: set curproc->p_dupfd to contain the value of the
1173: * the file descriptor being sought for duplication. The error
1174: * return ensures that the vnode for this device will be released
1175: * by vn_open. Open will detect this special error and take the
1176: * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1177: * will simply report the error.
1178: */
1179: p->p_dupfd = minor(dev);
1180: return (ENODEV);
1181: }
1182:
1183: /*
1184: * Duplicate the specified descriptor to a free descriptor.
1185: */
1186: int
1187: dupfdopen(fdp, indx, dfd, mode, error)
1188: register struct filedesc *fdp;
1189: register int indx, dfd;
1190: int mode;
1191: int error;
1192: {
1193: register struct file *wfp;
1194: struct file *fp;
1195:
1196: /*
1197: * If the to-be-dup'd fd number is greater than the allowed number
1198: * of file descriptors, or the fd to be dup'd has already been
1199: * closed, reject. Note, check for new == old is necessary as
1200: * falloc could allocate an already closed to-be-dup'd descriptor
1201: * as the new descriptor.
1202: */
1203: fp = fdp->fd_ofiles[indx];
1204: if ((u_int)dfd >= fdp->fd_nfiles ||
1205: (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
1206: (fdp->fd_ofileflags[dfd] & UF_RESERVED))
1207: return (EBADF);
1208:
1209: /*
1210: * There are two cases of interest here.
1211: *
1212: * For ENODEV simply dup (dfd) to file descriptor
1213: * (indx) and return.
1214: *
1215: * For ENXIO steal away the file structure from (dfd) and
1216: * store it in (indx). (dfd) is effectively closed by
1217: * this operation.
1218: *
1219: * Any other error code is just returned.
1220: */
1221: switch (error) {
1222: case ENODEV:
1223: /*
1224: * Check that the mode the file is being opened for is a
1225: * subset of the mode of the existing descriptor.
1226: */
1227: if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1228: return (EACCES);
1229: wfp->f_count++;
1230: if (indx > fdp->fd_lastfile)
1231: fdp->fd_lastfile = indx;;
1232: fdp->fd_ofiles[indx] = wfp;
1233: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1234: return (0);
1235:
1236: case ENXIO:
1237: /*
1238: * Steal away the file pointer from dfd, and stuff it into indx.
1239: */
1240: if (indx > fdp->fd_lastfile)
1241: fdp->fd_lastfile = indx;;
1242: fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
1243: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1244: _fdrelse(fdp, dfd);
1245: return (0);
1246:
1247: default:
1248: return (error);
1249: }
1250: /* NOTREACHED */
1251: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.