private void Initialize() { Console.WriteLine("Start Ext2.Initialize"); mBuffer = new byte[mBackend.BlockSize]; fixed (byte* xBufferAddress = &mBuffer[0]) { mBufferAddress = xBufferAddress; } // first get the superblock; var mBufferAsSuperblock = (SuperBlock*)mBufferAddress; int xAddr = (int)mBufferAddress; Console.WriteLine("Buffer address: " + xAddr); Console.WriteLine("Start reading superblock"); mBackend.ReadBlock(2, mBuffer); Console.WriteLine("End reading"); mSuperblock = *mBufferAsSuperblock; DebugUtil.Send_Ext2SuperBlock(mSuperblock); // read the group descriptors Console.WriteLine("INodeCount: " + mSuperblock.INodesCount); Console.WriteLine("INode#1: " + mBufferAddress[0]); Console.WriteLine("INode#2: " + mBufferAddress[1]); Console.WriteLine("INode#3: " + mBufferAddress[2]); Console.WriteLine("INode#4: " + mBufferAddress[3]); Console.WriteLine("BlockCount: " + mSuperblock.BlockCount); Console.WriteLine("INodesPerGroup: " + (int)mSuperblock.INodesPerGroup); if (mSuperblock.INodesPerGroup == 0x4000) { Console.WriteLine("INodesPerGroup has correct value!"); } uint xGroupDescriptorCount = mSuperblock.INodesCount / mSuperblock.INodesPerGroup; mGroupDescriptors = new GroupDescriptor[xGroupDescriptorCount]; var xDescriptorPtr = (GroupDescriptor*)mBufferAddress; Console.WriteLine("Process GroupDescriptors: " + xGroupDescriptorCount); //Console.ReadLine(); for (int i = 0; i < xGroupDescriptorCount; i++) { Console.WriteLine("Processing GroupDescriptor " + i); uint xATABlock ; if ( BlockSize == 1024 ) { xATABlock = ( BlockSize * 2 ) / mBackend.BlockSize ; } else { xATABlock = ( BlockSize ) / mBackend.BlockSize ; } xATABlock += (uint)(i / 16); if ((i % 16) == 0) { Console.WriteLine("Read new GroupDescriptorBlock"); mBackend.ReadBlock(xATABlock, mBuffer); Console.WriteLine("End Read"); } mGroupDescriptors[i] = xDescriptorPtr[i % 16]; Console.WriteLine("End of GroupDescriptor check"); } Console.WriteLine("Send GroupDescriptors to log"); DebugUtil.Send_Ext2GroupDescriptors(mGroupDescriptors); }
public FileSystemPropertiesWindow(SuperBlock sb) { InitializeComponent(); fsTypeEdit.Text = sb.FsType; clusterSizeEdit.Text = sb.ClusterSize.ToString() + " байт"; rootSizeEdit.Text = sb.RootSize.ToString() + " байт"; diskSizeEdit.Text = sb.DiskSize.ToString() + " байт"; fat1OffsetEdit.Text = sb.Fat1Offset.ToString() + " байт"; fat2OffsetEdit.Text = sb.Fat2Offset.ToString() + " байт"; rootOffsetEdit.Text = sb.RootOffset.ToString() + " байт"; dataOffsetEdit.Text = sb.DataOffset.ToString() + " байт"; }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.UTF8; ulong vmfsSuperOff = VXFS_BASE / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); SuperBlock vxSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); var sbInformation = new StringBuilder(); sbInformation.AppendLine("Veritas file system"); sbInformation.AppendFormat("Volume version {0}", vxSb.vs_version).AppendLine(); sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(vxSb.vs_fname, Encoding)). AppendLine(); sbInformation.AppendFormat("Volume has {0} blocks of {1} bytes each", vxSb.vs_bsize, vxSb.vs_size). AppendLine(); sbInformation.AppendFormat("Volume has {0} inodes per block", vxSb.vs_inopb).AppendLine(); sbInformation.AppendFormat("Volume has {0} free inodes", vxSb.vs_ifree).AppendLine(); sbInformation.AppendFormat("Volume has {0} free blocks", vxSb.vs_free).AppendLine(); sbInformation.AppendFormat("Volume created on {0}", DateHandlers.UnixUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime)).AppendLine(); sbInformation.AppendFormat("Volume last modified on {0}", DateHandlers.UnixUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime)).AppendLine(); if (vxSb.vs_clean != 0) { sbInformation.AppendLine("Volume is dirty"); } information = sbInformation.ToString(); XmlFsType = new FileSystemType { Type = "Veritas file system", CreationDate = DateHandlers.UnixUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime), CreationDateSpecified = true, ModificationDate = DateHandlers.UnixUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime), ModificationDateSpecified = true, Clusters = (ulong)vxSb.vs_size, ClusterSize = (uint)vxSb.vs_bsize, Dirty = vxSb.vs_clean != 0, FreeClusters = (ulong)vxSb.vs_free, FreeClustersSpecified = true }; }
/// <summary> /// Detects if the stream contains a SquashFs file system. /// </summary> /// <param name="stream">The stream to inspect</param> /// <returns><c>true</c> if stream appears to be a SquashFs file system.</returns> public static bool Detect(Stream stream) { stream.Position = 0; SuperBlock superBlock = new SuperBlock(); if (stream.Length < superBlock.Size) { return false; } byte[] buffer = Utilities.ReadFully(stream, superBlock.Size); superBlock.ReadFrom(buffer, 0); return superBlock.Magic == SuperBlock.SquashFsMagic; }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); byte[] sector = imagePlugin.ReadSector(partition.Start); uint magic = BitConverter.ToUInt32(sector, 0x00); var crSb = new SuperBlock(); bool littleEndian = true; switch (magic) { case CRAM_MAGIC: crSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); break; case CRAM_CIGAM: crSb = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sector); littleEndian = false; break; } var sbInformation = new StringBuilder(); sbInformation.AppendLine("Cram file system"); sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian"); sbInformation.AppendFormat("Volume edition {0}", crSb.edition).AppendLine(); sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(crSb.name, Encoding)).AppendLine(); sbInformation.AppendFormat("Volume has {0} bytes", crSb.size).AppendLine(); sbInformation.AppendFormat("Volume has {0} blocks", crSb.blocks).AppendLine(); sbInformation.AppendFormat("Volume has {0} files", crSb.files).AppendLine(); information = sbInformation.ToString(); XmlFsType = new FileSystemType { VolumeName = StringHandlers.CToString(crSb.name, Encoding), Type = "Cram file system", Clusters = crSb.blocks, Files = crSb.files, FilesSpecified = true, FreeClusters = 0, FreeClustersSpecified = true }; }
public void FormatTest() { DiskAdapterService diskAdapterService = new DiskAdapterService(_diskConnectService); diskAdapterService.Format(); SuperBlock superBlock = diskAdapterService.ReadSuperBlock(); Assert.AreEqual(6, superBlock.FreeBlockSize); Assert.AreEqual(5, superBlock.FreeBlock[0]); DataBlock dataBlock = diskAdapterService.ReadDataBlock(5, DataMode.Group); for (int i = 1; i < 51; i++) { Assert.AreEqual(56 - i, dataBlock.GroupMode[i]); } }
public void Format() { int count = 1; List <int> blockList = new List <int>(); blockList.Add(Constant.Constant.Nicfreeblk - 1); blockList.Add(-1); for (int i = 40954; i >= 0; i--) { if (count == Constant.Constant.Nicfreeblk) { DataBlock dataBlock = new DataBlock() { GroupMode = blockList }; WriteDataBlock(dataBlock, i, DataMode.Group); count = 1; blockList.Clear(); if (i >= Constant.Constant.Nicfreeblk) { blockList.Add(Constant.Constant.Nicfreeblk); } blockList.Add(i); } else { blockList.Add(i); count++; } } List <int> initInodeList = new List <int>(); for (int j = 1; j < Constant.Constant.Dinodeblk; j++) { initInodeList.Add(j); } SuperBlock superBlock = new SuperBlock() { FreeBlockSize = count, FreeBlock = blockList, FreeInodeSize = Constant.Constant.Dinodeblk, FreeInode = initInodeList }; WriteSuperBlock(superBlock); }
public int GetFreeInode(FileMode fileMode) { SuperBlock superBlock = _diskAdapterService.ReadSuperBlock(); superBlock.FreeInodeSize--; int freeInode = superBlock.FreeInode[0]; superBlock.FreeInode.RemoveAt(0); _diskAdapterService.WriteDiskInode(new DiskInode() { Number = 0, Mode = (int)fileMode, Size = 0, Addrs = new List <int>() }, freeInode); _diskAdapterService.WriteSuperBlock(superBlock); return(freeInode); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { int sbSizeInBytes = Marshal.SizeOf <SuperBlock>(); uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.Info.SectorSize); if (sbSizeInBytes % imagePlugin.Info.SectorSize > 0) { sbSizeInSectors++; } if (sbSizeInSectors + partition.Start >= partition.End) { return(false); } byte[] sbSector = imagePlugin.ReadSectors(partition.Start, sbSizeInSectors); SuperBlock supblk = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sbSector); return(supblk.s_magic == XIAFS_SUPER_MAGIC); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; if (partition.Start + bootSectors >= partition.End) { return(false); } byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors); if (sector.Length < 512) { return(false); } SuperBlock jfsSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); return(jfsSb.s_magic == JFS_MAGIC); }
public void CreatFileTest() { SuperBlock superBlock = new SuperBlock() { FreeBlockSize = 3, FreeBlock = new List <int>() { 1, 2, 3 }, FreeInodeSize = 3, FreeInode = new List <int>() { 1, 2, 3 } }; Dir dir = new Dir() { Size = 0, DirItems = new List <DirItem>() }; diskAdapterService.WriteSuperBlock(superBlock); diskManagementService.WriteDir(dir, 0); coreService.CreatFile(new User(), "newFile", 0); SuperBlock reSuperBlock = diskAdapterService.ReadSuperBlock(); Dir reDir = diskManagementService.ReadDir(0); Assert.AreEqual(1, reDir.Size); Assert.AreEqual("newFile", reDir.DirItems[0].Name); Assert.AreEqual(1, reDir.DirItems[0].Inode); Assert.AreEqual(2, reSuperBlock.FreeInodeSize); coreService.DeleteFile(new User(), "newFile", 0); reSuperBlock = diskAdapterService.ReadSuperBlock(); reDir = diskManagementService.ReadDir(0); Assert.AreEqual(superBlock.FreeInodeSize, reSuperBlock.FreeInodeSize); Assert.AreEqual(dir.Size, reDir.Size); Assert.AreEqual(0, reDir.DirItems.Count); }
public void WriteSuperBlock(SuperBlock superBlock) { //超级块字节化 byte[] bytes = new byte[Constant.Constant.Blocksize]; int count = 0; List <int> blockInfo = new List <int>(); blockInfo.Add(superBlock.FreeBlockSize); blockInfo.AddRange(superBlock.FreeBlock); blockInfo.Add(superBlock.FreeInodeSize); blockInfo.AddRange(superBlock.FreeInode); blockInfo.ForEach(delegate(int index) { Array.Copy(BitConverter.GetBytes(index), 0, bytes, count, 4); count += 4; }); //超级块写入虚拟磁盘 fileStream = _diskConnectService.GetFileStream(); fileStream.Seek(0, SeekOrigin.Begin); fileStream.Write(bytes, 0, bytes.Length); fileStream.Close(); }
public void Format() { SuperBlock = new SuperBlock { BlockSize = 2, //this should be calculated TotalReservedBlocks = 20, TotalBlocks = BlockDevice.TotalBlocks, SizeOfIndexInBytes = 0, Checksum = 0, DataSizeInBlocks = 0, TimeStamp = 0 }; SuperBlock.SizeOfIndexInBytes = 64 * 2; SuperBlock.Write(BlockBuffer); var volumeIdentifier = new VolumeIdentifier { TimeStamp = 0, VolumeName = "SFS Volume" }; var offset = 1; BlockBuffer.Offset = BlockDevice.BlockSize * BlockDevice.TotalBlocks - offset * 64; volumeIdentifier.Write(BlockBuffer); offset++; BlockBuffer.Offset = BlockDevice.BlockSize * BlockDevice.TotalBlocks - offset * 64; var marker = new StartingMarkerEntry(); marker.Write(BlockBuffer); ReadIndexAria(); }
public List <int> GetFreeBlocks(int num) { SuperBlock superBlock = _diskAdapterService.ReadSuperBlock(); List <int> blockList = new List <int>(); for (int i = 0; i < num; i++) { if (superBlock.FreeBlockSize == 1) { if (superBlock.FreeBlock[0] == -1) { RetrieveBlocks(blockList); return(null); //TODO:不知此处返回什么 //throw new NotImplementedException(); } else { int group = superBlock.FreeBlock[0]; blockList.Add(group); DataBlock dataBlock = _diskAdapterService.ReadDataBlock(group, DataMode.Group); superBlock.FreeBlockSize = dataBlock.GroupMode[0]; superBlock.FreeBlock = dataBlock.GroupMode.GetRange(1, superBlock.FreeBlockSize); } } else { superBlock.FreeBlockSize--; blockList.Add(superBlock.FreeBlock[superBlock.FreeBlock.Count - 1]); superBlock.FreeBlock.RemoveAt(superBlock.FreeBlock.Count - 1); } _diskAdapterService.WriteSuperBlock(superBlock); } return(blockList); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.Info.SectorSize; uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; if (partition.Start + bootSectors + sectors >= partition.End) { return(false); } byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors); byte[] sector = imagePlugin.ReadSectors(partition.Start + bootSectors, sectors); if (sector.Length < QNX6_SUPER_BLOCK_SIZE) { return(false); } AudiSuperBlock audiSb = Marshal.ByteArrayToStructureLittleEndian <AudiSuperBlock>(audiSector); SuperBlock qnxSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); return(qnxSb.magic == QNX6_MAGIC || audiSb.magic == QNX6_MAGIC); }
public void GetRetrieveBlock() { SuperBlock superBlock = new SuperBlock() { FreeBlockSize = 1, FreeBlock = new List <int>() { 0 }, FreeInodeSize = 3, FreeInode = new List <int>() { 1, 2, 3 } }; diskAdapterService.WriteSuperBlock(superBlock); DataBlock dataBlock = new DataBlock() { GroupMode = new List <int>() { 3, -1, 2, 1 } }; diskAdapterService.WriteDataBlock(dataBlock, 0, DataMode.Group); List <int> tFreeBlock = diskManagementService.GetFreeBlocks(2); Assert.AreEqual(0, tFreeBlock[0]); Assert.AreEqual(1, tFreeBlock[1]); tFreeBlock = diskManagementService.GetFreeBlocks(10); Assert.IsNull(tFreeBlock); superBlock = diskAdapterService.ReadSuperBlock(); Assert.AreEqual(2, superBlock.FreeBlockSize); Assert.AreEqual(2, superBlock.FreeBlock[1]); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sb = new StringBuilder(); uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.Info.SectorSize; uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors); byte[] sector = imagePlugin.ReadSectors(partition.Start + bootSectors, sectors); if (sector.Length < QNX6_SUPER_BLOCK_SIZE) { return; } AudiSuperBlock audiSb = Marshal.ByteArrayToStructureLittleEndian <AudiSuperBlock>(audiSector); SuperBlock qnxSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); bool audi = audiSb.magic == QNX6_MAGIC; if (audi) { sb.AppendLine("QNX6 (Audi) filesystem"); sb.AppendFormat("Checksum: 0x{0:X8}", audiSb.checksum).AppendLine(); sb.AppendFormat("Serial: 0x{0:X16}", audiSb.checksum).AppendLine(); sb.AppendFormat("{0} bytes per block", audiSb.blockSize).AppendLine(); sb.AppendFormat("{0} inodes free of {1}", audiSb.freeInodes, audiSb.numInodes).AppendLine(); sb.AppendFormat("{0} blocks ({1} bytes) free of {2} ({3} bytes)", audiSb.freeBlocks, audiSb.freeBlocks * audiSb.blockSize, audiSb.numBlocks, audiSb.numBlocks * audiSb.blockSize).AppendLine(); XmlFsType = new FileSystemType { Type = "QNX6 (Audi) filesystem", Clusters = audiSb.numBlocks, ClusterSize = audiSb.blockSize, Bootable = true, Files = audiSb.numInodes - audiSb.freeInodes, FilesSpecified = true, FreeClusters = audiSb.freeBlocks, FreeClustersSpecified = true, VolumeSerial = $"{audiSb.serial:X16}" }; //xmlFSType.VolumeName = CurrentEncoding.GetString(audiSb.id); information = sb.ToString(); return; } sb.AppendLine("QNX6 filesystem"); sb.AppendFormat("Checksum: 0x{0:X8}", qnxSb.checksum).AppendLine(); sb.AppendFormat("Serial: 0x{0:X16}", qnxSb.checksum).AppendLine(); sb.AppendFormat("Created on {0}", DateHandlers.UnixUnsignedToDateTime(qnxSb.ctime)).AppendLine(); sb.AppendFormat("Last mounted on {0}", DateHandlers.UnixUnsignedToDateTime(qnxSb.atime)).AppendLine(); sb.AppendFormat("Flags: 0x{0:X8}", qnxSb.flags).AppendLine(); sb.AppendFormat("Version1: 0x{0:X4}", qnxSb.version1).AppendLine(); sb.AppendFormat("Version2: 0x{0:X4}", qnxSb.version2).AppendLine(); //sb.AppendFormat("Volume ID: \"{0}\"", CurrentEncoding.GetString(qnxSb.volumeid)).AppendLine(); sb.AppendFormat("{0} bytes per block", qnxSb.blockSize).AppendLine(); sb.AppendFormat("{0} inodes free of {1}", qnxSb.freeInodes, qnxSb.numInodes).AppendLine(); sb.AppendFormat("{0} blocks ({1} bytes) free of {2} ({3} bytes)", qnxSb.freeBlocks, qnxSb.freeBlocks * qnxSb.blockSize, qnxSb.numBlocks, qnxSb.numBlocks * qnxSb.blockSize). AppendLine(); XmlFsType = new FileSystemType { Type = "QNX6 filesystem", Clusters = qnxSb.numBlocks, ClusterSize = qnxSb.blockSize, Bootable = true, Files = qnxSb.numInodes - qnxSb.freeInodes, FilesSpecified = true, FreeClusters = qnxSb.freeBlocks, FreeClustersSpecified = true, VolumeSerial = $"{qnxSb.serial:X16}", CreationDate = DateHandlers.UnixUnsignedToDateTime(qnxSb.ctime), CreationDateSpecified = true, ModificationDate = DateHandlers.UnixUnsignedToDateTime(qnxSb.atime), ModificationDateSpecified = true }; //xmlFSType.VolumeName = CurrentEncoding.GetString(qnxSb.volumeid); information = sb.ToString(); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("ibm850"); information = ""; var sb = new StringBuilder(); byte[] hpfsBpbSector = imagePlugin.ReadSector(0 + partition.Start); // Seek to BIOS parameter block, on logical sector 0 byte[] hpfsSbSector = imagePlugin.ReadSector(16 + partition.Start); // Seek to superblock, on logical sector 16 byte[] hpfsSpSector = imagePlugin.ReadSector(17 + partition.Start); // Seek to spareblock, on logical sector 17 BiosParameterBlock bpb = Marshal.ByteArrayToStructureLittleEndian <BiosParameterBlock>(hpfsBpbSector); SuperBlock hpfsSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(hpfsSbSector); SpareBlock sp = Marshal.ByteArrayToStructureLittleEndian <SpareBlock>(hpfsSpSector); if (StringHandlers.CToString(bpb.fs_type) != "HPFS " || hpfsSb.magic1 != 0xF995E849 || hpfsSb.magic2 != 0xFA53E9C5 || sp.magic1 != 0xF9911849 || sp.magic2 != 0xFA5229C5) { sb.AppendLine("This may not be HPFS, following information may be not correct."); sb.AppendFormat("File system type: \"{0}\" (Should be \"HPFS \")", bpb.fs_type).AppendLine(); sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfsSb.magic1).AppendLine(); sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfsSb.magic2).AppendLine(); sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", sp.magic1).AppendLine(); sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", sp.magic2).AppendLine(); } sb.AppendFormat("OEM name: {0}", StringHandlers.CToString(bpb.oem_name)).AppendLine(); sb.AppendFormat("{0} bytes per sector", bpb.bps).AppendLine(); // sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine(); // sb.AppendFormat("{0} reserved sectors", hpfs_bpb.rsectors).AppendLine(); // sb.AppendFormat("{0} FATs", hpfs_bpb.fats_no).AppendLine(); // sb.AppendFormat("{0} entries on root directory", hpfs_bpb.root_ent).AppendLine(); // sb.AppendFormat("{0} mini sectors on volume", hpfs_bpb.sectors).AppendLine(); sb.AppendFormat("Media descriptor: 0x{0:X2}", bpb.media).AppendLine(); // sb.AppendFormat("{0} sectors per FAT", hpfs_bpb.spfat).AppendLine(); // sb.AppendFormat("{0} sectors per track", hpfs_bpb.sptrk).AppendLine(); // sb.AppendFormat("{0} heads", hpfs_bpb.heads).AppendLine(); sb.AppendFormat("{0} sectors hidden before BPB", bpb.hsectors).AppendLine(); sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfsSb.sectors, hpfsSb.sectors * bpb.bps).AppendLine(); // sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_bpb.big_sectors, hpfs_bpb.big_sectors * hpfs_bpb.bps).AppendLine(); sb.AppendFormat("BIOS Drive Number: 0x{0:X2}", bpb.drive_no).AppendLine(); sb.AppendFormat("NT Flags: 0x{0:X2}", bpb.nt_flags).AppendLine(); sb.AppendFormat("Signature: 0x{0:X2}", bpb.signature).AppendLine(); sb.AppendFormat("Serial number: 0x{0:X8}", bpb.serial_no).AppendLine(); sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(bpb.volume_label, Encoding)).AppendLine(); // sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine(); DateTime lastChk = DateHandlers.UnixToDateTime(hpfsSb.last_chkdsk); DateTime lastOptim = DateHandlers.UnixToDateTime(hpfsSb.last_optim); sb.AppendFormat("HPFS version: {0}", hpfsSb.version).AppendLine(); sb.AppendFormat("Functional version: {0}", hpfsSb.func_version).AppendLine(); sb.AppendFormat("Sector of root directory FNode: {0}", hpfsSb.root_fnode).AppendLine(); sb.AppendFormat("{0} sectors are marked bad", hpfsSb.badblocks).AppendLine(); sb.AppendFormat("Sector of free space bitmaps: {0}", hpfsSb.bitmap_lsn).AppendLine(); sb.AppendFormat("Sector of bad blocks list: {0}", hpfsSb.badblock_lsn).AppendLine(); if (hpfsSb.last_chkdsk > 0) { sb.AppendFormat("Date of last integrity check: {0}", lastChk).AppendLine(); } else { sb.AppendLine("Filesystem integrity has never been checked"); } if (hpfsSb.last_optim > 0) { sb.AppendFormat("Date of last optimization {0}", lastOptim).AppendLine(); } else { sb.AppendLine("Filesystem has never been optimized"); } sb.AppendFormat("Directory band has {0} sectors", hpfsSb.dband_sectors).AppendLine(); sb.AppendFormat("Directory band starts at sector {0}", hpfsSb.dband_start).AppendLine(); sb.AppendFormat("Directory band ends at sector {0}", hpfsSb.dband_last).AppendLine(); sb.AppendFormat("Sector of directory band bitmap: {0}", hpfsSb.dband_bitmap).AppendLine(); sb.AppendFormat("Sector of ACL directory: {0}", hpfsSb.acl_start).AppendLine(); sb.AppendFormat("Sector of Hotfix directory: {0}", sp.hotfix_start).AppendLine(); sb.AppendFormat("{0} used Hotfix entries", sp.hotfix_used).AppendLine(); sb.AppendFormat("{0} total Hotfix entries", sp.hotfix_entries).AppendLine(); sb.AppendFormat("{0} free spare DNodes", sp.spare_dnodes_free).AppendLine(); sb.AppendFormat("{0} total spare DNodes", sp.spare_dnodes).AppendLine(); sb.AppendFormat("Sector of codepage directory: {0}", sp.codepage_lsn).AppendLine(); sb.AppendFormat("{0} codepages used in the volume", sp.codepages).AppendLine(); sb.AppendFormat("SuperBlock CRC32: {0:X8}", sp.sb_crc32).AppendLine(); sb.AppendFormat("SpareBlock CRC32: {0:X8}", sp.sp_crc32).AppendLine(); sb.AppendLine("Flags:"); sb.AppendLine((sp.flags1 & 0x01) == 0x01 ? "Filesystem is dirty." : "Filesystem is clean."); if ((sp.flags1 & 0x02) == 0x02) { sb.AppendLine("Spare directory blocks are in use"); } if ((sp.flags1 & 0x04) == 0x04) { sb.AppendLine("Hotfixes are in use"); } if ((sp.flags1 & 0x08) == 0x08) { sb.AppendLine("Disk contains bad sectors"); } if ((sp.flags1 & 0x10) == 0x10) { sb.AppendLine("Disk has a bad bitmap"); } if ((sp.flags1 & 0x20) == 0x20) { sb.AppendLine("Filesystem was formatted fast"); } if ((sp.flags1 & 0x40) == 0x40) { sb.AppendLine("Unknown flag 0x40 on flags1 is active"); } if ((sp.flags1 & 0x80) == 0x80) { sb.AppendLine("Filesystem has been mounted by an old IFS"); } if ((sp.flags2 & 0x01) == 0x01) { sb.AppendLine("Install DASD limits"); } if ((sp.flags2 & 0x02) == 0x02) { sb.AppendLine("Resync DASD limits"); } if ((sp.flags2 & 0x04) == 0x04) { sb.AppendLine("DASD limits are operational"); } if ((sp.flags2 & 0x08) == 0x08) { sb.AppendLine("Multimedia is active"); } if ((sp.flags2 & 0x10) == 0x10) { sb.AppendLine("DCE ACLs are active"); } if ((sp.flags2 & 0x20) == 0x20) { sb.AppendLine("DASD limits are dirty"); } if ((sp.flags2 & 0x40) == 0x40) { sb.AppendLine("Unknown flag 0x40 on flags2 is active"); } if ((sp.flags2 & 0x80) == 0x80) { sb.AppendLine("Unknown flag 0x80 on flags2 is active"); } XmlFsType = new FileSystemType(); // Theoretically everything from BPB to SB is boot code, should I hash everything or only the sector loaded by BIOS itself? if (bpb.jump[0] == 0xEB && bpb.jump[1] > 0x3C && bpb.jump[1] < 0x80 && bpb.signature2 == 0xAA55) { XmlFsType.Bootable = true; string bootChk = Sha1Context.Data(bpb.boot_code, out byte[] _); sb.AppendLine("Volume is bootable"); sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine(); } XmlFsType.Dirty |= (sp.flags1 & 0x01) == 0x01; XmlFsType.Clusters = hpfsSb.sectors; XmlFsType.ClusterSize = bpb.bps; XmlFsType.Type = "HPFS"; XmlFsType.VolumeName = StringHandlers.CToString(bpb.volume_label, Encoding); XmlFsType.VolumeSerial = $"{bpb.serial_no:X8}"; XmlFsType.SystemIdentifier = StringHandlers.CToString(bpb.oem_name); information = sb.ToString(); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sb = new StringBuilder(); var besb = new SuperBlock(); byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start); bool littleEndian; besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20); if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // Magic is at offset { littleEndian = besb.magic1 == BEFS_CIGAM1; } else { sbSector = imagePlugin.ReadSector(1 + partition.Start); besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20); if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector { littleEndian = besb.magic1 == BEFS_CIGAM1; } else if (sbSector.Length >= 0x400) { byte[] temp = imagePlugin.ReadSector(0 + partition.Start); besb.magic1 = BigEndianBitConverter.ToUInt32(temp, 0x220); if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector { littleEndian = besb.magic1 == BEFS_CIGAM1; sbSector = new byte[0x200]; Array.Copy(temp, 0x200, sbSector, 0, 0x200); } else { return; } } else { return; } } besb = littleEndian ? Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sbSector) : Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sbSector); sb.AppendLine(littleEndian ? "Little-endian BeFS" : "Big-endian BeFS"); if (besb.magic1 != BEFS_MAGIC1 || besb.fs_byte_order != BEFS_ENDIAN || besb.magic2 != BEFS_MAGIC2 || besb.magic3 != BEFS_MAGIC3 || besb.root_dir_len != 1 || besb.indices_len != 1 || 1 << (int)besb.block_shift != besb.block_size) { sb.AppendLine("Superblock seems corrupt, following information may be incorrect"); sb.AppendFormat("Magic 1: 0x{0:X8} (Should be 0x42465331)", besb.magic1).AppendLine(); sb.AppendFormat("Magic 2: 0x{0:X8} (Should be 0xDD121031)", besb.magic2).AppendLine(); sb.AppendFormat("Magic 3: 0x{0:X8} (Should be 0x15B6830E)", besb.magic3).AppendLine(); sb.AppendFormat("Filesystem endianness: 0x{0:X8} (Should be 0x42494745)", besb.fs_byte_order). AppendLine(); sb.AppendFormat("Root folder's i-node size: {0} blocks (Should be 1)", besb.root_dir_len).AppendLine(); sb.AppendFormat("Indices' i-node size: {0} blocks (Should be 1)", besb.indices_len).AppendLine(); sb.AppendFormat("1 << block_shift == block_size => 1 << {0} == {1} (Should be {2})", besb.block_shift, 1 << (int)besb.block_shift, besb.block_size).AppendLine(); } switch (besb.flags) { case BEFS_CLEAN: sb.AppendLine(besb.log_start == besb.log_end ? "Filesystem is clean" : "Filesystem is dirty"); break; case BEFS_DIRTY: sb.AppendLine("Filesystem is dirty"); break; default: sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine(); break; } sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(besb.name, Encoding)).AppendLine(); sb.AppendFormat("{0} bytes per block", besb.block_size).AppendLine(); sb.AppendFormat("{0} blocks in volume ({1} bytes)", besb.num_blocks, besb.num_blocks * besb.block_size). AppendLine(); sb.AppendFormat("{0} used blocks ({1} bytes)", besb.used_blocks, besb.used_blocks * besb.block_size). AppendLine(); sb.AppendFormat("{0} bytes per i-node", besb.inode_size).AppendLine(); sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", besb.blocks_per_ag, besb.blocks_per_ag * besb.block_size).AppendLine(); sb.AppendFormat("{0} allocation groups in volume", besb.num_ags).AppendLine(); sb.AppendFormat("Journal resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", besb.log_blocks_start, besb.log_blocks_ag, besb.log_blocks_len, besb.log_blocks_len * besb.block_size).AppendLine(); sb.AppendFormat("Journal starts in byte {0} and ends in byte {1}", besb.log_start, besb.log_end). AppendLine(); sb. AppendFormat("Root folder's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", besb.root_dir_start, besb.root_dir_ag, besb.root_dir_len, besb.root_dir_len * besb.block_size).AppendLine(); sb. AppendFormat("Indices' i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", besb.indices_start, besb.indices_ag, besb.indices_len, besb.indices_len * besb.block_size). AppendLine(); information = sb.ToString(); XmlFsType = new FileSystemType { Clusters = (ulong)besb.num_blocks, ClusterSize = besb.block_size, Dirty = besb.flags == BEFS_DIRTY, FreeClusters = (ulong)(besb.num_blocks - besb.used_blocks), FreeClustersSpecified = true, Type = "BeFS", VolumeName = StringHandlers.CToString(besb.name, Encoding) }; }
public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, Dictionary <string, string> options, string @namespace) { // TODO: Find correct default encoding Encoding = Encoding.ASCII; if (options == null) { options = GetDefaultOptions(); } if (options.TryGetValue("debug", out string debugString)) { bool.TryParse(debugString, out debug); } byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start); SuperBlock sb = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sbSector); if (sb.record_type != 1 || sb.record_version != 1) { return(Errno.InvalidArgument); } if (Encoding.ASCII.GetString(sb.sync_bytes) != SYNC) { return(Errno.InvalidArgument); } if (imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448) { volumeBlockSizeRatio = sb.block_size / 2048; } else { volumeBlockSizeRatio = sb.block_size / imagePlugin.Info.SectorSize; } XmlFsType = new FileSystemType { Type = "Opera", VolumeName = StringHandlers.CToString(sb.volume_label, Encoding), ClusterSize = sb.block_size, Clusters = sb.block_count, Bootable = true, VolumeSerial = $"{sb.volume_id:X8}" }; statfs = new FileSystemInfo { Blocks = sb.block_count, FilenameLength = MAX_NAME, FreeBlocks = 0, Id = new FileSystemId { IsInt = true, Serial32 = sb.volume_id }, PluginId = Id, Type = "Opera" }; image = imagePlugin; int firstRootBlock = BigEndianBitConverter.ToInt32(sbSector, Marshal.SizeOf <SuperBlock>()); rootDirectoryCache = DecodeDirectory(firstRootBlock); directoryCache = new Dictionary <string, Dictionary <string, DirectoryEntryWithPointers> >(); mounted = true; return(Errno.NoError); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sb = new StringBuilder(); bool newExt2 = false; bool ext3 = false; bool ext4 = false; int sbSizeInBytes = Marshal.SizeOf <SuperBlock>(); uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.Info.SectorSize); if (sbSizeInBytes % imagePlugin.Info.SectorSize > 0) { sbSizeInSectors++; } ulong sbSectorOff = SB_POS / imagePlugin.Info.SectorSize; uint sbOff = SB_POS % imagePlugin.Info.SectorSize; byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors); byte[] sblock = new byte[sbSizeInBytes]; Array.Copy(sbSector, sbOff, sblock, 0, sbSizeInBytes); SuperBlock supblk = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sblock); XmlFsType = new FileSystemType(); switch (supblk.magic) { case EXT2_MAGIC_OLD: sb.AppendLine("ext2 (old) filesystem"); XmlFsType.Type = "ext2"; break; case EXT2_MAGIC: ext3 |= (supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL || (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER || (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV; if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE || (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM || (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK || (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA) { ext3 = false; ext4 = true; } newExt2 |= !ext3 && !ext4; if (newExt2) { sb.AppendLine("ext2 filesystem"); XmlFsType.Type = "ext2"; } if (ext3) { sb.AppendLine("ext3 filesystem"); XmlFsType.Type = "ext3"; } if (ext4) { sb.AppendLine("ext4 filesystem"); XmlFsType.Type = "ext4"; } break; default: information = "Not a ext2/3/4 filesystem" + Environment.NewLine; return; } string extOs; switch (supblk.creator_os) { case EXT2_OS_FREEBSD: extOs = "FreeBSD"; break; case EXT2_OS_HURD: extOs = "Hurd"; break; case EXT2_OS_LINUX: extOs = "Linux"; break; case EXT2_OS_LITES: extOs = "Lites"; break; case EXT2_OS_MASIX: extOs = "MasIX"; break; default: extOs = $"Unknown OS ({supblk.creator_os})"; break; } XmlFsType.SystemIdentifier = extOs; if (supblk.mkfs_t > 0) { sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UnixUnsignedToDateTime(supblk.mkfs_t), extOs).AppendLine(); XmlFsType.CreationDate = DateHandlers.UnixUnsignedToDateTime(supblk.mkfs_t); XmlFsType.CreationDateSpecified = true; } else { sb.AppendFormat("Volume was created for {0}", extOs).AppendLine(); } byte[] tempBytes = new byte[8]; ulong blocks, reserved, free; if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT) { byte[] tempLo = BitConverter.GetBytes(supblk.blocks); byte[] tempHi = BitConverter.GetBytes(supblk.blocks_hi); tempBytes[0] = tempLo[0]; tempBytes[1] = tempLo[1]; tempBytes[2] = tempLo[2]; tempBytes[3] = tempLo[3]; tempBytes[4] = tempHi[0]; tempBytes[5] = tempHi[1]; tempBytes[6] = tempHi[2]; tempBytes[7] = tempHi[3]; blocks = BitConverter.ToUInt64(tempBytes, 0); tempLo = BitConverter.GetBytes(supblk.reserved_blocks); tempHi = BitConverter.GetBytes(supblk.reserved_blocks_hi); tempBytes[0] = tempLo[0]; tempBytes[1] = tempLo[1]; tempBytes[2] = tempLo[2]; tempBytes[3] = tempLo[3]; tempBytes[4] = tempHi[0]; tempBytes[5] = tempHi[1]; tempBytes[6] = tempHi[2]; tempBytes[7] = tempHi[3]; reserved = BitConverter.ToUInt64(tempBytes, 0); tempLo = BitConverter.GetBytes(supblk.free_blocks); tempHi = BitConverter.GetBytes(supblk.free_blocks_hi); tempBytes[0] = tempLo[0]; tempBytes[1] = tempLo[1]; tempBytes[2] = tempLo[2]; tempBytes[3] = tempLo[3]; tempBytes[4] = tempHi[0]; tempBytes[5] = tempHi[1]; tempBytes[6] = tempHi[2]; tempBytes[7] = tempHi[3]; free = BitConverter.ToUInt64(tempBytes, 0); } else { blocks = supblk.blocks; reserved = supblk.reserved_blocks; free = supblk.free_blocks; } if (supblk.block_size == 0) // Then it is 1024 bytes { supblk.block_size = 1024; } sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks, 1024 << (int)supblk.block_size, blocks * (ulong)(1024 << (int)supblk.block_size)). AppendLine(); XmlFsType.Clusters = blocks; XmlFsType.ClusterSize = (uint)(1024 << (int)supblk.block_size); if (supblk.mount_t > 0 || supblk.mount_c > 0) { if (supblk.mount_t > 0) { sb.AppendFormat("Last mounted on {0}", DateHandlers.UnixUnsignedToDateTime(supblk.mount_t)). AppendLine(); } if (supblk.max_mount_c != -1) { sb.AppendFormat("Volume has been mounted {0} times of a maximum of {1} mounts before checking", supblk.mount_c, supblk.max_mount_c).AppendLine(); } else { sb.AppendFormat("Volume has been mounted {0} times with no maximum no. of mounts before checking", supblk.mount_c).AppendLine(); } if (!string.IsNullOrEmpty(StringHandlers.CToString(supblk.last_mount_dir, Encoding))) { sb.AppendFormat("Last mounted on: \"{0}\"", StringHandlers.CToString(supblk.last_mount_dir, Encoding)).AppendLine(); } if (!string.IsNullOrEmpty(StringHandlers.CToString(supblk.mount_options, Encoding))) { sb.AppendFormat("Last used mount options were: {0}", StringHandlers.CToString(supblk.mount_options, Encoding)).AppendLine(); } } else { sb.AppendLine("Volume has never been mounted"); if (supblk.max_mount_c != -1) { sb.AppendFormat("Volume can be mounted {0} times before checking", supblk.max_mount_c).AppendLine(); } else { sb.AppendLine("Volume has no maximum no. of mounts before checking"); } } if (supblk.check_t > 0) { if (supblk.check_inv > 0) { sb.AppendFormat("Last checked on {0} (should check every {1} seconds)", DateHandlers.UnixUnsignedToDateTime(supblk.check_t), supblk.check_inv).AppendLine(); } else { sb.AppendFormat("Last checked on {0}", DateHandlers.UnixUnsignedToDateTime(supblk.check_t)). AppendLine(); } } else { if (supblk.check_inv > 0) { sb.AppendFormat("Volume has never been checked (should check every {0})", supblk.check_inv). AppendLine(); } else { sb.AppendLine("Volume has never been checked"); } } if (supblk.write_t > 0) { sb.AppendFormat("Last written on {0}", DateHandlers.UnixUnsignedToDateTime(supblk.write_t)). AppendLine(); XmlFsType.ModificationDate = DateHandlers.UnixUnsignedToDateTime(supblk.write_t); XmlFsType.ModificationDateSpecified = true; } else { sb.AppendLine("Volume has never been written"); } XmlFsType.Dirty = true; switch (supblk.state) { case EXT2_VALID_FS: sb.AppendLine("Volume is clean"); XmlFsType.Dirty = false; break; case EXT2_ERROR_FS: sb.AppendLine("Volume is dirty"); break; case EXT3_ORPHAN_FS: sb.AppendLine("Volume is recovering orphan files"); break; default: sb.AppendFormat("Volume is in an unknown state ({0})", supblk.state).AppendLine(); break; } if (!string.IsNullOrEmpty(StringHandlers.CToString(supblk.volume_name, Encoding))) { sb.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(supblk.volume_name, Encoding)). AppendLine(); XmlFsType.VolumeName = StringHandlers.CToString(supblk.volume_name, Encoding); } switch (supblk.err_behaviour) { case EXT2_ERRORS_CONTINUE: sb.AppendLine("On errors, filesystem should continue"); break; case EXT2_ERRORS_RO: sb.AppendLine("On errors, filesystem should remount read-only"); break; case EXT2_ERRORS_PANIC: sb.AppendLine("On errors, filesystem should panic"); break; default: sb.AppendFormat("On errors filesystem will do an unknown thing ({0})", supblk.err_behaviour). AppendLine(); break; } if (supblk.revision > 0) { sb.AppendFormat("Filesystem revision: {0}.{1}", supblk.revision, supblk.minor_revision).AppendLine(); } if (supblk.uuid != Guid.Empty) { sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine(); XmlFsType.VolumeSerial = supblk.uuid.ToString(); } if (supblk.kbytes_written > 0) { sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine(); } sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine(); XmlFsType.FreeClusters = free; XmlFsType.FreeClustersSpecified = true; sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes, (supblk.free_inodes * 100) / supblk.inodes).AppendLine(); if (supblk.first_inode > 0) { sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine(); } if (supblk.frag_size > 0) { sb.AppendFormat("{0} bytes per fragment", supblk.frag_size).AppendLine(); } if (supblk.blocks_per_grp > 0 && supblk.flags_per_grp > 0 && supblk.inodes_per_grp > 0) { sb.AppendFormat("{0} blocks, {1} flags and {2} inodes per group", supblk.blocks_per_grp, supblk.flags_per_grp, supblk.inodes_per_grp).AppendLine(); } if (supblk.first_block > 0) { sb.AppendFormat("{0} is first data block", supblk.first_block).AppendLine(); } sb.AppendFormat("Default UID: {0}, GID: {1}", supblk.default_uid, supblk.default_gid).AppendLine(); if (supblk.block_group_no > 0) { sb.AppendFormat("Block group number is {0}", supblk.block_group_no).AppendLine(); } if (supblk.desc_grp_size > 0) { sb.AppendFormat("Group descriptor size is {0} bytes", supblk.desc_grp_size).AppendLine(); } if (supblk.first_meta_bg > 0) { sb.AppendFormat("First metablock group is {0}", supblk.first_meta_bg).AppendLine(); } if (supblk.raid_stride > 0) { sb.AppendFormat("RAID stride: {0}", supblk.raid_stride).AppendLine(); } if (supblk.raid_stripe_width > 0) { sb.AppendFormat("{0} blocks on all data disks", supblk.raid_stripe_width).AppendLine(); } if (supblk.mmp_interval > 0 && supblk.mmp_block > 0) { sb.AppendFormat("{0} seconds for multi-mount protection wait, on block {1}", supblk.mmp_interval, supblk.mmp_block).AppendLine(); } if (supblk.flex_bg_grp_size > 0) { sb.AppendFormat("{0} Flexible block group size", supblk.flex_bg_grp_size).AppendLine(); } if (supblk.hash_seed_1 > 0 && supblk.hash_seed_2 > 0 && supblk.hash_seed_3 > 0 && supblk.hash_seed_4 > 0) { sb.AppendFormat("Hash seed: {0:X8}{1:X8}{2:X8}{3:X8}, version {4}", supblk.hash_seed_1, supblk.hash_seed_2, supblk.hash_seed_3, supblk.hash_seed_4, supblk.hash_version). AppendLine(); } if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL || (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { sb.AppendLine("Volume is journaled"); if (supblk.journal_uuid != Guid.Empty) { sb.AppendFormat("Journal UUID: {0}", supblk.journal_uuid).AppendLine(); } sb.AppendFormat("Journal has inode {0}", supblk.journal_inode).AppendLine(); if ((supblk.ftr_compat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV && supblk.journal_dev > 0) { sb.AppendFormat("Journal is on device {0}", supblk.journal_dev).AppendLine(); } if (supblk.jnl_backup_type > 0) { sb.AppendFormat("Journal backup type: {0}", supblk.jnl_backup_type).AppendLine(); } if (supblk.last_orphan > 0) { sb.AppendFormat("Last orphaned inode is {0}", supblk.last_orphan).AppendLine(); } else { sb.AppendLine("There are no orphaned inodes"); } } if (ext4) { if (supblk.snapshot_id > 0) { sb. AppendFormat("Active snapshot has ID {0}, on inode {1}, with {2} blocks reserved, list starting on block {3}", supblk.snapshot_id, supblk.snapshot_inum, supblk.snapshot_blocks, supblk.snapshot_list).AppendLine(); } if (supblk.error_count > 0) { sb.AppendFormat("{0} errors registered", supblk.error_count).AppendLine(); sb.AppendFormat("First error occurred on {0}, last on {1}", DateHandlers.UnixUnsignedToDateTime(supblk.first_error_t), DateHandlers.UnixUnsignedToDateTime(supblk.last_error_t)).AppendLine(); sb.AppendFormat("First error inode is {0}, last is {1}", supblk.first_error_inode, supblk.last_error_inode).AppendLine(); sb.AppendFormat("First error block is {0}, last is {1}", supblk.first_error_block, supblk.last_error_block).AppendLine(); sb.AppendFormat("First error function is \"{0}\", last is \"{1}\"", supblk.first_error_func, supblk.last_error_func).AppendLine(); } } sb.AppendFormat("Flags…:").AppendLine(); if ((supblk.flags & EXT2_FLAGS_SIGNED_HASH) == EXT2_FLAGS_SIGNED_HASH) { sb.AppendLine("Signed directory hash is in use"); } if ((supblk.flags & EXT2_FLAGS_UNSIGNED_HASH) == EXT2_FLAGS_UNSIGNED_HASH) { sb.AppendLine("Unsigned directory hash is in use"); } if ((supblk.flags & EXT2_FLAGS_TEST_FILESYS) == EXT2_FLAGS_TEST_FILESYS) { sb.AppendLine("Volume is testing development code"); } if ((supblk.flags & 0xFFFFFFF8) != 0) { sb.AppendFormat("Unknown set flags: {0:X8}", supblk.flags); } sb.AppendLine(); sb.AppendFormat("Default mount options…:").AppendLine(); if ((supblk.default_mnt_opts & EXT2_DEFM_DEBUG) == EXT2_DEFM_DEBUG) { sb.AppendLine("(debug): Enable debugging code"); } if ((supblk.default_mnt_opts & EXT2_DEFM_BSDGROUPS) == EXT2_DEFM_BSDGROUPS) { sb.AppendLine("(bsdgroups): Emulate BSD behaviour when creating new files"); } if ((supblk.default_mnt_opts & EXT2_DEFM_XATTR_USER) == EXT2_DEFM_XATTR_USER) { sb.AppendLine("(user_xattr): Enable user-specified extended attributes"); } if ((supblk.default_mnt_opts & EXT2_DEFM_ACL) == EXT2_DEFM_ACL) { sb.AppendLine("(acl): Enable POSIX ACLs"); } if ((supblk.default_mnt_opts & EXT2_DEFM_UID16) == EXT2_DEFM_UID16) { sb.AppendLine("(uid16): Disable 32bit UIDs and GIDs"); } if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_DATA) == EXT3_DEFM_JMODE_DATA) { sb.AppendLine("(journal_data): Journal data and metadata"); } if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_ORDERED) == EXT3_DEFM_JMODE_ORDERED) { sb.AppendLine("(journal_data_ordered): Write data before journaling metadata"); } if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_WBACK) == EXT3_DEFM_JMODE_WBACK) { sb.AppendLine("(journal_data_writeback): Write journal before data"); } if ((supblk.default_mnt_opts & 0xFFFFFE20) != 0) { sb.AppendFormat("Unknown set default mount options: {0:X8}", supblk.default_mnt_opts); } sb.AppendLine(); sb.AppendFormat("Compatible features…:").AppendLine(); if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_PREALLOC) == EXT2_FEATURE_COMPAT_DIR_PREALLOC) { sb.AppendLine("Pre-allocate directories"); } if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES) == EXT2_FEATURE_COMPAT_IMAGIC_INODES) { sb.AppendLine("imagic inodes ?"); } if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL) { sb.AppendLine("Has journal (ext3)"); } if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) == EXT2_FEATURE_COMPAT_EXT_ATTR) { sb.AppendLine("Has extended attribute blocks"); } if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) == EXT2_FEATURE_COMPAT_RESIZE_INO) { sb.AppendLine("Has online filesystem resize reservations"); } if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) == EXT2_FEATURE_COMPAT_DIR_INDEX) { sb.AppendLine("Can use hashed indexes on directories"); } if ((supblk.ftr_compat & 0xFFFFFFC0) != 0) { sb.AppendFormat("Unknown compatible features: {0:X8}", supblk.ftr_compat); } sb.AppendLine(); sb.AppendFormat("Compatible features if read-only…:").AppendLine(); if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) == EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) { sb.AppendLine("Reduced number of superblocks"); } if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == EXT2_FEATURE_RO_COMPAT_LARGE_FILE) { sb.AppendLine("Can have files bigger than 2GiB"); } if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_BTREE_DIR) == EXT2_FEATURE_RO_COMPAT_BTREE_DIR) { sb.AppendLine("Uses B-Tree for directories"); } if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE) { sb.AppendLine("Can have files bigger than 2TiB (ext4)"); } if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { sb.AppendLine("Group descriptor checksums and sparse inode table (ext4)"); } if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK) { sb.AppendLine("More than 32000 directory entries (ext4)"); } if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) { sb.AppendLine("Supports nanosecond timestamps and creation time (ext4)"); } if ((supblk.ftr_ro_compat & 0xFFFFFF80) != 0) { sb.AppendFormat("Unknown read-only compatible features: {0:X8}", supblk.ftr_ro_compat); } sb.AppendLine(); sb.AppendFormat("Incompatible features…:").AppendLine(); if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION) == EXT2_FEATURE_INCOMPAT_COMPRESSION) { sb.AppendLine("Uses compression"); } if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) == EXT2_FEATURE_INCOMPAT_FILETYPE) { sb.AppendLine("Filetype in directory entries"); } if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER) { sb.AppendLine("Journal needs recovery (ext3)"); } if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { sb.AppendLine("Has journal on another device (ext3)"); } if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_META_BG) == EXT2_FEATURE_INCOMPAT_META_BG) { sb.AppendLine("Reduced block group backups"); } if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS) == EXT4_FEATURE_INCOMPAT_EXTENTS) { sb.AppendLine("Volume use extents (ext4)"); } if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT) { sb.AppendLine("Supports volumes bigger than 2^32 blocks (ext4)"); } if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP) { sb.AppendLine("Multi-mount protection (ext4)"); } if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG) { sb.AppendLine("Flexible block group metadata location (ext4)"); } if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE) { sb.AppendLine("Extended attributes can reside in inode (ext4)"); } if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA) { sb.AppendLine("Data can reside in directory entry (ext4)"); } if ((supblk.ftr_incompat & 0xFFFFF020) != 0) { sb.AppendFormat("Unknown incompatible features: {0:X8}", supblk.ftr_incompat); } information = sb.ToString(); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sbInformation = new StringBuilder(); uint magic = 0; uint sb_size_in_sectors; byte[] ufs_sb_sectors; ulong sb_offset = partition.Start; bool fs_type_42bsd = false; bool fs_type_43bsd = false; bool fs_type_44bsd = false; bool fs_type_ufs = false; bool fs_type_ufs2 = false; bool fs_type_sun = false; bool fs_type_sun86 = false; if (imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448) { sb_size_in_sectors = block_size / 2048; } else { sb_size_in_sectors = block_size / imagePlugin.Info.SectorSize; } ulong[] locations = { sb_start_floppy, sb_start_boot, sb_start_long_boot, sb_start_piggy, sb_start_att_dsdd, 8192 / imagePlugin.Info.SectorSize, 65536 / imagePlugin.Info.SectorSize, 262144 / imagePlugin.Info.SectorSize }; foreach (ulong loc in locations.Where(loc => partition.End > partition.Start + loc + sb_size_in_sectors)) { ufs_sb_sectors = imagePlugin.ReadSectors(partition.Start + loc, sb_size_in_sectors); magic = BitConverter.ToUInt32(ufs_sb_sectors, 0x055C); if (magic == UFS_MAGIC || magic == UFS_CIGAM || magic == UFS_MAGIC_BW || magic == UFS_CIGAM_BW || magic == UFS2_MAGIC || magic == UFS2_CIGAM || magic == UFS_BAD_MAGIC || magic == UFS_BAD_CIGAM) { sb_offset = partition.Start + loc; break; } magic = 0; } if (magic == 0) { information = "Not a UFS filesystem, I shouldn't have arrived here!"; return; } XmlFsType = new FileSystemType(); switch (magic) { case UFS_MAGIC: sbInformation.AppendLine("UFS filesystem"); XmlFsType.Type = "UFS"; break; case UFS_CIGAM: sbInformation.AppendLine("Big-endian UFS filesystem"); XmlFsType.Type = "UFS"; break; case UFS_MAGIC_BW: sbInformation.AppendLine("BorderWare UFS filesystem"); XmlFsType.Type = "UFS"; break; case UFS_CIGAM_BW: sbInformation.AppendLine("Big-endian BorderWare UFS filesystem"); XmlFsType.Type = "UFS"; break; case UFS2_MAGIC: sbInformation.AppendLine("UFS2 filesystem"); XmlFsType.Type = "UFS2"; break; case UFS2_CIGAM: sbInformation.AppendLine("Big-endian UFS2 filesystem"); XmlFsType.Type = "UFS2"; break; case UFS_BAD_MAGIC: sbInformation.AppendLine("Incompletely initialized UFS filesystem"); sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); XmlFsType.Type = "UFS"; break; case UFS_BAD_CIGAM: sbInformation.AppendLine("Incompletely initialized big-endian UFS filesystem"); sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); XmlFsType.Type = "UFS"; break; } // Fun with seeking follows on superblock reading! ufs_sb_sectors = imagePlugin.ReadSectors(sb_offset, sb_size_in_sectors); SuperBlock sb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(ufs_sb_sectors); SuperBlock bs_sfu = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(ufs_sb_sectors); if ((bs_sfu.fs_magic == UFS_MAGIC && sb.fs_magic == UFS_CIGAM) || (bs_sfu.fs_magic == UFS_MAGIC_BW && sb.fs_magic == UFS_CIGAM_BW) || (bs_sfu.fs_magic == UFS2_MAGIC && sb.fs_magic == UFS2_CIGAM) || (bs_sfu.fs_magic == UFS_BAD_MAGIC && sb.fs_magic == UFS_BAD_CIGAM)) { sb = bs_sfu; sb.fs_old_cstotal.cs_nbfree = Swapping.Swap(sb.fs_old_cstotal.cs_nbfree); sb.fs_old_cstotal.cs_ndir = Swapping.Swap(sb.fs_old_cstotal.cs_ndir); sb.fs_old_cstotal.cs_nffree = Swapping.Swap(sb.fs_old_cstotal.cs_nffree); sb.fs_old_cstotal.cs_nifree = Swapping.Swap(sb.fs_old_cstotal.cs_nifree); sb.fs_cstotal.cs_numclusters = Swapping.Swap(sb.fs_cstotal.cs_numclusters); sb.fs_cstotal.cs_nbfree = Swapping.Swap(sb.fs_cstotal.cs_nbfree); sb.fs_cstotal.cs_ndir = Swapping.Swap(sb.fs_cstotal.cs_ndir); sb.fs_cstotal.cs_nffree = Swapping.Swap(sb.fs_cstotal.cs_nffree); sb.fs_cstotal.cs_nifree = Swapping.Swap(sb.fs_cstotal.cs_nifree); sb.fs_cstotal.cs_spare[0] = Swapping.Swap(sb.fs_cstotal.cs_spare[0]); sb.fs_cstotal.cs_spare[1] = Swapping.Swap(sb.fs_cstotal.cs_spare[1]); sb.fs_cstotal.cs_spare[2] = Swapping.Swap(sb.fs_cstotal.cs_spare[2]); } AaruConsole.DebugWriteLine("FFS plugin", "sb offset: 0x{0:X8}", sb_offset); AaruConsole.DebugWriteLine("FFS plugin", "fs_rlink: 0x{0:X8}", sb.fs_rlink); AaruConsole.DebugWriteLine("FFS plugin", "fs_sblkno: 0x{0:X8}", sb.fs_sblkno); AaruConsole.DebugWriteLine("FFS plugin", "fs_cblkno: 0x{0:X8}", sb.fs_cblkno); AaruConsole.DebugWriteLine("FFS plugin", "fs_iblkno: 0x{0:X8}", sb.fs_iblkno); AaruConsole.DebugWriteLine("FFS plugin", "fs_dblkno: 0x{0:X8}", sb.fs_dblkno); AaruConsole.DebugWriteLine("FFS plugin", "fs_size: 0x{0:X8}", sb.fs_size); AaruConsole.DebugWriteLine("FFS plugin", "fs_dsize: 0x{0:X8}", sb.fs_dsize); AaruConsole.DebugWriteLine("FFS plugin", "fs_ncg: 0x{0:X8}", sb.fs_ncg); AaruConsole.DebugWriteLine("FFS plugin", "fs_bsize: 0x{0:X8}", sb.fs_bsize); AaruConsole.DebugWriteLine("FFS plugin", "fs_fsize: 0x{0:X8}", sb.fs_fsize); AaruConsole.DebugWriteLine("FFS plugin", "fs_frag: 0x{0:X8}", sb.fs_frag); AaruConsole.DebugWriteLine("FFS plugin", "fs_minfree: 0x{0:X8}", sb.fs_minfree); AaruConsole.DebugWriteLine("FFS plugin", "fs_bmask: 0x{0:X8}", sb.fs_bmask); AaruConsole.DebugWriteLine("FFS plugin", "fs_fmask: 0x{0:X8}", sb.fs_fmask); AaruConsole.DebugWriteLine("FFS plugin", "fs_bshift: 0x{0:X8}", sb.fs_bshift); AaruConsole.DebugWriteLine("FFS plugin", "fs_fshift: 0x{0:X8}", sb.fs_fshift); AaruConsole.DebugWriteLine("FFS plugin", "fs_maxcontig: 0x{0:X8}", sb.fs_maxcontig); AaruConsole.DebugWriteLine("FFS plugin", "fs_maxbpg: 0x{0:X8}", sb.fs_maxbpg); AaruConsole.DebugWriteLine("FFS plugin", "fs_fragshift: 0x{0:X8}", sb.fs_fragshift); AaruConsole.DebugWriteLine("FFS plugin", "fs_fsbtodb: 0x{0:X8}", sb.fs_fsbtodb); AaruConsole.DebugWriteLine("FFS plugin", "fs_sbsize: 0x{0:X8}", sb.fs_sbsize); AaruConsole.DebugWriteLine("FFS plugin", "fs_csmask: 0x{0:X8}", sb.fs_csmask); AaruConsole.DebugWriteLine("FFS plugin", "fs_csshift: 0x{0:X8}", sb.fs_csshift); AaruConsole.DebugWriteLine("FFS plugin", "fs_nindir: 0x{0:X8}", sb.fs_nindir); AaruConsole.DebugWriteLine("FFS plugin", "fs_inopb: 0x{0:X8}", sb.fs_inopb); AaruConsole.DebugWriteLine("FFS plugin", "fs_optim: 0x{0:X8}", sb.fs_optim); AaruConsole.DebugWriteLine("FFS plugin", "fs_id_1: 0x{0:X8}", sb.fs_id_1); AaruConsole.DebugWriteLine("FFS plugin", "fs_id_2: 0x{0:X8}", sb.fs_id_2); AaruConsole.DebugWriteLine("FFS plugin", "fs_csaddr: 0x{0:X8}", sb.fs_csaddr); AaruConsole.DebugWriteLine("FFS plugin", "fs_cssize: 0x{0:X8}", sb.fs_cssize); AaruConsole.DebugWriteLine("FFS plugin", "fs_cgsize: 0x{0:X8}", sb.fs_cgsize); AaruConsole.DebugWriteLine("FFS plugin", "fs_ipg: 0x{0:X8}", sb.fs_ipg); AaruConsole.DebugWriteLine("FFS plugin", "fs_fpg: 0x{0:X8}", sb.fs_fpg); AaruConsole.DebugWriteLine("FFS plugin", "fs_fmod: 0x{0:X2}", sb.fs_fmod); AaruConsole.DebugWriteLine("FFS plugin", "fs_clean: 0x{0:X2}", sb.fs_clean); AaruConsole.DebugWriteLine("FFS plugin", "fs_ronly: 0x{0:X2}", sb.fs_ronly); AaruConsole.DebugWriteLine("FFS plugin", "fs_flags: 0x{0:X2}", sb.fs_flags); AaruConsole.DebugWriteLine("FFS plugin", "fs_magic: 0x{0:X8}", sb.fs_magic); if (sb.fs_magic == UFS2_MAGIC) { fs_type_ufs2 = true; } else { const uint SunOSEpoch = 0x1A54C580; // We are supposing there cannot be a Sun's fs created before 1/1/1982 00:00:00 fs_type_43bsd = true; // There is no way of knowing this is the version, but there is of knowing it is not. if (sb.fs_link > 0) { fs_type_42bsd = true; // It was used in 4.2BSD fs_type_43bsd = false; } if ((sb.fs_maxfilesize & 0xFFFFFFFF) > SunOSEpoch && DateHandlers.UnixUnsignedToDateTime(sb.fs_maxfilesize & 0xFFFFFFFF) < DateTime.Now) { fs_type_42bsd = false; fs_type_sun = true; fs_type_43bsd = false; } // This is for sure, as it is shared with a sectors/track with non-x86 SunOS, Epoch is absurdly high for that if (sb.fs_old_npsect > SunOSEpoch && DateHandlers.UnixToDateTime(sb.fs_old_npsect) < DateTime.Now) { fs_type_42bsd = false; fs_type_sun86 = true; fs_type_sun = false; fs_type_43bsd = false; } if (sb.fs_cgrotor > 0x00000000 && (uint)sb.fs_cgrotor < 0xFFFFFFFF) { fs_type_42bsd = false; fs_type_sun = false; fs_type_sun86 = false; fs_type_ufs = true; fs_type_43bsd = false; } // 4.3BSD code does not use these fields, they are always set up to 0 fs_type_43bsd &= sb.fs_id_2 == 0 && sb.fs_id_1 == 0; // This is the only 4.4BSD inode format fs_type_44bsd |= sb.fs_old_inodefmt == 2; } if (!fs_type_ufs2) { sbInformation.AppendLine("There are a lot of variants of UFS using overlapped values on same fields"); sbInformation. AppendLine("I will try to guess which one it is, but unless it's UFS2, I may be surely wrong"); } if (fs_type_42bsd) { sbInformation.AppendLine("Guessed as 42BSD FFS"); } if (fs_type_43bsd) { sbInformation.AppendLine("Guessed as 43BSD FFS"); } if (fs_type_44bsd) { sbInformation.AppendLine("Guessed as 44BSD FFS"); } if (fs_type_sun) { sbInformation.AppendLine("Guessed as SunOS FFS"); } if (fs_type_sun86) { sbInformation.AppendLine("Guessed as SunOS/x86 FFS"); } if (fs_type_ufs) { sbInformation.AppendLine("Guessed as UFS"); } if (fs_type_42bsd) { sbInformation.AppendFormat("Linked list of filesystems: 0x{0:X8}", sb.fs_link).AppendLine(); } sbInformation.AppendFormat("Superblock LBA: {0}", sb.fs_sblkno).AppendLine(); sbInformation.AppendFormat("Cylinder-block LBA: {0}", sb.fs_cblkno).AppendLine(); sbInformation.AppendFormat("inode-block LBA: {0}", sb.fs_iblkno).AppendLine(); sbInformation.AppendFormat("First data block LBA: {0}", sb.fs_dblkno).AppendLine(); sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", sb.fs_old_cgoffset).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(sb.fs_old_time)). AppendLine(); XmlFsType.ModificationDate = DateHandlers.UnixToDateTime(sb.fs_old_time); XmlFsType.ModificationDateSpecified = true; sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", sb.fs_old_size, (long)sb.fs_old_size * sb.fs_fsize).AppendLine(); XmlFsType.Clusters = (ulong)sb.fs_old_size; XmlFsType.ClusterSize = (uint)sb.fs_fsize; sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", sb.fs_old_dsize, (long)sb.fs_old_dsize * sb.fs_fsize).AppendLine(); sbInformation.AppendFormat("{0} cylinder groups in volume", sb.fs_ncg).AppendLine(); sbInformation.AppendFormat("{0} bytes in a basic block", sb.fs_bsize).AppendLine(); sbInformation.AppendFormat("{0} bytes in a frag block", sb.fs_fsize).AppendLine(); sbInformation.AppendFormat("{0} frags in a block", sb.fs_frag).AppendLine(); sbInformation.AppendFormat("{0}% of blocks must be free", sb.fs_minfree).AppendLine(); sbInformation.AppendFormat("{0}ms for optimal next block", sb.fs_old_rotdelay).AppendLine(); sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", sb.fs_old_rps, sb.fs_old_rps * 60). AppendLine(); /* sbInformation.AppendFormat("fs_bmask: 0x{0:X8}", sb.fs_bmask).AppendLine(); * sbInformation.AppendFormat("fs_fmask: 0x{0:X8}", sb.fs_fmask).AppendLine(); * sbInformation.AppendFormat("fs_bshift: 0x{0:X8}", sb.fs_bshift).AppendLine(); * sbInformation.AppendFormat("fs_fshift: 0x{0:X8}", sb.fs_fshift).AppendLine();*/ sbInformation.AppendFormat("{0} contiguous blocks at maximum", sb.fs_maxcontig).AppendLine(); sbInformation.AppendFormat("{0} blocks per cylinder group at maximum", sb.fs_maxbpg).AppendLine(); sbInformation.AppendFormat("Superblock is {0} bytes", sb.fs_sbsize).AppendLine(); sbInformation.AppendFormat("NINDIR: 0x{0:X8}", sb.fs_nindir).AppendLine(); sbInformation.AppendFormat("INOPB: 0x{0:X8}", sb.fs_inopb).AppendLine(); sbInformation.AppendFormat("NSPF: 0x{0:X8}", sb.fs_old_nspf).AppendLine(); switch (sb.fs_optim) { case 0: sbInformation.AppendLine("Filesystem will minimize allocation time"); break; case 1: sbInformation.AppendLine("Filesystem will minimize volume fragmentation"); break; default: sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", sb.fs_optim).AppendLine(); break; } if (fs_type_sun) { sbInformation.AppendFormat("{0} sectors/track", sb.fs_old_npsect).AppendLine(); } else if (fs_type_sun86) { sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(sb.fs_old_npsect)). AppendLine(); } sbInformation.AppendFormat("Hardware sector interleave: {0}", sb.fs_old_interleave).AppendLine(); sbInformation.AppendFormat("Sector 0 skew: {0}/track", sb.fs_old_trackskew).AppendLine(); if (!fs_type_43bsd && sb.fs_id_1 > 0 && sb.fs_id_2 > 0) { sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", sb.fs_id_1, sb.fs_id_2).AppendLine(); } else if (fs_type_43bsd && sb.fs_id_1 > 0 && sb.fs_id_2 > 0) { sbInformation.AppendFormat("{0} µsec for head switch", sb.fs_id_1).AppendLine(); sbInformation.AppendFormat("{0} µsec for track-to-track seek", sb.fs_id_2).AppendLine(); } sbInformation.AppendFormat("Cylinder group summary LBA: {0}", sb.fs_old_csaddr).AppendLine(); sbInformation.AppendFormat("{0} bytes in cylinder group summary", sb.fs_cssize).AppendLine(); sbInformation.AppendFormat("{0} bytes in cylinder group", sb.fs_cgsize).AppendLine(); sbInformation.AppendFormat("{0} tracks/cylinder", sb.fs_old_ntrak).AppendLine(); sbInformation.AppendFormat("{0} sectors/track", sb.fs_old_nsect).AppendLine(); sbInformation.AppendFormat("{0} sectors/cylinder", sb.fs_old_spc).AppendLine(); sbInformation.AppendFormat("{0} cylinder in volume", sb.fs_old_ncyl).AppendLine(); sbInformation.AppendFormat("{0} cylinders/group", sb.fs_old_cpg).AppendLine(); sbInformation.AppendFormat("{0} inodes per cylinder group", sb.fs_ipg).AppendLine(); sbInformation.AppendFormat("{0} blocks per group", sb.fs_fpg / sb.fs_frag).AppendLine(); sbInformation.AppendFormat("{0} directories", sb.fs_old_cstotal.cs_ndir).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", sb.fs_old_cstotal.cs_nbfree, (long)sb.fs_old_cstotal.cs_nbfree * sb.fs_fsize).AppendLine(); XmlFsType.FreeClusters = (ulong)sb.fs_old_cstotal.cs_nbfree; XmlFsType.FreeClustersSpecified = true; sbInformation.AppendFormat("{0} free inodes", sb.fs_old_cstotal.cs_nifree).AppendLine(); sbInformation.AppendFormat("{0} free frags", sb.fs_old_cstotal.cs_nffree).AppendLine(); if (sb.fs_fmod == 1) { sbInformation.AppendLine("Superblock is under modification"); XmlFsType.Dirty = true; } if (sb.fs_clean == 1) { sbInformation.AppendLine("Volume is clean"); } if (sb.fs_ronly == 1) { sbInformation.AppendLine("Volume is read-only"); } sbInformation.AppendFormat("Volume flags: 0x{0:X2}", sb.fs_flags).AppendLine(); if (fs_type_ufs) { sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(sb.fs_fsmnt)). AppendLine(); } else if (fs_type_ufs2) { sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(sb.fs_fsmnt)). AppendLine(); sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(sb.fs_volname)). AppendLine(); XmlFsType.VolumeName = StringHandlers.CToString(sb.fs_volname); sbInformation.AppendFormat("Volume ID: 0x{0:X16}", sb.fs_swuid).AppendLine(); //xmlFSType.VolumeSerial = string.Format("{0:X16}", sb.fs_swuid); sbInformation.AppendFormat("Last searched cylinder group: {0}", sb.fs_cgrotor).AppendLine(); sbInformation.AppendFormat("{0} contiguously allocated directories", sb.fs_contigdirs).AppendLine(); sbInformation.AppendFormat("Standard superblock LBA: {0}", sb.fs_sblkno).AppendLine(); sbInformation.AppendFormat("{0} directories", sb.fs_cstotal.cs_ndir).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", sb.fs_cstotal.cs_nbfree, sb.fs_cstotal.cs_nbfree * sb.fs_fsize).AppendLine(); XmlFsType.FreeClusters = (ulong)sb.fs_cstotal.cs_nbfree; XmlFsType.FreeClustersSpecified = true; sbInformation.AppendFormat("{0} free inodes", sb.fs_cstotal.cs_nifree).AppendLine(); sbInformation.AppendFormat("{0} free frags", sb.fs_cstotal.cs_nffree).AppendLine(); sbInformation.AppendFormat("{0} free clusters", sb.fs_cstotal.cs_numclusters).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(sb.fs_time)). AppendLine(); XmlFsType.ModificationDate = DateHandlers.UnixToDateTime(sb.fs_time); XmlFsType.ModificationDateSpecified = true; sbInformation.AppendFormat("{0} blocks ({1} bytes)", sb.fs_size, sb.fs_size * sb.fs_fsize).AppendLine(); XmlFsType.Clusters = (ulong)sb.fs_size; sbInformation.AppendFormat("{0} data blocks ({1} bytes)", sb.fs_dsize, sb.fs_dsize * sb.fs_fsize). AppendLine(); sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", sb.fs_csaddr).AppendLine(); sbInformation.AppendFormat("{0} blocks pending of being freed", sb.fs_pendingblocks).AppendLine(); sbInformation.AppendFormat("{0} inodes pending of being freed", sb.fs_pendinginodes).AppendLine(); } if (fs_type_sun) { sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(sb.fs_old_npsect)). AppendLine(); } else if (fs_type_sun86) { sbInformation.AppendFormat("{0} sectors/track", sb.fs_state).AppendLine(); } else if (fs_type_44bsd) { sbInformation.AppendFormat("{0} blocks on cluster summary array", sb.fs_contigsumsize).AppendLine(); sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", sb.fs_maxsymlinklen).AppendLine(); sbInformation.AppendFormat("A file can be {0} bytes at max", sb.fs_maxfilesize).AppendLine(); sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(sb.fs_state)). AppendLine(); } if (sb.fs_old_nrpos > 0) { sbInformation.AppendFormat("{0} rotational positions", sb.fs_old_nrpos).AppendLine(); } if (sb.fs_old_rotbloff > 0) { sbInformation.AppendFormat("{0} blocks per rotation", sb.fs_old_rotbloff).AppendLine(); } information = sbInformation.ToString(); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); var sbInformation = new StringBuilder(); XmlFsType = new FileSystemType(); information = ""; ulong sbSectorOff = 0x10000 / imagePlugin.Info.SectorSize; uint sbSectorSize = 0x1000 / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSectorSize); SuperBlock btrfsSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.checksum = {0}", btrfsSb.checksum); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.uuid = {0}", btrfsSb.uuid); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.pba = {0}", btrfsSb.pba); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.flags = {0}", btrfsSb.flags); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.magic = {0}", btrfsSb.magic); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.generation = {0}", btrfsSb.generation); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.root_lba = {0}", btrfsSb.root_lba); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.chunk_lba = {0}", btrfsSb.chunk_lba); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.log_lba = {0}", btrfsSb.log_lba); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.log_root_transid = {0}", btrfsSb.log_root_transid); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.total_bytes = {0}", btrfsSb.total_bytes); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.bytes_used = {0}", btrfsSb.bytes_used); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.root_dir_objectid = {0}", btrfsSb.root_dir_objectid); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.num_devices = {0}", btrfsSb.num_devices); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.sectorsize = {0}", btrfsSb.sectorsize); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.nodesize = {0}", btrfsSb.nodesize); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.leafsize = {0}", btrfsSb.leafsize); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.stripesize = {0}", btrfsSb.stripesize); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.n = {0}", btrfsSb.n); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.chunk_root_generation = {0}", btrfsSb.chunk_root_generation); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.compat_flags = 0x{0:X16}", btrfsSb.compat_flags); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.compat_ro_flags = 0x{0:X16}", btrfsSb.compat_ro_flags); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.incompat_flags = 0x{0:X16}", btrfsSb.incompat_flags); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.csum_type = {0}", btrfsSb.csum_type); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.root_level = {0}", btrfsSb.root_level); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.chunk_root_level = {0}", btrfsSb.chunk_root_level); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.log_root_level = {0}", btrfsSb.log_root_level); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.id = 0x{0:X16}", btrfsSb.dev_item.id); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.bytes = {0}", btrfsSb.dev_item.bytes); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.used = {0}", btrfsSb.dev_item.used); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.optimal_align = {0}", btrfsSb.dev_item.optimal_align); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.optimal_width = {0}", btrfsSb.dev_item.optimal_width); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.minimal_size = {0}", btrfsSb.dev_item.minimal_size); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.type = {0}", btrfsSb.dev_item.type); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.generation = {0}", btrfsSb.dev_item.generation); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.start_offset = {0}", btrfsSb.dev_item.start_offset); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.dev_group = {0}", btrfsSb.dev_item.dev_group); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.seek_speed = {0}", btrfsSb.dev_item.seek_speed); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.bandwitdh = {0}", btrfsSb.dev_item.bandwitdh); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.device_uuid = {0}", btrfsSb.dev_item.device_uuid); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.uuid = {0}", btrfsSb.dev_item.uuid); AaruConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.label = {0}", btrfsSb.label); sbInformation.AppendLine("B-tree filesystem"); sbInformation.AppendFormat("UUID: {0}", btrfsSb.uuid).AppendLine(); sbInformation.AppendFormat("This superblock resides on physical block {0}", btrfsSb.pba).AppendLine(); sbInformation.AppendFormat("Root tree starts at LBA {0}", btrfsSb.root_lba).AppendLine(); sbInformation.AppendFormat("Chunk tree starts at LBA {0}", btrfsSb.chunk_lba).AppendLine(); sbInformation.AppendFormat("Log tree starts at LBA {0}", btrfsSb.log_lba).AppendLine(); sbInformation.AppendFormat("Volume has {0} bytes spanned in {1} devices", btrfsSb.total_bytes, btrfsSb.num_devices).AppendLine(); sbInformation.AppendFormat("Volume has {0} bytes used", btrfsSb.bytes_used).AppendLine(); sbInformation.AppendFormat("{0} bytes/sector", btrfsSb.sectorsize).AppendLine(); sbInformation.AppendFormat("{0} bytes/node", btrfsSb.nodesize).AppendLine(); sbInformation.AppendFormat("{0} bytes/leaf", btrfsSb.leafsize).AppendLine(); sbInformation.AppendFormat("{0} bytes/stripe", btrfsSb.stripesize).AppendLine(); sbInformation.AppendFormat("Flags: 0x{0:X}", btrfsSb.flags).AppendLine(); sbInformation.AppendFormat("Compatible flags: 0x{0:X}", btrfsSb.compat_flags).AppendLine(); sbInformation.AppendFormat("Read-only compatible flags: 0x{0:X}", btrfsSb.compat_ro_flags).AppendLine(); sbInformation.AppendFormat("Incompatible flags: 0x{0:X}", btrfsSb.incompat_flags).AppendLine(); sbInformation.AppendFormat("Device's UUID: {0}", btrfsSb.dev_item.uuid).AppendLine(); sbInformation.AppendFormat("Volume label: {0}", btrfsSb.label).AppendLine(); information = sbInformation.ToString(); XmlFsType = new FileSystemType { Clusters = btrfsSb.total_bytes / btrfsSb.sectorsize, ClusterSize = btrfsSb.sectorsize, FreeClustersSpecified = true, VolumeName = btrfsSb.label, VolumeSerial = $"{btrfsSb.uuid}", VolumeSetIdentifier = $"{btrfsSb.dev_item.device_uuid}", Type = Name }; XmlFsType.FreeClusters = XmlFsType.Clusters - (btrfsSb.bytes_used / btrfsSb.sectorsize); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sb = new StringBuilder(); ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.Info.SectorSize; uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.Info.SectorSize; uint run = 1; if (imagePlugin.Info.SectorSize < AFS_SUPERBLOCK_SIZE) { run = AFS_SUPERBLOCK_SIZE / imagePlugin.Info.SectorSize; } byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run); byte[] sbSector = new byte[AFS_SUPERBLOCK_SIZE]; Array.Copy(tmp, offset, sbSector, 0, AFS_SUPERBLOCK_SIZE); SuperBlock afsSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sbSector); sb.AppendLine("Atheos filesystem"); if (afsSb.flags == 1) { sb.AppendLine("Filesystem is read-only"); } sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(afsSb.name, Encoding)).AppendLine(); sb.AppendFormat("{0} bytes per block", afsSb.block_size).AppendLine(); sb.AppendFormat("{0} blocks in volume ({1} bytes)", afsSb.num_blocks, afsSb.num_blocks * afsSb.block_size). AppendLine(); sb.AppendFormat("{0} used blocks ({1} bytes)", afsSb.used_blocks, afsSb.used_blocks * afsSb.block_size). AppendLine(); sb.AppendFormat("{0} bytes per i-node", afsSb.inode_size).AppendLine(); sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", afsSb.blocks_per_ag, afsSb.blocks_per_ag * afsSb.block_size).AppendLine(); sb.AppendFormat("{0} allocation groups in volume", afsSb.num_ags).AppendLine(); sb.AppendFormat("Journal resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", afsSb.log_blocks_start, afsSb.log_blocks_ag, afsSb.log_blocks_len, afsSb.log_blocks_len * afsSb.block_size).AppendLine(); sb.AppendFormat("Journal starts in byte {0} and has {1} bytes in {2} blocks", afsSb.log_start, afsSb.log_size, afsSb.log_valid_blocks).AppendLine(); sb. AppendFormat("Root folder's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", afsSb.root_dir_start, afsSb.root_dir_ag, afsSb.root_dir_len, afsSb.root_dir_len * afsSb.block_size).AppendLine(); sb. AppendFormat("Directory containing files scheduled for deletion's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", afsSb.deleted_start, afsSb.deleted_ag, afsSb.deleted_len, afsSb.deleted_len * afsSb.block_size).AppendLine(); sb. AppendFormat("Indices' i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", afsSb.indices_start, afsSb.indices_ag, afsSb.indices_len, afsSb.indices_len * afsSb.block_size).AppendLine(); sb.AppendFormat("{0} blocks for bootloader ({1} bytes)", afsSb.boot_size, afsSb.boot_size * afsSb.block_size).AppendLine(); information = sb.ToString(); XmlFsType = new FileSystemType { Clusters = (ulong)afsSb.num_blocks, ClusterSize = afsSb.block_size, Dirty = false, FreeClusters = (ulong)(afsSb.num_blocks - afsSb.used_blocks), FreeClustersSpecified = true, Type = "AtheOS filesystem", VolumeName = StringHandlers.CToString(afsSb.name, Encoding) }; }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sb = new StringBuilder(); uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors); if (sector.Length < 512) { return; } SuperBlock jfsSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); sb.AppendLine("JFS filesystem"); sb.AppendFormat("Version {0}", jfsSb.s_version).AppendLine(); sb.AppendFormat("{0} blocks of {1} bytes", jfsSb.s_size, jfsSb.s_bsize).AppendLine(); sb.AppendFormat("{0} blocks per allocation group", jfsSb.s_agsize).AppendLine(); if (jfsSb.s_flags.HasFlag(Flags.Unicode)) { sb.AppendLine("Volume uses Unicode for directory entries"); } if (jfsSb.s_flags.HasFlag(Flags.RemountRO)) { sb.AppendLine("Volume remounts read-only on error"); } if (jfsSb.s_flags.HasFlag(Flags.Continue)) { sb.AppendLine("Volume continues on error"); } if (jfsSb.s_flags.HasFlag(Flags.Panic)) { sb.AppendLine("Volume panics on error"); } if (jfsSb.s_flags.HasFlag(Flags.UserQuota)) { sb.AppendLine("Volume has user quotas enabled"); } if (jfsSb.s_flags.HasFlag(Flags.GroupQuota)) { sb.AppendLine("Volume has group quotas enabled"); } if (jfsSb.s_flags.HasFlag(Flags.NoJournal)) { sb.AppendLine("Volume is not using any journal"); } if (jfsSb.s_flags.HasFlag(Flags.Discard)) { sb.AppendLine("Volume sends TRIM/UNMAP commands to underlying device"); } if (jfsSb.s_flags.HasFlag(Flags.GroupCommit)) { sb.AppendLine("Volume commits in groups of 1"); } if (jfsSb.s_flags.HasFlag(Flags.LazyCommit)) { sb.AppendLine("Volume commits lazy"); } if (jfsSb.s_flags.HasFlag(Flags.Temporary)) { sb.AppendLine("Volume does not commit to log"); } if (jfsSb.s_flags.HasFlag(Flags.InlineLog)) { sb.AppendLine("Volume has log withing itself"); } if (jfsSb.s_flags.HasFlag(Flags.InlineMoving)) { sb.AppendLine("Volume has log withing itself and is moving it out"); } if (jfsSb.s_flags.HasFlag(Flags.BadSAIT)) { sb.AppendLine("Volume has bad current secondary ait"); } if (jfsSb.s_flags.HasFlag(Flags.Sparse)) { sb.AppendLine("Volume supports sparse files"); } if (jfsSb.s_flags.HasFlag(Flags.DASDEnabled)) { sb.AppendLine("Volume has DASD limits enabled"); } if (jfsSb.s_flags.HasFlag(Flags.DASDPrime)) { sb.AppendLine("Volume primes DASD on boot"); } if (jfsSb.s_flags.HasFlag(Flags.SwapBytes)) { sb.AppendLine("Volume is in a big-endian system"); } if (jfsSb.s_flags.HasFlag(Flags.DirIndex)) { sb.AppendLine("Volume has presistent indexes"); } if (jfsSb.s_flags.HasFlag(Flags.Linux)) { sb.AppendLine("Volume supports Linux"); } if (jfsSb.s_flags.HasFlag(Flags.DFS)) { sb.AppendLine("Volume supports DCE DFS LFS"); } if (jfsSb.s_flags.HasFlag(Flags.OS2)) { sb.AppendLine("Volume supports OS/2, and is case insensitive"); } if (jfsSb.s_flags.HasFlag(Flags.AIX)) { sb.AppendLine("Volume supports AIX"); } if (jfsSb.s_state != 0) { sb.AppendLine("Volume is dirty"); } sb.AppendFormat("Volume was last updated on {0}", DateHandlers.UnixUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec)). AppendLine(); if (jfsSb.s_version == 1) { sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(jfsSb.s_fpack, Encoding)).AppendLine(); } else { sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(jfsSb.s_label, Encoding)).AppendLine(); } sb.AppendFormat("Volume UUID: {0}", jfsSb.s_uuid).AppendLine(); XmlFsType = new FileSystemType { Type = "JFS filesystem", Clusters = jfsSb.s_size, ClusterSize = jfsSb.s_bsize, Bootable = true, VolumeName = StringHandlers.CToString(jfsSb.s_version == 1 ? jfsSb.s_fpack : jfsSb.s_label, Encoding), VolumeSerial = $"{jfsSb.s_uuid}", ModificationDate = DateHandlers.UnixUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec), ModificationDateSpecified = true }; if (jfsSb.s_state != 0) { XmlFsType.Dirty = true; } information = sb.ToString(); }
private void Initialize() { Console.WriteLine("Start Ext2.Initialize"); mBuffer = new byte[mBackend.BlockSize]; fixed(byte *xBufferAddress = &mBuffer[0]) { mBufferAddress = xBufferAddress; } // first get the superblock; var mBufferAsSuperblock = (SuperBlock *)mBufferAddress; int xAddr = (int)mBufferAddress; Console.WriteLine("Buffer address: " + xAddr); Console.WriteLine("Start reading superblock"); mBackend.ReadBlock(2, mBuffer); Console.WriteLine("End reading"); mSuperblock = *mBufferAsSuperblock; DebugUtil.Send_Ext2SuperBlock(mSuperblock); // read the group descriptors Console.WriteLine("INodeCount: " + mSuperblock.INodesCount); Console.WriteLine("INode#1: " + mBufferAddress[0]); Console.WriteLine("INode#2: " + mBufferAddress[1]); Console.WriteLine("INode#3: " + mBufferAddress[2]); Console.WriteLine("INode#4: " + mBufferAddress[3]); Console.WriteLine("BlockCount: " + mSuperblock.BlockCount); Console.WriteLine("INodesPerGroup: " + (int)mSuperblock.INodesPerGroup); if (mSuperblock.INodesPerGroup == 0x4000) { Console.WriteLine("INodesPerGroup has correct value!"); } uint xGroupDescriptorCount = mSuperblock.INodesCount / mSuperblock.INodesPerGroup; mGroupDescriptors = new GroupDescriptor[xGroupDescriptorCount]; var xDescriptorPtr = (GroupDescriptor *)mBufferAddress; Console.WriteLine("Process GroupDescriptors: " + xGroupDescriptorCount); //Console.ReadLine(); for (int i = 0; i < xGroupDescriptorCount; i++) { Console.WriteLine("Processing GroupDescriptor " + i); uint xATABlock; if (BlockSize == 1024) { xATABlock = (BlockSize * 2) / mBackend.BlockSize; } else { xATABlock = (BlockSize) / mBackend.BlockSize; } xATABlock += (uint)(i / 16); if ((i % 16) == 0) { Console.WriteLine("Read new GroupDescriptorBlock"); mBackend.ReadBlock(xATABlock, mBuffer); Console.WriteLine("End Read"); } mGroupDescriptors[i] = xDescriptorPtr[i % 16]; Console.WriteLine("End of GroupDescriptor check"); } Console.WriteLine("Send GroupDescriptors to log"); DebugUtil.Send_Ext2GroupDescriptors(mGroupDescriptors); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sb = new StringBuilder(); uint sector = 2; uint offset = 0; if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) { sector = 0; offset = 0x400; } bool minix3 = false; int filenamesize; string minixVersion; byte[] minixSbSector = imagePlugin.ReadSector(sector + partition.Start); // Optical media if (offset > 0) { byte[] tmp = new byte[0x200]; Array.Copy(minixSbSector, offset, tmp, 0, 0x200); minixSbSector = tmp; } ushort magic = BitConverter.ToUInt16(minixSbSector, 0x018); XmlFsType = new FileSystemType(); bool littleEndian; if (magic == MINIX3_MAGIC || magic == MINIX3_CIGAM || magic == MINIX2_MAGIC || magic == MINIX2_CIGAM || magic == MINIX_MAGIC || magic == MINIX_CIGAM) { filenamesize = 60; littleEndian = magic != MINIX3_CIGAM || magic == MINIX2_CIGAM || magic == MINIX_CIGAM; switch (magic) { case MINIX3_MAGIC: case MINIX3_CIGAM: minixVersion = "Minix v3 filesystem"; XmlFsType.Type = "Minix v3"; break; case MINIX2_MAGIC: case MINIX2_CIGAM: minixVersion = "Minix 3 v2 filesystem"; XmlFsType.Type = "Minix 3 v2"; break; default: minixVersion = "Minix 3 v1 filesystem"; XmlFsType.Type = "Minix 3 v1"; break; } minix3 = true; } else { magic = BitConverter.ToUInt16(minixSbSector, 0x010); switch (magic) { case MINIX_MAGIC: filenamesize = 14; minixVersion = "Minix v1 filesystem"; littleEndian = true; XmlFsType.Type = "Minix v1"; break; case MINIX_MAGIC2: filenamesize = 30; minixVersion = "Minix v1 filesystem"; littleEndian = true; XmlFsType.Type = "Minix v1"; break; case MINIX2_MAGIC: filenamesize = 14; minixVersion = "Minix v2 filesystem"; littleEndian = true; XmlFsType.Type = "Minix v2"; break; case MINIX2_MAGIC2: filenamesize = 30; minixVersion = "Minix v2 filesystem"; littleEndian = true; XmlFsType.Type = "Minix v2"; break; case MINIX_CIGAM: filenamesize = 14; minixVersion = "Minix v1 filesystem"; littleEndian = false; XmlFsType.Type = "Minix v1"; break; case MINIX_CIGAM2: filenamesize = 30; minixVersion = "Minix v1 filesystem"; littleEndian = false; XmlFsType.Type = "Minix v1"; break; case MINIX2_CIGAM: filenamesize = 14; minixVersion = "Minix v2 filesystem"; littleEndian = false; XmlFsType.Type = "Minix v2"; break; case MINIX2_CIGAM2: filenamesize = 30; minixVersion = "Minix v2 filesystem"; littleEndian = false; XmlFsType.Type = "Minix v2"; break; default: return; } } if (minix3) { SuperBlock3 mnxSb = littleEndian ? Marshal.ByteArrayToStructureLittleEndian <SuperBlock3>(minixSbSector) : Marshal.ByteArrayToStructureBigEndian <SuperBlock3>(minixSbSector); if (magic != MINIX3_MAGIC && magic != MINIX3_CIGAM) { mnxSb.s_blocksize = 1024; } sb.AppendLine(minixVersion); sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); if (mnxSb.s_zones > 0) // On V2 { sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024). AppendLine(); } else { sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_nzones, mnxSb.s_nzones * 1024). AppendLine(); } sb.AppendFormat("{0} bytes/block", mnxSb.s_blocksize).AppendLine(); sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine(); sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks, mnxSb.s_imap_blocks * mnxSb.s_blocksize).AppendLine(); sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks, mnxSb.s_zmap_blocks * mnxSb.s_blocksize).AppendLine(); sb.AppendFormat("First data zone: {0}", mnxSb.s_firstdatazone).AppendLine(); //sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0 sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine(); sb.AppendFormat("On-disk filesystem version: {0}", mnxSb.s_disk_version).AppendLine(); XmlFsType.ClusterSize = mnxSb.s_blocksize; XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones; } else { SuperBlock mnxSb = littleEndian ? Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(minixSbSector) : Marshal.ByteArrayToStructureBigEndian <SuperBlock>(minixSbSector); sb.AppendLine(minixVersion); sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); if (mnxSb.s_zones > 0) // On V2 { sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024). AppendLine(); } else { sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_nzones, mnxSb.s_nzones * 1024). AppendLine(); } sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine(); sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks, mnxSb.s_imap_blocks * 1024). AppendLine(); sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks, mnxSb.s_zmap_blocks * 1024). AppendLine(); sb.AppendFormat("First data zone: {0}", mnxSb.s_firstdatazone).AppendLine(); //sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0 sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine(); sb.AppendFormat("Filesystem state: {0:X4}", mnxSb.s_state).AppendLine(); XmlFsType.ClusterSize = 1024; XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones; } information = sb.ToString(); }
/// <summary> /// Writes the file system to an existing stream. /// </summary> /// <param name="output">The stream to write to.</param> /// <remarks>The <c>output</c> stream must support seeking and writing.</remarks> public void Build(Stream output) { if (output == null) { throw new ArgumentNullException("output"); } if (!output.CanWrite) { throw new ArgumentException("Output stream must be writable", "output"); } if (!output.CanSeek) { throw new ArgumentException("Output stream must support seeking", "output"); } _context = new BuilderContext() { RawStream = output, DataBlockSize = DefaultBlockSize, IoBuffer = new byte[DefaultBlockSize], }; MetablockWriter inodeWriter = new MetablockWriter(); MetablockWriter dirWriter = new MetablockWriter(); FragmentWriter fragWriter = new FragmentWriter(_context); IdTableWriter idWriter = new IdTableWriter(_context); _context.AllocateInode = AllocateInode; _context.AllocateId = idWriter.AllocateId; _context.WriteDataBlock = WriteDataBlock; _context.WriteFragment = fragWriter.WriteFragment; _context.InodeWriter = inodeWriter; _context.DirectoryWriter = dirWriter; _nextInode = 1; SuperBlock superBlock = new SuperBlock(); superBlock.Magic = SuperBlock.SquashFsMagic; superBlock.CreationTime = DateTime.Now; superBlock.BlockSize = (uint)_context.DataBlockSize; superBlock.Compression = 1; // DEFLATE superBlock.BlockSizeLog2 = (ushort)Utilities.Log2(superBlock.BlockSize); superBlock.MajorVersion = 4; superBlock.MinorVersion = 0; output.Position = superBlock.Size; GetRoot().Reset(); GetRoot().Write(_context); fragWriter.Flush(); superBlock.RootInode = GetRoot().InodeRef; superBlock.InodesCount = _nextInode - 1; superBlock.FragmentsCount = (uint)fragWriter.FragmentCount; superBlock.UidGidCount = (ushort)idWriter.IdCount; superBlock.InodeTableStart = output.Position; inodeWriter.Persist(output); superBlock.DirectoryTableStart = output.Position; dirWriter.Persist(output); if (fragWriter.FragmentCount > 0) { superBlock.FragmentTableStart = output.Position; fragWriter.Persist(); } else { superBlock.FragmentTableStart = -1; } superBlock.LookupTableStart = -1; if (idWriter.IdCount > 0) { superBlock.UidGidTableStart = output.Position; idWriter.Persist(); } else { superBlock.UidGidTableStart = -1; } superBlock.ExtendedAttrsTableStart = -1; superBlock.BytesUsed = output.Position; // Pad to 4KB long end = Utilities.RoundUp(output.Position, 4 * Sizes.OneKiB); if (end != output.Position) { byte[] padding = new byte[(int)(end - output.Position)]; output.Write(padding, 0, padding.Length); } // Go back and write the superblock output.Position = 0; byte[] buffer = new byte[superBlock.Size]; superBlock.WriteTo(buffer, 0); output.Write(buffer, 0, buffer.Length); output.Position = end; }
public VirtualFileSystem() { ufdtArr = new UFDT[Constants.TOTALFILES]; superBlockObj = new SuperBlock(); Head = null; }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { // TODO: Find correct default encoding Encoding = Encoding.ASCII; information = ""; StringBuilder superBlockMetadata = new StringBuilder(); byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start); SuperBlock sb = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sbSector); if (sb.record_type != 1 || sb.record_version != 1) { return; } if (Encoding.ASCII.GetString(sb.sync_bytes) != SYNC) { return; } superBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine(); if (!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_label, Encoding))) { superBlockMetadata .AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, Encoding)).AppendLine(); } if (!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_comment, Encoding))) { superBlockMetadata .AppendFormat("Volume comment: {0}", StringHandlers.CToString(sb.volume_comment, Encoding)) .AppendLine(); } superBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine(); superBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine(); if (imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448) { if (sb.block_size != 2048) { superBlockMetadata .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", sb.block_size, 2048); } } else if (imagePlugin.Info.SectorSize != sb.block_size) { superBlockMetadata .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", sb.block_size, imagePlugin.Info.SectorSize); } superBlockMetadata .AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size * sb.block_count) .AppendLine(); if (sb.block_count > imagePlugin.Info.Sectors) { superBlockMetadata .AppendFormat("WARNING: Filesystem indicates {0} blocks while device indicates {1} blocks", sb.block_count, imagePlugin.Info.Sectors); } superBlockMetadata.AppendFormat("Root directory identifier: 0x{0:X8}", sb.root_dirid).AppendLine(); superBlockMetadata.AppendFormat("Root directory block size: {0} bytes", sb.rootdir_bsize).AppendLine(); superBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", sb.rootdir_blocks, sb.rootdir_bsize * sb.rootdir_blocks).AppendLine(); superBlockMetadata.AppendFormat("Last root directory copy: {0}", sb.last_root_copy).AppendLine(); information = superBlockMetadata.ToString(); XmlFsType = new FileSystemType { Type = "Opera", VolumeName = StringHandlers.CToString(sb.volume_label, Encoding), ClusterSize = sb.block_size, Clusters = sb.block_count }; }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.UTF8; byte[] sector = imagePlugin.ReadSector(partition.Start); uint magic = BitConverter.ToUInt32(sector, 0x00); var sqSb = new SuperBlock(); bool littleEndian = true; switch (magic) { case SQUASH_MAGIC: sqSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector); break; case SQUASH_CIGAM: sqSb = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sector); littleEndian = false; break; } var sbInformation = new StringBuilder(); sbInformation.AppendLine("Squash file system"); sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian"); sbInformation.AppendFormat("Volume version {0}.{1}", sqSb.s_major, sqSb.s_minor).AppendLine(); sbInformation.AppendFormat("Volume has {0} bytes", sqSb.bytes_used).AppendLine(); sbInformation.AppendFormat("Volume has {0} bytes per block", sqSb.block_size).AppendLine(); sbInformation.AppendFormat("Volume created on {0}", DateHandlers.UnixUnsignedToDateTime(sqSb.mkfs_time)). AppendLine(); sbInformation.AppendFormat("Volume has {0} inodes", sqSb.inodes).AppendLine(); switch (sqSb.compression) { case (ushort)SquashCompression.Lz4: sbInformation.AppendLine("Volume is compressed using LZ4"); break; case (ushort)SquashCompression.Lzo: sbInformation.AppendLine("Volume is compressed using LZO"); break; case (ushort)SquashCompression.Lzma: sbInformation.AppendLine("Volume is compressed using LZMA"); break; case (ushort)SquashCompression.Xz: sbInformation.AppendLine("Volume is compressed using XZ"); break; case (ushort)SquashCompression.Zlib: sbInformation.AppendLine("Volume is compressed using GZIP"); break; case (ushort)SquashCompression.Zstd: sbInformation.AppendLine("Volume is compressed using Zstandard"); break; default: sbInformation.AppendFormat("Volume is compressed using unknown algorithm {0}", sqSb.compression). AppendLine(); break; } information = sbInformation.ToString(); XmlFsType = new FileSystemType { Type = "Squash file system", CreationDate = DateHandlers.UnixUnsignedToDateTime(sqSb.mkfs_time), CreationDateSpecified = true, Clusters = (((partition.End - partition.Start) + 1) * imagePlugin.Info.SectorSize) / sqSb.block_size, ClusterSize = sqSb.block_size, Files = sqSb.inodes, FilesSpecified = true, FreeClusters = 0, FreeClustersSpecified = true }; }
/// <summary> /// Initializes a new instance of the <see cref="PdbFile"/> class. /// </summary> /// <param name="path">Path to PDB file.</param> public PdbFile(string path) { File = new MMFile(path); Reader = new MMFileReader(File); // Parse file headers // Initialize MSF super block SuperBlock = MSF.SuperBlock.Read(Reader); SuperBlock.Validate(); if (File.Length % SuperBlock.BlockSize != 0) { throw new Exception("File size is not a multiple of block size"); } // Initialize Free Page Map. // The Fpm exists either at block 1 or block 2 of the MSF. However, this // allows for a maximum of getBlockSize() * 8 blocks bits in the Fpm, and // thusly an equal number of total blocks in the file. For a block size // of 4KiB (very common), this would yield 32KiB total blocks in file, for a // maximum file size of 32KiB * 4KiB = 128MiB. Obviously this won't do, so // the Fpm is split across the file at `getBlockSize()` intervals. As a // result, every block whose index is of the form |{1,2} + getBlockSize() * k| // for any non-negative integer k is an Fpm block. In theory, we only really // need to reserve blocks of the form |{1,2} + getBlockSize() * 8 * k|, but // current versions of the MSF format already expect the Fpm to be arranged // at getBlockSize() intervals, so we have to be compatible. // See the function fpmPn() for more information: // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489 uint fpmIntervals = (SuperBlock.NumBlocks + 8 * SuperBlock.BlockSize - 1) / (8 * SuperBlock.BlockSize); uint[] fpmBlocks = new uint[fpmIntervals]; uint currentFpmBlock = SuperBlock.FreeBlockMapBlock; for (int i = 0; i < fpmBlocks.Length; i++) { fpmBlocks[i] = currentFpmBlock; currentFpmBlock += SuperBlock.BlockSize; } IBinaryReader fpmStream = new MappedBlockBinaryReader <MMFileReader>(fpmBlocks, SuperBlock.BlockSize, (SuperBlock.NumBlocks + 7) / 8, Reader); FreePageMap = Reader.ReadByteArray((int)fpmStream.Length); // Read directory blocks Reader.Position = (long)SuperBlock.BlockMapOffset; uint[] directoryBlocks = Reader.ReadUintArray((int)SuperBlock.NumDirectoryBlocks); // Parse stream data uint NumStreams = 0; PdbStream directoryStream = new PdbStream(directoryBlocks, SuperBlock.NumDirectoryBytes, this); NumStreams = directoryStream.Reader.ReadUint(); streams = new PdbStream[NumStreams]; uint[] streamSizes = directoryStream.Reader.ReadUintArray(streams.Length); for (int i = 0; i < streams.Length; i++) { uint streamSize = streamSizes[i]; uint NumExpectedStreamBlocks = streamSize == uint.MaxValue ? 0 : SuperBlock.BytesToBlocks(streamSize); uint[] blocks = directoryStream.Reader.ReadUintArray((int)NumExpectedStreamBlocks); foreach (uint block in blocks) { ulong blockEndOffset = SuperBlock.BlocksToBytes(block + 1); if (blockEndOffset > (ulong)File.Length) { throw new Exception("Stream block map is corrupt."); } } streams[i] = new PdbStream(blocks, streamSize, this); } if (directoryStream.Reader.Position != SuperBlock.NumDirectoryBytes) { throw new Exception("Not whole directory stream was read"); } dbiStreamCache = SimpleCache.CreateStruct(() => new DbiStream(streams[(uint)SpecialStream.StreamDBI])); pdbSymbolStreamCache = SimpleCache.CreateStruct(() => new SymbolStream(streams[DbiStream.SymbolRecordStreamIndex])); tpiStreamCache = SimpleCache.CreateStruct(() => new TpiStream(streams[(uint)SpecialStream.StreamTPI])); ipiStreamCache = SimpleCache.CreateStruct(() => new TpiStream(streams[(uint)SpecialStream.StreamIPI])); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; var sb = new StringBuilder(); if (imagePlugin.Info.SectorSize < 512) { return; } ulong sbSectorOff = SB_POS / imagePlugin.Info.SectorSize; uint sbOff = SB_POS % imagePlugin.Info.SectorSize; if (sbSectorOff + partition.Start >= partition.End) { return; } byte[] sblock = imagePlugin.ReadSector(sbSectorOff + partition.Start); byte[] sbSector = new byte[512]; Array.Copy(sblock, sbOff, sbSector, 0, 512); var extSb = new SuperBlock { inodes = BitConverter.ToUInt32(sbSector, 0x000), zones = BitConverter.ToUInt32(sbSector, 0x004), firstfreeblk = BitConverter.ToUInt32(sbSector, 0x008), freecountblk = BitConverter.ToUInt32(sbSector, 0x00C), firstfreeind = BitConverter.ToUInt32(sbSector, 0x010), freecountind = BitConverter.ToUInt32(sbSector, 0x014), firstdatazone = BitConverter.ToUInt32(sbSector, 0x018), logzonesize = BitConverter.ToUInt32(sbSector, 0x01C), maxsize = BitConverter.ToUInt32(sbSector, 0x020) }; sb.AppendLine("ext filesystem"); sb.AppendFormat("{0} zones on volume", extSb.zones); sb.AppendFormat("{0} free blocks ({1} bytes)", extSb.freecountblk, extSb.freecountblk * 1024); sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", extSb.inodes, extSb.freecountind, (extSb.freecountind * 100) / extSb.inodes); sb.AppendFormat("First free inode is {0}", extSb.firstfreeind); sb.AppendFormat("First free block is {0}", extSb.firstfreeblk); sb.AppendFormat("First data zone is {0}", extSb.firstdatazone); sb.AppendFormat("Log zone size: {0}", extSb.logzonesize); sb.AppendFormat("Max zone size: {0}", extSb.maxsize); XmlFsType = new FileSystemType { Type = "ext", FreeClusters = extSb.freecountblk, FreeClustersSpecified = true, ClusterSize = 1024, Clusters = (((partition.End - partition.Start) + 1) * imagePlugin.Info.SectorSize) / 1024 }; information = sb.ToString(); }