|
|
1.1 root 1: /* $Header: /src386/STREAMS/coh.386/RCS/fs1.c,v 2.5 93/08/09 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 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: * Filesystem (mostly handling of in core inodes).
18: *
19: * $Log: fs1.c,v $
20: * Revision 2.5 93/08/09 13:35:29 bin
21: * Kernel 82 changes
22: *
23: * Revision 2.2 93/07/26 15:19:00 nigel
24: * Nigel's R80
25: *
26: * Revision 1.8 93/04/14 10:06:28 root
27: * r75
28: *
29: * Revision 1.7 93/02/23 15:50:51 root
30: * after caddr_t change, before blclear
31: *
32: * Revision 1.4 92/07/16 16:33:32 hal
33: * Kernel #58
34: *
35: * Revision 1.3 92/02/06 17:55:36 vlad
36: * Fix typo in ialloc panic.
37: *
38: * Revision 1.2 92/01/06 11:59:17 hal
39: * Compile with cc.mwc.
40: *
41: * Revision 1.1 88/03/24 16:13:47 src
42: * Initial revision
43: *
44: * 86/12/13 Allan Cornish /usr/src/sys/coh/fs1.c
45: * isync() no longer updates the disk image of a character device inode.
46: *
47: * 86/11/19 Allan Cornish /usr/src/sys/coh/fs1.c
48: * idirent() initializes the (new) (IO).io_flag field to 0.
49: */
50: #include <sys/coherent.h>
51: #include <sys/buf.h>
52: #include <canon.h>
53: #include <dirent.h>
54: #include <sys/errno.h>
55: #include <sys/filsys.h>
56: #include <sys/ino.h>
57: #include <sys/inode.h>
58: #include <sys/io.h>
59: #include <sys/mount.h>>
60: #include <sys/stat.h>
61: #include <sys/file.h>
62:
63: /*
64: * Get character for `ftoi' depending on what space the characters are
65: * coming from.
66: */
67:
68: #define ftoic(p,seg) ((seg) == IOSYS ? * (p) : getubd (p))
69:
70: /*
71: * Map the given filename to an inode. If an error is encountered,
72: * `u.u_error' is set. `u.u_error' is always returned. As this routine
73: * needs to set several things, depending on the type of access, `t',
74: * there are places in the processes' user area reserved for this routine
75: * to set. These are defined in the user process structure. The seek
76: * position is always set to the position of the directory entry of the
77: * child if the child exists or the first free position if it doesn't.
78: * 'r' => Reference. A pointer to the child's inode is returned locked.
79: * 'c' => Create. If the child exists, a pointer to the inode is returned
80: * locked. Otherwise if the parent directory exists, a pointer to
81: * the parent directory is returned locked. Otherwise, an error.
82: * 'u' => Unlink. The parent directory is returned unlocked. The child's
83: * inode number is returned. The seek position is also set.
84: */
85:
86: int
87: ftoi (np, t, iop, dirent)
88: char * np;
89: int t;
90: IO * iop;
91: struct direct * dirent;
92: {
93: return file_to_inode (np, t, 0, iop, dirent);
94: }
95:
96: /*
97: * Does main ftoi job. Was created to solve the problem with rmdir.
98: * doRmdir is 0 for all cases except when called from rmdir.
99: */
100:
101: int
102: file_to_inode (np, t, doRmdir, iop, dirent)
103: char * np;
104: int t;
105: int doRmdir;
106: IO * iop;
107: struct direct * dirent;
108: {
109: register INODE *cip;
110: register char *cp;
111: register int c;
112: register struct direct *dp;
113: register BUF *bp;
114: off_t cseek, fseek, s;
115: int fflag, mflag;
116: dev_t dev;
117: ino_t ino;
118: daddr_t b;
119:
120: u.u_cdirn = 0;
121: u.u_cdiri = NULL;
122: u.u_pdiri = NULL;
123:
124: if ((c = ftoic (np ++, iop->io_seg)) != '/') {
125: cip = u.u_cdir;
126: } else {
127: c = ftoic (np ++, iop->io_seg);
128: cip = u.u_rdir;
129: }
130: while (c == '/')
131: c = ftoic (np ++, iop->io_seg);
132: ilock (cip);
133: cip->i_refc ++;
134:
135: if (c == '\0') {
136: if (t == 'r') {
137: u.u_cdiri = cip;
138: return u.u_error;
139: }
140:
141: idetach (cip);
142: return u.u_error = ENOENT;
143: }
144:
145: for (;;) {
146: cp = dirent->d_name;
147: while (c != '/' && c != '\0') {
148: if (cp < & dirent->d_name [sizeof (dirent->d_name)])
149: * cp ++ = c;
150: c = ftoic (np ++, iop->io_seg);
151: }
152:
153: while (c == '/')
154: c = ftoic (np ++, iop->io_seg);
155:
156: while (cp < & dirent->d_name [sizeof (dirent->d_name)])
157: * cp ++ = '\0';
158:
159: if ((cip->i_mode & IFMT) != IFDIR)
160: u.u_error = ENOTDIR;
161: else {
162: /* For rmdir we need only write */
163: if (doRmdir)
164: iaccess (cip, IPW);
165: else
166: iaccess (cip, IPE);
167: }
168:
169: if (u.u_error) {
170: idetach (cip);
171: return u.u_error;
172: }
173:
174: cp = dirent->d_name;
175:
176: if (cip->i_ino == ROOTIN && cip->i_dev != rootdev &&
177: * cp ++ == '.' && * cp ++ == '.' && * cp ++ == '\0')
178: cip = ftoim (cip);
179:
180: b = 0;
181: fflag = 0;
182: mflag = 0;
183: cseek = 0;
184: s = cip->i_size;
185:
186: while (s > 0) {
187: if ((bp = vread (cip, b ++)) == NULL) {
188: idetach (cip);
189: return u.u_error;
190: }
191:
192: dp = bp->b_vaddr;
193: while (dp < bp->b_vaddr + BSIZE) {
194:
195: if ((s -= sizeof (* dp)) < 0)
196: break;
197:
198: if ((ino = dp->d_ino) == 0) {
199: if (fflag == 0) {
200: fflag++;
201: fseek = cseek;
202: }
203: } else if (direq (dp, dirent)) {
204: canino (ino);
205: mflag = 1;
206: s = 0;
207: break;
208: }
209: cseek += sizeof (* dp);
210: dp ++;
211: }
212: brelease (bp);
213: }
214:
215: dev = cip->i_dev;
216: if (fflag == 0)
217: fseek = cseek;
218:
219: if (mflag == 0) {
220: if (c == '\0' && t == 'c') {
221: u.u_pdiri = cip;
222: iop->io_seek = fseek;
223: } else {
224: u.u_error = ENOENT;
225: idetach (cip);
226: }
227: return u.u_error;
228: }
229:
230: if (c == '\0') {
231: if (t == 'u') {
232: u.u_cdirn = ino;
233: u.u_pdiri = cip;
234: iop->io_seek = cseek;
235: return u.u_error;
236: }
237:
238: idetach (cip);
239: u.u_cdiri = iattach (dev, ino);
240: return u.u_error;
241: }
242:
243: idetach (cip);
244: if ((cip = iattach (dev, ino)) == NULL)
245: return u.u_error;
246: }
247: }
248:
249:
250: /*
251: * Given an inode which is the root of a file system, return the inode
252: * on which the file system was mounted.
253: */
254: INODE *
255: ftoim(ip)
256: register INODE *ip;
257: {
258: register MOUNT *mp;
259:
260: for (mp = mountp ; mp != NULL ; mp = mp->m_next) {
261: if (mp->m_dev == ip->i_dev) {
262: idetach (ip);
263: ip = mp->m_ip;
264: ilock (ip);
265: ip->i_refc ++;
266: break;
267: }
268: }
269: return ip;
270: }
271:
272:
273: /*
274: * Compare the string in `u.u_direct.d_name' with the name in the
275: * given directory pointer.
276: */
277:
278: direq (dp1, dp2)
279: struct direct * dp1;
280: struct direct * dp2;
281: {
282: return dp1->d_ino == 0 ? 0 :
283: strncmp (dp1->d_name, dp2->d_name, sizeof (dp1->d_name)) == 0;
284: }
285:
286:
287: /*
288: * Make an inode of the given mode and device. The parent directory,
289: * name and such stuff is set by ftoi.
290: */
291:
292: INODE *
293: imake (mode, rdev, iop, dirent)
294: unsigned mode;
295: dev_t rdev;
296: IO * iop;
297: struct direct * dirent;
298: {
299: register INODE *ip;
300:
301: ip = NULL;
302: mode &= ~ u.u_umask;
303: if ((mode & ISVTXT) != 0 && super () == 0)
304: goto det;
305:
306: if (iaccess (u.u_pdiri, IPW) == 0)
307: goto det;
308:
309: if ((ip = ialloc (u.u_pdiri->i_dev, mode)) == NULL)
310: goto det;
311:
312: ip->i_nlink = 1;
313: ip->i_a.i_rdev = rdev;
314: idirent (ip->i_ino, iop, dirent);
315: iamc (ip); /* creat/mknod - atime/mtime/ctime */
316: det:
317: idetach (u.u_pdiri);
318: return ip;
319: }
320:
321:
322: /*
323: * Write a directory entry out. Everything necessary has been conveniently
324: * set by `ftoi', except the new inode number of this directory entry.
325: */
326:
327: idirent (ino, iop, dirent)
328: IO * iop;
329: struct direct * dirent;
330: {
331: dirent->d_ino = ino;
332: canino (dirent->d_ino);
333:
334: iop->io_ioc = sizeof (struct direct);
335: iop->io.vbase = dirent;
336: iop->io_seg = IOSYS;
337: iop->io_flag = 0;
338:
339: iwrite (u.u_pdiri, iop);
340: }
341:
342:
343: /*
344: * Return a pointer to a locked inode in core containing the given
345: * inode number and device.
346: */
347:
348: INODE *
349: iattach (dev, ino)
350: {
351: register INODE *ip;
352: register INODE *fip;
353: register unsigned lrt;
354: register MOUNT *mp;
355:
356: for (;;) {
357: fip = NULL;
358: for (ip = & inodep [NINODE - 1] ; ip >= inodep ; -- ip) {
359: if (ip->i_ino == ino && ip->i_dev == dev)
360: break;
361: if (ip->i_refc == 0) {
362: if (fip == NULL || ip->i_lrt < lrt) {
363: fip = ip;
364: lrt = ip->i_lrt;
365: }
366: }
367: }
368:
369: if (ip < inodep) {
370: if ((ip = fip) == NULL) {
371: devmsg (dev, "Inode table overflow");
372: u.u_error = ENFILE;
373: return NULL;
374: }
375: ilock (ip);
376: if (ip->i_refc != 0) {
377: iunlock (ip);
378: continue;
379: }
380: ip->i_dev = dev;
381: ip->i_ino = ino;
382: ip->i_refc = 1;
383: ip->i_lrt = timer.t_time;
384: ip->i_lastblock = -1;
385: if (icopydm (ip) == 0) {
386: ip->i_ino = 0;
387: ip->i_refc = 0;
388: iunlock (ip);
389: return NULL;
390: }
391: return ip;
392: }
393: if ((ip->i_flag & IFMNT) != 0) {
394: for (mp = mountp ; mp != NULL ; mp = mp->m_next) {
395: if (mp->m_ip == ip) {
396: ino = ROOTIN;
397: dev = mp->m_dev;
398: break;
399: }
400: }
401: continue;
402: }
403: ilock (ip);
404: if (ip->i_ino != ino || ip->i_dev != dev) {
405: iunlock (ip);
406: continue;
407: }
408: if (ip->i_refc < 0)
409: panic ("iattach(%x)", ip);
410: ip->i_refc ++;
411: ip->i_lrt = timer.t_time;
412: return ip;
413: }
414: }
415:
416: /*
417: * Given a locked inode, deaccess it.
418: */
419: idetach(ip)
420: register INODE *ip;
421: {
422: #if 0
423: if (ilocked (ip) == 0 || ip->i_refc <= 0)
424: panic("idetach(%p)", ip);
425: #else
426: if (ilocked (ip) == 0) {
427: printf ("bad unlocked inode, dev=%x, ino=%d, flags=%x\n",
428: ip->i_dev, ip->i_ino, ip->i_flag);
429: panic ("idetach(%p)", ip);
430: }
431: if (ip->i_refc <= 0) {
432: printf ("negative refc, dev=%x, ino=%d, flags=%x, refc=%d\n",
433: ip->i_dev, ip->i_ino, ip->i_flag, ip->i_refc);
434: panic ("idetach(%p)", ip);
435: }
436: #endif
437: if (-- ip->i_refc == 0) {
438: #if 1
439: if (ip->i_rl)
440: panic ("idetach(%p) with locked records", ip);
441: #endif
442: if ((ip->i_flag & (IFACC | IFMOD | IFCRT)) != 0 ||
443: ip->i_nlink == 0)
444: icopymd (ip);
445: }
446: iunlock (ip);
447: }
448:
449: /*
450: * Given a inode which isn't locked, lock it and then deaccess.
451: */
452: ldetach(ip)
453: register INODE *ip;
454: {
455: ilock (ip);
456: idetach (ip);
457: }
458:
459: /*
460: * A specialized routine for finding whether the given inode may be unlinked.
461: * Quite simple you say, but we already have an inode locked and could run
462: * into gating problems if we were to lock another. So we look through the
463: * cache to see if the inode is there. If it is, we can easily tell. If it
464: * isn't, `icopydm' is called with a static. This routine is only used by
465: * `uunlink'.
466: */
467: iucheck(dev, ino)
468: register dev_t dev;
469: register ino_t ino;
470: {
471: register INODE *ip;
472: INODE inode;
473:
474: for (ip = & inodep [NINODE - 1] ; ip >= inodep; -- ip) {
475: if (ip->i_ino == ino && ip->i_dev == dev)
476: break;
477: }
478: if (ip < inodep) {
479: ip = & inode;
480: ip->i_dev = dev;
481: ip->i_ino = ino;
482: if (icopydm (ip) == 0)
483: return 0;
484: }
485: if ((ip->i_mode & IFMT) == IFDIR) {
486: if (super () == 0)
487: return 0;
488: }
489: return 1;
490: }
491:
492: /*
493: * Copy an inode from disk to memory performing canonization.
494: */
495: icopydm(ip)
496: register INODE *ip;
497: {
498: register struct dinode *dip;
499: register BUF *bp;
500: register ino_t ino;
501: struct dinode dinode;
502: caddr_t v;
503:
504: ip->i_flag = 0;
505: ino = ip->i_ino;
506:
507: if ((bp = bread (ip->i_dev, (daddr_t) iblockn (ino),
508: BUF_SYNC)) == NULL)
509: return 0;
510:
511: dip = & dinode;
512: v = (char *) ((struct dinode *) bp->b_vaddr + iblocko (ino));
513: memcpy (dip, v, sizeof (dinode));
514: brelease (bp);
515:
516: ip->i_mode = dip->di_mode;
517: canshort (ip->i_mode);
518: ip->i_nlink = dip->di_nlink;
519: canshort (ip->i_nlink);
520: ip->i_uid = dip->di_uid;
521: canshort (ip->i_uid);
522: ip->i_gid = dip->di_gid;
523: canshort (ip->i_gid);
524: ip->i_size = dip->di_size;
525: cansize (ip->i_size);
526:
527: switch (ip->i_mode & IFMT) {
528: case IFBLK:
529: case IFCHR:
530: ip->i_a.i_rdev = dip->di_a.di_rdev;
531: candev (ip->i_a.i_rdev);
532: break;
533:
534: case IFREG:
535: case IFDIR:
536: l3tol (ip->i_a.i_addr, dip->di_a.di_addb, NADDR);
537: break;
538:
539: case IFPIPE:
540: l3tol (ip->i_pipe, dip->di_addp, ND);
541: ip->i_pnc = dip->di_pnc;
542: canshort (ip->i_pnc);
543: ip->i_prx = dip->di_prx;
544: canshort (ip->i_prx);
545: ip->i_pwx = dip->di_pwx;
546: canshort (ip->i_pwx);
547: break;
548:
549: default:
550: kclear (& ip->i_a, sizeof (ip->i_a));
551: break;
552: }
553:
554: ip->i_atime = dip->di_atime;
555: cantime (ip->i_atime);
556: ip->i_mtime = dip->di_mtime;
557: cantime (ip->i_mtime);
558: ip->i_ctime = dip->di_ctime;
559: cantime (ip->i_ctime);
560: ip->i_rl = NULL;
561: return 1;
562: }
563:
564: /*
565: * Copy an inode from memory back on to disk performing canonization.
566: */
567: icopymd(ip)
568: register INODE *ip;
569: {
570: register struct dinode *dip;
571: register BUF *bp;
572: register ino_t ino;
573: struct dinode dinode;
574: caddr_t v;
575:
576: if (getment (ip->i_dev, 0) == NULL)
577: return;
578:
579: ino = ip->i_ino;
580: if (ip->i_refc == 0 && ip->i_nlink == 0 && ino != BADFIN &&
581: ino != ROOTIN) {
582: iclear (ip);
583: ip->i_lrt = 0;
584: ip->i_mode = 0;
585: }
586:
587: dip = & dinode;
588: dip->di_mode = ip->i_mode;
589: canshort (dip->di_mode);
590: dip->di_nlink = ip->i_nlink;
591: canshort (dip->di_nlink);
592: dip->di_uid = ip->i_uid;
593: canshort (dip->di_uid);
594: dip->di_gid = ip->i_gid;
595: canshort (dip->di_gid);
596: dip->di_size = ip->i_size;
597: cansize (dip->di_size);
598:
599: switch (ip->i_mode & IFMT) {
600: case IFBLK:
601: case IFCHR:
602: dip->di_a.di_rdev = ip->i_a.i_rdev;
603: candev (dip->di_a.di_rdev);
604: break;
605:
606: case IFREG:
607: case IFDIR:
608: ltol3 (dip->di_addr, ip->i_a.i_addr, NADDR);
609: break;
610:
611: case IFPIPE:
612: ltol3 (dip->di_addp, ip->i_pipe, ND);
613: dip->di_pnc = ip->i_pnc;
614: canshort (dip->di_pnc);
615: dip->di_prx = ip->i_prx;
616: canshort (dip->di_prx);
617: dip->di_pwx = ip->i_pwx;
618: canshort (dip->di_pwx);
619: break;
620:
621: default:
622: kclear (& dip->di_a, sizeof (dip->di_a));
623: break;
624: }
625:
626: dip->di_atime = ip->i_atime;
627: cantime (dip->di_atime);
628: dip->di_mtime = ip->i_mtime;
629: cantime (dip->di_mtime);
630: dip->di_ctime = ip->i_ctime;
631: cantime (dip->di_ctime);
632:
633: if ((bp = bread (ip->i_dev, (daddr_t) iblockn (ino),
634: BUF_SYNC)) == NULL)
635: return;
636:
637: v = (char *) ((struct dinode *) bp->b_vaddr + iblocko (ino));
638: memcpy (v, dip, sizeof (dinode));
639: bp->b_flag |= BFMOD;
640: brelease (bp);
641: ip->i_flag &= ~ (IFACC | IFMOD | IFCRT);
642: if (ip->i_refc == 0 && ip->i_nlink == 0 && ino != BADFIN &&
643: ino != ROOTIN)
644: ifree (ip->i_dev, ino);
645: }
646:
647: /*
648: * Copy all relevant inodes out on device `dev'.
649: */
650: isync(dev)
651: register dev_t dev;
652: {
653: register INODE *ip;
654:
655: for (ip = & inodep [NINODE - 1] ; ip >= inodep ; -- ip) {
656: if (ip->i_refc == 0)
657: continue;
658: if (ip->i_dev != dev)
659: continue;
660: if ((ip->i_mode & IFMT) == IFCHR)
661: continue;
662: if ((ip->i_flag & (IFACC | IFMOD | IFCRT)) == 0)
663: continue;
664: icopymd (ip);
665: }
666: }
667:
668: /*
669: * Clear the given inode and all space associated with it.
670: */
671:
672: iclear (ip)
673: register INODE *ip;
674: {
675: register int n;
676: register daddr_t b;
677:
678: switch (ip->i_mode & IFMT) {
679: case IFPIPE:
680: ip->i_pnc = ip->i_prx = ip->i_pwx = 0;
681: n = ND;
682: while (n > 0) {
683: if ((b = ip->i_pipe [-- n]) != 0)
684: bfree (ip->i_dev, b);
685: }
686: memset (ip->i_pipe, 0, sizeof (ip->i_pipe));
687: break;
688:
689: case IFDIR:
690: case IFREG:
691: n = NADDR;
692: while (n > ND) {
693: if ((b = ip->i_a.i_addr [-- n]) != 0)
694: indfree (ip->i_dev, b, 1 + n - ND);
695: }
696: while (n > 0) {
697: if ((b = ip->i_a.i_addr [-- n]) != 0)
698: bfree (ip->i_dev, b);
699: }
700: memset (ip->i_a.i_addr, 0, sizeof (ip->i_a.i_addr));
701: break;
702:
703: default:
704: return;
705: }
706: ip->i_size = 0;
707: iamc (ip); /* creat/pipe - atime/mtime/ctime */
708: }
709:
710: /*
711: * blclear(ip, lbn) -- Clear all blocks in inode ip beginning with
712: * logical blocks number lbn. Called from uchsize() in sys5.c
713: */
714: blclear(ip, lbn)
715: register INODE *ip;
716: fsize_t lbn;
717: {}
718:
719: /*
720: * Copy the appropriate information from the inode to the stat buffer.
721: */
722: istat(ip, sbp)
723: register INODE *ip;
724: register struct stat *sbp;
725: {
726: sbp->st_dev = ip->i_dev;
727: sbp->st_ino = ip->i_ino;
728: sbp->st_mode = ip->i_mode;
729: sbp->st_nlink = ip->i_nlink;
730: sbp->st_uid = ip->i_uid;
731: sbp->st_gid = ip->i_gid;
732: sbp->st_rdev = NODEV;
733: sbp->st_size = ip->i_size;
734: sbp->st_atime = ip->i_atime;
735: sbp->st_mtime = ip->i_mtime;
736: sbp->st_ctime = ip->i_ctime;
737:
738: switch (ip->i_mode & IFMT) {
739: case IFBLK:
740: case IFCHR:
741: sbp->st_rdev = ip->i_a.i_rdev;
742: sbp->st_size = 0;
743: break;
744:
745: case IFPIPE:
746: sbp->st_size = ip->i_pnc;
747: break;
748: }
749: }
750:
751: /*
752: * See if it is possible to access the given inode with the bits in
753: * the given mode.
754: * If the mode includes writing, and i_refc is > 1, then check for
755: * shared text problems.
756: */
757: iaccess(ip, mode)
758: register INODE *ip;
759: register int mode;
760: {
761: /* Super user can do everything with directories */
762: if (((ip->i_mode & IFMT) != IFDIR) || u.u_uid)
763: if ((imode (ip, u.u_uid, u.u_gid) & mode) != mode) {
764: u.u_error = EACCES;
765: return 0;
766: }
767:
768: if ((mode & IPW) != 0 && ip->i_refc > 1 && sbusy (ip)) {
769: u.u_error = ETXTBSY;
770: return 0;
771: }
772: return 1;
773: }
774:
775:
776: /*
777: * Get the maximum allowable mode on a file.
778: */
779:
780: imode(ip, uid, gid)
781: register INODE *ip;
782: {
783: if (uid == 0) {
784: /* Superuser can read or write anything. */
785: int ret = IPR | IPW;
786: /*
787: * If superuser, say the file is executable if any
788: * of the 'x' perm bits is set.
789: */
790: if ((ip->i_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)
791: ret |= IPE;
792: return ret;
793: }
794: if (uid == ip->i_uid)
795: return (ip->i_mode & S_IRWXU) >> 6;
796: if (gid == ip->i_gid)
797: return (ip->i_mode & S_IRWXG) >> 3;
798: return ip->i_mode & S_IRWXO;
799: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.