/// <summary> /// 获取空闲块 /// </summary> /// <returns></returns> public int GetFreeBlock() { int reValue; byte[] readIn = new byte[4]; reValue = _initSuper._s_free[--_initSuper._s_nfree]; //出错处理,已经分配完空闲盘块 if (_initSuper._s_nfree <= 0 && reValue == 0) { throw (new Exception("空闲数据块已分配完")); } //如果本批次直接管理的空闲块用完,则导入下一组 if (_initSuper._s_nfree <= 0) { _diskFile.OpenFile(); _diskFile.SeekFilePosition(512 * reValue, System.IO.SeekOrigin.Begin); _diskFile.ReadFile(ref readIn, 0, 4); _initSuper._s_nfree = (int)Helper.Bytes2Struct(readIn, typeof(int)); for (int i = 0; i < 100; ++i) { _diskFile.ReadFile(ref readIn, 0, 4); _initSuper._s_free[i] = (int)Helper.Bytes2Struct(readIn, typeof(int)); } _diskFile.CloseFile(); } //最好在这里将新申请到的块全部清零 CleanBlock(reValue); _initSuper.UpdateSuperBlockToDisk(); return(reValue); }
/// <summary> /// 创建文件时的目录搜索 /// 本函数共4个出口 /// 出口1:目录搜索完毕,且满足三个条件:1.之前各级目录名都能找到,2.但没有符合的最后一级文件,3.且传入的flag为CREATFILE /// 出口2:目录搜索完毕,但不完全满足上述三个条件 /// 出口3:文件(或目录)在系统中已存在,且传入flag为DELETEFILE /// 出口4:文件(或目录)在系统中已存在,但传入flag不为DELETEFILE /// </summary> /// <param name="path">创建文件的目录</param> /// <param name="DirInodeNo">父目录的inode号</param> /// <returns>目录项的位置</returns> public int NameI(string path, ref int dirInodeNo, ref InodeStr dirInode, ref int fileInodeNo, ref InodeStr fileInode, ref char[] fileName, int flag) { //用于记录在路径字符串中扫描到了哪里 int curPos = 0; //用于记录inode号 dirInodeNo = 0; //首先读入根目录inode _inode.GetInodeFromDisk(dirInode, dirInodeNo); //跳过开始的一个(或者多个)'/'字符 for (; curPos < path.Length; ++curPos) { if (path[curPos] != '/') { break; } } //主循环 while (true) { //获取两个'/'当中的内容,存入dirPath中 char[] tmp = new char[28]; for (int i = 0; curPos < path.Length; ++curPos, ++i) { if (path[curPos] == '/') { break; } tmp[i] = path[curPos]; } tmp.CopyTo(fileName, 0); //跳过下一个(或者多个)'/'字符,为下一次循环(下一级目录,如果有的话)做准备 for (; curPos < path.Length; ++curPos) { if (path[curPos] != '/') { break; } } //用于存储扫描当前目录文件的偏移量 int offset = 0; //用于记录第一个空闲目录项的偏移量 int firstFreeOffset = 0; //记录是否又空闲目录项 int freeFlag = 0; //目录项项数 int dirSize = dirInode._i_size / 32; //用于读取一个磁盘块 byte[] buffer = new byte[512]; //(次循环)在当前目录文件中搜索 while (true) { //出口1:对当前目录搜索完毕(用于查找是否有同名文件存在) if (dirSize == 0) { //若当前目录索搜索完毕(没有找到相应项),且只是路径名的最后一段没有找到(要创建的文件名),则创建文件 if (flag == File.CREATFILE && curPos == path.Length) { //新分配一个inode控制块,返回该inode号 try { fileInodeNo = _inode.FetchFreeInode(); } catch (Exception ex) { Console.WriteLine(ex.Message); } //根据inode号获取对应的inode(搜索到了哪一层就获取哪一层目录的inode) _inode.GetInodeFromDisk(fileInode, fileInodeNo); //若之前扫描途中有空闲项,则返回其偏移,否则就返回当前inode的大小(即要对当前inode进行扩充) if (freeFlag == 0) { return(dirInode._i_size); } else { return(firstFreeOffset); } } //出口2:若当前目录搜索完毕(没有找到相应项),且中间路径没有找到,则出错 else { Error.ErrorType = Error.SEARCHDIR; return(-1); } } //搜索完一块,需要读入新块 if (offset % 512 == 0) { _diskFile.OpenFile(); _diskFile.SeekFilePosition(this.BMap(dirInode, offset / 512) * 512, System.IO.SeekOrigin.Begin); _diskFile.ReadFile(ref buffer, 0, 512); _diskFile.CloseFile(); } bool match = true; for (int j = 0; j < 28; ++j) { if (Convert.ToByte(fileName[j]) != buffer[offset % 512 + j + 4]) { match = false; break; } } //表示不匹配 if (!match) { dirSize--; //如果之前的目录项为空,则将其用first_free_offset标记 //+4是因为每个目录项的前四个字节是inode号 if (buffer[offset % 512 + 4] == '\0' && firstFreeOffset == 0) { firstFreeOffset = offset; freeFlag = 1; } offset += 32; continue; } //在当前目录中找到了和dirPath匹配的目录项 else { break; } } byte[] ino = new byte[4]; for (int k = 0; k < 4; ++k) { ino[k] = buffer[offset % 512 + k]; } /* 出口3: * 删除操作 * pathPoint == path.Length表示:目录项已经搜索完毕*/ if (flag == File.DELETEFILE && curPos == path.Length) { //需删除文件的inode号 fileInodeNo = (int)Helper.Bytes2Struct(ino, typeof(int)); return(offset); } /* 出口4: * 同一目录下的文件名相同,且不是要做删除操作,则出错 * pathPoint == path.Length表示:目录项已经搜索完毕*/ if (flag != File.DELETEFILE && curPos == path.Length) { Error.ErrorType = Error.SAMEFILENAME; return(-1); } //如果还有下级目录,则更新dirInodeNo与dirInode,为当前目录 dirInodeNo = (int)Helper.Bytes2Struct(ino, typeof(int)); _inode.GetInodeFromDisk(dirInode, dirInodeNo); } }
/// <summary> /// 从磁盘读出当前超级块的内容(暂无引用) /// </summary> public void ReadSuperBlock() { byte[] read; //定位到超级块起始位置 _diskFile.OpenFile(); _diskFile.SeekFilePosition(MachinePara.BootAndKernelSize * 512, System.IO.SeekOrigin.Begin); //inode区占据的磁盘块数 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_isize = (int)Helper.Bytes2Struct(read, typeof(int)); //总的磁盘块数,为扇区数的一半 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_fsize = (int)Helper.Bytes2Struct(read, typeof(int)); //得到直接管理块数 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_nfree = (int)Helper.Bytes2Struct(read, typeof(int)); //得到空闲列表 for (int i = 0; i < 100; ++i) { read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_free[i] = (int)Helper.Bytes2Struct(read, typeof(int)); } //得到直接管理的inode数量 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_ninode = (int)Helper.Bytes2Struct(read, typeof(int)); //得到空闲inode列表 for (int i = 0; i < 100; ++i) { read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_inode[i] = (int)Helper.Bytes2Struct(read, typeof(int)); } //封锁标志 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_flock = (int)Helper.Bytes2Struct(read, typeof(int)); //inode封锁标志 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_ilock = (int)Helper.Bytes2Struct(read, typeof(int)); //已修改标志 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_fmod = (int)Helper.Bytes2Struct(read, typeof(int)); //只读标志 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_ronly = (int)Helper.Bytes2Struct(read, typeof(int)); //最后修改时间 read = new byte[4]; _diskFile.ReadFile(ref read, 0, 4); _s_time = (int)Helper.Bytes2Struct(read, typeof(int)); _diskFile.CloseFile(); }