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