set up separate specinfo structure; allow aliased vnodes
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
da7c5cc6 1/*
c4ec2128
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
c4ec2128
KM
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
3c008f5d 17 * @(#)kern_descrip.c 7.7 (Berkeley) %G%
da7c5cc6 18 */
40056b21 19
94368568
JB
20#include "param.h"
21#include "systm.h"
c4ec2128 22#include "syscontext.h"
94368568 23#include "kernel.h"
c4ec2128 24#include "vnode.h"
94368568 25#include "proc.h"
94368568
JB
26#include "file.h"
27#include "socket.h"
28#include "socketvar.h"
29#include "mount.h"
30#include "stat.h"
4147b3f6 31
94368568 32#include "ioctl.h"
4147b3f6
BJ
33
34/*
35 * Descriptor management.
36 */
37
40056b21 38/*
4147b3f6 39 * System calls on descriptors.
40056b21 40 */
3ebb7a40 41getdtablesize()
4147b3f6
BJ
42{
43
44 u.u_r.r_val1 = NOFILE;
45}
46
40056b21
BJ
47dup()
48{
4147b3f6
BJ
49 register struct a {
50 int i;
51 } *uap = (struct a *) u.u_ap;
a81e9a81
SL
52 struct file *fp;
53 int j;
4147b3f6
BJ
54
55 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */
56
c4ec2128
KM
57 if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
58 RETURN (EBADF);
59 if (u.u_error = ufalloc(0, &j))
4147b3f6 60 return;
c4ec2128 61 u.u_r.r_val1 = j;
c05c2528 62 dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
4147b3f6
BJ
63}
64
65dup2()
66{
40056b21 67 register struct a {
4147b3f6
BJ
68 int i, j;
69 } *uap = (struct a *) u.u_ap;
70 register struct file *fp;
f9934296 71 int error;
40056b21 72
c4ec2128
KM
73 if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
74 RETURN (EBADF);
f9934296
KM
75 if (uap->j < 0 || uap->j >= NOFILE)
76 RETURN (EBADF);
4147b3f6
BJ
77 u.u_r.r_val1 = uap->j;
78 if (uap->i == uap->j)
f9934296 79 RETURN (0);
4147b3f6 80 if (u.u_ofile[uap->j]) {
67fc76c5
BJ
81 if (u.u_pofile[uap->j] & UF_MAPPED)
82 munmapfd(uap->j);
f9934296 83 error = closef(u.u_ofile[uap->j]);
4147b3f6 84 }
c05c2528 85 dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
f9934296
KM
86 /*
87 * dup2() must succeed even though the close had an error.
88 */
89 error = 0; /* XXX */
90 RETURN (error);
a81e9a81
SL
91}
92
55dfda24 93dupit(fd, fp, flags)
a81e9a81
SL
94 int fd;
95 register struct file *fp;
55dfda24 96 register int flags;
a81e9a81
SL
97{
98
99 u.u_ofile[fd] = fp;
55dfda24 100 u.u_pofile[fd] = flags;
4147b3f6 101 fp->f_count++;
8694aaad
MK
102 if (fd > u.u_lastfile)
103 u.u_lastfile = fd;
4147b3f6
BJ
104}
105
88a7a62a
SL
106/*
107 * The file control system call.
108 */
109fcntl()
4147b3f6 110{
4147b3f6 111 register struct file *fp;
4147b3f6 112 register struct a {
88a7a62a
SL
113 int fdes;
114 int cmd;
115 int arg;
c4ec2128 116 } *uap = (struct a *)u.u_ap;
88a7a62a 117 register char *pop;
c4ec2128 118 int i;
4147b3f6 119
c4ec2128
KM
120 if ((unsigned)uap->fdes >= NOFILE ||
121 (fp = u.u_ofile[uap->fdes]) == NULL)
122 RETURN (EBADF);
88a7a62a
SL
123 pop = &u.u_pofile[uap->fdes];
124 switch(uap->cmd) {
85f01bd4 125 case F_DUPFD:
c4ec2128 126 if (uap->arg < 0 || uap->arg >= NOFILE) {
12438177 127 u.u_error = EINVAL;
88a7a62a 128 return;
12438177 129 }
c4ec2128 130 if (u.u_error = ufalloc(uap->arg, &i))
88a7a62a 131 return;
c4ec2128 132 u.u_r.r_val1 = i;
c05c2528 133 dupit(i, fp, *pop &~ UF_EXCLOSE);
88a7a62a 134 break;
12438177 135
85f01bd4 136 case F_GETFD:
88a7a62a
SL
137 u.u_r.r_val1 = *pop & 1;
138 break;
40056b21 139
85f01bd4 140 case F_SETFD:
88a7a62a
SL
141 *pop = (*pop &~ 1) | (uap->arg & 1);
142 break;
12438177 143
85f01bd4 144 case F_GETFL:
88a7a62a 145 u.u_r.r_val1 = fp->f_flag+FOPEN;
12438177
BJ
146 break;
147
85f01bd4 148 case F_SETFL:
88a7a62a
SL
149 fp->f_flag &= FCNTLCANT;
150 fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
151 u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
152 if (u.u_error)
153 break;
154 u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
155 if (u.u_error)
156 (void) fset(fp, FNDELAY, 0);
40056b21 157 break;
88a7a62a 158
85f01bd4
MK
159 case F_GETOWN:
160 u.u_error = fgetown(fp, &u.u_r.r_val1);
88a7a62a
SL
161 break;
162
85f01bd4
MK
163 case F_SETOWN:
164 u.u_error = fsetown(fp, uap->arg);
88a7a62a
SL
165 break;
166
167 default:
168 u.u_error = EINVAL;
40056b21 169 }
40056b21
BJ
170}
171
88a7a62a 172fset(fp, bit, value)
40056b21 173 struct file *fp;
88a7a62a
SL
174 int bit, value;
175{
40056b21 176
88a7a62a
SL
177 if (value)
178 fp->f_flag |= bit;
179 else
180 fp->f_flag &= ~bit;
181 return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
182 (caddr_t)&value));
183}
12438177 184
88a7a62a
SL
185fgetown(fp, valuep)
186 struct file *fp;
187 int *valuep;
188{
189 int error;
40056b21 190
88a7a62a 191 switch (fp->f_type) {
12438177 192
88a7a62a 193 case DTYPE_SOCKET:
8fe87cbb 194 *valuep = ((struct socket *)fp->f_data)->so_pgid;
88a7a62a
SL
195 return (0);
196
197 default:
198 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
199 *valuep = -*valuep;
200 return (error);
40056b21 201 }
40056b21
BJ
202}
203
88a7a62a
SL
204fsetown(fp, value)
205 struct file *fp;
206 int value;
40056b21 207{
c4ec2128 208
88a7a62a 209 if (fp->f_type == DTYPE_SOCKET) {
8fe87cbb 210 ((struct socket *)fp->f_data)->so_pgid = value;
88a7a62a
SL
211 return (0);
212 }
213 if (value > 0) {
214 struct proc *p = pfind(value);
215 if (p == 0)
0aae4319 216 return (ESRCH);
8fe87cbb 217 value = p->p_pgrp->pg_id;
88a7a62a
SL
218 } else
219 value = -value;
220 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
40056b21
BJ
221}
222
88a7a62a
SL
223fioctl(fp, cmd, value)
224 struct file *fp;
225 int cmd;
226 caddr_t value;
40056b21 227{
40056b21 228
88a7a62a 229 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
40056b21
BJ
230}
231
88a7a62a 232close()
3ebb7a40 233{
8694aaad 234 struct a {
c4ec2128 235 int fdes;
88a7a62a
SL
236 } *uap = (struct a *)u.u_ap;
237 register struct file *fp;
92438dfc 238 register u_char *pf;
3ebb7a40 239
c4ec2128
KM
240 if ((unsigned)uap->fdes >= NOFILE ||
241 (fp = u.u_ofile[uap->fdes]) == NULL)
242 RETURN (EBADF);
243 pf = (u_char *)&u.u_pofile[uap->fdes];
92438dfc 244 if (*pf & UF_MAPPED)
c4ec2128
KM
245 munmapfd(uap->fdes);
246 u.u_ofile[uap->fdes] = NULL;
8694aaad
MK
247 while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
248 u.u_lastfile--;
92438dfc 249 *pf = 0;
f9934296 250 RETURN (closef(fp));
92438dfc
SL
251}
252
253fstat()
254{
255 register struct file *fp;
256 register struct a {
257 int fdes;
258 struct stat *sb;
c4ec2128 259 } *uap = (struct a *)u.u_ap;
92438dfc
SL
260 struct stat ub;
261
c4ec2128
KM
262 if ((unsigned)uap->fdes >= NOFILE ||
263 (fp = u.u_ofile[uap->fdes]) == NULL)
264 RETURN (EBADF);
92438dfc
SL
265 switch (fp->f_type) {
266
c4ec2128
KM
267 case DTYPE_VNODE:
268 u.u_error = vn_stat((struct vnode *)fp->f_data, &ub);
92438dfc
SL
269 break;
270
271 case DTYPE_SOCKET:
272 u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
273 break;
274
275 default:
276 panic("fstat");
277 /*NOTREACHED*/
278 }
279 if (u.u_error == 0)
55dfda24
SL
280 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
281 sizeof (ub));
3ebb7a40
BJ
282}
283
40056b21 284/*
4147b3f6 285 * Allocate a user file descriptor.
40056b21 286 */
c4ec2128
KM
287ufalloc(want, result)
288 register int want;
289 int *result;
4147b3f6 290{
4147b3f6 291
c4ec2128
KM
292 for (; want < NOFILE; want++)
293 if (u.u_ofile[want] == NULL) {
294 u.u_pofile[want] = 0;
295 if (want > u.u_lastfile)
296 u.u_lastfile = want;
297 if (result)
298 *result = want;
299 return (0);
4147b3f6 300 }
c4ec2128 301 return (EMFILE);
4147b3f6
BJ
302}
303
88a7a62a
SL
304ufavail()
305{
306 register int i, avail = 0;
307
308 for (i = 0; i < NOFILE; i++)
309 if (u.u_ofile[i] == NULL)
310 avail++;
311 return (avail);
312}
313
4147b3f6
BJ
314struct file *lastf;
315/*
316 * Allocate a user file descriptor
317 * and a file structure.
318 * Initialize the descriptor
319 * to point at the file structure.
320 */
c4ec2128
KM
321falloc(resultfp, resultfd)
322 struct file **resultfp;
323 int *resultfd;
4147b3f6
BJ
324{
325 register struct file *fp;
c4ec2128 326 int error, i;
4147b3f6 327
c4ec2128
KM
328 if (error = ufalloc(0, &i))
329 return (error);
4147b3f6
BJ
330 if (lastf == 0)
331 lastf = file;
332 for (fp = lastf; fp < fileNFILE; fp++)
333 if (fp->f_count == 0)
334 goto slot;
335 for (fp = file; fp < lastf; fp++)
336 if (fp->f_count == 0)
337 goto slot;
338 tablefull("file");
c4ec2128 339 return (ENFILE);
4147b3f6
BJ
340slot:
341 u.u_ofile[i] = fp;
88a7a62a
SL
342 fp->f_count = 1;
343 fp->f_data = 0;
4147b3f6 344 fp->f_offset = 0;
c4ec2128
KM
345 fp->f_cred = u.u_cred;
346 crhold(fp->f_cred);
4147b3f6 347 lastf = fp + 1;
c4ec2128
KM
348 if (resultfp)
349 *resultfp = fp;
350 if (resultfd)
351 *resultfd = i;
352 return (0);
4147b3f6
BJ
353}
354
355/*
356 * Internal form of close.
88a7a62a 357 * Decrement reference count on file structure.
4147b3f6 358 */
92438dfc 359closef(fp)
4147b3f6
BJ
360 register struct file *fp;
361{
f9934296 362 int error;
4147b3f6 363
40056b21 364 if (fp == NULL)
f9934296 365 return (0);
4147b3f6
BJ
366 if (fp->f_count > 1) {
367 fp->f_count--;
f9934296 368 return (0);
40056b21 369 }
c4ec2128
KM
370 if (fp->f_count < 1)
371 panic("closef: count < 1");
f9934296 372 error = (*fp->f_ops->fo_close)(fp);
c4ec2128 373 crfree(fp->f_cred);
4147b3f6 374 fp->f_count = 0;
f9934296 375 return (error);
8d528261 376}
92438dfc
SL
377
378/*
379 * Apply an advisory lock on a file descriptor.
380 */
381flock()
382{
383 register struct a {
c4ec2128 384 int fdes;
92438dfc
SL
385 int how;
386 } *uap = (struct a *)u.u_ap;
387 register struct file *fp;
92438dfc 388
c4ec2128
KM
389 if ((unsigned)uap->fdes >= NOFILE ||
390 (fp = u.u_ofile[uap->fdes]) == NULL)
391 RETURN (EBADF);
392 if (fp->f_type != DTYPE_VNODE) {
55dfda24 393 u.u_error = EOPNOTSUPP;
92438dfc
SL
394 return;
395 }
55dfda24 396 if (uap->how & LOCK_UN) {
c4ec2128 397 vn_unlock(fp, FSHLOCK|FEXLOCK);
92438dfc 398 return;
92438dfc 399 }
8b026909
MK
400 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
401 return; /* error? */
742253b3
MK
402 if (uap->how & LOCK_EX)
403 uap->how &= ~LOCK_SH;
55dfda24 404 /* avoid work... */
742253b3
MK
405 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
406 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
92438dfc 407 return;
c4ec2128 408 u.u_error = vn_lock(fp, uap->how);
92438dfc 409}
75ebd8c9
MT
410
411/*
412 * File Descriptor pseudo-device driver (/dev/fd/).
413 *
414 * Fred Blonder - U of Maryland 11-Sep-1984
415 *
416 * Opening minor device N dup()s the file (if any) connected to file
417 * descriptor N belonging to the calling process. Note that this driver
418 * consists of only the ``open()'' routine, because all subsequent
419 * references to this file will be direct to the other driver.
420 */
c4ec2128
KM
421/* ARGSUSED */
422fdopen(dev, mode, type)
75ebd8c9 423 dev_t dev;
c4ec2128 424 int mode, type;
75ebd8c9
MT
425{
426 struct file *fp, *wfp;
c4ec2128 427 int indx, dfd, rwmode;
75ebd8c9
MT
428
429 /*
430 * Note the horrid kludge here: u.u_r.r_val1 contains the value
c4ec2128
KM
431 * of the new file descriptor, which was set before the call to
432 * vn_open() by copen() in vfs_syscalls.c
75ebd8c9 433 */
c6fd5824 434 indx = u.u_r.r_val1; /* XXX from copen */
c4ec2128
KM
435 if ((unsigned)indx >= NOFILE || (fp = u.u_ofile[indx]) == NULL)
436 return (EBADF);
437 dfd = minor(dev);
438 if ((unsigned)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL)
439 return (EBADF);
75ebd8c9
MT
440 /*
441 * We must explicitly test for this case because ufalloc() may
442 * have allocated us the same file desriptor we are referring
443 * to, if the proccess referred to an invalid (closed) descriptor.
c4ec2128
KM
444 * Ordinarily this would be caught by the check for NULL above,
445 * but by the time we reach this routine u_pofile[minor(dev)]
446 * could already be set to point to our file struct.
75ebd8c9
MT
447 */
448 if (fp == wfp)
449 return (EBADF);
450 /*
451 * Fake a ``dup()'' sys call.
452 * Check that the mode the file is being opened
453 * for is consistent with the mode of the existing
454 * descriptor. This isn't as clean as it should be,
455 * but this entire driver is a real kludge anyway.
456 */
457 rwmode = mode & (FREAD|FWRITE);
3c008f5d 458 if ((wfp->f_flag & rwmode) != rwmode)
75ebd8c9 459 return (EACCES);
75ebd8c9
MT
460 /*
461 * Dup the file descriptor.
462 */
c4ec2128 463 dupit(indx, wfp, u.u_pofile[dfd]);
c6fd5824
KM
464 /*
465 * Delete references to this pseudo-device by returning
466 * a special error (-1) that will cause all resources to
467 * be freed, then detected and cleared by copen.
468 */
469 return (-1);
75ebd8c9 470}