xref: /original-bsd/sys/kern/kern_descrip.c (revision ed6e4306)
1 /*	kern_descrip.c	5.26	83/06/14	*/
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]);
88 		if (u.u_error)
89 			return;
90 	}
91 	dupit(uap->j, fp, u.u_pofile[uap->i]);
92 }
93 
94 dupit(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 }
104 
105 /*
106  * The file control system call.
107  */
108 fcntl()
109 {
110 	register struct file *fp;
111 	register struct a {
112 		int	fdes;
113 		int	cmd;
114 		int	arg;
115 	} *uap;
116 	register i;
117 	register char *pop;
118 
119 	uap = (struct a *)u.u_ap;
120 	fp = getf(uap->fdes);
121 	if (fp == NULL)
122 		return;
123 	pop = &u.u_pofile[uap->fdes];
124 	switch(uap->cmd) {
125 	case 0:
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);
134 		break;
135 
136 	case 1:
137 		u.u_r.r_val1 = *pop & 1;
138 		break;
139 
140 	case 2:
141 		*pop = (*pop &~ 1) | (uap->arg & 1);
142 		break;
143 
144 	case 3:
145 		u.u_r.r_val1 = fp->f_flag+FOPEN;
146 		break;
147 
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);
157 		break;
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;
169 	}
170 }
171 
172 fset(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 
185 fgetown(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_pgrp;
195 		return (0);
196 
197 	default:
198 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
199 		*valuep = -*valuep;
200 		return (error);
201 	}
202 }
203 
204 fsetown(fp, value)
205 	struct file *fp;
206 	int value;
207 {
208 
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));
221 }
222 
223 fioctl(fp, cmd, value)
224 	struct file *fp;
225 	int cmd;
226 	caddr_t value;
227 {
228 
229 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
230 }
231 
232 close()
233 {
234 	register struct a {
235 		int	i;
236 	} *uap = (struct a *)u.u_ap;
237 	register struct file *fp;
238 	register u_char *pf;
239 
240 	fp = getf(uap->i);
241 	if (fp == 0)
242 		return;
243 	pf = (u_char *)&u.u_pofile[uap->i];
244 	if (*pf & UF_MAPPED)
245 		munmapfd(uap->i);
246 	closef(fp);
247 	/* WHAT IF u.u_error ? */
248 	u.u_ofile[uap->i] = NULL;
249 	*pf = 0;
250 }
251 
252 fstat()
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)
280 		u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
281 		    sizeof (ub));
282 }
283 
284 /*
285  * Allocate a user file descriptor.
286  */
287 ufalloc(i)
288 	register int i;
289 {
290 
291 	for (; i < NOFILE; i++)
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 
301 ufavail()
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 
311 struct	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  */
318 struct file *
319 falloc()
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);
338 slot:
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  */
352 struct file *
353 getf(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  * 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.
373  */
374 closef(fp)
375 	register struct file *fp;
376 {
377 
378 	if (fp == NULL)
379 		return;
380 	if (fp->f_count > 1) {
381 		fp->f_count--;
382 		if (fp->f_count == fp->f_msgcount)
383 			unp_gc();
384 		return;
385 	}
386 	(*fp->f_ops->fo_close)(fp);
387 	fp->f_count = 0;
388 }
389 
390 /*
391  * Apply an advisory lock on a file descriptor.
392  */
393 flock()
394 {
395 	register struct a {
396 		int	fd;
397 		int	how;
398 	} *uap = (struct a *)u.u_ap;
399 	register struct file *fp;
400 
401 	fp = getf(uap->fd);
402 	if (fp == NULL)
403 		return;
404 	if (fp->f_type != DTYPE_INODE) {
405 		u.u_error = EOPNOTSUPP;
406 		return;
407 	}
408 	if (uap->how & LOCK_UN) {
409 		ino_unlock(fp, FSHLOCK|FEXLOCK);
410 		return;
411 	}
412 	/* avoid work... */
413 	if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
414 	    (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
415 		return;
416 	u.u_error = ino_lock(fp, uap->how);
417 }
418