revamp locking to be done at the file table level
[unix-history] / usr / src / sys / kern / kern_descrip.c
CommitLineData
55dfda24 1/* kern_descrip.c 5.26 83/06/14 */
40056b21
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
3ebb7a40 7#include "../h/kernel.h"
40056b21
BJ
8#include "../h/inode.h"
9#include "../h/proc.h"
40056b21 10#include "../h/conf.h"
40056b21 11#include "../h/file.h"
40056b21
BJ
12#include "../h/socket.h"
13#include "../h/socketvar.h"
4147b3f6 14#include "../h/mount.h"
92438dfc 15#include "../h/stat.h"
4147b3f6 16
88a7a62a 17#include "../h/ioctl.h"
4147b3f6
BJ
18
19/*
20 * Descriptor management.
21 */
22
23/*
24 * TODO:
88a7a62a
SL
25 * increase NOFILE
26 * eliminate u.u_error side effects
4147b3f6 27 */
40056b21
BJ
28
29/*
4147b3f6 30 * System calls on descriptors.
40056b21 31 */
3ebb7a40 32getdtablesize()
4147b3f6
BJ
33{
34
35 u.u_r.r_val1 = NOFILE;
36}
37
27b91f59
BJ
38getdopt()
39{
40
41}
42
43setdopt()
44{
45
46}
47
40056b21
BJ
48dup()
49{
4147b3f6
BJ
50 register struct a {
51 int i;
52 } *uap = (struct a *) u.u_ap;
a81e9a81
SL
53 struct file *fp;
54 int j;
4147b3f6
BJ
55
56 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */
57
58 fp = getf(uap->i);
59 if (fp == 0)
60 return;
88a7a62a 61 j = ufalloc(0);
4147b3f6
BJ
62 if (j < 0)
63 return;
88a7a62a 64 dupit(j, fp, u.u_pofile[uap->i]);
4147b3f6
BJ
65}
66
67dup2()
68{
40056b21 69 register struct a {
4147b3f6
BJ
70 int i, j;
71 } *uap = (struct a *) u.u_ap;
72 register struct file *fp;
40056b21 73
4147b3f6
BJ
74 fp = getf(uap->i);
75 if (fp == 0)
76 return;
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 }
88a7a62a 91 dupit(uap->j, fp, u.u_pofile[uap->i]);
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
BJ
102 fp->f_count++;
103}
104
88a7a62a
SL
105/*
106 * The file control system call.
107 */
108fcntl()
4147b3f6 109{
4147b3f6 110 register struct file *fp;
4147b3f6 111 register struct a {
88a7a62a
SL
112 int fdes;
113 int cmd;
114 int arg;
115 } *uap;
116 register i;
117 register char *pop;
4147b3f6 118
88a7a62a
SL
119 uap = (struct a *)u.u_ap;
120 fp = getf(uap->fdes);
121 if (fp == NULL)
4147b3f6 122 return;
88a7a62a
SL
123 pop = &u.u_pofile[uap->fdes];
124 switch(uap->cmd) {
125 case 0:
126 i = uap->arg;
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;
133 dupit(i, fp, *pop);
134 break;
12438177 135
88a7a62a
SL
136 case 1:
137 u.u_r.r_val1 = *pop & 1;
138 break;
40056b21 139
88a7a62a
SL
140 case 2:
141 *pop = (*pop &~ 1) | (uap->arg & 1);
142 break;
12438177 143
88a7a62a
SL
144 case 3:
145 u.u_r.r_val1 = fp->f_flag+FOPEN;
12438177
BJ
146 break;
147
88a7a62a
SL
148 case 4:
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
SL
158
159 case 5:
160 u.u_error = fsetown(fp, uap->arg);
161 break;
162
163 case 6:
164 u.u_error = fgetown(fp, &u.u_r.r_val1);
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)
216 return (EINVAL);
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{
88a7a62a
SL
234 register struct a {
235 int i;
236 } *uap = (struct a *)u.u_ap;
237 register struct file *fp;
92438dfc 238 register u_char *pf;
3ebb7a40 239
88a7a62a
SL
240 fp = getf(uap->i);
241 if (fp == 0)
242 return;
92438dfc
SL
243 pf = (u_char *)&u.u_pofile[uap->i];
244 if (*pf & UF_MAPPED)
88a7a62a 245 munmapfd(uap->i);
92438dfc 246 closef(fp);
88a7a62a
SL
247 /* WHAT IF u.u_error ? */
248 u.u_ofile[uap->i] = NULL;
92438dfc
SL
249 *pf = 0;
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 fp = getf(uap->fdes);
263 if (fp == 0)
264 return;
265 switch (fp->f_type) {
266
267 case DTYPE_INODE:
268 u.u_error = ino_stat((struct inode *)fp->f_data, &ub);
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 */
88a7a62a
SL
287ufalloc(i)
288 register int i;
4147b3f6 289{
4147b3f6 290
88a7a62a 291 for (; i < NOFILE; i++)
4147b3f6
BJ
292 if (u.u_ofile[i] == NULL) {
293 u.u_r.r_val1 = i;
294 u.u_pofile[i] = 0;
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
SL
367 * Decrement reference count on file structure.
368 * If last reference not going away, but no more
369 * references except in message queues, run a
370 * garbage collect. This would better be done by
371 * forcing a gc() to happen sometime soon, rather
372 * than running one each time.
4147b3f6 373 */
92438dfc 374closef(fp)
4147b3f6
BJ
375 register struct file *fp;
376{
4147b3f6 377
40056b21
BJ
378 if (fp == NULL)
379 return;
4147b3f6
BJ
380 if (fp->f_count > 1) {
381 fp->f_count--;
88a7a62a
SL
382 if (fp->f_count == fp->f_msgcount)
383 unp_gc();
40056b21
BJ
384 return;
385 }
92438dfc 386 (*fp->f_ops->fo_close)(fp);
4147b3f6 387 fp->f_count = 0;
8d528261 388}
92438dfc
SL
389
390/*
391 * Apply an advisory lock on a file descriptor.
392 */
393flock()
394{
395 register struct a {
396 int fd;
397 int how;
398 } *uap = (struct a *)u.u_ap;
399 register struct file *fp;
92438dfc
SL
400
401 fp = getf(uap->fd);
402 if (fp == NULL)
403 return;
55dfda24
SL
404 if (fp->f_type != DTYPE_INODE) {
405 u.u_error = EOPNOTSUPP;
92438dfc
SL
406 return;
407 }
55dfda24
SL
408 if (uap->how & LOCK_UN) {
409 ino_unlock(fp, FSHLOCK|FEXLOCK);
92438dfc 410 return;
92438dfc 411 }
55dfda24
SL
412 /* avoid work... */
413 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
414 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
92438dfc 415 return;
55dfda24 416 u.u_error = ino_lock(fp, uap->how);
92438dfc 417}