Lab9: file system

Large files

fs.h

#define NDIRECT 11
#define NINDIRECT (BSIZE / sizeof(uint))
#define NDOUBLEINDIRECT ((NINDIRECT) * (NINDIRECT))
#define MAXFILE ((NDIRECT) + (NINDIRECT) + (NDOUBLEINDIRECT))

// On-disk inode structure
struct dinode
{
	short type;				 // File type
	short major;			 // Major device number (T_DEVICE only)
	short minor;			 // Minor device number (T_DEVICE only)
	short nlink;			 // Number of links to inode in file system
	uint size;				 // Size of file (bytes)
	uint addrs[NDIRECT + 2]; // Data block addresses
};

file.h

struct inode
{
	uint dev;			   // Device number
	uint inum;			   // Inode number
	int ref;			   // Reference count
	struct sleeplock lock; // protects everything below here
	int valid;			   // inode has been read from disk?

	short type; // copy of disk inode
	short major;
	short minor;
	short nlink;
	uint size;
	uint addrs[NDIRECT + 2];
};

fs.c

static uint bmap(struct inode *ip, uint bn)
{
	uint addr, *a;
	struct buf *bp;

	if (bn < NDIRECT)
	{
		if ((addr = ip->addrs[bn]) == 0)
		{
			addr = balloc(ip->dev);
			if (addr == 0)
				return 0;
			ip->addrs[bn] = addr;
		}
		return addr;
	}

	bn -= NDIRECT;

	if (bn < NINDIRECT)
	{
		// Load indirect block, allocating if necessary.
		if ((addr = ip->addrs[NDIRECT]) == 0)
		{
			addr = balloc(ip->dev);
			if (addr == 0)
				return 0;
			ip->addrs[NDIRECT] = addr;
		}
		bp = bread(ip->dev, addr);
		a = (uint *)bp->data;
		if ((addr = a[bn]) == 0)
		{
			addr = balloc(ip->dev);
			if (addr)
			{
				a[bn] = addr;
				log_write(bp);
			}
		}
		brelse(bp);
		return addr;
	}

	bn -= NINDIRECT;

	if (bn < NDOUBLEINDIRECT)
	{
		if ((addr = ip->addrs[NDIRECT + 1]) == 0)
		{
			addr = balloc(ip->dev);
			if (addr == 0)
			{
				return 0;
			}
			ip->addrs[NDIRECT + 1] = addr;
		}
		
		bp = bread(ip->dev, addr);
		a = (uint *)bp->data;
		if ((addr = a[bn / NINDIRECT]) == 0)
		{
			addr = balloc(ip->dev);
			if (addr)
			{
				a[bn / NINDIRECT] = addr;
				log_write(bp);
			}
		}
		brelse(bp);
		
		bp = bread(ip->dev, addr);
		a = (uint *)bp->data;
		if ((addr = a[bn % NINDIRECT]) == 0)
		{
			addr = balloc(ip->dev);
			if (addr)
			{
				a[bn % NINDIRECT] = addr;
				log_write(bp);
			}
		}
		brelse(bp);

		return addr;
	}
	
	panic("bmap: out of range");
}

// Truncate inode (discard contents).
// Caller must hold ip->lock.
void itrunc(struct inode *ip)
{
	int i, j;
	struct buf *bp, *second_bp;
	uint *a, *b;

	for (i = 0; i < NDIRECT; i++)
	{
		if (ip->addrs[i])
		{
			bfree(ip->dev, ip->addrs[i]);
			ip->addrs[i] = 0;
		}
	}

	if (ip->addrs[NDIRECT])
	{
		bp = bread(ip->dev, ip->addrs[NDIRECT]);
		a = (uint *)bp->data;
		for (j = 0; j < NINDIRECT; j++)
		{
			if (a[j])
				bfree(ip->dev, a[j]);
		}
		brelse(bp);
		bfree(ip->dev, ip->addrs[NDIRECT]);
		ip->addrs[NDIRECT] = 0;
	}

	if (ip->addrs[NDIRECT + 1])
	{
		bp = bread(ip->dev, ip->addrs[NDIRECT + 1]);
		a = (uint *)bp->data;
		for (int i = 0; i < NINDIRECT; i++)
		{
			if (a[i])
			{
				second_bp = bread(ip->dev, a[i]);
				b = (uint *)second_bp->data;
				for (int j = 0; j < NINDIRECT; j++)
				{
					if (b[j])
					{
						bfree(ip->dev, b[j]);
					}		
				}
				brelse(second_bp);
				bfree(ip->dev, a[i]);	
			}		
		}
		brelse(bp);
		bfree(ip->dev, ip->addrs[NDIRECT + 1]);
		ip->addrs[NDIRECT + 1] = 0;
	}
	
	ip->size = 0;
	iupdate(ip);
}

Symbolic links

uint64 sys_symlink(void)
{
	char target[MAXPATH], path[MAXPATH];
	struct inode *ip;

	if (argstr(0, target, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0)
	{
		return -1;
	}

	begin_op();

	if ((ip = namei(path)) != 0)
	{
		end_op();
		return -1;
	}
	
	if ((ip = create(path, T_SYMLINK, 0, 0)) == 0)
	{
		end_op();
		return -1;
	}

	if (writei(ip, 0, (uint64)target, 0, MAXPATH) < 0)
	{
		iunlockput(ip);
    	end_op();
    	return -1;
	}
	
	iunlockput(ip);
	end_op();
	return 0;
}
uint64 sys_open(void)
{
	char path[MAXPATH], target[MAXPATH];
	int fd, omode;
	struct file *f;
	struct inode *ip;
	int n;

	argint(1, &omode);
	if ((n = argstr(0, path, MAXPATH)) < 0)
		return -1;

	begin_op();

	if (omode & O_CREATE)
	{
		ip = create(path, T_FILE, 0, 0);
		if (ip == 0)
		{
			end_op();
			return -1;
		}
	}
	else
	{
		if ((ip = namei(path)) == 0)
		{
			end_op();
			return -1;
		}
		ilock(ip);
		if (ip->type == T_DIR && omode != O_RDONLY)
		{
			iunlockput(ip);
			end_op();
			return -1;
		}
	}

	if (ip->type == T_SYMLINK && (omode & O_NOFOLLOW) == 0)
	{
		int i;
		for (i = 0; i < NSYMLINKS; i++)
		{
			if ((readi(ip, 0, (uint64)target, 0, MAXPATH)) < 0)
			{
				iunlockput(ip);
				end_op();
				return -1;
			}

			iunlockput(ip);

			if((ip = namei(target)) == 0)
			{
      			end_op();
      			return -1;
			}

			ilock(ip);
			if (ip->type != T_SYMLINK)
			{
				break;
			}		
		}

		if (i >= NSYMLINKS)
		{
			iunlock(ip);
      		end_op();
      		return -1;
		}
	}

	if (ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV))
	{
		iunlockput(ip);
		end_op();
		return -1;
	}

	if ((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0)
	{
		if (f)
			fileclose(f);
		iunlockput(ip);
		end_op();
		return -1;
	}

	if (ip->type == T_DEVICE)
	{
		f->type = FD_DEVICE;
		f->major = ip->major;
	}
	else
	{
		f->type = FD_INODE;
		f->off = 0;
	}
	f->ip = ip;
	f->readable = !(omode & O_WRONLY);
	f->writable = (omode & O_WRONLY) || (omode & O_RDWR);

	if ((omode & O_TRUNC) && ip->type == T_FILE)
	{
		itrunc(ip);
	}
	
	iunlock(ip);
	end_op();

	return fd;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值