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