public void Open(string path) { string parentFolder = Path.GetDirectoryName(path); string baseFilename = Path.GetFileName(path); FileStream finderDatStream = new FileStream(Path.Combine(parentFolder ?? throw new InvalidOperationException(), FINDER_INFO), FileMode.Open, FileAccess.Read); while (finderDatStream.Position + 0x5C <= finderDatStream.Length) { PCExchangeEntry datEntry = new PCExchangeEntry(); byte[] datEntry_b = new byte[Marshal.SizeOf(datEntry)]; finderDatStream.Read(datEntry_b, 0, Marshal.SizeOf(datEntry)); datEntry = BigEndianMarshal.ByteArrayToStructureBigEndian <PCExchangeEntry>(datEntry_b); string macName = StringHandlers.PascalToString(datEntry.macName, Encoding.GetEncoding("macintosh")); byte[] tmpDosName_b = new byte[8]; byte[] tmpDosExt_b = new byte[3]; Array.Copy(datEntry.dosName, 0, tmpDosName_b, 0, 8); Array.Copy(datEntry.dosName, 8, tmpDosExt_b, 0, 3); string dosName = Encoding.ASCII.GetString(tmpDosName_b).Trim() + "." + Encoding.ASCII.GetString(tmpDosExt_b).Trim(); string dosNameLow = dosName.ToLower(CultureInfo.CurrentCulture); if (baseFilename != macName && baseFilename != dosName && baseFilename != dosNameLow) { continue; } if (File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException()))) { dataPath = Path.Combine(parentFolder, macName); }
public void Open(string path) { FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); fs.Seek(0, SeekOrigin.Begin); byte[] hdr_b = new byte[128]; fs.Read(hdr_b, 0, 128); header = BigEndianMarshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdr_b); uint blocks = 1; blocks += (uint)(header.secondaryHeaderLength / 128); if (header.secondaryHeaderLength % 128 > 0) { blocks++; } dataForkOff = blocks * 128; blocks += header.dataLength / 128; if (header.dataLength % 128 > 0) { blocks++; } rsrcForkOff = blocks * 128; filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh")); creationTime = DateHandlers.MacToDateTime(header.creationTime); lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime); fs.Close(); opened = true; isPath = true; basePath = path; }
public bool Identify(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); if (stream.Length < 512) { return(false); } stream.Seek(-Marshal.SizeOf(footer), SeekOrigin.End); byte[] footerB = new byte[Marshal.SizeOf(footer)]; stream.Read(footerB, 0, Marshal.SizeOf(footer)); footer = BigEndianMarshal.ByteArrayToStructureBigEndian <UdifFooter>(footerB); if (footer.signature == UDIF_SIGNATURE) { return(true); } // Old UDIF as created by DiskCopy 6.5 using "OBSOLETE" format. (DiskCopy 5 rumored format?) stream.Seek(0, SeekOrigin.Begin); byte[] headerB = new byte[Marshal.SizeOf(footer)]; stream.Read(headerB, 0, Marshal.SizeOf(footer)); footer = BigEndianMarshal.ByteArrayToStructureBigEndian <UdifFooter>(headerB); return(footer.signature == UDIF_SIGNATURE); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { if (imagePlugin.Info.SectorSize < 512) { return(false); } UNICOS_Superblock unicosSb = new UNICOS_Superblock(); uint sbSize = (uint)(Marshal.SizeOf(unicosSb) / imagePlugin.Info.SectorSize); if (Marshal.SizeOf(unicosSb) % imagePlugin.Info.SectorSize != 0) { sbSize++; } byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if (sector.Length < Marshal.SizeOf(unicosSb)) { return(false); } unicosSb = BigEndianMarshal.ByteArrayToStructureBigEndian <UNICOS_Superblock>(sector); DicConsole.DebugWriteLine("UNICOS plugin", "magic = 0x{0:X16} (expected 0x{1:X16})", unicosSb.s_magic, UNICOS_Magic); return(unicosSb.s_magic == UNICOS_Magic); }
public void Open(Stream stream) { stream.Seek(0, SeekOrigin.Begin); byte[] hdr_b = new byte[128]; stream.Read(hdr_b, 0, 128); header = BigEndianMarshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdr_b); uint blocks = 1; blocks += (uint)(header.secondaryHeaderLength / 128); if (header.secondaryHeaderLength % 128 > 0) { blocks++; } dataForkOff = blocks * 128; blocks += header.dataLength / 128; if (header.dataLength % 128 > 0) { blocks++; } rsrcForkOff = blocks * 128; filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh")); creationTime = DateHandlers.MacToDateTime(header.creationTime); lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime); stream.Seek(0, SeekOrigin.Begin); opened = true; isStream = true; this.stream = stream; }
public bool Identify(string path) { string parentFolder = Path.GetDirectoryName(path); if (!File.Exists(Path.Combine(parentFolder ?? throw new InvalidOperationException(), FINDER_INFO))) { return(false); } if (!Directory.Exists(Path.Combine(parentFolder, RESOURCES))) { return(false); } string baseFilename = Path.GetFileName(path); bool dataFound = false; bool rsrcFound = false; FileStream finderDatStream = new FileStream(Path.Combine(parentFolder, FINDER_INFO), FileMode.Open, FileAccess.Read); while (finderDatStream.Position + 0x5C <= finderDatStream.Length) { PCExchangeEntry datEntry = new PCExchangeEntry(); byte[] datEntry_b = new byte[Marshal.SizeOf(datEntry)]; finderDatStream.Read(datEntry_b, 0, Marshal.SizeOf(datEntry)); datEntry = BigEndianMarshal.ByteArrayToStructureBigEndian <PCExchangeEntry>(datEntry_b); // TODO: Add support for encoding on filters string macName = StringHandlers.PascalToString(datEntry.macName, Encoding.GetEncoding("macintosh")); byte[] tmpDosName_b = new byte[8]; byte[] tmpDosExt_b = new byte[3]; Array.Copy(datEntry.dosName, 0, tmpDosName_b, 0, 8); Array.Copy(datEntry.dosName, 8, tmpDosExt_b, 0, 3); string dosName = Encoding.ASCII.GetString(tmpDosName_b).Trim() + "." + Encoding.ASCII.GetString(tmpDosExt_b).Trim(); string dosNameLow = dosName.ToLower(CultureInfo.CurrentCulture); if (baseFilename != macName && baseFilename != dosName && baseFilename != dosNameLow) { continue; } dataFound |= File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException())) || File.Exists(Path.Combine(parentFolder, dosName)) || File.Exists(Path.Combine(parentFolder, dosNameLow)); rsrcFound |= File.Exists(Path.Combine(parentFolder, RESOURCES, dosName)) || File.Exists(Path.Combine(parentFolder, RESOURCES, dosNameLow)); break; } finderDatStream.Close(); return(dataFound && rsrcFound); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { // Technically everything on Plan 9 from Bell Labs is in UTF-8 Encoding = Encoding.UTF8; information = ""; if (imagePlugin.Info.SectorSize < 512) { return; } ulong hdrSector = HEADER_POS / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + hdrSector); FossilHeader hdr = BigEndianMarshal.ByteArrayToStructureBigEndian <FossilHeader>(sector); DicConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic, FOSSIL_HDR_MAGIC); StringBuilder sb = new StringBuilder(); sb.AppendLine("Fossil"); sb.AppendFormat("Filesystem version {0}", hdr.version).AppendLine(); sb.AppendFormat("{0} bytes per block", hdr.blockSize).AppendLine(); sb.AppendFormat("Superblock resides in block {0}", hdr.super).AppendLine(); sb.AppendFormat("Labels resides in block {0}", hdr.label).AppendLine(); sb.AppendFormat("Data starts at block {0}", hdr.data).AppendLine(); sb.AppendFormat("Volume has {0} blocks", hdr.end).AppendLine(); ulong sbLocation = hdr.super * (hdr.blockSize / imagePlugin.Info.SectorSize) + partition.Start; XmlFsType = new FileSystemType { Type = "Fossil filesystem", ClusterSize = hdr.blockSize, Clusters = hdr.end }; if (sbLocation <= partition.End) { sector = imagePlugin.ReadSector(sbLocation); FossilSuperBlock fsb = BigEndianMarshal.ByteArrayToStructureBigEndian <FossilSuperBlock>(sector); DicConsole.DebugWriteLine("Fossil plugin", "magic 0x{0:X8} (expected 0x{1:X8})", fsb.magic, FOSSIL_SB_MAGIC); if (fsb.magic == FOSSIL_SB_MAGIC) { sb.AppendFormat("Epoch low {0}", fsb.epochLow).AppendLine(); sb.AppendFormat("Epoch high {0}", fsb.epochHigh).AppendLine(); sb.AppendFormat("Next QID {0}", fsb.qid).AppendLine(); sb.AppendFormat("Active root block {0}", fsb.active).AppendLine(); sb.AppendFormat("Next root block {0}", fsb.next).AppendLine(); sb.AppendFormat("Curren root block {0}", fsb.current).AppendLine(); sb.AppendFormat("Volume label: \"{0}\"", StringHandlers.CToString(fsb.name, Encoding)).AppendLine(); XmlFsType.VolumeName = StringHandlers.CToString(fsb.name, Encoding); } } information = sb.ToString(); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { if (imagePlugin.Info.SectorSize < 512) { return(false); } byte[] sector = imagePlugin.ReadSector(partition.Start); FATX_Superblock fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian <FATX_Superblock>(sector); return(fatxSb.magic == FATX_MAGIC); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { if (imagePlugin.Info.SectorSize < 256) { return(false); } byte[] sector = imagePlugin.ReadSector(partition.Start); LifSystemBlock lifSb = BigEndianMarshal.ByteArrayToStructureBigEndian <LifSystemBlock>(sector); DicConsole.DebugWriteLine("LIF plugin", "magic 0x{0:X8} (expected 0x{1:X8})", lifSb.magic, LIF_MAGIC); return(lifSb.magic == LIF_MAGIC); }
public bool Identify(byte[] buffer) { if (buffer == null || buffer.Length < 26) { return(false); } byte[] hdr_b = new byte[26]; Array.Copy(buffer, 0, hdr_b, 0, 26); header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleSingleHeader>(hdr_b); return(header.magic == AppleSingleMagic && (header.version == AppleSingleVersion || header.version == AppleSingleVersion2)); }
public void Update(byte[] data, bool bigEndian) { VersionInfo versionInfo = bigEndian ? BigEndianMarshal.ByteArrayToStructureBigEndian <VersionInfo>(data) : BigEndianMarshal.ByteArrayToStructureLittleEndian <VersionInfo>(data); txtMajorVersion.Text = $"{versionInfo.major}"; txtMiddleVersion.Text = $"{versionInfo.middle}"; txtMinorVersion.Text = $"{versionInfo.minor}"; txtVariety.Text = $"{versionInfo.variety}"; txtInternal.Text = $"{versionInfo.interna1}"; txtShortInfo.Text = StringHandlers.CToString(versionInfo.short_info, Encoding.UTF8); txtLongInfo.Text = StringHandlers.CToString(versionInfo.long_info, Encoding.UTF8); }
public bool Identify(Stream stream) { if (stream == null || stream.Length < 26) { return(false); } byte[] hdr_b = new byte[26]; stream.Seek(0, SeekOrigin.Begin); stream.Read(hdr_b, 0, 26); header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleSingleHeader>(hdr_b); return(header.magic == AppleSingleMagic && (header.version == AppleSingleVersion || header.version == AppleSingleVersion2)); }
public bool Identify(byte[] buffer) { if (buffer == null || buffer.Length < 128) { return(false); } byte[] hdr_b = new byte[128]; Array.Copy(buffer, 0, hdr_b, 0, 128); header = BigEndianMarshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdr_b); return(header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 && header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 && (header.dataLength > 0 || header.resourceLength > 0)); }
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); CramSuperBlock crSb = new CramSuperBlock(); bool littleEndian = true; switch (magic) { case CRAM_MAGIC: IntPtr crSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(crSb)); Marshal.Copy(sector, 0, crSbPtr, Marshal.SizeOf(crSb)); crSb = (CramSuperBlock)Marshal.PtrToStructure(crSbPtr, typeof(CramSuperBlock)); Marshal.FreeHGlobal(crSbPtr); break; case CRAM_CIGAM: crSb = BigEndianMarshal.ByteArrayToStructureBigEndian <CramSuperBlock>(sector); littleEndian = false; break; } StringBuilder 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 GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); byte[] rootBlockSector = imagePlugin.ReadSector(partition.Start); RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian <RootBlock>(rootBlockSector); StringBuilder sbInformation = new StringBuilder(); sbInformation.AppendLine("SmartFileSystem"); sbInformation.AppendFormat("Volume version {0}", rootBlock.version).AppendLine(); sbInformation.AppendFormat("Volume starts on device byte {0} and ends on byte {1}", rootBlock.firstbyte, rootBlock.lastbyte).AppendLine(); sbInformation .AppendFormat("Volume has {0} blocks of {1} bytes each", rootBlock.totalblocks, rootBlock.blocksize) .AppendLine(); sbInformation.AppendFormat("Volume created on {0}", DateHandlers.UnixUnsignedToDateTime(rootBlock.datecreated).AddYears(8)) .AppendLine(); sbInformation.AppendFormat("Bitmap starts in block {0}", rootBlock.bitmapbase).AppendLine(); sbInformation.AppendFormat("Admin space container starts in block {0}", rootBlock.adminspacecontainer) .AppendLine(); sbInformation.AppendFormat("Root object container starts in block {0}", rootBlock.rootobjectcontainer) .AppendLine(); sbInformation.AppendFormat("Root node of the extent B-tree resides in block {0}", rootBlock.extentbnoderoot) .AppendLine(); sbInformation.AppendFormat("Root node of the object B-tree resides in block {0}", rootBlock.objectnoderoot) .AppendLine(); if (rootBlock.bits.HasFlag(SFSFlags.CaseSensitive)) { sbInformation.AppendLine("Volume is case sensitive"); } if (rootBlock.bits.HasFlag(SFSFlags.RecyledFolder)) { sbInformation.AppendLine("Volume moves deleted files to a recycled folder"); } information = sbInformation.ToString(); XmlFsType = new FileSystemType { CreationDate = DateHandlers.UnixUnsignedToDateTime(rootBlock.datecreated).AddYears(8), CreationDateSpecified = true, Clusters = rootBlock.totalblocks, ClusterSize = (int)rootBlock.blocksize, Type = "SmartFileSystem" }; }
public bool Identify(Stream stream) { if (stream == null || stream.Length < 128) { return(false); } byte[] hdr_b = new byte[128]; stream.Seek(0, SeekOrigin.Begin); stream.Read(hdr_b, 0, 128); header = BigEndianMarshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdr_b); return(header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 && header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 && (header.dataLength > 0 || header.resourceLength > 0)); }
static RootBlock MarshalRootBlock(byte[] block) { byte[] tmp = new byte[228]; Array.Copy(block, 0, tmp, 0, 24); Array.Copy(block, block.Length - 200, tmp, 28, 200); RootBlock root = BigEndianMarshal.ByteArrayToStructureBigEndian <RootBlock>(tmp); root.hashTable = new uint[(block.Length - 224) / 4]; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; for (int i = 0; i < root.hashTable.Length; i++) { root.hashTable[i] = BigEndianBitConverter.ToUInt32(block, 24 + i * 4); } return(root); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { if (imagePlugin.Info.SectorSize < 256) { return(false); } // Documentation says ID should be sector 0 // I've found that OS-9/X68000 has it on sector 4 // I've read OS-9/Apple2 has it on sector 15 foreach (int i in new[] { 0, 4, 15 }) { ulong location = (ulong)i; RBF_IdSector rbfSb = new RBF_IdSector(); uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.Info.SectorSize); if (Marshal.SizeOf(rbfSb) % imagePlugin.Info.SectorSize != 0) { sbSize++; } if (partition.Start + location + sbSize >= imagePlugin.Info.Sectors) { break; } byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); if (sector.Length < Marshal.SizeOf(rbfSb)) { return(false); } rbfSb = BigEndianMarshal.ByteArrayToStructureBigEndian <RBF_IdSector>(sector); RBF_NewIdSector rbf9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian <RBF_NewIdSector>(sector); DicConsole.DebugWriteLine("RBF plugin", "magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})", location, rbfSb.dd_sync, rbf9000Sb.rid_sync, RBF_SYNC, RBF_CNYS); if (rbfSb.dd_sync == RBF_SYNC || rbf9000Sb.rid_sync == RBF_SYNC || rbf9000Sb.rid_sync == RBF_CNYS) { return(true); } } return(false); }
public bool Identify(string path) { FileStream fstream = new FileStream(path, FileMode.Open, FileAccess.Read); if (fstream.Length < 26) { return(false); } byte[] hdr_b = new byte[26]; fstream.Read(hdr_b, 0, 26); header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleSingleHeader>(hdr_b); fstream.Close(); return(header.magic == AppleSingleMagic && (header.version == AppleSingleVersion || header.version == AppleSingleVersion2)); }
public bool Identify(IMediaImage imagePlugin, Partition partition) { ulong hdrSector = HEADER_POS / imagePlugin.Info.SectorSize; if (partition.Start + hdrSector > imagePlugin.Info.Sectors) { return(false); } byte[] sector = imagePlugin.ReadSector(partition.Start + hdrSector); FossilHeader hdr = BigEndianMarshal.ByteArrayToStructureBigEndian <FossilHeader>(sector); DicConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic, FOSSIL_HDR_MAGIC); return(hdr.magic == FOSSIL_HDR_MAGIC); }
public bool Identify(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); if (stream.Length < 512) { return(false); } byte[] qHdrB = new byte[48]; stream.Read(qHdrB, 0, 48); qHdr = BigEndianMarshal.ByteArrayToStructureBigEndian <QCowHeader>(qHdrB); return(qHdr.magic == QCOW_MAGIC && qHdr.version == QCOW_VERSION); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; if (imagePlugin.Info.SectorSize < 256) { return; } byte[] sector = imagePlugin.ReadSector(partition.Start); LifSystemBlock lifSb = BigEndianMarshal.ByteArrayToStructureBigEndian <LifSystemBlock>(sector); if (lifSb.magic != LIF_MAGIC) { return; } StringBuilder sb = new StringBuilder(); sb.AppendLine("HP Logical Interchange Format"); sb.AppendFormat("Directory starts at cluster {0}", lifSb.directoryStart).AppendLine(); sb.AppendFormat("LIF identifier: {0}", lifSb.lifId).AppendLine(); sb.AppendFormat("Directory size: {0} clusters", lifSb.directorySize).AppendLine(); sb.AppendFormat("LIF version: {0}", lifSb.lifVersion).AppendLine(); // How is this related to volume size? I have only CDs to test and makes no sense there sb.AppendFormat("{0} tracks", lifSb.tracks).AppendLine(); sb.AppendFormat("{0} heads", lifSb.heads).AppendLine(); sb.AppendFormat("{0} sectors", lifSb.sectors).AppendLine(); sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(lifSb.volumeLabel, Encoding)).AppendLine(); sb.AppendFormat("Volume created on {0}", DateHandlers.LifToDateTime(lifSb.creationDate)).AppendLine(); information = sb.ToString(); XmlFsType = new FileSystemType { Type = "HP Logical Interchange Format", ClusterSize = 256, Clusters = (long)(partition.Size / 256), CreationDate = DateHandlers.LifToDateTime(lifSb.creationDate), CreationDateSpecified = true, VolumeName = StringHandlers.CToString(lifSb.volumeLabel, Encoding) }; }
public bool Identify(string path) { FileStream fstream = new FileStream(path, FileMode.Open, FileAccess.Read); if (fstream.Length < 128) { return(false); } byte[] hdr_b = new byte[128]; fstream.Read(hdr_b, 0, 128); header = BigEndianMarshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdr_b); fstream.Close(); return(header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 && header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 && (header.dataLength > 0 || header.resourceLength > 0)); }
public bool Identify(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); if (stream.Length < 512) { return(false); } byte[] qHdrB = new byte[Marshal.SizeOf(qHdr)]; stream.Read(qHdrB, 0, Marshal.SizeOf(qHdr)); qHdr = BigEndianMarshal.ByteArrayToStructureBigEndian <QCow2Header>(qHdrB); DicConsole.DebugWriteLine("QCOW plugin", "qHdr.magic = 0x{0:X8}", qHdr.magic); DicConsole.DebugWriteLine("QCOW plugin", "qHdr.version = {0}", qHdr.version); return(qHdr.magic == QCOW_MAGIC && (qHdr.version == QCOW_VERSION2 || qHdr.version == QCOW_VERSION3)); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = Encoding.UTF8; information = ""; if (imagePlugin.Info.SectorSize < 512) { return; } FATX_Superblock fatxSb; byte[] sector = imagePlugin.ReadSector(partition.Start); fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian <FATX_Superblock>(sector); if (fatxSb.magic != FATX_MAGIC) { return; } StringBuilder sb = new StringBuilder(); sb.AppendLine("FATX filesystem"); sb.AppendFormat("Filesystem id {0}", fatxSb.id).AppendLine(); sb.AppendFormat("{0} sectors ({1} bytes) per cluster", fatxSb.sectorsPerCluster, fatxSb.sectorsPerCluster * imagePlugin.Info.SectorSize).AppendLine(); sb.AppendFormat("Root directory starts on cluster {0}", fatxSb.rootDirectoryCluster).AppendLine(); information = sb.ToString(); XmlFsType = new FileSystemType { Type = "FATX filesystem", ClusterSize = (int)(fatxSb.sectorsPerCluster * imagePlugin.Info.SectorSize) }; XmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / (ulong)XmlFsType.ClusterSize); }
public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset) { uint sectorSize; if (imagePlugin.Info.SectorSize == 2352 || imagePlugin.Info.SectorSize == 2448) { sectorSize = 2048; } else { sectorSize = imagePlugin.Info.SectorSize; } partitions = new List <Partition>(); if (sectorOffset + 2 >= imagePlugin.Info.Sectors) { return(false); } byte[] ddmSector = imagePlugin.ReadSector(sectorOffset); ushort maxDrivers = 61; if (sectorSize == 256) { byte[] tmp = new byte[512]; Array.Copy(ddmSector, 0, tmp, 0, 256); ddmSector = tmp; maxDrivers = 29; } else if (sectorSize < 256) { return(false); } AppleDriverDescriptorMap ddm = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDriverDescriptorMap>(ddmSector); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbSig = 0x{0:X4}", ddm.sbSig); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbBlockSize = {0}", ddm.sbBlockSize); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbBlocks = {0}", ddm.sbBlocks); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbDevType = {0}", ddm.sbDevType); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbDevId = {0}", ddm.sbDevId); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbData = 0x{0:X8}", ddm.sbData); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbDrvrCount = {0}", ddm.sbDrvrCount); uint sequence = 0; if (ddm.sbSig == DDM_MAGIC) { if (ddm.sbDrvrCount < maxDrivers) { ddm.sbMap = new AppleDriverEntry[ddm.sbDrvrCount]; for (int i = 0; i < ddm.sbDrvrCount; i++) { byte[] tmp = new byte[8]; Array.Copy(ddmSector, 18 + i * 8, tmp, 0, 8); ddm.sbMap[i] = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDriverEntry>(tmp); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbMap[{1}].ddBlock = {0}", ddm.sbMap[i].ddBlock, i); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbMap[{1}].ddSize = {0}", ddm.sbMap[i].ddSize, i); DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbMap[{1}].ddType = {0}", ddm.sbMap[i].ddType, i); if (ddm.sbMap[i].ddSize == 0) { continue; } Partition part = new Partition { Size = (ulong)(ddm.sbMap[i].ddSize * 512), Length = (ulong)(ddm.sbMap[i].ddSize * 512 / sectorSize), Sequence = sequence, Offset = ddm.sbMap[i].ddBlock * sectorSize, Start = ddm.sbMap[i].ddBlock + sectorOffset, Type = "Apple_Driver" }; if (ddm.sbMap[i].ddSize * 512 % sectorSize > 0) { part.Length++; } partitions.Add(part); sequence++; } } } byte[] partSector = imagePlugin.ReadSector(1 + sectorOffset); AppleOldDevicePartitionMap oldMap = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleOldDevicePartitionMap>(partSector); // This is the easy one, no sector size mixing if (oldMap.pdSig == APM_MAGIC_OLD) { for (int i = 2; i < partSector.Length; i += 12) { byte[] tmp = new byte[12]; Array.Copy(partSector, i, tmp, 0, 12); AppleMapOldPartitionEntry oldEntry = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleMapOldPartitionEntry>(tmp); DicConsole.DebugWriteLine("AppleMap Plugin", "old_map.sbMap[{1}].pdStart = {0}", oldEntry.pdStart, (i - 2) / 12); DicConsole.DebugWriteLine("AppleMap Plugin", "old_map.sbMap[{1}].pdSize = {0}", oldEntry.pdSize, (i - 2) / 12); DicConsole.DebugWriteLine("AppleMap Plugin", "old_map.sbMap[{1}].pdFSID = 0x{0:X8}", oldEntry.pdFSID, (i - 2) / 12); if (oldEntry.pdSize == 0 && oldEntry.pdFSID == 0) { if (oldEntry.pdStart == 0) { break; } continue; } Partition part = new Partition { Size = oldEntry.pdStart * ddm.sbBlockSize, Length = oldEntry.pdStart * ddm.sbBlockSize / sectorSize, Sequence = sequence, Offset = oldEntry.pdSize * ddm.sbBlockSize, Start = oldEntry.pdSize * ddm.sbBlockSize / sectorSize, Scheme = Name, Type = oldEntry.pdFSID == HFS_MAGIC_OLD ? "Apple_HFS" : $"0x{oldEntry.pdFSID:X8}" }; partitions.Add(part); sequence++; } return(partitions.Count > 0); } AppleMapPartitionEntry entry; uint entrySize; uint entryCount; uint sectorsToRead; uint skipDdm; // If sector is bigger than 512 if (sectorSize > 512) { byte[] tmp = new byte[512]; Array.Copy(ddmSector, 512, tmp, 0, 512); entry = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleMapPartitionEntry>(tmp); // Check for a partition entry that's 512-byte aligned if (entry.signature == APM_MAGIC) { DicConsole.DebugWriteLine("AppleMap Plugin", "Found misaligned entry."); entrySize = 512; entryCount = entry.entries; skipDdm = 512; sectorsToRead = (entryCount + 1) * 512 / sectorSize + 1; } else { entry = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleMapPartitionEntry>(partSector); if (entry.signature == APM_MAGIC) { DicConsole.DebugWriteLine("AppleMap Plugin", "Found aligned entry."); entrySize = sectorSize; entryCount = entry.entries; skipDdm = sectorSize; sectorsToRead = entryCount + 2; } else { return(partitions.Count > 0); } } } else { entry = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleMapPartitionEntry>(partSector); if (entry.signature == APM_MAGIC) { DicConsole.DebugWriteLine("AppleMap Plugin", "Found aligned entry."); entrySize = sectorSize; entryCount = entry.entries; skipDdm = sectorSize; sectorsToRead = entryCount + 2; } else { return(partitions.Count > 0); } } byte[] entries = imagePlugin.ReadSectors(sectorOffset, sectorsToRead); DicConsole.DebugWriteLine("AppleMap Plugin", "entry_size = {0}", entrySize); DicConsole.DebugWriteLine("AppleMap Plugin", "entry_count = {0}", entryCount); DicConsole.DebugWriteLine("AppleMap Plugin", "skip_ddm = {0}", skipDdm); DicConsole.DebugWriteLine("AppleMap Plugin", "sectors_to_read = {0}", sectorsToRead); byte[] copy = new byte[entries.Length - skipDdm]; Array.Copy(entries, skipDdm, copy, 0, copy.Length); entries = copy; for (int i = 0; i < entryCount; i++) { byte[] tmp = new byte[entrySize]; Array.Copy(entries, i * entrySize, tmp, 0, entrySize); entry = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleMapPartitionEntry>(tmp); if (entry.signature != APM_MAGIC) { continue; } DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].signature = 0x{1:X4}", i, entry.signature); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].reserved1 = 0x{1:X4}", i, entry.reserved1); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entries = {1}", i, entry.entries); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].start = {1}", i, entry.start); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].sectors = {1}", i, entry.sectors); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].name = \"{1}\"", i, StringHandlers.CToString(entry.name)); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].type = \"{1}\"", i, StringHandlers.CToString(entry.type)); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_data_block = {1}", i, entry.first_data_block); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].data_sectors = {1}", i, entry.data_sectors); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].flags = {1}", i, (AppleMapFlags)entry.flags); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_boot_block = {1}", i, entry.first_boot_block); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].boot_size = {1}", i, entry.boot_size); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].load_address = 0x{1:X8}", i, entry.load_address); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].load_address2 = 0x{1:X8}", i, entry.load_address2); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point = 0x{1:X8}", i, entry.entry_point); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point2 = 0x{1:X8}", i, entry.entry_point2); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].checksum = 0x{1:X8}", i, entry.checksum); DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].processor = \"{1}\"", i, StringHandlers.CToString(entry.processor)); AppleMapFlags flags = (AppleMapFlags)entry.flags; // BeOS doesn't mark its partitions as valid //if(flags.HasFlag(AppleMapFlags.Valid) && if (StringHandlers.CToString(entry.type) == "Apple_partition_map" || entry.sectors <= 0) { continue; } StringBuilder sb = new StringBuilder(); Partition partition = new Partition { Sequence = sequence, Type = StringHandlers.CToString(entry.type), Name = StringHandlers.CToString(entry.name), Offset = entry.start * entrySize, Size = entry.sectors * entrySize, Start = entry.start * entrySize / sectorSize + sectorOffset, Length = entry.sectors * entrySize / sectorSize, Scheme = Name }; sb.AppendLine("Partition flags:"); if (flags.HasFlag(AppleMapFlags.Valid)) { sb.AppendLine("Partition is valid."); } if (flags.HasFlag(AppleMapFlags.Allocated)) { sb.AppendLine("Partition entry is allocated."); } if (flags.HasFlag(AppleMapFlags.InUse)) { sb.AppendLine("Partition is in use."); } if (flags.HasFlag(AppleMapFlags.Bootable)) { sb.AppendLine("Partition is bootable."); } if (flags.HasFlag(AppleMapFlags.Readable)) { sb.AppendLine("Partition is readable."); } if (flags.HasFlag(AppleMapFlags.Writable)) { sb.AppendLine("Partition is writable."); } if (flags.HasFlag(AppleMapFlags.Bootable)) { sb.AppendFormat("First boot sector: {0}", entry.first_boot_block * entrySize / sectorSize) .AppendLine(); sb.AppendFormat("Boot is {0} bytes.", entry.boot_size).AppendLine(); sb.AppendFormat("Boot load address: 0x{0:X8}", entry.load_address).AppendLine(); sb.AppendFormat("Boot entry point: 0x{0:X8}", entry.entry_point).AppendLine(); sb.AppendFormat("Boot code checksum: 0x{0:X8}", entry.checksum).AppendLine(); sb.AppendFormat("Processor: {0}", StringHandlers.CToString(entry.processor)).AppendLine(); if (flags.HasFlag(AppleMapFlags.PicCode)) { sb.AppendLine("Partition's boot code is position independent."); } } partition.Description = sb.ToString(); if (partition.Start < imagePlugin.Info.Sectors && partition.End < imagePlugin.Info.Sectors) { partitions.Add(partition); sequence++; } // Some CD and DVDs end with an Apple_Free that expands beyond the disc size... else if (partition.Start < imagePlugin.Info.Sectors) { DicConsole.DebugWriteLine("AppleMap Plugin", "Cutting last partition end ({0}) to media size ({1})", partition.End, imagePlugin.Info.Sectors - 1); partition.Length = imagePlugin.Info.Sectors - partition.Start; partitions.Add(partition); sequence++; } else { DicConsole.DebugWriteLine("AppleMap Plugin", "Not adding partition becaus start ({0}) is outside media size ({1})", partition.Start, imagePlugin.Info.Sectors - 1); } } return(partitions.Count > 0); }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; if (imagePlugin.Info.SectorSize < 512) { return; } if (partition.Start != 0) { return; } spcl16 oldHdr = new spcl16(); spcl_aix aixHdr = new spcl_aix(); s_spcl newHdr = new s_spcl(); uint sbSize = (uint)(Marshal.SizeOf(newHdr) / imagePlugin.Info.SectorSize); if (Marshal.SizeOf(newHdr) % imagePlugin.Info.SectorSize != 0) { sbSize++; } byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize); if (sector.Length < Marshal.SizeOf(newHdr)) { return; } IntPtr oldPtr = Marshal.AllocHGlobal(Marshal.SizeOf(oldHdr)); Marshal.Copy(sector, 0, oldPtr, Marshal.SizeOf(oldHdr)); oldHdr = (spcl16)Marshal.PtrToStructure(oldPtr, typeof(spcl16)); Marshal.FreeHGlobal(oldPtr); IntPtr aixPtr = Marshal.AllocHGlobal(Marshal.SizeOf(aixHdr)); Marshal.Copy(sector, 0, aixPtr, Marshal.SizeOf(aixHdr)); aixHdr = (spcl_aix)Marshal.PtrToStructure(aixPtr, typeof(spcl_aix)); Marshal.FreeHGlobal(aixPtr); IntPtr newPtr = Marshal.AllocHGlobal(Marshal.SizeOf(newHdr)); Marshal.Copy(sector, 0, newPtr, Marshal.SizeOf(newHdr)); newHdr = (s_spcl)Marshal.PtrToStructure(newPtr, typeof(s_spcl)); Marshal.FreeHGlobal(newPtr); bool useOld = false; bool useAix = false; if (newHdr.c_magic == OFS_MAGIC || newHdr.c_magic == NFS_MAGIC || newHdr.c_magic == OFS_CIGAM || newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_MAGIC || newHdr.c_magic == UFS2_CIGAM) { if (newHdr.c_magic == OFS_CIGAM || newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_CIGAM) { newHdr = BigEndianMarshal.ByteArrayToStructureBigEndian <s_spcl>(sector); } } else if (aixHdr.c_magic == XIX_MAGIC || aixHdr.c_magic == XIX_CIGAM) { useAix = true; if (aixHdr.c_magic == XIX_CIGAM) { aixHdr = BigEndianMarshal.ByteArrayToStructureBigEndian <spcl_aix>(sector); } } else if (oldHdr.c_magic == OFS_MAGIC) { useOld = true; // Swap PDP-11 endian oldHdr.c_date = (int)Swapping.PDPFromLittleEndian((uint)oldHdr.c_date); oldHdr.c_ddate = (int)Swapping.PDPFromLittleEndian((uint)oldHdr.c_ddate); } else { information = "Could not read dump(8) header block"; return; } StringBuilder sb = new StringBuilder(); XmlFsType = new FileSystemType { ClusterSize = 1024, Clusters = (long)(partition.Size / 1024) }; if (useOld) { XmlFsType.Type = "Old 16-bit dump(8)"; sb.AppendLine(XmlFsType.Type); if (oldHdr.c_date > 0) { XmlFsType.CreationDate = DateHandlers.UnixToDateTime(oldHdr.c_date); XmlFsType.CreationDateSpecified = true; sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); } if (oldHdr.c_ddate > 0) { XmlFsType.BackupDate = DateHandlers.UnixToDateTime(oldHdr.c_ddate); XmlFsType.BackupDateSpecified = true; sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); } sb.AppendFormat("Dump volume number: {0}", oldHdr.c_volume).AppendLine(); } else if (useAix) { XmlFsType.Type = "AIX dump(8)"; sb.AppendLine(XmlFsType.Type); if (aixHdr.c_date > 0) { XmlFsType.CreationDate = DateHandlers.UnixToDateTime(aixHdr.c_date); XmlFsType.CreationDateSpecified = true; sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); } if (aixHdr.c_ddate > 0) { XmlFsType.BackupDate = DateHandlers.UnixToDateTime(aixHdr.c_ddate); XmlFsType.BackupDateSpecified = true; sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); } sb.AppendFormat("Dump volume number: {0}", aixHdr.c_volume).AppendLine(); } else { XmlFsType.Type = "dump(8)"; sb.AppendLine(XmlFsType.Type); if (newHdr.c_ndate > 0) { XmlFsType.CreationDate = DateHandlers.UnixToDateTime(newHdr.c_ndate); XmlFsType.CreationDateSpecified = true; sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); } else if (newHdr.c_date > 0) { XmlFsType.CreationDate = DateHandlers.UnixToDateTime(newHdr.c_date); XmlFsType.CreationDateSpecified = true; sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine(); } if (newHdr.c_nddate > 0) { XmlFsType.BackupDate = DateHandlers.UnixToDateTime(newHdr.c_nddate); XmlFsType.BackupDateSpecified = true; sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); } else if (newHdr.c_ddate > 0) { XmlFsType.BackupDate = DateHandlers.UnixToDateTime(newHdr.c_ddate); XmlFsType.BackupDateSpecified = true; sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine(); } sb.AppendFormat("Dump volume number: {0}", newHdr.c_volume).AppendLine(); sb.AppendFormat("Dump level: {0}", newHdr.c_level).AppendLine(); string dumpname = StringHandlers.CToString(newHdr.c_label); if (!string.IsNullOrEmpty(dumpname)) { XmlFsType.VolumeName = dumpname; sb.AppendFormat("Dump label: {0}", dumpname).AppendLine(); } string str = StringHandlers.CToString(newHdr.c_filesys); if (!string.IsNullOrEmpty(str)) { sb.AppendFormat("Dumped filesystem name: {0}", str).AppendLine(); } str = StringHandlers.CToString(newHdr.c_dev); if (!string.IsNullOrEmpty(str)) { sb.AppendFormat("Dumped device: {0}", str).AppendLine(); } str = StringHandlers.CToString(newHdr.c_host); if (!string.IsNullOrEmpty(str)) { sb.AppendFormat("Dump hostname: {0}", str).AppendLine(); } } information = sb.ToString(); }
public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset) { partitions = new List <Partition>(); // Xbox partitions always start on 0 if (sectorOffset != 0) { return(false); } byte[] sector = imagePlugin.ReadSector(0); if (sector.Length < 512) { return(false); } Xbox360DevKitPartitionTable table = BigEndianMarshal.ByteArrayToStructureBigEndian <Xbox360DevKitPartitionTable>(sector); if (table.magic == XBOX360_DEVKIT_MAGIC && table.contentOff + table.contentLen <= imagePlugin.Info.Sectors && table.dashboardOff + table.dashboardLen <= imagePlugin.Info.Sectors) { Partition contentPart = new Partition { Description = "Content volume", Size = (ulong)table.contentLen * imagePlugin.Info.SectorSize, Length = table.contentLen, Sequence = 1, Offset = (ulong)table.contentOff * imagePlugin.Info.SectorSize, Start = table.contentOff, Scheme = Name }; Partition dashboardPart = new Partition { Description = "Dashboard volume", Size = (ulong)table.dashboardLen * imagePlugin.Info.SectorSize, Length = table.dashboardLen, Sequence = 2, Offset = (ulong)table.dashboardOff * imagePlugin.Info.SectorSize, Start = table.dashboardOff, Scheme = Name }; partitions.Add(contentPart); partitions.Add(dashboardPart); return(true); } uint temp; if (imagePlugin.Info.Sectors > (ulong)(MemoryUnitDataOff / imagePlugin.Info.SectorSize)) { sector = imagePlugin.ReadSector((ulong)(MemoryUnitDataOff / imagePlugin.Info.SectorSize)); temp = BitConverter.ToUInt32(sector, 0); if (temp == XboxCigam) { Partition sysCachePart = new Partition { Description = "System cache", Size = MemoryUnitDataOff, Length = (ulong)(MemoryUnitDataOff / imagePlugin.Info.SectorSize), Sequence = 1, Offset = 0, Start = 0, Scheme = Name }; Partition dataPart = new Partition { Description = "Data volume", Size = imagePlugin.Info.Sectors * imagePlugin.Info.SectorSize - MemoryUnitDataOff, Length = imagePlugin.Info.Sectors - sysCachePart.Length, Sequence = 2, Offset = MemoryUnitDataOff, Start = sysCachePart.Length, Scheme = Name }; partitions.Add(sysCachePart); partitions.Add(dataPart); return(true); } } if (imagePlugin.Info.Sectors <= (ulong)(Xbox360DataOff / imagePlugin.Info.SectorSize)) { return(false); } { sector = imagePlugin.ReadSector((ulong)(Xbox360DataOff / imagePlugin.Info.SectorSize)); temp = BitConverter.ToUInt32(sector, 0); if (temp != XboxCigam) { return(false); } Partition securityPart = new Partition { Description = "Security sectors", Size = Xbox360SecuritySectorLen, Length = (ulong)(Xbox360SecuritySectorLen / imagePlugin.Info.SectorSize), Sequence = 1, Offset = Xbox360SecuritySectorOff, Start = (ulong)(Xbox360SecuritySectorOff / imagePlugin.Info.SectorSize), Scheme = Name }; Partition sysCachePart = new Partition { Description = "System cache", Size = Xbox360SystemCacheLen, Length = (ulong)(Xbox360SystemCacheLen / imagePlugin.Info.SectorSize), Sequence = 2, Offset = Xbox360SystemCacheOff, Start = (ulong)(Xbox360SystemCacheOff / imagePlugin.Info.SectorSize), Scheme = Name }; Partition gameCachePart = new Partition { Description = "Game cache", Size = Xbox360GameCacheLen, Length = (ulong)(Xbox360GameCacheLen / imagePlugin.Info.SectorSize), Sequence = 3, Offset = Xbox360GameCacheOff, Start = (ulong)(Xbox360GameCacheOff / imagePlugin.Info.SectorSize), Scheme = Name }; Partition sysExtPart = new Partition { Description = "System volume", Size = Xbox368SysExtLen, Length = (ulong)(Xbox368SysExtLen / imagePlugin.Info.SectorSize), Sequence = 4, Offset = Xbox368SysExtOff, Start = (ulong)(Xbox368SysExtOff / imagePlugin.Info.SectorSize), Scheme = Name }; Partition sysExt2Part = new Partition { Description = "System volume 2", Size = Xbox360SysExt2Len, Length = (ulong)(Xbox360SysExt2Len / imagePlugin.Info.SectorSize), Sequence = 5, Offset = Xbox360SysExt2Off, Start = (ulong)(Xbox360SysExt2Off / imagePlugin.Info.SectorSize), Scheme = Name }; Partition xbox1Part = new Partition { Description = "Xbox backwards compatibility", Size = Xbox360CompatLen, Length = (ulong)(Xbox360CompatLen / imagePlugin.Info.SectorSize), Sequence = 6, Offset = Xbox360CompatOff, Start = (ulong)(Xbox360CompatOff / imagePlugin.Info.SectorSize), Scheme = Name }; Partition dataPart = new Partition { Description = "Data volume", Sequence = 7, Offset = Xbox360DataOff, Start = (ulong)(Xbox360DataOff / imagePlugin.Info.SectorSize), Scheme = Name }; dataPart.Length = imagePlugin.Info.Sectors - dataPart.Start; dataPart.Size = dataPart.Length * imagePlugin.Info.SectorSize; partitions.Add(securityPart); partitions.Add(sysCachePart); partitions.Add(gameCachePart); partitions.Add(sysExtPart); partitions.Add(sysExt2Part); partitions.Add(xbox1Part); partitions.Add(dataPart); return(true); } }
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); information = ""; StringBuilder 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); IntPtr sbPtr = Marshal.AllocHGlobal(ufs_sb_sectors.Length); Marshal.Copy(ufs_sb_sectors, 0, sbPtr, ufs_sb_sectors.Length); UFSSuperBlock ufs_sb = (UFSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(UFSSuperBlock)); Marshal.FreeHGlobal(sbPtr); UFSSuperBlock bs_sfu = BigEndianMarshal.ByteArrayToStructureBigEndian <UFSSuperBlock>(ufs_sb_sectors); if (bs_sfu.fs_magic == UFS_MAGIC && ufs_sb.fs_magic == UFS_CIGAM || bs_sfu.fs_magic == UFS_MAGIC_BW && ufs_sb.fs_magic == UFS_CIGAM_BW || bs_sfu.fs_magic == UFS2_MAGIC && ufs_sb.fs_magic == UFS2_CIGAM || bs_sfu.fs_magic == UFS_BAD_MAGIC && ufs_sb.fs_magic == UFS_BAD_CIGAM) { ufs_sb = bs_sfu; ufs_sb.fs_old_cstotal.cs_nbfree = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nbfree); ufs_sb.fs_old_cstotal.cs_ndir = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_ndir); ufs_sb.fs_old_cstotal.cs_nffree = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nffree); ufs_sb.fs_old_cstotal.cs_nifree = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nifree); ufs_sb.fs_cstotal.cs_numclusters = Swapping.Swap(ufs_sb.fs_cstotal.cs_numclusters); ufs_sb.fs_cstotal.cs_nbfree = Swapping.Swap(ufs_sb.fs_cstotal.cs_nbfree); ufs_sb.fs_cstotal.cs_ndir = Swapping.Swap(ufs_sb.fs_cstotal.cs_ndir); ufs_sb.fs_cstotal.cs_nffree = Swapping.Swap(ufs_sb.fs_cstotal.cs_nffree); ufs_sb.fs_cstotal.cs_nifree = Swapping.Swap(ufs_sb.fs_cstotal.cs_nifree); ufs_sb.fs_cstotal.cs_spare[0] = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[0]); ufs_sb.fs_cstotal.cs_spare[1] = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[1]); ufs_sb.fs_cstotal.cs_spare[2] = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[2]); } DicConsole.DebugWriteLine("FFS plugin", "ufs_sb offset: 0x{0:X8}", sb_offset); DicConsole.DebugWriteLine("FFS plugin", "fs_rlink: 0x{0:X8}", ufs_sb.fs_rlink); DicConsole.DebugWriteLine("FFS plugin", "fs_sblkno: 0x{0:X8}", ufs_sb.fs_sblkno); DicConsole.DebugWriteLine("FFS plugin", "fs_cblkno: 0x{0:X8}", ufs_sb.fs_cblkno); DicConsole.DebugWriteLine("FFS plugin", "fs_iblkno: 0x{0:X8}", ufs_sb.fs_iblkno); DicConsole.DebugWriteLine("FFS plugin", "fs_dblkno: 0x{0:X8}", ufs_sb.fs_dblkno); DicConsole.DebugWriteLine("FFS plugin", "fs_size: 0x{0:X8}", ufs_sb.fs_size); DicConsole.DebugWriteLine("FFS plugin", "fs_dsize: 0x{0:X8}", ufs_sb.fs_dsize); DicConsole.DebugWriteLine("FFS plugin", "fs_ncg: 0x{0:X8}", ufs_sb.fs_ncg); DicConsole.DebugWriteLine("FFS plugin", "fs_bsize: 0x{0:X8}", ufs_sb.fs_bsize); DicConsole.DebugWriteLine("FFS plugin", "fs_fsize: 0x{0:X8}", ufs_sb.fs_fsize); DicConsole.DebugWriteLine("FFS plugin", "fs_frag: 0x{0:X8}", ufs_sb.fs_frag); DicConsole.DebugWriteLine("FFS plugin", "fs_minfree: 0x{0:X8}", ufs_sb.fs_minfree); DicConsole.DebugWriteLine("FFS plugin", "fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask); DicConsole.DebugWriteLine("FFS plugin", "fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask); DicConsole.DebugWriteLine("FFS plugin", "fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift); DicConsole.DebugWriteLine("FFS plugin", "fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift); DicConsole.DebugWriteLine("FFS plugin", "fs_maxcontig: 0x{0:X8}", ufs_sb.fs_maxcontig); DicConsole.DebugWriteLine("FFS plugin", "fs_maxbpg: 0x{0:X8}", ufs_sb.fs_maxbpg); DicConsole.DebugWriteLine("FFS plugin", "fs_fragshift: 0x{0:X8}", ufs_sb.fs_fragshift); DicConsole.DebugWriteLine("FFS plugin", "fs_fsbtodb: 0x{0:X8}", ufs_sb.fs_fsbtodb); DicConsole.DebugWriteLine("FFS plugin", "fs_sbsize: 0x{0:X8}", ufs_sb.fs_sbsize); DicConsole.DebugWriteLine("FFS plugin", "fs_csmask: 0x{0:X8}", ufs_sb.fs_csmask); DicConsole.DebugWriteLine("FFS plugin", "fs_csshift: 0x{0:X8}", ufs_sb.fs_csshift); DicConsole.DebugWriteLine("FFS plugin", "fs_nindir: 0x{0:X8}", ufs_sb.fs_nindir); DicConsole.DebugWriteLine("FFS plugin", "fs_inopb: 0x{0:X8}", ufs_sb.fs_inopb); DicConsole.DebugWriteLine("FFS plugin", "fs_optim: 0x{0:X8}", ufs_sb.fs_optim); DicConsole.DebugWriteLine("FFS plugin", "fs_id_1: 0x{0:X8}", ufs_sb.fs_id_1); DicConsole.DebugWriteLine("FFS plugin", "fs_id_2: 0x{0:X8}", ufs_sb.fs_id_2); DicConsole.DebugWriteLine("FFS plugin", "fs_csaddr: 0x{0:X8}", ufs_sb.fs_csaddr); DicConsole.DebugWriteLine("FFS plugin", "fs_cssize: 0x{0:X8}", ufs_sb.fs_cssize); DicConsole.DebugWriteLine("FFS plugin", "fs_cgsize: 0x{0:X8}", ufs_sb.fs_cgsize); DicConsole.DebugWriteLine("FFS plugin", "fs_ipg: 0x{0:X8}", ufs_sb.fs_ipg); DicConsole.DebugWriteLine("FFS plugin", "fs_fpg: 0x{0:X8}", ufs_sb.fs_fpg); DicConsole.DebugWriteLine("FFS plugin", "fs_fmod: 0x{0:X2}", ufs_sb.fs_fmod); DicConsole.DebugWriteLine("FFS plugin", "fs_clean: 0x{0:X2}", ufs_sb.fs_clean); DicConsole.DebugWriteLine("FFS plugin", "fs_ronly: 0x{0:X2}", ufs_sb.fs_ronly); DicConsole.DebugWriteLine("FFS plugin", "fs_flags: 0x{0:X2}", ufs_sb.fs_flags); DicConsole.DebugWriteLine("FFS plugin", "fs_magic: 0x{0:X8}", ufs_sb.fs_magic); if (ufs_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 (ufs_sb.fs_link > 0) { fs_type_42bsd = true; // It was used in 4.2BSD fs_type_43bsd = false; } if ((ufs_sb.fs_maxfilesize & 0xFFFFFFFF) > SunOSEpoch && DateHandlers.UnixUnsignedToDateTime(ufs_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 (ufs_sb.fs_old_npsect > SunOSEpoch && DateHandlers.UnixToDateTime(ufs_sb.fs_old_npsect) < DateTime.Now ) { fs_type_42bsd = false; fs_type_sun86 = true; fs_type_sun = false; fs_type_43bsd = false; } if (ufs_sb.fs_cgrotor > 0x00000000 && (uint)ufs_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 &= ufs_sb.fs_id_2 == 0 && ufs_sb.fs_id_1 == 0; // This is the only 4.4BSD inode format fs_type_44bsd |= ufs_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}", ufs_sb.fs_link).AppendLine(); } sbInformation.AppendFormat("Superblock LBA: {0}", ufs_sb.fs_sblkno).AppendLine(); sbInformation.AppendFormat("Cylinder-block LBA: {0}", ufs_sb.fs_cblkno).AppendLine(); sbInformation.AppendFormat("inode-block LBA: {0}", ufs_sb.fs_iblkno).AppendLine(); sbInformation.AppendFormat("First data block LBA: {0}", ufs_sb.fs_dblkno).AppendLine(); sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_old_cgoffset).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_old_time)) .AppendLine(); XmlFsType.ModificationDate = DateHandlers.UnixToDateTime(ufs_sb.fs_old_time); XmlFsType.ModificationDateSpecified = true; sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_old_size, (long)ufs_sb.fs_old_size * ufs_sb.fs_fsize).AppendLine(); XmlFsType.Clusters = ufs_sb.fs_old_size; XmlFsType.ClusterSize = ufs_sb.fs_fsize; sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_old_dsize, (long)ufs_sb.fs_old_dsize * ufs_sb.fs_fsize).AppendLine(); sbInformation.AppendFormat("{0} cylinder groups in volume", ufs_sb.fs_ncg).AppendLine(); sbInformation.AppendFormat("{0} bytes in a basic block", ufs_sb.fs_bsize).AppendLine(); sbInformation.AppendFormat("{0} bytes in a frag block", ufs_sb.fs_fsize).AppendLine(); sbInformation.AppendFormat("{0} frags in a block", ufs_sb.fs_frag).AppendLine(); sbInformation.AppendFormat("{0}% of blocks must be free", ufs_sb.fs_minfree).AppendLine(); sbInformation.AppendFormat("{0}ms for optimal next block", ufs_sb.fs_old_rotdelay).AppendLine(); sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", ufs_sb.fs_old_rps, ufs_sb.fs_old_rps * 60).AppendLine(); /* sbInformation.AppendFormat("fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask).AppendLine(); * sbInformation.AppendFormat("fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask).AppendLine(); * sbInformation.AppendFormat("fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift).AppendLine(); * sbInformation.AppendFormat("fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift).AppendLine();*/ sbInformation.AppendFormat("{0} contiguous blocks at maximum", ufs_sb.fs_maxcontig).AppendLine(); sbInformation.AppendFormat("{0} blocks per cylinder group at maximum", ufs_sb.fs_maxbpg).AppendLine(); sbInformation.AppendFormat("Superblock is {0} bytes", ufs_sb.fs_sbsize).AppendLine(); sbInformation.AppendFormat("NINDIR: 0x{0:X8}", ufs_sb.fs_nindir).AppendLine(); sbInformation.AppendFormat("INOPB: 0x{0:X8}", ufs_sb.fs_inopb).AppendLine(); sbInformation.AppendFormat("NSPF: 0x{0:X8}", ufs_sb.fs_old_nspf).AppendLine(); switch (ufs_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}", ufs_sb.fs_optim).AppendLine(); break; } if (fs_type_sun) { sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_npsect).AppendLine(); } else if (fs_type_sun86) { sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_old_npsect)) .AppendLine(); } sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_old_interleave).AppendLine(); sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_old_trackskew).AppendLine(); if (!fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0) { sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2).AppendLine(); } else if (fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0) { sbInformation.AppendFormat("{0} µsec for head switch", ufs_sb.fs_id_1).AppendLine(); sbInformation.AppendFormat("{0} µsec for track-to-track seek", ufs_sb.fs_id_2).AppendLine(); } sbInformation.AppendFormat("Cylinder group summary LBA: {0}", ufs_sb.fs_old_csaddr).AppendLine(); sbInformation.AppendFormat("{0} bytes in cylinder group summary", ufs_sb.fs_cssize).AppendLine(); sbInformation.AppendFormat("{0} bytes in cylinder group", ufs_sb.fs_cgsize).AppendLine(); sbInformation.AppendFormat("{0} tracks/cylinder", ufs_sb.fs_old_ntrak).AppendLine(); sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_nsect).AppendLine(); sbInformation.AppendFormat("{0} sectors/cylinder", ufs_sb.fs_old_spc).AppendLine(); sbInformation.AppendFormat("{0} cylinder in volume", ufs_sb.fs_old_ncyl).AppendLine(); sbInformation.AppendFormat("{0} cylinders/group", ufs_sb.fs_old_cpg).AppendLine(); sbInformation.AppendFormat("{0} inodes per cylinder group", ufs_sb.fs_ipg).AppendLine(); sbInformation.AppendFormat("{0} blocks per group", ufs_sb.fs_fpg / ufs_sb.fs_frag).AppendLine(); sbInformation.AppendFormat("{0} directories", ufs_sb.fs_old_cstotal.cs_ndir).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_old_cstotal.cs_nbfree, (long)ufs_sb.fs_old_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine(); XmlFsType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree; XmlFsType.FreeClustersSpecified = true; sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_old_cstotal.cs_nifree).AppendLine(); sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_old_cstotal.cs_nffree).AppendLine(); if (ufs_sb.fs_fmod == 1) { sbInformation.AppendLine("Superblock is under modification"); XmlFsType.Dirty = true; } if (ufs_sb.fs_clean == 1) { sbInformation.AppendLine("Volume is clean"); } if (ufs_sb.fs_ronly == 1) { sbInformation.AppendLine("Volume is read-only"); } sbInformation.AppendFormat("Volume flags: 0x{0:X2}", ufs_sb.fs_flags).AppendLine(); if (fs_type_ufs) { sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(ufs_sb.fs_fsmnt)) .AppendLine(); } else if (fs_type_ufs2) { sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(ufs_sb.fs_fsmnt)) .AppendLine(); sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(ufs_sb.fs_volname)) .AppendLine(); XmlFsType.VolumeName = StringHandlers.CToString(ufs_sb.fs_volname); sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid).AppendLine(); //xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid); sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor).AppendLine(); sbInformation.AppendFormat("{0} contiguously allocated directories", ufs_sb.fs_contigdirs).AppendLine(); sbInformation.AppendFormat("Standard superblock LBA: {0}", ufs_sb.fs_sblkno).AppendLine(); sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal.cs_ndir).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal.cs_nbfree, ufs_sb.fs_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine(); XmlFsType.FreeClusters = ufs_sb.fs_cstotal.cs_nbfree; XmlFsType.FreeClustersSpecified = true; sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal.cs_nifree).AppendLine(); sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal.cs_nffree).AppendLine(); sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal.cs_numclusters).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_time)) .AppendLine(); XmlFsType.ModificationDate = DateHandlers.UnixToDateTime(ufs_sb.fs_time); XmlFsType.ModificationDateSpecified = true; sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_fsize) .AppendLine(); XmlFsType.Clusters = ufs_sb.fs_size; sbInformation .AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_fsize) .AppendLine(); sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", ufs_sb.fs_csaddr).AppendLine(); sbInformation.AppendFormat("{0} blocks pending of being freed", ufs_sb.fs_pendingblocks).AppendLine(); sbInformation.AppendFormat("{0} inodes pending of being freed", ufs_sb.fs_pendinginodes).AppendLine(); } if (fs_type_sun) { sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_old_npsect)) .AppendLine(); } else if (fs_type_sun86) { sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_state).AppendLine(); } else if (fs_type_44bsd) { sbInformation.AppendFormat("{0} blocks on cluster summary array", ufs_sb.fs_contigsumsize).AppendLine(); sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", ufs_sb.fs_maxsymlinklen) .AppendLine(); sbInformation.AppendFormat("A file can be {0} bytes at max", ufs_sb.fs_maxfilesize).AppendLine(); sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_state)) .AppendLine(); } if (ufs_sb.fs_old_nrpos > 0) { sbInformation.AppendFormat("{0} rotational positions", ufs_sb.fs_old_nrpos).AppendLine(); } if (ufs_sb.fs_old_rotbloff > 0) { sbInformation.AppendFormat("{0} blocks per rotation", ufs_sb.fs_old_rotbloff).AppendLine(); } information = sbInformation.ToString(); }
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); OperaSuperBlock sb = BigEndianMarshal.ByteArrayToStructureBigEndian <OperaSuperBlock>(sbSector); sb.sync_bytes = new byte[5]; if (sb.record_type != 1 || sb.record_version != 1) { return; } if (Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ") { 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 ((ulong)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 }; }