⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs.c

📁 类unix x86平台的简单操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
  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 + -