|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
23: /*
24: * Copyright (c) 1982, 1986, 1989, 1991, 1993
25: * The Regents of the University of California. All rights reserved.
26: * (c) UNIX System Laboratories, Inc.
27: * All or some portions of this file are derived from material licensed
28: * to the University of California by American Telephone and Telegraph
29: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30: * the permission of UNIX System Laboratories, Inc.
31: *
32: * Redistribution and use in source and binary forms, with or without
33: * modification, are permitted provided that the following conditions
34: * are met:
35: * 1. Redistributions of source code must retain the above copyright
36: * notice, this list of conditions and the following disclaimer.
37: * 2. Redistributions in binary form must reproduce the above copyright
38: * notice, this list of conditions and the following disclaimer in the
39: * documentation and/or other materials provided with the distribution.
40: * 3. All advertising materials mentioning features or use of this software
41: * must display the following acknowledgement:
42: * This product includes software developed by the University of
43: * California, Berkeley and its contributors.
44: * 4. Neither the name of the University nor the names of its contributors
45: * may be used to endorse or promote products derived from this software
46: * without specific prior written permission.
47: *
48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58: * SUCH DAMAGE.
59: *
60: * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
61: *
62: * History:
63: * CHW 8/5/98 Added F_SETSIZE command to truncate without
64: * zero filling space
65: * CHW 7/6/98 Updated Preallocate command to take a structure
66: * and return output.
67: * CHW 6/25/98 Fixed a bug in the lock call in fcntl
68: * Preallocate command
69: */
70:
71: #include <sys/param.h>
72: #include <sys/systm.h>
73: #include <sys/filedesc.h>
74: #include <sys/kernel.h>
75: #include <sys/vnode.h>
76: #include <sys/proc.h>
77: #include <sys/file.h>
78: #include <sys/socket.h>
79: #include <sys/socketvar.h>
80: #include <sys/stat.h>
81: #include <sys/ioctl.h>
82: #include <sys/fcntl.h>
83: #include <sys/malloc.h>
84: #include <sys/syslog.h>
85: #include <sys/unistd.h>
86: #include <sys/resourcevar.h>
87:
88: #include <sys/mount.h>
89:
90: /*
91: * Descriptor management.
92: */
93: struct filelist filehead; /* head of list of open files */
94: int nfiles; /* actual number of open files */
95:
96: /*
97: * System calls on descriptors.
98: */
99: /* ARGSUSED */
100: int
101: getdtablesize(p, uap, retval)
102: struct proc *p;
103: void *uap;
104: register_t *retval;
105: {
106:
107: *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
108: return (0);
109: }
110:
111: /* ARGSUSED */
112: int
113: ogetdtablesize(p, uap, retval)
114: struct proc *p;
115: void *uap;
116: register_t *retval;
117: {
118:
119: *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, NOFILE);
120: return (0);
121: }
122:
123: static __inline__
124: void _fdrelse(fdp, fd)
125: register struct filedesc *fdp;
126: register int fd;
127: {
128: if (fd < fdp->fd_freefile)
129: fdp->fd_freefile = fd;
130: #if DIAGNOSTIC
131: if (fd > fdp->fd_lastfile)
132: panic("fdrelse: fd_lastfile inconsistent");
133: #endif
134: fdp->fd_ofiles[fd] = NULL;
135: fdp->fd_ofileflags[fd] = 0;
136: while ((fd = fdp->fd_lastfile) > 0 &&
137: fdp->fd_ofiles[fd] == NULL &&
138: !(fdp->fd_ofileflags[fd] & UF_RESERVED))
139: fdp->fd_lastfile--;
140: }
141:
142: /*
143: * Duplicate a file descriptor.
144: */
145: struct dup_args {
146: u_int fd;
147: };
148: /* ARGSUSED */
149: int
150: dup(p, uap, retval)
151: struct proc *p;
152: struct dup_args *uap;
153: register_t *retval;
154: {
155: register struct filedesc *fdp = p->p_fd;
156: register int old = uap->fd;
157: int new, error;
158:
159: if ((u_int)old >= fdp->fd_nfiles ||
160: fdp->fd_ofiles[old] == NULL ||
161: (fdp->fd_ofileflags[old] & UF_RESERVED))
162: return (EBADF);
163: if (error = fdalloc(p, 0, &new))
164: return (error);
165: return (finishdup(fdp, old, new, retval));
166: }
167:
168: /*
169: * Duplicate a file descriptor to a particular value.
170: */
171: struct dup2_args {
172: u_int from;
173: u_int to;
174: };
175: /* ARGSUSED */
176: int
177: dup2(p, uap, retval)
178: struct proc *p;
179: struct dup2_args *uap;
180: register_t *retval;
181: {
182: register struct filedesc *fdp = p->p_fd;
183: register int old = uap->from, new = uap->to;
184: int i, error;
185:
186: if ((u_int)old >= fdp->fd_nfiles ||
187: fdp->fd_ofiles[old] == NULL ||
188: (fdp->fd_ofileflags[old] & UF_RESERVED) ||
189: (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
190: (u_int)new >= maxfiles)
191: return (EBADF);
192: if (old == new) {
193: *retval = new;
194: return (0);
195: }
196: if ((u_int)new >= fdp->fd_nfiles) {
197: if (error = fdalloc(p, new, &i))
198: return (error);
199: if (new != i) {
200: _fdrelse(fdp, i);
201: goto closeit;
202: }
203: }
204: else {
205: struct file **fpp;
206: char flags;
207: closeit:
208: if ((flags = fdp->fd_ofileflags[new]) & UF_RESERVED)
209: return (EBADF);
210: fdp->fd_ofileflags[new] = (flags & ~UF_MAPPED) | UF_RESERVED;
211: /*
212: * dup2() must succeed even if the close has an error.
213: */
214: if (*(fpp = &fdp->fd_ofiles[new])) {
215: struct file *fp = *fpp;
216:
217: *fpp = NULL; (void) closef(fp, p);
218: }
219: }
220: return (finishdup(fdp, old, new, retval));
221: }
222:
223: /*
224: * The file control system call.
225: */
226: struct fcntl_args {
227: int fd;
228: int cmd;
229: int arg;
230: };
231: /* ARGSUSED */
232: int
233: fcntl(p, uap, retval)
234: struct proc *p;
235: register struct fcntl_args *uap;
236: register_t *retval;
237: {
238: int fd = uap->fd;
239: register struct filedesc *fdp = p->p_fd;
240: register struct file *fp;
241: register char *pop;
242: struct vnode *vp;
243: int i, tmp, error, error2, flg = F_POSIX;
244: struct flock fl;
245: fstore_t alloc_struct; /* structure for allocate command */
246: u_int32_t alloc_flags = 0;
247: off_t offset; /* used for F_SETSIZE */
248: int newmin;
249: struct radvisory ra_struct;
250: fbootstraptransfer_t fbt_struct; /* for F_READBOOTSTRAP and F_WRITEBOOTSTRAP */
251:
252: if ((u_int)fd >= fdp->fd_nfiles ||
253: (fp = fdp->fd_ofiles[fd]) == NULL ||
254: (fdp->fd_ofileflags[fd] & UF_RESERVED))
255: return (EBADF);
256: pop = &fdp->fd_ofileflags[fd];
257: switch (uap->cmd) {
258:
259: case F_DUPFD:
260: newmin = (long)uap->arg;
261: if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
262: (u_int)newmin >= maxfiles)
263: return (EINVAL);
264: if (error = fdalloc(p, newmin, &i))
265: return (error);
266: return (finishdup(fdp, fd, i, retval));
267:
268: case F_GETFD:
269: *retval = (*pop & UF_EXCLOSE)? 1 : 0;
270: return (0);
271:
272: case F_SETFD:
273: *pop = (*pop &~ UF_EXCLOSE) |
274: ((long)(uap->arg) & 1)? UF_EXCLOSE : 0;
275: return (0);
276:
277: case F_GETFL:
278: *retval = OFLAGS(fp->f_flag);
279: return (0);
280:
281: case F_SETFL:
282: fp->f_flag &= ~FCNTLFLAGS;
283: fp->f_flag |= FFLAGS((long)uap->arg) & FCNTLFLAGS;
284: tmp = fp->f_flag & FNONBLOCK;
285: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
286: if (error)
287: return (error);
288: tmp = fp->f_flag & FASYNC;
289: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
290: if (!error)
291: return (0);
292: fp->f_flag &= ~FNONBLOCK;
293: tmp = 0;
294: (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
295: return (error);
296:
297: case F_GETOWN:
298: if (fp->f_type == DTYPE_SOCKET) {
299: *retval = ((struct socket *)fp->f_data)->so_pgid;
300: return (0);
301: }
302: error = (*fp->f_ops->fo_ioctl)
303: (fp, (int)TIOCGPGRP, (caddr_t)retval, p);
304: *retval = -*retval;
305: return (error);
306:
307: case F_SETOWN:
308: if (fp->f_type == DTYPE_SOCKET) {
309: ((struct socket *)fp->f_data)->so_pgid =
310: (long)uap->arg;
311: return (0);
312: }
313: if ((long)uap->arg <= 0) {
314: uap->arg = (void *)(-(long)(uap->arg));
315: } else {
316: struct proc *p1 = pfind((long)uap->arg);
317: if (p1 == 0)
318: return (ESRCH);
319: uap->arg = (void *)(long)p1->p_pgrp->pg_id;
320: }
321: return ((*fp->f_ops->fo_ioctl)
322: (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
323:
324: case F_SETLKW:
325: flg |= F_WAIT;
326: /* Fall into F_SETLK */
327:
328: case F_SETLK:
329: if (fp->f_type != DTYPE_VNODE)
330: return (EBADF);
331: vp = (struct vnode *)fp->f_data;
332: /* Copy in the lock structure */
333: error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
334: sizeof (fl));
335: if (error)
336: return (error);
337: if (fl.l_whence == SEEK_CUR)
338: fl.l_start += fp->f_offset;
339: switch (fl.l_type) {
340:
341: case F_RDLCK:
342: if ((fp->f_flag & FREAD) == 0)
343: return (EBADF);
344: p->p_flag |= P_ADVLOCK;
345: return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
346:
347: case F_WRLCK:
348: if ((fp->f_flag & FWRITE) == 0)
349: return (EBADF);
350: p->p_flag |= P_ADVLOCK;
351: return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
352:
353: case F_UNLCK:
354: return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
355: F_POSIX));
356:
357: default:
358: return (EINVAL);
359: }
360:
361: case F_GETLK:
362: if (fp->f_type != DTYPE_VNODE)
363: return (EBADF);
364: vp = (struct vnode *)fp->f_data;
365: /* Copy in the lock structure */
366: error = copyin((caddr_t)uap->arg, (caddr_t)&fl,
367: sizeof (fl));
368: if (error)
369: return (error);
370: if (fl.l_whence == SEEK_CUR)
371: fl.l_start += fp->f_offset;
372: if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
373: return (error);
374: return (copyout((caddr_t)&fl, (caddr_t)uap->arg,
375: sizeof (fl)));
376:
377: case F_PREALLOCATE:
378:
379: /* Copy in the structure */
380:
381: error = copyin((caddr_t)uap->arg, (caddr_t)&alloc_struct,
382: sizeof (alloc_struct));
383:
384: if (error)
385: return (error);
386:
387: /* now set the space allocated to 0 and pass it out in
388: case we get a parameter checking error */
389:
390: alloc_struct.fst_bytesalloc = 0;
391:
392: error = copyout((caddr_t)&alloc_struct, (caddr_t)uap->arg,
393: sizeof (alloc_struct));
394:
395: if (error)
396: return(error);
397:
398: /* First make sure that we have write permission */
399:
400: if ((fp->f_flag & FWRITE) == 0)
401: return (EBADF);
402:
403:
404: /* Do some simple parameter checking */
405:
406:
407: /* set up the flags */
408:
409: alloc_flags |= PREALLOCATE;
410:
411: if (alloc_struct.fst_flags & F_ALLOCATECONTIG) {
412: alloc_flags |= ALLOCATECONTIG;
413: }
414:
415: if (alloc_struct.fst_flags & F_ALLOCATEALL) {
416: alloc_flags |= ALLOCATEALL;
417: }
418:
419: /* Do any position mode specific stuff. The only */
420: /* position mode supported now is PEOFPOSMODE */
421:
422: switch (alloc_struct.fst_posmode) {
423:
424: case F_PEOFPOSMODE:
425:
426: if ((alloc_struct.fst_offset != 0) ||
427: (alloc_struct.fst_length < 0))
428: return (EINVAL);
429:
430: alloc_flags |= ALLOCATEFROMPEOF;
431: break;
432:
433: default:
434:
435: return(EINVAL);
436:
437: }
438:
439:
440: /* Now lock the vnode and call allocate to get the space */
441:
442: vp = (struct vnode *)fp->f_data;
443:
444: VOP_LOCK(vp,LK_EXCLUSIVE,p);
445: error = VOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
446: &alloc_struct.fst_bytesalloc,fp->f_cred,p);
447: VOP_UNLOCK(vp,0,p);
448:
449: if (error2 = (copyout((caddr_t)&alloc_struct, (caddr_t)uap->arg,
450: sizeof (alloc_struct)))) {
451: if (error) {
452: return(error);
453: } else {
454: return(error2);
455: }
456: }
457:
458: return(error);
459:
460: case F_SETSIZE:
461:
462: /* Copy in the structure */
463:
464: error = copyin((caddr_t)uap->arg, (caddr_t)&offset,
465: sizeof (off_t));
466:
467: if (error)
468: return (error);
469:
470:
471: /* First make sure that we are root. Growing a file */
472: /* without zero filling the data is a security hole */
473: /* root would have access anyway so we'll allow it */
474:
475: if (!is_suser()) {
476: return (EACCES);
477: }
478:
479: /* Now lock the vnode and call allocate to get the space */
480:
481: vp = (struct vnode *)fp->f_data;
482:
483: VOP_LOCK(vp,LK_EXCLUSIVE,p);
484: error = VOP_TRUNCATE(vp,offset,IO_NOZEROFILL,fp->f_cred,p);
485: VOP_UNLOCK(vp,0,p);
486:
487: return(error);
488:
489: case F_RDAHEAD:
490: vp = (struct vnode *)fp->f_data;
491:
492: simple_lock(&vp->v_interlock);
493: if (uap->arg)
494: vp->v_flag &= ~VRAOFF;
495: else
496: vp->v_flag |= VRAOFF;
497: simple_unlock(&vp->v_interlock);
498:
499: return (0);
500:
501: case F_RDADVISE:
502: vp = (struct vnode *)fp->f_data;
503:
504: if (error = copyin((caddr_t)uap->arg, (caddr_t)&ra_struct, sizeof (ra_struct)))
505: return(error);
506: return (VOP_IOCTL(vp, 1, &ra_struct, 0, fp->f_cred, p));
507:
508: case F_READBOOTSTRAP:
509: case F_WRITEBOOTSTRAP:
510:
511: /* Copy in the structure */
512:
513: error = copyin((caddr_t)uap->arg, (caddr_t)&fbt_struct,
514: sizeof (fbt_struct));
515:
516: if (error)
517: return (error);
518:
519:
520: if (uap->cmd == F_WRITEBOOTSTRAP) {
521: /* First make sure that we are root. Updating the */
522: /* bootstrap on a disk could be a security hole */
523:
524: if (!is_suser()) {
525: return (EACCES);
526: }
527: };
528:
529: /* Now lock the vnode and call VOP_IOCTL to handle the I/O: */
530:
531: vp = (struct vnode *)fp->f_data;
532: if (vp->v_tag != VT_HFS) {
533: error = EINVAL;
534: } else {
535: VOP_LOCK(vp,LK_EXCLUSIVE,p);
536: error = VOP_IOCTL(vp, (uap->cmd == F_WRITEBOOTSTRAP) ? 3 : 2, &fbt_struct, 0, fp->f_cred, p);
537: VOP_UNLOCK(vp,0,p);
538: };
539:
540: return(error);
541:
542:
543: default:
544: return (EINVAL);
545: }
546: /* NOTREACHED */
547: }
548:
549: /*
550: * Common code for dup, dup2, and fcntl(F_DUPFD).
551: */
552: int
553: finishdup(fdp, old, new, retval)
554: register struct filedesc *fdp;
555: register int old, new;
556: register_t *retval;
557: {
558: register struct file *fp;
559:
560: if ((fp = fdp->fd_ofiles[old]) == NULL ||
561: (fdp->fd_ofileflags[old] & UF_RESERVED)) {
562: _fdrelse(fdp, new);
563: return (EBADF);
564: }
565: fdp->fd_ofiles[new] = fp;
566: fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
567: if (++fp->f_count <= 0)
568: panic("finishdup f_count");
569: if (new > fdp->fd_lastfile)
570: fdp->fd_lastfile = new;
571: *retval = new;
572: return (0);
573: }
574:
575: /*
576: * Close a file descriptor.
577: */
578: struct close_args {
579: int fd;
580: };
581: /* ARGSUSED */
582: int
583: close(p, uap, retval)
584: struct proc *p;
585: struct close_args *uap;
586: register_t *retval;
587: {
588: int fd = uap->fd;
589: register struct filedesc *fdp = p->p_fd;
590: register struct file *fp;
591:
592: if ((u_int)fd >= fdp->fd_nfiles ||
593: (fp = fdp->fd_ofiles[fd]) == NULL ||
594: (fdp->fd_ofileflags[fd] & UF_RESERVED))
595: return (EBADF);
596: _fdrelse(fdp, fd);
597: return (closef(fp, p));
598: }
599:
600: /*
601: * Return status information about a file descriptor.
602: */
603: struct fstat_args {
604: int fd;
605: struct stat *sb;
606: };
607: /* ARGSUSED */
608: int
609: fstat(p, uap, retval)
610: struct proc *p;
611: register struct fstat_args *uap;
612: register_t *retval;
613: {
614: int fd = uap->fd;
615: register struct filedesc *fdp = p->p_fd;
616: register struct file *fp;
617: struct stat ub;
618: int error;
619:
620: if ((u_int)fd >= fdp->fd_nfiles ||
621: (fp = fdp->fd_ofiles[fd]) == NULL ||
622: (fdp->fd_ofileflags[fd] & UF_RESERVED))
623: return (EBADF);
624: switch (fp->f_type) {
625:
626: case DTYPE_VNODE:
627: error = vn_stat((struct vnode *)fp->f_data, &ub, p);
628: break;
629:
630: case DTYPE_SOCKET:
631: error = soo_stat((struct socket *)fp->f_data, &ub);
632: break;
633:
634: case DTYPE_PSXSHM:
635: error = pshm_stat((void *)fp->f_data, &ub);
636: break;
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;
923: struct ucred *cred;
924:
925: LIST_REMOVE(fp, f_list);
926: cred = fp->f_cred;
927: if (cred != NOCRED) {
928: fp->f_cred = NOCRED;
929: crfree(cred);
930: }
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++)
1015: if (*fpp != NULL && !(*flags & UF_RESERVED)) {
1016: if (++(*fpp)->f_count <= 0)
1017: panic("fdcopy f_count");
1018: } else {
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);
1236: if (++wfp->f_count <= 0)
1237: panic("dupfdopen f_count");
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: }
1260:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.