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