From 430d71693a1f39aac4e53501ed282f5530c2cc42 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 14 Apr 2014 02:29:13 +0000 Subject: [PATCH] Refactor and reformat code git-svn-id: svn://claunia.com/FileSystemIDandChk@29 17725271-3d32-4980-a8cb-9ff532f270ba --- FileSystemIDandChk/BigEndianBitConverter.cs | 57 +- FileSystemIDandChk/ChangeLog | 36 + FileSystemIDandChk/DateHandlers.cs | 158 +- FileSystemIDandChk/EndianAwareBinaryReader.cs | 225 ++- FileSystemIDandChk/FileSystemIDandChk.csproj | 57 + FileSystemIDandChk/ImagePlugins/CDRWin.cs | 80 +- .../ImagePlugins/ImagePlugin.cs | 2 +- FileSystemIDandChk/Main.cs | 294 ++-- FileSystemIDandChk/PartPlugins/AppleMap.cs | 222 +-- FileSystemIDandChk/PartPlugins/MBR.cs | 138 +- FileSystemIDandChk/PartPlugins/NeXT.cs | 11 +- FileSystemIDandChk/Plugins.cs | 68 +- FileSystemIDandChk/Plugins/AppleHFS.cs | 466 +++--- FileSystemIDandChk/Plugins/AppleHFSPlus.cs | 671 ++++---- FileSystemIDandChk/Plugins/AppleMFS.cs | 393 +++-- FileSystemIDandChk/Plugins/BFS.cs | 352 ++-- FileSystemIDandChk/Plugins/FAT.cs | 503 +++--- FileSystemIDandChk/Plugins/FFS.cs | 1466 +++++++++-------- FileSystemIDandChk/Plugins/HPFS.cs | 424 ++--- FileSystemIDandChk/Plugins/ISO9660.cs | 78 +- FileSystemIDandChk/Plugins/MinixFS.cs | 356 ++-- FileSystemIDandChk/Plugins/NTFS.cs | 219 +-- FileSystemIDandChk/Plugins/ODS.cs | 442 ++--- FileSystemIDandChk/Plugins/Opera.cs | 119 +- FileSystemIDandChk/Plugins/PCEngine.cs | 34 +- FileSystemIDandChk/Plugins/Plugin.cs | 1 - FileSystemIDandChk/Plugins/SolarFS.cs | 173 +- FileSystemIDandChk/Plugins/SysV.cs | 921 ++++++----- FileSystemIDandChk/Plugins/UNIXBFS.cs | 137 +- FileSystemIDandChk/Plugins/ext2FS.cs | 1455 ++++++++-------- FileSystemIDandChk/Plugins/extFS.cs | 137 +- FileSystemIDandChk/StringHandlers.cs | 48 +- FileSystemIDandChk/Swapping.cs | 16 +- 33 files changed, 5333 insertions(+), 4426 deletions(-) diff --git a/FileSystemIDandChk/BigEndianBitConverter.cs b/FileSystemIDandChk/BigEndianBitConverter.cs index f9332486..872f12f8 100644 --- a/FileSystemIDandChk/BigEndianBitConverter.cs +++ b/FileSystemIDandChk/BigEndianBitConverter.cs @@ -15,8 +15,8 @@ namespace FileSystemIDandChk /// Indicates the byte order ("endianess") in which data is stored in this computer /// architecture. /// - public static bool IsLittleEndian { get; set; } // should default to false, which is what we want for Empire - + public static bool IsLittleEndian { get; set; } + // should default to false, which is what we want for Empire /// /// Converts the specified double-precision floating point number to a 64-bit /// signed integer. @@ -28,7 +28,11 @@ namespace FileSystemIDandChk /// Returns: /// A 64-bit signed integer whose value is equivalent to value. /// - public static long DoubleToInt64Bits(double value) { throw new NotImplementedException(); } + public static long DoubleToInt64Bits(double value) + { + throw new NotImplementedException(); + } + /// /// /// Returns the specified Boolean value as an array of bytes. @@ -44,6 +48,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified Unicode character value as an array of bytes. @@ -59,6 +64,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified double-precision floating point value as an array of @@ -75,6 +81,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified single-precision floating point value as an array of @@ -91,6 +98,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified 32-bit signed integer value as an array of bytes. @@ -106,6 +114,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified 64-bit signed integer value as an array of bytes. @@ -121,6 +130,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified 16-bit signed integer value as an array of bytes. @@ -136,6 +146,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified 32-bit unsigned integer value as an array of bytes. @@ -147,11 +158,12 @@ namespace FileSystemIDandChk /// Returns: /// An array of bytes with length 4. /// - [CLSCompliant(false)] + //[CLSCompliant(false)] public static byte[] GetBytes(uint value) { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified 64-bit unsigned integer value as an array of bytes. @@ -163,11 +175,12 @@ namespace FileSystemIDandChk /// Returns: /// An array of bytes with length 8. /// - [CLSCompliant(false)] + //[CLSCompliant(false)] public static byte[] GetBytes(ulong value) { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Returns the specified 16-bit unsigned integer value as an array of bytes. @@ -183,6 +196,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray(); } + /// /// /// Converts the specified 64-bit signed integer to a double-precision floating @@ -195,7 +209,11 @@ namespace FileSystemIDandChk /// Returns: /// A double-precision floating point number whose value is equivalent to value. /// - public static double Int64BitsToDouble(long value) { throw new NotImplementedException(); } + public static double Int64BitsToDouble(long value) + { + throw new NotImplementedException(); + } + /// /// /// Returns a Boolean value converted from one byte at a specified position in @@ -218,7 +236,11 @@ namespace FileSystemIDandChk /// System.ArgumentOutOfRangeException: /// startIndex is less than zero or greater than the length of value minus 1. /// - public static bool ToBoolean(byte[] value, int startIndex) { throw new NotImplementedException(); } + public static bool ToBoolean(byte[] value, int startIndex) + { + throw new NotImplementedException(); + } + /// /// /// Returns a Unicode character converted from two bytes at a specified position @@ -244,7 +266,11 @@ namespace FileSystemIDandChk /// System.ArgumentOutOfRangeException: /// startIndex is less than zero or greater than the length of value minus 1. /// - public static char ToChar(byte[] value, int startIndex) { throw new NotImplementedException(); } + public static char ToChar(byte[] value, int startIndex) + { + throw new NotImplementedException(); + } + /// /// /// Returns a double-precision floating point number converted from eight bytes @@ -272,7 +298,11 @@ namespace FileSystemIDandChk /// System.ArgumentOutOfRangeException: /// startIndex is less than zero or greater than the length of value minus 1. /// - public static double ToDouble(byte[] value, int startIndex) { throw new NotImplementedException(); } + public static double ToDouble(byte[] value, int startIndex) + { + throw new NotImplementedException(); + } + /// /// /// Returns a 16-bit signed integer converted from two bytes at a specified position @@ -302,6 +332,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToInt16(value, startIndex) : BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(Int16) - startIndex); } + /// /// /// Returns a 32-bit signed integer converted from four bytes at a specified @@ -332,6 +363,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToInt32(value, startIndex) : BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(Int32) - startIndex); } + /// /// /// Returns a 64-bit signed integer converted from eight bytes at a specified @@ -362,6 +394,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToInt64(value, startIndex) : BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(Int64) - startIndex); } + /// /// /// Returns a single-precision floating point number converted from four bytes @@ -393,6 +426,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToSingle(value, startIndex) : BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(Single) - startIndex); } + /// /// /// Converts the numeric value of each element of a specified array of bytes @@ -414,6 +448,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToString(value) : BitConverter.ToString(value.Reverse().ToArray()); } + /// /// /// Converts the numeric value of each element of a specified subarray of bytes @@ -442,6 +477,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToString(value, startIndex) : BitConverter.ToString(value.Reverse().ToArray(), startIndex); } + /// /// /// Converts the numeric value of each element of a specified subarray of bytes @@ -479,6 +515,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToString(value, startIndex, length) : BitConverter.ToString(value.Reverse().ToArray(), startIndex, length); } + /// /// /// Returns a 16-bit unsigned integer converted from two bytes at a specified @@ -508,6 +545,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToUInt16(value, startIndex) : BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(UInt16) - startIndex); } + /// /// /// Returns a 32-bit unsigned integer converted from four bytes at a specified @@ -538,6 +576,7 @@ namespace FileSystemIDandChk { return !IsLittleEndian ? BitConverter.ToUInt32(value, startIndex) : BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(UInt32) - startIndex); } + /// /// /// Returns a 64-bit unsigned integer converted from eight bytes at a specified diff --git a/FileSystemIDandChk/ChangeLog b/FileSystemIDandChk/ChangeLog index 0a0d6642..1382a1d2 100644 --- a/FileSystemIDandChk/ChangeLog +++ b/FileSystemIDandChk/ChangeLog @@ -1,3 +1,39 @@ +2014-04-14 Natalia Portillo + + * Main.cs: + * Plugins.cs: + * Swapping.cs: + * Plugins/BFS.cs: + * Plugins/FAT.cs: + * Plugins/FFS.cs: + * Plugins/ODS.cs: + * Plugins/NTFS.cs: + * Plugins/HPFS.cs: + * DateHandlers.cs: + * Plugins/SysV.cs: + * Plugins/extFS.cs: + * Plugins/Opera.cs: + * Plugins/Plugin.cs: + * StringHandlers.cs: + * Plugins/ext2FS.cs: + * Plugins/SolarFS.cs: + * Plugins/UNIXBFS.cs: + * Plugins/MinixFS.cs: + * Plugins/ISO9660.cs: + * PartPlugins/MBR.cs: + * Plugins/AppleMFS.cs: + * PartPlugins/NeXT.cs: + * Plugins/PCEngine.cs: + * Plugins/AppleHFS.cs: + * ImagePlugins/CDRWin.cs: + * PartPlugins/AppleMap.cs: + * Plugins/AppleHFSPlus.cs: + * BigEndianBitConverter.cs: + * FileSystemIDandChk.csproj: + * EndianAwareBinaryReader.cs: + * ImagePlugins/ImagePlugin.cs: + Refactor and reformat code + 2014-04-14 Natalia Portillo * Main.cs: diff --git a/FileSystemIDandChk/DateHandlers.cs b/FileSystemIDandChk/DateHandlers.cs index b889c710..889fdb21 100644 --- a/FileSystemIDandChk/DateHandlers.cs +++ b/FileSystemIDandChk/DateHandlers.cs @@ -2,103 +2,103 @@ using System; namespace FileSystemIDandChk { - public static class DateHandlers - { - private static DateTime MacEpoch = new DateTime(1904, 1, 1, 0, 0, 0); - private static DateTime UNIXEpoch = new DateTime(1970, 1, 1, 0, 0, 0); - private static DateTime JulianEpoch = new DateTime(1858, 11, 17, 0, 0, 0); // Day 0 of Julian Date system + public static class DateHandlers + { + static readonly DateTime MacEpoch = new DateTime(1904, 1, 1, 0, 0, 0); + static readonly DateTime UNIXEpoch = new DateTime(1970, 1, 1, 0, 0, 0); + static readonly DateTime JulianEpoch = new DateTime(1858, 11, 17, 0, 0, 0); + // Day 0 of Julian Date system + public static DateTime MacToDateTime(ulong MacTimeStamp) + { + return MacEpoch.AddTicks((long)(MacTimeStamp * 10000000)); + } - public static DateTime MacToDateTime(ulong MacTimeStamp) - { - return MacEpoch.AddTicks((long)(MacTimeStamp*10000000)); - } + public static DateTime UNIXToDateTime(Int32 UNIXTimeStamp) + { + return UNIXEpoch.AddSeconds(UNIXTimeStamp); + } - public static DateTime UNIXToDateTime(Int32 UNIXTimeStamp) - { - return UNIXEpoch.AddSeconds(UNIXTimeStamp); - } + public static DateTime UNIXUnsignedToDateTime(UInt32 UNIXTimeStamp) + { + return UNIXEpoch.AddSeconds(UNIXTimeStamp); + } - public static DateTime UNIXUnsignedToDateTime(UInt32 UNIXTimeStamp) - { - return UNIXEpoch.AddSeconds(UNIXTimeStamp); - } - - public static DateTime ISO9660ToDateTime(byte[] VDDateTime) - { - int year, month, day, hour, minute, second, hundredths; - byte[] twocharvalue = new byte[2]; - byte[] fourcharvalue = new byte[4]; + public static DateTime ISO9660ToDateTime(byte[] VDDateTime) + { + int year, month, day, hour, minute, second, hundredths; + byte[] twocharvalue = new byte[2]; + byte[] fourcharvalue = new byte[4]; - fourcharvalue[0] = VDDateTime[0]; - fourcharvalue[1] = VDDateTime[1]; - fourcharvalue[2] = VDDateTime[2]; - fourcharvalue[3] = VDDateTime[3]; - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: year = \"{0}\"",StringHandlers.CToString(fourcharvalue)); - if(!Int32.TryParse(StringHandlers.CToString(fourcharvalue), out year)) - year = 0; + fourcharvalue[0] = VDDateTime[0]; + fourcharvalue[1] = VDDateTime[1]; + fourcharvalue[2] = VDDateTime[2]; + fourcharvalue[3] = VDDateTime[3]; + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: year = \"{0}\"", StringHandlers.CToString(fourcharvalue)); + if (!Int32.TryParse(StringHandlers.CToString(fourcharvalue), out year)) + year = 0; // year = Convert.ToInt32(StringHandlers.CToString(fourcharvalue)); - twocharvalue[0] = VDDateTime[4]; - twocharvalue[1] = VDDateTime[5]; - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: month = \"{0}\"",StringHandlers.CToString(twocharvalue)); - if(!Int32.TryParse(StringHandlers.CToString(twocharvalue), out month)) - month = 0; + twocharvalue[0] = VDDateTime[4]; + twocharvalue[1] = VDDateTime[5]; + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: month = \"{0}\"", StringHandlers.CToString(twocharvalue)); + if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out month)) + month = 0; // month = Convert.ToInt32(StringHandlers.CToString(twocharvalue)); - twocharvalue[0] = VDDateTime[6]; - twocharvalue[1] = VDDateTime[7]; - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: day = \"{0}\"",StringHandlers.CToString(twocharvalue)); - if(!Int32.TryParse(StringHandlers.CToString(twocharvalue), out day)) - day = 0; + twocharvalue[0] = VDDateTime[6]; + twocharvalue[1] = VDDateTime[7]; + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: day = \"{0}\"", StringHandlers.CToString(twocharvalue)); + if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out day)) + day = 0; // day = Convert.ToInt32(StringHandlers.CToString(twocharvalue)); - twocharvalue[0] = VDDateTime[8]; - twocharvalue[1] = VDDateTime[9]; - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: hour = \"{0}\"",StringHandlers.CToString(twocharvalue)); - if(!Int32.TryParse(StringHandlers.CToString(twocharvalue), out hour)) - hour = 0; + twocharvalue[0] = VDDateTime[8]; + twocharvalue[1] = VDDateTime[9]; + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: hour = \"{0}\"", StringHandlers.CToString(twocharvalue)); + if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out hour)) + hour = 0; // hour = Convert.ToInt32(StringHandlers.CToString(twocharvalue)); - twocharvalue[0] = VDDateTime[10]; - twocharvalue[1] = VDDateTime[11]; - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: minute = \"{0}\"",StringHandlers.CToString(twocharvalue)); - if(!Int32.TryParse(StringHandlers.CToString(twocharvalue), out minute)) - minute = 0; + twocharvalue[0] = VDDateTime[10]; + twocharvalue[1] = VDDateTime[11]; + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: minute = \"{0}\"", StringHandlers.CToString(twocharvalue)); + if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out minute)) + minute = 0; // minute = Convert.ToInt32(StringHandlers.CToString(twocharvalue)); - twocharvalue[0] = VDDateTime[12]; - twocharvalue[1] = VDDateTime[13]; - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: second = \"{0}\"",StringHandlers.CToString(twocharvalue)); - if(!Int32.TryParse(StringHandlers.CToString(twocharvalue), out second)) - second = 0; + twocharvalue[0] = VDDateTime[12]; + twocharvalue[1] = VDDateTime[13]; + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: second = \"{0}\"", StringHandlers.CToString(twocharvalue)); + if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out second)) + second = 0; // second = Convert.ToInt32(StringHandlers.CToString(twocharvalue)); - twocharvalue[0] = VDDateTime[14]; - twocharvalue[1] = VDDateTime[15]; - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: hundredths = \"{0}\"",StringHandlers.CToString(twocharvalue)); - if(!Int32.TryParse(StringHandlers.CToString(twocharvalue), out hundredths)) - hundredths = 0; + twocharvalue[0] = VDDateTime[14]; + twocharvalue[1] = VDDateTime[15]; + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: hundredths = \"{0}\"", StringHandlers.CToString(twocharvalue)); + if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out hundredths)) + hundredths = 0; // hundredths = Convert.ToInt32(StringHandlers.CToString(twocharvalue)); - if(MainClass.isDebug) - Console.WriteLine("ISO9600ToDateTime: decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);", year, month, day, hour, minute, second, hundredths *10); DateTime decodedDT = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Unspecified); + if (MainClass.isDebug) + Console.WriteLine("ISO9600ToDateTime: decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);", year, month, day, hour, minute, second, hundredths * 10); + DateTime decodedDT = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Unspecified); - return decodedDT; - } - - // C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC - public static DateTime VMSToDateTime(UInt64 vmsDate) - { - double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail - return JulianEpoch.AddMilliseconds(delta); - } - } + return decodedDT; + } + // C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC + public static DateTime VMSToDateTime(UInt64 vmsDate) + { + double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail + return JulianEpoch.AddMilliseconds(delta); + } + } } diff --git a/FileSystemIDandChk/EndianAwareBinaryReader.cs b/FileSystemIDandChk/EndianAwareBinaryReader.cs index d2c1d474..4d81550a 100644 --- a/FileSystemIDandChk/EndianAwareBinaryReader.cs +++ b/FileSystemIDandChk/EndianAwareBinaryReader.cs @@ -5,123 +5,120 @@ using System.Text; namespace FileSystemIDandChk { - public class EndianAwareBinaryReader : BinaryReader - { - private bool isLittleEndian; - private byte[] buffer = new byte[8]; - - public EndianAwareBinaryReader(Stream input, Encoding encoding, bool isLittleEndian) + public class EndianAwareBinaryReader : BinaryReader + { + byte[] buffer = new byte[8]; + + public EndianAwareBinaryReader(Stream input, Encoding encoding, bool isLittleEndian) : base(input, encoding) - { - this.isLittleEndian = isLittleEndian; - } - - public EndianAwareBinaryReader(Stream input, bool isLittleEndian) + { + IsLittleEndian = isLittleEndian; + } + + public EndianAwareBinaryReader(Stream input, bool isLittleEndian) : this(input, Encoding.UTF8, isLittleEndian) - { - } - - public bool IsLittleEndian - { - get { return isLittleEndian; } - set { isLittleEndian = value; } - } - - - public override double ReadDouble() - { - if (isLittleEndian) - return base.ReadDouble(); - FillMyBuffer(8); - return BitConverter.ToDouble(buffer.Take(8).Reverse().ToArray(), 0); - } - - public override short ReadInt16() - { - if (isLittleEndian) - return base.ReadInt16(); - FillMyBuffer(2); - return BitConverter.ToInt16(buffer.Take(2).Reverse().ToArray(), 0); + { + } + + public bool IsLittleEndian + { + get; + set; + } + + public override double ReadDouble() + { + if (IsLittleEndian) + return base.ReadDouble(); + FillMyBuffer(8); + return BitConverter.ToDouble(buffer.Take(8).Reverse().ToArray(), 0); + } + + public override short ReadInt16() + { + if (IsLittleEndian) + return base.ReadInt16(); + FillMyBuffer(2); + return BitConverter.ToInt16(buffer.Take(2).Reverse().ToArray(), 0); - } - - public override int ReadInt32() - { - if (isLittleEndian) - return base.ReadInt32(); - FillMyBuffer(4); - return BitConverter.ToInt32(buffer.Take(4).Reverse().ToArray(), 0); + } + + public override int ReadInt32() + { + if (IsLittleEndian) + return base.ReadInt32(); + FillMyBuffer(4); + return BitConverter.ToInt32(buffer.Take(4).Reverse().ToArray(), 0); - } - - public override long ReadInt64() - { - if (isLittleEndian) - return base.ReadInt64(); - FillMyBuffer(8); - return BitConverter.ToInt64(buffer.Take(8).Reverse().ToArray(), 0); + } + + public override long ReadInt64() + { + if (IsLittleEndian) + return base.ReadInt64(); + FillMyBuffer(8); + return BitConverter.ToInt64(buffer.Take(8).Reverse().ToArray(), 0); - } - - public override float ReadSingle() - { - if (isLittleEndian) - return base.ReadSingle(); - FillMyBuffer(4); - return BitConverter.ToSingle(buffer.Take(4).Reverse().ToArray(), 0); - } - - public override ushort ReadUInt16() - { - if (isLittleEndian) - return base.ReadUInt16(); - FillMyBuffer(2); - return BitConverter.ToUInt16(buffer.Take(2).Reverse().ToArray(), 0); - } - - - public override uint ReadUInt32() - { - if (isLittleEndian) - return base.ReadUInt32(); - FillMyBuffer(4); - return BitConverter.ToUInt32(buffer.Take(4).Reverse().ToArray(), 0); - } - - public override ulong ReadUInt64() - { - if (isLittleEndian) - return base.ReadUInt64(); - FillMyBuffer(8); - return BitConverter.ToUInt64(buffer.Take(8).Reverse().ToArray(), 0); - } - - private void FillMyBuffer(int numBytes) - { - int offset = 0; - int num2 = 0; - if (numBytes == 1) - { - num2 = BaseStream.ReadByte(); - if (num2 == -1) - { - throw new EndOfStreamException("Attempted to read past the end of the stream."); - } - buffer[0] = (byte)num2; - } - else - { - do - { - num2 = BaseStream.Read(buffer, offset, numBytes - offset); - if (num2 == 0) - { - throw new EndOfStreamException("Attempted to read past the end of the stream."); - } - offset += num2; - } - while (offset < numBytes); - } - } - } + } + + public override float ReadSingle() + { + if (IsLittleEndian) + return base.ReadSingle(); + FillMyBuffer(4); + return BitConverter.ToSingle(buffer.Take(4).Reverse().ToArray(), 0); + } + + public override ushort ReadUInt16() + { + if (IsLittleEndian) + return base.ReadUInt16(); + FillMyBuffer(2); + return BitConverter.ToUInt16(buffer.Take(2).Reverse().ToArray(), 0); + } + + public override uint ReadUInt32() + { + if (IsLittleEndian) + return base.ReadUInt32(); + FillMyBuffer(4); + return BitConverter.ToUInt32(buffer.Take(4).Reverse().ToArray(), 0); + } + + public override ulong ReadUInt64() + { + if (IsLittleEndian) + return base.ReadUInt64(); + FillMyBuffer(8); + return BitConverter.ToUInt64(buffer.Take(8).Reverse().ToArray(), 0); + } + + void FillMyBuffer(int numBytes) + { + int offset = 0; + int num2; + if (numBytes == 1) + { + num2 = BaseStream.ReadByte(); + if (num2 == -1) + { + throw new EndOfStreamException("Attempted to read past the end of the stream."); + } + buffer[0] = (byte)num2; + } + else + { + do + { + num2 = BaseStream.Read(buffer, offset, numBytes - offset); + if (num2 == 0) + { + throw new EndOfStreamException("Attempted to read past the end of the stream."); + } + offset += num2; + } + while (offset < numBytes); + } + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/FileSystemIDandChk.csproj b/FileSystemIDandChk/FileSystemIDandChk.csproj index cf98534c..0be0c252 100644 --- a/FileSystemIDandChk/FileSystemIDandChk.csproj +++ b/FileSystemIDandChk/FileSystemIDandChk.csproj @@ -87,6 +87,63 @@ + + + + + + + + + + + I + + + + + Attribute + + + + + EventArgs + + + + + Exception + + + + + + + + + _ + m_ + + + + + + _ + m_ + + + + + + + + + + T + + + + diff --git a/FileSystemIDandChk/ImagePlugins/CDRWin.cs b/FileSystemIDandChk/ImagePlugins/CDRWin.cs index 6f8b77e6..ed8598a2 100644 --- a/FileSystemIDandChk/ImagePlugins/CDRWin.cs +++ b/FileSystemIDandChk/ImagePlugins/CDRWin.cs @@ -207,7 +207,6 @@ namespace FileSystemIDandChk.ImagePlugins #region Internal variables - bool initialized; string imagePath; StreamReader cueStream; FileStream imageStream; @@ -622,11 +621,11 @@ namespace FileSystemIDandChk.ImagePlugins } else if (MatchFlags.Success) { + // TODO: Implement FLAGS support. if (MainClass.isDebug) Console.WriteLine("DEBUG (CDRWin plugin): Found FLAGS at line {0}", line); if (!intrack) throw new FeatureUnsupportedImageException(String.Format("Found FLAGS field in incorrect place at line {0}", line)); - // TODO: Implement FLAGS support. } else if (MatchGenre.Success) { @@ -769,8 +768,6 @@ namespace FileSystemIDandChk.ImagePlugins currenttrack.tracktype = MatchTrack.Groups[2].Value; currenttrack.session = currentsession; intrack = true; - - // TODO } else if (_line == "") // Empty line, ignore it { @@ -796,7 +793,6 @@ namespace FileSystemIDandChk.ImagePlugins for (int s = 1; s <= _sessions.Length; s++) { _sessions[s - 1].SessionSequence = 1; - ulong _session_offset; if (s > 1) _sessions[s - 1].StartSector = _sessions[s - 2].EndSector + 1; @@ -804,7 +800,6 @@ namespace FileSystemIDandChk.ImagePlugins _sessions[s - 1].StartSector = 0; ulong session_sectors = 0; - bool first_session_track = true; int last_session_track = 0; for (int i = 0; i < cuetracks.Length; i++) @@ -1375,26 +1370,27 @@ namespace FileSystemIDandChk.ImagePlugins byte[] buffer = new byte[sector_size * length]; - this.imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read); - BinaryReader br = new BinaryReader(this.imageStream); - - br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin); - - if (sector_offset == 0 && sector_skip == 0) - buffer = br.ReadBytes((int)(sector_size * length)); - else + imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read); + using (BinaryReader br = new BinaryReader(imageStream)) { - for (int i = 0; i < length; i++) + br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin); + if (sector_offset == 0 && sector_skip == 0) + buffer = br.ReadBytes((int)(sector_size * length)); + else { - byte[] sector = new byte[sector_size]; - br.BaseStream.Seek(sector_offset, SeekOrigin.Current); - sector = br.ReadBytes((int)sector_size); - br.BaseStream.Seek(sector_skip, SeekOrigin.Current); - - System.Array.Copy(sector, 0, buffer, i * sector_size, sector_size); + for (int i = 0; i < length; i++) + { + byte[] sector; + br.BaseStream.Seek(sector_offset, SeekOrigin.Current); + sector = br.ReadBytes((int)sector_size); + br.BaseStream.Seek(sector_skip, SeekOrigin.Current); + Array.Copy(sector, 0, buffer, i * sector_size, sector_size); + } } } + + return buffer; } @@ -1569,26 +1565,27 @@ namespace FileSystemIDandChk.ImagePlugins byte[] buffer = new byte[sector_size * length]; - this.imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read); - BinaryReader br = new BinaryReader(this.imageStream); - - br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin); - - if (sector_offset == 0 && sector_skip == 0) - buffer = br.ReadBytes((int)(sector_size * length)); - else + imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read); + using (BinaryReader br = new BinaryReader(imageStream)) { - for (int i = 0; i < length; i++) + br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin); + if (sector_offset == 0 && sector_skip == 0) + buffer = br.ReadBytes((int)(sector_size * length)); + else { - byte[] sector = new byte[sector_size]; - br.BaseStream.Seek(sector_offset, SeekOrigin.Current); - sector = br.ReadBytes((int)sector_size); - br.BaseStream.Seek(sector_skip, SeekOrigin.Current); - - System.Array.Copy(sector, 0, buffer, i * sector_size, sector_size); + for (int i = 0; i < length; i++) + { + byte[] sector; + br.BaseStream.Seek(sector_offset, SeekOrigin.Current); + sector = br.ReadBytes((int)sector_size); + br.BaseStream.Seek(sector_skip, SeekOrigin.Current); + Array.Copy(sector, 0, buffer, i * sector_size, sector_size); + } } } + + return buffer; } @@ -1695,8 +1692,8 @@ namespace FileSystemIDandChk.ImagePlugins byte[] buffer = new byte[sector_size * length]; - this.imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read); - BinaryReader br = new BinaryReader(this.imageStream); + imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read); + BinaryReader br = new BinaryReader(imageStream); br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin); @@ -1706,12 +1703,12 @@ namespace FileSystemIDandChk.ImagePlugins { for (int i = 0; i < length; i++) { - byte[] sector = new byte[sector_size]; + byte[] sector; br.BaseStream.Seek(sector_offset, SeekOrigin.Current); sector = br.ReadBytes((int)sector_size); br.BaseStream.Seek(sector_skip, SeekOrigin.Current); - System.Array.Copy(sector, 0, buffer, i * sector_size, sector_size); + Array.Copy(sector, 0, buffer, i * sector_size, sector_size); } } @@ -1810,8 +1807,7 @@ namespace FileSystemIDandChk.ImagePlugins { return GetSessionTracks(session.SessionSequence); } - else - throw new ImageNotSupportedException("Session does not exist in disc image"); + throw new ImageNotSupportedException("Session does not exist in disc image"); } public override List GetSessionTracks(UInt16 session) diff --git a/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs b/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs index 49160036..3433a8eb 100644 --- a/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs +++ b/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs @@ -1,6 +1,6 @@ using System; -using System.IO; using System.Collections.Generic; +using System.IO; namespace FileSystemIDandChk.ImagePlugins { diff --git a/FileSystemIDandChk/Main.cs b/FileSystemIDandChk/Main.cs index c99961cb..e1b142d2 100644 --- a/FileSystemIDandChk/Main.cs +++ b/FileSystemIDandChk/Main.cs @@ -7,26 +7,26 @@ using FileSystemIDandChk.ImagePlugins; namespace FileSystemIDandChk { - class MainClass - { - static PluginBase plugins; - public static bool chkPartitions; - public static bool chkFilesystems; - public static bool isDebug; - - public static void Main (string[] args) - { - plugins = new PluginBase(); + class MainClass + { + static PluginBase plugins; + public static bool chkPartitions; + public static bool chkFilesystems; + public static bool isDebug; + + public static void Main(string[] args) + { + plugins = new PluginBase(); - chkPartitions = true; - chkFilesystems = true; + chkPartitions = true; + chkFilesystems = true; // RELEASE //isDebug = false; // DEBUG isDebug = true; - Console.WriteLine ("Filesystem Identifier and Checker"); - Console.WriteLine ("Copyright (C) Natalia Portillo, All Rights Reserved"); + Console.WriteLine("Filesystem Identifier and Checker"); + Console.WriteLine("Copyright (C) Natalia Portillo, All Rights Reserved"); // For debug if (isDebug) @@ -82,32 +82,29 @@ namespace FileSystemIDandChk case "--debug": isDebug = true; break; - default: - break; } } Runner(args[args.Length - 1]); } } - } + } - private static void Runner (string filename) - { - FileStream stream; - List id_plugins; - Plugin _plugin; - string information; - bool checkraw = false; + static void Runner(string filename) + { + List id_plugins; + Plugin _plugin; + string information; + bool checkraw = false; ImagePlugin _imageFormat; - try - { + try + { _imageFormat = null; - foreach(ImagePlugin _imageplugin in plugins.ImagePluginsList.Values) + foreach (ImagePlugin _imageplugin in plugins.ImagePluginsList.Values) { - if(_imageplugin.IdentifyImage(filename)) + if (_imageplugin.IdentifyImage(filename)) { _imageFormat = _imageplugin; Console.WriteLine("Image format identified by {0}.", _imageplugin.Name); @@ -115,7 +112,7 @@ namespace FileSystemIDandChk } } - if(_imageFormat == null) + if (_imageFormat == null) { Console.WriteLine("Image format not identified, not proceeding."); return; @@ -123,21 +120,21 @@ namespace FileSystemIDandChk try { - if(!_imageFormat.OpenImage(filename)) + if (!_imageFormat.OpenImage(filename)) { Console.WriteLine("Unable to open image format"); Console.WriteLine("No error given"); return; } - if(isDebug) + if (isDebug) { Console.WriteLine("DEBUG: Correctly opened image file."); Console.WriteLine("DEBUG: Image without headers is {0} bytes.", _imageFormat.GetImageSize()); Console.WriteLine("DEBUG: Image has {0} sectors.", _imageFormat.GetSectors()); } } - catch(Exception ex) + catch (Exception ex) { Console.WriteLine("Unable to open image format"); Console.WriteLine("Error: {0}", ex.Message); @@ -146,152 +143,147 @@ namespace FileSystemIDandChk Console.WriteLine("Image identified as {0}.", _imageFormat.GetImageFormat()); - if(chkPartitions) - { - List partitions = new List(); - string partition_scheme = ""; + if (chkPartitions) + { + List partitions = new List(); + string partition_scheme = ""; // TODO: Solve possibility of multiple partition schemes (CUE + MBR, MBR + RDB, CUE + APM, etc) - foreach (PartPlugin _partplugin in plugins.PartPluginsList.Values) - { - List _partitions; + foreach (PartPlugin _partplugin in plugins.PartPluginsList.Values) + { + List _partitions; if (_partplugin.GetInformation(_imageFormat, out _partitions)) - { - partition_scheme=_partplugin.Name; - partitions = _partitions; - break; - } - } + { + partition_scheme = _partplugin.Name; + partitions = _partitions; + break; + } + } - if(_imageFormat.ImageHasPartitions()) + if (_imageFormat.ImageHasPartitions()) { partition_scheme = _imageFormat.GetImageFormat(); partitions = _imageFormat.GetPartitions(); } - if(partition_scheme=="") - { + if (partition_scheme == "") + { Console.WriteLine("DEBUG: No partitions found"); - if(!chkFilesystems) - { - Console.WriteLine("No partitions founds, not searching for filesystems"); - return; - } - else - checkraw = true; - } - else - { - Console.WriteLine("Partition scheme identified as {0}", partition_scheme); - Console.WriteLine("{0} partitions found.", partitions.Count); + if (!chkFilesystems) + { + Console.WriteLine("No partitions founds, not searching for filesystems"); + return; + } + checkraw = true; + } + else + { + Console.WriteLine("Partition scheme identified as {0}", partition_scheme); + Console.WriteLine("{0} partitions found.", partitions.Count); - for(int i = 0; i< partitions.Count; i++) - { - Console.WriteLine(); - Console.WriteLine("Partition {0}:", partitions[i].PartitionSequence); - Console.WriteLine("Partition name: {0}", partitions[i].PartitionName); - Console.WriteLine("Partition type: {0}", partitions[i].PartitionType); - Console.WriteLine("Partition start: {0}", partitions[i].PartitionStart); - Console.WriteLine("Partition length: {0}", partitions[i].PartitionLength); - Console.WriteLine("Partition description:"); - Console.WriteLine(partitions[i].PartitionDescription); + for (int i = 0; i < partitions.Count; i++) + { + Console.WriteLine(); + Console.WriteLine("Partition {0}:", partitions[i].PartitionSequence); + Console.WriteLine("Partition name: {0}", partitions[i].PartitionName); + Console.WriteLine("Partition type: {0}", partitions[i].PartitionType); + Console.WriteLine("Partition start: {0}", partitions[i].PartitionStart); + Console.WriteLine("Partition length: {0}", partitions[i].PartitionLength); + Console.WriteLine("Partition description:"); + Console.WriteLine(partitions[i].PartitionDescription); - if(chkFilesystems) - { - Console.WriteLine("Identifying filesystem on partition"); + if (chkFilesystems) + { + Console.WriteLine("Identifying filesystem on partition"); Identify(_imageFormat, out id_plugins, partitions[i].PartitionStart); - if(id_plugins.Count==0) - Console.WriteLine("Filesystem not identified"); - else if(id_plugins.Count>1) - { - Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count)); + if (id_plugins.Count == 0) + Console.WriteLine("Filesystem not identified"); + else if (id_plugins.Count > 1) + { + Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count)); - foreach(string plugin_name in id_plugins) - { - if(plugins.PluginsList.TryGetValue(plugin_name, out _plugin)) - { - Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name)); + foreach (string plugin_name in id_plugins) + { + if (plugins.PluginsList.TryGetValue(plugin_name, out _plugin)) + { + Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name)); _plugin.GetInformation(_imageFormat, partitions[i].PartitionStart, out information); - Console.Write(information); - } - } - } - else - { - plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin); - Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name)); + Console.Write(information); + } + } + } + else + { + plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin); + Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name)); _plugin.GetInformation(_imageFormat, partitions[i].PartitionStart, out information); - Console.Write(information); - } - } - } - } - } + Console.Write(information); + } + } + } + } + } - if(checkraw) - { + if (checkraw) + { Identify(_imageFormat, out id_plugins, 0); - if(id_plugins.Count==0) - Console.WriteLine("Filesystem not identified"); - else if(id_plugins.Count>1) - { - Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count)); + if (id_plugins.Count == 0) + Console.WriteLine("Filesystem not identified"); + else if (id_plugins.Count > 1) + { + Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count)); - foreach(string plugin_name in id_plugins) - { - if(plugins.PluginsList.TryGetValue(plugin_name, out _plugin)) - { - Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name)); + foreach (string plugin_name in id_plugins) + { + if (plugins.PluginsList.TryGetValue(plugin_name, out _plugin)) + { + Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name)); _plugin.GetInformation(_imageFormat, 0, out information); - Console.Write(information); - } - } - } - else - { - plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin); - Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name)); + Console.Write(information); + } + } + } + else + { + plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin); + Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name)); _plugin.GetInformation(_imageFormat, 0, out information); - Console.Write(information); - } - } - } - catch(Exception ex) - { - Console.WriteLine(String.Format("Error reading file: {0}", ex.Message)); - if(isDebug) - Console.WriteLine(ex.StackTrace); - } - finally - { - stream = null; - } - } + Console.Write(information); + } + } + } + catch (Exception ex) + { + Console.WriteLine(String.Format("Error reading file: {0}", ex.Message)); + if (isDebug) + Console.WriteLine(ex.StackTrace); + } + } - private static void Identify (ImagePlugins.ImagePlugin imagePlugin, out List id_plugins, ulong partitionOffset) - { - id_plugins = new List(); + static void Identify(ImagePlugin imagePlugin, out List id_plugins, ulong partitionOffset) + { + id_plugins = new List(); - foreach (Plugin _plugin in plugins.PluginsList.Values) + foreach (Plugin _plugin in plugins.PluginsList.Values) { if (_plugin.Identify(imagePlugin, partitionOffset)) - id_plugins.Add(_plugin.Name.ToLower()); + id_plugins.Add(_plugin.Name.ToLower()); } - } - - private static void Usage () - { - Console.WriteLine("Usage: filesystemidandchk [options] file"); - Console.WriteLine(); - Console.WriteLine(" --formats List all suported partition and filesystems"); - Console.WriteLine(" --debug Show debug information"); - Console.WriteLine(" --partitions Check only for partitions"); - Console.WriteLine(" --filesystems Check only for filesystems"); - Console.WriteLine(" --all Check for partitions and filesystems (default)"); - Console.WriteLine(); - } - } + } + + static void Usage() + { + Console.WriteLine("Usage: filesystemidandchk [options] file"); + Console.WriteLine(); + Console.WriteLine(" --formats List all suported partition and filesystems"); + Console.WriteLine(" --debug Show debug information"); + Console.WriteLine(" --partitions Check only for partitions"); + Console.WriteLine(" --filesystems Check only for filesystems"); + Console.WriteLine(" --all Check for partitions and filesystems (default)"); + Console.WriteLine(); + } + } } diff --git a/FileSystemIDandChk/PartPlugins/AppleMap.cs b/FileSystemIDandChk/PartPlugins/AppleMap.cs index 45187bf6..166bb9d2 100644 --- a/FileSystemIDandChk/PartPlugins/AppleMap.cs +++ b/FileSystemIDandChk/PartPlugins/AppleMap.cs @@ -1,28 +1,30 @@ using System; -using System.IO; using System.Text; using System.Collections.Generic; using FileSystemIDandChk; namespace FileSystemIDandChk.PartPlugins { - class AppleMap : PartPlugin - { - private const UInt16 APM_MAGIC = 0x4552; // "ER" - private const UInt16 APM_ENTRY = 0x504D; // "PM" - private const UInt16 APM_OLDENT = 0x5453; // "TS", old entry magic + class AppleMap : PartPlugin + { + // "ER" + const UInt16 APM_MAGIC = 0x4552; + // "PM" + const UInt16 APM_ENTRY = 0x504D; + // "TS", old entry magic + const UInt16 APM_OLDENT = 0x5453; - public AppleMap (PluginBase Core) - { + public AppleMap(PluginBase Core) + { Name = "Apple Partition Map"; - PluginUUID = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22"); - } - - public override bool GetInformation (ImagePlugins.ImagePlugin imagePlugin, out List partitions) - { - byte[] cString; + PluginUUID = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22"); + } + + public override bool GetInformation(ImagePlugins.ImagePlugin imagePlugin, out List partitions) + { + byte[] cString; - ulong apm_entries; + ulong apm_entries; uint sector_size; if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) @@ -30,10 +32,10 @@ namespace FileSystemIDandChk.PartPlugins else sector_size = imagePlugin.GetSectorSize(); - partitions = new List(); + partitions = new List(); - AppleMapBootEntry APMB = new AppleMapBootEntry(); - AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry(); + AppleMapBootEntry APMB = new AppleMapBootEntry(); + AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry(); byte[] APMB_sector = imagePlugin.ReadSector(0); @@ -88,8 +90,8 @@ namespace FileSystemIDandChk.PartPlugins apm_entries = APMEntry.entries; - for(ulong i = 0; i < apm_entries; i++) // For each partition - { + for (ulong i = 0; i < apm_entries; i++) // For each partition + { APMEntry = new AppleMapPartitionEntry(); APMEntry_sector = imagePlugin.ReadSector(first_sector + i); APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00); @@ -117,90 +119,118 @@ namespace FileSystemIDandChk.PartPlugins Array.Copy(APMEntry_sector, 0x78, cString, 0, 16); APMEntry.processor = StringHandlers.CToString(cString); - if(APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature - { - Partition _partition = new Partition(); - StringBuilder sb = new StringBuilder(); + if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature + { + Partition _partition = new Partition(); + StringBuilder sb = new StringBuilder(); - _partition.PartitionSequence = i; - _partition.PartitionType = APMEntry.type; - _partition.PartitionName = APMEntry.name; + _partition.PartitionSequence = i; + _partition.PartitionType = APMEntry.type; + _partition.PartitionName = APMEntry.name; _partition.PartitionStart = APMEntry.start * sector_size; _partition.PartitionLength = APMEntry.sectors * sector_size; _partition.PartitionStartSector = APMEntry.start; _partition.PartitionSectors = APMEntry.sectors; - sb.AppendLine("Partition flags:"); - if((APMEntry.status & 0x01) == 0x01) - sb.AppendLine("Partition is valid."); - if((APMEntry.status & 0x02) == 0x02) - sb.AppendLine("Partition entry is not available."); - if((APMEntry.status & 0x04) == 0x04) - sb.AppendLine("Partition is mounted."); - if((APMEntry.status & 0x08) == 0x08) - sb.AppendLine("Partition is bootable."); - if((APMEntry.status & 0x10) == 0x10) - sb.AppendLine("Partition is readable."); - if((APMEntry.status & 0x20) == 0x20) - sb.AppendLine("Partition is writable."); - if((APMEntry.status & 0x40) == 0x40) - sb.AppendLine("Partition's boot code is position independent."); + sb.AppendLine("Partition flags:"); + if ((APMEntry.status & 0x01) == 0x01) + sb.AppendLine("Partition is valid."); + if ((APMEntry.status & 0x02) == 0x02) + sb.AppendLine("Partition entry is not available."); + if ((APMEntry.status & 0x04) == 0x04) + sb.AppendLine("Partition is mounted."); + if ((APMEntry.status & 0x08) == 0x08) + sb.AppendLine("Partition is bootable."); + if ((APMEntry.status & 0x10) == 0x10) + sb.AppendLine("Partition is readable."); + if ((APMEntry.status & 0x20) == 0x20) + sb.AppendLine("Partition is writable."); + if ((APMEntry.status & 0x40) == 0x40) + sb.AppendLine("Partition's boot code is position independent."); - if((APMEntry.status & 0x08) == 0x08) - { - sb.AppendFormat("First boot sector: {0}", APMEntry.first_boot_block).AppendLine(); - sb.AppendFormat("Boot is {0} bytes.", APMEntry.boot_size).AppendLine(); - sb.AppendFormat("Boot load address: 0x{0:X8}", APMEntry.load_address).AppendLine(); - sb.AppendFormat("Boot entry point: 0x{0:X8}", APMEntry.entry_point).AppendLine(); - sb.AppendFormat("Boot code checksum: 0x{0:X8}", APMEntry.checksum).AppendLine(); - sb.AppendFormat("Processor: {0}", APMEntry.processor).AppendLine(); - } + if ((APMEntry.status & 0x08) == 0x08) + { + sb.AppendFormat("First boot sector: {0}", APMEntry.first_boot_block).AppendLine(); + sb.AppendFormat("Boot is {0} bytes.", APMEntry.boot_size).AppendLine(); + sb.AppendFormat("Boot load address: 0x{0:X8}", APMEntry.load_address).AppendLine(); + sb.AppendFormat("Boot entry point: 0x{0:X8}", APMEntry.entry_point).AppendLine(); + sb.AppendFormat("Boot code checksum: 0x{0:X8}", APMEntry.checksum).AppendLine(); + sb.AppendFormat("Processor: {0}", APMEntry.processor).AppendLine(); + } - _partition.PartitionDescription = sb.ToString(); + _partition.PartitionDescription = sb.ToString(); - if((APMEntry.status & 0x01) == 0x01) - if(APMEntry.type != "Apple_partition_map") - partitions.Add(_partition); - } - } + if ((APMEntry.status & 0x01) == 0x01) + if (APMEntry.type != "Apple_partition_map") + partitions.Add(_partition); + } + } - return true; - } - - public struct AppleMapBootEntry - { - public UInt16 signature; // Signature ("ER") - public UInt16 sector_size; // Byter per sector - public UInt32 sectors; // Sectors of the disk - public UInt16 reserved1; // Reserved - public UInt16 reserved2; // Reserved - public UInt32 reserved3; // Reserved - public UInt16 driver_entries; // Number of entries of the driver descriptor - public UInt32 first_driver_blk; // First sector of the driver - public UInt16 driver_size; // Size in 512bytes sectors of the driver - public UInt16 operating_system; // Operating system (MacOS = 1) - } - - public struct AppleMapPartitionEntry - { - public UInt16 signature; // Signature ("PM" or "TS") - public UInt16 reserved1; // Reserved - public UInt32 entries; // Number of entries on the partition map, each one sector - public UInt32 start; // First sector of the partition - public UInt32 sectors; // Number of sectos of the partition - public string name; // Partition name, 32 bytes, null-padded - public string type; // Partition type. 32 bytes, null-padded - public UInt32 first_data_block; // First sector of the data area - public UInt32 data_sectors; // Number of sectors of the data area - public UInt32 status; // Partition status - public UInt32 first_boot_block; // First sector of the boot code - public UInt32 boot_size; // Size in bytes of the boot code - public UInt32 load_address; // Load address of the boot code - public UInt32 reserved2; // Reserved - public UInt32 entry_point; // Entry point of the boot code - public UInt32 reserved3; // Reserved - public UInt32 checksum; // Boot code checksum - public string processor; // Processor type, 16 bytes, null-padded - } - } + return true; + } + + public struct AppleMapBootEntry + { + // Signature ("ER") + public UInt16 signature; + // Byter per sector + public UInt16 sector_size; + // Sectors of the disk + public UInt32 sectors; + // Reserved + public UInt16 reserved1; + // Reserved + public UInt16 reserved2; + // Reserved + public UInt32 reserved3; + // Number of entries of the driver descriptor + public UInt16 driver_entries; + // First sector of the driver + public UInt32 first_driver_blk; + // Size in 512bytes sectors of the driver + public UInt16 driver_size; + // Operating system (MacOS = 1) + public UInt16 operating_system; + } + + public struct AppleMapPartitionEntry + { + // Signature ("PM" or "TS") + public UInt16 signature; + // Reserved + public UInt16 reserved1; + // Number of entries on the partition map, each one sector + public UInt32 entries; + // First sector of the partition + public UInt32 start; + // Number of sectos of the partition + public UInt32 sectors; + // Partition name, 32 bytes, null-padded + public string name; + // Partition type. 32 bytes, null-padded + public string type; + // First sector of the data area + public UInt32 first_data_block; + // Number of sectors of the data area + public UInt32 data_sectors; + // Partition status + public UInt32 status; + // First sector of the boot code + public UInt32 first_boot_block; + // Size in bytes of the boot code + public UInt32 boot_size; + // Load address of the boot code + public UInt32 load_address; + // Reserved + public UInt32 reserved2; + // Entry point of the boot code + public UInt32 entry_point; + // Reserved + public UInt32 reserved3; + // Boot code checksum + public UInt32 checksum; + // Processor type, 16 bytes, null-padded + public string processor; + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/PartPlugins/MBR.cs b/FileSystemIDandChk/PartPlugins/MBR.cs index 4423c7c6..c25a26a5 100644 --- a/FileSystemIDandChk/PartPlugins/MBR.cs +++ b/FileSystemIDandChk/PartPlugins/MBR.cs @@ -1,7 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; using System.Text; -using System.Collections.Generic; using FileSystemIDandChk; // TODO: Support AAP, AST, SpeedStor and Ontrack extensions @@ -13,15 +13,14 @@ namespace FileSystemIDandChk.PartPlugins public MBR(PluginBase Core) { - base.Name = "Master Boot Record"; - base.PluginUUID = new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76"); + Name = "Master Boot Record"; + PluginUUID = new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76"); } public override bool GetInformation(ImagePlugins.ImagePlugin imagePlugin, out List partitions) { byte cyl_sect1, cyl_sect2; // For decoding cylinder and sector UInt16 signature; - UInt32 serial; ulong counter = 0; partitions = new List(); @@ -33,8 +32,6 @@ namespace FileSystemIDandChk.PartPlugins if (signature != MBRSignature) return false; // Not MBR - serial = BitConverter.ToUInt32(sector, 0x1B8); - for (int i = 0; i < 4; i++) { MBRPartitionEntry entry = new MBRPartitionEntry(); @@ -68,8 +65,7 @@ namespace FileSystemIDandChk.PartPlugins if (entry.status != 0x00 && entry.status != 0x80) return false; // Maybe a FAT filesystem - if (entry.type == 0x00) - valid = false; + valid &= entry.type != 0x00; if (entry.type == 0xEE || entry.type == 0xEF) return false; // This is a GPT if (entry.type == 0x05 || entry.type == 0x0F || entry.type == 0x85) @@ -84,8 +80,7 @@ namespace FileSystemIDandChk.PartPlugins disklabel = true; } - if (entry.lba_start == 0 && entry.lba_sectors == 0 && entry.start_cylinder == 0 && entry.start_head == 0 && entry.start_sector == 0 && entry.end_cylinder == 0 && entry.end_head == 0 && entry.end_sector == 0) - valid = false; + valid &= entry.lba_start != 0 || entry.lba_sectors != 0 || entry.start_cylinder != 0 || entry.start_head != 0 || entry.start_sector != 0 || entry.end_cylinder != 0 || entry.end_head != 0 || entry.end_sector != 0; if (entry.lba_start == 0 && entry.lba_sectors == 0 && valid) { entry.lba_start = CHStoLBA(entry.start_cylinder, entry.start_head, entry.start_sector); @@ -302,8 +297,7 @@ namespace FileSystemIDandChk.PartPlugins counter++; } } - if (!minix_subs) - valid = true; + valid |= !minix_subs; break; } @@ -338,10 +332,7 @@ namespace FileSystemIDandChk.PartPlugins part.PartitionType = String.Format("0x{0:X2}", entry.type); part.PartitionName = decodeMBRType(entry.type); part.PartitionSequence = counter; - if (entry.status == 0x80) - part.PartitionDescription = "Partition is bootable."; - else - part.PartitionDescription = ""; + part.PartitionDescription = entry.status == 0x80 ? "Partition is bootable." : ""; counter++; @@ -388,10 +379,8 @@ namespace FileSystemIDandChk.PartPlugins // Let's start the fun... - if (entry2.status != 0x00 && entry2.status != 0x80) - ext_valid = false; - if (entry2.type == 0x00) - valid = false; + ext_valid &= entry2.status == 0x00 || entry2.status == 0x80; + valid &= entry2.type != 0x00; if (entry2.type == 0x82 || entry2.type == 0xBF || entry2.type == 0xA5 || entry2.type == 0xA6 || entry2.type == 0xA9 || entry2.type == 0xB7 || entry2.type == 0x81 || entry2.type == 0x63) { @@ -404,8 +393,8 @@ namespace FileSystemIDandChk.PartPlugins ext_disklabel = false; ext_extended = true; // Extended partition } - else if (l == 1) - processing_extended = false; + else + processing_extended &= l != 1; if (ext_disklabel) { @@ -610,8 +599,7 @@ namespace FileSystemIDandChk.PartPlugins counter++; } } - if (!minix_subs) - ext_valid = true; + ext_valid |= !minix_subs; break; } @@ -647,10 +635,7 @@ namespace FileSystemIDandChk.PartPlugins part.PartitionType = String.Format("0x{0:X2}", entry2.type); part.PartitionName = decodeMBRType(entry2.type); part.PartitionSequence = counter; - if (entry2.status == 0x80) - part.PartitionDescription = "Partition is bootable."; - else - part.PartitionDescription = ""; + part.PartitionDescription = entry2.status == 0x80 ? "Partition is bootable." : ""; counter++; @@ -668,18 +653,15 @@ namespace FileSystemIDandChk.PartPlugins } // An empty MBR may exist, NeXT creates one and then hardcodes its disklabel - if (partitions.Count == 0) - return false; - else - return true; + return partitions.Count != 0; } - private UInt32 CHStoLBA(ushort cyl, byte head, byte sector) + static UInt32 CHStoLBA(ushort cyl, byte head, byte sector) { return (((UInt32)cyl * 16) + (UInt32)head) * 63 + (UInt32)sector - 1; } - private string decodeBSDType(byte type) + static string decodeBSDType(byte type) { switch (type) { @@ -716,7 +698,7 @@ namespace FileSystemIDandChk.PartPlugins } } - private string decodeMBRType(byte type) + static string decodeMBRType(byte type) { switch (type) { @@ -1057,10 +1039,10 @@ namespace FileSystemIDandChk.PartPlugins // Total sectors } - private const UInt32 UNIXDiskLabel_MAGIC = 0xCA5E600D; - private const UInt32 UNIXVTOC_MAGIC = 0x600DDEEE; + const UInt32 UNIXDiskLabel_MAGIC = 0xCA5E600D; + const UInt32 UNIXVTOC_MAGIC = 0x600DDEEE; // Same as Solaris VTOC - private struct UNIXDiskLabel + struct UNIXDiskLabel { public UInt32 type; // Drive type, seems always 0 @@ -1103,7 +1085,7 @@ namespace FileSystemIDandChk.PartPlugins // 32bytes } - private struct UNIXVTOC + struct UNIXVTOC { public UInt32 magic; // UNIXVTOC_MAGIC @@ -1119,7 +1101,7 @@ namespace FileSystemIDandChk.PartPlugins // 40 bytes } - private struct UNIXVTOCEntry + struct UNIXVTOCEntry { public UInt16 tag; // TAG @@ -1131,51 +1113,51 @@ namespace FileSystemIDandChk.PartPlugins // Length of slice in sectors } - private const UInt16 UNIX_TAG_EMPTY = 0x0000; + const UInt16 UNIX_TAG_EMPTY = 0x0000; // empty - private const UInt16 UNIX_TAG_BOOT = 0x0001; + const UInt16 UNIX_TAG_BOOT = 0x0001; // boot - private const UInt16 UNIX_TAG_ROOT = 0x0002; + const UInt16 UNIX_TAG_ROOT = 0x0002; // root - private const UInt16 UNIX_TAG_SWAP = 0x0003; + const UInt16 UNIX_TAG_SWAP = 0x0003; // swap - private const UInt16 UNIX_TAG_USER = 0x0004; + const UInt16 UNIX_TAG_USER = 0x0004; // /usr - private const UInt16 UNIX_TAG_WHOLE = 0x0005; + const UInt16 UNIX_TAG_WHOLE = 0x0005; // whole disk - private const UInt16 UNIX_TAG_STAND = 0x0006; + const UInt16 UNIX_TAG_STAND = 0x0006; // stand partition ?? - private const UInt16 UNIX_TAG_ALT_S = 0x0006; + const UInt16 UNIX_TAG_ALT_S = 0x0006; // alternate sector space - private const UInt16 UNIX_TAG_VAR = 0x0007; + const UInt16 UNIX_TAG_VAR = 0x0007; // /var - private const UInt16 UNIX_TAG_OTHER = 0x0007; + const UInt16 UNIX_TAG_OTHER = 0x0007; // non UNIX - private const UInt16 UNIX_TAG_HOME = 0x0008; + const UInt16 UNIX_TAG_HOME = 0x0008; // /home - private const UInt16 UNIX_TAG_ALT_T = 0x0008; + const UInt16 UNIX_TAG_ALT_T = 0x0008; // alternate track space - private const UInt16 UNIX_TAG_ALT_ST = 0x0009; + const UInt16 UNIX_TAG_ALT_ST = 0x0009; // alternate sector track - private const UInt16 UNIX_TAG_NEW_STAND = 0x0009; + const UInt16 UNIX_TAG_NEW_STAND = 0x0009; // stand partition ?? - private const UInt16 UNIX_TAG_CACHE = 0x000A; + const UInt16 UNIX_TAG_CACHE = 0x000A; // cache - private const UInt16 UNIX_TAG_NEW_VAR = 0x000A; + const UInt16 UNIX_TAG_NEW_VAR = 0x000A; // /var - private const UInt16 UNIX_TAG_RESERVED = 0x000B; + const UInt16 UNIX_TAG_RESERVED = 0x000B; // reserved - private const UInt16 UNIX_TAG_NEW_HOME = 0x000B; + const UInt16 UNIX_TAG_NEW_HOME = 0x000B; // /home - private const UInt16 UNIX_TAG_DUMP = 0x000C; + const UInt16 UNIX_TAG_DUMP = 0x000C; // dump partition - private const UInt16 UNIX_TAG_NEW_ALT_ST = 0x000D; + const UInt16 UNIX_TAG_NEW_ALT_ST = 0x000D; // alternate sector track - private const UInt16 UNIX_TAG_VM_PUBLIC = 0x000E; + const UInt16 UNIX_TAG_VM_PUBLIC = 0x000E; // volume mgt public partition - private const UInt16 UNIX_TAG_VM_PRIVATE = 0x000F; + const UInt16 UNIX_TAG_VM_PRIVATE = 0x000F; // volume mgt private partition - private string decodeUNIXTAG(UInt16 type, bool isNew) + static string decodeUNIXTAG(UInt16 type, bool isNew) { switch (type) { @@ -1192,35 +1174,17 @@ namespace FileSystemIDandChk.PartPlugins case UNIX_TAG_WHOLE: return "Whole disk"; case UNIX_TAG_STAND: - if (isNew) - return "Stand"; - else - return "Alternate sector space"; + return isNew ? "Stand" : "Alternate sector space"; case UNIX_TAG_VAR: - if (isNew) - return "/var"; - else - return "non UNIX"; + return isNew ? "/var" : "non UNIX"; case UNIX_TAG_HOME: - if (isNew) - return "/home"; - else - return "Alternate track space"; + return isNew ? "/home" : "Alternate track space"; case UNIX_TAG_ALT_ST: - if (isNew) - return "Alternate sector track"; - else - return "Stand"; + return isNew ? "Alternate sector track" : "Stand"; case UNIX_TAG_CACHE: - if (isNew) - return "Cache"; - else - return "/var"; + return isNew ? "Cache" : "/var"; case UNIX_TAG_RESERVED: - if (isNew) - return "Reserved"; - else - return "/home"; + return isNew ? "Reserved" : "/home"; case UNIX_TAG_DUMP: return "dump"; case UNIX_TAG_NEW_ALT_ST: diff --git a/FileSystemIDandChk/PartPlugins/NeXT.cs b/FileSystemIDandChk/PartPlugins/NeXT.cs index 67c0e81d..a54c164b 100644 --- a/FileSystemIDandChk/PartPlugins/NeXT.cs +++ b/FileSystemIDandChk/PartPlugins/NeXT.cs @@ -1,7 +1,6 @@ using System; -using System.IO; -using System.Text; using System.Collections.Generic; +using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.PartPlugins @@ -14,10 +13,10 @@ namespace FileSystemIDandChk.PartPlugins // "dlV2" const UInt32 NEXT_MAGIC3 = 0x646C5633; // "dlV3" - - const UInt16 disktabStart = 0xB4; // 180 - const UInt16 disktabEntrySize = 0x2C; // 44 - + const UInt16 disktabStart = 0xB4; + // 180 + const UInt16 disktabEntrySize = 0x2C; + // 44 public NeXTDisklabel(PluginBase Core) { Name = "NeXT Disklabel"; diff --git a/FileSystemIDandChk/Plugins.cs b/FileSystemIDandChk/Plugins.cs index f3bb7cee..af885075 100644 --- a/FileSystemIDandChk/Plugins.cs +++ b/FileSystemIDandChk/Plugins.cs @@ -1,26 +1,26 @@ using System; -using System.Reflection; using System.Collections.Generic; -using FileSystemIDandChk.Plugins; -using FileSystemIDandChk.PartPlugins; +using System.Reflection; using FileSystemIDandChk.ImagePlugins; +using FileSystemIDandChk.PartPlugins; +using FileSystemIDandChk.Plugins; namespace FileSystemIDandChk { - public class PluginBase - { - public Dictionary PluginsList; - public Dictionary PartPluginsList; + public class PluginBase + { + public Dictionary PluginsList; + public Dictionary PartPluginsList; public Dictionary ImagePluginsList; - - public PluginBase () - { - this.PluginsList = new Dictionary(); - this.PartPluginsList = new Dictionary(); - this.ImagePluginsList = new Dictionary(); - } - - public void RegisterAllPlugins() + + public PluginBase() + { + PluginsList = new Dictionary(); + PartPluginsList = new Dictionary(); + ImagePluginsList = new Dictionary(); + } + + public void RegisterAllPlugins() { Assembly assembly = Assembly.GetExecutingAssembly(); @@ -30,51 +30,51 @@ namespace FileSystemIDandChk { if (type.IsSubclassOf(typeof(ImagePlugin))) { - ImagePlugin plugin = (ImagePlugin)type.GetConstructor(new Type[] { typeof(PluginBase) }).Invoke(new object[] { this }); - this.RegisterImagePlugin(plugin); + ImagePlugin plugin = (ImagePlugin)type.GetConstructor(new [] { typeof(PluginBase) }).Invoke(new object[] { this }); + RegisterImagePlugin(plugin); } if (type.IsSubclassOf(typeof(Plugin))) { - Plugin plugin = (Plugin)type.GetConstructor(new Type[] { typeof(PluginBase) }).Invoke(new object[] { this }); - this.RegisterPlugin(plugin); + Plugin plugin = (Plugin)type.GetConstructor(new [] { typeof(PluginBase) }).Invoke(new object[] { this }); + RegisterPlugin(plugin); } - else if (type.IsSubclassOf(typeof(PartPlugin))) + else if (type.IsSubclassOf(typeof(PartPlugin))) { - PartPlugin partplugin = (PartPlugin)type.GetConstructor(new Type[] { typeof(PluginBase) }).Invoke(new object[] { this }); - this.RegisterPartPlugin(partplugin); + PartPlugin partplugin = (PartPlugin)type.GetConstructor(new [] { typeof(PluginBase) }).Invoke(new object[] { this }); + RegisterPartPlugin(partplugin); } } catch (Exception exception) { - Console.WriteLine(exception.ToString()); + Console.WriteLine(exception); } } } - private void RegisterImagePlugin(ImagePlugin plugin) + void RegisterImagePlugin(ImagePlugin plugin) { - if (!this.ImagePluginsList.ContainsKey(plugin.Name.ToLower())) + if (!ImagePluginsList.ContainsKey(plugin.Name.ToLower())) { - this.ImagePluginsList.Add(plugin.Name.ToLower(), plugin); + ImagePluginsList.Add(plugin.Name.ToLower(), plugin); } } - private void RegisterPlugin(Plugin plugin) + void RegisterPlugin(Plugin plugin) { - if (!this.PluginsList.ContainsKey(plugin.Name.ToLower())) + if (!PluginsList.ContainsKey(plugin.Name.ToLower())) { - this.PluginsList.Add(plugin.Name.ToLower(), plugin); + PluginsList.Add(plugin.Name.ToLower(), plugin); } } - private void RegisterPartPlugin(PartPlugin partplugin) + void RegisterPartPlugin(PartPlugin partplugin) { - if (!this.PartPluginsList.ContainsKey(partplugin.Name.ToLower())) + if (!PartPluginsList.ContainsKey(partplugin.Name.ToLower())) { - this.PartPluginsList.Add(partplugin.Name.ToLower(), partplugin); + PartPluginsList.Add(partplugin.Name.ToLower(), partplugin); } } - } + } } diff --git a/FileSystemIDandChk/Plugins/AppleHFS.cs b/FileSystemIDandChk/Plugins/AppleHFS.cs index eab4b0ce..7f295e22 100644 --- a/FileSystemIDandChk/Plugins/AppleHFS.cs +++ b/FileSystemIDandChk/Plugins/AppleHFS.cs @@ -7,52 +7,50 @@ using FileSystemIDandChk; // https://developer.apple.com/legacy/library/documentation/mac/pdf/Files/File_Manager.pdf namespace FileSystemIDandChk.Plugins { - class AppleHFS : Plugin - { - private const UInt16 HFS_MAGIC = 0x4244; // "BD" - private const UInt16 HFSP_MAGIC = 0x482B; // "H+" - private const UInt16 HFSBB_MAGIC = 0x4C4B; // "LK" - - public AppleHFS(PluginBase Core) + class AppleHFS : Plugin + { + const UInt16 HFS_MAGIC = 0x4244; + // "BD" + const UInt16 HFSP_MAGIC = 0x482B; + // "H+" + const UInt16 HFSBB_MAGIC = 0x4C4B; + // "LK" + public AppleHFS(PluginBase Core) { - base.Name = "Apple Hierarchical File System"; - base.PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F"); + Name = "Apple Hierarchical File System"; + PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { + { byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); UInt16 drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); - if(drSigWord == HFS_MAGIC) - { + if (drSigWord == HFS_MAGIC) + { drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature - if(drSigWord == HFSP_MAGIC) // "H+" - return false; - else - return true; - } - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; - - StringBuilder sb = new StringBuilder(); - - HFS_MasterDirectoryBlock MDB = new HFS_MasterDirectoryBlock(); - HFS_BootBlock BB = new HFS_BootBlock(); + return drSigWord != HFSP_MAGIC; + } + return false; + } - byte[] pString; + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; + + StringBuilder sb = new StringBuilder(); + + HFS_MasterDirectoryBlock MDB = new HFS_MasterDirectoryBlock(); + HFS_BootBlock BB = new HFS_BootBlock(); + + byte[] pString; byte[] bb_sector = imagePlugin.ReadSector(2 + partitionOffset); // BB's first sector byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); // MDB sector MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000); - if(MDB.drSigWord != HFS_MAGIC) - return; + if (MDB.drSigWord != HFS_MAGIC) + return; MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdb_sector, 0x002); MDB.drLsMod = BigEndianBitConverter.ToUInt32(mdb_sector, 0x006); @@ -68,7 +66,7 @@ namespace FileSystemIDandChk.Plugins MDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x022); pString = new byte[28]; Array.Copy(mdb_sector, 0x024, pString, 0, 28); - MDB.drVN = StringHandlers.PascalToString(pString); + MDB.drVN = StringHandlers.PascalToString(pString); MDB.drVolBkUp = BigEndianBitConverter.ToUInt32(mdb_sector, 0x040); MDB.drVSeqNum = BigEndianBitConverter.ToUInt16(mdb_sector, 0x044); @@ -102,8 +100,8 @@ namespace FileSystemIDandChk.Plugins BB.signature = BigEndianBitConverter.ToUInt16(bb_sector, 0x000); - if(BB.signature == HFSBB_MAGIC) - { + if (BB.signature == HFSBB_MAGIC) + { BB.branch = BigEndianBitConverter.ToUInt32(bb_sector, 0x002); BB.boot_flags = bb_sector[0x006]; BB.boot_version = bb_sector[0x007]; @@ -112,100 +110,100 @@ namespace FileSystemIDandChk.Plugins pString = new byte[16]; Array.Copy(bb_sector, 0x00A, pString, 0, 16); - BB.system_name = StringHandlers.PascalToString(pString); + BB.system_name = StringHandlers.PascalToString(pString); pString = new byte[16]; Array.Copy(bb_sector, 0x01A, pString, 0, 16); - BB.finder_name = StringHandlers.PascalToString(pString); + BB.finder_name = StringHandlers.PascalToString(pString); pString = new byte[16]; Array.Copy(bb_sector, 0x02A, pString, 0, 16); - BB.debug_name = StringHandlers.PascalToString(pString); + BB.debug_name = StringHandlers.PascalToString(pString); pString = new byte[16]; Array.Copy(bb_sector, 0x03A, pString, 0, 16); - BB.disasm_name = StringHandlers.PascalToString(pString); + BB.disasm_name = StringHandlers.PascalToString(pString); pString = new byte[16]; Array.Copy(bb_sector, 0x04A, pString, 0, 16); - BB.stupscr_name = StringHandlers.PascalToString(pString); + BB.stupscr_name = StringHandlers.PascalToString(pString); pString = new byte[16]; Array.Copy(bb_sector, 0x05A, pString, 0, 16); - BB.bootup_name = StringHandlers.PascalToString(pString); + BB.bootup_name = StringHandlers.PascalToString(pString); pString = new byte[16]; Array.Copy(bb_sector, 0x06A, pString, 0, 16); - BB.clipbrd_name = StringHandlers.PascalToString(pString); + BB.clipbrd_name = StringHandlers.PascalToString(pString); BB.max_files = BigEndianBitConverter.ToUInt16(bb_sector, 0x07A); BB.queue_size = BigEndianBitConverter.ToUInt16(bb_sector, 0x07C); BB.heap_128k = BigEndianBitConverter.ToUInt32(bb_sector, 0x07E); BB.heap_256k = BigEndianBitConverter.ToUInt32(bb_sector, 0x082); BB.heap_512k = BigEndianBitConverter.ToUInt32(bb_sector, 0x086); - } - else - BB.signature = 0x0000; + } + else + BB.signature = 0x0000; - sb.AppendLine("Apple Hierarchical File System"); - sb.AppendLine(); - sb.AppendLine("Master Directory Block:"); - sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine(); - sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(MDB.drLsMod)).AppendLine(); - sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(MDB.drVolBkUp)).AppendLine(); - sb.AppendFormat("Backup sequence number: {0}", MDB.drVSeqNum).AppendLine(); + sb.AppendLine("Apple Hierarchical File System"); + sb.AppendLine(); + sb.AppendLine("Master Directory Block:"); + sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine(); + sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(MDB.drLsMod)).AppendLine(); + sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(MDB.drVolBkUp)).AppendLine(); + sb.AppendFormat("Backup sequence number: {0}", MDB.drVSeqNum).AppendLine(); - if((MDB.drAtrb & 0x80) == 0x80) - sb.AppendLine("Volume is locked by hardware."); - if((MDB.drAtrb & 0x100) == 0x100) - sb.AppendLine("Volume was unmonted."); - else - sb.AppendLine("Volume is mounted."); - if((MDB.drAtrb & 0x200) == 0x200) - sb.AppendLine("Volume has spared bad blocks."); - if((MDB.drAtrb & 0x400) == 0x400) - sb.AppendLine("Volume does not need cache."); - if((MDB.drAtrb & 0x800) == 0x800) - sb.AppendLine("Boot volume is inconsistent."); - if((MDB.drAtrb & 0x1000) == 0x1000) - sb.AppendLine("There are reused CNIDs."); - if((MDB.drAtrb & 0x2000) == 0x2000) - sb.AppendLine("Volume is journaled."); - if((MDB.drAtrb & 0x4000) == 0x4000) - sb.AppendLine("Volume is seriously inconsistent."); - if((MDB.drAtrb & 0x8000) == 0x8000) - sb.AppendLine("Volume is locked by software."); + if ((MDB.drAtrb & 0x80) == 0x80) + sb.AppendLine("Volume is locked by hardware."); + if ((MDB.drAtrb & 0x100) == 0x100) + sb.AppendLine("Volume was unmonted."); + else + sb.AppendLine("Volume is mounted."); + if ((MDB.drAtrb & 0x200) == 0x200) + sb.AppendLine("Volume has spared bad blocks."); + if ((MDB.drAtrb & 0x400) == 0x400) + sb.AppendLine("Volume does not need cache."); + if ((MDB.drAtrb & 0x800) == 0x800) + sb.AppendLine("Boot volume is inconsistent."); + if ((MDB.drAtrb & 0x1000) == 0x1000) + sb.AppendLine("There are reused CNIDs."); + if ((MDB.drAtrb & 0x2000) == 0x2000) + sb.AppendLine("Volume is journaled."); + if ((MDB.drAtrb & 0x4000) == 0x4000) + sb.AppendLine("Volume is seriously inconsistent."); + if ((MDB.drAtrb & 0x8000) == 0x8000) + sb.AppendLine("Volume is locked by software."); - sb.AppendFormat("{0} files on root directory", MDB.drNmFls).AppendLine(); - sb.AppendFormat("{0} directories on root directory", MDB.drNmRtDirs).AppendLine(); - sb.AppendFormat("{0} files on volume", MDB.drFilCnt).AppendLine(); - sb.AppendFormat("{0} directories on volume", MDB.drDirCnt).AppendLine(); - sb.AppendFormat("Volume write count: {0}", MDB.drWrCnt).AppendLine(); + sb.AppendFormat("{0} files on root directory", MDB.drNmFls).AppendLine(); + sb.AppendFormat("{0} directories on root directory", MDB.drNmRtDirs).AppendLine(); + sb.AppendFormat("{0} files on volume", MDB.drFilCnt).AppendLine(); + sb.AppendFormat("{0} directories on volume", MDB.drDirCnt).AppendLine(); + sb.AppendFormat("Volume write count: {0}", MDB.drWrCnt).AppendLine(); - sb.AppendFormat("Volume bitmap starting sector (in 512-bytes): {0}", MDB.drVBMSt).AppendLine(); - sb.AppendFormat("Next allocation block: {0}.", MDB.drAllocPtr).AppendLine(); - sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine(); - sb.AppendFormat("{0} bytes per allocation block.", MDB.drAlBlkSiz).AppendLine(); - sb.AppendFormat("{0} bytes to allocate when extending a file.", MDB.drClpSiz).AppendLine(); - sb.AppendFormat("{0} bytes to allocate when extending a Extents B-Tree.", MDB.drXTClpSiz).AppendLine(); - sb.AppendFormat("{0} bytes to allocate when extending a Catalog B-Tree.", MDB.drCTClpSiz).AppendLine(); - sb.AppendFormat("Sector of first allocation block: {0}", MDB.drAlBlSt).AppendLine(); - sb.AppendFormat("Next unused CNID: {0}", MDB.drNxtCNID).AppendLine(); - sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine(); + sb.AppendFormat("Volume bitmap starting sector (in 512-bytes): {0}", MDB.drVBMSt).AppendLine(); + sb.AppendFormat("Next allocation block: {0}.", MDB.drAllocPtr).AppendLine(); + sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine(); + sb.AppendFormat("{0} bytes per allocation block.", MDB.drAlBlkSiz).AppendLine(); + sb.AppendFormat("{0} bytes to allocate when extending a file.", MDB.drClpSiz).AppendLine(); + sb.AppendFormat("{0} bytes to allocate when extending a Extents B-Tree.", MDB.drXTClpSiz).AppendLine(); + sb.AppendFormat("{0} bytes to allocate when extending a Catalog B-Tree.", MDB.drCTClpSiz).AppendLine(); + sb.AppendFormat("Sector of first allocation block: {0}", MDB.drAlBlSt).AppendLine(); + sb.AppendFormat("Next unused CNID: {0}", MDB.drNxtCNID).AppendLine(); + sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine(); - sb.AppendFormat("{0} bytes in the Extents B-Tree", MDB.drXTFlSize).AppendLine(); - sb.AppendFormat("{0} bytes in the Catalog B-Tree", MDB.drCTFlSize).AppendLine(); + sb.AppendFormat("{0} bytes in the Extents B-Tree", MDB.drXTFlSize).AppendLine(); + sb.AppendFormat("{0} bytes in the Catalog B-Tree", MDB.drCTFlSize).AppendLine(); - sb.AppendFormat("Volume name: {0}", MDB.drVN).AppendLine(); + sb.AppendFormat("Volume name: {0}", MDB.drVN).AppendLine(); - sb.AppendLine("Finder info:"); - sb.AppendFormat("CNID of bootable system's directory: {0}", MDB.drFndrInfo0).AppendLine(); - sb.AppendFormat("CNID of first-run application's directory: {0}", MDB.drFndrInfo1).AppendLine(); - sb.AppendFormat("CNID of previously opened directory: {0}", MDB.drFndrInfo2).AppendLine(); - sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", MDB.drFndrInfo3).AppendLine(); - sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", MDB.drFndrInfo5).AppendLine(); - sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", MDB.drFndrInfo6, MDB.drFndrInfo7).AppendLine(); + sb.AppendLine("Finder info:"); + sb.AppendFormat("CNID of bootable system's directory: {0}", MDB.drFndrInfo0).AppendLine(); + sb.AppendFormat("CNID of first-run application's directory: {0}", MDB.drFndrInfo1).AppendLine(); + sb.AppendFormat("CNID of previously opened directory: {0}", MDB.drFndrInfo2).AppendLine(); + sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", MDB.drFndrInfo3).AppendLine(); + sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", MDB.drFndrInfo5).AppendLine(); + sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", MDB.drFndrInfo6, MDB.drFndrInfo7).AppendLine(); - if(MDB.drEmbedSigWord == HFSP_MAGIC) - { - sb.AppendLine("Volume wraps a HFS+ volume."); - sb.AppendFormat("Starting block of the HFS+ volume: {0}", MDB.xdrStABNt).AppendLine(); - sb.AppendFormat("Allocations blocks of the HFS+ volume: {0}", MDB.xdrNumABlks).AppendLine(); - } + if (MDB.drEmbedSigWord == HFSP_MAGIC) + { + sb.AppendLine("Volume wraps a HFS+ volume."); + sb.AppendFormat("Starting block of the HFS+ volume: {0}", MDB.xdrStABNt).AppendLine(); + sb.AppendFormat("Allocations blocks of the HFS+ volume: {0}", MDB.xdrNumABlks).AppendLine(); + } else { sb.AppendFormat("{0} blocks in volume cache", MDB.drVCSize).AppendLine(); @@ -213,112 +211,168 @@ namespace FileSystemIDandChk.Plugins sb.AppendFormat("{0} blocks in volume common cache", MDB.drCtlCSize).AppendLine(); } - if(BB.signature == HFSBB_MAGIC) - { - sb.AppendLine("Volume is bootable."); - sb.AppendLine(); - sb.AppendLine("Boot Block:"); - if((BB.boot_flags & 0x40) == 0x40) - sb.AppendLine("Boot block should be executed."); - if((BB.boot_flags & 0x80) == 0x80) - { - sb.AppendLine("Boot block is in new unknown format."); - } - else - { - if(BB.sec_sv_pages > 0) - sb.AppendLine("Allocate secondary sound buffer at boot."); - else if(BB.sec_sv_pages < 0) - sb.AppendLine("Allocate secondary sound and video buffers at boot."); + if (BB.signature == HFSBB_MAGIC) + { + sb.AppendLine("Volume is bootable."); + sb.AppendLine(); + sb.AppendLine("Boot Block:"); + if ((BB.boot_flags & 0x40) == 0x40) + sb.AppendLine("Boot block should be executed."); + if ((BB.boot_flags & 0x80) == 0x80) + { + sb.AppendLine("Boot block is in new unknown format."); + } + else + { + if (BB.sec_sv_pages > 0) + sb.AppendLine("Allocate secondary sound buffer at boot."); + else if (BB.sec_sv_pages < 0) + sb.AppendLine("Allocate secondary sound and video buffers at boot."); - sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine(); - sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine(); - sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine(); - sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine(); - sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine(); - sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine(); - sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine(); - sb.AppendFormat("Maximum opened files: {0}", BB.max_files*4).AppendLine(); - sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine(); - sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine(); - sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine(); - sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine(); - } - } - else - sb.AppendLine("Volume is not bootable."); + sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine(); + sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine(); + sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine(); + sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine(); + sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine(); + sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine(); + sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine(); + sb.AppendFormat("Maximum opened files: {0}", BB.max_files * 4).AppendLine(); + sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine(); + sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine(); + sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine(); + sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine(); + } + } + else + sb.AppendLine("Volume is not bootable."); - information = sb.ToString(); + information = sb.ToString(); - return; - } - - private struct HFS_MasterDirectoryBlock // Should be sector 2 in volume - { - public UInt16 drSigWord; // 0x000, Signature, 0x4244 - public UInt32 drCrDate; // 0x002, Volume creation date - public UInt32 drLsMod; // 0x006, Volume last modification date - public UInt16 drAtrb; // 0x00A, Volume attributes - public UInt16 drNmFls; // 0x00C, Files in root directory - public UInt16 drVBMSt; // 0x00E, Start 512-byte sector of volume bitmap - public UInt16 drAllocPtr; // 0x010, Allocation block to begin next allocation - public UInt16 drNmAlBlks; // 0x012, Allocation blocks - public UInt32 drAlBlkSiz; // 0x014, Bytes per allocation block - public UInt32 drClpSiz; // 0x018, Bytes to allocate when extending a file - public UInt16 drAlBlSt; // 0x01C, Start 512-byte sector of first allocation block - public UInt32 drNxtCNID; // 0x01E, CNID for next file - public UInt16 drFreeBks; // 0x022, Free allocation blocks - public string drVN; // 0x024, Volume name (28 bytes) - public UInt32 drVolBkUp; // 0x040, Volume last backup time - public UInt16 drVSeqNum; // 0x044, Volume backup sequence number - public UInt32 drWrCnt; // 0x046, Filesystem write count - public UInt32 drXTClpSiz; // 0x04A, Bytes to allocate when extending the extents B-Tree - public UInt32 drCTClpSiz; // 0x04E, Bytes to allocate when extending the catalog B-Tree - public UInt16 drNmRtDirs; // 0x052, Number of directories in root directory - public UInt32 drFilCnt; // 0x054, Number of files in the volume - public UInt32 drDirCnt; // 0x058, Number of directories in the volume - public UInt32 drFndrInfo0; // 0x05C, finderInfo[0], CNID for bootable system's directory - public UInt32 drFndrInfo1; // 0x060, finderInfo[1], CNID of the directory containing the boot application - public UInt32 drFndrInfo2; // 0x064, finderInfo[2], CNID of the directory that should be opened on boot - public UInt32 drFndrInfo3; // 0x068, finderInfo[3], CNID for Mac OS 8 or 9 directory - public UInt32 drFndrInfo4; // 0x06C, finderInfo[4], Reserved - public UInt32 drFndrInfo5; // 0x070, finderInfo[5], CNID for Mac OS X directory - public UInt32 drFndrInfo6; // 0x074, finderInfo[6], first part of Mac OS X volume ID - public UInt32 drFndrInfo7; // 0x078, finderInfo[7], second part of Mac OS X volume ID + return; + } + + struct HFS_MasterDirectoryBlock // Should be sector 2 in volume + { + public UInt16 drSigWord; + // 0x000, Signature, 0x4244 + public UInt32 drCrDate; + // 0x002, Volume creation date + public UInt32 drLsMod; + // 0x006, Volume last modification date + public UInt16 drAtrb; + // 0x00A, Volume attributes + public UInt16 drNmFls; + // 0x00C, Files in root directory + public UInt16 drVBMSt; + // 0x00E, Start 512-byte sector of volume bitmap + public UInt16 drAllocPtr; + // 0x010, Allocation block to begin next allocation + public UInt16 drNmAlBlks; + // 0x012, Allocation blocks + public UInt32 drAlBlkSiz; + // 0x014, Bytes per allocation block + public UInt32 drClpSiz; + // 0x018, Bytes to allocate when extending a file + public UInt16 drAlBlSt; + // 0x01C, Start 512-byte sector of first allocation block + public UInt32 drNxtCNID; + // 0x01E, CNID for next file + public UInt16 drFreeBks; + // 0x022, Free allocation blocks + public string drVN; + // 0x024, Volume name (28 bytes) + public UInt32 drVolBkUp; + // 0x040, Volume last backup time + public UInt16 drVSeqNum; + // 0x044, Volume backup sequence number + public UInt32 drWrCnt; + // 0x046, Filesystem write count + public UInt32 drXTClpSiz; + // 0x04A, Bytes to allocate when extending the extents B-Tree + public UInt32 drCTClpSiz; + // 0x04E, Bytes to allocate when extending the catalog B-Tree + public UInt16 drNmRtDirs; + // 0x052, Number of directories in root directory + public UInt32 drFilCnt; + // 0x054, Number of files in the volume + public UInt32 drDirCnt; + // 0x058, Number of directories in the volume + public UInt32 drFndrInfo0; + // 0x05C, finderInfo[0], CNID for bootable system's directory + public UInt32 drFndrInfo1; + // 0x060, finderInfo[1], CNID of the directory containing the boot application + public UInt32 drFndrInfo2; + // 0x064, finderInfo[2], CNID of the directory that should be opened on boot + public UInt32 drFndrInfo3; + // 0x068, finderInfo[3], CNID for Mac OS 8 or 9 directory + public UInt32 drFndrInfo4; + // 0x06C, finderInfo[4], Reserved + public UInt32 drFndrInfo5; + // 0x070, finderInfo[5], CNID for Mac OS X directory + public UInt32 drFndrInfo6; + // 0x074, finderInfo[6], first part of Mac OS X volume ID + public UInt32 drFndrInfo7; + // 0x078, finderInfo[7], second part of Mac OS X volume ID // If wrapping HFS+ - public UInt16 drEmbedSigWord; // 0x07C, Embedded volume signature, "H+" if HFS+ is embedded ignore following two fields if not - public UInt16 xdrStABNt; // 0x07E, Starting block number of embedded HFS+ volume - public UInt16 xdrNumABlks; // 0x080, Allocation blocks used by embedded volume + public UInt16 drEmbedSigWord; + // 0x07C, Embedded volume signature, "H+" if HFS+ is embedded ignore following two fields if not + public UInt16 xdrStABNt; + // 0x07E, Starting block number of embedded HFS+ volume + public UInt16 xdrNumABlks; + // 0x080, Allocation blocks used by embedded volume // If not - public UInt16 drVCSize; // 0x07C, Size in blocks of volume cache - public UInt16 drVBMCSize; // 0x07E, Size in blocks of volume bitmap cache - public UInt16 drCtlCSize; // 0x080, Size in blocks of volume common cache + public UInt16 drVCSize; + // 0x07C, Size in blocks of volume cache + public UInt16 drVBMCSize; + // 0x07E, Size in blocks of volume bitmap cache + public UInt16 drCtlCSize; + // 0x080, Size in blocks of volume common cache // End of variable variables :D - public UInt32 drXTFlSize; // 0x082, Bytes in the extents B-Tree - // 3 HFS extents following, 32 bits each - public UInt32 drCTFlSize; // 0x092, Bytes in the catalog B-Tree - // 3 HFS extents following, 32 bits each - } - - private struct HFS_BootBlock // Should be sectors 0 and 1 in volume - { - public UInt16 signature; // 0x000, Signature, 0x4C4B if bootable - public UInt32 branch; // 0x002, Branch - public byte boot_flags; // 0x006, Boot block flags - public byte boot_version; // 0x007, Boot block version - public Int16 sec_sv_pages; // 0x008, Allocate secondary buffers - public string system_name; // 0x00A, System file name (16 bytes) - public string finder_name; // 0x01A, Finder file name (16 bytes) - public string debug_name; // 0x02A, Debugger file name (16 bytes) - public string disasm_name; // 0x03A, Disassembler file name (16 bytes) - public string stupscr_name; // 0x04A, Startup screen file name (16 bytes) - public string bootup_name; // 0x05A, First program to execute on boot (16 bytes) - public string clipbrd_name; // 0x06A, Clipboard file name (16 bytes) - public UInt16 max_files; // 0x07A, 1/4 of maximum opened at a time files - public UInt16 queue_size; // 0x07C, Event queue size - public UInt32 heap_128k; // 0x07E, Heap size on a Mac with 128KiB of RAM - public UInt32 heap_256k; // 0x082, Heap size on a Mac with 256KiB of RAM - public UInt32 heap_512k; // 0x086, Heap size on a Mac with 512KiB of RAM or more - } // Follows boot code - } + public UInt32 drXTFlSize; + // 0x082, Bytes in the extents B-Tree + // 3 HFS extents following, 32 bits each + public UInt32 drCTFlSize; + // 0x092, Bytes in the catalog B-Tree + // 3 HFS extents following, 32 bits each + } + + struct HFS_BootBlock // Should be sectors 0 and 1 in volume + { + public UInt16 signature; + // 0x000, Signature, 0x4C4B if bootable + public UInt32 branch; + // 0x002, Branch + public byte boot_flags; + // 0x006, Boot block flags + public byte boot_version; + // 0x007, Boot block version + public Int16 sec_sv_pages; + // 0x008, Allocate secondary buffers + public string system_name; + // 0x00A, System file name (16 bytes) + public string finder_name; + // 0x01A, Finder file name (16 bytes) + public string debug_name; + // 0x02A, Debugger file name (16 bytes) + public string disasm_name; + // 0x03A, Disassembler file name (16 bytes) + public string stupscr_name; + // 0x04A, Startup screen file name (16 bytes) + public string bootup_name; + // 0x05A, First program to execute on boot (16 bytes) + public string clipbrd_name; + // 0x06A, Clipboard file name (16 bytes) + public UInt16 max_files; + // 0x07A, 1/4 of maximum opened at a time files + public UInt16 queue_size; + // 0x07C, Event queue size + public UInt32 heap_128k; + // 0x07E, Heap size on a Mac with 128KiB of RAM + public UInt32 heap_256k; + // 0x082, Heap size on a Mac with 256KiB of RAM + public UInt32 heap_512k; + // 0x086, Heap size on a Mac with 512KiB of RAM or more + } + // Follows boot code + } } diff --git a/FileSystemIDandChk/Plugins/AppleHFSPlus.cs b/FileSystemIDandChk/Plugins/AppleHFSPlus.cs index 5e1cff41..d8b5b0cd 100644 --- a/FileSystemIDandChk/Plugins/AppleHFSPlus.cs +++ b/FileSystemIDandChk/Plugins/AppleHFSPlus.cs @@ -1,29 +1,30 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; // Information from Apple TechNote 1150: https://developer.apple.com/legacy/library/technotes/tn/tn1150.html namespace FileSystemIDandChk.Plugins { - class AppleHFSPlus : Plugin - { - private const UInt16 HFS_MAGIC = 0x4244; // "BD" - private const UInt16 HFSP_MAGIC = 0x482B; // "H+" - private const UInt16 HFSX_MAGIC = 0x4858; // "HX" - - public AppleHFSPlus(PluginBase Core) + class AppleHFSPlus : Plugin + { + const UInt16 HFS_MAGIC = 0x4244; + // "BD" + const UInt16 HFSP_MAGIC = 0x482B; + // "H+" + const UInt16 HFSX_MAGIC = 0x4858; + // "HX" + public AppleHFSPlus(PluginBase Core) { - base.Name = "Apple HFS+ filesystem"; - base.PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08"); + Name = "Apple HFS+ filesystem"; + PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - UInt16 drSigWord; - UInt16 xdrStABNt; - UInt16 drAlBlSt; - UInt32 drAlBlkSiz; + { + UInt16 drSigWord; + UInt16 xdrStABNt; + UInt16 drAlBlSt; + UInt32 drAlBlkSiz; byte[] vh_sector; ulong hfsp_offset; @@ -32,106 +33,105 @@ namespace FileSystemIDandChk.Plugins drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0); // Check for HFS Wrapper MDB - if(drSigWord == HFS_MAGIC) // "BD" - { + if (drSigWord == HFS_MAGIC) // "BD" + { drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x07C); // Read embedded HFS+ signature - if(drSigWord == HFSP_MAGIC) // "H+" - { + if (drSigWord == HFSP_MAGIC) // "H+" + { xdrStABNt = BigEndianBitConverter.ToUInt16(vh_sector, 0x07E); // Starting block number of embedded HFS+ volume drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x014); // Block size drAlBlSt = BigEndianBitConverter.ToUInt16(vh_sector, 0x01C); // Start of allocated blocks (in 512-byte/block) - hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512))*(imagePlugin.GetSectorSize() / 512); - } - else - { - hfsp_offset = 0; - } - } - else - { - hfsp_offset = 0; - } + hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512)) * (imagePlugin.GetSectorSize() / 512); + } + else + { + hfsp_offset = 0; + } + } + else + { + hfsp_offset = 0; + } vh_sector = imagePlugin.ReadSector(2 + partitionOffset + hfsp_offset); // Read volume header drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0); - if(drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC) - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + if (drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC) + return true; + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - UInt16 drSigWord; - UInt16 xdrStABNt; - UInt16 drAlBlSt; - UInt32 drAlBlkSiz; - HFSPlusVolumeHeader HPVH = new HFSPlusVolumeHeader(); + UInt16 drSigWord; + UInt16 xdrStABNt; + UInt16 drAlBlSt; + UInt32 drAlBlkSiz; + HFSPlusVolumeHeader HPVH = new HFSPlusVolumeHeader(); ulong hfsp_offset; - bool wrapped = false; + bool wrapped; byte[] vh_sector; vh_sector = imagePlugin.ReadSector(2 + partitionOffset); // Read volume header, of HFS Wrapper MDB drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0); // Check for HFS Wrapper MDB - if(drSigWord == HFS_MAGIC) // "BD" - { + if (drSigWord == HFS_MAGIC) // "BD" + { drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x07C); // Read embedded HFS+ signature - if(drSigWord == HFSP_MAGIC) // "H+" - { + if (drSigWord == HFSP_MAGIC) // "H+" + { xdrStABNt = BigEndianBitConverter.ToUInt16(vh_sector, 0x07E); // Starting block number of embedded HFS+ volume drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x014); // Block size drAlBlSt = BigEndianBitConverter.ToUInt16(vh_sector, 0x01C); // Start of allocated blocks (in 512-byte/block) - hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512))*(imagePlugin.GetSectorSize() / 512); - wrapped = true; - } - else - { - hfsp_offset = 0; - wrapped = false; - } - } - else - { - hfsp_offset = 0; - wrapped = false; - } + hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512)) * (imagePlugin.GetSectorSize() / 512); + wrapped = true; + } + else + { + hfsp_offset = 0; + wrapped = false; + } + } + else + { + hfsp_offset = 0; + wrapped = false; + } vh_sector = imagePlugin.ReadSector(2 + partitionOffset + hfsp_offset); // Read volume header HPVH.signature = BigEndianBitConverter.ToUInt16(vh_sector, 0x000); - if(HPVH.signature == HFSP_MAGIC || HPVH.signature == HFSX_MAGIC) - { - StringBuilder sb = new StringBuilder(); + if (HPVH.signature == HFSP_MAGIC || HPVH.signature == HFSX_MAGIC) + { + StringBuilder sb = new StringBuilder(); - if(HPVH.signature == 0x482B) - sb.AppendLine("HFS+ filesystem."); - if(HPVH.signature == 0x4858) - sb.AppendLine("HFSX filesystem."); - if(wrapped) - sb.AppendLine("Volume is wrapped inside an HFS volume."); + if (HPVH.signature == 0x482B) + sb.AppendLine("HFS+ filesystem."); + if (HPVH.signature == 0x4858) + sb.AppendLine("HFSX filesystem."); + if (wrapped) + sb.AppendLine("Volume is wrapped inside an HFS volume."); HPVH.version = BigEndianBitConverter.ToUInt16(vh_sector, 0x002); - if(HPVH.version == 4 || HPVH.version == 5) - { + if (HPVH.version == 4 || HPVH.version == 5) + { HPVH.attributes = BigEndianBitConverter.ToUInt32(vh_sector, 0x004); byte[] lastMountedVersion_b = new byte[4]; Array.Copy(vh_sector, 0x008, lastMountedVersion_b, 0, 4); - HPVH.lastMountedVersion = Encoding.ASCII.GetString(lastMountedVersion_b); + HPVH.lastMountedVersion = Encoding.ASCII.GetString(lastMountedVersion_b); HPVH.journalInfoBlock = BigEndianBitConverter.ToUInt32(vh_sector, 0x00C); HPVH.createDate = BigEndianBitConverter.ToUInt32(vh_sector, 0x010); @@ -167,210 +167,325 @@ namespace FileSystemIDandChk.Plugins HPVH.attributesFile_logicalSize = BigEndianBitConverter.ToUInt64(vh_sector, 0x170); HPVH.startupFile_logicalSize = BigEndianBitConverter.ToUInt64(vh_sector, 0x1C0); - sb.AppendFormat("Filesystem version is {0}.", HPVH.version).AppendLine(); + sb.AppendFormat("Filesystem version is {0}.", HPVH.version).AppendLine(); - if((HPVH.attributes & 0x80) == 0x80) - sb.AppendLine("Volume is locked on hardware."); - if((HPVH.attributes & 0x100) == 0x100) - sb.AppendLine("Volume is unmounted."); - if((HPVH.attributes & 0x200) == 0x200) - sb.AppendLine("There are bad blocks in the extents file."); - if((HPVH.attributes & 0x400) == 0x400) - sb.AppendLine("Volume does not require cache."); - if((HPVH.attributes & 0x800) == 0x800) - sb.AppendLine("Volume state is inconsistent."); - if((HPVH.attributes & 0x1000) == 0x1000) - sb.AppendLine("CNIDs are reused."); - if((HPVH.attributes & 0x2000) == 0x2000) - sb.AppendLine("Volume is journaled."); - if((HPVH.attributes & 0x8000) == 0x8000) - sb.AppendLine("Volume is locked on software."); + if ((HPVH.attributes & 0x80) == 0x80) + sb.AppendLine("Volume is locked on hardware."); + if ((HPVH.attributes & 0x100) == 0x100) + sb.AppendLine("Volume is unmounted."); + if ((HPVH.attributes & 0x200) == 0x200) + sb.AppendLine("There are bad blocks in the extents file."); + if ((HPVH.attributes & 0x400) == 0x400) + sb.AppendLine("Volume does not require cache."); + if ((HPVH.attributes & 0x800) == 0x800) + sb.AppendLine("Volume state is inconsistent."); + if ((HPVH.attributes & 0x1000) == 0x1000) + sb.AppendLine("CNIDs are reused."); + if ((HPVH.attributes & 0x2000) == 0x2000) + sb.AppendLine("Volume is journaled."); + if ((HPVH.attributes & 0x8000) == 0x8000) + sb.AppendLine("Volume is locked on software."); - sb.AppendFormat("Implementation that last mounted the volume: \"{0}\".", HPVH.lastMountedVersion).AppendLine(); - if((HPVH.attributes & 0x2000) == 0x2000) - sb.AppendFormat("Journal starts at allocation block {0}.", HPVH.journalInfoBlock).AppendLine(); - sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(HPVH.createDate)).AppendLine(); - sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(HPVH.modifyDate)).AppendLine(); - sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(HPVH.backupDate)).AppendLine(); - sb.AppendFormat("Last check date: {0}", DateHandlers.MacToDateTime(HPVH.checkedDate)).AppendLine(); - sb.AppendFormat("{0} files on volume.", HPVH.fileCount).AppendLine(); - sb.AppendFormat("{0} folders on volume.", HPVH.folderCount).AppendLine(); - sb.AppendFormat("{0} bytes per allocation block.", HPVH.blockSize).AppendLine(); - sb.AppendFormat("{0} allocation blocks.", HPVH.totalBlocks).AppendLine(); - sb.AppendFormat("{0} free blocks.", HPVH.freeBlocks).AppendLine(); - sb.AppendFormat("Next allocation block: {0}.", HPVH.nextAllocation).AppendLine(); - sb.AppendFormat("Resource fork clump size: {0} bytes.", HPVH.rsrcClumpSize).AppendLine(); - sb.AppendFormat("Data fork clump size: {0} bytes.", HPVH.dataClumpSize).AppendLine(); - sb.AppendFormat("Next unused CNID: {0}.", HPVH.nextCatalogID).AppendLine(); - sb.AppendFormat("Volume has been mounted writable {0} times.", HPVH.writeCount).AppendLine(); - sb.AppendFormat("Allocation File is {0} bytes.", HPVH.allocationFile_logicalSize).AppendLine(); - sb.AppendFormat("Extents File is {0} bytes.", HPVH.extentsFile_logicalSize).AppendLine(); - sb.AppendFormat("Catalog File is {0} bytes.", HPVH.catalogFile_logicalSize).AppendLine(); - sb.AppendFormat("Attributes File is {0} bytes.", HPVH.attributesFile_logicalSize).AppendLine(); - sb.AppendFormat("Startup File is {0} bytes.", HPVH.startupFile_logicalSize).AppendLine(); - sb.AppendLine("Finder info:"); - sb.AppendFormat("CNID of bootable system's directory: {0}", HPVH.drFndrInfo0).AppendLine(); - sb.AppendFormat("CNID of first-run application's directory: {0}", HPVH.drFndrInfo1).AppendLine(); - sb.AppendFormat("CNID of previously opened directory: {0}", HPVH.drFndrInfo2).AppendLine(); - sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", HPVH.drFndrInfo3).AppendLine(); - sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", HPVH.drFndrInfo5).AppendLine(); - sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7).AppendLine(); - } - else - { - sb.AppendFormat("Filesystem version is {0}.", HPVH.version).AppendLine(); - sb.AppendLine("This version is not supported yet."); - } + sb.AppendFormat("Implementation that last mounted the volume: \"{0}\".", HPVH.lastMountedVersion).AppendLine(); + if ((HPVH.attributes & 0x2000) == 0x2000) + sb.AppendFormat("Journal starts at allocation block {0}.", HPVH.journalInfoBlock).AppendLine(); + sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(HPVH.createDate)).AppendLine(); + sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(HPVH.modifyDate)).AppendLine(); + sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(HPVH.backupDate)).AppendLine(); + sb.AppendFormat("Last check date: {0}", DateHandlers.MacToDateTime(HPVH.checkedDate)).AppendLine(); + sb.AppendFormat("{0} files on volume.", HPVH.fileCount).AppendLine(); + sb.AppendFormat("{0} folders on volume.", HPVH.folderCount).AppendLine(); + sb.AppendFormat("{0} bytes per allocation block.", HPVH.blockSize).AppendLine(); + sb.AppendFormat("{0} allocation blocks.", HPVH.totalBlocks).AppendLine(); + sb.AppendFormat("{0} free blocks.", HPVH.freeBlocks).AppendLine(); + sb.AppendFormat("Next allocation block: {0}.", HPVH.nextAllocation).AppendLine(); + sb.AppendFormat("Resource fork clump size: {0} bytes.", HPVH.rsrcClumpSize).AppendLine(); + sb.AppendFormat("Data fork clump size: {0} bytes.", HPVH.dataClumpSize).AppendLine(); + sb.AppendFormat("Next unused CNID: {0}.", HPVH.nextCatalogID).AppendLine(); + sb.AppendFormat("Volume has been mounted writable {0} times.", HPVH.writeCount).AppendLine(); + sb.AppendFormat("Allocation File is {0} bytes.", HPVH.allocationFile_logicalSize).AppendLine(); + sb.AppendFormat("Extents File is {0} bytes.", HPVH.extentsFile_logicalSize).AppendLine(); + sb.AppendFormat("Catalog File is {0} bytes.", HPVH.catalogFile_logicalSize).AppendLine(); + sb.AppendFormat("Attributes File is {0} bytes.", HPVH.attributesFile_logicalSize).AppendLine(); + sb.AppendFormat("Startup File is {0} bytes.", HPVH.startupFile_logicalSize).AppendLine(); + sb.AppendLine("Finder info:"); + sb.AppendFormat("CNID of bootable system's directory: {0}", HPVH.drFndrInfo0).AppendLine(); + sb.AppendFormat("CNID of first-run application's directory: {0}", HPVH.drFndrInfo1).AppendLine(); + sb.AppendFormat("CNID of previously opened directory: {0}", HPVH.drFndrInfo2).AppendLine(); + sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", HPVH.drFndrInfo3).AppendLine(); + sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", HPVH.drFndrInfo5).AppendLine(); + sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7).AppendLine(); + } + else + { + sb.AppendFormat("Filesystem version is {0}.", HPVH.version).AppendLine(); + sb.AppendLine("This version is not supported yet."); + } - information = sb.ToString(); - } - else - return; - } - + information = sb.ToString(); + } + else + return; + } // Size = 532 bytes - private struct HFSPlusVolumeHeader // Should be offset 0x0400 bytes in volume - { - public UInt16 signature; // 0x000, "H+" for HFS+, "HX" for HFSX - public UInt16 version; // 0x002, 4 for HFS+, 5 for HFSX - public UInt32 attributes; // 0x004, Volume attributes - public string lastMountedVersion; // 0x008, Implementation that last mounted the volume. - // Reserved by Apple: - // "8.10" Mac OS 8.1 to 9.2.2 - // "10.0" Mac OS X - // "HFSJ" Journaled implementation - // "fsck" /sbin/fsck - public UInt32 journalInfoBlock; // 0x00C, Allocation block number containing the journal - - public ulong createDate; // 0x010, Date of volume creation - public ulong modifyDate; // 0x018, Date of last volume modification - public ulong backupDate; // 0x020, Date of last backup - public ulong checkedDate; // 0x028, Date of last consistency check - - public UInt32 fileCount; // 0x030, File on the volume - public UInt32 folderCount; // 0x034, Folders on the volume - - public UInt32 blockSize; // 0x038, Bytes per allocation block - public UInt32 totalBlocks; // 0x03C, Allocation blocks on the volume - public UInt32 freeBlocks; // 0x040, Free allocation blocks - - public UInt32 nextAllocation; // 0x044, Hint for next allocation block - public UInt32 rsrcClumpSize; // 0x048, Resource fork clump size - public UInt32 dataClumpSize; // 0x04C, Data fork clump size - public UInt32 nextCatalogID; // 0x050, Next unused CNID - - public UInt32 writeCount; // 0x054, Times that the volume has been mounted writable - public UInt64 encodingsBitmap; // 0x058, Used text encoding hints - - public UInt32 drFndrInfo0; // 0x060, finderInfo[0], CNID for bootable system's directory - public UInt32 drFndrInfo1; // 0x064, finderInfo[1], CNID of the directory containing the boot application - public UInt32 drFndrInfo2; // 0x068, finderInfo[2], CNID of the directory that should be opened on boot - public UInt32 drFndrInfo3; // 0x06C, finderInfo[3], CNID for Mac OS 8 or 9 directory - public UInt32 drFndrInfo4; // 0x070, finderInfo[4], Reserved - public UInt32 drFndrInfo5; // 0x074, finderInfo[5], CNID for Mac OS X directory - public UInt32 drFndrInfo6; // 0x078, finderInfo[6], first part of Mac OS X volume ID - public UInt32 drFndrInfo7; // 0x07C, finderInfo[7], second part of Mac OS X volume ID - - // HFSPlusForkData allocationFile; - public UInt64 allocationFile_logicalSize; // 0x080 - public UInt32 allocationFile_clumpSize; // 0x088 - public UInt32 allocationFile_totalBlocks; // 0x08C - public UInt32 allocationFile_extents_startBlock0; // 0x090 - public UInt32 allocationFile_extents_blockCount0; // 0x094 - public UInt32 allocationFile_extents_startBlock1; // 0x098 - public UInt32 allocationFile_extents_blockCount1; // 0x09C - public UInt32 allocationFile_extents_startBlock2; // 0x0A0 - public UInt32 allocationFile_extents_blockCount2; // 0x0A4 - public UInt32 allocationFile_extents_startBlock3; // 0x0A8 - public UInt32 allocationFile_extents_blockCount3; // 0x0AC - public UInt32 allocationFile_extents_startBlock4; // 0x0B0 - public UInt32 allocationFile_extents_blockCount4; // 0x0B4 - public UInt32 allocationFile_extents_startBlock5; // 0x0B8 - public UInt32 allocationFile_extents_blockCount5; // 0x0BC - public UInt32 allocationFile_extents_startBlock6; // 0x0C0 - public UInt32 allocationFile_extents_blockCount6; // 0x0C4 - public UInt32 allocationFile_extents_startBlock7; // 0x0C8 - public UInt32 allocationFile_extents_blockCount7; // 0x0CC - // HFSPlusForkData extentsFile; - public UInt64 extentsFile_logicalSize; // 0x0D0 - public UInt32 extentsFile_clumpSize; // 0x0D8 - public UInt32 extentsFile_totalBlocks; // 0x0DC - public UInt32 extentsFile_extents_startBlock0; // 0x0E0 - public UInt32 extentsFile_extents_blockCount0; // 0x0E4 - public UInt32 extentsFile_extents_startBlock1; // 0x0E8 - public UInt32 extentsFile_extents_blockCount1; // 0x0EC - public UInt32 extentsFile_extents_startBlock2; // 0x0F0 - public UInt32 extentsFile_extents_blockCount2; // 0x0F4 - public UInt32 extentsFile_extents_startBlock3; // 0x0F8 - public UInt32 extentsFile_extents_blockCount3; // 0x0FC - public UInt32 extentsFile_extents_startBlock4; // 0x100 - public UInt32 extentsFile_extents_blockCount4; // 0x104 - public UInt32 extentsFile_extents_startBlock5; // 0x108 - public UInt32 extentsFile_extents_blockCount5; // 0x10C - public UInt32 extentsFile_extents_startBlock6; // 0x110 - public UInt32 extentsFile_extents_blockCount6; // 0x114 - public UInt32 extentsFile_extents_startBlock7; // 0x118 - public UInt32 extentsFile_extents_blockCount7; // 0x11C - // HFSPlusForkData catalogFile; - public UInt64 catalogFile_logicalSize; // 0x120 - public UInt32 catalogFile_clumpSize; // 0x128 - public UInt32 catalogFile_totalBlocks; // 0x12C - public UInt32 catalogFile_extents_startBlock0; // 0x130 - public UInt32 catalogFile_extents_blockCount0; // 0x134 - public UInt32 catalogFile_extents_startBlock1; // 0x138 - public UInt32 catalogFile_extents_blockCount1; // 0x13C - public UInt32 catalogFile_extents_startBlock2; // 0x140 - public UInt32 catalogFile_extents_blockCount2; // 0x144 - public UInt32 catalogFile_extents_startBlock3; // 0x148 - public UInt32 catalogFile_extents_blockCount3; // 0x14C - public UInt32 catalogFile_extents_startBlock4; // 0x150 - public UInt32 catalogFile_extents_blockCount4; // 0x154 - public UInt32 catalogFile_extents_startBlock5; // 0x158 - public UInt32 catalogFile_extents_blockCount5; // 0x15C - public UInt32 catalogFile_extents_startBlock6; // 0x160 - public UInt32 catalogFile_extents_blockCount6; // 0x164 - public UInt32 catalogFile_extents_startBlock7; // 0x168 - public UInt32 catalogFile_extents_blockCount7; // 0x16C - // HFSPlusForkData attributesFile; - public UInt64 attributesFile_logicalSize; // 0x170 - public UInt32 attributesFile_clumpSize; // 0x178 - public UInt32 attributesFile_totalBlocks; // 0x17C - public UInt32 attributesFile_extents_startBlock0; // 0x180 - public UInt32 attributesFile_extents_blockCount0; // 0x184 - public UInt32 attributesFile_extents_startBlock1; // 0x188 - public UInt32 attributesFile_extents_blockCount1; // 0x18C - public UInt32 attributesFile_extents_startBlock2; // 0x190 - public UInt32 attributesFile_extents_blockCount2; // 0x194 - public UInt32 attributesFile_extents_startBlock3; // 0x198 - public UInt32 attributesFile_extents_blockCount3; // 0x19C - public UInt32 attributesFile_extents_startBlock4; // 0x1A0 - public UInt32 attributesFile_extents_blockCount4; // 0x1A4 - public UInt32 attributesFile_extents_startBlock5; // 0x1A8 - public UInt32 attributesFile_extents_blockCount5; // 0x1AC - public UInt32 attributesFile_extents_startBlock6; // 0x1B0 - public UInt32 attributesFile_extents_blockCount6; // 0x1B4 - public UInt32 attributesFile_extents_startBlock7; // 0x1B8 - public UInt32 attributesFile_extents_blockCount7; // 0x1BC - // HFSPlusForkData startupFile; - public UInt64 startupFile_logicalSize; // 0x1C0 - public UInt32 startupFile_clumpSize; // 0x1C8 - public UInt32 startupFile_totalBlocks; // 0x1CC - public UInt32 startupFile_extents_startBlock0; // 0x1D0 - public UInt32 startupFile_extents_blockCount0; // 0x1D4 - public UInt32 startupFile_extents_startBlock1; // 0x1D8 - public UInt32 startupFile_extents_blockCount1; // 0x1E0 - public UInt32 startupFile_extents_startBlock2; // 0x1E4 - public UInt32 startupFile_extents_blockCount2; // 0x1E8 - public UInt32 startupFile_extents_startBlock3; // 0x1EC - public UInt32 startupFile_extents_blockCount3; // 0x1F0 - public UInt32 startupFile_extents_startBlock4; // 0x1F4 - public UInt32 startupFile_extents_blockCount4; // 0x1F8 - public UInt32 startupFile_extents_startBlock5; // 0x1FC - public UInt32 startupFile_extents_blockCount5; // 0x200 - public UInt32 startupFile_extents_startBlock6; // 0x204 - public UInt32 startupFile_extents_blockCount6; // 0x208 - public UInt32 startupFile_extents_startBlock7; // 0x20C - public UInt32 startupFile_extents_blockCount7; // 0x210 - } - } + struct HFSPlusVolumeHeader // Should be offset 0x0400 bytes in volume + { + public UInt16 signature; + // 0x000, "H+" for HFS+, "HX" for HFSX + public UInt16 version; + // 0x002, 4 for HFS+, 5 for HFSX + public UInt32 attributes; + // 0x004, Volume attributes + public string lastMountedVersion; + // 0x008, Implementation that last mounted the volume. + // Reserved by Apple: + // "8.10" Mac OS 8.1 to 9.2.2 + // "10.0" Mac OS X + // "HFSJ" Journaled implementation + // "fsck" /sbin/fsck + public UInt32 journalInfoBlock; + // 0x00C, Allocation block number containing the journal + public ulong createDate; + // 0x010, Date of volume creation + public ulong modifyDate; + // 0x018, Date of last volume modification + public ulong backupDate; + // 0x020, Date of last backup + public ulong checkedDate; + // 0x028, Date of last consistency check + public UInt32 fileCount; + // 0x030, File on the volume + public UInt32 folderCount; + // 0x034, Folders on the volume + public UInt32 blockSize; + // 0x038, Bytes per allocation block + public UInt32 totalBlocks; + // 0x03C, Allocation blocks on the volume + public UInt32 freeBlocks; + // 0x040, Free allocation blocks + public UInt32 nextAllocation; + // 0x044, Hint for next allocation block + public UInt32 rsrcClumpSize; + // 0x048, Resource fork clump size + public UInt32 dataClumpSize; + // 0x04C, Data fork clump size + public UInt32 nextCatalogID; + // 0x050, Next unused CNID + public UInt32 writeCount; + // 0x054, Times that the volume has been mounted writable + public UInt64 encodingsBitmap; + // 0x058, Used text encoding hints + public UInt32 drFndrInfo0; + // 0x060, finderInfo[0], CNID for bootable system's directory + public UInt32 drFndrInfo1; + // 0x064, finderInfo[1], CNID of the directory containing the boot application + public UInt32 drFndrInfo2; + // 0x068, finderInfo[2], CNID of the directory that should be opened on boot + public UInt32 drFndrInfo3; + // 0x06C, finderInfo[3], CNID for Mac OS 8 or 9 directory + public UInt32 drFndrInfo4; + // 0x070, finderInfo[4], Reserved + public UInt32 drFndrInfo5; + // 0x074, finderInfo[5], CNID for Mac OS X directory + public UInt32 drFndrInfo6; + // 0x078, finderInfo[6], first part of Mac OS X volume ID + public UInt32 drFndrInfo7; + // 0x07C, finderInfo[7], second part of Mac OS X volume ID + // HFSPlusForkData allocationFile; + public UInt64 allocationFile_logicalSize; + // 0x080 + public UInt32 allocationFile_clumpSize; + // 0x088 + public UInt32 allocationFile_totalBlocks; + // 0x08C + public UInt32 allocationFile_extents_startBlock0; + // 0x090 + public UInt32 allocationFile_extents_blockCount0; + // 0x094 + public UInt32 allocationFile_extents_startBlock1; + // 0x098 + public UInt32 allocationFile_extents_blockCount1; + // 0x09C + public UInt32 allocationFile_extents_startBlock2; + // 0x0A0 + public UInt32 allocationFile_extents_blockCount2; + // 0x0A4 + public UInt32 allocationFile_extents_startBlock3; + // 0x0A8 + public UInt32 allocationFile_extents_blockCount3; + // 0x0AC + public UInt32 allocationFile_extents_startBlock4; + // 0x0B0 + public UInt32 allocationFile_extents_blockCount4; + // 0x0B4 + public UInt32 allocationFile_extents_startBlock5; + // 0x0B8 + public UInt32 allocationFile_extents_blockCount5; + // 0x0BC + public UInt32 allocationFile_extents_startBlock6; + // 0x0C0 + public UInt32 allocationFile_extents_blockCount6; + // 0x0C4 + public UInt32 allocationFile_extents_startBlock7; + // 0x0C8 + public UInt32 allocationFile_extents_blockCount7; + // 0x0CC + // HFSPlusForkData extentsFile; + public UInt64 extentsFile_logicalSize; + // 0x0D0 + public UInt32 extentsFile_clumpSize; + // 0x0D8 + public UInt32 extentsFile_totalBlocks; + // 0x0DC + public UInt32 extentsFile_extents_startBlock0; + // 0x0E0 + public UInt32 extentsFile_extents_blockCount0; + // 0x0E4 + public UInt32 extentsFile_extents_startBlock1; + // 0x0E8 + public UInt32 extentsFile_extents_blockCount1; + // 0x0EC + public UInt32 extentsFile_extents_startBlock2; + // 0x0F0 + public UInt32 extentsFile_extents_blockCount2; + // 0x0F4 + public UInt32 extentsFile_extents_startBlock3; + // 0x0F8 + public UInt32 extentsFile_extents_blockCount3; + // 0x0FC + public UInt32 extentsFile_extents_startBlock4; + // 0x100 + public UInt32 extentsFile_extents_blockCount4; + // 0x104 + public UInt32 extentsFile_extents_startBlock5; + // 0x108 + public UInt32 extentsFile_extents_blockCount5; + // 0x10C + public UInt32 extentsFile_extents_startBlock6; + // 0x110 + public UInt32 extentsFile_extents_blockCount6; + // 0x114 + public UInt32 extentsFile_extents_startBlock7; + // 0x118 + public UInt32 extentsFile_extents_blockCount7; + // 0x11C + // HFSPlusForkData catalogFile; + public UInt64 catalogFile_logicalSize; + // 0x120 + public UInt32 catalogFile_clumpSize; + // 0x128 + public UInt32 catalogFile_totalBlocks; + // 0x12C + public UInt32 catalogFile_extents_startBlock0; + // 0x130 + public UInt32 catalogFile_extents_blockCount0; + // 0x134 + public UInt32 catalogFile_extents_startBlock1; + // 0x138 + public UInt32 catalogFile_extents_blockCount1; + // 0x13C + public UInt32 catalogFile_extents_startBlock2; + // 0x140 + public UInt32 catalogFile_extents_blockCount2; + // 0x144 + public UInt32 catalogFile_extents_startBlock3; + // 0x148 + public UInt32 catalogFile_extents_blockCount3; + // 0x14C + public UInt32 catalogFile_extents_startBlock4; + // 0x150 + public UInt32 catalogFile_extents_blockCount4; + // 0x154 + public UInt32 catalogFile_extents_startBlock5; + // 0x158 + public UInt32 catalogFile_extents_blockCount5; + // 0x15C + public UInt32 catalogFile_extents_startBlock6; + // 0x160 + public UInt32 catalogFile_extents_blockCount6; + // 0x164 + public UInt32 catalogFile_extents_startBlock7; + // 0x168 + public UInt32 catalogFile_extents_blockCount7; + // 0x16C + // HFSPlusForkData attributesFile; + public UInt64 attributesFile_logicalSize; + // 0x170 + public UInt32 attributesFile_clumpSize; + // 0x178 + public UInt32 attributesFile_totalBlocks; + // 0x17C + public UInt32 attributesFile_extents_startBlock0; + // 0x180 + public UInt32 attributesFile_extents_blockCount0; + // 0x184 + public UInt32 attributesFile_extents_startBlock1; + // 0x188 + public UInt32 attributesFile_extents_blockCount1; + // 0x18C + public UInt32 attributesFile_extents_startBlock2; + // 0x190 + public UInt32 attributesFile_extents_blockCount2; + // 0x194 + public UInt32 attributesFile_extents_startBlock3; + // 0x198 + public UInt32 attributesFile_extents_blockCount3; + // 0x19C + public UInt32 attributesFile_extents_startBlock4; + // 0x1A0 + public UInt32 attributesFile_extents_blockCount4; + // 0x1A4 + public UInt32 attributesFile_extents_startBlock5; + // 0x1A8 + public UInt32 attributesFile_extents_blockCount5; + // 0x1AC + public UInt32 attributesFile_extents_startBlock6; + // 0x1B0 + public UInt32 attributesFile_extents_blockCount6; + // 0x1B4 + public UInt32 attributesFile_extents_startBlock7; + // 0x1B8 + public UInt32 attributesFile_extents_blockCount7; + // 0x1BC + // HFSPlusForkData startupFile; + public UInt64 startupFile_logicalSize; + // 0x1C0 + public UInt32 startupFile_clumpSize; + // 0x1C8 + public UInt32 startupFile_totalBlocks; + // 0x1CC + public UInt32 startupFile_extents_startBlock0; + // 0x1D0 + public UInt32 startupFile_extents_blockCount0; + // 0x1D4 + public UInt32 startupFile_extents_startBlock1; + // 0x1D8 + public UInt32 startupFile_extents_blockCount1; + // 0x1E0 + public UInt32 startupFile_extents_startBlock2; + // 0x1E4 + public UInt32 startupFile_extents_blockCount2; + // 0x1E8 + public UInt32 startupFile_extents_startBlock3; + // 0x1EC + public UInt32 startupFile_extents_blockCount3; + // 0x1F0 + public UInt32 startupFile_extents_startBlock4; + // 0x1F4 + public UInt32 startupFile_extents_blockCount4; + // 0x1F8 + public UInt32 startupFile_extents_startBlock5; + // 0x1FC + public UInt32 startupFile_extents_blockCount5; + // 0x200 + public UInt32 startupFile_extents_startBlock6; + // 0x204 + public UInt32 startupFile_extents_blockCount6; + // 0x208 + public UInt32 startupFile_extents_startBlock7; + // 0x20C + public UInt32 startupFile_extents_blockCount7; + // 0x210 + } + } } diff --git a/FileSystemIDandChk/Plugins/AppleMFS.cs b/FileSystemIDandChk/Plugins/AppleMFS.cs index 41fbc957..f9faecef 100644 --- a/FileSystemIDandChk/Plugins/AppleMFS.cs +++ b/FileSystemIDandChk/Plugins/AppleMFS.cs @@ -1,207 +1,234 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; // Information from Inside Macintosh -// TODO: Implement support for disc images -/* namespace FileSystemIDandChk.Plugins { - class AppleMFS : Plugin - { - private const UInt16 MFS_MAGIC = 0xD2D7; - private const UInt16 MFSBB_MAGIC = 0x4C4B; // "LK" + class AppleMFS : Plugin + { + const UInt16 MFS_MAGIC = 0xD2D7; + // "LK" + const UInt16 MFSBB_MAGIC = 0x4C4B; - public AppleMFS(PluginBase Core) + public AppleMFS(PluginBase Core) { - base.Name = "Apple Macintosh File System"; - base.PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A"); + Name = "Apple Macintosh File System"; + PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A"); } - - public override bool Identify(FileStream stream, long offset) - { - UInt16 drSigWord; - EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian - eabr.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin); - - drSigWord = eabr.ReadUInt16(); - - if(drSigWord == MFS_MAGIC) - return true; - else - return false; - } - - public override void GetInformation (FileStream stream, long offset, out string information) - { - information = ""; - - StringBuilder sb = new StringBuilder(); - - MFS_MasterDirectoryBlock MDB = new MFS_MasterDirectoryBlock(); - MFS_BootBlock BB = new MFS_BootBlock(); - - byte[] pString; - byte[] variable_size; + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) + { + UInt16 drSigWord; - EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian - eabr.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin); - MDB.drSigWord = eabr.ReadUInt16(); - if(MDB.drSigWord != MFS_MAGIC) - return; + byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); + + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000); - MDB.drCrDate = eabr.ReadUInt32(); - MDB.drLsBkUp = eabr.ReadUInt32(); - MDB.drAtrb = eabr.ReadUInt16(); - MDB.drNmFls = eabr.ReadUInt16(); - MDB.drDirSt = eabr.ReadUInt16(); - MDB.drBlLen = eabr.ReadUInt16(); - MDB.drNmAlBlks = eabr.ReadUInt16(); - MDB.drAlBlkSiz = eabr.ReadUInt32(); - MDB.drClpSiz = eabr.ReadUInt32(); - MDB.drAlBlSt = eabr.ReadUInt16(); - MDB.drNxtFNum = eabr.ReadUInt32(); - MDB.drFreeBks = eabr.ReadUInt16(); - MDB.drVNSiz = eabr.ReadByte(); - variable_size = eabr.ReadBytes(MDB.drVNSiz); - MDB.drVN = Encoding.ASCII.GetString(variable_size); + return drSigWord == MFS_MAGIC; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - eabr.BaseStream.Seek(0 + offset, SeekOrigin.Begin); - BB.signature = eabr.ReadUInt16(); + StringBuilder sb = new StringBuilder(); - if(BB.signature == MFSBB_MAGIC) - { - BB.branch = eabr.ReadUInt32(); - BB.boot_flags = eabr.ReadByte(); - BB.boot_version = eabr.ReadByte(); + MFS_MasterDirectoryBlock MDB = new MFS_MasterDirectoryBlock(); + MFS_BootBlock BB = new MFS_BootBlock(); + + byte[] pString = new byte[16]; + byte[] variable_size; + + byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); + byte[] bb_sector = imagePlugin.ReadSector(0 + partitionOffset); + + MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000); + if (MDB.drSigWord != MFS_MAGIC) + return; + + MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdb_sector, 0x002); + MDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdb_sector, 0x00A); + MDB.drAtrb = BigEndianBitConverter.ToUInt16(mdb_sector, 0x012); + MDB.drNmFls = BigEndianBitConverter.ToUInt16(mdb_sector, 0x014); + MDB.drDirSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x016); + MDB.drBlLen = BigEndianBitConverter.ToUInt16(mdb_sector, 0x018); + MDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x01A); + MDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x01C); + MDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x020); + MDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x024); + MDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdb_sector, 0x026); + MDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x02A); + MDB.drVNSiz = mdb_sector[0x02C]; + variable_size = new byte[MDB.drVNSiz]; + Array.Copy(mdb_sector, 0x02D, variable_size, 0, MDB.drVNSiz); + MDB.drVN = Encoding.ASCII.GetString(variable_size); + + BB.signature = BigEndianBitConverter.ToUInt16(bb_sector, 0x000); + + if (BB.signature == MFSBB_MAGIC) + { + BB.branch = BigEndianBitConverter.ToUInt32(bb_sector, 0x002); + BB.boot_flags = bb_sector[0x006]; + BB.boot_version = bb_sector[0x007]; - BB.sec_sv_pages = eabr.ReadInt16(); + BB.sec_sv_pages = BigEndianBitConverter.ToInt16(bb_sector, 0x008); - pString = eabr.ReadBytes(16); - BB.system_name = StringHandlers.PascalToString(pString); - pString = eabr.ReadBytes(16); - BB.finder_name = StringHandlers.PascalToString(pString); - pString = eabr.ReadBytes(16); - BB.debug_name = StringHandlers.PascalToString(pString); - pString = eabr.ReadBytes(16); - BB.disasm_name = StringHandlers.PascalToString(pString); - pString = eabr.ReadBytes(16); - BB.stupscr_name = StringHandlers.PascalToString(pString); - pString = eabr.ReadBytes(16); - BB.bootup_name = StringHandlers.PascalToString(pString); - pString = eabr.ReadBytes(16); - BB.clipbrd_name = StringHandlers.PascalToString(pString); + Array.Copy(mdb_sector, 0x00A, pString, 0, 16); + BB.system_name = StringHandlers.PascalToString(pString); + Array.Copy(mdb_sector, 0x01A, pString, 0, 16); + BB.finder_name = StringHandlers.PascalToString(pString); + Array.Copy(mdb_sector, 0x02A, pString, 0, 16); + BB.debug_name = StringHandlers.PascalToString(pString); + Array.Copy(mdb_sector, 0x03A, pString, 0, 16); + BB.disasm_name = StringHandlers.PascalToString(pString); + Array.Copy(mdb_sector, 0x04A, pString, 0, 16); + BB.stupscr_name = StringHandlers.PascalToString(pString); + Array.Copy(mdb_sector, 0x05A, pString, 0, 16); + BB.bootup_name = StringHandlers.PascalToString(pString); + Array.Copy(mdb_sector, 0x06A, pString, 0, 16); + BB.clipbrd_name = StringHandlers.PascalToString(pString); - BB.max_files = eabr.ReadUInt16(); - BB.queue_size = eabr.ReadUInt16(); - BB.heap_128k = eabr.ReadUInt32(); - BB.heap_256k = eabr.ReadUInt32(); - BB.heap_512k = eabr.ReadUInt32(); - } - else - BB.signature = 0x0000; + BB.max_files = BigEndianBitConverter.ToUInt16(bb_sector, 0x07A); + BB.queue_size = BigEndianBitConverter.ToUInt16(bb_sector, 0x07C); + BB.heap_128k = BigEndianBitConverter.ToUInt32(bb_sector, 0x07E); + BB.heap_256k = BigEndianBitConverter.ToUInt32(bb_sector, 0x082); + BB.heap_512k = BigEndianBitConverter.ToUInt32(bb_sector, 0x086); + } + else + BB.signature = 0x0000; - sb.AppendLine("Apple Macintosh File System"); - sb.AppendLine(); - sb.AppendLine("Master Directory Block:"); - sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine(); - sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(MDB.drLsBkUp)).AppendLine(); - if((MDB.drAtrb & 0x80) == 0x80) - sb.AppendLine("Volume is locked by hardware."); - if((MDB.drAtrb & 0x8000) == 0x8000) - sb.AppendLine("Volume is locked by software."); - sb.AppendFormat("{0} files on volume", MDB.drNmFls).AppendLine(); - sb.AppendFormat("First directory block: {0}", MDB.drDirSt).AppendLine(); - sb.AppendFormat("{0} blocks in directory.", MDB.drBlLen).AppendLine(); - sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine(); - sb.AppendFormat("Size of allocation blocks: {0}", MDB.drAlBlkSiz).AppendLine(); - sb.AppendFormat("{0} bytes to allocate.", MDB.drClpSiz).AppendLine(); - sb.AppendFormat("{0} first allocation block.", MDB.drAlBlSt).AppendLine(); - sb.AppendFormat("Next unused file number: {0}", MDB.drNxtFNum).AppendLine(); - sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine(); - sb.AppendFormat("Volume name: {0}", MDB.drVN).AppendLine(); + sb.AppendLine("Apple Macintosh File System"); + sb.AppendLine(); + sb.AppendLine("Master Directory Block:"); + sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine(); + sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(MDB.drLsBkUp)).AppendLine(); + if ((MDB.drAtrb & 0x80) == 0x80) + sb.AppendLine("Volume is locked by hardware."); + if ((MDB.drAtrb & 0x8000) == 0x8000) + sb.AppendLine("Volume is locked by software."); + sb.AppendFormat("{0} files on volume", MDB.drNmFls).AppendLine(); + sb.AppendFormat("First directory block: {0}", MDB.drDirSt).AppendLine(); + sb.AppendFormat("{0} blocks in directory.", MDB.drBlLen).AppendLine(); + sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine(); + sb.AppendFormat("Size of allocation blocks: {0}", MDB.drAlBlkSiz).AppendLine(); + sb.AppendFormat("{0} bytes to allocate.", MDB.drClpSiz).AppendLine(); + sb.AppendFormat("{0} first allocation block.", MDB.drAlBlSt).AppendLine(); + sb.AppendFormat("Next unused file number: {0}", MDB.drNxtFNum).AppendLine(); + sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine(); + sb.AppendFormat("Volume name: {0}", MDB.drVN).AppendLine(); - if(BB.signature == MFSBB_MAGIC) - { - sb.AppendLine("Volume is bootable."); - sb.AppendLine(); - sb.AppendLine("Boot Block:"); - if((BB.boot_flags & 0x40) == 0x40) - sb.AppendLine("Boot block should be executed."); - if((BB.boot_flags & 0x80) == 0x80) - { - sb.AppendLine("Boot block is in new unknown format."); - } - else - { - if(BB.sec_sv_pages > 0) - sb.AppendLine("Allocate secondary sound buffer at boot."); - else if(BB.sec_sv_pages < 0) - sb.AppendLine("Allocate secondary sound and video buffers at boot."); + if (BB.signature == MFSBB_MAGIC) + { + sb.AppendLine("Volume is bootable."); + sb.AppendLine(); + sb.AppendLine("Boot Block:"); + if ((BB.boot_flags & 0x40) == 0x40) + sb.AppendLine("Boot block should be executed."); + if ((BB.boot_flags & 0x80) == 0x80) + { + sb.AppendLine("Boot block is in new unknown format."); + } + else + { + if (BB.sec_sv_pages > 0) + sb.AppendLine("Allocate secondary sound buffer at boot."); + else if (BB.sec_sv_pages < 0) + sb.AppendLine("Allocate secondary sound and video buffers at boot."); - sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine(); - sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine(); - sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine(); - sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine(); - sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine(); - sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine(); - sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine(); - sb.AppendFormat("Maximum opened files: {0}", BB.max_files*4).AppendLine(); - sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine(); - sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine(); - sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine(); - sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine(); - } - } - else - sb.AppendLine("Volume is not bootable."); + sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine(); + sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine(); + sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine(); + sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine(); + sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine(); + sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine(); + sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine(); + sb.AppendFormat("Maximum opened files: {0}", BB.max_files * 4).AppendLine(); + sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine(); + sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine(); + sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine(); + sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine(); + } + } + else + sb.AppendLine("Volume is not bootable."); - information = sb.ToString(); + information = sb.ToString(); - return; - } - - private struct MFS_MasterDirectoryBlock // Should be offset 0x0400 bytes in volume - { - public UInt16 drSigWord; // 0x000, Signature, 0xD2D7 - public ulong drCrDate; // 0x002, Volume creation date - public ulong drLsBkUp; // 0x00A, Volume last backup date - public UInt16 drAtrb; // 0x012, Volume attributes - public UInt16 drNmFls; // 0x014, Volume number of files - public UInt16 drDirSt; // 0x016, First directory block - public UInt16 drBlLen; // 0x018, Length of directory in blocks - public UInt16 drNmAlBlks; // 0x01A, Volume allocation blocks - public UInt32 drAlBlkSiz; // 0x01C, Size of allocation blocks - public UInt32 drClpSiz; // 0x020, Number of bytes to allocate - public UInt16 drAlBlSt; // 0x024, First allocation block in block map - public UInt32 drNxtFNum; // 0x026. Next unused file number - public UInt16 drFreeBks; // 0x02A, Number of unused allocation blocks - public byte drVNSiz; // 0x02C, Length of volume name - public string drVN; // 0x02D, Characters of volume name - } - - private struct MFS_BootBlock // Should be offset 0x0000 bytes in volume - { - public UInt16 signature; // 0x000, Signature, 0x4C4B if bootable - public UInt32 branch; // 0x002, Branch - public byte boot_flags; // 0x006, Boot block flags - public byte boot_version; // 0x007, Boot block version - public short sec_sv_pages; // 0x008, Allocate secondary buffers - public string system_name; // 0x00A, System file name (10 bytes) - public string finder_name; // 0x014, Finder file name (10 bytes) - public string debug_name; // 0x01E, Debugger file name (10 bytes) - public string disasm_name; // 0x028, Disassembler file name (10 bytes) - public string stupscr_name; // 0x032, Startup screen file name (10 bytes) - public string bootup_name; // 0x03C, First program to execute on boot (10 bytes) - public string clipbrd_name; // 0x046, Clipboard file name (10 bytes) - public UInt16 max_files; // 0x050, 1/4 of maximum opened at a time files - public UInt16 queue_size; // 0x052, Event queue size - public UInt32 heap_128k; // 0x054, Heap size on a Mac with 128KiB of RAM - public UInt32 heap_256k; // 0x058, Heap size on a Mac with 256KiB of RAM - public UInt32 heap_512k; // 0x05C, Heap size on a Mac with 512KiB of RAM or more - } // Follows boot code - } + return; + } + + struct MFS_MasterDirectoryBlock // Should be offset 0x0400 bytes in volume + { + public UInt16 drSigWord; + // 0x000, Signature, 0xD2D7 + public ulong drCrDate; + // 0x002, Volume creation date + public ulong drLsBkUp; + // 0x00A, Volume last backup date + public UInt16 drAtrb; + // 0x012, Volume attributes + public UInt16 drNmFls; + // 0x014, Volume number of files + public UInt16 drDirSt; + // 0x016, First directory block + public UInt16 drBlLen; + // 0x018, Length of directory in blocks + public UInt16 drNmAlBlks; + // 0x01A, Volume allocation blocks + public UInt32 drAlBlkSiz; + // 0x01C, Size of allocation blocks + public UInt32 drClpSiz; + // 0x020, Number of bytes to allocate + public UInt16 drAlBlSt; + // 0x024, First allocation block in block map + public UInt32 drNxtFNum; + // 0x026. Next unused file number + public UInt16 drFreeBks; + // 0x02A, Number of unused allocation blocks + public byte drVNSiz; + // 0x02C, Length of volume name + public string drVN; + // 0x02D, Characters of volume name + } + + struct MFS_BootBlock // Should be offset 0x0000 bytes in volume + { + public UInt16 signature; + // 0x000, Signature, 0x4C4B if bootable + public UInt32 branch; + // 0x002, Branch + public byte boot_flags; + // 0x006, Boot block flags + public byte boot_version; + // 0x007, Boot block version + public short sec_sv_pages; + // 0x008, Allocate secondary buffers + public string system_name; + // 0x00A, System file name (16 bytes) + public string finder_name; + // 0x01A, Finder file name (16 bytes) + public string debug_name; + // 0x02A, Debugger file name (16 bytes) + public string disasm_name; + // 0x03A, Disassembler file name (16 bytes) + public string stupscr_name; + // 0x04A, Startup screen file name (16 bytes) + public string bootup_name; + // 0x05A, First program to execute on boot (16 bytes) + public string clipbrd_name; + // 0x06A, Clipboard file name (16 bytes) + public UInt16 max_files; + // 0x07A, 1/4 of maximum opened at a time files + public UInt16 queue_size; + // 0x07C, Event queue size + public UInt32 heap_128k; + // 0x07E, Heap size on a Mac with 128KiB of RAM + public UInt32 heap_256k; + // 0x082, Heap size on a Mac with 256KiB of RAM + public UInt32 heap_512k; + // 0x086, Heap size on a Mac with 512KiB of RAM or more + } + // Follows boot code + } } -*/ diff --git a/FileSystemIDandChk/Plugins/BFS.cs b/FileSystemIDandChk/Plugins/BFS.cs index 69c829ba..e40d487b 100644 --- a/FileSystemIDandChk/Plugins/BFS.cs +++ b/FileSystemIDandChk/Plugins/BFS.cs @@ -1,196 +1,212 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class BeFS : Plugin - { - // Little endian constants (that is, as read by .NET :p) - private const UInt32 BEFS_MAGIC1 = 0x42465331; - private const UInt32 BEFS_MAGIC2 = 0xDD121031; - private const UInt32 BEFS_MAGIC3 = 0x15B6830E; - private const UInt32 BEFS_ENDIAN = 0x42494745; + class BeFS : Plugin + { + // Little endian constants (that is, as read by .NET :p) + const UInt32 BEFS_MAGIC1 = 0x42465331; + const UInt32 BEFS_MAGIC2 = 0xDD121031; + const UInt32 BEFS_MAGIC3 = 0x15B6830E; + const UInt32 BEFS_ENDIAN = 0x42494745; + // Big endian constants + const UInt32 BEFS_CIGAM1 = 0x31534642; + const UInt32 BEFS_NAIDNE = 0x45474942; + // Common constants + const UInt32 BEFS_CLEAN = 0x434C454E; + const UInt32 BEFS_DIRTY = 0x44495254; - // Big endian constants - private const UInt32 BEFS_CIGAM1 = 0x31534642; - private const UInt32 BEFS_NAIDNE = 0x45474942; - - // Common constants - private const UInt32 BEFS_CLEAN = 0x434C454E; - private const UInt32 BEFS_DIRTY = 0x44495254; - - public BeFS(PluginBase Core) + public BeFS(PluginBase Core) { - base.Name = "Be Filesystem"; - base.PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672"); + Name = "Be Filesystem"; + PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672"); } - - public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - UInt32 magic; - UInt32 magic_be; - byte[] sb_sector = imagePlugin.ReadSector (0 + partitionOffset); + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) + { + UInt32 magic; + UInt32 magic_be; - magic = BitConverter.ToUInt32 (sb_sector, 0x20); - magic_be = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); + byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset); - if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) - return true; - else - { - sb_sector = imagePlugin.ReadSector (1 + partitionOffset); + magic = BitConverter.ToUInt32(sb_sector, 0x20); + magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + + if (magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) + return true; + sb_sector = imagePlugin.ReadSector(1 + partitionOffset); - magic = BitConverter.ToUInt32 (sb_sector, 0x20); - magic_be = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); + magic = BitConverter.ToUInt32(sb_sector, 0x20); + magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); - if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) - return true; - else - return false; - } - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; - byte[] name_bytes = new byte[32]; + if (magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) + return true; + return false; + } - StringBuilder sb = new StringBuilder(); + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; + byte[] name_bytes = new byte[32]; + + StringBuilder sb = new StringBuilder(); - BeSuperBlock besb = new BeSuperBlock(); + BeSuperBlock besb = new BeSuperBlock(); - byte[] sb_sector = imagePlugin.ReadSector (0 + partitionOffset); + byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset); - BigEndianBitConverter.IsLittleEndian = true; // Default for little-endian + BigEndianBitConverter.IsLittleEndian = true; // Default for little-endian - besb.magic1 = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // Magic is at offset - { - if(besb.magic1 == BEFS_CIGAM1) - BigEndianBitConverter.IsLittleEndian = false; - } - else - { - sb_sector = imagePlugin.ReadSector (1 + partitionOffset); - besb.magic1 = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); + besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // Magic is at offset + { + BigEndianBitConverter.IsLittleEndian &= besb.magic1 != BEFS_CIGAM1; + } + else + { + sb_sector = imagePlugin.ReadSector(1 + partitionOffset); + besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); - if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector - { - if(besb.magic1 == BEFS_CIGAM1) - BigEndianBitConverter.IsLittleEndian = false; - } - else - return; - } + if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector + { + BigEndianBitConverter.IsLittleEndian &= besb.magic1 != BEFS_CIGAM1; + } + else + return; + } - Array.Copy (sb_sector, 0x000, name_bytes, 0, 0x20); - besb.name = StringHandlers.CToString(name_bytes); - besb.magic1 = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - besb.fs_byte_order = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - besb.block_size = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - besb.block_shift = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - besb.num_blocks = BigEndianBitConverter.ToInt64 (sb_sector, 0x20); - besb.used_blocks = BigEndianBitConverter.ToInt64 (sb_sector, 0x20); - besb.inode_size = BigEndianBitConverter.ToInt32 (sb_sector, 0x20); - besb.magic2 = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - besb.blocks_per_ag = BigEndianBitConverter.ToInt32 (sb_sector, 0x20); - besb.ag_shift = BigEndianBitConverter.ToInt32 (sb_sector, 0x20); - besb.num_ags = BigEndianBitConverter.ToInt32 (sb_sector, 0x20); - besb.flags = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - besb.log_blocks_ag = BigEndianBitConverter.ToInt32 (sb_sector, 0x20); - besb.log_blocks_start = BigEndianBitConverter.ToUInt16 (sb_sector, 0x20); - besb.log_blocks_len = BigEndianBitConverter.ToUInt16 (sb_sector, 0x20); - besb.log_start = BigEndianBitConverter.ToInt64 (sb_sector, 0x20); - besb.log_end = BigEndianBitConverter.ToInt64 (sb_sector, 0x20); - besb.magic3 = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20); - besb.root_dir_ag = BigEndianBitConverter.ToInt32 (sb_sector, 0x20); - besb.root_dir_start = BigEndianBitConverter.ToUInt16 (sb_sector, 0x20); - besb.root_dir_len = BigEndianBitConverter.ToUInt16 (sb_sector, 0x20); - besb.indices_ag = BigEndianBitConverter.ToInt32 (sb_sector, 0x20); - besb.indices_start = BigEndianBitConverter.ToUInt16 (sb_sector, 0x20); - besb.indices_len = BigEndianBitConverter.ToUInt16 (sb_sector, 0x20); + Array.Copy(sb_sector, 0x000, name_bytes, 0, 0x20); + besb.name = StringHandlers.CToString(name_bytes); + besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + besb.fs_byte_order = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + besb.block_size = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + besb.block_shift = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + besb.num_blocks = BigEndianBitConverter.ToInt64(sb_sector, 0x20); + besb.used_blocks = BigEndianBitConverter.ToInt64(sb_sector, 0x20); + besb.inode_size = BigEndianBitConverter.ToInt32(sb_sector, 0x20); + besb.magic2 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + besb.blocks_per_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20); + besb.ag_shift = BigEndianBitConverter.ToInt32(sb_sector, 0x20); + besb.num_ags = BigEndianBitConverter.ToInt32(sb_sector, 0x20); + besb.flags = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + besb.log_blocks_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20); + besb.log_blocks_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x20); + besb.log_blocks_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x20); + besb.log_start = BigEndianBitConverter.ToInt64(sb_sector, 0x20); + besb.log_end = BigEndianBitConverter.ToInt64(sb_sector, 0x20); + besb.magic3 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); + besb.root_dir_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20); + besb.root_dir_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x20); + besb.root_dir_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x20); + besb.indices_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20); + besb.indices_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x20); + besb.indices_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x20); - if(!BigEndianBitConverter.IsLittleEndian) // Big-endian filesystem + if (!BigEndianBitConverter.IsLittleEndian) // Big-endian filesystem sb.AppendLine("Big-endian BeFS"); - else - sb.AppendLine("Little-endian BeFS"); + else + sb.AppendLine("Little-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(); - } + 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(); + } - if(besb.flags == BEFS_CLEAN) - { - if(besb.log_start == besb.log_end) - sb.AppendLine("Filesystem is clean"); - else - sb.AppendLine("Filesystem is dirty"); - } - else if(besb.flags == BEFS_DIRTY) - sb.AppendLine("Filesystem is dirty"); - else - sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine(); + if (besb.flags == BEFS_CLEAN) + { + if (besb.log_start == besb.log_end) + sb.AppendLine("Filesystem is clean"); + else + sb.AppendLine("Filesystem is dirty"); + } + else if (besb.flags == BEFS_DIRTY) + sb.AppendLine("Filesystem is dirty"); + else + sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine(); - sb.AppendFormat("Volume name: {0}", besb.name).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(); + sb.AppendFormat("Volume name: {0}", besb.name).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(); - } - - private struct BeSuperBlock - { - public string name; // 0x000, Volume name, 32 bytes - public UInt32 magic1; // 0x020, "BFS1", 0x42465331 - public UInt32 fs_byte_order; // 0x024, "BIGE", 0x42494745 - public UInt32 block_size; // 0x028, Bytes per block - public UInt32 block_shift; // 0x02C, 1 << block_shift == block_size - public Int64 num_blocks; // 0x030, Blocks in volume - public Int64 used_blocks; // 0x038, Used blocks in volume - public Int32 inode_size; // 0x040, Bytes per inode - public UInt32 magic2; // 0x044, 0xDD121031 - public Int32 blocks_per_ag; // 0x048, Blocks per allocation group - public Int32 ag_shift; // 0x04C, 1 << ag_shift == blocks_per_ag - public Int32 num_ags; // 0x050, Allocation groups in volume - public UInt32 flags; // 0x054, 0x434c454e if clean, 0x44495254 if dirty - public Int32 log_blocks_ag; // 0x058, Allocation group of journal - public UInt16 log_blocks_start; // 0x05C, Start block of journal, inside ag - public UInt16 log_blocks_len; // 0x05E, Length in blocks of journal, inside ag - public Int64 log_start; // 0x060, Start of journal - public Int64 log_end; // 0x068, End of journal - public UInt32 magic3; // 0x070, 0x15B6830E - public Int32 root_dir_ag; // 0x074, Allocation group where root folder's i-node resides - public UInt16 root_dir_start; // 0x078, Start in ag of root folder's i-node - public UInt16 root_dir_len; // 0x07A, As this is part of inode_addr, this is 1 - public Int32 indices_ag; // 0x07C, Allocation group where indices' i-node resides - public UInt16 indices_start; // 0x080, Start in ag of indices' i-node - public UInt16 indices_len; // 0x082, As this is part of inode_addr, this is 1 - } - } + information = sb.ToString(); + } + + struct BeSuperBlock + { + public string name; + // 0x000, Volume name, 32 bytes + public UInt32 magic1; + // 0x020, "BFS1", 0x42465331 + public UInt32 fs_byte_order; + // 0x024, "BIGE", 0x42494745 + public UInt32 block_size; + // 0x028, Bytes per block + public UInt32 block_shift; + // 0x02C, 1 << block_shift == block_size + public Int64 num_blocks; + // 0x030, Blocks in volume + public Int64 used_blocks; + // 0x038, Used blocks in volume + public Int32 inode_size; + // 0x040, Bytes per inode + public UInt32 magic2; + // 0x044, 0xDD121031 + public Int32 blocks_per_ag; + // 0x048, Blocks per allocation group + public Int32 ag_shift; + // 0x04C, 1 << ag_shift == blocks_per_ag + public Int32 num_ags; + // 0x050, Allocation groups in volume + public UInt32 flags; + // 0x054, 0x434c454e if clean, 0x44495254 if dirty + public Int32 log_blocks_ag; + // 0x058, Allocation group of journal + public UInt16 log_blocks_start; + // 0x05C, Start block of journal, inside ag + public UInt16 log_blocks_len; + // 0x05E, Length in blocks of journal, inside ag + public Int64 log_start; + // 0x060, Start of journal + public Int64 log_end; + // 0x068, End of journal + public UInt32 magic3; + // 0x070, 0x15B6830E + public Int32 root_dir_ag; + // 0x074, Allocation group where root folder's i-node resides + public UInt16 root_dir_start; + // 0x078, Start in ag of root folder's i-node + public UInt16 root_dir_len; + // 0x07A, As this is part of inode_addr, this is 1 + public Int32 indices_ag; + // 0x07C, Allocation group where indices' i-node resides + public UInt16 indices_start; + // 0x080, Start in ag of indices' i-node + public UInt16 indices_len; + // 0x082, As this is part of inode_addr, this is 1 + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/FAT.cs b/FileSystemIDandChk/Plugins/FAT.cs index 4c339d94..b5ca2e48 100644 --- a/FileSystemIDandChk/Plugins/FAT.cs +++ b/FileSystemIDandChk/Plugins/FAT.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; @@ -7,130 +6,130 @@ using FileSystemIDandChk; // TODO: Implement detecting Atari TOS bootable disks and printing corresponding fields namespace FileSystemIDandChk.Plugins { - class FAT : Plugin - { - public FAT(PluginBase Core) + class FAT : Plugin + { + public FAT(PluginBase Core) { - base.Name = "Microsoft File Allocation Table"; - base.PluginUUID = new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0"); + Name = "Microsoft File Allocation Table"; + PluginUUID = new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0"); } - - public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry - byte fats_no; // Must be 1 or 2. Dunno if it can be 0 in the wild, but it CANNOT BE bigger than 2 - byte[] fat32_signature = new byte[8]; // "FAT32 " - UInt32 first_fat_entry; // No matter FAT size we read 4 bytes for checking - UInt16 bps, rsectors; - byte[] bpb_sector = imagePlugin.ReadSector (0 + partitionOffset); - byte[] fat_sector; + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) + { + byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry + byte fats_no; // Must be 1 or 2. Dunno if it can be 0 in the wild, but it CANNOT BE bigger than 2 + byte[] fat32_signature = new byte[8]; // "FAT32 " + UInt32 first_fat_entry; // No matter FAT size we read 4 bytes for checking + UInt16 bps, rsectors; - fats_no = bpb_sector[0x010]; // FATs, 1 or 2, maybe 0, never bigger - media_descriptor = bpb_sector[0x015]; // Media Descriptor if present is in 0x15 - Array.Copy (bpb_sector, 0x52, fat32_signature, 0, 8); // FAT32 signature, if present, is in 0x52 - bps = BitConverter.ToUInt16(bpb_sector, 0x00B); // Bytes per sector - if(bps==0) - bps=0x200; - rsectors = BitConverter.ToUInt16 (bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT) - if(rsectors==0) - rsectors=1; - if(imagePlugin.GetSectors() > ((ulong)rsectors + partitionOffset)) - fat_sector = imagePlugin.ReadSector(rsectors + partitionOffset); // First FAT entry + byte[] bpb_sector = imagePlugin.ReadSector(0 + partitionOffset); + byte[] fat_sector; + + fats_no = bpb_sector[0x010]; // FATs, 1 or 2, maybe 0, never bigger + media_descriptor = bpb_sector[0x015]; // Media Descriptor if present is in 0x15 + Array.Copy(bpb_sector, 0x52, fat32_signature, 0, 8); // FAT32 signature, if present, is in 0x52 + bps = BitConverter.ToUInt16(bpb_sector, 0x00B); // Bytes per sector + if (bps == 0) + bps = 0x200; + rsectors = BitConverter.ToUInt16(bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT) + if (rsectors == 0) + rsectors = 1; + if (imagePlugin.GetSectors() > ((ulong)rsectors + partitionOffset)) + fat_sector = imagePlugin.ReadSector(rsectors + partitionOffset); // First FAT entry else - return false; - first_fat_entry = BitConverter.ToUInt32 (fat_sector, 0); // Easier to manage + return false; + first_fat_entry = BitConverter.ToUInt32(fat_sector, 0); // Easier to manage - if(MainClass.isDebug) - { - Console.WriteLine("FAT: fats_no = {0}", fats_no); - Console.WriteLine("FAT: media_descriptor = 0x{0:X2}", media_descriptor); - Console.WriteLine("FAT: fat32_signature = {0}", StringHandlers.CToString(fat32_signature)); - Console.WriteLine("FAT: bps = {0}", bps); - Console.WriteLine("FAT: first_fat_entry = 0x{0:X8}", first_fat_entry); - } + if (MainClass.isDebug) + { + Console.WriteLine("FAT: fats_no = {0}", fats_no); + Console.WriteLine("FAT: media_descriptor = 0x{0:X2}", media_descriptor); + Console.WriteLine("FAT: fat32_signature = {0}", StringHandlers.CToString(fat32_signature)); + Console.WriteLine("FAT: bps = {0}", bps); + Console.WriteLine("FAT: first_fat_entry = 0x{0:X8}", first_fat_entry); + } - if(fats_no > 2) // Must be 1 or 2, but as TOS makes strange things and I have not checked if it puts this to 0, ignore if 0. MUST NOT BE BIGGER THAN 2! + if (fats_no > 2) // Must be 1 or 2, but as TOS makes strange things and I have not checked if it puts this to 0, ignore if 0. MUST NOT BE BIGGER THAN 2! return false; - // Let's start the fun - if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") - return true; // Seems easy, check reading + // Let's start the fun + if (Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") + return true; // Seems easy, check reading - if((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16 - { - if((first_fat_entry & 0xFF) == media_descriptor) - return true; // It MUST be FAT16, or... maybe not :S - } - else if((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0) - { - //if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is != - return true; // It MUST be FAT12, or... maybe not :S - } + if ((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16 + { + if ((first_fat_entry & 0xFF) == media_descriptor) + return true; // It MUST be FAT16, or... maybe not :S + } + else if ((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0) + { + //if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is != + return true; // It MUST be FAT12, or... maybe not :S + } - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - byte[] dosString; // Space-padded - bool isFAT32 = false; - UInt32 first_fat_entry; - byte media_descriptor, fats_no; - string fat32_signature; - UInt16 bps, rsectors; + byte[] dosString; // Space-padded + bool isFAT32 = false; + UInt32 first_fat_entry; + byte media_descriptor, fats_no; + string fat32_signature; + UInt16 bps, rsectors; - byte[] bpb_sector = imagePlugin.ReadSector (0 + partitionOffset); - byte[] fat_sector; + byte[] bpb_sector = imagePlugin.ReadSector(0 + partitionOffset); + byte[] fat_sector; - fats_no = bpb_sector[0x010]; // FATs, 1 or 2, maybe 0, never bigger - media_descriptor = bpb_sector[0x015]; // Media Descriptor if present is in 0x15 + fats_no = bpb_sector[0x010]; // FATs, 1 or 2, maybe 0, never bigger + media_descriptor = bpb_sector[0x015]; // Media Descriptor if present is in 0x15 dosString = new byte[8]; - Array.Copy (bpb_sector, 0x52, dosString, 0, 8); // FAT32 signature, if present, is in 0x52 + Array.Copy(bpb_sector, 0x52, dosString, 0, 8); // FAT32 signature, if present, is in 0x52 fat32_signature = Encoding.ASCII.GetString(dosString); - bps = BitConverter.ToUInt16(bpb_sector, 0x00B); // Bytes per sector - if(bps==0) - bps=0x200; - rsectors = BitConverter.ToUInt16 (bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT) - if(rsectors==0) - rsectors=1; - fat_sector = imagePlugin.ReadSector(rsectors + partitionOffset); // First FAT entry - first_fat_entry = BitConverter.ToUInt32 (fat_sector, 0); // Easier to manage + bps = BitConverter.ToUInt16(bpb_sector, 0x00B); // Bytes per sector + if (bps == 0) + bps = 0x200; + rsectors = BitConverter.ToUInt16(bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT) + if (rsectors == 0) + rsectors = 1; + fat_sector = imagePlugin.ReadSector(rsectors + partitionOffset); // First FAT entry + first_fat_entry = BitConverter.ToUInt32(fat_sector, 0); // Easier to manage - if(fats_no > 2) // Must be 1 or 2, but as TOS makes strange things and I have not checked if it puts this to 0, ignore if 0. MUST NOT BE BIGGER THAN 2! + if (fats_no > 2) // Must be 1 or 2, but as TOS makes strange things and I have not checked if it puts this to 0, ignore if 0. MUST NOT BE BIGGER THAN 2! return; - // Let's start the fun - if(fat32_signature == "FAT32 ") - { - sb.AppendLine("Microsoft FAT32"); // Seems easy, check reading - isFAT32 = true; - } - else if((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16 - { - if((first_fat_entry & 0xFF) == media_descriptor) - sb.AppendLine("Microsoft FAT16"); // It MUST be FAT16, or... maybe not :S - } - else if((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0) - { - //if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is != - sb.AppendLine("Microsoft FAT12"); // It MUST be FAT12, or... maybe not :S - } - else - return; + // Let's start the fun + if (fat32_signature == "FAT32 ") + { + sb.AppendLine("Microsoft FAT32"); // Seems easy, check reading + isFAT32 = true; + } + else if ((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16 + { + if ((first_fat_entry & 0xFF) == media_descriptor) + sb.AppendLine("Microsoft FAT16"); // It MUST be FAT16, or... maybe not :S + } + else if ((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0) + { + //if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is != + sb.AppendLine("Microsoft FAT12"); // It MUST be FAT12, or... maybe not :S + } + else + return; - BIOSParameterBlock BPB = new BIOSParameterBlock(); - ExtendedParameterBlock EPB = new ExtendedParameterBlock(); - FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock(); + BIOSParameterBlock BPB = new BIOSParameterBlock(); + ExtendedParameterBlock EPB = new ExtendedParameterBlock(); + FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock(); dosString = new byte[8]; - Array.Copy (bpb_sector, 0x03, dosString, 0, 8); - BPB.OEMName = Encoding.ASCII.GetString(dosString); - BPB.bps = BitConverter.ToUInt16(bpb_sector, 0x0B);; + Array.Copy(bpb_sector, 0x03, dosString, 0, 8); + BPB.OEMName = Encoding.ASCII.GetString(dosString); + BPB.bps = BitConverter.ToUInt16(bpb_sector, 0x0B); BPB.spc = bpb_sector[0x0D]; BPB.rsectors = BitConverter.ToUInt16(bpb_sector, 0x0E); BPB.fats_no = bpb_sector[0x10]; @@ -143,8 +142,8 @@ namespace FileSystemIDandChk.Plugins BPB.hsectors = BitConverter.ToUInt32(bpb_sector, 0x1C); BPB.big_sectors = BitConverter.ToUInt32(bpb_sector, 0x20); - if(isFAT32) - { + if (isFAT32) + { FAT32PB.spfat = BitConverter.ToUInt32(bpb_sector, 0x24); FAT32PB.fat_flags = BitConverter.ToUInt16(bpb_sector, 0x28); FAT32PB.version = BitConverter.ToUInt16(bpb_sector, 0x2A); @@ -156,144 +155,186 @@ namespace FileSystemIDandChk.Plugins FAT32PB.signature = bpb_sector[0x42]; FAT32PB.serial_no = BitConverter.ToUInt32(bpb_sector, 0x43); dosString = new byte[11]; - Array.Copy (bpb_sector, 0x47, dosString, 0, 11); - FAT32PB.volume_label = Encoding.ASCII.GetString(dosString); + Array.Copy(bpb_sector, 0x47, dosString, 0, 11); + FAT32PB.volume_label = Encoding.ASCII.GetString(dosString); dosString = new byte[8]; - Array.Copy (bpb_sector, 0x52, dosString, 0, 8); - FAT32PB.fs_type = Encoding.ASCII.GetString(dosString); - } - else - { + Array.Copy(bpb_sector, 0x52, dosString, 0, 8); + FAT32PB.fs_type = Encoding.ASCII.GetString(dosString); + } + else + { EPB.drive_no = bpb_sector[0x24]; EPB.nt_flags = bpb_sector[0x25]; EPB.signature = bpb_sector[0x26]; EPB.serial_no = BitConverter.ToUInt32(bpb_sector, 0x27); dosString = new byte[11]; - Array.Copy (bpb_sector, 0x2B, dosString, 0, 11); - EPB.volume_label = Encoding.ASCII.GetString(dosString); + Array.Copy(bpb_sector, 0x2B, dosString, 0, 11); + EPB.volume_label = Encoding.ASCII.GetString(dosString); dosString = new byte[8]; - Array.Copy (bpb_sector, 0x36, dosString, 0, 8); - EPB.fs_type = Encoding.ASCII.GetString(dosString); - } + Array.Copy(bpb_sector, 0x36, dosString, 0, 8); + EPB.fs_type = Encoding.ASCII.GetString(dosString); + } - sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine(); - sb.AppendFormat("{0} bytes per sector.", BPB.bps).AppendLine(); - sb.AppendFormat("{0} sectors per cluster.", BPB.spc).AppendLine(); - sb.AppendFormat("{0} sectors reserved between BPB and FAT.", BPB.rsectors).AppendLine(); - sb.AppendFormat("{0} FATs.", BPB.fats_no).AppendLine(); - sb.AppendFormat("{0} entires on root directory.", BPB.root_ent).AppendLine(); - if(BPB.sectors==0) - sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.big_sectors, BPB.big_sectors*BPB.bps).AppendLine(); - else - sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.sectors, BPB.sectors*BPB.bps).AppendLine(); - if((BPB.media & 0xF0) == 0xF0) - sb.AppendFormat("Media format: 0x{0:X2}", BPB.media).AppendLine(); - if(fat32_signature == "FAT32 ") - sb.AppendFormat("{0} sectors per FAT.", FAT32PB.spfat).AppendLine(); - else - sb.AppendFormat("{0} sectors per FAT.", BPB.spfat).AppendLine(); - sb.AppendFormat("{0} sectors per track.", BPB.sptrk).AppendLine(); - sb.AppendFormat("{0} heads.", BPB.heads).AppendLine(); - sb.AppendFormat("{0} hidden sectors before BPB.", BPB.hsectors).AppendLine(); + sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine(); + sb.AppendFormat("{0} bytes per sector.", BPB.bps).AppendLine(); + sb.AppendFormat("{0} sectors per cluster.", BPB.spc).AppendLine(); + sb.AppendFormat("{0} sectors reserved between BPB and FAT.", BPB.rsectors).AppendLine(); + sb.AppendFormat("{0} FATs.", BPB.fats_no).AppendLine(); + sb.AppendFormat("{0} entires on root directory.", BPB.root_ent).AppendLine(); + if (BPB.sectors == 0) + sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.big_sectors, BPB.big_sectors * BPB.bps).AppendLine(); + else + sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.sectors, BPB.sectors * BPB.bps).AppendLine(); + if ((BPB.media & 0xF0) == 0xF0) + sb.AppendFormat("Media format: 0x{0:X2}", BPB.media).AppendLine(); + if (fat32_signature == "FAT32 ") + sb.AppendFormat("{0} sectors per FAT.", FAT32PB.spfat).AppendLine(); + else + sb.AppendFormat("{0} sectors per FAT.", BPB.spfat).AppendLine(); + sb.AppendFormat("{0} sectors per track.", BPB.sptrk).AppendLine(); + sb.AppendFormat("{0} heads.", BPB.heads).AppendLine(); + sb.AppendFormat("{0} hidden sectors before BPB.", BPB.hsectors).AppendLine(); - if(isFAT32) - { - sb.AppendFormat("Cluster of root directory: {0}", FAT32PB.root_cluster).AppendLine(); - sb.AppendFormat("Sector of FSINFO structure: {0}", FAT32PB.fsinfo_sector).AppendLine(); - sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", FAT32PB.backup_sector).AppendLine(); - sb.AppendFormat("Drive number: 0x{0:X2}", FAT32PB.drive_no).AppendLine(); - sb.AppendFormat("Volume Serial Number: 0x{0:X8}", FAT32PB.serial_no).AppendLine(); - if((FAT32PB.nt_flags & 0x01) == 0x01) - { - sb.AppendLine("Volume should be checked on next mount."); - if((EPB.nt_flags & 0x02) == 0x02) - sb.AppendLine("Disk surface should be checked also."); - } + if (isFAT32) + { + sb.AppendFormat("Cluster of root directory: {0}", FAT32PB.root_cluster).AppendLine(); + sb.AppendFormat("Sector of FSINFO structure: {0}", FAT32PB.fsinfo_sector).AppendLine(); + sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", FAT32PB.backup_sector).AppendLine(); + sb.AppendFormat("Drive number: 0x{0:X2}", FAT32PB.drive_no).AppendLine(); + sb.AppendFormat("Volume Serial Number: 0x{0:X8}", FAT32PB.serial_no).AppendLine(); + if ((FAT32PB.nt_flags & 0x01) == 0x01) + { + sb.AppendLine("Volume should be checked on next mount."); + if ((EPB.nt_flags & 0x02) == 0x02) + sb.AppendLine("Disk surface should be checked also."); + } - sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine(); - sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine(); - } - else if(EPB.signature == 0x28 || EPB.signature == 0x29) - { - sb.AppendFormat("Drive number: 0x{0:X2}", EPB.drive_no).AppendLine(); - sb.AppendFormat("Volume Serial Number: 0x{0:X8}", EPB.serial_no).AppendLine(); - if(EPB.signature==0x29) - { - if((EPB.nt_flags & 0x01) == 0x01) - { - sb.AppendLine("Volume should be checked on next mount."); - if((EPB.nt_flags & 0x02) == 0x02) - sb.AppendLine("Disk surface should be checked also."); - } + sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine(); + sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine(); + } + else if (EPB.signature == 0x28 || EPB.signature == 0x29) + { + sb.AppendFormat("Drive number: 0x{0:X2}", EPB.drive_no).AppendLine(); + sb.AppendFormat("Volume Serial Number: 0x{0:X8}", EPB.serial_no).AppendLine(); + if (EPB.signature == 0x29) + { + if ((EPB.nt_flags & 0x01) == 0x01) + { + sb.AppendLine("Volume should be checked on next mount."); + if ((EPB.nt_flags & 0x02) == 0x02) + sb.AppendLine("Disk surface should be checked also."); + } - sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine(); - sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine(); - } - } + sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine(); + sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine(); + } + } - information = sb.ToString(); - } - - public struct BIOSParameterBlock - { - public string OEMName; // 0x03, OEM Name, 8 bytes, space-padded - public UInt16 bps; // 0x0B, Bytes per sector - public byte spc; // 0x0D, Sectors per cluster - public UInt16 rsectors; // 0x0E, Reserved sectors between BPB and FAT - public byte fats_no; // 0x10, Number of FATs - public UInt16 root_ent; // 0x11, Number of entries on root directory - public UInt16 sectors; // 0x13, Sectors in volume - public byte media; // 0x15, Media descriptor - public UInt16 spfat; // 0x16, Sectors per FAT - public UInt16 sptrk; // 0x18, Sectors per track - public UInt16 heads; // 0x1A, Heads - public UInt32 hsectors; // 0x1C, Hidden sectors before BPB - public UInt32 big_sectors; // 0x20, Sectors in volume if > 65535 - } + information = sb.ToString(); + } - // This only applies for bootable disks - // From http://info-coach.fr/atari/software/FD-Soft.php - public struct AtariBootBlock - { - public UInt16 hsectors; // 0x01C, Atari ST use 16 bit for hidden sectors, probably so did old DOS - public UInt16 xflag; // 0x01E, indicates if COMMAND.PRG must be executed after OS load - public UInt16 ldmode; // 0x020, load mode for, or 0 if fname indicates boot file - public UInt16 bsect; // 0x022, sector from which to boot - public UInt16 bsects_no; // 0x024, how many sectors to boot - public UInt32 ldaddr; // 0x026, RAM address where boot should be located - public UInt32 fatbuf; // 0x02A, RAM address to copy the FAT and root directory - public string fname; // 0x02E, 11 bytes, name of boot file - public UInt16 reserved; // 0x039, unused - public byte[] boot_code; // 0x03B, 451 bytes boot code - public UInt16 checksum; // 0x1FE, the sum of all the BPB+ABB must be 0x1234, so this bigendian value works as adjustment - } - - public struct ExtendedParameterBlock - { - public byte drive_no; // 0x24, Drive number - public byte nt_flags; // 0x25, Volume flags if NT (must be 0x29 signature) - public byte signature; // 0x26, EPB signature, 0x28 or 0x29 - public UInt32 serial_no; // 0x27, Volume serial number - /* Present only if signature == 0x29 */ - public string volume_label; // 0x2B, Volume label, 11 bytes, space-padded - public string fs_type; // 0x36, Filesystem type, 8 bytes, space-padded - } - - public struct FAT32ParameterBlock - { - public UInt32 spfat; // 0x24, Sectors per FAT - public UInt16 fat_flags; // 0x28, FAT flags - public UInt16 version; // 0x2A, FAT32 version - public UInt32 root_cluster; // 0x2C, Cluster of root directory - public UInt16 fsinfo_sector; // 0x30, Sector of FSINFO structure - public UInt16 backup_sector; // 0x32, Sector of FAT32PB bacup - byte[] reserved; // 0x34, 12 reserved bytes - public byte drive_no; // 0x40, Drive number - public byte nt_flags; // 0x41, Volume flags - public byte signature; // 0x42, FAT32PB signature, should be 0x29 - public UInt32 serial_no; // 0x43, Volume serial number - public string volume_label; // 0x47, Volume label, 11 bytes, space-padded - public string fs_type; // 0x52, Filesystem type, 8 bytes, space-padded, must be "FAT32 " - } - } + public struct BIOSParameterBlock + { + public string OEMName; + // 0x03, OEM Name, 8 bytes, space-padded + public UInt16 bps; + // 0x0B, Bytes per sector + public byte spc; + // 0x0D, Sectors per cluster + public UInt16 rsectors; + // 0x0E, Reserved sectors between BPB and FAT + public byte fats_no; + // 0x10, Number of FATs + public UInt16 root_ent; + // 0x11, Number of entries on root directory + public UInt16 sectors; + // 0x13, Sectors in volume + public byte media; + // 0x15, Media descriptor + public UInt16 spfat; + // 0x16, Sectors per FAT + public UInt16 sptrk; + // 0x18, Sectors per track + public UInt16 heads; + // 0x1A, Heads + public UInt32 hsectors; + // 0x1C, Hidden sectors before BPB + public UInt32 big_sectors; + // 0x20, Sectors in volume if > 65535 + } + // This only applies for bootable disks + // From http://info-coach.fr/atari/software/FD-Soft.php + public struct AtariBootBlock + { + public UInt16 hsectors; + // 0x01C, Atari ST use 16 bit for hidden sectors, probably so did old DOS + public UInt16 xflag; + // 0x01E, indicates if COMMAND.PRG must be executed after OS load + public UInt16 ldmode; + // 0x020, load mode for, or 0 if fname indicates boot file + public UInt16 bsect; + // 0x022, sector from which to boot + public UInt16 bsects_no; + // 0x024, how many sectors to boot + public UInt32 ldaddr; + // 0x026, RAM address where boot should be located + public UInt32 fatbuf; + // 0x02A, RAM address to copy the FAT and root directory + public string fname; + // 0x02E, 11 bytes, name of boot file + public UInt16 reserved; + // 0x039, unused + public byte[] boot_code; + // 0x03B, 451 bytes boot code + public UInt16 checksum; + // 0x1FE, the sum of all the BPB+ABB must be 0x1234, so this bigendian value works as adjustment + } + + public struct ExtendedParameterBlock + { + public byte drive_no; + // 0x24, Drive number + public byte nt_flags; + // 0x25, Volume flags if NT (must be 0x29 signature) + public byte signature; + // 0x26, EPB signature, 0x28 or 0x29 + public UInt32 serial_no; + // 0x27, Volume serial number + /* Present only if signature == 0x29 */ + public string volume_label; + // 0x2B, Volume label, 11 bytes, space-padded + public string fs_type; + // 0x36, Filesystem type, 8 bytes, space-padded + } + + public struct FAT32ParameterBlock + { + public UInt32 spfat; + // 0x24, Sectors per FAT + public UInt16 fat_flags; + // 0x28, FAT flags + public UInt16 version; + // 0x2A, FAT32 version + public UInt32 root_cluster; + // 0x2C, Cluster of root directory + public UInt16 fsinfo_sector; + // 0x30, Sector of FSINFO structure + public UInt16 backup_sector; + // 0x32, Sector of FAT32PB bacup + byte[] reserved; + // 0x34, 12 reserved bytes + public byte drive_no; + // 0x40, Drive number + public byte nt_flags; + // 0x41, Volume flags + public byte signature; + // 0x42, FAT32PB signature, should be 0x29 + public UInt32 serial_no; + // 0x43, Volume serial number + public string volume_label; + // 0x47, Volume label, 11 bytes, space-padded + public string fs_type; + // 0x52, Filesystem type, 8 bytes, space-padded, must be "FAT32 " + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/FFS.cs b/FileSystemIDandChk/Plugins/FFS.cs index de7f4149..42931777 100644 --- a/FileSystemIDandChk/Plugins/FFS.cs +++ b/FileSystemIDandChk/Plugins/FFS.cs @@ -1,176 +1,170 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; // Using information from Linux kernel headers namespace FileSystemIDandChk.Plugins { - public class FFSPlugin : Plugin - { - public FFSPlugin (PluginBase Core) - { - base.Name = "BSD Fast File System (aka UNIX File System, UFS)"; - base.PluginUUID = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3"); - } + public class FFSPlugin : Plugin + { + public FFSPlugin(PluginBase Core) + { + Name = "BSD Fast File System (aka UNIX File System, UFS)"; + PluginUUID = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3"); + } public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - UInt32 magic; + { + UInt32 magic; uint sb_size_in_sectors; byte[] ufs_sb_sectors; - if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||imagePlugin.GetSectorSize() == 2448) + if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) sb_size_in_sectors = block_size / 2048; else sb_size_in_sectors = block_size / imagePlugin.GetSectorSize(); - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_floppy*sb_size_in_sectors + sb_size_in_sectors)) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_floppy * sb_size_in_sectors + sb_size_in_sectors)) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_floppy * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) - return true; - } + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs1*sb_size_in_sectors + sb_size_in_sectors)) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs1 * sb_size_in_sectors + sb_size_in_sectors)) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_ufs1 * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) - return true; - } + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs2*sb_size_in_sectors + sb_size_in_sectors)) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs2 * sb_size_in_sectors + sb_size_in_sectors)) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_ufs2 * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) - return true; - } + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_piggy*sb_size_in_sectors + sb_size_in_sectors)) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_piggy * sb_size_in_sectors + sb_size_in_sectors)) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_piggy * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) - return true; - } + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; - StringBuilder sbInformation = new StringBuilder(); + return false; + } - UInt32 magic = 0; + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; + StringBuilder sbInformation = new StringBuilder(); + + UInt32 magic = 0; uint sb_size_in_sectors; byte[] ufs_sb_sectors; ulong sb_offset = partitionOffset; - 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; + 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.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||imagePlugin.GetSectorSize() == 2448) + if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) sb_size_in_sectors = block_size / 2048; else sb_size_in_sectors = block_size / imagePlugin.GetSectorSize(); - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_floppy*sb_size_in_sectors + sb_size_in_sectors) && magic == 0) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_floppy * sb_size_in_sectors + sb_size_in_sectors) && magic == 0) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_floppy * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) sb_offset = partitionOffset + sb_start_floppy * sb_size_in_sectors; - else - magic = 0; - } + else + magic = 0; + } - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs1*sb_size_in_sectors + sb_size_in_sectors) && magic == 0) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs1 * sb_size_in_sectors + sb_size_in_sectors) && magic == 0) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_ufs1 * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) sb_offset = partitionOffset + sb_start_ufs1 * sb_size_in_sectors; - else - magic = 0; - } + else + magic = 0; + } - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs2*sb_size_in_sectors + sb_size_in_sectors) && magic == 0) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs2 * sb_size_in_sectors + sb_size_in_sectors) && magic == 0) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_ufs2 * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) sb_offset = partitionOffset + sb_start_ufs2 * sb_size_in_sectors; - else - magic = 0; - } + else + magic = 0; + } - if(imagePlugin.GetSectors() > (partitionOffset + sb_start_piggy*sb_size_in_sectors + sb_size_in_sectors) && magic == 0) - { + if (imagePlugin.GetSectors() > (partitionOffset + sb_start_piggy * sb_size_in_sectors + sb_size_in_sectors) && magic == 0) + { ufs_sb_sectors = imagePlugin.ReadSectors(partitionOffset + sb_start_piggy * sb_size_in_sectors, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) sb_offset = partitionOffset + sb_start_piggy * sb_size_in_sectors; - else - magic = 0; - } + else + magic = 0; + } - if(magic == 0) - { - information = "Not a UFS filesystem, I shouldn't have arrived here!"; - return; - } + if (magic == 0) + { + information = "Not a UFS filesystem, I shouldn't have arrived here!"; + return; + } - switch(magic) - { - case UFS_MAGIC: - sbInformation.AppendLine("UFS filesystem"); - break; - case UFS_MAGIC_BW: - sbInformation.AppendLine("BorderWare UFS filesystem"); - break; - case UFS2_MAGIC: - sbInformation.AppendLine("UFS2 filesystem"); - break; - case UFS_CIGAM: - sbInformation.AppendLine("Big-endian UFS filesystem"); - break; - case UFS_BAD_MAGIC: - sbInformation.AppendLine("Incompletely initialized UFS filesystem"); - sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); - break; - default: - break; - } + switch (magic) + { + case UFS_MAGIC: + sbInformation.AppendLine("UFS filesystem"); + break; + case UFS_MAGIC_BW: + sbInformation.AppendLine("BorderWare UFS filesystem"); + break; + case UFS2_MAGIC: + sbInformation.AppendLine("UFS2 filesystem"); + break; + case UFS_CIGAM: + sbInformation.AppendLine("Big-endian UFS filesystem"); + break; + case UFS_BAD_MAGIC: + sbInformation.AppendLine("Incompletely initialized UFS filesystem"); + sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); + break; + } - if (magic == UFS_CIGAM) - BigEndianBitConverter.IsLittleEndian = false; // Big-endian UFS - else - BigEndianBitConverter.IsLittleEndian = true; // Little-endian UFS - // Are there any other cases to detect big-endian UFS? + BigEndianBitConverter.IsLittleEndian = magic != UFS_CIGAM; // Little-endian UFS + // Are there any other cases to detect big-endian UFS? - // Fun with seeking follows on superblock reading! - UFSSuperBlock ufs_sb = new UFSSuperBlock(); - byte[] strings_b; + // Fun with seeking follows on superblock reading! + UFSSuperBlock ufs_sb = new UFSSuperBlock(); + byte[] strings_b; ufs_sb_sectors = imagePlugin.ReadSectors(sb_offset, sb_size_in_sectors); ufs_sb.fs_link_42bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); // 0x0000 - ufs_sb.fs_state_sun = ufs_sb.fs_link_42bsd; + ufs_sb.fs_state_sun = ufs_sb.fs_link_42bsd; ufs_sb.fs_rlink = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0004); // 0x0004 UNUSED ufs_sb.fs_sblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0008); // 0x0008 addr of super-block in filesys ufs_sb.fs_cblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x000C); // 0x000C offset of cyl-block in filesys @@ -185,19 +179,19 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_bsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0030); // 0x0030 size of basic blocks in fs ufs_sb.fs_fsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0034); // 0x0034 size of frag blocks in fs ufs_sb.fs_frag = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0038); // 0x0038 number of frags in a block in fs - // these are configuration parameters + // these are configuration parameters ufs_sb.fs_minfree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x003C); // 0x003C minimum percentage of free blocks ufs_sb.fs_rotdelay = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0040); // 0x0040 num of ms for optimal next block ufs_sb.fs_rps = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0044); // 0x0044 disk revolutions per second - // these fields can be computed from the others + // these fields can be computed from the others ufs_sb.fs_bmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0048); // 0x0048 ``blkoff'' calc of blk offsets ufs_sb.fs_fmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x004C); // 0x004C ``fragoff'' calc of frag offsets ufs_sb.fs_bshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0050); // 0x0050 ``lblkno'' calc of logical blkno ufs_sb.fs_fshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0054); // 0x0054 ``numfrags'' calc number of frags - // these are configuration parameters + // these are configuration parameters ufs_sb.fs_maxcontig = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0058); // 0x0058 max number of contiguous blks ufs_sb.fs_maxbpg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x005C); // 0x005C max number of blks per cyl group - // these fields can be computed from the others + // these fields can be computed from the others ufs_sb.fs_fragshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0060); // 0x0060 block to frag shift ufs_sb.fs_fsbtodb = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0064); // 0x0064 fsbtodb and dbtofsb shift constant ufs_sb.fs_sbsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0068); // 0x0068 actual size of super block @@ -206,75 +200,75 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_nindir = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0074); // 0x0074 value of NINDIR ufs_sb.fs_inopb = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0078); // 0x0078 value of INOPB ufs_sb.fs_nspf = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x007C); // 0x007C value of NSPF - // yet another configuration parameter + // yet another configuration parameter ufs_sb.fs_optim = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0080); // 0x0080 optimization preference, see below - // these fields are derived from the hardware - #region Sun + // these fields are derived from the hardware + #region Sun ufs_sb.fs_npsect_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0084); // 0x0084 # sectors/track including spares - #endregion Sun - #region Sunx86 + #endregion Sun + #region Sunx86 ufs_sb.fs_state_t_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0084); // 0x0084 file system state time stamp - #endregion Sunx86 - #region COMMON + #endregion Sunx86 + #region COMMON ufs_sb.fs_interleave = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0088); // 0x0088 hardware sector interleave ufs_sb.fs_trackskew = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x008C); // 0x008C sector 0 skew, per track - #endregion COMMON - // a unique id for this filesystem (currently unused and unmaintained) - // In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek - // Neither of those fields is used in the Tahoe code right now but - // there could be problems if they are. - #region COMMON + #endregion COMMON + // a unique id for this filesystem (currently unused and unmaintained) + // In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek + // Neither of those fields is used in the Tahoe code right now but + // there could be problems if they are. + #region COMMON ufs_sb.fs_id_1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0090); // 0x0090 ufs_sb.fs_id_2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0094); // 0x0094 - #endregion COMMON - #region 43BSD + #endregion COMMON + #region 43BSD ufs_sb.fs_headswitch_43bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0090); // 0x0090 ufs_sb.fs_trkseek_43bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0094); // 0x0094 - #endregion 43BSD - #region COMMON - // sizes determined by number of cylinder groups and their sizes + #endregion 43BSD + #region COMMON + // sizes determined by number of cylinder groups and their sizes ufs_sb.fs_csaddr = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0098); // 0x0098 blk addr of cyl grp summary area ufs_sb.fs_cssize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x009C); // 0x009C size of cyl grp summary area ufs_sb.fs_cgsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00A0); // 0x00A0 cylinder group size - // these fields are derived from the hardware + // these fields are derived from the hardware ufs_sb.fs_ntrak = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00A4); // 0x00A4 tracks per cylinder ufs_sb.fs_nsect = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00A8); // 0x00A8 sectors per track ufs_sb.fs_spc = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00AC); // 0x00AC sectors per cylinder - // this comes from the disk driver partitioning + // this comes from the disk driver partitioning ufs_sb.fs_ncyl = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00B0); // 0x00B0 cylinders in file system - // these fields can be computed from the others + // these fields can be computed from the others ufs_sb.fs_cpg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00B4); // 0x00B4 cylinders per group ufs_sb.fs_ipg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00B8); // 0x00B8 inodes per cylinder group ufs_sb.fs_fpg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00BC); // 0x00BC blocks per group * fs_frag - // this data must be re-computed after crashes - // struct ufs_csum fs_cstotal = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); // cylinder summary information + // this data must be re-computed after crashes + // struct ufs_csum fs_cstotal = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); // cylinder summary information ufs_sb.fs_cstotal_ndir = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00C0); // 0x00C0 number of directories ufs_sb.fs_cstotal_nbfree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00C4); // 0x00C4 number of free blocks ufs_sb.fs_cstotal_nifree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00C8); // 0x00C8 number of free inodes ufs_sb.fs_cstotal_nffree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00CC); // 0x00CC number of free frags - // these fields are cleared at mount time + // these fields are cleared at mount time ufs_sb.fs_fmod = ufs_sb_sectors[0x00D0]; // 0x00D0 super block modified flag ufs_sb.fs_clean = ufs_sb_sectors[0x00D1]; // 0x00D1 file system is clean flag ufs_sb.fs_ronly = ufs_sb_sectors[0x00D2]; // 0x00D2 mounted read-only flag ufs_sb.fs_flags = ufs_sb_sectors[0x00D3]; // 0x00D3 - #endregion COMMON - #region UFS1 + #endregion COMMON + #region UFS1 strings_b = new byte[512]; Array.Copy(ufs_sb_sectors, 0x00D4, strings_b, 0, 512); - ufs_sb.fs_fsmnt_ufs1 = StringHandlers.CToString(strings_b); // 0x00D4, 512 bytes, name mounted on - ufs_sb.fs_cgrotor_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); // 0x02D4 last cg searched + ufs_sb.fs_fsmnt_ufs1 = StringHandlers.CToString(strings_b); // 0x00D4, 512 bytes, name mounted on + ufs_sb.fs_cgrotor_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); // 0x02D4 last cg searched Array.Copy(ufs_sb_sectors, 0x02D8, ufs_sb.fs_cs_ufs1, 0, 124); // 0x02D8, 124 bytes, UInt32s, list of fs_cs info buffers ufs_sb.fs_maxcluster_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0354); // 0x0354 ufs_sb.fs_cpc_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0358); // 0x0358 cyl per cycle in postbl Array.Copy(ufs_sb_sectors, 0x035C, ufs_sb.fs_opostbl_ufs1, 0, 256); // 0x035C, 256 bytes, [16][8] matrix of UInt16s, old rotation block list head - #endregion UFS1 - #region UFS2 + #endregion UFS1 + #region UFS2 strings_b = new byte[468]; Array.Copy(ufs_sb_sectors, 0x00D4, strings_b, 0, 468); - ufs_sb.fs_fsmnt_ufs2 = StringHandlers.CToString(strings_b); // 0x00D4, 468 bytes, name mounted on + ufs_sb.fs_fsmnt_ufs2 = StringHandlers.CToString(strings_b); // 0x00D4, 468 bytes, name mounted on strings_b = new byte[32]; Array.Copy(ufs_sb_sectors, 0x02A8, strings_b, 0, 32); - ufs_sb.fs_volname_ufs2 = StringHandlers.CToString(strings_b); // 0x02A8, 32 bytes, volume name + ufs_sb.fs_volname_ufs2 = StringHandlers.CToString(strings_b); // 0x02A8, 32 bytes, volume name ufs_sb.fs_swuid_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02C8); // 0x02C8 system-wide uid ufs_sb.fs_pad_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02D0); // 0x02D0 due to alignment of fs_swuid ufs_sb.fs_cgrotor_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02D4); // 0x02D4 last cg searched @@ -287,7 +281,7 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_maxbsize_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x035C); // 0x035C maximum blocking factor permitted Array.Copy(ufs_sb_sectors, 0x0360, ufs_sb.fs_sparecon64_ufs2, 0, 136); // 0x0360, 136 bytes, UInt64s, old rotation block list head ufs_sb.fs_sblockloc_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x03E8); // 0x03E8 byte offset of standard superblock - //cylinder summary information*/ + //cylinder summary information*/ ufs_sb.fs_cstotal_ndir_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x03F0); // 0x03F0 number of directories ufs_sb.fs_cstotal_nbfree_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x03F8); // 0x03F8 number of free blocks ufs_sb.fs_cstotal_nifree_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0400); // 0x0400 number of free inodes @@ -303,8 +297,8 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_csaddr_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0448); // 0x0448 blk addr of cyl grp summary area ufs_sb.fs_pendingblocks_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0450); // 0x0450 blocks in process of being freed ufs_sb.fs_pendinginodes_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0458); // 0x0458 inodes in process of being freed - #endregion UFS2 - #region Sun + #endregion UFS2 + #region Sun Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_sun, 0, 212); // 0x045C, 212 bytes, reserved for future constants ufs_sb.fs_reclaim_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); // 0x0530 ufs_sb.fs_sparecon2_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); // 0x0534 @@ -313,8 +307,8 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_qbmask1_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0540); // 0x0540 ~usb_bmask ufs_sb.fs_qfmask0_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0544); // 0x0544 ~usb_fmask ufs_sb.fs_qfmask1_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); // 0x0548 ~usb_fmask - #endregion Sun - #region Sunx86 + #endregion Sun + #region Sunx86 Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_sun86, 0, 212); // 0x045C, 212 bytes, reserved for future constants ufs_sb.fs_reclaim_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); // 0x0530 ufs_sb.fs_sparecon2_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); // 0x0534 @@ -323,8 +317,8 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_qbmask1_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0540); // 0x0540 ~usb_bmask ufs_sb.fs_qfmask0_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0544); // 0x0544 ~usb_fmask ufs_sb.fs_qfmask1_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); // 0x0548 ~usb_fmask - #endregion Sunx86 - #region 44BSD + #endregion Sunx86 + #region 44BSD Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_44bsd, 0, 200); // 0x045C, 200 bytes ufs_sb.fs_contigsumsize_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0524); // 0x0524 size of cluster summary array ufs_sb.fs_maxsymlinklen_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0528); // 0x0528 max length of an internal symlink @@ -336,7 +330,7 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_qfmask0_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0540); // 0x0540 ~usb_fmask ufs_sb.fs_qfmask1_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0544); // 0x0544 ~usb_fmask ufs_sb.fs_state_t_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); // 0x0548 file system state time stamp - #endregion 44BSD + #endregion 44BSD ufs_sb.fs_postblformat = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x054C); // 0x054C format of positional layout tables ufs_sb.fs_nrpos = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0550); // 0x0550 number of rotational positions ufs_sb.fs_postbloff = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0554); // 0x0554 (__s16) rotation block list head @@ -344,520 +338,696 @@ namespace FileSystemIDandChk.Plugins ufs_sb.fs_magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); // 0x055C magic number ufs_sb.fs_space = ufs_sb_sectors[0x0560]; // 0x0560 list of blocks for each rotation - if(MainClass.isDebug) - { - Console.WriteLine("ufs_sb offset: 0x{0:X8}", sb_offset); - Console.WriteLine("fs_link_42bsd: 0x{0:X8}", ufs_sb.fs_link_42bsd); - Console.WriteLine("fs_state_sun: 0x{0:X8}", ufs_sb.fs_state_sun); - Console.WriteLine("fs_rlink: 0x{0:X8}", ufs_sb.fs_rlink); - Console.WriteLine("fs_sblkno: 0x{0:X8}", ufs_sb.fs_sblkno); - Console.WriteLine("fs_cblkno: 0x{0:X8}", ufs_sb.fs_cblkno); - Console.WriteLine("fs_iblkno: 0x{0:X8}", ufs_sb.fs_iblkno); - Console.WriteLine("fs_dblkno: 0x{0:X8}", ufs_sb.fs_dblkno); - Console.WriteLine("fs_cgoffset: 0x{0:X8}", ufs_sb.fs_cgoffset); - Console.WriteLine("fs_cgmask: 0x{0:X8}", ufs_sb.fs_cgmask); - Console.WriteLine("fs_time_t: 0x{0:X8}", ufs_sb.fs_time_t); - Console.WriteLine("fs_size: 0x{0:X8}", ufs_sb.fs_size); - Console.WriteLine("fs_dsize: 0x{0:X8}", ufs_sb.fs_dsize); - Console.WriteLine("fs_ncg: 0x{0:X8}", ufs_sb.fs_ncg); - Console.WriteLine("fs_bsize: 0x{0:X8}", ufs_sb.fs_bsize); - Console.WriteLine("fs_fsize: 0x{0:X8}", ufs_sb.fs_fsize); - Console.WriteLine("fs_frag: 0x{0:X8}", ufs_sb.fs_frag); - Console.WriteLine("fs_minfree: 0x{0:X8}", ufs_sb.fs_minfree); - Console.WriteLine("fs_rotdelay: 0x{0:X8}", ufs_sb.fs_rotdelay); - Console.WriteLine("fs_rps: 0x{0:X8}", ufs_sb.fs_rps); - Console.WriteLine("fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask); - Console.WriteLine("fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask); - Console.WriteLine("fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift); - Console.WriteLine("fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift); - Console.WriteLine("fs_maxcontig: 0x{0:X8}", ufs_sb.fs_maxcontig); - Console.WriteLine("fs_maxbpg: 0x{0:X8}", ufs_sb.fs_maxbpg); - Console.WriteLine("fs_fragshift: 0x{0:X8}", ufs_sb.fs_fragshift); - Console.WriteLine("fs_fsbtodb: 0x{0:X8}", ufs_sb.fs_fsbtodb); - Console.WriteLine("fs_sbsize: 0x{0:X8}", ufs_sb.fs_sbsize); - Console.WriteLine("fs_csmask: 0x{0:X8}", ufs_sb.fs_csmask); - Console.WriteLine("fs_csshift: 0x{0:X8}", ufs_sb.fs_csshift); - Console.WriteLine("fs_nindir: 0x{0:X8}", ufs_sb.fs_nindir); - Console.WriteLine("fs_inopb: 0x{0:X8}", ufs_sb.fs_inopb); - Console.WriteLine("fs_nspf: 0x{0:X8}", ufs_sb.fs_nspf); - Console.WriteLine("fs_optim: 0x{0:X8}", ufs_sb.fs_optim); - Console.WriteLine("fs_npsect_sun: 0x{0:X8}", ufs_sb.fs_npsect_sun); - Console.WriteLine("fs_state_t_sun86: 0x{0:X8}", ufs_sb.fs_state_t_sun86); - Console.WriteLine("fs_interleave: 0x{0:X8}", ufs_sb.fs_interleave); - Console.WriteLine("fs_trackskew: 0x{0:X8}", ufs_sb.fs_trackskew); - Console.WriteLine("fs_id_1: 0x{0:X8}", ufs_sb.fs_id_1); - Console.WriteLine("fs_id_2: 0x{0:X8}", ufs_sb.fs_id_2); - Console.WriteLine("fs_headswitch_43bsd: 0x{0:X8}", ufs_sb.fs_headswitch_43bsd); - Console.WriteLine("fs_trkseek_43bsd: 0x{0:X8}", ufs_sb.fs_trkseek_43bsd); - Console.WriteLine("fs_csaddr: 0x{0:X8}", ufs_sb.fs_csaddr); - Console.WriteLine("fs_cssize: 0x{0:X8}", ufs_sb.fs_cssize); - Console.WriteLine("fs_cgsize: 0x{0:X8}", ufs_sb.fs_cgsize); - Console.WriteLine("fs_ntrak: 0x{0:X8}", ufs_sb.fs_ntrak); - Console.WriteLine("fs_nsect: 0x{0:X8}", ufs_sb.fs_nsect); - Console.WriteLine("fs_spc: 0x{0:X8}", ufs_sb.fs_spc); - Console.WriteLine("fs_ncyl: 0x{0:X8}", ufs_sb.fs_ncyl); - Console.WriteLine("fs_cpg: 0x{0:X8}", ufs_sb.fs_cpg); - Console.WriteLine("fs_ipg: 0x{0:X8}", ufs_sb.fs_ipg); - Console.WriteLine("fs_fpg: 0x{0:X8}", ufs_sb.fs_fpg); - Console.WriteLine("fs_cstotal_ndir: 0x{0:X8}", ufs_sb.fs_cstotal_ndir); - Console.WriteLine("fs_cstotal_nbfree: 0x{0:X8}", ufs_sb.fs_cstotal_nbfree); - Console.WriteLine("fs_cstotal_nifree: 0x{0:X8}", ufs_sb.fs_cstotal_nifree); - Console.WriteLine("fs_cstotal_nffree: 0x{0:X8}", ufs_sb.fs_cstotal_nffree); - Console.WriteLine("fs_fmod: 0x{0:X2}", ufs_sb.fs_fmod); - Console.WriteLine("fs_clean: 0x{0:X2}", ufs_sb.fs_clean); - Console.WriteLine("fs_ronly: 0x{0:X2}", ufs_sb.fs_ronly); - Console.WriteLine("fs_flags: 0x{0:X2}", ufs_sb.fs_flags); - Console.WriteLine("fs_fsmnt_ufs1: {0}", ufs_sb.fs_fsmnt_ufs1); - Console.WriteLine("fs_cgrotor_ufs1: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs1); - Console.WriteLine("fs_cs_ufs1: 0x{0:X}", ufs_sb.fs_cs_ufs1); - Console.WriteLine("fs_maxcluster_ufs1: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs1); - Console.WriteLine("fs_cpc_ufs1: 0x{0:X8}", ufs_sb.fs_cpc_ufs1); - Console.WriteLine("fs_opostbl_ufs1: 0x{0:X}", ufs_sb.fs_opostbl_ufs1); - Console.WriteLine("fs_fsmnt_ufs2: {0}", ufs_sb.fs_fsmnt_ufs2); - Console.WriteLine("fs_volname_ufs2: {0}", ufs_sb.fs_volname_ufs2); - Console.WriteLine("fs_swuid_ufs2: 0x{0:X16}", ufs_sb.fs_swuid_ufs2); - Console.WriteLine("fs_pad_ufs2: 0x{0:X8}", ufs_sb.fs_pad_ufs2); - Console.WriteLine("fs_cgrotor_ufs2: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs2); - Console.WriteLine("fs_ocsp_ufs2: 0x{0:X}", ufs_sb.fs_ocsp_ufs2); - Console.WriteLine("fs_contigdirs_ufs2: 0x{0:X8}", ufs_sb.fs_contigdirs_ufs2); - Console.WriteLine("fs_csp_ufs2: 0x{0:X8}", ufs_sb.fs_csp_ufs2); - Console.WriteLine("fs_maxcluster_ufs2: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs2); - Console.WriteLine("fs_active_ufs2: 0x{0:X8}", ufs_sb.fs_active_ufs2); - Console.WriteLine("fs_old_cpc_ufs2: 0x{0:X8}", ufs_sb.fs_old_cpc_ufs2); - Console.WriteLine("fs_maxbsize_ufs2: 0x{0:X8}", ufs_sb.fs_maxbsize_ufs2); - Console.WriteLine("fs_sparecon64_ufs2: 0x{0:X}", ufs_sb.fs_sparecon64_ufs2); - Console.WriteLine("fs_sblockloc_ufs2: 0x{0:X16}", ufs_sb.fs_sblockloc_ufs2); - Console.WriteLine("fs_cstotal_ndir_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_ndir_ufs2); - Console.WriteLine("fs_cstotal_nbfree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nbfree_ufs2); - Console.WriteLine("fs_cstotal_nifree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nifree_ufs2); - Console.WriteLine("fs_cstotal_nffree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nffree_ufs2); - Console.WriteLine("fs_cstotal_numclusters_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_numclusters_ufs2); - Console.WriteLine("fs_cstotal_spare0_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare0_ufs2); - Console.WriteLine("fs_cstotal_spare1_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare1_ufs2); - Console.WriteLine("fs_cstotal_spare2_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare2_ufs2); - Console.WriteLine("fs_time_sec_ufs2: 0x{0:X8}", ufs_sb.fs_time_sec_ufs2); - Console.WriteLine("fs_time_usec_ufs2: 0x{0:X8}", ufs_sb.fs_time_usec_ufs2); - Console.WriteLine("fs_size_ufs2: 0x{0:X16}", ufs_sb.fs_size_ufs2); - Console.WriteLine("fs_dsize_ufs2: 0x{0:X16}", ufs_sb.fs_dsize_ufs2); - Console.WriteLine("fs_csaddr_ufs2: 0x{0:X16}", ufs_sb.fs_csaddr_ufs2); - Console.WriteLine("fs_pendingblocks_ufs2: 0x{0:X16}", ufs_sb.fs_pendingblocks_ufs2); - Console.WriteLine("fs_pendinginodes_ufs2: 0x{0:X8}", ufs_sb.fs_pendinginodes_ufs2); - Console.WriteLine("fs_sparecon_sun: 0x{0:X}", ufs_sb.fs_sparecon_sun); - Console.WriteLine("fs_reclaim_sun: 0x{0:X8}", ufs_sb.fs_reclaim_sun); - Console.WriteLine("fs_sparecon2_sun: 0x{0:X8}", ufs_sb.fs_sparecon2_sun); - Console.WriteLine("fs_state_t_sun: 0x{0:X8}", ufs_sb.fs_state_t_sun); - Console.WriteLine("fs_qbmask0_sun: 0x{0:X8}", ufs_sb.fs_qbmask0_sun); - Console.WriteLine("fs_qbmask1_sun: 0x{0:X8}", ufs_sb.fs_qbmask1_sun); - Console.WriteLine("fs_qfmask0_sun: 0x{0:X8}", ufs_sb.fs_qfmask0_sun); - Console.WriteLine("fs_qfmask1_sun: 0x{0:X8}", ufs_sb.fs_qfmask1_sun); - Console.WriteLine("fs_sparecon_sun86: 0x{0:X}", ufs_sb.fs_sparecon_sun86); - Console.WriteLine("fs_reclaim_sun86: 0x{0:X8}", ufs_sb.fs_reclaim_sun86); - Console.WriteLine("fs_sparecon2_sun86: 0x{0:X8}", ufs_sb.fs_sparecon2_sun86); - Console.WriteLine("fs_npsect_sun86: 0x{0:X8}", ufs_sb.fs_npsect_sun86); - Console.WriteLine("fs_qbmask0_sun86: 0x{0:X8}", ufs_sb.fs_qbmask0_sun86); - Console.WriteLine("fs_qbmask1_sun86: 0x{0:X8}", ufs_sb.fs_qbmask1_sun86); - Console.WriteLine("fs_qfmask0_sun86: 0x{0:X8}", ufs_sb.fs_qfmask0_sun86); - Console.WriteLine("fs_qfmask1_sun86: 0x{0:X8}", ufs_sb.fs_qfmask1_sun86); - Console.WriteLine("fs_sparecon_44bsd: 0x{0:X}", ufs_sb.fs_sparecon_44bsd); - Console.WriteLine("fs_contigsumsize_44bsd: 0x{0:X8}", ufs_sb.fs_contigsumsize_44bsd); - Console.WriteLine("fs_maxsymlinklen_44bsd: 0x{0:X8}", ufs_sb.fs_maxsymlinklen_44bsd); - Console.WriteLine("fs_inodefmt_44bsd: 0x{0:X8}", ufs_sb.fs_inodefmt_44bsd); - Console.WriteLine("fs_maxfilesize0_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize0_44bsd); - Console.WriteLine("fs_maxfilesize1_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize1_44bsd); - Console.WriteLine("fs_qbmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask0_44bsd); - Console.WriteLine("fs_qbmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask1_44bsd); - Console.WriteLine("fs_qfmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask0_44bsd); - Console.WriteLine("fs_qfmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask1_44bsd); - Console.WriteLine("fs_state_t_44bsd: 0x{0:X8}", ufs_sb.fs_state_t_44bsd); - Console.WriteLine("fs_postblformat: 0x{0:X8}", ufs_sb.fs_postblformat); - Console.WriteLine("fs_nrpos: 0x{0:X8}", ufs_sb.fs_nrpos); - Console.WriteLine("fs_postbloff: 0x{0:X8}", ufs_sb.fs_postbloff); - Console.WriteLine("fs_rotbloff: 0x{0:X8}", ufs_sb.fs_rotbloff); - Console.WriteLine("fs_magic: 0x{0:X8}", ufs_sb.fs_magic); - Console.WriteLine("fs_space: 0x{0:X2}", ufs_sb.fs_space); - } + if (MainClass.isDebug) + { + Console.WriteLine("ufs_sb offset: 0x{0:X8}", sb_offset); + Console.WriteLine("fs_link_42bsd: 0x{0:X8}", ufs_sb.fs_link_42bsd); + Console.WriteLine("fs_state_sun: 0x{0:X8}", ufs_sb.fs_state_sun); + Console.WriteLine("fs_rlink: 0x{0:X8}", ufs_sb.fs_rlink); + Console.WriteLine("fs_sblkno: 0x{0:X8}", ufs_sb.fs_sblkno); + Console.WriteLine("fs_cblkno: 0x{0:X8}", ufs_sb.fs_cblkno); + Console.WriteLine("fs_iblkno: 0x{0:X8}", ufs_sb.fs_iblkno); + Console.WriteLine("fs_dblkno: 0x{0:X8}", ufs_sb.fs_dblkno); + Console.WriteLine("fs_cgoffset: 0x{0:X8}", ufs_sb.fs_cgoffset); + Console.WriteLine("fs_cgmask: 0x{0:X8}", ufs_sb.fs_cgmask); + Console.WriteLine("fs_time_t: 0x{0:X8}", ufs_sb.fs_time_t); + Console.WriteLine("fs_size: 0x{0:X8}", ufs_sb.fs_size); + Console.WriteLine("fs_dsize: 0x{0:X8}", ufs_sb.fs_dsize); + Console.WriteLine("fs_ncg: 0x{0:X8}", ufs_sb.fs_ncg); + Console.WriteLine("fs_bsize: 0x{0:X8}", ufs_sb.fs_bsize); + Console.WriteLine("fs_fsize: 0x{0:X8}", ufs_sb.fs_fsize); + Console.WriteLine("fs_frag: 0x{0:X8}", ufs_sb.fs_frag); + Console.WriteLine("fs_minfree: 0x{0:X8}", ufs_sb.fs_minfree); + Console.WriteLine("fs_rotdelay: 0x{0:X8}", ufs_sb.fs_rotdelay); + Console.WriteLine("fs_rps: 0x{0:X8}", ufs_sb.fs_rps); + Console.WriteLine("fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask); + Console.WriteLine("fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask); + Console.WriteLine("fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift); + Console.WriteLine("fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift); + Console.WriteLine("fs_maxcontig: 0x{0:X8}", ufs_sb.fs_maxcontig); + Console.WriteLine("fs_maxbpg: 0x{0:X8}", ufs_sb.fs_maxbpg); + Console.WriteLine("fs_fragshift: 0x{0:X8}", ufs_sb.fs_fragshift); + Console.WriteLine("fs_fsbtodb: 0x{0:X8}", ufs_sb.fs_fsbtodb); + Console.WriteLine("fs_sbsize: 0x{0:X8}", ufs_sb.fs_sbsize); + Console.WriteLine("fs_csmask: 0x{0:X8}", ufs_sb.fs_csmask); + Console.WriteLine("fs_csshift: 0x{0:X8}", ufs_sb.fs_csshift); + Console.WriteLine("fs_nindir: 0x{0:X8}", ufs_sb.fs_nindir); + Console.WriteLine("fs_inopb: 0x{0:X8}", ufs_sb.fs_inopb); + Console.WriteLine("fs_nspf: 0x{0:X8}", ufs_sb.fs_nspf); + Console.WriteLine("fs_optim: 0x{0:X8}", ufs_sb.fs_optim); + Console.WriteLine("fs_npsect_sun: 0x{0:X8}", ufs_sb.fs_npsect_sun); + Console.WriteLine("fs_state_t_sun86: 0x{0:X8}", ufs_sb.fs_state_t_sun86); + Console.WriteLine("fs_interleave: 0x{0:X8}", ufs_sb.fs_interleave); + Console.WriteLine("fs_trackskew: 0x{0:X8}", ufs_sb.fs_trackskew); + Console.WriteLine("fs_id_1: 0x{0:X8}", ufs_sb.fs_id_1); + Console.WriteLine("fs_id_2: 0x{0:X8}", ufs_sb.fs_id_2); + Console.WriteLine("fs_headswitch_43bsd: 0x{0:X8}", ufs_sb.fs_headswitch_43bsd); + Console.WriteLine("fs_trkseek_43bsd: 0x{0:X8}", ufs_sb.fs_trkseek_43bsd); + Console.WriteLine("fs_csaddr: 0x{0:X8}", ufs_sb.fs_csaddr); + Console.WriteLine("fs_cssize: 0x{0:X8}", ufs_sb.fs_cssize); + Console.WriteLine("fs_cgsize: 0x{0:X8}", ufs_sb.fs_cgsize); + Console.WriteLine("fs_ntrak: 0x{0:X8}", ufs_sb.fs_ntrak); + Console.WriteLine("fs_nsect: 0x{0:X8}", ufs_sb.fs_nsect); + Console.WriteLine("fs_spc: 0x{0:X8}", ufs_sb.fs_spc); + Console.WriteLine("fs_ncyl: 0x{0:X8}", ufs_sb.fs_ncyl); + Console.WriteLine("fs_cpg: 0x{0:X8}", ufs_sb.fs_cpg); + Console.WriteLine("fs_ipg: 0x{0:X8}", ufs_sb.fs_ipg); + Console.WriteLine("fs_fpg: 0x{0:X8}", ufs_sb.fs_fpg); + Console.WriteLine("fs_cstotal_ndir: 0x{0:X8}", ufs_sb.fs_cstotal_ndir); + Console.WriteLine("fs_cstotal_nbfree: 0x{0:X8}", ufs_sb.fs_cstotal_nbfree); + Console.WriteLine("fs_cstotal_nifree: 0x{0:X8}", ufs_sb.fs_cstotal_nifree); + Console.WriteLine("fs_cstotal_nffree: 0x{0:X8}", ufs_sb.fs_cstotal_nffree); + Console.WriteLine("fs_fmod: 0x{0:X2}", ufs_sb.fs_fmod); + Console.WriteLine("fs_clean: 0x{0:X2}", ufs_sb.fs_clean); + Console.WriteLine("fs_ronly: 0x{0:X2}", ufs_sb.fs_ronly); + Console.WriteLine("fs_flags: 0x{0:X2}", ufs_sb.fs_flags); + Console.WriteLine("fs_fsmnt_ufs1: {0}", ufs_sb.fs_fsmnt_ufs1); + Console.WriteLine("fs_cgrotor_ufs1: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs1); + Console.WriteLine("fs_cs_ufs1: 0x{0:X}", ufs_sb.fs_cs_ufs1); + Console.WriteLine("fs_maxcluster_ufs1: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs1); + Console.WriteLine("fs_cpc_ufs1: 0x{0:X8}", ufs_sb.fs_cpc_ufs1); + Console.WriteLine("fs_opostbl_ufs1: 0x{0:X}", ufs_sb.fs_opostbl_ufs1); + Console.WriteLine("fs_fsmnt_ufs2: {0}", ufs_sb.fs_fsmnt_ufs2); + Console.WriteLine("fs_volname_ufs2: {0}", ufs_sb.fs_volname_ufs2); + Console.WriteLine("fs_swuid_ufs2: 0x{0:X16}", ufs_sb.fs_swuid_ufs2); + Console.WriteLine("fs_pad_ufs2: 0x{0:X8}", ufs_sb.fs_pad_ufs2); + Console.WriteLine("fs_cgrotor_ufs2: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs2); + Console.WriteLine("fs_ocsp_ufs2: 0x{0:X}", ufs_sb.fs_ocsp_ufs2); + Console.WriteLine("fs_contigdirs_ufs2: 0x{0:X8}", ufs_sb.fs_contigdirs_ufs2); + Console.WriteLine("fs_csp_ufs2: 0x{0:X8}", ufs_sb.fs_csp_ufs2); + Console.WriteLine("fs_maxcluster_ufs2: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs2); + Console.WriteLine("fs_active_ufs2: 0x{0:X8}", ufs_sb.fs_active_ufs2); + Console.WriteLine("fs_old_cpc_ufs2: 0x{0:X8}", ufs_sb.fs_old_cpc_ufs2); + Console.WriteLine("fs_maxbsize_ufs2: 0x{0:X8}", ufs_sb.fs_maxbsize_ufs2); + Console.WriteLine("fs_sparecon64_ufs2: 0x{0:X}", ufs_sb.fs_sparecon64_ufs2); + Console.WriteLine("fs_sblockloc_ufs2: 0x{0:X16}", ufs_sb.fs_sblockloc_ufs2); + Console.WriteLine("fs_cstotal_ndir_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_ndir_ufs2); + Console.WriteLine("fs_cstotal_nbfree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nbfree_ufs2); + Console.WriteLine("fs_cstotal_nifree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nifree_ufs2); + Console.WriteLine("fs_cstotal_nffree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nffree_ufs2); + Console.WriteLine("fs_cstotal_numclusters_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_numclusters_ufs2); + Console.WriteLine("fs_cstotal_spare0_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare0_ufs2); + Console.WriteLine("fs_cstotal_spare1_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare1_ufs2); + Console.WriteLine("fs_cstotal_spare2_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare2_ufs2); + Console.WriteLine("fs_time_sec_ufs2: 0x{0:X8}", ufs_sb.fs_time_sec_ufs2); + Console.WriteLine("fs_time_usec_ufs2: 0x{0:X8}", ufs_sb.fs_time_usec_ufs2); + Console.WriteLine("fs_size_ufs2: 0x{0:X16}", ufs_sb.fs_size_ufs2); + Console.WriteLine("fs_dsize_ufs2: 0x{0:X16}", ufs_sb.fs_dsize_ufs2); + Console.WriteLine("fs_csaddr_ufs2: 0x{0:X16}", ufs_sb.fs_csaddr_ufs2); + Console.WriteLine("fs_pendingblocks_ufs2: 0x{0:X16}", ufs_sb.fs_pendingblocks_ufs2); + Console.WriteLine("fs_pendinginodes_ufs2: 0x{0:X8}", ufs_sb.fs_pendinginodes_ufs2); + Console.WriteLine("fs_sparecon_sun: 0x{0:X}", ufs_sb.fs_sparecon_sun); + Console.WriteLine("fs_reclaim_sun: 0x{0:X8}", ufs_sb.fs_reclaim_sun); + Console.WriteLine("fs_sparecon2_sun: 0x{0:X8}", ufs_sb.fs_sparecon2_sun); + Console.WriteLine("fs_state_t_sun: 0x{0:X8}", ufs_sb.fs_state_t_sun); + Console.WriteLine("fs_qbmask0_sun: 0x{0:X8}", ufs_sb.fs_qbmask0_sun); + Console.WriteLine("fs_qbmask1_sun: 0x{0:X8}", ufs_sb.fs_qbmask1_sun); + Console.WriteLine("fs_qfmask0_sun: 0x{0:X8}", ufs_sb.fs_qfmask0_sun); + Console.WriteLine("fs_qfmask1_sun: 0x{0:X8}", ufs_sb.fs_qfmask1_sun); + Console.WriteLine("fs_sparecon_sun86: 0x{0:X}", ufs_sb.fs_sparecon_sun86); + Console.WriteLine("fs_reclaim_sun86: 0x{0:X8}", ufs_sb.fs_reclaim_sun86); + Console.WriteLine("fs_sparecon2_sun86: 0x{0:X8}", ufs_sb.fs_sparecon2_sun86); + Console.WriteLine("fs_npsect_sun86: 0x{0:X8}", ufs_sb.fs_npsect_sun86); + Console.WriteLine("fs_qbmask0_sun86: 0x{0:X8}", ufs_sb.fs_qbmask0_sun86); + Console.WriteLine("fs_qbmask1_sun86: 0x{0:X8}", ufs_sb.fs_qbmask1_sun86); + Console.WriteLine("fs_qfmask0_sun86: 0x{0:X8}", ufs_sb.fs_qfmask0_sun86); + Console.WriteLine("fs_qfmask1_sun86: 0x{0:X8}", ufs_sb.fs_qfmask1_sun86); + Console.WriteLine("fs_sparecon_44bsd: 0x{0:X}", ufs_sb.fs_sparecon_44bsd); + Console.WriteLine("fs_contigsumsize_44bsd: 0x{0:X8}", ufs_sb.fs_contigsumsize_44bsd); + Console.WriteLine("fs_maxsymlinklen_44bsd: 0x{0:X8}", ufs_sb.fs_maxsymlinklen_44bsd); + Console.WriteLine("fs_inodefmt_44bsd: 0x{0:X8}", ufs_sb.fs_inodefmt_44bsd); + Console.WriteLine("fs_maxfilesize0_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize0_44bsd); + Console.WriteLine("fs_maxfilesize1_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize1_44bsd); + Console.WriteLine("fs_qbmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask0_44bsd); + Console.WriteLine("fs_qbmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask1_44bsd); + Console.WriteLine("fs_qfmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask0_44bsd); + Console.WriteLine("fs_qfmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask1_44bsd); + Console.WriteLine("fs_state_t_44bsd: 0x{0:X8}", ufs_sb.fs_state_t_44bsd); + Console.WriteLine("fs_postblformat: 0x{0:X8}", ufs_sb.fs_postblformat); + Console.WriteLine("fs_nrpos: 0x{0:X8}", ufs_sb.fs_nrpos); + Console.WriteLine("fs_postbloff: 0x{0:X8}", ufs_sb.fs_postbloff); + Console.WriteLine("fs_rotbloff: 0x{0:X8}", ufs_sb.fs_rotbloff); + Console.WriteLine("fs_magic: 0x{0:X8}", ufs_sb.fs_magic); + Console.WriteLine("fs_space: 0x{0:X2}", ufs_sb.fs_space); + } - 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"); + 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(ufs_sb.fs_magic == UFS2_MAGIC) - { - fs_type_ufs2 = true; - } - else - { - UInt32 SunOSEpoch = 0x1A54C580; // We are supposing there cannot be a Sun's fs created before 1/1/1982 00:00:00 + if (ufs_sb.fs_magic == UFS2_MAGIC) + { + fs_type_ufs2 = true; + } + else + { + const UInt32 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. + 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_42bsd > 0) - { - fs_type_42bsd = true; // It was used in 4.2BSD - fs_type_43bsd = false; - } + if (ufs_sb.fs_link_42bsd > 0) + { + fs_type_42bsd = true; // It was used in 4.2BSD + fs_type_43bsd = false; + } - if(ufs_sb.fs_state_t_sun > SunOSEpoch && DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun) < DateTime.Now) - { - fs_type_42bsd = false; - fs_type_sun = true; - fs_type_43bsd = false; - } + if (ufs_sb.fs_state_t_sun > SunOSEpoch && DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun) < 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_state_t_sun86 > SunOSEpoch && DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun) < DateTime.Now) - { - fs_type_42bsd = false; - fs_type_sun86 = true; - fs_type_sun = false; - 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_state_t_sun86 > SunOSEpoch && DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun) < DateTime.Now) + { + fs_type_42bsd = false; + fs_type_sun86 = true; + fs_type_sun = false; + fs_type_43bsd = false; + } - if(ufs_sb.fs_cgrotor_ufs1 > 0x00000000 && ufs_sb.fs_cgrotor_ufs1 < 0xFFFFFFFF) - { - fs_type_42bsd = false; - fs_type_sun = false; - fs_type_sun86 = false; - fs_type_ufs = true; - fs_type_43bsd = false; - } + if (ufs_sb.fs_cgrotor_ufs1 > 0x00000000 && ufs_sb.fs_cgrotor_ufs1 < 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 - if(ufs_sb.fs_trkseek_43bsd != 0 || ufs_sb.fs_headswitch_43bsd != 0) - 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_trkseek_43bsd == 0 && ufs_sb.fs_headswitch_43bsd == 0; - // This is the only 4.4BSD inode format - if(ufs_sb.fs_inodefmt_44bsd == 2) - fs_type_44bsd = true; - } + // This is the only 4.4BSD inode format + fs_type_44bsd |= ufs_sb.fs_inodefmt_44bsd == 2; + } - 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_ufs2) - sbInformation.AppendLine("Guessed as UFS2"); + 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_ufs2) + sbInformation.AppendLine("Guessed as UFS2"); - if(fs_type_42bsd) - sbInformation.AppendFormat("Linked list of filesystems: 0x{0:X8}", ufs_sb.fs_link_42bsd).AppendLine(); - else if(fs_type_sun) - sbInformation.AppendFormat("Filesystem state flag: 0x{0:X8}", ufs_sb.fs_state_sun).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_cgoffset).AppendLine(); - sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_t)).AppendLine(); - sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size*ufs_sb.fs_bsize).AppendLine(); - sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize*ufs_sb.fs_bsize).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_rotdelay).AppendLine(); - sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", ufs_sb.fs_rps, ufs_sb.fs_rps*60).AppendLine(); + if (fs_type_42bsd) + sbInformation.AppendFormat("Linked list of filesystems: 0x{0:X8}", ufs_sb.fs_link_42bsd).AppendLine(); + else if (fs_type_sun) + sbInformation.AppendFormat("Filesystem state flag: 0x{0:X8}", ufs_sb.fs_state_sun).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_cgoffset).AppendLine(); + sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_t)).AppendLine(); + sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_bsize).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_rotdelay).AppendLine(); + sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", ufs_sb.fs_rps, ufs_sb.fs_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_nspf).AppendLine(); - if(ufs_sb.fs_optim == 0) - sbInformation.AppendLine("Filesystem will minimize allocation time"); - else if(ufs_sb.fs_optim == 1) - sbInformation.AppendLine("Filesystem will minimize volume fragmentation"); - else - sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine(); - if(fs_type_sun) - sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_npsect_sun).AppendLine(); - else if(fs_type_sun86) - sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun86)).AppendLine(); - sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_interleave).AppendLine(); - sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_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_headswitch_43bsd > 0 && ufs_sb.fs_trkseek_43bsd > 0) - { - sbInformation.AppendFormat("{0} µsec for head switch", ufs_sb.fs_headswitch_43bsd).AppendLine(); - sbInformation.AppendFormat("{0} µsec for track-to-track seek", ufs_sb.fs_trkseek_43bsd).AppendLine(); - } - sbInformation.AppendFormat("Cylinder group summary LBA: {0}", ufs_sb.fs_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_ntrak).AppendLine(); - sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_nsect).AppendLine(); - sbInformation.AppendFormat("{0} sectors/cylinder", ufs_sb.fs_spc).AppendLine(); - sbInformation.AppendFormat("{0} cylinder in volume", ufs_sb.fs_ncyl).AppendLine(); - sbInformation.AppendFormat("{0} cylinders/group", ufs_sb.fs_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_cstotal_ndir).AppendLine(); - sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree, ufs_sb.fs_cstotal_nbfree*ufs_sb.fs_bsize).AppendLine(); - sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree).AppendLine(); - sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree).AppendLine(); - if(ufs_sb.fs_fmod == 1) - sbInformation.AppendLine("Superblock is under modification"); - 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}\"", ufs_sb.fs_fsmnt_ufs1).AppendLine(); - sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor_ufs1).AppendLine(); - } - else if(fs_type_ufs2) - { - sbInformation.AppendFormat("Volume last mounted on \"{0}\"", ufs_sb.fs_fsmnt_ufs2).AppendLine(); - sbInformation.AppendFormat("Volume name: \"{0}\"", ufs_sb.fs_volname_ufs2).AppendLine(); - sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid_ufs2).AppendLine(); - sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor_ufs2).AppendLine(); - sbInformation.AppendFormat("{0} contiguously allocated directories", ufs_sb.fs_contigdirs_ufs2).AppendLine(); - sbInformation.AppendFormat("Standard superblock LBA: {0}", ufs_sb.fs_sblockloc_ufs2).AppendLine(); - sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal_ndir_ufs2).AppendLine(); - sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree_ufs2, ufs_sb.fs_cstotal_nbfree_ufs2*ufs_sb.fs_bsize).AppendLine(); - sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree_ufs2).AppendLine(); - sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree_ufs2).AppendLine(); - sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal_numclusters_ufs2).AppendLine(); - sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_sec_ufs2)).AppendLine(); - sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size_ufs2, ufs_sb.fs_size_ufs2*ufs_sb.fs_bsize).AppendLine(); - sbInformation.AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize_ufs2, ufs_sb.fs_dsize_ufs2*ufs_sb.fs_bsize).AppendLine(); - sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", ufs_sb.fs_csaddr_ufs2).AppendLine(); - sbInformation.AppendFormat("{0} blocks pending of being freed", ufs_sb.fs_pendingblocks_ufs2).AppendLine(); - sbInformation.AppendFormat("{0} inodes pending of being freed", ufs_sb.fs_pendinginodes_ufs2).AppendLine(); - } - if(fs_type_sun) - { - sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun)).AppendLine(); - } - else if(fs_type_sun86) - { - sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_npsect_sun86).AppendLine(); - } - else if(fs_type_44bsd) - { - sbInformation.AppendFormat("{0} blocks on cluster summary array", ufs_sb.fs_contigsumsize_44bsd).AppendLine(); - sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", ufs_sb.fs_maxsymlinklen_44bsd).AppendLine(); - ulong bsd44_maxfilesize = ((ulong)ufs_sb.fs_maxfilesize0_44bsd)*0x100000000 + ufs_sb.fs_maxfilesize1_44bsd; - sbInformation.AppendFormat("A file can be {0} bytes at max", bsd44_maxfilesize).AppendLine(); - sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_44bsd)).AppendLine(); - } - sbInformation.AppendFormat("{0} rotational positions", ufs_sb.fs_nrpos).AppendLine(); - sbInformation.AppendFormat("{0} blocks per rotation", ufs_sb.fs_rotbloff).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_nspf).AppendLine(); + if (ufs_sb.fs_optim == 0) + sbInformation.AppendLine("Filesystem will minimize allocation time"); + else if (ufs_sb.fs_optim == 1) + sbInformation.AppendLine("Filesystem will minimize volume fragmentation"); + else + sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine(); + if (fs_type_sun) + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_npsect_sun).AppendLine(); + else if (fs_type_sun86) + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun86)).AppendLine(); + sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_interleave).AppendLine(); + sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_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_headswitch_43bsd > 0 && ufs_sb.fs_trkseek_43bsd > 0) + { + sbInformation.AppendFormat("{0} µsec for head switch", ufs_sb.fs_headswitch_43bsd).AppendLine(); + sbInformation.AppendFormat("{0} µsec for track-to-track seek", ufs_sb.fs_trkseek_43bsd).AppendLine(); + } + sbInformation.AppendFormat("Cylinder group summary LBA: {0}", ufs_sb.fs_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_ntrak).AppendLine(); + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_nsect).AppendLine(); + sbInformation.AppendFormat("{0} sectors/cylinder", ufs_sb.fs_spc).AppendLine(); + sbInformation.AppendFormat("{0} cylinder in volume", ufs_sb.fs_ncyl).AppendLine(); + sbInformation.AppendFormat("{0} cylinders/group", ufs_sb.fs_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_cstotal_ndir).AppendLine(); + sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree, ufs_sb.fs_cstotal_nbfree * ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree).AppendLine(); + sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree).AppendLine(); + if (ufs_sb.fs_fmod == 1) + sbInformation.AppendLine("Superblock is under modification"); + 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}\"", ufs_sb.fs_fsmnt_ufs1).AppendLine(); + sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor_ufs1).AppendLine(); + } + else if (fs_type_ufs2) + { + sbInformation.AppendFormat("Volume last mounted on \"{0}\"", ufs_sb.fs_fsmnt_ufs2).AppendLine(); + sbInformation.AppendFormat("Volume name: \"{0}\"", ufs_sb.fs_volname_ufs2).AppendLine(); + sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid_ufs2).AppendLine(); + sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} contiguously allocated directories", ufs_sb.fs_contigdirs_ufs2).AppendLine(); + sbInformation.AppendFormat("Standard superblock LBA: {0}", ufs_sb.fs_sblockloc_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal_ndir_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree_ufs2, ufs_sb.fs_cstotal_nbfree_ufs2 * ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal_numclusters_ufs2).AppendLine(); + sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_sec_ufs2)).AppendLine(); + sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size_ufs2, ufs_sb.fs_size_ufs2 * ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize_ufs2, ufs_sb.fs_dsize_ufs2 * ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", ufs_sb.fs_csaddr_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} blocks pending of being freed", ufs_sb.fs_pendingblocks_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} inodes pending of being freed", ufs_sb.fs_pendinginodes_ufs2).AppendLine(); + } + if (fs_type_sun) + { + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun)).AppendLine(); + } + else if (fs_type_sun86) + { + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_npsect_sun86).AppendLine(); + } + else if (fs_type_44bsd) + { + sbInformation.AppendFormat("{0} blocks on cluster summary array", ufs_sb.fs_contigsumsize_44bsd).AppendLine(); + sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", ufs_sb.fs_maxsymlinklen_44bsd).AppendLine(); + ulong bsd44_maxfilesize = ((ulong)ufs_sb.fs_maxfilesize0_44bsd) * 0x100000000 + ufs_sb.fs_maxfilesize1_44bsd; + sbInformation.AppendFormat("A file can be {0} bytes at max", bsd44_maxfilesize).AppendLine(); + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_44bsd)).AppendLine(); + } + sbInformation.AppendFormat("{0} rotational positions", ufs_sb.fs_nrpos).AppendLine(); + sbInformation.AppendFormat("{0} blocks per rotation", ufs_sb.fs_rotbloff).AppendLine(); - information = sbInformation.ToString(); - } + information = sbInformation.ToString(); + } - private const uint block_size = 8192; - - // As specified in FreeBSD source code, FFS/UFS can start in any of four places - private const ulong sb_start_floppy = 0; // For floppies, start at offset 0 - private const ulong sb_start_ufs1 = 1; // For normal devices, start at offset 8192 - private const ulong sb_start_ufs2 = 8; // For UFS2, start at offset 65536 - private const ulong sb_start_piggy = 32; // For piggy devices (?), start at offset 262144 - - // MAGICs - private const UInt32 UFS_MAGIC = 0x00011954; // UFS magic - private const UInt32 UFS_MAGIC_BW = 0x0f242697; // BorderWare UFS - private const UInt32 UFS2_MAGIC = 0x19540119; // UFS2 magic - private const UInt32 UFS_CIGAM = 0x54190100; // byteswapped - private const UInt32 UFS_BAD_MAGIC = 0x19960408; // Incomplete newfs - - // On-disk superblock is quite a mixture of all the UFS/FFS variants - // There is no clear way to detect which one is correct - // And as C# does not support unions this struct will clearly appear quite dirty :p - // To clean up things a little, comment starts with relative superblock offset of field + const uint block_size = 8192; + // As specified in FreeBSD source code, FFS/UFS can start in any of four places + const ulong sb_start_floppy = 0; + // For floppies, start at offset 0 + const ulong sb_start_ufs1 = 1; + // For normal devices, start at offset 8192 + const ulong sb_start_ufs2 = 8; + // For UFS2, start at offset 65536 + const ulong sb_start_piggy = 32; + // For piggy devices (?), start at offset 262144 + // MAGICs + const UInt32 UFS_MAGIC = 0x00011954; + // UFS magic + const UInt32 UFS_MAGIC_BW = 0x0f242697; + // BorderWare UFS + const UInt32 UFS2_MAGIC = 0x19540119; + // UFS2 magic + const UInt32 UFS_CIGAM = 0x54190100; + // byteswapped + const UInt32 UFS_BAD_MAGIC = 0x19960408; + // Incomplete newfs + // On-disk superblock is quite a mixture of all the UFS/FFS variants + // There is no clear way to detect which one is correct + // And as C# does not support unions this struct will clearly appear quite dirty :p + // To clean up things a little, comment starts with relative superblock offset of field // Biggest sized supleblock would be 1377 bytes - public struct UFSSuperBlock - { - #region 42BSD - public UInt32 fs_link_42bsd; // 0x0000 linked list of file systems - #endregion - #region Sun - public UInt32 fs_state_sun; // 0x0000 file system state flag - #endregion - #region COMMON - public UInt32 fs_rlink; // 0x0004 used for incore super blocks - public UInt32 fs_sblkno; // 0x0008 addr of super-block in filesys - public UInt32 fs_cblkno; // 0x000C offset of cyl-block in filesys - public UInt32 fs_iblkno; // 0x0010 offset of inode-blocks in filesys - public UInt32 fs_dblkno; // 0x0014 offset of first data after cg - public UInt32 fs_cgoffset; // 0x0018 cylinder group offset in cylinder - public UInt32 fs_cgmask; // 0x001C used to calc mod fs_ntrak - public UInt32 fs_time_t; // 0x0020 last time written -- time_t - public UInt32 fs_size; // 0x0024 number of blocks in fs - public UInt32 fs_dsize; // 0x0028 number of data blocks in fs - public UInt32 fs_ncg; // 0x002C number of cylinder groups - public UInt32 fs_bsize; // 0x0030 size of basic blocks in fs - public UInt32 fs_fsize; // 0x0034 size of frag blocks in fs - public UInt32 fs_frag; // 0x0038 number of frags in a block in fs - // these are configuration parameters - public UInt32 fs_minfree; // 0x003C minimum percentage of free blocks - public UInt32 fs_rotdelay; // 0x0040 num of ms for optimal next block - public UInt32 fs_rps; // 0x0044 disk revolutions per second - // these fields can be computed from the others - public UInt32 fs_bmask; // 0x0048 ``blkoff'' calc of blk offsets - public UInt32 fs_fmask; // 0x004C ``fragoff'' calc of frag offsets - public UInt32 fs_bshift; // 0x0050 ``lblkno'' calc of logical blkno - public UInt32 fs_fshift; // 0x0054 ``numfrags'' calc number of frags - // these are configuration parameters - public UInt32 fs_maxcontig; // 0x0058 max number of contiguous blks - public UInt32 fs_maxbpg; // 0x005C max number of blks per cyl group - // these fields can be computed from the others - public UInt32 fs_fragshift; // 0x0060 block to frag shift - public UInt32 fs_fsbtodb; // 0x0064 fsbtodb and dbtofsb shift constant - public UInt32 fs_sbsize; // 0x0068 actual size of super block - public UInt32 fs_csmask; // 0x006C csum block offset - public UInt32 fs_csshift; // 0x0070 csum block number - public UInt32 fs_nindir; // 0x0074 value of NINDIR - public UInt32 fs_inopb; // 0x0078 value of INOPB - public UInt32 fs_nspf; // 0x007C value of NSPF - // yet another configuration parameter - public UInt32 fs_optim; // 0x0080 optimization preference, see below - #endregion COMMON - // these fields are derived from the hardware - #region Sun - public UInt32 fs_npsect_sun; // 0x0084 # sectors/track including spares - #endregion Sun - #region Sunx86 - public UInt32 fs_state_t_sun86; // 0x0084 file system state time stamp - #endregion Sunx86 - #region COMMON - public UInt32 fs_interleave; // 0x0088 hardware sector interleave - public UInt32 fs_trackskew; // 0x008C sector 0 skew, per track - #endregion COMMON - // a unique id for this filesystem (currently unused and unmaintained) - // In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek - // Neither of those fields is used in the Tahoe code right now but - // there could be problems if they are. - #region COMMON - public UInt32 fs_id_1; // 0x0090 - public UInt32 fs_id_2; // 0x0094 - #endregion COMMON - #region 43BSD - public UInt32 fs_headswitch_43bsd; // 0x0090 head switch time, usec - public UInt32 fs_trkseek_43bsd; // 0x0094 track-to-track seek, usec - #endregion 43BSD - #region COMMON - // sizes determined by number of cylinder groups and their sizes - public UInt32 fs_csaddr; // 0x0098 blk addr of cyl grp summary area - public UInt32 fs_cssize; // 0x009C size of cyl grp summary area - public UInt32 fs_cgsize; // 0x00A0 cylinder group size - // these fields are derived from the hardware - public UInt32 fs_ntrak; // 0x00A4 tracks per cylinder - public UInt32 fs_nsect; // 0x00A8 sectors per track - public UInt32 fs_spc; // 0x00AC sectors per cylinder - // this comes from the disk driver partitioning - public UInt32 fs_ncyl; // 0x00B0 cylinders in file system - // these fields can be computed from the others - public UInt32 fs_cpg; // 0x00B4 cylinders per group - public UInt32 fs_ipg; // 0x00B8 inodes per cylinder group - public UInt32 fs_fpg; // 0x00BC blocks per group * fs_frag - // this data must be re-computed after crashes - // struct ufs_csum fs_cstotal; // cylinder summary information - public UInt32 fs_cstotal_ndir; // 0x00C0 number of directories - public UInt32 fs_cstotal_nbfree; // 0x00C4 number of free blocks - public UInt32 fs_cstotal_nifree; // 0x00C8 number of free inodes - public UInt32 fs_cstotal_nffree; // 0x00CC number of free frags - // these fields are cleared at mount time - public byte fs_fmod; // 0x00D0 super block modified flag - public byte fs_clean; // 0x00D1 file system is clean flag - public byte fs_ronly; // 0x00D2 mounted read-only flag - public byte fs_flags; // 0x00D3 - #endregion common - #region UFS1 - public string fs_fsmnt_ufs1; // 0x00D4, 512 bytes, name mounted on - public UInt32 fs_cgrotor_ufs1; // 0x02D4 last cg searched - public byte[] fs_cs_ufs1; // 0x02D8, 124 bytes, UInt32s, list of fs_cs info buffers - public UInt32 fs_maxcluster_ufs1; // 0x0354 - public UInt32 fs_cpc_ufs1; // 0x0358 cyl per cycle in postbl - public byte[] fs_opostbl_ufs1; // 0x035C, 256 bytes, [16][8] matrix of UInt16s, old rotation block list head - #endregion UFS1 - #region UFS2 - public string fs_fsmnt_ufs2; // 0x00D4, 468 bytes, name mounted on - public string fs_volname_ufs2; // 0x02A8, 32 bytes, volume name - public UInt64 fs_swuid_ufs2; // 0x02C8 system-wide uid - public UInt32 fs_pad_ufs2; // 0x02D0 due to alignment of fs_swuid - public UInt32 fs_cgrotor_ufs2; // 0x02D4 last cg searched - public byte[] fs_ocsp_ufs2; // 0x02D8, 112 bytes, UInt32s, list of fs_cs info buffers - public UInt32 fs_contigdirs_ufs2; // 0x0348 # of contiguously allocated dirs - public UInt32 fs_csp_ufs2; // 0x034C cg summary info buffer for fs_cs - public UInt32 fs_maxcluster_ufs2; // 0x0350 - public UInt32 fs_active_ufs2; // 0x0354 used by snapshots to track fs - public UInt32 fs_old_cpc_ufs2; // 0x0358 cyl per cycle in postbl - public UInt32 fs_maxbsize_ufs2; // 0x035C maximum blocking factor permitted - public byte[] fs_sparecon64_ufs2; // 0x0360, 136 bytes, UInt64s, old rotation block list head - public UInt64 fs_sblockloc_ufs2; // 0x03E8 byte offset of standard superblock - //cylinder summary information*/ - public UInt64 fs_cstotal_ndir_ufs2; // 0x03F0 number of directories - public UInt64 fs_cstotal_nbfree_ufs2; // 0x03F8 number of free blocks - public UInt64 fs_cstotal_nifree_ufs2; // 0x0400 number of free inodes - public UInt64 fs_cstotal_nffree_ufs2; // 0x0408 number of free frags - public UInt64 fs_cstotal_numclusters_ufs2; // 0x0410 number of free clusters - public UInt64 fs_cstotal_spare0_ufs2; // 0x0418 future expansion - public UInt64 fs_cstotal_spare1_ufs2; // 0x0420 future expansion - public UInt64 fs_cstotal_spare2_ufs2; // 0x0428 future expansion - public UInt32 fs_time_sec_ufs2; // 0x0430 last time written - public UInt32 fs_time_usec_ufs2; // 0x0434 last time written - public UInt64 fs_size_ufs2; // 0x0438 number of blocks in fs - public UInt64 fs_dsize_ufs2; // 0x0440 number of data blocks in fs - public UInt64 fs_csaddr_ufs2; // 0x0448 blk addr of cyl grp summary area - public UInt64 fs_pendingblocks_ufs2; // 0x0450 blocks in process of being freed - public UInt32 fs_pendinginodes_ufs2; // 0x0458 inodes in process of being freed - #endregion UFS2 - #region Sun - public byte[] fs_sparecon_sun; // 0x045C, 212 bytes, reserved for future constants - public UInt32 fs_reclaim_sun; // 0x0530 - public UInt32 fs_sparecon2_sun; // 0x0534 - public UInt32 fs_state_t_sun; // 0x0538 file system state time stamp - public UInt32 fs_qbmask0_sun; // 0x053C ~usb_bmask - public UInt32 fs_qbmask1_sun; // 0x0540 ~usb_bmask - public UInt32 fs_qfmask0_sun; // 0x0544 ~usb_fmask - public UInt32 fs_qfmask1_sun; // 0x0548 ~usb_fmask - #endregion Sun - #region Sunx86 - public byte[] fs_sparecon_sun86; // 0x045C, 212 bytes, reserved for future constants - public UInt32 fs_reclaim_sun86; // 0x0530 - public UInt32 fs_sparecon2_sun86; // 0x0534 - public UInt32 fs_npsect_sun86; // 0x0538 # sectors/track including spares - public UInt32 fs_qbmask0_sun86; // 0x053C ~usb_bmask - public UInt32 fs_qbmask1_sun86; // 0x0540 ~usb_bmask - public UInt32 fs_qfmask0_sun86; // 0x0544 ~usb_fmask - public UInt32 fs_qfmask1_sun86; // 0x0548 ~usb_fmask - #endregion Sunx86 - #region 44BSD - public byte[] fs_sparecon_44bsd; // 0x045C, 200 bytes - public UInt32 fs_contigsumsize_44bsd; // 0x0524 size of cluster summary array - public UInt32 fs_maxsymlinklen_44bsd; // 0x0528 max length of an internal symlink - public UInt32 fs_inodefmt_44bsd; // 0x052C format of on-disk inodes - public UInt32 fs_maxfilesize0_44bsd; // 0x0530 max representable file size - public UInt32 fs_maxfilesize1_44bsd; // 0x0534 max representable file size - public UInt32 fs_qbmask0_44bsd; // 0x0538 ~usb_bmask - public UInt32 fs_qbmask1_44bsd; // 0x053C ~usb_bmask - public UInt32 fs_qfmask0_44bsd; // 0x0540 ~usb_fmask - public UInt32 fs_qfmask1_44bsd; // 0x0544 ~usb_fmask - public UInt32 fs_state_t_44bsd; // 0x0548 file system state time stamp - #endregion 44BSD - public UInt32 fs_postblformat; // 0x054C format of positional layout tables - public UInt32 fs_nrpos; // 0x0550 number of rotational positions - public UInt32 fs_postbloff; // 0x0554 (__s16) rotation block list head - public UInt32 fs_rotbloff; // 0x0558 (__u8) blocks for each rotation - public UInt32 fs_magic; // 0x055C magic number - public byte fs_space; // 0x0560 list of blocks for each rotation - // 0x0561 - } - } + public struct UFSSuperBlock + { + #region 42BSD + + public UInt32 fs_link_42bsd; + // 0x0000 linked list of file systems + + #endregion + + #region Sun + + public UInt32 fs_state_sun; + // 0x0000 file system state flag + + #endregion + + #region COMMON + + public UInt32 fs_rlink; + // 0x0004 used for incore super blocks + public UInt32 fs_sblkno; + // 0x0008 addr of super-block in filesys + public UInt32 fs_cblkno; + // 0x000C offset of cyl-block in filesys + public UInt32 fs_iblkno; + // 0x0010 offset of inode-blocks in filesys + public UInt32 fs_dblkno; + // 0x0014 offset of first data after cg + public UInt32 fs_cgoffset; + // 0x0018 cylinder group offset in cylinder + public UInt32 fs_cgmask; + // 0x001C used to calc mod fs_ntrak + public UInt32 fs_time_t; + // 0x0020 last time written -- time_t + public UInt32 fs_size; + // 0x0024 number of blocks in fs + public UInt32 fs_dsize; + // 0x0028 number of data blocks in fs + public UInt32 fs_ncg; + // 0x002C number of cylinder groups + public UInt32 fs_bsize; + // 0x0030 size of basic blocks in fs + public UInt32 fs_fsize; + // 0x0034 size of frag blocks in fs + public UInt32 fs_frag; + // 0x0038 number of frags in a block in fs + // these are configuration parameters + public UInt32 fs_minfree; + // 0x003C minimum percentage of free blocks + public UInt32 fs_rotdelay; + // 0x0040 num of ms for optimal next block + public UInt32 fs_rps; + // 0x0044 disk revolutions per second + // these fields can be computed from the others + public UInt32 fs_bmask; + // 0x0048 ``blkoff'' calc of blk offsets + public UInt32 fs_fmask; + // 0x004C ``fragoff'' calc of frag offsets + public UInt32 fs_bshift; + // 0x0050 ``lblkno'' calc of logical blkno + public UInt32 fs_fshift; + // 0x0054 ``numfrags'' calc number of frags + // these are configuration parameters + public UInt32 fs_maxcontig; + // 0x0058 max number of contiguous blks + public UInt32 fs_maxbpg; + // 0x005C max number of blks per cyl group + // these fields can be computed from the others + public UInt32 fs_fragshift; + // 0x0060 block to frag shift + public UInt32 fs_fsbtodb; + // 0x0064 fsbtodb and dbtofsb shift constant + public UInt32 fs_sbsize; + // 0x0068 actual size of super block + public UInt32 fs_csmask; + // 0x006C csum block offset + public UInt32 fs_csshift; + // 0x0070 csum block number + public UInt32 fs_nindir; + // 0x0074 value of NINDIR + public UInt32 fs_inopb; + // 0x0078 value of INOPB + public UInt32 fs_nspf; + // 0x007C value of NSPF + // yet another configuration parameter + public UInt32 fs_optim; + // 0x0080 optimization preference, see below + + #endregion COMMON + + // these fields are derived from the hardware + + #region Sun + + public UInt32 fs_npsect_sun; + // 0x0084 # sectors/track including spares + + #endregion Sun + + #region Sunx86 + + public UInt32 fs_state_t_sun86; + // 0x0084 file system state time stamp + + #endregion Sunx86 + + #region COMMON + + public UInt32 fs_interleave; + // 0x0088 hardware sector interleave + public UInt32 fs_trackskew; + // 0x008C sector 0 skew, per track + + #endregion COMMON + + // a unique id for this filesystem (currently unused and unmaintained) + // In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek + // Neither of those fields is used in the Tahoe code right now but + // there could be problems if they are. + + #region COMMON + + public UInt32 fs_id_1; + // 0x0090 + public UInt32 fs_id_2; + // 0x0094 + + #endregion COMMON + + #region 43BSD + + public UInt32 fs_headswitch_43bsd; + // 0x0090 head switch time, usec + public UInt32 fs_trkseek_43bsd; + // 0x0094 track-to-track seek, usec + + #endregion 43BSD + + #region COMMON + + // sizes determined by number of cylinder groups and their sizes + public UInt32 fs_csaddr; + // 0x0098 blk addr of cyl grp summary area + public UInt32 fs_cssize; + // 0x009C size of cyl grp summary area + public UInt32 fs_cgsize; + // 0x00A0 cylinder group size + // these fields are derived from the hardware + public UInt32 fs_ntrak; + // 0x00A4 tracks per cylinder + public UInt32 fs_nsect; + // 0x00A8 sectors per track + public UInt32 fs_spc; + // 0x00AC sectors per cylinder + // this comes from the disk driver partitioning + public UInt32 fs_ncyl; + // 0x00B0 cylinders in file system + // these fields can be computed from the others + public UInt32 fs_cpg; + // 0x00B4 cylinders per group + public UInt32 fs_ipg; + // 0x00B8 inodes per cylinder group + public UInt32 fs_fpg; + // 0x00BC blocks per group * fs_frag + // this data must be re-computed after crashes + // struct ufs_csum fs_cstotal; // cylinder summary information + public UInt32 fs_cstotal_ndir; + // 0x00C0 number of directories + public UInt32 fs_cstotal_nbfree; + // 0x00C4 number of free blocks + public UInt32 fs_cstotal_nifree; + // 0x00C8 number of free inodes + public UInt32 fs_cstotal_nffree; + // 0x00CC number of free frags + // these fields are cleared at mount time + public byte fs_fmod; + // 0x00D0 super block modified flag + public byte fs_clean; + // 0x00D1 file system is clean flag + public byte fs_ronly; + // 0x00D2 mounted read-only flag + public byte fs_flags; + // 0x00D3 + + #endregion common + + #region UFS1 + + public string fs_fsmnt_ufs1; + // 0x00D4, 512 bytes, name mounted on + public UInt32 fs_cgrotor_ufs1; + // 0x02D4 last cg searched + public byte[] fs_cs_ufs1; + // 0x02D8, 124 bytes, UInt32s, list of fs_cs info buffers + public UInt32 fs_maxcluster_ufs1; + // 0x0354 + public UInt32 fs_cpc_ufs1; + // 0x0358 cyl per cycle in postbl + public byte[] fs_opostbl_ufs1; + // 0x035C, 256 bytes, [16][8] matrix of UInt16s, old rotation block list head + + #endregion UFS1 + + #region UFS2 + + public string fs_fsmnt_ufs2; + // 0x00D4, 468 bytes, name mounted on + public string fs_volname_ufs2; + // 0x02A8, 32 bytes, volume name + public UInt64 fs_swuid_ufs2; + // 0x02C8 system-wide uid + public UInt32 fs_pad_ufs2; + // 0x02D0 due to alignment of fs_swuid + public UInt32 fs_cgrotor_ufs2; + // 0x02D4 last cg searched + public byte[] fs_ocsp_ufs2; + // 0x02D8, 112 bytes, UInt32s, list of fs_cs info buffers + public UInt32 fs_contigdirs_ufs2; + // 0x0348 # of contiguously allocated dirs + public UInt32 fs_csp_ufs2; + // 0x034C cg summary info buffer for fs_cs + public UInt32 fs_maxcluster_ufs2; + // 0x0350 + public UInt32 fs_active_ufs2; + // 0x0354 used by snapshots to track fs + public UInt32 fs_old_cpc_ufs2; + // 0x0358 cyl per cycle in postbl + public UInt32 fs_maxbsize_ufs2; + // 0x035C maximum blocking factor permitted + public byte[] fs_sparecon64_ufs2; + // 0x0360, 136 bytes, UInt64s, old rotation block list head + public UInt64 fs_sblockloc_ufs2; + // 0x03E8 byte offset of standard superblock + //cylinder summary information*/ + public UInt64 fs_cstotal_ndir_ufs2; + // 0x03F0 number of directories + public UInt64 fs_cstotal_nbfree_ufs2; + // 0x03F8 number of free blocks + public UInt64 fs_cstotal_nifree_ufs2; + // 0x0400 number of free inodes + public UInt64 fs_cstotal_nffree_ufs2; + // 0x0408 number of free frags + public UInt64 fs_cstotal_numclusters_ufs2; + // 0x0410 number of free clusters + public UInt64 fs_cstotal_spare0_ufs2; + // 0x0418 future expansion + public UInt64 fs_cstotal_spare1_ufs2; + // 0x0420 future expansion + public UInt64 fs_cstotal_spare2_ufs2; + // 0x0428 future expansion + public UInt32 fs_time_sec_ufs2; + // 0x0430 last time written + public UInt32 fs_time_usec_ufs2; + // 0x0434 last time written + public UInt64 fs_size_ufs2; + // 0x0438 number of blocks in fs + public UInt64 fs_dsize_ufs2; + // 0x0440 number of data blocks in fs + public UInt64 fs_csaddr_ufs2; + // 0x0448 blk addr of cyl grp summary area + public UInt64 fs_pendingblocks_ufs2; + // 0x0450 blocks in process of being freed + public UInt32 fs_pendinginodes_ufs2; + // 0x0458 inodes in process of being freed + + #endregion UFS2 + + #region Sun + + public byte[] fs_sparecon_sun; + // 0x045C, 212 bytes, reserved for future constants + public UInt32 fs_reclaim_sun; + // 0x0530 + public UInt32 fs_sparecon2_sun; + // 0x0534 + public UInt32 fs_state_t_sun; + // 0x0538 file system state time stamp + public UInt32 fs_qbmask0_sun; + // 0x053C ~usb_bmask + public UInt32 fs_qbmask1_sun; + // 0x0540 ~usb_bmask + public UInt32 fs_qfmask0_sun; + // 0x0544 ~usb_fmask + public UInt32 fs_qfmask1_sun; + // 0x0548 ~usb_fmask + + #endregion Sun + + #region Sunx86 + + public byte[] fs_sparecon_sun86; + // 0x045C, 212 bytes, reserved for future constants + public UInt32 fs_reclaim_sun86; + // 0x0530 + public UInt32 fs_sparecon2_sun86; + // 0x0534 + public UInt32 fs_npsect_sun86; + // 0x0538 # sectors/track including spares + public UInt32 fs_qbmask0_sun86; + // 0x053C ~usb_bmask + public UInt32 fs_qbmask1_sun86; + // 0x0540 ~usb_bmask + public UInt32 fs_qfmask0_sun86; + // 0x0544 ~usb_fmask + public UInt32 fs_qfmask1_sun86; + // 0x0548 ~usb_fmask + + #endregion Sunx86 + + #region 44BSD + + public byte[] fs_sparecon_44bsd; + // 0x045C, 200 bytes + public UInt32 fs_contigsumsize_44bsd; + // 0x0524 size of cluster summary array + public UInt32 fs_maxsymlinklen_44bsd; + // 0x0528 max length of an internal symlink + public UInt32 fs_inodefmt_44bsd; + // 0x052C format of on-disk inodes + public UInt32 fs_maxfilesize0_44bsd; + // 0x0530 max representable file size + public UInt32 fs_maxfilesize1_44bsd; + // 0x0534 max representable file size + public UInt32 fs_qbmask0_44bsd; + // 0x0538 ~usb_bmask + public UInt32 fs_qbmask1_44bsd; + // 0x053C ~usb_bmask + public UInt32 fs_qfmask0_44bsd; + // 0x0540 ~usb_fmask + public UInt32 fs_qfmask1_44bsd; + // 0x0544 ~usb_fmask + public UInt32 fs_state_t_44bsd; + // 0x0548 file system state time stamp + + #endregion 44BSD + + public UInt32 fs_postblformat; + // 0x054C format of positional layout tables + public UInt32 fs_nrpos; + // 0x0550 number of rotational positions + public UInt32 fs_postbloff; + // 0x0554 (__s16) rotation block list head + public UInt32 fs_rotbloff; + // 0x0558 (__u8) blocks for each rotation + public UInt32 fs_magic; + // 0x055C magic number + public byte fs_space; + // 0x0560 list of blocks for each rotation + // 0x0561 + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/HPFS.cs b/FileSystemIDandChk/Plugins/HPFS.cs index 16ccd46e..cad7a364 100644 --- a/FileSystemIDandChk/Plugins/HPFS.cs +++ b/FileSystemIDandChk/Plugins/HPFS.cs @@ -1,44 +1,42 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class HPFS : Plugin - { - public HPFS(PluginBase Core) + class HPFS : Plugin + { + public HPFS(PluginBase Core) { - base.Name = "OS/2 High Performance File System"; - base.PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); + Name = "OS/2 High Performance File System"; + PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - UInt32 magic1, magic2; + { + UInt32 magic1, magic2; byte[] hpfs_sb_sector = imagePlugin.ReadSector(16 + partitionOffset); // Seek to superblock, on logical sector 16 magic1 = BitConverter.ToUInt32(hpfs_sb_sector, 0x000); magic2 = BitConverter.ToUInt32(hpfs_sb_sector, 0x004); - if(magic1 == 0xF995E849 && magic2 == 0xFA53E9C5) - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + if (magic1 == 0xF995E849 && magic2 == 0xFA53E9C5) + return true; + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - HPFS_BIOSParameterBlock hpfs_bpb = new HPFS_BIOSParameterBlock(); - HPFS_SuperBlock hpfs_sb = new HPFS_SuperBlock(); - HPFS_SpareBlock hpfs_sp = new HPFS_SpareBlock(); + HPFS_BIOSParameterBlock hpfs_bpb = new HPFS_BIOSParameterBlock(); + HPFS_SuperBlock hpfs_sb = new HPFS_SuperBlock(); + HPFS_SpareBlock hpfs_sp = new HPFS_SpareBlock(); - byte[] oem_name = new byte[8]; - byte[] volume_name = new byte[11]; + byte[] oem_name = new byte[8]; + byte[] volume_name = new byte[11]; byte[] hpfs_bpb_sector = imagePlugin.ReadSector(0 + partitionOffset); // Seek to BIOS parameter block, on logical sector 0 byte[] hpfs_sb_sector = imagePlugin.ReadSector(16 + partitionOffset); // Seek to superblock, on logical sector 16 @@ -47,7 +45,7 @@ namespace FileSystemIDandChk.Plugins hpfs_bpb.jmp1 = hpfs_bpb_sector[0x000]; hpfs_bpb.jmp2 = BitConverter.ToUInt16(hpfs_bpb_sector, 0x001); Array.Copy(hpfs_bpb_sector, 0x003, oem_name, 0, 8); - hpfs_bpb.OEMName = StringHandlers.CToString(oem_name); + hpfs_bpb.OEMName = StringHandlers.CToString(oem_name); hpfs_bpb.bps = BitConverter.ToUInt16(hpfs_bpb_sector, 0x00B); hpfs_bpb.spc = hpfs_bpb_sector[0x00D]; hpfs_bpb.rsectors = BitConverter.ToUInt16(hpfs_bpb_sector, 0x00E); @@ -65,11 +63,11 @@ namespace FileSystemIDandChk.Plugins hpfs_bpb.signature = hpfs_bpb_sector[0x02A]; hpfs_bpb.serial_no = BitConverter.ToUInt32(hpfs_bpb_sector, 0x02B); Array.Copy(hpfs_bpb_sector, 0x02F, volume_name, 0, 11); - hpfs_bpb.volume_label = StringHandlers.CToString(volume_name); + hpfs_bpb.volume_label = StringHandlers.CToString(volume_name); Array.Copy(hpfs_bpb_sector, 0x03A, oem_name, 0, 8); - hpfs_bpb.fs_type = StringHandlers.CToString(oem_name); + hpfs_bpb.fs_type = StringHandlers.CToString(oem_name); - hpfs_sb.magic1 = BitConverter.ToUInt32(hpfs_sb_sector, 0x000); + hpfs_sb.magic1 = BitConverter.ToUInt32(hpfs_sb_sector, 0x000); hpfs_sb.magic2 = BitConverter.ToUInt32(hpfs_sb_sector, 0x004); hpfs_sb.version = hpfs_sb_sector[0x008]; hpfs_sb.func_version = hpfs_sb_sector[0x009]; @@ -108,176 +106,234 @@ namespace FileSystemIDandChk.Plugins hpfs_sp.sb_crc32 = BitConverter.ToUInt32(hpfs_sp_sector, 0x028); hpfs_sp.sp_crc32 = BitConverter.ToUInt32(hpfs_sp_sector, 0x02C); - if(hpfs_bpb.fs_type != "HPFS " || - hpfs_sb.magic1 != 0xF995E849 || hpfs_sb.magic2 != 0xFA53E9C5 || - hpfs_sp.magic1 != 0xF9911849 || hpfs_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 \")", hpfs_bpb.fs_type).AppendLine(); - sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfs_sb.magic1).AppendLine(); - sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfs_sb.magic2).AppendLine(); - sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", hpfs_sp.magic1).AppendLine(); - sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", hpfs_sp.magic2).AppendLine(); - } + if (hpfs_bpb.fs_type != "HPFS " || + hpfs_sb.magic1 != 0xF995E849 || hpfs_sb.magic2 != 0xFA53E9C5 || + hpfs_sp.magic1 != 0xF9911849 || hpfs_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 \")", hpfs_bpb.fs_type).AppendLine(); + sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfs_sb.magic1).AppendLine(); + sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfs_sb.magic2).AppendLine(); + sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", hpfs_sp.magic1).AppendLine(); + sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", hpfs_sp.magic2).AppendLine(); + } - sb.AppendFormat("OEM name: {0}", hpfs_bpb.OEMName).AppendLine(); - sb.AppendFormat("{0} bytes per sector", hpfs_bpb.bps).AppendLine(); - sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine(); + sb.AppendFormat("OEM name: {0}", hpfs_bpb.OEMName).AppendLine(); + sb.AppendFormat("{0} bytes per sector", hpfs_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}", hpfs_bpb.media).AppendLine(); + sb.AppendFormat("Media descriptor: 0x{0:X2}", hpfs_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", hpfs_bpb.hsectors).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}", hpfs_bpb.drive_no).AppendLine(); + sb.AppendFormat("{0} sectors hidden before BPB", hpfs_bpb.hsectors).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}", hpfs_bpb.drive_no).AppendLine(); // sb.AppendFormat("NT Flags: 0x{0:X2}", hpfs_bpb.nt_flags).AppendLine(); - sb.AppendFormat("Signature: 0x{0:X2}", hpfs_bpb.signature).AppendLine(); - sb.AppendFormat("Serial number: 0x{0:X8}", hpfs_bpb.serial_no).AppendLine(); - sb.AppendFormat("Volume label: {0}", hpfs_bpb.volume_label).AppendLine(); + sb.AppendFormat("Signature: 0x{0:X2}", hpfs_bpb.signature).AppendLine(); + sb.AppendFormat("Serial number: 0x{0:X8}", hpfs_bpb.serial_no).AppendLine(); + sb.AppendFormat("Volume label: {0}", hpfs_bpb.volume_label).AppendLine(); // sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine(); - DateTime last_chk = DateHandlers.UNIXToDateTime(hpfs_sb.last_chkdsk); - DateTime last_optim = DateHandlers.UNIXToDateTime(hpfs_sb.last_optim); + DateTime last_chk = DateHandlers.UNIXToDateTime(hpfs_sb.last_chkdsk); + DateTime last_optim = DateHandlers.UNIXToDateTime(hpfs_sb.last_optim); - sb.AppendFormat("HPFS version: {0}", hpfs_sb.version).AppendLine(); - sb.AppendFormat("Functional version: {0}", hpfs_sb.func_version).AppendLine(); - sb.AppendFormat("Sector of root directory FNode: {0}", hpfs_sb.root_fnode).AppendLine(); + sb.AppendFormat("HPFS version: {0}", hpfs_sb.version).AppendLine(); + sb.AppendFormat("Functional version: {0}", hpfs_sb.func_version).AppendLine(); + sb.AppendFormat("Sector of root directory FNode: {0}", hpfs_sb.root_fnode).AppendLine(); // sb.AppendFormat("{0} sectors on volume", hpfs_sb.sectors).AppendLine(); - sb.AppendFormat("{0} sectors are marked bad", hpfs_sb.badblocks).AppendLine(); - sb.AppendFormat("Sector of free space bitmaps: {0}", hpfs_sb.bitmap_lsn).AppendLine(); - sb.AppendFormat("Sector of bad blocks list: {0}", hpfs_sb.badblock_lsn).AppendLine(); - sb.AppendFormat("Date of last integrity check: {0}", last_chk).AppendLine(); - if(hpfs_sb.last_optim>0) - sb.AppendFormat("Date of last optimization {0}", last_optim).AppendLine(); - else - sb.AppendLine("Filesystem has never been optimized"); - sb.AppendFormat("Directory band has {0} sectors", hpfs_sb.dband_sectors).AppendLine(); - sb.AppendFormat("Directory band starts at sector {0}", hpfs_sb.dband_start).AppendLine(); - sb.AppendFormat("Directory band ends at sector {0}", hpfs_sb.dband_last).AppendLine(); - sb.AppendFormat("Sector of directory band bitmap: {0}", hpfs_sb.dband_bitmap).AppendLine(); - sb.AppendFormat("Sector of ACL directory: {0}", hpfs_sb.acl_start).AppendLine(); + sb.AppendFormat("{0} sectors are marked bad", hpfs_sb.badblocks).AppendLine(); + sb.AppendFormat("Sector of free space bitmaps: {0}", hpfs_sb.bitmap_lsn).AppendLine(); + sb.AppendFormat("Sector of bad blocks list: {0}", hpfs_sb.badblock_lsn).AppendLine(); + sb.AppendFormat("Date of last integrity check: {0}", last_chk).AppendLine(); + if (hpfs_sb.last_optim > 0) + sb.AppendFormat("Date of last optimization {0}", last_optim).AppendLine(); + else + sb.AppendLine("Filesystem has never been optimized"); + sb.AppendFormat("Directory band has {0} sectors", hpfs_sb.dband_sectors).AppendLine(); + sb.AppendFormat("Directory band starts at sector {0}", hpfs_sb.dband_start).AppendLine(); + sb.AppendFormat("Directory band ends at sector {0}", hpfs_sb.dband_last).AppendLine(); + sb.AppendFormat("Sector of directory band bitmap: {0}", hpfs_sb.dband_bitmap).AppendLine(); + sb.AppendFormat("Sector of ACL directory: {0}", hpfs_sb.acl_start).AppendLine(); - sb.AppendFormat("Sector of Hotfix directory: {0}", hpfs_sp.hotfix_start).AppendLine(); - sb.AppendFormat("{0} used Hotfix entries", hpfs_sp.hotfix_used).AppendLine(); - sb.AppendFormat("{0} total Hotfix entries", hpfs_sp.hotfix_entries).AppendLine(); - sb.AppendFormat("{0} free spare DNodes", hpfs_sp.spare_dnodes_free).AppendLine(); - sb.AppendFormat("{0} total spare DNodes", hpfs_sp.spare_dnodes).AppendLine(); - sb.AppendFormat("Sector of codepage directory: {0}", hpfs_sp.codepage_lsn).AppendLine(); - sb.AppendFormat("{0} codepages used in the volume", hpfs_sp.codepages).AppendLine(); - sb.AppendFormat("SuperBlock CRC32: {0:X8}", hpfs_sp.sb_crc32).AppendLine(); - sb.AppendFormat("SpareBlock CRC32: {0:X8}", hpfs_sp.sp_crc32).AppendLine(); + sb.AppendFormat("Sector of Hotfix directory: {0}", hpfs_sp.hotfix_start).AppendLine(); + sb.AppendFormat("{0} used Hotfix entries", hpfs_sp.hotfix_used).AppendLine(); + sb.AppendFormat("{0} total Hotfix entries", hpfs_sp.hotfix_entries).AppendLine(); + sb.AppendFormat("{0} free spare DNodes", hpfs_sp.spare_dnodes_free).AppendLine(); + sb.AppendFormat("{0} total spare DNodes", hpfs_sp.spare_dnodes).AppendLine(); + sb.AppendFormat("Sector of codepage directory: {0}", hpfs_sp.codepage_lsn).AppendLine(); + sb.AppendFormat("{0} codepages used in the volume", hpfs_sp.codepages).AppendLine(); + sb.AppendFormat("SuperBlock CRC32: {0:X8}", hpfs_sp.sb_crc32).AppendLine(); + sb.AppendFormat("SpareBlock CRC32: {0:X8}", hpfs_sp.sp_crc32).AppendLine(); - sb.AppendLine("Flags:"); - if((hpfs_sp.flags1 & 0x01) == 0x01) - sb.AppendLine("Filesystem is dirty."); - else - sb.AppendLine("Filesystem is clean."); - if((hpfs_sp.flags1 & 0x02) == 0x02) - sb.AppendLine("Spare directory blocks are in use"); - if((hpfs_sp.flags1 & 0x04) == 0x04) - sb.AppendLine("Hotfixes are in use"); - if((hpfs_sp.flags1 & 0x08) == 0x08) - sb.AppendLine("Disk contains bad sectors"); - if((hpfs_sp.flags1 & 0x10) == 0x10) - sb.AppendLine("Disk has a bad bitmap"); - if((hpfs_sp.flags1 & 0x20) == 0x20) - sb.AppendLine("Filesystem was formatted fast"); - if((hpfs_sp.flags1 & 0x40) == 0x40) - sb.AppendLine("Unknown flag 0x40 on flags1 is active"); - if((hpfs_sp.flags1 & 0x80) == 0x80) - sb.AppendLine("Filesystem has been mounted by an old IFS"); - if((hpfs_sp.flags2 & 0x01) == 0x01) - sb.AppendLine("Install DASD limits"); - if((hpfs_sp.flags2 & 0x02) == 0x02) - sb.AppendLine("Resync DASD limits"); - if((hpfs_sp.flags2 & 0x04) == 0x04) - sb.AppendLine("DASD limits are operational"); - if((hpfs_sp.flags2 & 0x08) == 0x08) - sb.AppendLine("Multimedia is active"); - if((hpfs_sp.flags2 & 0x10) == 0x10) - sb.AppendLine("DCE ACLs are active"); - if((hpfs_sp.flags2 & 0x20) == 0x20) - sb.AppendLine("DASD limits are dirty"); - if((hpfs_sp.flags2 & 0x40) == 0x40) - sb.AppendLine("Unknown flag 0x40 on flags2 is active"); - if((hpfs_sp.flags2 & 0x80) == 0x80) - sb.AppendLine("Unknown flag 0x80 on flags2 is active"); + sb.AppendLine("Flags:"); + if ((hpfs_sp.flags1 & 0x01) == 0x01) + sb.AppendLine("Filesystem is dirty."); + else + sb.AppendLine("Filesystem is clean."); + if ((hpfs_sp.flags1 & 0x02) == 0x02) + sb.AppendLine("Spare directory blocks are in use"); + if ((hpfs_sp.flags1 & 0x04) == 0x04) + sb.AppendLine("Hotfixes are in use"); + if ((hpfs_sp.flags1 & 0x08) == 0x08) + sb.AppendLine("Disk contains bad sectors"); + if ((hpfs_sp.flags1 & 0x10) == 0x10) + sb.AppendLine("Disk has a bad bitmap"); + if ((hpfs_sp.flags1 & 0x20) == 0x20) + sb.AppendLine("Filesystem was formatted fast"); + if ((hpfs_sp.flags1 & 0x40) == 0x40) + sb.AppendLine("Unknown flag 0x40 on flags1 is active"); + if ((hpfs_sp.flags1 & 0x80) == 0x80) + sb.AppendLine("Filesystem has been mounted by an old IFS"); + if ((hpfs_sp.flags2 & 0x01) == 0x01) + sb.AppendLine("Install DASD limits"); + if ((hpfs_sp.flags2 & 0x02) == 0x02) + sb.AppendLine("Resync DASD limits"); + if ((hpfs_sp.flags2 & 0x04) == 0x04) + sb.AppendLine("DASD limits are operational"); + if ((hpfs_sp.flags2 & 0x08) == 0x08) + sb.AppendLine("Multimedia is active"); + if ((hpfs_sp.flags2 & 0x10) == 0x10) + sb.AppendLine("DCE ACLs are active"); + if ((hpfs_sp.flags2 & 0x20) == 0x20) + sb.AppendLine("DASD limits are dirty"); + if ((hpfs_sp.flags2 & 0x40) == 0x40) + sb.AppendLine("Unknown flag 0x40 on flags2 is active"); + if ((hpfs_sp.flags2 & 0x80) == 0x80) + sb.AppendLine("Unknown flag 0x80 on flags2 is active"); - information = sb.ToString(); - } - - private struct HPFS_BIOSParameterBlock // Sector 0 - { - public byte jmp1; // 0x000, Jump to boot code - public UInt16 jmp2; // 0x001, ...; - public string OEMName; // 0x003, OEM Name, 8 bytes, space-padded - public UInt16 bps; // 0x00B, Bytes per sector - public byte spc; // 0x00D, Sectors per cluster - public UInt16 rsectors; // 0x00E, Reserved sectors between BPB and... does it have sense in HPFS? - public byte fats_no; // 0x010, Number of FATs... seriously? - public UInt16 root_ent; // 0x011, Number of entries on root directory... ok - public UInt16 sectors; // 0x013, Sectors in volume... doubt it - public byte media; // 0x015, Media descriptor - public UInt16 spfat; // 0x016, Sectors per FAT... again - public UInt16 sptrk; // 0x018, Sectors per track... you're kidding - public UInt16 heads; // 0x01A, Heads... stop! - public UInt32 hsectors; // 0x01C, Hidden sectors before BPB - public UInt32 big_sectors; // 0x024, Sectors in volume if > 65535... - public byte drive_no; // 0x028, Drive number - public byte nt_flags; // 0x029, Volume flags? - public byte signature; // 0x02A, EPB signature, 0x29 - public UInt32 serial_no; // 0x02B, Volume serial number - public string volume_label; // 0x02F, Volume label, 11 bytes, space-padded - public string fs_type; // 0x03A, Filesystem type, 8 bytes, space-padded ("HPFS ") - } - - private struct HPFS_SuperBlock // Sector 16 - { - public UInt32 magic1; // 0x000, 0xF995E849 - public UInt32 magic2; // 0x004, 0xFA53E9C5 - public byte version; // 0x008, HPFS version - public byte func_version; // 0x009, 2 if <= 4 GiB, 3 if > 4 GiB - public UInt16 dummy; // 0x00A, Alignment - public UInt32 root_fnode; // 0x00C, LSN pointer to root fnode - public UInt32 sectors; // 0x010, Sectors on volume - public UInt32 badblocks; // 0x014, Bad blocks on volume - public UInt32 bitmap_lsn; // 0x018, LSN pointer to volume bitmap - public UInt32 zero1; // 0x01C, 0 - public UInt32 badblock_lsn; // 0x020, LSN pointer to badblock directory - public UInt32 zero2; // 0x024, 0 - public Int32 last_chkdsk; // 0x028, Time of last CHKDSK - public Int32 last_optim; // 0x02C, Time of last optimization - public UInt32 dband_sectors; // 0x030, Sectors of dir band - public UInt32 dband_start; // 0x034, Start sector of dir band - public UInt32 dband_last; // 0x038, Last sector of dir band - public UInt32 dband_bitmap; // 0x03C, LSN of free space bitmap - public UInt64 zero3; // 0x040, Can be used for volume name (32 bytes) - public UInt64 zero4; // 0x048, ... - public UInt64 zero5; // 0x04C, ... - public UInt64 zero6; // 0x050, ...; - public UInt32 acl_start; // 0x058, LSN pointer to ACLs (only HPFS386) - } - - private struct HPFS_SpareBlock // Sector 17 - { - public UInt32 magic1; // 0x000, 0xF9911849 - public UInt32 magic2; // 0x004, 0xFA5229C5 - public byte flags1; // 0x008, HPFS flags - public byte flags2; // 0x009, HPFS386 flags - public UInt16 dummy; // 0x00A, Alignment - public UInt32 hotfix_start; // 0x00C, LSN of hotfix directory - public UInt32 hotfix_used; // 0x010, Used hotfixes - public UInt32 hotfix_entries; // 0x014, Total hotfixes available - public UInt32 spare_dnodes_free; // 0x018, Unused spare dnodes - public UInt32 spare_dnodes; // 0x01C, Length of spare dnodes list - public UInt32 codepage_lsn; // 0x020, LSN of codepage directory - public UInt32 codepages; // 0x024, Number of codepages used - public UInt32 sb_crc32; // 0x028, SuperBlock CRC32 (only HPFS386) - public UInt32 sp_crc32; // 0x02C, SpareBlock CRC32 (only HPFS386) - } - } + information = sb.ToString(); + } + + struct HPFS_BIOSParameterBlock // Sector 0 + { + public byte jmp1; + // 0x000, Jump to boot code + public UInt16 jmp2; + // 0x001, ...; + public string OEMName; + // 0x003, OEM Name, 8 bytes, space-padded + public UInt16 bps; + // 0x00B, Bytes per sector + public byte spc; + // 0x00D, Sectors per cluster + public UInt16 rsectors; + // 0x00E, Reserved sectors between BPB and... does it have sense in HPFS? + public byte fats_no; + // 0x010, Number of FATs... seriously? + public UInt16 root_ent; + // 0x011, Number of entries on root directory... ok + public UInt16 sectors; + // 0x013, Sectors in volume... doubt it + public byte media; + // 0x015, Media descriptor + public UInt16 spfat; + // 0x016, Sectors per FAT... again + public UInt16 sptrk; + // 0x018, Sectors per track... you're kidding + public UInt16 heads; + // 0x01A, Heads... stop! + public UInt32 hsectors; + // 0x01C, Hidden sectors before BPB + public UInt32 big_sectors; + // 0x024, Sectors in volume if > 65535... + public byte drive_no; + // 0x028, Drive number + public byte nt_flags; + // 0x029, Volume flags? + public byte signature; + // 0x02A, EPB signature, 0x29 + public UInt32 serial_no; + // 0x02B, Volume serial number + public string volume_label; + // 0x02F, Volume label, 11 bytes, space-padded + public string fs_type; + // 0x03A, Filesystem type, 8 bytes, space-padded ("HPFS ") + } + + struct HPFS_SuperBlock // Sector 16 + { + public UInt32 magic1; + // 0x000, 0xF995E849 + public UInt32 magic2; + // 0x004, 0xFA53E9C5 + public byte version; + // 0x008, HPFS version + public byte func_version; + // 0x009, 2 if <= 4 GiB, 3 if > 4 GiB + public UInt16 dummy; + // 0x00A, Alignment + public UInt32 root_fnode; + // 0x00C, LSN pointer to root fnode + public UInt32 sectors; + // 0x010, Sectors on volume + public UInt32 badblocks; + // 0x014, Bad blocks on volume + public UInt32 bitmap_lsn; + // 0x018, LSN pointer to volume bitmap + public UInt32 zero1; + // 0x01C, 0 + public UInt32 badblock_lsn; + // 0x020, LSN pointer to badblock directory + public UInt32 zero2; + // 0x024, 0 + public Int32 last_chkdsk; + // 0x028, Time of last CHKDSK + public Int32 last_optim; + // 0x02C, Time of last optimization + public UInt32 dband_sectors; + // 0x030, Sectors of dir band + public UInt32 dband_start; + // 0x034, Start sector of dir band + public UInt32 dband_last; + // 0x038, Last sector of dir band + public UInt32 dband_bitmap; + // 0x03C, LSN of free space bitmap + public UInt64 zero3; + // 0x040, Can be used for volume name (32 bytes) + public UInt64 zero4; + // 0x048, ... + public UInt64 zero5; + // 0x04C, ... + public UInt64 zero6; + // 0x050, ...; + public UInt32 acl_start; + // 0x058, LSN pointer to ACLs (only HPFS386) + } + + struct HPFS_SpareBlock // Sector 17 + { + public UInt32 magic1; + // 0x000, 0xF9911849 + public UInt32 magic2; + // 0x004, 0xFA5229C5 + public byte flags1; + // 0x008, HPFS flags + public byte flags2; + // 0x009, HPFS386 flags + public UInt16 dummy; + // 0x00A, Alignment + public UInt32 hotfix_start; + // 0x00C, LSN of hotfix directory + public UInt32 hotfix_used; + // 0x010, Used hotfixes + public UInt32 hotfix_entries; + // 0x014, Total hotfixes available + public UInt32 spare_dnodes_free; + // 0x018, Unused spare dnodes + public UInt32 spare_dnodes; + // 0x01C, Length of spare dnodes list + public UInt32 codepage_lsn; + // 0x020, LSN of codepage directory + public UInt32 codepages; + // 0x024, Number of codepages used + public UInt32 sb_crc32; + // 0x028, SuperBlock CRC32 (only HPFS386) + public UInt32 sp_crc32; + // 0x02C, SpareBlock CRC32 (only HPFS386) + } + } } diff --git a/FileSystemIDandChk/Plugins/ISO9660.cs b/FileSystemIDandChk/Plugins/ISO9660.cs index e4e75528..b9a0d93a 100644 --- a/FileSystemIDandChk/Plugins/ISO9660.cs +++ b/FileSystemIDandChk/Plugins/ISO9660.cs @@ -1,7 +1,6 @@ using System; -using System.IO; -using System.Text; using System.Globalization; +using System.Text; using FileSystemIDandChk; // This is coded following ECMA-119. @@ -13,16 +12,16 @@ namespace FileSystemIDandChk.Plugins { class ISO9660Plugin : Plugin { - private static bool alreadyLaunched; + static bool alreadyLaunched; public ISO9660Plugin(PluginBase Core) { - base.Name = "ISO9660 Filesystem"; - base.PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); + Name = "ISO9660 Filesystem"; + PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); alreadyLaunched = false; } - private struct DecodedVolumeDescriptor + struct DecodedVolumeDescriptor { public string SystemIdentifier; public string VolumeIdentifier; @@ -41,12 +40,11 @@ namespace FileSystemIDandChk.Plugins public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) { - if(alreadyLaunched) - return false; - else - alreadyLaunched = true; + if (alreadyLaunched) + return false; + alreadyLaunched = true; - byte VDType; + byte VDType; // ISO9660 is designed for 2048 bytes/sector devices if (imagePlugin.GetSectorSize() < 2048) @@ -60,19 +58,16 @@ namespace FileSystemIDandChk.Plugins byte[] vd_sector = imagePlugin.ReadSector(16 + partitionOffset); VDType = vd_sector[0]; - byte[] VDMagic = new byte[5]; + byte[] VDMagic = new byte[5]; - // Wrong, VDs can be any order! + // Wrong, VDs can be any order! if (VDType == 255) // Supposedly we are in the PVD. return false; Array.Copy(vd_sector, 0x001, VDMagic, 0, 5); - if (Encoding.ASCII.GetString(VDMagic) != "CD001") // Recognized, it is an ISO9660, now check for rest of data. - return false; - - return true; - } + return Encoding.ASCII.GetString(VDMagic) == "CD001"; + } public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) { @@ -246,10 +241,7 @@ namespace FileSystemIDandChk.Plugins if (Encoding.ASCII.GetString(SUSPMagic) == "SP") { Array.Copy(root_dir, 0x29, RRMagic, 0, 2); - if (Encoding.ASCII.GetString(RRMagic) == "RR") - { - RockRidge = true; - } + RockRidge |= Encoding.ASCII.GetString(RRMagic) == "RR"; } #region SEGA IP.BIN Read and decoding @@ -345,7 +337,7 @@ namespace FileSystemIDandChk.Plugins Array.Copy(ipbin_sector, 0x1B0, spare_space7, 0, 64); // Inside here should be modem information, but I need to get a modem-enabled game Array.Copy(ipbin_sector, 0x1F0, region_codes, 0, 16); // Region codes, space-filled // Decoding all data - DateTime ipbindate = new DateTime(); + DateTime ipbindate; CultureInfo provider = CultureInfo.InvariantCulture; ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "MMddyyyy", provider); @@ -377,7 +369,7 @@ namespace FileSystemIDandChk.Plugins IPBinInformation.AppendFormat("System program load size: {0} bytes", BitConverter.ToInt32(sp_loadsize, 0)).AppendLine(); IPBinInformation.AppendFormat("System program entry address: 0x{0}", BitConverter.ToInt32(sp_entry_address, 0).ToString("X")).AppendLine(); IPBinInformation.AppendFormat("System program work RAM: {0} bytes", BitConverter.ToInt32(sp_work_ram_size, 0)).AppendLine(); - IPBinInformation.AppendFormat("Release date: {0}", ipbindate.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); IPBinInformation.AppendFormat("Release date (other format): {0}", Encoding.ASCII.GetString(release_date2)).AppendLine(); IPBinInformation.AppendFormat("Hardware ID: {0}", Encoding.ASCII.GetString(hardware_id)).AppendLine(); IPBinInformation.AppendFormat("Developer code: {0}", Encoding.ASCII.GetString(developer_code)).AppendLine(); @@ -425,7 +417,7 @@ namespace FileSystemIDandChk.Plugins case ' ': break; default: - IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); break; } } @@ -446,7 +438,7 @@ namespace FileSystemIDandChk.Plugins case ' ': break; default: - IPBinInformation.AppendFormat("Game supports unknown region {0}.", region.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); break; } } @@ -488,13 +480,13 @@ namespace FileSystemIDandChk.Plugins Array.Copy(ipbin_sector, 0x050, peripherals, 0, 16); // Supported peripherals, see above Array.Copy(ipbin_sector, 0x060, product_name, 0, 112); // Game name, space-filled // Decoding all data - DateTime ipbindate = new DateTime(); + DateTime ipbindate; CultureInfo provider = CultureInfo.InvariantCulture; ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "yyyyMMdd", provider); IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(product_name)).AppendLine(); IPBinInformation.AppendFormat("Product number: {0}", Encoding.ASCII.GetString(product_no)).AppendLine(); IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(product_version)).AppendLine(); - IPBinInformation.AppendFormat("Release date: {0}", ipbindate.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); IPBinInformation.AppendFormat("Disc number {0} of {1}", Encoding.ASCII.GetString(disc_no), Encoding.ASCII.GetString(disc_total_nos)).AppendLine(); IPBinInformation.AppendFormat("Peripherals:").AppendLine(); @@ -523,7 +515,7 @@ namespace FileSystemIDandChk.Plugins case ' ': break; default: - IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); break; } } @@ -547,7 +539,7 @@ namespace FileSystemIDandChk.Plugins case ' ': break; default: - IPBinInformation.AppendFormat("Game supports unknown region {0}.", region.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); break; } } @@ -599,7 +591,7 @@ namespace FileSystemIDandChk.Plugins Array.Copy(ipbin_sector, 0x068, producer, 0, 16); // Game producer, space-filled Array.Copy(ipbin_sector, 0x078, product_name, 0, 128); // Game name, space-filled // Decoding all data - DateTime ipbindate = new DateTime(); + DateTime ipbindate; CultureInfo provider = CultureInfo.InvariantCulture; ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "yyyyMMdd", provider); IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(product_name)).AppendLine(); @@ -607,7 +599,7 @@ namespace FileSystemIDandChk.Plugins IPBinInformation.AppendFormat("Producer: {0}", Encoding.ASCII.GetString(producer)).AppendLine(); IPBinInformation.AppendFormat("Disc media: {0}", Encoding.ASCII.GetString(dreamcast_media)).AppendLine(); IPBinInformation.AppendFormat("Disc number {0} of {1}", Encoding.ASCII.GetString(disc_no), Encoding.ASCII.GetString(disc_total_nos)).AppendLine(); - IPBinInformation.AppendFormat("Release date: {0}", ipbindate.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); switch (Encoding.ASCII.GetString(boot_filename)) { case "1ST_READ.BIN": @@ -637,7 +629,7 @@ namespace FileSystemIDandChk.Plugins case ' ': break; default: - IPBinInformation.AppendFormat("Game supports unknown region {0}.", region.ToString()).AppendLine(); + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); break; } } @@ -728,17 +720,17 @@ namespace FileSystemIDandChk.Plugins ISOMetadata.AppendFormat("Publisher identifier: {0}", decodedVD.PublisherIdentifier).AppendLine(); ISOMetadata.AppendFormat("Data preparer identifier: {0}", decodedVD.DataPreparerIdentifier).AppendLine(); ISOMetadata.AppendFormat("Application identifier: {0}", decodedVD.ApplicationIdentifier).AppendLine(); - ISOMetadata.AppendFormat("Volume creation date: {0}", decodedVD.CreationTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume creation date: {0}", decodedVD.CreationTime).AppendLine(); if (decodedVD.HasModificationTime) - ISOMetadata.AppendFormat("Volume modification date: {0}", decodedVD.ModificationTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume modification date: {0}", decodedVD.ModificationTime).AppendLine(); else ISOMetadata.AppendFormat("Volume has not been modified.").AppendLine(); if (decodedVD.HasExpirationTime) - ISOMetadata.AppendFormat("Volume expiration date: {0}", decodedVD.ExpirationTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume expiration date: {0}", decodedVD.ExpirationTime).AppendLine(); else ISOMetadata.AppendFormat("Volume does not expire.").AppendLine(); if (decodedVD.HasEffectiveTime) - ISOMetadata.AppendFormat("Volume effective date: {0}", decodedVD.EffectiveTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume effective date: {0}", decodedVD.EffectiveTime).AppendLine(); else ISOMetadata.AppendFormat("Volume has always been effective.").AppendLine(); @@ -753,17 +745,17 @@ namespace FileSystemIDandChk.Plugins ISOMetadata.AppendFormat("Publisher identifier: {0}", decodedJolietVD.PublisherIdentifier).AppendLine(); ISOMetadata.AppendFormat("Data preparer identifier: {0}", decodedJolietVD.DataPreparerIdentifier).AppendLine(); ISOMetadata.AppendFormat("Application identifier: {0}", decodedJolietVD.ApplicationIdentifier).AppendLine(); - ISOMetadata.AppendFormat("Volume creation date: {0}", decodedJolietVD.CreationTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume creation date: {0}", decodedJolietVD.CreationTime).AppendLine(); if (decodedJolietVD.HasModificationTime) - ISOMetadata.AppendFormat("Volume modification date: {0}", decodedJolietVD.ModificationTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume modification date: {0}", decodedJolietVD.ModificationTime).AppendLine(); else ISOMetadata.AppendFormat("Volume has not been modified.").AppendLine(); if (decodedJolietVD.HasExpirationTime) - ISOMetadata.AppendFormat("Volume expiration date: {0}", decodedJolietVD.ExpirationTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume expiration date: {0}", decodedJolietVD.ExpirationTime).AppendLine(); else ISOMetadata.AppendFormat("Volume does not expire.").AppendLine(); if (decodedJolietVD.HasEffectiveTime) - ISOMetadata.AppendFormat("Volume effective date: {0}", decodedJolietVD.EffectiveTime.ToString()).AppendLine(); + ISOMetadata.AppendFormat("Volume effective date: {0}", decodedJolietVD.EffectiveTime).AppendLine(); else ISOMetadata.AppendFormat("Volume has always been effective.").AppendLine(); } @@ -771,7 +763,7 @@ namespace FileSystemIDandChk.Plugins information = ISOMetadata.ToString(); } - private DecodedVolumeDescriptor DecodeJolietDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime) + static DecodedVolumeDescriptor DecodeJolietDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime) { DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor(); @@ -819,7 +811,7 @@ namespace FileSystemIDandChk.Plugins return decodedVD; } - private DecodedVolumeDescriptor DecodeVolumeDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime) + static DecodedVolumeDescriptor DecodeVolumeDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime) { DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor(); diff --git a/FileSystemIDandChk/Plugins/MinixFS.cs b/FileSystemIDandChk/Plugins/MinixFS.cs index 38234222..2b4fc63b 100644 --- a/FileSystemIDandChk/Plugins/MinixFS.cs +++ b/FileSystemIDandChk/Plugins/MinixFS.cs @@ -1,133 +1,132 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class MinixFS : Plugin - { - private const UInt16 MINIX_MAGIC = 0x137F; // Minix v1, 14 char filenames - private const UInt16 MINIX_MAGIC2 = 0x138F; // Minix v1, 30 char filenames - private const UInt16 MINIX2_MAGIC = 0x2468; // Minix v2, 14 char filenames - private const UInt16 MINIX2_MAGIC2 = 0x2478; // Minix v2, 30 char filenames - private const UInt16 MINIX3_MAGIC = 0x4D5A; // Minix v3, 60 char filenames + class MinixFS : Plugin + { + const UInt16 MINIX_MAGIC = 0x137F; + // Minix v1, 14 char filenames + const UInt16 MINIX_MAGIC2 = 0x138F; + // Minix v1, 30 char filenames + const UInt16 MINIX2_MAGIC = 0x2468; + // Minix v2, 14 char filenames + const UInt16 MINIX2_MAGIC2 = 0x2478; + // Minix v2, 30 char filenames + const UInt16 MINIX3_MAGIC = 0x4D5A; + // Minix v3, 60 char filenames + // Byteswapped + const UInt16 MINIX_CIGAM = 0x7F13; + // Minix v1, 14 char filenames + const UInt16 MINIX_CIGAM2 = 0x8F13; + // Minix v1, 30 char filenames + const UInt16 MINIX2_CIGAM = 0x6824; + // Minix v2, 14 char filenames + const UInt16 MINIX2_CIGAM2 = 0x7824; + // Minix v2, 30 char filenames + const UInt16 MINIX3_CIGAM = 0x5A4D; + // Minix v3, 60 char filenames - // Byteswapped - private const UInt16 MINIX_CIGAM = 0x7F13; // Minix v1, 14 char filenames - private const UInt16 MINIX_CIGAM2 = 0x8F13; // Minix v1, 30 char filenames - private const UInt16 MINIX2_CIGAM = 0x6824; // Minix v2, 14 char filenames - private const UInt16 MINIX2_CIGAM2 = 0x7824; // Minix v2, 30 char filenames - private const UInt16 MINIX3_CIGAM = 0x5A4D; // Minix v3, 60 char filenames - - public MinixFS(PluginBase Core) + public MinixFS(PluginBase Core) { - base.Name = "Minix Filesystem"; - base.PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); + Name = "Minix Filesystem"; + PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - UInt16 magic; + { + UInt16 magic; byte[] minix_sb_sector = imagePlugin.ReadSector(2 + partitionOffset); magic = BitConverter.ToUInt16(minix_sb_sector, 0x010); // Here should reside magic number on Minix V1 & V2 - if(magic == MINIX_MAGIC || magic == MINIX_MAGIC2 || magic == MINIX2_MAGIC || magic == MINIX2_MAGIC2 || - magic == MINIX_CIGAM || magic == MINIX_CIGAM2 || magic == MINIX2_CIGAM || magic == MINIX2_CIGAM2) - return true; - else - { - magic = BitConverter.ToUInt16(minix_sb_sector, 0x018); // Here should reside magic number on Minix V3 + if (magic == MINIX_MAGIC || magic == MINIX_MAGIC2 || magic == MINIX2_MAGIC || magic == MINIX2_MAGIC2 || + magic == MINIX_CIGAM || magic == MINIX_CIGAM2 || magic == MINIX2_CIGAM || magic == MINIX2_CIGAM2) + return true; + magic = BitConverter.ToUInt16(minix_sb_sector, 0x018); // Here should reside magic number on Minix V3 - if(magic == MINIX3_MAGIC || magic == MINIX3_CIGAM) - return true; - else - return false; - } - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + if (magic == MINIX3_MAGIC || magic == MINIX3_CIGAM) + return true; + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - bool littleendian = true; - bool minix3 = false; - int filenamesize = 0; - string minixVersion; - UInt16 magic; + bool minix3 = false; + int filenamesize; + string minixVersion; + UInt16 magic; byte[] minix_sb_sector = imagePlugin.ReadSector(2 + partitionOffset); magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x018); - if(magic == MINIX3_MAGIC || magic == MINIX3_CIGAM) - { - filenamesize = 60; - minixVersion = "Minix V3 filesystem"; - if(magic == MINIX3_CIGAM) - littleendian = false; - else - littleendian = true; + if (magic == MINIX3_MAGIC || magic == MINIX3_CIGAM) + { + filenamesize = 60; + minixVersion = "Minix V3 filesystem"; + BigEndianBitConverter.IsLittleEndian = magic != MINIX3_CIGAM; - minix3 = true; - } - else - { - magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x010); + minix3 = true; + } + else + { + magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x010); - switch(magic) - { - case MINIX_MAGIC: - filenamesize = 14; - minixVersion = "Minix V1 filesystem"; - BigEndianBitConverter.IsLittleEndian = true; - break; - case MINIX_MAGIC2: - filenamesize = 30; - minixVersion = "Minix V1 filesystem"; - BigEndianBitConverter.IsLittleEndian = true; - break; - case MINIX2_MAGIC: - filenamesize = 14; - minixVersion = "Minix V2 filesystem"; - BigEndianBitConverter.IsLittleEndian = true; - break; - case MINIX2_MAGIC2: - filenamesize = 30; - minixVersion = "Minix V2 filesystem"; - BigEndianBitConverter.IsLittleEndian = true; - break; - case MINIX_CIGAM: - filenamesize = 14; - minixVersion = "Minix V1 filesystem"; - BigEndianBitConverter.IsLittleEndian = false; - break; - case MINIX_CIGAM2: - filenamesize = 30; - minixVersion = "Minix V1 filesystem"; - BigEndianBitConverter.IsLittleEndian = false; - break; - case MINIX2_CIGAM: - filenamesize = 14; - minixVersion = "Minix V2 filesystem"; - BigEndianBitConverter.IsLittleEndian = false; - break; - case MINIX2_CIGAM2: - filenamesize = 30; - minixVersion = "Minix V2 filesystem"; - BigEndianBitConverter.IsLittleEndian = false; - break; - default: - return; - break; - } - } + switch (magic) + { + case MINIX_MAGIC: + filenamesize = 14; + minixVersion = "Minix V1 filesystem"; + BigEndianBitConverter.IsLittleEndian = true; + break; + case MINIX_MAGIC2: + filenamesize = 30; + minixVersion = "Minix V1 filesystem"; + BigEndianBitConverter.IsLittleEndian = true; + break; + case MINIX2_MAGIC: + filenamesize = 14; + minixVersion = "Minix V2 filesystem"; + BigEndianBitConverter.IsLittleEndian = true; + break; + case MINIX2_MAGIC2: + filenamesize = 30; + minixVersion = "Minix V2 filesystem"; + BigEndianBitConverter.IsLittleEndian = true; + break; + case MINIX_CIGAM: + filenamesize = 14; + minixVersion = "Minix V1 filesystem"; + BigEndianBitConverter.IsLittleEndian = false; + break; + case MINIX_CIGAM2: + filenamesize = 30; + minixVersion = "Minix V1 filesystem"; + BigEndianBitConverter.IsLittleEndian = false; + break; + case MINIX2_CIGAM: + filenamesize = 14; + minixVersion = "Minix V2 filesystem"; + BigEndianBitConverter.IsLittleEndian = false; + break; + case MINIX2_CIGAM2: + filenamesize = 30; + minixVersion = "Minix V2 filesystem"; + BigEndianBitConverter.IsLittleEndian = false; + break; + default: + return; + } + } - if(minix3) - { - Minix3SuperBlock mnx_sb = new Minix3SuperBlock(); + if (minix3) + { + Minix3SuperBlock mnx_sb = new Minix3SuperBlock(); mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x00); mnx_sb.s_pad0 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x04); @@ -143,21 +142,21 @@ namespace FileSystemIDandChk.Plugins mnx_sb.s_blocksize = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x1C); mnx_sb.s_disk_version = minix_sb_sector[0x1E]; - sb.AppendLine(minixVersion); - sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); - sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones*mnx_sb.s_blocksize).AppendLine(); - sb.AppendFormat("{0} bytes/block", mnx_sb.s_blocksize).AppendLine(); - sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine(); - sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, mnx_sb.s_imap_blocks*mnx_sb.s_blocksize).AppendLine(); - sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, mnx_sb.s_zmap_blocks*mnx_sb.s_blocksize).AppendLine(); - sb.AppendFormat("First data zone: {0}", mnx_sb.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", mnx_sb.s_max_size).AppendLine(); - sb.AppendFormat("On-disk filesystem version: {0}", mnx_sb.s_disk_version).AppendLine(); - } - else - { - MinixSuperBlock mnx_sb = new MinixSuperBlock(); + sb.AppendLine(minixVersion); + sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); + sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * mnx_sb.s_blocksize).AppendLine(); + sb.AppendFormat("{0} bytes/block", mnx_sb.s_blocksize).AppendLine(); + sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine(); + sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, mnx_sb.s_imap_blocks * mnx_sb.s_blocksize).AppendLine(); + sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, mnx_sb.s_zmap_blocks * mnx_sb.s_blocksize).AppendLine(); + sb.AppendFormat("First data zone: {0}", mnx_sb.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", mnx_sb.s_max_size).AppendLine(); + sb.AppendFormat("On-disk filesystem version: {0}", mnx_sb.s_disk_version).AppendLine(); + } + else + { + MinixSuperBlock mnx_sb = new MinixSuperBlock(); mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x00); mnx_sb.s_nzones = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x02); @@ -170,53 +169,76 @@ namespace FileSystemIDandChk.Plugins mnx_sb.s_state = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x12); mnx_sb.s_zones = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x14); - sb.AppendLine(minixVersion); - sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); - if(mnx_sb.s_zones > 0) // On V2 - sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones*1024).AppendLine(); - else - sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_nzones, mnx_sb.s_nzones*1024).AppendLine(); - sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine(); - sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, mnx_sb.s_imap_blocks*1024).AppendLine(); - sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, mnx_sb.s_zmap_blocks*1024).AppendLine(); - sb.AppendFormat("First data zone: {0}", mnx_sb.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", mnx_sb.s_max_size).AppendLine(); - sb.AppendFormat("Filesystem state: {0:X4}", mnx_sb.s_state).AppendLine(); - } - information = sb.ToString(); - } + sb.AppendLine(minixVersion); + sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); + if (mnx_sb.s_zones > 0) // On V2 + sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * 1024).AppendLine(); + else + sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_nzones, mnx_sb.s_nzones * 1024).AppendLine(); + sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine(); + sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, mnx_sb.s_imap_blocks * 1024).AppendLine(); + sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, mnx_sb.s_zmap_blocks * 1024).AppendLine(); + sb.AppendFormat("First data zone: {0}", mnx_sb.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", mnx_sb.s_max_size).AppendLine(); + sb.AppendFormat("Filesystem state: {0:X4}", mnx_sb.s_state).AppendLine(); + } + information = sb.ToString(); + } - public struct MinixSuperBlock - { - public UInt16 s_ninodes; // 0x00, inodes on volume - public UInt16 s_nzones; // 0x02, zones on volume - public UInt16 s_imap_blocks; // 0x04, blocks on inode map - public UInt16 s_zmap_blocks; // 0x06, blocks on zone map - public UInt16 s_firstdatazone; // 0x08, first data zone - public UInt16 s_log_zone_size; // 0x0A, log2 of blocks/zone - public UInt32 s_max_size; // 0x0C, max file size - public UInt16 s_magic; // 0x10, magic - public UInt16 s_state; // 0x12, filesystem state - public UInt32 s_zones; // 0x14, number of zones - } + public struct MinixSuperBlock + { + public UInt16 s_ninodes; + // 0x00, inodes on volume + public UInt16 s_nzones; + // 0x02, zones on volume + public UInt16 s_imap_blocks; + // 0x04, blocks on inode map + public UInt16 s_zmap_blocks; + // 0x06, blocks on zone map + public UInt16 s_firstdatazone; + // 0x08, first data zone + public UInt16 s_log_zone_size; + // 0x0A, log2 of blocks/zone + public UInt32 s_max_size; + // 0x0C, max file size + public UInt16 s_magic; + // 0x10, magic + public UInt16 s_state; + // 0x12, filesystem state + public UInt32 s_zones; + // 0x14, number of zones + } - public struct Minix3SuperBlock - { - public UInt32 s_ninodes; // 0x00, inodes on volume - public UInt16 s_pad0; // 0x04, padding - public UInt16 s_imap_blocks; // 0x06, blocks on inode map - public UInt16 s_zmap_blocks; // 0x08, blocks on zone map - public UInt16 s_firstdatazone; // 0x0A, first data zone - public UInt16 s_log_zone_size; // 0x0C, log2 of blocks/zone - public UInt16 s_pad1; // 0x0E, padding - public UInt32 s_max_size; // 0x10, max file size - public UInt32 s_zones; // 0x14, number of zones - public UInt16 s_magic; // 0x18, magic - public UInt16 s_pad2; // 0x1A, padding - public UInt16 s_blocksize; // 0x1C, bytes in a block - public byte s_disk_version; // 0x1E, on-disk structures version - } - } + public struct Minix3SuperBlock + { + public UInt32 s_ninodes; + // 0x00, inodes on volume + public UInt16 s_pad0; + // 0x04, padding + public UInt16 s_imap_blocks; + // 0x06, blocks on inode map + public UInt16 s_zmap_blocks; + // 0x08, blocks on zone map + public UInt16 s_firstdatazone; + // 0x0A, first data zone + public UInt16 s_log_zone_size; + // 0x0C, log2 of blocks/zone + public UInt16 s_pad1; + // 0x0E, padding + public UInt32 s_max_size; + // 0x10, max file size + public UInt32 s_zones; + // 0x14, number of zones + public UInt16 s_magic; + // 0x18, magic + public UInt16 s_pad2; + // 0x1A, padding + public UInt16 s_blocksize; + // 0x1C, bytes in a block + public byte s_disk_version; + // 0x1E, on-disk structures version + } + } } diff --git a/FileSystemIDandChk/Plugins/NTFS.cs b/FileSystemIDandChk/Plugins/NTFS.cs index 47129e4a..59cd3028 100644 --- a/FileSystemIDandChk/Plugins/NTFS.cs +++ b/FileSystemIDandChk/Plugins/NTFS.cs @@ -1,72 +1,69 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class NTFS : Plugin - { - public NTFS(PluginBase Core) + class NTFS : Plugin + { + public NTFS(PluginBase Core) { - base.Name = "New Technology File System (NTFS)"; - base.PluginUUID = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871"); + Name = "New Technology File System (NTFS)"; + PluginUUID = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - byte[] eigth_bytes = new byte[8]; - byte signature1, fats_no; - UInt16 spfat, signature2; - string oem_name; + { + byte[] eigth_bytes = new byte[8]; + byte signature1, fats_no; + UInt16 spfat, signature2; + string oem_name; byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partitionOffset); Array.Copy(ntfs_bpb, 0x003, eigth_bytes, 0, 8); - oem_name = StringHandlers.CToString(eigth_bytes); + oem_name = StringHandlers.CToString(eigth_bytes); - if(oem_name != "NTFS ") - return false; + if (oem_name != "NTFS ") + return false; fats_no = ntfs_bpb[0x010]; - if(fats_no != 0) - return false; + if (fats_no != 0) + return false; spfat = BitConverter.ToUInt16(ntfs_bpb, 0x016); - if(spfat != 0) - return false; + if (spfat != 0) + return false; signature1 = ntfs_bpb[0x026]; - if(signature1 != 0x80) - return false; + if (signature1 != 0x80) + return false; signature2 = BitConverter.ToUInt16(ntfs_bpb, 0x1FE); - if(signature2 != 0xAA55) - return false; + return signature2 == 0xAA55; - return true; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partitionOffset); - NTFS_BootBlock ntfs_bb = new NTFS_BootBlock(); + NTFS_BootBlock ntfs_bb = new NTFS_BootBlock(); - byte[] oem_name = new byte[8]; + byte[] oem_name = new byte[8]; - ntfs_bb.jmp1 = ntfs_bpb[0x000]; + ntfs_bb.jmp1 = ntfs_bpb[0x000]; ntfs_bb.jmp2 = BitConverter.ToUInt16(ntfs_bpb, 0x001); Array.Copy(ntfs_bpb, 0x003, oem_name, 0, 8); - ntfs_bb.OEMName = StringHandlers.CToString(oem_name); + ntfs_bb.OEMName = StringHandlers.CToString(oem_name); ntfs_bb.bps = BitConverter.ToUInt16(ntfs_bpb, 0x00B); ntfs_bb.spc = ntfs_bpb[0x00D]; ntfs_bb.rsectors = BitConverter.ToUInt16(ntfs_bpb, 0x00E); @@ -95,78 +92,108 @@ namespace FileSystemIDandChk.Plugins ntfs_bb.serial_no = BitConverter.ToUInt64(ntfs_bpb, 0x048); ntfs_bb.signature2 = BitConverter.ToUInt16(ntfs_bpb, 0x1FE); - sb.AppendFormat("{0} bytes per sector", ntfs_bb.bps).AppendLine(); - sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfs_bb.spc, ntfs_bb.spc*ntfs_bb.bps).AppendLine(); + sb.AppendFormat("{0} bytes per sector", ntfs_bb.bps).AppendLine(); + sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfs_bb.spc, ntfs_bb.spc * ntfs_bb.bps).AppendLine(); // sb.AppendFormat("{0} reserved sectors", ntfs_bb.rsectors).AppendLine(); // sb.AppendFormat("{0} FATs", ntfs_bb.fats_no).AppendLine(); // sb.AppendFormat("{0} entries in the root folder", ntfs_bb.root_ent).AppendLine(); // sb.AppendFormat("{0} sectors on volume (small)", ntfs_bb.sml_sectors).AppendLine(); - sb.AppendFormat("Media descriptor: 0x{0:X2}", ntfs_bb.media).AppendLine(); + sb.AppendFormat("Media descriptor: 0x{0:X2}", ntfs_bb.media).AppendLine(); // sb.AppendFormat("{0} sectors per FAT", ntfs_bb.spfat).AppendLine(); - sb.AppendFormat("{0} sectors per track", ntfs_bb.sptrk).AppendLine(); - sb.AppendFormat("{0} heads", ntfs_bb.heads).AppendLine(); - sb.AppendFormat("{0} hidden sectors before filesystem", ntfs_bb.hsectors).AppendLine(); + sb.AppendFormat("{0} sectors per track", ntfs_bb.sptrk).AppendLine(); + sb.AppendFormat("{0} heads", ntfs_bb.heads).AppendLine(); + sb.AppendFormat("{0} hidden sectors before filesystem", ntfs_bb.hsectors).AppendLine(); // sb.AppendFormat("{0} sectors on volume (big)", ntfs_bb.big_sectors).AppendLine(); - sb.AppendFormat("BIOS drive number: 0x{0:X2}", ntfs_bb.drive_no).AppendLine(); + sb.AppendFormat("BIOS drive number: 0x{0:X2}", ntfs_bb.drive_no).AppendLine(); // sb.AppendFormat("NT flags: 0x{0:X2}", ntfs_bb.nt_flags).AppendLine(); // sb.AppendFormat("Signature 1: 0x{0:X2}", ntfs_bb.signature1).AppendLine(); - sb.AppendFormat("{0} sectors on volume ({1} bytes)", ntfs_bb.sectors, ntfs_bb.sectors*ntfs_bb.bps).AppendLine(); - sb.AppendFormat("Sectors where $MFT starts: {0}", ntfs_bb.mft_lsn).AppendLine(); - sb.AppendFormat("Sectors where $MFTMirr starts: {0}", ntfs_bb.mftmirror_lsn).AppendLine(); + sb.AppendFormat("{0} sectors on volume ({1} bytes)", ntfs_bb.sectors, ntfs_bb.sectors * ntfs_bb.bps).AppendLine(); + sb.AppendFormat("Sectors where $MFT starts: {0}", ntfs_bb.mft_lsn).AppendLine(); + sb.AppendFormat("Sectors where $MFTMirr starts: {0}", ntfs_bb.mftmirror_lsn).AppendLine(); - if (ntfs_bb.mft_rc_clusters > 0) - sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfs_bb.mft_rc_clusters, - ntfs_bb.mft_rc_clusters*ntfs_bb.bps*ntfs_bb.spc).AppendLine(); - else - sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfs_bb.mft_rc_clusters).AppendLine(); - if (ntfs_bb.index_blk_cts > 0) - sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfs_bb.index_blk_cts, - ntfs_bb.index_blk_cts*ntfs_bb.bps*ntfs_bb.spc).AppendLine(); - else - sb.AppendFormat("{0} bytes per Index block", 1 << -ntfs_bb.index_blk_cts).AppendLine(); + if (ntfs_bb.mft_rc_clusters > 0) + sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfs_bb.mft_rc_clusters, + ntfs_bb.mft_rc_clusters * ntfs_bb.bps * ntfs_bb.spc).AppendLine(); + else + sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfs_bb.mft_rc_clusters).AppendLine(); + if (ntfs_bb.index_blk_cts > 0) + sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfs_bb.index_blk_cts, + ntfs_bb.index_blk_cts * ntfs_bb.bps * ntfs_bb.spc).AppendLine(); + else + sb.AppendFormat("{0} bytes per Index block", 1 << -ntfs_bb.index_blk_cts).AppendLine(); - sb.AppendFormat("Volume serial number: {0:X16}", ntfs_bb.serial_no).AppendLine(); + sb.AppendFormat("Volume serial number: {0:X16}", ntfs_bb.serial_no).AppendLine(); // sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine(); - information = sb.ToString(); - } - - private struct NTFS_BootBlock // Sector 0 - { - // BIOS Parameter Block - public byte jmp1; // 0x000, Jump to boot code - public UInt16 jmp2; // 0x001, ...; - public string OEMName; // 0x003, OEM Name, 8 bytes, space-padded, must be "NTFS " - public UInt16 bps; // 0x00B, Bytes per sector - public byte spc; // 0x00D, Sectors per cluster - public UInt16 rsectors; // 0x00E, Reserved sectors, seems 0 - public byte fats_no; // 0x010, Number of FATs... obviously, 0 - public UInt16 root_ent; // 0x011, Number of entries on root directory... 0 - public UInt16 sml_sectors; // 0x013, Sectors in volume... 0 - public byte media; // 0x015, Media descriptor - public UInt16 spfat; // 0x016, Sectors per FAT... 0 - public UInt16 sptrk; // 0x018, Sectors per track, required to boot - public UInt16 heads; // 0x01A, Heads... required to boot - public UInt32 hsectors; // 0x01C, Hidden sectors before BPB - public UInt32 big_sectors; // 0x020, Sectors in volume if > 65535... 0 - public byte drive_no; // 0x024, Drive number - public byte nt_flags; // 0x025, 0 - public byte signature1; // 0x026, EPB signature, 0x80 - public byte dummy; // 0x027, Alignment - // End of BIOS Parameter Block - // NTFS real superblock - public Int64 sectors; // 0x028, Sectors on volume - public Int64 mft_lsn; // 0x030, LSN of $MFT - public Int64 mftmirror_lsn; // 0x038, LSN of $MFTMirror - public sbyte mft_rc_clusters; // 0x040, Clusters per MFT record - public byte dummy2; // 0x041, Alignment - public UInt16 dummy3; // 0x042, Alignment - public sbyte index_blk_cts; // 0x044, Clusters per index block - public byte dummy4; // 0x045, Alignment - public UInt16 dummy5; // 0x046, Alignment - public UInt64 serial_no; // 0x048, Volume serial number - // End of NTFS superblock, followed by 430 bytes of boot code - public UInt16 signature2; // 0x1FE, 0xAA55 - } - } + information = sb.ToString(); + } + + struct NTFS_BootBlock // Sector 0 + { + // BIOS Parameter Block + public byte jmp1; + // 0x000, Jump to boot code + public UInt16 jmp2; + // 0x001, ...; + public string OEMName; + // 0x003, OEM Name, 8 bytes, space-padded, must be "NTFS " + public UInt16 bps; + // 0x00B, Bytes per sector + public byte spc; + // 0x00D, Sectors per cluster + public UInt16 rsectors; + // 0x00E, Reserved sectors, seems 0 + public byte fats_no; + // 0x010, Number of FATs... obviously, 0 + public UInt16 root_ent; + // 0x011, Number of entries on root directory... 0 + public UInt16 sml_sectors; + // 0x013, Sectors in volume... 0 + public byte media; + // 0x015, Media descriptor + public UInt16 spfat; + // 0x016, Sectors per FAT... 0 + public UInt16 sptrk; + // 0x018, Sectors per track, required to boot + public UInt16 heads; + // 0x01A, Heads... required to boot + public UInt32 hsectors; + // 0x01C, Hidden sectors before BPB + public UInt32 big_sectors; + // 0x020, Sectors in volume if > 65535... 0 + public byte drive_no; + // 0x024, Drive number + public byte nt_flags; + // 0x025, 0 + public byte signature1; + // 0x026, EPB signature, 0x80 + public byte dummy; + // 0x027, Alignment + // End of BIOS Parameter Block + // NTFS real superblock + public Int64 sectors; + // 0x028, Sectors on volume + public Int64 mft_lsn; + // 0x030, LSN of $MFT + public Int64 mftmirror_lsn; + // 0x038, LSN of $MFTMirror + public sbyte mft_rc_clusters; + // 0x040, Clusters per MFT record + public byte dummy2; + // 0x041, Alignment + public UInt16 dummy3; + // 0x042, Alignment + public sbyte index_blk_cts; + // 0x044, Clusters per index block + public byte dummy4; + // 0x045, Alignment + public UInt16 dummy5; + // 0x046, Alignment + public UInt64 serial_no; + // 0x048, Volume serial number + // End of NTFS superblock, followed by 430 bytes of boot code + public UInt16 signature2; + // 0x1FE, 0xAA55 + } + } } diff --git a/FileSystemIDandChk/Plugins/ODS.cs b/FileSystemIDandChk/Plugins/ODS.cs index 05450ff6..3e13e03a 100644 --- a/FileSystemIDandChk/Plugins/ODS.cs +++ b/FileSystemIDandChk/Plugins/ODS.cs @@ -1,55 +1,47 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; // Information from VMS File System Internals by Kirby McCoy // ISBN: 1-55558-056-4 // With some hints from http://www.decuslib.com/DECUS/vmslt97b/gnusoftware/gccaxp/7_1/vms/hm2def.h - // Expects the home block to be always in sector #1 (does not check deltas) // Assumes a sector size of 512 bytes (VMS does on HDDs and optical drives, dunno about M.O.) // Book only describes ODS-2. Need to test ODS-1 and OSD-5 // There is an ODS with signature "DECFILES11A", yet to be seen - // Time is a 64 bit unsigned integer, tenths of microseconds since 1858/11/17 00:00:00. - // TODO: Implement checksum - namespace FileSystemIDandChk.Plugins { - class ODS : Plugin - { - public ODS(PluginBase Core) + class ODS : Plugin + { + public ODS(PluginBase Core) { - base.Name = "Files-11 On-Disk Structure"; - base.PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); + Name = "Files-11 On-Disk Structure"; + PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - byte[] magic_b = new byte[12]; - string magic; + { + byte[] magic_b = new byte[12]; + string magic; byte[] hb_sector = imagePlugin.ReadSector(1 + partitionOffset); Array.Copy(hb_sector, 0x1F0, magic_b, 0, 12); - magic = Encoding.ASCII.GetString(magic_b); + magic = Encoding.ASCII.GetString(magic_b); - if(magic == "DECFILE11A " || magic == "DECFILE11B ") - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + return magic == "DECFILE11A " || magic == "DECFILE11B "; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); - ODSHomeBlock homeblock = new ODSHomeBlock(); - byte[] temp_string = new byte[12]; - homeblock.min_class = new byte[20]; - homeblock.max_class = new byte[20]; + StringBuilder sb = new StringBuilder(); + ODSHomeBlock homeblock = new ODSHomeBlock(); + byte[] temp_string = new byte[12]; + homeblock.min_class = new byte[20]; + homeblock.max_class = new byte[20]; byte[] hb_sector = imagePlugin.ReadSector(1 + partitionOffset); @@ -93,186 +85,232 @@ namespace FileSystemIDandChk.Plugins homeblock.copydate = BitConverter.ToUInt64(hb_sector, 0x092); homeblock.serialnum = BitConverter.ToUInt32(hb_sector, 0x1C8); Array.Copy(hb_sector, 0x1CC, temp_string, 0, 12); - homeblock.strucname = StringHandlers.CToString(temp_string); + homeblock.strucname = StringHandlers.CToString(temp_string); Array.Copy(hb_sector, 0x1D8, temp_string, 0, 12); - homeblock.volname = StringHandlers.CToString(temp_string); + homeblock.volname = StringHandlers.CToString(temp_string); Array.Copy(hb_sector, 0x1E4, temp_string, 0, 12); - homeblock.ownername = StringHandlers.CToString(temp_string); + homeblock.ownername = StringHandlers.CToString(temp_string); Array.Copy(hb_sector, 0x1F0, temp_string, 0, 12); - homeblock.format = StringHandlers.CToString(temp_string); + homeblock.format = StringHandlers.CToString(temp_string); homeblock.checksum2 = BitConverter.ToUInt16(hb_sector, 0x1FE); - if((homeblock.struclev & 0xFF00) != 0x0200 || (homeblock.struclev & 0xFF) != 1 || homeblock.format != "DECFILE11B ") - sb.AppendLine("The following information may be incorrect for this volume."); - if(homeblock.resfiles < 5 || homeblock.devtype != 0) - sb.AppendLine("This volume may be corrupted."); + if ((homeblock.struclev & 0xFF00) != 0x0200 || (homeblock.struclev & 0xFF) != 1 || homeblock.format != "DECFILE11B ") + sb.AppendLine("The following information may be incorrect for this volume."); + if (homeblock.resfiles < 5 || homeblock.devtype != 0) + sb.AppendLine("This volume may be corrupted."); - sb.AppendFormat("Volume format is {0}", homeblock.format).AppendLine(); - sb.AppendFormat("Volume is Level {0} revision {1}", (homeblock.struclev&0xFF00)>>8, homeblock.struclev&0xFF).AppendLine(); - sb.AppendFormat("Lowest structure in the volume is Level {0}, revision {1}", (homeblock.lowstruclev&0xFF00)>>8, homeblock.lowstruclev&0xFF).AppendLine(); - sb.AppendFormat("Highest structure in the volume is Level {0}, revision {1}", (homeblock.highstruclev&0xFF00)>>8, homeblock.highstruclev&0xFF).AppendLine(); - sb.AppendFormat("{0} sectors per cluster ({1} bytes)", homeblock.cluster, homeblock.cluster*512).AppendLine(); - sb.AppendFormat("This home block is on sector {0} (cluster {1})", homeblock.homelbn, homeblock.homevbn).AppendLine(); - sb.AppendFormat("Secondary home block is on sector {0} (cluster {1})", homeblock.alhomelbn, homeblock.alhomevbn).AppendLine(); - sb.AppendFormat("Volume bitmap starts in sector {0} (cluster {1})", homeblock.ibmaplbn, homeblock.ibmapvbn).AppendLine(); - sb.AppendFormat("Volume bitmap runs for {0} sectors ({1} bytes)", homeblock.ibmapsize, homeblock.ibmapsize*512).AppendLine(); - sb.AppendFormat("Backup INDEXF.SYS;1 is in sector {0} (cluster {1})", homeblock.altidxlbn, homeblock.altidxvbn).AppendLine(); - sb.AppendFormat("{0} maximum files on the volume", homeblock.maxfiles).AppendLine(); - sb.AppendFormat("{0} reserved files", homeblock.resfiles).AppendLine(); - if(homeblock.rvn > 0 && homeblock.setcount > 0 && homeblock.strucname != " ") - sb.AppendFormat("Volume is {0} of {1} in set \"{2}\".", homeblock.rvn, homeblock.setcount, homeblock.strucname).AppendLine(); - sb.AppendFormat("Volume owner is \"{0}\" (ID 0x{1:X8})", homeblock.ownername, homeblock.volowner).AppendLine(); - sb.AppendFormat("Volume label: \"{0}\"", homeblock.volname).AppendLine(); - sb.AppendFormat("Drive serial number: 0x{0:X8}", homeblock.serialnum).AppendLine(); - sb.AppendFormat("Volume was created on {0}", DateHandlers.VMSToDateTime(homeblock.credate).ToString()).AppendLine(); - if(homeblock.revdate > 0) - sb.AppendFormat("Volume was last modified on {0}", DateHandlers.VMSToDateTime(homeblock.revdate).ToString()).AppendLine(); - if(homeblock.copydate > 0) - sb.AppendFormat("Volume copied on {0}", DateHandlers.VMSToDateTime(homeblock.copydate).ToString()).AppendLine(); - sb.AppendFormat("Checksums: 0x{0:X4} and 0x{1:X4}", homeblock.checksum1, homeblock.checksum2).AppendLine(); - sb.AppendLine("Flags:"); - sb.AppendFormat("Window: {0}", homeblock.window).AppendLine(); - sb.AppendFormat("Cached directores: {0}", homeblock.lru_lim).AppendLine(); - sb.AppendFormat("Default allocation: {0} blocks", homeblock.extend).AppendLine(); - if((homeblock.volchar & 0x01) == 0x01) - sb.AppendLine("Readings should be verified"); - if((homeblock.volchar & 0x02) == 0x02) - sb.AppendLine("Writings should be verified"); - if((homeblock.volchar & 0x04) == 0x04) - sb.AppendLine("Files should be erased or overwritten when deleted"); - if((homeblock.volchar & 0x08) == 0x08) - sb.AppendLine("Highwater mark is to be disabled"); - if((homeblock.volchar & 0x10) == 0x10) - sb.AppendLine("Classification checks are enabled"); - sb.AppendLine("Volume permissions (r = read, w = write, c = create, d = delete)"); - sb.AppendLine("System, owner, group, world"); - // System - if((homeblock.protect & 0x1000) == 0x1000) - sb.Append("-"); - else - sb.Append("r"); - if((homeblock.protect & 0x2000) == 0x2000) - sb.Append("-"); - else - sb.Append("w"); - if((homeblock.protect & 0x4000) == 0x4000) - sb.Append("-"); - else - sb.Append("c"); - if((homeblock.protect & 0x8000) == 0x8000) - sb.Append("-"); - else - sb.Append("d"); - // Owner - if((homeblock.protect & 0x100) == 0x100) - sb.Append("-"); - else - sb.Append("r"); - if((homeblock.protect & 0x200) == 0x200) - sb.Append("-"); - else - sb.Append("w"); - if((homeblock.protect & 0x400) == 0x400) - sb.Append("-"); - else - sb.Append("c"); - if((homeblock.protect & 0x800) == 0x800) - sb.Append("-"); - else - sb.Append("d"); - // Group - if((homeblock.protect & 0x10) == 0x10) - sb.Append("-"); - else - sb.Append("r"); - if((homeblock.protect & 0x20) == 0x20) - sb.Append("-"); - else - sb.Append("w"); - if((homeblock.protect & 0x40) == 0x40) - sb.Append("-"); - else - sb.Append("c"); - if((homeblock.protect & 0x80) == 0x80) - sb.Append("-"); - else - sb.Append("d"); - // World (other) - if((homeblock.protect & 0x1) == 0x1) - sb.Append("-"); - else - sb.Append("r"); - if((homeblock.protect & 0x2) == 0x2) - sb.Append("-"); - else - sb.Append("w"); - if((homeblock.protect & 0x4) == 0x4) - sb.Append("-"); - else - sb.Append("c"); - if((homeblock.protect & 0x8) == 0x8) - sb.Append("-"); - else - sb.Append("d"); + sb.AppendFormat("Volume format is {0}", homeblock.format).AppendLine(); + sb.AppendFormat("Volume is Level {0} revision {1}", (homeblock.struclev & 0xFF00) >> 8, homeblock.struclev & 0xFF).AppendLine(); + sb.AppendFormat("Lowest structure in the volume is Level {0}, revision {1}", (homeblock.lowstruclev & 0xFF00) >> 8, homeblock.lowstruclev & 0xFF).AppendLine(); + sb.AppendFormat("Highest structure in the volume is Level {0}, revision {1}", (homeblock.highstruclev & 0xFF00) >> 8, homeblock.highstruclev & 0xFF).AppendLine(); + sb.AppendFormat("{0} sectors per cluster ({1} bytes)", homeblock.cluster, homeblock.cluster * 512).AppendLine(); + sb.AppendFormat("This home block is on sector {0} (cluster {1})", homeblock.homelbn, homeblock.homevbn).AppendLine(); + sb.AppendFormat("Secondary home block is on sector {0} (cluster {1})", homeblock.alhomelbn, homeblock.alhomevbn).AppendLine(); + sb.AppendFormat("Volume bitmap starts in sector {0} (cluster {1})", homeblock.ibmaplbn, homeblock.ibmapvbn).AppendLine(); + sb.AppendFormat("Volume bitmap runs for {0} sectors ({1} bytes)", homeblock.ibmapsize, homeblock.ibmapsize * 512).AppendLine(); + sb.AppendFormat("Backup INDEXF.SYS;1 is in sector {0} (cluster {1})", homeblock.altidxlbn, homeblock.altidxvbn).AppendLine(); + sb.AppendFormat("{0} maximum files on the volume", homeblock.maxfiles).AppendLine(); + sb.AppendFormat("{0} reserved files", homeblock.resfiles).AppendLine(); + if (homeblock.rvn > 0 && homeblock.setcount > 0 && homeblock.strucname != " ") + sb.AppendFormat("Volume is {0} of {1} in set \"{2}\".", homeblock.rvn, homeblock.setcount, homeblock.strucname).AppendLine(); + sb.AppendFormat("Volume owner is \"{0}\" (ID 0x{1:X8})", homeblock.ownername, homeblock.volowner).AppendLine(); + sb.AppendFormat("Volume label: \"{0}\"", homeblock.volname).AppendLine(); + sb.AppendFormat("Drive serial number: 0x{0:X8}", homeblock.serialnum).AppendLine(); + sb.AppendFormat("Volume was created on {0}", DateHandlers.VMSToDateTime(homeblock.credate)).AppendLine(); + if (homeblock.revdate > 0) + sb.AppendFormat("Volume was last modified on {0}", DateHandlers.VMSToDateTime(homeblock.revdate)).AppendLine(); + if (homeblock.copydate > 0) + sb.AppendFormat("Volume copied on {0}", DateHandlers.VMSToDateTime(homeblock.copydate)).AppendLine(); + sb.AppendFormat("Checksums: 0x{0:X4} and 0x{1:X4}", homeblock.checksum1, homeblock.checksum2).AppendLine(); + sb.AppendLine("Flags:"); + sb.AppendFormat("Window: {0}", homeblock.window).AppendLine(); + sb.AppendFormat("Cached directores: {0}", homeblock.lru_lim).AppendLine(); + sb.AppendFormat("Default allocation: {0} blocks", homeblock.extend).AppendLine(); + if ((homeblock.volchar & 0x01) == 0x01) + sb.AppendLine("Readings should be verified"); + if ((homeblock.volchar & 0x02) == 0x02) + sb.AppendLine("Writings should be verified"); + if ((homeblock.volchar & 0x04) == 0x04) + sb.AppendLine("Files should be erased or overwritten when deleted"); + if ((homeblock.volchar & 0x08) == 0x08) + sb.AppendLine("Highwater mark is to be disabled"); + if ((homeblock.volchar & 0x10) == 0x10) + sb.AppendLine("Classification checks are enabled"); + sb.AppendLine("Volume permissions (r = read, w = write, c = create, d = delete)"); + sb.AppendLine("System, owner, group, world"); + // System + if ((homeblock.protect & 0x1000) == 0x1000) + sb.Append("-"); + else + sb.Append("r"); + if ((homeblock.protect & 0x2000) == 0x2000) + sb.Append("-"); + else + sb.Append("w"); + if ((homeblock.protect & 0x4000) == 0x4000) + sb.Append("-"); + else + sb.Append("c"); + if ((homeblock.protect & 0x8000) == 0x8000) + sb.Append("-"); + else + sb.Append("d"); + // Owner + if ((homeblock.protect & 0x100) == 0x100) + sb.Append("-"); + else + sb.Append("r"); + if ((homeblock.protect & 0x200) == 0x200) + sb.Append("-"); + else + sb.Append("w"); + if ((homeblock.protect & 0x400) == 0x400) + sb.Append("-"); + else + sb.Append("c"); + if ((homeblock.protect & 0x800) == 0x800) + sb.Append("-"); + else + sb.Append("d"); + // Group + if ((homeblock.protect & 0x10) == 0x10) + sb.Append("-"); + else + sb.Append("r"); + if ((homeblock.protect & 0x20) == 0x20) + sb.Append("-"); + else + sb.Append("w"); + if ((homeblock.protect & 0x40) == 0x40) + sb.Append("-"); + else + sb.Append("c"); + if ((homeblock.protect & 0x80) == 0x80) + sb.Append("-"); + else + sb.Append("d"); + // World (other) + if ((homeblock.protect & 0x1) == 0x1) + sb.Append("-"); + else + sb.Append("r"); + if ((homeblock.protect & 0x2) == 0x2) + sb.Append("-"); + else + sb.Append("w"); + if ((homeblock.protect & 0x4) == 0x4) + sb.Append("-"); + else + sb.Append("c"); + if ((homeblock.protect & 0x8) == 0x8) + sb.Append("-"); + else + sb.Append("d"); - sb.AppendLine(); + sb.AppendLine(); - sb.AppendLine("Unknown structures:"); - sb.AppendFormat("Security mask: 0x{0:X8}", homeblock.sec_mask).AppendLine(); - sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine(); - sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine(); + sb.AppendLine("Unknown structures:"); + sb.AppendFormat("Security mask: 0x{0:X8}", homeblock.sec_mask).AppendLine(); + sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine(); + sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine(); - information = sb.ToString(); - } - - private struct ODSHomeBlock - { - public UInt32 homelbn; // 0x000, LBN of THIS home block - public UInt32 alhomelbn; // 0x004, LBN of the secondary home block - public UInt32 altidxlbn; // 0x008, LBN of backup INDEXF.SYS;1 - public UInt16 struclev; // 0x00C, High byte contains filesystem version (1, 2 or 5), low byte contains revision (1) - public UInt16 cluster; // 0x00E, Number of blocks each bit of the volume bitmap represents - public UInt16 homevbn; // 0x010, VBN of THIS home block - public UInt16 alhomevbn; // 0x012, VBN of the secondary home block - public UInt16 altidxvbn; // 0x014, VBN of backup INDEXF.SYS;1 - public UInt16 ibmapvbn; // 0x016, VBN of the bitmap - public UInt32 ibmaplbn; // 0x018, LBN of the bitmap - public UInt32 maxfiles; // 0x01C, Max files on volume - public UInt16 ibmapsize; // 0x020, Bitmap size in sectors - public UInt16 resfiles; // 0x022, Reserved files, 5 at minimum - public UInt16 devtype; // 0x024, Device type, ODS-2 defines it as always 0 - public UInt16 rvn; // 0x026, Relative volume number (number of the volume in a set) - public UInt16 setcount; // 0x028, Total number of volumes in the set this volume is - public UInt16 volchar; // 0x02A, Flags - public UInt32 volowner; // 0x02C, User ID of the volume owner - public UInt32 sec_mask; // 0x030, Security mask (??) - public UInt16 protect; // 0x034, Volume permissions (system, owner, group and other) - public UInt16 fileprot; // 0x036, Default file protection, unsupported in ODS-2 - public UInt16 recprot; // 0x038, Default file record protection - public UInt16 checksum1; // 0x03A, Checksum of all preceding entries - public UInt64 credate; // 0x03C, Creation date - public byte window; // 0x044, Window size (pointers for the window) - public byte lru_lim; // 0x045, Directories to be stored in cache - public UInt16 extend; // 0x046, Default allocation size in blocks - public UInt64 retainmin; // 0x048, Minimum file retention period - public UInt64 retainmax; // 0x050, Maximum file retention period - public UInt64 revdate; // 0x058, Last modification date - public byte[] min_class; // 0x060, Minimum security class, 20 bytes - public byte[] max_class; // 0x074, Maximum security class, 20 bytes - public UInt16 filetab_fid1; // 0x088, File lookup table FID - public UInt16 filetab_fid2; // 0x08A, File lookup table FID - public UInt16 filetab_fid3; // 0x08C, File lookup table FID - public UInt16 lowstruclev; // 0x08E, Lowest structure level on the volume - public UInt16 highstruclev; // 0x090, Highest structure level on the volume - public UInt64 copydate; // 0x092, Volume copy date (??) - public byte[] reserved1; // 0x09A, 302 bytes - public UInt32 serialnum; // 0x1C8, Physical drive serial number - public string strucname; // 0x1CC, Name of the volume set, 12 bytes - public string volname; // 0x1D8, Volume label, 12 bytes - public string ownername; // 0x1E4, Name of the volume owner, 12 bytes - public string format; // 0x1F0, ODS-2 defines it as "DECFILE11B", 12 bytes - public UInt16 reserved2; // 0x1FC, Reserved - public UInt16 checksum2; // 0x1FE, Checksum of preceding 255 words (16 bit units) - } - } + information = sb.ToString(); + } + + struct ODSHomeBlock + { + public UInt32 homelbn; + // 0x000, LBN of THIS home block + public UInt32 alhomelbn; + // 0x004, LBN of the secondary home block + public UInt32 altidxlbn; + // 0x008, LBN of backup INDEXF.SYS;1 + public UInt16 struclev; + // 0x00C, High byte contains filesystem version (1, 2 or 5), low byte contains revision (1) + public UInt16 cluster; + // 0x00E, Number of blocks each bit of the volume bitmap represents + public UInt16 homevbn; + // 0x010, VBN of THIS home block + public UInt16 alhomevbn; + // 0x012, VBN of the secondary home block + public UInt16 altidxvbn; + // 0x014, VBN of backup INDEXF.SYS;1 + public UInt16 ibmapvbn; + // 0x016, VBN of the bitmap + public UInt32 ibmaplbn; + // 0x018, LBN of the bitmap + public UInt32 maxfiles; + // 0x01C, Max files on volume + public UInt16 ibmapsize; + // 0x020, Bitmap size in sectors + public UInt16 resfiles; + // 0x022, Reserved files, 5 at minimum + public UInt16 devtype; + // 0x024, Device type, ODS-2 defines it as always 0 + public UInt16 rvn; + // 0x026, Relative volume number (number of the volume in a set) + public UInt16 setcount; + // 0x028, Total number of volumes in the set this volume is + public UInt16 volchar; + // 0x02A, Flags + public UInt32 volowner; + // 0x02C, User ID of the volume owner + public UInt32 sec_mask; + // 0x030, Security mask (??) + public UInt16 protect; + // 0x034, Volume permissions (system, owner, group and other) + public UInt16 fileprot; + // 0x036, Default file protection, unsupported in ODS-2 + public UInt16 recprot; + // 0x038, Default file record protection + public UInt16 checksum1; + // 0x03A, Checksum of all preceding entries + public UInt64 credate; + // 0x03C, Creation date + public byte window; + // 0x044, Window size (pointers for the window) + public byte lru_lim; + // 0x045, Directories to be stored in cache + public UInt16 extend; + // 0x046, Default allocation size in blocks + public UInt64 retainmin; + // 0x048, Minimum file retention period + public UInt64 retainmax; + // 0x050, Maximum file retention period + public UInt64 revdate; + // 0x058, Last modification date + public byte[] min_class; + // 0x060, Minimum security class, 20 bytes + public byte[] max_class; + // 0x074, Maximum security class, 20 bytes + public UInt16 filetab_fid1; + // 0x088, File lookup table FID + public UInt16 filetab_fid2; + // 0x08A, File lookup table FID + public UInt16 filetab_fid3; + // 0x08C, File lookup table FID + public UInt16 lowstruclev; + // 0x08E, Lowest structure level on the volume + public UInt16 highstruclev; + // 0x090, Highest structure level on the volume + public UInt64 copydate; + // 0x092, Volume copy date (??) + public byte[] reserved1; + // 0x09A, 302 bytes + public UInt32 serialnum; + // 0x1C8, Physical drive serial number + public string strucname; + // 0x1CC, Name of the volume set, 12 bytes + public string volname; + // 0x1D8, Volume label, 12 bytes + public string ownername; + // 0x1E4, Name of the volume owner, 12 bytes + public string format; + // 0x1F0, ODS-2 defines it as "DECFILE11B", 12 bytes + public UInt16 reserved2; + // 0x1FC, Reserved + public UInt16 checksum2; + // 0x1FE, Checksum of preceding 255 words (16 bit units) + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/Opera.cs b/FileSystemIDandChk/Plugins/Opera.cs index ff7bf6a6..d78b44ec 100644 --- a/FileSystemIDandChk/Plugins/Opera.cs +++ b/FileSystemIDandChk/Plugins/Opera.cs @@ -1,21 +1,19 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; - namespace FileSystemIDandChk.Plugins { - class OperaFS : Plugin - { - public OperaFS(PluginBase Core) + class OperaFS : Plugin + { + public OperaFS(PluginBase Core) { - base.Name = "Opera Filesystem Plugin"; - base.PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd"); + Name = "Opera Filesystem Plugin"; + PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { + { byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset); byte record_type; @@ -26,22 +24,20 @@ namespace FileSystemIDandChk.Plugins Array.Copy(sb_sector, 0x001, sync_bytes, 0, 5); record_version = sb_sector[0x006]; - if (record_type != 1 || record_version != 1) - return false; - if(Encoding.ASCII.GetString(sync_bytes) != "ZZZZZ") + if (record_type != 1 || record_version != 1) return false; + return Encoding.ASCII.GetString(sync_bytes) == "ZZZZZ"; - return true; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; StringBuilder SuperBlockMetadata = new StringBuilder(); byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset); - OperaSuperBlock sb = new OperaSuperBlock(); + OperaSuperBlock sb = new OperaSuperBlock(); byte[] cString = new byte[32]; sb.sync_bytes = new byte[5]; @@ -50,9 +46,9 @@ namespace FileSystemIDandChk.Plugins sb.record_version = sb_sector[0x006]; sb.volume_flags = sb_sector[0x007]; Array.Copy(sb_sector, 0x008, cString, 0, 32); - sb.volume_comment = StringHandlers.CToString(cString); + sb.volume_comment = StringHandlers.CToString(cString); Array.Copy(sb_sector, 0x028, cString, 0, 32); - sb.volume_label = StringHandlers.CToString(cString); + sb.volume_label = StringHandlers.CToString(cString); sb.volume_id = BigEndianBitConverter.ToInt32(sb_sector, 0x048); sb.block_size = BigEndianBitConverter.ToInt32(sb_sector, 0x04C); sb.block_count = BigEndianBitConverter.ToInt32(sb_sector, 0x050); @@ -61,22 +57,22 @@ namespace FileSystemIDandChk.Plugins sb.rootdir_bsize = BigEndianBitConverter.ToInt32(sb_sector, 0x05C); sb.last_root_copy = BigEndianBitConverter.ToInt32(sb_sector, 0x060); - if (sb.record_type != 1 || sb.record_version != 1) + if (sb.record_type != 1 || sb.record_version != 1) return; - if(Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ") + if (Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ") return; - if (sb.volume_comment.Length == 0) - sb.volume_comment = "Not set."; + if (sb.volume_comment.Length == 0) + sb.volume_comment = "Not set."; - if (sb.volume_label.Length == 0) - sb.volume_label = "Not set."; + if (sb.volume_label.Length == 0) + sb.volume_label = "Not set."; SuperBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine(); - SuperBlockMetadata.AppendFormat("Volume label: {0}", sb.volume_label).AppendLine(); - SuperBlockMetadata.AppendFormat("Volume comment: {0}", sb.volume_comment).AppendLine(); - SuperBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine(); - SuperBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine(); + SuperBlockMetadata.AppendFormat("Volume label: {0}", sb.volume_label).AppendLine(); + SuperBlockMetadata.AppendFormat("Volume comment: {0}", sb.volume_comment).AppendLine(); + SuperBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine(); + SuperBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine(); if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) { if (sb.block_size != 2048) @@ -84,32 +80,45 @@ namespace FileSystemIDandChk.Plugins } else if (imagePlugin.GetSectorSize() != sb.block_size) SuperBlockMetadata.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", sb.block_size, imagePlugin.GetSectorSize()); - SuperBlockMetadata.AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size*sb.block_count).AppendLine(); - if((ulong)sb.block_count > imagePlugin.GetSectors()) + SuperBlockMetadata.AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size * sb.block_count).AppendLine(); + if ((ulong)sb.block_count > imagePlugin.GetSectors()) SuperBlockMetadata.AppendFormat("WARNING: Filesystem indicates {0} blocks while device indicates {1} blocks", sb.block_count, imagePlugin.GetSectors()); - 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(); + 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(); - } + } - private struct OperaSuperBlock - { - public byte record_type; // 0x000, Record type, must be 1 - public byte[] sync_bytes; // 0x001, 5 bytes, "ZZZZZ" = new byte[5]; - public byte record_version; // 0x006, Record version, must be 1 - public byte volume_flags; // 0x007, Volume flags - public string volume_comment; // 0x008, 32 bytes, volume comment - public string volume_label; // 0x028, 32 bytes, volume label - public Int32 volume_id; // 0x048, Volume ID - public Int32 block_size; // 0x04C, Block size in bytes - public Int32 block_count; // 0x050, Blocks in volume - public Int32 root_dirid; // 0x054, Root directory ID - public Int32 rootdir_blocks; // 0x058, Root directory blocks - public Int32 rootdir_bsize; // 0x05C, Root directory block size - public Int32 last_root_copy; // 0x060, Last root directory copy - } - } + struct OperaSuperBlock + { + public byte record_type; + // 0x000, Record type, must be 1 + public byte[] sync_bytes; + // 0x001, 5 bytes, "ZZZZZ" = new byte[5]; + public byte record_version; + // 0x006, Record version, must be 1 + public byte volume_flags; + // 0x007, Volume flags + public string volume_comment; + // 0x008, 32 bytes, volume comment + public string volume_label; + // 0x028, 32 bytes, volume label + public Int32 volume_id; + // 0x048, Volume ID + public Int32 block_size; + // 0x04C, Block size in bytes + public Int32 block_count; + // 0x050, Blocks in volume + public Int32 root_dirid; + // 0x054, Root directory ID + public Int32 rootdir_blocks; + // 0x058, Root directory blocks + public Int32 rootdir_bsize; + // 0x05C, Root directory block size + public Int32 last_root_copy; + // 0x060, Last root directory copy + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/PCEngine.cs b/FileSystemIDandChk/Plugins/PCEngine.cs index 749d4a27..ea610295 100644 --- a/FileSystemIDandChk/Plugins/PCEngine.cs +++ b/FileSystemIDandChk/Plugins/PCEngine.cs @@ -1,34 +1,30 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class PCEnginePlugin : Plugin - { - public PCEnginePlugin(PluginBase Core) + class PCEnginePlugin : Plugin + { + public PCEnginePlugin(PluginBase Core) { - base.Name = "PC Engine CD Plugin"; - base.PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); + Name = "PC Engine CD Plugin"; + PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { + { byte[] system_descriptor = new byte[23]; byte[] sector = imagePlugin.ReadSector(1 + partitionOffset); Array.Copy(sector, 0x20, system_descriptor, 0, 23); - if(Encoding.ASCII.GetString(system_descriptor) == "PC Engine CD-ROM SYSTEM") - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; - } - } + return Encoding.ASCII.GetString(system_descriptor) == "PC Engine CD-ROM SYSTEM"; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/Plugin.cs b/FileSystemIDandChk/Plugins/Plugin.cs index f49b4d5a..e40d1bfd 100644 --- a/FileSystemIDandChk/Plugins/Plugin.cs +++ b/FileSystemIDandChk/Plugins/Plugin.cs @@ -1,5 +1,4 @@ using System; -using System.IO; namespace FileSystemIDandChk.Plugins { diff --git a/FileSystemIDandChk/Plugins/SolarFS.cs b/FileSystemIDandChk/Plugins/SolarFS.cs index e88a278c..34042398 100644 --- a/FileSystemIDandChk/Plugins/SolarFS.cs +++ b/FileSystemIDandChk/Plugins/SolarFS.cs @@ -1,47 +1,45 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; // Based on FAT's BPB, cannot find a FAT or directory namespace FileSystemIDandChk.Plugins { - class SolarFS : Plugin - { - public SolarFS(PluginBase Core) + class SolarFS : Plugin + { + public SolarFS(PluginBase Core) { - base.Name = "Solar_OS filesystem"; - base.PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); + Name = "Solar_OS filesystem"; + PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); } - - public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - byte signature; // 0x29 - string fs_type; // "SOL_FS " - byte[] bpb = imagePlugin.ReadSector (0 + partitionOffset); + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) + { + byte signature; // 0x29 + string fs_type; // "SOL_FS " + + byte[] bpb = imagePlugin.ReadSector(0 + partitionOffset); byte[] fs_type_b = new byte[8]; - signature = bpb [0x25]; - Array.Copy (bpb, 0x35, fs_type_b, 0, 8); - fs_type = StringHandlers.CToString(fs_type_b); + signature = bpb[0x25]; + Array.Copy(bpb, 0x35, fs_type_b, 0, 8); + fs_type = StringHandlers.CToString(fs_type_b); - if(signature == 0x29 && fs_type == "SOL_FS ") - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + if (signature == 0x29 && fs_type == "SOL_FS ") + return true; + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); byte[] bpb_sector = imagePlugin.ReadSector(0 + partitionOffset); byte[] bpb_strings; - SolarOSParameterBlock BPB = new SolarOSParameterBlock(); + SolarOSParameterBlock BPB = new SolarOSParameterBlock(); bpb_strings = new byte[8]; Array.Copy(bpb_sector, 0x03, bpb_strings, 0, 8); @@ -61,8 +59,8 @@ namespace FileSystemIDandChk.Plugins Array.Copy(bpb_sector, 0x35, bpb_strings, 0, 8); BPB.fs_type = StringHandlers.CToString(bpb_strings); - if(MainClass.isDebug) - { + if (MainClass.isDebug) + { BPB.x86_jump = new byte[3]; Array.Copy(bpb_sector, 0x00, BPB.x86_jump, 0, 3); BPB.unk1 = bpb_sector[0x0D]; @@ -71,27 +69,27 @@ namespace FileSystemIDandChk.Plugins Array.Copy(bpb_sector, 0x1B, BPB.unk3, 0, 10); BPB.unk4 = BitConverter.ToUInt32(bpb_sector, 0x26); - Console.WriteLine("(SolarFS) BPB.x86_jump: 0x{0:X2}{1:X2}{2:X2}", BPB.x86_jump[0], BPB.x86_jump[1], BPB.x86_jump[2]); - Console.WriteLine("(SolarFS) BPB.OEMName: \"{0}\"", BPB.OEMName); - Console.WriteLine("(SolarFS) BPB.bps: {0}", BPB.bps); - Console.WriteLine("(SolarFS) BPB.unk1: 0x{0:X2}", BPB.unk1); - Console.WriteLine("(SolarFS) BPB.unk2: 0x{0:X4}", BPB.unk2); - Console.WriteLine("(SolarFS) BPB.root_ent: {0}", BPB.root_ent); - Console.WriteLine("(SolarFS) BPB.sectors: {0}", BPB.sectors); - Console.WriteLine("(SolarFS) BPB.media: 0x{0:X2}", BPB.media); - Console.WriteLine("(SolarFS) BPB.spfat: {0}", BPB.spfat); - Console.WriteLine("(SolarFS) BPB.sptrk: {0}", BPB.sptrk); - Console.WriteLine("(SolarFS) BPB.heads: {0}", BPB.heads); - Console.WriteLine("(SolarFS) BPB.unk3: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}", BPB.unk3[0], BPB.unk3[1], BPB.unk3[2], BPB.unk3[3], BPB.unk3[4], BPB.unk3[5], BPB.unk3[6], BPB.unk3[7], BPB.unk3[8], BPB.unk3[9]); - Console.WriteLine("(SolarFS) BPB.signature: 0x{0:X2}", BPB.signature); - Console.WriteLine("(SolarFS) BPB.unk4: 0x{0:X8}", BPB.unk4); - Console.WriteLine("(SolarFS) BPB.vol_name: \"{0}\"", BPB.vol_name); - Console.WriteLine("(SolarFS) BPB.fs_type: \"{0}\"", BPB.fs_type); - } + Console.WriteLine("(SolarFS) BPB.x86_jump: 0x{0:X2}{1:X2}{2:X2}", BPB.x86_jump[0], BPB.x86_jump[1], BPB.x86_jump[2]); + Console.WriteLine("(SolarFS) BPB.OEMName: \"{0}\"", BPB.OEMName); + Console.WriteLine("(SolarFS) BPB.bps: {0}", BPB.bps); + Console.WriteLine("(SolarFS) BPB.unk1: 0x{0:X2}", BPB.unk1); + Console.WriteLine("(SolarFS) BPB.unk2: 0x{0:X4}", BPB.unk2); + Console.WriteLine("(SolarFS) BPB.root_ent: {0}", BPB.root_ent); + Console.WriteLine("(SolarFS) BPB.sectors: {0}", BPB.sectors); + Console.WriteLine("(SolarFS) BPB.media: 0x{0:X2}", BPB.media); + Console.WriteLine("(SolarFS) BPB.spfat: {0}", BPB.spfat); + Console.WriteLine("(SolarFS) BPB.sptrk: {0}", BPB.sptrk); + Console.WriteLine("(SolarFS) BPB.heads: {0}", BPB.heads); + Console.WriteLine("(SolarFS) BPB.unk3: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}", BPB.unk3[0], BPB.unk3[1], BPB.unk3[2], BPB.unk3[3], BPB.unk3[4], BPB.unk3[5], BPB.unk3[6], BPB.unk3[7], BPB.unk3[8], BPB.unk3[9]); + Console.WriteLine("(SolarFS) BPB.signature: 0x{0:X2}", BPB.signature); + Console.WriteLine("(SolarFS) BPB.unk4: 0x{0:X8}", BPB.unk4); + Console.WriteLine("(SolarFS) BPB.vol_name: \"{0}\"", BPB.vol_name); + Console.WriteLine("(SolarFS) BPB.fs_type: \"{0}\"", BPB.fs_type); + } - sb.AppendLine("Solar_OS filesystem"); - sb.AppendFormat("Media descriptor: 0x{0:X2}", BPB.media).AppendLine(); - sb.AppendFormat("{0} bytes per sector", BPB.bps).AppendLine(); + sb.AppendLine("Solar_OS filesystem"); + sb.AppendFormat("Media descriptor: 0x{0:X2}", BPB.media).AppendLine(); + sb.AppendFormat("{0} bytes per sector", BPB.bps).AppendLine(); if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) { if (BPB.bps != imagePlugin.GetSectorSize()) @@ -99,39 +97,54 @@ namespace FileSystemIDandChk.Plugins sb.AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector", BPB.bps, 2048).AppendLine(); } } - else - if (BPB.bps != imagePlugin.GetSectorSize()) - { - sb.AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector", BPB.bps, imagePlugin.GetSectorSize()).AppendLine(); - } - sb.AppendFormat("{0} sectors on volume ({1} bytes)", BPB.sectors, BPB.sectors*BPB.bps).AppendLine(); + else if (BPB.bps != imagePlugin.GetSectorSize()) + { + sb.AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector", BPB.bps, imagePlugin.GetSectorSize()).AppendLine(); + } + sb.AppendFormat("{0} sectors on volume ({1} bytes)", BPB.sectors, BPB.sectors * BPB.bps).AppendLine(); if (BPB.sectors > imagePlugin.GetSectors()) sb.AppendFormat("WARNING: Filesystem describes a {0} sectors volume, bigger than device ({1} sectors)", BPB.sectors, imagePlugin.GetSectors()); - sb.AppendFormat("{0} heads", BPB.heads).AppendLine(); - sb.AppendFormat("{0} sectors per track", BPB.sptrk).AppendLine(); - sb.AppendFormat("Volume name: {0}", BPB.vol_name).AppendLine(); + sb.AppendFormat("{0} heads", BPB.heads).AppendLine(); + sb.AppendFormat("{0} sectors per track", BPB.sptrk).AppendLine(); + sb.AppendFormat("Volume name: {0}", BPB.vol_name).AppendLine(); - information = sb.ToString(); - } - - public struct SolarOSParameterBlock - { - public byte[] x86_jump; // 0x00, x86 jump (3 bytes), jumps to 0x60 - public string OEMName; // 0x03, 8 bytes, "SOLAR_OS" - public UInt16 bps; // 0x0B, Bytes per sector - public byte unk1; // 0x0D, unknown, 0x01 - public UInt16 unk2; // 0x0E, unknown, 0x0201 - public UInt16 root_ent; // 0x10, Number of entries on root directory ? (no root directory found) - public UInt16 sectors; // 0x12, Sectors in volume - public byte media; // 0x14, Media descriptor - public UInt16 spfat; // 0x15, Sectors per FAT ? (no FAT found) - public UInt16 sptrk; // 0x17, Sectors per track - public UInt16 heads; // 0x19, Heads - public byte[] unk3; // 0x1B, unknown, 10 bytes, zero-filled - public byte signature; // 0x25, 0x29 - public UInt32 unk4; // 0x26, unknown, zero-filled - public string vol_name; // 0x2A, 11 bytes, volume name, space-padded - public string fs_type; // 0x35, 8 bytes, "SOL_FS " - } - } + information = sb.ToString(); + } + + public struct SolarOSParameterBlock + { + public byte[] x86_jump; + // 0x00, x86 jump (3 bytes), jumps to 0x60 + public string OEMName; + // 0x03, 8 bytes, "SOLAR_OS" + public UInt16 bps; + // 0x0B, Bytes per sector + public byte unk1; + // 0x0D, unknown, 0x01 + public UInt16 unk2; + // 0x0E, unknown, 0x0201 + public UInt16 root_ent; + // 0x10, Number of entries on root directory ? (no root directory found) + public UInt16 sectors; + // 0x12, Sectors in volume + public byte media; + // 0x14, Media descriptor + public UInt16 spfat; + // 0x15, Sectors per FAT ? (no FAT found) + public UInt16 sptrk; + // 0x17, Sectors per track + public UInt16 heads; + // 0x19, Heads + public byte[] unk3; + // 0x1B, unknown, 10 bytes, zero-filled + public byte signature; + // 0x25, 0x29 + public UInt32 unk4; + // 0x26, unknown, zero-filled + public string vol_name; + // 0x2A, 11 bytes, volume name, space-padded + public string fs_type; + // 0x35, 8 bytes, "SOL_FS " + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/SysV.cs b/FileSystemIDandChk/Plugins/SysV.cs index 2cb5b970..629dd958 100644 --- a/FileSystemIDandChk/Plugins/SysV.cs +++ b/FileSystemIDandChk/Plugins/SysV.cs @@ -1,41 +1,40 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class SysVfs : Plugin - { - private const UInt32 XENIX_MAGIC = 0x002B5544; - private const UInt32 XENIX_CIGAM = 0x44552B00; - private const UInt32 SYSV_MAGIC = 0xFD187E20; - private const UInt32 SYSV_CIGAM = 0xFD187E20; - // Rest have no magic. - // Per a Linux kernel, Coherent fs has following: - private const string COH_FNAME = "nonamexxxxx "; - private const string COH_FPACK = "nopackxxxxx\n"; - // SCO AFS - private const UInt16 SCO_NFREE = 0xFFFF; - // UNIX 7th Edition has nothing to detect it, so check for a valid filesystem is a must :( - private const UInt16 V7_NICINOD = 100; - private const UInt16 V7_NICFREE = 50; - private const UInt32 V7_MAXSIZE = 0x00FFFFFF; + class SysVfs : Plugin + { + const UInt32 XENIX_MAGIC = 0x002B5544; + const UInt32 XENIX_CIGAM = 0x44552B00; + const UInt32 SYSV_MAGIC = 0xFD187E20; + const UInt32 SYSV_CIGAM = 0xFD187E20; + // Rest have no magic. + // Per a Linux kernel, Coherent fs has following: + const string COH_FNAME = "nonamexxxxx "; + const string COH_FPACK = "nopackxxxxx\n"; + // SCO AFS + const UInt16 SCO_NFREE = 0xFFFF; + // UNIX 7th Edition has nothing to detect it, so check for a valid filesystem is a must :( + const UInt16 V7_NICINOD = 100; + const UInt16 V7_NICFREE = 50; + const UInt32 V7_MAXSIZE = 0x00FFFFFF; - public SysVfs(PluginBase Core) + public SysVfs(PluginBase Core) { - base.Name = "UNIX System V filesystem"; - base.PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); + Name = "UNIX System V filesystem"; + PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); } - - public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - UInt32 magic; - string s_fname, s_fpack; - UInt16 s_nfree, s_ninode; - UInt32 s_fsize; - /*for(int j = 0; j<=(br.BaseStream.Length/0x200); j++) + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) + { + UInt32 magic; + string s_fname, s_fpack; + UInt16 s_nfree, s_ninode; + UInt32 s_fsize; + + /*for(int j = 0; j<=(br.BaseStream.Length/0x200); j++) { br.BaseStream.Seek(offset + j*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location magic = br.ReadUInt32(); @@ -46,7 +45,7 @@ namespace FileSystemIDandChk.Plugins Console.WriteLine("0x{0:X8}: 0x{1:X8}", br.BaseStream.Position-4, magic); }*/ - /*UInt32 number; + /*UInt32 number; br.BaseStream.Seek(offset+0x3A00, SeekOrigin.Begin); while((br.BaseStream.Position) <= (offset+0x3C00)) { @@ -66,19 +65,19 @@ namespace FileSystemIDandChk.Plugins return false; // Superblock can start on 0x000, 0x200, 0x600 and 0x800, not aligned, so we assume 16 (128 bytes/sector) sectors as a safe value - for(int i = 0; i<=16; i++) - { + for (int i = 0; i <= 16; i++) + { byte[] sb_sector = imagePlugin.ReadSectors((ulong)i + partitionOffset, sb_size_in_sectors); magic = BitConverter.ToUInt32(sb_sector, 0x3F8); // XENIX magic location - if(magic == XENIX_MAGIC || magic == XENIX_CIGAM) - return true; + if (magic == XENIX_MAGIC || magic == XENIX_CIGAM) + return true; magic = BitConverter.ToUInt32(sb_sector, 0x1F8); // System V magic location - if(magic == SYSV_MAGIC || magic == SYSV_CIGAM) - return true; + if (magic == SYSV_MAGIC || magic == SYSV_CIGAM) + return true; byte[] coherent_string = new byte[6]; Array.Copy(sb_sector, 0x1E8, coherent_string, 0, 6); // Coherent UNIX s_fname location @@ -86,56 +85,54 @@ namespace FileSystemIDandChk.Plugins Array.Copy(sb_sector, 0x1EE, coherent_string, 0, 6); // Coherent UNIX s_fpack location s_fpack = StringHandlers.CToString(coherent_string); - if(s_fname == COH_FNAME || s_fpack == COH_FPACK) - return true; + if (s_fname == COH_FNAME || s_fpack == COH_FPACK) + return true; - // Now try to identify 7th edition + // Now try to identify 7th edition s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode - if(s_fsize > 0 && s_fsize < 0xFFFFFFFF && s_nfree > 0 && s_nfree < 0xFFFF && s_ninode > 0 && s_ninode < 0xFFFF) - { - if((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00) - { - // Byteswap - s_fsize = ((s_fsize & 0xFF)<<24) + ((s_fsize & 0xFF00)<<8) + ((s_fsize & 0xFF0000)>>8) + ((s_fsize & 0xFF000000)>>24); - s_nfree = (UInt16)(s_nfree>>8); - s_ninode = (UInt16)(s_ninode>>8); - } + if (s_fsize > 0 && s_fsize < 0xFFFFFFFF && s_nfree > 0 && s_nfree < 0xFFFF && s_ninode > 0 && s_ninode < 0xFFFF) + { + if ((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00) + { + // Byteswap + s_fsize = ((s_fsize & 0xFF) << 24) + ((s_fsize & 0xFF00) << 8) + ((s_fsize & 0xFF0000) >> 8) + ((s_fsize & 0xFF000000) >> 24); + s_nfree = (UInt16)(s_nfree >> 8); + s_ninode = (UInt16)(s_ninode >> 8); + } - if((s_fsize & 0xFF000000) == 0x00 && (s_nfree & 0xFF00) == 0x00 && (s_ninode & 0xFF00) == 0x00) - { - if(s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD) - { - if((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize())) - return true; - } - } - } - } + if ((s_fsize & 0xFF000000) == 0x00 && (s_nfree & 0xFF00) == 0x00 && (s_ninode & 0xFF00) == 0x00) + { + if (s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD) + { + if ((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize())) + return true; + } + } + } + } - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); - bool littleendian = true; + StringBuilder sb = new StringBuilder(); BigEndianBitConverter.IsLittleEndian = true; // Start in little endian until we know what are we handling here - int start; - UInt32 magic; - string s_fname, s_fpack; - UInt16 s_nfree, s_ninode; - UInt32 s_fsize; - bool xenix = false; - bool sysv = false; - bool sysvr2 = false; - bool sysvr4 = false; - bool sys7th = false; - bool coherent = false; + int start; + UInt32 magic; + string s_fname, s_fpack; + UInt16 s_nfree, s_ninode; + UInt32 s_fsize; + bool xenix = false; + bool sysv = false; + bool sysvr4 = false; + bool sys7th = false; + bool coherent = false; byte[] sb_sector; byte sb_size_in_sectors; @@ -145,38 +142,38 @@ namespace FileSystemIDandChk.Plugins sb_size_in_sectors = 1; // If not a single sector can store it // Superblock can start on 0x000, 0x200, 0x600 and 0x800, not aligned, so we assume 16 (128 bytes/sector) sectors as a safe value - for(start = 0; start<=16; start++) - { + for (start = 0; start <= 16; start++) + { sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors); magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8); // XENIX magic location - if(magic == XENIX_MAGIC) - { + if (magic == XENIX_MAGIC) + { BigEndianBitConverter.IsLittleEndian = true; // Little endian - xenix = true; - break; - } - else if(magic == XENIX_CIGAM) - { + xenix = true; + break; + } + if (magic == XENIX_CIGAM) + { BigEndianBitConverter.IsLittleEndian = false; // Big endian - xenix = true; - break; - } + xenix = true; + break; + } magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F8); // XENIX magic location - if(magic == SYSV_MAGIC) - { + if (magic == SYSV_MAGIC) + { BigEndianBitConverter.IsLittleEndian = true; // Little endian - sysv = true; - break; - } - else if(magic == SYSV_CIGAM) - { + sysv = true; + break; + } + if (magic == SYSV_CIGAM) + { BigEndianBitConverter.IsLittleEndian = false; // Big endian - sysv = true; - break; - } + sysv = true; + break; + } byte[] coherent_string = new byte[6]; Array.Copy(sb_sector, 0x1E8, coherent_string, 0, 6); // Coherent UNIX s_fname location @@ -184,51 +181,49 @@ namespace FileSystemIDandChk.Plugins Array.Copy(sb_sector, 0x1EE, coherent_string, 0, 6); // Coherent UNIX s_fpack location s_fpack = StringHandlers.CToString(coherent_string); - if(s_fname == COH_FNAME || s_fpack == COH_FPACK) - { + if (s_fname == COH_FNAME || s_fpack == COH_FPACK) + { BigEndianBitConverter.IsLittleEndian = true; // Coherent is in PDP endianness, use helper for that - coherent = true; - break; - } + coherent = true; + break; + } - // Now try to identify 7th edition + // Now try to identify 7th edition s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode - if(s_fsize > 0 && s_fsize < 0xFFFFFFFF && s_nfree > 0 && s_nfree < 0xFFFF && s_ninode > 0 && s_ninode < 0xFFFF) - { - bool byteswapped = false; - if((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00) - { - // Byteswap - s_fsize = ((s_fsize & 0xFF)<<24) + ((s_fsize & 0xFF00)<<8) + ((s_fsize & 0xFF0000)>>8) + ((s_fsize & 0xFF000000)>>24); - s_nfree = (UInt16)(s_nfree>>8); - s_ninode = (UInt16)(s_ninode>>8); - byteswapped = true; - } + if (s_fsize > 0 && s_fsize < 0xFFFFFFFF && s_nfree > 0 && s_nfree < 0xFFFF && s_ninode > 0 && s_ninode < 0xFFFF) + { + if ((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00) + { + // Byteswap + s_fsize = ((s_fsize & 0xFF) << 24) + ((s_fsize & 0xFF00) << 8) + ((s_fsize & 0xFF0000) >> 8) + ((s_fsize & 0xFF000000) >> 24); + s_nfree = (UInt16)(s_nfree >> 8); + s_ninode = (UInt16)(s_ninode >> 8); + } - if((s_fsize & 0xFF000000) == 0x00 && (s_nfree & 0xFF00) == 0x00 && (s_ninode & 0xFF00) == 0x00) - { - if(s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD) - { - if((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize())) - { - sys7th = true; + if ((s_fsize & 0xFF000000) == 0x00 && (s_nfree & 0xFF00) == 0x00 && (s_ninode & 0xFF00) == 0x00) + { + if (s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD) + { + if ((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize())) + { + sys7th = true; BigEndianBitConverter.IsLittleEndian = true; - break; - } - } - } - } - } - if(!sys7th && !sysv && !coherent && !xenix) - return; + break; + } + } + } + } + } + if (!sys7th && !sysv && !coherent && !xenix) + return; - if(xenix) - { + if (xenix) + { byte[] xenix_strings = new byte[6]; - XenixSuperBlock xnx_sb = new XenixSuperBlock(); + XenixSuperBlock xnx_sb = new XenixSuperBlock(); sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors); xnx_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000); @@ -254,25 +249,25 @@ namespace FileSystemIDandChk.Plugins xnx_sb.s_magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8); xnx_sb.s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x3FC); - UInt32 bs = 512; - sb.AppendLine("XENIX filesystem"); - switch(xnx_sb.s_type) - { - case 1: - sb.AppendLine("512 bytes per block"); - break; - case 2: - sb.AppendLine("1024 bytes per block"); - bs=1024; - break; - case 3: - sb.AppendLine("2048 bytes per block"); - bs=2048; - break; - default: - sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine(); - break; - } + UInt32 bs = 512; + sb.AppendLine("XENIX filesystem"); + switch (xnx_sb.s_type) + { + case 1: + sb.AppendLine("512 bytes per block"); + break; + case 2: + sb.AppendLine("1024 bytes per block"); + bs = 1024; + break; + case 3: + sb.AppendLine("2048 bytes per block"); + bs = 2048; + break; + default: + sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine(); + break; + } if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) { if (bs != 2048) @@ -283,49 +278,45 @@ namespace FileSystemIDandChk.Plugins if (bs != imagePlugin.GetSectorSize()) sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", bs, imagePlugin.GetSectorSize()).AppendLine(); } - sb.AppendFormat("{0} zones on volume ({1} bytes)", xnx_sb.s_fsize, xnx_sb.s_fsize*bs).AppendLine(); - sb.AppendFormat("{0} free zones on volume ({1} bytes)", xnx_sb.s_tfree, xnx_sb.s_tfree*bs).AppendLine(); - sb.AppendFormat("{0} free blocks on list ({1} bytes)", xnx_sb.s_nfree, xnx_sb.s_nfree*bs).AppendLine(); - sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", xnx_sb.s_cylblks, xnx_sb.s_cylblks*bs).AppendLine(); - sb.AppendFormat("{0} blocks per gap ({1} bytes)", xnx_sb.s_gapblks, xnx_sb.s_gapblks*bs).AppendLine(); - sb.AppendFormat("First data zone: {0}", xnx_sb.s_isize).AppendLine(); - sb.AppendFormat("{0} free inodes on volume", xnx_sb.s_tinode).AppendLine(); - sb.AppendFormat("{0} free inodes on list", xnx_sb.s_ninode).AppendLine(); - if(xnx_sb.s_flock > 0) - sb.AppendLine("Free block list is locked"); - if(xnx_sb.s_ilock > 0) - sb.AppendLine("inode cache is locked"); - if(xnx_sb.s_fmod > 0) - sb.AppendLine("Superblock is being modified"); - if(xnx_sb.s_ronly > 0) - sb.AppendLine("Volume is mounted read-only"); - sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(xnx_sb.s_time)).AppendLine(); - sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine(); - sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine(); - if(xnx_sb.s_clean == 0x46) - sb.AppendLine("Volume is clean"); - else - sb.AppendLine("Volume is dirty"); - } + sb.AppendFormat("{0} zones on volume ({1} bytes)", xnx_sb.s_fsize, xnx_sb.s_fsize * bs).AppendLine(); + sb.AppendFormat("{0} free zones on volume ({1} bytes)", xnx_sb.s_tfree, xnx_sb.s_tfree * bs).AppendLine(); + sb.AppendFormat("{0} free blocks on list ({1} bytes)", xnx_sb.s_nfree, xnx_sb.s_nfree * bs).AppendLine(); + sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", xnx_sb.s_cylblks, xnx_sb.s_cylblks * bs).AppendLine(); + sb.AppendFormat("{0} blocks per gap ({1} bytes)", xnx_sb.s_gapblks, xnx_sb.s_gapblks * bs).AppendLine(); + sb.AppendFormat("First data zone: {0}", xnx_sb.s_isize).AppendLine(); + sb.AppendFormat("{0} free inodes on volume", xnx_sb.s_tinode).AppendLine(); + sb.AppendFormat("{0} free inodes on list", xnx_sb.s_ninode).AppendLine(); + if (xnx_sb.s_flock > 0) + sb.AppendLine("Free block list is locked"); + if (xnx_sb.s_ilock > 0) + sb.AppendLine("inode cache is locked"); + if (xnx_sb.s_fmod > 0) + sb.AppendLine("Superblock is being modified"); + if (xnx_sb.s_ronly > 0) + sb.AppendLine("Volume is mounted read-only"); + sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(xnx_sb.s_time)).AppendLine(); + sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine(); + sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine(); + if (xnx_sb.s_clean == 0x46) + sb.AppendLine("Volume is clean"); + else + sb.AppendLine("Volume is dirty"); + } - if(sysv) - { + if (sysv) + { sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors); - UInt16 pad0, pad1, pad2, pad3; + UInt16 pad0, pad1, pad2; byte[] sysv_strings = new byte[6]; pad0 = BigEndianBitConverter.ToUInt16(sb_sector, 0x002); // First padding pad1 = BigEndianBitConverter.ToUInt16(sb_sector, 0x00A); // Second padding pad2 = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D6); // Third padding - pad3 = BigEndianBitConverter.ToUInt16(sb_sector, 0x1B6); // Fourth padding - // This detection is not working as expected - if(pad0 == 0 && pad1 == 0 && pad2 == 0) - sysvr4 = true; - else - sysvr2 = true; + // This detection is not working as expected + sysvr4 |= pad0 == 0 && pad1 == 0 && pad2 == 0; - SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock(); + SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock(); // Common offsets sysv_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000); @@ -376,28 +367,28 @@ namespace FileSystemIDandChk.Plugins sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings); } - UInt32 bs = 512; - if(sysvr4) - sb.AppendLine("System V Release 4 filesystem"); - else - sb.AppendLine("System V Release 2 filesystem"); - switch(sysv_sb.s_type) - { - case 1: - sb.AppendLine("512 bytes per block"); - break; - case 2: - sb.AppendLine("1024 bytes per block"); - bs = 1024; - break; - case 3: - sb.AppendLine("2048 bytes per block"); - bs = 2048; - break; - default: - sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine(); - break; - } + UInt32 bs = 512; + if (sysvr4) + sb.AppendLine("System V Release 4 filesystem"); + else + sb.AppendLine("System V Release 2 filesystem"); + switch (sysv_sb.s_type) + { + case 1: + sb.AppendLine("512 bytes per block"); + break; + case 2: + sb.AppendLine("1024 bytes per block"); + bs = 1024; + break; + case 3: + sb.AppendLine("2048 bytes per block"); + bs = 2048; + break; + default: + sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine(); + break; + } if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) { if (bs != 2048) @@ -408,35 +399,35 @@ namespace FileSystemIDandChk.Plugins if (bs != imagePlugin.GetSectorSize()) sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", bs, imagePlugin.GetSectorSize()).AppendLine(); } - sb.AppendFormat("{0} zones on volume ({1} bytes)", sysv_sb.s_fsize, sysv_sb.s_fsize*bs).AppendLine(); - sb.AppendFormat("{0} free zones on volume ({1} bytes)", sysv_sb.s_tfree, sysv_sb.s_tfree*bs).AppendLine(); - sb.AppendFormat("{0} free blocks on list ({1} bytes)", sysv_sb.s_nfree, sysv_sb.s_nfree*bs).AppendLine(); - sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", sysv_sb.s_cylblks, sysv_sb.s_cylblks*bs).AppendLine(); - sb.AppendFormat("{0} blocks per gap ({1} bytes)", sysv_sb.s_gapblks, sysv_sb.s_gapblks*bs).AppendLine(); - sb.AppendFormat("First data zone: {0}", sysv_sb.s_isize).AppendLine(); - sb.AppendFormat("{0} free inodes on volume", sysv_sb.s_tinode).AppendLine(); - sb.AppendFormat("{0} free inodes on list", sysv_sb.s_ninode).AppendLine(); - if(sysv_sb.s_flock > 0) - sb.AppendLine("Free block list is locked"); - if(sysv_sb.s_ilock > 0) - sb.AppendLine("inode cache is locked"); - if(sysv_sb.s_fmod > 0) - sb.AppendLine("Superblock is being modified"); - if(sysv_sb.s_ronly > 0) - sb.AppendLine("Volume is mounted read-only"); - sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time)).AppendLine(); - sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine(); - sb.AppendFormat("Pack name: {0}", sysv_sb.s_fpack).AppendLine(); - if(sysv_sb.s_state == (0x7C269D38 - sysv_sb.s_time)) - sb.AppendLine("Volume is clean"); - else - sb.AppendLine("Volume is dirty"); - } + sb.AppendFormat("{0} zones on volume ({1} bytes)", sysv_sb.s_fsize, sysv_sb.s_fsize * bs).AppendLine(); + sb.AppendFormat("{0} free zones on volume ({1} bytes)", sysv_sb.s_tfree, sysv_sb.s_tfree * bs).AppendLine(); + sb.AppendFormat("{0} free blocks on list ({1} bytes)", sysv_sb.s_nfree, sysv_sb.s_nfree * bs).AppendLine(); + sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", sysv_sb.s_cylblks, sysv_sb.s_cylblks * bs).AppendLine(); + sb.AppendFormat("{0} blocks per gap ({1} bytes)", sysv_sb.s_gapblks, sysv_sb.s_gapblks * bs).AppendLine(); + sb.AppendFormat("First data zone: {0}", sysv_sb.s_isize).AppendLine(); + sb.AppendFormat("{0} free inodes on volume", sysv_sb.s_tinode).AppendLine(); + sb.AppendFormat("{0} free inodes on list", sysv_sb.s_ninode).AppendLine(); + if (sysv_sb.s_flock > 0) + sb.AppendLine("Free block list is locked"); + if (sysv_sb.s_ilock > 0) + sb.AppendLine("inode cache is locked"); + if (sysv_sb.s_fmod > 0) + sb.AppendLine("Superblock is being modified"); + if (sysv_sb.s_ronly > 0) + sb.AppendLine("Volume is mounted read-only"); + sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time)).AppendLine(); + sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine(); + sb.AppendFormat("Pack name: {0}", sysv_sb.s_fpack).AppendLine(); + if (sysv_sb.s_state == (0x7C269D38 - sysv_sb.s_time)) + sb.AppendLine("Volume is clean"); + else + sb.AppendLine("Volume is dirty"); + } - if(coherent) - { + if (coherent) + { sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors); - CoherentSuperBlock coh_sb = new CoherentSuperBlock(); + CoherentSuperBlock coh_sb = new CoherentSuperBlock(); byte[] coh_strings = new byte[6]; coh_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000); @@ -457,30 +448,30 @@ namespace FileSystemIDandChk.Plugins Array.Copy(sb_sector, 0x1EE, coh_strings, 0, 6); coh_sb.s_fpack = StringHandlers.CToString(coh_strings); - sb.AppendLine("Coherent UNIX filesystem"); + sb.AppendLine("Coherent UNIX filesystem"); if (imagePlugin.GetSectorSize() != 512) sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", 512, 2048).AppendLine(); - sb.AppendFormat("{0} zones on volume ({1} bytes)", coh_sb.s_fsize, coh_sb.s_fsize*512).AppendLine(); - sb.AppendFormat("{0} free zones on volume ({1} bytes)", coh_sb.s_tfree, coh_sb.s_tfree*512).AppendLine(); - sb.AppendFormat("{0} free blocks on list ({1} bytes)", coh_sb.s_nfree, coh_sb.s_nfree*512).AppendLine(); - sb.AppendFormat("First data zone: {0}", coh_sb.s_isize).AppendLine(); - sb.AppendFormat("{0} free inodes on volume", coh_sb.s_tinode).AppendLine(); - sb.AppendFormat("{0} free inodes on list", coh_sb.s_ninode).AppendLine(); - if(coh_sb.s_flock > 0) - sb.AppendLine("Free block list is locked"); - if(coh_sb.s_ilock > 0) - sb.AppendLine("inode cache is locked"); - if(coh_sb.s_fmod > 0) - sb.AppendLine("Superblock is being modified"); - if(coh_sb.s_ronly > 0) - sb.AppendLine("Volume is mounted read-only"); - sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time)).AppendLine(); - sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine(); - sb.AppendFormat("Pack name: {0}", coh_sb.s_fpack).AppendLine(); - } + sb.AppendFormat("{0} zones on volume ({1} bytes)", coh_sb.s_fsize, coh_sb.s_fsize * 512).AppendLine(); + sb.AppendFormat("{0} free zones on volume ({1} bytes)", coh_sb.s_tfree, coh_sb.s_tfree * 512).AppendLine(); + sb.AppendFormat("{0} free blocks on list ({1} bytes)", coh_sb.s_nfree, coh_sb.s_nfree * 512).AppendLine(); + sb.AppendFormat("First data zone: {0}", coh_sb.s_isize).AppendLine(); + sb.AppendFormat("{0} free inodes on volume", coh_sb.s_tinode).AppendLine(); + sb.AppendFormat("{0} free inodes on list", coh_sb.s_ninode).AppendLine(); + if (coh_sb.s_flock > 0) + sb.AppendLine("Free block list is locked"); + if (coh_sb.s_ilock > 0) + sb.AppendLine("inode cache is locked"); + if (coh_sb.s_fmod > 0) + sb.AppendLine("Superblock is being modified"); + if (coh_sb.s_ronly > 0) + sb.AppendLine("Volume is mounted read-only"); + sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time)).AppendLine(); + sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine(); + sb.AppendFormat("Pack name: {0}", coh_sb.s_fpack).AppendLine(); + } - if(sys7th) - { + if (sys7th) + { sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors); UNIX7thEditionSuperBlock v7_sb = new UNIX7thEditionSuperBlock(); byte[] sys7_strings = new byte[6]; @@ -503,169 +494,277 @@ namespace FileSystemIDandChk.Plugins Array.Copy(sb_sector, 0x1B2, sys7_strings, 0, 6); v7_sb.s_fpack = StringHandlers.CToString(sys7_strings); - sb.AppendLine("UNIX 7th Edition filesystem"); + sb.AppendLine("UNIX 7th Edition filesystem"); if (imagePlugin.GetSectorSize() != 512) sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", 512, 2048).AppendLine(); - sb.AppendFormat("{0} zones on volume ({1} bytes)", v7_sb.s_fsize, v7_sb.s_fsize*512).AppendLine(); - sb.AppendFormat("{0} free zones on volume ({1} bytes)", v7_sb.s_tfree, v7_sb.s_tfree*512).AppendLine(); - sb.AppendFormat("{0} free blocks on list ({1} bytes)", v7_sb.s_nfree, v7_sb.s_nfree*512).AppendLine(); - sb.AppendFormat("First data zone: {0}", v7_sb.s_isize).AppendLine(); - sb.AppendFormat("{0} free inodes on volume", v7_sb.s_tinode).AppendLine(); - sb.AppendFormat("{0} free inodes on list", v7_sb.s_ninode).AppendLine(); - if(v7_sb.s_flock > 0) - sb.AppendLine("Free block list is locked"); - if(v7_sb.s_ilock > 0) - sb.AppendLine("inode cache is locked"); - if(v7_sb.s_fmod > 0) - sb.AppendLine("Superblock is being modified"); - if(v7_sb.s_ronly > 0) - sb.AppendLine("Volume is mounted read-only"); - sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time)).AppendLine(); - sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine(); - sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine(); - } + sb.AppendFormat("{0} zones on volume ({1} bytes)", v7_sb.s_fsize, v7_sb.s_fsize * 512).AppendLine(); + sb.AppendFormat("{0} free zones on volume ({1} bytes)", v7_sb.s_tfree, v7_sb.s_tfree * 512).AppendLine(); + sb.AppendFormat("{0} free blocks on list ({1} bytes)", v7_sb.s_nfree, v7_sb.s_nfree * 512).AppendLine(); + sb.AppendFormat("First data zone: {0}", v7_sb.s_isize).AppendLine(); + sb.AppendFormat("{0} free inodes on volume", v7_sb.s_tinode).AppendLine(); + sb.AppendFormat("{0} free inodes on list", v7_sb.s_ninode).AppendLine(); + if (v7_sb.s_flock > 0) + sb.AppendLine("Free block list is locked"); + if (v7_sb.s_ilock > 0) + sb.AppendLine("inode cache is locked"); + if (v7_sb.s_fmod > 0) + sb.AppendLine("Superblock is being modified"); + if (v7_sb.s_ronly > 0) + sb.AppendLine("Volume is mounted read-only"); + sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time)).AppendLine(); + sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine(); + sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine(); + } - information = sb.ToString(); + information = sb.ToString(); BigEndianBitConverter.IsLittleEndian = false; // Return to default (bigendian) - } + } - private struct XenixSuperBlock - { - public UInt16 s_isize; // 0x000, index of first data zone - public UInt32 s_fsize; // 0x002, total number of zones of this volume - // the start of the free block list: - public UInt16 s_nfree; // 0x006, blocks in s_free, <=100 - public UInt32[] s_free; // 0x008, 100 entries, first free block list chunk - // the cache of free inodes: - public UInt16 s_ninode; // 0x198, number of inodes in s_inode, <= 100 - public UInt16[] s_inode; // 0x19A, 100 entries, some free inodes - public byte s_flock; // 0x262, free block list manipulation lock - public byte s_ilock; // 0x263, inode cache manipulation lock - public byte s_fmod; // 0x264, superblock modification flag - public byte s_ronly; // 0x265, read-only mounted flag - public UInt32 s_time; // 0x266, time of last superblock update - public UInt32 s_tfree; // 0x26A, total number of free zones - public UInt16 s_tinode; // 0x26E, total number of free inodes - public UInt16 s_cylblks; // 0x270, blocks per cylinder - public UInt16 s_gapblks; // 0x272, blocks per gap - public UInt16 s_dinfo0; // 0x274, device information ?? - public UInt16 s_dinfo1; // 0x276, device information ?? - public string s_fname; // 0x278, 6 bytes, volume name - public string s_fpack; // 0x27E, 6 bytes, pack name - public byte s_clean; // 0x284, 0x46 if volume is clean - public byte[] s_fill; // 0x285, 371 bytes - public UInt32 s_magic; // 0x3F8, magic - public UInt32 s_type; // 0x3FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk, 3 = 2048 bytes/blk) - } + struct XenixSuperBlock + { + public UInt16 s_isize; + // 0x000, index of first data zone + public UInt32 s_fsize; + // 0x002, total number of zones of this volume + // the start of the free block list: + public UInt16 s_nfree; + // 0x006, blocks in s_free, <=100 + public UInt32[] s_free; + // 0x008, 100 entries, first free block list chunk + // the cache of free inodes: + public UInt16 s_ninode; + // 0x198, number of inodes in s_inode, <= 100 + public UInt16[] s_inode; + // 0x19A, 100 entries, some free inodes + public byte s_flock; + // 0x262, free block list manipulation lock + public byte s_ilock; + // 0x263, inode cache manipulation lock + public byte s_fmod; + // 0x264, superblock modification flag + public byte s_ronly; + // 0x265, read-only mounted flag + public UInt32 s_time; + // 0x266, time of last superblock update + public UInt32 s_tfree; + // 0x26A, total number of free zones + public UInt16 s_tinode; + // 0x26E, total number of free inodes + public UInt16 s_cylblks; + // 0x270, blocks per cylinder + public UInt16 s_gapblks; + // 0x272, blocks per gap + public UInt16 s_dinfo0; + // 0x274, device information ?? + public UInt16 s_dinfo1; + // 0x276, device information ?? + public string s_fname; + // 0x278, 6 bytes, volume name + public string s_fpack; + // 0x27E, 6 bytes, pack name + public byte s_clean; + // 0x284, 0x46 if volume is clean + public byte[] s_fill; + // 0x285, 371 bytes + public UInt32 s_magic; + // 0x3F8, magic + public UInt32 s_type; + // 0x3FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk, 3 = 2048 bytes/blk) + } - private struct SystemVRelease4SuperBlock - { - public UInt16 s_isize; // 0x000, index of first data zone - public UInt16 s_pad0; // 0x002, padding - public UInt32 s_fsize; // 0x004, total number of zones of this volume - // the start of the free block list: - public UInt16 s_nfree; // 0x008, blocks in s_free, <=100 - public UInt16 s_pad1; // 0x00A, padding - public UInt32[] s_free; // 0x00C, 50 entries, first free block list chunk - // the cache of free inodes: - public UInt16 s_ninode; // 0x0D4, number of inodes in s_inode, <= 100 - public UInt16 s_pad2; // 0x0D6, padding - public UInt16[] s_inode; // 0x0D8, 100 entries, some free inodes - public byte s_flock; // 0x1A0, free block list manipulation lock - public byte s_ilock; // 0x1A1, inode cache manipulation lock - public byte s_fmod; // 0x1A2, superblock modification flag - public byte s_ronly; // 0x1A3, read-only mounted flag - public UInt32 s_time; // 0x1A4, time of last superblock update - public UInt16 s_cylblks; // 0x1A8, blocks per cylinder - public UInt16 s_gapblks; // 0x1AA, blocks per gap - public UInt16 s_dinfo0; // 0x1AC, device information ?? - public UInt16 s_dinfo1; // 0x1AE, device information ?? - public UInt32 s_tfree; // 0x1B0, total number of free zones - public UInt16 s_tinode; // 0x1B4, total number of free inodes - public UInt16 s_pad3; // 0x1B6, padding - public string s_fname; // 0x1B8, 6 bytes, volume name - public string s_fpack; // 0x1BE, 6 bytes, pack name - public byte[] s_fill; // 0x1C4, 48 bytes - public UInt32 s_state; // 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean - public UInt32 s_magic; // 0x1F8, magic - public UInt32 s_type; // 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk) - } + struct SystemVRelease4SuperBlock + { + public UInt16 s_isize; + // 0x000, index of first data zone + public UInt16 s_pad0; + // 0x002, padding + public UInt32 s_fsize; + // 0x004, total number of zones of this volume + // the start of the free block list: + public UInt16 s_nfree; + // 0x008, blocks in s_free, <=100 + public UInt16 s_pad1; + // 0x00A, padding + public UInt32[] s_free; + // 0x00C, 50 entries, first free block list chunk + // the cache of free inodes: + public UInt16 s_ninode; + // 0x0D4, number of inodes in s_inode, <= 100 + public UInt16 s_pad2; + // 0x0D6, padding + public UInt16[] s_inode; + // 0x0D8, 100 entries, some free inodes + public byte s_flock; + // 0x1A0, free block list manipulation lock + public byte s_ilock; + // 0x1A1, inode cache manipulation lock + public byte s_fmod; + // 0x1A2, superblock modification flag + public byte s_ronly; + // 0x1A3, read-only mounted flag + public UInt32 s_time; + // 0x1A4, time of last superblock update + public UInt16 s_cylblks; + // 0x1A8, blocks per cylinder + public UInt16 s_gapblks; + // 0x1AA, blocks per gap + public UInt16 s_dinfo0; + // 0x1AC, device information ?? + public UInt16 s_dinfo1; + // 0x1AE, device information ?? + public UInt32 s_tfree; + // 0x1B0, total number of free zones + public UInt16 s_tinode; + // 0x1B4, total number of free inodes + public UInt16 s_pad3; + // 0x1B6, padding + public string s_fname; + // 0x1B8, 6 bytes, volume name + public string s_fpack; + // 0x1BE, 6 bytes, pack name + public byte[] s_fill; + // 0x1C4, 48 bytes + public UInt32 s_state; + // 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean + public UInt32 s_magic; + // 0x1F8, magic + public UInt32 s_type; + // 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk) + } - private struct SystemVRelease2SuperBlock - { - public UInt16 s_isize; // 0x000, index of first data zone - public UInt32 s_fsize; // 0x002, total number of zones of this volume - // the start of the free block list: - public UInt16 s_nfree; // 0x006, blocks in s_free, <=100 - public UInt32[] s_free; // 0x008, 50 entries, first free block list chunk - // the cache of free inodes: - public UInt16 s_ninode; // 0x0D0, number of inodes in s_inode, <= 100 - public UInt16[] s_inode; // 0x0D2, 100 entries, some free inodes - public byte s_flock; // 0x19A, free block list manipulation lock - public byte s_ilock; // 0x19B, inode cache manipulation lock - public byte s_fmod; // 0x19C, superblock modification flag - public byte s_ronly; // 0x19D, read-only mounted flag - public UInt32 s_time; // 0x19E, time of last superblock update - public UInt16 s_cylblks; // 0x1A2, blocks per cylinder - public UInt16 s_gapblks; // 0x1A4, blocks per gap - public UInt16 s_dinfo0; // 0x1A6, device information ?? - public UInt16 s_dinfo1; // 0x1A8, device information ?? - public UInt32 s_tfree; // 0x1AA, total number of free zones - public UInt16 s_tinode; // 0x1AE, total number of free inodes - public string s_fname; // 0x1B0, 6 bytes, volume name - public string s_fpack; // 0x1B6, 6 bytes, pack name - public byte[] s_fill; // 0x1BC, 56 bytes - public UInt32 s_state; // 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean - public UInt32 s_magic; // 0x1F8, magic - public UInt32 s_type; // 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk) - } + struct SystemVRelease2SuperBlock + { + public UInt16 s_isize; + // 0x000, index of first data zone + public UInt32 s_fsize; + // 0x002, total number of zones of this volume + // the start of the free block list: + public UInt16 s_nfree; + // 0x006, blocks in s_free, <=100 + public UInt32[] s_free; + // 0x008, 50 entries, first free block list chunk + // the cache of free inodes: + public UInt16 s_ninode; + // 0x0D0, number of inodes in s_inode, <= 100 + public UInt16[] s_inode; + // 0x0D2, 100 entries, some free inodes + public byte s_flock; + // 0x19A, free block list manipulation lock + public byte s_ilock; + // 0x19B, inode cache manipulation lock + public byte s_fmod; + // 0x19C, superblock modification flag + public byte s_ronly; + // 0x19D, read-only mounted flag + public UInt32 s_time; + // 0x19E, time of last superblock update + public UInt16 s_cylblks; + // 0x1A2, blocks per cylinder + public UInt16 s_gapblks; + // 0x1A4, blocks per gap + public UInt16 s_dinfo0; + // 0x1A6, device information ?? + public UInt16 s_dinfo1; + // 0x1A8, device information ?? + public UInt32 s_tfree; + // 0x1AA, total number of free zones + public UInt16 s_tinode; + // 0x1AE, total number of free inodes + public string s_fname; + // 0x1B0, 6 bytes, volume name + public string s_fpack; + // 0x1B6, 6 bytes, pack name + public byte[] s_fill; + // 0x1BC, 56 bytes + public UInt32 s_state; + // 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean + public UInt32 s_magic; + // 0x1F8, magic + public UInt32 s_type; + // 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk) + } - private struct UNIX7thEditionSuperBlock - { - public UInt16 s_isize; // 0x000, index of first data zone - public UInt32 s_fsize; // 0x002, total number of zones of this volume - // the start of the free block list: - public UInt16 s_nfree; // 0x006, blocks in s_free, <=100 - public UInt32[] s_free; // 0x008, 50 entries, first free block list chunk - // the cache of free inodes: - public UInt16 s_ninode; // 0x0D0, number of inodes in s_inode, <= 100 - public UInt16[] s_inode; // 0x0D2, 100 entries, some free inodes - public byte s_flock; // 0x19A, free block list manipulation lock - public byte s_ilock; // 0x19B, inode cache manipulation lock - public byte s_fmod; // 0x19C, superblock modification flag - public byte s_ronly; // 0x19D, read-only mounted flag - public UInt32 s_time; // 0x19E, time of last superblock update - public UInt32 s_tfree; // 0x1A2, total number of free zones - public UInt16 s_tinode; // 0x1A6, total number of free inodes - public UInt16 s_int_m; // 0x1A8, interleave factor - public UInt16 s_int_n; // 0x1AA, interleave factor - public string s_fname; // 0x1AC, 6 bytes, volume name - public string s_fpack; // 0x1B2, 6 bytes, pack name - } + struct UNIX7thEditionSuperBlock + { + public UInt16 s_isize; + // 0x000, index of first data zone + public UInt32 s_fsize; + // 0x002, total number of zones of this volume + // the start of the free block list: + public UInt16 s_nfree; + // 0x006, blocks in s_free, <=100 + public UInt32[] s_free; + // 0x008, 50 entries, first free block list chunk + // the cache of free inodes: + public UInt16 s_ninode; + // 0x0D0, number of inodes in s_inode, <= 100 + public UInt16[] s_inode; + // 0x0D2, 100 entries, some free inodes + public byte s_flock; + // 0x19A, free block list manipulation lock + public byte s_ilock; + // 0x19B, inode cache manipulation lock + public byte s_fmod; + // 0x19C, superblock modification flag + public byte s_ronly; + // 0x19D, read-only mounted flag + public UInt32 s_time; + // 0x19E, time of last superblock update + public UInt32 s_tfree; + // 0x1A2, total number of free zones + public UInt16 s_tinode; + // 0x1A6, total number of free inodes + public UInt16 s_int_m; + // 0x1A8, interleave factor + public UInt16 s_int_n; + // 0x1AA, interleave factor + public string s_fname; + // 0x1AC, 6 bytes, volume name + public string s_fpack; + // 0x1B2, 6 bytes, pack name + } - private struct CoherentSuperBlock - { - public UInt16 s_isize; // 0x000, index of first data zone - public UInt32 s_fsize; // 0x002, total number of zones of this volume - // the start of the free block list: - public UInt16 s_nfree; // 0x006, blocks in s_free, <=100 - public UInt32[] s_free; // 0x008, 64 entries, first free block list chunk - // the cache of free inodes: - public UInt16 s_ninode; // 0x108, number of inodes in s_inode, <= 100 - public UInt16[] s_inode; // 0x10A, 100 entries, some free inodes - public byte s_flock; // 0x1D2, free block list manipulation lock - public byte s_ilock; // 0x1D3, inode cache manipulation lock - public byte s_fmod; // 0x1D4, superblock modification flag - public byte s_ronly; // 0x1D5, read-only mounted flag - public UInt32 s_time; // 0x1D6, time of last superblock update - public UInt32 s_tfree; // 0x1DE, total number of free zones - public UInt16 s_tinode; // 0x1E2, total number of free inodes - public UInt16 s_int_m; // 0x1E4, interleave factor - public UInt16 s_int_n; // 0x1E6, interleave factor - public string s_fname; // 0x1E8, 6 bytes, volume name - public string s_fpack; // 0x1EE, 6 bytes, pack name - public UInt32 s_unique; // 0x1F4, zero-filled - } - } + struct CoherentSuperBlock + { + public UInt16 s_isize; + // 0x000, index of first data zone + public UInt32 s_fsize; + // 0x002, total number of zones of this volume + // the start of the free block list: + public UInt16 s_nfree; + // 0x006, blocks in s_free, <=100 + public UInt32[] s_free; + // 0x008, 64 entries, first free block list chunk + // the cache of free inodes: + public UInt16 s_ninode; + // 0x108, number of inodes in s_inode, <= 100 + public UInt16[] s_inode; + // 0x10A, 100 entries, some free inodes + public byte s_flock; + // 0x1D2, free block list manipulation lock + public byte s_ilock; + // 0x1D3, inode cache manipulation lock + public byte s_fmod; + // 0x1D4, superblock modification flag + public byte s_ronly; + // 0x1D5, read-only mounted flag + public UInt32 s_time; + // 0x1D6, time of last superblock update + public UInt32 s_tfree; + // 0x1DE, total number of free zones + public UInt16 s_tinode; + // 0x1E2, total number of free inodes + public UInt16 s_int_m; + // 0x1E4, interleave factor + public UInt16 s_int_n; + // 0x1E6, interleave factor + public string s_fname; + // 0x1E8, 6 bytes, volume name + public string s_fpack; + // 0x1EE, 6 bytes, pack name + public UInt32 s_unique; + // 0x1F4, zero-filled + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/UNIXBFS.cs b/FileSystemIDandChk/Plugins/UNIXBFS.cs index 19756e0b..425026d0 100644 --- a/FileSystemIDandChk/Plugins/UNIXBFS.cs +++ b/FileSystemIDandChk/Plugins/UNIXBFS.cs @@ -1,86 +1,91 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class BFS : Plugin - { - private const UInt32 BFS_MAGIC = 0x1BADFACE; + class BFS : Plugin + { + const UInt32 BFS_MAGIC = 0x1BADFACE; - public BFS(PluginBase Core) + public BFS(PluginBase Core) { - base.Name = "UNIX Boot filesystem"; - base.PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); + Name = "UNIX Boot filesystem"; + PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); } - + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - UInt32 magic; + { + UInt32 magic; - magic = BitConverter.ToUInt32 (imagePlugin.ReadSector (0 + partitionOffset), 0); + magic = BitConverter.ToUInt32(imagePlugin.ReadSector(0 + partitionOffset), 0); - if(magic == BFS_MAGIC) - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + return magic == BFS_MAGIC; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); - byte[] bfs_sb_sector = imagePlugin.ReadSector (0 + partitionOffset); - byte[] sb_strings = new byte[6]; + StringBuilder sb = new StringBuilder(); + byte[] bfs_sb_sector = imagePlugin.ReadSector(0 + partitionOffset); + byte[] sb_strings = new byte[6]; - BFSSuperBlock bfs_sb = new BFSSuperBlock(); + BFSSuperBlock bfs_sb = new BFSSuperBlock(); - bfs_sb.s_magic = BitConverter.ToUInt32 (bfs_sb_sector, 0x00); - bfs_sb.s_start = BitConverter.ToUInt32 (bfs_sb_sector, 0x04); - bfs_sb.s_end = BitConverter.ToUInt32 (bfs_sb_sector, 0x08); - bfs_sb.s_from = BitConverter.ToUInt32 (bfs_sb_sector, 0x0C); - bfs_sb.s_to = BitConverter.ToUInt32 (bfs_sb_sector, 0x10); - bfs_sb.s_bfrom = BitConverter.ToInt32 (bfs_sb_sector, 0x14); - bfs_sb.s_bto = BitConverter.ToInt32 (bfs_sb_sector, 0x18); - Array.Copy (bfs_sb_sector, 0x1C, sb_strings, 0, 6); - bfs_sb.s_fsname = StringHandlers.CToString(sb_strings); - Array.Copy (bfs_sb_sector, 0x22, sb_strings, 0, 6); - bfs_sb.s_volume = StringHandlers.CToString(sb_strings); + bfs_sb.s_magic = BitConverter.ToUInt32(bfs_sb_sector, 0x00); + bfs_sb.s_start = BitConverter.ToUInt32(bfs_sb_sector, 0x04); + bfs_sb.s_end = BitConverter.ToUInt32(bfs_sb_sector, 0x08); + bfs_sb.s_from = BitConverter.ToUInt32(bfs_sb_sector, 0x0C); + bfs_sb.s_to = BitConverter.ToUInt32(bfs_sb_sector, 0x10); + bfs_sb.s_bfrom = BitConverter.ToInt32(bfs_sb_sector, 0x14); + bfs_sb.s_bto = BitConverter.ToInt32(bfs_sb_sector, 0x18); + Array.Copy(bfs_sb_sector, 0x1C, sb_strings, 0, 6); + bfs_sb.s_fsname = StringHandlers.CToString(sb_strings); + Array.Copy(bfs_sb_sector, 0x22, sb_strings, 0, 6); + bfs_sb.s_volume = StringHandlers.CToString(sb_strings); - if(MainClass.isDebug) - { - Console.WriteLine("(BFS) bfs_sb.s_magic: 0x{0:X8}", bfs_sb.s_magic); - Console.WriteLine("(BFS) bfs_sb.s_start: 0x{0:X8}", bfs_sb.s_start); - Console.WriteLine("(BFS) bfs_sb.s_end: 0x{0:X8}", bfs_sb.s_end); - Console.WriteLine("(BFS) bfs_sb.s_from: 0x{0:X8}", bfs_sb.s_from); - Console.WriteLine("(BFS) bfs_sb.s_to: 0x{0:X8}", bfs_sb.s_to); - Console.WriteLine("(BFS) bfs_sb.s_bfrom: 0x{0:X8}", bfs_sb.s_bfrom); - Console.WriteLine("(BFS) bfs_sb.s_bto: 0x{0:X8}", bfs_sb.s_bto); - Console.WriteLine("(BFS) bfs_sb.s_fsname: 0x{0}", bfs_sb.s_fsname); - Console.WriteLine("(BFS) bfs_sb.s_volume: 0x{0}", bfs_sb.s_volume); - } + if (MainClass.isDebug) + { + Console.WriteLine("(BFS) bfs_sb.s_magic: 0x{0:X8}", bfs_sb.s_magic); + Console.WriteLine("(BFS) bfs_sb.s_start: 0x{0:X8}", bfs_sb.s_start); + Console.WriteLine("(BFS) bfs_sb.s_end: 0x{0:X8}", bfs_sb.s_end); + Console.WriteLine("(BFS) bfs_sb.s_from: 0x{0:X8}", bfs_sb.s_from); + Console.WriteLine("(BFS) bfs_sb.s_to: 0x{0:X8}", bfs_sb.s_to); + Console.WriteLine("(BFS) bfs_sb.s_bfrom: 0x{0:X8}", bfs_sb.s_bfrom); + Console.WriteLine("(BFS) bfs_sb.s_bto: 0x{0:X8}", bfs_sb.s_bto); + Console.WriteLine("(BFS) bfs_sb.s_fsname: 0x{0}", bfs_sb.s_fsname); + Console.WriteLine("(BFS) bfs_sb.s_volume: 0x{0}", bfs_sb.s_volume); + } - sb.AppendLine("UNIX Boot filesystem"); - sb.AppendFormat("Volume goes from byte {0} to byte {1}, for {2} bytes", bfs_sb.s_start, bfs_sb.s_end, bfs_sb.s_end-bfs_sb.s_start).AppendLine(); - sb.AppendFormat("Filesystem name: {0}", bfs_sb.s_fsname).AppendLine(); - sb.AppendFormat("Volume name: {0}", bfs_sb.s_volume).AppendLine(); + sb.AppendLine("UNIX Boot filesystem"); + sb.AppendFormat("Volume goes from byte {0} to byte {1}, for {2} bytes", bfs_sb.s_start, bfs_sb.s_end, bfs_sb.s_end - bfs_sb.s_start).AppendLine(); + sb.AppendFormat("Filesystem name: {0}", bfs_sb.s_fsname).AppendLine(); + sb.AppendFormat("Volume name: {0}", bfs_sb.s_volume).AppendLine(); - information = sb.ToString(); - } + information = sb.ToString(); + } - private struct BFSSuperBlock - { - public UInt32 s_magic; // 0x00, 0x1BADFACE - public UInt32 s_start; // 0x04, start in bytes of volume - public UInt32 s_end; // 0x08, end in bytes of volume - public UInt32 s_from; // 0x0C, unknown :p - public UInt32 s_to; // 0x10, unknown :p - public Int32 s_bfrom; // 0x14, unknown :p - public Int32 s_bto; // 0x18, unknown :p - public string s_fsname; // 0x1C, 6 bytes, filesystem name - public string s_volume; // 0x22, 6 bytes, volume name - } - } + struct BFSSuperBlock + { + public UInt32 s_magic; + // 0x00, 0x1BADFACE + public UInt32 s_start; + // 0x04, start in bytes of volume + public UInt32 s_end; + // 0x08, end in bytes of volume + public UInt32 s_from; + // 0x0C, unknown :p + public UInt32 s_to; + // 0x10, unknown :p + public Int32 s_bfrom; + // 0x14, unknown :p + public Int32 s_bto; + // 0x18, unknown :p + public string s_fsname; + // 0x1C, 6 bytes, filesystem name + public string s_volume; + // 0x22, 6 bytes, volume name + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/ext2FS.cs b/FileSystemIDandChk/Plugins/ext2FS.cs index 2fa866d5..98818fe3 100644 --- a/FileSystemIDandChk/Plugins/ext2FS.cs +++ b/FileSystemIDandChk/Plugins/ext2FS.cs @@ -1,729 +1,836 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class ext2FS : Plugin - { - public ext2FS(PluginBase Core) + class ext2FS : Plugin + { + public ext2FS(PluginBase Core) { - base.Name = "Linux extended Filesystem 2, 3 and 4"; - base.PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); + Name = "Linux extended Filesystem 2, 3 and 4"; + PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); } - - public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - byte[] sb_sector = imagePlugin.ReadSector (2 + partitionOffset); - UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038); + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) + { + byte[] sb_sector = imagePlugin.ReadSector(2 + partitionOffset); + + UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038); - if(magic == ext2FSMagic || magic == ext2OldFSMagic) - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + if (magic == ext2FSMagic || magic == ext2OldFSMagic) + return true; + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - ext2FSSuperBlock supblk = new ext2FSSuperBlock(); - byte[] forstrings; - bool old_ext2 = false; - bool new_ext2 = false; - bool ext3 = false; - bool ext4 = false; + ext2FSSuperBlock supblk = new ext2FSSuperBlock(); + byte[] forstrings; + bool new_ext2 = false; + bool ext3 = false; + bool ext4 = false; - byte[] guid_a = new byte[16]; - byte[] guid_b = new byte[16]; + byte[] guid_a = new byte[16]; + byte[] guid_b = new byte[16]; - uint sb_size_in_sectors = 0; + uint sb_size_in_sectors; - if (imagePlugin.GetSectorSize () < 1024) - sb_size_in_sectors = 1024 / imagePlugin.GetSectorSize (); - else - sb_size_in_sectors = 1; + if (imagePlugin.GetSectorSize() < 1024) + sb_size_in_sectors = 1024 / imagePlugin.GetSectorSize(); + else + sb_size_in_sectors = 1; - if (sb_size_in_sectors == 0) { - information = "Error calculating size in sectors of ext2/3/4 superblocks"; - return; - } + if (sb_size_in_sectors == 0) + { + information = "Error calculating size in sectors of ext2/3/4 superblocks"; + return; + } - byte[] sb_sector = imagePlugin.ReadSectors (2 + partitionOffset, sb_size_in_sectors); - supblk.inodes = BitConverter.ToUInt32 (sb_sector, 0x000); - supblk.blocks = BitConverter.ToUInt32 (sb_sector, 0x004); - supblk.reserved_blocks = BitConverter.ToUInt32 (sb_sector, 0x008); - supblk.free_blocks = BitConverter.ToUInt32 (sb_sector, 0x00C); - supblk.free_inodes = BitConverter.ToUInt32 (sb_sector, 0x010); - supblk.first_block = BitConverter.ToUInt32 (sb_sector, 0x014); - supblk.block_size = BitConverter.ToUInt32 (sb_sector, 0x018); - supblk.frag_size = BitConverter.ToInt32 (sb_sector, 0x01C); - supblk.blocks_per_grp = BitConverter.ToUInt32 (sb_sector, 0x020); - supblk.flags_per_grp = BitConverter.ToUInt32 (sb_sector, 0x024); - supblk.inodes_per_grp = BitConverter.ToUInt32 (sb_sector, 0x028); - supblk.mount_t = BitConverter.ToUInt32 (sb_sector, 0x02C); - supblk.write_t = BitConverter.ToUInt32 (sb_sector, 0x030); - supblk.mount_c = BitConverter.ToUInt16 (sb_sector, 0x034); - supblk.max_mount_c = BitConverter.ToInt16 (sb_sector, 0x036); - supblk.magic = BitConverter.ToUInt16 (sb_sector, 0x038); - supblk.state = BitConverter.ToUInt16 (sb_sector, 0x03A); - supblk.err_behaviour = BitConverter.ToUInt16 (sb_sector, 0x03C); - supblk.minor_revision = BitConverter.ToUInt16 (sb_sector, 0x03E); - supblk.check_t = BitConverter.ToUInt32 (sb_sector, 0x040); - supblk.check_inv = BitConverter.ToUInt32 (sb_sector, 0x044); - // From 0.5a onward - supblk.creator_os = BitConverter.ToUInt32 (sb_sector, 0x048); - supblk.revision = BitConverter.ToUInt32 (sb_sector, 0x04C); - supblk.default_uid = BitConverter.ToUInt16 (sb_sector, 0x050); - supblk.default_gid = BitConverter.ToUInt16 (sb_sector, 0x052); - // From 0.5b onward - supblk.first_inode = BitConverter.ToUInt32 (sb_sector, 0x054); - supblk.inode_size = BitConverter.ToUInt16 (sb_sector, 0x058); - supblk.block_group_no = BitConverter.ToUInt16 (sb_sector, 0x05A); - supblk.ftr_compat = BitConverter.ToUInt32 (sb_sector, 0x05C); - supblk.ftr_incompat = BitConverter.ToUInt32 (sb_sector, 0x060); - supblk.ftr_ro_compat = BitConverter.ToUInt32 (sb_sector, 0x064); - // Volume UUID - Array.Copy (sb_sector, 0x068, guid_a, 0, 16); - guid_b[0] = guid_a[3]; - guid_b[1] = guid_a[2]; - guid_b[2] = guid_a[1]; - guid_b[3] = guid_a[0]; - guid_b[4] = guid_a[5]; - guid_b[5] = guid_a[4]; - guid_b[6] = guid_a[7]; - guid_b[7] = guid_a[6]; - guid_b[8] = guid_a[8]; - guid_b[9] = guid_a[9]; - guid_b[10] = guid_a[10]; - guid_b[11] = guid_a[11]; - guid_b[12] = guid_a[12]; - guid_b[13] = guid_a[13]; - guid_b[14] = guid_a[14]; - guid_b[15] = guid_a[15]; - supblk.uuid = new Guid(guid_b); - // End of volume UUID - forstrings = new byte[16]; - Array.Copy (sb_sector, 0x078, forstrings, 0, 16); - supblk.volume_name = StringHandlers.CToString(forstrings); - forstrings = new byte[64]; - Array.Copy (sb_sector, 0x088, forstrings, 0, 64); - supblk.last_mount_dir = StringHandlers.CToString(forstrings); - supblk.algo_usage_bmp = BitConverter.ToUInt32 (sb_sector, 0x0C8); - supblk.prealloc_blks = sb_sector[0x0CC]; - supblk.prealloc_dir_blks = sb_sector[0x0CD]; - supblk.rsrvd_gdt_blocks = BitConverter.ToUInt16 (sb_sector, 0x0CE); - // ext3 - Array.Copy (sb_sector, 0x0D0, guid_a, 0, 16); - guid_b[0] = guid_a[3]; - guid_b[1] = guid_a[2]; - guid_b[2] = guid_a[1]; - guid_b[3] = guid_a[0]; - guid_b[4] = guid_a[5]; - guid_b[5] = guid_a[4]; - guid_b[6] = guid_a[7]; - guid_b[7] = guid_a[6]; - guid_b[8] = guid_a[8]; - guid_b[9] = guid_a[9]; - guid_b[10] = guid_a[10]; - guid_b[11] = guid_a[11]; - guid_b[12] = guid_a[12]; - guid_b[13] = guid_a[13]; - guid_b[14] = guid_a[14]; - guid_b[15] = guid_a[15]; - supblk.journal_uuid = new Guid(guid_b); - supblk.journal_inode = BitConverter.ToUInt32 (sb_sector, 0x0E0); - supblk.journal_dev = BitConverter.ToUInt32 (sb_sector, 0x0E4); - supblk.last_orphan = BitConverter.ToUInt32 (sb_sector, 0x0E8); - supblk.hash_seed_1 = BitConverter.ToUInt32 (sb_sector, 0x0EC); - supblk.hash_seed_2 = BitConverter.ToUInt32 (sb_sector, 0x0F0); - supblk.hash_seed_3 = BitConverter.ToUInt32 (sb_sector, 0x0F4); - supblk.hash_seed_4 = BitConverter.ToUInt32 (sb_sector, 0x0F8); - supblk.hash_version = sb_sector[0x0FC]; - supblk.jnl_backup_type = sb_sector[0x0FD]; - supblk.desc_grp_size = BitConverter.ToUInt16 (sb_sector, 0x0FE); - supblk.default_mnt_opts = BitConverter.ToUInt32 (sb_sector, 0x100); - supblk.first_meta_bg = BitConverter.ToUInt32 (sb_sector, 0x104); - // ext4 - supblk.mkfs_t = BitConverter.ToUInt32 (sb_sector, 0x108); - supblk.blocks_hi = BitConverter.ToUInt32 (sb_sector, 0x14C); - supblk.reserved_blocks_hi = BitConverter.ToUInt32 (sb_sector, 0x150); - supblk.free_blocks_hi = BitConverter.ToUInt32 (sb_sector, 0x154); - supblk.min_inode_size = BitConverter.ToUInt16 (sb_sector, 0x158); - supblk.rsv_inode_size = BitConverter.ToUInt16 (sb_sector, 0x15A); - supblk.flags = BitConverter.ToUInt32 (sb_sector, 0x15C); - supblk.raid_stride = BitConverter.ToUInt16 (sb_sector, 0x160); - supblk.mmp_interval = BitConverter.ToUInt16 (sb_sector, 0x162); - supblk.mmp_block = BitConverter.ToUInt64 (sb_sector, 0x164); - supblk.raid_stripe_width = BitConverter.ToUInt32 (sb_sector, 0x16C); - supblk.flex_bg_grp_size = sb_sector[0x170]; - supblk.kbytes_written = BitConverter.ToUInt64 (sb_sector, 0x174); - supblk.snapshot_inum = BitConverter.ToUInt32 (sb_sector, 0x17C); - supblk.snapshot_id = BitConverter.ToUInt32 (sb_sector, 0x180); - supblk.snapshot_blocks = BitConverter.ToUInt64 (sb_sector, 0x184); - supblk.snapshot_list = BitConverter.ToUInt32 (sb_sector, 0x18C); - supblk.error_count = BitConverter.ToUInt32 (sb_sector, 0x190); - supblk.first_error_t = BitConverter.ToUInt32 (sb_sector, 0x194); - supblk.first_error_inode = BitConverter.ToUInt32 (sb_sector, 0x198); - supblk.first_error_block = BitConverter.ToUInt64 (sb_sector, 0x19C); - forstrings = new byte[32]; - Array.Copy (sb_sector, 0x1A0, forstrings, 0, 32); - supblk.first_error_func = StringHandlers.CToString(forstrings); - supblk.first_error_line = BitConverter.ToUInt32 (sb_sector, 0x1B0); - supblk.last_error_t = BitConverter.ToUInt32 (sb_sector, 0x1B4); - supblk.last_error_inode = BitConverter.ToUInt32 (sb_sector, 0x1B8); - supblk.last_error_line = BitConverter.ToUInt32 (sb_sector, 0x1BC); - supblk.last_error_block = BitConverter.ToUInt64 (sb_sector, 0x1C0); - forstrings = new byte[32]; - Array.Copy (sb_sector, 0x1C8, forstrings, 0, 32); - supblk.last_error_func = StringHandlers.CToString(forstrings); - forstrings = new byte[64]; - Array.Copy (sb_sector, 0x1D8, forstrings, 0, 64); - supblk.mount_options = StringHandlers.CToString(forstrings); + byte[] sb_sector = imagePlugin.ReadSectors(2 + partitionOffset, sb_size_in_sectors); + supblk.inodes = BitConverter.ToUInt32(sb_sector, 0x000); + supblk.blocks = BitConverter.ToUInt32(sb_sector, 0x004); + supblk.reserved_blocks = BitConverter.ToUInt32(sb_sector, 0x008); + supblk.free_blocks = BitConverter.ToUInt32(sb_sector, 0x00C); + supblk.free_inodes = BitConverter.ToUInt32(sb_sector, 0x010); + supblk.first_block = BitConverter.ToUInt32(sb_sector, 0x014); + supblk.block_size = BitConverter.ToUInt32(sb_sector, 0x018); + supblk.frag_size = BitConverter.ToInt32(sb_sector, 0x01C); + supblk.blocks_per_grp = BitConverter.ToUInt32(sb_sector, 0x020); + supblk.flags_per_grp = BitConverter.ToUInt32(sb_sector, 0x024); + supblk.inodes_per_grp = BitConverter.ToUInt32(sb_sector, 0x028); + supblk.mount_t = BitConverter.ToUInt32(sb_sector, 0x02C); + supblk.write_t = BitConverter.ToUInt32(sb_sector, 0x030); + supblk.mount_c = BitConverter.ToUInt16(sb_sector, 0x034); + supblk.max_mount_c = BitConverter.ToInt16(sb_sector, 0x036); + supblk.magic = BitConverter.ToUInt16(sb_sector, 0x038); + supblk.state = BitConverter.ToUInt16(sb_sector, 0x03A); + supblk.err_behaviour = BitConverter.ToUInt16(sb_sector, 0x03C); + supblk.minor_revision = BitConverter.ToUInt16(sb_sector, 0x03E); + supblk.check_t = BitConverter.ToUInt32(sb_sector, 0x040); + supblk.check_inv = BitConverter.ToUInt32(sb_sector, 0x044); + // From 0.5a onward + supblk.creator_os = BitConverter.ToUInt32(sb_sector, 0x048); + supblk.revision = BitConverter.ToUInt32(sb_sector, 0x04C); + supblk.default_uid = BitConverter.ToUInt16(sb_sector, 0x050); + supblk.default_gid = BitConverter.ToUInt16(sb_sector, 0x052); + // From 0.5b onward + supblk.first_inode = BitConverter.ToUInt32(sb_sector, 0x054); + supblk.inode_size = BitConverter.ToUInt16(sb_sector, 0x058); + supblk.block_group_no = BitConverter.ToUInt16(sb_sector, 0x05A); + supblk.ftr_compat = BitConverter.ToUInt32(sb_sector, 0x05C); + supblk.ftr_incompat = BitConverter.ToUInt32(sb_sector, 0x060); + supblk.ftr_ro_compat = BitConverter.ToUInt32(sb_sector, 0x064); + // Volume UUID + Array.Copy(sb_sector, 0x068, guid_a, 0, 16); + guid_b[0] = guid_a[3]; + guid_b[1] = guid_a[2]; + guid_b[2] = guid_a[1]; + guid_b[3] = guid_a[0]; + guid_b[4] = guid_a[5]; + guid_b[5] = guid_a[4]; + guid_b[6] = guid_a[7]; + guid_b[7] = guid_a[6]; + guid_b[8] = guid_a[8]; + guid_b[9] = guid_a[9]; + guid_b[10] = guid_a[10]; + guid_b[11] = guid_a[11]; + guid_b[12] = guid_a[12]; + guid_b[13] = guid_a[13]; + guid_b[14] = guid_a[14]; + guid_b[15] = guid_a[15]; + supblk.uuid = new Guid(guid_b); + // End of volume UUID + forstrings = new byte[16]; + Array.Copy(sb_sector, 0x078, forstrings, 0, 16); + supblk.volume_name = StringHandlers.CToString(forstrings); + forstrings = new byte[64]; + Array.Copy(sb_sector, 0x088, forstrings, 0, 64); + supblk.last_mount_dir = StringHandlers.CToString(forstrings); + supblk.algo_usage_bmp = BitConverter.ToUInt32(sb_sector, 0x0C8); + supblk.prealloc_blks = sb_sector[0x0CC]; + supblk.prealloc_dir_blks = sb_sector[0x0CD]; + supblk.rsrvd_gdt_blocks = BitConverter.ToUInt16(sb_sector, 0x0CE); + // ext3 + Array.Copy(sb_sector, 0x0D0, guid_a, 0, 16); + guid_b[0] = guid_a[3]; + guid_b[1] = guid_a[2]; + guid_b[2] = guid_a[1]; + guid_b[3] = guid_a[0]; + guid_b[4] = guid_a[5]; + guid_b[5] = guid_a[4]; + guid_b[6] = guid_a[7]; + guid_b[7] = guid_a[6]; + guid_b[8] = guid_a[8]; + guid_b[9] = guid_a[9]; + guid_b[10] = guid_a[10]; + guid_b[11] = guid_a[11]; + guid_b[12] = guid_a[12]; + guid_b[13] = guid_a[13]; + guid_b[14] = guid_a[14]; + guid_b[15] = guid_a[15]; + supblk.journal_uuid = new Guid(guid_b); + supblk.journal_inode = BitConverter.ToUInt32(sb_sector, 0x0E0); + supblk.journal_dev = BitConverter.ToUInt32(sb_sector, 0x0E4); + supblk.last_orphan = BitConverter.ToUInt32(sb_sector, 0x0E8); + supblk.hash_seed_1 = BitConverter.ToUInt32(sb_sector, 0x0EC); + supblk.hash_seed_2 = BitConverter.ToUInt32(sb_sector, 0x0F0); + supblk.hash_seed_3 = BitConverter.ToUInt32(sb_sector, 0x0F4); + supblk.hash_seed_4 = BitConverter.ToUInt32(sb_sector, 0x0F8); + supblk.hash_version = sb_sector[0x0FC]; + supblk.jnl_backup_type = sb_sector[0x0FD]; + supblk.desc_grp_size = BitConverter.ToUInt16(sb_sector, 0x0FE); + supblk.default_mnt_opts = BitConverter.ToUInt32(sb_sector, 0x100); + supblk.first_meta_bg = BitConverter.ToUInt32(sb_sector, 0x104); + // ext4 + supblk.mkfs_t = BitConverter.ToUInt32(sb_sector, 0x108); + supblk.blocks_hi = BitConverter.ToUInt32(sb_sector, 0x14C); + supblk.reserved_blocks_hi = BitConverter.ToUInt32(sb_sector, 0x150); + supblk.free_blocks_hi = BitConverter.ToUInt32(sb_sector, 0x154); + supblk.min_inode_size = BitConverter.ToUInt16(sb_sector, 0x158); + supblk.rsv_inode_size = BitConverter.ToUInt16(sb_sector, 0x15A); + supblk.flags = BitConverter.ToUInt32(sb_sector, 0x15C); + supblk.raid_stride = BitConverter.ToUInt16(sb_sector, 0x160); + supblk.mmp_interval = BitConverter.ToUInt16(sb_sector, 0x162); + supblk.mmp_block = BitConverter.ToUInt64(sb_sector, 0x164); + supblk.raid_stripe_width = BitConverter.ToUInt32(sb_sector, 0x16C); + supblk.flex_bg_grp_size = sb_sector[0x170]; + supblk.kbytes_written = BitConverter.ToUInt64(sb_sector, 0x174); + supblk.snapshot_inum = BitConverter.ToUInt32(sb_sector, 0x17C); + supblk.snapshot_id = BitConverter.ToUInt32(sb_sector, 0x180); + supblk.snapshot_blocks = BitConverter.ToUInt64(sb_sector, 0x184); + supblk.snapshot_list = BitConverter.ToUInt32(sb_sector, 0x18C); + supblk.error_count = BitConverter.ToUInt32(sb_sector, 0x190); + supblk.first_error_t = BitConverter.ToUInt32(sb_sector, 0x194); + supblk.first_error_inode = BitConverter.ToUInt32(sb_sector, 0x198); + supblk.first_error_block = BitConverter.ToUInt64(sb_sector, 0x19C); + forstrings = new byte[32]; + Array.Copy(sb_sector, 0x1A0, forstrings, 0, 32); + supblk.first_error_func = StringHandlers.CToString(forstrings); + supblk.first_error_line = BitConverter.ToUInt32(sb_sector, 0x1B0); + supblk.last_error_t = BitConverter.ToUInt32(sb_sector, 0x1B4); + supblk.last_error_inode = BitConverter.ToUInt32(sb_sector, 0x1B8); + supblk.last_error_line = BitConverter.ToUInt32(sb_sector, 0x1BC); + supblk.last_error_block = BitConverter.ToUInt64(sb_sector, 0x1C0); + forstrings = new byte[32]; + Array.Copy(sb_sector, 0x1C8, forstrings, 0, 32); + supblk.last_error_func = StringHandlers.CToString(forstrings); + forstrings = new byte[64]; + Array.Copy(sb_sector, 0x1D8, forstrings, 0, 64); + supblk.mount_options = StringHandlers.CToString(forstrings); - if(supblk.magic == ext2OldFSMagic) - { - old_ext2 = true; - sb.AppendLine("ext2 (old) filesystem"); - } - else if(supblk.magic == ext2FSMagic) - { - if((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) - { - ext3 = true; - } + if (supblk.magic == ext2OldFSMagic) + { + sb.AppendLine("ext2 (old) filesystem"); + } + else if (supblk.magic == ext2FSMagic) + { + 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; - } + 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; + } - if(ext3 == false && ext4 == false) - new_ext2 = true; + new_ext2 |= !ext3 && !ext4; - if(new_ext2) - sb.AppendLine("ext2 filesystem"); - if(ext3) - sb.AppendLine("ext3 filesystem"); - if(ext4) - sb.AppendLine("ext4 filesystem"); - } - else - { - information = "Not a ext2/3/4 filesystem" + System.Environment.NewLine; - return; - } + if (new_ext2) + sb.AppendLine("ext2 filesystem"); + if (ext3) + sb.AppendLine("ext3 filesystem"); + if (ext4) + sb.AppendLine("ext4 filesystem"); + } + else + { + information = "Not a ext2/3/4 filesystem" + Environment.NewLine; + return; + } - string ext_os; - switch(supblk.creator_os) - { - case EXT2_OS_FREEBSD: - ext_os = "FreeBSD"; - break; - case EXT2_OS_HURD: - ext_os = "Hurd"; - break; - case EXT2_OS_LINUX: - ext_os = "Linux"; - break; - case EXT2_OS_LITES: - ext_os = "Lites"; - break; - case EXT2_OS_MASIX: - ext_os = "MasIX"; - break; - default: - ext_os = "Unknown OS (" + supblk.creator_os.ToString() + ")"; - break; - } + string ext_os; + switch (supblk.creator_os) + { + case EXT2_OS_FREEBSD: + ext_os = "FreeBSD"; + break; + case EXT2_OS_HURD: + ext_os = "Hurd"; + break; + case EXT2_OS_LINUX: + ext_os = "Linux"; + break; + case EXT2_OS_LITES: + ext_os = "Lites"; + break; + case EXT2_OS_MASIX: + ext_os = "MasIX"; + break; + default: + ext_os = string.Format("Unknown OS ({0})", supblk.creator_os); + break; + } - if(supblk.mkfs_t > 0) - sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t), ext_os).AppendLine(); - else - sb.AppendFormat("Volume was created for {0}", ext_os).AppendLine(); + if (supblk.mkfs_t > 0) + sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t), ext_os).AppendLine(); + else + sb.AppendFormat("Volume was created for {0}", ext_os).AppendLine(); - byte[] temp_lo, temp_hi; - byte[] temp_bytes = new byte[8]; - UInt64 blocks, reserved, free; + byte[] temp_lo, temp_hi; + byte[] temp_bytes = new byte[8]; + UInt64 blocks, reserved, free; - if((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT) - { - temp_lo = BitConverter.GetBytes (supblk.blocks); - temp_hi = BitConverter.GetBytes (supblk.blocks_hi); - temp_bytes[0] = temp_lo[0]; - temp_bytes[1] = temp_lo[1]; - temp_bytes[2] = temp_lo[2]; - temp_bytes[3] = temp_lo[3]; - temp_bytes[4] = temp_hi[0]; - temp_bytes[5] = temp_hi[1]; - temp_bytes[6] = temp_hi[2]; - temp_bytes[7] = temp_hi[3]; - blocks = BitConverter.ToUInt64 (temp_bytes, 0); + if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT) + { + temp_lo = BitConverter.GetBytes(supblk.blocks); + temp_hi = BitConverter.GetBytes(supblk.blocks_hi); + temp_bytes[0] = temp_lo[0]; + temp_bytes[1] = temp_lo[1]; + temp_bytes[2] = temp_lo[2]; + temp_bytes[3] = temp_lo[3]; + temp_bytes[4] = temp_hi[0]; + temp_bytes[5] = temp_hi[1]; + temp_bytes[6] = temp_hi[2]; + temp_bytes[7] = temp_hi[3]; + blocks = BitConverter.ToUInt64(temp_bytes, 0); - temp_lo = BitConverter.GetBytes (supblk.reserved_blocks); - temp_hi = BitConverter.GetBytes (supblk.reserved_blocks_hi); - temp_bytes[0] = temp_lo[0]; - temp_bytes[1] = temp_lo[1]; - temp_bytes[2] = temp_lo[2]; - temp_bytes[3] = temp_lo[3]; - temp_bytes[4] = temp_hi[0]; - temp_bytes[5] = temp_hi[1]; - temp_bytes[6] = temp_hi[2]; - temp_bytes[7] = temp_hi[3]; - reserved = BitConverter.ToUInt64 (temp_bytes, 0); + temp_lo = BitConverter.GetBytes(supblk.reserved_blocks); + temp_hi = BitConverter.GetBytes(supblk.reserved_blocks_hi); + temp_bytes[0] = temp_lo[0]; + temp_bytes[1] = temp_lo[1]; + temp_bytes[2] = temp_lo[2]; + temp_bytes[3] = temp_lo[3]; + temp_bytes[4] = temp_hi[0]; + temp_bytes[5] = temp_hi[1]; + temp_bytes[6] = temp_hi[2]; + temp_bytes[7] = temp_hi[3]; + reserved = BitConverter.ToUInt64(temp_bytes, 0); - temp_lo = BitConverter.GetBytes (supblk.free_blocks); - temp_hi = BitConverter.GetBytes (supblk.free_blocks_hi); - temp_bytes[0] = temp_lo[0]; - temp_bytes[1] = temp_lo[1]; - temp_bytes[2] = temp_lo[2]; - temp_bytes[3] = temp_lo[3]; - temp_bytes[4] = temp_hi[0]; - temp_bytes[5] = temp_hi[1]; - temp_bytes[6] = temp_hi[2]; - temp_bytes[7] = temp_hi[3]; - free = BitConverter.ToUInt64 (temp_bytes, 0); - } - else - { - blocks = supblk.blocks; - reserved = supblk.reserved_blocks; - free = supblk.free_blocks; - } + temp_lo = BitConverter.GetBytes(supblk.free_blocks); + temp_hi = BitConverter.GetBytes(supblk.free_blocks_hi); + temp_bytes[0] = temp_lo[0]; + temp_bytes[1] = temp_lo[1]; + temp_bytes[2] = temp_lo[2]; + temp_bytes[3] = temp_lo[3]; + temp_bytes[4] = temp_hi[0]; + temp_bytes[5] = temp_hi[1]; + temp_bytes[6] = temp_hi[2]; + temp_bytes[7] = temp_hi[3]; + free = BitConverter.ToUInt64(temp_bytes, 0); + } + else + { + blocks = supblk.blocks; + reserved = supblk.reserved_blocks; + free = supblk.free_blocks; + } - if(supblk.block_size == 0) // Then it is 1024 bytes + 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, supblk.block_size, blocks*supblk.block_size).AppendLine(); - 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(supblk.last_mount_dir != "") - sb.AppendFormat("Last mounted on: \"{0}\"", supblk.last_mount_dir).AppendLine(); - if(supblk.mount_options != "") - sb.AppendFormat("Last used mount options were: {0}", supblk.mount_options).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"); - } + sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks, supblk.block_size, blocks * supblk.block_size).AppendLine(); + 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 (supblk.last_mount_dir != "") + sb.AppendFormat("Last mounted on: \"{0}\"", supblk.last_mount_dir).AppendLine(); + if (supblk.mount_options != "") + sb.AppendFormat("Last used mount options were: {0}", supblk.mount_options).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.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(); - else - sb.AppendLine("Volume has never been written"); + if (supblk.write_t > 0) + sb.AppendFormat("Last written on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.write_t)).AppendLine(); + else + sb.AppendLine("Volume has never been written"); - switch(supblk.state) - { - case EXT2_VALID_FS: - sb.AppendLine("Volume is clean"); - 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; - } + switch (supblk.state) + { + case EXT2_VALID_FS: + sb.AppendLine("Volume is clean"); + 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(supblk.volume_name != "") - sb.AppendFormat("Volume name: \"{0}\"", supblk.volume_name).AppendLine(); + if (supblk.volume_name != "") + sb.AppendFormat("Volume name: \"{0}\"", supblk.volume_name).AppendLine(); - 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; - } + 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.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(); + if (supblk.uuid != Guid.Empty) + sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine(); - if(supblk.kbytes_written > 0) - sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine(); + 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(); - 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(); + sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine(); + 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 ((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 (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(); - } - } + 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…:", supblk.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.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.AppendLine(); - sb.AppendFormat("Default mount options…:", supblk.default_mnt_opts).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.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.AppendLine(); - sb.AppendFormat("Compatible features…:", supblk.ftr_compat).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.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.AppendLine(); - sb.AppendFormat("Compatible features if read-only…:", supblk.ftr_ro_compat).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.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.AppendLine(); - sb.AppendFormat("Incompatible features…:", supblk.ftr_incompat).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); + 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 const UInt16 ext2FSMagic = 0xEF53; // Same for ext3 and ext4 - public const UInt16 ext2OldFSMagic = 0xEF51; + information = sb.ToString(); + } + public const UInt16 ext2FSMagic = 0xEF53; + // Same for ext3 and ext4 + public const UInt16 ext2OldFSMagic = 0xEF51; // Size = 536 bytes - public struct ext2FSSuperBlock - { - public UInt32 inodes; // 0x000, inodes on volume - public UInt32 blocks; // 0x004, blocks on volume - public UInt32 reserved_blocks; // 0x008, reserved blocks - public UInt32 free_blocks; // 0x00C, free blocks count - public UInt32 free_inodes; // 0x010, free inodes count - public UInt32 first_block; // 0x014, first data block - public UInt32 block_size; // 0x018, block size - public Int32 frag_size; // 0x01C, fragment size - public UInt32 blocks_per_grp; // 0x020, blocks per group - public UInt32 flags_per_grp; // 0x024, fragments per group - public UInt32 inodes_per_grp; // 0x028, inodes per group - public UInt32 mount_t; // 0x02C, last mount time - public UInt32 write_t; // 0x030, last write time - public UInt16 mount_c; // 0x034, mounts count - public Int16 max_mount_c; // 0x036, max mounts - public UInt16 magic; // 0x038, (little endian) - public UInt16 state; // 0x03A, filesystem state - public UInt16 err_behaviour; // 0x03C, behaviour on errors - public UInt16 minor_revision; // 0x03E, From 0.5b onward - public UInt32 check_t; // 0x040, last check time - public UInt32 check_inv; // 0x044, max time between checks - // From 0.5a onward - public UInt32 creator_os; // 0x048, Creation OS - public UInt32 revision; // 0x04C, Revison level - public UInt16 default_uid; // 0x050, Default UID for reserved blocks - public UInt16 default_gid; // 0x052, Default GID for reserved blocks - // From 0.5b onward - public UInt32 first_inode; // 0x054, First unreserved inode - public UInt16 inode_size; // 0x058, inode size - public UInt16 block_group_no; // 0x05A, Block group number of THIS superblock - public UInt32 ftr_compat; // 0x05C, Compatible features set - public UInt32 ftr_incompat; // 0x060, Incompatible features set - // Found on Linux 2.0.40 - public UInt32 ftr_ro_compat; // 0x064, Read-only compatible features set - // Found on Linux 2.1.132 - public Guid uuid; // 0x068, 16 bytes, UUID - public string volume_name; // 0x078, 16 bytes, volume name - public string last_mount_dir; // 0x088, 64 bytes, where last mounted - public UInt32 algo_usage_bmp; // 0x0C8, Usage bitmap algorithm, for compression - public byte prealloc_blks; // 0x0CC, Block to try to preallocate - public byte prealloc_dir_blks; // 0x0CD, Blocks to try to preallocate for directories - public UInt16 rsrvd_gdt_blocks; // 0x0CE, Per-group desc for online growth - // Found on Linux 2.4 - // ext3 - public Guid journal_uuid; // 0x0D0, 16 bytes, UUID of journal superblock - public UInt32 journal_inode; // 0x0E0, inode no. of journal file - public UInt32 journal_dev; // 0x0E4, device no. of journal file - public UInt32 last_orphan; // 0x0E8, Start of list of inodes to delete - public UInt32 hash_seed_1; // 0x0EC, First byte of 128bit HTREE hash seed - public UInt32 hash_seed_2; // 0x0F0, Second byte of 128bit HTREE hash seed - public UInt32 hash_seed_3; // 0x0F4, Third byte of 128bit HTREE hash seed - public UInt32 hash_seed_4; // 0x0F8, Fourth byte of 128bit HTREE hash seed - public byte hash_version; // 0x0FC, Hash version - public byte jnl_backup_type; // 0x0FD, Journal backup type - public UInt16 desc_grp_size; // 0x0FE, Size of group descriptor - public UInt32 default_mnt_opts; // 0x100, Default mount options - public UInt32 first_meta_bg; // 0x104, First metablock block group - // Introduced with ext4, some can be ext3 - public UInt32 mkfs_t; // 0x108, Filesystem creation time - // Follows 17 uint32 (68 bytes) of journal inode backup - // Following 3 fields are valid if EXT4_FEATURE_COMPAT_64BIT is set - public UInt32 blocks_hi; // 0x14C, High 32bits of blocks no. - public UInt32 reserved_blocks_hi; // 0x150, High 32bits of reserved blocks no. - public UInt32 free_blocks_hi; // 0x154, High 32bits of free blocks no. - public UInt16 min_inode_size; // 0x158, inodes minimal size in bytes - public UInt16 rsv_inode_size; // 0x15A, Bytes reserved by new inodes - public UInt32 flags; // 0x15C, Flags - public UInt16 raid_stride; // 0x160, RAID stride - public UInt16 mmp_interval; // 0x162, Waiting seconds in MMP check - public UInt64 mmp_block; // 0x164, Block for multi-mount protection - public UInt32 raid_stripe_width; // 0x16C, Blocks on all data disks (N*stride) - public byte flex_bg_grp_size; // 0x170, FLEX_BG group size - public byte padding; // 0x171 - public UInt16 padding2; // 0x172 - // Following are introduced with ext4 - public UInt64 kbytes_written; // 0x174, Kibibytes written in volume lifetime - public UInt32 snapshot_inum; // 0x17C, Active snapshot inode number - public UInt32 snapshot_id; // 0x180, Active snapshot sequential ID - public UInt64 snapshot_blocks; // 0x184, Reserved blocks for active snapshot's future use - public UInt32 snapshot_list; // 0x18C, inode number of the on-disk start of the snapshot list - // Optional ext4 error-handling features - public UInt32 error_count; // 0x190, total registered filesystem errors - public UInt32 first_error_t; // 0x194, time on first error - public UInt32 first_error_inode; // 0x198, inode involved in first error - public UInt64 first_error_block; // 0x19C, block involved of first error - public string first_error_func; // 0x1A0, 32 bytes, function where the error happened - public UInt32 first_error_line; // 0x1B0, line number where error happened - public UInt32 last_error_t; // 0x1B4, time of most recent error - public UInt32 last_error_inode; // 0x1B8, inode involved in last error - public UInt32 last_error_line; // 0x1BC, line number where error happened - public UInt64 last_error_block; // 0x1C0, block involved of last error - public string last_error_func; // 0x1C8, 32 bytes, function where the error happened - // End of optional error-handling features - public string mount_options; // 0x1D8, 64 bytes, last used mount options - } - - // ext? filesystem states - public const UInt16 EXT2_VALID_FS = 0x0001; // Cleanly-unmounted volume - public const UInt16 EXT2_ERROR_FS = 0x0002; // Dirty volume - public const UInt16 EXT3_ORPHAN_FS = 0x0004; // Recovering orphan files - - // ext? default mount flags - public const UInt32 EXT2_DEFM_DEBUG = 0x000001; // Enable debugging messages - public const UInt32 EXT2_DEFM_BSDGROUPS = 0x000002; // Emulates BSD behaviour on new file creation - public const UInt32 EXT2_DEFM_XATTR_USER = 0x000004; // Enable user xattrs - public const UInt32 EXT2_DEFM_ACL = 0x000008; // Enable POSIX ACLs - public const UInt32 EXT2_DEFM_UID16 = 0x000010; // Use 16bit UIDs - public const UInt32 EXT3_DEFM_JMODE_DATA = 0x000040; // Journal data mode - public const UInt32 EXT3_DEFM_JMODE_ORDERED = 0x000080; // Journal ordered mode - public const UInt32 EXT3_DEFM_JMODE_WBACK = 0x000100; // Journal writeback mode - - // Behaviour on errors - public const UInt16 EXT2_ERRORS_CONTINUE = 1; // Continue execution - public const UInt16 EXT2_ERRORS_RO = 2; // Remount fs read-only - public const UInt16 EXT2_ERRORS_PANIC = 3; // Panic - - // OS codes - public const UInt32 EXT2_OS_LINUX = 0; - public const UInt32 EXT2_OS_HURD = 1; - public const UInt32 EXT2_OS_MASIX = 2; - public const UInt32 EXT2_OS_FREEBSD = 3; - public const UInt32 EXT2_OS_LITES = 4; - - // Revision levels - public const UInt32 EXT2_GOOD_OLD_REV = 0; /* The good old (original) format */ - public const UInt32 EXT2_DYNAMIC_REV = 1; /* V2 format w/ dynamic inode sizes */ - - // Compatible features - public const UInt32 EXT2_FEATURE_COMPAT_DIR_PREALLOC = 0x00000001; // Pre-allocate directories - public const UInt32 EXT2_FEATURE_COMPAT_IMAGIC_INODES = 0x00000002; // imagic inodes ? - public const UInt32 EXT3_FEATURE_COMPAT_HAS_JOURNAL = 0x00000004; // Has journal (it's ext3) - public const UInt32 EXT2_FEATURE_COMPAT_EXT_ATTR = 0x00000008; // EA blocks - public const UInt32 EXT2_FEATURE_COMPAT_RESIZE_INO = 0x00000010; // Online filesystem resize reservations - public const UInt32 EXT2_FEATURE_COMPAT_DIR_INDEX = 0x00000020; // Can use hashed indexes on directories - - // Read-only compatible features - public const UInt32 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x00000001; // Reduced number of superblocks - public const UInt32 EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x00000002; // Can have files bigger than 2GiB - public const UInt32 EXT2_FEATURE_RO_COMPAT_BTREE_DIR = 0x00000004; // Use B-Tree for directories - public const UInt32 EXT4_FEATURE_RO_COMPAT_HUGE_FILE = 0x00000008; // Can have files bigger than 2TiB *ext4* - public const UInt32 EXT4_FEATURE_RO_COMPAT_GDT_CSUM = 0x00000010; // Group descriptor checksums and sparse inode table *ext4* - public const UInt32 EXT4_FEATURE_RO_COMPAT_DIR_NLINK = 0x00000020; // More than 32000 directory entries *ext4* - public const UInt32 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE = 0x00000040; // Nanosecond timestamps and creation time *ext4* - - // Incompatible features - public const UInt32 EXT2_FEATURE_INCOMPAT_COMPRESSION = 0x00000001; // Uses compression - public const UInt32 EXT2_FEATURE_INCOMPAT_FILETYPE = 0x00000002; // Filetype in directory entries - public const UInt32 EXT3_FEATURE_INCOMPAT_RECOVER = 0x00000004; // Journal needs recovery *ext3* - public const UInt32 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV = 0x00000008; // Has journal on another device *ext3* - public const UInt32 EXT2_FEATURE_INCOMPAT_META_BG = 0x00000010; // Reduced block group backups - public const UInt32 EXT4_FEATURE_INCOMPAT_EXTENTS = 0x00000040; // Volume use extents *ext4* - public const UInt32 EXT4_FEATURE_INCOMPAT_64BIT = 0x00000080; // Supports volumes bigger than 2^32 blocks *ext4* - public const UInt32 EXT4_FEATURE_INCOMPAT_MMP = 0x00000100; // Multi-mount protection *ext4* - public const UInt32 EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x00000200; // Flexible block group metadata location *ext4* - public const UInt32 EXT4_FEATURE_INCOMPAT_EA_INODE = 0x00000400; // EA in inode *ext4* - public const UInt32 EXT4_FEATURE_INCOMPAT_DIRDATA = 0x00001000; // Data can reside in directory entry *ext4* - - // Miscellaneous filesystem flags - public const UInt32 EXT2_FLAGS_SIGNED_HASH = 0x00000001; // Signed dirhash in use - public const UInt32 EXT2_FLAGS_UNSIGNED_HASH = 0x00000002; // Unsigned dirhash in use - public const UInt32 EXT2_FLAGS_TEST_FILESYS = 0x00000004; // Testing development code - } + public struct ext2FSSuperBlock + { + public UInt32 inodes; + // 0x000, inodes on volume + public UInt32 blocks; + // 0x004, blocks on volume + public UInt32 reserved_blocks; + // 0x008, reserved blocks + public UInt32 free_blocks; + // 0x00C, free blocks count + public UInt32 free_inodes; + // 0x010, free inodes count + public UInt32 first_block; + // 0x014, first data block + public UInt32 block_size; + // 0x018, block size + public Int32 frag_size; + // 0x01C, fragment size + public UInt32 blocks_per_grp; + // 0x020, blocks per group + public UInt32 flags_per_grp; + // 0x024, fragments per group + public UInt32 inodes_per_grp; + // 0x028, inodes per group + public UInt32 mount_t; + // 0x02C, last mount time + public UInt32 write_t; + // 0x030, last write time + public UInt16 mount_c; + // 0x034, mounts count + public Int16 max_mount_c; + // 0x036, max mounts + public UInt16 magic; + // 0x038, (little endian) + public UInt16 state; + // 0x03A, filesystem state + public UInt16 err_behaviour; + // 0x03C, behaviour on errors + public UInt16 minor_revision; + // 0x03E, From 0.5b onward + public UInt32 check_t; + // 0x040, last check time + public UInt32 check_inv; + // 0x044, max time between checks + // From 0.5a onward + public UInt32 creator_os; + // 0x048, Creation OS + public UInt32 revision; + // 0x04C, Revison level + public UInt16 default_uid; + // 0x050, Default UID for reserved blocks + public UInt16 default_gid; + // 0x052, Default GID for reserved blocks + // From 0.5b onward + public UInt32 first_inode; + // 0x054, First unreserved inode + public UInt16 inode_size; + // 0x058, inode size + public UInt16 block_group_no; + // 0x05A, Block group number of THIS superblock + public UInt32 ftr_compat; + // 0x05C, Compatible features set + public UInt32 ftr_incompat; + // 0x060, Incompatible features set + // Found on Linux 2.0.40 + public UInt32 ftr_ro_compat; + // 0x064, Read-only compatible features set + // Found on Linux 2.1.132 + public Guid uuid; + // 0x068, 16 bytes, UUID + public string volume_name; + // 0x078, 16 bytes, volume name + public string last_mount_dir; + // 0x088, 64 bytes, where last mounted + public UInt32 algo_usage_bmp; + // 0x0C8, Usage bitmap algorithm, for compression + public byte prealloc_blks; + // 0x0CC, Block to try to preallocate + public byte prealloc_dir_blks; + // 0x0CD, Blocks to try to preallocate for directories + public UInt16 rsrvd_gdt_blocks; + // 0x0CE, Per-group desc for online growth + // Found on Linux 2.4 + // ext3 + public Guid journal_uuid; + // 0x0D0, 16 bytes, UUID of journal superblock + public UInt32 journal_inode; + // 0x0E0, inode no. of journal file + public UInt32 journal_dev; + // 0x0E4, device no. of journal file + public UInt32 last_orphan; + // 0x0E8, Start of list of inodes to delete + public UInt32 hash_seed_1; + // 0x0EC, First byte of 128bit HTREE hash seed + public UInt32 hash_seed_2; + // 0x0F0, Second byte of 128bit HTREE hash seed + public UInt32 hash_seed_3; + // 0x0F4, Third byte of 128bit HTREE hash seed + public UInt32 hash_seed_4; + // 0x0F8, Fourth byte of 128bit HTREE hash seed + public byte hash_version; + // 0x0FC, Hash version + public byte jnl_backup_type; + // 0x0FD, Journal backup type + public UInt16 desc_grp_size; + // 0x0FE, Size of group descriptor + public UInt32 default_mnt_opts; + // 0x100, Default mount options + public UInt32 first_meta_bg; + // 0x104, First metablock block group + // Introduced with ext4, some can be ext3 + public UInt32 mkfs_t; + // 0x108, Filesystem creation time + // Follows 17 uint32 (68 bytes) of journal inode backup + // Following 3 fields are valid if EXT4_FEATURE_COMPAT_64BIT is set + public UInt32 blocks_hi; + // 0x14C, High 32bits of blocks no. + public UInt32 reserved_blocks_hi; + // 0x150, High 32bits of reserved blocks no. + public UInt32 free_blocks_hi; + // 0x154, High 32bits of free blocks no. + public UInt16 min_inode_size; + // 0x158, inodes minimal size in bytes + public UInt16 rsv_inode_size; + // 0x15A, Bytes reserved by new inodes + public UInt32 flags; + // 0x15C, Flags + public UInt16 raid_stride; + // 0x160, RAID stride + public UInt16 mmp_interval; + // 0x162, Waiting seconds in MMP check + public UInt64 mmp_block; + // 0x164, Block for multi-mount protection + public UInt32 raid_stripe_width; + // 0x16C, Blocks on all data disks (N*stride) + public byte flex_bg_grp_size; + // 0x170, FLEX_BG group size + public byte padding; + // 0x171 + public UInt16 padding2; + // 0x172 + // Following are introduced with ext4 + public UInt64 kbytes_written; + // 0x174, Kibibytes written in volume lifetime + public UInt32 snapshot_inum; + // 0x17C, Active snapshot inode number + public UInt32 snapshot_id; + // 0x180, Active snapshot sequential ID + public UInt64 snapshot_blocks; + // 0x184, Reserved blocks for active snapshot's future use + public UInt32 snapshot_list; + // 0x18C, inode number of the on-disk start of the snapshot list + // Optional ext4 error-handling features + public UInt32 error_count; + // 0x190, total registered filesystem errors + public UInt32 first_error_t; + // 0x194, time on first error + public UInt32 first_error_inode; + // 0x198, inode involved in first error + public UInt64 first_error_block; + // 0x19C, block involved of first error + public string first_error_func; + // 0x1A0, 32 bytes, function where the error happened + public UInt32 first_error_line; + // 0x1B0, line number where error happened + public UInt32 last_error_t; + // 0x1B4, time of most recent error + public UInt32 last_error_inode; + // 0x1B8, inode involved in last error + public UInt32 last_error_line; + // 0x1BC, line number where error happened + public UInt64 last_error_block; + // 0x1C0, block involved of last error + public string last_error_func; + // 0x1C8, 32 bytes, function where the error happened + // End of optional error-handling features + public string mount_options; + // 0x1D8, 64 bytes, last used mount options + } + // ext? filesystem states + public const UInt16 EXT2_VALID_FS = 0x0001; + // Cleanly-unmounted volume + public const UInt16 EXT2_ERROR_FS = 0x0002; + // Dirty volume + public const UInt16 EXT3_ORPHAN_FS = 0x0004; + // Recovering orphan files + // ext? default mount flags + public const UInt32 EXT2_DEFM_DEBUG = 0x000001; + // Enable debugging messages + public const UInt32 EXT2_DEFM_BSDGROUPS = 0x000002; + // Emulates BSD behaviour on new file creation + public const UInt32 EXT2_DEFM_XATTR_USER = 0x000004; + // Enable user xattrs + public const UInt32 EXT2_DEFM_ACL = 0x000008; + // Enable POSIX ACLs + public const UInt32 EXT2_DEFM_UID16 = 0x000010; + // Use 16bit UIDs + public const UInt32 EXT3_DEFM_JMODE_DATA = 0x000040; + // Journal data mode + public const UInt32 EXT3_DEFM_JMODE_ORDERED = 0x000080; + // Journal ordered mode + public const UInt32 EXT3_DEFM_JMODE_WBACK = 0x000100; + // Journal writeback mode + // Behaviour on errors + public const UInt16 EXT2_ERRORS_CONTINUE = 1; + // Continue execution + public const UInt16 EXT2_ERRORS_RO = 2; + // Remount fs read-only + public const UInt16 EXT2_ERRORS_PANIC = 3; + // Panic + // OS codes + public const UInt32 EXT2_OS_LINUX = 0; + public const UInt32 EXT2_OS_HURD = 1; + public const UInt32 EXT2_OS_MASIX = 2; + public const UInt32 EXT2_OS_FREEBSD = 3; + public const UInt32 EXT2_OS_LITES = 4; + // Revision levels + public const UInt32 EXT2_GOOD_OLD_REV = 0; + /* The good old (original) format */ + public const UInt32 EXT2_DYNAMIC_REV = 1; + /* V2 format w/ dynamic inode sizes */ + // Compatible features + public const UInt32 EXT2_FEATURE_COMPAT_DIR_PREALLOC = 0x00000001; + // Pre-allocate directories + public const UInt32 EXT2_FEATURE_COMPAT_IMAGIC_INODES = 0x00000002; + // imagic inodes ? + public const UInt32 EXT3_FEATURE_COMPAT_HAS_JOURNAL = 0x00000004; + // Has journal (it's ext3) + public const UInt32 EXT2_FEATURE_COMPAT_EXT_ATTR = 0x00000008; + // EA blocks + public const UInt32 EXT2_FEATURE_COMPAT_RESIZE_INO = 0x00000010; + // Online filesystem resize reservations + public const UInt32 EXT2_FEATURE_COMPAT_DIR_INDEX = 0x00000020; + // Can use hashed indexes on directories + // Read-only compatible features + public const UInt32 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x00000001; + // Reduced number of superblocks + public const UInt32 EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x00000002; + // Can have files bigger than 2GiB + public const UInt32 EXT2_FEATURE_RO_COMPAT_BTREE_DIR = 0x00000004; + // Use B-Tree for directories + public const UInt32 EXT4_FEATURE_RO_COMPAT_HUGE_FILE = 0x00000008; + // Can have files bigger than 2TiB *ext4* + public const UInt32 EXT4_FEATURE_RO_COMPAT_GDT_CSUM = 0x00000010; + // Group descriptor checksums and sparse inode table *ext4* + public const UInt32 EXT4_FEATURE_RO_COMPAT_DIR_NLINK = 0x00000020; + // More than 32000 directory entries *ext4* + public const UInt32 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE = 0x00000040; + // Nanosecond timestamps and creation time *ext4* + // Incompatible features + public const UInt32 EXT2_FEATURE_INCOMPAT_COMPRESSION = 0x00000001; + // Uses compression + public const UInt32 EXT2_FEATURE_INCOMPAT_FILETYPE = 0x00000002; + // Filetype in directory entries + public const UInt32 EXT3_FEATURE_INCOMPAT_RECOVER = 0x00000004; + // Journal needs recovery *ext3* + public const UInt32 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV = 0x00000008; + // Has journal on another device *ext3* + public const UInt32 EXT2_FEATURE_INCOMPAT_META_BG = 0x00000010; + // Reduced block group backups + public const UInt32 EXT4_FEATURE_INCOMPAT_EXTENTS = 0x00000040; + // Volume use extents *ext4* + public const UInt32 EXT4_FEATURE_INCOMPAT_64BIT = 0x00000080; + // Supports volumes bigger than 2^32 blocks *ext4* + public const UInt32 EXT4_FEATURE_INCOMPAT_MMP = 0x00000100; + // Multi-mount protection *ext4* + public const UInt32 EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x00000200; + // Flexible block group metadata location *ext4* + public const UInt32 EXT4_FEATURE_INCOMPAT_EA_INODE = 0x00000400; + // EA in inode *ext4* + public const UInt32 EXT4_FEATURE_INCOMPAT_DIRDATA = 0x00001000; + // Data can reside in directory entry *ext4* + // Miscellaneous filesystem flags + public const UInt32 EXT2_FLAGS_SIGNED_HASH = 0x00000001; + // Signed dirhash in use + public const UInt32 EXT2_FLAGS_UNSIGNED_HASH = 0x00000002; + // Unsigned dirhash in use + public const UInt32 EXT2_FLAGS_TEST_FILESYS = 0x00000004; + // Testing development code + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Plugins/extFS.cs b/FileSystemIDandChk/Plugins/extFS.cs index 3718f7dc..e4328cb1 100644 --- a/FileSystemIDandChk/Plugins/extFS.cs +++ b/FileSystemIDandChk/Plugins/extFS.cs @@ -1,81 +1,92 @@ using System; -using System.IO; using System.Text; using FileSystemIDandChk; namespace FileSystemIDandChk.Plugins { - class extFS : Plugin - { - public extFS(PluginBase Core) + class extFS : Plugin + { + public extFS(PluginBase Core) { - base.Name = "Linux extended Filesystem"; - base.PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); + Name = "Linux extended Filesystem"; + PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); } - - public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) - { - byte[] sb_sector = imagePlugin.ReadSector (2 + partitionOffset); // Superblock resides at 0x400 - UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038); // Here should reside magic number + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset) + { + byte[] sb_sector = imagePlugin.ReadSector(2 + partitionOffset); // Superblock resides at 0x400 + + UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038); // Here should reside magic number - if(magic == extFSMagic) - return true; - else - return false; - } - - public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) - { - information = ""; + return magic == extFSMagic; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information) + { + information = ""; - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - byte[] sb_sector = imagePlugin.ReadSector (2 + partitionOffset); // Superblock resides at 0x400 - extFSSuperBlock ext_sb = new extFSSuperBlock(); + byte[] sb_sector = imagePlugin.ReadSector(2 + partitionOffset); // Superblock resides at 0x400 + extFSSuperBlock ext_sb = new extFSSuperBlock(); - ext_sb.inodes = BitConverter.ToUInt32(sb_sector, 0x000); - ext_sb.zones = BitConverter.ToUInt32(sb_sector, 0x004); - ext_sb.firstfreeblk = BitConverter.ToUInt32(sb_sector, 0x008); - ext_sb.freecountblk = BitConverter.ToUInt32(sb_sector, 0x00C); - ext_sb.firstfreeind = BitConverter.ToUInt32(sb_sector, 0x010); - ext_sb.freecountind = BitConverter.ToUInt32(sb_sector, 0x014); - ext_sb.firstdatazone = BitConverter.ToUInt32(sb_sector, 0x018); - ext_sb.logzonesize = BitConverter.ToUInt32(sb_sector, 0x01C); - ext_sb.maxsize = BitConverter.ToUInt32(sb_sector, 0x020); + ext_sb.inodes = BitConverter.ToUInt32(sb_sector, 0x000); + ext_sb.zones = BitConverter.ToUInt32(sb_sector, 0x004); + ext_sb.firstfreeblk = BitConverter.ToUInt32(sb_sector, 0x008); + ext_sb.freecountblk = BitConverter.ToUInt32(sb_sector, 0x00C); + ext_sb.firstfreeind = BitConverter.ToUInt32(sb_sector, 0x010); + ext_sb.freecountind = BitConverter.ToUInt32(sb_sector, 0x014); + ext_sb.firstdatazone = BitConverter.ToUInt32(sb_sector, 0x018); + ext_sb.logzonesize = BitConverter.ToUInt32(sb_sector, 0x01C); + ext_sb.maxsize = BitConverter.ToUInt32(sb_sector, 0x020); - sb.AppendLine("ext filesystem"); - sb.AppendFormat("{0} zones on volume", ext_sb.zones); - sb.AppendFormat("{0} free blocks ({1} bytes)", ext_sb.freecountblk, ext_sb.freecountblk*1024); - sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", ext_sb.inodes, ext_sb.freecountind, ext_sb.freecountind*100/ext_sb.inodes); - sb.AppendFormat("First free inode is {0}", ext_sb.firstfreeind); - sb.AppendFormat("First free block is {0}", ext_sb.firstfreeblk); - sb.AppendFormat("First data zone is {0}", ext_sb.firstdatazone); - sb.AppendFormat("Log zone size: {0}", ext_sb.logzonesize); - sb.AppendFormat("Max zone size: {0}", ext_sb.maxsize); + sb.AppendLine("ext filesystem"); + sb.AppendFormat("{0} zones on volume", ext_sb.zones); + sb.AppendFormat("{0} free blocks ({1} bytes)", ext_sb.freecountblk, ext_sb.freecountblk * 1024); + sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", ext_sb.inodes, ext_sb.freecountind, ext_sb.freecountind * 100 / ext_sb.inodes); + sb.AppendFormat("First free inode is {0}", ext_sb.firstfreeind); + sb.AppendFormat("First free block is {0}", ext_sb.firstfreeblk); + sb.AppendFormat("First data zone is {0}", ext_sb.firstdatazone); + sb.AppendFormat("Log zone size: {0}", ext_sb.logzonesize); + sb.AppendFormat("Max zone size: {0}", ext_sb.maxsize); - information = sb.ToString(); - } + information = sb.ToString(); + } - public const UInt16 extFSMagic = 0x137D; + public const UInt16 extFSMagic = 0x137D; - public struct extFSSuperBlock - { - public UInt32 inodes; // 0x000, inodes on volume - public UInt32 zones; // 0x004, zones on volume - public UInt32 firstfreeblk; // 0x008, first free block - public UInt32 freecountblk; // 0x00C, free blocks count - public UInt32 firstfreeind; // 0x010, first free inode - public UInt32 freecountind; // 0x014, free inodes count - public UInt32 firstdatazone; // 0x018, first data zone - public UInt32 logzonesize; // 0x01C, log zone size - public UInt32 maxsize; // 0x020, max zone size - public UInt32 reserved1; // 0x024, reserved - public UInt32 reserved2; // 0x028, reserved - public UInt32 reserved3; // 0x02C, reserved - public UInt32 reserved4; // 0x030, reserved - public UInt32 reserved5; // 0x034, reserved - public UInt16 magic; // 0x038, 0x137D (little endian) - } - } + public struct extFSSuperBlock + { + public UInt32 inodes; + // 0x000, inodes on volume + public UInt32 zones; + // 0x004, zones on volume + public UInt32 firstfreeblk; + // 0x008, first free block + public UInt32 freecountblk; + // 0x00C, free blocks count + public UInt32 firstfreeind; + // 0x010, first free inode + public UInt32 freecountind; + // 0x014, free inodes count + public UInt32 firstdatazone; + // 0x018, first data zone + public UInt32 logzonesize; + // 0x01C, log zone size + public UInt32 maxsize; + // 0x020, max zone size + public UInt32 reserved1; + // 0x024, reserved + public UInt32 reserved2; + // 0x028, reserved + public UInt32 reserved3; + // 0x02C, reserved + public UInt32 reserved4; + // 0x030, reserved + public UInt32 reserved5; + // 0x034, reserved + public UInt16 magic; + // 0x038, 0x137D (little endian) + } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/StringHandlers.cs b/FileSystemIDandChk/StringHandlers.cs index 58b6472a..ccc4cd74 100644 --- a/FileSystemIDandChk/StringHandlers.cs +++ b/FileSystemIDandChk/StringHandlers.cs @@ -3,36 +3,36 @@ using System.Text; namespace FileSystemIDandChk { - public static class StringHandlers - { - public static string CToString (byte[] CString) - { - StringBuilder sb = new StringBuilder(); + public static class StringHandlers + { + public static string CToString(byte[] CString) + { + StringBuilder sb = new StringBuilder(); - for(int i = 0; i> 16); - } + public static UInt32 PDPFromLittleEndian(UInt32 x) + { + return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16); + } - public static UInt32 PDPFromBigEndian(UInt32 x) - { - return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8); - } + public static UInt32 PDPFromBigEndian(UInt32 x) + { + return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8); + } } }