merge in 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 *
17 * @(#)kern_descrip.c 7.4 (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;
40056b21 71
c4ec2128
KM
72 if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
73 RETURN (EBADF);
4147b3f6
BJ
74 if (uap->j < 0 || uap->j >= NOFILE) {
75 u.u_error = EBADF;
40056b21 76 return;
40056b21 77 }
4147b3f6
BJ
78 u.u_r.r_val1 = uap->j;
79 if (uap->i == uap->j)
80 return;
81 if (u.u_ofile[uap->j]) {
67fc76c5
BJ
82 if (u.u_pofile[uap->j] & UF_MAPPED)
83 munmapfd(uap->j);
55dfda24 84 closef(u.u_ofile[uap->j]);
40056b21
BJ
85 if (u.u_error)
86 return;
4147b3f6 87 }
c05c2528 88 dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
a81e9a81
SL
89}
90
55dfda24 91dupit(fd, fp, flags)
a81e9a81
SL
92 int fd;
93 register struct file *fp;
55dfda24 94 register int flags;
a81e9a81
SL
95{
96
97 u.u_ofile[fd] = fp;
55dfda24 98 u.u_pofile[fd] = flags;
4147b3f6 99 fp->f_count++;
8694aaad
MK
100 if (fd > u.u_lastfile)
101 u.u_lastfile = fd;
4147b3f6
BJ
102}
103
88a7a62a
SL
104/*
105 * The file control system call.
106 */
107fcntl()
4147b3f6 108{
4147b3f6 109 register struct file *fp;
4147b3f6 110 register struct a {
88a7a62a
SL
111 int fdes;
112 int cmd;
113 int arg;
c4ec2128 114 } *uap = (struct a *)u.u_ap;
88a7a62a 115 register char *pop;
c4ec2128 116 int i;
4147b3f6 117
c4ec2128
KM
118 if ((unsigned)uap->fdes >= NOFILE ||
119 (fp = u.u_ofile[uap->fdes]) == NULL)
120 RETURN (EBADF);
88a7a62a
SL
121 pop = &u.u_pofile[uap->fdes];
122 switch(uap->cmd) {
85f01bd4 123 case F_DUPFD:
c4ec2128 124 if (uap->arg < 0 || uap->arg >= NOFILE) {
12438177 125 u.u_error = EINVAL;
88a7a62a 126 return;
12438177 127 }
c4ec2128 128 if (u.u_error = ufalloc(uap->arg, &i))
88a7a62a 129 return;
c4ec2128 130 u.u_r.r_val1 = i;
c05c2528 131 dupit(i, fp, *pop &~ UF_EXCLOSE);
88a7a62a 132 break;
12438177 133
85f01bd4 134 case F_GETFD:
88a7a62a
SL
135 u.u_r.r_val1 = *pop & 1;
136 break;
40056b21 137
85f01bd4 138 case F_SETFD:
88a7a62a
SL
139 *pop = (*pop &~ 1) | (uap->arg & 1);
140 break;
12438177 141
85f01bd4 142 case F_GETFL:
88a7a62a 143 u.u_r.r_val1 = fp->f_flag+FOPEN;
12438177
BJ
144 break;
145
85f01bd4 146 case F_SETFL:
88a7a62a
SL
147 fp->f_flag &= FCNTLCANT;
148 fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
149 u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
150 if (u.u_error)
151 break;
152 u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
153 if (u.u_error)
154 (void) fset(fp, FNDELAY, 0);
40056b21 155 break;
88a7a62a 156
85f01bd4
MK
157 case F_GETOWN:
158 u.u_error = fgetown(fp, &u.u_r.r_val1);
88a7a62a
SL
159 break;
160
85f01bd4
MK
161 case F_SETOWN:
162 u.u_error = fsetown(fp, uap->arg);
88a7a62a
SL
163 break;
164
165 default:
166 u.u_error = EINVAL;
40056b21 167 }
40056b21
BJ
168}
169
88a7a62a 170fset(fp, bit, value)
40056b21 171 struct file *fp;
88a7a62a
SL
172 int bit, value;
173{
40056b21 174
88a7a62a
SL
175 if (value)
176 fp->f_flag |= bit;
177 else
178 fp->f_flag &= ~bit;
179 return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
180 (caddr_t)&value));
181}
12438177 182
88a7a62a
SL
183fgetown(fp, valuep)
184 struct file *fp;
185 int *valuep;
186{
187 int error;
40056b21 188
88a7a62a 189 switch (fp->f_type) {
12438177 190
88a7a62a 191 case DTYPE_SOCKET:
8fe87cbb 192 *valuep = ((struct socket *)fp->f_data)->so_pgid;
88a7a62a
SL
193 return (0);
194
195 default:
196 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
197 *valuep = -*valuep;
198 return (error);
40056b21 199 }
40056b21
BJ
200}
201
88a7a62a
SL
202fsetown(fp, value)
203 struct file *fp;
204 int value;
40056b21 205{
c4ec2128 206
88a7a62a 207 if (fp->f_type == DTYPE_SOCKET) {
8fe87cbb 208 ((struct socket *)fp->f_data)->so_pgid = value;
88a7a62a
SL
209 return (0);
210 }
211 if (value > 0) {
212 struct proc *p = pfind(value);
213 if (p == 0)
0aae4319 214 return (ESRCH);
8fe87cbb 215 value = p->p_pgrp->pg_id;
88a7a62a
SL
216 } else
217 value = -value;
218 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
40056b21
BJ
219}
220
88a7a62a
SL
221fioctl(fp, cmd, value)
222 struct file *fp;
223 int cmd;
224 caddr_t value;
40056b21 225{
40056b21 226
88a7a62a 227 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
40056b21
BJ
228}
229
88a7a62a 230close()
3ebb7a40 231{
8694aaad 232 struct a {
c4ec2128 233 int fdes;
88a7a62a
SL
234 } *uap = (struct a *)u.u_ap;
235 register struct file *fp;
92438dfc 236 register u_char *pf;
3ebb7a40 237
c4ec2128
KM
238 if ((unsigned)uap->fdes >= NOFILE ||
239 (fp = u.u_ofile[uap->fdes]) == NULL)
240 RETURN (EBADF);
241 pf = (u_char *)&u.u_pofile[uap->fdes];
92438dfc 242 if (*pf & UF_MAPPED)
c4ec2128
KM
243 munmapfd(uap->fdes);
244 u.u_ofile[uap->fdes] = NULL;
8694aaad
MK
245 while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
246 u.u_lastfile--;
92438dfc 247 *pf = 0;
e125c45d
MK
248 closef(fp);
249 /* WHAT IF u.u_error ? */
92438dfc
SL
250}
251
252fstat()
253{
254 register struct file *fp;
255 register struct a {
256 int fdes;
257 struct stat *sb;
c4ec2128 258 } *uap = (struct a *)u.u_ap;
92438dfc
SL
259 struct stat ub;
260
c4ec2128
KM
261 if ((unsigned)uap->fdes >= NOFILE ||
262 (fp = u.u_ofile[uap->fdes]) == NULL)
263 RETURN (EBADF);
92438dfc
SL
264 switch (fp->f_type) {
265
c4ec2128
KM
266 case DTYPE_VNODE:
267 u.u_error = vn_stat((struct vnode *)fp->f_data, &ub);
92438dfc
SL
268 break;
269
270 case DTYPE_SOCKET:
271 u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
272 break;
273
274 default:
275 panic("fstat");
276 /*NOTREACHED*/
277 }
278 if (u.u_error == 0)
55dfda24
SL
279 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
280 sizeof (ub));
3ebb7a40
BJ
281}
282
40056b21 283/*
4147b3f6 284 * Allocate a user file descriptor.
40056b21 285 */
c4ec2128
KM
286ufalloc(want, result)
287 register int want;
288 int *result;
4147b3f6 289{
4147b3f6 290
c4ec2128
KM
291 for (; want < NOFILE; want++)
292 if (u.u_ofile[want] == NULL) {
293 u.u_pofile[want] = 0;
294 if (want > u.u_lastfile)
295 u.u_lastfile = want;
296 if (result)
297 *result = want;
298 return (0);
4147b3f6 299 }
c4ec2128 300 return (EMFILE);
4147b3f6
BJ
301}
302
88a7a62a
SL
303ufavail()
304{
305 register int i, avail = 0;
306
307 for (i = 0; i < NOFILE; i++)
308 if (u.u_ofile[i] == NULL)
309 avail++;
310 return (avail);
311}
312
4147b3f6
BJ
313struct file *lastf;
314/*
315 * Allocate a user file descriptor
316 * and a file structure.
317 * Initialize the descriptor
318 * to point at the file structure.
319 */
c4ec2128
KM
320falloc(resultfp, resultfd)
321 struct file **resultfp;
322 int *resultfd;
4147b3f6
BJ
323{
324 register struct file *fp;
c4ec2128 325 int error, i;
4147b3f6 326
c4ec2128
KM
327 if (error = ufalloc(0, &i))
328 return (error);
4147b3f6
BJ
329 if (lastf == 0)
330 lastf = file;
331 for (fp = lastf; fp < fileNFILE; fp++)
332 if (fp->f_count == 0)
333 goto slot;
334 for (fp = file; fp < lastf; fp++)
335 if (fp->f_count == 0)
336 goto slot;
337 tablefull("file");
c4ec2128 338 return (ENFILE);
4147b3f6
BJ
339slot:
340 u.u_ofile[i] = fp;
88a7a62a
SL
341 fp->f_count = 1;
342 fp->f_data = 0;
4147b3f6 343 fp->f_offset = 0;
c4ec2128
KM
344 fp->f_cred = u.u_cred;
345 crhold(fp->f_cred);
4147b3f6 346 lastf = fp + 1;
c4ec2128
KM
347 if (resultfp)
348 *resultfp = fp;
349 if (resultfd)
350 *resultfd = i;
351 return (0);
4147b3f6
BJ
352}
353
354/*
355 * Internal form of close.
88a7a62a 356 * Decrement reference count on file structure.
4147b3f6 357 */
92438dfc 358closef(fp)
4147b3f6
BJ
359 register struct file *fp;
360{
4147b3f6 361
40056b21
BJ
362 if (fp == NULL)
363 return;
4147b3f6
BJ
364 if (fp->f_count > 1) {
365 fp->f_count--;
40056b21
BJ
366 return;
367 }
c4ec2128
KM
368 if (fp->f_count < 1)
369 panic("closef: count < 1");
92438dfc 370 (*fp->f_ops->fo_close)(fp);
c4ec2128 371 crfree(fp->f_cred);
4147b3f6 372 fp->f_count = 0;
8d528261 373}
92438dfc
SL
374
375/*
376 * Apply an advisory lock on a file descriptor.
377 */
378flock()
379{
380 register struct a {
c4ec2128 381 int fdes;
92438dfc
SL
382 int how;
383 } *uap = (struct a *)u.u_ap;
384 register struct file *fp;
92438dfc 385
c4ec2128
KM
386 if ((unsigned)uap->fdes >= NOFILE ||
387 (fp = u.u_ofile[uap->fdes]) == NULL)
388 RETURN (EBADF);
389 if (fp->f_type != DTYPE_VNODE) {
55dfda24 390 u.u_error = EOPNOTSUPP;
92438dfc
SL
391 return;
392 }
55dfda24 393 if (uap->how & LOCK_UN) {
c4ec2128 394 vn_unlock(fp, FSHLOCK|FEXLOCK);
92438dfc 395 return;
92438dfc 396 }
8b026909
MK
397 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
398 return; /* error? */
742253b3
MK
399 if (uap->how & LOCK_EX)
400 uap->how &= ~LOCK_SH;
55dfda24 401 /* avoid work... */
742253b3
MK
402 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
403 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
92438dfc 404 return;
c4ec2128 405 u.u_error = vn_lock(fp, uap->how);
92438dfc 406}
75ebd8c9
MT
407
408/*
409 * File Descriptor pseudo-device driver (/dev/fd/).
410 *
411 * Fred Blonder - U of Maryland 11-Sep-1984
412 *
413 * Opening minor device N dup()s the file (if any) connected to file
414 * descriptor N belonging to the calling process. Note that this driver
415 * consists of only the ``open()'' routine, because all subsequent
416 * references to this file will be direct to the other driver.
417 */
c4ec2128
KM
418/* ARGSUSED */
419fdopen(dev, mode, type)
75ebd8c9 420 dev_t dev;
c4ec2128 421 int mode, type;
75ebd8c9
MT
422{
423 struct file *fp, *wfp;
c4ec2128 424 int indx, dfd, rwmode;
75ebd8c9
MT
425
426 /*
427 * Note the horrid kludge here: u.u_r.r_val1 contains the value
c4ec2128
KM
428 * of the new file descriptor, which was set before the call to
429 * vn_open() by copen() in vfs_syscalls.c
75ebd8c9 430 */
c4ec2128
KM
431 indx = u.u_r.r_val1; /* XXX */
432 if ((unsigned)indx >= NOFILE || (fp = u.u_ofile[indx]) == NULL)
433 return (EBADF);
434 dfd = minor(dev);
435 if ((unsigned)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL)
436 return (EBADF);
75ebd8c9
MT
437 /*
438 * We must explicitly test for this case because ufalloc() may
439 * have allocated us the same file desriptor we are referring
440 * to, if the proccess referred to an invalid (closed) descriptor.
c4ec2128
KM
441 * Ordinarily this would be caught by the check for NULL above,
442 * but by the time we reach this routine u_pofile[minor(dev)]
443 * could already be set to point to our file struct.
75ebd8c9
MT
444 */
445 if (fp == wfp)
446 return (EBADF);
447 /*
448 * Fake a ``dup()'' sys call.
449 * Check that the mode the file is being opened
450 * for is consistent with the mode of the existing
451 * descriptor. This isn't as clean as it should be,
452 * but this entire driver is a real kludge anyway.
453 */
454 rwmode = mode & (FREAD|FWRITE);
455 if ((fp->f_flag & rwmode) != rwmode)
456 return (EACCES);
457 /*
458 * Delete references to this pseudo-device.
459 * Note that fp->f_count is guaranteed == 1, and
c4ec2128 460 * that fp references the vnode for this driver.
75ebd8c9 461 */
c4ec2128 462 if (fp->f_count != 1 || fp->f_type != DTYPE_VNODE)
75ebd8c9 463 panic("fdopen");
c4ec2128 464 vrele((struct vnode *)fp->f_data);
75ebd8c9
MT
465 fp->f_count = 0;
466 /*
467 * Dup the file descriptor.
468 */
c4ec2128 469 dupit(indx, wfp, u.u_pofile[dfd]);
75ebd8c9
MT
470 return (0);
471}