|
|
1.1 root 1: /* $Header: /ker/coh.386/RCS/fd.c,v 2.4 93/07/26 15:09:56 nigel Exp $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * Coherent.
17: * File descriptor routines.
18: *
19: * $Log: fd.c,v $
20: * Revision 2.4 93/07/26 15:09:56 nigel
21: * Nigel's R80
22: *
23: * Revision 1.5 93/04/14 10:06:26 root
24: * r75
25: *
26: * Revision 1.3 92/06/10 12:52:39 hal
27: * First record locking changes.
28: *
29: * Revision 1.2 92/01/06 11:59:07 hal
30: * Compile with cc.mwc.
31: *
32: * Revision 1.1 88/03/24 16:13:43 src
33: * Initial revision
34: *
35: */
36:
37: #include <common/ccompat.h>
38: #include <sys/debug.h>
39: #include <sys/coherent.h>
40: #include <sys/errno.h>
41: #include <fcntl.h>
42: #include <sys/fd.h>
43: #include <sys/inode.h>
44:
45: /*
46: * Operations for converting from tagged to untagged "pointer to system file
47: * table entry" and vice versa.
48: */
49:
50: enum {
51: TAGMASK = sizeof (int) - 1
52: };
53:
54: #define MAKE_TAGGED_FD(untag,flag) \
55: (ASSERT (((int) (untag) & TAGMASK) == 0), \
56: ASSERT (((flag) & ~ TAGMASK) == 0), \
57: (tagfd_t) ((unsigned long) (untag) + (flag)))
58:
59: #define GET_UNTAGGED_FD(tagged) \
60: ((FD *) ((unsigned long) (tagged) & ~ TAGMASK))
61:
62: #define GET_TAGGED_FLAG(tagged) \
63: ((int) (tagged) & TAGMASK)
64:
65: /*
66: * Given a file number, return the file descriptor. Now that file descriptors
67: * stored in the U area have their low bits tagged to store flag information
68: * that is FD-specific (gotta avoid that space crunch in the U area), this
69: * interface deals with masking out any extra stuff and returning a plain
70: * pointer.
71: */
72:
73: #if __USE_PROTO__
74: FD * fdget (fd_t fd)
75: #else
76: FD *
77: fdget (fd)
78: fd_t fd;
79: #endif
80: {
81: FD * fdp;
82:
83: if (fd >= NOFILE ||
84: (fdp = GET_UNTAGGED_FD (u.u_filep [fd])) == NULL) {
85: u.u_error = EBADF;
86: return NULL;
87: }
88: return fdp;
89: }
90:
91:
92: /*
93: * Return tag bits from file descriptor.
94: */
95:
96: #if __USE_PROTO__
97: int fdgetflags (fd_t fd)
98: #else
99: int
100: fdgetflags (fd)
101: fd_t fd;
102: #endif
103: {
104: if (fd >= NOFILE || u.u_filep [fd] == NULL) {
105: u.u_error = EBADF;
106: return -1;
107: }
108: return GET_TAGGED_FLAG (u.u_filep [fd]);
109: }
110:
111:
112: /*
113: * This function allows clients to set the flag bits.
114: */
115:
116: #if __USE_PROTO__
117: int fdsetflags (fd_t fd, int flags)
118: #else
119: int
120: fdsetflags (fd, flags)
121: fd_t fd;
122: int flags;
123: #endif
124: {
125: if (fd >= NOFILE || u.u_filep [fd] == NULL) {
126: u.u_error = EBADF;
127: return -1;
128: }
129: if ((flags & ~ TAGMASK) != 0) {
130: u.u_error = EINVAL;
131: return -1;
132: }
133:
134: u.u_filep [fd] = MAKE_TAGGED_FD (GET_UNTAGGED_FD (u.u_filep [fd]),
135: flags);
136: return 0;
137: }
138:
139:
140: /*
141: * This function performs something similar to the F_DUPFD function of
142: * fcntl ()... this functionality is needed several places internally.
143: */
144:
145: #if __USE_PROTO__
146: fd_t fddup (fd_t old, fd_t base)
147: #else
148: fd_t
149: fddup (old, base)
150: fd_t old;
151: fd_t base;
152: #endif
153: {
154: while (base < NOFILE)
155: if (u.u_filep [base] == NULL) {
156: FD * fdp = fdget (old);
157:
158: if (fdp == NULL)
159: return ERROR_FD;
160: u.u_filep [base] = MAKE_TAGGED_FD (fdp, 0);
161: fdp->f_refc ++;
162: return base;
163: } else
164: base ++;
165:
166: u.u_error = EMFILE;
167: return ERROR_FD;
168: }
169:
170:
171: /*
172: * This function finds a free slot in the process file descriptor table and
173: * fills it in with a partially initialised entry.
174: *
175: * This function returns a file descriptor number on success, -1 on failure.
176: */
177:
178: #if __USE_PROTO__
179: fd_t fdalloc (void)
180: #else
181: fd_t
182: fdalloc ()
183: #endif
184: {
185: int i;
186:
187: for (i = 0 ; i < sizeof (u.u_filep) / sizeof (* u.u_filep) ; i ++) {
188: if (u.u_filep [i] == NULL) {
189: FD * filep;
190:
191: if ((filep = kalloc (sizeof (FD))) == NULL) {
192: /*
193: * Insufficient resources!
194: */
195:
196: u.u_error = EAGAIN;
197: return ERROR_FD;
198: }
199:
200: u.u_filep [i] = MAKE_TAGGED_FD (filep, 0);
201:
202: filep->f_flag = 0;
203: filep->f_refc = 0;
204: filep->f_seek = 0;
205: filep->f_ip = NULL;
206:
207: return i;
208: }
209: }
210:
211: u.u_error = EMFILE;
212: return ERROR_FD;
213: }
214:
215:
216: /*
217: * This function performs the second half of the file open process by filling
218: * in the inode member of the file table entry and requesting that the inode be
219: * opened.
220: *
221: * This function returns -1 on error, 0 on success.
222: */
223:
224: #if __USE_PROTO__
225: int fdinit (fd_t fd, INODE * ip, int mode)
226: #else
227: int
228: fdinit (fd, ip, mode)
229: fd_t fd;
230: INODE * ip;
231: int mode;
232: #endif
233: {
234: FD * filep;
235:
236: if ((filep = fdget (fd)) == NULL)
237: return -1;
238:
239: iopen (ip, mode);
240:
241: if (u.u_error != 0)
242: return -1;
243:
244: filep->f_ip = ip;
245: filep->f_flag = mode;
246: filep->f_refc = 1;
247:
248: return 0;
249: }
250:
251:
252: /*
253: * This function finalises an open; normally this does nothing, but if there
254: * has been an error, this code will take care of deallocating the entry.
255: *
256: * This function returns the file descriptor number on success, or -1 on error.
257: */
258:
259: #if __USE_PROTO__
260: fd_t fdfinish (fd_t fd)
261: #else
262: fd_t
263: fdfinish (fd)
264: fd_t fd;
265: #endif
266: {
267: FD * filep;
268:
269: if ((filep = fdget (fd)) == NULL)
270: return ERROR_FD;
271:
272: if (filep->f_refc == 0) {
273: /*
274: * The open never really succeeded, release resources.
275: */
276:
277: kfree (filep);
278: u.u_filep [fd] = NULL;
279: fd = ERROR_FD;
280: }
281:
282: return fd;
283: }
284:
285:
286: /*
287: * Given an inode, and a mode containing permission flags, open the
288: * inode with the appropriate permissions and return a file descriptor
289: * containing it.
290: */
291:
292: #if __USE_PROTO__
293: fd_t fdopen (INODE * ip, int mode)
294: #else
295: fd_t
296: fdopen (ip, mode)
297: INODE * ip;
298: int mode;
299: #endif
300: {
301: int fd;
302:
303: if ((fd = fdalloc ()) != ERROR_FD) {
304: fdinit (fd, ip, mode);
305: fd = fdfinish (fd);
306: }
307:
308: return fd;
309: }
310:
311:
312: /*
313: * Close the given file number.
314: */
315:
316: #if __USE_PROTO__
317: void fdclose (unsigned fd)
318: #else
319: void
320: fdclose(fd)
321: unsigned fd;
322: #endif
323: {
324: register FD *fdp;
325: static struct flock flock = { F_UNLCK, 0, 0, 0 };
326:
327: if (fd >= NOFILE ||
328: (fdp = GET_UNTAGGED_FD (u.u_filep [fd])) == NULL) {
329: u.u_error = EBADF;
330: return;
331: }
332:
333: if (fdp->f_ip->i_rl != NULL)
334: rlock (fdp, F_SETLK, & flock); /* delete all record locks */
335:
336: u.u_filep[fd] = NULL;
337:
338: if (fdp->f_refc == 0)
339: panic("fdclose()");
340:
341: if (-- fdp->f_refc == 0) {
342: iclose (fdp->f_ip, fdp->f_flag);
343: kfree (fdp);
344: }
345: }
346:
347:
348: /*
349: * Assuming we have made a copy of the user area, increment the reference
350: * of all open files. (used in fork).
351: */
352:
353: #if __USE_PROTO__
354: void fdadupl (void)
355: #else
356: void
357: fdadupl ()
358: #endif
359: {
360: int i;
361:
362: for (i = 0 ; i < NOFILE ; i ++)
363: if (u.u_filep [i] != NULL)
364: GET_UNTAGGED_FD (u.u_filep [i])->f_refc ++;
365: }
366:
367:
368: /*
369: * Close all open files in the current process.
370: */
371:
372: #if __USE_PROTO__
373: void fdaclose (void)
374: #else
375: void
376: fdaclose()
377: #endif
378: {
379: int fd;
380:
381: for (fd = 0 ; fd < NOFILE ; fd ++)
382: if (u.u_filep [fd] != NULL)
383: fdclose (fd);
384: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.