xref: /original-bsd/sys/kern/kern_descrip.c (revision 014fe330)
1 /*	kern_descrip.c	5.25	83/06/12	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/kernel.h"
8 #include "../h/inode.h"
9 #include "../h/proc.h"
10 #include "../h/conf.h"
11 #include "../h/file.h"
12 #include "../h/socket.h"
13 #include "../h/socketvar.h"
14 #include "../h/mount.h"
15 #include "../h/stat.h"
16 
17 #include "../h/ioctl.h"
18 
19 /*
20  * Descriptor management.
21  */
22 
23 /*
24  * TODO:
25  *	increase NOFILE
26  *	eliminate u.u_error side effects
27  */
28 
29 /*
30  * System calls on descriptors.
31  */
32 getdtablesize()
33 {
34 
35 	u.u_r.r_val1 = NOFILE;
36 }
37 
38 getdopt()
39 {
40 
41 }
42 
43 setdopt()
44 {
45 
46 }
47 
48 dup()
49 {
50 	register struct a {
51 		int	i;
52 	} *uap = (struct a *) u.u_ap;
53 	struct file *fp;
54 	int j;
55 
56 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
57 
58 	fp = getf(uap->i);
59 	if (fp == 0)
60 		return;
61 	j = ufalloc(0);
62 	if (j < 0)
63 		return;
64 	dupit(j, fp, u.u_pofile[uap->i]);
65 }
66 
67 dup2()
68 {
69 	register struct a {
70 		int	i, j;
71 	} *uap = (struct a *) u.u_ap;
72 	register struct file *fp;
73 
74 	fp = getf(uap->i);
75 	if (fp == 0)
76 		return;
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], u.u_pofile[uap->j]);
88 		if (u.u_error)
89 			return;
90 		/* u.u_ofile[uap->j] = 0; */
91 		/* u.u_pofile[uap->j] = 0; */
92 	}
93 	dupit(uap->j, fp, u.u_pofile[uap->i]);
94 }
95 
96 dupit(fd, fp, lockflags)
97 	int fd;
98 	register struct file *fp;
99 	register int lockflags;
100 {
101 
102 	u.u_ofile[fd] = fp;
103 	u.u_pofile[fd] = lockflags;
104 	fp->f_count++;
105 /* THIS DOESN'T BELONG HERE */
106 	if (lockflags&UF_SHLOCK)
107 		((struct inode *)fp->f_data)->i_shlockc++;
108 	if (lockflags&UF_EXLOCK)
109 		((struct inode *)fp->f_data)->i_exlockc++;
110 /* END DOESN'T BELONG */
111 }
112 
113 /*
114  * The file control system call.
115  */
116 fcntl()
117 {
118 	register struct file *fp;
119 	register struct a {
120 		int	fdes;
121 		int	cmd;
122 		int	arg;
123 	} *uap;
124 	register i;
125 	register char *pop;
126 
127 	uap = (struct a *)u.u_ap;
128 	fp = getf(uap->fdes);
129 	if (fp == NULL)
130 		return;
131 	pop = &u.u_pofile[uap->fdes];
132 	switch(uap->cmd) {
133 	case 0:
134 		i = uap->arg;
135 		if (i < 0 || i > NOFILE) {
136 			u.u_error = EINVAL;
137 			return;
138 		}
139 		if ((i = ufalloc(i)) < 0)
140 			return;
141 		dupit(i, fp, *pop);
142 		break;
143 
144 	case 1:
145 		u.u_r.r_val1 = *pop & 1;
146 		break;
147 
148 	case 2:
149 		*pop = (*pop &~ 1) | (uap->arg & 1);
150 		break;
151 
152 	case 3:
153 		u.u_r.r_val1 = fp->f_flag+FOPEN;
154 		break;
155 
156 	case 4:
157 		fp->f_flag &= FCNTLCANT;
158 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
159 		u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
160 		if (u.u_error)
161 			break;
162 		u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
163 		if (u.u_error)
164 			(void) fset(fp, FNDELAY, 0);
165 		break;
166 
167 	case 5:
168 		u.u_error = fsetown(fp, uap->arg);
169 		break;
170 
171 	case 6:
172 		u.u_error = fgetown(fp, &u.u_r.r_val1);
173 		break;
174 
175 	default:
176 		u.u_error = EINVAL;
177 	}
178 }
179 
180 fset(fp, bit, value)
181 	struct file *fp;
182 	int bit, value;
183 {
184 
185 	if (value)
186 		fp->f_flag |= bit;
187 	else
188 		fp->f_flag &= ~bit;
189 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
190 	    (caddr_t)&value));
191 }
192 
193 fgetown(fp, valuep)
194 	struct file *fp;
195 	int *valuep;
196 {
197 	int error;
198 
199 	switch (fp->f_type) {
200 
201 	case DTYPE_SOCKET:
202 		*valuep = ((struct socket *)fp->f_data)->so_pgrp;
203 		return (0);
204 
205 	default:
206 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
207 		*valuep = -*valuep;
208 		return (error);
209 	}
210 }
211 
212 fsetown(fp, value)
213 	struct file *fp;
214 	int value;
215 {
216 
217 	if (fp->f_type == DTYPE_SOCKET) {
218 		((struct socket *)fp->f_data)->so_pgrp = value;
219 		return (0);
220 	}
221 	if (value > 0) {
222 		struct proc *p = pfind(value);
223 		if (p == 0)
224 			return (EINVAL);
225 		value = p->p_pgrp;
226 	} else
227 		value = -value;
228 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
229 }
230 
231 fioctl(fp, cmd, value)
232 	struct file *fp;
233 	int cmd;
234 	caddr_t value;
235 {
236 
237 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
238 }
239 
240 close()
241 {
242 	register struct a {
243 		int	i;
244 	} *uap = (struct a *)u.u_ap;
245 	register struct file *fp;
246 	register u_char *pf;
247 
248 	fp = getf(uap->i);
249 	if (fp == 0)
250 		return;
251 	pf = (u_char *)&u.u_pofile[uap->i];
252 	if (*pf & UF_MAPPED)
253 		munmapfd(uap->i);
254 	if (*pf & (UF_SHLOCK|UF_EXLOCK))
255 		unlockf(fp, pf);
256 	closef(fp);
257 	/* WHAT IF u.u_error ? */
258 	u.u_ofile[uap->i] = NULL;
259 	*pf = 0;
260 }
261 
262 fstat()
263 {
264 	register struct file *fp;
265 	register struct a {
266 		int	fdes;
267 		struct	stat *sb;
268 	} *uap;
269 	struct stat ub;
270 
271 	uap = (struct a *)u.u_ap;
272 	fp = getf(uap->fdes);
273 	if (fp == 0)
274 		return;
275 	switch (fp->f_type) {
276 
277 	case DTYPE_INODE:
278 		u.u_error = ino_stat((struct inode *)fp->f_data, &ub);
279 		break;
280 
281 	case DTYPE_SOCKET:
282 		u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
283 		break;
284 
285 	default:
286 		panic("fstat");
287 		/*NOTREACHED*/
288 	}
289 	if (u.u_error == 0)
290 		u.u_error = copyout(&ub, uap->sb, sizeof (ub));
291 }
292 
293 /*
294  * Allocate a user file descriptor.
295  */
296 ufalloc(i)
297 	register int i;
298 {
299 
300 	for (; i < NOFILE; i++)
301 		if (u.u_ofile[i] == NULL) {
302 			u.u_r.r_val1 = i;
303 			u.u_pofile[i] = 0;
304 			return (i);
305 		}
306 	u.u_error = EMFILE;
307 	return (-1);
308 }
309 
310 ufavail()
311 {
312 	register int i, avail = 0;
313 
314 	for (i = 0; i < NOFILE; i++)
315 		if (u.u_ofile[i] == NULL)
316 			avail++;
317 	return (avail);
318 }
319 
320 struct	file *lastf;
321 /*
322  * Allocate a user file descriptor
323  * and a file structure.
324  * Initialize the descriptor
325  * to point at the file structure.
326  */
327 struct file *
328 falloc()
329 {
330 	register struct file *fp;
331 	register i;
332 
333 	i = ufalloc(0);
334 	if (i < 0)
335 		return (NULL);
336 	if (lastf == 0)
337 		lastf = file;
338 	for (fp = lastf; fp < fileNFILE; fp++)
339 		if (fp->f_count == 0)
340 			goto slot;
341 	for (fp = file; fp < lastf; fp++)
342 		if (fp->f_count == 0)
343 			goto slot;
344 	tablefull("file");
345 	u.u_error = ENFILE;
346 	return (NULL);
347 slot:
348 	u.u_ofile[i] = fp;
349 	fp->f_count = 1;
350 	fp->f_data = 0;
351 	fp->f_offset = 0;
352 	lastf = fp + 1;
353 	return (fp);
354 }
355 
356 /*
357  * Convert a user supplied file descriptor into a pointer
358  * to a file structure.  Only task is to check range of the descriptor.
359  * Critical paths should use the GETF macro.
360  */
361 struct file *
362 getf(f)
363 	register int f;
364 {
365 	register struct file *fp;
366 
367 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
368 		u.u_error = EBADF;
369 		return (NULL);
370 	}
371 	return (fp);
372 }
373 
374 /*
375  * Internal form of close.
376  * Decrement reference count on file structure.
377  * If last reference not going away, but no more
378  * references except in message queues, run a
379  * garbage collect.  This would better be done by
380  * forcing a gc() to happen sometime soon, rather
381  * than running one each time.
382  */
383 closef(fp)
384 	register struct file *fp;
385 {
386 
387 	if (fp == NULL)
388 		return;
389 	if (fp->f_count > 1) {
390 		fp->f_count--;
391 		if (fp->f_count == fp->f_msgcount)
392 			unp_gc();
393 		return;
394 	}
395 	(*fp->f_ops->fo_close)(fp);
396 	fp->f_count = 0;
397 }
398 
399 /*
400  * Apply an advisory lock on a file descriptor.
401  */
402 flock()
403 {
404 	register struct a {
405 		int	fd;
406 		int	how;
407 	} *uap = (struct a *)u.u_ap;
408 	register struct file *fp;
409 	register u_char *pf;
410 	int cmd;
411 
412 	fp = getf(uap->fd);
413 	if (fp == NULL)
414 		return;
415 	cmd = uap->how;
416 	pf = (u_char *)&u.u_pofile[uap->fd];
417 	if (cmd & LOCK_UN) {
418 		unlockf(fp, pf);
419 		return;
420 	}
421 	/*
422 	 * No reason to write lock a file we've already
423 	 * write locked, similarly with a read lock.
424 	 */
425 	if ((*pf & UF_EXLOCK) && (cmd & LOCK_EX) ||
426 	    (*pf & UF_SHLOCK) && (cmd & LOCK_SH))
427 		return;
428 	switch (fp->f_type) {
429 
430 	case DTYPE_INODE:
431 		u.u_error = ino_lock((struct inode *)fp->f_data, pf, cmd);
432 		break;
433 
434 	case DTYPE_SOCKET:
435 		u.u_error = soo_lock((struct socket *)fp->f_data, pf, cmd);
436 		break;
437 
438 	default:
439 		panic("lockf");
440 	}
441 }
442 
443 unlockf(fp, pf)
444 	register struct file *fp;
445 	register u_char *pf;
446 {
447 
448 	if ((*pf & (UF_SHLOCK|UF_EXLOCK)) == 0)
449 		return;
450 	switch (fp->f_type) {
451 
452 	case DTYPE_INODE:
453 		ino_unlock((struct inode *)fp->f_data, *pf);
454 		break;
455 
456 	case DTYPE_SOCKET:
457 		soo_unlock((struct socket *)fp->f_data, *pf);
458 		break;
459 
460 	default:
461 		panic("unlockf");
462 	}
463 	*pf &= ~(UF_SHLOCK|UF_EXLOCK);
464 }
465