marc's changes: malloc uio if too large, ktrace
[unix-history] / usr / src / sys / kern / kern_descrip.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)kern_descrip.c 7.2 (Berkeley) %G%
7 */
8
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"
16#include "file.h"
17#include "socket.h"
18#include "socketvar.h"
19#include "mount.h"
20#include "stat.h"
21
22#include "ioctl.h"
23
24/*
25 * Descriptor management.
26 */
27
28/*
29 * TODO:
30 * eliminate u.u_error side effects
31 */
32
33/*
34 * System calls on descriptors.
35 */
36getdtablesize()
37{
38
39 u.u_r.r_val1 = NOFILE;
40}
41
42getdopt()
43{
44
45}
46
47setdopt()
48{
49
50}
51
52dup()
53{
54 register struct a {
55 int i;
56 } *uap = (struct a *) u.u_ap;
57 struct file *fp;
58 int j;
59
60 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */
61
62 GETF(fp, uap->i);
63 j = ufalloc(0);
64 if (j < 0)
65 return;
66 dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
67}
68
69dup2()
70{
71 register struct a {
72 int i, j;
73 } *uap = (struct a *) u.u_ap;
74 register struct file *fp;
75
76 GETF(fp, uap->i);
77 if (uap->j < 0 || uap->j >= NOFILE) {
78 u.u_error = EBADF;
79 return;
80 }
81 u.u_r.r_val1 = uap->j;
82 if (uap->i == uap->j)
83 return;
84 if (u.u_ofile[uap->j]) {
85 if (u.u_pofile[uap->j] & UF_MAPPED)
86 munmapfd(uap->j);
87 closef(u.u_ofile[uap->j]);
88 if (u.u_error)
89 return;
90 }
91 dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
92}
93
94dupit(fd, fp, flags)
95 int fd;
96 register struct file *fp;
97 register int flags;
98{
99
100 u.u_ofile[fd] = fp;
101 u.u_pofile[fd] = flags;
102 fp->f_count++;
103 if (fd > u.u_lastfile)
104 u.u_lastfile = fd;
105}
106
107/*
108 * The file control system call.
109 */
110fcntl()
111{
112 register struct file *fp;
113 register struct a {
114 int fdes;
115 int cmd;
116 int arg;
117 } *uap;
118 register i;
119 register char *pop;
120
121 uap = (struct a *)u.u_ap;
122 GETF(fp, uap->fdes);
123 pop = &u.u_pofile[uap->fdes];
124 switch(uap->cmd) {
125 case F_DUPFD:
126 i = uap->arg;
127 if (i < 0 || i >= NOFILE) {
128 u.u_error = EINVAL;
129 return;
130 }
131 if ((i = ufalloc(i)) < 0)
132 return;
133 dupit(i, fp, *pop &~ UF_EXCLOSE);
134 break;
135
136 case F_GETFD:
137 u.u_r.r_val1 = *pop & 1;
138 break;
139
140 case F_SETFD:
141 *pop = (*pop &~ 1) | (uap->arg & 1);
142 break;
143
144 case F_GETFL:
145 u.u_r.r_val1 = fp->f_flag+FOPEN;
146 break;
147
148 case F_SETFL:
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);
157 break;
158
159 case F_GETOWN:
160 u.u_error = fgetown(fp, &u.u_r.r_val1);
161 break;
162
163 case F_SETOWN:
164 u.u_error = fsetown(fp, uap->arg);
165 break;
166
167 default:
168 u.u_error = EINVAL;
169 }
170}
171
172fset(fp, bit, value)
173 struct file *fp;
174 int bit, value;
175{
176
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}
184
185fgetown(fp, valuep)
186 struct file *fp;
187 int *valuep;
188{
189 int error;
190
191 switch (fp->f_type) {
192
193 case DTYPE_SOCKET:
194 *valuep = ((struct socket *)fp->f_data)->so_pgid;
195 return (0);
196
197 default:
198 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
199 *valuep = -*valuep;
200 return (error);
201 }
202}
203
204fsetown(fp, value)
205 struct file *fp;
206 int value;
207{
208 if (fp->f_type == DTYPE_SOCKET) {
209 ((struct socket *)fp->f_data)->so_pgid = value;
210 return (0);
211 }
212 if (value > 0) {
213 struct proc *p = pfind(value);
214 if (p == 0)
215 return (ESRCH);
216 value = p->p_pgrp->pg_id;
217 } else
218 value = -value;
219 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
220}
221
222fioctl(fp, cmd, value)
223 struct file *fp;
224 int cmd;
225 caddr_t value;
226{
227
228 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
229}
230
231close()
232{
233 struct a {
234 int i;
235 } *uap = (struct a *)u.u_ap;
236 register int i = uap->i;
237 register struct file *fp;
238 register u_char *pf;
239
240 GETF(fp, i);
241 pf = (u_char *)&u.u_pofile[i];
242 if (*pf & UF_MAPPED)
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--;
247 *pf = 0;
248 closef(fp);
249 /* WHAT IF u.u_error ? */
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;
262 GETF(fp, uap->fdes);
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)
278 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
279 sizeof (ub));
280}
281
282/*
283 * Allocate a user file descriptor.
284 */
285ufalloc(i)
286 register int i;
287{
288
289 for (; i < NOFILE; i++)
290 if (u.u_ofile[i] == NULL) {
291 u.u_r.r_val1 = i;
292 u.u_pofile[i] = 0;
293 if (i > u.u_lastfile)
294 u.u_lastfile = i;
295 return (i);
296 }
297 u.u_error = EMFILE;
298 return (-1);
299}
300
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
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
324 i = ufalloc(0);
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;
340 fp->f_count = 1;
341 fp->f_data = 0;
342 fp->f_offset = 0;
343 lastf = fp + 1;
344 return (fp);
345}
346
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.
350 * Critical paths should use the GETF macro.
351 */
352struct file *
353getf(f)
354 register int f;
355{
356 register struct file *fp;
357
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.
367 * Decrement reference count on file structure.
368 */
369closef(fp)
370 register struct file *fp;
371{
372
373 if (fp == NULL)
374 return;
375 if (fp->f_count > 1) {
376 fp->f_count--;
377 return;
378 }
379 (*fp->f_ops->fo_close)(fp);
380 fp->f_count = 0;
381}
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;
393
394 GETF(fp, uap->fd);
395 if (fp->f_type != DTYPE_INODE) {
396 u.u_error = EOPNOTSUPP;
397 return;
398 }
399 if (uap->how & LOCK_UN) {
400 ino_unlock(fp, FSHLOCK|FEXLOCK);
401 return;
402 }
403 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
404 return; /* error? */
405 if (uap->how & LOCK_EX)
406 uap->how &= ~LOCK_SH;
407 /* avoid work... */
408 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
409 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
410 return;
411 u.u_error = ino_lock(fp, uap->how);
412}