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