|
|
1.1 root 1: /* $Header: /kernel/kersrc/coh.286/RCS/sys2.c,v 1.1 92/07/17 15:18:51 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: /*
17: * Coherent.
18: * System calls (filesystem related).
19: *
20: * $Log: sys2.c,v $
21: * Revision 1.1 92/07/17 15:18:51 bin
22: * Initial revision
23: *
24: * Revision 1.1 91/04/30 13:56:54 root
25: * Shipped with COH 3.1.0.
26: *
27: */
28: #include <sys/coherent.h>
29: #include <errno.h>
30: #include <fcntl.h>
31: #include <sys/fd.h>
32: #include <sys/ino.h>
33: #include <sys/inode.h>
34: #include <sys/mount.h>
35: #include <sys/poll.h>
36: #include <sys/sched.h>
37: #include <sys/stat.h>
38:
39: /*
40: * Determine accessibility of the given file.
41: */
42: uaccess(np, mode)
43: char *np;
44: register int mode;
45: {
46: register INODE *ip;
47: register int r;
48:
49: schizo();
50: r = ftoi(np, 'r');
51: schizo();
52: if (r != 0)
53: return;
54: ip = u.u_cdiri;
55: if ((mode&imode(ip, u.u_ruid, u.u_rgid)) != mode)
56: u.u_error = EACCES;
57: idetach(ip);
58: return (0);
59: }
60:
61: /*
62: * Schizo - swap real and effective id's.
63: */
64: schizo()
65: {
66: register int t;
67:
68: t = u.u_uid;
69: u.u_uid = u.u_ruid;
70: u.u_ruid = t;
71: t = u.u_gid;
72: u.u_gid = u.u_rgid;
73: u.u_rgid = t;
74: }
75:
76: /*
77: * Turn accounting on or off.
78: */
79: uacct(np)
80: register char *np;
81: {
82: register INODE *ip;
83:
84: if (super() == 0)
85: return;
86: if (np == NULL) {
87: if (acctip == NULL) {
88: u.u_error = EINVAL;
89: return;
90: }
91: ldetach(acctip);
92: acctip = NULL;
93: } else {
94: if (acctip != NULL) {
95: u.u_error = EINVAL;
96: return;
97: }
98: if (ftoi(np, 'r') != 0)
99: return;
100: ip = u.u_cdiri;
101: if ((ip->i_mode&IFMT) != IFREG) {
102: u.u_error = EINVAL;
103: idetach(ip);
104: return;
105: }
106: iunlock(ip);
107: acctip = ip;
108: }
109: return (0);
110: }
111:
112: /*
113: * Set current directory.
114: */
115: uchdir(np)
116: char *np;
117: {
118: setcdir(np, &u.u_cdir);
119: return (0);
120: }
121:
122: /*
123: * Given a directory name and a pointer to a working directory pointer,
124: * Save the inode associated with the directory name in the working
125: * directory pointer and release the old one. This is used to change
126: * working and root directories.
127: */
128: setcdir(np, ipp)
129: char *np;
130: register INODE **ipp;
131: {
132: register INODE *ip;
133:
134: if (ftoi(np, 'r') != 0)
135: return;
136: ip = u.u_cdiri;
137: if ((ip->i_mode&IFMT) != IFDIR) {
138: u.u_error = ENOTDIR;
139: idetach(ip);
140: return;
141: }
142: if (iaccess(ip, IPE) == 0) {
143: u.u_error = EACCES;
144: idetach(ip);
145: return;
146: }
147: iunlock(ip);
148: ldetach(*ipp);
149: *ipp = ip;
150: }
151:
152: /*
153: * Change the mode of a file.
154: */
155: uchmod(np, mode)
156: char *np;
157: {
158: register INODE *ip;
159:
160: if (ftoi(np, 'r') != 0)
161: return;
162: ip = u.u_cdiri;
163: if (owner(ip->i_uid)) {
164: if (u.u_uid != 0)
165: mode &= ~ISVTXT;
166: ip->i_mode &= IFMT;
167: ip->i_mode |= mode&~IFMT;
168: icrt(ip); /* chmod - ctime */
169: }
170: idetach(ip);
171: return (0);
172: }
173:
174: /*
175: * Change owner and group of a file.
176: */
177: uchown(np, uid, gid)
178: char *np;
179: {
180: register INODE *ip;
181:
182: if (ftoi(np, 'r') != 0)
183: return;
184: ip = u.u_cdiri;
185: if (super()) {
186: ip->i_mode &= ~(ISUID | ISGID); /* clear any setuid/setgid */
187: ip->i_uid = uid;
188: ip->i_gid = gid;
189: icrt(ip); /* chown - ctime */
190: }
191: idetach(ip);
192: return (0);
193: }
194:
195: /*
196: * Set root directory.
197: */
198: uchroot(np)
199: register char *np;
200: {
201: if (super())
202: setcdir(np, &u.u_rdir);
203: return (0);
204: }
205:
206: /*
207: * Close the given file descriptor.
208: */
209: uclose(fd)
210: {
211: fdclose(fd);
212: return (0);
213: }
214:
215: /*
216: * Create a file with the given mode.
217: */
218: ucreat(np, mode)
219: char *np;
220: register int mode;
221: {
222: register INODE *ip;
223: register int fd;
224: register int cflag;
225:
226: cflag = 0;
227: if (ftoi(np, 'c') != 0)
228: return;
229: if ((ip=u.u_cdiri) == NULL) {
230: if ((ip=imake((mode&~IFMT)|IFREG, 0)) == NULL)
231: return;
232: } else {
233: if (iaccess(ip, IPW)==0) {
234: idetach(ip);
235: return;
236: }
237: switch (ip->i_mode&IFMT) {
238: case IFBLK:
239: case IFCHR:
240: break;
241: case IFDIR:
242: u.u_error = EISDIR;
243: idetach(ip);
244: return;
245: default:
246: if (getment(ip->i_dev, 1) == NULL) {
247: idetach(ip);
248: return;
249: }
250: }
251: cflag = 1;
252: }
253: if ((fd=fdopen(ip, IPW)) < 0) {
254: idetach(ip);
255: return;
256: }
257: if (cflag)
258: iclear(ip);
259: iunlock(ip);
260: return (fd);
261: }
262:
263: /*
264: * Duplicate a file descriptor.
265: */
266: udup(ofd, nfd)
267: {
268: return (fddup(ofd, nfd));
269: }
270:
271: /*
272: * Given a file descriptor, return a status structure.
273: */
274: ufstat(fd, stp)
275: struct stat *stp;
276: {
277: register INODE *ip;
278: register FD *fdp;
279: struct stat stat;
280:
281: if ((fdp=fdget(fd)) == NULL)
282: return;
283: ip = fdp->f_ip;
284: istat(ip, &stat);
285: kucopy(&stat, stp, sizeof(stat));
286: return (0);
287: }
288:
289: /*
290: * File control.
291: */
292: ufcntl( fd, cmd, arg )
293: int fd, cmd, arg;
294: {
295: register FD * fdp;
296:
297: /*
298: * Validate file descriptor.
299: */
300: if ( (fd < 0) || (fd >= NUFILE) || ((fdp = u.u_filep[fd]) == 0) ) {
301: u.u_error = EBADF;
302: return;
303: }
304:
305: switch ( cmd ) {
306:
307: case F_DUPFD:
308: /*
309: * Validate base file descriptor.
310: */
311: if ( (arg < 0) || (arg >= NUFILE) ) {
312: u.u_error = EINVAL;
313: return;
314: }
315:
316: /*
317: * Search for next available file descriptor.
318: */
319: do {
320: if ( u.u_filep[arg] == 0 ) {
321: u.u_filep[arg] = fdp;
322: fdp->f_refc++;
323: return arg;
324: }
325: } while ( ++arg < NUFILE );
326:
327: u.u_error = EMFILE;
328: return;
329:
330: case F_SETFL:
331: fdp->f_flag &= ~IPNDLY;
332: if ( arg & O_NDELAY )
333: fdp->f_flag |= IPNDLY;
334: if ( arg & O_APPEND )
335: fdp->f_flag |= IPAPPEND;
336: /* no break */
337:
338: case F_GETFL:
339: switch ( fdp->f_flag & (IPR+IPW) ) {
340: case IPR: arg = O_RDONLY; break;
341: case IPW: arg = O_WRONLY; break;
342: default: arg = O_RDWR; break;
343: }
344: if ( fdp->f_flag & IPNDLY )
345: arg |= O_NDELAY;
346: if ( fdp->f_flag & IPAPPEND )
347: arg |= O_APPEND;
348: return arg;
349:
350: default:
351: u.u_error = EINVAL;
352: }
353: }
354:
355: /*
356: * Device control information.
357: */
358: uioctl(fd, r, argp)
359: struct sgttyb *argp;
360: {
361: register FD *fdp;
362: register INODE *ip;
363: register int mode;
364:
365: if ((fdp=fdget(fd)) == NULL)
366: return;
367: ip = fdp->f_ip;
368: mode = ip->i_mode&IFMT;
369: if (mode!=IFCHR && mode!=IFBLK) {
370: u.u_error = ENOTTY;
371: return;
372: }
373: dioctl(ip->i_a.i_rdev, r, argp);
374: return (0);
375: }
376:
377: /*
378: * Create a link, `np2' to the already existing file `np1'.
379: */
380: ulink(np1, np2)
381: char *np1;
382: char *np2;
383: {
384: register INODE *ip1;
385:
386: if (ftoi(np1, 'r') != 0)
387: return;
388: ip1 = u.u_cdiri;
389: if ((ip1->i_mode&IFMT)==IFDIR && super()==0) {
390: idetach(ip1);
391: return;
392: }
393: iunlock(ip1);
394: if (ftoi(np2, 'c') != 0) {
395: ldetach(ip1);
396: return;
397: }
398: if (u.u_cdiri != NULL) {
399: u.u_error = EEXIST;
400: idetach(u.u_cdiri);
401: ldetach(ip1);
402: return;
403: }
404: if (ip1->i_dev != u.u_pdiri->i_dev) {
405: u.u_error = EXDEV;
406: idetach(u.u_pdiri);
407: ldetach(ip1);
408: return;
409: }
410: if (iaccess(u.u_pdiri, IPW) == 0) {
411: idetach(u.u_pdiri);
412: ldetach(ip1);
413: return;
414: }
415: idirent(ip1->i_ino);
416: idetach(u.u_pdiri);
417: ilock(ip1);
418: ip1->i_nlink++;
419: icrt(ip1); /* link - ctime */
420: idetach(ip1);
421: return (0);
422: }
423:
424: /*
425: * Seek on the given file descriptor.
426: */
427: fsize_t
428: ulseek(fd, off, w)
429: register fsize_t off;
430: {
431: register FD *fdp;
432: register INODE *ip;
433:
434: if ((fdp=fdget(fd)) == NULL)
435: return;
436: ip = fdp->f_ip;
437: if ((ip->i_mode&IFMT) == IFPIPE) {
438: u.u_error = ESPIPE;
439: return;
440: }
441: switch (w) {
442: case 0:
443: break;
444: case 1:
445: off += fdp->f_seek;
446: break;
447: case 2:
448: off += ip->i_size;
449: break;
450: default:
451: u.u_error = EINVAL;
452: return;
453: }
454: if (off < 0) {
455: u.u_error = EINVAL;
456: return;
457: }
458: fdp->f_seek = off;
459: return (off);
460: }
461:
462: /*
463: * Create a special file.
464: */
465: umknod(np, mode, rdev)
466: char *np;
467: dev_t rdev;
468: {
469: register INODE *ip;
470: register int type;
471:
472: type = mode&IFMT;
473: if (type!=IFPIPE && super()==0)
474: return;
475: if (type!=IFBLK && type!=IFCHR)
476: rdev = 0;
477: if (ftoi(np, 'c') != 0)
478: return;
479: if ((ip=u.u_cdiri) != NULL) {
480: u.u_error = EEXIST;
481: idetach(ip);
482: return;
483: }
484: if ((ip=imake(mode, rdev)) != NULL)
485: idetach(ip);
486: return (0);
487: }
488:
489: /*
490: * Mount the device `sp' on the pathname `np'. The flag, `f',
491: * indicates that the device is to be mounted read only.
492: */
493: umount(sp, np, f)
494: char *sp;
495: char *np;
496: {
497: register INODE *ip;
498: register MOUNT *mp;
499: register dev_t rdev;
500: register int mode;
501:
502: if (ftoi(sp, 'r') != 0)
503: return;
504: ip = u.u_cdiri;
505: if (iaccess(ip, IPR|IPW) == 0)
506: goto err;
507: mode = ip->i_mode;
508: rdev = ip->i_a.i_rdev;
509: if ((mode&IFMT) != IFBLK) {
510: u.u_error = ENOTBLK;
511: goto err;
512: }
513: idetach(ip);
514: if (ftoi(np, 'r') != 0)
515: return;
516: ip = u.u_cdiri;
517: if (iaccess(ip, IPR) == 0)
518: goto err;
519: if ((ip->i_mode&IFMT) != IFDIR) {
520: u.u_error = ENOTDIR;
521: goto err;
522: }
523: /* Check for current directory, open, or mount directory */
524: if (ip->i_refc > 1 || ip->i_ino == ROOTIN) {
525: u.u_error = EBUSY;
526: goto err;
527: }
528: for (mp=mountp; mp!=NULL; mp=mp->m_next) {
529: if (mp->m_dev == rdev) {
530: u.u_error = EBUSY;
531: goto err;
532: }
533: }
534: if ((mp=fsmount(rdev, f)) == NULL)
535: goto err;
536: mp->m_ip = ip;
537: ip->i_flag |= IFMNT;
538: ip->i_refc++;
539: err:
540: idetach(ip);
541: return (0);
542: }
543:
544: /*
545: * Poll devices for input/output events.
546: */
547: int
548: upoll( pollfds, npoll, msec )
549: struct pollfd * pollfds;
550: unsigned long npoll;
551: int msec;
552: {
553: register struct pollfd * pollp; /* current poll pointer */
554: register FD * fdp; /* current file descriptor ptr */
555: auto int fd; /* current file descriptor */
556: auto int rev; /* last event report received */
557: auto int nev; /* number non-zero event reports */
558: auto int i;
559: extern char * udl;
560:
561: /*
562: * Validate number of polls.
563: */
564: if ( (npoll < 0) || (npoll > NUFILE) ) {
565: u.u_error = EINVAL;
566: return;
567: }
568:
569: /*
570: * Validate address of polling information.
571: */
572: pollp = &pollfds[npoll];
573: if ( (pollfds == NULL) || (pollp < pollfds) || (pollp > udl) ) {
574: u.u_error = EFAULT;
575: return;
576: }
577:
578: do {
579: /*
580: * Service each poll in turn.
581: */
582: for ( nev=0, i=npoll, pollp = pollfds; i > 0; --i, pollp++ ) {
583:
584: /*
585: * Fetch file descriptor.
586: */
587: fd = getuwd( &pollp->fd );
588:
589: /*
590: * Ignore negative file descriptors.
591: */
592: if ( fd < 0 ) {
593: rev = 0;
594: }
595:
596: /*
597: * Poll message queue.
598: */
599: else if ( fd >= NUFILE ) {
600: #ifdef MSGPOLL
601: /*
602: * this code only good if msgpoll() is available to the kernel -
603: * no good with loadable msg driver
604: */
605: rev = msgpoll( fd,
606: getuwd( &pollp->events),
607: msec );
608: #else
609: rev = POLLNVAL;
610: #endif
611: }
612:
613: /*
614: * Validate file descriptor.
615: */
616: else if ( (fdp = u.u_filep[fd]) == 0 ) {
617: rev = POLLNVAL;
618: }
619:
620: /*
621: * Non-character device.
622: */
623: else if ( (fdp->f_ip->i_mode & IFMT) != IFCHR ) {
624: rev = POLLNVAL;
625: }
626:
627: /*
628: * Poll character device driver.
629: */
630: else {
631: rev = dpoll( fdp->f_ip->i_a.i_rdev,
632: getuwd(&pollp->events),
633: msec );
634: }
635:
636: /*
637: * Remember reponses.
638: */
639: putuwd( &pollp->revents, rev );
640:
641: /*
642: * Record number of non-zero responses.
643: */
644: if ( rev != 0 ) {
645: msec = 0;
646: nev++;
647: }
648: }
649:
650: /*
651: * Non-blocking poll or poll response received.
652: */
653: if ( msec == 0 ) {
654: pollexit();
655: return nev;
656: }
657:
658: /*
659: * Schedule wakeup timer if positive delay interval given.
660: */
661: if ( msec > 0 ) {
662: /*
663: * Convert milliseconds to clock ticks.
664: */
665: msec += (1000 / HZ) - 1;
666: msec /= (1000 / HZ);
667: timeout( &cprocp->p_polltim, msec,
668: wakeup, &cprocp->p_polls );
669: }
670:
671: /*
672: * Wake for polled event, poll timeout, or signal.
673: */
674: sleep( &cprocp->p_polls, CVTTOUT, IVTTOUT, SVTTOUT );
675:
676: /*
677: * Terminate event monitoring.
678: */
679: pollexit();
680:
681: /*
682: * Perform non-blocking poll after first poll timeout.
683: */
684: if ( msec > 0 ) {
685: timeout( &cprocp->p_polltim, 0, NULL, NULL );
686: msec = 0;
687: }
688:
689: /*
690: * Signal woke us up.
691: */
692: if ( nondsig() ) {
693: u.u_error = EINTR;
694: return -1;
695: }
696:
697: } while ( msec != 0 );
698:
699: return 0;
700: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.