init KTRACE variables
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
8fe87cbb 6 * @(#)kern_descrip.c 7.2 (Berkeley) %G%
da7c5cc6 7 */
40056b21 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "dir.h"
12#include "user.h"
13#include "kernel.h"
14#include "inode.h"
15#include "proc.h"
94368568
JB
16#include "file.h"
17#include "socket.h"
18#include "socketvar.h"
19#include "mount.h"
20#include "stat.h"
4147b3f6 21
94368568 22#include "ioctl.h"
4147b3f6
BJ
23
24/*
25 * Descriptor management.
26 */
27
28/*
29 * TODO:
88a7a62a 30 * eliminate u.u_error side effects
4147b3f6 31 */
40056b21
BJ
32
33/*
4147b3f6 34 * System calls on descriptors.
40056b21 35 */
3ebb7a40 36getdtablesize()
4147b3f6
BJ
37{
38
39 u.u_r.r_val1 = NOFILE;
40}
41
27b91f59
BJ
42getdopt()
43{
44
45}
46
47setdopt()
48{
49
50}
51
40056b21
BJ
52dup()
53{
4147b3f6
BJ
54 register struct a {
55 int i;
56 } *uap = (struct a *) u.u_ap;
a81e9a81
SL
57 struct file *fp;
58 int j;
4147b3f6
BJ
59
60 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */
61
21e0a474 62 GETF(fp, uap->i);
88a7a62a 63 j = ufalloc(0);
4147b3f6
BJ
64 if (j < 0)
65 return;
c05c2528 66 dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
4147b3f6
BJ
67}
68
69dup2()
70{
40056b21 71 register struct a {
4147b3f6
BJ
72 int i, j;
73 } *uap = (struct a *) u.u_ap;
74 register struct file *fp;
40056b21 75
21e0a474 76 GETF(fp, uap->i);
4147b3f6
BJ
77 if (uap->j < 0 || uap->j >= NOFILE) {
78 u.u_error = EBADF;
40056b21 79 return;
40056b21 80 }
4147b3f6
BJ
81 u.u_r.r_val1 = uap->j;
82 if (uap->i == uap->j)
83 return;
84 if (u.u_ofile[uap->j]) {
67fc76c5
BJ
85 if (u.u_pofile[uap->j] & UF_MAPPED)
86 munmapfd(uap->j);
55dfda24 87 closef(u.u_ofile[uap->j]);
40056b21
BJ
88 if (u.u_error)
89 return;
4147b3f6 90 }
c05c2528 91 dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
a81e9a81
SL
92}
93
55dfda24 94dupit(fd, fp, flags)
a81e9a81
SL
95 int fd;
96 register struct file *fp;
55dfda24 97 register int flags;
a81e9a81
SL
98{
99
100 u.u_ofile[fd] = fp;
55dfda24 101 u.u_pofile[fd] = flags;
4147b3f6 102 fp->f_count++;
8694aaad
MK
103 if (fd > u.u_lastfile)
104 u.u_lastfile = fd;
4147b3f6
BJ
105}
106
88a7a62a
SL
107/*
108 * The file control system call.
109 */
110fcntl()
4147b3f6 111{
4147b3f6 112 register struct file *fp;
4147b3f6 113 register struct a {
88a7a62a
SL
114 int fdes;
115 int cmd;
116 int arg;
117 } *uap;
118 register i;
119 register char *pop;
4147b3f6 120
88a7a62a 121 uap = (struct a *)u.u_ap;
21e0a474 122 GETF(fp, uap->fdes);
88a7a62a
SL
123 pop = &u.u_pofile[uap->fdes];
124 switch(uap->cmd) {
85f01bd4 125 case F_DUPFD:
88a7a62a 126 i = uap->arg;
8b026909 127 if (i < 0 || i >= NOFILE) {
12438177 128 u.u_error = EINVAL;
88a7a62a 129 return;
12438177 130 }
88a7a62a
SL
131 if ((i = ufalloc(i)) < 0)
132 return;
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{
88a7a62a 208 if (fp->f_type == DTYPE_SOCKET) {
8fe87cbb 209 ((struct socket *)fp->f_data)->so_pgid = value;
88a7a62a
SL
210 return (0);
211 }
212 if (value > 0) {
213 struct proc *p = pfind(value);
214 if (p == 0)
0aae4319 215 return (ESRCH);
8fe87cbb 216 value = p->p_pgrp->pg_id;
88a7a62a
SL
217 } else
218 value = -value;
219 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
40056b21
BJ
220}
221
88a7a62a
SL
222fioctl(fp, cmd, value)
223 struct file *fp;
224 int cmd;
225 caddr_t value;
40056b21 226{
40056b21 227
88a7a62a 228 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
40056b21
BJ
229}
230
88a7a62a 231close()
3ebb7a40 232{
8694aaad 233 struct a {
88a7a62a
SL
234 int i;
235 } *uap = (struct a *)u.u_ap;
8694aaad 236 register int i = uap->i;
88a7a62a 237 register struct file *fp;
92438dfc 238 register u_char *pf;
3ebb7a40 239
8694aaad
MK
240 GETF(fp, i);
241 pf = (u_char *)&u.u_pofile[i];
92438dfc 242 if (*pf & UF_MAPPED)
8694aaad
MK
243 munmapfd(i);
244 u.u_ofile[i] = NULL;
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;
258 } *uap;
259 struct stat ub;
260
261 uap = (struct a *)u.u_ap;
21e0a474 262 GETF(fp, uap->fdes);
92438dfc
SL
263 switch (fp->f_type) {
264
265 case DTYPE_INODE:
266 u.u_error = ino_stat((struct inode *)fp->f_data, &ub);
267 break;
268
269 case DTYPE_SOCKET:
270 u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
271 break;
272
273 default:
274 panic("fstat");
275 /*NOTREACHED*/
276 }
277 if (u.u_error == 0)
55dfda24
SL
278 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
279 sizeof (ub));
3ebb7a40
BJ
280}
281
40056b21 282/*
4147b3f6 283 * Allocate a user file descriptor.
40056b21 284 */
88a7a62a
SL
285ufalloc(i)
286 register int i;
4147b3f6 287{
4147b3f6 288
88a7a62a 289 for (; i < NOFILE; i++)
4147b3f6
BJ
290 if (u.u_ofile[i] == NULL) {
291 u.u_r.r_val1 = i;
292 u.u_pofile[i] = 0;
8694aaad
MK
293 if (i > u.u_lastfile)
294 u.u_lastfile = i;
4147b3f6
BJ
295 return (i);
296 }
297 u.u_error = EMFILE;
298 return (-1);
299}
300
88a7a62a
SL
301ufavail()
302{
303 register int i, avail = 0;
304
305 for (i = 0; i < NOFILE; i++)
306 if (u.u_ofile[i] == NULL)
307 avail++;
308 return (avail);
309}
310
4147b3f6
BJ
311struct file *lastf;
312/*
313 * Allocate a user file descriptor
314 * and a file structure.
315 * Initialize the descriptor
316 * to point at the file structure.
317 */
318struct file *
319falloc()
320{
321 register struct file *fp;
322 register i;
323
88a7a62a 324 i = ufalloc(0);
4147b3f6
BJ
325 if (i < 0)
326 return (NULL);
327 if (lastf == 0)
328 lastf = file;
329 for (fp = lastf; fp < fileNFILE; fp++)
330 if (fp->f_count == 0)
331 goto slot;
332 for (fp = file; fp < lastf; fp++)
333 if (fp->f_count == 0)
334 goto slot;
335 tablefull("file");
336 u.u_error = ENFILE;
337 return (NULL);
338slot:
339 u.u_ofile[i] = fp;
88a7a62a
SL
340 fp->f_count = 1;
341 fp->f_data = 0;
4147b3f6 342 fp->f_offset = 0;
4147b3f6
BJ
343 lastf = fp + 1;
344 return (fp);
345}
88a7a62a 346
4147b3f6
BJ
347/*
348 * Convert a user supplied file descriptor into a pointer
349 * to a file structure. Only task is to check range of the descriptor.
88a7a62a 350 * Critical paths should use the GETF macro.
4147b3f6
BJ
351 */
352struct file *
353getf(f)
354 register int f;
40056b21
BJ
355{
356 register struct file *fp;
40056b21 357
4147b3f6
BJ
358 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
359 u.u_error = EBADF;
360 return (NULL);
361 }
362 return (fp);
363}
364
365/*
366 * Internal form of close.
88a7a62a 367 * Decrement reference count on file structure.
4147b3f6 368 */
92438dfc 369closef(fp)
4147b3f6
BJ
370 register struct file *fp;
371{
4147b3f6 372
40056b21
BJ
373 if (fp == NULL)
374 return;
4147b3f6
BJ
375 if (fp->f_count > 1) {
376 fp->f_count--;
40056b21
BJ
377 return;
378 }
92438dfc 379 (*fp->f_ops->fo_close)(fp);
4147b3f6 380 fp->f_count = 0;
8d528261 381}
92438dfc
SL
382
383/*
384 * Apply an advisory lock on a file descriptor.
385 */
386flock()
387{
388 register struct a {
389 int fd;
390 int how;
391 } *uap = (struct a *)u.u_ap;
392 register struct file *fp;
92438dfc 393
21e0a474 394 GETF(fp, uap->fd);
55dfda24
SL
395 if (fp->f_type != DTYPE_INODE) {
396 u.u_error = EOPNOTSUPP;
92438dfc
SL
397 return;
398 }
55dfda24
SL
399 if (uap->how & LOCK_UN) {
400 ino_unlock(fp, FSHLOCK|FEXLOCK);
92438dfc 401 return;
92438dfc 402 }
8b026909
MK
403 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
404 return; /* error? */
742253b3
MK
405 if (uap->how & LOCK_EX)
406 uap->how &= ~LOCK_SH;
55dfda24 407 /* avoid work... */
742253b3
MK
408 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
409 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
92438dfc 410 return;
55dfda24 411 u.u_error = ino_lock(fp, uap->how);
92438dfc 412}