📄 fs.c
字号:
st->size = ip->size;}#define min(a, b) ((a) < (b) ? (a) : (b))// Read data from inode.intreadi(struct inode *ip, char *dst, uint off, uint n){ uint target = n, n1; struct buf *bp; if(ip->type == T_DEV) { if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].read) return -1; return devsw[ip->major].read(ip->minor, dst, n); } while(n > 0 && off < ip->size){ bp = bread(ip->dev, bmap(ip, off / BSIZE)); n1 = min(n, ip->size - off); n1 = min(n1, BSIZE - (off % BSIZE)); memmove(dst, bp->data + (off % BSIZE), n1); n -= n1; off += n1; dst += n1; brelse(bp); } return target - n;}// Allocate the nth block in inode ip if necessary.static intnewblock(struct inode *ip, uint lbn){ struct buf *inbp; uint *inaddrs; uint b; if(lbn < NDIRECT) { if(ip->addrs[lbn] == 0) { b = balloc(ip->dev); if(b <= 0) return -1; ip->addrs[lbn] = b; } } else { if(ip->addrs[INDIRECT] == 0) { b = balloc(ip->dev); if(b <= 0) return -1; ip->addrs[INDIRECT] = b; } inbp = bread(ip->dev, ip->addrs[INDIRECT]); inaddrs = (uint*) inbp->data; if(inaddrs[lbn - NDIRECT] == 0) { b = balloc(ip->dev); if(b <= 0) return -1; inaddrs[lbn - NDIRECT] = b; bwrite(inbp, ip->addrs[INDIRECT]); } brelse(inbp); } return 0;}// Write data to inode.intwritei(struct inode *ip, char *addr, uint off, uint n){ if(ip->type == T_DEV) { if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].write) return -1; return devsw[ip->major].write(ip->minor, addr, n); } else if(ip->type == T_FILE || ip->type == T_DIR) { struct buf *bp; int r = 0; int m; int lbn; while(r < n) { lbn = off / BSIZE; if(lbn >= MAXFILE) return r; if(newblock(ip, lbn) < 0) { cprintf("newblock failed\n"); return r; } m = min(BSIZE - off % BSIZE, n-r); bp = bread(ip->dev, bmap(ip, lbn)); memmove(bp->data + off % BSIZE, addr, m); bwrite(bp, bmap(ip, lbn)); brelse(bp); r += m; off += m; } if(r > 0) { if(off > ip->size) { if(ip->type == T_DIR) ip->size = ((off / BSIZE) + 1) * BSIZE; else ip->size = off; } iupdate(ip); } return r; } else { panic("writei: unknown type"); return 0; }}// look up a path name, in one of three modes.// NAMEI_LOOKUP: return locked target inode.// NAMEI_CREATE: return locked parent inode.// return 0 if name does exist.// *ret_last points to last path component (i.e. new file name).// *ret_ip points to the the name that did exist, if it did.// *ret_ip and *ret_last may be zero even if return value is zero.// NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off.// return 0 if name doesn't exist.struct inode*namei(char *path, int mode, uint *ret_off, char **ret_last, struct inode **ret_ip){ struct inode *dp; struct proc *p = curproc[cpu()]; char *cp = path, *cp1; uint off, dev; struct buf *bp; struct dirent *ep; int i, l, atend; uint ninum; if(ret_off) *ret_off = 0xffffffff; if(ret_last) *ret_last = 0; if(ret_ip) *ret_ip = 0; if(*cp == '/') dp = iget(rootdev, 1); else { dp = p->cwd; iincref(dp); ilock(dp); } for(;;){ while(*cp == '/') cp++; if(*cp == '\0'){ if(mode == NAMEI_LOOKUP) return dp; if(mode == NAMEI_CREATE && ret_ip){ *ret_ip = dp; return 0; } iput(dp); return 0; } if(dp->type != T_DIR){ iput(dp); return 0; } for(i = 0; cp[i] != 0 && cp[i] != '/'; i++) ; l = i; if(i > DIRSIZ) l = DIRSIZ; for(off = 0; off < dp->size; off += BSIZE){ bp = bread(dp->dev, bmap(dp, off / BSIZE)); for(ep = (struct dirent*) bp->data; ep < (struct dirent*) (bp->data + BSIZE); ep++){ if(ep->inum == 0) continue; if(memcmp(cp, ep->name, l) == 0 && (l == DIRSIZ || ep->name[l]== 0)){ // entry matches path element off += (uchar*)ep - bp->data; ninum = ep->inum; brelse(bp); cp += i; goto found; } } brelse(bp); } atend = 1; for(cp1 = cp; *cp1; cp1++) if(*cp1 == '/') atend = 0; if(mode == NAMEI_CREATE && atend){ if(*cp == '\0'){ iput(dp); return 0; } *ret_last = cp; return dp; } iput(dp); return 0; found: if(mode == NAMEI_DELETE && *cp == '\0'){ *ret_off = off; return dp; } dev = dp->dev; iput(dp); dp = iget(dev, ninum); if(dp->type == 0 || dp->nlink < 1) panic("namei"); }}// Write a new directory entry (name, ino) into the directory dp.// Caller must have locked dp.voidwdir(struct inode *dp, char *name, uint ino){ uint off; struct dirent de; int i; for(off = 0; off < dp->size; off += sizeof(de)){ if(readi(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) panic("wdir read"); if(de.inum == 0) break; } de.inum = ino; for(i = 0; i < DIRSIZ && name[i]; i++) de.name[i] = name[i]; for( ; i < DIRSIZ; i++) de.name[i] = '\0'; if(writei(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) panic("wdir write");}// Create the path cp and return its locked inode structure.// If cp already exists, return 0.struct inode*mknod(char *cp, short type, short major, short minor){ struct inode *ip, *dp; char *last; if((dp = namei(cp, NAMEI_CREATE, 0, &last, 0)) == 0) return 0; ip = mknod1(dp, last, type, major, minor); iput(dp); return ip;}// Create a new inode named name inside dp// and return its locked inode structure.// If name already exists, return 0.struct inode*mknod1(struct inode *dp, char *name, short type, short major, short minor){ struct inode *ip; ip = ialloc(dp->dev, type); if(ip == 0) return 0; ip->major = major; ip->minor = minor; ip->size = 0; ip->nlink = 1; iupdate(ip); // write new inode to disk wdir(dp, name, ip->inum); return ip;}// Unlink the inode named cp.intunlink(char *cp){ struct inode *ip, *dp; struct dirent de; uint off, inum, dev; dp = namei(cp, NAMEI_DELETE, &off, 0, 0); if(dp == 0) return -1; dev = dp->dev; if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0) panic("unlink no entry"); inum = de.inum; memset(&de, 0, sizeof(de)); if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) panic("unlink dir write"); iupdate(dp); iput(dp); ip = iget(dev, inum); if(ip->nlink < 1) panic("unlink nlink < 1"); ip->nlink--; iupdate(ip); iput(ip); return 0;}// Create the path new as a link to the same inode as old.intlink(char *name1, char *name2){ struct inode *ip, *dp; char *last; if((ip = namei(name1, NAMEI_LOOKUP, 0, 0, 0)) == 0) return -1; if(ip->type == T_DIR){ iput(ip); return -1; } iunlock(ip); if((dp = namei(name2, NAMEI_CREATE, 0, &last, 0)) == 0) { idecref(ip); return -1; } if(dp->dev != ip->dev){ idecref(ip); iput(dp); return -1; } ilock(ip); ip->nlink++; iupdate(ip); wdir(dp, last, ip->inum); iput(dp); iput(ip); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -