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