updates for 4.3
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
da7c5cc6
KM
1/*
2 * Copyright (c) 1982 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
0aae4319 6 * @(#)kern_descrip.c 6.13 (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
SL
193 case DTYPE_SOCKET:
194 *valuep = ((struct socket *)fp->f_data)->so_pgrp;
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
BJ
207{
208
88a7a62a
SL
209 if (fp->f_type == DTYPE_SOCKET) {
210 ((struct socket *)fp->f_data)->so_pgrp = value;
211 return (0);
212 }
213 if (value > 0) {
214 struct proc *p = pfind(value);
215 if (p == 0)
0aae4319 216 return (ESRCH);
88a7a62a
SL
217 value = p->p_pgrp;
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 {
88a7a62a
SL
235 int i;
236 } *uap = (struct a *)u.u_ap;
8694aaad 237 register int i = uap->i;
88a7a62a 238 register struct file *fp;
92438dfc 239 register u_char *pf;
3ebb7a40 240
8694aaad
MK
241 GETF(fp, i);
242 pf = (u_char *)&u.u_pofile[i];
92438dfc 243 if (*pf & UF_MAPPED)
8694aaad
MK
244 munmapfd(i);
245 u.u_ofile[i] = NULL;
246 while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
247 u.u_lastfile--;
92438dfc 248 *pf = 0;
e125c45d
MK
249 closef(fp);
250 /* WHAT IF u.u_error ? */
92438dfc
SL
251}
252
253fstat()
254{
255 register struct file *fp;
256 register struct a {
257 int fdes;
258 struct stat *sb;
259 } *uap;
260 struct stat ub;
261
262 uap = (struct a *)u.u_ap;
21e0a474 263 GETF(fp, uap->fdes);
92438dfc
SL
264 switch (fp->f_type) {
265
266 case DTYPE_INODE:
267 u.u_error = ino_stat((struct inode *)fp->f_data, &ub);
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 */
88a7a62a
SL
286ufalloc(i)
287 register int i;
4147b3f6 288{
4147b3f6 289
88a7a62a 290 for (; i < NOFILE; i++)
4147b3f6
BJ
291 if (u.u_ofile[i] == NULL) {
292 u.u_r.r_val1 = i;
293 u.u_pofile[i] = 0;
8694aaad
MK
294 if (i > u.u_lastfile)
295 u.u_lastfile = i;
4147b3f6
BJ
296 return (i);
297 }
298 u.u_error = EMFILE;
299 return (-1);
300}
301
88a7a62a
SL
302ufavail()
303{
304 register int i, avail = 0;
305
306 for (i = 0; i < NOFILE; i++)
307 if (u.u_ofile[i] == NULL)
308 avail++;
309 return (avail);
310}
311
4147b3f6
BJ
312struct file *lastf;
313/*
314 * Allocate a user file descriptor
315 * and a file structure.
316 * Initialize the descriptor
317 * to point at the file structure.
318 */
319struct file *
320falloc()
321{
322 register struct file *fp;
323 register i;
324
88a7a62a 325 i = ufalloc(0);
4147b3f6
BJ
326 if (i < 0)
327 return (NULL);
328 if (lastf == 0)
329 lastf = file;
330 for (fp = lastf; fp < fileNFILE; fp++)
331 if (fp->f_count == 0)
332 goto slot;
333 for (fp = file; fp < lastf; fp++)
334 if (fp->f_count == 0)
335 goto slot;
336 tablefull("file");
337 u.u_error = ENFILE;
338 return (NULL);
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;
4147b3f6
BJ
344 lastf = fp + 1;
345 return (fp);
346}
88a7a62a 347
4147b3f6
BJ
348/*
349 * Convert a user supplied file descriptor into a pointer
350 * to a file structure. Only task is to check range of the descriptor.
88a7a62a 351 * Critical paths should use the GETF macro.
4147b3f6
BJ
352 */
353struct file *
354getf(f)
355 register int f;
40056b21
BJ
356{
357 register struct file *fp;
40056b21 358
4147b3f6
BJ
359 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
360 u.u_error = EBADF;
361 return (NULL);
362 }
363 return (fp);
364}
365
366/*
367 * Internal form of close.
88a7a62a 368 * Decrement reference count on file structure.
4147b3f6 369 */
92438dfc 370closef(fp)
4147b3f6
BJ
371 register struct file *fp;
372{
4147b3f6 373
40056b21
BJ
374 if (fp == NULL)
375 return;
4147b3f6
BJ
376 if (fp->f_count > 1) {
377 fp->f_count--;
40056b21
BJ
378 return;
379 }
92438dfc 380 (*fp->f_ops->fo_close)(fp);
4147b3f6 381 fp->f_count = 0;
8d528261 382}
92438dfc
SL
383
384/*
385 * Apply an advisory lock on a file descriptor.
386 */
387flock()
388{
389 register struct a {
390 int fd;
391 int how;
392 } *uap = (struct a *)u.u_ap;
393 register struct file *fp;
92438dfc 394
21e0a474 395 GETF(fp, uap->fd);
55dfda24
SL
396 if (fp->f_type != DTYPE_INODE) {
397 u.u_error = EOPNOTSUPP;
92438dfc
SL
398 return;
399 }
55dfda24
SL
400 if (uap->how & LOCK_UN) {
401 ino_unlock(fp, FSHLOCK|FEXLOCK);
92438dfc 402 return;
92438dfc 403 }
8b026909
MK
404 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
405 return; /* error? */
742253b3
MK
406 if (uap->how & LOCK_EX)
407 uap->how &= ~LOCK_SH;
55dfda24 408 /* avoid work... */
742253b3
MK
409 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
410 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
92438dfc 411 return;
55dfda24 412 u.u_error = ino_lock(fp, uap->how);
92438dfc 413}