|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 13347 (0x3423) Types: TextFile Notes: UNIX file Names: »fs1.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦2d53db1df⟧ UNIX Filesystem └─⟦this⟧ »sys/coh/fs1.c«
/* (-lgl * The information contained herein is a trade secret of Mark Williams * Company, and is confidential information. It is provided under a * license agreement, and may be copied or disclosed only under the * terms of that agreement. Any reproduction or disclosure of this * material without the express written authorization of Mark Williams * Company or persuant to the license agreement is unlawful. * * COHERENT Version 0.7.3 * Copyright (c) 1982, 1983, 1984. * An unpublished work by Mark Williams Company, Chicago. * All rights reserved. -lgl) */ /* * Coherent. * Filesystem (mostly handling of in core inodes). */ #include <coherent.h> #include <buf.h> #include <canon.h> #include <dir.h> #include <errno.h> #include <filsys.h> #include <ino.h> #include <inode.h> #include <io.h> #include <mount.h> #include <stat.h> #include <uproc.h> /* * Get character for `ftoi' depending on what space the characters are * coming from. */ #define ftoic(p) (u.u_io.io_seg==IOSYS ? *p : getubd(p)) /* * Map the given filename to an inode. If an error is encountered, * `u.u_error' is set. `u.u_error' is always returned. As this routine * needs to set several things, depending on the type of access, `t', * there are places in the processes' user area reserved for this routine * to set. These are defined in the user process structure. The seek * position is always set to the position of the directory entry of the * child if the child exists or the first free position if it doesn't. * 'r' => Reference. A pointer to the child's inode is returned locked. * 'c' => Create. If the child exists, a pointer to the inode is returned * locked. Otherwise if the parent directory exists, a pointer to * the parent directory is returned locked. Otherwise, an error. * 'u' => Unlink. The parent directory is returned unlocked. The child's * inode number is returned. The seek position is also set. */ ftoi(np, t) char *np; { register INODE *cip; register char *cp; register int c; register struct direct *dp; register BUF *bp; size_t cseek, fseek, s; int fflag, mflag; dev_t dev; ino_t ino; daddr_t b; u.u_cdirn = 0; u.u_cdiri = NULL; u.u_pdiri = NULL; c = ftoic(np++); if (u.u_error != 0) return (u.u_error); if (c != '/') cip = u.u_cdir; else { c = ftoic(np++); cip = u.u_rdir; } while (c == '/') c = ftoic(np++); ilock(cip); cip->i_refc++; if (c == '\0') { if (t == 'r') { u.u_cdiri = cip; return (u.u_error); } u.u_error = ENOENT; idetach(cip); return (u.u_error); } for (;;) { cp = u.u_direct.d_name; while (c!='/' && c!='\0') { if (cp < &u.u_direct.d_name[DIRSIZ]) *cp++ = c; c = ftoic(np++); } while (c == '/') c = ftoic(np++); while (cp < &u.u_direct.d_name[DIRSIZ]) *cp++ = '\0'; if ((cip->i_mode&IFMT) != IFDIR) u.u_error = ENOTDIR; else iaccess(cip, IPE); if (u.u_error) { idetach(cip); return (u.u_error); } cp = u.u_direct.d_name; if (cip->i_ino==ROOTIN && cip->i_dev!=rootdev) if (*cp++=='.' && *cp++=='.' && *cp++=='\0') cip = ftoim(cip); b = 0; fflag = 0; mflag = 0; cseek = 0; s = cip->i_size; while (s > 0) { if ((bp=vread(cip, b++)) == NULL) { idetach(cip); return (u.u_error); } dp = bp->b_vaddr; while (dp < bp->b_vaddr+BSIZE) { if ((s-=sizeof(*dp)) < 0) break; if ((ino=dp->d_ino) == 0) { if (fflag == 0) { fflag++; fseek = cseek; } } else { if (direq(dp)) { canino(ino); mflag = 1; s = 0; break; } } cseek += sizeof(*dp); dp++; } brelease(bp); } dev = cip->i_dev; if (fflag == 0) fseek = cseek; if (mflag == 0) { if (c=='\0' && t=='c') { u.u_pdiri = cip; u.u_io.io_seek = fseek; } else { u.u_error = ENOENT; idetach(cip); } return (u.u_error); } if (c == '\0') { if (t == 'u') { u.u_cdirn = ino; u.u_pdiri = cip; u.u_io.io_seek = cseek; return (u.u_error); } idetach(cip); u.u_cdiri = iattach(dev, ino); return (u.u_error); } idetach(cip); if ((cip=iattach(dev, ino)) == NULL) return (u.u_error); } } /* * Given an inode which is the root of a file system, return the inode * on which the file system was mounted. */ INODE * ftoim(ip) register INODE *ip; { register MOUNT *mp; for (mp=mountp; mp!=NULL; mp=mp->m_next) { if (mp->m_dev == ip->i_dev) { idetach(ip); ip = mp->m_ip; ilock(ip); ip->i_refc++; break; } } return (ip); } /* * Compare the string in `u.u_direct.d_name' with the name in the * given directory pointer. */ direq(dp) struct direct *dp; { register char *cp1, *cp2; register unsigned n; if (dp->d_ino == 0) return (0); cp1 = dp->d_name; cp2 = u.u_direct.d_name; n = DIRSIZ; do { if (*cp1++ != *cp2++) return (0); } while (--n); return (1); } /* * Make an inode of the given mode and device. The parent directory, * name and such stuff is set by ftoi. */ INODE * imake(mode, rdev) unsigned mode; dev_t rdev; { register INODE *ip; ip = NULL; mode &= ~u.u_umask; if ((mode&ISVTXT)!=0 && super()==0) goto det; if (iaccess(u.u_pdiri, IPW) == 0) goto det; if ((ip=ialloc(u.u_pdiri->i_dev, mode)) == NULL) goto det; ip->i_nlink = 1; ip->i_a.i_rdev = rdev; idirent(ip->i_ino); iamc(ip); /* creat/mknod - atime/mtime/ctime */ det: idetach(u.u_pdiri); return (ip); } /* * Write a directory entry out. Everything necessary has been conveniently * set by `ftoi', except the new inode number of this directory entry. */ idirent(ino) { u.u_direct.d_ino = ino; canino(u.u_direct.d_ino); u.u_io.io_ioc = sizeof (struct direct); u.u_io.io_base = &u.u_direct; u.u_io.io_seg = IOSYS; iwrite(u.u_pdiri, &u.u_io); } /* * Return a pointer to a locked inode in core containing the given * inode number and device. */ INODE * iattach(dev, ino) { register INODE *ip; register INODE *fip; register unsigned lrt; register MOUNT *mp; for (;;) { fip = NULL; for (ip=inodep; ip<&inodep[NINODE]; ip++) { if (ip->i_ino==ino && ip->i_dev==dev) break; if (ip->i_refc == 0) { if (fip==NULL || ip->i_lrt<lrt) { fip = ip; lrt = ip->i_lrt; } } } if (ip == &inodep[NINODE]) { if ((ip=fip) == NULL) { devmsg(dev, "Inode table overflow"); u.u_error = ENFILE; return (NULL); } ilock(ip); if (ip->i_refc != 0) { iunlock(ip); continue; } ip->i_dev = dev; ip->i_ino = ino; ip->i_refc = 1; ip->i_lrt = timer.t_time; if (icopydm(ip) == 0) { ip->i_ino = 0; ip->i_refc = 0; iunlock(ip); return (NULL); } return (ip); } if ((ip->i_flag&IFMNT) != 0) { for (mp=mountp; mp!=NULL; mp=mp->m_next) { if (mp->m_ip == ip) { ino = ROOTIN; dev = mp->m_dev; break; } } continue; } ilock(ip); if (ip->i_ino!=ino || ip->i_dev!=dev) { iunlock(ip); continue; } if (ip->i_refc < 0) panic("ialloc(%p), ip"); ip->i_refc++; ip->i_lrt = timer.t_time; return (ip); } } /* * Given a locked inode, deaccess it. */ idetach(ip) register INODE *ip; { if (ilocked(ip)==0 || ip->i_refc<=0) panic("idetach(%p)", ip); if (--ip->i_refc == 0) { if ((ip->i_flag&(IFACC|IFMOD|IFCRT)) != 0 || ip->i_nlink == 0) icopymd(ip); } iunlock(ip); } /* * Given a inode which isn't locked, lock it and then deaccess. */ ldetach(ip) register INODE *ip; { ilock(ip); idetach(ip); } /* * A specialized routine for finding whether the given inode may be unlinked. * Quite simple you say, but we already have an inode locked and could run * into gating problems if we were to lock another. So we look through the * cache to see if the inode is there. If it is, we can easily tell. If it * isn't, `icopydm' is called with a static. This routine is only used by * `uunlink'. */ iucheck(dev, ino) register dev_t dev; register ino_t ino; { register INODE *ip; INODE inode; for (ip=inodep; ip<&inodep[NINODE]; ip++) { if (ip->i_ino==ino && ip->i_dev==dev) break; } if (ip == &inodep[NINODE]) { ip = &inode; ip->i_dev = dev; ip->i_ino = ino; if (icopydm(ip) == 0) return (0); } if ((ip->i_mode&IFMT) == IFDIR) { if (super() == 0) return (0); } return (1); } /* * Copy an inode from disk to memory performing canonization. */ icopydm(ip) register INODE *ip; { register struct dinode *dip; register BUF *bp; register ino_t ino; struct dinode dinode; ip->i_flag = 0; ino = ip->i_ino; if ((bp=bread(ip->i_dev, (daddr_t)iblockn(ino), 1)) == NULL) return (0); dip = &dinode; kkcopy((char *)((struct dinode *)bp->b_vaddr+iblocko(ino)), dip, sizeof(dinode)); brelease(bp); ip->i_mode = dip->di_mode; canshort(ip->i_mode); ip->i_nlink = dip->di_nlink; canshort(ip->i_nlink); ip->i_uid = dip->di_uid; canshort(ip->i_uid); ip->i_gid = dip->di_gid; canshort(ip->i_gid); ip->i_size = dip->di_size; cansize(ip->i_size); switch (ip->i_mode&IFMT) { case IFBLK: case IFCHR: ip->i_a.i_rdev = dip->di_a.di_rdev; candev(ip->i_a.i_rdev); break; case IFREG: case IFDIR: l3tol(ip->i_a.i_addr, dip->di_a.di_addb, NADDR); break; case IFPIPE: l3tol(ip->i_a.i_pipe, dip->di_a.di_addp, ND); ip->i_pnc = dip->di_pnc; canint(ip->i_pnc); ip->i_prx = dip->di_prx; canint(ip->i_prx); ip->i_pwx = dip->di_pwx; canint(ip->i_pwx); break; default: kclear(&ip->i_a, sizeof(ip->i_a)); break; } ip->i_atime = dip->di_atime; cantime(ip->i_atime); ip->i_mtime = dip->di_mtime; cantime(ip->i_mtime); ip->i_ctime = dip->di_ctime; cantime(ip->i_ctime); return (1); } /* * Copy an inode from memory back on to disk performing canonization. */ icopymd(ip) register INODE *ip; { register struct dinode *dip; register BUF *bp; register ino_t ino; struct dinode dinode; if (getment(ip->i_dev, 0) == NULL) return; ino = ip->i_ino; if (ip->i_refc==0 && ip->i_nlink==0 && ino!=BADFIN && ino!=ROOTIN) { iclear(ip); ip->i_lrt = 0; ip->i_mode = 0; ifree(ip->i_dev, ino); } dip = &dinode; dip->di_mode = ip->i_mode; canshort(dip->di_mode); dip->di_nlink = ip->i_nlink; canshort(dip->di_nlink); dip->di_uid = ip->i_uid; canshort(dip->di_uid); dip->di_gid = ip->i_gid; canshort(dip->di_gid); dip->di_size = ip->i_size; cansize(dip->di_size); switch (ip->i_mode&IFMT) { case IFBLK: case IFCHR: dip->di_a.di_rdev = ip->i_a.i_rdev; candev(dip->di_a.di_rdev); break; case IFREG: case IFDIR: ltol3(dip->di_a.di_addb, ip->i_a.i_addr, NADDR); break; case IFPIPE: ltol3(dip->di_a.di_addp, ip->i_a.i_pipe, ND); dip->di_pnc = ip->i_pnc; canshort(dip->di_pnc); dip->di_prx = ip->i_prx; canshort(dip->di_prx); dip->di_pwx = ip->i_pwx; canshort(dip->di_pwx); break; default: kclear(&dip->di_a, sizeof(dip->di_a)); break; } dip->di_atime = ip->i_atime; cantime(dip->di_atime); dip->di_mtime = ip->i_mtime; cantime(dip->di_mtime); dip->di_ctime = ip->i_ctime; cantime(dip->di_ctime); if ((bp=bread(ip->i_dev, (daddr_t)iblockn(ino), 1)) == NULL) return; kkcopy(dip, (char *)((struct dinode *)bp->b_vaddr+iblocko(ino)), sizeof(dinode)); bp->b_flag |= BFMOD; brelease(bp); ip->i_flag &= ~(IFACC|IFMOD|IFCRT); } /* * Copy all relevant inodes out on device `dev'. */ isync(dev) register dev_t dev; { register INODE *ip; for (ip=inodep; ip<&inodep[NINODE]; ip++) { if (ip->i_refc == 0) continue; if (ip->i_dev != dev) continue; if ((ip->i_flag&(IFACC|IFMOD|IFCRT)) == 0) continue; icopymd(ip); } } /* * Clear the given inode and all space associated with it. */ iclear(ip) register INODE *ip; { register int n; register daddr_t b; switch (ip->i_mode&IFMT) { case IFPIPE: ip->i_a.i_pnc = 0; ip->i_a.i_prx = 0; ip->i_a.i_pwx = 0; n = ND; break; case IFDIR: case IFREG: n = NADDR; break; default: return; } while (n > ND) { if ((b=ip->i_a.i_addr[--n]) != 0) indfree(ip->i_dev, b, 1+n-ND); } while (n > 0) { if ((b=ip->i_a.i_addr[--n]) != 0) bfree(ip->i_dev, b); } ip->i_size = 0; kclear(ip->i_a.i_addr, sizeof(ip->i_a.i_addr)); iamc(ip); /* creat/pipe - atime/mtime/ctime */ } /* * Copy the appropriate information from the inode to the stat buffer. */ istat(ip, sbp) register INODE *ip; register struct stat *sbp; { sbp->st_dev = ip->i_dev; sbp->st_ino = ip->i_ino; sbp->st_mode = ip->i_mode; sbp->st_nlink = ip->i_nlink; sbp->st_uid = ip->i_uid; sbp->st_gid = ip->i_gid; sbp->st_rdev = NODEV; sbp->st_size = ip->i_size; sbp->st_atime = ip->i_atime; sbp->st_mtime = ip->i_mtime; sbp->st_ctime = ip->i_ctime; switch (ip->i_mode&IFMT) { case IFBLK: case IFCHR: sbp->st_rdev = ip->i_a.i_rdev; sbp->st_size = 0; break; case IFPIPE: sbp->st_size = ip->i_a.i_pnc; break; } } /* * See if it is possible to access the given inode with the bits in * the given mode. */ iaccess(ip, mode) register INODE *ip; register int mode; { if ((imode(ip, u.u_uid, u.u_gid)&mode) != mode) { u.u_error = EACCES; return (0); } return (1); } /* * Get the maximum allowable mode on a file. */ imode(ip, uid, gid) register INODE *ip; { if (uid == 0) return (IPR|IPW|IPE); if (uid == ip->i_uid) return ((ip->i_mode>>6)&07); if (gid == ip->i_gid) return ((ip->i_mode>>3)&07); return (ip->i_mode&07); }