|
|
1.1 root 1: /* $Header: /y/coh.386/RCS/sys3.c,v 1.5 92/07/16 16:33:36 hal 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: * System calls (more filesystem related calls).
18: *
19: * $Log: sys3.c,v $
20: * Revision 1.5 92/07/16 16:33:36 hal
21: * Kernel #58
22: *
23: * Revision 1.3 92/02/20 19:37:59 piggy
24: * Three-argument S5-style open().
25: *
26: * Revision 1.2 92/01/06 12:00:52 hal
27: * Compile with cc.mwc.
28: *
29: * Revision 1.3 89/02/07 18:50:27 src
30: * Bug: Console driver did not validate user addresses before initiating a
31: * transfer. This resulted in a system trap in protected mode if a write
32: * outside of user data space was attempted.
33: * Fix: Reads and writes now validate user addresses via 'useracc' prior to
34: * calling drivers. (ABC)
35: *
36: * Revision 1.2 88/08/02 15:01:04 src
37: * O_APPEND flag now supported on open/fcntl system calls.
38: *
39: * Revision 1.1 88/03/24 16:14:35 src
40: * Initial revision
41: *
42: * 88/01/22 Allan Cornish /usr/src/sys/coh/sys3.c
43: * sysio() inode lock extended to cover getting/modifying file seek offset.
44: *
45: * 86/11/19 Allan Cornish /usr/src/sys/coh/sys3.c
46: * uopen() now checks mode for O_NDELAY and sets IPNDLY bit in fdp->f_flag.
47: * sysio() now checks fdp->f_flag for IPNDLY and sets IONDLY bit in io_flag.
48: */
49: #include <sys/coherent.h>
50: #include <sys/buf.h>
51: #include <errno.h>
52: #include <fcntl.h>
53: #include <sys/fd.h>
54: #include <sys/filsys.h>
55: #include <sys/ino.h>
56: #include <sys/inode.h>
57: #include <sys/io.h>
58: #include <sys/mount.h>
59: #include <sys/stat.h>
60:
61: /*
62: * Open the file `np' with the mode `mode'.
63: */
64: uopen(np, oflag, magic)
65: char *np;
66: {
67: register int f;
68: register INODE *ip;
69: register int fd;
70: int cflag; /* Flag is set if we create a file. */
71:
72: cflag = 0; /* Nothing created so far. */
73:
74: /* Determine read or write status for fdopen. */
75:
76: switch (oflag & 3) {
77: case O_RDONLY:
78: f = IPR;
79: break;
80: case O_WRONLY:
81: f = IPW;
82: break;
83: case O_RDWR:
84: f = IPR|IPW;
85: break;
86: default:
87: SET_U_ERROR( EINVAL, "bad oflag" );
88: T_PIGGY( 0x10000, printf("<open: bad oflag %x>", oflag); );
89: return;
90: }
91:
92: /* Process the O_CREAT flag. */
93: if ( oflag & O_CREAT ) {
94: if (ftoi(np, 'c') != 0) {
95: T_PIGGY( 0x10000,
96: printf("<open: bad ftoi(%s, 'c')>", np); );
97: return;
98: }
99:
100: /* If it didn't exist, but its parent did, then make it. */
101: if ((ip=u.u_cdiri) == NULL) {
102: if ((ip=imake((magic&~IFMT)|IFREG, 0)) == NULL) {
103: T_PIGGY( 0x10000,
104: printf("<open: bad imake(%x, 0)>",
105: (magic&~IFMT)|IFREG);
106: );
107: return;
108: }
109: cflag = 1; /* Note that we just created a file. */
110: } else { /* The file already exists. */
111: /*
112: * Exclusive O_CREAT on existing file should fail.
113: */
114: if ( oflag & O_EXCL ) {
115: idetach(ip);
116: SET_U_ERROR( EEXIST,
117: "exclusive creat on existing file");
118: return;
119: }
120: /* Do not write to a read only file system;
121: * never write to a directory;
122: * always write to block and character special devices.
123: */
124: switch (ip->i_mode&IFMT) {
125: case IFBLK:
126: case IFCHR:
127: break;
128: case IFDIR:
129: idetach(ip);
130: SET_U_ERROR( EISDIR, "<open: EISDIR>" );
131: return;
132: default:
133: if (getment(ip->i_dev, 1) == NULL) {
134: idetach(ip);
135: SET_U_ERROR( EROFS,
136: "Could not fetch mount entry");
137: T_PIGGY( 0x10000,
138: printf("<open: bad getment(ip->i_dev: %x, 1)>", ip->i_dev); );
139: return;
140: }
141: }
142: } /* Did the file exist? */
143:
144: } else { /* O_CREAT was not set--just reference the file. */
145: if (ftoi(np, 'r') != 0) {
146: T_PIGGY( 0x10000, printf("<open: bad ftoi(%s, 'r')>",
147: np);
148: );
149: return;
150: }
151: ip = u.u_cdiri; /* This must be the inode we wanted. */
152: }
153:
154: /*
155: * ASSERTION: We probably have an inode for an existing file.
156: * If we don't, the ip will be NULL and iaccess() will fail (as
157: * desired.)
158: */
159:
160: /*
161: * Only check permissions on a pre-existing file.
162: */
163: if ((0 == cflag) && (iaccess(ip, f) == 0)) {
164: idetach(ip);
165: T_PIGGY( 0x10000,
166: printf("<open: bad access(ip:%x, f:%x)>", ip, f);
167: );
168: return;
169: }
170:
171: /*
172: * ASSERTION: We have an inode for a file we
173: * have valid permissions on.
174: */
175:
176: if ( ip->i_flag & IFEXCL) {
177: idetach(ip);
178: SET_U_ERROR( EEXIST, "open: file already open O_EXCL" );
179: return; /* Somebody else has an exclusive open. */
180: }
181:
182: /*
183: * If requesting exclusive open, fail if someone else has it open.
184: */
185: if ( oflag & O_EXCL ) {
186: if (ip->i_refc != 1) {
187: idetach(ip);
188: SET_U_ERROR( EEXIST, "<open: O_EXCL but already open>" );
189: return;
190: }
191:
192: /* Mark this open inode as exclusive. */
193: ip->i_flag &= IFEXCL;
194: }
195:
196: if ( oflag & O_NDELAY ) {
197: f |= IPNDLY;
198: }
199: if ( oflag & O_APPEND ) {
200: f |= IPAPPEND;
201: }
202: if ( oflag & O_SYNC ) {
203: f |= IPSYNC;
204: }
205: if ( oflag & O_EXCL ) {
206: f |= IPEXCL;
207: }
208: if ( oflag & O_NOCTTY ) {
209: f |= IPNOCTTY;
210: }
211:
212: if ((fd=fdopen(ip, f)) < 0) {
213: idetach(ip);
214: T_PIGGY( 0x10000,
215: printf("<open: bad fdopen(ip: %x, f: %x>", ip, f);
216: );
217: return;
218: }
219:
220: /* If requested, truncate the file. */
221: if ( oflag & O_TRUNC ) {
222: if (0 == cflag) { /* No need to truncate a new file. */
223: if (iaccess(ip, IPW) != 0) {
224: iclear(ip);
225: } else {
226: idetach(ip);
227: T_PIGGY( 0x10000,
228: printf("<open: No access to truncate.>");
229: );
230: return;
231: }
232: }
233: }
234:
235: iunlock(ip);
236: return (fd);
237: }
238:
239: /*
240: * Create a pipe.
241: */
242: upipe(fdp)
243: short fdp[2];
244: {
245: register INODE *ip;
246: register int fd1;
247: register int fd2;
248:
249: if ((ip=pmake(0)) == NULL)
250: return;
251: if ((fd1=fdopen(ip, IPR)) >= 0) {
252: ip->i_refc++;
253: if ((fd2=fdopen(ip, IPW)) >= 0) {
254: iunlock(ip);
255: u.u_rval2 = fd2;
256: return fd1;
257: }
258: --ip->i_refc;
259: iunlock(ip);
260: fdclose(fd1);
261: return 0;
262: }
263: idetach(ip);
264: return 0;
265: }
266:
267: /*
268: * Read `n' bytes into the buffer `bp' from file number `fd'.
269: */
270: uread(fd, bp, n)
271: char *bp;
272: unsigned n;
273: {
274: T_PIGGY( 0x200, printf("uread(fd: %d, bp: %x, n: %d)", fd, bp, n); );
275: return (sysio(fd, bp, n, 0));
276: }
277:
278: /*
279: * Read or write `n' bytes from the file number `fd' using the buffer
280: * `bp'. If `do_write' is nonzero, write, else read.
281: */
282: int
283: sysio(fd, bp, n, do_write)
284: int fd;
285: char *bp;
286: unsigned n;
287: int do_write;
288: {
289: register FD *fdp;
290: register INODE *ip;
291: register int type;
292:
293: if ((fdp=fdget(fd)) == NULL)
294: return 0;
295: if ((fdp->f_flag&(do_write?IPW:IPR)) == 0) {
296: u.u_error = EBADF;
297: return 0;
298: }
299:
300: /*
301: * When reading, buffer may NOT be in text segment.
302: */
303: if (!useracc(bp, n) && do_write == 0) {
304: u.u_error = EFAULT;
305: return 0;
306: }
307:
308: /*
309: * When writing, buffer may be in text segment.
310: */
311: if (!useracc(bp, n) && !acctext(bp, n)) {
312: u.u_error = EFAULT;
313: return 0;
314: }
315:
316: ip = fdp->f_ip;
317: type = ip->i_mode&IFMT;
318: if (type != IFCHR)
319: ilock(ip);
320: if ( fdp->f_flag & IPAPPEND )
321: fdp->f_seek = ip->i_size;
322: u.u_io.io_seek = fdp->f_seek;
323: u.u_io.io.vbase = (vaddr_t) bp;
324: u.u_io.io_ioc = n;
325: u.u_io.io_flag = (fdp->f_flag & IPNDLY) ? IONDLY : 0;
326: if (do_write) {
327: iwrite(ip, &u.u_io);
328: } else {
329: iread(ip, &u.u_io);
330: iacc(ip); /* read - atime */
331: }
332: n -= u.u_io.io_ioc;
333: fdp->f_seek += n;
334: if (type != IFCHR)
335: iunlock(ip);
336:
337: /* Was this inode opened for synchronous writes? */
338: if (fdp->f_flag & IPSYNC)
339: isync(ip->i_dev);
340:
341: return n;
342: }
343:
344: /*
345: * Return a status structure for the given file name.
346: */
347: ustat(np, stp)
348: char *np;
349: struct stat *stp;
350: {
351: register INODE *ip;
352: struct stat stat;
353:
354: if (ftoi(np, 'r') != 0)
355: return;
356: ip = u.u_cdiri;
357: istat(ip, &stat);
358: idetach(ip);
359: kucopy(&stat, stp, sizeof(stat));
360: return 0;
361: }
362:
363: /*
364: * Write out all modified buffers, inodes and super blocks to disk.
365: */
366: usync()
367: {
368: register MOUNT *mp;
369: static GATE syngate;
370:
371: lock(syngate);
372: for (mp=mountp; mp!=NULL; mp=mp->m_next)
373: msync(mp);
374: bsync();
375: unlock(syngate);
376: return 0;
377: }
378:
379: /*
380: * Set the mask for file access.
381: */
382: uumask(mask)
383: {
384: register int omask;
385:
386: omask = u.u_umask;
387: u.u_umask = mask & 0777;
388: return (omask);
389: }
390:
391: /*
392: * Unmount the given device.
393: */
394: uumount(sp)
395: char *sp;
396: {
397: register INODE *ip;
398: register MOUNT *mp;
399: register MOUNT **mpp;
400: register dev_t rdev;
401: register int mode;
402:
403: if (ftoi(sp, 'r') != 0)
404: return;
405: ip = u.u_cdiri;
406: if (iaccess(ip, IPR|IPW) == 0) {
407: idetach(ip);
408: return;
409: }
410: rdev = ip->i_a.i_rdev;
411: mode = ip->i_mode;
412: idetach(ip);
413: if ((mode&IFMT) != IFBLK) {
414: u.u_error = ENOTBLK;
415: return;
416: }
417: for (mpp=&mountp; (mp=*mpp)!=NULL; mpp=&mp->m_next)
418: if (mp->m_dev == rdev)
419: break;
420: if (mp == NULL) {
421: u.u_error = EINVAL;
422: return;
423: }
424: msync(mp);
425: for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
426: if (ip->i_refc>0 && ip->i_dev==rdev) {
427: u.u_error = EBUSY;
428: return;
429: }
430: }
431: for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
432: if (ip->i_dev == rdev)
433: ip->i_ino = 0;
434: }
435: bflush(rdev);
436: dclose(rdev);
437: *mpp = mp->m_next;
438: mp->m_ip->i_flag &= ~IFMNT;
439: ldetach(mp->m_ip);
440: kfree(mp);
441: return 0;
442: }
443:
444: /*
445: * Unlink the given file.
446: */
447: uunlink(np)
448: char *np;
449: {
450: register INODE *ip;
451: register dev_t dev;
452:
453: if (ftoi(np, 'u') != 0)
454: return;
455: ip = u.u_pdiri;
456: if (iaccess(ip, IPW) == 0) {
457: u.u_error = EACCES;
458: goto err;
459: }
460: dev = ip->i_dev;
461: if (iucheck(dev, u.u_cdirn) == 0)
462: goto err;
463: idirent(0);
464: idetach(ip);
465: if ((ip=iattach(dev, u.u_cdirn)) == NULL)
466: return;
467: if (ip->i_nlink > 0)
468: --ip->i_nlink;
469: icrt(ip); /* unlink - ctime */
470: if ((ip->i_mode&IFMT)==IFPIPE && ip->i_nlink==0 && ip->i_refc==2)
471: pevent(ip);
472: err:
473: idetach(ip);
474: return 0;
475: }
476:
477: /*
478: * Set file times.
479: */
480: uutime(np, utime)
481: char *np;
482: time_t utime[2];
483: {
484: register INODE *ip;
485: time_t stime[2];
486:
487: if (ftoi(np, 'r') != 0)
488: return;
489: ip = u.u_cdiri;
490: if (owner(ip->i_uid)) {
491: iamc(ip); /* utime - atime/mtime/ctime */
492: if (utime != NULL) {
493: ukcopy(utime, stime, sizeof(time_t[2]));
494: ip->i_atime = stime[0];
495: ip->i_mtime = stime[1];
496: }
497: }
498: idetach(ip);
499: return 0;
500: }
501:
502: /*
503: * Write `n' bytes from buffer `bp' on file number `fd'.
504: */
505: uwrite(fd, bp, n)
506: char *bp;
507: unsigned n;
508: {
509: return (sysio(fd, bp, n, 1));
510: }
511:
512: /**
513: *
514: * int
515: * useracc( base, count, mode ) -- determine user accessibility
516: * caddr_t base;
517: * int count;
518: * int mode;
519: *
520: * Input: base = offset in user data space of the region to be accessed.
521: * count = size of access region in bytes.
522: * mode = access mode desired [B_READ or B_WRITE].
523: *
524: * Action: Verify user has desired access mode into specified region.
525: *
526: * Return: 0 = permission denied.
527: * 1 = access allowed.
528: *
529: * Notes: Mode is ignored for now, but is required for compatibility
530: * with System V, and future protected mode extensions.
531: */
532: int
533: useracc( base, count, mode )
534: register char *base;
535: int mode, count;
536: {
537: if (base+count < base) {
538: return 0;
539: }
540: return accdata(base, count) || accstack(base, count);
541: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.