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