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