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