mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
* FileSystemIDandChk/BigEndianBitConverter.cs:
Added BitConverter for BigEndian * FileSystemIDandChk/FileSystemIDandChk.csproj: FileSystemIDandChk/BigEndianBitConverter.cs * FileSystemIDandChk/ImagePlugins/CDRWin.cs: Corrected parsing Implemented all ImagePlugin methods * FileSystemIDandChk/ImagePlugins/ImagePlugin.cs: Used document auto formatting * FileSystemIDandChk/Main.cs: * FileSystemIDandChk/Plugins/FAT.cs: * FileSystemIDandChk/Plugins/BFS.cs: * FileSystemIDandChk/Plugins/FFS.cs: * FileSystemIDandChk/Plugins/ODS.cs: * FileSystemIDandChk/Plugins/HPFS.cs: * FileSystemIDandChk/Plugins/SysV.cs: * FileSystemIDandChk/Plugins/NTFS.cs: * FileSystemIDandChk/Plugins/extFS.cs: * FileSystemIDandChk/Plugins/Opera.cs: * FileSystemIDandChk/Plugins/ext2FS.cs: * FileSystemIDandChk/Plugins/Plugin.cs: * FileSystemIDandChk/Plugins/UNIXBFS.cs: * FileSystemIDandChk/Plugins/SolarFS.cs: * FileSystemIDandChk/PartPlugins/MBR.cs: * FileSystemIDandChk/Plugins/MinixFS.cs: * FileSystemIDandChk/Plugins/ISO9660.cs: * FileSystemIDandChk/Plugins/PCEngine.cs: * FileSystemIDandChk/Plugins/AppleHFS.cs: * FileSystemIDandChk/PartPlugins/NeXT.cs: * FileSystemIDandChk/Plugins/AppleMFS.cs: * FileSystemIDandChk/PartPlugins/AppleMap.cs: * FileSystemIDandChk/Plugins/AppleHFSPlus.cs: Added support for disc image plugins * FileSystemIDandChk/PartPlugins/PartPlugin.cs: Added support for disc image plugins Added start sector and length in sectors to partitions * FileSystemIDandChk/Plugins/Symbian.cs: Commented til code is adapted for disc image plugins git-svn-id: svn://claunia.com/FileSystemIDandChk@27 17725271-3d32-4980-a8cb-9ff532f270ba
This commit is contained in:
572
FileSystemIDandChk/BigEndianBitConverter.cs
Normal file
572
FileSystemIDandChk/BigEndianBitConverter.cs
Normal file
@@ -0,0 +1,572 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace FileSystemIDandChk
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts base data types to an array of bytes, and an array of bytes to base
|
||||
/// data types.
|
||||
/// All info taken from the meta data of System.BitConverter. This implementation
|
||||
/// allows for Endianness consideration.
|
||||
///</summary>
|
||||
public static class BigEndianBitConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the byte order ("endianess") in which data is stored in this computer
|
||||
/// architecture.
|
||||
///</summary>
|
||||
public static bool IsLittleEndian { get; set; } // should default to false, which is what we want for Empire
|
||||
|
||||
/// <summary>
|
||||
/// Converts the specified double-precision floating point number to a 64-bit
|
||||
/// signed integer.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// A 64-bit signed integer whose value is equivalent to value.
|
||||
///</summary>
|
||||
public static long DoubleToInt64Bits(double value) { throw new NotImplementedException(); }
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified Boolean value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// A Boolean value.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 1.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(bool value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified Unicode character value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// A character to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 2.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(char value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified double-precision floating point value as an array of
|
||||
/// bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 8.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(double value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified single-precision floating point value as an array of
|
||||
/// bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 4.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(float value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified 32-bit signed integer value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 4.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(int value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified 64-bit signed integer value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 8.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(long value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified 16-bit signed integer value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 2.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(short value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified 32-bit unsigned integer value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 4.
|
||||
///</summary>
|
||||
[CLSCompliant(false)]
|
||||
public static byte[] GetBytes(uint value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified 64-bit unsigned integer value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 8.
|
||||
///</summary>
|
||||
[CLSCompliant(false)]
|
||||
public static byte[] GetBytes(ulong value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns the specified 16-bit unsigned integer value as an array of bytes.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// An array of bytes with length 2.
|
||||
///</summary>
|
||||
public static byte[] GetBytes(ushort value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.GetBytes(value) : BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Converts the specified 64-bit signed integer to a double-precision floating
|
||||
/// point number.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The number to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// A double-precision floating point number whose value is equivalent to value.
|
||||
///</summary>
|
||||
public static double Int64BitsToDouble(long value) { throw new NotImplementedException(); }
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a Boolean value converted from one byte at a specified position in
|
||||
/// a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// true if the byte at startIndex in value is nonzero; otherwise, false.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static bool ToBoolean(byte[] value, int startIndex) { throw new NotImplementedException(); }
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a Unicode character converted from two bytes at a specified position
|
||||
/// in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A character formed by two bytes beginning at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex equals the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static char ToChar(byte[] value, int startIndex) { throw new NotImplementedException(); }
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a double-precision floating point number converted from eight bytes
|
||||
/// at a specified position in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A double precision floating point number formed by eight bytes beginning
|
||||
/// at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex is greater than or equal to the length of value minus 7, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static double ToDouble(byte[] value, int startIndex) { throw new NotImplementedException(); }
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a 16-bit signed integer converted from two bytes at a specified position
|
||||
/// in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A 16-bit signed integer formed by two bytes beginning at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex equals the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static short ToInt16(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToInt16(value, startIndex) : BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(Int16) - startIndex);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a 32-bit signed integer converted from four bytes at a specified
|
||||
/// position in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A 32-bit signed integer formed by four bytes beginning at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex is greater than or equal to the length of value minus 3, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static int ToInt32(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToInt32(value, startIndex) : BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(Int32) - startIndex);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a 64-bit signed integer converted from eight bytes at a specified
|
||||
/// position in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A 64-bit signed integer formed by eight bytes beginning at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex is greater than or equal to the length of value minus 7, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static long ToInt64(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToInt64(value, startIndex) : BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(Int64) - startIndex);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a single-precision floating point number converted from four bytes
|
||||
/// at a specified position in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A single-precision floating point number formed by four bytes beginning at
|
||||
/// startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex is greater than or equal to the length of value minus 3, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static float ToSingle(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToSingle(value, startIndex) : BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(Single) - startIndex);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified array of bytes
|
||||
/// to its equivalent hexadecimal string representation.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// Returns:
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair
|
||||
/// represents the corresponding element in value; for example, "7F-2C-4A".
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///</summary>
|
||||
public static string ToString(byte[] value)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToString(value) : BitConverter.ToString(value.Reverse().ToArray());
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified subarray of bytes
|
||||
/// to its equivalent hexadecimal string representation.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair
|
||||
/// represents the corresponding element in a subarray of value; for example,
|
||||
/// "7F-2C-4A".
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static string ToString(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToString(value, startIndex) : BitConverter.ToString(value.Reverse().ToArray(), startIndex);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Converts the numeric value of each element of a specified subarray of bytes
|
||||
/// to its equivalent hexadecimal string representation.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// length:
|
||||
/// The number of array elements in value to convert.
|
||||
///
|
||||
/// Returns:
|
||||
/// A System.String of hexadecimal pairs separated by hyphens, where each pair
|
||||
/// represents the corresponding element in a subarray of value; for example,
|
||||
/// "7F-2C-4A".
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex or length is less than zero. -or- startIndex is greater than
|
||||
/// zero and is greater than or equal to the length of value.
|
||||
///
|
||||
/// System.ArgumentException:
|
||||
/// The combination of startIndex and length does not specify a position within
|
||||
/// value; that is, the startIndex parameter is greater than the length of value
|
||||
/// minus the length parameter.
|
||||
///</summary>
|
||||
public static string ToString(byte[] value, int startIndex, int length)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToString(value, startIndex, length) : BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a 16-bit unsigned integer converted from two bytes at a specified
|
||||
/// position in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// The array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A 16-bit unsigned integer formed by two bytes beginning at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex equals the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static ushort ToUInt16(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToUInt16(value, startIndex) : BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(UInt16) - startIndex);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a 32-bit unsigned integer converted from four bytes at a specified
|
||||
/// position in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A 32-bit unsigned integer formed by four bytes beginning at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex is greater than or equal to the length of value minus 3, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static uint ToUInt32(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToUInt32(value, startIndex) : BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(UInt32) - startIndex);
|
||||
}
|
||||
///
|
||||
/// <summary>
|
||||
/// Returns a 64-bit unsigned integer converted from eight bytes at a specified
|
||||
/// position in a byte array.
|
||||
///
|
||||
/// Parameters:
|
||||
/// value:
|
||||
/// An array of bytes.
|
||||
///
|
||||
/// startIndex:
|
||||
/// The starting position within value.
|
||||
///
|
||||
/// Returns:
|
||||
/// A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.
|
||||
///
|
||||
/// Exceptions:
|
||||
/// System.ArgumentException:
|
||||
/// startIndex is greater than or equal to the length of value minus 7, and is
|
||||
/// less than or equal to the length of value minus 1.
|
||||
///
|
||||
/// System.ArgumentNullException:
|
||||
/// value is null.
|
||||
///
|
||||
/// System.ArgumentOutOfRangeException:
|
||||
/// startIndex is less than zero or greater than the length of value minus 1.
|
||||
///</summary>
|
||||
public static ulong ToUInt64(byte[] value, int startIndex)
|
||||
{
|
||||
return !IsLittleEndian ? BitConverter.ToUInt64(value, startIndex) : BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(UInt64) - startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,51 @@
|
||||
2014-04-14 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* BigEndianBitConverter.cs:
|
||||
Added BitConverter for BigEndian
|
||||
|
||||
* FileSystemIDandChk.csproj:
|
||||
FileSystemIDandChk/BigEndianBitConverter.cs
|
||||
|
||||
|
||||
* ImagePlugins/CDRWin.cs:
|
||||
Corrected parsing
|
||||
Implemented all ImagePlugin methods
|
||||
|
||||
* ImagePlugins/ImagePlugin.cs:
|
||||
Used document auto formatting
|
||||
|
||||
* Main.cs:
|
||||
* Plugins/FAT.cs:
|
||||
* Plugins/BFS.cs:
|
||||
* Plugins/FFS.cs:
|
||||
* Plugins/ODS.cs:
|
||||
* Plugins/HPFS.cs:
|
||||
* Plugins/SysV.cs:
|
||||
* Plugins/NTFS.cs:
|
||||
* Plugins/extFS.cs:
|
||||
* Plugins/Opera.cs:
|
||||
* Plugins/ext2FS.cs:
|
||||
* Plugins/Plugin.cs:
|
||||
* Plugins/UNIXBFS.cs:
|
||||
* Plugins/SolarFS.cs:
|
||||
* PartPlugins/MBR.cs:
|
||||
* Plugins/MinixFS.cs:
|
||||
* Plugins/ISO9660.cs:
|
||||
* Plugins/PCEngine.cs:
|
||||
* Plugins/AppleHFS.cs:
|
||||
* PartPlugins/NeXT.cs:
|
||||
* Plugins/AppleMFS.cs:
|
||||
* PartPlugins/AppleMap.cs:
|
||||
* Plugins/AppleHFSPlus.cs:
|
||||
Added support for disc image plugins
|
||||
|
||||
* PartPlugins/PartPlugin.cs:
|
||||
Added support for disc image plugins
|
||||
Added start sector and length in sectors to partitions
|
||||
|
||||
* Plugins/Symbian.cs:
|
||||
Commented til code is adapted for disc image plugins
|
||||
|
||||
2012-08-07 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/SysV.cs:
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
<Compile Include="Plugins\SysV.cs" />
|
||||
<Compile Include="ImagePlugins\ImagePlugin.cs" />
|
||||
<Compile Include="ImagePlugins\CDRWin.cs" />
|
||||
<Compile Include="BigEndianBitConverter.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
@@ -83,7 +84,7 @@
|
||||
<VersionControlPolicy inheritsSet="Mono">
|
||||
<CommitMessageStyle Indent=" " LastFilePostfix=":
 " IncludeDirectoryPaths="True" />
|
||||
</VersionControlPolicy>
|
||||
<ChangeLogPolicy UpdateMode="ProjectRoot" inheritsSet="Mono">
|
||||
<ChangeLogPolicy UpdateMode="ProjectRoot" VcsIntegration="RequireEntry" inheritsSet="Mono">
|
||||
<MessageStyle LastFilePostfix=":
 " IncludeDirectoryPaths="True" />
|
||||
</ChangeLogPolicy>
|
||||
</Policies>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,283 +9,454 @@ namespace FileSystemIDandChk.ImagePlugins
|
||||
public string Name;
|
||||
public Guid PluginUUID;
|
||||
|
||||
protected ImagePlugin ()
|
||||
protected ImagePlugin()
|
||||
{
|
||||
}
|
||||
|
||||
// Basic image handling functions
|
||||
public abstract bool IdentifyImage(string imagepath); // Returns true if the plugin can handle the given image file
|
||||
public abstract bool OpenImage(string imagepath); // Initialize internal plugin structures to handle image
|
||||
public abstract bool ImageHasPartitions(); // Image has different partitions (sessions, tracks)
|
||||
|
||||
public abstract bool IdentifyImage(string imagePath);
|
||||
// Returns true if the plugin can handle the given image file
|
||||
public abstract bool OpenImage(string imagePath);
|
||||
// Initialize internal plugin structures to handle image
|
||||
public abstract bool ImageHasPartitions();
|
||||
// Image has different partitions (sessions, tracks)
|
||||
// Image size functions
|
||||
public abstract UInt64 GetImageSize(); // Returns image size, without headers, in bytes
|
||||
public abstract UInt64 GetSectors(); // Returns image size in sectors
|
||||
public abstract UInt32 GetSectorSize(); // Returns sector size in bytes (user data only)
|
||||
|
||||
public abstract UInt64 GetImageSize();
|
||||
// Returns image size, without headers, in bytes
|
||||
public abstract UInt64 GetSectors();
|
||||
// Returns image size in sectors
|
||||
public abstract UInt32 GetSectorSize();
|
||||
// Returns sector size in bytes (user data only)
|
||||
// Image reading functions
|
||||
public abstract byte[] ReadDiskTag(DiskTagType tag); // Gets a disk tag
|
||||
public abstract byte[] ReadSector(UInt64 SectorAddress); // Reads a sector (user data only)
|
||||
public abstract byte[] ReadSectorTag(UInt64 SectorAddress, SectorTagType tag); // Reads specified tag from sector
|
||||
public abstract byte[] ReadSector(UInt64 SectorAddress, UInt32 track); // Reads a sector (user data only), relative to track
|
||||
public abstract byte[] ReadSectorTag(UInt64 SectorAddress, UInt32 track, SectorTagType tag); // Reads specified tag from sector
|
||||
public abstract byte[] ReadSectors(UInt64 SectorAddress, UInt32 length); // Reads sector (user data only)
|
||||
public abstract byte[] ReadSectorsTag(UInt64 SectorAddress, UInt32 length, SectorTagType tag); // Reads specified tag from sector
|
||||
public abstract byte[] ReadSectors(UInt64 SectorAddress, UInt32 length, UInt32 track); // Reads a sector (user data only), relative to track
|
||||
public abstract byte[] ReadSectorsTag(UInt64 SectorAddress, UInt32 length, UInt32 track, SectorTagType tag); // Reads specified tag from sector, relative to track
|
||||
public abstract byte[] ReadSectorLong(UInt64 SectorAddress); // Reads a sector (user data + tags)
|
||||
public abstract byte[] ReadSectorLong(UInt64 SectorAddress, UInt32 track); // Reads a sector (user data + tags), relative to track
|
||||
public abstract byte[] ReadSectorsLong(UInt64 SectorAddress, UInt32 length); // Reads sector (user data + tags)
|
||||
public abstract byte[] ReadSectorsLong(UInt64 SectorAddress, UInt32 length, UInt32 track); // Reads sectors (user data + tags), relative to track
|
||||
|
||||
public abstract byte[] ReadDiskTag(DiskTagType tag);
|
||||
// Gets a disk tag
|
||||
public abstract byte[] ReadSector(UInt64 sectorAddress);
|
||||
// Reads a sector (user data only)
|
||||
public abstract byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag);
|
||||
// Reads specified tag from sector
|
||||
public abstract byte[] ReadSector(UInt64 sectorAddress, UInt32 track);
|
||||
// Reads a sector (user data only), relative to track
|
||||
public abstract byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag);
|
||||
// Reads specified tag from sector
|
||||
public abstract byte[] ReadSectors(UInt64 sectorAddress, UInt32 length);
|
||||
// Reads sector (user data only)
|
||||
public abstract byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag);
|
||||
// Reads specified tag from sector
|
||||
public abstract byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track);
|
||||
// Reads a sector (user data only), relative to track
|
||||
public abstract byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag);
|
||||
// Reads specified tag from sector, relative to track
|
||||
public abstract byte[] ReadSectorLong(UInt64 sectorAddress);
|
||||
// Reads a sector (user data + tags)
|
||||
public abstract byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track);
|
||||
// Reads a sector (user data + tags), relative to track
|
||||
public abstract byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length);
|
||||
// Reads sector (user data + tags)
|
||||
public abstract byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track);
|
||||
// Reads sectors (user data + tags), relative to track
|
||||
// Image information functions
|
||||
public abstract string GetImageFormat(); // Gets image format
|
||||
public abstract string GetImageVersion(); // Gets format's version
|
||||
public abstract string GetImageApplication(); // Gets application that created this image
|
||||
public abstract string GetImageApplicationVersion(); // Gets application version
|
||||
public abstract string GetImageCreator(); // Gets image creator (person)
|
||||
public abstract DateTime GetImageCreationTime(); // Gets image creation time
|
||||
public abstract DateTime GetImageLastModificationTime(); // Gets image last modification time
|
||||
public abstract string GetImageName(); // Gets image name
|
||||
public abstract string GetImageComments(); // Gets image comments
|
||||
|
||||
public abstract string GetImageFormat();
|
||||
// Gets image format
|
||||
public abstract string GetImageVersion();
|
||||
// Gets format's version
|
||||
public abstract string GetImageApplication();
|
||||
// Gets application that created this image
|
||||
public abstract string GetImageApplicationVersion();
|
||||
// Gets application version
|
||||
public abstract string GetImageCreator();
|
||||
// Gets image creator (person)
|
||||
public abstract DateTime GetImageCreationTime();
|
||||
// Gets image creation time
|
||||
public abstract DateTime GetImageLastModificationTime();
|
||||
// Gets image last modification time
|
||||
public abstract string GetImageName();
|
||||
// Gets image name
|
||||
public abstract string GetImageComments();
|
||||
// Gets image comments
|
||||
// Functions to get information from disk represented by image
|
||||
public abstract string GetDiskManufacturer(); // Gets disk manufacturer
|
||||
public abstract string GetDiskModel(); // Gets disk model
|
||||
public abstract string GetDiskSerialNumber(); // Gets disk serial number
|
||||
public abstract string GetDiskBarcode(); // Gets disk (or product)
|
||||
public abstract string GetDiskPartNumber(); // Gets disk part no. as manufacturer set
|
||||
public abstract DiskType GetDiskType(); // Gets disk type
|
||||
public abstract int GetDiskSequence(); // Gets disk sequence number, 1-starting
|
||||
public abstract int GetLastDiskSequence(); // Gets last disk sequence number
|
||||
|
||||
public abstract string GetDiskManufacturer();
|
||||
// Gets disk manufacturer
|
||||
public abstract string GetDiskModel();
|
||||
// Gets disk model
|
||||
public abstract string GetDiskSerialNumber();
|
||||
// Gets disk serial number
|
||||
public abstract string GetDiskBarcode();
|
||||
// Gets disk (or product)
|
||||
public abstract string GetDiskPartNumber();
|
||||
// Gets disk part no. as manufacturer set
|
||||
public abstract DiskType GetDiskType();
|
||||
// Gets disk type
|
||||
public abstract int GetDiskSequence();
|
||||
// Gets disk sequence number, 1-starting
|
||||
public abstract int GetLastDiskSequence();
|
||||
// Gets last disk sequence number
|
||||
// Functions to get information from drive used to create image
|
||||
public abstract string GetDriveManufacturer(); // Gets drive manufacturer
|
||||
public abstract string GetDriveModel(); // Gets drive model
|
||||
public abstract string GetDriveSerialNumber(); // Gets drive serial number
|
||||
|
||||
public abstract string GetDriveManufacturer();
|
||||
// Gets drive manufacturer
|
||||
public abstract string GetDriveModel();
|
||||
// Gets drive model
|
||||
public abstract string GetDriveSerialNumber();
|
||||
// Gets drive serial number
|
||||
// Partitioning functions
|
||||
public abstract List<PartPlugins.Partition> GetPartitions(); // Returns disc partitions, tracks, sessions, as partition extents
|
||||
public abstract List<Track> GetTracks(); // Returns disc track extents
|
||||
public abstract List<Track> GetSessionTracks(Session Session); // Returns disc track extensts for a session
|
||||
public abstract List<Track> GetSessionTracks(UInt16 Session); // Returns disc track extensts for a session
|
||||
public abstract List<Session> GetSessions(); // Returns disc sessions
|
||||
|
||||
public abstract List<PartPlugins.Partition> GetPartitions();
|
||||
// Returns disc partitions, tracks, sessions, as partition extents
|
||||
public abstract List<Track> GetTracks();
|
||||
// Returns disc track extents
|
||||
public abstract List<Track> GetSessionTracks(Session session);
|
||||
// Returns disc track extensts for a session
|
||||
public abstract List<Track> GetSessionTracks(UInt16 session);
|
||||
// Returns disc track extensts for a session
|
||||
public abstract List<Session> GetSessions();
|
||||
// Returns disc sessions
|
||||
// CD flags bitmask
|
||||
public const byte CDFlagsFourChannel = 0x20;
|
||||
public const byte CDFlagsDataTrack = 0x10;
|
||||
public const byte CDFlagsDataTrack = 0x10;
|
||||
public const byte CDFlagsCopyPrevent = 0x08;
|
||||
public const byte CDFlagsPreEmphasis = 0x04;
|
||||
}
|
||||
|
||||
// Disk types
|
||||
public enum DiskType
|
||||
{
|
||||
Unknown,
|
||||
// Somewhat standard Compact Disc formats
|
||||
CDDA, // CD Digital Audio (Red Book)
|
||||
CDG, // CD+G (Red Book)
|
||||
CDEG, // CD+EG (Red Book)
|
||||
CDI, // CD-i (Green Book)
|
||||
CDROM, // CD-ROM (Yellow Book)
|
||||
CDROMXA, // CD-ROM XA (Yellow Book)
|
||||
CDPLUS, // CD+ (Blue Book)
|
||||
CDMO, // CD-MO (Orange Book)
|
||||
CDR, // CD-Recordable (Orange Book)
|
||||
CDRW, // CD-ReWritable (Orange Book)
|
||||
CDMRW, // Mount-Rainier CD-RW
|
||||
VCD, // Video CD (White Book)
|
||||
SVCD, // Super Video CD (White Book)
|
||||
PCD, // Photo CD (Beige Book)
|
||||
SACD, // Super Audio CD (Scarlet Book)
|
||||
DDCD, // Double-Density CD-ROM (Purple Book)
|
||||
DDCDR, // DD CD-R (Purple Book)
|
||||
DDCDRW, // DD CD-RW (Purple Book)
|
||||
DTSCD, // DTS audio CD (non-standard)
|
||||
CDMIDI, // CD-MIDI (Red Book)
|
||||
CD, // Any unknown or standard violating CD
|
||||
CDDA,
|
||||
// CD Digital Audio (Red Book)
|
||||
CDG,
|
||||
// CD+G (Red Book)
|
||||
CDEG,
|
||||
// CD+EG (Red Book)
|
||||
CDI,
|
||||
// CD-i (Green Book)
|
||||
CDROM,
|
||||
// CD-ROM (Yellow Book)
|
||||
CDROMXA,
|
||||
// CD-ROM XA (Yellow Book)
|
||||
CDPLUS,
|
||||
// CD+ (Blue Book)
|
||||
CDMO,
|
||||
// CD-MO (Orange Book)
|
||||
CDR,
|
||||
// CD-Recordable (Orange Book)
|
||||
CDRW,
|
||||
// CD-ReWritable (Orange Book)
|
||||
CDMRW,
|
||||
// Mount-Rainier CD-RW
|
||||
VCD,
|
||||
// Video CD (White Book)
|
||||
SVCD,
|
||||
// Super Video CD (White Book)
|
||||
PCD,
|
||||
// Photo CD (Beige Book)
|
||||
SACD,
|
||||
// Super Audio CD (Scarlet Book)
|
||||
DDCD,
|
||||
// Double-Density CD-ROM (Purple Book)
|
||||
DDCDR,
|
||||
// DD CD-R (Purple Book)
|
||||
DDCDRW,
|
||||
// DD CD-RW (Purple Book)
|
||||
DTSCD,
|
||||
// DTS audio CD (non-standard)
|
||||
CDMIDI,
|
||||
// CD-MIDI (Red Book)
|
||||
CD,
|
||||
// Any unknown or standard violating CD
|
||||
// Standard DVD formats
|
||||
DVDROM, // DVD-ROM (applies to DVD Video and DVD Audio)
|
||||
DVDR, // DVD-R
|
||||
DVDRW, // DVD-RW
|
||||
DVDPR, // DVD+R
|
||||
DVDPRW, // DVD+RW
|
||||
DVDPRWDL, // DVD+RW DL
|
||||
DVDRDL, // DVD-R DL
|
||||
DVDPRDL, // DVD+R DL
|
||||
DVDRAM, // DVD-RAM
|
||||
DVDROM,
|
||||
// DVD-ROM (applies to DVD Video and DVD Audio)
|
||||
DVDR,
|
||||
// DVD-R
|
||||
DVDRW,
|
||||
// DVD-RW
|
||||
DVDPR,
|
||||
// DVD+R
|
||||
DVDPRW,
|
||||
// DVD+RW
|
||||
DVDPRWDL,
|
||||
// DVD+RW DL
|
||||
DVDRDL,
|
||||
// DVD-R DL
|
||||
DVDPRDL,
|
||||
// DVD+R DL
|
||||
DVDRAM,
|
||||
// DVD-RAM
|
||||
// Standard HD-DVD formats
|
||||
HDDVDROM, // HD DVD-ROM (applies to HD DVD Video)
|
||||
HDDVDRAM, // HD DVD-RAM
|
||||
HDDVDR, // HD DVD-R
|
||||
HDDVDRW, // HD DVD-RW
|
||||
HDDVDROM,
|
||||
// HD DVD-ROM (applies to HD DVD Video)
|
||||
HDDVDRAM,
|
||||
// HD DVD-RAM
|
||||
HDDVDR,
|
||||
// HD DVD-R
|
||||
HDDVDRW,
|
||||
// HD DVD-RW
|
||||
// Standard Blu-ray formats
|
||||
BDROM, // BD-ROM (and BD Video)
|
||||
BDR, // BD-R
|
||||
BDRE, // BD-RE
|
||||
BDROM,
|
||||
// BD-ROM (and BD Video)
|
||||
BDR,
|
||||
// BD-R
|
||||
BDRE,
|
||||
// BD-RE
|
||||
// Rare or uncommon standards
|
||||
EVD, // Enhanced Versatile Disc
|
||||
FVD, // Forward Versatile Disc
|
||||
HVD, // Holographic Versatile Disc
|
||||
CBHD, // China Blue High Definition
|
||||
HDVMD, // High Definition Versatile Multilayer Disc
|
||||
VCDHD, // Versatile Compact Disc High Density
|
||||
LD, // Pioneer LaserDisc
|
||||
LDROM, // Pioneer LaserDisc data
|
||||
MD, // Sony MiniDisc
|
||||
HiMD, // Sony Hi-MD
|
||||
UDO, // Ultra Density Optical
|
||||
SVOD, // Stacked Volumetric Optical Disc
|
||||
FDDVD, // Five Dimensional disc
|
||||
EVD,
|
||||
// Enhanced Versatile Disc
|
||||
FVD,
|
||||
// Forward Versatile Disc
|
||||
HVD,
|
||||
// Holographic Versatile Disc
|
||||
CBHD,
|
||||
// China Blue High Definition
|
||||
HDVMD,
|
||||
// High Definition Versatile Multilayer Disc
|
||||
VCDHD,
|
||||
// Versatile Compact Disc High Density
|
||||
LD,
|
||||
// Pioneer LaserDisc
|
||||
LDROM,
|
||||
// Pioneer LaserDisc data
|
||||
MD,
|
||||
// Sony MiniDisc
|
||||
HiMD,
|
||||
// Sony Hi-MD
|
||||
UDO,
|
||||
// Ultra Density Optical
|
||||
SVOD,
|
||||
// Stacked Volumetric Optical Disc
|
||||
FDDVD,
|
||||
// Five Dimensional disc
|
||||
// Propietary game discs
|
||||
PS1CD, // Sony PlayStation game CD
|
||||
PS2CD, // Sony PlayStation 2 game CD
|
||||
PS2DVD, // Sony PlayStation 2 game DVD
|
||||
PS3DVD, // Sony PlayStation 3 game DVD
|
||||
PS3BD, // Sony PlayStation 3 game Blu-ray
|
||||
PS4BD, // Sony PlayStation 4 game Blu-ray
|
||||
UMD, // Sony PlayStation Portable Universal Media Disc (ECMA-365)
|
||||
GOD, // Nintendo GameCube Optical Disc
|
||||
WOD, // Nintendo Wii Optical Disc
|
||||
WUOD, // Nintendo Wii U Optical Disc
|
||||
XGD, // Microsoft X-box Game Disc
|
||||
XGD2, // Microsoft X-box 360 Game Disc
|
||||
XGD3, // Microsoft X-box 360 Game Disc
|
||||
XGD4, // Microsoft X-box One Game Disc
|
||||
MEGACD, // Sega MegaCD
|
||||
SATURNCD, // Sega Saturn disc
|
||||
GDROM, // Sega/Yamaha Gigabyte Disc
|
||||
GDR // Sega/Yamaha recordable Gigabyte Disc
|
||||
};
|
||||
PS1CD,
|
||||
// Sony PlayStation game CD
|
||||
PS2CD,
|
||||
// Sony PlayStation 2 game CD
|
||||
PS2DVD,
|
||||
// Sony PlayStation 2 game DVD
|
||||
PS3DVD,
|
||||
// Sony PlayStation 3 game DVD
|
||||
PS3BD,
|
||||
// Sony PlayStation 3 game Blu-ray
|
||||
PS4BD,
|
||||
// Sony PlayStation 4 game Blu-ray
|
||||
UMD,
|
||||
// Sony PlayStation Portable Universal Media Disc (ECMA-365)
|
||||
GOD,
|
||||
// Nintendo GameCube Optical Disc
|
||||
WOD,
|
||||
// Nintendo Wii Optical Disc
|
||||
WUOD,
|
||||
// Nintendo Wii U Optical Disc
|
||||
XGD,
|
||||
// Microsoft X-box Game Disc
|
||||
XGD2,
|
||||
// Microsoft X-box 360 Game Disc
|
||||
XGD3,
|
||||
// Microsoft X-box 360 Game Disc
|
||||
XGD4,
|
||||
// Microsoft X-box One Game Disc
|
||||
MEGACD,
|
||||
// Sega MegaCD
|
||||
SATURNCD,
|
||||
// Sega Saturn disc
|
||||
GDROM,
|
||||
// Sega/Yamaha Gigabyte Disc
|
||||
GDR
|
||||
// Sega/Yamaha recordable Gigabyte Disc}}
|
||||
|
||||
};
|
||||
// Track (as partitioning element) types
|
||||
public enum TrackType
|
||||
{
|
||||
Audio, // Audio track
|
||||
Data, // Data track (not any of the below defined ones)
|
||||
CDMode1, // Data track, compact disc mode 1
|
||||
CDMode2Formless, // Data track, compact disc mode 2, formless
|
||||
CDMode2Form1, // Data track, compact disc mode 2, form 1
|
||||
CDMode2Form2 // Data track, compact disc mode 2, form 2
|
||||
};
|
||||
Audio,
|
||||
// Audio track
|
||||
Data,
|
||||
// Data track (not any of the below defined ones)
|
||||
CDMode1,
|
||||
// Data track, compact disc mode 1
|
||||
CDMode2Formless,
|
||||
// Data track, compact disc mode 2, formless
|
||||
CDMode2Form1,
|
||||
// Data track, compact disc mode 2, form 1
|
||||
CDMode2Form2
|
||||
// Data track, compact disc mode 2, form 2}}
|
||||
|
||||
};
|
||||
// Track defining structure
|
||||
public struct Track
|
||||
{
|
||||
public UInt32 TrackSequence; // Track number, 1-started
|
||||
public TrackType TrackType; // Partition type
|
||||
public UInt64 TrackStartSector; // Track starting sector
|
||||
public UInt64 TrackEndSector; // Track ending sector
|
||||
public UInt64 TrackPregap; // Track pre-gap
|
||||
public UInt16 TrackSession; // Session this track belongs to
|
||||
public string TrackDescription; // Information that does not find space in this struct
|
||||
public UInt32 TrackSequence;
|
||||
// Track number, 1-started
|
||||
public TrackType TrackType;
|
||||
// Partition type
|
||||
public UInt64 TrackStartSector;
|
||||
// Track starting sector
|
||||
public UInt64 TrackEndSector;
|
||||
// Track ending sector
|
||||
public UInt64 TrackPregap;
|
||||
// Track pre-gap
|
||||
public UInt16 TrackSession;
|
||||
// Session this track belongs to
|
||||
public string TrackDescription;
|
||||
// Information that does not find space in this struct
|
||||
public Dictionary<int, UInt64> Indexes;
|
||||
// Indexes, 00 to 99 and sector offset
|
||||
}
|
||||
|
||||
// Track index (subpartitioning)
|
||||
public struct TrackIndex
|
||||
{
|
||||
public byte IndexSequence; // Index number (00 to 99)
|
||||
public UInt64 IndexOffset; // Index sector
|
||||
}
|
||||
|
||||
// Session defining structure
|
||||
public struct Session
|
||||
{
|
||||
public UInt16 SessionSequence; // Session number, 1-started
|
||||
public UInt32 StartTrack; // First track present on this session
|
||||
public UInt32 EndTrack; // Last track present on this session
|
||||
public UInt64 StartSector; // First sector present on this session
|
||||
public UInt64 EndSector; // Last sector present on this session
|
||||
public UInt16 SessionSequence;
|
||||
// Session number, 1-started
|
||||
public UInt32 StartTrack;
|
||||
// First track present on this session
|
||||
public UInt32 EndTrack;
|
||||
// Last track present on this session
|
||||
public UInt64 StartSector;
|
||||
// First sector present on this session
|
||||
public UInt64 EndSector;
|
||||
// Last sector present on this session
|
||||
}
|
||||
|
||||
// Metadata present for each sector (aka, "tag")
|
||||
public enum SectorTagType
|
||||
{
|
||||
AppleSectorTag, // Apple's GCR sector tags, 20 bytes
|
||||
CDSectorSync, // Sync frame from CD sector, 12 bytes
|
||||
CDSectorHeader, // CD sector header, 4 bytes
|
||||
CDSectorSubHeader, // CD mode 2 sector subheader
|
||||
CDSectorEDC, // CD sector EDC, 4 bytes
|
||||
CDSectorECC_P, // CD sector ECC P, 172 bytes
|
||||
CDSectorECC_Q, // CD sector ECC Q, 104 bytes
|
||||
CDSectorECC, // CD sector ECC (P and Q), 276 bytes
|
||||
CDSectorSubchannel, // CD sector subchannel, 96 bytes
|
||||
CDTrackISRC, // CD track ISRC, string, 12 bytes
|
||||
CDTrackText, // CD track text, string, 13 bytes
|
||||
CDTrackFlags, // CD track flags, 1 byte
|
||||
DVD_CMI // DVD sector copyright information
|
||||
};
|
||||
AppleSectorTag,
|
||||
// Apple's GCR sector tags, 20 bytes
|
||||
CDSectorSync,
|
||||
// Sync frame from CD sector, 12 bytes
|
||||
CDSectorHeader,
|
||||
// CD sector header, 4 bytes
|
||||
CDSectorSubHeader,
|
||||
// CD mode 2 sector subheader
|
||||
CDSectorEDC,
|
||||
// CD sector EDC, 4 bytes
|
||||
CDSectorECC_P,
|
||||
// CD sector ECC P, 172 bytes
|
||||
CDSectorECC_Q,
|
||||
// CD sector ECC Q, 104 bytes
|
||||
CDSectorECC,
|
||||
// CD sector ECC (P and Q), 276 bytes
|
||||
CDSectorSubchannel,
|
||||
// CD sector subchannel, 96 bytes
|
||||
CDTrackISRC,
|
||||
// CD track ISRC, string, 12 bytes
|
||||
CDTrackText,
|
||||
// CD track text, string, 13 bytes
|
||||
CDTrackFlags,
|
||||
// CD track flags, 1 byte
|
||||
DVD_CMI
|
||||
// DVD sector copyright information}}
|
||||
|
||||
};
|
||||
// Metadata present for each disk
|
||||
public enum DiskTagType
|
||||
{
|
||||
CD_PMA, // CD PMA
|
||||
CD_ATIP, // CD Adress-Time-In-Pregroove
|
||||
CD_TEXT, // CD-Text
|
||||
CD_MCN, // CD Media Catalogue Number
|
||||
DVD_BCA, // DVD Burst Cutting Area
|
||||
DVD_PFI, // DVD Physical Format Information
|
||||
DVD_CMI, // DVD Copyright Management Information
|
||||
DVD_DMI // DVD Disc Manufacturer Information
|
||||
};
|
||||
CD_PMA,
|
||||
// CD PMA
|
||||
CD_ATIP,
|
||||
// CD Adress-Time-In-Pregroove
|
||||
CD_TEXT,
|
||||
// CD-Text
|
||||
CD_MCN,
|
||||
// CD Media Catalogue Number
|
||||
DVD_BCA,
|
||||
// DVD Burst Cutting Area
|
||||
DVD_PFI,
|
||||
// DVD Physical Format Information
|
||||
DVD_CMI,
|
||||
// DVD Copyright Management Information
|
||||
DVD_DMI
|
||||
// DVD Disc Manufacturer Information}}
|
||||
|
||||
};
|
||||
// Feature is supported by image but not implemented yet
|
||||
[Serializable()]
|
||||
public class FeatureSupportedButNotImplementedImageException : System.Exception
|
||||
[Serializable]
|
||||
public class FeatureSupportedButNotImplementedImageException : Exception
|
||||
{
|
||||
public FeatureSupportedButNotImplementedImageException() : base() { }
|
||||
public FeatureSupportedButNotImplementedImageException(string message) : base(message) { }
|
||||
public FeatureSupportedButNotImplementedImageException(string message, System.Exception inner) : base(message, inner) { }
|
||||
public FeatureSupportedButNotImplementedImageException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
public FeatureSupportedButNotImplementedImageException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
protected FeatureSupportedButNotImplementedImageException(System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) { }
|
||||
System.Runtime.Serialization.StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
// Feature is not supported by image
|
||||
[Serializable()]
|
||||
public class FeatureUnsupportedImageException : System.Exception
|
||||
[Serializable]
|
||||
public class FeatureUnsupportedImageException : Exception
|
||||
{
|
||||
public FeatureUnsupportedImageException() : base() { }
|
||||
public FeatureUnsupportedImageException(string message) : base(message) { }
|
||||
public FeatureUnsupportedImageException(string message, System.Exception inner) : base(message, inner) { }
|
||||
public FeatureUnsupportedImageException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
public FeatureUnsupportedImageException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
protected FeatureUnsupportedImageException(System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) { }
|
||||
System.Runtime.Serialization.StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
// Feature is supported by image but not present on it
|
||||
[Serializable()]
|
||||
public class FeatureNotPresentImageException : System.Exception
|
||||
[Serializable]
|
||||
public class FeatureNotPresentImageException : Exception
|
||||
{
|
||||
public FeatureNotPresentImageException() : base() { }
|
||||
public FeatureNotPresentImageException(string message) : base(message) { }
|
||||
public FeatureNotPresentImageException(string message, System.Exception inner) : base(message, inner) { }
|
||||
public FeatureNotPresentImageException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
public FeatureNotPresentImageException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
protected FeatureNotPresentImageException(System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) { }
|
||||
System.Runtime.Serialization.StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
// Feature is supported by image but not by the disc it represents
|
||||
[Serializable()]
|
||||
public class FeaturedNotSupportedByDiscImageException : System.Exception
|
||||
[Serializable]
|
||||
public class FeaturedNotSupportedByDiscImageException : Exception
|
||||
{
|
||||
public FeaturedNotSupportedByDiscImageException() : base() { }
|
||||
public FeaturedNotSupportedByDiscImageException(string message) : base(message) { }
|
||||
public FeaturedNotSupportedByDiscImageException(string message, System.Exception inner) : base(message, inner) { }
|
||||
public FeaturedNotSupportedByDiscImageException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
public FeaturedNotSupportedByDiscImageException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
protected FeaturedNotSupportedByDiscImageException(System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) { }
|
||||
System.Runtime.Serialization.StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
// Corrupt, incorrect or unhandled feature found on image
|
||||
[Serializable()]
|
||||
public class ImageNotSupportedException : System.Exception
|
||||
[Serializable]
|
||||
public class ImageNotSupportedException : Exception
|
||||
{
|
||||
public ImageNotSupportedException() : base() { }
|
||||
public ImageNotSupportedException(string message) : base(message) { }
|
||||
public ImageNotSupportedException(string message, System.Exception inner) : base(message, inner) { }
|
||||
public ImageNotSupportedException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
public ImageNotSupportedException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
protected ImageNotSupportedException(System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) { }
|
||||
System.Runtime.Serialization.StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,70 +20,76 @@ namespace FileSystemIDandChk
|
||||
|
||||
chkPartitions = true;
|
||||
chkFilesystems = true;
|
||||
isDebug = false;
|
||||
// RELEASE
|
||||
//isDebug = false;
|
||||
// DEBUG
|
||||
isDebug = true;
|
||||
|
||||
Console.WriteLine ("Filesystem Identifier and Checker");
|
||||
Console.WriteLine ("Copyright (C) Natalia Portillo, All Rights Reserved");
|
||||
|
||||
// For debug
|
||||
plugins.RegisterAllPlugins();
|
||||
Runner("");
|
||||
|
||||
/*
|
||||
if(args.Length==0)
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
else if(args.Length==1)
|
||||
{
|
||||
plugins.RegisterAllPlugins();
|
||||
if (isDebug)
|
||||
{
|
||||
plugins.RegisterAllPlugins();
|
||||
Runner("/Users/claunia/Desktop/disk_images/cdrom.cue");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
else if (args.Length == 1)
|
||||
{
|
||||
plugins.RegisterAllPlugins();
|
||||
|
||||
if(args[0]=="--formats")
|
||||
{
|
||||
Console.WriteLine("Supported images:");
|
||||
foreach(KeyValuePair<string, ImagePlugin> kvp in plugins.ImagePluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Supported filesystems:");
|
||||
foreach(KeyValuePair<string, Plugin> kvp in plugins.PluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Supported partitions:");
|
||||
foreach(KeyValuePair<string, PartPlugin> kvp in plugins.PartPluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
}
|
||||
else
|
||||
Runner(args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i<args.Length-1; i++)
|
||||
{
|
||||
switch(args[i])
|
||||
{
|
||||
case "--filesystems":
|
||||
chkFilesystems = true;
|
||||
chkPartitions = false;
|
||||
break;
|
||||
case "--partitions":
|
||||
chkFilesystems = false;
|
||||
chkPartitions = true;
|
||||
break;
|
||||
case "--all":
|
||||
chkFilesystems = true;
|
||||
chkPartitions = true;
|
||||
break;
|
||||
case "--debug":
|
||||
isDebug = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (args[0] == "--formats")
|
||||
{
|
||||
Console.WriteLine("Supported images:");
|
||||
foreach (KeyValuePair<string, ImagePlugin> kvp in plugins.ImagePluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Supported filesystems:");
|
||||
foreach (KeyValuePair<string, Plugin> kvp in plugins.PluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Supported partitions:");
|
||||
foreach (KeyValuePair<string, PartPlugin> kvp in plugins.PartPluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
}
|
||||
else
|
||||
Runner(args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < args.Length - 1; i++)
|
||||
{
|
||||
switch (args[i])
|
||||
{
|
||||
case "--filesystems":
|
||||
chkFilesystems = true;
|
||||
chkPartitions = false;
|
||||
break;
|
||||
case "--partitions":
|
||||
chkFilesystems = false;
|
||||
chkPartitions = true;
|
||||
break;
|
||||
case "--all":
|
||||
chkFilesystems = true;
|
||||
chkPartitions = true;
|
||||
break;
|
||||
case "--debug":
|
||||
isDebug = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Runner(args[args.Length-1]);
|
||||
}
|
||||
*/
|
||||
Runner(args[args.Length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Runner (string filename)
|
||||
@@ -101,9 +107,6 @@ namespace FileSystemIDandChk
|
||||
|
||||
foreach(ImagePlugin _imageplugin in plugins.ImagePluginsList.Values)
|
||||
{
|
||||
// DEBUG
|
||||
filename = "/Users/claunia/Desktop/disk_images/cdrom.cue";
|
||||
|
||||
if(_imageplugin.IdentifyImage(filename))
|
||||
{
|
||||
_imageFormat = _imageplugin;
|
||||
@@ -123,7 +126,9 @@ namespace FileSystemIDandChk
|
||||
if(_imageFormat.OpenImage(filename))
|
||||
{
|
||||
Console.WriteLine("DEBUG: Correctly opened image file.");
|
||||
return;
|
||||
|
||||
Console.WriteLine("DEBUG: Image without headers is {0} bytes.", _imageFormat.GetImageSize());
|
||||
Console.WriteLine("DEBUG: Image has {0} sectors.", _imageFormat.GetSectors());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -139,29 +144,35 @@ namespace FileSystemIDandChk
|
||||
return;
|
||||
}
|
||||
|
||||
// All commented until image formats are implemented correctly.
|
||||
/*
|
||||
stream = File.OpenRead(filename);
|
||||
|
||||
Console.WriteLine("Image identified as {0}.", _imageFormat.GetImageFormat());
|
||||
|
||||
if(chkPartitions)
|
||||
{
|
||||
List<Partition> partitions = new List<Partition>();
|
||||
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<Partition> _partitions;
|
||||
|
||||
if (_partplugin.GetInformation(stream, out _partitions))
|
||||
if (_partplugin.GetInformation(_imageFormat, out _partitions))
|
||||
{
|
||||
partition_scheme=_partplugin.Name;
|
||||
partitions = _partitions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(_imageFormat.ImageHasPartitions())
|
||||
{
|
||||
partition_scheme = _imageFormat.GetImageFormat();
|
||||
partitions = _imageFormat.GetPartitions();
|
||||
}
|
||||
|
||||
if(partition_scheme=="")
|
||||
{
|
||||
Console.WriteLine("DEBUG: No partitions found");
|
||||
if(!chkFilesystems)
|
||||
{
|
||||
Console.WriteLine("No partitions founds, not searching for filesystems");
|
||||
@@ -190,7 +201,7 @@ namespace FileSystemIDandChk
|
||||
{
|
||||
Console.WriteLine("Identifying filesystem on partition");
|
||||
|
||||
Identify(stream, out id_plugins, partitions[i].PartitionStart);
|
||||
Identify(_imageFormat, out id_plugins, partitions[i].PartitionStart);
|
||||
if(id_plugins.Count==0)
|
||||
Console.WriteLine("Filesystem not identified");
|
||||
else if(id_plugins.Count>1)
|
||||
@@ -202,7 +213,7 @@ namespace FileSystemIDandChk
|
||||
if(plugins.PluginsList.TryGetValue(plugin_name, out _plugin))
|
||||
{
|
||||
Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, partitions[i].PartitionStart, out information);
|
||||
_plugin.GetInformation(_imageFormat, partitions[i].PartitionStart, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
@@ -211,7 +222,7 @@ namespace FileSystemIDandChk
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin);
|
||||
Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, partitions[i].PartitionStart, out information);
|
||||
_plugin.GetInformation(_imageFormat, partitions[i].PartitionStart, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
@@ -219,9 +230,9 @@ namespace FileSystemIDandChk
|
||||
}
|
||||
}
|
||||
|
||||
if(checkraw)
|
||||
if(checkraw)
|
||||
{
|
||||
Identify(stream, out id_plugins, 0);
|
||||
Identify(_imageFormat, out id_plugins, 0);
|
||||
if(id_plugins.Count==0)
|
||||
Console.WriteLine("Filesystem not identified");
|
||||
else if(id_plugins.Count>1)
|
||||
@@ -233,7 +244,7 @@ namespace FileSystemIDandChk
|
||||
if(plugins.PluginsList.TryGetValue(plugin_name, out _plugin))
|
||||
{
|
||||
Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, 0, out information);
|
||||
_plugin.GetInformation(_imageFormat, 0, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
@@ -242,11 +253,10 @@ namespace FileSystemIDandChk
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin);
|
||||
Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, 0, out information);
|
||||
_plugin.GetInformation(_imageFormat, 0, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
@@ -260,13 +270,13 @@ namespace FileSystemIDandChk
|
||||
}
|
||||
}
|
||||
|
||||
private static void Identify (FileStream stream, out List<string> id_plugins, long offset)
|
||||
private static void Identify (ImagePlugins.ImagePlugin imagePlugin, out List<string> id_plugins, ulong partitionOffset)
|
||||
{
|
||||
id_plugins = new List<string>();
|
||||
|
||||
foreach (Plugin _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
if (_plugin.Identify(stream, offset))
|
||||
if (_plugin.Identify(imagePlugin, partitionOffset))
|
||||
id_plugins.Add(_plugin.Name.ToLower());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,121 +14,121 @@ namespace FileSystemIDandChk.PartPlugins
|
||||
|
||||
public AppleMap (PluginBase Core)
|
||||
{
|
||||
base.Name = "Apple Partition Map";
|
||||
base.PluginUUID = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22");
|
||||
Name = "Apple Partition Map";
|
||||
PluginUUID = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22");
|
||||
}
|
||||
|
||||
public override bool GetInformation (FileStream stream, out List<Partition> partitions)
|
||||
public override bool GetInformation (ImagePlugins.ImagePlugin imagePlugin, out List<Partition> partitions)
|
||||
{
|
||||
byte[] cString;
|
||||
|
||||
ulong apm_entries;
|
||||
uint sector_size;
|
||||
|
||||
if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448)
|
||||
sector_size = 2048;
|
||||
else
|
||||
sector_size = imagePlugin.GetSectorSize();
|
||||
|
||||
partitions = new List<Partition>();
|
||||
|
||||
AppleMapBootEntry APMB = new AppleMapBootEntry();
|
||||
AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry();
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
|
||||
|
||||
eabr.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||
APMB.signature = eabr.ReadUInt16();
|
||||
|
||||
if(APMB.signature == APM_MAGIC)
|
||||
{
|
||||
APMB.sector_size = eabr.ReadUInt16();
|
||||
}
|
||||
else
|
||||
APMB.sector_size = 512; // Some disks omit the boot entry
|
||||
byte[] APMB_sector = imagePlugin.ReadSector(0);
|
||||
|
||||
if(APMB.sector_size == 2048) // A CD, search if buggy (aligns in 512 bytes blocks) first
|
||||
{
|
||||
eabr.BaseStream.Seek(512, SeekOrigin.Begin); // Seek to first entry
|
||||
APMEntry.signature = eabr.ReadUInt16();
|
||||
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) // It should have partition entry signature if buggy
|
||||
{
|
||||
eabr.BaseStream.Seek(2048, SeekOrigin.Begin); // Seek to first entry considering 2048 bytes blocks. Unbuggy.
|
||||
APMEntry.signature = eabr.ReadUInt16();
|
||||
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
||||
return false;
|
||||
else
|
||||
APMB.sector_size = 2048;
|
||||
}
|
||||
else
|
||||
APMB.sector_size = 512;
|
||||
}
|
||||
else
|
||||
{
|
||||
eabr.BaseStream.Seek(APMB.sector_size, SeekOrigin.Begin); // Seek to first entry
|
||||
APMEntry.signature = eabr.ReadUInt16();
|
||||
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) // It should have partition entry signature if buggy
|
||||
{
|
||||
eabr.BaseStream.Seek(512, SeekOrigin.Begin); // Seek to first entry considering 512 bytes blocks. Buggy.
|
||||
APMEntry.signature = eabr.ReadUInt16();
|
||||
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
||||
return false;
|
||||
else
|
||||
APMB.sector_size = 512;
|
||||
}
|
||||
}
|
||||
APMB.signature = BigEndianBitConverter.ToUInt16(APMB_sector, 0x00);
|
||||
APMB.sector_size = BigEndianBitConverter.ToUInt16(APMB_sector, 0x02);
|
||||
APMB.sectors = BigEndianBitConverter.ToUInt32(APMB_sector, 0x04);
|
||||
APMB.reserved1 = BigEndianBitConverter.ToUInt16(APMB_sector, 0x08);
|
||||
APMB.reserved2 = BigEndianBitConverter.ToUInt16(APMB_sector, 0x0A);
|
||||
APMB.reserved3 = BigEndianBitConverter.ToUInt32(APMB_sector, 0x0C);
|
||||
APMB.driver_entries = BigEndianBitConverter.ToUInt16(APMB_sector, 0x10);
|
||||
APMB.first_driver_blk = BigEndianBitConverter.ToUInt32(APMB_sector, 0x12);
|
||||
APMB.driver_size = BigEndianBitConverter.ToUInt16(APMB_sector, 0x16);
|
||||
APMB.operating_system = BigEndianBitConverter.ToUInt16(APMB_sector, 0x18);
|
||||
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip reserved1
|
||||
APMEntry.entries = eabr.ReadUInt32();
|
||||
if(APMEntry.entries <= 1) // It should have more than one entry
|
||||
return false;
|
||||
ulong first_sector = 0;
|
||||
|
||||
if (APMB.signature == APM_MAGIC) // APM boot block found, APM starts in next sector
|
||||
first_sector = 1;
|
||||
|
||||
// Read first entry
|
||||
byte[] APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
||||
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
||||
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
||||
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
||||
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
||||
APMEntry.name = StringHandlers.CToString(cString);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
||||
APMEntry.type = StringHandlers.CToString(cString);
|
||||
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
||||
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
||||
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
||||
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
||||
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
||||
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
||||
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
||||
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
||||
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
||||
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
||||
cString = new byte[16];
|
||||
Array.Copy(APMEntry_sector, 0x78, cString, 0, 16);
|
||||
APMEntry.processor = StringHandlers.CToString(cString);
|
||||
|
||||
if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
||||
return false;
|
||||
|
||||
if (APMEntry.entries <= 1)
|
||||
return false;
|
||||
|
||||
apm_entries = APMEntry.entries;
|
||||
|
||||
// eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip start, we don't need it
|
||||
// eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip sectors, we don't need it
|
||||
// eabr.BaseStream.Seek(32, SeekOrigin.Current); // Skip name, we don't ned it
|
||||
|
||||
// cString = eabr.ReadBytes(32);
|
||||
// APMEntry.type = StringHandlers.CToString(cString);
|
||||
// if(APMEntry.type != "Apple_partition_map") // APM self-describes, if not, this is incorrect
|
||||
// return false;
|
||||
|
||||
apm_entries = APMEntry.entries;
|
||||
|
||||
for(ulong i = 1; i <= apm_entries; i++) // For each partition
|
||||
for(ulong i = 0; i < apm_entries; i++) // For each partition
|
||||
{
|
||||
APMEntry = new AppleMapPartitionEntry();
|
||||
|
||||
eabr.BaseStream.Seek((long)(APMB.sector_size*i), SeekOrigin.Begin); // Seek to partition descriptor
|
||||
//eabr.BaseStream.Seek((long)(0x200*i), SeekOrigin.Begin); // Seek to partition descriptor
|
||||
|
||||
APMEntry.signature = eabr.ReadUInt16();
|
||||
if(APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature
|
||||
APMEntry = new AppleMapPartitionEntry();
|
||||
APMEntry_sector = imagePlugin.ReadSector(first_sector + i);
|
||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
||||
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
||||
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
||||
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
||||
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
||||
APMEntry.name = StringHandlers.CToString(cString);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
||||
APMEntry.type = StringHandlers.CToString(cString);
|
||||
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
||||
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
||||
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
||||
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
||||
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
||||
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
||||
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
||||
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
||||
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
||||
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
||||
cString = new byte[16];
|
||||
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();
|
||||
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip reserved1
|
||||
eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip entries
|
||||
|
||||
APMEntry.start = eabr.ReadUInt32();
|
||||
APMEntry.sectors = eabr.ReadUInt32();
|
||||
cString = eabr.ReadBytes(32);
|
||||
APMEntry.name = StringHandlers.CToString(cString);
|
||||
cString = eabr.ReadBytes(32);
|
||||
APMEntry.type = StringHandlers.CToString(cString);
|
||||
APMEntry.first_data_block = eabr.ReadUInt32();
|
||||
APMEntry.data_sectors = eabr.ReadUInt32();
|
||||
APMEntry.status = eabr.ReadUInt32();
|
||||
APMEntry.first_boot_block = eabr.ReadUInt32();
|
||||
APMEntry.boot_size = eabr.ReadUInt32();
|
||||
APMEntry.load_address = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
APMEntry.entry_point = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
APMEntry.checksum = eabr.ReadUInt32();
|
||||
cString = eabr.ReadBytes(16);
|
||||
APMEntry.processor = StringHandlers.CToString(cString);
|
||||
|
||||
_partition.PartitionSequence = i;
|
||||
_partition.PartitionType = APMEntry.type;
|
||||
_partition.PartitionName = APMEntry.name;
|
||||
// _partition.PartitionStart = APMEntry.start * 0x200; // This seems to be hardcoded
|
||||
_partition.PartitionStart = APMEntry.start * APMB.sector_size;
|
||||
// _partition.PartitionLength = APMEntry.sectors * 0x200; // This seems to be hardcoded
|
||||
_partition.PartitionLength = APMEntry.sectors * APMB.sector_size;
|
||||
_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)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,140 +6,159 @@ using FileSystemIDandChk;
|
||||
|
||||
namespace FileSystemIDandChk.PartPlugins
|
||||
{
|
||||
class NeXTDisklabel : PartPlugin
|
||||
{
|
||||
public const UInt32 NEXT_MAGIC1 = 0x4E655854; // "NeXT"
|
||||
public const UInt32 NEXT_MAGIC2 = 0x646C5632; // "dlV2"
|
||||
public const UInt32 NEXT_MAGIC3 = 0x646C5633; // "dlV3"
|
||||
class NeXTDisklabel : PartPlugin
|
||||
{
|
||||
const UInt32 NEXT_MAGIC1 = 0x4E655854;
|
||||
// "NeXT"
|
||||
const UInt32 NEXT_MAGIC2 = 0x646C5632;
|
||||
// "dlV2"
|
||||
const UInt32 NEXT_MAGIC3 = 0x646C5633;
|
||||
// "dlV3"
|
||||
|
||||
public NeXTDisklabel (PluginBase Core)
|
||||
{
|
||||
base.Name = "NeXT Disklabel";
|
||||
base.PluginUUID = new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9");
|
||||
}
|
||||
|
||||
public override bool GetInformation (FileStream stream, out List<Partition> partitions)
|
||||
{
|
||||
byte[] cString;
|
||||
bool magic_found = false;
|
||||
|
||||
UInt32 magic;
|
||||
UInt32 sector_size;
|
||||
UInt16 front_porch;
|
||||
|
||||
partitions = new List<Partition>();
|
||||
const UInt16 disktabStart = 0xB4; // 180
|
||||
const UInt16 disktabEntrySize = 0x2C; // 44
|
||||
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
|
||||
public NeXTDisklabel(PluginBase Core)
|
||||
{
|
||||
Name = "NeXT Disklabel";
|
||||
PluginUUID = new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9");
|
||||
}
|
||||
|
||||
public override bool GetInformation(ImagePlugins.ImagePlugin imagePlugin, out List<Partition> partitions)
|
||||
{
|
||||
byte[] cString;
|
||||
bool magic_found;
|
||||
byte[] entry_sector;
|
||||
|
||||
eabr.BaseStream.Seek(0, SeekOrigin.Begin); // Starts on sector 0 on NeXT machines, CDs and floppies
|
||||
magic = eabr.ReadUInt32();
|
||||
UInt32 magic;
|
||||
UInt32 sector_size;
|
||||
UInt16 front_porch;
|
||||
|
||||
if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448)
|
||||
sector_size = 2048;
|
||||
else
|
||||
sector_size = imagePlugin.GetSectorSize();
|
||||
|
||||
if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
|
||||
magic_found = true;
|
||||
else
|
||||
{
|
||||
eabr.BaseStream.Seek(0x1E00, SeekOrigin.Begin); // Starts on sector 15 on MBR machines
|
||||
magic = eabr.ReadUInt32();
|
||||
|
||||
if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
|
||||
magic_found = true;
|
||||
else
|
||||
{
|
||||
eabr.BaseStream.Seek(0x2000, SeekOrigin.Begin); // Starts on sector 16 (4 on CD) on RISC disks
|
||||
magic = eabr.ReadUInt32();
|
||||
partitions = new List<Partition>();
|
||||
|
||||
entry_sector = imagePlugin.ReadSector(0); // Starts on sector 0 on NeXT machines, CDs and floppies
|
||||
magic = BigEndianBitConverter.ToUInt32(entry_sector, 0x00);
|
||||
|
||||
if (magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
|
||||
magic_found = true;
|
||||
else
|
||||
{
|
||||
entry_sector = imagePlugin.ReadSector(15); // Starts on sector 15 on MBR machines
|
||||
magic = BigEndianBitConverter.ToUInt32(entry_sector, 0x00);
|
||||
|
||||
if (magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
|
||||
magic_found = true;
|
||||
else
|
||||
{
|
||||
if (sector_size == 2048)
|
||||
entry_sector = imagePlugin.ReadSector(4); // Starts on sector 4 on RISC CDs
|
||||
else
|
||||
entry_sector = imagePlugin.ReadSector(16); // Starts on sector 16 on RISC disks
|
||||
magic = BigEndianBitConverter.ToUInt32(entry_sector, 0x00);
|
||||
|
||||
if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
|
||||
magic_found = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
|
||||
magic_found = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(magic_found)
|
||||
{
|
||||
eabr.BaseStream.Seek(88, SeekOrigin.Current); // Seek to sector size
|
||||
sector_size = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(16, SeekOrigin.Current); // Seek to front porch
|
||||
front_porch = eabr.ReadUInt16();
|
||||
|
||||
eabr.BaseStream.Seek(76, SeekOrigin.Current); // Seek to first partition entry
|
||||
|
||||
for(int i = 0; i < 8; i ++)
|
||||
{
|
||||
NeXTEntry entry = new NeXTEntry();
|
||||
front_porch = BigEndianBitConverter.ToUInt16(entry_sector, 0x6A);
|
||||
|
||||
entry.start = eabr.ReadUInt32();
|
||||
entry.sectors = eabr.ReadUInt32();
|
||||
entry.block_size = eabr.ReadUInt16();
|
||||
entry.frag_size = eabr.ReadUInt16();
|
||||
entry.optimization = eabr.ReadByte();
|
||||
entry.cpg = eabr.ReadUInt16();
|
||||
entry.bpi = eabr.ReadUInt16();
|
||||
entry.freemin = eabr.ReadByte();
|
||||
entry.unknown = eabr.ReadByte();
|
||||
entry.newfs = eabr.ReadByte();
|
||||
cString = eabr.ReadBytes(16);
|
||||
entry.mount_point = StringHandlers.CToString(cString);
|
||||
entry.automount = eabr.ReadByte();
|
||||
cString = eabr.ReadBytes(8);
|
||||
entry.type = StringHandlers.CToString(cString);
|
||||
entry.unknown2 = eabr.ReadByte();
|
||||
|
||||
if(entry.sectors > 0 && entry.sectors < 0xFFFFFFFF && entry.start < 0xFFFFFFFF)
|
||||
{
|
||||
Partition part = new Partition();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (magic_found)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
NeXTEntry entry = new NeXTEntry();
|
||||
|
||||
entry.start = BigEndianBitConverter.ToUInt32(entry_sector, disktabStart + disktabEntrySize * i + 0x00);
|
||||
entry.sectors = BigEndianBitConverter.ToUInt32(entry_sector, disktabStart + disktabEntrySize * i + 0x04);
|
||||
entry.block_size = BigEndianBitConverter.ToUInt16(entry_sector, disktabStart + disktabEntrySize * i + 0x08);
|
||||
entry.frag_size = BigEndianBitConverter.ToUInt16(entry_sector, disktabStart + disktabEntrySize * i + 0x0A);
|
||||
entry.optimization = entry_sector[disktabStart + disktabEntrySize * i + 0x0C];
|
||||
entry.cpg = BigEndianBitConverter.ToUInt16(entry_sector, disktabStart + disktabEntrySize * i + 0x0D);
|
||||
entry.bpi = BigEndianBitConverter.ToUInt16(entry_sector, disktabStart + disktabEntrySize * i + 0x0F);
|
||||
entry.freemin = entry_sector[disktabStart + disktabEntrySize * i + 0x11];
|
||||
entry.newfs = entry_sector[disktabStart + disktabEntrySize * i + 0x12];
|
||||
cString = new byte[16];
|
||||
Array.Copy(entry_sector, disktabStart + disktabEntrySize * i + 0x13, cString, 0, 16);
|
||||
entry.mount_point = StringHandlers.CToString(cString);
|
||||
entry.automount = entry_sector[disktabStart + disktabEntrySize * i + 0x23];
|
||||
cString = new byte[8];
|
||||
Array.Copy(entry_sector, disktabStart + disktabEntrySize * i + 0x24, cString, 0, 8);
|
||||
entry.type = StringHandlers.CToString(cString);
|
||||
|
||||
if (entry.sectors > 0 && entry.sectors < 0xFFFFFFFF && entry.start < 0xFFFFFFFF)
|
||||
{
|
||||
Partition part = new Partition();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
part.PartitionLength = (long)entry.sectors * sector_size;
|
||||
part.PartitionStart = ((long)entry.start + front_porch) * sector_size;
|
||||
part.PartitionType = entry.type;
|
||||
part.PartitionSequence = (ulong)i;
|
||||
part.PartitionName = entry.mount_point;
|
||||
part.PartitionLength = (ulong)entry.sectors * sector_size;
|
||||
part.PartitionStart = ((ulong)entry.start + front_porch) * sector_size;
|
||||
part.PartitionType = entry.type;
|
||||
part.PartitionSequence = (ulong)i;
|
||||
part.PartitionName = entry.mount_point;
|
||||
part.PartitionSectors = (ulong)entry.sectors;
|
||||
part.PartitionStartSector = ((ulong)entry.start + front_porch);
|
||||
|
||||
sb.AppendFormat("{0} bytes per block", entry.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per fragment", entry.frag_size).AppendLine();
|
||||
if(entry.optimization == 's')
|
||||
sb.AppendLine("Space optimized");
|
||||
else if(entry.optimization == 't')
|
||||
sb.AppendLine("Time optimized");
|
||||
else
|
||||
sb.AppendFormat("Unknown optimization {0:X2}", entry.optimization).AppendLine();
|
||||
sb.AppendFormat("{0} cylinders per group", entry.cpg).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per inode", entry.bpi).AppendLine();
|
||||
sb.AppendFormat("{0}% of space must be free at minimum", entry.freemin).AppendLine();
|
||||
if(entry.newfs != 1) // Seems to indicate news has been already run
|
||||
sb.AppendFormat("{0} bytes per block", entry.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per fragment", entry.frag_size).AppendLine();
|
||||
if (entry.optimization == 's')
|
||||
sb.AppendLine("Space optimized");
|
||||
else if (entry.optimization == 't')
|
||||
sb.AppendLine("Time optimized");
|
||||
else
|
||||
sb.AppendFormat("Unknown optimization {0:X2}", entry.optimization).AppendLine();
|
||||
sb.AppendFormat("{0} cylinders per group", entry.cpg).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per inode", entry.bpi).AppendLine();
|
||||
sb.AppendFormat("{0}% of space must be free at minimum", entry.freemin).AppendLine();
|
||||
if (entry.newfs != 1) // Seems to indicate newfs has been already run
|
||||
sb.AppendLine("Filesystem should be formatted at start");
|
||||
if(entry.automount == 1)
|
||||
sb.AppendLine("Filesystem should be automatically mounted");
|
||||
if (entry.automount == 1)
|
||||
sb.AppendLine("Filesystem should be automatically mounted");
|
||||
|
||||
part.PartitionDescription = sb.ToString();
|
||||
part.PartitionDescription = sb.ToString();
|
||||
|
||||
partitions.Add(part);
|
||||
}
|
||||
}
|
||||
partitions.Add(part);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private struct NeXTEntry
|
||||
{
|
||||
public UInt32 start; // Sector of start, counting from front porch
|
||||
public UInt32 sectors; // Length in sectors
|
||||
public UInt16 block_size; // Filesystem's block size
|
||||
public UInt16 frag_size; // Filesystem's fragment size
|
||||
public byte optimization; // 's'pace or 't'ime
|
||||
public UInt16 cpg; // Cylinders per group
|
||||
public UInt16 bpi; // Bytes per inode
|
||||
public byte freemin; // % of minimum free space
|
||||
public byte unknown; // Unknown
|
||||
public byte newfs; // Should newfs be run on first start?
|
||||
public string mount_point; // Mount point or empty if mount where you want
|
||||
public byte automount; // Should automount
|
||||
public string type; // Filesystem type, always "4.3BSD"?
|
||||
public byte unknown2; // Unknown
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct NeXTEntry
|
||||
{
|
||||
public UInt32 start;
|
||||
// Sector of start, counting from front porch
|
||||
public UInt32 sectors;
|
||||
// Length in sectors
|
||||
public UInt16 block_size;
|
||||
// Filesystem's block size
|
||||
public UInt16 frag_size;
|
||||
// Filesystem's fragment size
|
||||
public byte optimization;
|
||||
// 's'pace or 't'ime
|
||||
public UInt16 cpg;
|
||||
// Cylinders per group
|
||||
public UInt16 bpi;
|
||||
// Bytes per inode
|
||||
public byte freemin;
|
||||
// % of minimum free space
|
||||
public byte newfs;
|
||||
// Should newfs be run on first start?
|
||||
public string mount_point;
|
||||
// Mount point or empty if mount where you want
|
||||
public byte automount;
|
||||
// Should automount
|
||||
public string type;
|
||||
// Filesystem type, always "4.3BSD"?
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,25 +4,35 @@ using System.Collections.Generic;
|
||||
|
||||
namespace FileSystemIDandChk.PartPlugins
|
||||
{
|
||||
public abstract class PartPlugin
|
||||
{
|
||||
public string Name;
|
||||
public abstract class PartPlugin
|
||||
{
|
||||
public string Name;
|
||||
public Guid PluginUUID;
|
||||
|
||||
protected PartPlugin ()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract bool GetInformation(FileStream stream, out List<Partition> partitions);
|
||||
}
|
||||
|
||||
public struct Partition
|
||||
{
|
||||
public ulong PartitionSequence; // Partition number, 0-started
|
||||
public string PartitionType; // Partition type
|
||||
public string PartitionName; // Partition name (if the scheme supports it)
|
||||
public long PartitionStart; // Start of the partition, in bytes
|
||||
public long PartitionLength; // Length in bytes of the partition
|
||||
public string PartitionDescription; // Information that does not find space in this struct
|
||||
}
|
||||
|
||||
protected PartPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract bool GetInformation(ImagePlugins.ImagePlugin imagePlugin, out List<Partition> partitions);
|
||||
}
|
||||
|
||||
public struct Partition
|
||||
{
|
||||
public ulong PartitionSequence;
|
||||
// Partition number, 0-started
|
||||
public string PartitionType;
|
||||
// Partition type
|
||||
public string PartitionName;
|
||||
// Partition name (if the scheme supports it)
|
||||
public ulong PartitionStart;
|
||||
// Start of the partition, in bytes
|
||||
public ulong PartitionStartSector;
|
||||
// LBA of partition start
|
||||
public ulong PartitionLength;
|
||||
// Length in bytes of the partition
|
||||
public ulong PartitionSectors;
|
||||
// Length in sectors of the partition
|
||||
public string PartitionDescription;
|
||||
// Information that does not find space in this struct
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
// https://developer.apple.com/legacy/library/documentation/mac/pdf/Files/File_Manager.pdf
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class AppleHFS : Plugin
|
||||
@@ -19,20 +19,14 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] signature = new byte[2];
|
||||
UInt16 drSigWord;
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
UInt16 drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
|
||||
eabr.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
|
||||
drSigWord = eabr.ReadUInt16();
|
||||
|
||||
if(drSigWord == HFS_MAGIC)
|
||||
{
|
||||
eabr.BaseStream.Seek(0x47C + offset, SeekOrigin.Begin); // Seek to embedded HFS+ signature
|
||||
drSigWord = eabr.ReadUInt16();
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||
|
||||
if(drSigWord == HFSP_MAGIC) // "H+"
|
||||
return false;
|
||||
@@ -43,7 +37,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
@@ -54,85 +48,95 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
byte[] pString;
|
||||
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
|
||||
eabr.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
MDB.drSigWord = eabr.ReadUInt16();
|
||||
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;
|
||||
|
||||
MDB.drCrDate = eabr.ReadUInt32();
|
||||
MDB.drLsMod = eabr.ReadUInt32();
|
||||
MDB.drAtrb = eabr.ReadUInt16();
|
||||
MDB.drNmFls = eabr.ReadUInt16();
|
||||
MDB.drVBMSt = eabr.ReadUInt16();
|
||||
MDB.drAllocPtr = eabr.ReadUInt16();
|
||||
MDB.drNmAlBlks = eabr.ReadUInt16();
|
||||
MDB.drAlBlkSiz = eabr.ReadUInt32();
|
||||
MDB.drClpSiz = eabr.ReadUInt32();
|
||||
MDB.drAlBlSt = eabr.ReadUInt16();
|
||||
MDB.drNxtCNID = eabr.ReadUInt32();
|
||||
MDB.drFreeBks = eabr.ReadUInt16();
|
||||
pString = eabr.ReadBytes(28);
|
||||
MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdb_sector, 0x002);
|
||||
MDB.drLsMod = BigEndianBitConverter.ToUInt32(mdb_sector, 0x006);
|
||||
MDB.drAtrb = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00A);
|
||||
MDB.drNmFls = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00C);
|
||||
MDB.drVBMSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0X00E);
|
||||
MDB.drAllocPtr = BigEndianBitConverter.ToUInt16(mdb_sector, 0x010);
|
||||
MDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x012);
|
||||
MDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x014);
|
||||
MDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x018);
|
||||
MDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x01C);
|
||||
MDB.drNxtCNID = BigEndianBitConverter.ToUInt32(mdb_sector, 0x01E);
|
||||
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.drVolBkUp = eabr.ReadUInt32();
|
||||
MDB.drVSeqNum = eabr.ReadUInt16();
|
||||
MDB.drWrCnt = eabr.ReadUInt32();
|
||||
MDB.drXTClpSiz = eabr.ReadUInt32();
|
||||
MDB.drCTClpSiz = eabr.ReadUInt32();
|
||||
MDB.drNmRtDirs = eabr.ReadUInt16();
|
||||
MDB.drFilCnt = eabr.ReadUInt32();
|
||||
MDB.drDirCnt = eabr.ReadUInt32();
|
||||
MDB.drVolBkUp = BigEndianBitConverter.ToUInt32(mdb_sector, 0x040);
|
||||
MDB.drVSeqNum = BigEndianBitConverter.ToUInt16(mdb_sector, 0x044);
|
||||
MDB.drWrCnt = BigEndianBitConverter.ToUInt32(mdb_sector, 0x046);
|
||||
MDB.drXTClpSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x04A);
|
||||
MDB.drCTClpSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x04E);
|
||||
MDB.drNmRtDirs = BigEndianBitConverter.ToUInt16(mdb_sector, 0x052);
|
||||
MDB.drFilCnt = BigEndianBitConverter.ToUInt32(mdb_sector, 0x054);
|
||||
MDB.drDirCnt = BigEndianBitConverter.ToUInt32(mdb_sector, 0x058);
|
||||
|
||||
MDB.drFndrInfo0 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo1 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo2 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo3 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo4 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo5 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo6 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo7 = eabr.ReadUInt32();
|
||||
MDB.drFndrInfo0 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x05C);
|
||||
MDB.drFndrInfo1 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x060);
|
||||
MDB.drFndrInfo2 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x064);
|
||||
MDB.drFndrInfo3 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x068);
|
||||
MDB.drFndrInfo4 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x06C);
|
||||
MDB.drFndrInfo5 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x070);
|
||||
MDB.drFndrInfo6 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x074);
|
||||
MDB.drFndrInfo7 = BigEndianBitConverter.ToUInt32(mdb_sector, 0x078);
|
||||
|
||||
MDB.drVCSize = BigEndianBitConverter.ToUInt16(mdb_sector, 0x07C);
|
||||
MDB.drVBMCSize = BigEndianBitConverter.ToUInt16(mdb_sector, 0x07E);
|
||||
MDB.drCtlCSize = BigEndianBitConverter.ToUInt16(mdb_sector, 0x080);
|
||||
|
||||
// For HFS+ embedded volume
|
||||
MDB.drEmbedSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x07C);
|
||||
MDB.xdrStABNt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x07E);
|
||||
MDB.xdrNumABlks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x080);
|
||||
|
||||
MDB.drEmbedSigWord = eabr.ReadUInt16();
|
||||
MDB.xdrStABNt = eabr.ReadUInt16();
|
||||
MDB.xdrNumABlks = eabr.ReadUInt16();
|
||||
MDB.drXTFlSize = BigEndianBitConverter.ToUInt32(mdb_sector, 0x082);
|
||||
MDB.drCTFlSize = BigEndianBitConverter.ToUInt32(mdb_sector, 0x092);
|
||||
|
||||
MDB.drXTFlSize = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(12, SeekOrigin.Current);
|
||||
MDB.drCTFlSize = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(12, SeekOrigin.Current);
|
||||
|
||||
eabr.BaseStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
BB.signature = eabr.ReadUInt16();
|
||||
BB.signature = BigEndianBitConverter.ToUInt16(bb_sector, 0x000);
|
||||
|
||||
if(BB.signature == HFSBB_MAGIC)
|
||||
{
|
||||
BB.branch = eabr.ReadUInt32();
|
||||
BB.boot_flags = eabr.ReadByte();
|
||||
BB.boot_version = eabr.ReadByte();
|
||||
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);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x00A, pString, 0, 16);
|
||||
BB.system_name = StringHandlers.PascalToString(pString);
|
||||
pString = eabr.ReadBytes(16);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x01A, pString, 0, 16);
|
||||
BB.finder_name = StringHandlers.PascalToString(pString);
|
||||
pString = eabr.ReadBytes(16);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x02A, pString, 0, 16);
|
||||
BB.debug_name = StringHandlers.PascalToString(pString);
|
||||
pString = eabr.ReadBytes(16);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x03A, pString, 0, 16);
|
||||
BB.disasm_name = StringHandlers.PascalToString(pString);
|
||||
pString = eabr.ReadBytes(16);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x04A, pString, 0, 16);
|
||||
BB.stupscr_name = StringHandlers.PascalToString(pString);
|
||||
pString = eabr.ReadBytes(16);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x05A, pString, 0, 16);
|
||||
BB.bootup_name = StringHandlers.PascalToString(pString);
|
||||
pString = eabr.ReadBytes(16);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_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();
|
||||
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;
|
||||
@@ -202,6 +206,12 @@ namespace FileSystemIDandChk.Plugins
|
||||
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();
|
||||
sb.AppendFormat("{0} blocks in volume bitmap cache", MDB.drVBMCSize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume common cache", MDB.drCtlCSize).AppendLine();
|
||||
}
|
||||
|
||||
if(BB.signature == HFSBB_MAGIC)
|
||||
{
|
||||
@@ -243,67 +253,72 @@ namespace FileSystemIDandChk.Plugins
|
||||
return;
|
||||
}
|
||||
|
||||
private struct HFS_MasterDirectoryBlock // Should be offset 0x0400 bytes in volume
|
||||
private struct HFS_MasterDirectoryBlock // Should be sector 2 in volume
|
||||
{
|
||||
public UInt16 drSigWord; // Signature, 0x4244
|
||||
public ulong drCrDate; // Volume creation date
|
||||
public ulong drLsMod; // Volume last modification date
|
||||
public UInt16 drAtrb; // Volume attributes
|
||||
public UInt16 drNmFls; // Files in root directory
|
||||
public UInt16 drVBMSt; // Start 512-byte sector of volume bitmap
|
||||
public UInt16 drAllocPtr; // Allocation block to begin next allocation
|
||||
public UInt16 drNmAlBlks; // Allocation blocks
|
||||
public UInt32 drAlBlkSiz; // Bytes per allocation block
|
||||
public UInt32 drClpSiz; // Bytes to allocate when extending a file
|
||||
public UInt16 drAlBlSt; // Start 512-byte sector of first allocation block
|
||||
public UInt32 drNxtCNID; // CNID for next file
|
||||
public UInt16 drFreeBks; // Free allocation blocks
|
||||
public string drVN; // Volume name (28 bytes)
|
||||
public ulong drVolBkUp; // Volume last backup time
|
||||
public UInt16 drVSeqNum; // Volume backup sequence number
|
||||
public UInt32 drWrCnt; // Filesystem write count
|
||||
public UInt32 drXTClpSiz; // Bytes to allocate when extending the extents B-Tree
|
||||
public UInt32 drCTClpSiz; // Bytes to allocate when extending the catalog B-Tree
|
||||
public UInt16 drNmRtDirs; // Number of directories in root directory
|
||||
public UInt32 drFilCnt; // Number of files in the volume
|
||||
public UInt32 drDirCnt; // Number of directories in the volume
|
||||
public UInt32 drFndrInfo0; // finderInfo[0], CNID for bootable system's directory
|
||||
public UInt32 drFndrInfo1; // finderInfo[1], CNID of the directory containing the boot application
|
||||
public UInt32 drFndrInfo2; // finderInfo[2], CNID of the directory that should be opened on boot
|
||||
public UInt32 drFndrInfo3; // finderInfo[3], CNID for Mac OS 8 or 9 directory
|
||||
public UInt32 drFndrInfo4; // finderInfo[4], Reserved
|
||||
public UInt32 drFndrInfo5; // finderInfo[5], CNID for Mac OS X directory
|
||||
public UInt32 drFndrInfo6; // finderInfo[6], first part of Mac OS X volume ID
|
||||
public UInt32 drFndrInfo7; // finderInfo[7], second part of Mac OS X volume ID
|
||||
public UInt16 drEmbedSigWord; // Embedded volume signature, "H+" if HFS+ is embedded ignore following two fields if not
|
||||
public UInt16 xdrStABNt; // Starting block number of embedded HFS+ volume
|
||||
public UInt16 xdrNumABlks; // Allocation blocks used by embedded volume
|
||||
public UInt32 drXTFlSize; // Bytes in the extents B-Tree
|
||||
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
|
||||
// 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
|
||||
// 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; // Bytes in the catalog B-Tree
|
||||
public UInt32 drCTFlSize; // 0x092, Bytes in the catalog B-Tree
|
||||
// 3 HFS extents following, 32 bits each
|
||||
}
|
||||
|
||||
private struct HFS_BootBlock // Should be offset 0x0000 bytes in volume
|
||||
private struct HFS_BootBlock // Should be sectors 0 and 1 in volume
|
||||
{
|
||||
public UInt16 signature; // Signature, 0x4C4B if bootable
|
||||
public UInt32 branch; // Branch
|
||||
public byte boot_flags; // Boot block flags
|
||||
public byte boot_version; // Boot block version
|
||||
public Int16 sec_sv_pages; // Allocate secondary buffers
|
||||
public string system_name; // System file name (10 bytes)
|
||||
public string finder_name; // Finder file name (10 bytes)
|
||||
public string debug_name; // Debugger file name (10 bytes)
|
||||
public string disasm_name; // Disassembler file name (10 bytes)
|
||||
public string stupscr_name; // Startup screen file name (10 bytes)
|
||||
public string bootup_name; // First program to execute on boot (10 bytes)
|
||||
public string clipbrd_name; // Clipboard file name (10 bytes)
|
||||
public UInt16 max_files; // 1/4 of maximum opened at a time files
|
||||
public UInt16 queue_size; // Event queue size
|
||||
public UInt32 heap_128k; // Heap size on a Mac with 128KiB of RAM
|
||||
public UInt32 heap_256k; // Heap size on a Mac with 256KiB of RAM
|
||||
public UInt32 heap_512k; // Heap size on a Mac with 512KiB of RAM or more
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
// Information from Apple TechNote 1150: https://developer.apple.com/legacy/library/technotes/tn/tn1150.html
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class AppleHFSPlus : Plugin
|
||||
@@ -19,36 +18,33 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt16 drSigWord;
|
||||
UInt16 xdrStABNt;
|
||||
UInt16 drAlBlSt;
|
||||
UInt32 drAlBlkSiz;
|
||||
|
||||
long hfsp_offset;
|
||||
byte[] vh_sector;
|
||||
ulong hfsp_offset;
|
||||
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
|
||||
eabr.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
vh_sector = imagePlugin.ReadSector(2 + partitionOffset); // Read volume header, of HFS Wrapper MDB
|
||||
|
||||
drSigWord = eabr.ReadUInt16();
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0); // Check for HFS Wrapper MDB
|
||||
|
||||
if(drSigWord == HFS_MAGIC) // "BD"
|
||||
{
|
||||
eabr.BaseStream.Seek(0x47C + offset, SeekOrigin.Begin); // Seek to embedded HFS+ signature
|
||||
drSigWord = eabr.ReadUInt16();
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x07C); // Read embedded HFS+ signature
|
||||
|
||||
if(drSigWord == HFSP_MAGIC) // "H+"
|
||||
{
|
||||
xdrStABNt = eabr.ReadUInt16();
|
||||
xdrStABNt = BigEndianBitConverter.ToUInt16(vh_sector, 0x07E); // Starting block number of embedded HFS+ volume
|
||||
|
||||
eabr.BaseStream.Seek(0x414 + offset, SeekOrigin.Begin);
|
||||
drAlBlkSiz = eabr.ReadUInt32();
|
||||
drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x014); // Block size
|
||||
|
||||
eabr.BaseStream.Seek(0x41C + offset, SeekOrigin.Begin);
|
||||
drAlBlSt = eabr.ReadUInt16();
|
||||
drAlBlSt = BigEndianBitConverter.ToUInt16(vh_sector, 0x01C); // Start of allocated blocks (in 512-byte/block)
|
||||
|
||||
hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512))*512;
|
||||
hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512))*(imagePlugin.GetSectorSize() / 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -60,16 +56,16 @@ namespace FileSystemIDandChk.Plugins
|
||||
hfsp_offset = 0;
|
||||
}
|
||||
|
||||
eabr.BaseStream.Seek(0x400 + offset + hfsp_offset, SeekOrigin.Begin);
|
||||
vh_sector = imagePlugin.ReadSector(2 + partitionOffset + hfsp_offset); // Read volume header
|
||||
|
||||
drSigWord = eabr.ReadUInt16();
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0);
|
||||
if(drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
@@ -79,30 +75,27 @@ namespace FileSystemIDandChk.Plugins
|
||||
UInt32 drAlBlkSiz;
|
||||
HFSPlusVolumeHeader HPVH = new HFSPlusVolumeHeader();
|
||||
|
||||
long hfsp_offset;
|
||||
ulong hfsp_offset;
|
||||
bool wrapped = false;
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
|
||||
byte[] vh_sector;
|
||||
|
||||
eabr.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
|
||||
drSigWord = eabr.ReadUInt16();
|
||||
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"
|
||||
{
|
||||
eabr.BaseStream.Seek(0x47C + offset, SeekOrigin.Begin); // Seek to embedded HFS+ signature
|
||||
drSigWord = eabr.ReadUInt16();
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x07C); // Read embedded HFS+ signature
|
||||
|
||||
if(drSigWord == HFSP_MAGIC) // "H+"
|
||||
{
|
||||
xdrStABNt = eabr.ReadUInt16();
|
||||
|
||||
eabr.BaseStream.Seek(0x414 + offset, SeekOrigin.Begin);
|
||||
drAlBlkSiz = eabr.ReadUInt32();
|
||||
|
||||
eabr.BaseStream.Seek(0x41C + offset, SeekOrigin.Begin);
|
||||
drAlBlSt = eabr.ReadUInt16();
|
||||
|
||||
hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512))*512;
|
||||
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
|
||||
@@ -117,9 +110,9 @@ namespace FileSystemIDandChk.Plugins
|
||||
wrapped = false;
|
||||
}
|
||||
|
||||
eabr.BaseStream.Seek(0x400 + offset + hfsp_offset, SeekOrigin.Begin);
|
||||
vh_sector = imagePlugin.ReadSector(2 + partitionOffset + hfsp_offset); // Read volume header
|
||||
|
||||
HPVH.signature = eabr.ReadUInt16();
|
||||
HPVH.signature = BigEndianBitConverter.ToUInt16(vh_sector, 0x000);
|
||||
if(HPVH.signature == HFSP_MAGIC || HPVH.signature == HFSX_MAGIC)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -131,53 +124,48 @@ namespace FileSystemIDandChk.Plugins
|
||||
if(wrapped)
|
||||
sb.AppendLine("Volume is wrapped inside an HFS volume.");
|
||||
|
||||
HPVH.version = eabr.ReadUInt16();
|
||||
HPVH.version = BigEndianBitConverter.ToUInt16(vh_sector, 0x002);
|
||||
|
||||
if(HPVH.version == 4 || HPVH.version == 5)
|
||||
{
|
||||
HPVH.attributes = eabr.ReadUInt32();
|
||||
byte[] lastMountedVersion_b = eabr.ReadBytes(4);
|
||||
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.journalInfoBlock = eabr.ReadUInt32();
|
||||
HPVH.journalInfoBlock = BigEndianBitConverter.ToUInt32(vh_sector, 0x00C);
|
||||
|
||||
HPVH.createDate = eabr.ReadUInt32();
|
||||
HPVH.modifyDate = eabr.ReadUInt32();
|
||||
HPVH.backupDate = eabr.ReadUInt32();
|
||||
HPVH.checkedDate = eabr.ReadUInt32();
|
||||
HPVH.createDate = BigEndianBitConverter.ToUInt32(vh_sector, 0x010);
|
||||
HPVH.modifyDate = BigEndianBitConverter.ToUInt32(vh_sector, 0x018);
|
||||
HPVH.backupDate = BigEndianBitConverter.ToUInt32(vh_sector, 0x020);
|
||||
HPVH.checkedDate = BigEndianBitConverter.ToUInt32(vh_sector, 0x028);
|
||||
|
||||
HPVH.fileCount = eabr.ReadUInt32();
|
||||
HPVH.folderCount = eabr.ReadUInt32();
|
||||
HPVH.fileCount = BigEndianBitConverter.ToUInt32(vh_sector, 0x030);
|
||||
HPVH.folderCount = BigEndianBitConverter.ToUInt32(vh_sector, 0x034);
|
||||
|
||||
HPVH.blockSize = eabr.ReadUInt32();
|
||||
HPVH.totalBlocks = eabr.ReadUInt32();
|
||||
HPVH.freeBlocks = eabr.ReadUInt32();
|
||||
HPVH.blockSize = BigEndianBitConverter.ToUInt32(vh_sector, 0x038);
|
||||
HPVH.totalBlocks = BigEndianBitConverter.ToUInt32(vh_sector, 0x03C);
|
||||
HPVH.freeBlocks = BigEndianBitConverter.ToUInt32(vh_sector, 0x040);
|
||||
|
||||
HPVH.nextAllocation = eabr.ReadUInt32();
|
||||
HPVH.rsrcClumpSize = eabr.ReadUInt32();
|
||||
HPVH.dataClumpSize = eabr.ReadUInt32();
|
||||
HPVH.nextCatalogID = eabr.ReadUInt32();
|
||||
HPVH.nextAllocation = BigEndianBitConverter.ToUInt32(vh_sector, 0x044);
|
||||
HPVH.rsrcClumpSize = BigEndianBitConverter.ToUInt32(vh_sector, 0x048);
|
||||
HPVH.dataClumpSize = BigEndianBitConverter.ToUInt32(vh_sector, 0x04C);
|
||||
HPVH.nextCatalogID = BigEndianBitConverter.ToUInt32(vh_sector, 0x050);
|
||||
|
||||
HPVH.writeCount = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(8,SeekOrigin.Current); // Skipping encoding bitmap
|
||||
HPVH.writeCount = BigEndianBitConverter.ToUInt32(vh_sector, 0x054);
|
||||
|
||||
HPVH.drFndrInfo0 = eabr.ReadUInt32();
|
||||
HPVH.drFndrInfo1 = eabr.ReadUInt32();
|
||||
HPVH.drFndrInfo2 = eabr.ReadUInt32();
|
||||
HPVH.drFndrInfo3 = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skipping reserved finder info
|
||||
HPVH.drFndrInfo5 = eabr.ReadUInt32();
|
||||
HPVH.drFndrInfo6 = eabr.ReadUInt32();
|
||||
HPVH.drFndrInfo7 = eabr.ReadUInt32();
|
||||
HPVH.drFndrInfo0 = BigEndianBitConverter.ToUInt32(vh_sector, 0x060);
|
||||
HPVH.drFndrInfo1 = BigEndianBitConverter.ToUInt32(vh_sector, 0x064);
|
||||
HPVH.drFndrInfo2 = BigEndianBitConverter.ToUInt32(vh_sector, 0x068);
|
||||
HPVH.drFndrInfo3 = BigEndianBitConverter.ToUInt32(vh_sector, 0x06C);
|
||||
HPVH.drFndrInfo5 = BigEndianBitConverter.ToUInt32(vh_sector, 0x074);
|
||||
HPVH.drFndrInfo6 = BigEndianBitConverter.ToUInt32(vh_sector, 0x078);
|
||||
HPVH.drFndrInfo7 = BigEndianBitConverter.ToUInt32(vh_sector, 0x07C);
|
||||
|
||||
HPVH.allocationFile_logicalSize = eabr.ReadUInt64();
|
||||
eabr.BaseStream.Seek(72, SeekOrigin.Current); // Skip to next file info
|
||||
HPVH.extentsFile_logicalSize = eabr.ReadUInt64();
|
||||
eabr.BaseStream.Seek(72, SeekOrigin.Current); // Skip to next file info
|
||||
HPVH.catalogFile_logicalSize = eabr.ReadUInt64();
|
||||
eabr.BaseStream.Seek(72, SeekOrigin.Current); // Skip to next file info
|
||||
HPVH.attributesFile_logicalSize = eabr.ReadUInt64();
|
||||
eabr.BaseStream.Seek(72, SeekOrigin.Current); // Skip to next file info
|
||||
HPVH.startupFile_logicalSize = eabr.ReadUInt64();
|
||||
HPVH.allocationFile_logicalSize = BigEndianBitConverter.ToUInt64(vh_sector, 0x080);
|
||||
HPVH.extentsFile_logicalSize = BigEndianBitConverter.ToUInt64(vh_sector, 0x0D0);
|
||||
HPVH.catalogFile_logicalSize = BigEndianBitConverter.ToUInt64(vh_sector, 0x120);
|
||||
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();
|
||||
|
||||
@@ -239,150 +227,150 @@ namespace FileSystemIDandChk.Plugins
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Size = 532 bytes
|
||||
private struct HFSPlusVolumeHeader // Should be offset 0x0400 bytes in volume
|
||||
{
|
||||
public UInt16 signature; // "H+" for HFS+, "HX" for HFSX
|
||||
public UInt16 version; // 4 for HFS+, 5 for HFSX
|
||||
public UInt32 attributes; // Volume attributes
|
||||
public string lastMountedVersion; // Implementation that last mounted the 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; // Allocation block number containing the journal
|
||||
public UInt32 journalInfoBlock; // 0x00C, Allocation block number containing the journal
|
||||
|
||||
public ulong createDate; // Date of volume creation
|
||||
public ulong modifyDate; // Date of last volume modification
|
||||
public ulong backupDate; // Date of last backup
|
||||
public ulong checkedDate; // Date of last consistency check
|
||||
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; // File on the volume
|
||||
public UInt32 folderCount; // Folders on the volume
|
||||
public UInt32 fileCount; // 0x030, File on the volume
|
||||
public UInt32 folderCount; // 0x034, Folders on the volume
|
||||
|
||||
public UInt32 blockSize; // Bytes per allocation block
|
||||
public UInt32 totalBlocks; // Allocation blocks on the volume
|
||||
public UInt32 freeBlocks; // Free allocation blocks
|
||||
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; // Hint for next allocation block
|
||||
public UInt32 rsrcClumpSize; // Resource fork clump size
|
||||
public UInt32 dataClumpSize; // Data fork clump size
|
||||
public UInt32 nextCatalogID; // Next unused CNID
|
||||
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; // Times that the volume has been mounted writable
|
||||
public UInt64 encodingsBitmap; // Used text encoding hints
|
||||
public UInt32 writeCount; // 0x054, Times that the volume has been mounted writable
|
||||
public UInt64 encodingsBitmap; // 0x058, Used text encoding hints
|
||||
|
||||
public UInt32 drFndrInfo0; // finderInfo[0], CNID for bootable system's directory
|
||||
public UInt32 drFndrInfo1; // finderInfo[1], CNID of the directory containing the boot application
|
||||
public UInt32 drFndrInfo2; // finderInfo[2], CNID of the directory that should be opened on boot
|
||||
public UInt32 drFndrInfo3; // finderInfo[3], CNID for Mac OS 8 or 9 directory
|
||||
public UInt32 drFndrInfo4; // finderInfo[4], Reserved
|
||||
public UInt32 drFndrInfo5; // finderInfo[5], CNID for Mac OS X directory
|
||||
public UInt32 drFndrInfo6; // finderInfo[6], first part of Mac OS X volume ID
|
||||
public UInt32 drFndrInfo7; // finderInfo[7], second part of Mac OS X volume ID
|
||||
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;
|
||||
public UInt32 allocationFile_clumpSize;
|
||||
public UInt32 allocationFile_totalBlocks;
|
||||
public UInt32 allocationFile_extents_startBlock0;
|
||||
public UInt32 allocationFile_extents_blockCount0;
|
||||
public UInt32 allocationFile_extents_startBlock1;
|
||||
public UInt32 allocationFile_extents_blockCount1;
|
||||
public UInt32 allocationFile_extents_startBlock2;
|
||||
public UInt32 allocationFile_extents_blockCount2;
|
||||
public UInt32 allocationFile_extents_startBlock3;
|
||||
public UInt32 allocationFile_extents_blockCount3;
|
||||
public UInt32 allocationFile_extents_startBlock4;
|
||||
public UInt32 allocationFile_extents_blockCount4;
|
||||
public UInt32 allocationFile_extents_startBlock5;
|
||||
public UInt32 allocationFile_extents_blockCount5;
|
||||
public UInt32 allocationFile_extents_startBlock6;
|
||||
public UInt32 allocationFile_extents_blockCount6;
|
||||
public UInt32 allocationFile_extents_startBlock7;
|
||||
public UInt32 allocationFile_extents_blockCount7;
|
||||
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;
|
||||
public UInt32 extentsFile_clumpSize;
|
||||
public UInt32 extentsFile_totalBlocks;
|
||||
public UInt32 extentsFile_extents_startBlock0;
|
||||
public UInt32 extentsFile_extents_blockCount0;
|
||||
public UInt32 extentsFile_extents_startBlock1;
|
||||
public UInt32 extentsFile_extents_blockCount1;
|
||||
public UInt32 extentsFile_extents_startBlock2;
|
||||
public UInt32 extentsFile_extents_blockCount2;
|
||||
public UInt32 extentsFile_extents_startBlock3;
|
||||
public UInt32 extentsFile_extents_blockCount3;
|
||||
public UInt32 extentsFile_extents_startBlock4;
|
||||
public UInt32 extentsFile_extents_blockCount4;
|
||||
public UInt32 extentsFile_extents_startBlock5;
|
||||
public UInt32 extentsFile_extents_blockCount5;
|
||||
public UInt32 extentsFile_extents_startBlock6;
|
||||
public UInt32 extentsFile_extents_blockCount6;
|
||||
public UInt32 extentsFile_extents_startBlock7;
|
||||
public UInt32 extentsFile_extents_blockCount7;
|
||||
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;
|
||||
public UInt32 catalogFile_clumpSize;
|
||||
public UInt32 catalogFile_totalBlocks;
|
||||
public UInt32 catalogFile_extents_startBlock0;
|
||||
public UInt32 catalogFile_extents_blockCount0;
|
||||
public UInt32 catalogFile_extents_startBlock1;
|
||||
public UInt32 catalogFile_extents_blockCount1;
|
||||
public UInt32 catalogFile_extents_startBlock2;
|
||||
public UInt32 catalogFile_extents_blockCount2;
|
||||
public UInt32 catalogFile_extents_startBlock3;
|
||||
public UInt32 catalogFile_extents_blockCount3;
|
||||
public UInt32 catalogFile_extents_startBlock4;
|
||||
public UInt32 catalogFile_extents_blockCount4;
|
||||
public UInt32 catalogFile_extents_startBlock5;
|
||||
public UInt32 catalogFile_extents_blockCount5;
|
||||
public UInt32 catalogFile_extents_startBlock6;
|
||||
public UInt32 catalogFile_extents_blockCount6;
|
||||
public UInt32 catalogFile_extents_startBlock7;
|
||||
public UInt32 catalogFile_extents_blockCount7;
|
||||
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;
|
||||
public UInt32 attributesFile_clumpSize;
|
||||
public UInt32 attributesFile_totalBlocks;
|
||||
public UInt32 attributesFile_extents_startBlock0;
|
||||
public UInt32 attributesFile_extents_blockCount0;
|
||||
public UInt32 attributesFile_extents_startBlock1;
|
||||
public UInt32 attributesFile_extents_blockCount1;
|
||||
public UInt32 attributesFile_extents_startBlock2;
|
||||
public UInt32 attributesFile_extents_blockCount2;
|
||||
public UInt32 attributesFile_extents_startBlock3;
|
||||
public UInt32 attributesFile_extents_blockCount3;
|
||||
public UInt32 attributesFile_extents_startBlock4;
|
||||
public UInt32 attributesFile_extents_blockCount4;
|
||||
public UInt32 attributesFile_extents_startBlock5;
|
||||
public UInt32 attributesFile_extents_blockCount5;
|
||||
public UInt32 attributesFile_extents_startBlock6;
|
||||
public UInt32 attributesFile_extents_blockCount6;
|
||||
public UInt32 attributesFile_extents_startBlock7;
|
||||
public UInt32 attributesFile_extents_blockCount7;
|
||||
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;
|
||||
public UInt32 startupFile_clumpSize;
|
||||
public UInt32 startupFile_totalBlocks;
|
||||
public UInt32 startupFile_extents_startBlock0;
|
||||
public UInt32 startupFile_extents_blockCount0;
|
||||
public UInt32 startupFile_extents_startBlock1;
|
||||
public UInt32 startupFile_extents_blockCount1;
|
||||
public UInt32 startupFile_extents_startBlock2;
|
||||
public UInt32 startupFile_extents_blockCount2;
|
||||
public UInt32 startupFile_extents_startBlock3;
|
||||
public UInt32 startupFile_extents_blockCount3;
|
||||
public UInt32 startupFile_extents_startBlock4;
|
||||
public UInt32 startupFile_extents_blockCount4;
|
||||
public UInt32 startupFile_extents_startBlock5;
|
||||
public UInt32 startupFile_extents_blockCount5;
|
||||
public UInt32 startupFile_extents_startBlock6;
|
||||
public UInt32 startupFile_extents_blockCount6;
|
||||
public UInt32 startupFile_extents_startBlock7;
|
||||
public UInt32 startupFile_extents_blockCount7;
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
// TODO: Implement support for disc images
|
||||
/*
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class AppleMFS : Plugin
|
||||
@@ -164,43 +165,43 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
private struct MFS_MasterDirectoryBlock // Should be offset 0x0400 bytes in volume
|
||||
{
|
||||
public UInt16 drSigWord; // Signature, 0xD2D7
|
||||
public ulong drCrDate; // Volume creation date
|
||||
public ulong drLsBkUp; // Volume last backup date
|
||||
public UInt16 drAtrb; // Volume attributes
|
||||
public UInt16 drNmFls; // Volume number of files
|
||||
public UInt16 drDirSt; // First directory block
|
||||
public UInt16 drBlLen; // Length of directory in blocks
|
||||
public UInt16 drNmAlBlks; // Volume allocation blocks
|
||||
public UInt32 drAlBlkSiz; // Size of allocation blocks
|
||||
public UInt32 drClpSiz; // Number of bytes to allocate
|
||||
public UInt16 drAlBlSt; // First allocation block in block map
|
||||
public UInt32 drNxtFNum; // Next unused file number
|
||||
public UInt16 drFreeBks; // Number of unused allocation blocks
|
||||
public byte drVNSiz; // Length of volume name
|
||||
public string drVN; // Characters of volume name
|
||||
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; // Signature, 0x4C4B if bootable
|
||||
public UInt32 branch; // Branch
|
||||
public byte boot_flags; // Boot block flags
|
||||
public byte boot_version; // Boot block version
|
||||
public short sec_sv_pages; // Allocate secondary buffers
|
||||
public string system_name; // System file name (10 bytes)
|
||||
public string finder_name; // Finder file name (10 bytes)
|
||||
public string debug_name; // Debugger file name (10 bytes)
|
||||
public string disasm_name; // Disassembler file name (10 bytes)
|
||||
public string stupscr_name; // Startup screen file name (10 bytes)
|
||||
public string bootup_name; // First program to execute on boot (10 bytes)
|
||||
public string clipbrd_name; // Clipboard file name (10 bytes)
|
||||
public UInt16 max_files; // 1/4 of maximum opened at a time files
|
||||
public UInt16 queue_size; // Event queue size
|
||||
public UInt32 heap_128k; // Heap size on a Mac with 128KiB of RAM
|
||||
public UInt32 heap_256k; // Heap size on a Mac with 256KiB of RAM
|
||||
public UInt32 heap_512k; // Heap size on a Mac with 512KiB of RAM or more
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@@ -3,8 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class BeFS : Plugin
|
||||
@@ -29,100 +27,93 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
br.BaseStream.Seek(32 + offset, SeekOrigin.Begin); // Seek to magic
|
||||
|
||||
magic = br.ReadUInt32();
|
||||
|
||||
if(magic == BEFS_MAGIC1) // Little-endian BFS
|
||||
return true;
|
||||
else if(magic == BEFS_CIGAM1) // Big-endian BFS
|
||||
UInt32 magic_be;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector (0 + partitionOffset);
|
||||
|
||||
magic = BitConverter.ToUInt32 (sb_sector, 0x20);
|
||||
magic_be = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20);
|
||||
|
||||
if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
br.BaseStream.Seek(32 + 512 + offset, SeekOrigin.Begin); // Seek to magic, skip boot
|
||||
sb_sector = imagePlugin.ReadSector (1 + partitionOffset);
|
||||
|
||||
magic = BitConverter.ToUInt32 (sb_sector, 0x20);
|
||||
magic_be = BigEndianBitConverter.ToUInt32 (sb_sector, 0x20);
|
||||
|
||||
magic = br.ReadUInt32();
|
||||
|
||||
if(magic == BEFS_MAGIC1) // Little-endian BFS
|
||||
return true;
|
||||
else if(magic == BEFS_CIGAM1) // Big-endian BFS
|
||||
if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
byte[] name_bytes = new byte[32];
|
||||
bool littleendian = true;
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BeSuperBlock besb = new BeSuperBlock();
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
br.BaseStream.Seek(32 + offset, SeekOrigin.Begin); // Seek to magic
|
||||
besb.magic1 = br.ReadUInt32();
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector (0 + partitionOffset);
|
||||
|
||||
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
|
||||
{
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
if(besb.magic1 == BEFS_CIGAM1)
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
br.BaseStream.Seek(32 + 512 + offset, SeekOrigin.Begin); // Seek to magic
|
||||
besb.magic1 = br.ReadUInt32();
|
||||
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
|
||||
{
|
||||
br.BaseStream.Seek(offset + 512, SeekOrigin.Begin);
|
||||
if(besb.magic1 == BEFS_CIGAM1)
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
name_bytes = eabr.ReadBytes(32);
|
||||
|
||||
Array.Copy (sb_sector, 0x000, name_bytes, 0, 0x20);
|
||||
besb.name = StringHandlers.CToString(name_bytes);
|
||||
besb.magic1 = eabr.ReadUInt32();
|
||||
besb.fs_byte_order = eabr.ReadUInt32();
|
||||
besb.block_size = eabr.ReadUInt32();
|
||||
besb.block_shift = eabr.ReadUInt32();
|
||||
besb.num_blocks = eabr.ReadInt64();
|
||||
besb.used_blocks = eabr.ReadInt64();
|
||||
besb.inode_size = eabr.ReadInt32();
|
||||
besb.magic2 = eabr.ReadUInt32();
|
||||
besb.blocks_per_ag = eabr.ReadInt32();
|
||||
besb.ag_shift = eabr.ReadInt32();
|
||||
besb.num_ags = eabr.ReadInt32();
|
||||
besb.flags = eabr.ReadUInt32();
|
||||
besb.log_blocks_ag = eabr.ReadInt32();
|
||||
besb.log_blocks_start = eabr.ReadUInt16();
|
||||
besb.log_blocks_len = eabr.ReadUInt16();
|
||||
besb.log_start = eabr.ReadInt64();
|
||||
besb.log_end = eabr.ReadInt64();
|
||||
besb.magic3 = eabr.ReadUInt32();
|
||||
besb.root_dir_ag = eabr.ReadInt32();
|
||||
besb.root_dir_start = eabr.ReadUInt16();
|
||||
besb.root_dir_len = eabr.ReadUInt16();
|
||||
besb.indices_ag = eabr.ReadInt32();
|
||||
besb.indices_start = eabr.ReadUInt16();
|
||||
besb.indices_len = eabr.ReadUInt16();
|
||||
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(!littleendian) // Big-endian filesystem
|
||||
if(!BigEndianBitConverter.IsLittleEndian) // Big-endian filesystem
|
||||
sb.AppendLine("Big-endian BeFS");
|
||||
else
|
||||
sb.AppendLine("Little-endian BeFS");
|
||||
@@ -175,32 +166,31 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
private struct BeSuperBlock
|
||||
{
|
||||
public string name; // Volume name, 32 bytes
|
||||
public UInt32 magic1; // "BFS1", 0x42465331
|
||||
public UInt32 fs_byte_order; // "BIGE", 0x42494745
|
||||
public UInt32 block_size; // Bytes per block
|
||||
public UInt32 block_shift; // 1 << block_shift == block_size
|
||||
public Int64 num_blocks; // Blocks in volume
|
||||
public Int64 used_blocks; // Used blocks in volume
|
||||
public Int32 inode_size; // Bytes per inode
|
||||
public UInt32 magic2; // 0xDD121031
|
||||
public Int32 blocks_per_ag; // Blocks per allocation group
|
||||
public Int32 ag_shift; // 1 << ag_shift == blocks_per_ag
|
||||
public Int32 num_ags; // Allocation groups in volume
|
||||
public UInt32 flags; // 0x434c454e if clean, 0x44495254 if dirty
|
||||
public Int32 log_blocks_ag; // Allocation group of journal
|
||||
public UInt16 log_blocks_start; // Start block of journal, inside ag
|
||||
public UInt16 log_blocks_len; // Length in blocks of journal, inside ag
|
||||
public Int64 log_start; // Start of journal
|
||||
public Int64 log_end; // End of journal
|
||||
public UInt32 magic3; // 0x15B6830E
|
||||
public Int32 root_dir_ag; // Allocation group where root folder's i-node resides
|
||||
public UInt16 root_dir_start; // Start in ag of root folder's i-node
|
||||
public UInt16 root_dir_len; // As this is part of inode_addr, this is 1
|
||||
public Int32 indices_ag; // Allocation group where indices' i-node resides
|
||||
public UInt16 indices_start; // Start in ag of indices' i-node
|
||||
public UInt16 indices_len; // As this is part of inode_addr, this is 1
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
// TODO: Implement detecting DOS bootable disks
|
||||
// TODO: Implement detecting Atari TOS bootable disks and printing corresponding fields
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class FAT : Plugin
|
||||
@@ -15,7 +15,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
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
|
||||
@@ -23,27 +23,23 @@ namespace FileSystemIDandChk.Plugins
|
||||
UInt32 first_fat_entry; // No matter FAT size we read 4 bytes for checking
|
||||
UInt16 bps, rsectors;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
byte[] bpb_sector = imagePlugin.ReadSector (0 + partitionOffset);
|
||||
byte[] fat_sector;
|
||||
|
||||
br.BaseStream.Seek(0x10 + offset, SeekOrigin.Begin); // FATs, 1 or 2, maybe 0, never bigger
|
||||
fats_no = br.ReadByte();
|
||||
br.BaseStream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
|
||||
media_descriptor = br.ReadByte();
|
||||
br.BaseStream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52
|
||||
fat32_signature = br.ReadBytes(8);
|
||||
br.BaseStream.Seek(0x0B + offset, SeekOrigin.Begin); // Bytes per sector
|
||||
bps = br.ReadUInt16();
|
||||
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;
|
||||
br.BaseStream.Seek(0x0E + offset, SeekOrigin.Begin); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT)
|
||||
rsectors = br.ReadUInt16();
|
||||
rsectors = BitConverter.ToUInt16 (bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT)
|
||||
if(rsectors==0)
|
||||
rsectors=1;
|
||||
if((ulong)br.BaseStream.Length > (ulong)(bps*rsectors + offset))
|
||||
br.BaseStream.Seek(bps*rsectors + offset, SeekOrigin.Begin); // First FAT entry
|
||||
if(imagePlugin.GetSectors() > ((ulong)rsectors + partitionOffset))
|
||||
fat_sector = imagePlugin.ReadSector(rsectors + partitionOffset); // First FAT entry
|
||||
else
|
||||
return false;
|
||||
first_fat_entry = br.ReadUInt32(); // Easier to manage
|
||||
first_fat_entry = BitConverter.ToUInt32 (fat_sector, 0); // Easier to manage
|
||||
|
||||
if(MainClass.isDebug)
|
||||
{
|
||||
@@ -75,12 +71,11 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
byte[] dosString; // Space-padded
|
||||
bool isFAT32 = false;
|
||||
@@ -89,23 +84,22 @@ namespace FileSystemIDandChk.Plugins
|
||||
string fat32_signature;
|
||||
UInt16 bps, rsectors;
|
||||
|
||||
br.BaseStream.Seek(0x10 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
|
||||
fats_no = br.ReadByte();
|
||||
br.BaseStream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
|
||||
media_descriptor =(byte) stream.ReadByte();
|
||||
br.BaseStream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52
|
||||
dosString = br.ReadBytes(8);
|
||||
fat32_signature = Encoding.ASCII.GetString(dosString);
|
||||
br.BaseStream.Seek(0x0B + offset, SeekOrigin.Begin); // Bytes per sector
|
||||
bps = br.ReadUInt16();
|
||||
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
|
||||
dosString = new byte[8];
|
||||
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;
|
||||
br.BaseStream.Seek(0x0E + offset, SeekOrigin.Begin); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT)
|
||||
rsectors = br.ReadUInt16();
|
||||
rsectors = BitConverter.ToUInt16 (bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT)
|
||||
if(rsectors==0)
|
||||
rsectors=1;
|
||||
br.BaseStream.Seek(bps*rsectors + offset, SeekOrigin.Begin); // First FAT entry
|
||||
first_fat_entry = br.ReadUInt32(); // Easier to manage
|
||||
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!
|
||||
return;
|
||||
@@ -133,49 +127,52 @@ namespace FileSystemIDandChk.Plugins
|
||||
ExtendedParameterBlock EPB = new ExtendedParameterBlock();
|
||||
FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock();
|
||||
|
||||
|
||||
br.BaseStream.Seek(3 + offset, SeekOrigin.Begin);
|
||||
dosString = br.ReadBytes(8);
|
||||
dosString = new byte[8];
|
||||
Array.Copy (bpb_sector, 0x03, dosString, 0, 8);
|
||||
BPB.OEMName = Encoding.ASCII.GetString(dosString);
|
||||
BPB.bps = br.ReadUInt16();
|
||||
BPB.spc = br.ReadByte();
|
||||
BPB.rsectors = br.ReadUInt16();
|
||||
BPB.fats_no = br.ReadByte();
|
||||
BPB.root_ent = br.ReadUInt16();
|
||||
BPB.sectors = br.ReadUInt16();
|
||||
BPB.media = br.ReadByte();
|
||||
BPB.spfat = br.ReadUInt16();
|
||||
BPB.sptrk = br.ReadUInt16();
|
||||
BPB.heads = br.ReadUInt16();
|
||||
BPB.hsectors = br.ReadUInt32();
|
||||
BPB.big_sectors = br.ReadUInt32();
|
||||
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];
|
||||
BPB.root_ent = BitConverter.ToUInt16(bpb_sector, 0x11);
|
||||
BPB.sectors = BitConverter.ToUInt16(bpb_sector, 0x13);
|
||||
BPB.media = bpb_sector[0x15];
|
||||
BPB.spfat = BitConverter.ToUInt16(bpb_sector, 0x16);
|
||||
BPB.sptrk = BitConverter.ToUInt16(bpb_sector, 0x18);
|
||||
BPB.heads = BitConverter.ToUInt16(bpb_sector, 0x1A);
|
||||
BPB.hsectors = BitConverter.ToUInt32(bpb_sector, 0x1C);
|
||||
BPB.big_sectors = BitConverter.ToUInt32(bpb_sector, 0x20);
|
||||
|
||||
if(isFAT32)
|
||||
{
|
||||
FAT32PB.spfat = br.ReadUInt32();
|
||||
FAT32PB.fat_flags = br.ReadUInt16();
|
||||
FAT32PB.version = br.ReadUInt16();
|
||||
FAT32PB.root_cluster = br.ReadUInt32();
|
||||
FAT32PB.fsinfo_sector = br.ReadUInt16();
|
||||
FAT32PB.backup_sector = br.ReadUInt16();
|
||||
FAT32PB.drive_no = br.ReadByte();
|
||||
FAT32PB.nt_flags = br.ReadByte();
|
||||
FAT32PB.signature = br.ReadByte();
|
||||
FAT32PB.serial_no = br.ReadUInt32();
|
||||
dosString = br.ReadBytes(11);
|
||||
FAT32PB.spfat = BitConverter.ToUInt32(bpb_sector, 0x24);
|
||||
FAT32PB.fat_flags = BitConverter.ToUInt16(bpb_sector, 0x28);
|
||||
FAT32PB.version = BitConverter.ToUInt16(bpb_sector, 0x2A);
|
||||
FAT32PB.root_cluster = BitConverter.ToUInt32(bpb_sector, 0x2C);
|
||||
FAT32PB.fsinfo_sector = BitConverter.ToUInt16(bpb_sector, 0x30);
|
||||
FAT32PB.backup_sector = BitConverter.ToUInt16(bpb_sector, 0x32);
|
||||
FAT32PB.drive_no = bpb_sector[0x40];
|
||||
FAT32PB.nt_flags = bpb_sector[0x41];
|
||||
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);
|
||||
dosString = br.ReadBytes(8);
|
||||
dosString = new byte[8];
|
||||
Array.Copy (bpb_sector, 0x52, dosString, 0, 8);
|
||||
FAT32PB.fs_type = Encoding.ASCII.GetString(dosString);
|
||||
}
|
||||
else
|
||||
{
|
||||
EPB.drive_no = br.ReadByte();
|
||||
EPB.nt_flags = br.ReadByte();
|
||||
EPB.signature = br.ReadByte();
|
||||
EPB.serial_no = br.ReadUInt32();
|
||||
dosString = br.ReadBytes(11);
|
||||
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);
|
||||
dosString = br.ReadBytes(8);
|
||||
dosString = new byte[8];
|
||||
Array.Copy (bpb_sector, 0x36, dosString, 0, 8);
|
||||
EPB.fs_type = Encoding.ASCII.GetString(dosString);
|
||||
}
|
||||
|
||||
@@ -299,5 +296,4 @@ namespace FileSystemIDandChk.Plugins
|
||||
public string fs_type; // 0x52, Filesystem type, 8 bytes, space-padded, must be "FAT32 "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Using information from Linux kernel headers
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
public class FFSPlugin : Plugin
|
||||
@@ -15,42 +14,48 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream fileStream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic;
|
||||
BinaryReader br = new BinaryReader(fileStream);
|
||||
uint sb_size_in_sectors;
|
||||
byte[] ufs_sb_sectors;
|
||||
|
||||
if(fileStream.Length > (offset + sb_start_floppy + 0x055C))
|
||||
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))
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_floppy + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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(fileStream.Length > (offset + sb_start_ufs1 + 0x055C))
|
||||
if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs1*sb_size_in_sectors + sb_size_in_sectors))
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_ufs1 + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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(fileStream.Length > (offset + sb_start_ufs2 + 0x055C))
|
||||
if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs2*sb_size_in_sectors + sb_size_in_sectors))
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_ufs2 + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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(fileStream.Length > (offset + sb_start_piggy + 0x055C))
|
||||
if(imagePlugin.GetSectors() > (partitionOffset + sb_start_piggy*sb_size_in_sectors + sb_size_in_sectors))
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_piggy + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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;
|
||||
@@ -59,14 +64,15 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream fileStream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
|
||||
UInt32 magic = 0;
|
||||
BinaryReader br = new BinaryReader(fileStream);
|
||||
long sb_offset = offset;
|
||||
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;
|
||||
@@ -74,47 +80,52 @@ namespace FileSystemIDandChk.Plugins
|
||||
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)
|
||||
sb_size_in_sectors = block_size / 2048;
|
||||
else
|
||||
sb_size_in_sectors = block_size / imagePlugin.GetSectorSize();
|
||||
|
||||
if(fileStream.Length > (offset + sb_start_floppy + 0x055C) && magic == 0)
|
||||
if(imagePlugin.GetSectors() > (partitionOffset + sb_start_floppy*sb_size_in_sectors + sb_size_in_sectors) && magic == 0)
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_floppy + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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)
|
||||
sb_offset = offset + sb_start_floppy;
|
||||
sb_offset = partitionOffset + sb_start_floppy * sb_size_in_sectors;
|
||||
else
|
||||
magic = 0;
|
||||
}
|
||||
|
||||
if(fileStream.Length > (offset + sb_start_ufs1 + 0x055C) && magic == 0)
|
||||
if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs1*sb_size_in_sectors + sb_size_in_sectors) && magic == 0)
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_ufs1 + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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)
|
||||
sb_offset = offset + sb_start_ufs1;
|
||||
sb_offset = partitionOffset + sb_start_ufs1 * sb_size_in_sectors;
|
||||
else
|
||||
magic = 0;
|
||||
}
|
||||
|
||||
if(fileStream.Length > (offset + sb_start_ufs2 + 0x055C) && magic == 0)
|
||||
if(imagePlugin.GetSectors() > (partitionOffset + sb_start_ufs2*sb_size_in_sectors + sb_size_in_sectors) && magic == 0)
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_ufs2 + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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)
|
||||
sb_offset = offset + sb_start_ufs2;
|
||||
sb_offset = partitionOffset + sb_start_ufs2 * sb_size_in_sectors;
|
||||
else
|
||||
magic = 0;
|
||||
}
|
||||
|
||||
if(fileStream.Length > (offset + sb_start_piggy + 0x055C) && magic == 0)
|
||||
if(imagePlugin.GetSectors() > (partitionOffset + sb_start_piggy*sb_size_in_sectors + sb_size_in_sectors) && magic == 0)
|
||||
{
|
||||
br.BaseStream.Seek(offset + sb_start_piggy + 0x055C, SeekOrigin.Begin);
|
||||
magic = br.ReadUInt32();
|
||||
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)
|
||||
sb_offset = offset + sb_start_piggy;
|
||||
sb_offset = partitionOffset + sb_start_piggy * sb_size_in_sectors;
|
||||
else
|
||||
magic = 0;
|
||||
}
|
||||
@@ -147,196 +158,191 @@ namespace FileSystemIDandChk.Plugins
|
||||
break;
|
||||
}
|
||||
|
||||
EndianAwareBinaryReader eabr;
|
||||
if(magic == UFS_CIGAM)
|
||||
eabr = new EndianAwareBinaryReader(fileStream, false); // Big-endian UFS
|
||||
if (magic == UFS_CIGAM)
|
||||
BigEndianBitConverter.IsLittleEndian = false; // Big-endian UFS
|
||||
else
|
||||
eabr = new EndianAwareBinaryReader(fileStream, true); // Little-endian UFS
|
||||
BigEndianBitConverter.IsLittleEndian = true; // 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;
|
||||
eabr.BaseStream.Seek(sb_offset, SeekOrigin.Begin);
|
||||
ufs_sb_sectors = imagePlugin.ReadSectors(sb_offset, sb_size_in_sectors);
|
||||
|
||||
ufs_sb.fs_link_42bsd = eabr.ReadUInt32();
|
||||
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_rlink = eabr.ReadUInt32(); // 0x0004 UNUSED
|
||||
ufs_sb.fs_sblkno = eabr.ReadUInt32(); // 0x0008 addr of super-block in filesys
|
||||
ufs_sb.fs_cblkno = eabr.ReadUInt32(); // 0x000C offset of cyl-block in filesys
|
||||
ufs_sb.fs_iblkno = eabr.ReadUInt32(); // 0x0010 offset of inode-blocks in filesys
|
||||
ufs_sb.fs_dblkno = eabr.ReadUInt32(); // 0x0014 offset of first data after cg
|
||||
ufs_sb.fs_cgoffset = eabr.ReadUInt32(); // 0x0018 cylinder group offset in cylinder
|
||||
ufs_sb.fs_cgmask = eabr.ReadUInt32(); // 0x001C used to calc mod fs_ntrak
|
||||
ufs_sb.fs_time_t = eabr.ReadUInt32(); // 0x0020 last time written -- time_t
|
||||
ufs_sb.fs_size = eabr.ReadUInt32(); // 0x0024 number of blocks in fs
|
||||
ufs_sb.fs_dsize = eabr.ReadUInt32(); // 0x0028 number of data blocks in fs
|
||||
ufs_sb.fs_ncg = eabr.ReadUInt32(); // 0x002C number of cylinder groups
|
||||
ufs_sb.fs_bsize = eabr.ReadUInt32(); // 0x0030 size of basic blocks in fs
|
||||
ufs_sb.fs_fsize = eabr.ReadUInt32(); // 0x0034 size of frag blocks in fs
|
||||
ufs_sb.fs_frag = eabr.ReadUInt32(); // 0x0038 number of frags in a block in fs
|
||||
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
|
||||
ufs_sb.fs_iblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0010); // 0x0010 offset of inode-blocks in filesys
|
||||
ufs_sb.fs_dblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0014); // 0x0014 offset of first data after cg
|
||||
ufs_sb.fs_cgoffset = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0018); // 0x0018 cylinder group offset in cylinder
|
||||
ufs_sb.fs_cgmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x001C); // 0x001C used to calc mod fs_ntrak
|
||||
ufs_sb.fs_time_t = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0020); // 0x0020 last time written -- time_t
|
||||
ufs_sb.fs_size = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0024); // 0x0024 number of blocks in fs
|
||||
ufs_sb.fs_dsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0028); // 0x0028 number of data blocks in fs
|
||||
ufs_sb.fs_ncg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x002C); // 0x002C number of cylinder groups
|
||||
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
|
||||
ufs_sb.fs_minfree = eabr.ReadUInt32(); // 0x003C minimum percentage of free blocks
|
||||
ufs_sb.fs_rotdelay = eabr.ReadUInt32(); // 0x0040 num of ms for optimal next block
|
||||
ufs_sb.fs_rps = eabr.ReadUInt32(); // 0x0044 disk revolutions per second
|
||||
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
|
||||
ufs_sb.fs_bmask = eabr.ReadUInt32(); // 0x0048 ``blkoff'' calc of blk offsets
|
||||
ufs_sb.fs_fmask = eabr.ReadUInt32(); // 0x004C ``fragoff'' calc of frag offsets
|
||||
ufs_sb.fs_bshift = eabr.ReadUInt32(); // 0x0050 ``lblkno'' calc of logical blkno
|
||||
ufs_sb.fs_fshift = eabr.ReadUInt32(); // 0x0054 ``numfrags'' calc number of frags
|
||||
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
|
||||
ufs_sb.fs_maxcontig = eabr.ReadUInt32(); // 0x0058 max number of contiguous blks
|
||||
ufs_sb.fs_maxbpg = eabr.ReadUInt32(); // 0x005C max number of blks per cyl group
|
||||
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
|
||||
ufs_sb.fs_fragshift = eabr.ReadUInt32(); // 0x0060 block to frag shift
|
||||
ufs_sb.fs_fsbtodb = eabr.ReadUInt32(); // 0x0064 fsbtodb and dbtofsb shift constant
|
||||
ufs_sb.fs_sbsize = eabr.ReadUInt32(); // 0x0068 actual size of super block
|
||||
ufs_sb.fs_csmask = eabr.ReadUInt32(); // 0x006C csum block offset
|
||||
ufs_sb.fs_csshift = eabr.ReadUInt32(); // 0x0070 csum block number
|
||||
ufs_sb.fs_nindir = eabr.ReadUInt32(); // 0x0074 value of NINDIR
|
||||
ufs_sb.fs_inopb = eabr.ReadUInt32(); // 0x0078 value of INOPB
|
||||
ufs_sb.fs_nspf = eabr.ReadUInt32(); // 0x007C value of NSPF
|
||||
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
|
||||
ufs_sb.fs_csmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x006C); // 0x006C csum block offset
|
||||
ufs_sb.fs_csshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0070); // 0x0070 csum block number
|
||||
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
|
||||
ufs_sb.fs_optim = eabr.ReadUInt32(); // 0x0080 optimization preference, see below
|
||||
ufs_sb.fs_optim = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0080); // 0x0080 optimization preference, see below
|
||||
// these fields are derived from the hardware
|
||||
#region Sun
|
||||
ufs_sb.fs_npsect_sun = eabr.ReadUInt32(); // 0x0084 # sectors/track including spares
|
||||
ufs_sb.fs_npsect_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0084); // 0x0084 # sectors/track including spares
|
||||
#endregion Sun
|
||||
#region Sunx86
|
||||
eabr.BaseStream.Seek(sb_offset + 0x0084, SeekOrigin.Begin);
|
||||
ufs_sb.fs_state_t_sun86 = eabr.ReadUInt32(); // 0x0084 file system state time stamp
|
||||
ufs_sb.fs_state_t_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0084); // 0x0084 file system state time stamp
|
||||
#endregion Sunx86
|
||||
#region COMMON
|
||||
ufs_sb.fs_interleave = eabr.ReadUInt32(); // 0x0088 hardware sector interleave
|
||||
ufs_sb.fs_trackskew = eabr.ReadUInt32(); // 0x008C sector 0 skew, per track
|
||||
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
|
||||
ufs_sb.fs_id_1 = eabr.ReadUInt32(); // 0x0090
|
||||
ufs_sb.fs_id_2 = eabr.ReadUInt32(); // 0x0094
|
||||
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
|
||||
eabr.BaseStream.Seek(sb_offset + 0x0090, SeekOrigin.Begin);
|
||||
ufs_sb.fs_headswitch_43bsd = eabr.ReadUInt32(); // 0x0090
|
||||
ufs_sb.fs_trkseek_43bsd = eabr.ReadUInt32(); // 0x0094
|
||||
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
|
||||
ufs_sb.fs_csaddr = eabr.ReadUInt32(); // 0x0098 blk addr of cyl grp summary area
|
||||
ufs_sb.fs_cssize = eabr.ReadUInt32(); // 0x009C size of cyl grp summary area
|
||||
ufs_sb.fs_cgsize = eabr.ReadUInt32(); // 0x00A0 cylinder group size
|
||||
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
|
||||
ufs_sb.fs_ntrak = eabr.ReadUInt32(); // 0x00A4 tracks per cylinder
|
||||
ufs_sb.fs_nsect = eabr.ReadUInt32(); // 0x00A8 sectors per track
|
||||
ufs_sb.fs_spc = eabr.ReadUInt32(); // 0x00AC sectors per cylinder
|
||||
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
|
||||
ufs_sb.fs_ncyl = eabr.ReadUInt32(); // 0x00B0 cylinders in file system
|
||||
ufs_sb.fs_ncyl = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00B0); // 0x00B0 cylinders in file system
|
||||
// these fields can be computed from the others
|
||||
ufs_sb.fs_cpg = eabr.ReadUInt32(); // 0x00B4 cylinders per group
|
||||
ufs_sb.fs_ipg = eabr.ReadUInt32(); // 0x00B8 inodes per cylinder group
|
||||
ufs_sb.fs_fpg = eabr.ReadUInt32(); // 0x00BC blocks per group * fs_frag
|
||||
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 = eabr.ReadUInt32(); // cylinder summary information
|
||||
ufs_sb.fs_cstotal_ndir = eabr.ReadUInt32(); // 0x00C0 number of directories
|
||||
ufs_sb.fs_cstotal_nbfree = eabr.ReadUInt32(); // 0x00C4 number of free blocks
|
||||
ufs_sb.fs_cstotal_nifree = eabr.ReadUInt32(); // 0x00C8 number of free inodes
|
||||
ufs_sb.fs_cstotal_nffree = eabr.ReadUInt32(); // 0x00CC number of free frags
|
||||
// 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
|
||||
ufs_sb.fs_fmod = eabr.ReadByte(); // 0x00D0 super block modified flag
|
||||
ufs_sb.fs_clean = eabr.ReadByte(); // 0x00D1 file system is clean flag
|
||||
ufs_sb.fs_ronly = eabr.ReadByte(); // 0x00D2 mounted read-only flag
|
||||
ufs_sb.fs_flags = eabr.ReadByte(); // 0x00D3
|
||||
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
|
||||
strings_b = eabr.ReadBytes(512);
|
||||
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 = eabr.ReadUInt32(); // 0x02D4 last cg searched
|
||||
ufs_sb.fs_cs_ufs1 = eabr.ReadBytes(124); // 0x02D8, 124 bytes, UInt32s, list of fs_cs info buffers
|
||||
ufs_sb.fs_maxcluster_ufs1 = eabr.ReadUInt32(); // 0x0354
|
||||
ufs_sb.fs_cpc_ufs1 = eabr.ReadUInt32(); // 0x0358 cyl per cycle in postbl
|
||||
ufs_sb.fs_opostbl_ufs1 = eabr.ReadBytes(256); // 0x035C, 256 bytes, [16][8] matrix of UInt16s, old rotation block list head
|
||||
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
|
||||
eabr.BaseStream.Seek(sb_offset + 0x00D4, SeekOrigin.Begin);
|
||||
strings_b = eabr.ReadBytes(468);
|
||||
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
|
||||
strings_b = eabr.ReadBytes(32);
|
||||
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_swuid_ufs2 = eabr.ReadUInt32(); // 0x02C8 system-wide uid
|
||||
ufs_sb.fs_pad_ufs2 = eabr.ReadUInt32(); // 0x02D0 due to alignment of fs_swuid
|
||||
ufs_sb.fs_cgrotor_ufs2 = eabr.ReadUInt32(); // 0x02D4 last cg searched
|
||||
ufs_sb.fs_ocsp_ufs2 = eabr.ReadBytes(112); // 0x02D8, 112 bytes, UInt32s, list of fs_cs info buffers
|
||||
ufs_sb.fs_contigdirs_ufs2 = eabr.ReadUInt32(); // 0x0348 # of contiguously allocated dirs
|
||||
ufs_sb.fs_csp_ufs2 = eabr.ReadUInt32(); // 0x034C cg summary info buffer for fs_cs
|
||||
ufs_sb.fs_maxcluster_ufs2 = eabr.ReadUInt32(); // 0x0350
|
||||
ufs_sb.fs_active_ufs2 = eabr.ReadUInt32(); // 0x0354 used by snapshots to track fs
|
||||
ufs_sb.fs_old_cpc_ufs2 = eabr.ReadUInt32(); // 0x0358 cyl per cycle in postbl
|
||||
ufs_sb.fs_maxbsize_ufs2 = eabr.ReadUInt32(); // 0x035C maximum blocking factor permitted
|
||||
ufs_sb.fs_sparecon64_ufs2 = eabr.ReadBytes(136); // 0x0360, 136 bytes, UInt64s, old rotation block list head
|
||||
ufs_sb.fs_sblockloc_ufs2 = eabr.ReadUInt64(); // 0x03E8 byte offset of standard superblock
|
||||
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
|
||||
Array.Copy(ufs_sb_sectors, 0x02D8, ufs_sb.fs_ocsp_ufs2, 0, 112); // 0x02D8, 112 bytes, UInt32s, list of fs_cs info buffers
|
||||
ufs_sb.fs_contigdirs_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0348); // 0x0348 # of contiguously allocated dirs
|
||||
ufs_sb.fs_csp_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x034C); // 0x034C cg summary info buffer for fs_cs
|
||||
ufs_sb.fs_maxcluster_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0350); // 0x0350
|
||||
ufs_sb.fs_active_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0354); // 0x0354 used by snapshots to track fs
|
||||
ufs_sb.fs_old_cpc_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0358); // 0x0358 cyl per cycle in postbl
|
||||
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*/
|
||||
ufs_sb.fs_cstotal_ndir_ufs2 = eabr.ReadUInt64(); // 0x03F0 number of directories
|
||||
ufs_sb.fs_cstotal_nbfree_ufs2 = eabr.ReadUInt64(); // 0x03F8 number of free blocks
|
||||
ufs_sb.fs_cstotal_nifree_ufs2 = eabr.ReadUInt64(); // 0x0400 number of free inodes
|
||||
ufs_sb.fs_cstotal_nffree_ufs2 = eabr.ReadUInt64(); // 0x0408 number of free frags
|
||||
ufs_sb.fs_cstotal_numclusters_ufs2 = eabr.ReadUInt64(); // 0x0410 number of free clusters
|
||||
ufs_sb.fs_cstotal_spare0_ufs2 = eabr.ReadUInt64(); // 0x0418 future expansion
|
||||
ufs_sb.fs_cstotal_spare1_ufs2 = eabr.ReadUInt64(); // 0x0420 future expansion
|
||||
ufs_sb.fs_cstotal_spare2_ufs2 = eabr.ReadUInt64(); // 0x0428 future expansion
|
||||
ufs_sb.fs_time_sec_ufs2 = eabr.ReadUInt32(); // 0x0430 last time written
|
||||
ufs_sb.fs_time_usec_ufs2 = eabr.ReadUInt32(); // 0x0434 last time written
|
||||
ufs_sb.fs_size_ufs2 = eabr.ReadUInt64(); // 0x0438 number of blocks in fs
|
||||
ufs_sb.fs_dsize_ufs2 = eabr.ReadUInt64(); // 0x0440 number of data blocks in fs
|
||||
ufs_sb.fs_csaddr_ufs2 = eabr.ReadUInt64(); // 0x0448 blk addr of cyl grp summary area
|
||||
ufs_sb.fs_pendingblocks_ufs2 = eabr.ReadUInt64(); // 0x0450 blocks in process of being freed
|
||||
ufs_sb.fs_pendinginodes_ufs2 = eabr.ReadUInt32(); // 0x0458 inodes in process of being freed
|
||||
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
|
||||
ufs_sb.fs_cstotal_nffree_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0408); // 0x0408 number of free frags
|
||||
ufs_sb.fs_cstotal_numclusters_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0410); // 0x0410 number of free clusters
|
||||
ufs_sb.fs_cstotal_spare0_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0418); // 0x0418 future expansion
|
||||
ufs_sb.fs_cstotal_spare1_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0420); // 0x0420 future expansion
|
||||
ufs_sb.fs_cstotal_spare2_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0428); // 0x0428 future expansion
|
||||
ufs_sb.fs_time_sec_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0430); // 0x0430 last time written
|
||||
ufs_sb.fs_time_usec_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0434); // 0x0434 last time written
|
||||
ufs_sb.fs_size_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0438); // 0x0438 number of blocks in fs
|
||||
ufs_sb.fs_dsize_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0440); // 0x0440 number of data blocks in fs
|
||||
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
|
||||
ufs_sb.fs_sparecon_sun = eabr.ReadBytes(212); // 0x045C, 212 bytes, reserved for future constants
|
||||
ufs_sb.fs_reclaim_sun = eabr.ReadUInt32(); // 0x0530
|
||||
ufs_sb.fs_sparecon2_sun = eabr.ReadUInt32(); // 0x0534
|
||||
ufs_sb.fs_state_t_sun = eabr.ReadUInt32(); // 0x0538 file system state time stamp
|
||||
ufs_sb.fs_qbmask0_sun = eabr.ReadUInt32(); // 0x053C ~usb_bmask
|
||||
ufs_sb.fs_qbmask1_sun = eabr.ReadUInt32(); // 0x0540 ~usb_bmask
|
||||
ufs_sb.fs_qfmask0_sun = eabr.ReadUInt32(); // 0x0544 ~usb_fmask
|
||||
ufs_sb.fs_qfmask1_sun = eabr.ReadUInt32(); // 0x0548 ~usb_fmask
|
||||
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
|
||||
ufs_sb.fs_state_t_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0538); // 0x0538 file system state time stamp
|
||||
ufs_sb.fs_qbmask0_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x053C); // 0x053C ~usb_bmask
|
||||
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
|
||||
eabr.BaseStream.Seek(sb_offset + 0x045C, SeekOrigin.Begin);
|
||||
ufs_sb.fs_sparecon_sun86 = eabr.ReadBytes(212); // 0x045C, 212 bytes, reserved for future constants
|
||||
ufs_sb.fs_reclaim_sun86 = eabr.ReadUInt32(); // 0x0530
|
||||
ufs_sb.fs_sparecon2_sun86 = eabr.ReadUInt32(); // 0x0534
|
||||
ufs_sb.fs_npsect_sun86 = eabr.ReadUInt32(); // 0x0538 # sectors/track including spares
|
||||
ufs_sb.fs_qbmask0_sun86 = eabr.ReadUInt32(); // 0x053C ~usb_bmask
|
||||
ufs_sb.fs_qbmask1_sun86 = eabr.ReadUInt32(); // 0x0540 ~usb_bmask
|
||||
ufs_sb.fs_qfmask0_sun86 = eabr.ReadUInt32(); // 0x0544 ~usb_fmask
|
||||
ufs_sb.fs_qfmask1_sun86 = eabr.ReadUInt32(); // 0x0548 ~usb_fmask
|
||||
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
|
||||
ufs_sb.fs_npsect_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0538); // 0x0538 # sectors/track including spares
|
||||
ufs_sb.fs_qbmask0_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x053C); // 0x053C ~usb_bmask
|
||||
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
|
||||
eabr.BaseStream.Seek(sb_offset + 0x045C, SeekOrigin.Begin);
|
||||
ufs_sb.fs_sparecon_44bsd = eabr.ReadBytes(200); // 0x045C, 200 bytes
|
||||
ufs_sb.fs_contigsumsize_44bsd = eabr.ReadUInt32(); // 0x0524 size of cluster summary array
|
||||
ufs_sb.fs_maxsymlinklen_44bsd = eabr.ReadUInt32(); // 0x0528 max length of an internal symlink
|
||||
ufs_sb.fs_inodefmt_44bsd = eabr.ReadUInt32(); // 0x052C format of on-disk inodes
|
||||
ufs_sb.fs_maxfilesize0_44bsd = eabr.ReadUInt32(); // 0x0530 max representable file size
|
||||
ufs_sb.fs_maxfilesize1_44bsd = eabr.ReadUInt32(); // 0x0534 max representable file size
|
||||
ufs_sb.fs_qbmask0_44bsd = eabr.ReadUInt32(); // 0x0538 ~usb_bmask
|
||||
ufs_sb.fs_qbmask1_44bsd = eabr.ReadUInt32(); // 0x053C ~usb_bmask
|
||||
ufs_sb.fs_qfmask0_44bsd = eabr.ReadUInt32(); // 0x0540 ~usb_fmask
|
||||
ufs_sb.fs_qfmask1_44bsd = eabr.ReadUInt32(); // 0x0544 ~usb_fmask
|
||||
ufs_sb.fs_state_t_44bsd = eabr.ReadUInt32(); // 0x0548 file system state time stamp
|
||||
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
|
||||
ufs_sb.fs_inodefmt_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x052C); // 0x052C format of on-disk inodes
|
||||
ufs_sb.fs_maxfilesize0_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); // 0x0530 max representable file size
|
||||
ufs_sb.fs_maxfilesize1_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); // 0x0534 max representable file size
|
||||
ufs_sb.fs_qbmask0_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0538); // 0x0538 ~usb_bmask
|
||||
ufs_sb.fs_qbmask1_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x053C); // 0x053C ~usb_bmask
|
||||
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
|
||||
ufs_sb.fs_postblformat = eabr.ReadUInt32(); // 0x054C format of positional layout tables
|
||||
ufs_sb.fs_nrpos = eabr.ReadUInt32(); // 0x0550 number of rotational positions
|
||||
ufs_sb.fs_postbloff = eabr.ReadUInt32(); // 0x0554 (__s16) rotation block list head
|
||||
ufs_sb.fs_rotbloff = eabr.ReadUInt32(); // 0x0558 (__u8) blocks for each rotation
|
||||
ufs_sb.fs_magic = eabr.ReadUInt32(); // 0x055C magic number
|
||||
ufs_sb.fs_space = eabr.ReadByte(); // 0x0560 list of blocks for each rotation
|
||||
if(eabr.BaseStream.Position != (sb_offset + 0x0561) && MainClass.isDebug)
|
||||
Console.WriteLine("Error reading superblock, out of alignment 0x{0:X8}, expected 0x{1:X8}", eabr.BaseStream.Position, (sb_offset + 0x0561));
|
||||
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
|
||||
ufs_sb.fs_rotbloff = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0558); // 0x0558 (__u8) blocks for each rotation
|
||||
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)
|
||||
{
|
||||
@@ -655,13 +661,13 @@ namespace FileSystemIDandChk.Plugins
|
||||
information = sbInformation.ToString();
|
||||
}
|
||||
|
||||
private const int block_size = 8192;
|
||||
private const uint block_size = 8192;
|
||||
|
||||
// As specified in FreeBSD source code, FFS/UFS can start in any of four places
|
||||
private const long sb_start_floppy = 0; // For floppies, start at offset 0
|
||||
private const long sb_start_ufs1 = block_size; // For normal devices, start at offset 8192
|
||||
private const long sb_start_ufs2 = block_size*8; // For UFS2, start at offset 65536
|
||||
private const long sb_start_piggy = block_size*32; // For piggy devices (?), start at offset 262144
|
||||
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
|
||||
@@ -674,6 +680,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
// 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
|
||||
|
||||
@@ -3,8 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class HPFS : Plugin
|
||||
@@ -15,22 +13,13 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt16 bps;
|
||||
UInt32 magic1, magic2;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
br.BaseStream.Seek(offset + 3 + 8, SeekOrigin.Begin); // Seek to bps
|
||||
bps = br.ReadUInt16();
|
||||
|
||||
if(br.BaseStream.Length < offset + (16 * bps))
|
||||
return false;
|
||||
|
||||
br.BaseStream.Seek(offset + (16 * bps), SeekOrigin.Begin); // Seek to superblock, on logical sector 16
|
||||
magic1 = br.ReadUInt32();
|
||||
magic2 = br.ReadUInt32();
|
||||
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;
|
||||
@@ -38,14 +27,12 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
HPFS_BIOSParameterBlock hpfs_bpb = new HPFS_BIOSParameterBlock();
|
||||
HPFS_SuperBlock hpfs_sb = new HPFS_SuperBlock();
|
||||
HPFS_SpareBlock hpfs_sp = new HPFS_SpareBlock();
|
||||
@@ -53,73 +40,73 @@ namespace FileSystemIDandChk.Plugins
|
||||
byte[] oem_name = new byte[8];
|
||||
byte[] volume_name = new byte[11];
|
||||
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin); // Seek to BPB
|
||||
hpfs_bpb.jmp1 = br.ReadByte();
|
||||
hpfs_bpb.jmp2 = br.ReadUInt16();
|
||||
oem_name = br.ReadBytes(8);
|
||||
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
|
||||
byte[] hpfs_sp_sector = imagePlugin.ReadSector(17 + partitionOffset); // Seek to spareblock, on logical sector 17
|
||||
|
||||
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.bps = br.ReadUInt16();
|
||||
hpfs_bpb.spc = br.ReadByte();
|
||||
hpfs_bpb.rsectors = br.ReadUInt16();
|
||||
hpfs_bpb.fats_no = br.ReadByte();
|
||||
hpfs_bpb.root_ent = br.ReadUInt16();
|
||||
hpfs_bpb.sectors = br.ReadUInt16();
|
||||
hpfs_bpb.media = br.ReadByte();
|
||||
hpfs_bpb.spfat = br.ReadUInt16();
|
||||
hpfs_bpb.sptrk = br.ReadUInt16();
|
||||
hpfs_bpb.heads = br.ReadUInt16();
|
||||
hpfs_bpb.hsectors = br.ReadUInt32();
|
||||
hpfs_bpb.big_sectors = br.ReadUInt32();
|
||||
hpfs_bpb.drive_no = br.ReadByte();
|
||||
hpfs_bpb.nt_flags = br.ReadByte();
|
||||
hpfs_bpb.signature = br.ReadByte();
|
||||
hpfs_bpb.serial_no = br.ReadUInt32();
|
||||
volume_name = br.ReadBytes(11);
|
||||
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);
|
||||
hpfs_bpb.fats_no = hpfs_bpb_sector[0x010];
|
||||
hpfs_bpb.root_ent = BitConverter.ToUInt16(hpfs_bpb_sector, 0x011);
|
||||
hpfs_bpb.sectors = BitConverter.ToUInt16(hpfs_bpb_sector, 0x013);
|
||||
hpfs_bpb.media = hpfs_bpb_sector[0x015];
|
||||
hpfs_bpb.spfat = BitConverter.ToUInt16(hpfs_bpb_sector, 0x016);
|
||||
hpfs_bpb.sptrk = BitConverter.ToUInt16(hpfs_bpb_sector, 0x018);
|
||||
hpfs_bpb.heads = BitConverter.ToUInt16(hpfs_bpb_sector, 0x01A);
|
||||
hpfs_bpb.hsectors = BitConverter.ToUInt32(hpfs_bpb_sector, 0x01C);
|
||||
hpfs_bpb.big_sectors = BitConverter.ToUInt32(hpfs_bpb_sector, 0x024);
|
||||
hpfs_bpb.drive_no = hpfs_bpb_sector[0x028];
|
||||
hpfs_bpb.nt_flags = hpfs_bpb_sector[0x029];
|
||||
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);
|
||||
oem_name = br.ReadBytes(8);
|
||||
Array.Copy(hpfs_bpb_sector, 0x03A, oem_name, 0, 8);
|
||||
hpfs_bpb.fs_type = StringHandlers.CToString(oem_name);
|
||||
|
||||
br.BaseStream.Seek((16*hpfs_bpb.bps) + offset, SeekOrigin.Begin); // Seek to SuperBlock
|
||||
|
||||
hpfs_sb.magic1 = br.ReadUInt32();
|
||||
hpfs_sb.magic2 = br.ReadUInt32();
|
||||
hpfs_sb.version = br.ReadByte();
|
||||
hpfs_sb.func_version = br.ReadByte();
|
||||
hpfs_sb.dummy = br.ReadUInt16();
|
||||
hpfs_sb.root_fnode = br.ReadUInt32();
|
||||
hpfs_sb.sectors = br.ReadUInt32();
|
||||
hpfs_sb.badblocks = br.ReadUInt32();
|
||||
hpfs_sb.bitmap_lsn = br.ReadUInt32();
|
||||
hpfs_sb.zero1 = br.ReadUInt32();
|
||||
hpfs_sb.badblock_lsn = br.ReadUInt32();
|
||||
hpfs_sb.zero2 = br.ReadUInt32();
|
||||
hpfs_sb.last_chkdsk = br.ReadInt32();
|
||||
hpfs_sb.last_optim = br.ReadInt32();
|
||||
hpfs_sb.dband_sectors = br.ReadUInt32();
|
||||
hpfs_sb.dband_start = br.ReadUInt32();
|
||||
hpfs_sb.dband_last = br.ReadUInt32();
|
||||
hpfs_sb.dband_bitmap = br.ReadUInt32();
|
||||
hpfs_sb.zero3 = br.ReadUInt64();
|
||||
hpfs_sb.zero4 = br.ReadUInt64();
|
||||
hpfs_sb.zero5 = br.ReadUInt64();
|
||||
hpfs_sb.zero6 = br.ReadUInt64();
|
||||
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];
|
||||
hpfs_sb.dummy = BitConverter.ToUInt16(hpfs_sb_sector, 0x00A);
|
||||
hpfs_sb.root_fnode = BitConverter.ToUInt32(hpfs_sb_sector, 0x00C);
|
||||
hpfs_sb.sectors = BitConverter.ToUInt32(hpfs_sb_sector, 0x010);
|
||||
hpfs_sb.badblocks = BitConverter.ToUInt32(hpfs_sb_sector, 0x014);
|
||||
hpfs_sb.bitmap_lsn = BitConverter.ToUInt32(hpfs_sb_sector, 0x018);
|
||||
hpfs_sb.zero1 = BitConverter.ToUInt32(hpfs_sb_sector, 0x01C);
|
||||
hpfs_sb.badblock_lsn = BitConverter.ToUInt32(hpfs_sb_sector, 0x020);
|
||||
hpfs_sb.zero2 = BitConverter.ToUInt32(hpfs_sb_sector, 0x024);
|
||||
hpfs_sb.last_chkdsk = BitConverter.ToInt32(hpfs_sb_sector, 0x028);
|
||||
hpfs_sb.last_optim = BitConverter.ToInt32(hpfs_sb_sector, 0x02C);
|
||||
hpfs_sb.dband_sectors = BitConverter.ToUInt32(hpfs_sb_sector, 0x030);
|
||||
hpfs_sb.dband_start = BitConverter.ToUInt32(hpfs_sb_sector, 0x034);
|
||||
hpfs_sb.dband_last = BitConverter.ToUInt32(hpfs_sb_sector, 0x038);
|
||||
hpfs_sb.dband_bitmap = BitConverter.ToUInt32(hpfs_sb_sector, 0x03C);
|
||||
hpfs_sb.zero3 = BitConverter.ToUInt64(hpfs_sb_sector, 0x040);
|
||||
hpfs_sb.zero4 = BitConverter.ToUInt64(hpfs_sb_sector, 0x048);
|
||||
hpfs_sb.zero5 = BitConverter.ToUInt64(hpfs_sb_sector, 0x04C);
|
||||
hpfs_sb.zero6 = BitConverter.ToUInt64(hpfs_sb_sector, 0x050);
|
||||
hpfs_sb.acl_start = BitConverter.ToUInt32(hpfs_sb_sector, 0x058);
|
||||
|
||||
br.BaseStream.Seek((17*hpfs_bpb.bps) + offset, SeekOrigin.Begin); // Seek to SuperBlock
|
||||
|
||||
hpfs_sp.magic1 = br.ReadUInt32();
|
||||
hpfs_sp.magic2 = br.ReadUInt32();
|
||||
hpfs_sp.flags1 = br.ReadByte();
|
||||
hpfs_sp.flags2 = br.ReadByte();
|
||||
hpfs_sp.dummy = br.ReadUInt16();
|
||||
hpfs_sp.hotfix_start = br.ReadUInt32();
|
||||
hpfs_sp.hotfix_used = br.ReadUInt32();
|
||||
hpfs_sp.hotfix_entries = br.ReadUInt32();
|
||||
hpfs_sp.spare_dnodes_free = br.ReadUInt32();
|
||||
hpfs_sp.spare_dnodes = br.ReadUInt32();
|
||||
hpfs_sp.codepage_lsn = br.ReadUInt32();
|
||||
hpfs_sp.codepages = br.ReadUInt32();
|
||||
hpfs_sp.sb_crc32 = br.ReadUInt32();
|
||||
hpfs_sp.sp_crc32 = br.ReadUInt32();
|
||||
hpfs_sp.magic1 = BitConverter.ToUInt32(hpfs_sp_sector, 0x000);
|
||||
hpfs_sp.magic2 = BitConverter.ToUInt32(hpfs_sp_sector, 0x004);
|
||||
hpfs_sp.flags1 = hpfs_sp_sector[0x008];
|
||||
hpfs_sp.flags2 = hpfs_sp_sector[0x009];
|
||||
hpfs_sp.dummy = BitConverter.ToUInt16(hpfs_sp_sector, 0x00A);
|
||||
hpfs_sp.hotfix_start = BitConverter.ToUInt32(hpfs_sp_sector, 0x00C);
|
||||
hpfs_sp.hotfix_used = BitConverter.ToUInt32(hpfs_sp_sector, 0x010);
|
||||
hpfs_sp.hotfix_entries = BitConverter.ToUInt32(hpfs_sp_sector, 0x014);
|
||||
hpfs_sp.spare_dnodes_free = BitConverter.ToUInt32(hpfs_sp_sector, 0x018);
|
||||
hpfs_sp.spare_dnodes = BitConverter.ToUInt32(hpfs_sp_sector, 0x01C);
|
||||
hpfs_sp.codepage_lsn = BitConverter.ToUInt32(hpfs_sp_sector, 0x020);
|
||||
hpfs_sp.codepages = BitConverter.ToUInt32(hpfs_sp_sector, 0x024);
|
||||
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 ||
|
||||
@@ -225,73 +212,72 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
private struct HPFS_BIOSParameterBlock // Sector 0
|
||||
{
|
||||
public byte jmp1; // Jump to boot code
|
||||
public UInt16 jmp2; // ...;
|
||||
public string OEMName; // OEM Name, 8 bytes, space-padded
|
||||
public UInt16 bps; // Bytes per sector
|
||||
public byte spc; // Sectors per cluster
|
||||
public UInt16 rsectors; // Reserved sectors between BPB and... does it have sense in HPFS?
|
||||
public byte fats_no; // Number of FATs... seriously?
|
||||
public UInt16 root_ent; // Number of entries on root directory... ok
|
||||
public UInt16 sectors; // Sectors in volume... doubt it
|
||||
public byte media; // Media descriptor
|
||||
public UInt16 spfat; // Sectors per FAT... again
|
||||
public UInt16 sptrk; // Sectors per track... you're kidding
|
||||
public UInt16 heads; // Heads... stop!
|
||||
public UInt32 hsectors; // Hidden sectors before BPB
|
||||
public UInt32 big_sectors; // Sectors in volume if > 65535...
|
||||
public byte drive_no; // Drive number
|
||||
public byte nt_flags; // Volume flags?
|
||||
public byte signature; // EPB signature, 0x29
|
||||
public UInt32 serial_no; // Volume serial number
|
||||
public string volume_label; // Volume label, 11 bytes, space-padded
|
||||
public string fs_type; // Filesystem type, 8 bytes, space-padded ("HPFS ")
|
||||
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; // 0xF995E849
|
||||
public UInt32 magic2; // 0xFA53E9C5
|
||||
public byte version; // HPFS version
|
||||
public byte func_version; // 2 if <= 4 GiB, 3 if > 4 GiB
|
||||
public UInt16 dummy; // Alignment
|
||||
public UInt32 root_fnode; // LSN pointer to root fnode
|
||||
public UInt32 sectors; // Sectors on volume
|
||||
public UInt32 badblocks; // Bad blocks on volume
|
||||
public UInt32 bitmap_lsn; // LSN pointer to volume bitmap
|
||||
public UInt32 zero1; // 0
|
||||
public UInt32 badblock_lsn; // LSN pointer to badblock directory
|
||||
public UInt32 zero2; // 0
|
||||
public Int32 last_chkdsk; // Time of last CHKDSK
|
||||
public Int32 last_optim; // Time of last optimization
|
||||
public UInt32 dband_sectors; // Sectors of dir band
|
||||
public UInt32 dband_start; // Start sector of dir band
|
||||
public UInt32 dband_last; // Last sector of dir band
|
||||
public UInt32 dband_bitmap; // LSN of free space bitmap
|
||||
public UInt64 zero3; // Can be used for volume name (32 bytes)
|
||||
public UInt64 zero4; // ...
|
||||
public UInt64 zero5; // ...
|
||||
public UInt64 zero6; // ...;
|
||||
public UInt32 acl_start; // LSN pointer to ACLs (only HPFS386)
|
||||
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; // 0xF9911849
|
||||
public UInt32 magic2; // 0xFA5229C5
|
||||
public byte flags1; // HPFS flags
|
||||
public byte flags2; // HPFS386 flags
|
||||
public UInt16 dummy; // Alignment
|
||||
public UInt32 hotfix_start; // LSN of hotfix directory
|
||||
public UInt32 hotfix_used; // Used hotfixes
|
||||
public UInt32 hotfix_entries; // Total hotfixes available
|
||||
public UInt32 spare_dnodes_free; // Unused spare dnodes
|
||||
public UInt32 spare_dnodes; // Length of spare dnodes list
|
||||
public UInt32 codepage_lsn; // LSN of codepage directory
|
||||
public UInt32 codepages; // Number of codepages used
|
||||
public UInt32 sb_crc32; // SuperBlock CRC32 (only HPFS386)
|
||||
public UInt32 sp_crc32; // SpareBlock CRC32 (only HPFS386)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using FileSystemIDandChk;
|
||||
// This is coded following ECMA-119.
|
||||
// TODO: Differentiate ISO Level 1, 2, 3 and ISO 9660:1999
|
||||
// TODO: Apple extensiones, requires XA or advance RR interpretation.
|
||||
// TODO: Needs a major rewrite
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
@@ -38,7 +39,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
public DateTime EffectiveTime;
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream fileStream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
if(alreadyLaunched)
|
||||
return false;
|
||||
@@ -47,22 +48,25 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
byte VDType;
|
||||
|
||||
// ISO9660 Primary Volume Descriptor starts at 32768, so that's minimal size.
|
||||
if (fileStream.Length < 32768)
|
||||
// ISO9660 is designed for 2048 bytes/sector devices
|
||||
if (imagePlugin.GetSectorSize() < 2048)
|
||||
return false;
|
||||
|
||||
// Seek to Volume Descriptor
|
||||
fileStream.Seek(32768, SeekOrigin.Begin);
|
||||
|
||||
VDType = (byte)fileStream.ReadByte();
|
||||
// ISO9660 Primary Volume Descriptor starts at sector 16, so that's minimal size.
|
||||
if (imagePlugin.GetSectors() < 16)
|
||||
return false;
|
||||
|
||||
// Read to Volume Descriptor
|
||||
byte[] vd_sector = imagePlugin.ReadSector(16 + partitionOffset);
|
||||
|
||||
VDType = vd_sector[0];
|
||||
byte[] VDMagic = new byte[5];
|
||||
|
||||
// Wrong, VDs can be any order!
|
||||
if (VDType == 255) // Supposedly we are in the PVD.
|
||||
return false;
|
||||
|
||||
if (fileStream.Read(VDMagic, 0, 5) != 5)
|
||||
return false; // Something bad happened
|
||||
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;
|
||||
@@ -70,7 +74,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream fileStream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder ISOMetadata = new StringBuilder();
|
||||
@@ -108,20 +112,22 @@ namespace FileSystemIDandChk.Plugins
|
||||
byte[] VDPathTableStart = new byte[4];
|
||||
byte[] RootDirectoryLocation = new byte[4];
|
||||
|
||||
fileStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// ISO9660 Primary Volume Descriptor starts at 32768, so that's minimal size.
|
||||
if (fileStream.Length < 32768)
|
||||
// ISO9660 is designed for 2048 bytes/sector devices
|
||||
if (imagePlugin.GetSectorSize() < 2048)
|
||||
return;
|
||||
|
||||
int counter = 0;
|
||||
// ISO9660 Primary Volume Descriptor starts at sector 16, so that's minimal size.
|
||||
if (imagePlugin.GetSectors() < 16)
|
||||
return;
|
||||
|
||||
ulong counter = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Seek to Volume Descriptor
|
||||
fileStream.Seek(32768+(2048*counter), SeekOrigin.Begin);
|
||||
byte[] vd_sector = imagePlugin.ReadSector(16 + counter + partitionOffset);
|
||||
|
||||
VDType = (byte)fileStream.ReadByte();
|
||||
VDType = vd_sector[0];
|
||||
|
||||
if (VDType == 255) // Supposedly we are in the PVD.
|
||||
{
|
||||
@@ -130,12 +136,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
break;
|
||||
}
|
||||
|
||||
if (fileStream.Read(VDMagic, 0, 5) != 5)
|
||||
{
|
||||
if (counter == 0)
|
||||
return; // Something bad happened
|
||||
break;
|
||||
}
|
||||
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.
|
||||
{
|
||||
@@ -151,11 +152,8 @@ namespace FileSystemIDandChk.Plugins
|
||||
Bootable = true;
|
||||
BootSpec = "Unknown";
|
||||
|
||||
// Seek to boot system identifier
|
||||
fileStream.Seek(32775 + (2048 * counter), SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(BootSysId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
// Read to boot system identifier
|
||||
Array.Copy(vd_sector, 0x007, BootSysId, 0, 32);
|
||||
|
||||
if (Encoding.ASCII.GetString(BootSysId).Substring(0, 23) == "EL TORITO SPECIFICATION")
|
||||
BootSpec = "El Torito";
|
||||
@@ -164,56 +162,31 @@ namespace FileSystemIDandChk.Plugins
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// Seek to first identifiers
|
||||
fileStream.Seek(32776 + (2048 * counter), SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(VDSysId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDVolId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
// Read first identifiers
|
||||
Array.Copy(vd_sector, 0x008, VDSysId, 0, 32);
|
||||
Array.Copy(vd_sector, 0x028, VDVolId, 0, 32);
|
||||
|
||||
// Get path table start
|
||||
fileStream.Seek(32908 + (2048 * counter), SeekOrigin.Begin);
|
||||
Array.Copy(vd_sector, 0x08C, VDPathTableStart, 0, 4);
|
||||
|
||||
if (fileStream.Read(VDPathTableStart, 0, 4) != 4)
|
||||
break; // Something bad happened
|
||||
// Read next identifiers
|
||||
Array.Copy(vd_sector, 0x0BE, VDVolSetId, 0, 128);
|
||||
Array.Copy(vd_sector, 0x13E, VDPubId, 0, 128);
|
||||
Array.Copy(vd_sector, 0x1BE, VDDataPrepId, 0, 128);
|
||||
Array.Copy(vd_sector, 0x23E, VDAppId, 0, 128);
|
||||
|
||||
// Seek to next identifiers
|
||||
fileStream.Seek(32958 + (2048 * counter), SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(VDVolSetId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDPubId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDDataPrepId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDAppId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
|
||||
// Seek to dates
|
||||
fileStream.Seek(33581 + (2048 * counter), SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(VCTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VMTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VXTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VETime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
// Read dates
|
||||
Array.Copy(vd_sector, 0x32D, VCTime, 0, 17);
|
||||
Array.Copy(vd_sector, 0x33E, VMTime, 0, 17);
|
||||
Array.Copy(vd_sector, 0x34F, VXTime, 0, 17);
|
||||
Array.Copy(vd_sector, 0x360, VETime, 0, 17);
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// Check if this is Joliet
|
||||
fileStream.Seek(32856 + (2048 * counter), SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(JolietMagic, 0, 3) != 3)
|
||||
{
|
||||
break; // Something bad happened
|
||||
}
|
||||
|
||||
Array.Copy(vd_sector, 0x058, JolietMagic, 0, 3);
|
||||
if (JolietMagic[0] == '%' && JolietMagic[1] == '/')
|
||||
{
|
||||
if (JolietMagic[2] == '@' || JolietMagic[2] == 'C' || JolietMagic[2] == 'E')
|
||||
@@ -228,37 +201,21 @@ namespace FileSystemIDandChk.Plugins
|
||||
else
|
||||
break;
|
||||
|
||||
// Seek to first identifiers
|
||||
fileStream.Seek(32776 + (2048 * counter), SeekOrigin.Begin);
|
||||
// Read first identifiers
|
||||
Array.Copy(vd_sector, 0x008, JolietSysId, 0, 32);
|
||||
Array.Copy(vd_sector, 0x028, JolietVolId, 0, 32);
|
||||
|
||||
if (fileStream.Read(JolietSysId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietVolId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
// Read next identifiers
|
||||
Array.Copy(vd_sector, 0x0BE, JolietVolSetId, 0, 128);
|
||||
Array.Copy(vd_sector, 0x13E, JolietPubId, 0, 128);
|
||||
Array.Copy(vd_sector, 0x13E, JolietDataPrepId, 0, 128);
|
||||
Array.Copy(vd_sector, 0x13E, JolietAppId, 0, 128);
|
||||
|
||||
// Seek to next identifiers
|
||||
fileStream.Seek(32958 + (2048 * counter), SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(JolietVolSetId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietPubId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietDataPrepId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietAppId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
|
||||
// Seek to dates
|
||||
fileStream.Seek(33581 + (2048 * counter), SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(JolietCTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietMTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietXTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietETime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
// Read dates
|
||||
Array.Copy(vd_sector, 0x32D, JolietCTime, 0, 17);
|
||||
Array.Copy(vd_sector, 0x33E, JolietMTime, 0, 17);
|
||||
Array.Copy(vd_sector, 0x34F, JolietXTime, 0, 17);
|
||||
Array.Copy(vd_sector, 0x360, JolietETime, 0, 17);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -275,27 +232,23 @@ namespace FileSystemIDandChk.Plugins
|
||||
decodedJolietVD = DecodeJolietDescriptor(JolietSysId, JolietVolId, JolietVolSetId, JolietPubId, JolietDataPrepId, JolietAppId, JolietCTime, JolietMTime, JolietXTime, JolietETime);
|
||||
|
||||
|
||||
int i = BitConverter.ToInt32(VDPathTableStart, 0);
|
||||
|
||||
fileStream.Seek((i * 2048)+2, SeekOrigin.Begin); // Seek to first path table location field
|
||||
ulong i = (ulong)BitConverter.ToInt32(VDPathTableStart, 0);
|
||||
|
||||
byte[] path_table = imagePlugin.ReadSector(i + partitionOffset);
|
||||
Array.Copy(path_table, 2, RootDirectoryLocation, 0, 4);
|
||||
// Check for Rock Ridge
|
||||
if (fileStream.Read(RootDirectoryLocation, 0, 4) == 4)
|
||||
byte[] root_dir = imagePlugin.ReadSector((ulong)BitConverter.ToInt32(RootDirectoryLocation, 0) + partitionOffset);
|
||||
|
||||
byte[] SUSPMagic = new byte[2];
|
||||
byte[] RRMagic = new byte[2];
|
||||
|
||||
Array.Copy(root_dir, 0x22, SUSPMagic, 0, 2);
|
||||
if (Encoding.ASCII.GetString(SUSPMagic) == "SP")
|
||||
{
|
||||
fileStream.Seek((BitConverter.ToInt32(RootDirectoryLocation,0) * 2048)+34, SeekOrigin.Begin); // Seek to root directory, first entry, system use field
|
||||
|
||||
byte[] SUSPMagic = new byte[2];
|
||||
byte[] RRMagic = new byte[2];
|
||||
|
||||
fileStream.Read(SUSPMagic, 0, 2);
|
||||
if (Encoding.ASCII.GetString(SUSPMagic) == "SP")
|
||||
Array.Copy(root_dir, 0x29, RRMagic, 0, 2);
|
||||
if (Encoding.ASCII.GetString(RRMagic) == "RR")
|
||||
{
|
||||
fileStream.Seek(5, SeekOrigin.Current); // Seek for rock ridge magic
|
||||
fileStream.Read(RRMagic, 0, 2);
|
||||
if (Encoding.ASCII.GetString(RRMagic) == "RR")
|
||||
{
|
||||
RockRidge = true;
|
||||
}
|
||||
RockRidge = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,8 +260,8 @@ namespace FileSystemIDandChk.Plugins
|
||||
StringBuilder IPBinInformation = new StringBuilder();
|
||||
|
||||
byte[] SegaHardwareID = new byte[16];
|
||||
fileStream.Seek(0, SeekOrigin.Begin); // Seek to start (again)
|
||||
fileStream.Read(SegaHardwareID, 0, 16);
|
||||
byte[] ipbin_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
Array.Copy(ipbin_sector, 0x000, SegaHardwareID, 0, 16);
|
||||
|
||||
switch (Encoding.ASCII.GetString(SegaHardwareID))
|
||||
{
|
||||
@@ -323,85 +276,80 @@ namespace FileSystemIDandChk.Plugins
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Definitions following
|
||||
byte[] volume_name = new byte[11]; // Varies
|
||||
byte[] spare_space1 = new byte[1]; // 0x00
|
||||
byte[] volume_version = new byte[2]; // Volume version in BCD. <100 = Prerelease.
|
||||
byte[] volume_type = new byte[2]; // Bit 0 = 1 => CD-ROM. Rest should be 0.
|
||||
byte[] system_name = new byte[11]; // Unknown, varies!
|
||||
byte[] spare_space2 = new byte[1]; // 0x00
|
||||
byte[] system_version = new byte[2]; // Should be 1
|
||||
byte[] spare_space3 = new byte[2]; // 0x0000
|
||||
byte[] ip_address = new byte[4]; // Initial program address
|
||||
byte[] ip_loadsize = new byte[4]; // Load size of initial program
|
||||
byte[] ip_entry_address = new byte[4]; // Initial program entry address
|
||||
byte[] ip_work_ram_size = new byte[4]; // Initial program work RAM size in bytes
|
||||
byte[] sp_address = new byte[4]; // System program address
|
||||
byte[] sp_loadsize = new byte[4]; // Load size of system program
|
||||
byte[] sp_entry_address = new byte[4]; // System program entry address
|
||||
byte[] sp_work_ram_size = new byte[4]; // System program work RAM size in bytes
|
||||
byte[] release_date = new byte[8]; // MMDDYYYY
|
||||
byte[] unknown1 = new byte[7]; // Seems to be all 0x20s
|
||||
byte[] spare_space4 = new byte[1]; // 0x00 ?
|
||||
byte[] system_reserved = new byte[160]; // System Reserved Area
|
||||
byte[] hardware_id = new byte[16]; // Hardware ID
|
||||
byte[] copyright = new byte[3]; // "(C)" -- Can be the developer code directly!, if that is the code release date will be displaced
|
||||
byte[] developer_code = new byte[5]; // "SEGA" or "T-xx"
|
||||
byte[] unknown2 = new byte[1]; // Seems to be part of developer code, need to get a SEGA disc to check
|
||||
byte[] release_date2 = new byte[8]; // Another release date, this with month in letters?
|
||||
byte[] domestic_title = new byte[48]; // Domestic version of the game title
|
||||
byte[] overseas_title = new byte[48]; // Overseas version of the game title
|
||||
byte[] application_type = new byte[2]; // Application type
|
||||
byte[] space_space5 = new byte[1]; // 0x20
|
||||
byte[] product_code = new byte[13]; // Official product code
|
||||
byte[] peripherals = new byte[16]; // Supported peripherals, see above
|
||||
byte[] spare_space6 = new byte[16]; // 0x20
|
||||
byte[] spare_space7 = new byte[64]; // Inside here should be modem information, but I need to get a modem-enabled game
|
||||
byte[] region_codes = new byte[16]; // Region codes, space-filled
|
||||
byte[] volume_name = new byte[11]; // 0x010, Varies
|
||||
byte[] spare_space1 = new byte[1]; // 0x01B, 0x00
|
||||
byte[] volume_version = new byte[2]; // 0x01C, Volume version in BCD. <100 = Prerelease.
|
||||
byte[] volume_type = new byte[2]; // 0x01E, Bit 0 = 1 => CD-ROM. Rest should be 0.
|
||||
byte[] system_name = new byte[11]; // 0x020, Unknown, varies!
|
||||
byte[] spare_space2 = new byte[1]; // 0x02B, 0x00
|
||||
byte[] system_version = new byte[2]; // 0x02C, Should be 1
|
||||
byte[] spare_space3 = new byte[2]; // 0x02E, 0x0000
|
||||
byte[] ip_address = new byte[4]; // 0x030, Initial program address
|
||||
byte[] ip_loadsize = new byte[4]; // 0x034, Load size of initial program
|
||||
byte[] ip_entry_address = new byte[4]; // 0x038, Initial program entry address
|
||||
byte[] ip_work_ram_size = new byte[4]; // 0x03C, Initial program work RAM size in bytes
|
||||
byte[] sp_address = new byte[4]; // 0x040, System program address
|
||||
byte[] sp_loadsize = new byte[4]; // 0x044, Load size of system program
|
||||
byte[] sp_entry_address = new byte[4]; // 0x048, System program entry address
|
||||
byte[] sp_work_ram_size = new byte[4]; // 0x04C, System program work RAM size in bytes
|
||||
byte[] release_date = new byte[8]; // 0x050, MMDDYYYY
|
||||
byte[] unknown1 = new byte[7]; // 0x058, Seems to be all 0x20s
|
||||
byte[] spare_space4 = new byte[1]; // 0x05F, 0x00 ?
|
||||
byte[] system_reserved = new byte[160]; // 0x060, System Reserved Area
|
||||
byte[] hardware_id = new byte[16]; // 0x100, Hardware ID
|
||||
byte[] copyright = new byte[3]; // 0x110, "(C)" -- Can be the developer code directly!, if that is the code release date will be displaced
|
||||
byte[] developer_code = new byte[5]; // 0x113 or 0x110, "SEGA" or "T-xx"
|
||||
byte[] release_date2 = new byte[8]; // 0x118, Another release date, this with month in letters?
|
||||
byte[] domestic_title = new byte[48]; // 0x120, Domestic version of the game title
|
||||
byte[] overseas_title = new byte[48]; // 0x150, Overseas version of the game title
|
||||
byte[] product_code = new byte[13]; // 0x180, Official product code
|
||||
byte[] peripherals = new byte[16]; // 0x190, Supported peripherals, see above
|
||||
byte[] spare_space6 = new byte[16]; // 0x1A0, 0x20
|
||||
byte[] spare_space7 = new byte[64]; // 0x1B0, Inside here should be modem information, but I need to get a modem-enabled game
|
||||
byte[] region_codes = new byte[16]; // 0x1F0, Region codes, space-filled
|
||||
//Reading all data
|
||||
fileStream.Read(volume_name, 0, 11); // Varies
|
||||
fileStream.Read(spare_space1, 0, 1); // 0x00
|
||||
fileStream.Read(volume_version, 0, 2); // Volume version in BCD. <100 = Prerelease.
|
||||
fileStream.Read(volume_type, 0, 2); // Bit 0 = 1 => CD-ROM. Rest should be 0.
|
||||
fileStream.Read(system_name, 0, 11); // Unknown, varies!
|
||||
fileStream.Read(spare_space2, 0, 1); // 0x00
|
||||
fileStream.Read(system_version, 0, 2); // Should be 1
|
||||
fileStream.Read(spare_space3, 0, 2); // 0x0000
|
||||
fileStream.Read(ip_address, 0, 4); // Initial program address
|
||||
fileStream.Read(ip_loadsize, 0, 4); // Load size of initial program
|
||||
fileStream.Read(ip_entry_address, 0, 4); // Initial program entry address
|
||||
fileStream.Read(ip_work_ram_size, 0, 4); // Initial program work RAM size in bytes
|
||||
fileStream.Read(sp_address, 0, 4); // System program address
|
||||
fileStream.Read(sp_loadsize, 0, 4); // Load size of system program
|
||||
fileStream.Read(sp_entry_address, 0, 4); // System program entry address
|
||||
fileStream.Read(sp_work_ram_size, 0, 4); // System program work RAM size in bytes
|
||||
fileStream.Read(release_date, 0, 8); // MMDDYYYY
|
||||
fileStream.Read(unknown1, 0, 7); // Seems to be all 0x20s
|
||||
fileStream.Read(spare_space4, 0, 1); // 0x00 ?
|
||||
fileStream.Read(system_reserved, 0, 160); // System Reserved Area
|
||||
fileStream.Read(hardware_id, 0, 16); // Hardware ID
|
||||
fileStream.Read(copyright, 0, 3); // "(C)" -- Can be the developer code directly!, if that is the code release date will be displaced
|
||||
if (Encoding.ASCII.GetString(copyright) != "(C)")
|
||||
fileStream.Seek(-3, SeekOrigin.Current);
|
||||
fileStream.Read(developer_code, 0, 5); // "SEGA" or "T-xx"
|
||||
if (Encoding.ASCII.GetString(copyright) != "(C)")
|
||||
fileStream.Seek(1, SeekOrigin.Current);
|
||||
fileStream.Read(release_date2, 0, 8); // Another release date, this with month in letters?
|
||||
if (Encoding.ASCII.GetString(copyright) != "(C)")
|
||||
fileStream.Seek(2, SeekOrigin.Current);
|
||||
fileStream.Read(domestic_title, 0, 48); // Domestic version of the game title
|
||||
fileStream.Read(overseas_title, 0, 48); // Overseas version of the game title
|
||||
fileStream.Read(application_type, 0, 2); // Application type
|
||||
fileStream.Read(space_space5, 0, 1); // 0x20
|
||||
fileStream.Read(product_code, 0, 13); // Official product code
|
||||
fileStream.Read(peripherals, 0, 16); // Supported peripherals, see above
|
||||
fileStream.Read(spare_space6, 0, 16); // 0x20
|
||||
fileStream.Read(spare_space7, 0, 64); // Inside here should be modem information, but I need to get a modem-enabled game
|
||||
fileStream.Read(region_codes, 0, 16); // Region codes, space-filled
|
||||
Array.Copy(ipbin_sector, 0x010, volume_name, 0, 11); // Varies
|
||||
Array.Copy(ipbin_sector, 0x01B, spare_space1, 0, 1); // 0x00
|
||||
Array.Copy(ipbin_sector, 0x01C, volume_version, 0, 2); // Volume version in BCD. <100 = Prerelease.
|
||||
Array.Copy(ipbin_sector, 0x01E, volume_type, 0, 2); // Bit 0 = 1 => CD-ROM. Rest should be 0.
|
||||
Array.Copy(ipbin_sector, 0x020, system_name, 0, 11); // Unknown, varies!
|
||||
Array.Copy(ipbin_sector, 0x02B, spare_space2, 0, 1); // 0x00
|
||||
Array.Copy(ipbin_sector, 0x02C, system_version, 0, 2); // Should be 1
|
||||
Array.Copy(ipbin_sector, 0x02E, spare_space3, 0, 2); // 0x0000
|
||||
Array.Copy(ipbin_sector, 0x030, ip_address, 0, 4); // Initial program address
|
||||
Array.Copy(ipbin_sector, 0x034, ip_loadsize, 0, 4); // Load size of initial program
|
||||
Array.Copy(ipbin_sector, 0x038, ip_entry_address, 0, 4); // Initial program entry address
|
||||
Array.Copy(ipbin_sector, 0x03C, ip_work_ram_size, 0, 4); // Initial program work RAM size in bytes
|
||||
Array.Copy(ipbin_sector, 0x040, sp_address, 0, 4); // System program address
|
||||
Array.Copy(ipbin_sector, 0x044, sp_loadsize, 0, 4); // Load size of system program
|
||||
Array.Copy(ipbin_sector, 0x048, sp_entry_address, 0, 4); // System program entry address
|
||||
Array.Copy(ipbin_sector, 0x04C, sp_work_ram_size, 0, 4); // System program work RAM size in bytes
|
||||
Array.Copy(ipbin_sector, 0x050, release_date, 0, 8); // MMDDYYYY
|
||||
Array.Copy(ipbin_sector, 0x058, unknown1, 0, 7); // Seems to be all 0x20s
|
||||
Array.Copy(ipbin_sector, 0x05F, spare_space4, 0, 1); // 0x00 ?
|
||||
Array.Copy(ipbin_sector, 0x060, system_reserved, 0, 160); // System Reserved Area
|
||||
Array.Copy(ipbin_sector, 0x100, hardware_id, 0, 16); // Hardware ID
|
||||
Array.Copy(ipbin_sector, 0x110, copyright, 0, 3); // "(C)" -- Can be the developer code directly!, if that is the code release date will be displaced
|
||||
if (Encoding.ASCII.GetString(copyright) == "(C)")
|
||||
Array.Copy(ipbin_sector, 0x113, developer_code, 0, 5); // "SEGA" or "T-xx"
|
||||
else
|
||||
Array.Copy(ipbin_sector, 0x110, developer_code, 0, 5); // "SEGA" or "T-xx"
|
||||
Array.Copy(ipbin_sector, 0x118, release_date2, 0, 8); // Another release date, this with month in letters?
|
||||
Array.Copy(ipbin_sector, 0x120, domestic_title, 0, 48); // Domestic version of the game title
|
||||
Array.Copy(ipbin_sector, 0x150, overseas_title, 0, 48); // Overseas version of the game title
|
||||
//Array.Copy(ipbin_sector, 0x000, application_type, 0, 2); // Application type
|
||||
//Array.Copy(ipbin_sector, 0x000, space_space5, 0, 1); // 0x20
|
||||
Array.Copy(ipbin_sector, 0x180, product_code, 0, 13); // Official product code
|
||||
Array.Copy(ipbin_sector, 0x190, peripherals, 0, 16); // Supported peripherals, see above
|
||||
Array.Copy(ipbin_sector, 0x1A0, spare_space6, 0, 16); // 0x20
|
||||
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();
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "MMddyyyy", provider);
|
||||
|
||||
/*
|
||||
switch (Encoding.ASCII.GetString(application_type))
|
||||
{
|
||||
case "GM":
|
||||
@@ -414,6 +362,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
IPBinInformation.AppendLine("Disc is from unknown type.");
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
IPBinInformation.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(volume_name)).AppendLine();
|
||||
//IPBinInformation.AppendFormat("Volume version: {0}", Encoding.ASCII.GetString(volume_version)).AppendLine();
|
||||
@@ -513,33 +462,31 @@ namespace FileSystemIDandChk.Plugins
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Definitions following
|
||||
byte[] maker_id = new byte[16]; // "SEGA ENTERPRISES"
|
||||
byte[] product_no = new byte[10]; // Product number
|
||||
byte[] product_version = new byte[6]; // Product version
|
||||
byte[] release_date = new byte[8]; // YYYYMMDD
|
||||
byte[] saturn_media = new byte[3]; // "CD-"
|
||||
byte[] disc_no = new byte[1]; // Disc number
|
||||
byte[] disc_no_separator = new byte[1]; // '/'
|
||||
byte[] disc_total_nos = new byte[1]; // Total number of discs
|
||||
byte[] spare_space1 = new byte[2]; // " "
|
||||
byte[] region_codes = new byte[10]; // Region codes, space-filled
|
||||
byte[] spare_space2 = new byte[6]; // " "
|
||||
byte[] peripherals = new byte[16]; // Supported peripherals, see above
|
||||
byte[] product_name = new byte[112]; // Game name, space-filled
|
||||
byte[] maker_id = new byte[16]; // 0x010, "SEGA ENTERPRISES"
|
||||
byte[] product_no = new byte[10]; // 0x020, Product number
|
||||
byte[] product_version = new byte[6]; // 0x02A, Product version
|
||||
byte[] release_date = new byte[8]; // 0x030, YYYYMMDD
|
||||
byte[] saturn_media = new byte[3]; // 0x038, "CD-"
|
||||
byte[] disc_no = new byte[1]; // 0x03B, Disc number
|
||||
byte[] disc_no_separator = new byte[1]; // 0x03C, '/'
|
||||
byte[] disc_total_nos = new byte[1]; // 0x03D, Total number of discs
|
||||
byte[] spare_space1 = new byte[2]; // 0x03E, " "
|
||||
byte[] region_codes = new byte[16]; // 0x040, Region codes, space-filled
|
||||
byte[] peripherals = new byte[16]; // 0x050, Supported peripherals, see above
|
||||
byte[] product_name = new byte[112]; // 0x060, Game name, space-filled
|
||||
// Reading all data
|
||||
fileStream.Read(maker_id, 0, 16); // "SEGA ENTERPRISES"
|
||||
fileStream.Read(product_no, 0, 10); // Product number
|
||||
fileStream.Read(product_version, 0, 6); // Product version
|
||||
fileStream.Read(release_date, 0, 8); // YYYYMMDD
|
||||
fileStream.Read(saturn_media, 0, 3); // "CD-"
|
||||
fileStream.Read(disc_no, 0, 1); // Disc number
|
||||
fileStream.Read(disc_no_separator, 0, 1); // '/'
|
||||
fileStream.Read(disc_total_nos, 0, 1); // Total number of discs
|
||||
fileStream.Read(spare_space1, 0, 2); // " "
|
||||
fileStream.Read(region_codes, 0, 10); // Region codes, space-filled
|
||||
fileStream.Read(spare_space2, 0, 6); // " "
|
||||
fileStream.Read(peripherals, 0, 16); // Supported peripherals, see above
|
||||
fileStream.Read(product_name, 0, 112); // Game name, space-filled
|
||||
Array.Copy(ipbin_sector, 0x010, maker_id, 0, 16); // "SEGA ENTERPRISES"
|
||||
Array.Copy(ipbin_sector, 0x020, product_no, 0, 10); // Product number
|
||||
Array.Copy(ipbin_sector, 0x02A, product_version, 0, 6); // Product version
|
||||
Array.Copy(ipbin_sector, 0x030, release_date, 0, 8); // YYYYMMDD
|
||||
Array.Copy(ipbin_sector, 0x038, saturn_media, 0, 3); // "CD-"
|
||||
Array.Copy(ipbin_sector, 0x03B, disc_no, 0, 1); // Disc number
|
||||
Array.Copy(ipbin_sector, 0x03C, disc_no_separator, 0, 1); // '/'
|
||||
Array.Copy(ipbin_sector, 0x03D, disc_total_nos, 0, 1); // Total number of discs
|
||||
Array.Copy(ipbin_sector, 0x03E, spare_space1, 0, 2); // " "
|
||||
Array.Copy(ipbin_sector, 0x040, region_codes, 0, 16); // Region codes, space-filled
|
||||
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();
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
@@ -616,41 +563,41 @@ namespace FileSystemIDandChk.Plugins
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Declarations following
|
||||
byte[] maker_id = new byte[16]; // "SEGA ENTERPRISES"
|
||||
byte[] dreamcast_crc = new byte[4]; // CRC of product_no and product_version
|
||||
byte[] spare_space1 = new byte[1]; // " "
|
||||
byte[] dreamcast_media = new byte[6]; // "GD-ROM"
|
||||
byte[] disc_no = new byte[1]; // Disc number
|
||||
byte[] disc_no_separator = new byte[1]; // '/'
|
||||
byte[] disc_total_nos = new byte[1]; // Total number of discs
|
||||
byte[] spare_space2 = new byte[2]; // " "
|
||||
byte[] region_codes = new byte[8]; // Region codes, space-filled
|
||||
byte[] peripherals = new byte[4]; // Supported peripherals, bitwise
|
||||
byte[] product_no = new byte[10]; // Product number
|
||||
byte[] product_version = new byte[6]; // Product version
|
||||
byte[] release_date = new byte[8]; // YYYYMMDD
|
||||
byte[] spare_space3 = new byte[8]; // " "
|
||||
byte[] boot_filename = new byte[12]; // Usually "1ST_READ.BIN" or "0WINCE.BIN "
|
||||
byte[] producer = new byte[16]; // Game producer, space-filled
|
||||
byte[] product_name = new byte[128]; // Game name, space-filled
|
||||
byte[] maker_id = new byte[16]; // 0x010, "SEGA ENTERPRISES"
|
||||
byte[] dreamcast_crc = new byte[4]; // 0x020, CRC of product_no and product_version
|
||||
byte[] spare_space1 = new byte[1]; // 0x024, " "
|
||||
byte[] dreamcast_media = new byte[6]; // 0x025, "GD-ROM"
|
||||
byte[] disc_no = new byte[1]; // 0x02B, Disc number
|
||||
byte[] disc_no_separator = new byte[1]; // 0x02C, '/'
|
||||
byte[] disc_total_nos = new byte[1]; // 0x02D, Total number of discs
|
||||
byte[] spare_space2 = new byte[2]; // 0x02E, " "
|
||||
byte[] region_codes = new byte[8]; // 0x030, Region codes, space-filled
|
||||
byte[] peripherals = new byte[4]; // 0x038, Supported peripherals, bitwise
|
||||
byte[] product_no = new byte[10]; // 0x03C, Product number
|
||||
byte[] product_version = new byte[6]; // 0x046, Product version
|
||||
byte[] release_date = new byte[8]; // 0x04C, YYYYMMDD
|
||||
byte[] spare_space3 = new byte[8]; // 0x054, " "
|
||||
byte[] boot_filename = new byte[12]; // 0x05C, Usually "1ST_READ.BIN" or "0WINCE.BIN "
|
||||
byte[] producer = new byte[16]; // 0x068, Game producer, space-filled
|
||||
byte[] product_name = new byte[128]; // 0x078, Game name, space-filled
|
||||
// Reading all data
|
||||
fileStream.Read(maker_id, 0, 16); // "SEGA ENTERPRISES"
|
||||
fileStream.Read(dreamcast_crc, 0, 4); // CRC of product_no and product_version
|
||||
fileStream.Read(spare_space1, 0, 1); // " "
|
||||
fileStream.Read(dreamcast_media, 0, 6); // "GD-ROM"
|
||||
fileStream.Read(disc_no, 0, 1); // Disc number
|
||||
fileStream.Read(disc_no_separator, 0, 1); // '/'
|
||||
fileStream.Read(disc_total_nos, 0, 1); // Total number of discs
|
||||
fileStream.Read(spare_space2, 0, 2); // " "
|
||||
fileStream.Read(region_codes, 0, 8); // Region codes, space-filled
|
||||
fileStream.Read(peripherals, 0, 4); // Supported peripherals, bitwise
|
||||
fileStream.Read(product_no, 0, 10); // Product number
|
||||
fileStream.Read(product_version, 0, 6); // Product version
|
||||
fileStream.Read(release_date, 0, 8); // YYYYMMDD
|
||||
fileStream.Read(spare_space3, 0, 8); // " "
|
||||
fileStream.Read(boot_filename, 0, 12); // Usually "1ST_READ.BIN" or "0WINCE.BIN "
|
||||
fileStream.Read(producer, 0, 16); // Game producer, space-filled
|
||||
fileStream.Read(product_name, 0, 128); // Game name, space-filled
|
||||
Array.Copy(ipbin_sector, 0x010, maker_id, 0, 16); // "SEGA ENTERPRISES"
|
||||
Array.Copy(ipbin_sector, 0x020, dreamcast_crc, 0, 4); // CRC of product_no and product_version
|
||||
Array.Copy(ipbin_sector, 0x024, spare_space1, 0, 1); // " "
|
||||
Array.Copy(ipbin_sector, 0x025, dreamcast_media, 0, 6); // "GD-ROM"
|
||||
Array.Copy(ipbin_sector, 0x02B, disc_no, 0, 1); // Disc number
|
||||
Array.Copy(ipbin_sector, 0x02C, disc_no_separator, 0, 1); // '/'
|
||||
Array.Copy(ipbin_sector, 0x02D, disc_total_nos, 0, 1); // Total number of discs
|
||||
Array.Copy(ipbin_sector, 0x02E, spare_space2, 0, 2); // " "
|
||||
Array.Copy(ipbin_sector, 0x030, region_codes, 0, 8); // Region codes, space-filled
|
||||
Array.Copy(ipbin_sector, 0x038, peripherals, 0, 4); // Supported peripherals, bitwise
|
||||
Array.Copy(ipbin_sector, 0x03C, product_no, 0, 10); // Product number
|
||||
Array.Copy(ipbin_sector, 0x046, product_version, 0, 6); // Product version
|
||||
Array.Copy(ipbin_sector, 0x04C, release_date, 0, 8); // YYYYMMDD
|
||||
Array.Copy(ipbin_sector, 0x054, spare_space3, 0, 8); // " "
|
||||
Array.Copy(ipbin_sector, 0x05C, boot_filename, 0, 12); // Usually "1ST_READ.BIN" or "0WINCE.BIN "
|
||||
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();
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
@@ -920,4 +867,4 @@ namespace FileSystemIDandChk.Plugins
|
||||
return decodedVD;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class MinixFS : Plugin
|
||||
@@ -28,21 +26,19 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt16 magic;
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
byte[] minix_sb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
|
||||
br.BaseStream.Seek(0x400 + 0x10 + offset, SeekOrigin.Begin); // Here should reside magic number on Minix V1 & V2
|
||||
magic = br.ReadUInt16();
|
||||
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
|
||||
{
|
||||
br.BaseStream.Seek(0x400 + 0x18 + offset, SeekOrigin.Begin); // Here should reside magic number on Minix V1 & V2
|
||||
magic = br.ReadUInt16();
|
||||
magic = BitConverter.ToUInt16(minix_sb_sector, 0x018); // Here should reside magic number on Minix V3
|
||||
|
||||
if(magic == MINIX3_MAGIC || magic == MINIX3_CIGAM)
|
||||
return true;
|
||||
@@ -51,7 +47,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
}
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
@@ -62,10 +58,9 @@ namespace FileSystemIDandChk.Plugins
|
||||
int filenamesize = 0;
|
||||
string minixVersion;
|
||||
UInt16 magic;
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
byte[] minix_sb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
|
||||
eabr.BaseStream.Seek(0x400 + 0x18 + offset, SeekOrigin.Begin);
|
||||
magic = eabr.ReadUInt16();
|
||||
magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x018);
|
||||
|
||||
if(magic == MINIX3_MAGIC || magic == MINIX3_CIGAM)
|
||||
{
|
||||
@@ -80,50 +75,49 @@ namespace FileSystemIDandChk.Plugins
|
||||
}
|
||||
else
|
||||
{
|
||||
eabr.BaseStream.Seek(0x400 + 0x10 + offset, SeekOrigin.Begin);
|
||||
magic = eabr.ReadUInt16();
|
||||
magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x010);
|
||||
|
||||
switch(magic)
|
||||
{
|
||||
case MINIX_MAGIC:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
littleendian = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX_MAGIC2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
littleendian = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX2_MAGIC:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
littleendian = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX2_MAGIC2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
littleendian = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX_CIGAM:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
case MINIX_CIGAM2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
case MINIX2_CIGAM:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
case MINIX2_CIGAM2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -131,26 +125,23 @@ namespace FileSystemIDandChk.Plugins
|
||||
}
|
||||
}
|
||||
|
||||
eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
eabr.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
|
||||
if(minix3)
|
||||
{
|
||||
Minix3SuperBlock mnx_sb = new Minix3SuperBlock();
|
||||
|
||||
mnx_sb.s_ninodes = eabr.ReadUInt32();
|
||||
mnx_sb.s_pad0 = eabr.ReadUInt16();
|
||||
mnx_sb.s_imap_blocks = eabr.ReadUInt16();
|
||||
mnx_sb.s_zmap_blocks = eabr.ReadUInt16();
|
||||
mnx_sb.s_firstdatazone = eabr.ReadUInt16();
|
||||
mnx_sb.s_log_zone_size = eabr.ReadUInt16();
|
||||
mnx_sb.s_pad1 = eabr.ReadUInt16();
|
||||
mnx_sb.s_max_size = eabr.ReadUInt32();
|
||||
mnx_sb.s_zones = eabr.ReadUInt32();
|
||||
mnx_sb.s_magic = eabr.ReadUInt16();
|
||||
mnx_sb.s_pad2 = eabr.ReadUInt16();
|
||||
mnx_sb.s_blocksize = eabr.ReadUInt16();
|
||||
mnx_sb.s_disk_version = eabr.ReadByte();
|
||||
mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x00);
|
||||
mnx_sb.s_pad0 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x04);
|
||||
mnx_sb.s_imap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x06);
|
||||
mnx_sb.s_zmap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x08);
|
||||
mnx_sb.s_firstdatazone = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0A);
|
||||
mnx_sb.s_log_zone_size = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0C);
|
||||
mnx_sb.s_pad1 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0E);
|
||||
mnx_sb.s_max_size = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x10);
|
||||
mnx_sb.s_zones = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x14);
|
||||
mnx_sb.s_magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x18);
|
||||
mnx_sb.s_pad2 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x1A);
|
||||
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();
|
||||
@@ -168,16 +159,16 @@ namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
MinixSuperBlock mnx_sb = new MinixSuperBlock();
|
||||
|
||||
mnx_sb.s_ninodes = eabr.ReadUInt16();
|
||||
mnx_sb.s_nzones = eabr.ReadUInt16();
|
||||
mnx_sb.s_imap_blocks = eabr.ReadUInt16();
|
||||
mnx_sb.s_zmap_blocks = eabr.ReadUInt16();
|
||||
mnx_sb.s_firstdatazone = eabr.ReadUInt16();
|
||||
mnx_sb.s_log_zone_size = eabr.ReadUInt16();
|
||||
mnx_sb.s_max_size = eabr.ReadUInt32();
|
||||
mnx_sb.s_magic = eabr.ReadUInt16();
|
||||
mnx_sb.s_state = eabr.ReadUInt16();
|
||||
mnx_sb.s_zones = eabr.ReadUInt32();
|
||||
mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x00);
|
||||
mnx_sb.s_nzones = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x02);
|
||||
mnx_sb.s_imap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x04);
|
||||
mnx_sb.s_zmap_blocks = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x06);
|
||||
mnx_sb.s_firstdatazone = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x08);
|
||||
mnx_sb.s_log_zone_size = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x0A);
|
||||
mnx_sb.s_max_size = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x0C);
|
||||
mnx_sb.s_magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x10);
|
||||
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();
|
||||
|
||||
@@ -3,8 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class NTFS : Plugin
|
||||
@@ -15,42 +13,37 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
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;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
br.BaseStream.Seek(3 + offset, SeekOrigin.Begin);
|
||||
eigth_bytes = br.ReadBytes(8);
|
||||
Array.Copy(ntfs_bpb, 0x003, eigth_bytes, 0, 8);
|
||||
oem_name = StringHandlers.CToString(eigth_bytes);
|
||||
|
||||
if(oem_name != "NTFS ")
|
||||
return false;
|
||||
|
||||
br.BaseStream.Seek(0x10 + offset, SeekOrigin.Begin);
|
||||
fats_no = br.ReadByte();
|
||||
fats_no = ntfs_bpb[0x010];
|
||||
|
||||
if(fats_no != 0)
|
||||
return false;
|
||||
|
||||
br.BaseStream.Seek(0x16 + offset, SeekOrigin.Begin);
|
||||
spfat = br.ReadUInt16();
|
||||
spfat = BitConverter.ToUInt16(ntfs_bpb, 0x016);
|
||||
|
||||
if(spfat != 0)
|
||||
return false;
|
||||
|
||||
br.BaseStream.Seek(0x26 + offset, SeekOrigin.Begin);
|
||||
signature1 = br.ReadByte();
|
||||
signature1 = ntfs_bpb[0x026];
|
||||
|
||||
if(signature1 != 0x80)
|
||||
return false;
|
||||
|
||||
br.BaseStream.Seek(0x1FE + offset, SeekOrigin.Begin);
|
||||
signature2 = br.ReadUInt16();
|
||||
signature2 = BitConverter.ToUInt16(ntfs_bpb, 0x1FE);
|
||||
|
||||
if(signature2 != 0xAA55)
|
||||
return false;
|
||||
@@ -58,52 +51,49 @@ namespace FileSystemIDandChk.Plugins
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
NTFS_BootBlock ntfs_bb = new NTFS_BootBlock();
|
||||
|
||||
byte[] oem_name = new byte[8];
|
||||
|
||||
ntfs_bb.jmp1 = br.ReadByte();
|
||||
ntfs_bb.jmp2 = br.ReadUInt16();
|
||||
oem_name = br.ReadBytes(8);
|
||||
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.bps = br.ReadUInt16();
|
||||
ntfs_bb.spc = br.ReadByte();
|
||||
ntfs_bb.rsectors = br.ReadUInt16();
|
||||
ntfs_bb.fats_no = br.ReadByte();
|
||||
ntfs_bb.root_ent = br.ReadUInt16();
|
||||
ntfs_bb.sml_sectors = br.ReadUInt16();
|
||||
ntfs_bb.media = br.ReadByte();
|
||||
ntfs_bb.spfat = br.ReadUInt16();
|
||||
ntfs_bb.sptrk = br.ReadUInt16();
|
||||
ntfs_bb.heads = br.ReadUInt16();
|
||||
ntfs_bb.hsectors = br.ReadUInt32();
|
||||
ntfs_bb.big_sectors = br.ReadUInt32();
|
||||
ntfs_bb.drive_no = br.ReadByte();
|
||||
ntfs_bb.nt_flags = br.ReadByte();
|
||||
ntfs_bb.signature1 = br.ReadByte();
|
||||
ntfs_bb.dummy = br.ReadByte();
|
||||
ntfs_bb.sectors = br.ReadInt64();
|
||||
ntfs_bb.mft_lsn = br.ReadInt64();
|
||||
ntfs_bb.mftmirror_lsn = br.ReadInt64();
|
||||
ntfs_bb.mft_rc_clusters = br.ReadSByte();
|
||||
ntfs_bb.dummy2 = br.ReadByte();
|
||||
ntfs_bb.dummy3 = br.ReadUInt16();
|
||||
ntfs_bb.index_blk_cts = br.ReadSByte();
|
||||
ntfs_bb.dummy4 = br.ReadByte();
|
||||
ntfs_bb.dummy5 = br.ReadUInt16();
|
||||
ntfs_bb.serial_no = br.ReadUInt64();
|
||||
br.BaseStream.Seek(430, SeekOrigin.Current);
|
||||
ntfs_bb.signature2 = br.ReadUInt16();
|
||||
ntfs_bb.bps = BitConverter.ToUInt16(ntfs_bpb, 0x00B);
|
||||
ntfs_bb.spc = ntfs_bpb[0x00D];
|
||||
ntfs_bb.rsectors = BitConverter.ToUInt16(ntfs_bpb, 0x00E);
|
||||
ntfs_bb.fats_no = ntfs_bpb[0x010];
|
||||
ntfs_bb.root_ent = BitConverter.ToUInt16(ntfs_bpb, 0x011);
|
||||
ntfs_bb.sml_sectors = BitConverter.ToUInt16(ntfs_bpb, 0x013);
|
||||
ntfs_bb.media = ntfs_bpb[0x015];
|
||||
ntfs_bb.spfat = BitConverter.ToUInt16(ntfs_bpb, 0x016);
|
||||
ntfs_bb.sptrk = BitConverter.ToUInt16(ntfs_bpb, 0x018);
|
||||
ntfs_bb.heads = BitConverter.ToUInt16(ntfs_bpb, 0x01A);
|
||||
ntfs_bb.hsectors = BitConverter.ToUInt32(ntfs_bpb, 0x01C);
|
||||
ntfs_bb.big_sectors = BitConverter.ToUInt32(ntfs_bpb, 0x020);
|
||||
ntfs_bb.drive_no = ntfs_bpb[0x024];
|
||||
ntfs_bb.nt_flags = ntfs_bpb[0x025];
|
||||
ntfs_bb.signature1 = ntfs_bpb[0x026];
|
||||
ntfs_bb.dummy = ntfs_bpb[0x027];
|
||||
ntfs_bb.sectors = BitConverter.ToInt64(ntfs_bpb, 0x028);
|
||||
ntfs_bb.mft_lsn = BitConverter.ToInt64(ntfs_bpb, 0x030);
|
||||
ntfs_bb.mftmirror_lsn = BitConverter.ToInt64(ntfs_bpb, 0x038);
|
||||
ntfs_bb.mft_rc_clusters = (sbyte)ntfs_bpb[0x040];
|
||||
ntfs_bb.dummy2 = ntfs_bpb[0x041];
|
||||
ntfs_bb.dummy3 = BitConverter.ToUInt16(ntfs_bpb, 0x042);
|
||||
ntfs_bb.index_blk_cts = (sbyte)ntfs_bpb[0x044];
|
||||
ntfs_bb.dummy4 = ntfs_bpb[0x045];
|
||||
ntfs_bb.dummy5 = BitConverter.ToUInt16(ntfs_bpb, 0x046);
|
||||
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();
|
||||
@@ -144,40 +134,39 @@ namespace FileSystemIDandChk.Plugins
|
||||
private struct NTFS_BootBlock // Sector 0
|
||||
{
|
||||
// BIOS Parameter Block
|
||||
public byte jmp1; // Jump to boot code
|
||||
public UInt16 jmp2; // ...;
|
||||
public string OEMName; // OEM Name, 8 bytes, space-padded, must be "NTFS "
|
||||
public UInt16 bps; // Bytes per sector
|
||||
public byte spc; // Sectors per cluster
|
||||
public UInt16 rsectors; // Reserved sectors, seems 0
|
||||
public byte fats_no; // Number of FATs... obviously, 0
|
||||
public UInt16 root_ent; // Number of entries on root directory... 0
|
||||
public UInt16 sml_sectors; // Sectors in volume... 0
|
||||
public byte media; // Media descriptor
|
||||
public UInt16 spfat; // Sectors per FAT... 0
|
||||
public UInt16 sptrk; // Sectors per track, required to boot
|
||||
public UInt16 heads; // Heads... required to boot
|
||||
public UInt32 hsectors; // Hidden sectors before BPB
|
||||
public UInt32 big_sectors; // Sectors in volume if > 65535... 0
|
||||
public byte drive_no; // Drive number
|
||||
public byte nt_flags; // 0
|
||||
public byte signature1; // EPB signature, 0x80
|
||||
public byte dummy; // Alignment
|
||||
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; // Sectors on volume
|
||||
public Int64 mft_lsn; // LSN of $MFT
|
||||
public Int64 mftmirror_lsn; // LSN of $MFTMirror
|
||||
public sbyte mft_rc_clusters; // Clusters per MFT record
|
||||
public byte dummy2; // Alignment
|
||||
public UInt16 dummy3; // Alignment
|
||||
public sbyte index_blk_cts; // Clusters per index block
|
||||
public byte dummy4; // Alignment
|
||||
public UInt16 dummy5; // Alignment
|
||||
public UInt64 serial_no; // Volume serial number
|
||||
// End of NTFS superblock, followed by 426 bytes of boot code
|
||||
public UInt16 signature2; // 0xAA55
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ using FileSystemIDandChk;
|
||||
|
||||
// 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
|
||||
@@ -24,17 +26,13 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] magic_b = new byte[12];
|
||||
string magic;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
br.BaseStream.Seek(0x200 + offset, SeekOrigin.Begin); // Seek to home block
|
||||
br.BaseStream.Seek(0x1F0, SeekOrigin.Current); // Seek to format
|
||||
|
||||
br.BaseStream.Read(magic_b, 0, 12);
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
Array.Copy(hb_sector, 0x1F0, magic_b, 0, 12);
|
||||
magic = Encoding.ASCII.GetString(magic_b);
|
||||
|
||||
if(magic == "DECFILE11A " || magic == "DECFILE11B ")
|
||||
@@ -43,70 +41,66 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
ODSHomeBlock homeblock = new ODSHomeBlock();
|
||||
byte[] temp_string = new byte[12];
|
||||
homeblock.min_class = new byte[20];
|
||||
homeblock.max_class = new byte[20];
|
||||
homeblock.reserved1 = new byte[302];
|
||||
|
||||
br.BaseStream.Seek(0x200 + offset, SeekOrigin.Begin);
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
homeblock.homelbn = br.ReadUInt32();
|
||||
homeblock.alhomelbn = br.ReadUInt32();
|
||||
homeblock.altidxlbn = br.ReadUInt32();
|
||||
homeblock.struclev = br.ReadUInt16();
|
||||
homeblock.cluster = br.ReadUInt16();
|
||||
homeblock.homevbn = br.ReadUInt16();
|
||||
homeblock.alhomevbn = br.ReadUInt16();
|
||||
homeblock.altidxvbn = br.ReadUInt16();
|
||||
homeblock.ibmapvbn = br.ReadUInt16();
|
||||
homeblock.ibmaplbn = br.ReadUInt32();
|
||||
homeblock.maxfiles = br.ReadUInt32();
|
||||
homeblock.ibmapsize = br.ReadUInt16();
|
||||
homeblock.resfiles = br.ReadUInt16();
|
||||
homeblock.devtype = br.ReadUInt16();
|
||||
homeblock.rvn = br.ReadUInt16();
|
||||
homeblock.setcount = br.ReadUInt16();
|
||||
homeblock.volchar = br.ReadUInt16();
|
||||
homeblock.volowner = br.ReadUInt32();
|
||||
homeblock.sec_mask = br.ReadUInt32();
|
||||
homeblock.protect = br.ReadUInt16();
|
||||
homeblock.fileprot = br.ReadUInt16();
|
||||
homeblock.recprot = br.ReadUInt16();
|
||||
homeblock.checksum1 = br.ReadUInt16();
|
||||
homeblock.credate = br.ReadUInt64();
|
||||
homeblock.window = br.ReadByte();
|
||||
homeblock.lru_lim = br.ReadByte();
|
||||
homeblock.extend = br.ReadUInt16();
|
||||
homeblock.retainmin = br.ReadUInt64();
|
||||
homeblock.retainmax = br.ReadUInt64();
|
||||
homeblock.revdate = br.ReadUInt64();
|
||||
homeblock.min_class = br.ReadBytes(20);
|
||||
homeblock.max_class = br.ReadBytes(20);
|
||||
homeblock.filetab_fid1 = br.ReadUInt16();
|
||||
homeblock.filetab_fid2 = br.ReadUInt16();
|
||||
homeblock.filetab_fid3 = br.ReadUInt16();
|
||||
homeblock.lowstruclev = br.ReadUInt16();
|
||||
homeblock.highstruclev = br.ReadUInt16();
|
||||
homeblock.copydate = br.ReadUInt64();
|
||||
homeblock.reserved1 = br.ReadBytes(302);
|
||||
homeblock.serialnum = br.ReadUInt32();
|
||||
temp_string = br.ReadBytes(12);
|
||||
homeblock.homelbn = BitConverter.ToUInt32(hb_sector, 0x000);
|
||||
homeblock.alhomelbn = BitConverter.ToUInt32(hb_sector, 0x004);
|
||||
homeblock.altidxlbn = BitConverter.ToUInt32(hb_sector, 0x008);
|
||||
homeblock.struclev = BitConverter.ToUInt16(hb_sector, 0x00C);
|
||||
homeblock.cluster = BitConverter.ToUInt16(hb_sector, 0x00E);
|
||||
homeblock.homevbn = BitConverter.ToUInt16(hb_sector, 0x010);
|
||||
homeblock.alhomevbn = BitConverter.ToUInt16(hb_sector, 0x012);
|
||||
homeblock.altidxvbn = BitConverter.ToUInt16(hb_sector, 0x014);
|
||||
homeblock.ibmapvbn = BitConverter.ToUInt16(hb_sector, 0x016);
|
||||
homeblock.ibmaplbn = BitConverter.ToUInt32(hb_sector, 0x018);
|
||||
homeblock.maxfiles = BitConverter.ToUInt32(hb_sector, 0x01C);
|
||||
homeblock.ibmapsize = BitConverter.ToUInt16(hb_sector, 0x020);
|
||||
homeblock.resfiles = BitConverter.ToUInt16(hb_sector, 0x022);
|
||||
homeblock.devtype = BitConverter.ToUInt16(hb_sector, 0x024);
|
||||
homeblock.rvn = BitConverter.ToUInt16(hb_sector, 0x026);
|
||||
homeblock.setcount = BitConverter.ToUInt16(hb_sector, 0x028);
|
||||
homeblock.volchar = BitConverter.ToUInt16(hb_sector, 0x02A);
|
||||
homeblock.volowner = BitConverter.ToUInt32(hb_sector, 0x02C);
|
||||
homeblock.sec_mask = BitConverter.ToUInt32(hb_sector, 0x030);
|
||||
homeblock.protect = BitConverter.ToUInt16(hb_sector, 0x034);
|
||||
homeblock.fileprot = BitConverter.ToUInt16(hb_sector, 0x036);
|
||||
homeblock.recprot = BitConverter.ToUInt16(hb_sector, 0x038);
|
||||
homeblock.checksum1 = BitConverter.ToUInt16(hb_sector, 0x03A);
|
||||
homeblock.credate = BitConverter.ToUInt64(hb_sector, 0x03C);
|
||||
homeblock.window = hb_sector[0x044];
|
||||
homeblock.lru_lim = hb_sector[0x045];
|
||||
homeblock.extend = BitConverter.ToUInt16(hb_sector, 0x046);
|
||||
homeblock.retainmin = BitConverter.ToUInt64(hb_sector, 0x048);
|
||||
homeblock.retainmax = BitConverter.ToUInt64(hb_sector, 0x050);
|
||||
homeblock.revdate = BitConverter.ToUInt64(hb_sector, 0x058);
|
||||
Array.Copy(hb_sector, 0x060, homeblock.min_class, 0, 20);
|
||||
Array.Copy(hb_sector, 0x074, homeblock.max_class, 0, 20);
|
||||
homeblock.filetab_fid1 = BitConverter.ToUInt16(hb_sector, 0x088);
|
||||
homeblock.filetab_fid2 = BitConverter.ToUInt16(hb_sector, 0x08A);
|
||||
homeblock.filetab_fid3 = BitConverter.ToUInt16(hb_sector, 0x08C);
|
||||
homeblock.lowstruclev = BitConverter.ToUInt16(hb_sector, 0x08E);
|
||||
homeblock.highstruclev = BitConverter.ToUInt16(hb_sector, 0x090);
|
||||
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);
|
||||
temp_string = br.ReadBytes(12);
|
||||
Array.Copy(hb_sector, 0x1D8, temp_string, 0, 12);
|
||||
homeblock.volname = StringHandlers.CToString(temp_string);
|
||||
temp_string = br.ReadBytes(12);
|
||||
Array.Copy(hb_sector, 0x1E4, temp_string, 0, 12);
|
||||
homeblock.ownername = StringHandlers.CToString(temp_string);
|
||||
temp_string = br.ReadBytes(12);
|
||||
Array.Copy(hb_sector, 0x1F0, temp_string, 0, 12);
|
||||
homeblock.format = StringHandlers.CToString(temp_string);
|
||||
homeblock.reserved2 = br.ReadUInt16();
|
||||
homeblock.checksum2 = br.ReadUInt16();
|
||||
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.");
|
||||
@@ -233,53 +227,52 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
private struct ODSHomeBlock
|
||||
{
|
||||
public UInt32 homelbn; // LBN of THIS home block
|
||||
public UInt32 alhomelbn; // LBN of the secondary home block
|
||||
public UInt32 altidxlbn; // LBN of backup INDEXF.SYS;1
|
||||
public UInt16 struclev; // High byte contains filesystem version (1, 2 or 5), low byte contains revision (1)
|
||||
public UInt16 cluster; // Number of blocks each bit of the volume bitmap represents
|
||||
public UInt16 homevbn; // VBN of THIS home block
|
||||
public UInt16 alhomevbn; // VBN of the secondary home block
|
||||
public UInt16 altidxvbn; // VBN of backup INDEXF.SYS;1
|
||||
public UInt16 ibmapvbn; // VBN of the bitmap
|
||||
public UInt32 ibmaplbn; // LBN of the bitmap
|
||||
public UInt32 maxfiles; // Max files on volume
|
||||
public UInt16 ibmapsize; // Bitmap size in sectors
|
||||
public UInt16 resfiles; // Reserved files, 5 at minimum
|
||||
public UInt16 devtype; // Device type, ODS-2 defines it as always 0
|
||||
public UInt16 rvn; // Relative volume number (number of the volume in a set)
|
||||
public UInt16 setcount; // Total number of volumes in the set this volume is
|
||||
public UInt16 volchar; // Flags
|
||||
public UInt32 volowner; // User ID of the volume owner
|
||||
public UInt32 sec_mask; // Security mask (??)
|
||||
public UInt16 protect; // Volume permissions (system, owner, group and other)
|
||||
public UInt16 fileprot; // Default file protection, unsupported in ODS-2
|
||||
public UInt16 recprot; // Default file record protection
|
||||
public UInt16 checksum1; // Checksum of all preceding entries
|
||||
public UInt64 credate; // Creation date
|
||||
public byte window; // Window size (pointers for the window)
|
||||
public byte lru_lim; // Directories to be stored in cache
|
||||
public UInt16 extend; // Default allocation size in blocks
|
||||
public UInt64 retainmin; // Minimum file retention period
|
||||
public UInt64 retainmax; // Maximum file retention period
|
||||
public UInt64 revdate; // Last modification date
|
||||
public byte[] min_class; // Minimum security class, 20 bytes
|
||||
public byte[] max_class; // Maximum security class, 20 bytes
|
||||
public UInt16 filetab_fid1; // File lookup table FID
|
||||
public UInt16 filetab_fid2; // File lookup table FID
|
||||
public UInt16 filetab_fid3; // File lookup table FID
|
||||
public UInt16 lowstruclev; // Lowest structure level on the volume
|
||||
public UInt16 highstruclev; // Highest structure level on the volume
|
||||
public UInt64 copydate; // Volume copy date (??)
|
||||
public byte[] reserved1; // 302 bytes
|
||||
public UInt32 serialnum; // Physical drive serial number
|
||||
public string strucname; // Name of the volume set, 12 bytes
|
||||
public string volname; // Volume label, 12 bytes
|
||||
public string ownername; // Name of the volume owner, 12 bytes
|
||||
public string format; // ODS-2 defines it as "DECFILE11B", 12 bytes
|
||||
public UInt16 reserved2; // Reserved
|
||||
public UInt16 checksum2; // Checksum of preceding 255 words (16 bit units)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
@@ -15,17 +14,17 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream fileStream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
fileStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
byte record_type;
|
||||
byte[] sync_bytes = new byte[5];
|
||||
byte record_version;
|
||||
|
||||
record_type = (byte)fileStream.ReadByte();
|
||||
fileStream.Read(sync_bytes, 0, 5);
|
||||
record_version = (byte)fileStream.ReadByte();
|
||||
record_type = sb_sector[0x000];
|
||||
Array.Copy(sb_sector, 0x001, sync_bytes, 0, 5);
|
||||
record_version = sb_sector[0x006];
|
||||
|
||||
if (record_type != 1 || record_version != 1)
|
||||
return false;
|
||||
@@ -35,32 +34,32 @@ namespace FileSystemIDandChk.Plugins
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream fileStream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder SuperBlockMetadata = new StringBuilder();
|
||||
|
||||
fileStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(fileStream, false); // BigEndian
|
||||
OperaSuperBlock sb = new OperaSuperBlock();
|
||||
byte[] cString;
|
||||
byte[] cString = new byte[32];
|
||||
sb.sync_bytes = new byte[5];
|
||||
|
||||
sb.record_type = eabr.ReadByte();
|
||||
sb.sync_bytes = eabr.ReadBytes(5);
|
||||
sb.record_version = eabr.ReadByte();
|
||||
sb.volume_flags = eabr.ReadByte();
|
||||
cString = eabr.ReadBytes(32);
|
||||
sb.record_type = sb_sector[0x000];
|
||||
Array.Copy(sb_sector, 0x001, sb.sync_bytes, 0, 5);
|
||||
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);
|
||||
cString = eabr.ReadBytes(32);
|
||||
Array.Copy(sb_sector, 0x028, cString, 0, 32);
|
||||
sb.volume_label = StringHandlers.CToString(cString);
|
||||
sb.volume_id = eabr.ReadInt32();
|
||||
sb.block_size = eabr.ReadInt32();
|
||||
sb.block_count = eabr.ReadInt32();
|
||||
sb.root_dirid = eabr.ReadInt32();
|
||||
sb.rootdir_blocks = eabr.ReadInt32();
|
||||
sb.rootdir_bsize = eabr.ReadInt32();
|
||||
sb.last_root_copy = eabr.ReadInt32();
|
||||
sb.volume_id = BigEndianBitConverter.ToInt32(sb_sector, 0x048);
|
||||
sb.block_size = BigEndianBitConverter.ToInt32(sb_sector, 0x04C);
|
||||
sb.block_count = BigEndianBitConverter.ToInt32(sb_sector, 0x050);
|
||||
sb.root_dirid = BigEndianBitConverter.ToInt32(sb_sector, 0x054);
|
||||
sb.rootdir_blocks = BigEndianBitConverter.ToInt32(sb_sector, 0x058);
|
||||
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)
|
||||
return;
|
||||
@@ -78,7 +77,16 @@ namespace FileSystemIDandChk.Plugins
|
||||
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)
|
||||
SuperBlockMetadata.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", sb.block_size, 2048);
|
||||
}
|
||||
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("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();
|
||||
@@ -89,20 +97,19 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
private struct OperaSuperBlock
|
||||
{
|
||||
public byte record_type; // Record type, must be 1
|
||||
public byte[] sync_bytes; // 5 bytes, "ZZZZZ" = new byte[5];
|
||||
public byte record_version; // Record version, must be 1
|
||||
public byte volume_flags; // Volume flags
|
||||
public string volume_comment; // 32 bytes, volume comment
|
||||
public string volume_label; // 32 bytes, volume label
|
||||
public Int32 volume_id; // Volume ID
|
||||
public Int32 block_size; // Block size in bytes
|
||||
public Int32 block_count; // Blocks in volume
|
||||
public Int32 root_dirid; // Root directory ID
|
||||
public Int32 rootdir_blocks; // Root directory blocks
|
||||
public Int32 rootdir_bsize; // Root directory block size
|
||||
public Int32 last_root_copy; // Last root directory copy
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class PCEnginePlugin : Plugin
|
||||
@@ -15,13 +13,12 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] system_descriptor = new byte[23];
|
||||
byte[] sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
stream.Seek(2080 + offset, SeekOrigin.Begin);
|
||||
|
||||
stream.Read(system_descriptor, 0, 23);
|
||||
Array.Copy(sector, 0x20, system_descriptor, 0, 23);
|
||||
|
||||
if(Encoding.ASCII.GetString(system_descriptor) == "PC Engine CD-ROM SYSTEM")
|
||||
return true;
|
||||
@@ -29,10 +26,9 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,8 +12,8 @@ namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
}
|
||||
|
||||
public abstract bool Identify(FileStream stream, long offset);
|
||||
public abstract void GetInformation(FileStream stream, long offset, out string information);
|
||||
public abstract bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset);
|
||||
public abstract void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Based on FAT's BPB, cannot find a FAT or directory
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class SolarFS : Plugin
|
||||
@@ -15,17 +14,18 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte signature; // 0x29
|
||||
string fs_type; // "SOL_FS "
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
byte[] bpb = imagePlugin.ReadSector (0 + partitionOffset);
|
||||
|
||||
br.BaseStream.Seek(0x25 + offset, SeekOrigin.Begin); // FATs, 1 or 2, maybe 0, never bigger
|
||||
signature = br.ReadByte();
|
||||
br.BaseStream.Seek(0x35 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
|
||||
fs_type = StringHandlers.CToString(br.ReadBytes(8));
|
||||
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);
|
||||
|
||||
if(signature == 0x29 && fs_type == "SOL_FS ")
|
||||
return true;
|
||||
@@ -33,35 +33,44 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
byte[] bpb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
byte[] bpb_strings;
|
||||
|
||||
SolarOSParameterBlock BPB = new SolarOSParameterBlock();
|
||||
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
BPB.x86_jump = br.ReadBytes(3);
|
||||
BPB.OEMName = StringHandlers.CToString(br.ReadBytes(8));
|
||||
BPB.bps = br.ReadUInt16();
|
||||
BPB.unk1 = br.ReadByte();
|
||||
BPB.unk2 = br.ReadUInt16();
|
||||
BPB.root_ent = br.ReadUInt16();
|
||||
BPB.sectors = br.ReadUInt16();
|
||||
BPB.media = br.ReadByte();
|
||||
BPB.spfat = br.ReadUInt16();
|
||||
BPB.sptrk = br.ReadUInt16();
|
||||
BPB.heads = br.ReadUInt16();
|
||||
BPB.unk3 = br.ReadBytes(10);
|
||||
BPB.signature = br.ReadByte();
|
||||
BPB.unk4 = br.ReadUInt32();
|
||||
BPB.vol_name = StringHandlers.CToString(br.ReadBytes(11));
|
||||
BPB.fs_type = StringHandlers.CToString(br.ReadBytes(8));
|
||||
bpb_strings = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x03, bpb_strings, 0, 8);
|
||||
BPB.OEMName = StringHandlers.CToString(bpb_strings);
|
||||
BPB.bps = BitConverter.ToUInt16(bpb_sector, 0x0B);
|
||||
BPB.root_ent = BitConverter.ToUInt16(bpb_sector, 0x10);
|
||||
BPB.sectors = BitConverter.ToUInt16(bpb_sector, 0x12);
|
||||
BPB.media = bpb_sector[0x14];
|
||||
BPB.spfat = BitConverter.ToUInt16(bpb_sector, 0x15);
|
||||
BPB.sptrk = BitConverter.ToUInt16(bpb_sector, 0x17);
|
||||
BPB.heads = BitConverter.ToUInt16(bpb_sector, 0x19);
|
||||
BPB.signature = bpb_sector[0x25];
|
||||
bpb_strings = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x2A, bpb_strings, 0, 11);
|
||||
BPB.vol_name = StringHandlers.CToString(bpb_strings);
|
||||
bpb_strings = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x35, bpb_strings, 0, 8);
|
||||
BPB.fs_type = StringHandlers.CToString(bpb_strings);
|
||||
|
||||
if(MainClass.isDebug)
|
||||
{
|
||||
BPB.x86_jump = new byte[3];
|
||||
Array.Copy(bpb_sector, 0x00, BPB.x86_jump, 0, 3);
|
||||
BPB.unk1 = bpb_sector[0x0D];
|
||||
BPB.unk2 = BitConverter.ToUInt16(bpb_sector, 0x0E);
|
||||
BPB.unk3 = new byte[10];
|
||||
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);
|
||||
@@ -83,7 +92,21 @@ namespace FileSystemIDandChk.Plugins
|
||||
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())
|
||||
{
|
||||
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();
|
||||
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();
|
||||
@@ -111,5 +134,4 @@ namespace FileSystemIDandChk.Plugins
|
||||
public string fs_type; // 0x35, 8 bytes, "SOL_FS "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,8 @@ using FileSystemIDandChk;
|
||||
using System.Collections.Generic;
|
||||
|
||||
// Information from http://www.thoukydides.webspace.virginmedia.com/software/psifs/sis.html
|
||||
// TODO: Implement support for disc images
|
||||
/*
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
@@ -330,3 +332,4 @@ namespace FileSystemIDandChk.Plugins
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -28,15 +28,13 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic;
|
||||
string s_fname, s_fpack;
|
||||
UInt16 s_nfree, s_ninode;
|
||||
UInt32 s_fsize;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
/*for(int j = 0; j<=(br.BaseStream.Length/0x200); j++)
|
||||
{
|
||||
br.BaseStream.Seek(offset + j*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
@@ -57,37 +55,44 @@ namespace FileSystemIDandChk.Plugins
|
||||
Console.WriteLine("@{0:X8}: 0x{1:X8} ({1})", br.BaseStream.Position-offset-4, number);
|
||||
}*/
|
||||
|
||||
for(int i = 0; i<=4; i++) // Check on 0x0000, 0x0200, 0x0600, 0x0800 + offset
|
||||
{
|
||||
if((ulong)br.BaseStream.Length <= (ulong)(offset + i*0x200 + 0x400)) // Stream must be bigger than SB location + SB size + offset
|
||||
return false;
|
||||
byte sb_size_in_sectors;
|
||||
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x3F8, SeekOrigin.Begin); // XENIX magic location
|
||||
magic = br.ReadUInt32();
|
||||
if (imagePlugin.GetSectorSize() <= 0x400) // Check if underlying device sector size is smaller than SuperBlock size
|
||||
sb_size_in_sectors = (byte)(0x400 / imagePlugin.GetSectorSize());
|
||||
else
|
||||
sb_size_in_sectors = 1; // If not a single sector can store it
|
||||
|
||||
if (imagePlugin.GetSectors() <= (partitionOffset + 4 * (ulong)sb_size_in_sectors + (ulong)sb_size_in_sectors)) // Device must be bigger than SB location + SB size + offset
|
||||
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++)
|
||||
{
|
||||
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;
|
||||
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
magic = br.ReadUInt32();
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x1F8); // System V magic location
|
||||
|
||||
if(magic == SYSV_MAGIC || magic == SYSV_CIGAM)
|
||||
return true;
|
||||
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x1E8, SeekOrigin.Begin); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(br.ReadBytes(6));
|
||||
s_fpack = StringHandlers.CToString(br.ReadBytes(6));
|
||||
byte[] coherent_string = new byte[6];
|
||||
Array.Copy(sb_sector, 0x1E8, coherent_string, 0, 6); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(coherent_string);
|
||||
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;
|
||||
|
||||
// Now try to identify 7th edition
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x002, SeekOrigin.Begin);
|
||||
s_fsize = br.ReadUInt32();
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x006, SeekOrigin.Begin);
|
||||
s_nfree = br.ReadUInt16();
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x0D0, SeekOrigin.Begin);
|
||||
s_ninode = br.ReadUInt16();
|
||||
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)
|
||||
{
|
||||
@@ -103,7 +108,7 @@ namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
if(s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD)
|
||||
{
|
||||
if((s_fsize * 1024) <= (br.BaseStream.Length-offset) || (s_fsize * 512) <= (br.BaseStream.Length-offset))
|
||||
if((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -113,13 +118,13 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
bool littleendian = true;
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, littleendian); // Start in little endian until we know what are we handling here
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Start in little endian until we know what are we handling here
|
||||
int start;
|
||||
UInt32 magic;
|
||||
string s_fname, s_fpack;
|
||||
@@ -131,59 +136,65 @@ namespace FileSystemIDandChk.Plugins
|
||||
bool sysvr4 = false;
|
||||
bool sys7th = false;
|
||||
bool coherent = false;
|
||||
byte[] sb_sector;
|
||||
byte sb_size_in_sectors;
|
||||
|
||||
for(start = 0; start<=4; start++) // Check on 0x0000, 0x0200, 0x0600, 0x0800 + offset
|
||||
if (imagePlugin.GetSectorSize() <= 0x400) // Check if underlying device sector size is smaller than SuperBlock size
|
||||
sb_size_in_sectors = (byte)(0x400 / imagePlugin.GetSectorSize());
|
||||
else
|
||||
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++)
|
||||
{
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x3F8, SeekOrigin.Begin); // XENIX magic location
|
||||
magic = eabr.ReadUInt32();
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8); // XENIX magic location
|
||||
|
||||
if(magic == XENIX_MAGIC)
|
||||
{
|
||||
littleendian = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Little endian
|
||||
xenix = true;
|
||||
break;
|
||||
}
|
||||
else if(magic == XENIX_CIGAM)
|
||||
{
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false; // Big endian
|
||||
xenix = true;
|
||||
break;
|
||||
}
|
||||
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
magic = eabr.ReadUInt32();
|
||||
magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F8); // XENIX magic location
|
||||
|
||||
if(magic == SYSV_MAGIC)
|
||||
{
|
||||
littleendian = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Little endian
|
||||
sysv = true;
|
||||
break;
|
||||
}
|
||||
else if(magic == SYSV_CIGAM)
|
||||
{
|
||||
littleendian = false;
|
||||
BigEndianBitConverter.IsLittleEndian = false; // Big endian
|
||||
sysv = true;
|
||||
break;
|
||||
}
|
||||
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x1E8, SeekOrigin.Begin); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
byte[] coherent_string = new byte[6];
|
||||
Array.Copy(sb_sector, 0x1E8, coherent_string, 0, 6); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(coherent_string);
|
||||
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)
|
||||
{
|
||||
littleendian = true; // Coherent is in PDP endianness, use helper for that
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Coherent is in PDP endianness, use helper for that
|
||||
coherent = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Now try to identify 7th edition
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x002, SeekOrigin.Begin);
|
||||
s_fsize = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x006, SeekOrigin.Begin);
|
||||
s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x0D0, SeekOrigin.Begin);
|
||||
s_ninode = eabr.ReadUInt16();
|
||||
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)
|
||||
{
|
||||
@@ -201,10 +212,10 @@ namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
if(s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD)
|
||||
{
|
||||
if((s_fsize * 1024) <= (eabr.BaseStream.Length-offset) || (s_fsize * 512) <= (eabr.BaseStream.Length-offset))
|
||||
if((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()))
|
||||
{
|
||||
sys7th = true;
|
||||
littleendian = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -216,32 +227,32 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
if(xenix)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
byte[] xenix_strings = new byte[6];
|
||||
XenixSuperBlock xnx_sb = new XenixSuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
xnx_sb.s_isize = eabr.ReadUInt16();
|
||||
xnx_sb.s_fsize = eabr.ReadUInt32();
|
||||
xnx_sb.s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(400, SeekOrigin.Current); // Skip free block list
|
||||
xnx_sb.s_ninode = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
xnx_sb.s_flock = eabr.ReadByte();
|
||||
xnx_sb.s_ilock = eabr.ReadByte();
|
||||
xnx_sb.s_fmod = eabr.ReadByte();
|
||||
xnx_sb.s_ronly = eabr.ReadByte();
|
||||
xnx_sb.s_time = eabr.ReadUInt32();
|
||||
xnx_sb.s_tfree = eabr.ReadUInt32();
|
||||
xnx_sb.s_tinode = eabr.ReadUInt16();
|
||||
xnx_sb.s_cylblks = eabr.ReadUInt16();
|
||||
xnx_sb.s_gapblks = eabr.ReadUInt16();
|
||||
xnx_sb.s_dinfo0 = eabr.ReadUInt16();
|
||||
xnx_sb.s_dinfo1 = eabr.ReadUInt16();
|
||||
xnx_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
xnx_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
xnx_sb.s_clean = eabr.ReadByte();
|
||||
xnx_sb.s_magic = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(371, SeekOrigin.Current); // Skip fill zone
|
||||
xnx_sb.s_type = eabr.ReadUInt32();
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
|
||||
xnx_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
|
||||
xnx_sb.s_fsize = BigEndianBitConverter.ToUInt32(sb_sector, 0x002);
|
||||
xnx_sb.s_nfree = BigEndianBitConverter.ToUInt16(sb_sector, 0x006);
|
||||
xnx_sb.s_ninode = BigEndianBitConverter.ToUInt16(sb_sector, 0x198);
|
||||
xnx_sb.s_flock = sb_sector[0x262];
|
||||
xnx_sb.s_ilock = sb_sector[0x263];
|
||||
xnx_sb.s_fmod = sb_sector[0x264];
|
||||
xnx_sb.s_ronly = sb_sector[0x265];
|
||||
xnx_sb.s_time = BigEndianBitConverter.ToUInt32(sb_sector, 0x266);
|
||||
xnx_sb.s_tfree = BigEndianBitConverter.ToUInt32(sb_sector, 0x26A);
|
||||
xnx_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x26E);
|
||||
xnx_sb.s_cylblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x270);
|
||||
xnx_sb.s_gapblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x272);
|
||||
xnx_sb.s_dinfo0 = BigEndianBitConverter.ToUInt16(sb_sector, 0x274);
|
||||
xnx_sb.s_dinfo1 = BigEndianBitConverter.ToUInt16(sb_sector, 0x276);
|
||||
Array.Copy(sb_sector, 0x278, xenix_strings, 0, 6);
|
||||
xnx_sb.s_fname = StringHandlers.CToString(xenix_strings);
|
||||
Array.Copy(sb_sector, 0x27E, xenix_strings, 0, 6);
|
||||
xnx_sb.s_fpack = StringHandlers.CToString(xenix_strings);
|
||||
xnx_sb.s_clean = sb_sector[0x284];
|
||||
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");
|
||||
@@ -262,6 +273,16 @@ namespace FileSystemIDandChk.Plugins
|
||||
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)
|
||||
sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", bs, 2048).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
@@ -289,17 +310,14 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
if(sysv)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
UInt16 pad0, pad1, pad2, pad3;
|
||||
byte[] sysv_strings = new byte[6];
|
||||
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x002, SeekOrigin.Begin); // First padding
|
||||
pad0 = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x00A, SeekOrigin.Begin); // Second padding
|
||||
pad1 = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x0D6, SeekOrigin.Begin); // Third padding
|
||||
pad2 = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x1B6, SeekOrigin.Begin); // Fourth padding
|
||||
pad3 = eabr.ReadUInt16();
|
||||
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)
|
||||
@@ -308,43 +326,55 @@ namespace FileSystemIDandChk.Plugins
|
||||
sysvr2 = true;
|
||||
|
||||
SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
sysv_sb.s_isize = eabr.ReadUInt16();
|
||||
if(sysvr4)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
sysv_sb.s_fsize = eabr.ReadUInt32();
|
||||
sysv_sb.s_nfree = eabr.ReadUInt16();
|
||||
if(sysvr4)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free block list
|
||||
sysv_sb.s_ninode = eabr.ReadUInt16();
|
||||
if(sysvr4)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
sysv_sb.s_flock = eabr.ReadByte();
|
||||
sysv_sb.s_ilock = eabr.ReadByte();
|
||||
sysv_sb.s_fmod = eabr.ReadByte();
|
||||
sysv_sb.s_ronly = eabr.ReadByte();
|
||||
sysv_sb.s_time = eabr.ReadUInt32();
|
||||
sysv_sb.s_cylblks = eabr.ReadUInt16();
|
||||
sysv_sb.s_gapblks = eabr.ReadUInt16();
|
||||
sysv_sb.s_dinfo0 = eabr.ReadUInt16();
|
||||
sysv_sb.s_dinfo1 = eabr.ReadUInt16();
|
||||
sysv_sb.s_tfree = eabr.ReadUInt32();
|
||||
sysv_sb.s_tinode = eabr.ReadUInt16();
|
||||
if(sysvr4 && pad3 == 0)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
sysv_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
sysv_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
if(sysvr4 && pad3 == 0)
|
||||
eabr.BaseStream.Seek(50, SeekOrigin.Current); // Skip fill zone
|
||||
else if(sysvr4)
|
||||
eabr.BaseStream.Seek(50, SeekOrigin.Current); // Skip fill zone
|
||||
else
|
||||
eabr.BaseStream.Seek(56, SeekOrigin.Current); // Skip fill zone
|
||||
sysv_sb.s_state = eabr.ReadUInt32();
|
||||
sysv_sb.s_magic = eabr.ReadUInt32();
|
||||
sysv_sb.s_type = eabr.ReadUInt32();
|
||||
|
||||
// Common offsets
|
||||
sysv_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
|
||||
sysv_sb.s_state = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F4);
|
||||
sysv_sb.s_magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F8);
|
||||
sysv_sb.s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x1FC);
|
||||
|
||||
if (sysvr4)
|
||||
{
|
||||
sysv_sb.s_fsize = BigEndianBitConverter.ToUInt32(sb_sector, 0x004);
|
||||
sysv_sb.s_nfree = BigEndianBitConverter.ToUInt16(sb_sector, 0x008);
|
||||
sysv_sb.s_ninode = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D4);
|
||||
sysv_sb.s_flock = sb_sector[0x1A0];
|
||||
sysv_sb.s_ilock = sb_sector[0x1A1];
|
||||
sysv_sb.s_fmod = sb_sector[0x1A2];
|
||||
sysv_sb.s_ronly = sb_sector[0x1A3];
|
||||
sysv_sb.s_time = BigEndianBitConverter.ToUInt32(sb_sector, 0x1A4);
|
||||
sysv_sb.s_cylblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8);
|
||||
sysv_sb.s_gapblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AA);
|
||||
sysv_sb.s_dinfo0 = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AC);
|
||||
sysv_sb.s_dinfo1 = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AE);
|
||||
sysv_sb.s_tfree = BigEndianBitConverter.ToUInt32(sb_sector, 0x1B0);
|
||||
sysv_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x1B4);
|
||||
Array.Copy(sb_sector, 0x1B8, sysv_strings, 0, 6);
|
||||
sysv_sb.s_fname = StringHandlers.CToString(sysv_strings);
|
||||
Array.Copy(sb_sector, 0x1BE, sysv_strings, 0, 6);
|
||||
sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings);
|
||||
}
|
||||
else
|
||||
{
|
||||
sysv_sb.s_fsize = BigEndianBitConverter.ToUInt32(sb_sector, 0x002);
|
||||
sysv_sb.s_nfree = BigEndianBitConverter.ToUInt16(sb_sector, 0x006);
|
||||
sysv_sb.s_ninode = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D0);
|
||||
sysv_sb.s_flock = sb_sector[0x19A];
|
||||
sysv_sb.s_ilock = sb_sector[0x19B];
|
||||
sysv_sb.s_fmod = sb_sector[0x19C];
|
||||
sysv_sb.s_ronly = sb_sector[0x19D];
|
||||
sysv_sb.s_time = BigEndianBitConverter.ToUInt32(sb_sector, 0x19E);
|
||||
sysv_sb.s_cylblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A2);
|
||||
sysv_sb.s_gapblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A4);
|
||||
sysv_sb.s_dinfo0 = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A6);
|
||||
sysv_sb.s_dinfo1 = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8);
|
||||
sysv_sb.s_tfree = BigEndianBitConverter.ToUInt32(sb_sector, 0x1AA);
|
||||
sysv_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AE);
|
||||
Array.Copy(sb_sector, 0x1B0, sysv_strings, 0, 6);
|
||||
sysv_sb.s_fname = StringHandlers.CToString(sysv_strings);
|
||||
Array.Copy(sb_sector, 0x1B6, sysv_strings, 0, 6);
|
||||
sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings);
|
||||
}
|
||||
|
||||
UInt32 bs = 512;
|
||||
if(sysvr4)
|
||||
@@ -368,6 +398,16 @@ namespace FileSystemIDandChk.Plugins
|
||||
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)
|
||||
sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", bs, 2048).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
@@ -395,28 +435,31 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
if(coherent)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, true);
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
CoherentSuperBlock coh_sb = new CoherentSuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
coh_sb.s_isize = eabr.ReadUInt16();
|
||||
coh_sb.s_fsize = Swapping.PDPFromLittleEndian(eabr.ReadUInt32());
|
||||
coh_sb.s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(256, SeekOrigin.Current); // Skip free block list
|
||||
coh_sb.s_ninode = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
coh_sb.s_flock = eabr.ReadByte();
|
||||
coh_sb.s_ilock = eabr.ReadByte();
|
||||
coh_sb.s_fmod = eabr.ReadByte();
|
||||
coh_sb.s_ronly = eabr.ReadByte();
|
||||
coh_sb.s_time = Swapping.PDPFromLittleEndian(eabr.ReadUInt32());
|
||||
coh_sb.s_tfree = Swapping.PDPFromLittleEndian(eabr.ReadUInt32());
|
||||
coh_sb.s_tinode = eabr.ReadUInt16();
|
||||
coh_sb.s_int_m = eabr.ReadUInt16();
|
||||
coh_sb.s_int_n = eabr.ReadUInt16();
|
||||
coh_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
coh_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
byte[] coh_strings = new byte[6];
|
||||
|
||||
coh_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
|
||||
coh_sb.s_fsize = Swapping.PDPFromLittleEndian(BigEndianBitConverter.ToUInt32(sb_sector, 0x002));
|
||||
coh_sb.s_nfree = BigEndianBitConverter.ToUInt16(sb_sector, 0x006);
|
||||
coh_sb.s_ninode = BigEndianBitConverter.ToUInt16(sb_sector, 0x108);
|
||||
coh_sb.s_flock = sb_sector[0x1D2];
|
||||
coh_sb.s_ilock = sb_sector[0x1D3];
|
||||
coh_sb.s_fmod = sb_sector[0x1D4];
|
||||
coh_sb.s_ronly = sb_sector[0x1D5];
|
||||
coh_sb.s_time = Swapping.PDPFromLittleEndian(BigEndianBitConverter.ToUInt32(sb_sector, 0x1D6));
|
||||
coh_sb.s_tfree = Swapping.PDPFromLittleEndian(BigEndianBitConverter.ToUInt32(sb_sector, 0x1DE));
|
||||
coh_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x1E2);
|
||||
coh_sb.s_int_m = BigEndianBitConverter.ToUInt16(sb_sector, 0x1E4);
|
||||
coh_sb.s_int_n = BigEndianBitConverter.ToUInt16(sb_sector, 0x1E6);
|
||||
Array.Copy(sb_sector, 0x1E8, coh_strings, 0, 6);
|
||||
coh_sb.s_fname = StringHandlers.CToString(coh_strings);
|
||||
Array.Copy(sb_sector, 0x1EE, coh_strings, 0, 6);
|
||||
coh_sb.s_fpack = StringHandlers.CToString(coh_strings);
|
||||
|
||||
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();
|
||||
@@ -438,28 +481,31 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
if(sys7th)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
UNIX7thEditionSuperBlock v7_sb = new UNIX7thEditionSuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
v7_sb.s_isize = eabr.ReadUInt16();
|
||||
v7_sb.s_fsize = eabr.ReadUInt32();
|
||||
v7_sb.s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free block list
|
||||
v7_sb.s_ninode = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
v7_sb.s_flock = eabr.ReadByte();
|
||||
v7_sb.s_ilock = eabr.ReadByte();
|
||||
v7_sb.s_fmod = eabr.ReadByte();
|
||||
v7_sb.s_ronly = eabr.ReadByte();
|
||||
v7_sb.s_time = eabr.ReadUInt32();
|
||||
v7_sb.s_tfree = eabr.ReadUInt32();
|
||||
v7_sb.s_tinode = eabr.ReadUInt16();
|
||||
v7_sb.s_int_m = eabr.ReadUInt16();
|
||||
v7_sb.s_int_n = eabr.ReadUInt16();
|
||||
v7_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
v7_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
UNIX7thEditionSuperBlock v7_sb = new UNIX7thEditionSuperBlock();
|
||||
byte[] sys7_strings = new byte[6];
|
||||
|
||||
v7_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
|
||||
v7_sb.s_fsize = BigEndianBitConverter.ToUInt32(sb_sector, 0x002);
|
||||
v7_sb.s_nfree = BigEndianBitConverter.ToUInt16(sb_sector, 0x006);
|
||||
v7_sb.s_ninode = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D0);
|
||||
v7_sb.s_flock = sb_sector[0x19A];
|
||||
v7_sb.s_ilock = sb_sector[0x19B];
|
||||
v7_sb.s_fmod = sb_sector[0x19C];
|
||||
v7_sb.s_ronly = sb_sector[0x19D];
|
||||
v7_sb.s_time = BigEndianBitConverter.ToUInt32(sb_sector, 0x19E);
|
||||
v7_sb.s_tfree = BigEndianBitConverter.ToUInt32(sb_sector, 0x1A2);
|
||||
v7_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A6);
|
||||
v7_sb.s_int_m = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8);
|
||||
v7_sb.s_int_n = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AA);
|
||||
Array.Copy(sb_sector, 0x1AC, sys7_strings, 0, 6);
|
||||
v7_sb.s_fname = StringHandlers.CToString(sys7_strings);
|
||||
Array.Copy(sb_sector, 0x1B2, sys7_strings, 0, 6);
|
||||
v7_sb.s_fpack = StringHandlers.CToString(sys7_strings);
|
||||
|
||||
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();
|
||||
@@ -480,6 +526,8 @@ namespace FileSystemIDandChk.Plugins
|
||||
}
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = false; // Return to default (bigendian)
|
||||
}
|
||||
|
||||
private struct XenixSuperBlock
|
||||
@@ -620,5 +668,4 @@ namespace FileSystemIDandChk.Plugins
|
||||
public UInt32 s_unique; // 0x1F4, zero-filled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,39 +15,39 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
magic = BitConverter.ToUInt32 (imagePlugin.ReadSector (0 + partitionOffset), 0);
|
||||
|
||||
magic = br.ReadUInt32();
|
||||
if(magic == BFS_MAGIC)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
byte[] bfs_sb_sector = imagePlugin.ReadSector (0 + partitionOffset);
|
||||
byte[] sb_strings = new byte[6];
|
||||
|
||||
BFSSuperBlock bfs_sb = new BFSSuperBlock();
|
||||
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
bfs_sb.s_magic = br.ReadUInt32();
|
||||
bfs_sb.s_start = br.ReadUInt32();
|
||||
bfs_sb.s_end = br.ReadUInt32();
|
||||
bfs_sb.s_from = br.ReadUInt32();
|
||||
bfs_sb.s_to = br.ReadUInt32();
|
||||
bfs_sb.s_bfrom = br.ReadInt32();
|
||||
bfs_sb.s_bto = br.ReadInt32();
|
||||
bfs_sb.s_fsname = StringHandlers.CToString(br.ReadBytes(6));
|
||||
bfs_sb.s_volume = StringHandlers.CToString(br.ReadBytes(6));
|
||||
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)
|
||||
{
|
||||
@@ -83,5 +83,4 @@ namespace FileSystemIDandChk.Plugins
|
||||
public string s_volume; // 0x22, 6 bytes, volume name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class ext2FS : Plugin
|
||||
@@ -15,14 +13,11 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] magic_b = new byte[2];
|
||||
ushort magic;
|
||||
byte[] sb_sector = imagePlugin.ReadSector (2 + partitionOffset);
|
||||
|
||||
stream.Seek(0x400 + 56 + offset, SeekOrigin.Begin); // Here should reside magic number
|
||||
stream.Read(magic_b, 0, 2);
|
||||
magic = BitConverter.ToUInt16(magic_b, 0);
|
||||
UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038);
|
||||
|
||||
if(magic == ext2FSMagic || magic == ext2OldFSMagic)
|
||||
return true;
|
||||
@@ -30,13 +25,12 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
ext2FSSuperBlock supblk = new ext2FSSuperBlock();
|
||||
byte[] forstrings;
|
||||
bool old_ext2 = false;
|
||||
@@ -47,42 +41,54 @@ namespace FileSystemIDandChk.Plugins
|
||||
byte[] guid_a = new byte[16];
|
||||
byte[] guid_b = new byte[16];
|
||||
|
||||
br.BaseStream.Seek (0x400 + offset, SeekOrigin.Begin);
|
||||
supblk.inodes = br.ReadUInt32();
|
||||
supblk.blocks = br.ReadUInt32();
|
||||
supblk.reserved_blocks = br.ReadUInt32();
|
||||
supblk.free_blocks = br.ReadUInt32();
|
||||
supblk.free_inodes = br.ReadUInt32();
|
||||
supblk.first_block = br.ReadUInt32();
|
||||
supblk.block_size = br.ReadUInt32();
|
||||
supblk.frag_size = br.ReadInt32();
|
||||
supblk.blocks_per_grp = br.ReadUInt32();
|
||||
supblk.flags_per_grp = br.ReadUInt32();
|
||||
supblk.inodes_per_grp = br.ReadUInt32();
|
||||
supblk.mount_t = br.ReadUInt32();
|
||||
supblk.write_t = br.ReadUInt32();
|
||||
supblk.mount_c = br.ReadUInt16();
|
||||
supblk.max_mount_c = br.ReadInt16();
|
||||
supblk.magic = br.ReadUInt16();
|
||||
supblk.state = br.ReadUInt16();
|
||||
supblk.err_behaviour = br.ReadUInt16();
|
||||
supblk.minor_revision = br.ReadUInt16();
|
||||
supblk.check_t = br.ReadUInt32();
|
||||
supblk.check_inv = br.ReadUInt32();
|
||||
uint sb_size_in_sectors = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 = br.ReadUInt32();
|
||||
supblk.revision = br.ReadUInt32();
|
||||
supblk.default_uid = br.ReadUInt16();
|
||||
supblk.default_gid = br.ReadUInt16();
|
||||
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 = br.ReadUInt32();
|
||||
supblk.inode_size = br.ReadUInt16();
|
||||
supblk.block_group_no = br.ReadUInt16();
|
||||
supblk.ftr_compat = br.ReadUInt32();
|
||||
supblk.ftr_incompat = br.ReadUInt32();
|
||||
supblk.ftr_ro_compat = br.ReadUInt32();
|
||||
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
|
||||
guid_a = br.ReadBytes(16);
|
||||
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];
|
||||
@@ -102,17 +108,17 @@ namespace FileSystemIDandChk.Plugins
|
||||
supblk.uuid = new Guid(guid_b);
|
||||
// End of volume UUID
|
||||
forstrings = new byte[16];
|
||||
forstrings = br.ReadBytes(16);
|
||||
Array.Copy (sb_sector, 0x078, forstrings, 0, 16);
|
||||
supblk.volume_name = StringHandlers.CToString(forstrings);
|
||||
forstrings = new byte[64];
|
||||
forstrings = br.ReadBytes(64);
|
||||
Array.Copy (sb_sector, 0x088, forstrings, 0, 64);
|
||||
supblk.last_mount_dir = StringHandlers.CToString(forstrings);
|
||||
supblk.algo_usage_bmp = br.ReadUInt32();
|
||||
supblk.prealloc_blks = br.ReadByte();
|
||||
supblk.prealloc_dir_blks = br.ReadByte();
|
||||
supblk.rsrvd_gdt_blocks = br.ReadUInt16();
|
||||
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
|
||||
guid_a = br.ReadBytes(16);
|
||||
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];
|
||||
@@ -130,56 +136,53 @@ namespace FileSystemIDandChk.Plugins
|
||||
guid_b[14] = guid_a[14];
|
||||
guid_b[15] = guid_a[15];
|
||||
supblk.journal_uuid = new Guid(guid_b);
|
||||
supblk.journal_inode = br.ReadUInt32();
|
||||
supblk.journal_dev = br.ReadUInt32();
|
||||
supblk.last_orphan = br.ReadUInt32();
|
||||
supblk.hash_seed_1 = br.ReadUInt32();
|
||||
supblk.hash_seed_2 = br.ReadUInt32();
|
||||
supblk.hash_seed_3 = br.ReadUInt32();
|
||||
supblk.hash_seed_4 = br.ReadUInt32();
|
||||
supblk.hash_version = br.ReadByte();
|
||||
supblk.jnl_backup_type = br.ReadByte();
|
||||
supblk.desc_grp_size = br.ReadUInt16();
|
||||
supblk.default_mnt_opts = br.ReadUInt32();
|
||||
supblk.first_meta_bg = br.ReadUInt32();
|
||||
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 = br.ReadUInt32();
|
||||
br.BaseStream.Seek(68, SeekOrigin.Current);
|
||||
supblk.blocks_hi = br.ReadUInt32();
|
||||
supblk.reserved_blocks_hi = br.ReadUInt32();
|
||||
supblk.free_blocks_hi = br.ReadUInt32();
|
||||
supblk.min_inode_size = br.ReadUInt16();
|
||||
supblk.rsv_inode_size = br.ReadUInt16();
|
||||
supblk.flags = br.ReadUInt32();
|
||||
supblk.raid_stride = br.ReadUInt16();
|
||||
supblk.mmp_interval = br.ReadUInt16();
|
||||
supblk.mmp_block = br.ReadUInt64();
|
||||
supblk.raid_stripe_width = br.ReadUInt32();
|
||||
supblk.flex_bg_grp_size = br.ReadByte();
|
||||
supblk.padding = br.ReadByte();
|
||||
supblk.padding2 = br.ReadUInt16();
|
||||
supblk.kbytes_written = br.ReadUInt64();
|
||||
supblk.snapshot_inum = br.ReadUInt32();
|
||||
supblk.snapshot_id = br.ReadUInt32();
|
||||
supblk.snapshot_blocks = br.ReadUInt64();
|
||||
supblk.snapshot_list = br.ReadUInt32();
|
||||
supblk.error_count = br.ReadUInt32();
|
||||
supblk.first_error_t = br.ReadUInt32();
|
||||
supblk.first_error_inode = br.ReadUInt32();
|
||||
supblk.first_error_block = br.ReadUInt64();
|
||||
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];
|
||||
forstrings = br.ReadBytes(32);
|
||||
Array.Copy (sb_sector, 0x1A0, forstrings, 0, 32);
|
||||
supblk.first_error_func = StringHandlers.CToString(forstrings);
|
||||
supblk.first_error_line = br.ReadUInt32();
|
||||
supblk.last_error_t = br.ReadUInt32();
|
||||
supblk.last_error_inode = br.ReadUInt32();
|
||||
supblk.last_error_block = br.ReadUInt64();
|
||||
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];
|
||||
forstrings = br.ReadBytes(32);
|
||||
Array.Copy (sb_sector, 0x1C8, forstrings, 0, 32);
|
||||
supblk.last_error_func = StringHandlers.CToString(forstrings);
|
||||
supblk.last_error_line = br.ReadUInt32();
|
||||
forstrings = new byte[64];
|
||||
forstrings = br.ReadBytes(64);
|
||||
Array.Copy (sb_sector, 0x1D8, forstrings, 0, 64);
|
||||
supblk.mount_options = StringHandlers.CToString(forstrings);
|
||||
|
||||
if(supblk.magic == ext2OldFSMagic)
|
||||
@@ -558,102 +561,103 @@ namespace FileSystemIDandChk.Plugins
|
||||
public const UInt16 ext2FSMagic = 0xEF53; // Same for ext3 and ext4
|
||||
public const UInt16 ext2OldFSMagic = 0xEF51;
|
||||
|
||||
// Size = 536 bytes
|
||||
public struct ext2FSSuperBlock
|
||||
{
|
||||
public UInt32 inodes; // inodes on volume
|
||||
public UInt32 blocks; // blocks on volume
|
||||
public UInt32 reserved_blocks; // reserved blocks
|
||||
public UInt32 free_blocks; // free blocks count
|
||||
public UInt32 free_inodes; // free inodes count
|
||||
public UInt32 first_block; // first data block
|
||||
public UInt32 block_size; // block size
|
||||
public Int32 frag_size; // fragment size
|
||||
public UInt32 blocks_per_grp; // blocks per group
|
||||
public UInt32 flags_per_grp; // fragments per group
|
||||
public UInt32 inodes_per_grp; // inodes per group
|
||||
public UInt32 mount_t; // last mount time
|
||||
public UInt32 write_t; // last write time
|
||||
public UInt16 mount_c; // mounts count
|
||||
public Int16 max_mount_c; // max mounts
|
||||
public UInt16 magic; // (little endian)
|
||||
public UInt16 state; // filesystem state
|
||||
public UInt16 err_behaviour; // behaviour on errors
|
||||
public UInt16 minor_revision; // From 0.5b onward
|
||||
public UInt32 check_t; // last check time
|
||||
public UInt32 check_inv; // max time between checks
|
||||
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; // Creation OS
|
||||
public UInt32 revision; // Revison level
|
||||
public UInt16 default_uid; // Default UID for reserved blocks
|
||||
public UInt16 default_gid; // Default GID for reserved blocks
|
||||
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; // First unreserved inode
|
||||
public UInt16 inode_size; // inode size
|
||||
public UInt16 block_group_no; // Block group number of THIS superblock
|
||||
public UInt32 ftr_compat; // Compatible features set
|
||||
public UInt32 ftr_incompat; // Incompatible features set
|
||||
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; // Read-only compatible features set
|
||||
public UInt32 ftr_ro_compat; // 0x064, Read-only compatible features set
|
||||
// Found on Linux 2.1.132
|
||||
public Guid uuid; // 16 bytes, UUID
|
||||
public string volume_name; // 16 bytes, volume name
|
||||
public string last_mount_dir; // 64 bytes, where last mounted
|
||||
public UInt32 algo_usage_bmp; // Usage bitmap algorithm, for compression
|
||||
public byte prealloc_blks; // Block to try to preallocate
|
||||
public byte prealloc_dir_blks; // Blocks to try to preallocate for directories
|
||||
public UInt16 rsrvd_gdt_blocks; // Per-group desc for online growth
|
||||
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; // 16 bytes, UUID of journal superblock
|
||||
public UInt32 journal_inode; // inode no. of journal file
|
||||
public UInt32 journal_dev; // device no. of journal file
|
||||
public UInt32 last_orphan; // Start of list of inodes to delete
|
||||
public UInt32 hash_seed_1; // First byte of 128bit HTREE hash seed
|
||||
public UInt32 hash_seed_2; // Second byte of 128bit HTREE hash seed
|
||||
public UInt32 hash_seed_3; // Third byte of 128bit HTREE hash seed
|
||||
public UInt32 hash_seed_4; // Fourth byte of 128bit HTREE hash seed
|
||||
public byte hash_version; // Hash version
|
||||
public byte jnl_backup_type; // Journal backup type
|
||||
public UInt16 desc_grp_size; // Size of group descriptor
|
||||
public UInt32 default_mnt_opts; // Default mount options
|
||||
public UInt32 first_meta_bg; // First metablock block group
|
||||
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; // Filesystem creation time
|
||||
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; // High 32bits of blocks no.
|
||||
public UInt32 reserved_blocks_hi; // High 32bits of reserved blocks no.
|
||||
public UInt32 free_blocks_hi; // High 32bits of free blocks no.
|
||||
public UInt16 min_inode_size; // inodes minimal size in bytes
|
||||
public UInt16 rsv_inode_size; // Bytes reserved by new inodes
|
||||
public UInt32 flags; // Flags
|
||||
public UInt16 raid_stride; // RAID stride
|
||||
public UInt16 mmp_interval; // Waiting seconds in MMP check
|
||||
public UInt64 mmp_block; // Block for multi-mount protection
|
||||
public UInt32 raid_stripe_width; // Blocks on all data disks (N*stride)
|
||||
public byte flex_bg_grp_size; // FLEX_BG group size
|
||||
public byte padding;
|
||||
public UInt16 padding2;
|
||||
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; // Kibibytes written in volume lifetime
|
||||
public UInt32 snapshot_inum; // Active snapshot inode number
|
||||
public UInt32 snapshot_id; // Active snapshot sequential ID
|
||||
public UInt64 snapshot_blocks; // Reserved blocks for active snapshot's future use
|
||||
public UInt32 snapshot_list; // inode number of the on-disk start of the snapshot list
|
||||
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; // total registered filesystem errors
|
||||
public UInt32 first_error_t; // time on first error
|
||||
public UInt32 first_error_inode; // inode involved in first error
|
||||
public UInt64 first_error_block; // block involved of first error
|
||||
public string first_error_func; // 32 bytes, function where the error happened
|
||||
public UInt32 first_error_line; // line number where error happened
|
||||
public UInt32 last_error_t; // time of most recent error
|
||||
public UInt32 last_error_inode; // inode involved in last error
|
||||
public UInt32 last_error_line; // line number where error happened
|
||||
public UInt64 last_error_block; // block involved of last error
|
||||
public string last_error_func; // 32 bytes, function where the error happened
|
||||
// End of optiona error-handling features
|
||||
public string mount_options; // 64 bytes, last used mount options
|
||||
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
|
||||
@@ -722,5 +726,4 @@ namespace FileSystemIDandChk.Plugins
|
||||
public const UInt32 EXT2_FLAGS_UNSIGNED_HASH = 0x00000002; // Unsigned dirhash in use
|
||||
public const UInt32 EXT2_FLAGS_TEST_FILESYS = 0x00000004; // Testing development code
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,6 @@ using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class extFS : Plugin
|
||||
@@ -15,14 +13,11 @@ namespace FileSystemIDandChk.Plugins
|
||||
base.PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] magic_b = new byte[2];
|
||||
ushort magic;
|
||||
byte[] sb_sector = imagePlugin.ReadSector (2 + partitionOffset); // Superblock resides at 0x400
|
||||
|
||||
stream.Seek(0x400 + 56 + offset, SeekOrigin.Begin); // Here should reside magic number
|
||||
stream.Read(magic_b, 0, 2);
|
||||
magic = BitConverter.ToUInt16(magic_b, 0);
|
||||
UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038); // Here should reside magic number
|
||||
|
||||
if(magic == extFSMagic)
|
||||
return true;
|
||||
@@ -30,25 +25,24 @@ namespace FileSystemIDandChk.Plugins
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
byte[] sb_sector = imagePlugin.ReadSector (2 + partitionOffset); // Superblock resides at 0x400
|
||||
extFSSuperBlock ext_sb = new extFSSuperBlock();
|
||||
|
||||
br.BaseStream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
ext_sb.inodes = br.ReadUInt32();
|
||||
ext_sb.zones = br.ReadUInt32();
|
||||
ext_sb.firstfreeblk = br.ReadUInt32();
|
||||
ext_sb.freecountblk = br.ReadUInt32();
|
||||
ext_sb.firstfreeind = br.ReadUInt32();
|
||||
ext_sb.freecountind = br.ReadUInt32();
|
||||
ext_sb.firstdatazone = br.ReadUInt32();
|
||||
ext_sb.logzonesize = br.ReadUInt32();
|
||||
ext_sb.maxsize = br.ReadUInt32();
|
||||
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);
|
||||
@@ -67,22 +61,21 @@ namespace FileSystemIDandChk.Plugins
|
||||
|
||||
public struct extFSSuperBlock
|
||||
{
|
||||
public UInt32 inodes; // inodes on volume
|
||||
public UInt32 zones; // zones on volume
|
||||
public UInt32 firstfreeblk; // first free block
|
||||
public UInt32 freecountblk; // free blocks count
|
||||
public UInt32 firstfreeind; // first free inode
|
||||
public UInt32 freecountind; // free inodes count
|
||||
public UInt32 firstdatazone; // first data zone
|
||||
public UInt32 logzonesize; // log zone size
|
||||
public UInt32 maxsize; // max zone size
|
||||
public UInt32 reserved1; // reserved
|
||||
public UInt32 reserved2; // reserved
|
||||
public UInt32 reserved3; // reserved
|
||||
public UInt32 reserved4; // reserved
|
||||
public UInt32 reserved5; // reserved
|
||||
public UInt16 magic; // 0x137D (little endian)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user