CSAPP Lab —— FSLAB

CSAPP Lab —— FSLAB

写在前面:

本实验的代码中清除了大部分调试痕迹,但是保留了一部分,以展示作者写实验时崩溃的精神状态

实验概览

完成一个运行在用户态的文件系统,对模拟的块设备进行读写,从而实现一些基本的文件读
写以及管理功能。

准备

各部分文件大小:

// 至少支持文件或目录数量
#define FILE_NUM 32768      //来自实验文档要求
// inode节点大小
#define INODE_SIZE 128
// super block大小
#define SUPERBLOCK_SIZE 4096// 4KB
// Imap大小
#define IMAP_SIZE 4096      // 4KB
// Dmap大小
#define DMAP_SIZE 8192      // 2*4KB = 8KB
// Inodes table大小
#define INODE_TABLE_SIZE (FILE_NUM * INODE_SIZE)
// 块大小
#define BLOCK_SIZE 4096		// 4KB
// 文件最大大小
#define MAX_SIZE 8<<20		// 8MB
// 总块数
#define BLOCK_NUM 65536		// 0-65535 block_id

Supernode数据结构:

typedef struct super_node
{
	int 		inode_num;			// inode_num = FILE_NUM
	int 		block_num;			// block_num = BLOCK_NUM
	int* 		imap_block;			// Imap位置
	int* 		dmap_block;			// Dmap位置
	int			dir_count;			// 目录数量
	int 		file_count;			// 文件数量
	int*		inode_table_block;	// Inodes table位置
}super_node, *SuperNode;

Inode数据结构:

typedef struct inode						// 128B
{
	mode_t 		i_mode;						// 文件mode/目录mode
	nlink_t 	i_links_count;				// 链接数
	off_t   	i_size;						// 文件大小
	time_t  	i_atime;					// 文件被访问的时间
	time_t		i_mtime;					// 文件被修改的时间
	time_t		i_ctime;					// 文件状态改变时间
	int			i_blocks_count;				// 文件占据block数量
	int 		i_block_pointer[18];		// 18个一级指针			// 4B * 18 = 72B
	int			i_double_block_pointer;		// 1个二级指针			// 4B * 1 = 4B
}inode, *Inode;

Inode数据结构包含了fuse ppt中应该包含的全部内容。指针的数量分配要满足两个条件:

  1. Inode大小为128B(为了让一个块中有完整的32个Inode块)
  2. Inode的指针指向的文件区域大于等于8MB
    遗憾的是,直到完成实验,本人才发现,自己在最一开始算错了。这里的Inode只能满足18 * 4KB + 1024 * 4KB = 4168KB的文件大小。幸运的是,刚好能够满足本实验的测试需要。由于整个实验已经完成,本人没有修改该数据结构。但真正正确的指针分配应该是:
int 		i_block_pointer[14];		    // 14个一级指针			// 4B * 14 = 56B
int			i_double_block_pointer[2];		// 1个二级指针			// 4B * 2 = 8B
// 支持14 * 4KB + 2 * 1024 * 4KB = 8248KB 的文件大小

catalog数据结构:

typedef struct catalog						//32B
{
	char name[24];							//名字				   //24B
	// nlink_t i_links_count;				//链接数			   //2B
	mode_t i_mode;							//模式(目录/文件)		//2B
	int i_ino;								//i-number			  //4B

}catalog, *Catalog;

catalog是存放在目录块中的数据结构,一个目录块中有128个catalog,可以存放128个子目录或子文件。在这里我最一开始犯了一个严重的错误:我并不清楚nlink_t的大小,却贸然在这里使用了,结果nlink_t并非我最一开始以为的2B而是8B,因此导致了目录块的错乱。
Imap、Dmap数据结构:

// int共32位,每一位代表一个inode/datablock
int Imap[1024];      //32786    //1024 * 4 = 4KB
int Dmap[2048];      //65536    //2048 * 4 = 8KB

mkfs

思路:

  1. 创建super_block
  2. 创建Imap
  3. 创建Dmap
  4. 创建Inode_table
  5. 初始化super_block
  6. 创建根目录root的inode
  7. 创建root的datablock
  8. super_block更新(由于创建了根目录,dir_count ++)
  9. Imap更新(只有root占用1个inode)
  10. Dmap更新
  11. 将super_block, Imp, Dmap, Root 写入磁盘
  12. 释放内存空间
    其中,superblock初始化如下:
    / 初始化super_block
	super_block->inode_num = FILE_NUM;
	super_block->block_num = BLOCK_NUM;
	super_block->imap_block = Imap;
	super_block->dmap_block = Dmap;
	super_block->dir_count = 0;
	super_block->file_count = 0;
	super_block->inode_table_block = Dmap + DMAP_SIZE;

根目录初始化如下:

    Inode_table[0].i_mode = DIRMODE;
	Inode_table[0].i_links_count = 0;
	Inode_table[0].i_size = sizeof(catalog);
	Inode_table[0].i_atime = time(NULL);
	Inode_table[0].i_mtime = time(NULL);
	Inode_table[0].i_ctime = time(NULL);
	Inode_table[0].i_blocks_count = 1;
	for(int i = 0; i < 18; i++)
		Inode_table[0].i_block_pointer[i] = -1;
	Inode_table[0].i_double_block_pointer = -1;

各部分占据磁盘情况如下:
super_block -> block[0], Imap -> block[1], Dmap -> block[2] + block[3], Inode_table -> block[4] ~ block[1027], datablock从block[1028]开始

    // 将super_block, Imp, Dmap, Root 写入磁盘
	disk_write(0, super_block);
	disk_write(1, Imap);
	disk_write(2, Dmap);
	disk_write(3, Dmap + (DMAP_SIZE) / 2);
	for(i = 0; i < 1024; i++)
		disk_write(i + 4, (Inode_table + i * BLOCK_SIZE));
	disk_write(1028, cata_buffer);

在mkfs中,已经出现了非常困难的两个敌人:malloc -> free,以及disk_read -> disk_write 这两个部分将给我的fslab写作带来极坏的体验

fs_getattr

思路:

  1. 解析目录
  2. 访问根目录inode
  3. 访问根目录datablock
  4. 根据名称找到一级目录的inumber
  5. 若一级目录不是目标目录,找到一级目录inode和datablock
  6. 重复4、5步,直至找到目标目录
  7. 找到目标inode
  8. 写入stat attr
    细节:
    解析目录:将目录以char ** 数组的形式存储,按照’/'拆分,每一个char
    是一级目录。在malloc char** 的时候,要多分配一个char* 空间,以确保最后一级目录的下一个path一定是NULL或strlen为0.
    寻找目标目录:对于每一个inode,遍历它的所有目录块。对于这个块下面的所有目录,如果找到对应目录/文件,如果是文件 或 最后一个目录,完成搜索;如果是目录(且非最后一个),找到该目录的inode,读取下一个目录。如果已经完成搜索 或 需要更换Inode,跳出指针遍历循环。如果遍历了所有指针块仍然没有找到目标,返回未找到。
    问题:
    getattr作为最频繁被调用的函数,问题实在是太太太多了……首先是解析目录,一开始没有为目录多分配一个char*空间(我的分发是:只要遇到’/',num++,真实的目录数量是num+1,要多分配就要变成num+2),导致path[k+1]常常是乱码,无法终止循环
    然后是attr结构体,不能malloc,不能free,不然会有奇怪的内存错误
    最后是不要随意修改返回值,会造成bad error value的错误
    还有很多错误,都忘记怎么解决的了。但是看到我在这个函数里写的调试信息,应该能感受到我写时的精神状态

fs_readdir

思路:

  1. 利用getattr 查询该目录信息
  2. 获取目录inumber/block等磁盘位置信息
  3. 读取目录对应inode内容
  4. 遍历db每一个dir_node, 将有效文件/目录写入buffer
  5. 释放内存
    细节:
    在遍历db每一个dir_node的时候,注意判断该文件或目录是否已经被删除
if(strlen(db_buffer[i].name) == 0)
{
	if(db_buffer[i].i_ino == -5)
		continue;
	else 
		break;
}

问题同细节

fs_read

思路:

  1. 利用getattr查询该文件信息
  2. 读取Inode
  3. 更新atime,写回磁盘
  4. 把该文件的所有内容都读取到file中
  5. 利用memcpy,从offset处读取file,共读取readline个字节
  6. 释放内存空间
    细节:
    读取Inode:
    int blk = ((ino * INODE_SIZE) / BLOCK_SIZE) + 4;           //Inode在第blk个块中
	int sec = ((ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;  //Inode在该块中的第sec个位置
	disk_read(blk, inode_buffer);

遍历所有的datablock(利用一级指针和二级指针),读取内容至file中

    for(int i = 0; i < current.i_blocks_count; i++)     //遍历所有datablock
	{
		if(i < 18)                                      //对于一级指针块
		{
			cur_blk = current.i_block_pointer[i];
			disk_read(cur_blk, file);
			file += BLOCK_SIZE;                         //更新起始位置
		}
		else                                            //对于二级指针块
		{
			dir_blk = current.i_double_block_pointer;   //目录快
			disk_read(dir_blk,dir_buffer);
			cur_blk = dir_buffer[i - 18];               //文件块
			disk_read(cur_blk, file);
			file += BLOCK_SIZE;                         //更新起始位置
		}
	}
	printf("read data is done\n");

利用memcpy读取:

    char* start = origin + offset;              //读取的起始位置
	int readlen;
	if(current.i_size - offset >= size)         //如果剩余字节足够
		readlen = size;
	else
		readlen = current.i_size - offset;      //如果剩余字节不足
	memcpy(buffer,start,readlen);

问题:
最一开始,没有设置origin指针记录file的起始位置,结果由于file指针变更,读取失败

fs_mknod

思路:

  1. 遍历查找Imap中第一个空位并写
  2. 创建并初始化该文件inode
  3. 将该文件Inode写回磁盘中
  4. super_block更新
  5. 将该目录挂载在父目录下
    6. 分离父目录与子目录名, 并调用getattr()获取新创建目录的上一级目录信息
    7. 查询父目录信息
    8. 读取父目录的inode
    9. 挂载父目录
    10. 修改父目录inode
    11. 将父目录inode写回磁盘中
  6. 释放内存空间
    细节:
    挂载父目录:
  7. 找到父目录最后一个目录块
int block_num = node_buffer[iloc].i_size / BLOCK_SIZE;
  1. 若block_num < 18, 只使用一级指针
if(node_buffer[iloc].i_block_pointer[block_num] < 0)	    //该指针尚未分配块
{
	new_cata_once(&node_buffer[iloc],block_num);
}
cata_db = node_buffer[iloc].i_block_pointer[block_num];		//最后一个目录块
printf("use once pointer, cata_db is:%d\n",cata_db);
disk_read(cata_db,cata_buffer);
for(int j = 0; j < 128; j++)	                            //寻找父目录的第一个空闲cata
{
	if(strlen(cata_buffer[j].name) == 0)	                //找到空闲块,挂载
	{
		printf("strlen:%d\n",strlen(myself));
		memcpy(cata_buffer[j].name,myself,strlen(myself));
		cata_buffer[j].i_mode = REGMODE;							
		cata_buffer[j].i_ino = start_i;
		disk_write(cata_db,cata_buffer);
		enough_flag = 1;
		find_flag = 1;
		break;
	}
}

若该块空间不够,为父目录分配新块
如果cata_db != 17,一级指针尚有空间。分配一级指针快并且写入第一个catalog
否则,分配二级指针块
3. 如果block_num > 18,说明已经分配了二级指针
重复一级指针块的操作直至二级指针的目录块也被分配满
4. 如果所有的块都挂满,返回-ENOSPC
分配二级指针块:

void new_cata_twice(Inode parent_node)
{
	int dir_db = find_dmap();	//为二级指针块分配空间
	parent_node->i_double_block_pointer = dir_db;
	// 清空二级指针块
	int * int_buffer = (int *)malloc(BLOCK_SIZE);
	disk_read(dir_db, int_buffer);
	for(int i = 0; i < 1024; i++) 	//清空指针
		int_buffer[i] = -1;
	// 为二级指针db中第一个int指针分配db
	int first_double_db = find_dmap();
	int_buffer[0] = first_double_db;
	disk_write(dir_db, int_buffer);
	parent_node->i_blocks_count += 1;
	free(int_buffer);
}

分配一级指针块的过程过于简单,在此不赘述
问题:
问题实在是太多了,这个函数应该是我debug倒数第二久的一个函数(最久的是getattr),直到ddl当天的上午还在de。大部分错误都忘了是怎么回事了,仅举几例还记得的:

  1. 未检测指针块是否已分配,直接挂载,导致指针乱指,disk_write失败(随机写入块)
  2. disk_read后未及时write,磁盘里写入的数据和预想的不一样
  3. 将 遍历查找Imap中第一个空位并写 封装成一个函数,但是没有在函数内部malloc和free Inode,而是作为参数传递,导致segmentation fault. 此事给我的教训特别深刻,以后在写的时候都尽量将malloc和free在同一个函数中成对进行
  4. 当文件名长度为24时,strcpy和memcpy都无法为cata.name设置’/0’,导致字符串结尾乱码。这个我看了一圈,没有什么太好的解决办法。为了维持catalog的大小不超过32B,char[]只能分配24B。最后没有办法,使用strncmp和strncpy,忽略结尾的乱码,只比较和读取前24个字节

fs_mkdir

和fs_mknod几乎完全相同,把REGMODE改成DIRMODE就行了
说到这里,再说一下一个奇怪问题。使用fuse中定义的REGMODE和DIRMODE,不知为何无法正确判断==和!=,我猜测是由于fuse定义的REGMODE和DIRMODE不是一般意义上的整数,将其直接定义为对应的整数就解决了

fs_rmdir

思路:

  1. 找到父目录
  2. 更新父目录的ctime与mtime
  3. 将该目录从父目录的db中删除
  4. 父目录的link数减一
  5. 将父目录的Inode和db写回磁盘
  6. 清除本目录的Inode信息
  7. 释放本目录占据的db(置为0)(此时清除对应的Dmap)
  8. 清除Imap
    细节:
    与mkdir相匹配,将目录从父目录中删除时,需要遍历一级指针和二级指针以找到该目录
    在删除时,将cata.name置为0,并将cata.ino设置为-5,以标志这是一个被删除的目录
    在清除datablock时,也要清除全部的一级指针和二级指针以及二级目录块
    问题:
    最一开始写的时候,只是单纯把cata.name置为0(其实那个时候catalog里还包含i_blocks_link,我用那个判断,后来将其删除后才使用cata.name判断),没有设置cata.ino标志,在ls中就会出现找到了对应文件(空文件名也是文件名)但是找不到对应块的情况。必须在readdir中检查标志位。

fs_unlink

与fs_rmdir基本相同

fs_rename

思路:

  1. 解析新旧目录,获取新旧父目录的ino和文件名
  2. 若父路径不变,只修改名字
  3. 否则删除就路径,更改为新路径
    4. 遍历旧路径db寻找待改路径文件/目录
    5. 更新旧路径inode
    6. 将target node加入新路径
    7. 遍历新路径db寻找是否有空位写入dir_node
    8. 若无,则分配新db
    细节:更新路径时注意遍历二级指针块
    问题:意外的没有什么问题

fs_write

思路:

  1. 判断权限
  2. 解析目录
  3. 获得要写的文件的inumber
  4. 若该文件还未被创建
    5. 创建新文件
    6. 将文件写入db
  5. 若已被创建
    8. 覆盖写,修改文件大小,清空该文件的db,将文件写入db
    9. 追加写,修改文件大小,若需要写入的字节数不整齐,则写入剩余的字节,再写入整齐的字节
  6. 修改inode,写入磁盘
    细节:
    写入整块:循环写入新块,寻找Dmap的空位并写Dmap,将buffer写入disk,更新下次写的起始位置。注意分配二级指针。
    问题:创建文件不能直接调用mknod,因为不能随意修改返回值,否则出现错误

fs_truncate

思路:

  1. 根据inumber找到inode
  2. 读取inode
  3. 修改size、ctime
  4. 在修改size的时候判断剩余空间
  5. 写回inode
    细节:
    注意修改的文件size不能大于8MB

fs_utime

思路:

  1. 读取inode
  2. 修改time
  3. 写回磁盘

fs_statfs

思路:

  1. 遍历Imap,Dmap,找出空闲块数量
  2. 写入statvfs *stat
    细节:
    注意位运算正确性。为了确定自己的位运算正确,我在调试时将每一条Imap[i]和Dmap[i]以二进制格式打印出来

fs_open

思路:

  1. 利用getattr查询文件信息
  2. 检查权限
    细节:
    linux fuse判断文件权限有自己的一套规则,我csdn了一下,然后找着实际fuse的规则写的

结果

前14个trace在mount模式下通过,最后一个trace在debug模式下通过(是的我手动敲了128个mkdir和cd dir),但不知为何无法在mount模式下通过

完整代码

/*
Filesystem Lab disigned and implemented by Liang Junkai,RUC
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <fuse.h>
#include <errno.h>
#include <stdlib.h>
#include "disk.h"

// 目录mode与普通文件mode
#define DIRMODE 16877
#define REGMODE 33188

// 至少支持文件或目录数量
#define FILE_NUM 32768
// inode节点大小
#define INODE_SIZE 128
// super block大小
#define SUPERBLOCK_SIZE 4096
// Imap大小
#define IMAP_SIZE 4096
// Dmap大小
#define DMAP_SIZE 8192
// Inodes table大小
#define INODE_TABLE_SIZE (FILE_NUM * INODE_SIZE)
// 块大小
#define BLOCK_SIZE 4096		// 4KB
// 文件最大大小
#define MAX_SIZE 8<<20		// 8MB
// 总块数
#define BLOCK_NUM 65536		// 0-65535 block_id
// 全1掩码
#define MASK_ALL ~1 + 1
// 最高位为1的掩码
#define MASK_ONE 1<<31
typedef struct super_node
{
	int 		inode_num;			// inode_num = FILE_NUM
	int 		block_num;			// block_num = BLOCK_NUM
	int* 		imap_block;			// Imap位置
	int* 		dmap_block;			// Dmap位置
	int			dir_count;			// 目录数量
	int 		file_count;			// 文件数量
	int*		inode_table_block;	// Inodes table位置
}super_node, *SuperNode;

typedef struct inode						// 128B
{
	mode_t 		i_mode;						// 文件mode/目录mode
	nlink_t 	i_links_count;				// 链接数
	off_t   	i_size;						// 文件大小
	time_t  	i_atime;					// 文件被访问的时间
	time_t		i_mtime;					// 文件被修改的时间
	time_t		i_ctime;					// 文件状态改变时间
	int			i_blocks_count;				// 文件占据block数量
	int 		i_block_pointer[18];		// 18个一级指针			// 4B * 18 = 72B
	int			i_double_block_pointer;		// 1个二级指针			// 4B * 1 = 4B
}inode, *Inode;
// 创建目录结构体,存放在目录的db中
typedef struct catalog						//32B
{
	char name[24];							//名字				   //24B
	//nlink_t i_links_count;					//链接数			   //2B
	mode_t i_mode;							//模式(目录/文件)		//2B
	int i_ino;								//i-number			  //4B

}catalog, *Catalog;
SuperNode super_block;
int find_imap();	
int find_dmap();	
char** getpath(const char* path, char** temp);	
int find_target(char** temp);
void cleardb(Inode current);	//给定inode,清除它的所有db
void clearimap(int file_ino);	//给定Inode的ino,清除它的imap标志
int find_parent(char* path,char* myself);

// /* disk.h宏定义 */
// #define BLOCK_SIZE 4096		// 4KB
// #define BLOCK_NUM 65536		// 0-65535 block_id
// #define DISK_SIZE (BLOCK_SIZE * BLOCK_NUM)	// 256MB
// /*
// 	block_id : 0-65535
// 	buffer : 指向一块4KB的连续内存
// 	当执行写操作后,buffer指向的内存中的数据会被写入指定块中
// */
// int disk_read(int block_id, void *buffer);
// int disk_write(int block_id, void *buffer);

//Format the virtual block device in the following function
int mkfs()
{
	int* Imap;
	int* Dmap;
	Inode Inode_table;
	// 创建super_block
	super_block = (SuperNode)malloc(SUPERBLOCK_SIZE);			// 4KB
	// 创建Imap
	Imap = (int*)malloc(IMAP_SIZE);		// 4KB
	memset(Imap, 0, IMAP_SIZE);
	// 创建Dmap
	Dmap = (int*)malloc(DMAP_SIZE);		// 8KB
	memset(Dmap, 0, DMAP_SIZE);
	// 创建Inode_table
	Inode_table = (Inode)malloc(INODE_TABLE_SIZE);	// 4MB
	memset(Inode_table, 0, INODE_TABLE_SIZE);
	// 初始化super_block
	super_block->inode_num = FILE_NUM;
	super_block->block_num = BLOCK_NUM;
	super_block->imap_block = Imap;
	super_block->dmap_block = Dmap;
	super_block->dir_count = 0;
	super_block->file_count = 0;
	super_block->inode_table_block = Dmap + DMAP_SIZE;
	// 创建根目录root的inode
	Inode_table[0].i_mode = DIRMODE;
	Inode_table[0].i_links_count = 0;
	Inode_table[0].i_size = sizeof(catalog);
	Inode_table[0].i_atime = time(NULL);
	Inode_table[0].i_mtime = time(NULL);
	Inode_table[0].i_ctime = time(NULL);
	Inode_table[0].i_blocks_count = 1;
	for(int i = 0; i < 18; i++)
		Inode_table[0].i_block_pointer[i] = -1;
	Inode_table[0].i_double_block_pointer = -1;
	// 创建root的datablock
	Inode_table[0].i_block_pointer[0] = 1028;
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);
	cata_buffer[0].i_ino = 0;
	cata_buffer[0].i_mode = DIRMODE;
	strcpy(cata_buffer[0].name, "/");
	// super_block更新
	super_block->dir_count += 1;
	// Imap更新
	Imap[0] |= 1 << 31;		// 只有root占用1个inode
	// Dmap更新
	/* 	
		super block, imap, dmap, inodes table
		共占据db 1+1+2+1024+1=1028个db
		需要将1028个bit置1	
	*/
	int i = 0;
	for(i = 0; i < 1029 / 32; i++) Dmap[i] = -1;	// 前1024个bit置1
	Dmap[i] = 1 << 31 >> (1029 % 32 - 1);			// 剩余5个bit置1
	// 将super_block, Imp, Dmap, Root 写入磁盘
	disk_write(0, super_block);
	disk_write(1, Imap);
	disk_write(2, Dmap);
	disk_write(3, Dmap + (DMAP_SIZE) / 2);
	for(i = 0; i < 1024; i++)
		disk_write(i + 4, (Inode_table + i * BLOCK_SIZE));
	disk_write(1028, cata_buffer);
	// 释放内存空间
	free(Imap);
	free(Dmap);
	free(Inode_table);
	free(cata_buffer);
	return 0;
}
//将路径拆分为目录名和文件名
char** getpath(const char* path, char** temp)
{
	char array[2560];
	char *buf = array;
	if(path[0] == '/' && strlen(path) > 1){
		path++;
	}
	strcpy(buf, path);
	int num = 0;
	for(int i = 0; i < strlen(buf); i++)
		if(buf[i] == '/') num++;
	num += 2;
	temp = (char **)malloc(sizeof(char *) * num);
	memset(temp, 0, (sizeof(char *) * num));
	printf("make temp\n");
	for(int k = 0; k < num; k++){
		temp[k] = (char*)malloc(24 * sizeof(char));
		memset(temp[k], 0, 24);
		// printf("make temp[%d]\n",k);
	}
	printf("finish make temp\n");
	int argc = 0;
	int i = 0;
	strcpy(buf, path);
	printf("finish copy buf,buf is:%s\n",buf);
	printf("strlen buf:%d\n",strlen(buf));
	int count = strlen(buf);
	char* origin = buf;
	while(buf < (origin+count)){
		if((*buf) == '/'){
			temp[argc][i] = '\0';
			i = 0;
			printf("argc:%d\n",argc);
			argc++;
			buf++;
		}
		temp[argc][i++] = *buf;
		buf++;
	}
	printf("finish make buf\n");
	temp[argc][i] = '\0';
	return temp;
}

int find_target(char** temp)
{
	printf("start find target\n");
	// 特殊处理root根目录"/"
	if(strlen(temp[0]) == 0) 
		temp[0] = "/";
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);			//4KB空间用于存放得到的inode
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);		//4KB空间用于存放得到的catalog
	disk_read(4,node_buffer);		//访问根目录inode
	printf("finish read root inode\n");
	char* dir = temp[0];
	inode current;	//当前搜索的Inode
	int cata_db;	//目录文件的db
	int k = 0;
	int blk;		//inode所在磁盘块的编号
	int iloc;		//inode在所在磁盘块中的位置
	int count = 0;
	int block_num;
	int flag = 0;
	int find_flag = 0;
	int file_ino = -1;	// 最终找到的inumber
	int end_search_flag = 0;
	// 从根目录db开始检索子目录/子文件
	current = node_buffer[0];
	block_num = node_buffer[0].i_blocks_count;
	printf("			length : %d\n", block_num);
	while(!end_search_flag)		//对于每一个inode
	{
		find_flag = 0;			//新的Inode
		count = 0;				//每一个inode共遍历了几个目录块
		block_num = current.i_blocks_count;
		for(int p = 0; p < block_num; p++)		//遍历它的所有目录块
		{
			count++;
			if(find_flag)	//已经完成搜索 或 需要更换Inode
				break;
			if(p < 18)
			{
				cata_db = current.i_block_pointer[p];
				disk_read(cata_db, cata_buffer);
				for(int i = 0; i < 128; i++)	//对于这个块下面的所有目录
				{
					// if(strlen(cata_buffer[i].name) == 0){
					// 	if(cata_buffer[i].i_ino != -5){
					// 		flag = 0;
					// 		break;
					// 	}
					// }
					if(!strncasecmp(dir,cata_buffer[i].name,strlen(dir)))	//如果找到对应目录/文件
					{
						printf("find target\n");
						// printf("next strlen:%d\n",strlen(temp[k+1]));
						if(cata_buffer[i].i_mode == REGMODE || temp[k+1] == NULL || strlen(temp[k+1]) == 0)	
						{	//如果是文件 或 最后一个目录
							file_ino = cata_buffer[i].i_ino;
							end_search_flag = 1;
							find_flag = 1;
							// printf("in cata_buffer[%d], find target %s\n",i,cata_buffer[i].name);
							break;
						}
						else	//如果是目录(且非最后一个)
						{
							// 找到该目录的inode
							blk = (cata_buffer[i].i_ino * INODE_SIZE) / BLOCK_SIZE + 4;
							iloc = ((cata_buffer[i].i_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
							// 访问该目录的inode
							disk_read(blk, node_buffer);
							// 找到该目录的inode
							current = node_buffer[iloc];
							find_flag = 1;
							k++;	//读取下一个目录
							dir = temp[k];
							if(dir == NULL)
							{
								printf("can't find target with k: %d\n",k);
								return -ENOSPC;
							}
							// printf("next target is: %s\n",dir);
							break;
						}
					}
				}
			}
			else
			{
				int* dir_buffer = (int*)malloc(BLOCK_SIZE);
				int dir_db = current.i_double_block_pointer;
				disk_read(dir_db,dir_buffer);
				cata_db = dir_buffer[p - 18 - 1];
				disk_read(cata_db, cata_buffer);
				for(int i = 0; i < 128; i++)	//对于这个块下面的所有目录
				{
					if(!strncasecmp(dir,cata_buffer[i].name,strlen(dir)))	//如果找到对应目录/文件
					{
						printf("find target\n");
						printf("next strlen:%d\n",strlen(temp[k+1]));
						if(cata_buffer[i].i_mode == REGMODE || temp[k+1] == NULL || strlen(temp[k+1]) == 0)	
						{	//如果是文件 或 最后一个目录
							file_ino = cata_buffer[i].i_ino;
							end_search_flag = 1;
							find_flag = 1;
							// printf("in cata_buffer[%d], find target %s\n",i,cata_buffer[i].name);
							break;
						}
						else	//如果是目录(且非最后一个)
						{
							// 找到该目录的inode
							blk = (cata_buffer[i].i_ino * INODE_SIZE) / BLOCK_SIZE + 4;
							iloc = ((cata_buffer[i].i_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
							// 访问该目录的inode
							disk_read(blk, node_buffer);
							// 找到该目录的inode
							current = node_buffer[iloc];
							find_flag = 1;
							k++;	//读取下一个目录
							dir = temp[k];
							if(dir == NULL)
							{
								printf("can't find target with k: %d\n",k);
								return -ENOSPC;
							}
							// printf("next target is: %s\n",dir);
							break;
						}
					}
				}
				free(dir_buffer);
			}
		}
		if(count == block_num && end_search_flag == 0 && find_flag == 0)		//如果遍历了这个inode的所有目录块仍未找到
		{
			file_ino = -1;
			end_search_flag = 1;
		}
	}

	free(node_buffer);
	free(cata_buffer);
	return file_ino;
}

int find_parent(char* path,char* myself)
{
	printf("start find parent with path: %s\n",path);
	char temp[2560];		//父目录名
    strcpy(temp, path);
	printf("str: %d\n",strlen(temp));
	printf("old temp:%s\n",temp);
	// 提取新目录名, 分离父目录
    for(int i = strlen(temp) - 2; i >= 0; i--){
        if(temp[i] == '/'){
            temp[i] = '\0';
            strcpy(myself, temp + i + 1);
            break;
        }
    }
	// 若path只有新目录名无父目录, 则父目录为根目录root
    if(strlen(temp) == 0){
        temp[0] = '/';
        temp[1] = '\0';
    }
	printf("myself:%s\n",myself);
	printf("new temp:%s\n",temp);
	int parent_ino = cur_find(temp);
	return parent_ino;
}
int cur_find(const char* path)
{
	char** temp;
	temp = getpath(path,temp);	//解析目录
	int file_ino;	//文件 或 最后一级目录的inumber
	//mode_t c_mode;	//文件模式
	int cata_db;	//目录文件的db
	int blk;		//inode所在磁盘块的编号
	int iloc;		//inode在所在磁盘块中的位置
	file_ino = find_target(temp);
	if(file_ino < 0)
	{
		printf("(Getattr) Cannot find path: %s\n", path);
        return -ENOENT;
	}
	printf("finish find target inode\n");
	return file_ino;
}
//Filesystem operations that you need to implement
int fs_getattr (const char *path, struct stat *attr)
{
	//查询一个目录文件或常规文件的信息
	//解析目录-访问根目录inode-访问根目录db-根据名称找到一级目录的inumber
	//-找到一级目录inode-找到一级目录db-根据名称找到二级目录/文件的inumber
	//-找到文件inode-获得文件stat
	printf("Getattr is called:%s\n",path);
	char** temp;
	temp = getpath(path,temp);	//解析目录
	int file_ino = find_target(temp);
	if(file_ino < 0)
	{
		printf("(Getattr) Cannot find path: %s\n", path);
        return -ENOENT;
	}
	printf("finish find target inode\n");
	printf("file ino:%d\n",file_ino);
	// 读取目标文件/目录的inode
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);
	int blk = (file_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	int iloc = ((file_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("blk:%d    iloc:%d\n",blk,iloc);
	if(disk_read(blk, node_buffer))
		printf("fail to read target inode\n");
	attr->st_ino = file_ino;
	attr->st_mode = node_buffer[iloc].i_mode;
	attr->st_nlink = 1;
	attr->st_uid = getuid();
	attr->st_gid = getgid();
	attr->st_size = node_buffer[iloc].i_size;
	attr->st_atime = node_buffer[iloc].i_atime;
	attr->st_mtime = node_buffer[iloc].i_mtime;
	attr->st_ctime = node_buffer[iloc].i_ctime;
	printf("%d %d %d %d\n", attr->st_mode, attr->st_ino, attr->st_size, attr->st_atime);
	free(node_buffer);
	// free(temp);
	printf("Getattr is finished: %s\n", path);
	return 0;
}
//查询一个目录下的所有文件
int fs_readdir(const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
	printf("Readdir is called:%s\n", path);
	// 查询该目录信息
	char name[28];
	struct stat attr;
	fs_getattr(path, &attr);
	int ino = attr.st_ino;
	if(attr.st_mode == DIRMODE)
		ino = attr.st_ino;
	else
		return -ENOENT;
	printf("attr.st_ino:%d\n",attr.st_ino);
	// 获取目录inumber/block等磁盘位置信息
	int blk = ((ino * INODE_SIZE) / BLOCK_SIZE) + 4;
	int sec = ((ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	Inode inode_buffer = (Inode)malloc(BLOCK_SIZE);
	Catalog db_buffer = (Catalog)malloc(BLOCK_SIZE);
	// 读取目录对应inode内容
	disk_read(blk, inode_buffer);
	// 遍历db每一个dir_node, 将有效文件/目录写入buffer
	int block_num = inode_buffer[sec].i_blocks_count;
	for(int p = 0; p < block_num; p++)
	{
		if(p < 18)
		{
			disk_read(inode_buffer[sec].i_block_pointer[p], db_buffer);
			printf("pointer:%d    pointer db:%d\n",p,inode_buffer[sec].i_block_pointer[p]);
			int i = 0;
			if(inode_buffer[sec].i_block_pointer[p] == 1028) i = 1;
			for(i; i < 128; i++)
			{
				if(strlen(db_buffer[i].name) == 0)
				{
					if(db_buffer[i].i_ino == -5)
						continue;
					else 
						break;
				}
				struct stat *temp = (struct stat *)malloc(sizeof(struct stat));
				Inode tempBlock = (Inode)malloc(sizeof(inode) * 32);
				int kid_ino = db_buffer[i].i_ino;
				int kid_blk = ((kid_ino * INODE_SIZE) / BLOCK_SIZE) + 4;
				int kid_sec = ((kid_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
				disk_read(kid_blk, tempBlock);
				temp->st_mode = tempBlock[kid_sec].i_mode;
				temp->st_nlink = 1;
				temp->st_uid = getuid();
				temp->st_gid = getgid();
				temp->st_size = tempBlock[kid_sec].i_size;
				temp->st_atime = time(NULL);
				temp->st_mtime = tempBlock[kid_sec].i_mtime;
				temp->st_ctime = tempBlock[kid_sec].i_ctime;
				int num = 24;
				strncpy(name,db_buffer[i].name,24);
				name[24] = '\0';
				printf("name:%s\n",name);
				// 写入缓冲区
				filler(buffer, name, temp, offset);
				free(temp);
				free(tempBlock);
			}
		}
		else
		{
			int indir = inode_buffer[sec].i_double_block_pointer;
			int * int_buffer = (int *)malloc(sizeof(int) * 1024);
			disk_read(indir, int_buffer);
			disk_read(int_buffer[p - 18 - 1], db_buffer);
			free(int_buffer);
			int i = 0;
			if(inode_buffer[sec].i_block_pointer[p] == 1028) i = 1;
			for(i; i < 128; i++)
			{
				
				if(strlen(db_buffer[i].name) == 0)
				{
					if(db_buffer[i].i_ino == -5)
						continue;
					else 
						break;
				}
				struct stat *temp = (struct stat *)malloc(sizeof(struct stat));
				Inode tempBlock = (Inode)malloc(sizeof(inode) * 32);
				int kid_ino = db_buffer[i].i_ino;
				int kid_blk = ((kid_ino * INODE_SIZE) / BLOCK_SIZE) + 4;
				int kid_sec = ((kid_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
				disk_read(kid_blk, tempBlock);
				temp->st_mode = tempBlock[kid_sec].i_mode;
				temp->st_nlink = 1;
				temp->st_uid = getuid();
				temp->st_gid = getgid();
				temp->st_size = tempBlock[kid_sec].i_size;
				temp->st_atime = time(NULL);
				temp->st_mtime = tempBlock[kid_sec].i_mtime;
				temp->st_ctime = tempBlock[kid_sec].i_ctime;
				// 写入缓冲区
				filler(buffer, db_buffer[i].name, temp, offset);
				free(temp);
				free(tempBlock);
			}
		}
	}
	// 释放内存
	free(inode_buffer);
	free(db_buffer);
	printf("Readdir is finished : %s\n", path);
	return 0;
}

int fs_read(const char *path, char *buffer, size_t size, off_t offset, struct fuse_file_info *fi)
{
	//查询该文件信息
	printf("Read is called : %s\n", path);
	struct stat attr;
	fs_getattr(path, &attr);
	if(attr.st_mode == DIRMODE)
	{
		printf("this is not a file!\n");
		return -EISDIR;
	}
	if(offset > attr.st_size)
	{
		printf("too much offset\n");
		return -ERANGE;
	}
	// 获取文件inumber/block等磁盘位置信息
	int ino = attr.st_ino;
	int blk = ((ino * INODE_SIZE) / BLOCK_SIZE) + 4;
	int sec = ((ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("(Read:)blk:%d   sec:%d\n",blk,sec);
	Inode inode_buffer = (Inode)malloc(BLOCK_SIZE);
	disk_read(blk, inode_buffer);
	// 更新atime
	inode_buffer[sec].i_atime = time(NULL);
	inode current = inode_buffer[sec];
	disk_write(blk, inode_buffer);
	free(inode_buffer);
	char* origin = (char*)malloc(MAX_SIZE);
	memset(origin, 0, MAX_SIZE);
	char* file = origin;
	int* dir_buffer = (int*)malloc(BLOCK_SIZE);
	int cur_blk,dir_blk;
	// 把该文件的所有内容都读取到file中
	for(int i = 0; i < current.i_blocks_count; i++)
	{
		if(i < 18)
		{
			cur_blk = current.i_block_pointer[i];
			disk_read(cur_blk, file);
			file += BLOCK_SIZE;
		}
		else
		{
			dir_blk = current.i_double_block_pointer;
			disk_read(dir_blk,dir_buffer);
			cur_blk = dir_buffer[i - 18];
			disk_read(cur_blk, file);
			file += BLOCK_SIZE;
		}
	}
	printf("read data is done\n");
	char* start = origin + offset;
	int readlen;
	if(current.i_size - offset >= size)
		readlen = size;
	else
		readlen = current.i_size - offset;
	printf("readlen:%d\n",offset + readlen);
	memcpy(buffer,start,readlen);
	free(dir_buffer);
	free(origin);
	printf("Read is finished : %s\n", path);
	return readlen;
}
// 为父目录分配一个新的一级块
void new_cata_once(Inode parent_node,int block_num)
{
	int start_d = find_dmap();
	printf("new cata start_d: %d\n",start_d);
	if(block_num >= 18)
	{
		printf("block_num > 18\n");
		return -EPERM;
	}
	parent_node->i_block_pointer[block_num] = start_d;
	parent_node->i_blocks_count += 1;
}
// 为父目录分配一个新的二级块并设置第一个二级指针
void new_cata_twice(Inode parent_node)
{
	int dir_db = find_dmap();	//为二级指针块分配空间
	printf("new dir start_d:%d\n",dir_db);
	parent_node->i_double_block_pointer = dir_db;
	// 清空二级指针块
	int * int_buffer = (int *)malloc(BLOCK_SIZE);
	disk_read(dir_db, int_buffer);
	for(int i = 0; i < 1024; i++) 	//清空指针
		int_buffer[i] = -1;
	// 为二级指针db中第一个int指针分配db
	int first_double_db = find_dmap();
	printf("first double db:%d\n",first_double_db);
	int_buffer[0] = first_double_db;
	disk_write(dir_db, int_buffer);
	parent_node->i_blocks_count += 1;
	free(int_buffer);
}
// 创建一个常规文件
int fs_mknod (const char *path, mode_t mode, dev_t dev)
{
	printf("Mknod is called:%s\n",path);
	// 遍历查找Imap中第一个空位并写
	int start_i = find_imap();
	printf("find imap is finished,start_i is %d\n",start_i);
	if(start_i < 0)
		exit(0);
	//创建inode
	Inode Inode_buffer = (Inode)malloc(BLOCK_SIZE);
	int i_blk = ((start_i * INODE_SIZE) / BLOCK_SIZE) + 4;
	int i_sec = ((start_i * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("i_blk: %d    i_sec: %d\n",i_blk,i_sec);
	disk_read(i_blk,Inode_buffer);
	Inode_buffer[i_sec].i_mode = REGMODE;
	Inode_buffer[i_sec].i_links_count = 0;
	Inode_buffer[i_sec].i_size = 0;
	Inode_buffer[i_sec].i_atime = time(NULL);
	Inode_buffer[i_sec].i_mtime = time(NULL);
	Inode_buffer[i_sec].i_ctime = time(NULL);
	Inode_buffer[i_sec].i_blocks_count = 0;
	for(int i = 0; i < 18; i++)
		Inode_buffer[i_sec].i_block_pointer[i] = -1;
	Inode_buffer[i_sec].i_double_block_pointer = -1;
	//将Inode写回磁盘中	
	disk_write(i_blk,Inode_buffer);
	printf("write inode is finished\n");
	//super_block更新
	super_block->file_count += 1;
	printf("create inode is finished\n");
	//将该目录挂载在父目录下
	char myself[24];	//自己的文件名
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);			//4KB空间用于存放得到的inode
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);		//4KB空间用于存放得到的catalog

	// 分离父目录与子目录名, 并调用getattr()获取新创建目录的上一级目录信息
    char temp[2560];
    strcpy(temp, path);
	// 提取新目录名, 分离父目录
    for(int i = strlen(temp) - 2; i >= 0; i--){
        if(temp[i] == '/'){
            temp[i] = '\0';
            strcpy(myself, temp + i + 1);
            break;
        }
    }
	// 若path只有新目录名无父目录, 则父目录为根目录root
    if(strlen(temp) == 0){
        temp[0] = '/';
        temp[1] = '\0';
    }
	printf("parent path:%s\n",temp);
	// 查询父目录信息
	int parent_ino = cur_find(temp);
	if(parent_ino < 0)
	{
		printf("(Mknod): Cannot find path: %s\n", path);
        return -ECHILD;
	}
	printf("find parent is finished\n");
	// 读取父目录的inode
	int blk = (parent_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	int iloc = ((parent_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("parent blk:%d   parent iloc:%d\n",blk,iloc);
	disk_read(blk, node_buffer);
	// 挂载在父目录上
	int cata_db;	//目录块序号
	int find_flag = 0;
	int enough_flag = 0;
	// 找到父目录最后一个目录块
	int block_num = node_buffer[iloc].i_size / BLOCK_SIZE;
	if(block_num < 18)		//只使用一级指针
	{	if(node_buffer[iloc].i_block_pointer[block_num] < 0)	//该指针尚未分配块
		{
			new_cata_once(&node_buffer[iloc],block_num);
		}
		cata_db = node_buffer[iloc].i_block_pointer[block_num];		//最后一个目录块
		printf("use once pointer, cata_db is:%d\n",cata_db);
		disk_read(cata_db,cata_buffer);
		for(int j = 0; j < 128; j++)	//寻找父目录的第一个空闲cata
		{
			if(strlen(cata_buffer[j].name) == 0)	//找到空闲块,挂载
			{
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[j].name,myself,strlen(myself));
				// strcpy(cata_buffer[j].name,myself);
				printf("block is:%d, cata block is: %d, my name is: %s\n",cata_db,j,cata_buffer[j].name);
				//cata_buffer[j].i_links_count += 1;
				cata_buffer[j].i_mode = REGMODE;							
				cata_buffer[j].i_ino = start_i;
				disk_write(cata_db,cata_buffer);
				enough_flag = 1;
				find_flag = 1;
				break;
			}
		}
		if(!enough_flag)	//如果该块剩余空间不足
		{
			if(cata_db != 17)	//一级指针尚有空间
			{
				//为父目录分配一个新的cata块
				new_cata_once(&node_buffer[iloc],block_num + 1);
				// int num = node_buffer[iloc].i_blocks_count;
				cata_db = node_buffer[iloc].i_block_pointer[block_num + 1];
				printf("new once cata, cata_db is:%d\n",cata_db);
				disk_read(cata_db,cata_buffer);
				// 新块,直接写在第0个就可以了
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[0].name,myself,strlen(myself));
				// strcpy(cata_buffer[0].name,myself);
				printf("block is:%d, cata block is: %d, my name is: %s\n",cata_db,0,cata_buffer[0].name);
				//cata_buffer[0].i_links_count += 1;
				cata_buffer[0].i_mode = REGMODE;							
				cata_buffer[0].i_ino = start_i;
				disk_write(cata_db,cata_buffer);
				enough_flag = 1;
				find_flag = 1;
			}
			else	//分配二级指针块
			{
				new_cata_twice(&node_buffer[iloc]);
				int dir_db = node_buffer[iloc].i_double_block_pointer;
				int* int_buffer = (int*)malloc(BLOCK_SIZE);
				cata_db = int_buffer[0];
				printf("new twice cata, cata_db is:%d\n",cata_db);
				disk_read(cata_db,cata_buffer);
				// 新块,直接写在第0个就可以了
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[0].name,myself,strlen(myself));
				// strcpy(cata_buffer[0].name,myself);
				printf("block is:%d, cata block is: %d, my name is: %s\n",cata_db,0,cata_buffer[0].name);
				//cata_buffer[0].i_links_count += 1;
				cata_buffer[0].i_mode = REGMODE;							
				cata_buffer[0].i_ino = start_i;
				disk_write(cata_db,cata_buffer);
				enough_flag = 1;
				find_flag = 1;
				free(int_buffer);
			}
		}
	}
	else		//已经分配了二级指针
	{
		int * int_buffer = (int *)malloc(BLOCK_SIZE);
		disk_read(node_buffer[iloc].i_double_block_pointer, int_buffer);
		printf("have had twice pointer\n");
		for(int i = 0; i < 1024; i++)	//遍历指针块
		{
			if(find_flag)
				break;
			if(int_buffer[i] != -1)		//该目录块已被分配
			{
				disk_read(int_buffer[i], cata_buffer);
				printf("use twice pointer, cata_db is:%d\n",int_buffer[i]);
				for(int j = 0; j < 128; j++)
				{
					if(strlen(cata_buffer[j].name) == 0)	//找到空闲块,挂载
					{
						printf("strlen:%d\n",strlen(myself));
						memcpy(cata_buffer[j].name,myself,strlen(myself));
						// strcpy(cata_buffer[j].name,myself);
						printf("block is:%d, cata block is: %d, my name is: %s\n",int_buffer[i],j,cata_buffer[j].name);
						//cata_buffer[j].i_links_count += 1;
						cata_buffer[j].i_mode = REGMODE;							
						cata_buffer[j].i_ino = start_i;
						disk_write(int_buffer[i],cata_buffer);
						enough_flag = 1;
						find_flag = 1;
						break;
					}
				}
			}
			else if(!find_flag && int_buffer[i] == -1)		//需要分配新的目录块
			{
				int dir_db = find_dmap();
				int_buffer[i] = dir_db;
				disk_read(dir_db, cata_buffer);
				printf("new twice cata, cata_db is:%d\n",dir_db);
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[0].name,myself,strlen(myself));
				// strcpy(cata_buffer[0].name,myself);
				printf("block is:%d, cata block is: %d, my name is: %s\n",dir_db,0,cata_buffer[0].name);
				//cata_buffer[0].i_links_count += 1;
				cata_buffer[0].i_mode = REGMODE;							
				cata_buffer[0].i_ino = start_i;
				disk_write(dir_db,cata_buffer);
				enough_flag = 1;
				find_flag = 1;
				// 更新父目录的inode
				node_buffer[iloc].i_blocks_count += 1;
				break;
			}
		}
		free(int_buffer);
	}
	if(!enough_flag)	//如果没有足够空间
	{
		return -ENOSPC;
	}
	node_buffer[iloc].i_size += sizeof(catalog);
	printf("mount dir is finished\n");
	// 修改父目录inode
	printf("%d %d %d\n", node_buffer[iloc].i_mode, node_buffer[iloc].i_size, node_buffer[iloc].i_atime);
	node_buffer[iloc].i_links_count += 1;
	node_buffer[iloc].i_atime = time(NULL);
	node_buffer[iloc].i_mtime = time(NULL);		
	//将父目录inode写回磁盘中
	if(disk_write(blk, node_buffer))
		printf("fail to write parent inode\n");
	// //将父目录db写回磁盘中
	// if(disk_write(cata_db,cata_buffer))
	// 	printf("fail to write parent datablock\n");
	// printf("write parent is finished\n");
	printDirInode(parent_ino);	//检验是否挂载成功
	free(Inode_buffer);
	free(node_buffer);
	free(cata_buffer);
	printf("Mknod is finished:%s\n",path);
	return 0;
}

int find_imap()	// 遍历查找Imap中第一个空位并写
{
	int* Imap;
	Imap = (int*)malloc(IMAP_SIZE);		// 4KB
	disk_read(1,Imap);
	int free_flag = 0;
	int start_i = -100;				//Imap中第一个空位
	for(int i = 0; i < 1024; i++)
	{
		for(int j = 0; j < 32; j++)
		{
			int mask = 1 << (31 - j);
			if(!((Imap[i] & mask) >> (31 - j)))
			{
				free_flag = 1;
				start_i = i * 32 + j;
				// 更新imap
				int mask_i = start_i / 32;
				int mask_j = start_i % 32;
				int mask = 1 << (31 - mask_j);
				Imap[mask_i] = Imap[mask_i] | mask;
				break;
			}
		}
		if(free_flag) break;
	}
	disk_write(1,Imap);
	free(Imap);
	return start_i;
}

int find_dmap()	//遍历查找dmap中第一个空位并写
{
	int start_d = -100;
	int free_block_flag = 0;
	int* Dmap;
	Dmap = (int*)malloc(DMAP_SIZE);		// 8KB
	disk_read(2,Dmap);
	disk_read(3,Dmap + (DMAP_SIZE) / 2);
	for(int i = 0; i < 2048; i++)
	{
		for(int j = 0; j < 32; j++)
		{
			int mask = 1 << (31 - j);
			if(!((Dmap[i] & mask) >> (31 - j)))
			{
				free_block_flag = 1;
				start_d = i * 32 + j;
				// 更新Dmap
				Dmap[i] = Dmap[i] | mask;
				break;
			}
		}
		if(free_block_flag) break;
	}
	disk_write(2,Dmap);
	disk_write(3,Dmap + (DMAP_SIZE) / 2);
	free(Dmap);
	return start_d;
}

void printDirInode(int parent_ino)
{
	//读取父目录的db
	//遍历db,打印db中的目录
	//如果有当前目录,则挂载成功
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);

	int blk = (parent_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	int iloc = ((parent_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	if(disk_read(blk, node_buffer))
		printf("fail to read target inode\n");
	// 找到父目录的db
	int cata_db = node_buffer[iloc].i_block_pointer[0];
	printf("(Print node):cata_db is: %d\n",cata_db);
	// 访问父目录db
	disk_read(cata_db,cata_buffer);
	for(int i = 0; i < 5; i++)
	{
		if(cata_buffer[i].name != NULL)
		{
			printf("child dir is: %s\n",cata_buffer[i].name);
		}
		else
			break;
	}
	free(node_buffer);
	free(cata_buffer);
}

int fs_mkdir (const char *path, mode_t mode)
{
	// 创建目录的inode
	// 创建目录的db
	printf("Mkdir is called:%s\n",path);
	// 读取Imap
	// int* Imap;
	// Imap = (int*)malloc(IMAP_SIZE);		// 4KB
	// int* Dmap;
	// Dmap = (int*)malloc(DMAP_SIZE);		// 8KB
	// 遍历查找Imap中第一个空位并写
	int start_i = find_imap();
	printf("find imap is finished,start_i is %d\n",start_i);
	if(start_i < 0)
		exit(0);
	//遍历查找dmap中第一个空位并写
	int start_d = find_dmap();
	printf("find dmap is finished,start_d is %d\n",start_d);
	if(start_d < 0)
	 	exit(0);
	//创建inode
	Inode Inode_buffer = (Inode)malloc(BLOCK_SIZE);
	int i_blk = ((start_i * INODE_SIZE) / BLOCK_SIZE) + 4;
	int i_sec = ((start_i * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("i_blk: %d    i_sec: %d\n",i_blk,i_sec);
	disk_read(i_blk,Inode_buffer);
	Inode_buffer[i_sec].i_mode = DIRMODE;
	Inode_buffer[i_sec].i_links_count = 1;
	Inode_buffer[i_sec].i_size = sizeof(catalog);
	Inode_buffer[i_sec].i_size = sizeof(catalog);
	Inode_buffer[i_sec].i_atime = time(NULL);
	Inode_buffer[i_sec].i_mtime = time(NULL);
	Inode_buffer[i_sec].i_ctime = time(NULL);
	Inode_buffer[i_sec].i_blocks_count = 1;
	for(int i = 0; i < 18; i++)
		Inode_buffer[i_sec].i_block_pointer[i] = -1;
	Inode_buffer[i_sec].i_double_block_pointer = -1;
	Inode_buffer[i_sec].i_block_pointer[0] = start_d;
	//将Inode写回磁盘中	
	disk_write(i_blk,Inode_buffer);
	printf("write inode is finished\n");
	//super_block更新
	super_block->dir_count += 1;
	printf("create inode is finished\n");
	//将该目录挂载在父目录下
	char myself[24];										//自己的文件名
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);			//4KB空间用于存放得到的inode
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);		//4KB空间用于存放得到的catalog

	// 分离父目录与子目录名, 并调用getattr()获取新创建目录的上一级目录信息
    char temp[2560];
    strcpy(temp, path);
	// 提取新目录名, 分离父目录
    for(int i = strlen(temp) - 2; i >= 0; i--){
        if(temp[i] == '/'){
            temp[i] = '\0';
            strcpy(myself, temp + i + 1);
            break;
        }
    }
	// 若path只有新目录名无父目录, 则父目录为根目录root
    if(strlen(temp) == 0){
        temp[0] = '/';
        temp[1] = '\0';
    }
	printf("parent path:%s\n",temp);
	// 查询父目录信息
	int parent_ino = cur_find(temp);
	if(parent_ino < 0)
	{
		printf("(Mkdir) Cannot find path: %s\n", path);
        return -ECHILD;
	}
	printf("find parent is finished\n");
	// 读取父目录的inode
	int blk = (parent_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	int iloc = ((parent_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("parent blk:%d   parent iloc:%d\n",blk,iloc);
	if(disk_read(blk, node_buffer))
		printf("fail to read target inode\n");
	// 挂载在父目录上
	int cata_db;	//目录块序号
	int find_flag = 0;
	int enough_flag = 0;
	// 找到父目录最后一个目录块
	int block_num = node_buffer[iloc].i_size / BLOCK_SIZE;
	if(block_num < 18)		//只使用一级指针
	{	if(node_buffer[iloc].i_block_pointer[block_num] < 0)	//该指针尚未分配块
		{
			new_cata_once(&node_buffer[iloc],block_num);
		}
		cata_db = node_buffer[iloc].i_block_pointer[block_num];		//最后一个目录块
		printf("use once pointer, cata_db is:%d\n",cata_db);
		disk_read(cata_db,cata_buffer);
		for(int j = 0; j < 128; j++)	//寻找父目录的第一个空闲cata
		{
			if(strlen(cata_buffer[j].name) == 0)	//找到空闲块,挂载
			{
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[j].name,myself,strlen(myself));
				// strcpy(cata_buffer[j].name,myself);
				printf("cata block is: %d, my name is: %s\n",j,cata_buffer[j].name);
				//cata_buffer[j].i_links_count += 1;
				cata_buffer[j].i_mode = DIRMODE;							
				cata_buffer[j].i_ino = start_i;
				enough_flag = 1;
				find_flag = 1;
				break;
			}
		}
		disk_write(cata_db,cata_buffer);
		if(!enough_flag)	//如果该块剩余空间不足
		{
			if(cata_db != 17)	//一级指针尚有空间
			{
				//为父目录分配一个新的cata块
				new_cata_once(&node_buffer[iloc],block_num + 1);
				// int num = node_buffer[iloc].i_blocks_count;
				cata_db = node_buffer[iloc].i_block_pointer[block_num + 1];
				printf("new once cata, cata_db is:%d\n",cata_db);
				disk_read(cata_db,cata_buffer);
				// 新块,直接写在第0个就可以了
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[0].name,myself,strlen(myself));
				// strcpy(cata_buffer[0].name,myself);
				printf("cata block is: %d, my name is: %s\n",0,cata_buffer[0].name);
				//cata_buffer[0].i_links_count += 1;
				cata_buffer[0].i_mode = DIRMODE;							
				cata_buffer[0].i_ino = start_i;
				disk_write(cata_db,cata_buffer);
				enough_flag = 1;
				find_flag = 1;
			}
			else	//分配二级指针块
			{
				new_cata_twice(&node_buffer[iloc]);
				int dir_db = node_buffer[iloc].i_double_block_pointer;
				int* int_buffer = (int*)malloc(BLOCK_SIZE);
				cata_db = int_buffer[0];
				printf("new twice cata, cata_db is:%d\n",cata_db);
				disk_read(cata_db,cata_buffer);
				// 新块,直接写在第0个就可以了
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[0].name,myself,strlen(myself));
				// strcpy(cata_buffer[0].name,myself);
				printf("cata block is: %d, my name is: %s\n",0,cata_buffer[0].name);
				//cata_buffer[0].i_links_count += 1;
				cata_buffer[0].i_mode = DIRMODE;							
				cata_buffer[0].i_ino = start_i;
				disk_write(cata_db,cata_buffer);
				enough_flag = 1;
				find_flag = 1;
				free(int_buffer);
			}
		}
	}
	else		//已经分配了二级指针
	{
		int * int_buffer = (int *)malloc(BLOCK_SIZE);
		disk_read(node_buffer[iloc].i_double_block_pointer, int_buffer);
		printf("have had twice pointer\n");
		for(int i = 0; i < 1024; i++)	//遍历指针块
		{
			if(find_flag)
				break;
			if(int_buffer[i] != -1)		//该目录块已被分配
			{
				disk_read(int_buffer[i], cata_buffer);
				printf("use twice pointer, cata_db is:%d\n",int_buffer[i]);
				for(int j = 0; j < 128; j++)
				{
					if(strlen(cata_buffer[j].name) == 0)	//找到空闲块,挂载
					{
						printf("strlen:%d\n",strlen(myself));
						memcpy(cata_buffer[j].name,myself,strlen(myself));
						// strcpy(cata_buffer[j].name,myself);
						printf("cata block is: %d, my name is: %s\n",j,cata_buffer[j].name);
						//cata_buffer[j].i_links_count += 1;
						cata_buffer[j].i_mode = DIRMODE;							
						cata_buffer[j].i_ino = start_i;
						enough_flag = 1;
						find_flag = 1;
						break;
					}
				}
				disk_write(int_buffer[i],cata_buffer);
			}
			else if(!find_flag && int_buffer[i] == -1)		//需要分配新的目录块
			{
				int dir_db = find_dmap();
				int_buffer[i] = dir_db;
				disk_read(dir_db, cata_buffer);
				printf("new twice cata, cata_db is:%d\n",dir_db);
				printf("strlen:%d\n",strlen(myself));
				memcpy(cata_buffer[0].name,myself,strlen(myself));
				// strcpy(cata_buffer[0].name,myself);
				printf("cata block is: %d, my name is: %s\n",0,cata_buffer[0].name);
				//cata_buffer[0].i_links_count += 1;
				cata_buffer[0].i_mode = DIRMODE;							
				cata_buffer[0].i_ino = start_i;
				disk_write(dir_db,cata_buffer);
				enough_flag = 1;
				find_flag = 1;
				// 更新父目录的inode
				node_buffer[iloc].i_blocks_count += 1;
				break;
			}
		}
		free(int_buffer);
	}
	if(!enough_flag)	//如果没有足够空间
	{
		return -ENOSPC;
	}
	node_buffer[iloc].i_size += sizeof(catalog);
	printf("mount dir is finished\n");
	// 修改父目录inode
	printf("%d %d %d\n", node_buffer[iloc].i_mode,  node_buffer[iloc].i_size, node_buffer[iloc].i_atime);
	node_buffer[iloc].i_links_count += 1;
	node_buffer[iloc].i_atime = time(NULL);
	node_buffer[iloc].i_mtime = time(NULL);		
	//将父目录inode写回磁盘中
	if(disk_write(blk, node_buffer))
		printf("fail to write parent inode\n");
	//将父目录db写回磁盘中
	// if(disk_write(cata_db,cata_buffer))
	// 	printf("fail to write parent datablock\n");
	// printf("write parent is finished\n");
	// printDirInode(parent_ino);	//检验是否挂载成功
	// free(Imap);
	// free(Dmap);
	free(Inode_buffer);
	free(node_buffer);
	free(cata_buffer);
	printf("Mkdir is finished:%s\n",path);
	return 0;
}
// 删除一个目录文件
int fs_rmdir (const char *path)
{
	printf("Rmdir is called:%s\n",path);
	//找到父目录,更新父目录的ctime与mtime,将该文件从父目录的db中删除,父目录的link数减一
	char myself[24];			//自己的文件名
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);			//4KB空间用于存放得到的inode
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);		//4KB空间用于存放得到的catalog

	int parent_ino = find_parent(path,myself);		//找到父目录inumber
	if(parent_ino < 0)
	{
		printf("(Rmdir) Cannot find parent path: %s\n", path);
        return -ECHILD;
	}

	char** temp;
	temp = getpath(path,temp);						//解析目录
	int file_ino = find_target(temp);				//找到自己的ino
	if(file_ino < 0)
	{
		printf("(Rmdir) Cannot find path: %s\n", path);
		return -ENOENT;
	}
	printf("(Rmdir) need to remove found (%s) inodeId %d\n", myself, file_ino);
    printf("(Rmdir) parent found inodeId %d\n", parent_ino);
	// 读取父目录的inode
	int blk = (parent_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	int iloc = ((parent_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	disk_read(blk, node_buffer);
	// 找到父目录的db
	int cata_db = node_buffer[iloc].i_block_pointer[0];
	printf("(Rmdir):cata_db is: %d\n",cata_db);
	// 访问父目录db
	disk_read(cata_db,cata_buffer);
	// 修改父目录ctime和mtime
	node_buffer[iloc].i_ctime = time(NULL);
	node_buffer[iloc].i_mtime = time(NULL);
	// 父目录link - 1
	node_buffer[iloc].i_size -= sizeof(catalog);
	node_buffer[iloc].i_links_count -= 1;
	// 目录从父目录的db中删除
	int j = 0;
	for(int i = 0; i < 128; i++)	//父目录中的该目录
	{
		if(!strcmp(cata_buffer[i].name,myself))		//找到该目录	
		{
			printf("block is: %d, my name is: %s\n",i,cata_buffer[i].name);
			file_ino = cata_buffer[i].i_ino;
			strcpy(cata_buffer[i].name,"");	
			//cata_buffer[i].i_links_count = 0;
			cata_buffer[i].i_ino = -5;
			break;
		}
	}	
	// 将父目录的Inode和db写回磁盘
	disk_write(blk, node_buffer);
	disk_write(cata_db, cata_buffer);
	// 访问本文件的Inode
	blk = (file_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	iloc = ((file_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	disk_read(blk, node_buffer);
	// 清除本文件的Inode信息
	node_buffer[iloc].i_size = 0;
	node_buffer[iloc].i_links_count = 0;
	node_buffer[iloc].i_blocks_count = 0;
	// 释放本文件占据的db(置为0)(此时清除对应的Dmap),之后清除Imap
	// 释放本文件的全部db(其实就是分配的目录db)
	cleardb(&node_buffer[iloc]);
	printf("finish clear db\n");
	disk_write(blk, node_buffer);
	// 修改Imap
	clearimap(file_ino);
	printf("finish clear imap\n");
	free(node_buffer);
	free(cata_buffer);
	return 0;
}

void FuncOutputBin(unsigned int value)	//打印二进制
{
	int binaryNum[32] = {0};
	int i = 0;
	while(value > 0)
	{
		binaryNum[i] = value % 2;
		value  = value / 2;
		i++;
	}
	for(int j = 31; j >= 0; j--)
		printf("%d",binaryNum[j]);
	printf("\n");
}

void cleardb(Inode current)	//给定inode,清除它的所有db,并且清除对应的inode指针
{
	printf("start cleardb\n");
	int file_db;
	int dir_db;
	int dmap_i, dmap_j;
	unsigned int mask_one = 1<<31;	//最高位为1的掩码,进行无符号位移
	FuncOutputBin(mask_one);
	int* Dmap = (int*)malloc(DMAP_SIZE);
	disk_read(2,Dmap);
	disk_read(3,Dmap + (DMAP_SIZE) / 2);
	char* buffer = (char*)malloc(BLOCK_SIZE);
	memset(buffer, 0, BLOCK_SIZE);
	int* dir_buffer = (int*)malloc(BLOCK_SIZE);
	for(int i = 0; i < current->i_blocks_count; i++)
	{
		if(i < 18)	//一级指针链接
		{
			file_db = current->i_block_pointer[i];
			disk_write(file_db,buffer);		//清空该块中的数据
			dmap_i = file_db/32;
			dmap_j = file_db%32;
			printf("file ino:%d   dmap_i: %d    dmap_j: %d\n",file_db,dmap_i,dmap_j);
			FuncOutputBin(Dmap[dmap_i]);
			mask_one = mask_one >> dmap_j;		//00001000
			FuncOutputBin(mask_one);
			mask_one = ~mask_one;			//11110111
			FuncOutputBin(mask_one);
			Dmap[dmap_i] = Dmap[dmap_i] & mask_one;		//将第i个数字的第j位置0
			FuncOutputBin(Dmap[dmap_i]);
			current->i_block_pointer[i] = -1;
		}
		else	//二级指针链接
		{
			dir_db = current->i_double_block_pointer;	//指针块,块中存放着指向数据块的指针
			// 读取指针块
			disk_read(dir_db,dir_buffer);
			// 释放db块
			file_db = dir_buffer[i-18];
			disk_write(file_db,buffer);
			dmap_i = file_db/32;
			dmap_j = file_db%32;
			mask_one = mask_one >> dmap_j;		//00001000
			mask_one = ~mask_one;			//11110111
			Dmap[dmap_i] = Dmap[dmap_i] & mask_one;		//将第i个数字的第j位置0
		}
	}
	if(current->i_blocks_count > 18)		//释放二级指针块
	{
		file_db = current->i_double_block_pointer;
		disk_write(file_db,buffer);
		dmap_i = file_db/32;
		dmap_j = file_db%32;
		mask_one = mask_one >> dmap_j;		//00001000
		mask_one = ~mask_one;			//11110111
		Dmap[dmap_i] = Dmap[dmap_i] & mask_one;		//将第i个数字的第j位置0
		current->i_double_block_pointer = -1;
	}
	current->i_blocks_count = 0;	//清空指针数量
	//将dmap写回磁盘中
	disk_write(2,Dmap);
	disk_write(3,Dmap + (DMAP_SIZE) / 2);
	free(Dmap);
	free(buffer);
	free(dir_buffer);
}

void clearimap(int file_ino)	//给定Inode的ino,清除它的imap标志
{
	printf("start clear imap\n");
	int imap_i,imap_j;
	unsigned int mask_one = 1<<31;
	FuncOutputBin(mask_one);
	int* Imap = (int*)malloc(IMAP_SIZE);
	disk_read(1,Imap);
	imap_i = file_ino/32;
	imap_j = file_ino%32;
	printf("imap_i:%d    imp_j:%d\n",imap_i,imap_j);
	FuncOutputBin(Imap[imap_i]);
	mask_one = mask_one >> imap_j;		//00001000
	FuncOutputBin(mask_one);
	mask_one = ~mask_one;			//11110111
	FuncOutputBin(mask_one);
	Imap[imap_i] = Imap[imap_i] & mask_one;		//将第i个数字的第j位置0 
	FuncOutputBin(Imap[imap_i]);
	disk_write(1,Imap);
	free(Imap);
}
// 删除一个常规文件
int fs_unlink (const char *path)
{
	printf("Unlink is callded:%s\n",path);
	char* myself = (char*)malloc(32*sizeof(char));			//自己的文件名
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);			//4KB空间用于存放得到的inode
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);		//4KB空间用于存放得到的catalog

	int parent_ino = find_parent(path,myself);		//找到父目录inumber
	if(parent_ino < 0)
	{
		printf("(Unlink) Cannot find parent path: %s\n", path);
        return -ECHILD;
	}

	char** temp;
	temp = getpath(path,temp);						//解析目录
	int file_ino = find_target(temp);				//找到自己的ino
	if(file_ino < 0)
	{
		printf("(Unlink) Cannot find path: %s\n", path);
		return -ENOENT;
	}
	printf("(Unlink) need to remove found (%s) inodeId %d\n", myself, file_ino);
    printf("(Unlink) parent found inodeId %d\n", parent_ino);
	// 读取父目录的inode
	int blk = (parent_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	int iloc = ((parent_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	if(disk_read(blk, node_buffer))
		printf("fail to read target inode\n");
	// 找到父目录的db
	int cata_db = node_buffer[iloc].i_block_pointer[0];
	printf("(Unlink):cata_db is: %d\n",cata_db);
	// 访问父目录db
	disk_read(cata_db,cata_buffer);
	// 修改父目录ctime和mtime
	node_buffer[iloc].i_ctime = time(NULL);
	node_buffer[iloc].i_mtime = time(NULL);
	// 父目录link - 1
	node_buffer[iloc].i_links_count -= 1;
	// 文件从父目录的db中删除
	for(int i = 0; i < 128; i++)	//父目录中的该文件
	{
		if(!strcmp(cata_buffer[i].name,myself))		//找到该文件	
		{
			printf("block is: %d, my name is: %s\n",i,cata_buffer[i].name);
			file_ino = cata_buffer[i].i_ino;	
			strcpy(cata_buffer[i].name,"");	
			//cata_buffer[i].i_links_count = 0;
			cata_buffer[i].i_ino = -5;
			break;
		}
	}	
	// 将父目录的Inode和db写回磁盘
	disk_write(blk, node_buffer);
	disk_write(cata_db, cata_buffer);
	// 访问本文件的Inode
	blk = (file_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	iloc = ((file_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	disk_read(blk, node_buffer);
	// 释放本文件占据的db(置为0)(此时清除对应的Dmap),之后清除Imap
	// 释放本文件的全部db
	cleardb(&node_buffer[iloc]);
	// 清除本文件的Inode信息
	node_buffer[iloc].i_size = 0;
	node_buffer[iloc].i_links_count = 0;
	node_buffer[iloc].i_blocks_count = 0;
	disk_write(blk,node_buffer);
	// 修改Imap
	clearimap(file_ino);
	return 0;
}
// 更改一个目录文件或常规文件的名称(及/或路径)
int fs_rename (const char *oldpath, const char *newpath)
{
	printf("Rename is called:%s\n",newpath);
	int oldparent, newparent;
	char* oldname = (char*)malloc(32 * sizeof(char));
	char* newname = (char*)malloc(32 * sizeof(char));
	oldparent = find_parent(oldpath,oldname);
	if(oldparent < 0)
	{
		printf("(Rename:)Cannot find old parent\n");
		return -ECHILD;
	}
	newparent = find_parent(newpath,newname);
	if(newparent < 0)
	{
		printf("(Rename:)Cannot find new parent\n");
		return -ECHILD;
	}
	printf("oldparent ino:%d      newparent ino:%d\n",oldparent,newparent);
	printf("oldname: %s     newname:%s\n",oldname,newname);
	int o_blk = ((oldparent * INODE_SIZE) / BLOCK_SIZE) + 4;
	int o_sec = ((oldparent * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE; 
	int n_blk = ((newparent * INODE_SIZE) / BLOCK_SIZE) + 4;
	int n_sec = ((newparent * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE; 
	int cata_db;
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);
	Inode old_buffer = (Inode)malloc(BLOCK_SIZE);
	Inode new_buffer = (Inode)malloc(BLOCK_SIZE);
	disk_read(o_blk,old_buffer);
	disk_read(n_blk,new_buffer);
	int flag = 0;
	if(oldparent == newparent)		//父路径不变,只修改名字
	{
		printf("just change name\n");
		for(int i = 0; i < old_buffer[o_sec].i_blocks_count; i++)
		{
			if(i < 18)
			{
				cata_db = old_buffer[o_sec].i_block_pointer[i];
				disk_read(cata_db,cata_buffer);
				for(int j = 0; j < 128; j++)
				{
					if(!strcmp(oldname,cata_buffer[j].name))	//find old name
					{
						strcpy(cata_buffer[j].name,newname);
						flag = 1;
						break;
					}
				}
				disk_write(cata_db,cata_buffer);
			}
			else
			{
				cata_db = old_buffer[o_sec].i_double_block_pointer;
				int * dir_buffer = (int *)malloc(BLOCK_SIZE);
				disk_read(cata_db, dir_buffer);
				disk_read(dir_buffer[i - 18 - 1], cata_buffer);
				for(int j = 0; j < 128; j++)
				{
					if(strcmp(cata_buffer[j].name, oldname) == 0)
					{
						strcpy(cata_buffer[j].name, newname);
						flag = 1;
						break;
					}
				}
				disk_write(dir_buffer[i - 18 - 1], cata_buffer);
				free(dir_buffer);
			}
			if(flag)
				break;
		}
		old_buffer[o_sec].i_ctime = time(NULL);
		old_buffer[o_sec].i_mtime = time(NULL);
		disk_write(o_blk,old_buffer);
	}
	else	//删除就路径,更改为新路径
	{
		printf("change path start\n");
		catalog target_node;
		// 遍历旧路径db寻找待改路径文件/目录
		for(int i = 0; i < old_buffer[o_sec].i_blocks_count; i++)
		{
			if(i < 18)
			{
				disk_read(old_buffer[o_sec].i_block_pointer[i], cata_buffer);
				for(int j = 0; j < 128; j++)
				{
					if(strcmp(cata_buffer[j].name, oldname) == 0){
						// 复制旧文件/目录的dir_node
						target_node.i_ino = cata_buffer[j].i_ino;
						target_node.i_mode = cata_buffer[j].i_mode;
						strcpy(target_node.name, newname);
						// 将旧文件/目录的dir_node从旧的路径中删除
						cata_buffer[j].i_ino = -5;
						cata_buffer[j].i_mode = 0;
						// 更新父目录db
						disk_write(old_buffer[o_sec].i_block_pointer[i], cata_buffer);
						flag = 1;
						break;
					}
				}
			}
			else
			{
				cata_db = old_buffer[o_sec].i_double_block_pointer;
				int * dir_buffer = (int *)malloc(BLOCK_SIZE);
				disk_read(cata_db, dir_buffer);
				disk_read(dir_buffer[i - 18 - 1], cata_buffer);
				for(int j = 0; j < 128; j++)
				{
					if(strcmp(cata_buffer[j].name, oldname) == 0)
					{
						// 复制旧文件/目录的dir_node
						target_node.i_ino = cata_buffer[j].i_ino;
						target_node.i_mode = cata_buffer[j].i_mode;
						strcpy(target_node.name, newname);
						// 将旧文件/目录的dir_node从旧的路径中删除
						cata_buffer[j].i_ino = -5;
						cata_buffer[j].i_mode = 0;
						// 更新父目录db
						disk_write(dir_buffer[i - 18 - 1], cata_buffer);
						flag = 1;
						break;
					}
				}
			}
			if(flag) break;
		}
		// 更新旧路径inode
		old_buffer[o_sec].i_links_count -= 1;
		old_buffer[o_sec].i_mtime = time(NULL);
		old_buffer[o_sec].i_ctime = time(NULL);
		disk_write(o_blk, old_buffer);
		// 将target node加入新路径
		// 遍历新路径db寻找是否有空位写入dir_node
		int flag = 0;
		for(int i = 0; i < new_buffer[n_sec].i_blocks_count; i++)
		{
			if(i < 18)
			{
				disk_read(new_buffer[n_sec].i_block_pointer[i], cata_buffer);
				for(int j = 0; j < 128; j++)
				{
					if(strlen(cata_buffer[j].name) == 0)
					{
						// 写入旧文件/目录的dir_node
						cata_buffer[j].i_ino = target_node.i_ino;
						cata_buffer[j].i_mode = target_node.i_mode;
						strcpy(cata_buffer[j].name, target_node.name);
						flag = 1;
						break;
					}
				}
				disk_write(new_buffer[n_sec].i_block_pointer[i], cata_buffer);
				if(flag) break;
			}
			else{
				cata_db = new_buffer[n_sec].i_double_block_pointer;
				int * int_buffer = (int *)malloc(sizeof(int) * 1024);
				disk_read(cata_db, int_buffer);
				disk_read(int_buffer[i - 18 - 1], cata_buffer);
				for(int j = 0; j < 128; j++)
				{
					if(strlen(cata_buffer[j].name) == 0)
					{
						// 写入旧文件/目录的dir_node
						cata_buffer[j].i_ino = target_node.i_ino;
						cata_buffer[j].i_mode = target_node.i_mode;
						strcpy(cata_buffer[j].name, target_node.name);
						flag = 1;
						break;
					}
				}
				// 更新新路径db
				disk_write(int_buffer[i - 18 - 1], cata_buffer);
			}
			if(flag) break;
		}
		if(!flag)
		{	// 需要开辟新的db
			if(new_buffer[n_sec].i_links_count < 18)
			{
				int new_db = find_dmap();
				printf("new db:%d\n",new_db);
				if(new_db > 0){
					new_buffer[n_sec].i_block_pointer[new_buffer[n_sec].i_links_count] = new_db;
					new_buffer[n_sec].i_blocks_count += 1;
					disk_read(new_db, cata_buffer);
					cata_buffer[0].i_ino = target_node.i_ino;
					cata_buffer[0].i_mode = target_node.i_mode;
					strcpy(cata_buffer[0].name, target_node.name);
					disk_write(new_db, cata_buffer);
				}
				else return -ENOSPC;
			}
			else if(new_buffer[n_sec].i_links_count == 18){
				int new_db = find_dmap();
				printf("new db:%d\n",new_db);
				if(new_db < 0) return -ENOSPC;
				new_buffer[n_sec].i_double_block_pointer = new_db;
				int * int_buffer = (int *)malloc(sizeof(int) * 1024);
				disk_read(new_db, int_buffer);
				new_db = find_dmap();
				if(new_db < 0) return -ENOSPC;
				int_buffer[0] = new_db;
				disk_read(int_buffer[0], cata_buffer);
				cata_buffer[0].i_ino = target_node.i_ino;
				cata_buffer[0].i_mode = target_node.i_mode;
				strcpy(cata_buffer[0].name, target_node.name);
				disk_write(int_buffer[0], cata_buffer);
				disk_write(new_buffer[n_sec].i_double_block_pointer, int_buffer);
				new_buffer[n_sec].i_blocks_count += 2;
				free(int_buffer);
			}
			else{
				int flag1 = 0;
				int * int_buffer = (int *)malloc(sizeof(int) * 1024);
				disk_read(new_buffer[n_sec].i_double_block_pointer, int_buffer);
				for(int k = 0; k < 1024; k++){
					if(k > 0 && int_buffer[k] <= 0 && int_buffer[k - 1] > 0){
						// 需要开辟新的db
						int new_db = find_dmap();
						printf("new db:%d\n",new_db);
						if(new_db < 0) return -ENOSPC;
						int_buffer[k] = new_db;
						new_buffer[n_sec].i_blocks_count += 1;
						disk_write(new_buffer[n_sec].i_double_block_pointer, int_buffer);
						disk_read(new_db, cata_buffer);
						cata_buffer[0].i_ino = target_node.i_ino;
						cata_buffer[0].i_mode = target_node.i_mode;
						strcpy(cata_buffer[0].name, target_node.name);
						disk_write(new_db, cata_buffer);
						break;
					}
				}
			}
		}
		// 更新新路径inode
		new_buffer[n_sec].i_links_count += 1;
		disk_write(n_blk, new_buffer);
		free(old_buffer);
		free(new_buffer);
		free(cata_buffer);
	}
	return 0;
}
// 分配Dmap,写入数据并写入磁盘
int writenewdb(char* buf)
{
	int start_d = find_dmap();	//寻找Dmap的空位并写Dmap
	int blk = start_d;	//db所在的block
	printf("write db blk:%d\n",blk);
	if(start_d < 0)
		exit(0);
	disk_write(blk,buf);	//将buffer写入disk
	printf("finish write new db\n");
	return blk;		//返回新分配的block id
}
void write_datablock(Inode inode, char* buf, int size)
{
	printf("start write_datablock\n");
	char* current = buf;
	int cur_blk;
	int* dir_db = (int*)malloc(BLOCK_SIZE);
	memset(dir_db, 0, BLOCK_SIZE);
	while(current - buf < size)	//循环写入新块
	{
		cur_blk = writenewdb(current);	//分配并写入新块
		current += BLOCK_SIZE;			//更新下次写的起始位置
		if(inode->i_blocks_count < 18)
		{
			inode->i_block_pointer[inode->i_blocks_count] = cur_blk;
			inode->i_blocks_count += 1;
		}
		else if(inode->i_blocks_count == 18)
		{
			// 分配一个二级指针块
			dir_db[inode->i_blocks_count - 18] = cur_blk;	//设置二级指针
			int dir_blk = writenewdb((char*)dir_db);	//写入二级指针
			inode->i_double_block_pointer = dir_blk;	//指向二级指针
			inode->i_blocks_count += 1;
		}
		else
		{
			int dir_blk = inode->i_double_block_pointer;	//找到二级指针
			disk_read(dir_blk, dir_db);					//读取二级指针
			dir_db[inode->i_blocks_count - 18] = cur_blk;	//设置二级指针
			disk_write(dir_blk, dir_db);				//写入二级指针
			inode->i_blocks_count += 1;
		}
	}
	free(dir_db);
}
int create_file(const char* path)
{
	printf("start create_file:%s\n",path);
	// 遍历查找Imap中第一个空位并写
	int start_i = find_imap();
	printf("find imap is finished,start_i is %d\n",start_i);
	if(start_i < 0)
		exit(0);
	//创建inode
	Inode Inode_buffer = (Inode)malloc(BLOCK_SIZE);
	int i_blk = ((start_i * INODE_SIZE) / BLOCK_SIZE) + 4;
	int i_sec = ((start_i * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("i_blk: %d    i_sec: %d\n",i_blk,i_sec);
	disk_read(i_blk,Inode_buffer);
	Inode_buffer[i_sec].i_mode = REGMODE;
	Inode_buffer[i_sec].i_links_count = 0;
	Inode_buffer[i_sec].i_size = 0;
	Inode_buffer[i_sec].i_atime = time(NULL);
	Inode_buffer[i_sec].i_mtime = time(NULL);
	Inode_buffer[i_sec].i_ctime = time(NULL);
	Inode_buffer[i_sec].i_blocks_count = 0;
	for(int i = 0; i < 18; i++)
		Inode_buffer[i_sec].i_block_pointer[i] = -1;
	Inode_buffer[i_sec].i_double_block_pointer = -1;
	// Inode_buffer[i_sec].i_block_pointer[0] = start_d;
	//将Inode写回磁盘中	
	disk_write(i_blk,Inode_buffer);
	printf("write inode is finished\n");
	//super_block更新
	super_block->file_count += 1;
	printf("create inode is finished\n");
	//将该目录挂载在父目录下
	char* myself = (char*)malloc(32*sizeof(char));	//自己的文件名
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);			//4KB空间用于存放得到的inode
	Catalog cata_buffer = (Catalog)malloc(BLOCK_SIZE);		//4KB空间用于存放得到的catalog

	// 分离父目录与子目录名, 并调用getattr()获取新创建目录的上一级目录信息
    char temp[2560];
    strcpy(temp, path);
	// 提取新目录名, 分离父目录
    for(int i = strlen(temp) - 2; i >= 0; i--){
        if(temp[i] == '/'){
            temp[i] = '\0';
            strcpy(myself, temp + i + 1);
            break;
        }
    }
	// 若path只有新目录名无父目录, 则父目录为根目录root
    if(strlen(temp) == 0){
        temp[0] = '/';
        temp[1] = '\0';
    }
	printf("parent path:%s\n",temp);
	// 查询父目录信息
	int parent_ino = cur_find(temp);
	if(parent_ino < 0)
	{
		printf("(Create file): Cannot find path: %s\n", path);
        return -ECHILD;
	}
	printf("find parent is finished\n");
	// 读取父目录的inode
	int blk = (parent_ino * INODE_SIZE) / BLOCK_SIZE + 4;
	int iloc = ((parent_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	printf("parent blk:%d   parent iloc:%d\n",blk,iloc);
	disk_read(blk, node_buffer);
	// 找到父目录的db
	int cata_db = node_buffer[iloc].i_block_pointer[0];
	printf("(Create file):cata_db is: %d\n",cata_db);
	// 访问父目录db
	disk_read(cata_db,cata_buffer);
	// 挂载文件
	int enough_flag = 0;
	for(int i = 0; i < 128; i++)	//寻找父目录的第一个空闲cata
	{
		if(strlen(cata_buffer[i].name) == 0)
		{
			strcpy(cata_buffer[i].name,myself);
			printf("block is: %d, my name is: %s\n",i,cata_buffer[i].name);
			//cata_buffer[i].i_links_count += 1;
			cata_buffer[i].i_mode = REGMODE;							
			cata_buffer[i].i_ino = start_i;
			enough_flag = 1;
			break;
		}
	}		
	if(!enough_flag)	//如果没有足够空间
	{
		return -ENOSPC;
	}
	printf("mount dir is finished\n");
	// 修改父目录inode
	printf("%d %d %d\n", node_buffer[iloc].i_mode, node_buffer[iloc].i_size, node_buffer[iloc].i_atime);
	node_buffer[iloc].i_links_count += 1;
	node_buffer[iloc].i_atime = time(NULL);
	node_buffer[iloc].i_mtime = time(NULL);		
	//将父目录inode写回磁盘中
	if(disk_write(blk, node_buffer))
		printf("fail to write parent inode\n");
	//将父目录db写回磁盘中
	if(disk_write(cata_db,cata_buffer))
		printf("fail to write parent datablock\n");
	printf("write parent is finished\n");
	printDirInode(parent_ino);	//检验是否挂载成功
	free(Inode_buffer);
	free(node_buffer);
	free(cata_buffer);
	printf("Create file is finished:%s\n",path);
	return start_i;
}
int fs_write (const char *path, const char *buffer, size_t size, off_t offset, struct fuse_file_info *fi)
{
	printf("Write is called:%s\n",path);
	int wmode = fi->flags;
	// 若是只读模式则退出
	if(wmode & O_RDONLY)
        return -EACCES;
    // 若要写的字节数超过文件最大容量则退出
    if(size > MAX_SIZE)
        return -EACCES;
	// char* file = (char*)malloc(MAX_SIZE);	//用来存放buf的空间
	Inode node_buffer = (Inode)malloc(BLOCK_SIZE);
	int i_blk,sec,file_size;
	char** temp;
	temp = getpath(path,temp);	//解析目录
	int file_ino = find_target(temp);	//获得要写的文件的inumber
	if(file_ino < 0)	//该文件还未被创建
	{
		printf("file hasn't been created\n");
		file_ino = create_file(path);	//创建新文件
		i_blk = ((file_ino * INODE_SIZE) / BLOCK_SIZE) + 4;
		sec = ((file_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
		disk_read(i_blk,node_buffer);
		file_size = size;
		write_datablock(&node_buffer[sec],buffer,size);	// 将文件写入db
	}
	else
	{
		printf("file is exist\n");
		if(wmode & O_EXCL)
		{
			if(wmode & O_CREAT)
				return -EEXIST;
		}
		i_blk = ((file_ino * INODE_SIZE) / BLOCK_SIZE) + 4;
		sec = ((file_ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
		disk_read(i_blk,node_buffer);

		file_size = node_buffer[sec].i_size;
		if(wmode & O_APPEND)	//若追加写
		{
			if(wmode & O_TRUNC)	//覆盖写
			{
				file_size = size;	//修改文件大小
				cleardb(&node_buffer[sec]);	//清空该文件的db
				write_datablock(&node_buffer[sec],buffer,size);	// 将文件写入db
			}
			else
			{
				char* tempBlock = (char*)malloc(BLOCK_SIZE);
				int aline = file_size % BLOCK_SIZE;
				file_size += size;	//修改文件大小
				int remain_size = size;	//剩余要写入的文件大小
				if(aline != 0)
				{
					if(node_buffer[sec].i_blocks_count <= 18)
					{
						int blk = node_buffer[sec].i_block_pointer[node_buffer[sec].i_blocks_count - 1];
						disk_read(blk, tempBlock);
                        memcpy(tempBlock + aline, buffer, BLOCK_SIZE - aline);
						disk_write(blk, tempBlock);
                        buffer += BLOCK_SIZE - aline;
                        remain_size -= BLOCK_SIZE - aline;
					}
					else
					{
						int dir_blk = node_buffer[sec].i_double_block_pointer;
						disk_read(dir_blk, tempBlock);
                        int dir_num = ((int *)tempBlock)[node_buffer[sec].i_blocks_count - 14 - 1];
                        disk_read(dir_num, tempBlock);
                        memcpy(tempBlock + aline, buffer, BLOCK_SIZE - aline);
                        disk_write(dir_num, tempBlock);
                        buffer += BLOCK_SIZE - aline;
                        remain_size -= BLOCK_SIZE - aline;
					}
				}
				if(remain_size > 0)		//写入剩余的整齐数据
				{
					write_datablock(&node_buffer[sec],buffer,remain_size);	// 将文件写入db
				}
				free(tempBlock);
			}
		}
		else
        {
            file_size = offset + size;
            if(size > 0)
                write_datablock(&node_buffer[sec],buffer,size);
        }
	}
	node_buffer[sec].i_size = file_size;	
	node_buffer[sec].i_ctime = time(NULL);
	node_buffer[sec].i_mtime = time(NULL);
	disk_write(i_blk,node_buffer);
	// free(file);
	free(node_buffer);
	return size;
}

int fs_truncate (const char *path, off_t size)
{
	// 根据path找到attr
	// 根据inumber找到inode
	// 读取inode
	// 修改size、ctime
	// 在修改size的时候判断剩余空间
	// 写回inode
	printf("Truncate is called:%s\n",path);
	struct stat attr;
	fs_getattr(path, &attr);
	if(attr.st_mode == DIRMODE){
		printf("this is not a file!\n");
		return -EISDIR;
	}
	int ino = attr.st_ino;
	int blk = ((ino * INODE_SIZE) / BLOCK_SIZE) + 4;
	int sec = ((ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	Inode inode_buffer = (Inode)malloc(BLOCK_SIZE);
	disk_read(blk, inode_buffer);
	inode_buffer[sec].i_ctime = time(NULL);
	if(size > MAX_SIZE)
		return -ENOSPC;
	inode_buffer[sec].i_size = size;
	if(size == 0)
		cleardb(&inode_buffer[sec]);
	disk_write(blk, inode_buffer);
	free(inode_buffer);
	return 0;
}

int fs_utime (const char *path, struct utimbuf *buffer)
{
	printf("Utime is called:%s\n",path);
	struct stat attr;
	fs_getattr(path, &attr);
	if(attr.st_mode == DIRMODE){
		printf("this is not a file!\n");
		return -EISDIR;
	}
	int ino = attr.st_ino;
	int blk = ((ino * INODE_SIZE) / BLOCK_SIZE) + 4;
	int sec = ((ino * INODE_SIZE) % BLOCK_SIZE) / INODE_SIZE;
	Inode inode_buffer = (Inode)malloc(sizeof(inode) * 32);
	disk_read(blk, inode_buffer);
	inode_buffer[sec].i_ctime = time(NULL);
	inode_buffer[sec].i_atime = buffer->actime;
	inode_buffer[sec].i_mtime = buffer->modtime;
	disk_write(blk, inode_buffer);
	free(inode_buffer);
	// free(attr);
	return 0;
}

int fs_statfs (const char *path, struct statvfs *stat)
{
	printf("Statfs is called:%s\n",path);
	/*
	unsigned long  f_bsize; 	//块大小
    fsblkcnt_t     f_blocks;	//块数量
    fsblkcnt_t     f_bfree; 	//空闲块数量
    fsblkcnt_t     f_bavail;	//可用块数量
    fsfilcnt_t     f_files; 	//文件节点数
    fsfilcnt_t     f_ffree; 	//空闲节点数
    fsfilcnt_t     f_favail;	//可用节点数
    unsigned long  f_namemax;	//文件名长度上限
	*/
	stat->f_bsize = BLOCK_SIZE;
	stat->f_blocks = BLOCK_NUM;
	stat->f_namemax = 24;
	int freeblock;
	//读取imap与dmap
	int* Imap = (int*)malloc(IMAP_SIZE);
	int* Dmap = (int*)malloc(DMAP_SIZE);		// 8KB
	if(disk_read(1,Imap))
		printf("fail to read Imap\n");
	if(disk_read(2,Dmap))
		printf("fail to read Dmap1\n");
	if(disk_read(3,Dmap + (DMAP_SIZE) / 2))
		printf("fail to read Dmap2\n");
	//遍历imap和dmap得到freeblock
	int mask_all = ~1 + 1;	//全1掩码
	int mask_one = 1<<31;	//最高位为1的掩码
	for(int i = 0; i < 1024; i++)
	{
		if(Imap[i]^mask_all)		//如果Imap[i]没满
		{
			for(int j = 0; j < 32; j++)
			{
				if(Imap[i]^(mask_one>>j))	//该位为非空闲位
					continue;
				else
				{
					freeblock++;	//空闲位数量+1
				}
			}
		}
		else
			continue;
	}
	for(int i = 0; i < 2048; i++)
	{
		if(Dmap[i]^mask_all)		//如果Dmap[i]没满
		{
			for(int j = 0; j < 32; j++)
			{
				if(Dmap[i]^(mask_one>>j))	
					continue;
				else
				{
					freeblock++;
				}
			}
		}
		else
			continue;
	}
	stat->f_bavail = freeblock;
	stat->f_bfree = freeblock;
	stat->f_files = super_block->file_count;
	stat->f_ffree = FILE_NUM - stat->f_files;
	stat->f_favail = FILE_NUM - stat->f_files;
	free(Imap);
	free(Dmap);
	return 0;
}

int fs_open (const char *path, struct fuse_file_info *fi)
{
	/*
	当你需要访问或修改一个文件或目录时会进行调用。
	主要判断当前用户是否有权限读/写这个文件/目录。
	本次实验除fs_open外不需要修改。
	*/
	printf("Open is called:%s\n",path);
	// 查询该文件信息
	struct stat attr;
	fs_getattr(path, &attr);
	if(attr.st_mode == DIRMODE)		//如果不是文件,则不能打开
        return -EISDIR;
	// 告知fi inumber
	int ino = attr.st_ino;
	fi->fh = ino;
	int offset = 2;
    if(getuid() != attr.st_uid)
    {
        offset = 1;
        if(getgid() != attr.st_gid)
        {
            offset = 0;
        }
    }
    offset *= 3;
    int mask = 0x7;
    int perm = (attr.st_mode >> offset) & mask;

    int readOK = (perm >> 2) & 1;
    int writeOK = (perm >> 1) & 1;
    int execOK = perm & 1;

    if(!readOK)
    {
        return -EACCES;
    }
    if(!writeOK)
    {
        if(fi->flags & O_WRONLY)
            return -EACCES;
        if(fi->flags & O_RDWR)
            return -EACCES;
        if(fi->flags & O_APPEND)
            return -EACCES;
    }
	return 0;
}

//Functions you don't actually need to modify
int fs_release (const char *path, struct fuse_file_info *fi)
{
	printf("Release is called:%s\n",path);
	return 0;
}

int fs_opendir (const char *path, struct fuse_file_info *fi)
{
	printf("Opendir is called:%s\n",path);
	return 0;
}

int fs_releasedir (const char * path, struct fuse_file_info *fi)
{
	printf("Releasedir is called:%s\n",path);
	return 0;
}

static struct fuse_operations fs_operations = {
	.getattr    = fs_getattr,
	.readdir    = fs_readdir,
	.read       = fs_read,
	.mkdir      = fs_mkdir,
	.rmdir      = fs_rmdir,
	.unlink     = fs_unlink,
	.rename     = fs_rename,
	.truncate   = fs_truncate,
	.utime      = fs_utime,
	.mknod      = fs_mknod,
	.write      = fs_write,
	.statfs     = fs_statfs,
	.open       = fs_open,
	.release    = fs_release,
	.opendir    = fs_opendir,
	.releasedir = fs_releasedir
};

int main(int argc, char *argv[])
{
	if(disk_init())
	{
		printf("Can't open virtual disk!\n");
		return -1;
	}
	if(mkfs())
	{
		printf("Mkfs failed!\n");
		return -2;
	}
	if(!mkfs())
	{
		// char* path = "/dir1";
		// mode_t mode = DIRMODE;
		// fs_mkdir(path,mode);
	}
    return fuse_main(argc, argv, &fs_operations, NULL);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值