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