// 进入下级目录 private void buttonForward_Click(object sender, EventArgs e) { if (blockGroup == null) { MessageBox.Show("请先格式化!", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var selectedItem = listBoxFile.SelectedItem; if (selectedItem == null) { return; } String selectedName = selectedItem.ToString().Split(new char[] { ' ' })[0]; int indexOfSelectedInode = blockGroup.getIndexFromeName(selectedName, blockGroup.currentInodeIndex); if (indexOfSelectedInode == -1 || blockGroup.inodeList[indexOfSelectedInode].fileMode != FileMode.directory) { return; } //blockGroup.inodeList[blockGroup.currentInodeIndex].childInodeIndex.Clear(); // 清除 blockGroup.currentInodeIndex = indexOfSelectedInode; if (blockGroup.inodeList[blockGroup.currentInodeIndex].childInodeIndex.Count == 0) { Inode dirInode = blockGroup.inodeList[blockGroup.currentInodeIndex]; blockGroup.readDirectoryFileFromDisk(ref dirInode); blockGroup.inodeList[blockGroup.currentInodeIndex] = dirInode; } blockGroup.showFile(ref listBoxFile); directorySet(); }
public static bool walkChild(Inode cur, string name, out Inode child) { //Console.WriteLine ("cur={0}, name={1}", cur.dir.name, name); if (name.Equals("..")) { if (cur.dir.name.Equals("/")) { child = cur; } else { child = cur.parent; } return(true); } if (name.Equals(".")) { child = cur; return(true); } foreach (Inode i in cur.children) { if (i.dir.name.Equals(name)) { child = i; return(true); } } child = cur; return(false); }
public void CanReadSymlink() { var context = new Context { SuperBlock = new SuperBlock(), Options = new XfsFileSystemOptions { FileNameEncoding = Encoding.UTF8 } }; var inode = new Inode(1, context); inode.ReadFrom(GetInodeBuffer(), 0); var symlink = new Symlink(context, inode); Assert.Equal("init.d", symlink.TargetPath); inode = new Inode(1, context); var inodeBuffer = GetInodeBuffer(); inodeBuffer[0x6C] = 60; //garbage after first null byte inode.ReadFrom(inodeBuffer, 0); symlink = new Symlink(context, inode); Assert.Equal("init.d", symlink.TargetPath); }
// 删除选中的文件 public void deleteFile(String fileName) { int deleteFileIndex = getIndexFromeName(fileName, currentInodeIndex); if (deleteFileIndex == -1) { return; } int tempCurrentInodeIndex = currentInodeIndex; Inode deleteInode = inodeList[deleteFileIndex]; if (inodeList[deleteFileIndex].childrenNum == 0) // 普通文件和空目录直接删除 { foreach (var index in deleteInode.dataBlockList) { groupDescriptorList[0].blockBitmap[index] = true; // 释放占用的数据块 } groupDescriptorList[0].inodeBitmap[deleteFileIndex] = true; // 释放占用的inode块 //MessageBox.Show(inodeList[deleteFileIndex].fileName, "", MessageBoxButtons.OK, MessageBoxIcon.Error); // 检查删除顺序 inodeList[currentInodeIndex].childInodeIndex.Remove(deleteFileIndex); // 抹去inode信息和数据块内容 deleteInode.blockSize = 0; foreach (var index in deleteInode.dataBlockList) { DataBlock dataBlock = dataBlockList[index]; for (int i = 0; i < BLOCKSIZE / 2; i++) { dataBlock.data[i] = '\0'; } dataBlockList[index] = dataBlock; } deleteInode.dataBlockList.Clear(); deleteInode.fatherIndex = -1; deleteInode.fileSize = 0; superBlock.freeInodeNum++; inodeList[deleteFileIndex] = deleteInode; // 写回 Inode fatherInode = inodeList[tempCurrentInodeIndex]; fatherInode.childrenNum--; inodeList[tempCurrentInodeIndex] = fatherInode; // 写回 writeDirectoryFileToDisk(tempCurrentInodeIndex); } else // 有子文件的目录文件递归删除 { int childrenNum = deleteInode.childrenNum; for (int i = 0; i < childrenNum; i++) // 遍历目录文件的子文件索引 { currentInodeIndex = deleteFileIndex; // 将当前目录切换到要删除的目录下 int childIndex = deleteInode.childInodeIndex[0]; String childName = inodeList[childIndex].fileName; deleteFile(childName); } currentInodeIndex = tempCurrentInodeIndex; deleteFile(fileName); } }
internal BobFsNode(BobFs bobFs, uint inum) { _bobFs = bobFs; Inum = inum; _tmpBuffer = new byte[BobFs.BlockSize]; _node = new Inode(); _indirect = new Indirects(); _nodeValid = _indirectValid = false; }
private void _read() { _magic = m_io.EnsureFixedContents(new byte[] { 69, 61, 205, 40 }); _size = m_io.ReadU4le(); _flags = m_io.ReadU4le(); _future = m_io.ReadU4le(); _signature = m_io.EnsureFixedContents(new byte[] { 67, 111, 109, 112, 114, 101, 115, 115, 101, 100, 32, 82, 79, 77, 70, 83 }); _fsid = new Info(m_io, this, m_root); _name = System.Text.Encoding.GetEncoding("ASCII").GetString(m_io.ReadBytes(16)); _root = new Inode(m_io, this, m_root); }
public Inodes(int numInodes) { _inodes = new Inode[numInodes]; Inode inode = new Inode(); for (int i = 0; i < _inodes.Length; i++) { inode.inodeId = i + 1; _inodes[i] = inode; } }
// 普通文件从磁盘读取数据 public String readCommonFileFromDisk(int commonIndex) { Inode inode = inodeList[commonIndex]; String content = ""; foreach (int index in inode.dataBlockList) { DataBlock dataBlock = dataBlockList[index]; // 一个数据块 String data = new string(dataBlock.data); content += data; } return(content); }
public Inode ExistsInode(string filename) { Inode i = ExistsFile(filename); if (i != null) { return(i); } else { return(ExistsFolder(filename)); } }
public static bool delnode(Inode parent, string name) { if (parent != null) { foreach (Inode c in parent.children) { if (c.dir.name.Equals(name)) { parent.children.Remove(c); return(true); } } } return(false); }
// 在当前目录下创建文件 public bool createFile(FileMode fileMode, String fileName) { // 获取inode if (superBlock.freeInodeNum == 0) { return(false); } superBlock.freeInodeNum--; int indexOfInode = -1; foreach (KeyValuePair <int, bool> kvp in groupDescriptorList[0].inodeBitmap) { if (kvp.Value == true) { indexOfInode = kvp.Key; break; } } if (indexOfInode == -1) { return(false); } groupDescriptorList[0].inodeBitmap[indexOfInode] = false; Inode inode = inodeList[indexOfInode]; // 创建文件,改写inode inode.fileMode = fileMode; inode.fileName = fileName; inode.fatherIndex = currentInodeIndex; inode.createdTime = DateTime.Now; inode.updatedTime = inode.createdTime; inodeList[indexOfInode] = inode; // 为父目录添加记录 if (currentInodeIndex == -1) // 无父目录 { return(true); } inodeList[currentInodeIndex].childInodeIndex.Add(indexOfInode); Inode dirInode = inodeList[currentInodeIndex]; dirInode.childrenNum++; inodeList[currentInodeIndex] = dirInode; if (!writeDirectoryFileToDisk(currentInodeIndex)) { return(false); } return(true); }
// 目录文件从磁盘数据块读取数据 public void readDirectoryFileFromDisk(ref Inode inode) { foreach (var i in inode.dataBlockList) // 逐个读取数据块 { DataBlock dataBlock = dataBlockList[i]; // 一个数据块 String data = new string(dataBlock.data); var indexGroup = data.Split(new char[] { '\0' }).Take(inode.childrenNum); foreach (var indexStr in indexGroup) { int index; bool result = int.TryParse(indexStr, out index); if (result == true) // 转换成功 { inode.childInodeIndex.Add(index); } } } }
public static void ListInode(bool details, bool color, CommandStructure value, Inode inode, bool folder) { //folder or file if (details) { value.value += folder ? "d" : "-"; //permissions rwx for (int i = 0; i < 9; ++i) { if (inode.permissions [i]) { if (i % 3 == 0) { value.value += "r"; } else if (i % 3 == 1) { value.value += "w"; } else { value.value += "x"; } } else { value.value += "-"; } } value.value += " " + inode.owner; value.value += " " + inode.creator; value.value += " " + inode.date; value.value += " "; } value.value += inode.name + " "; if (details) { value.value += Console.jump; } }
public static void Main(string[] args) { //Inode i = new Inode(); Inode f = new Inode(1); //f.SetArrayBlock(0, 3); int i = f.GetArrayBlock(0); byte[] b = new byte ["fooooooo".Length]; HDD.Read(ref b, SuperBlock.BlockSize * i + SuperBlock.BlockStart); while (!HDD.isNullReadHandler()) { ; } string s = System.Text.Encoding.ASCII.GetString(b); Console.WriteLine(s); // HDD.Write(b, SuperBlock.BlockSize * 3 + SuperBlock.BlockStart); }
private void _read() { _magic = m_io.ReadBytes(4); if (!((KaitaiStream.ByteArrayCompare(Magic, new byte[] { 69, 61, 205, 40 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 69, 61, 205, 40 }, Magic, M_Io, "/types/super_block_struct/seq/0"); } _size = m_io.ReadU4le(); _flags = m_io.ReadU4le(); _future = m_io.ReadU4le(); _signature = m_io.ReadBytes(16); if (!((KaitaiStream.ByteArrayCompare(Signature, new byte[] { 67, 111, 109, 112, 114, 101, 115, 115, 101, 100, 32, 82, 79, 77, 70, 83 }) == 0))) { throw new ValidationNotEqualError(new byte[] { 67, 111, 109, 112, 114, 101, 115, 115, 101, 100, 32, 82, 79, 77, 70, 83 }, Signature, M_Io, "/types/super_block_struct/seq/4"); } _fsid = new Info(m_io, this, m_root); _name = System.Text.Encoding.GetEncoding("ASCII").GetString(m_io.ReadBytes(16)); _root = new Inode(m_io, this, m_root); }
public bool setNeigbor(int nodeId, int neighborNodeId) { //check if nodeId Exist foreach (var node in nodes) { if (node.getNodeId() == nodeId) { foreach (var Inode in nodes) { if (Inode.getNodeId() == neighborNodeId) { node.setNeighbors(Inode); Inode.setNeighbors(node); return(true); } } } } return(false); }
public static Inode createnode(string name, uint mode, string uid, string gid, byte type) { Inode node = new Inode(); node.dir.qid = new Qid(); node.dir.qid.path = ++path; node.dir.qid.vers = 0; node.dir.qid.type = type; node.dir.name = name; node.dir.atime = (uint)DateTime.Now.ToFileTime(); node.dir.mtime = node.dir.atime; node.dir.uid = uid; node.dir.gid = gid; node.dir.muid = uid; node.dir.mode = mode; node.dir.status = 0; node.dir.type = 0; node.dir.dev = 0; node.dir.length = 0; return(node); }
// 命名事件处理函数 public void nameEventHandler(String newName, FileMode fileMode, NameMode nameMode) { foreach (var nodeIndex in blockGroup.inodeList[blockGroup.currentInodeIndex].childInodeIndex) { if (blockGroup.inodeList[nodeIndex].fileName == newName) { MessageBox.Show("存在重名文件!", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } if (nameMode == NameMode.rename) // 重命名 { var selectedItem = listBoxFile.SelectedItem; String selectedName = selectedItem.ToString().Split(new char[] { ' ' })[0]; int fileIndex = blockGroup.getIndexFromeName(selectedName, blockGroup.currentInodeIndex); if (fileIndex == -1) { return; } else { Inode inode = blockGroup.inodeList[fileIndex]; inode.fileName = newName; blockGroup.inodeList[fileIndex] = inode; } blockGroup.showFile(ref listBoxFile); this.Enabled = true; return; } if (!blockGroup.createFile(fileMode, newName)) { MessageBox.Show("磁盘空间不足!", "", MessageBoxButtons.OK, MessageBoxIcon.Error); } blockGroup.showFile(ref this.listBoxFile); this.Enabled = true; }
// 计算文件大小 public int calculateFileSize(String name, int fatherIndex) { int fileIndex = getIndexFromeName(name, fatherIndex); Inode inode = inodeList[fileIndex]; int size = 0; foreach (var i in inode.dataBlockList) { DataBlock dataBlock = dataBlockList[i]; String data = new string(dataBlock.data); if (inode.fileMode == FileMode.directory) // 目录 { foreach (var indexStr in data.Split(new char[] { '\0' }).Take(inode.childrenNum)) { size += indexStr.Length; } } else // 文件 { size += data.Split(new char[] { '\0' })[0].Length; } } return(size * 2); }
// 返回上级目录 private void buttonBack_Click(object sender, EventArgs e) { if (blockGroup == null) { MessageBox.Show("请先格式化!", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Inode inode = blockGroup.inodeList[blockGroup.currentInodeIndex]; if (inode.fatherIndex == -1) { return; } //blockGroup.inodeList[blockGroup.currentInodeIndex].childInodeIndex.Clear(); // 清除 blockGroup.currentInodeIndex = inode.fatherIndex; if (blockGroup.inodeList[blockGroup.currentInodeIndex].childInodeIndex.Count == 0) { Inode dirInode = blockGroup.inodeList[blockGroup.currentInodeIndex]; blockGroup.readDirectoryFileFromDisk(ref dirInode); blockGroup.inodeList[blockGroup.currentInodeIndex] = dirInode; } blockGroup.showFile(ref listBoxFile); directorySet(); }
public static void Main(string[] args) { ninepc.ninep protocol; string cmd, server; int i; uint offset; Dir[] dirs; string[] lss, lsc; ushort tag = 10; int fid = 6; ffid = 5; root = 9; cwd = 7; protocol = new ninepc.ninep(); //server = "sources.cs.bell-labs.com"; server = "127.0.0.1"; try { //test.connect (server, 564); protocol.connect(server, 9999); protocol.doTversion(65535); protocol.doTauth(tag++); protocol.doTattach(tag++, root); protocol.doTwalk(tag++, root, cwd, new string[0]); dofid(protocol, tag++, root, cwd); for (;;) { Console.Write("{0}% ", server); cmd = Console.ReadLine(); if (cmd.StartsWith("ls")) { protocol.doTwalk(tag++, cwd, ffid, new string[] { "." }); dofid(protocol, tag++, cwd, ffid); //printPacket (test.pktR, "R"); protocol.doTopen(tag++, ffid, 0x00); //printPacket (test.pktR, "R"); protocol.doTread(tag++, ffid, 0, (uint)protocol.mdatasz); //printPacket (test.pktR, "R"); //printPacket (test.pktT, "T"); //printPacket (test.pktR, "R"); dirs = protocol.dols(protocol.readbuf); foreach (Dir d in dirs) { Console.WriteLine("{0} {1} {2} {3} {4}", protocol.modestr(d.mode), d.uid, d.gid, d.length, d.name); } protocol.doTclunk(tag++, ffid); continue; } if (cmd.StartsWith("cd")) { lss = cmd.Split(" ".ToCharArray()); if (lss.Length < 2) { continue; } lsc = lss [1].Split("/".ToCharArray()); protocol.doTwalk(tag++, cwd, fid, lsc); dofid(protocol, tag++, cwd, fid); continue; } if (cmd.StartsWith("cat")) { lss = cmd.Split(" ".ToCharArray()); Array.Copy(lss, 1, lss, 0, lss.Length - 1); for (i = 0; i < (lss.Length - 1); i++) { offset = 0; protocol.doTwalk(tag++, cwd, ffid, new string[] { lss [i] }); dofid(protocol, tag++, cwd, ffid); protocol.doTstat(tag++, ffid); protocol.doTopen(tag++, ffid, 0x00); protocol.doTread(tag++, ffid, offset, (uint)protocol.dir.length); Console.WriteLine(protocol.convstring(protocol.readbuf)); protocol.doTclunk(tag++, ffid); } } if (cmd.StartsWith("rm")) { lss = cmd.Split(" ".ToCharArray()); Array.Copy(lss, 1, lss, 0, lss.Length - 1); for (i = 0; i < (lss.Length - 1); i++) { offset = 0; protocol.doTwalk(tag++, cwd, ffid, new string[] { lss [i] }); dofid(protocol, tag++, cwd, ffid); protocol.doTremove(tag++, ffid); } } if (cmd.StartsWith("touch")) { lss = cmd.Split(" ".ToCharArray()); Array.Copy(lss, 1, lss, 0, lss.Length - 1); for (i = 0; i < (lss.Length - 1); i++) { offset = 0; protocol.doTcreate(tag++, cwd, lss[i], 0x0777, (byte)proto.ORDWR); } } if (cmd.StartsWith("mkdir")) { lss = cmd.Split(" ".ToCharArray()); Array.Copy(lss, 1, lss, 0, lss.Length - 1); for (i = 0; i < (lss.Length - 1); i++) { offset = 0; protocol.doTcreate(tag++, cwd, lss[i], 0x00000777 | (uint)proto.DMDIR, (byte)proto.OREAD); } } if (cmd.StartsWith("wstat")) { lss = cmd.Split(" ".ToCharArray()); //Array.Copy (lss, 1, lss, 0, lss.Length - 1); Array.ForEach(lss, x => Console.WriteLine(x)); protocol.doTwalk(tag++, cwd, ffid, new string[] { lss [1] }); dofid(protocol, tag++, cwd, ffid); Inode node = createnode(lss[2], 0x00000777, lss[3], lss[4], (byte)proto.QTFILE); node.dir.length = 0; Console.WriteLine("{0} {1} {2} {3} {4}", protocol.modestr(node.dir.mode), node.dir.uid, node.dir.gid, node.dir.length, node.dir.name); protocol.doTwstat(tag++, protocol.ffid, node.dir); protocol.doTclunk(tag++, protocol.ffid); } if (cmd.StartsWith("q")) { break; } } protocol.doTclunk(tag++, cwd); protocol.doTclunk(tag++, root); protocol.shutdown(); } catch (Exception ex) { Console.WriteLine("Error main: {0}", ex.ToString()); } }
/// <summary> /// Записывает информацию о новом созданном каталоге на диск. /// </summary> /// <param name="direcoryName">Имя каталога.</param> /// <param name="freeDirectoryRecordAddress">Адрес свободной записи в родительском каталоге.</param> /// <param name="freeInodeAddress">Адрес свободного индексного дескриптора.</param> /// <param name="freeInodeId">ID свободного индексного дескриптора.</param> /// <param name="parentInodeId">ID индексного дескриптора родительского каталога.</param> /// <param name="freeDataClusterIndex">Индекс свободного блока данных.</param> private void FlushNewDirectory(string direcoryName, int freeDirectoryRecordAddress, int freeInodeAddress, int freeInodeId, int parentInodeId, int freeDataClusterIndex) { DirectoryRecord newDirectoryRecord = new DirectoryRecord(); newDirectoryRecord.fileName = direcoryName; newDirectoryRecord.fileExtension = string.Empty; newDirectoryRecord.fileInodeId = freeInodeId; Inode newDirectoryInode = new Inode(); newDirectoryInode.fileType = DIRECTORY_INODE_TYPE; newDirectoryInode.inodeId = freeInodeId; newDirectoryInode.userId = UserId; newDirectoryInode.groupId = GroupId; newDirectoryInode.permissions = new AccessRights(true, true, true, true, false, true, true, false, true).ToInt16(); Attributes attributes = new Attributes(); attributes.hidden = false; attributes.readOnly = false; attributes.system = false; newDirectoryInode.attributes = attributes.ToByte(); newDirectoryInode.fileSize = _superblock.clusterFactor * DISK_BYTES_PER_SECTOR; newDirectoryInode.datetimeFileCreated = Utils.GetTimestamp(); newDirectoryInode.datetimeFileModified = Utils.GetTimestamp(); newDirectoryInode.datetimeInodeModified = Utils.GetTimestamp(); newDirectoryInode.firstClusterIndex = freeDataClusterIndex; FileStream.Seek(freeDirectoryRecordAddress, SeekOrigin.Begin); WriteStruct(FileStream, newDirectoryRecord); FileStream.Seek(freeInodeAddress, SeekOrigin.Begin); WriteStruct(FileStream, newDirectoryInode); FileStream.Seek(_superblock.dataAddress + (freeDataClusterIndex - 1) * CLUSTER_SIZE, SeekOrigin.Begin); // Записать один кластер каталога FileStream.Write(BitConverter.GetBytes(LAST_CLUSTER_ID), 0, sizeof(int)); DirectoryRecord current = new DirectoryRecord(); current.fileName = "."; current.fileExtension = ""; current.fileInodeId = freeInodeId; DirectoryRecord parent = new DirectoryRecord(); parent.fileName = ".."; parent.fileExtension = ""; parent.fileInodeId = parentInodeId; WriteStruct(FileStream, current); WriteStruct(FileStream, parent); int upperBound = (CLUSTER_SIZE - sizeof(int)) / Marshal.SizeOf(typeof(DirectoryRecord)) - 2; for (int i = 0; i < upperBound; i++) { DirectoryRecord directoryRecord = new DirectoryRecord(); directoryRecord.fileInodeId = FREE_DIRECTORY_RECORD; directoryRecord.fileName = ""; directoryRecord.fileExtension = ""; WriteStruct(FileStream, directoryRecord); } }
/// <summary> /// Записывает информацию о новом созданном файле на диск. /// </summary> /// <param name="fileName">Имя файла.</param> /// <param name="fileExtension">Расширение файла.</param> /// <param name="freeDirectoryRecordAddress">Адрес свободной записи в родительском каталоге.</param> /// <param name="freeInodeAddress">Адрес свободного индексного дескриптора.</param> /// <param name="freeInodeId">ID свободного индексного дескриптора.</param> /// <param name="freeDataClusterIndex">Индекс свободного блока данных.</param> private void FlushNewFile(string fileName, string fileExtension, int freeDirectoryRecordAddress, int freeInodeAddress, int freeInodeId, int freeDataClusterIndex) { DirectoryRecord newDirectoryRecord = new DirectoryRecord(); newDirectoryRecord.fileName = fileName; newDirectoryRecord.fileExtension = fileExtension; newDirectoryRecord.fileInodeId = freeInodeId; Inode newFileInode = new Inode(); newFileInode.fileType = FILE_INODE_TYPE; newFileInode.inodeId = freeInodeId; newFileInode.userId = UserId; newFileInode.groupId = GroupId; newFileInode.permissions = new AccessRights(true, true, false, true, false, false, true, false, false).ToInt16(); Attributes attributes = new Attributes(); attributes.hidden = false; attributes.readOnly = false; attributes.system = false; newFileInode.attributes = attributes.ToByte(); newFileInode.fileSize = 0; newFileInode.datetimeFileCreated = Utils.GetTimestamp(); newFileInode.datetimeFileModified = Utils.GetTimestamp(); newFileInode.datetimeInodeModified = Utils.GetTimestamp(); newFileInode.firstClusterIndex = freeDataClusterIndex; FileStream.Seek(freeDirectoryRecordAddress, SeekOrigin.Begin); WriteStruct(FileStream, newDirectoryRecord); FileStream.Seek(freeInodeAddress, SeekOrigin.Begin); WriteStruct(FileStream, newFileInode); FileStream.Seek(_superblock.dataAddress + (freeDataClusterIndex - 1) * CLUSTER_SIZE, SeekOrigin.Begin); // Записать один кластер файла FileStream.Write(BitConverter.GetBytes(LAST_CLUSTER_ID), 0, sizeof(int)); }
public static void Main(string[] args) { //SERVER CODE: if you want the client, comment until CLIENT CODE ninepc.ninep protocol; protocol = new ninepc.ninep(); string clientname = "unset"; //string cmd, server; TcpListener server = protocol.serve(9999); Inode root = createnode("/", 0x00000755, "jeb", "kerman", (byte)proto.QTDIR); root.data = new Byte[0]; Inode testdir = createnode("testdir", 0x00000755, "jeb", "kerman", (byte)proto.QTDIR); testdir.data = new Byte[0]; testdir.parent = root; root.children.Add(testdir); Qid[] wqid = new Qid[10]; //max number of walks... increase if needed. UTF8Encoding utf8 = new UTF8Encoding(); Byte[] strdata = utf8.GetBytes("This is the file contents"); Inode child = createnode("test", 0x00000755, "valerie", "kerman", (byte)proto.QTFILE); child.data = strdata; child.dir.length = (ulong)strdata.Length; child.dir.qid.vers++; testdir.children.Add(child); child.parent = testdir; server.Start(); //ep = new IPEndPoint(addr[0], port); while (true) { TcpClient client = protocol.AcceptTcpClient(server); while (client.Connected) { protocol.recieve(client); printPacket(protocol.pktT, "T"); ushort tag = protocol.fT.tag; int fid = protocol.fT.fid; switch (protocol.fT.type) { case (byte)proto.Tstat: Inode statnode; if (!fidlist.TryGetValue(fid, out statnode)) { protocol.doRerror(tag, "unrecognized fid"); } protocol.doRstat(tag, statnode.dir); break; case (byte)proto.Topen: Inode opnode; if (!fidlist.TryGetValue(fid, out opnode)) { protocol.doRerror(tag, "unrecognized fid"); } //permissions stuff goes here opnode.mode = protocol.fT.mode; protocol.doRopen(tag, opnode.dir.qid, protocol.mmsgsz); break; case (byte)proto.Tread: Inode rnode; uint count; Byte[] data; if (!fidlist.TryGetValue(fid, out rnode)) { protocol.doRerror(tag, "unrecognized fid"); } count = protocol.fT.count; if (count + protocol.fT.offset > rnode.dir.length) { count = (uint)rnode.dir.length - (uint)protocol.fT.offset; } if (rnode.dir.qid.type == (byte)proto.QTDIR) { List <Byte[]> dirdata = new List <Byte[]> (); int len = 0; foreach (Inode i in rnode.children) { Byte[] temp = new Byte[protocol.sizeD2M(i.dir)]; protocol.convD2M(i.dir, temp); //printPacket (temp, "D"); len += temp.Length; dirdata.Add(temp); } data = new Byte[len]; int pp = 0; foreach (Byte[] b in dirdata) { System.Buffer.BlockCopy(b, 0, data, pp, b.Length); pp += b.Length; } protocol.doRread(tag, (uint)data.Length, data); } else { if (count > 0) { data = new Byte[count]; Array.Copy(rnode.data, (int)protocol.fT.offset, data, 0, count); protocol.doRread(tag, count, data); } else { protocol.doRread(tag, 0, new Byte[0]); } } break; case (byte)proto.Tauth: clientname = protocol.fT.uname; protocol.doRerror(tag, "u9fs authnone: no authentication required"); break; case (byte)proto.Tattach: if (protocol.fT.aname.Equals("")) { if (fidlist.ContainsKey(fid) == false) { fidlist.Add(fid, root); protocol.doRattach(tag, root.dir.qid); } else { protocol.doRerror(tag, "Fid currently in use"); } } printfidlist(); break; case (byte)proto.Tclunk: if (listclunk(fid)) { Console.WriteLine("clunked fid:{0}", fid); protocol.doRclunk(tag, fid); } else { protocol.doRerror(tag, "Unrecognized fid"); } printfidlist(); break; case (byte)proto.Twalk: Inode cfidnode; Inode wfidnode; ushort nwqid = 0; if (fidlist.TryGetValue(fid, out cfidnode) == false) { protocol.doRerror(tag, "Unrecognized fid"); break; } else if (fidlist.ContainsKey(protocol.fT.newfid)) { //protocol.doRerror (tag, protocol.fT.tag, "New fid already in use"); listclunk(fid); break; } if (protocol.fT.nwname > 0) { //walk throught the file tree, creating qid's wfidnode = cfidnode; for (nwqid = 0; nwqid < protocol.fT.nwname; nwqid++, cfidnode = wfidnode) { Console.WriteLine("nwname={0}, wname={1}", protocol.fT.nwname, protocol.fT.wname [nwqid]); if (walkChild(cfidnode, protocol.fT.wname [nwqid], out wfidnode)) { //Console.WriteLine ("Walkchild succeeded"); wqid [nwqid] = wfidnode.dir.qid; } else if (nwqid == 0) { protocol.doRerror(tag, "first nwname walk failed"); //Console.WriteLine ("first nwname walk failed"); break; } } // take the last successful walk and make that the new fid. fidlist.Add(protocol.fT.newfid, wfidnode); } else // simply create a new fid for the current file { fidlist.Add(protocol.fT.newfid, cfidnode); nwqid = 1; wqid [0] = cfidnode.dir.qid; } printfidlist(); protocol.doRwalk(tag, nwqid, wqid); break; case (byte)proto.Tremove: Inode rfidnode; if (fidlist.TryGetValue(fid, out rfidnode) == false) { protocol.doRerror(tag, "Unrecognized fid"); break; } if (delnode(rfidnode.parent, rfidnode.dir.name)) { listclunk(fid); protocol.doRremove(tag); } break; case (byte)proto.Tversion: if (protocol.fT.version.Equals("9P2000")) { protocol.doRversion(tag); } else { protocol.doRerror(tag, "Version :" + protocol.fT.version + " not supported."); } break; case (byte)proto.Tflush: //do nothing protocol.doRflush(tag); break; case (byte)proto.Tcreate: Inode dirnode; if (fidlist.TryGetValue(fid, out dirnode) == false) { protocol.doRerror(tag, "Unrecognized fid"); break; } byte type = (byte)proto.QTFILE; Console.WriteLine("perm = {0}", BitConverter.ToString((BitConverter.GetBytes(protocol.fT.perm)))); if ((protocol.fT.perm & (uint)proto.DMDIR) != 0) { type = (byte)proto.QTDIR; Console.WriteLine("Created Directory"); } Inode newfile = createnode(protocol.fT.name, protocol.fT.perm, clientname, "client", type); dirnode.children.Add(newfile); newfile.parent = dirnode; newfile.mode = protocol.fT.mode; newfile.data = new Byte[0]; protocol.doRcreate(tag, new Qid(), protocol.mmsgsz); break; case (byte)proto.Twstat: Inode wnode; Dir tdir; if (fidlist.TryGetValue(fid, out wnode) == false) { protocol.doRerror(tag, "Unrecognized fid"); break; } tdir = protocol.convM2D(protocol.fT.stat, 0); wnode.dir = tdir; // some permissions stuff should precede this. protocol.doRwstat(tag); break; case (byte)proto.Twrite: Inode wrnode; if (fidlist.TryGetValue(fid, out wrnode) == false) { protocol.doRerror(tag, "Unrecognized fid"); break; } if (wrnode.mode.Equals((uint)proto.OREAD)) { protocol.doRerror(tag, "File not opened for writing"); break; } int woffset = (int)protocol.fT.offset; if ((wrnode.mode & (uint)proto.OAPPEND) > 0) { woffset = (int)wrnode.data.Length; } if (woffset > (int)wrnode.data.Length) { protocol.doRerror(tag, "offset out of bounds"); break; } Byte[] newdata = new Byte[woffset + (int)protocol.fT.count]; Array.Copy(wrnode.data, 0, newdata, 0, woffset); //copy existing data before offset Array.Copy(protocol.fT.data, 0, newdata, woffset, protocol.fT.count); wrnode.data = newdata; wrnode.dir.muid = clientname; wrnode.dir.mtime = (uint)DateTime.Now.ToFileTime(); wrnode.dir.qid.vers += 1; wrnode.dir.length = (ulong)wrnode.data.Length; protocol.doRwrite(tag, protocol.fT.count); Console.WriteLine("new contents:{0}", BitConverter.ToString(wrnode.data, 0, wrnode.data.Length)); break; default: throw new ninepexception("unrecognized message type"); } printPacket(protocol.pktR, "R"); } } }
// 将目录文件写入虚拟磁盘 public bool writeDirectoryFileToDisk(int directoryIndex) { Inode dirInode = inodeList[directoryIndex]; int childIndex = 0, blockNum; for (blockNum = 0; blockNum < dirInode.dataBlockList.Count; blockNum++) // 遍历目录占用的数据块 { DataBlock block = dataBlockList[dirInode.dataBlockList[blockNum]]; int blockPoint = 0; for (; childIndex < dirInode.childInodeIndex.Count; childIndex++) // 遍历目录包含的文件 { String index = dirInode.childInodeIndex[childIndex].ToString(); if (BLOCKSIZE / 2 - blockPoint >= index.Length) { for (int j = 0; j < index.Length; j++) // 逐字写入 { block.data[blockPoint] = index[j]; blockPoint++; } block.data[blockPoint] = '\0'; blockPoint++; } } for (; blockPoint < BLOCKSIZE / 2; blockPoint++) { block.data[blockPoint] = '\0'; } dataBlockList[dirInode.dataBlockList[blockNum]] = block; if (childIndex == dirInode.childInodeIndex.Count) // 已经遍历完了所有的文件 { blockNum++; break; } } // 遍历之后有两种结果:原始块不足或剩余 int count = dirInode.dataBlockList.Count; if (childIndex < dirInode.childInodeIndex.Count || (childIndex == 0) && dirInode.childrenNum != 0) // 原始块不足 { int indexOfBlock = -1; foreach (KeyValuePair <int, bool> kvp in groupDescriptorList[0].blockBitmap) // 找到一个空闲数据块 { if (kvp.Value == true) { indexOfBlock = kvp.Key; break; } } if (indexOfBlock == -1) // 没有足够的数据块 { updateInodeInfo(ref dirInode); inodeList[directoryIndex] = dirInode; // 写回 return(false); } groupDescriptorList[0].blockBitmap[indexOfBlock] = false; String index = dirInode.childInodeIndex[childIndex].ToString(); DataBlock block = dataBlockList[indexOfBlock]; for (int j = 0; j < index.Length; j++) // 逐字写入 { block.data[j] = index[j]; } dirInode.dataBlockList.Add(indexOfBlock); // 添加新的数据块的索引 dataBlockList[indexOfBlock] = block; // 写入数据块 } if (blockNum < count || dirInode.childrenNum == 0) // 原始块剩余 { for (; blockNum < dirInode.dataBlockList.Count; blockNum++) { int freeIndex = dirInode.dataBlockList[blockNum]; // 要释放的数据块的index groupDescriptorList[0].blockBitmap[freeIndex] = true; for (int i = 0; i < BLOCKSIZE / 2; i++) { dataBlockList[freeIndex].data[i] = '\0'; } dirInode.dataBlockList.Remove(freeIndex); // 从子列表中移除 } } updateInodeInfo(ref dirInode); inodeList[directoryIndex] = dirInode; // 写回 return(true); }
/// <summary> /// Создаёт новый пустой файл. /// </summary> /// <param name="path">Путь к создаваемому файлу.</param> public void CreateFile(string path) { if (!CanCreateFileOrDirectory) { throw new OutOfMemoryException("Невозможно создать файл, недостаточно свободного дискового пространства!"); } Utils.CheckPath(path); string fullPath = Utils.GetFullPath(path, CurrentDirectory.FullPath); string parentDirectoryPath = Utils.GetDirectoryName(fullPath); string newFileName = Utils.GetFileName(fullPath); string newFileNameWithoutExtension = Utils.GetFileNameWithoutExtension(fullPath); string newFileExtension = Utils.GetExtension(fullPath); // TODO: Каждый раз начинает поиск метафайла с корневого каталога, даже если передан относительный путь. Directory backupDirectory = CurrentDirectory; CurrentDirectory = _rootDirectory; CurrentDirectory = OpenDirectory(parentDirectoryPath); //AccessRights ar = CurrentDirectory.AccessRights; if (!Utils.GetAccessRightsGroup(UserId, GroupId, CurrentDirectory.UserId, CurrentDirectory.GroupId, CurrentDirectory.AccessRights).canWrite) { throw new UnauthorizedAccessException("Текущий пользователь не имеет доступа к записи в родительский каталог!"); } if (CurrentDirectory.Find(newFileName) != null) { throw new ArgumentException("Файл или каталог с таким именем уже существует!", nameof(path)); } // Найти свободный блок данных int freeDataClusterIndex = _bitMap.FindFirstFreeCluster(); if (freeDataClusterIndex < 0) { throw new OutOfMemoryException("Невозможно создать каталог, недостаточно места на жёстком диске!"); } // Найти свободный инод int addressFreeInode = -1; int addressInodes = _superblock.inodeArrayAddress; int inodesCount = _superblock.numClusters; int sizeOfInode = Marshal.SizeOf(typeof(Inode)); FileStream.Seek(addressInodes, SeekOrigin.Begin); Inode freeInode = new Inode(); for (int i = 0; i < inodesCount; i++) { //FileStream.Seek(sizeOfInode, SeekOrigin.Current); freeInode = (Inode)ReadStruct(FileStream, typeof(Inode)); if (freeInode.fileType == FREE_INODE_TYPE) { addressFreeInode = (int)(FileStream.Position - sizeOfInode); break; } } if (addressFreeInode < 0) { throw new OutOfMemoryException("Невозможно создать каталог, не найден адрес свободного индексного дескриптора!"); } // Найти свободное место в каталоге. Разместить запись в каталоге int freeDirectoryRecordAddress = -1; //FileStream.Seek(CurrentDirectory.StreamAddress, SeekOrigin.Begin); long address = CurrentDirectory.StreamAddress; int nextClusterIndex = LAST_CLUSTER_ID; int sizeOfDirectoryRecord = Marshal.SizeOf(typeof(DirectoryRecord)); do { FileStream.Seek(address, SeekOrigin.Begin); nextClusterIndex = (int)ReadStruct(FileStream, typeof(int)); DirectoryRecord directoryRecord; int upperBound = (int)(address + CLUSTER_SIZE); for (long i = address + sizeof(int); i < upperBound; i += sizeOfDirectoryRecord) { directoryRecord = (DirectoryRecord)ReadStruct(FileStream, typeof(DirectoryRecord)); if (directoryRecord.fileInodeId == FREE_DIRECTORY_RECORD) { freeDirectoryRecordAddress = (int)(FileStream.Position - sizeOfDirectoryRecord); break; } //else //{ // FileStream.Seek(sizeOfDirectoryRecord, SeekOrigin.Current); //} } address = _superblock.dataAddress + (nextClusterIndex - 1) * CLUSTER_SIZE; } while (nextClusterIndex != LAST_CLUSTER_ID); if (freeDirectoryRecordAddress < 0) { throw new OutOfMemoryException("Невозможно создать каталог, превышен лимит записей в каталоге!"); } // Поток уже находится на свободной записи родительского каталога. FileStream.Seek(freeDirectoryRecordAddress, SeekOrigin.Begin); FlushNewFile(newFileNameWithoutExtension, newFileExtension, freeDirectoryRecordAddress, addressFreeInode, freeInode.inodeId, freeDataClusterIndex); _bitMap.SetClusterState(freeDataClusterIndex, BitMap.ClusterState.Used); _superblock.numFreeClusters--; _superblock.numFreeInode--; FlushAll(); CurrentDirectory = backupDirectory; }
// 从真实磁盘读入文件系统 public bool readFileSystemFromRealDisk() { try { FileStream fsTest = new FileStream("disk.img", System.IO.FileMode.Open, FileAccess.Read); fsTest.Close(); } catch (FileNotFoundException) // 未找到文件 { MessageBox.Show("未找到磁盘映像!", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } FileStream fs = new FileStream("disk.img", System.IO.FileMode.Open, FileAccess.Read); StreamReader sr = new StreamReader(fs); String volumnStr = sr.ReadLine(); // 读入卷大小 blockGroup = new BlockGroup(int.Parse(volumnStr), INODENUM); // 建立文件系统 blockGroup.volume = int.Parse(volumnStr); String superBlockStr = sr.ReadLine(); // 读入超级块 blockGroup.superBlock.inodeNum = int.Parse(superBlockStr.Split(' ')[0]); blockGroup.superBlock.freeInodeNum = int.Parse(superBlockStr.Split(' ')[1]); String blockBitMapStr = sr.ReadLine(); // 读入数据块位图 foreach (var index in blockBitMapStr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { blockGroup.groupDescriptorList[0].blockBitmap[int.Parse(index)] = false; } String inodeBitMapStr = sr.ReadLine(); // 读入inode位图 foreach (var index in inodeBitMapStr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { blockGroup.groupDescriptorList[0].inodeBitmap[int.Parse(index)] = false; } // 逐个读入数据块 foreach (var i in blockBitMapStr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { int index = int.Parse(i); DataBlock dataBlock = new DataBlock(); dataBlock.data = new char[BLOCKSIZE / 2]; sr.ReadBlock(dataBlock.data, 0, BLOCKSIZE / 2); blockGroup.dataBlockList[index] = dataBlock; } sr.ReadLine(); // 逐个读入inode foreach (var i in inodeBitMapStr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { int index = int.Parse(i); Inode inode = new Inode(); String inodeStr = sr.ReadLine(); var strList = inodeStr.Split(' '); // 读入文件类型 if (strList[0] == FileMode.directory.ToString()) { inode.fileMode = FileMode.directory; } else if (strList[0] == FileMode.common.ToString()) { inode.fileMode = FileMode.common; } else { inode.fileMode = FileMode.unknown; } // 读入文件大小 inode.fileSize = int.Parse(strList[1]); // 读入文件名称 inode.fileName = strList[2]; // 读入创建时间 inode.createdTime = DateTime.Parse(strList[3] + ' ' + strList[4]); // 读入更新时间 inode.updatedTime = DateTime.Parse(strList[5] + ' ' + strList[6]); // 读入占块数 inode.blockSize = int.Parse(strList[7]); // 读入占用的数据块的索引 inode.dataBlockList = new List <int>(); foreach (var j in strList[8].Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)) { inode.dataBlockList.Add(int.Parse(j)); } // 读入子文件的inode索引 inode.childInodeIndex = new List <int>(); foreach (var j in strList[9].Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)) { inode.childInodeIndex.Add(int.Parse(j)); } // 读入子文件数量 inode.childrenNum = int.Parse(strList[10]); // 读入父目录编号 inode.fatherIndex = int.Parse(strList[11]); // 写入inode blockGroup.inodeList[index] = inode; } sr.Close(); fs.Close(); return(true); }
// 关闭系统,保存磁盘镜像 private void buttonCancel_Click(object sender, EventArgs e) { this.Close(); if (blockGroup != null) { FileStream fs = new FileStream("disk.img", System.IO.FileMode.Create, FileAccess.ReadWrite); StreamWriter sw = new StreamWriter(fs); sw.WriteLine(blockGroup.volume); // 写入卷大小 sw.WriteLine(blockGroup.superBlock.inodeNum.ToString() + ' ' + blockGroup.superBlock.freeInodeNum.ToString()); // 写入超级块 // 写入组描述符 String bbm = ""; foreach (var kvp in blockGroup.groupDescriptorList[0].blockBitmap) { if (kvp.Value == false) { bbm = bbm + kvp.Key.ToString() + ' '; } } sw.WriteLine(bbm); // 写入数据块位图 String ibm = ""; foreach (var kvp in blockGroup.groupDescriptorList[0].inodeBitmap) { if (kvp.Value == false) { ibm = ibm + kvp.Key.ToString() + ' '; } } sw.WriteLine(ibm); // 写入inode位图 foreach (var kvp in blockGroup.groupDescriptorList[0].blockBitmap) // 写入数据块 { if (kvp.Value == false) { String data = new string(blockGroup.dataBlockList[kvp.Key].data); sw.Write(data); //sw.WriteLine(data); } } sw.WriteLine(); foreach (var kvp in blockGroup.groupDescriptorList[0].inodeBitmap) // 写入inode块 { if (kvp.Value == false) { String data = ""; Inode inode = blockGroup.inodeList[kvp.Key]; data = inode.fileMode.ToString() + ' ' + inode.fileSize.ToString() + ' ' + inode.fileName + ' ' + inode.createdTime.ToString() + ' ' + inode.updatedTime.ToString() + ' ' + inode.blockSize.ToString() + ' '; foreach (int index in inode.dataBlockList) { data = data + index.ToString() + '/'; } data += ' '; foreach (int index in inode.childInodeIndex) { data = data + index.ToString() + '/'; } data = data + ' ' + inode.childrenNum.ToString() + ' ' + inode.fatherIndex.ToString(); sw.WriteLine(data); } } sw.Close(); fs.Close(); } }
/// <summary> /// Удаляет запись из родительского каталога объекта и освобождает индексный дескриптор. /// </summary> /// <param name="path">Путь к каталогу или файлу, который необходимо удалить.</param> private void DeleteFileOrDirectory(string path) { Utils.CheckPath(path); string fullPath = Utils.GetFullPath(path, CurrentDirectory.FullPath); string fileName = Utils.GetFileNameWithoutExtension(path); string fileExtension = Utils.GetExtension(path); string fullFileName = Utils.GetFileName(path); string directoryPath = Utils.GetDirectoryName(fullPath); Directory directory = OpenDirectory(directoryPath); //AccessRights ar = directory.AccessRights; if (!Utils.GetAccessRightsGroup(UserId, GroupId, directory.UserId, directory.GroupId, directory.AccessRights).canWrite) { throw new UnauthorizedAccessException("Текущий пользователь не имеет доступа к изменению этого каталога!"); } MetaFile metaFile = directory.Find(fullFileName); if (metaFile == null) { throw new FileNotFoundException("Ошибка удаления файла! Указанный файл не существует.", fullFileName); } // Удалить всё содержимое, если это каталог. if (metaFile is Directory) { Directory deletingDirectory = ReadDirectoryClusters(metaFile.FirstClusterIndex, directory.FullPath + (directory.FullPath != "/" ? "/" : string.Empty) + metaFile.FullName); for (int i = 2; i < deletingDirectory.Count; i++) { DeleteFileOrDirectory(deletingDirectory.FullPath + "/" + deletingDirectory[i].FullName); } } long address = (metaFile.FirstClusterIndex == 0 ? _superblock.rootAddress : _superblock.dataAddress + (metaFile.FirstClusterIndex - 1) * CLUSTER_SIZE); List<int> usedClustersIndexes = new List<int>(); usedClustersIndexes.Add(metaFile.FirstClusterIndex); FileStream.Seek(address, SeekOrigin.Begin); int nextClusterIndex = -1; while ((nextClusterIndex = (int)ReadStruct(FileStream, typeof(int))) != LAST_CLUSTER_ID) { usedClustersIndexes.Add(nextClusterIndex); FileStream.Seek(_superblock.dataAddress + (nextClusterIndex - 1) * CLUSTER_SIZE, SeekOrigin.Begin); } for (int i = 0; i < usedClustersIndexes.Count; i++) { _bitMap.SetClusterState(usedClustersIndexes[i], BitMap.ClusterState.Free); } FileStream.Seek(metaFile.DiskRecordAddress, SeekOrigin.Begin); DirectoryRecord directoryRecord = new DirectoryRecord(); directoryRecord.fileInodeId = FREE_DIRECTORY_RECORD; WriteStruct(FileStream, directoryRecord); _superblock.numFreeClusters += usedClustersIndexes.Count; // Перейти к заданному индексному дескриптору int sizeOfInode = Marshal.SizeOf(typeof(Inode)); FileStream.Seek(_superblock.inodeArrayAddress + (metaFile.InodeId - 1) * sizeOfInode, SeekOrigin.Begin); Inode inode = new Inode(); inode.fileType = FREE_INODE_TYPE; inode.inodeId = metaFile.InodeId; WriteStruct(FileStream, inode); _superblock.numFreeInode++; FlushAll(); }
/// <summary> /// Возвращает права доступа к файлу или каталогу. /// </summary> /// <param name="path">Путь к файлу или каталогу.</param> /// <returns>права доступа к файлу или каталогу</returns> public AccessRights GetAccessRights(string path) { Directory current = CurrentDirectory; Utils.CheckPath(path); string fullPath = Utils.GetFullPath(path, CurrentDirectory.FullPath); string parentDirectoryPath = Utils.GetDirectoryName(fullPath); Directory directory = OpenDirectory(parentDirectoryPath); //AccessRights ar = directory.AccessRights; if (!Utils.GetAccessRightsGroup(UserId, GroupId, directory.UserId, directory.GroupId, directory.AccessRights).canExecute) { throw new UnauthorizedAccessException("Текущий пользователь не имеет доступа к чтению прав доступа к объектам этого каталога!"); } string fileName = Utils.GetFileName(path); MetaFile metaFile = directory.Find(fileName); if (metaFile == null) { throw new FileNotFoundException("Указанный файл или каталог не существует!", path); } Inode inode = new Inode(); int sizeOfInode = Marshal.SizeOf(typeof(Inode)); FileStream.Seek(_superblock.inodeArrayAddress + (metaFile.InodeId - 1) * sizeOfInode, SeekOrigin.Begin); inode = (Inode)ReadStruct(FileStream, typeof(Inode)); AccessRights accessRights = new AccessRights(inode.permissions); CurrentDirectory = current; return accessRights; }
/// <summary> /// Задаёт указанные атрибуты файлу или каталогу. /// Не изменяет текущий рабочий каталог. /// </summary> /// <param name="path">Путь к файлу или каталогу.</param> /// <param name="attributes">Атрибуты, которые будут заданы.</param> public void SetAttributes(string path, Attributes attributes) { Directory current = CurrentDirectory; Utils.CheckPath(path); string fullPath = Utils.GetFullPath(path, CurrentDirectory.FullPath); string parentDirectoryPath = Utils.GetDirectoryName(fullPath); Directory directory = OpenDirectory(parentDirectoryPath); //AccessRights ar = directory.AccessRights; if (!Utils.GetAccessRightsGroup(UserId, GroupId, directory.UserId, directory.GroupId, directory.AccessRights).canExecute) { throw new UnauthorizedAccessException("Текущий пользователь не имеет доступа к изменению атрибутов объектов этого каталога!"); } string fileName = Utils.GetFileName(path); MetaFile metaFile = directory.Find(fileName); if (metaFile == null) { throw new FileNotFoundException("Указанный файл или каталог не существует!", path); } Inode inode = new Inode(); int sizeOfInode = Marshal.SizeOf(typeof(Inode)); FileStream.Seek(_superblock.inodeArrayAddress + (metaFile.InodeId - 1) * sizeOfInode, SeekOrigin.Begin); inode = (Inode)ReadStruct(FileStream, typeof(Inode)); inode.attributes = attributes.ToByte(); FileStream.Seek(-sizeOfInode, SeekOrigin.Current); WriteStruct(FileStream, inode); FlushAll(false); CurrentDirectory = current; }
// 将普通文件写入虚拟磁盘 public bool writeCommonFileToDisk(int commonIndex, String content) { Inode inode = inodeList[commonIndex]; int contentPoint = 0; // 文件内容指针 int blockNum; for (blockNum = 0; blockNum < inode.dataBlockList.Count; blockNum++) // 遍历文件占用的数据块 { DataBlock dataBlock = dataBlockList[inode.dataBlockList[blockNum]]; for (int i = 0; i < BLOCKSIZE / 2; i++) // 将内容写入 { if (contentPoint < content.Length) { dataBlock.data[i] = content[contentPoint]; } else { dataBlock.data[i] = '\0'; } contentPoint++; } } // 原始块不足或剩余 int count = inode.dataBlockList.Count; for (; contentPoint < content.Length;) // 原始块不足 { int indexOfBlock = -1; foreach (KeyValuePair <int, bool> kvp in groupDescriptorList[0].blockBitmap) // 找到一个空闲数据块 { if (kvp.Value == true) { indexOfBlock = kvp.Key; break; } } if (indexOfBlock == -1) // 没有足够的数据块 { updateInodeInfo(ref inode); inodeList[commonIndex] = inode; return(false); } groupDescriptorList[0].blockBitmap[indexOfBlock] = false; DataBlock dataBlock = dataBlockList[indexOfBlock]; for (int i = 0; i < BLOCKSIZE / 2 && contentPoint < content.Length; i++) { dataBlock.data[i] = content[contentPoint]; contentPoint++; } inode.dataBlockList.Add(indexOfBlock); // 添加索引 dataBlockList[indexOfBlock] = dataBlock; // 写回 } for (; blockNum < count; blockNum++) // 原始块剩余 { int freeIndex = inode.dataBlockList[blockNum]; // 要释放的数据块的index groupDescriptorList[0].blockBitmap[freeIndex] = true; for (int i = 0; i < BLOCKSIZE / 2; i++) { dataBlockList[freeIndex].data[i] = '\0'; } inode.dataBlockList.Remove(freeIndex); // 从子列表中移除 } updateInodeInfo(ref inode); inodeList[commonIndex] = inode; // 写回 return(true); }
// 更新文件信息 public void updateInodeInfo(ref Inode inode) { inode.blockSize = inode.dataBlockList.Count; inode.updatedTime = DateTime.Now; inode.fileSize = calculateFileSize(inode.fileName, inode.fatherIndex); }
public void ReachTo(Inode obj) { obj.Reach(); }