|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)kern_descrip.c 7.16 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "user.h"
26: #include "kernel.h"
27: #include "vnode.h"
28: #include "proc.h"
29: #include "file.h"
30: #include "socket.h"
31: #include "socketvar.h"
32: #include "stat.h"
33: #include "ioctl.h"
34:
35: /*
36: * Descriptor management.
37: */
38:
39: /*
40: * System calls on descriptors.
41: */
42: /* ARGSUSED */
43: getdtablesize(p, uap, retval)
44: struct proc *p;
45: struct args *uap;
46: int *retval;
47: {
48:
49: *retval = NOFILE;
50: return (0);
51: }
52:
53: /*
54: * Duplicate a file descriptor.
55: */
56: /* ARGSUSED */
57: dup(p, uap, retval)
58: struct proc *p;
59: struct args {
60: int i;
61: } *uap;
62: int *retval;
63: {
64: struct file *fp;
65: int fd, error;
66:
67: /*
68: * XXX Compatibility
69: */
70: if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); }
71:
72: if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
73: return (EBADF);
74: if (error = ufalloc(0, &fd))
75: return (error);
76: u.u_ofile[fd] = fp;
77: u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE;
78: fp->f_count++;
79: if (fd > u.u_lastfile)
80: u.u_lastfile = fd;
81: *retval = fd;
82: return (0);
83: }
84:
85: /*
86: * Duplicate a file descriptor to a particular value.
87: */
88: /* ARGSUSED */
89: dup2(p, uap, retval)
90: struct proc *p;
91: register struct args {
92: int i;
93: int j;
94: } *uap;
95: int *retval;
96: {
97: register struct file *fp;
98: int error;
99:
100: if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
101: return (EBADF);
102: if (uap->j < 0 || uap->j >= NOFILE)
103: return (EBADF);
104: *retval = uap->j;
105: if (uap->i == uap->j)
106: return (0);
107: if (u.u_ofile[uap->j]) {
108: if (u.u_pofile[uap->j] & UF_MAPPED)
109: munmapfd(uap->j);
110: error = closef(u.u_ofile[uap->j]);
111: }
112: u.u_ofile[uap->j] = fp;
113: u.u_pofile[uap->j] = u.u_pofile[uap->i] &~ UF_EXCLOSE;
114: fp->f_count++;
115: if (uap->j > u.u_lastfile)
116: u.u_lastfile = uap->j;
117: /*
118: * dup2() must suceed even though the close had an error.
119: */
120: error = 0; /* XXX */
121: return (error);
122: }
123:
124: /*
125: * The file control system call.
126: */
127: /* ARGSUSED */
128: fcntl(p, uap, retval)
129: struct proc *p;
130: register struct args {
131: int fdes;
132: int cmd;
133: int arg;
134: } *uap;
135: int *retval;
136: {
137: register struct file *fp;
138: register char *pop;
139: int i, error;
140:
141: if ((unsigned)uap->fdes >= NOFILE ||
142: (fp = u.u_ofile[uap->fdes]) == NULL)
143: return (EBADF);
144: pop = &u.u_pofile[uap->fdes];
145: switch(uap->cmd) {
146: case F_DUPFD:
147: if (uap->arg < 0 || uap->arg >= NOFILE)
148: return (EINVAL);
149: if (error = ufalloc(uap->arg, &i))
150: return (error);
151: u.u_ofile[i] = fp;
152: u.u_pofile[i] = *pop &~ UF_EXCLOSE;
153: fp->f_count++;
154: if (i > u.u_lastfile)
155: u.u_lastfile = i;
156: *retval = i;
157: return (0);
158:
159: case F_GETFD:
160: *retval = *pop & 1;
161: return (0);
162:
163: case F_SETFD:
164: *pop = (*pop &~ 1) | (uap->arg & 1);
165: return (0);
166:
167: case F_GETFL:
168: *retval = fp->f_flag + FOPEN;
169: return (0);
170:
171: case F_SETFL:
172: fp->f_flag &= FCNTLCANT;
173: fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
174: if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY))
175: return (error);
176: if (error = fset(fp, FASYNC, fp->f_flag & FASYNC))
177: (void) fset(fp, FNDELAY, 0);
178: return (error);
179:
180: case F_GETOWN:
181: return (fgetown(fp, retval));
182:
183: case F_SETOWN:
184: return (fsetown(fp, uap->arg));
185:
186: default:
187: return (EINVAL);
188: }
189: /* NOTREACHED */
190: }
191:
192: fset(fp, bit, value)
193: struct file *fp;
194: int bit, value;
195: {
196:
197: if (value)
198: fp->f_flag |= bit;
199: else
200: fp->f_flag &= ~bit;
201: return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
202: (caddr_t)&value));
203: }
204:
205: fgetown(fp, valuep)
206: struct file *fp;
207: int *valuep;
208: {
209: int error;
210:
211: switch (fp->f_type) {
212:
213: case DTYPE_SOCKET:
214: *valuep = ((struct socket *)fp->f_data)->so_pgid;
215: return (0);
216:
217: default:
218: error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
219: *valuep = -*valuep;
220: return (error);
221: }
222: }
223:
224: fsetown(fp, value)
225: struct file *fp;
226: int value;
227: {
228:
229: if (fp->f_type == DTYPE_SOCKET) {
230: ((struct socket *)fp->f_data)->so_pgid = value;
231: return (0);
232: }
233: if (value > 0) {
234: struct proc *p = pfind(value);
235: if (p == 0)
236: return (ESRCH);
237: value = p->p_pgrp->pg_id;
238: } else
239: value = -value;
240: return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
241: }
242:
243: fioctl(fp, cmd, value)
244: struct file *fp;
245: int cmd;
246: caddr_t value;
247: {
248:
249: return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
250: }
251:
252: /*
253: * Close a file descriptor.
254: */
255: /* ARGSUSED */
256: close(p, uap, retval)
257: struct proc *p;
258: struct args {
259: int fdes;
260: } *uap;
261: int *retval;
262: {
263: register struct file *fp;
264: register u_char *pf;
265:
266: if ((unsigned)uap->fdes >= NOFILE ||
267: (fp = u.u_ofile[uap->fdes]) == NULL)
268: return (EBADF);
269: pf = (u_char *)&u.u_pofile[uap->fdes];
270: if (*pf & UF_MAPPED)
271: munmapfd(uap->fdes);
272: u.u_ofile[uap->fdes] = NULL;
273: while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
274: u.u_lastfile--;
275: *pf = 0;
276: return (closef(fp));
277: }
278:
279: /*
280: * Return status information about a file descriptor.
281: */
282: /* ARGSUSED */
283: fstat(p, uap, retval)
284: struct proc *p;
285: register struct args {
286: int fdes;
287: struct stat *sb;
288: } *uap;
289: int *retval;
290: {
291: register struct file *fp;
292: struct stat ub;
293: int error;
294:
295: if ((unsigned)uap->fdes >= NOFILE ||
296: (fp = u.u_ofile[uap->fdes]) == NULL)
297: return (EBADF);
298: switch (fp->f_type) {
299:
300: case DTYPE_VNODE:
301: error = vn_stat((struct vnode *)fp->f_data, &ub);
302: break;
303:
304: case DTYPE_SOCKET:
305: error = soo_stat((struct socket *)fp->f_data, &ub);
306: break;
307:
308: default:
309: panic("fstat");
310: /*NOTREACHED*/
311: }
312: if (error == 0)
313: error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
314: return (error);
315: }
316:
317: /*
318: * Allocate a user file descriptor.
319: */
320: ufalloc(want, result)
321: register int want;
322: int *result;
323: {
324:
325: for (; want < NOFILE; want++) {
326: if (u.u_ofile[want] == NULL) {
327: u.u_pofile[want] = 0;
328: if (want > u.u_lastfile)
329: u.u_lastfile = want;
330: *result = want;
331: return (0);
332: }
333: }
334: return (EMFILE);
335: }
336:
337: /*
338: * Check to see if any user file descriptors are available.
339: */
340: ufavail()
341: {
342: register int i, avail = 0;
343:
344: for (i = 0; i < NOFILE; i++)
345: if (u.u_ofile[i] == NULL)
346: avail++;
347: return (avail);
348: }
349:
350: struct file *lastf;
351: /*
352: * Allocate a user file descriptor
353: * and a file structure.
354: * Initialize the descriptor
355: * to point at the file structure.
356: */
357: falloc(resultfp, resultfd)
358: struct file **resultfp;
359: int *resultfd;
360: {
361: register struct file *fp;
362: int error, i;
363:
364: if (error = ufalloc(0, &i))
365: return (error);
366: if (lastf == 0)
367: lastf = file;
368: for (fp = lastf; fp < fileNFILE; fp++)
369: if (fp->f_count == 0)
370: goto slot;
371: for (fp = file; fp < lastf; fp++)
372: if (fp->f_count == 0)
373: goto slot;
374: tablefull("file");
375: return (ENFILE);
376: slot:
377: u.u_ofile[i] = fp;
378: fp->f_count = 1;
379: fp->f_data = 0;
380: fp->f_offset = 0;
381: fp->f_cred = u.u_cred;
382: crhold(fp->f_cred);
383: lastf = fp + 1;
384: if (resultfp)
385: *resultfp = fp;
386: if (resultfd)
387: *resultfd = i;
388: return (0);
389: }
390:
391: /*
392: * Internal form of close.
393: * Decrement reference count on file structure.
394: */
395: closef(fp)
396: register struct file *fp;
397: {
398: int error;
399:
400: if (fp == NULL)
401: return (0);
402: if (fp->f_count > 1) {
403: fp->f_count--;
404: return (0);
405: }
406: if (fp->f_count < 1)
407: panic("closef: count < 1");
408: error = (*fp->f_ops->fo_close)(fp);
409: crfree(fp->f_cred);
410: fp->f_count = 0;
411: return (error);
412: }
413:
414: /*
415: * Apply an advisory lock on a file descriptor.
416: */
417: /* ARGSUSED */
418: flock(p, uap, retval)
419: struct proc *p;
420: register struct args {
421: int fdes;
422: int how;
423: } *uap;
424: int *retval;
425: {
426: register struct file *fp;
427:
428: if ((unsigned)uap->fdes >= NOFILE ||
429: (fp = u.u_ofile[uap->fdes]) == NULL)
430: return (EBADF);
431: if (fp->f_type != DTYPE_VNODE)
432: return (EOPNOTSUPP);
433: if (uap->how & LOCK_UN) {
434: vn_unlock(fp, FSHLOCK|FEXLOCK);
435: return (0);
436: }
437: if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
438: return (0); /* error? */
439: if (uap->how & LOCK_EX)
440: uap->how &= ~LOCK_SH;
441: /* avoid work... */
442: if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
443: (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
444: return (0);
445: return (vn_lock(fp, uap->how));
446: }
447:
448: /*
449: * File Descriptor pseudo-device driver (/dev/fd/).
450: *
451: * Opening minor device N dup()s the file (if any) connected to file
452: * descriptor N belonging to the calling process. Note that this driver
453: * consists of only the ``open()'' routine, because all subsequent
454: * references to this file will be direct to the other driver.
455: */
456: /* ARGSUSED */
457: fdopen(dev, mode, type)
458: dev_t dev;
459: int mode, type;
460: {
461: struct proc *p = u.u_procp; /* XXX */
462:
463: /*
464: * XXX Kludge: set p->p_dupfd to contain the value of the
465: * the file descriptor being sought for duplication. The error
466: * return ensures that the vnode for this device will be released
467: * by vn_open. Open will detect this special error and take the
468: * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
469: * will simply report the error.
470: */
471: p->p_dupfd = minor(dev);
472: return (ENODEV);
473: }
474:
475: /*
476: * Duplicate the specified descriptor to a free descriptor.
477: */
478: dupfdopen(indx, dfd, mode)
479: register int indx, dfd;
480: int mode;
481: {
482: register struct file *wfp;
483: struct file *fp;
484:
485: /*
486: * If the to-be-dup'd fd number is greater than the allowed number
487: * of file descriptors, or the fd to be dup'd has already been
488: * closed, reject. Note, check for new == old is necessary as
489: * falloc could allocate an already closed to-be-dup'd descriptor
490: * as the new descriptor.
491: */
492: fp = u.u_ofile[indx];
493: if ((u_int)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL ||
494: fp == wfp)
495: return (EBADF);
496:
497: /*
498: * Check that the mode the file is being opened for is a subset
499: * of the mode of the existing descriptor.
500: */
501: if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
502: return (EACCES);
503: u.u_ofile[indx] = wfp;
504: u.u_pofile[indx] = u.u_pofile[dfd];
505: wfp->f_count++;
506: if (indx > u.u_lastfile)
507: u.u_lastfile = indx;
508: return (0);
509: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.