mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Rename project folder.
This commit is contained in:
70
DiscImageChef/ArrayFill.cs
Normal file
70
DiscImageChef/ArrayFill.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ArrayFill.cs
|
||||
Version : 1.0
|
||||
Author(s) : https://github.com/mykohsu
|
||||
|
||||
Component : Helpers
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Fills an array with a
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
No license specified by creator.
|
||||
|
||||
Published on https://github.com/mykohsu/Extensions/blob/master/ArrayExtensions.cs
|
||||
|
||||
Assuming open source.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2014 mykohsu
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
using System;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
public static class ArrayHelpers
|
||||
{
|
||||
public static void ArrayFill<T>(T[] destinationArray, T value)
|
||||
{
|
||||
// if called with a single value, wrap the value in an array and call the main function
|
||||
ArrayFill<T>(destinationArray, new T[] { value });
|
||||
}
|
||||
|
||||
public static void ArrayFill<T>(T[] destinationArray, T[] value)
|
||||
{
|
||||
if (destinationArray == null)
|
||||
{
|
||||
throw new ArgumentNullException("destinationArray");
|
||||
}
|
||||
|
||||
if (value.Length > destinationArray.Length)
|
||||
{
|
||||
throw new ArgumentException("Length of value array must not be more than length of destination");
|
||||
}
|
||||
|
||||
// set the initial array value
|
||||
Array.Copy(value, destinationArray, value.Length);
|
||||
|
||||
int arrayToFillHalfLength = destinationArray.Length / 2;
|
||||
int copyLength;
|
||||
|
||||
for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
|
||||
{
|
||||
Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
|
||||
}
|
||||
|
||||
Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
64
DiscImageChef/AssemblyInfo.cs
Normal file
64
DiscImageChef/AssemblyInfo.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : AssemblyInfo.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Main loop
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
C# assembly definitions
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("DiscImageChef")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
649
DiscImageChef/BigEndianBitConverter.cs
Normal file
649
DiscImageChef/BigEndianBitConverter.cs
Normal file
@@ -0,0 +1,649 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : BigEndianBitConverter.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Program tools
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Override of System.BitConverter that knows how to handle big-endian.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
}
|
||||
456
DiscImageChef/ChangeLog
Normal file
456
DiscImageChef/ChangeLog
Normal file
@@ -0,0 +1,456 @@
|
||||
2014-04-21 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* ImagePlugins/TeleDisk.cs:
|
||||
Start to implement OpenImage(), decode comment block.
|
||||
|
||||
2014-04-21 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* ImagePlugins/TeleDisk.cs:
|
||||
Added CRC calculation method and check of header using CRC
|
||||
to return a positive identification.
|
||||
|
||||
2014-04-19 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* ImagePlugins/TeleDisk.cs:
|
||||
* FileSystemIDandChk.csproj:
|
||||
Started Sydex TeleDisk implementation, with structs,
|
||||
constants and initial Identify() implementation.
|
||||
|
||||
2014-04-19 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* LICENSE:
|
||||
* Main.cs:
|
||||
* Plugins.cs:
|
||||
* Swapping.cs:
|
||||
* Plugins/BFS.cs:
|
||||
* Plugins/FFS.cs:
|
||||
* Plugins/ODS.cs:
|
||||
* Plugins/FAT.cs:
|
||||
* Plugins/SysV.cs:
|
||||
* Plugins/NTFS.cs:
|
||||
* AssemblyInfo.cs:
|
||||
* Plugins/HPFS.cs:
|
||||
* DateHandlers.cs:
|
||||
* Plugins/Opera.cs:
|
||||
* Plugins/extFS.cs:
|
||||
* Plugins/ext2FS.cs:
|
||||
* Plugins/LisaFS.cs:
|
||||
* StringHandlers.cs:
|
||||
* Plugins/Plugin.cs:
|
||||
* Plugins/MinixFS.cs:
|
||||
* Plugins/UNIXBFS.cs:
|
||||
* Plugins/ISO9660.cs:
|
||||
* Plugins/Symbian.cs:
|
||||
* Plugins/SolarFS.cs:
|
||||
* PartPlugins/MBR.cs:
|
||||
* PartPlugins/NeXT.cs:
|
||||
* Plugins/AppleMFS.cs:
|
||||
* Plugins/PCEngine.cs:
|
||||
* Plugins/AppleHFS.cs:
|
||||
* ImagePlugins/CDRWin.cs:
|
||||
* Plugins/AppleHFSPlus.cs:
|
||||
* PartPlugins/AppleMap.cs:
|
||||
* BigEndianBitConverter.cs:
|
||||
* PartPlugins/PartPlugin.cs:
|
||||
* EndianAwareBinaryReader.cs:
|
||||
* ImagePlugins/DiskCopy42.cs:
|
||||
* ImagePlugins/ImagePlugin.cs:
|
||||
Change license from AGPLv3 to GPLv3 to make some good
|
||||
friends happier, and be able to use code from Linux if ever
|
||||
*ever* needed.
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* TODO:
|
||||
* LICENSE:
|
||||
* Main.cs:
|
||||
* README.md:
|
||||
* FileSystemIDandChk.csproj:
|
||||
Add documentation and license and prepare for publication
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Main.cs:
|
||||
* Plugins.cs:
|
||||
* Swapping.cs:
|
||||
* Plugins/ODS.cs:
|
||||
* Plugins/FFS.cs:
|
||||
* Plugins/FAT.cs:
|
||||
* Plugins/BFS.cs:
|
||||
* Plugins/SysV.cs:
|
||||
* DateHandlers.cs:
|
||||
* Plugins/NTFS.cs:
|
||||
* AssemblyInfo.cs:
|
||||
* Plugins/HPFS.cs:
|
||||
* Plugins/Opera.cs:
|
||||
* Plugins/extFS.cs:
|
||||
* Plugins/Plugin.cs:
|
||||
* Plugins/LisaFS.cs:
|
||||
* StringHandlers.cs:
|
||||
* Plugins/ext2FS.cs:
|
||||
* PartPlugins/MBR.cs:
|
||||
* Plugins/MinixFS.cs:
|
||||
* Plugins/UNIXBFS.cs:
|
||||
* Plugins/ISO9660.cs:
|
||||
* Plugins/Symbian.cs:
|
||||
* Plugins/SolarFS.cs:
|
||||
* Plugins/PCEngine.cs:
|
||||
* Plugins/AppleHFS.cs:
|
||||
* PartPlugins/NeXT.cs:
|
||||
* Plugins/AppleMFS.cs:
|
||||
* ImagePlugins/CDRWin.cs:
|
||||
* Plugins/AppleHFSPlus.cs:
|
||||
* PartPlugins/AppleMap.cs:
|
||||
* BigEndianBitConverter.cs:
|
||||
* PartPlugins/PartPlugin.cs:
|
||||
* ImagePlugins/DiskCopy42.cs:
|
||||
* EndianAwareBinaryReader.cs:
|
||||
* ImagePlugins/ImagePlugin.cs:
|
||||
Added information and license header.
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* DateHandlers.cs:
|
||||
Lisa epoch is 1901 not 1904
|
||||
|
||||
* Plugins/LisaFS.cs:
|
||||
Typos corrected, now works perfectly
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* DateHandlers.cs:
|
||||
lisatime_t is unsigned
|
||||
|
||||
* Plugins/LisaFS.cs:
|
||||
Added code to search for MDDF, check some variables to be
|
||||
sure it's a real MDDF, and get information about it.
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/LisaFS.cs:
|
||||
* FileSystemIDandChk.csproj:
|
||||
Added LisaFS skeleton with Lisa's MDDF and tag structs
|
||||
|
||||
* DateHandlers.cs:
|
||||
Added convert function from Lisa timestamp fields to C#
|
||||
DateTime
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* ImagePlugins/DiskCopy42.cs:
|
||||
* ImagePlugins/ImagePlugin.cs:
|
||||
Added support for Apple FileWare (aka Twiggy) disks as
|
||||
dumped by Sigma Seven's BLU
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/AppleMFS.cs:
|
||||
Corrected alignment failure because of incorrect type
|
||||
definition on MDB struct.
|
||||
|
||||
2014-04-17 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* ImagePlugins/DiskCopy42.cs:
|
||||
Correct typos, misalignment of field and
|
||||
BigEndianBitConverter behaviour
|
||||
|
||||
2014-04-15 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* FileSystemIDandChk.csproj:
|
||||
* ImagePlugins/DiskCopy42.cs:
|
||||
Added support for Apple DiskCopy 4.2 format
|
||||
|
||||
* ImagePlugins/ImagePlugin.cs:
|
||||
Added standard IBM, DEC and Apple floppy formats
|
||||
|
||||
2014-04-14 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Main.cs:
|
||||
* Plugins.cs:
|
||||
* Swapping.cs:
|
||||
* Plugins/BFS.cs:
|
||||
* Plugins/FAT.cs:
|
||||
* Plugins/FFS.cs:
|
||||
* Plugins/ODS.cs:
|
||||
* Plugins/NTFS.cs:
|
||||
* Plugins/HPFS.cs:
|
||||
* DateHandlers.cs:
|
||||
* Plugins/SysV.cs:
|
||||
* Plugins/extFS.cs:
|
||||
* Plugins/Opera.cs:
|
||||
* Plugins/Plugin.cs:
|
||||
* StringHandlers.cs:
|
||||
* Plugins/ext2FS.cs:
|
||||
* Plugins/SolarFS.cs:
|
||||
* Plugins/UNIXBFS.cs:
|
||||
* Plugins/MinixFS.cs:
|
||||
* Plugins/ISO9660.cs:
|
||||
* PartPlugins/MBR.cs:
|
||||
* Plugins/AppleMFS.cs:
|
||||
* PartPlugins/NeXT.cs:
|
||||
* Plugins/PCEngine.cs:
|
||||
* Plugins/AppleHFS.cs:
|
||||
* ImagePlugins/CDRWin.cs:
|
||||
* PartPlugins/AppleMap.cs:
|
||||
* Plugins/AppleHFSPlus.cs:
|
||||
* BigEndianBitConverter.cs:
|
||||
* FileSystemIDandChk.csproj:
|
||||
* EndianAwareBinaryReader.cs:
|
||||
* ImagePlugins/ImagePlugin.cs:
|
||||
Refactor and reformat code
|
||||
|
||||
2014-04-14 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Main.cs:
|
||||
* ImagePlugins/CDRWin.cs:
|
||||
Constrain debug information to debug mode
|
||||
|
||||
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:
|
||||
* FileSystemIDandChk.csproj:
|
||||
Added support for System V filesystem
|
||||
|
||||
* PartPlugins/MBR.cs:
|
||||
UnixWare is not the only one using the UNIX disklabel
|
||||
Corrected UNIX disklabel sector.
|
||||
Enhanced UNIX disklabel with structs and consts.
|
||||
Added support for old UNIX disklabels.
|
||||
|
||||
* Swapping.cs:
|
||||
Added code for middle-endian (PDP-endian)
|
||||
|
||||
2012-08-06 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/UNIXBFS.cs:
|
||||
* FileSystemIDandChk.csproj:
|
||||
Added UNIX Boot filesystem.
|
||||
|
||||
* Plugins/FAT.cs:
|
||||
Don't seek to FAT if value is bigger than volume size.
|
||||
|
||||
2012-08-06 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/SolarFS.cs:
|
||||
* FileSystemIDandChk.csproj:
|
||||
Added code for detection Solar_OS filesystem
|
||||
|
||||
2012-08-05 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/FAT.cs:
|
||||
Add debug information.
|
||||
De-hardcode FAT location, use correct data from BPB or
|
||||
hardcode in case data is empty.
|
||||
Show volume size in bytes also.
|
||||
Added offset of PB entries on comments.
|
||||
|
||||
2012-08-05 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/MinixFS.cs:
|
||||
* FileSystemIDandChk.csproj:
|
||||
Added Minix V1, V2 and V3 filesystems.
|
||||
|
||||
2012-08-05 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* DateHandlers.cs:
|
||||
Added debug information and prevent malformed datetime
|
||||
strings crash ISO9660ToDateTime class
|
||||
|
||||
2012-08-05 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/ISO9660.cs:
|
||||
Added code preventing it to be run on each partition,
|
||||
because this filesystem will be once and only. Now it runs
|
||||
only one time whenever there are partitions or how many.
|
||||
|
||||
* Plugins/FAT.cs:
|
||||
Added code to handle false positives (FATs can be 1 or 2,
|
||||
maybe 0 in the wild, never bigger).
|
||||
Modified for BinaryReader class.
|
||||
|
||||
* Plugins/BFS.cs:
|
||||
Missed negation operand
|
||||
|
||||
* PartPlugins/NeXT.cs:
|
||||
* PartPlugins/AppleMap.cs:
|
||||
Added constants and modified for EndianAwareBinaryReader
|
||||
class.
|
||||
|
||||
2012-08-05 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/ODS.cs:
|
||||
Use StringHandlers class to prevent garbage coming from
|
||||
strings (even if they are not C strings, it does not hurt).
|
||||
|
||||
* Plugins/AppleHFS.cs:
|
||||
Use constants.
|
||||
|
||||
* Plugins/BFS.cs:
|
||||
* Plugins/AppleMFS.cs:
|
||||
* Plugins/AppleHFSPlus.cs:
|
||||
Use constants and EndianAwareBinaryReader class.
|
||||
|
||||
* Plugins/Opera.cs:
|
||||
Use a superblock structure and EndianAwareBinaryReader
|
||||
class, reduces lots of code.
|
||||
|
||||
2012-08-04 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* CToString.cs:
|
||||
Renamed to StringHandlers.cs
|
||||
|
||||
* Plugins/AppleHFS.cs:
|
||||
Modified to use EndianAwareBinaryReader and PascalToString
|
||||
classes
|
||||
|
||||
* FileSystemIDandChk.csproj:
|
||||
CToString.cs renamed to StringHandlers.cs
|
||||
|
||||
* StringHandlers.cs:
|
||||
Added code to convert Pascal string to .NET String
|
||||
|
||||
2012-08-04 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/FFS.cs:
|
||||
Added code for detecting 42BSD, 43BSD, 44BSD, SunOS,
|
||||
SunOS/x86, UFS and UFS2 filesystems. Block size is incorrect
|
||||
on NeXTStep's CD UFSs, but there is no way to check for it.
|
||||
|
||||
* Main.cs:
|
||||
Disable debug by default
|
||||
|
||||
* FileSystemIDandChk.csproj:
|
||||
Moved to .NET 4 and added EndianAwareBinaryReader class
|
||||
|
||||
* EndianAwareBinaryReader.cs:
|
||||
Override of BinaryReader class with the ability to
|
||||
automatically swap endianness
|
||||
|
||||
2012-08-03 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/ISO9660.cs:
|
||||
When Joliet is present, show both Joliet and Primary volume
|
||||
descriptors, as they may not be in sync
|
||||
|
||||
2012-08-03 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Plugins/ODS.cs:
|
||||
* Plugins/HPFS.cs:
|
||||
* Plugins/ISO9660.cs:
|
||||
* Plugins/AppleMFS.cs:
|
||||
* Plugins/AppleHFS.cs:
|
||||
* Plugins/AppleHFSPlus.cs:
|
||||
Moved datetime conversion to DateHandlers class.
|
||||
|
||||
* Plugins/Symbian.cs:
|
||||
Identifies .SIS files. Yes I know it's not a filesystem but
|
||||
I needed it so.
|
||||
|
||||
* Main.cs:
|
||||
Corrected typo
|
||||
|
||||
* FileSystemIDandChk.csproj:
|
||||
Added datetime conversion handling class, Symbian .SIS
|
||||
installers, ext filesystem and ext2/3/4 filesystems.
|
||||
|
||||
* Plugins/ext2FS.cs:
|
||||
Detects ext2, ext3 and ext4 filesystems up to Linux 3.1
|
||||
kernel.
|
||||
|
||||
* Plugins/extFS.cs:
|
||||
Detects ext filesystems. Untested as no Linux 2.0 was
|
||||
available at time :p
|
||||
|
||||
* DateHandlers.cs:
|
||||
Moved all datetime convertions from plugins to central
|
||||
class.
|
||||
|
||||
2011-06-02 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Added VMS ODS
|
||||
|
||||
2011-03-29 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Added NTFS
|
||||
|
||||
2011-03-28 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Added HPFS
|
||||
|
||||
2011-03-28 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Added Be filesystem
|
||||
|
||||
2011-03-28 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Use FOBOS guids
|
||||
|
||||
2011-03-25 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Added NeXT disklabels and unidentify MBR with 0 entries
|
||||
|
||||
2011-03-25 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* ISO9660 should always check from offset 0, needs to be sure it runs only once
|
||||
|
||||
2011-03-25 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Added MBR partition scheme.
|
||||
|
||||
2011-03-06 Natalia Portillo <claunia@claunia.com>
|
||||
* Added skeleton for BSD FFS.
|
||||
* Added HFS+.
|
||||
* If HFS detects it has wrapped a HFS+ volume, inform that it's not its filesystem.
|
||||
* Added a workaround in calculation with UInt32 and ulong that made HFS and MFS show a bad date.
|
||||
|
||||
2011-03-203 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* First commit to SVN
|
||||
150
DiscImageChef/DateHandlers.cs
Normal file
150
DiscImageChef/DateHandlers.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : DateHandlers.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Program tools
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Convert several timestamp formats to C# DateTime.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
public static class DateHandlers
|
||||
{
|
||||
static readonly DateTime LisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0);
|
||||
static readonly DateTime MacEpoch = new DateTime(1904, 1, 1, 0, 0, 0);
|
||||
static readonly DateTime UNIXEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
|
||||
// Day 0 of Julian Date system
|
||||
static readonly DateTime JulianEpoch = new DateTime(1858, 11, 17, 0, 0, 0);
|
||||
|
||||
public static DateTime MacToDateTime(ulong MacTimeStamp)
|
||||
{
|
||||
return MacEpoch.AddTicks((long)(MacTimeStamp * 10000000));
|
||||
}
|
||||
|
||||
public static DateTime LisaToDateTime(UInt32 LisaTimeStamp)
|
||||
{
|
||||
return LisaEpoch.AddSeconds(LisaTimeStamp);
|
||||
}
|
||||
|
||||
public static DateTime UNIXToDateTime(Int32 UNIXTimeStamp)
|
||||
{
|
||||
return UNIXEpoch.AddSeconds(UNIXTimeStamp);
|
||||
}
|
||||
|
||||
public static DateTime UNIXUnsignedToDateTime(UInt32 UNIXTimeStamp)
|
||||
{
|
||||
return UNIXEpoch.AddSeconds(UNIXTimeStamp);
|
||||
}
|
||||
|
||||
public static DateTime ISO9660ToDateTime(byte[] VDDateTime)
|
||||
{
|
||||
int year, month, day, hour, minute, second, hundredths;
|
||||
byte[] twocharvalue = new byte[2];
|
||||
byte[] fourcharvalue = new byte[4];
|
||||
|
||||
fourcharvalue[0] = VDDateTime[0];
|
||||
fourcharvalue[1] = VDDateTime[1];
|
||||
fourcharvalue[2] = VDDateTime[2];
|
||||
fourcharvalue[3] = VDDateTime[3];
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): year = \"{0}\"", StringHandlers.CToString(fourcharvalue));
|
||||
if (!Int32.TryParse(StringHandlers.CToString(fourcharvalue), out year))
|
||||
year = 0;
|
||||
// year = Convert.ToInt32(StringHandlers.CToString(fourcharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[4];
|
||||
twocharvalue[1] = VDDateTime[5];
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): month = \"{0}\"", StringHandlers.CToString(twocharvalue));
|
||||
if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out month))
|
||||
month = 0;
|
||||
// month = Convert.ToInt32(StringHandlers.CToString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[6];
|
||||
twocharvalue[1] = VDDateTime[7];
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): day = \"{0}\"", StringHandlers.CToString(twocharvalue));
|
||||
if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out day))
|
||||
day = 0;
|
||||
// day = Convert.ToInt32(StringHandlers.CToString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[8];
|
||||
twocharvalue[1] = VDDateTime[9];
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): hour = \"{0}\"", StringHandlers.CToString(twocharvalue));
|
||||
if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out hour))
|
||||
hour = 0;
|
||||
// hour = Convert.ToInt32(StringHandlers.CToString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[10];
|
||||
twocharvalue[1] = VDDateTime[11];
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): minute = \"{0}\"", StringHandlers.CToString(twocharvalue));
|
||||
if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out minute))
|
||||
minute = 0;
|
||||
// minute = Convert.ToInt32(StringHandlers.CToString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[12];
|
||||
twocharvalue[1] = VDDateTime[13];
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): second = \"{0}\"", StringHandlers.CToString(twocharvalue));
|
||||
if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out second))
|
||||
second = 0;
|
||||
// second = Convert.ToInt32(StringHandlers.CToString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[14];
|
||||
twocharvalue[1] = VDDateTime[15];
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): hundredths = \"{0}\"", StringHandlers.CToString(twocharvalue));
|
||||
if (!Int32.TryParse(StringHandlers.CToString(twocharvalue), out hundredths))
|
||||
hundredths = 0;
|
||||
// hundredths = Convert.ToInt32(StringHandlers.CToString(twocharvalue));
|
||||
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (ISO9600ToDateTime handler): decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);", year, month, day, hour, minute, second, hundredths * 10);
|
||||
DateTime decodedDT = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Unspecified);
|
||||
|
||||
return decodedDT;
|
||||
}
|
||||
|
||||
// C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC
|
||||
public static DateTime VMSToDateTime(UInt64 vmsDate)
|
||||
{
|
||||
double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail
|
||||
return JulianEpoch.AddMilliseconds(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
163
DiscImageChef/DiscImageChef.csproj
Normal file
163
DiscImageChef/DiscImageChef.csproj
Normal file
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>DiscImageChef</RootNamespace>
|
||||
<AssemblyName>DiscImageChef</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<ReleaseVersion>1.10</ReleaseVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<Externalconsole>True</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<Externalconsole>True</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Plugins\AppleMFS.cs" />
|
||||
<Compile Include="Swapping.cs" />
|
||||
<Compile Include="Plugins\Plugin.cs" />
|
||||
<Compile Include="Plugins.cs" />
|
||||
<Compile Include="Plugins\ISO9660.cs" />
|
||||
<Compile Include="Plugins\PCEngine.cs" />
|
||||
<Compile Include="Plugins\Opera.cs" />
|
||||
<Compile Include="Plugins\AppleHFS.cs" />
|
||||
<Compile Include="Plugins\FAT.cs" />
|
||||
<Compile Include="PartPlugins\PartPlugin.cs" />
|
||||
<Compile Include="PartPlugins\AppleMap.cs" />
|
||||
<Compile Include="Plugins\FFS.cs" />
|
||||
<Compile Include="Plugins\AppleHFSPlus.cs" />
|
||||
<Compile Include="PartPlugins\MBR.cs" />
|
||||
<Compile Include="PartPlugins\NeXT.cs" />
|
||||
<Compile Include="Plugins\BFS.cs" />
|
||||
<Compile Include="Plugins\HPFS.cs" />
|
||||
<Compile Include="Plugins\NTFS.cs" />
|
||||
<Compile Include="Plugins\ODS.cs" />
|
||||
<Compile Include="Plugins\Symbian.cs" />
|
||||
<Compile Include="Plugins\extFS.cs" />
|
||||
<Compile Include="Plugins\ext2FS.cs" />
|
||||
<Compile Include="DateHandlers.cs" />
|
||||
<Compile Include="EndianAwareBinaryReader.cs" />
|
||||
<Compile Include="StringHandlers.cs" />
|
||||
<Compile Include="Plugins\MinixFS.cs" />
|
||||
<Compile Include="Plugins\SolarFS.cs" />
|
||||
<Compile Include="Plugins\UNIXBFS.cs" />
|
||||
<Compile Include="Plugins\SysV.cs" />
|
||||
<Compile Include="ImagePlugins\ImagePlugin.cs" />
|
||||
<Compile Include="ImagePlugins\CDRWin.cs" />
|
||||
<Compile Include="BigEndianBitConverter.cs" />
|
||||
<Compile Include="ImagePlugins\DiskCopy42.cs" />
|
||||
<Compile Include="Plugins\LisaFS.cs" />
|
||||
<Compile Include="ImagePlugins\TeleDisk.cs" />
|
||||
<Compile Include="ArrayFill.cs" />
|
||||
<Compile Include="PrintHex.cs" />
|
||||
<Compile Include="ImagePlugins\ZZZRawImage.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<Folder Include="Plugins\" />
|
||||
<Folder Include="PartPlugins\" />
|
||||
<Folder Include="ImagePlugins\" />
|
||||
</ItemGroup>
|
||||
<ProjectExtensions>
|
||||
<MonoDevelop>
|
||||
<Properties>
|
||||
<Policies>
|
||||
<VersionControlPolicy inheritsSet="Mono">
|
||||
<CommitMessageStyle Indent=" " LastFilePostfix=":
 " IncludeDirectoryPaths="True" />
|
||||
</VersionControlPolicy>
|
||||
<ChangeLogPolicy UpdateMode="ProjectRoot" VcsIntegration="RequireEntry" inheritsSet="Mono">
|
||||
<MessageStyle LastFilePostfix=":
 " IncludeDirectoryPaths="True" />
|
||||
</ChangeLogPolicy>
|
||||
<DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
|
||||
<TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
|
||||
<CSharpFormattingPolicy IndentSwitchBody="True" AnonymousMethodBraceStyle="NextLine" PropertyBraceStyle="NextLine" PropertyGetBraceStyle="NextLine" PropertySetBraceStyle="NextLine" EventBraceStyle="NextLine" EventAddBraceStyle="NextLine" EventRemoveBraceStyle="NextLine" StatementBraceStyle="NextLine" ElseNewLinePlacement="NewLine" CatchNewLinePlacement="NewLine" FinallyNewLinePlacement="NewLine" WhileNewLinePlacement="DoNotCare" ArrayInitializerWrapping="DoNotChange" ArrayInitializerBraceStyle="NextLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
|
||||
<TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
|
||||
<NameConventionPolicy>
|
||||
<Rules>
|
||||
<NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
|
||||
<RequiredPrefixes>
|
||||
<String>I</String>
|
||||
</RequiredPrefixes>
|
||||
</NamingRule>
|
||||
<NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
|
||||
<RequiredSuffixes>
|
||||
<String>Attribute</String>
|
||||
</RequiredSuffixes>
|
||||
</NamingRule>
|
||||
<NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
|
||||
<RequiredSuffixes>
|
||||
<String>EventArgs</String>
|
||||
</RequiredSuffixes>
|
||||
</NamingRule>
|
||||
<NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
|
||||
<RequiredSuffixes>
|
||||
<String>Exception</String>
|
||||
</RequiredSuffixes>
|
||||
</NamingRule>
|
||||
<NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="PascalCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Protected, Public" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
|
||||
<NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
|
||||
<AllowedPrefixes>
|
||||
<String>_</String>
|
||||
<String>m_</String>
|
||||
</AllowedPrefixes>
|
||||
</NamingRule>
|
||||
<NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
|
||||
<AllowedPrefixes>
|
||||
<String>_</String>
|
||||
<String>m_</String>
|
||||
</AllowedPrefixes>
|
||||
</NamingRule>
|
||||
<NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Parameters" AffectedEntity="Parameter" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
|
||||
<NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
|
||||
<RequiredPrefixes>
|
||||
<String>T</String>
|
||||
</RequiredPrefixes>
|
||||
</NamingRule>
|
||||
</Rules>
|
||||
</NameConventionPolicy>
|
||||
</Policies>
|
||||
</Properties>
|
||||
</MonoDevelop>
|
||||
</ProjectExtensions>
|
||||
<ItemGroup>
|
||||
<None Include="TODO" />
|
||||
<None Include="LICENSE" />
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
162
DiscImageChef/EndianAwareBinaryReader.cs
Normal file
162
DiscImageChef/EndianAwareBinaryReader.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : EndianAwareBinaryReader.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Program tools
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Override for System.IO.Binary.Reader that knows how to handle big-endian.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
public class EndianAwareBinaryReader : BinaryReader
|
||||
{
|
||||
byte[] buffer = new byte[8];
|
||||
|
||||
public EndianAwareBinaryReader(Stream input, Encoding encoding, bool isLittleEndian)
|
||||
: base(input, encoding)
|
||||
{
|
||||
IsLittleEndian = isLittleEndian;
|
||||
}
|
||||
|
||||
public EndianAwareBinaryReader(Stream input, bool isLittleEndian)
|
||||
: this(input, Encoding.UTF8, isLittleEndian)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsLittleEndian
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override double ReadDouble()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadDouble();
|
||||
FillMyBuffer(8);
|
||||
return BitConverter.ToDouble(buffer.Take(8).Reverse().ToArray(), 0);
|
||||
}
|
||||
|
||||
public override short ReadInt16()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadInt16();
|
||||
FillMyBuffer(2);
|
||||
return BitConverter.ToInt16(buffer.Take(2).Reverse().ToArray(), 0);
|
||||
|
||||
}
|
||||
|
||||
public override int ReadInt32()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadInt32();
|
||||
FillMyBuffer(4);
|
||||
return BitConverter.ToInt32(buffer.Take(4).Reverse().ToArray(), 0);
|
||||
|
||||
}
|
||||
|
||||
public override long ReadInt64()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadInt64();
|
||||
FillMyBuffer(8);
|
||||
return BitConverter.ToInt64(buffer.Take(8).Reverse().ToArray(), 0);
|
||||
|
||||
}
|
||||
|
||||
public override float ReadSingle()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadSingle();
|
||||
FillMyBuffer(4);
|
||||
return BitConverter.ToSingle(buffer.Take(4).Reverse().ToArray(), 0);
|
||||
}
|
||||
|
||||
public override ushort ReadUInt16()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadUInt16();
|
||||
FillMyBuffer(2);
|
||||
return BitConverter.ToUInt16(buffer.Take(2).Reverse().ToArray(), 0);
|
||||
}
|
||||
|
||||
public override uint ReadUInt32()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadUInt32();
|
||||
FillMyBuffer(4);
|
||||
return BitConverter.ToUInt32(buffer.Take(4).Reverse().ToArray(), 0);
|
||||
}
|
||||
|
||||
public override ulong ReadUInt64()
|
||||
{
|
||||
if (IsLittleEndian)
|
||||
return base.ReadUInt64();
|
||||
FillMyBuffer(8);
|
||||
return BitConverter.ToUInt64(buffer.Take(8).Reverse().ToArray(), 0);
|
||||
}
|
||||
|
||||
void FillMyBuffer(int numBytes)
|
||||
{
|
||||
int offset = 0;
|
||||
int num2;
|
||||
if (numBytes == 1)
|
||||
{
|
||||
num2 = BaseStream.ReadByte();
|
||||
if (num2 == -1)
|
||||
{
|
||||
throw new EndOfStreamException("Attempted to read past the end of the stream.");
|
||||
}
|
||||
buffer[0] = (byte)num2;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
num2 = BaseStream.Read(buffer, offset, numBytes - offset);
|
||||
if (num2 == 0)
|
||||
{
|
||||
throw new EndOfStreamException("Attempted to read past the end of the stream.");
|
||||
}
|
||||
offset += num2;
|
||||
}
|
||||
while (offset < numBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2067
DiscImageChef/ImagePlugins/CDRWin.cs
Normal file
2067
DiscImageChef/ImagePlugins/CDRWin.cs
Normal file
File diff suppressed because it is too large
Load Diff
597
DiscImageChef/ImagePlugins/DiskCopy42.cs
Normal file
597
DiscImageChef/ImagePlugins/DiskCopy42.cs
Normal file
@@ -0,0 +1,597 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : DiskCopy42.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Disc image plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Manages Apple DiskCopy 4.2 disc images, including unofficial modifications.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscImageChef.ImagePlugins
|
||||
{
|
||||
// Checked using several images and strings inside Apple's DiskImages.framework
|
||||
class DiskCopy42 : ImagePlugin
|
||||
{
|
||||
#region Internal Structures
|
||||
|
||||
// DiskCopy 4.2 header, big-endian, data-fork, start of file, 84 bytes
|
||||
struct DC42Header
|
||||
{
|
||||
// 0x00, 64 bytes, pascal string, disk name or "-not a Macintosh disk-", filled with garbage
|
||||
public string diskName;
|
||||
// 0x40, size of data in bytes (usually sectors*512)
|
||||
public UInt32 dataSize;
|
||||
// 0x44, size of tags in bytes (usually sectors*12)
|
||||
public UInt32 tagSize;
|
||||
// 0x48, checksum of data bytes
|
||||
public UInt32 dataChecksum;
|
||||
// 0x4C, checksum of tag bytes
|
||||
public UInt32 tagChecksum;
|
||||
// 0x50, format of disk, see constants
|
||||
public byte format;
|
||||
// 0x51, format of sectors, see constants
|
||||
public byte fmtByte;
|
||||
// 0x52, is disk image valid? always 0x01
|
||||
public byte valid;
|
||||
// 0x53, reserved, always 0x00
|
||||
public byte reserved;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constants
|
||||
|
||||
// format byte
|
||||
// 3.5", single side, double density, GCR
|
||||
const byte kSonyFormat400K = 0x00;
|
||||
// 3.5", double side, double density, GCR
|
||||
const byte kSonyFormat800K = 0x01;
|
||||
// 3.5", double side, double density, MFM
|
||||
const byte kSonyFormat720K = 0x02;
|
||||
// 3.5", double side, high density, MFM
|
||||
const byte kSonyFormat1440K = 0x03;
|
||||
// 3.5", double side, high density, MFM, 21 sectors/track (aka, Microsoft DMF)
|
||||
// Unchecked value
|
||||
const byte kSonyFormat1680K = 0x04;
|
||||
// Defined by Sigma Seven's BLU
|
||||
const byte kSigmaFormatTwiggy = 0x54;
|
||||
// There should be a value for Apple HD20 hard disks, unknown...
|
||||
// fmyByte byte
|
||||
// Based on GCR nibble
|
||||
// Always 0x02 for MFM disks
|
||||
// Unknown for Apple HD20
|
||||
// Defined by Sigma Seven's BLU
|
||||
const byte kSignaFmtByteTwiggy = 0x01;
|
||||
// 3.5" single side double density GCR and MFM all use same code
|
||||
const byte kSonyFmtByte400K = 0x02;
|
||||
const byte kSonyFmtByte720K = kSonyFmtByte400K;
|
||||
const byte kSonyFmtByte1440K = kSonyFmtByte400K;
|
||||
const byte kSonyFmtByte1680K = kSonyFmtByte400K;
|
||||
// 3.5" double side double density GCR, 512 bytes/sector, interleave 2:1
|
||||
const byte kSonyFmtByte800K = 0x22;
|
||||
// 3.5" double side double density GCR, 512 bytes/sector, interleave 2:1, incorrect value (but appears on official documentation)
|
||||
const byte kSonyFmtByte800KIncorrect = 0x12;
|
||||
// 3.5" double side double density GCR, ProDOS format, interleave 4:1
|
||||
const byte kSonyFmtByteProDos = 0x24;
|
||||
// Unformatted sectors
|
||||
const byte kInvalidFmtByte = 0x96;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal variables
|
||||
|
||||
// Start of data sectors in disk image, should be 0x58
|
||||
UInt32 dataOffset;
|
||||
// Start of tags in disk image, after data sectors
|
||||
UInt32 tagOffset;
|
||||
// Sectors
|
||||
UInt32 sectors;
|
||||
// Bytes per sector, should be 512
|
||||
UInt32 bps;
|
||||
// Bytes per tag, should be 12
|
||||
UInt32 bptag;
|
||||
// Header of opened image
|
||||
DC42Header header;
|
||||
// Disk image file
|
||||
string dc42ImagePath;
|
||||
|
||||
#endregion
|
||||
|
||||
public DiskCopy42(PluginBase Core)
|
||||
{
|
||||
Name = "Apple DiskCopy 4.2";
|
||||
PluginUUID = new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
|
||||
}
|
||||
|
||||
public override bool IdentifyImage(string imagePath)
|
||||
{
|
||||
FileStream stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
byte[] buffer = new byte[0x58];
|
||||
byte[] pString = new byte[64];
|
||||
stream.Read(buffer, 0, 0x58);
|
||||
|
||||
// Incorrect pascal string length, not DC42
|
||||
if (buffer[0] > 63)
|
||||
return false;
|
||||
|
||||
DC42Header tmp_header = new DC42Header();
|
||||
|
||||
Array.Copy(buffer, 0, pString, 0, 64);
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
tmp_header.diskName = StringHandlers.PascalToString(pString);
|
||||
tmp_header.dataSize = BigEndianBitConverter.ToUInt32(buffer, 0x40);
|
||||
tmp_header.tagSize = BigEndianBitConverter.ToUInt32(buffer, 0x44);
|
||||
tmp_header.dataChecksum = BigEndianBitConverter.ToUInt32(buffer, 0x48);
|
||||
tmp_header.tagChecksum = BigEndianBitConverter.ToUInt32(buffer, 0x4C);
|
||||
tmp_header.format = buffer[0x50];
|
||||
tmp_header.fmtByte = buffer[0x51];
|
||||
tmp_header.valid = buffer[0x52];
|
||||
tmp_header.reserved = buffer[0x53];
|
||||
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.diskName = \"{0}\"", tmp_header.diskName);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.dataSize = {0} bytes", tmp_header.dataSize);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.tagSize = {0} bytes", tmp_header.tagSize);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.dataChecksum = 0x{0:X8}", tmp_header.dataChecksum);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.tagChecksum = 0x{0:X8}", tmp_header.tagChecksum);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.format = 0x{0:X2}", tmp_header.format);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.fmtByte = 0x{0:X2}", tmp_header.fmtByte);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.valid = {0}", tmp_header.valid);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): tmp_header.reserved = {0}", tmp_header.reserved);
|
||||
}
|
||||
|
||||
if (tmp_header.valid != 1 || tmp_header.reserved != 0)
|
||||
return false;
|
||||
|
||||
FileInfo fi = new FileInfo(imagePath);
|
||||
|
||||
if (tmp_header.dataSize + tmp_header.tagSize + 0x54 != fi.Length && tmp_header.format != kSigmaFormatTwiggy)
|
||||
return false;
|
||||
|
||||
if (tmp_header.format != kSonyFormat400K && tmp_header.format != kSonyFormat800K && tmp_header.format != kSonyFormat720K &&
|
||||
tmp_header.format != kSonyFormat1440K && tmp_header.format != kSonyFormat1680K && tmp_header.format != kSigmaFormatTwiggy)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("Unknown tmp_header.format = 0x{0:X2} value", tmp_header.format);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tmp_header.fmtByte != kSonyFmtByte400K && tmp_header.fmtByte != kSonyFmtByte800K && tmp_header.fmtByte != kSonyFmtByte800KIncorrect &&
|
||||
tmp_header.fmtByte != kSonyFmtByteProDos && tmp_header.fmtByte != kInvalidFmtByte && tmp_header.fmtByte != kSignaFmtByteTwiggy)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("Unknown tmp_header.fmtByte = 0x{0:X2} value", tmp_header.fmtByte);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tmp_header.fmtByte == kInvalidFmtByte)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("Image says it's unformatted");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OpenImage(string imagePath)
|
||||
{
|
||||
FileStream stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
byte[] buffer = new byte[0x58];
|
||||
byte[] pString = new byte[64];
|
||||
stream.Read(buffer, 0, 0x58);
|
||||
|
||||
// Incorrect pascal string length, not DC42
|
||||
if (buffer[0] > 63)
|
||||
return false;
|
||||
|
||||
header = new DC42Header();
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
Array.Copy(buffer, 0, pString, 0, 64);
|
||||
header.diskName = StringHandlers.PascalToString(pString);
|
||||
header.dataSize = BigEndianBitConverter.ToUInt32(buffer, 0x40);
|
||||
header.tagSize = BigEndianBitConverter.ToUInt32(buffer, 0x44);
|
||||
header.dataChecksum = BigEndianBitConverter.ToUInt32(buffer, 0x48);
|
||||
header.tagChecksum = BigEndianBitConverter.ToUInt32(buffer, 0x4C);
|
||||
header.format = buffer[0x50];
|
||||
header.fmtByte = buffer[0x51];
|
||||
header.valid = buffer[0x52];
|
||||
header.reserved = buffer[0x53];
|
||||
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.diskName = \"{0}\"", header.diskName);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.dataSize = {0} bytes", header.dataSize);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.tagSize = {0} bytes", header.tagSize);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.dataChecksum = 0x{0:X8}", header.dataChecksum);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.tagChecksum = 0x{0:X8}", header.tagChecksum);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.format = 0x{0:X2}", header.format);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.fmtByte = 0x{0:X2}", header.fmtByte);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.valid = {0}", header.valid);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.reserved = {0}", header.reserved);
|
||||
}
|
||||
|
||||
if (header.valid != 1 || header.reserved != 0)
|
||||
return false;
|
||||
|
||||
FileInfo fi = new FileInfo(imagePath);
|
||||
|
||||
if (header.dataSize + header.tagSize + 0x54 != fi.Length && header.format != kSigmaFormatTwiggy)
|
||||
return false;
|
||||
|
||||
if (header.format != kSonyFormat400K && header.format != kSonyFormat800K && header.format != kSonyFormat720K &&
|
||||
header.format != kSonyFormat1440K && header.format != kSonyFormat1680K && header.format != kSigmaFormatTwiggy)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Unknown header.format = 0x{0:X2} value", header.format);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.fmtByte != kSonyFmtByte400K && header.fmtByte != kSonyFmtByte800K && header.fmtByte != kSonyFmtByte800KIncorrect &&
|
||||
header.fmtByte != kSonyFmtByteProDos && header.fmtByte != kInvalidFmtByte && header.fmtByte != kSignaFmtByteTwiggy)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Unknown tmp_header.fmtByte = 0x{0:X2} value", header.fmtByte);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.fmtByte == kInvalidFmtByte)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Image says it's unformatted");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
dataOffset = 0x54;
|
||||
tagOffset = header.tagSize != 0 ? 0x54 + header.dataSize : 0;
|
||||
bps = 512;
|
||||
bptag = (uint)(header.tagSize != 0 ? 12 : 0);
|
||||
dc42ImagePath = imagePath;
|
||||
|
||||
sectors = header.dataSize / 512;
|
||||
|
||||
if (header.tagSize != 0)
|
||||
{
|
||||
if (header.tagSize / 12 != sectors)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): header.tagSize / 12 != sectors");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ImageHasPartitions()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override UInt64 GetImageSize()
|
||||
{
|
||||
return sectors * bps + sectors * bptag;
|
||||
}
|
||||
|
||||
public override UInt64 GetSectors()
|
||||
{
|
||||
return sectors;
|
||||
}
|
||||
|
||||
public override UInt32 GetSectorSize()
|
||||
{
|
||||
return bps;
|
||||
}
|
||||
|
||||
public override byte[] ReadSector(UInt64 sectorAddress)
|
||||
{
|
||||
return ReadSectors(sectorAddress, 1);
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag)
|
||||
{
|
||||
return ReadSectorsTag(sectorAddress, 1, tag);
|
||||
}
|
||||
|
||||
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
|
||||
{
|
||||
if (sectorAddress > sectors - 1)
|
||||
throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
|
||||
|
||||
if (sectorAddress + length > sectors)
|
||||
throw new ArgumentOutOfRangeException("length", "Requested more sectors than available");
|
||||
|
||||
byte[] buffer = new byte[length * bps];
|
||||
|
||||
FileStream stream = new FileStream(dc42ImagePath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
stream.Seek((long)(dataOffset + sectorAddress * bps), SeekOrigin.Begin);
|
||||
|
||||
stream.Read(buffer, 0, (int)(length * bps));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag)
|
||||
{
|
||||
if (tag != SectorTagType.AppleSectorTag)
|
||||
throw new FeatureUnsupportedImageException(String.Format("Tag {0} not supported by image format", tag));
|
||||
|
||||
if (header.tagSize == 0)
|
||||
throw new FeatureNotPresentImageException("Disk image does not have tags");
|
||||
|
||||
if (sectorAddress > sectors - 1)
|
||||
throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
|
||||
|
||||
if (sectorAddress + length > sectors)
|
||||
throw new ArgumentOutOfRangeException("length", "Requested more sectors than available");
|
||||
|
||||
byte[] buffer = new byte[length * bptag];
|
||||
|
||||
FileStream stream = new FileStream(dc42ImagePath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
stream.Seek((long)(tagOffset + sectorAddress * bptag), SeekOrigin.Begin);
|
||||
|
||||
stream.Read(buffer, 0, (int)(length * bptag));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorLong(UInt64 sectorAddress)
|
||||
{
|
||||
return ReadSectorsLong(sectorAddress, 1);
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length)
|
||||
{
|
||||
if (sectorAddress > sectors - 1)
|
||||
throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
|
||||
|
||||
if (sectorAddress + length > sectors)
|
||||
throw new ArgumentOutOfRangeException("length", "Requested more sectors than available");
|
||||
|
||||
byte[] data = ReadSectors(sectorAddress, length);
|
||||
byte[] tags = ReadSectorsTag(sectorAddress, length, SectorTagType.AppleSectorTag);
|
||||
byte[] buffer = new byte[data.Length + tags.Length];
|
||||
|
||||
for (uint i = 0; i < length; i++)
|
||||
{
|
||||
Array.Copy(data, i * (bps), buffer, i * (bps + bptag), bps);
|
||||
Array.Copy(tags, i * (bptag), buffer, i * (bps + bptag) + bps, bptag);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public override string GetImageFormat()
|
||||
{
|
||||
return "Apple DiskCopy 4.2";
|
||||
}
|
||||
|
||||
public override string GetImageVersion()
|
||||
{
|
||||
return "4.2";
|
||||
}
|
||||
|
||||
public override string GetImageApplication()
|
||||
{
|
||||
return "Apple DiskCopy";
|
||||
}
|
||||
|
||||
public override string GetImageApplicationVersion()
|
||||
{
|
||||
return "4.2";
|
||||
}
|
||||
|
||||
public override DateTime GetImageCreationTime()
|
||||
{
|
||||
FileInfo fi = new FileInfo(dc42ImagePath);
|
||||
|
||||
return fi.CreationTimeUtc;
|
||||
}
|
||||
|
||||
public override DateTime GetImageLastModificationTime()
|
||||
{
|
||||
FileInfo fi = new FileInfo(dc42ImagePath);
|
||||
|
||||
return fi.LastWriteTimeUtc;
|
||||
}
|
||||
|
||||
public override string GetImageName()
|
||||
{
|
||||
return header.diskName;
|
||||
}
|
||||
|
||||
public override DiskType GetDiskType()
|
||||
{
|
||||
switch (header.format)
|
||||
{
|
||||
case kSonyFormat400K:
|
||||
return DiskType.AppleSonySS;
|
||||
case kSonyFormat800K:
|
||||
return DiskType.AppleSonyDS;
|
||||
case kSonyFormat720K:
|
||||
return DiskType.DOS_35_DS_DD_9;
|
||||
case kSonyFormat1440K:
|
||||
return DiskType.DOS_35_HD;
|
||||
case kSonyFormat1680K:
|
||||
return DiskType.DMF;
|
||||
case kSigmaFormatTwiggy:
|
||||
return DiskType.AppleFileWare;
|
||||
default:
|
||||
return DiskType.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
#region Unsupported features
|
||||
|
||||
public override byte[] ReadDiskTag(DiskTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetImageCreator()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetImageComments()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskManufacturer()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskModel()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskSerialNumber()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskBarcode()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskPartNumber()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override int GetDiskSequence()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override int GetLastDiskSequence()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDriveManufacturer()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDriveModel()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDriveSerialNumber()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<PartPlugins.Partition> GetPartitions()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Track> GetTracks()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Track> GetSessionTracks(Session session)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Track> GetSessionTracks(UInt16 session)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Session> GetSessions()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
#endregion Unsupported features
|
||||
}
|
||||
}
|
||||
|
||||
947
DiscImageChef/ImagePlugins/ImagePlugin.cs
Normal file
947
DiscImageChef/ImagePlugins/ImagePlugin.cs
Normal file
@@ -0,0 +1,947 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ImagePlugin.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Disc image plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Defines functions to be used by disc image plugins and several constants.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscImageChef.ImagePlugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class to implement disk image reading plugins.
|
||||
/// </summary>
|
||||
public abstract class ImagePlugin
|
||||
{
|
||||
/// <summary>Plugin name.</summary>
|
||||
public string Name;
|
||||
/// <summary>Plugin UUID.</summary>
|
||||
public Guid PluginUUID;
|
||||
|
||||
protected ImagePlugin()
|
||||
{
|
||||
}
|
||||
|
||||
// Basic image handling functions
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the image.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if image was identified, <c>false</c> otherwise.</returns>
|
||||
/// <param name="imagePath">Image path.</param>
|
||||
public abstract bool IdentifyImage(string imagePath);
|
||||
|
||||
/// <summary>
|
||||
/// Opens the image.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if image was opened, <c>false</c> otherwise.</returns>
|
||||
/// <param name="imagePath">Image path.</param>
|
||||
public abstract bool OpenImage(string imagePath);
|
||||
|
||||
/// <summary>
|
||||
/// Asks the disk image plugin if the image contains partitions
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if the image contains partitions, <c>false</c> otherwise.</returns>
|
||||
public abstract bool ImageHasPartitions();
|
||||
|
||||
// Image size functions
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the image, without headers.
|
||||
/// </summary>
|
||||
/// <returns>The image size.</returns>
|
||||
public abstract UInt64 GetImageSize();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of sectors in the image.
|
||||
/// </summary>
|
||||
/// <returns>Sectors in image.</returns>
|
||||
public abstract UInt64 GetSectors();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the size of the biggest sector, counting user data only.
|
||||
/// </summary>
|
||||
/// <returns>Biggest sector size (user data only).</returns>
|
||||
public abstract UInt32 GetSectorSize();
|
||||
|
||||
// Image reading functions
|
||||
|
||||
/// <summary>
|
||||
/// Reads a disk tag.
|
||||
/// </summary>
|
||||
/// <returns>Disk tag</returns>
|
||||
/// <param name="tag">Tag type to read.</param>
|
||||
public abstract byte[] ReadDiskTag(DiskTagType tag);
|
||||
|
||||
// Gets a disk tag
|
||||
/// <summary>
|
||||
/// Reads a sector's user data.
|
||||
/// </summary>
|
||||
/// <returns>The sector's user data.</returns>
|
||||
/// <param name="sectorAddress">Sector address (LBA).</param>
|
||||
public abstract byte[] ReadSector(UInt64 sectorAddress);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sector's tag.
|
||||
/// </summary>
|
||||
/// <returns>The sector's tag.</returns>
|
||||
/// <param name="sectorAddress">Sector address (LBA).</param>
|
||||
/// <param name="tag">Tag type.</param>
|
||||
public abstract byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sector's user data, relative to track.
|
||||
/// </summary>
|
||||
/// <returns>The sector's user data.</returns>
|
||||
/// <param name="sectorAddress">Sector address (relative LBA).</param>
|
||||
/// <param name="track">Track.</param>
|
||||
public abstract byte[] ReadSector(UInt64 sectorAddress, UInt32 track);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sector's tag, relative to track.
|
||||
/// </summary>
|
||||
/// <returns>The sector's tag.</returns>
|
||||
/// <param name="sectorAddress">Sector address (relative LBA).</param>
|
||||
/// <param name="track">Track.</param>
|
||||
/// <param name="tag">Tag type.</param>
|
||||
public abstract byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag);
|
||||
|
||||
/// <summary>
|
||||
/// Reads user data from several sectors.
|
||||
/// </summary>
|
||||
/// <returns>The sectors user data.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
public abstract byte[] ReadSectors(UInt64 sectorAddress, UInt32 length);
|
||||
|
||||
/// <summary>
|
||||
/// Reads tag from several sectors.
|
||||
/// </summary>
|
||||
/// <returns>The sectors tag.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
/// <param name="tag">Tag type.</param>
|
||||
public abstract byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag);
|
||||
|
||||
/// <summary>
|
||||
/// Reads user data from several sectors, relative to track.
|
||||
/// </summary>
|
||||
/// <returns>The sectors user data.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
/// <param name="track">Track.</param>
|
||||
public abstract byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track);
|
||||
|
||||
/// <summary>
|
||||
/// Reads tag from several sectors, relative to track.
|
||||
/// </summary>
|
||||
/// <returns>The sectors tag.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
/// <param name="track">Track.</param>
|
||||
/// <param name="tag">Tag type.</param>
|
||||
public abstract byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a complete sector (user data + all tags).
|
||||
/// </summary>
|
||||
/// <returns>The complete sector. Format depends on disk type.</returns>
|
||||
/// <param name="sectorAddress">Sector address (LBA).</param>
|
||||
public abstract byte[] ReadSectorLong(UInt64 sectorAddress);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a complete sector (user data + all tags), relative to track.
|
||||
/// </summary>
|
||||
/// <returns>The complete sector. Format depends on disk type.</returns>
|
||||
/// <param name="sectorAddress">Sector address (relative LBA).</param>
|
||||
/// <param name="track">Track.</param>
|
||||
public abstract byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track);
|
||||
|
||||
/// <summary>
|
||||
/// Reads several complete sector (user data + all tags).
|
||||
/// </summary>
|
||||
/// <returns>The complete sectors. Format depends on disk type.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
public abstract byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length);
|
||||
|
||||
/// <summary>
|
||||
/// Reads several complete sector (user data + all tags), relative to track.
|
||||
/// </summary>
|
||||
/// <returns>The complete sectors. Format depends on disk type.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
/// <param name="track">Track.</param>
|
||||
public abstract byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track);
|
||||
|
||||
// Image information functions
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image format.
|
||||
/// </summary>
|
||||
/// <returns>The image format.</returns>
|
||||
public abstract string GetImageFormat();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image version.
|
||||
/// </summary>
|
||||
/// <returns>The image version.</returns>
|
||||
public abstract string GetImageVersion();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the application that created the image.
|
||||
/// </summary>
|
||||
/// <returns>The application that created the image.</returns>
|
||||
public abstract string GetImageApplication();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version of the application that created the image.
|
||||
/// </summary>
|
||||
/// <returns>The version of the application that created the image.</returns>
|
||||
public abstract string GetImageApplicationVersion();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image creator.
|
||||
/// </summary>
|
||||
/// <returns>Who created the image.</returns>
|
||||
public abstract string GetImageCreator();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image creation time.
|
||||
/// </summary>
|
||||
/// <returns>The image creation time.</returns>
|
||||
public abstract DateTime GetImageCreationTime();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image last modification time.
|
||||
/// </summary>
|
||||
/// <returns>The image last modification time.</returns>
|
||||
public abstract DateTime GetImageLastModificationTime();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the image.
|
||||
/// </summary>
|
||||
/// <returns>The image name.</returns>
|
||||
public abstract string GetImageName();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image comments.
|
||||
/// </summary>
|
||||
/// <returns>The image comments.</returns>
|
||||
public abstract string GetImageComments();
|
||||
|
||||
// Functions to get information from disk represented by image
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disk manufacturer.
|
||||
/// </summary>
|
||||
/// <returns>The disk manufacturer.</returns>
|
||||
public abstract string GetDiskManufacturer();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disk model.
|
||||
/// </summary>
|
||||
/// <returns>The disk model.</returns>
|
||||
public abstract string GetDiskModel();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disk serial number.
|
||||
/// </summary>
|
||||
/// <returns>The disk serial number.</returns>
|
||||
public abstract string GetDiskSerialNumber();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disk (or product) barcode.
|
||||
/// </summary>
|
||||
/// <returns>The disk barcode.</returns>
|
||||
public abstract string GetDiskBarcode();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disk part number.
|
||||
/// </summary>
|
||||
/// <returns>The disk part number.</returns>
|
||||
public abstract string GetDiskPartNumber();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the disk.
|
||||
/// </summary>
|
||||
/// <returns>The disk type.</returns>
|
||||
public abstract DiskType GetDiskType();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disk sequence.
|
||||
/// </summary>
|
||||
/// <returns>The disk sequence, starting at 1.</returns>
|
||||
public abstract int GetDiskSequence();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last disk in the sequence.
|
||||
/// </summary>
|
||||
/// <returns>The last disk in the sequence.</returns>
|
||||
public abstract int GetLastDiskSequence();
|
||||
|
||||
// Functions to get information from drive used to create image
|
||||
|
||||
/// <summary>
|
||||
/// Gets the manufacturer of the drive used to create the image.
|
||||
/// </summary>
|
||||
/// <returns>The drive manufacturer.</returns>
|
||||
public abstract string GetDriveManufacturer();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the model of the drive used to create the image.
|
||||
/// </summary>
|
||||
/// <returns>The drive model.</returns>
|
||||
public abstract string GetDriveModel();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the serial number of the drive used to create the image.
|
||||
/// </summary>
|
||||
/// <returns>The drive serial number.</returns>
|
||||
public abstract string GetDriveSerialNumber();
|
||||
|
||||
// Partitioning functions
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array partitions. Typically only useful for optical disc
|
||||
/// images where each track and index means a different partition, as
|
||||
/// reads can be relative to them.
|
||||
/// </summary>
|
||||
/// <returns>The partitions.</returns>
|
||||
public abstract List<PartPlugins.Partition> GetPartitions();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disc track extents (start, length).
|
||||
/// </summary>
|
||||
/// <returns>The track extents.</returns>
|
||||
public abstract List<Track> GetTracks();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disc track extents for a specified session.
|
||||
/// </summary>
|
||||
/// <returns>The track exents for that session.</returns>
|
||||
/// <param name="session">Session.</param>
|
||||
public abstract List<Track> GetSessionTracks(Session session);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the disc track extents for a specified session.
|
||||
/// </summary>
|
||||
/// <returns>The track exents for that session.</returns>
|
||||
/// <param name="session">Session.</param>
|
||||
public abstract List<Track> GetSessionTracks(UInt16 session);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sessions (optical discs only).
|
||||
/// </summary>
|
||||
/// <returns>The sessions.</returns>
|
||||
public abstract List<Session> GetSessions();
|
||||
// Returns disc sessions
|
||||
|
||||
// CD flags bitmask
|
||||
|
||||
/// <summary>Track is quadraphonic.</summary>
|
||||
public const byte CDFlagsFourChannel = 0x20;
|
||||
/// <summary>Track is non-audio (data).</summary>
|
||||
public const byte CDFlagsDataTrack = 0x10;
|
||||
/// <summary>Track is copy protected.</summary>
|
||||
public const byte CDFlagsCopyPrevent = 0x08;
|
||||
/// <summary>Track has pre-emphasis.</summary>
|
||||
public const byte CDFlagsPreEmphasis = 0x04;
|
||||
}
|
||||
|
||||
// Disk types
|
||||
public enum DiskType
|
||||
{
|
||||
/// <summary>Unknown disk type</summary>
|
||||
Unknown,
|
||||
|
||||
// Somewhat standard Compact Disc formats
|
||||
/// <summary>CD Digital Audio (Red Book)</summary>
|
||||
CDDA,
|
||||
/// <summary>CD+G (Red Book)</summary>
|
||||
CDG,
|
||||
/// <summary>CD+EG (Red Book)</summary>
|
||||
CDEG,
|
||||
/// <summary>CD-i (Green Book)</summary>
|
||||
CDI,
|
||||
/// <summary>CD-ROM (Yellow Book)</summary>
|
||||
CDROM,
|
||||
/// <summary>CD-ROM XA (Yellow Book)</summary>
|
||||
CDROMXA,
|
||||
/// <summary>CD+ (Blue Book)</summary>
|
||||
CDPLUS,
|
||||
/// <summary>CD-MO (Orange Book)</summary>
|
||||
CDMO,
|
||||
/// <summary>CD-Recordable (Orange Book)</summary>
|
||||
CDR,
|
||||
/// <summary>CD-ReWritable (Orange Book)</summary>
|
||||
CDRW,
|
||||
/// <summary>Mount-Rainier CD-RW</summary>
|
||||
CDMRW,
|
||||
/// <summary>Video CD (White Book)</summary>
|
||||
VCD,
|
||||
/// <summary>Super Video CD (White Book)</summary>
|
||||
SVCD,
|
||||
/// <summary>Photo CD (Beige Book)</summary>
|
||||
PCD,
|
||||
/// <summary>Super Audio CD (Scarlet Book)</summary>
|
||||
SACD,
|
||||
/// <summary>Double-Density CD-ROM (Purple Book)</summary>
|
||||
DDCD,
|
||||
/// <summary>DD CD-R (Purple Book)</summary>
|
||||
DDCDR,
|
||||
/// <summary>DD CD-RW (Purple Book)</summary>
|
||||
DDCDRW,
|
||||
/// <summary>DTS audio CD (non-standard)</summary>
|
||||
DTSCD,
|
||||
/// <summary>CD-MIDI (Red Book)</summary>
|
||||
CDMIDI,
|
||||
/// <summary>Any unknown or standard violating CD</summary>
|
||||
CD,
|
||||
|
||||
// Standard DVD formats
|
||||
/// <summary>DVD-ROM (applies to DVD Video and DVD Audio)</summary>
|
||||
DVDROM,
|
||||
/// <summary>DVD-R</summary>
|
||||
DVDR,
|
||||
/// <summary>DVD-RW</summary>
|
||||
DVDRW,
|
||||
/// <summary>DVD+R</summary>
|
||||
DVDPR,
|
||||
/// <summary>DVD+RW</summary>
|
||||
DVDPRW,
|
||||
/// <summary>DVD+RW DL</summary>
|
||||
DVDPRWDL,
|
||||
/// <summary>DVD-R DL</summary>
|
||||
DVDRDL,
|
||||
/// <summary>DVD+R DL</summary>
|
||||
DVDPRDL,
|
||||
/// <summary>DVD-RAM</summary>
|
||||
DVDRAM,
|
||||
|
||||
// Standard HD-DVD formats
|
||||
/// <summary>HD DVD-ROM (applies to HD DVD Video)</summary>
|
||||
HDDVDROM,
|
||||
/// <summary>HD DVD-RAM</summary>
|
||||
HDDVDRAM,
|
||||
/// <summary>HD DVD-R</summary>
|
||||
HDDVDR,
|
||||
/// <summary>HD DVD-RW</summary>
|
||||
HDDVDRW,
|
||||
|
||||
// Standard Blu-ray formats
|
||||
/// <summary>BD-ROM (and BD Video)</summary>
|
||||
BDROM,
|
||||
/// <summary>BD-R</summary>
|
||||
BDR,
|
||||
/// <summary>BD-RE</summary>
|
||||
BDRE,
|
||||
/// <summary>BD-R XL</summary>
|
||||
BDRXL,
|
||||
/// <summary>BD-RE XL</summary>
|
||||
BDREXL,
|
||||
|
||||
// Rare or uncommon standards
|
||||
/// <summary>Enhanced Versatile Disc</summary>
|
||||
EVD,
|
||||
/// <summary>Forward Versatile Disc</summary>
|
||||
FVD,
|
||||
/// <summary>Holographic Versatile Disc</summary>
|
||||
HVD,
|
||||
/// <summary>China Blue High Definition</summary>
|
||||
CBHD,
|
||||
/// <summary>High Definition Versatile Multilayer Disc</summary>
|
||||
HDVMD,
|
||||
/// <summary>Versatile Compact Disc High Density</summary>
|
||||
VCDHD,
|
||||
/// <summary>Pioneer LaserDisc</summary>
|
||||
LD,
|
||||
/// <summary>Pioneer LaserDisc data</summary>
|
||||
LDROM,
|
||||
/// <summary>Sony MiniDisc</summary>
|
||||
MD,
|
||||
/// <summary>Sony Hi-MD</summary>
|
||||
HiMD,
|
||||
/// <summary>Ultra Density Optical</summary>
|
||||
UDO,
|
||||
/// <summary>Stacked Volumetric Optical Disc</summary>
|
||||
SVOD,
|
||||
/// <summary>Five Dimensional disc</summary>
|
||||
FDDVD,
|
||||
|
||||
// Propietary game discs
|
||||
/// <summary>Sony PlayStation game CD</summary>
|
||||
PS1CD,
|
||||
/// <summary>Sony PlayStation 2 game CD</summary>
|
||||
PS2CD,
|
||||
/// <summary>Sony PlayStation 2 game DVD</summary>
|
||||
PS2DVD,
|
||||
/// <summary>Sony PlayStation 3 game DVD</summary>
|
||||
PS3DVD,
|
||||
/// <summary>Sony PlayStation 3 game Blu-ray</summary>
|
||||
PS3BD,
|
||||
/// <summary>Sony PlayStation 4 game Blu-ray</summary>
|
||||
PS4BD,
|
||||
/// <summary>Sony PlayStation Portable Universal Media Disc (ECMA-365)</summary>
|
||||
UMD,
|
||||
/// <summary>Nintendo GameCube Optical Disc</summary>
|
||||
GOD,
|
||||
/// <summary>Nintendo Wii Optical Disc</summary>
|
||||
WOD,
|
||||
/// <summary>Nintendo Wii U Optical Disc</summary>
|
||||
WUOD,
|
||||
/// <summary>Microsoft X-box Game Disc</summary>
|
||||
XGD,
|
||||
/// <summary>Microsoft X-box 360 Game Disc</summary>
|
||||
XGD2,
|
||||
/// <summary>Microsoft X-box 360 Game Disc</summary>
|
||||
XGD3,
|
||||
/// <summary>Microsoft X-box One Game Disc</summary>
|
||||
XGD4,
|
||||
/// <summary>Sega MegaCD</summary>
|
||||
MEGACD,
|
||||
/// <summary>Sega Saturn disc</summary>
|
||||
SATURNCD,
|
||||
/// <summary>Sega/Yamaha Gigabyte Disc</summary>
|
||||
GDROM,
|
||||
/// <summary>Sega/Yamaha recordable Gigabyte Disc}}</summary>
|
||||
GDR,
|
||||
|
||||
// Apple standard floppy format
|
||||
/// <summary>5.25", SS, DD, 35 tracks, 13 spt, 256 bytes/sector, GCR</summary>
|
||||
Apple32SS,
|
||||
/// <summary>5.25", DS, DD, 35 tracks, 13 spt, 256 bytes/sector, GCR</summary>
|
||||
Apple32DS,
|
||||
/// <summary>5.25", SS, DD, 35 tracks, 16 spt, 256 bytes/sector, GCR</summary>
|
||||
Apple33SS,
|
||||
/// <summary>5.25", DS, DD, 35 tracks, 16 spt, 256 bytes/sector, GCR</summary>
|
||||
Apple33DS,
|
||||
/// <summary>3.5", SS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR</summary>
|
||||
AppleSonySS,
|
||||
/// <summary>3.5", DS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR</summary>
|
||||
AppleSonyDS,
|
||||
/// <summary>5.25", DS, ?D, ?? tracks, ?? spt, 512 bytes/sector, GCR, opposite side heads, aka Twiggy</summary>
|
||||
AppleFileWare,
|
||||
|
||||
// IBM/Microsoft PC standard floppy formats
|
||||
/// <summary>5.25", SS, DD, 40 tracks, 8 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_525_SS_DD_8,
|
||||
/// <summary>5.25", SS, DD, 40 tracks, 9 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_525_SS_DD_9,
|
||||
/// <summary>5.25", DS, DD, 40 tracks, 8 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_525_DS_DD_8,
|
||||
/// <summary>5.25", DS, DD, 40 tracks, 9 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_525_DS_DD_9,
|
||||
/// <summary>5.25", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_525_HD,
|
||||
/// <summary>3.5", SS, DD, 80 tracks, 8 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_35_SS_DD_8,
|
||||
/// <summary>3.5", SS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_35_SS_DD_9,
|
||||
/// <summary>3.5", DS, DD, 80 tracks, 8 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_35_DS_DD_8,
|
||||
/// <summary>3.5", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_35_DS_DD_9,
|
||||
/// <summary>3.5", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_35_HD,
|
||||
/// <summary>3.5", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM</summary>
|
||||
DOS_35_ED,
|
||||
|
||||
// Microsoft non standard floppy formats
|
||||
/// <summary>3.5", DS, DD, 80 tracks, 21 spt, 512 bytes/sector, MFM</summary>
|
||||
DMF,
|
||||
/// <summary>3.5", DS, DD, 82 tracks, 21 spt, 512 bytes/sector, MFM</summary>
|
||||
DMF_82,
|
||||
|
||||
// IBM non standard floppy formats
|
||||
XDF_525,
|
||||
XDF_35,
|
||||
|
||||
// IBM standard floppy formats
|
||||
/// <summary>8", SS, SD, 32 tracks, 8 spt, 319 bytes/sector, FM</summary>
|
||||
IBM23FD,
|
||||
/// <summary>8", SS, SD, 73 tracks, 26 spt, 128 bytes/sector, FM</summary>
|
||||
IBM33FD_128,
|
||||
/// <summary>8", SS, SD, 74 tracks, 15 spt, 256 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector</summary>
|
||||
IBM33FD_256,
|
||||
/// <summary>8", SS, SD, 74 tracks, 8 spt, 512 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector</summary>
|
||||
IBM33FD_512,
|
||||
/// <summary>8", DS, SD, 74 tracks, 26 spt, 128 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector</summary>
|
||||
IBM43FD_128,
|
||||
/// <summary>8", DS, SD, 74 tracks, 26 spt, 256 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector</summary>
|
||||
IBM43FD_256,
|
||||
/// <summary>8", DS, DD, 74 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
IBM53FD_256,
|
||||
/// <summary>8", DS, DD, 74 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
IBM53FD_512,
|
||||
/// <summary>8", DS, DD, 74 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
IBM53FD_1024,
|
||||
|
||||
// DEC standard floppy formats
|
||||
/// <summary>8", SS, DD, 77 tracks, 26 spt, 128 bytes/sector, FM</summary>
|
||||
RX01,
|
||||
/// <summary>8", SS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM</summary>
|
||||
RX02,
|
||||
|
||||
// Acorn standard floppy formats
|
||||
/// <summary>5,25", SS, SD, 40 tracks, 10 spt, 256 bytes/sector, FM</summary>
|
||||
ACORN_525_SS_SD_40,
|
||||
/// <summary>5,25", SS, SD, 80 tracks, 10 spt, 256 bytes/sector, FM</summary>
|
||||
ACORN_525_SS_SD_80,
|
||||
/// <summary>5,25", SS, DD, 40 tracks, 16 spt, 256 bytes/sector, MFM</summary>
|
||||
ACORN_525_SS_DD_40,
|
||||
/// <summary>5,25", SS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM</summary>
|
||||
ACORN_525_SS_DD_80,
|
||||
/// <summary>5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM</summary>
|
||||
ACORN_525_DS_DD,
|
||||
|
||||
// Atari standard floppy formats
|
||||
/// <summary>5,25", SS, SD, 40 tracks, 18 spt, 128 bytes/sector, FM</summary>
|
||||
ATARI_525_SD,
|
||||
/// <summary>5,25", SS, ED, 40 tracks, 26 spt, 128 bytes/sector, MFM</summary>
|
||||
ATARI_525_ED,
|
||||
/// <summary>5,25", SS, DD, 40 tracks, 18 spt, 256 bytes/sector, MFM</summary>
|
||||
ATARI_525_DD,
|
||||
|
||||
// Commodore standard floppy formats
|
||||
/// <summary>3,5", DS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM</summary>
|
||||
CBM_35_DD,
|
||||
/// <summary>3,5", DS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM (Amiga)</summary>
|
||||
CBM_AMIGA_35_DD,
|
||||
/// <summary>3,5", DS, HD, 80 tracks, 22 spt, 512 bytes/sector, MFM (Amiga)</summary>
|
||||
CBM_AMIGA_35_HD,
|
||||
|
||||
// NEC standard floppy formats
|
||||
/// <summary>8", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM</summary>
|
||||
NEC_8_SD,
|
||||
/// <summary>8", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, MFM</summary>
|
||||
NEC_8_DD,
|
||||
/// <summary>5,25", DS, HD, 80 tracks, 8 spt, 1024 bytes/sector, MFM</summary>
|
||||
NEC_525_HD,
|
||||
/// <summary>3,5", DS, HD, 80 tracks, 8 spt, 1024 bytes/sector, MFM</summary>
|
||||
NEC_35_HD_8,
|
||||
/// <summary>3,5", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM</summary>
|
||||
NEC_35_HD_15,
|
||||
|
||||
// SHARP standard floppy formats
|
||||
/// <summary>5,25", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM</summary>
|
||||
SHARP_525,
|
||||
/// <summary>3,5", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM</summary>
|
||||
SHARP_35,
|
||||
|
||||
// ECMA standards
|
||||
/// <summary>5,25", DS, DD, 80 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
ECMA_99_8,
|
||||
/// <summary>5,25", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
ECMA_99_15,
|
||||
/// <summary>5,25", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
ECMA_99_26,
|
||||
/// <summary>3,5", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM</summary>
|
||||
ECMA_100,
|
||||
/// <summary>3,5", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM</summary>
|
||||
ECMA_125,
|
||||
/// <summary>3,5", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM</summary>
|
||||
ECMA_147,
|
||||
/// <summary>8", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM</summary>
|
||||
ECMA_54,
|
||||
/// <summary>8", DS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM</summary>
|
||||
ECMA_59,
|
||||
/// <summary>5,25", SS, DD, 35 tracks, 9 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector</summary>
|
||||
ECMA_66,
|
||||
/// <summary>8", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
ECMA_69_8,
|
||||
/// <summary>8", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
ECMA_69_15,
|
||||
/// <summary>8", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector</summary>
|
||||
ECMA_69_26,
|
||||
/// <summary>5,25", DS, DD, 40 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector</summary>
|
||||
ECMA_70,
|
||||
/// <summary>5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector</summary>
|
||||
ECMA_78,
|
||||
/// <summary>5,25", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, FM</summary>
|
||||
ECMA_78_2,
|
||||
/// <summary>3,5", M.O., 250000 sectors, 512 bytes/sector</summary>
|
||||
ECMA_154,
|
||||
/// <summary>5,25", M.O., 940470 sectors, 512 bytes/sector</summary>
|
||||
ECMA_183_512,
|
||||
/// <summary>5,25", M.O., 520902 sectors, 1024 bytes/sector</summary>
|
||||
ECMA_183_1024,
|
||||
/// <summary>5,25", M.O., 1165600 sectors, 512 bytes/sector</summary>
|
||||
ECMA_184_512,
|
||||
/// <summary>5,25", M.O., 639200 sectors, 1024 bytes/sector</summary>
|
||||
ECMA_184_1024,
|
||||
/// <summary>3,5", M.O., 448500 sectors, 512 bytes/sector</summary>
|
||||
ECMA_201,
|
||||
|
||||
// FDFORMAT, non-standard floppy formats
|
||||
/// <summary>5,25", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM</summary>
|
||||
FDFORMAT_525_DD,
|
||||
/// <summary>5,25", DS, HD, 82 tracks, 17 spt, 512 bytes/sector, MFM</summary>
|
||||
FDFORMAT_525_HD,
|
||||
/// <summary>5,25", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM</summary>
|
||||
FDFORMAT_35_DD,
|
||||
/// <summary>5,25", DS, HD, 82 tracks, 21 spt, 512 bytes/sector, MFM</summary>
|
||||
FDFORMAT_35_HD,
|
||||
|
||||
// Generic hard disks
|
||||
GENERIC_HDD
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Track (as partitioning element) types.
|
||||
/// </summary>
|
||||
public enum TrackType
|
||||
{
|
||||
/// <summary>Audio track</summary>
|
||||
Audio,
|
||||
/// <summary>Data track (not any of the below defined ones)</summary>
|
||||
Data,
|
||||
/// <summary>Data track, compact disc mode 1</summary>
|
||||
CDMode1,
|
||||
/// <summary>Data track, compact disc mode 2, formless</summary>
|
||||
CDMode2Formless,
|
||||
/// <summary>Data track, compact disc mode 2, form 1</summary>
|
||||
CDMode2Form1,
|
||||
/// <summary>Data track, compact disc mode 2, form 2</summary>
|
||||
CDMode2Form2
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Track defining structure.
|
||||
/// </summary>
|
||||
public struct Track
|
||||
{
|
||||
/// <summary>Track number, 1-started</summary>
|
||||
public UInt32 TrackSequence;
|
||||
/// <summary>Partition type</summary>
|
||||
public TrackType TrackType;
|
||||
/// <summary>Track starting sector</summary>
|
||||
public UInt64 TrackStartSector;
|
||||
/// <summary>Track ending sector</summary>
|
||||
public UInt64 TrackEndSector;
|
||||
/// <summary>Track pre-gap</summary>
|
||||
public UInt64 TrackPregap;
|
||||
/// <summary>Session this track belongs to</summary>
|
||||
public UInt16 TrackSession;
|
||||
/// <summary>Information that does not find space in this struct</summary>
|
||||
public string TrackDescription;
|
||||
/// <summary>Indexes, 00 to 99 and sector offset</summary>
|
||||
public Dictionary<int, UInt64> Indexes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Session defining structure.
|
||||
/// </summary>
|
||||
public struct Session
|
||||
{
|
||||
/// <summary>Session number, 1-started</summary>
|
||||
public UInt16 SessionSequence;
|
||||
/// <summary>First track present on this session</summary>
|
||||
public UInt32 StartTrack;
|
||||
/// <summary>Last track present on this session</summary>
|
||||
public UInt32 EndTrack;
|
||||
/// <summary>First sector present on this session</summary>
|
||||
public UInt64 StartSector;
|
||||
/// <summary>Last sector present on this session</summary>
|
||||
public UInt64 EndSector;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metadata present for each sector (aka, "tag").
|
||||
/// </summary>
|
||||
public enum SectorTagType
|
||||
{
|
||||
/// <summary>Apple's GCR sector tags, 12 bytes</summary>
|
||||
AppleSectorTag,
|
||||
/// <summary>Sync frame from CD sector, 12 bytes</summary>
|
||||
CDSectorSync,
|
||||
/// <summary>CD sector header, 4 bytes</summary>
|
||||
CDSectorHeader,
|
||||
/// <summary>CD mode 2 sector subheader</summary>
|
||||
CDSectorSubHeader,
|
||||
/// <summary>CD sector EDC, 4 bytes</summary>
|
||||
CDSectorEDC,
|
||||
/// <summary>CD sector ECC P, 172 bytes</summary>
|
||||
CDSectorECC_P,
|
||||
/// <summary>CD sector ECC Q, 104 bytes</summary>
|
||||
CDSectorECC_Q,
|
||||
/// <summary>CD sector ECC (P and Q), 276 bytes</summary>
|
||||
CDSectorECC,
|
||||
/// <summary>CD sector subchannel, 96 bytes</summary>
|
||||
CDSectorSubchannel,
|
||||
/// <summary>CD track ISRC, string, 12 bytes</summary>
|
||||
CDTrackISRC,
|
||||
/// <summary>CD track text, string, 13 bytes</summary>
|
||||
CDTrackText,
|
||||
/// <summary>CD track flags, 1 byte</summary>
|
||||
CDTrackFlags,
|
||||
/// <summary>DVD sector copyright information</summary>
|
||||
DVD_CMI
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Metadata present for each disk.
|
||||
/// </summary>
|
||||
public enum DiskTagType
|
||||
{
|
||||
/// <summary>CD PMA</summary>
|
||||
CD_PMA,
|
||||
/// <summary>CD Adress-Time-In-Pregroove</summary>
|
||||
CD_ATIP,
|
||||
/// <summary>CD-Text</summary>
|
||||
CD_TEXT,
|
||||
/// <summary>CD Media Catalogue Number</summary>
|
||||
CD_MCN,
|
||||
/// <summary>DVD Burst Cutting Area</summary>
|
||||
DVD_BCA,
|
||||
/// <summary>DVD Physical Format Information</summary>
|
||||
DVD_PFI,
|
||||
/// <summary>DVD Copyright Management Information</summary>
|
||||
DVD_CMI,
|
||||
/// <summary>DVD Disc Manufacturer Information</summary>
|
||||
DVD_DMI
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Feature is supported by image but not implemented yet.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class FeatureSupportedButNotImplementedImageException : Exception
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Feature is not supported by image.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class FeatureUnsupportedImageException : Exception
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Feature is supported by image but not present on it.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class FeatureNotPresentImageException : Exception
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Feature is supported by image but not by the disc it represents.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class FeaturedNotSupportedByDiscImageException : Exception
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Corrupt, incorrect or unhandled feature found on image
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ImageNotSupportedException : Exception
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
}
|
||||
}
|
||||
1127
DiscImageChef/ImagePlugins/TeleDisk.cs
Normal file
1127
DiscImageChef/ImagePlugins/TeleDisk.cs
Normal file
File diff suppressed because it is too large
Load Diff
618
DiscImageChef/ImagePlugins/ZZZRawImage.cs
Normal file
618
DiscImageChef/ImagePlugins/ZZZRawImage.cs
Normal file
@@ -0,0 +1,618 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ZZZRawImage.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Disc image plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Manages raw image, that is, user data sector by sector copy.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscImageChef.ImagePlugins
|
||||
{
|
||||
// Checked using several images and strings inside Apple's DiskImages.framework
|
||||
class ZZZRawImage : ImagePlugin
|
||||
{
|
||||
#region Internal variables
|
||||
|
||||
UInt64 imageSize;
|
||||
UInt64 sectors;
|
||||
UInt32 sectorSize;
|
||||
DateTime creationTime;
|
||||
DateTime modificationTime;
|
||||
string imageName;
|
||||
string rawImagePath;
|
||||
bool differentTrackZeroSize;
|
||||
#endregion
|
||||
|
||||
public ZZZRawImage(PluginBase Core)
|
||||
{
|
||||
Name = "Raw Disk Image";
|
||||
// Non-random UUID to recognize this specific plugin
|
||||
PluginUUID = new Guid("12345678-AAAA-BBBB-CCCC-123456789000");
|
||||
}
|
||||
|
||||
public override bool IdentifyImage(string imagePath)
|
||||
{
|
||||
FileInfo fi = new FileInfo(imagePath);
|
||||
|
||||
// Check if file is not multiple of 512
|
||||
if ((fi.Length % 512) != 0)
|
||||
{
|
||||
// Check known disk sizes with sectors smaller than 512
|
||||
switch (fi.Length)
|
||||
{
|
||||
case 81664:
|
||||
case 116480:
|
||||
case 242944:
|
||||
case 256256:
|
||||
case 287488:
|
||||
case 306432:
|
||||
case 495872:
|
||||
case 988416:
|
||||
case 995072:
|
||||
case 1021696:
|
||||
case 1146624:
|
||||
case 1177344:
|
||||
case 1222400:
|
||||
case 1304320:
|
||||
case 1255168:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OpenImage(string imagePath)
|
||||
{
|
||||
FileStream stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
FileInfo fi = new FileInfo(imagePath);
|
||||
string extension = Path.GetExtension(imagePath).ToLower();
|
||||
if (extension == ".iso" && (fi.Length % 2048) == 0)
|
||||
sectorSize = 2048;
|
||||
else
|
||||
{
|
||||
switch (fi.Length)
|
||||
{
|
||||
case 242944:
|
||||
case 256256:
|
||||
case 495872:
|
||||
case 92160:
|
||||
case 133120:
|
||||
sectorSize = 128;
|
||||
break;
|
||||
case 116480:
|
||||
case 287488: // T0S0 = 128bps
|
||||
case 988416: // T0S0 = 128bps
|
||||
case 995072: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1021696: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 232960:
|
||||
case 143360:
|
||||
case 286720:
|
||||
case 512512:
|
||||
case 102400:
|
||||
case 204800:
|
||||
case 163840:
|
||||
case 327680:
|
||||
case 655360:
|
||||
case 80384: // T0S0 = 128bps
|
||||
case 325632: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 653312: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectorSize = 256;
|
||||
break;
|
||||
case 81664:
|
||||
sectorSize = 319;
|
||||
break;
|
||||
case 306432: // T0S0 = 128bps
|
||||
case 1146624: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1177344: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectorSize = 512;
|
||||
break;
|
||||
case 1222400: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1304320: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1255168: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1261568:
|
||||
case 1310720:
|
||||
sectorSize = 1024;
|
||||
break;
|
||||
default:
|
||||
sectorSize = 512;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imageSize = (ulong)fi.Length;
|
||||
creationTime = fi.CreationTimeUtc;
|
||||
modificationTime = fi.LastWriteTimeUtc;
|
||||
imageName = Path.GetFileNameWithoutExtension(imagePath);
|
||||
differentTrackZeroSize = false;
|
||||
rawImagePath = imagePath;
|
||||
|
||||
switch (fi.Length)
|
||||
{
|
||||
case 242944:
|
||||
sectors = 1898;
|
||||
break;
|
||||
case 256256:
|
||||
sectors = 2002;
|
||||
break;
|
||||
case 495872:
|
||||
sectors = 3874;
|
||||
break;
|
||||
case 116480:
|
||||
sectors = 455;
|
||||
break;
|
||||
case 287488: // T0S0 = 128bps
|
||||
sectors = 1136;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 988416: // T0S0 = 128bps
|
||||
sectors = 3874;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 995072: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 3900;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 1021696: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 4004;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 81664:
|
||||
sectors = 256;
|
||||
break;
|
||||
case 306432: // T0S0 = 128bps
|
||||
sectors = 618;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 1146624: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 2272;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 1177344: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 2332;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 1222400: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 1236;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 1304320: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 1316;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 1255168: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 1268;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 80384: // T0S0 = 128bps
|
||||
sectors = 322;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 325632: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 1280;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 653312: // T0S0 = 128bps, T0S1 = 256bps
|
||||
sectors = 2560;
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
case 1880064: // IBM XDF, 3,5", real number of sectors
|
||||
sectors = 670;
|
||||
sectorSize = 8192; // Biggest sector size
|
||||
differentTrackZeroSize = true;
|
||||
break;
|
||||
default:
|
||||
sectors = imageSize / sectorSize;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ImageHasPartitions()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override UInt64 GetImageSize()
|
||||
{
|
||||
return imageSize;
|
||||
}
|
||||
|
||||
public override UInt64 GetSectors()
|
||||
{
|
||||
return sectors;
|
||||
}
|
||||
|
||||
public override UInt32 GetSectorSize()
|
||||
{
|
||||
return sectorSize;
|
||||
}
|
||||
|
||||
public override byte[] ReadSector(UInt64 sectorAddress)
|
||||
{
|
||||
return ReadSectors(sectorAddress, 1);
|
||||
}
|
||||
|
||||
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
|
||||
{
|
||||
if (differentTrackZeroSize)
|
||||
{
|
||||
throw new NotImplementedException("Not yet implemented");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sectorAddress > sectors - 1)
|
||||
throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
|
||||
|
||||
if (sectorAddress + length > sectors)
|
||||
throw new ArgumentOutOfRangeException("length", "Requested more sectors than available");
|
||||
|
||||
byte[] buffer = new byte[length * sectorSize];
|
||||
|
||||
FileStream stream = new FileStream(rawImagePath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
stream.Seek((long)(sectorAddress * sectorSize), SeekOrigin.Begin);
|
||||
|
||||
stream.Read(buffer, 0, (int)(length * sectorSize));
|
||||
|
||||
return buffer;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetImageFormat()
|
||||
{
|
||||
return "Raw disk image (sector by sector copy)";
|
||||
}
|
||||
|
||||
public override DateTime GetImageCreationTime()
|
||||
{
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public override DateTime GetImageLastModificationTime()
|
||||
{
|
||||
return modificationTime;
|
||||
}
|
||||
|
||||
public override string GetImageName()
|
||||
{
|
||||
return imageName;
|
||||
}
|
||||
|
||||
public override DiskType GetDiskType()
|
||||
{
|
||||
if (sectorSize == 2048)
|
||||
{
|
||||
if (sectors <= 360000)
|
||||
return DiskType.CD;
|
||||
if (sectors <= 2295104)
|
||||
return DiskType.DVDPR;
|
||||
if (sectors <= 2298496)
|
||||
return DiskType.DVDR;
|
||||
if (sectors <= 4171712)
|
||||
return DiskType.DVDRDL;
|
||||
if (sectors <= 4173824)
|
||||
return DiskType.DVDPRDL;
|
||||
if (sectors <= 24438784)
|
||||
return DiskType.BDR;
|
||||
if (sectors <= 62500864)
|
||||
return DiskType.BDRXL;
|
||||
return DiskType.Unknown;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (imageSize)
|
||||
{
|
||||
case 80384:
|
||||
return DiskType.ECMA_66;
|
||||
case 81664:
|
||||
return DiskType.IBM23FD;
|
||||
case 92160:
|
||||
return DiskType.ATARI_525_SD;
|
||||
case 102400:
|
||||
return DiskType.ACORN_525_SS_SD_40;
|
||||
case 116480:
|
||||
return DiskType.Apple32SS;
|
||||
case 133120:
|
||||
return DiskType.ATARI_525_ED;
|
||||
case 143360:
|
||||
return DiskType.Apple33SS;
|
||||
case 163840:
|
||||
return DiskType.DOS_525_SS_DD_8;
|
||||
case 184320:
|
||||
return DiskType.DOS_525_SS_DD_9;
|
||||
case 204800:
|
||||
return DiskType.ACORN_525_SS_SD_80;
|
||||
case 232960:
|
||||
return DiskType.Apple32DS;
|
||||
case 242944:
|
||||
return DiskType.IBM33FD_128;
|
||||
case 256256:
|
||||
return DiskType.ECMA_54;
|
||||
case 286720:
|
||||
return DiskType.Apple33DS;
|
||||
case 287488:
|
||||
return DiskType.IBM33FD_256;
|
||||
case 306432:
|
||||
return DiskType.IBM33FD_512;
|
||||
case 325632:
|
||||
return DiskType.ECMA_70;
|
||||
case 327680:
|
||||
return DiskType.DOS_525_DS_DD_8;
|
||||
case 368640:
|
||||
return DiskType.DOS_525_DS_DD_9;
|
||||
case 409600:
|
||||
return DiskType.AppleSonySS;
|
||||
case 495872:
|
||||
return DiskType.IBM43FD_128;
|
||||
case 512512:
|
||||
return DiskType.ECMA_59;
|
||||
case 653312:
|
||||
return DiskType.ECMA_78;
|
||||
case 655360:
|
||||
return DiskType.ACORN_525_DS_DD;
|
||||
case 737280:
|
||||
return DiskType.DOS_35_DS_DD_9;
|
||||
case 819200:
|
||||
return DiskType.AppleSonyDS;
|
||||
case 839680:
|
||||
return DiskType.FDFORMAT_35_DD;
|
||||
case 901120:
|
||||
return DiskType.CBM_AMIGA_35_DD;
|
||||
case 988416:
|
||||
return DiskType.IBM43FD_256;
|
||||
case 995072:
|
||||
return DiskType.IBM53FD_256;
|
||||
case 1021696:
|
||||
return DiskType.ECMA_99_26;
|
||||
case 1146624:
|
||||
return DiskType.IBM53FD_512;
|
||||
case 1177344:
|
||||
return DiskType.ECMA_99_15;
|
||||
case 1222400:
|
||||
return DiskType.IBM53FD_1024;
|
||||
case 1228800:
|
||||
return DiskType.DOS_525_HD;
|
||||
case 1255168:
|
||||
return DiskType.ECMA_69_8;
|
||||
case 1261568:
|
||||
return DiskType.NEC_8_DD;
|
||||
case 1304320:
|
||||
return DiskType.ECMA_99_8;
|
||||
case 1310720:
|
||||
return DiskType.NEC_525_HD;
|
||||
case 1427456:
|
||||
return DiskType.FDFORMAT_525_HD;
|
||||
case 1474560:
|
||||
return DiskType.DOS_35_HD;
|
||||
case 1720320:
|
||||
return DiskType.DMF;
|
||||
case 1763328:
|
||||
return DiskType.FDFORMAT_35_HD;
|
||||
case 1802240:
|
||||
return DiskType.CBM_AMIGA_35_HD;
|
||||
case 1880064:
|
||||
return DiskType.XDF_35;
|
||||
case 1884160:
|
||||
return DiskType.XDF_35;
|
||||
case 2949120:
|
||||
return DiskType.DOS_35_ED;
|
||||
case 128000000:
|
||||
return DiskType.ECMA_154;
|
||||
case 229632000:
|
||||
return DiskType.ECMA_201;
|
||||
case 481520640:
|
||||
return DiskType.ECMA_183_512;
|
||||
case 533403648:
|
||||
return DiskType.ECMA_183_1024;
|
||||
case 596787200:
|
||||
return DiskType.ECMA_184_512;
|
||||
case 654540800:
|
||||
return DiskType.ECMA_184_1024;
|
||||
default:
|
||||
return DiskType.GENERIC_HDD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Unsupported features
|
||||
|
||||
public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorLong(UInt64 sectorAddress)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetImageVersion()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetImageApplication()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetImageApplicationVersion()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadDiskTag(DiskTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetImageCreator()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetImageComments()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskManufacturer()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskModel()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskSerialNumber()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskBarcode()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDiskPartNumber()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override int GetDiskSequence()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override int GetLastDiskSequence()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDriveManufacturer()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDriveModel()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override string GetDriveSerialNumber()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<PartPlugins.Partition> GetPartitions()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Track> GetTracks()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Track> GetSessionTracks(Session session)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Track> GetSessionTracks(UInt16 session)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override List<Session> GetSessions()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
#endregion Unsupported features
|
||||
}
|
||||
}
|
||||
|
||||
674
DiscImageChef/LICENSE
Normal file
674
DiscImageChef/LICENSE
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
350
DiscImageChef/Main.cs
Normal file
350
DiscImageChef/Main.cs
Normal file
@@ -0,0 +1,350 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : Main.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Main program loop.
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains the main program loop.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
using DiscImageChef.PartPlugins;
|
||||
using DiscImageChef.Plugins;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
class MainClass
|
||||
{
|
||||
static PluginBase plugins;
|
||||
public static bool chkPartitions;
|
||||
public static bool chkFilesystems;
|
||||
public static bool isDebug;
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
plugins = new PluginBase();
|
||||
|
||||
chkPartitions = true;
|
||||
chkFilesystems = true;
|
||||
// RELEASE
|
||||
isDebug = false;
|
||||
// DEBUG
|
||||
//isDebug = true;
|
||||
|
||||
Console.WriteLine("Filesystem Identifier and Checker");
|
||||
Console.WriteLine("Copyright (C) 2011-2014 Natalia Portillo");
|
||||
|
||||
// For debug
|
||||
if (isDebug)
|
||||
{
|
||||
plugins.RegisterAllPlugins();
|
||||
Runner("");
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Runner(args[args.Length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Runner(string filename)
|
||||
{
|
||||
List<string> id_plugins;
|
||||
Plugin _plugin;
|
||||
string information;
|
||||
bool checkraw = false;
|
||||
ImagePlugin _imageFormat;
|
||||
|
||||
try
|
||||
{
|
||||
_imageFormat = null;
|
||||
|
||||
// Check all but RAW plugin
|
||||
foreach (ImagePlugin _imageplugin in plugins.ImagePluginsList.Values)
|
||||
{
|
||||
if(_imageplugin.PluginUUID != new Guid("12345678-AAAA-BBBB-CCCC-123456789000"))
|
||||
{
|
||||
if (_imageplugin.IdentifyImage(filename))
|
||||
{
|
||||
_imageFormat = _imageplugin;
|
||||
Console.WriteLine("Image format identified by {0}.", _imageplugin.Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check only RAW plugin
|
||||
if (_imageFormat == null)
|
||||
{
|
||||
foreach (ImagePlugin _imageplugin in plugins.ImagePluginsList.Values)
|
||||
{
|
||||
if(_imageplugin.PluginUUID == new Guid("12345678-AAAA-BBBB-CCCC-123456789000"))
|
||||
{
|
||||
if (_imageplugin.IdentifyImage(filename))
|
||||
{
|
||||
_imageFormat = _imageplugin;
|
||||
Console.WriteLine("Image format identified by {0}.", _imageplugin.Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Still not recognized
|
||||
if (_imageFormat == null)
|
||||
{
|
||||
Console.WriteLine("Image format not identified, not proceeding.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_imageFormat.OpenImage(filename))
|
||||
{
|
||||
Console.WriteLine("Unable to open image format");
|
||||
Console.WriteLine("No error given");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG: Correctly opened image file.");
|
||||
Console.WriteLine("DEBUG: Image without headers is {0} bytes.", _imageFormat.GetImageSize());
|
||||
Console.WriteLine("DEBUG: Image has {0} sectors.", _imageFormat.GetSectors());
|
||||
Console.WriteLine("DEBUG: Image identifies disk type as {0}.", _imageFormat.GetDiskType());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Unable to open image format");
|
||||
Console.WriteLine("Error: {0}", ex.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
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(_imageFormat, out _partitions))
|
||||
{
|
||||
partition_scheme = _partplugin.Name;
|
||||
partitions = _partitions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_imageFormat.ImageHasPartitions())
|
||||
{
|
||||
partition_scheme = _imageFormat.GetImageFormat();
|
||||
partitions = _imageFormat.GetPartitions();
|
||||
}
|
||||
|
||||
if (partition_scheme == "")
|
||||
{
|
||||
if(MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG: No partitions found");
|
||||
if (!chkFilesystems)
|
||||
{
|
||||
Console.WriteLine("No partitions founds, not searching for filesystems");
|
||||
return;
|
||||
}
|
||||
checkraw = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Partition scheme identified as {0}", partition_scheme);
|
||||
Console.WriteLine("{0} partitions found.", partitions.Count);
|
||||
|
||||
for (int i = 0; i < partitions.Count; i++)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Partition {0}:", partitions[i].PartitionSequence);
|
||||
Console.WriteLine("Partition name: {0}", partitions[i].PartitionName);
|
||||
Console.WriteLine("Partition type: {0}", partitions[i].PartitionType);
|
||||
Console.WriteLine("Partition start: sector {0}, byte {1}", partitions[i].PartitionStartSector, partitions[i].PartitionStart);
|
||||
Console.WriteLine("Partition length: {0} sectors, {1} bytes", partitions[i].PartitionSectors, partitions[i].PartitionLength);
|
||||
Console.WriteLine("Partition description:");
|
||||
Console.WriteLine(partitions[i].PartitionDescription);
|
||||
|
||||
if (chkFilesystems)
|
||||
{
|
||||
Console.WriteLine("Identifying filesystem on partition");
|
||||
|
||||
Identify(_imageFormat, out id_plugins, partitions[i].PartitionStartSector);
|
||||
if (id_plugins.Count == 0)
|
||||
Console.WriteLine("Filesystem not identified");
|
||||
else if (id_plugins.Count > 1)
|
||||
{
|
||||
Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count));
|
||||
|
||||
foreach (string plugin_name in id_plugins)
|
||||
{
|
||||
if (plugins.PluginsList.TryGetValue(plugin_name, out _plugin))
|
||||
{
|
||||
Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(_imageFormat, partitions[i].PartitionStartSector, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin);
|
||||
Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(_imageFormat, partitions[i].PartitionStartSector, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checkraw)
|
||||
{
|
||||
Identify(_imageFormat, out id_plugins, 0);
|
||||
if (id_plugins.Count == 0)
|
||||
Console.WriteLine("Filesystem not identified");
|
||||
else if (id_plugins.Count > 1)
|
||||
{
|
||||
Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count));
|
||||
|
||||
foreach (string plugin_name in id_plugins)
|
||||
{
|
||||
if (plugins.PluginsList.TryGetValue(plugin_name, out _plugin))
|
||||
{
|
||||
Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(_imageFormat, 0, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin);
|
||||
Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(_imageFormat, 0, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(String.Format("Error reading file: {0}", ex.Message));
|
||||
if (isDebug)
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
static void Identify(ImagePlugin imagePlugin, out List<string> id_plugins, ulong partitionOffset)
|
||||
{
|
||||
id_plugins = new List<string>();
|
||||
|
||||
foreach (Plugin _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
if (_plugin.Identify(imagePlugin, partitionOffset))
|
||||
id_plugins.Add(_plugin.Name.ToLower());
|
||||
}
|
||||
}
|
||||
|
||||
static void Usage()
|
||||
{
|
||||
Console.WriteLine("Usage: filesystemidandchk [options] file");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(" --formats List all suported partition and filesystems");
|
||||
Console.WriteLine(" --debug Show debug information");
|
||||
Console.WriteLine(" --partitions Check only for partitions");
|
||||
Console.WriteLine(" --filesystems Check only for filesystems");
|
||||
Console.WriteLine(" --all Check for partitions and filesystems (default)");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
276
DiscImageChef/PartPlugins/AppleMap.cs
Normal file
276
DiscImageChef/PartPlugins/AppleMap.cs
Normal file
@@ -0,0 +1,276 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : AppleMap.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Partitioning scheme plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Manages Apple Partition Map.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information about structures learnt from Inside Macintosh
|
||||
// Constants from image testing
|
||||
namespace DiscImageChef.PartPlugins
|
||||
{
|
||||
class AppleMap : PartPlugin
|
||||
{
|
||||
// "ER"
|
||||
const UInt16 APM_MAGIC = 0x4552;
|
||||
// "PM"
|
||||
const UInt16 APM_ENTRY = 0x504D;
|
||||
// "TS", old entry magic
|
||||
const UInt16 APM_OLDENT = 0x5453;
|
||||
|
||||
public AppleMap(PluginBase Core)
|
||||
{
|
||||
Name = "Apple Partition Map";
|
||||
PluginUUID = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22");
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
byte[] APMB_sector = imagePlugin.ReadSector(0);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
for (ulong i = 0; i < apm_entries; i++) // For each partition
|
||||
{
|
||||
APMEntry = new AppleMapPartitionEntry();
|
||||
APMEntry_sector = imagePlugin.ReadSector(first_sector + i);
|
||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
||||
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();
|
||||
|
||||
_partition.PartitionSequence = i;
|
||||
_partition.PartitionType = APMEntry.type;
|
||||
_partition.PartitionName = APMEntry.name;
|
||||
_partition.PartitionStart = APMEntry.start * sector_size;
|
||||
_partition.PartitionLength = APMEntry.sectors * sector_size;
|
||||
_partition.PartitionStartSector = APMEntry.start;
|
||||
_partition.PartitionSectors = APMEntry.sectors;
|
||||
|
||||
sb.AppendLine("Partition flags:");
|
||||
if ((APMEntry.status & 0x01) == 0x01)
|
||||
sb.AppendLine("Partition is valid.");
|
||||
if ((APMEntry.status & 0x02) == 0x02)
|
||||
sb.AppendLine("Partition entry is not available.");
|
||||
if ((APMEntry.status & 0x04) == 0x04)
|
||||
sb.AppendLine("Partition is mounted.");
|
||||
if ((APMEntry.status & 0x08) == 0x08)
|
||||
sb.AppendLine("Partition is bootable.");
|
||||
if ((APMEntry.status & 0x10) == 0x10)
|
||||
sb.AppendLine("Partition is readable.");
|
||||
if ((APMEntry.status & 0x20) == 0x20)
|
||||
sb.AppendLine("Partition is writable.");
|
||||
if ((APMEntry.status & 0x40) == 0x40)
|
||||
sb.AppendLine("Partition's boot code is position independent.");
|
||||
|
||||
if ((APMEntry.status & 0x08) == 0x08)
|
||||
{
|
||||
sb.AppendFormat("First boot sector: {0}", APMEntry.first_boot_block).AppendLine();
|
||||
sb.AppendFormat("Boot is {0} bytes.", APMEntry.boot_size).AppendLine();
|
||||
sb.AppendFormat("Boot load address: 0x{0:X8}", APMEntry.load_address).AppendLine();
|
||||
sb.AppendFormat("Boot entry point: 0x{0:X8}", APMEntry.entry_point).AppendLine();
|
||||
sb.AppendFormat("Boot code checksum: 0x{0:X8}", APMEntry.checksum).AppendLine();
|
||||
sb.AppendFormat("Processor: {0}", APMEntry.processor).AppendLine();
|
||||
}
|
||||
|
||||
_partition.PartitionDescription = sb.ToString();
|
||||
|
||||
if ((APMEntry.status & 0x01) == 0x01)
|
||||
if (APMEntry.type != "Apple_partition_map")
|
||||
partitions.Add(_partition);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public struct AppleMapBootEntry
|
||||
{
|
||||
// Signature ("ER")
|
||||
public UInt16 signature;
|
||||
// Byter per sector
|
||||
public UInt16 sector_size;
|
||||
// Sectors of the disk
|
||||
public UInt32 sectors;
|
||||
// Reserved
|
||||
public UInt16 reserved1;
|
||||
// Reserved
|
||||
public UInt16 reserved2;
|
||||
// Reserved
|
||||
public UInt32 reserved3;
|
||||
// Number of entries of the driver descriptor
|
||||
public UInt16 driver_entries;
|
||||
// First sector of the driver
|
||||
public UInt32 first_driver_blk;
|
||||
// Size in 512bytes sectors of the driver
|
||||
public UInt16 driver_size;
|
||||
// Operating system (MacOS = 1)
|
||||
public UInt16 operating_system;
|
||||
}
|
||||
|
||||
public struct AppleMapPartitionEntry
|
||||
{
|
||||
// Signature ("PM" or "TS")
|
||||
public UInt16 signature;
|
||||
// Reserved
|
||||
public UInt16 reserved1;
|
||||
// Number of entries on the partition map, each one sector
|
||||
public UInt32 entries;
|
||||
// First sector of the partition
|
||||
public UInt32 start;
|
||||
// Number of sectos of the partition
|
||||
public UInt32 sectors;
|
||||
// Partition name, 32 bytes, null-padded
|
||||
public string name;
|
||||
// Partition type. 32 bytes, null-padded
|
||||
public string type;
|
||||
// First sector of the data area
|
||||
public UInt32 first_data_block;
|
||||
// Number of sectors of the data area
|
||||
public UInt32 data_sectors;
|
||||
// Partition status
|
||||
public UInt32 status;
|
||||
// First sector of the boot code
|
||||
public UInt32 first_boot_block;
|
||||
// Size in bytes of the boot code
|
||||
public UInt32 boot_size;
|
||||
// Load address of the boot code
|
||||
public UInt32 load_address;
|
||||
// Reserved
|
||||
public UInt32 reserved2;
|
||||
// Entry point of the boot code
|
||||
public UInt32 entry_point;
|
||||
// Reserved
|
||||
public UInt32 reserved3;
|
||||
// Boot code checksum
|
||||
public UInt32 checksum;
|
||||
// Processor type, 16 bytes, null-padded
|
||||
public string processor;
|
||||
}
|
||||
}
|
||||
}
|
||||
1240
DiscImageChef/PartPlugins/MBR.cs
Normal file
1240
DiscImageChef/PartPlugins/MBR.cs
Normal file
File diff suppressed because it is too large
Load Diff
202
DiscImageChef/PartPlugins/NeXT.cs
Normal file
202
DiscImageChef/PartPlugins/NeXT.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : NeXT.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Partitioning scheme plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Manages NeXTStep and OpenStep partitions.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information learnt from XNU source and testing against real disks
|
||||
namespace DiscImageChef.PartPlugins
|
||||
{
|
||||
class NeXTDisklabel : PartPlugin
|
||||
{
|
||||
const UInt32 NEXT_MAGIC1 = 0x4E655854;
|
||||
// "NeXT"
|
||||
const UInt32 NEXT_MAGIC2 = 0x646C5632;
|
||||
// "dlV2"
|
||||
const UInt32 NEXT_MAGIC3 = 0x646C5633;
|
||||
// "dlV3"
|
||||
const UInt16 disktabStart = 0xB4;
|
||||
// 180
|
||||
const UInt16 disktabEntrySize = 0x2C;
|
||||
// 44
|
||||
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;
|
||||
|
||||
UInt32 magic;
|
||||
UInt32 sector_size;
|
||||
UInt16 front_porch;
|
||||
|
||||
if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448)
|
||||
sector_size = 2048;
|
||||
else
|
||||
sector_size = imagePlugin.GetSectorSize();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
front_porch = BigEndianBitConverter.ToUInt16(entry_sector, 0x6A);
|
||||
|
||||
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 = (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 newfs has been already run
|
||||
sb.AppendLine("Filesystem should be formatted at start");
|
||||
if (entry.automount == 1)
|
||||
sb.AppendLine("Filesystem should be automatically mounted");
|
||||
|
||||
part.PartitionDescription = sb.ToString();
|
||||
|
||||
partitions.Add(part);
|
||||
}
|
||||
}
|
||||
|
||||
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"?
|
||||
}
|
||||
}
|
||||
}
|
||||
89
DiscImageChef/PartPlugins/PartPlugin.cs
Normal file
89
DiscImageChef/PartPlugins/PartPlugin.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : PartPlugin.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Partitioning scheme plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Defines functions to be used by partitioning scheme plugins and several constants.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscImageChef.PartPlugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class to implement partitioning schemes interpreting plugins.
|
||||
/// </summary>
|
||||
public abstract class PartPlugin
|
||||
{
|
||||
/// <summary>Plugin name.</summary>
|
||||
public string Name;
|
||||
/// <summary>Plugin UUID.</summary>
|
||||
public Guid PluginUUID;
|
||||
|
||||
protected PartPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interprets a partitioning scheme.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if partitioning scheme is recognized, <c>false</c> otherwise.</returns>
|
||||
/// <param name="imagePlugin">Disk image.</param>
|
||||
/// <param name="partitions">Returns list of partitions.</param>
|
||||
public abstract bool GetInformation(ImagePlugins.ImagePlugin imagePlugin, out List<Partition> partitions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Partition structure.
|
||||
/// </summary>
|
||||
public struct Partition
|
||||
{
|
||||
/// <summary>Partition number, 0-started</summary>
|
||||
public ulong PartitionSequence;
|
||||
/// <summary>Partition type</summary>
|
||||
public string PartitionType;
|
||||
/// <summary>Partition name (if the scheme supports it)</summary>
|
||||
public string PartitionName;
|
||||
/// <summary>Start of the partition, in bytes</summary>
|
||||
public ulong PartitionStart;
|
||||
/// <summary>LBA of partition start</summary>
|
||||
public ulong PartitionStartSector;
|
||||
/// <summary>Length in bytes of the partition</summary>
|
||||
public ulong PartitionLength;
|
||||
/// <summary>Length in sectors of the partition</summary>
|
||||
public ulong PartitionSectors;
|
||||
/// <summary>Information that does not find space in this struct</summary>
|
||||
public string PartitionDescription;
|
||||
}
|
||||
}
|
||||
118
DiscImageChef/Plugins.cs
Normal file
118
DiscImageChef/Plugins.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : Plugins.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Base methods for plugins.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
using DiscImageChef.PartPlugins;
|
||||
using DiscImageChef.Plugins;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
public class PluginBase
|
||||
{
|
||||
public Dictionary<string, Plugin> PluginsList;
|
||||
public Dictionary<string, PartPlugin> PartPluginsList;
|
||||
public Dictionary<string, ImagePlugin> ImagePluginsList;
|
||||
|
||||
public PluginBase()
|
||||
{
|
||||
PluginsList = new Dictionary<string, Plugin>();
|
||||
PartPluginsList = new Dictionary<string, PartPlugin>();
|
||||
ImagePluginsList = new Dictionary<string, ImagePlugin>();
|
||||
}
|
||||
|
||||
public void RegisterAllPlugins()
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (type.IsSubclassOf(typeof(ImagePlugin)))
|
||||
{
|
||||
ImagePlugin plugin = (ImagePlugin)type.GetConstructor(new [] { typeof(PluginBase) }).Invoke(new object[] { this });
|
||||
RegisterImagePlugin(plugin);
|
||||
}
|
||||
if (type.IsSubclassOf(typeof(Plugin)))
|
||||
{
|
||||
Plugin plugin = (Plugin)type.GetConstructor(new [] { typeof(PluginBase) }).Invoke(new object[] { this });
|
||||
RegisterPlugin(plugin);
|
||||
}
|
||||
else if (type.IsSubclassOf(typeof(PartPlugin)))
|
||||
{
|
||||
PartPlugin partplugin = (PartPlugin)type.GetConstructor(new [] { typeof(PluginBase) }).Invoke(new object[] { this });
|
||||
RegisterPartPlugin(partplugin);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterImagePlugin(ImagePlugin plugin)
|
||||
{
|
||||
if (!ImagePluginsList.ContainsKey(plugin.Name.ToLower()))
|
||||
{
|
||||
ImagePluginsList.Add(plugin.Name.ToLower(), plugin);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterPlugin(Plugin plugin)
|
||||
{
|
||||
if (!PluginsList.ContainsKey(plugin.Name.ToLower()))
|
||||
{
|
||||
PluginsList.Add(plugin.Name.ToLower(), plugin);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterPartPlugin(PartPlugin partplugin)
|
||||
{
|
||||
if (!PartPluginsList.ContainsKey(partplugin.Name.ToLower()))
|
||||
{
|
||||
PartPluginsList.Add(partplugin.Name.ToLower(), partplugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
415
DiscImageChef/Plugins/AppleHFS.cs
Normal file
415
DiscImageChef/Plugins/AppleHFS.cs
Normal file
@@ -0,0 +1,415 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : AppleHFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies HFS filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
// https://developer.apple.com/legacy/library/documentation/mac/pdf/Files/File_Manager.pdf
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class AppleHFS : Plugin
|
||||
{
|
||||
const UInt16 HFS_MAGIC = 0x4244;
|
||||
// "BD"
|
||||
const UInt16 HFSP_MAGIC = 0x482B;
|
||||
// "H+"
|
||||
const UInt16 HFSBB_MAGIC = 0x4C4B;
|
||||
// "LK"
|
||||
public AppleHFS(PluginBase Core)
|
||||
{
|
||||
Name = "Apple Hierarchical File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
UInt16 drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
if (drSigWord == HFS_MAGIC)
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||
|
||||
return drSigWord != HFSP_MAGIC;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
HFS_MasterDirectoryBlock MDB = new HFS_MasterDirectoryBlock();
|
||||
HFS_BootBlock BB = new HFS_BootBlock();
|
||||
|
||||
byte[] pString;
|
||||
|
||||
byte[] bb_sector = imagePlugin.ReadSector(2 + partitionOffset); // BB's first sector
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); // MDB sector
|
||||
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
||||
if (MDB.drSigWord != HFS_MAGIC)
|
||||
return;
|
||||
|
||||
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 = 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 = 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.drXTFlSize = BigEndianBitConverter.ToUInt32(mdb_sector, 0x082);
|
||||
MDB.drCTFlSize = BigEndianBitConverter.ToUInt32(mdb_sector, 0x092);
|
||||
|
||||
BB.signature = BigEndianBitConverter.ToUInt16(bb_sector, 0x000);
|
||||
|
||||
if (BB.signature == HFSBB_MAGIC)
|
||||
{
|
||||
BB.branch = BigEndianBitConverter.ToUInt32(bb_sector, 0x002);
|
||||
BB.boot_flags = bb_sector[0x006];
|
||||
BB.boot_version = bb_sector[0x007];
|
||||
|
||||
BB.sec_sv_pages = BigEndianBitConverter.ToInt16(bb_sector, 0x008);
|
||||
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x00A, pString, 0, 16);
|
||||
BB.system_name = StringHandlers.PascalToString(pString);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x01A, pString, 0, 16);
|
||||
BB.finder_name = StringHandlers.PascalToString(pString);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x02A, pString, 0, 16);
|
||||
BB.debug_name = StringHandlers.PascalToString(pString);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x03A, pString, 0, 16);
|
||||
BB.disasm_name = StringHandlers.PascalToString(pString);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x04A, pString, 0, 16);
|
||||
BB.stupscr_name = StringHandlers.PascalToString(pString);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x05A, pString, 0, 16);
|
||||
BB.bootup_name = StringHandlers.PascalToString(pString);
|
||||
pString = new byte[16];
|
||||
Array.Copy(bb_sector, 0x06A, pString, 0, 16);
|
||||
BB.clipbrd_name = StringHandlers.PascalToString(pString);
|
||||
|
||||
BB.max_files = BigEndianBitConverter.ToUInt16(bb_sector, 0x07A);
|
||||
BB.queue_size = BigEndianBitConverter.ToUInt16(bb_sector, 0x07C);
|
||||
BB.heap_128k = BigEndianBitConverter.ToUInt32(bb_sector, 0x07E);
|
||||
BB.heap_256k = BigEndianBitConverter.ToUInt32(bb_sector, 0x082);
|
||||
BB.heap_512k = BigEndianBitConverter.ToUInt32(bb_sector, 0x086);
|
||||
}
|
||||
else
|
||||
BB.signature = 0x0000;
|
||||
|
||||
sb.AppendLine("Apple Hierarchical File System");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Master Directory Block:");
|
||||
sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine();
|
||||
sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(MDB.drLsMod)).AppendLine();
|
||||
sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(MDB.drVolBkUp)).AppendLine();
|
||||
sb.AppendFormat("Backup sequence number: {0}", MDB.drVSeqNum).AppendLine();
|
||||
|
||||
if ((MDB.drAtrb & 0x80) == 0x80)
|
||||
sb.AppendLine("Volume is locked by hardware.");
|
||||
if ((MDB.drAtrb & 0x100) == 0x100)
|
||||
sb.AppendLine("Volume was unmonted.");
|
||||
else
|
||||
sb.AppendLine("Volume is mounted.");
|
||||
if ((MDB.drAtrb & 0x200) == 0x200)
|
||||
sb.AppendLine("Volume has spared bad blocks.");
|
||||
if ((MDB.drAtrb & 0x400) == 0x400)
|
||||
sb.AppendLine("Volume does not need cache.");
|
||||
if ((MDB.drAtrb & 0x800) == 0x800)
|
||||
sb.AppendLine("Boot volume is inconsistent.");
|
||||
if ((MDB.drAtrb & 0x1000) == 0x1000)
|
||||
sb.AppendLine("There are reused CNIDs.");
|
||||
if ((MDB.drAtrb & 0x2000) == 0x2000)
|
||||
sb.AppendLine("Volume is journaled.");
|
||||
if ((MDB.drAtrb & 0x4000) == 0x4000)
|
||||
sb.AppendLine("Volume is seriously inconsistent.");
|
||||
if ((MDB.drAtrb & 0x8000) == 0x8000)
|
||||
sb.AppendLine("Volume is locked by software.");
|
||||
|
||||
sb.AppendFormat("{0} files on root directory", MDB.drNmFls).AppendLine();
|
||||
sb.AppendFormat("{0} directories on root directory", MDB.drNmRtDirs).AppendLine();
|
||||
sb.AppendFormat("{0} files on volume", MDB.drFilCnt).AppendLine();
|
||||
sb.AppendFormat("{0} directories on volume", MDB.drDirCnt).AppendLine();
|
||||
sb.AppendFormat("Volume write count: {0}", MDB.drWrCnt).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume bitmap starting sector (in 512-bytes): {0}", MDB.drVBMSt).AppendLine();
|
||||
sb.AppendFormat("Next allocation block: {0}.", MDB.drAllocPtr).AppendLine();
|
||||
sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per allocation block.", MDB.drAlBlkSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate when extending a file.", MDB.drClpSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate when extending a Extents B-Tree.", MDB.drXTClpSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate when extending a Catalog B-Tree.", MDB.drCTClpSiz).AppendLine();
|
||||
sb.AppendFormat("Sector of first allocation block: {0}", MDB.drAlBlSt).AppendLine();
|
||||
sb.AppendFormat("Next unused CNID: {0}", MDB.drNxtCNID).AppendLine();
|
||||
sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} bytes in the Extents B-Tree", MDB.drXTFlSize).AppendLine();
|
||||
sb.AppendFormat("{0} bytes in the Catalog B-Tree", MDB.drCTFlSize).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume name: {0}", MDB.drVN).AppendLine();
|
||||
|
||||
sb.AppendLine("Finder info:");
|
||||
sb.AppendFormat("CNID of bootable system's directory: {0}", MDB.drFndrInfo0).AppendLine();
|
||||
sb.AppendFormat("CNID of first-run application's directory: {0}", MDB.drFndrInfo1).AppendLine();
|
||||
sb.AppendFormat("CNID of previously opened directory: {0}", MDB.drFndrInfo2).AppendLine();
|
||||
sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", MDB.drFndrInfo3).AppendLine();
|
||||
sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", MDB.drFndrInfo5).AppendLine();
|
||||
sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", MDB.drFndrInfo6, MDB.drFndrInfo7).AppendLine();
|
||||
|
||||
if (MDB.drEmbedSigWord == HFSP_MAGIC)
|
||||
{
|
||||
sb.AppendLine("Volume wraps a HFS+ volume.");
|
||||
sb.AppendFormat("Starting block of the HFS+ volume: {0}", MDB.xdrStABNt).AppendLine();
|
||||
sb.AppendFormat("Allocations blocks of the HFS+ volume: {0}", MDB.xdrNumABlks).AppendLine();
|
||||
}
|
||||
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)
|
||||
{
|
||||
sb.AppendLine("Volume is bootable.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Boot Block:");
|
||||
if ((BB.boot_flags & 0x40) == 0x40)
|
||||
sb.AppendLine("Boot block should be executed.");
|
||||
if ((BB.boot_flags & 0x80) == 0x80)
|
||||
{
|
||||
sb.AppendLine("Boot block is in new unknown format.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BB.sec_sv_pages > 0)
|
||||
sb.AppendLine("Allocate secondary sound buffer at boot.");
|
||||
else if (BB.sec_sv_pages < 0)
|
||||
sb.AppendLine("Allocate secondary sound and video buffers at boot.");
|
||||
|
||||
sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine();
|
||||
sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine();
|
||||
sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine();
|
||||
sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine();
|
||||
sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine();
|
||||
sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine();
|
||||
sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine();
|
||||
sb.AppendFormat("Maximum opened files: {0}", BB.max_files * 4).AppendLine();
|
||||
sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine();
|
||||
sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
sb.AppendLine("Volume is not bootable.");
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct HFS_MasterDirectoryBlock // Should be sector 2 in volume
|
||||
{
|
||||
public UInt16 drSigWord;
|
||||
// 0x000, Signature, 0x4244
|
||||
public UInt32 drCrDate;
|
||||
// 0x002, Volume creation date
|
||||
public UInt32 drLsMod;
|
||||
// 0x006, Volume last modification date
|
||||
public UInt16 drAtrb;
|
||||
// 0x00A, Volume attributes
|
||||
public UInt16 drNmFls;
|
||||
// 0x00C, Files in root directory
|
||||
public UInt16 drVBMSt;
|
||||
// 0x00E, Start 512-byte sector of volume bitmap
|
||||
public UInt16 drAllocPtr;
|
||||
// 0x010, Allocation block to begin next allocation
|
||||
public UInt16 drNmAlBlks;
|
||||
// 0x012, Allocation blocks
|
||||
public UInt32 drAlBlkSiz;
|
||||
// 0x014, Bytes per allocation block
|
||||
public UInt32 drClpSiz;
|
||||
// 0x018, Bytes to allocate when extending a file
|
||||
public UInt16 drAlBlSt;
|
||||
// 0x01C, Start 512-byte sector of first allocation block
|
||||
public UInt32 drNxtCNID;
|
||||
// 0x01E, CNID for next file
|
||||
public UInt16 drFreeBks;
|
||||
// 0x022, Free allocation blocks
|
||||
public string drVN;
|
||||
// 0x024, Volume name (28 bytes)
|
||||
public UInt32 drVolBkUp;
|
||||
// 0x040, Volume last backup time
|
||||
public UInt16 drVSeqNum;
|
||||
// 0x044, Volume backup sequence number
|
||||
public UInt32 drWrCnt;
|
||||
// 0x046, Filesystem write count
|
||||
public UInt32 drXTClpSiz;
|
||||
// 0x04A, Bytes to allocate when extending the extents B-Tree
|
||||
public UInt32 drCTClpSiz;
|
||||
// 0x04E, Bytes to allocate when extending the catalog B-Tree
|
||||
public UInt16 drNmRtDirs;
|
||||
// 0x052, Number of directories in root directory
|
||||
public UInt32 drFilCnt;
|
||||
// 0x054, Number of files in the volume
|
||||
public UInt32 drDirCnt;
|
||||
// 0x058, Number of directories in the volume
|
||||
public UInt32 drFndrInfo0;
|
||||
// 0x05C, finderInfo[0], CNID for bootable system's directory
|
||||
public UInt32 drFndrInfo1;
|
||||
// 0x060, finderInfo[1], CNID of the directory containing the boot application
|
||||
public UInt32 drFndrInfo2;
|
||||
// 0x064, finderInfo[2], CNID of the directory that should be opened on boot
|
||||
public UInt32 drFndrInfo3;
|
||||
// 0x068, finderInfo[3], CNID for Mac OS 8 or 9 directory
|
||||
public UInt32 drFndrInfo4;
|
||||
// 0x06C, finderInfo[4], Reserved
|
||||
public UInt32 drFndrInfo5;
|
||||
// 0x070, finderInfo[5], CNID for Mac OS X directory
|
||||
public UInt32 drFndrInfo6;
|
||||
// 0x074, finderInfo[6], first part of Mac OS X volume ID
|
||||
public UInt32 drFndrInfo7;
|
||||
// 0x078, finderInfo[7], second part of Mac OS X volume ID
|
||||
// If wrapping HFS+
|
||||
public UInt16 drEmbedSigWord;
|
||||
// 0x07C, Embedded volume signature, "H+" if HFS+ is embedded ignore following two fields if not
|
||||
public UInt16 xdrStABNt;
|
||||
// 0x07E, Starting block number of embedded HFS+ volume
|
||||
public UInt16 xdrNumABlks;
|
||||
// 0x080, Allocation blocks used by embedded volume
|
||||
// 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;
|
||||
// 0x092, Bytes in the catalog B-Tree
|
||||
// 3 HFS extents following, 32 bits each
|
||||
}
|
||||
|
||||
struct HFS_BootBlock // Should be sectors 0 and 1 in volume
|
||||
{
|
||||
public UInt16 signature;
|
||||
// 0x000, Signature, 0x4C4B if bootable
|
||||
public UInt32 branch;
|
||||
// 0x002, Branch
|
||||
public byte boot_flags;
|
||||
// 0x006, Boot block flags
|
||||
public byte boot_version;
|
||||
// 0x007, Boot block version
|
||||
public Int16 sec_sv_pages;
|
||||
// 0x008, Allocate secondary buffers
|
||||
public string system_name;
|
||||
// 0x00A, System file name (16 bytes)
|
||||
public string finder_name;
|
||||
// 0x01A, Finder file name (16 bytes)
|
||||
public string debug_name;
|
||||
// 0x02A, Debugger file name (16 bytes)
|
||||
public string disasm_name;
|
||||
// 0x03A, Disassembler file name (16 bytes)
|
||||
public string stupscr_name;
|
||||
// 0x04A, Startup screen file name (16 bytes)
|
||||
public string bootup_name;
|
||||
// 0x05A, First program to execute on boot (16 bytes)
|
||||
public string clipbrd_name;
|
||||
// 0x06A, Clipboard file name (16 bytes)
|
||||
public UInt16 max_files;
|
||||
// 0x07A, 1/4 of maximum opened at a time files
|
||||
public UInt16 queue_size;
|
||||
// 0x07C, Event queue size
|
||||
public UInt32 heap_128k;
|
||||
// 0x07E, Heap size on a Mac with 128KiB of RAM
|
||||
public UInt32 heap_256k;
|
||||
// 0x082, Heap size on a Mac with 256KiB of RAM
|
||||
public UInt32 heap_512k;
|
||||
// 0x086, Heap size on a Mac with 512KiB of RAM or more
|
||||
}
|
||||
// Follows boot code
|
||||
}
|
||||
}
|
||||
529
DiscImageChef/Plugins/AppleHFSPlus.cs
Normal file
529
DiscImageChef/Plugins/AppleHFSPlus.cs
Normal file
@@ -0,0 +1,529 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : AppleHFSPlus.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies HFS+/HFSX filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from Apple TechNote 1150: https://developer.apple.com/legacy/library/technotes/tn/tn1150.html
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class AppleHFSPlus : Plugin
|
||||
{
|
||||
const UInt16 HFS_MAGIC = 0x4244;
|
||||
// "BD"
|
||||
const UInt16 HFSP_MAGIC = 0x482B;
|
||||
// "H+"
|
||||
const UInt16 HFSX_MAGIC = 0x4858;
|
||||
// "HX"
|
||||
public AppleHFSPlus(PluginBase Core)
|
||||
{
|
||||
Name = "Apple HFS+ filesystem";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt16 drSigWord;
|
||||
UInt16 xdrStABNt;
|
||||
UInt16 drAlBlSt;
|
||||
UInt32 drAlBlkSiz;
|
||||
|
||||
byte[] vh_sector;
|
||||
ulong hfsp_offset;
|
||||
|
||||
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"
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x07C); // Read embedded HFS+ signature
|
||||
|
||||
if (drSigWord == HFSP_MAGIC) // "H+"
|
||||
{
|
||||
xdrStABNt = BigEndianBitConverter.ToUInt16(vh_sector, 0x07E); // Starting block number of embedded HFS+ volume
|
||||
|
||||
drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x014); // Block size
|
||||
|
||||
drAlBlSt = BigEndianBitConverter.ToUInt16(vh_sector, 0x01C); // Start of allocated blocks (in 512-byte/block)
|
||||
|
||||
hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512)) * (imagePlugin.GetSectorSize() / 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
hfsp_offset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hfsp_offset = 0;
|
||||
}
|
||||
|
||||
vh_sector = imagePlugin.ReadSector(2 + partitionOffset + hfsp_offset); // Read volume header
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0);
|
||||
if (drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
UInt16 drSigWord;
|
||||
UInt16 xdrStABNt;
|
||||
UInt16 drAlBlSt;
|
||||
UInt32 drAlBlkSiz;
|
||||
HFSPlusVolumeHeader HPVH = new HFSPlusVolumeHeader();
|
||||
|
||||
ulong hfsp_offset;
|
||||
bool wrapped;
|
||||
byte[] vh_sector;
|
||||
|
||||
vh_sector = imagePlugin.ReadSector(2 + partitionOffset); // Read volume header, of HFS Wrapper MDB
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0); // Check for HFS Wrapper MDB
|
||||
|
||||
if (drSigWord == HFS_MAGIC) // "BD"
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x07C); // Read embedded HFS+ signature
|
||||
|
||||
if (drSigWord == HFSP_MAGIC) // "H+"
|
||||
{
|
||||
xdrStABNt = BigEndianBitConverter.ToUInt16(vh_sector, 0x07E); // Starting block number of embedded HFS+ volume
|
||||
|
||||
drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x014); // Block size
|
||||
|
||||
drAlBlSt = BigEndianBitConverter.ToUInt16(vh_sector, 0x01C); // Start of allocated blocks (in 512-byte/block)
|
||||
|
||||
hfsp_offset = (drAlBlSt + xdrStABNt * (drAlBlkSiz / 512)) * (imagePlugin.GetSectorSize() / 512);
|
||||
wrapped = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hfsp_offset = 0;
|
||||
wrapped = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hfsp_offset = 0;
|
||||
wrapped = false;
|
||||
}
|
||||
|
||||
vh_sector = imagePlugin.ReadSector(2 + partitionOffset + hfsp_offset); // Read volume header
|
||||
|
||||
HPVH.signature = BigEndianBitConverter.ToUInt16(vh_sector, 0x000);
|
||||
if (HPVH.signature == HFSP_MAGIC || HPVH.signature == HFSX_MAGIC)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (HPVH.signature == 0x482B)
|
||||
sb.AppendLine("HFS+ filesystem.");
|
||||
if (HPVH.signature == 0x4858)
|
||||
sb.AppendLine("HFSX filesystem.");
|
||||
if (wrapped)
|
||||
sb.AppendLine("Volume is wrapped inside an HFS volume.");
|
||||
|
||||
HPVH.version = BigEndianBitConverter.ToUInt16(vh_sector, 0x002);
|
||||
|
||||
if (HPVH.version == 4 || HPVH.version == 5)
|
||||
{
|
||||
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 = BigEndianBitConverter.ToUInt32(vh_sector, 0x00C);
|
||||
|
||||
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 = BigEndianBitConverter.ToUInt32(vh_sector, 0x030);
|
||||
HPVH.folderCount = BigEndianBitConverter.ToUInt32(vh_sector, 0x034);
|
||||
|
||||
HPVH.blockSize = BigEndianBitConverter.ToUInt32(vh_sector, 0x038);
|
||||
HPVH.totalBlocks = BigEndianBitConverter.ToUInt32(vh_sector, 0x03C);
|
||||
HPVH.freeBlocks = BigEndianBitConverter.ToUInt32(vh_sector, 0x040);
|
||||
|
||||
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 = BigEndianBitConverter.ToUInt32(vh_sector, 0x054);
|
||||
|
||||
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 = 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();
|
||||
|
||||
if ((HPVH.attributes & 0x80) == 0x80)
|
||||
sb.AppendLine("Volume is locked on hardware.");
|
||||
if ((HPVH.attributes & 0x100) == 0x100)
|
||||
sb.AppendLine("Volume is unmounted.");
|
||||
if ((HPVH.attributes & 0x200) == 0x200)
|
||||
sb.AppendLine("There are bad blocks in the extents file.");
|
||||
if ((HPVH.attributes & 0x400) == 0x400)
|
||||
sb.AppendLine("Volume does not require cache.");
|
||||
if ((HPVH.attributes & 0x800) == 0x800)
|
||||
sb.AppendLine("Volume state is inconsistent.");
|
||||
if ((HPVH.attributes & 0x1000) == 0x1000)
|
||||
sb.AppendLine("CNIDs are reused.");
|
||||
if ((HPVH.attributes & 0x2000) == 0x2000)
|
||||
sb.AppendLine("Volume is journaled.");
|
||||
if ((HPVH.attributes & 0x8000) == 0x8000)
|
||||
sb.AppendLine("Volume is locked on software.");
|
||||
|
||||
sb.AppendFormat("Implementation that last mounted the volume: \"{0}\".", HPVH.lastMountedVersion).AppendLine();
|
||||
if ((HPVH.attributes & 0x2000) == 0x2000)
|
||||
sb.AppendFormat("Journal starts at allocation block {0}.", HPVH.journalInfoBlock).AppendLine();
|
||||
sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(HPVH.createDate)).AppendLine();
|
||||
sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(HPVH.modifyDate)).AppendLine();
|
||||
sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(HPVH.backupDate)).AppendLine();
|
||||
sb.AppendFormat("Last check date: {0}", DateHandlers.MacToDateTime(HPVH.checkedDate)).AppendLine();
|
||||
sb.AppendFormat("{0} files on volume.", HPVH.fileCount).AppendLine();
|
||||
sb.AppendFormat("{0} folders on volume.", HPVH.folderCount).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per allocation block.", HPVH.blockSize).AppendLine();
|
||||
sb.AppendFormat("{0} allocation blocks.", HPVH.totalBlocks).AppendLine();
|
||||
sb.AppendFormat("{0} free blocks.", HPVH.freeBlocks).AppendLine();
|
||||
sb.AppendFormat("Next allocation block: {0}.", HPVH.nextAllocation).AppendLine();
|
||||
sb.AppendFormat("Resource fork clump size: {0} bytes.", HPVH.rsrcClumpSize).AppendLine();
|
||||
sb.AppendFormat("Data fork clump size: {0} bytes.", HPVH.dataClumpSize).AppendLine();
|
||||
sb.AppendFormat("Next unused CNID: {0}.", HPVH.nextCatalogID).AppendLine();
|
||||
sb.AppendFormat("Volume has been mounted writable {0} times.", HPVH.writeCount).AppendLine();
|
||||
sb.AppendFormat("Allocation File is {0} bytes.", HPVH.allocationFile_logicalSize).AppendLine();
|
||||
sb.AppendFormat("Extents File is {0} bytes.", HPVH.extentsFile_logicalSize).AppendLine();
|
||||
sb.AppendFormat("Catalog File is {0} bytes.", HPVH.catalogFile_logicalSize).AppendLine();
|
||||
sb.AppendFormat("Attributes File is {0} bytes.", HPVH.attributesFile_logicalSize).AppendLine();
|
||||
sb.AppendFormat("Startup File is {0} bytes.", HPVH.startupFile_logicalSize).AppendLine();
|
||||
sb.AppendLine("Finder info:");
|
||||
sb.AppendFormat("CNID of bootable system's directory: {0}", HPVH.drFndrInfo0).AppendLine();
|
||||
sb.AppendFormat("CNID of first-run application's directory: {0}", HPVH.drFndrInfo1).AppendLine();
|
||||
sb.AppendFormat("CNID of previously opened directory: {0}", HPVH.drFndrInfo2).AppendLine();
|
||||
sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", HPVH.drFndrInfo3).AppendLine();
|
||||
sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", HPVH.drFndrInfo5).AppendLine();
|
||||
sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendFormat("Filesystem version is {0}.", HPVH.version).AppendLine();
|
||||
sb.AppendLine("This version is not supported yet.");
|
||||
}
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
// Size = 532 bytes
|
||||
struct HFSPlusVolumeHeader // Should be offset 0x0400 bytes in volume
|
||||
{
|
||||
public UInt16 signature;
|
||||
// 0x000, "H+" for HFS+, "HX" for HFSX
|
||||
public UInt16 version;
|
||||
// 0x002, 4 for HFS+, 5 for HFSX
|
||||
public UInt32 attributes;
|
||||
// 0x004, Volume attributes
|
||||
public string lastMountedVersion;
|
||||
// 0x008, Implementation that last mounted the volume.
|
||||
// Reserved by Apple:
|
||||
// "8.10" Mac OS 8.1 to 9.2.2
|
||||
// "10.0" Mac OS X
|
||||
// "HFSJ" Journaled implementation
|
||||
// "fsck" /sbin/fsck
|
||||
public UInt32 journalInfoBlock;
|
||||
// 0x00C, Allocation block number containing the journal
|
||||
public ulong createDate;
|
||||
// 0x010, Date of volume creation
|
||||
public ulong modifyDate;
|
||||
// 0x018, Date of last volume modification
|
||||
public ulong backupDate;
|
||||
// 0x020, Date of last backup
|
||||
public ulong checkedDate;
|
||||
// 0x028, Date of last consistency check
|
||||
public UInt32 fileCount;
|
||||
// 0x030, File on the volume
|
||||
public UInt32 folderCount;
|
||||
// 0x034, Folders on the volume
|
||||
public UInt32 blockSize;
|
||||
// 0x038, Bytes per allocation block
|
||||
public UInt32 totalBlocks;
|
||||
// 0x03C, Allocation blocks on the volume
|
||||
public UInt32 freeBlocks;
|
||||
// 0x040, Free allocation blocks
|
||||
public UInt32 nextAllocation;
|
||||
// 0x044, Hint for next allocation block
|
||||
public UInt32 rsrcClumpSize;
|
||||
// 0x048, Resource fork clump size
|
||||
public UInt32 dataClumpSize;
|
||||
// 0x04C, Data fork clump size
|
||||
public UInt32 nextCatalogID;
|
||||
// 0x050, Next unused CNID
|
||||
public UInt32 writeCount;
|
||||
// 0x054, Times that the volume has been mounted writable
|
||||
public UInt64 encodingsBitmap;
|
||||
// 0x058, Used text encoding hints
|
||||
public UInt32 drFndrInfo0;
|
||||
// 0x060, finderInfo[0], CNID for bootable system's directory
|
||||
public UInt32 drFndrInfo1;
|
||||
// 0x064, finderInfo[1], CNID of the directory containing the boot application
|
||||
public UInt32 drFndrInfo2;
|
||||
// 0x068, finderInfo[2], CNID of the directory that should be opened on boot
|
||||
public UInt32 drFndrInfo3;
|
||||
// 0x06C, finderInfo[3], CNID for Mac OS 8 or 9 directory
|
||||
public UInt32 drFndrInfo4;
|
||||
// 0x070, finderInfo[4], Reserved
|
||||
public UInt32 drFndrInfo5;
|
||||
// 0x074, finderInfo[5], CNID for Mac OS X directory
|
||||
public UInt32 drFndrInfo6;
|
||||
// 0x078, finderInfo[6], first part of Mac OS X volume ID
|
||||
public UInt32 drFndrInfo7;
|
||||
// 0x07C, finderInfo[7], second part of Mac OS X volume ID
|
||||
// HFSPlusForkData allocationFile;
|
||||
public UInt64 allocationFile_logicalSize;
|
||||
// 0x080
|
||||
public UInt32 allocationFile_clumpSize;
|
||||
// 0x088
|
||||
public UInt32 allocationFile_totalBlocks;
|
||||
// 0x08C
|
||||
public UInt32 allocationFile_extents_startBlock0;
|
||||
// 0x090
|
||||
public UInt32 allocationFile_extents_blockCount0;
|
||||
// 0x094
|
||||
public UInt32 allocationFile_extents_startBlock1;
|
||||
// 0x098
|
||||
public UInt32 allocationFile_extents_blockCount1;
|
||||
// 0x09C
|
||||
public UInt32 allocationFile_extents_startBlock2;
|
||||
// 0x0A0
|
||||
public UInt32 allocationFile_extents_blockCount2;
|
||||
// 0x0A4
|
||||
public UInt32 allocationFile_extents_startBlock3;
|
||||
// 0x0A8
|
||||
public UInt32 allocationFile_extents_blockCount3;
|
||||
// 0x0AC
|
||||
public UInt32 allocationFile_extents_startBlock4;
|
||||
// 0x0B0
|
||||
public UInt32 allocationFile_extents_blockCount4;
|
||||
// 0x0B4
|
||||
public UInt32 allocationFile_extents_startBlock5;
|
||||
// 0x0B8
|
||||
public UInt32 allocationFile_extents_blockCount5;
|
||||
// 0x0BC
|
||||
public UInt32 allocationFile_extents_startBlock6;
|
||||
// 0x0C0
|
||||
public UInt32 allocationFile_extents_blockCount6;
|
||||
// 0x0C4
|
||||
public UInt32 allocationFile_extents_startBlock7;
|
||||
// 0x0C8
|
||||
public UInt32 allocationFile_extents_blockCount7;
|
||||
// 0x0CC
|
||||
// HFSPlusForkData extentsFile;
|
||||
public UInt64 extentsFile_logicalSize;
|
||||
// 0x0D0
|
||||
public UInt32 extentsFile_clumpSize;
|
||||
// 0x0D8
|
||||
public UInt32 extentsFile_totalBlocks;
|
||||
// 0x0DC
|
||||
public UInt32 extentsFile_extents_startBlock0;
|
||||
// 0x0E0
|
||||
public UInt32 extentsFile_extents_blockCount0;
|
||||
// 0x0E4
|
||||
public UInt32 extentsFile_extents_startBlock1;
|
||||
// 0x0E8
|
||||
public UInt32 extentsFile_extents_blockCount1;
|
||||
// 0x0EC
|
||||
public UInt32 extentsFile_extents_startBlock2;
|
||||
// 0x0F0
|
||||
public UInt32 extentsFile_extents_blockCount2;
|
||||
// 0x0F4
|
||||
public UInt32 extentsFile_extents_startBlock3;
|
||||
// 0x0F8
|
||||
public UInt32 extentsFile_extents_blockCount3;
|
||||
// 0x0FC
|
||||
public UInt32 extentsFile_extents_startBlock4;
|
||||
// 0x100
|
||||
public UInt32 extentsFile_extents_blockCount4;
|
||||
// 0x104
|
||||
public UInt32 extentsFile_extents_startBlock5;
|
||||
// 0x108
|
||||
public UInt32 extentsFile_extents_blockCount5;
|
||||
// 0x10C
|
||||
public UInt32 extentsFile_extents_startBlock6;
|
||||
// 0x110
|
||||
public UInt32 extentsFile_extents_blockCount6;
|
||||
// 0x114
|
||||
public UInt32 extentsFile_extents_startBlock7;
|
||||
// 0x118
|
||||
public UInt32 extentsFile_extents_blockCount7;
|
||||
// 0x11C
|
||||
// HFSPlusForkData catalogFile;
|
||||
public UInt64 catalogFile_logicalSize;
|
||||
// 0x120
|
||||
public UInt32 catalogFile_clumpSize;
|
||||
// 0x128
|
||||
public UInt32 catalogFile_totalBlocks;
|
||||
// 0x12C
|
||||
public UInt32 catalogFile_extents_startBlock0;
|
||||
// 0x130
|
||||
public UInt32 catalogFile_extents_blockCount0;
|
||||
// 0x134
|
||||
public UInt32 catalogFile_extents_startBlock1;
|
||||
// 0x138
|
||||
public UInt32 catalogFile_extents_blockCount1;
|
||||
// 0x13C
|
||||
public UInt32 catalogFile_extents_startBlock2;
|
||||
// 0x140
|
||||
public UInt32 catalogFile_extents_blockCount2;
|
||||
// 0x144
|
||||
public UInt32 catalogFile_extents_startBlock3;
|
||||
// 0x148
|
||||
public UInt32 catalogFile_extents_blockCount3;
|
||||
// 0x14C
|
||||
public UInt32 catalogFile_extents_startBlock4;
|
||||
// 0x150
|
||||
public UInt32 catalogFile_extents_blockCount4;
|
||||
// 0x154
|
||||
public UInt32 catalogFile_extents_startBlock5;
|
||||
// 0x158
|
||||
public UInt32 catalogFile_extents_blockCount5;
|
||||
// 0x15C
|
||||
public UInt32 catalogFile_extents_startBlock6;
|
||||
// 0x160
|
||||
public UInt32 catalogFile_extents_blockCount6;
|
||||
// 0x164
|
||||
public UInt32 catalogFile_extents_startBlock7;
|
||||
// 0x168
|
||||
public UInt32 catalogFile_extents_blockCount7;
|
||||
// 0x16C
|
||||
// HFSPlusForkData attributesFile;
|
||||
public UInt64 attributesFile_logicalSize;
|
||||
// 0x170
|
||||
public UInt32 attributesFile_clumpSize;
|
||||
// 0x178
|
||||
public UInt32 attributesFile_totalBlocks;
|
||||
// 0x17C
|
||||
public UInt32 attributesFile_extents_startBlock0;
|
||||
// 0x180
|
||||
public UInt32 attributesFile_extents_blockCount0;
|
||||
// 0x184
|
||||
public UInt32 attributesFile_extents_startBlock1;
|
||||
// 0x188
|
||||
public UInt32 attributesFile_extents_blockCount1;
|
||||
// 0x18C
|
||||
public UInt32 attributesFile_extents_startBlock2;
|
||||
// 0x190
|
||||
public UInt32 attributesFile_extents_blockCount2;
|
||||
// 0x194
|
||||
public UInt32 attributesFile_extents_startBlock3;
|
||||
// 0x198
|
||||
public UInt32 attributesFile_extents_blockCount3;
|
||||
// 0x19C
|
||||
public UInt32 attributesFile_extents_startBlock4;
|
||||
// 0x1A0
|
||||
public UInt32 attributesFile_extents_blockCount4;
|
||||
// 0x1A4
|
||||
public UInt32 attributesFile_extents_startBlock5;
|
||||
// 0x1A8
|
||||
public UInt32 attributesFile_extents_blockCount5;
|
||||
// 0x1AC
|
||||
public UInt32 attributesFile_extents_startBlock6;
|
||||
// 0x1B0
|
||||
public UInt32 attributesFile_extents_blockCount6;
|
||||
// 0x1B4
|
||||
public UInt32 attributesFile_extents_startBlock7;
|
||||
// 0x1B8
|
||||
public UInt32 attributesFile_extents_blockCount7;
|
||||
// 0x1BC
|
||||
// HFSPlusForkData startupFile;
|
||||
public UInt64 startupFile_logicalSize;
|
||||
// 0x1C0
|
||||
public UInt32 startupFile_clumpSize;
|
||||
// 0x1C8
|
||||
public UInt32 startupFile_totalBlocks;
|
||||
// 0x1CC
|
||||
public UInt32 startupFile_extents_startBlock0;
|
||||
// 0x1D0
|
||||
public UInt32 startupFile_extents_blockCount0;
|
||||
// 0x1D4
|
||||
public UInt32 startupFile_extents_startBlock1;
|
||||
// 0x1D8
|
||||
public UInt32 startupFile_extents_blockCount1;
|
||||
// 0x1E0
|
||||
public UInt32 startupFile_extents_startBlock2;
|
||||
// 0x1E4
|
||||
public UInt32 startupFile_extents_blockCount2;
|
||||
// 0x1E8
|
||||
public UInt32 startupFile_extents_startBlock3;
|
||||
// 0x1EC
|
||||
public UInt32 startupFile_extents_blockCount3;
|
||||
// 0x1F0
|
||||
public UInt32 startupFile_extents_startBlock4;
|
||||
// 0x1F4
|
||||
public UInt32 startupFile_extents_blockCount4;
|
||||
// 0x1F8
|
||||
public UInt32 startupFile_extents_startBlock5;
|
||||
// 0x1FC
|
||||
public UInt32 startupFile_extents_blockCount5;
|
||||
// 0x200
|
||||
public UInt32 startupFile_extents_startBlock6;
|
||||
// 0x204
|
||||
public UInt32 startupFile_extents_blockCount6;
|
||||
// 0x208
|
||||
public UInt32 startupFile_extents_startBlock7;
|
||||
// 0x20C
|
||||
public UInt32 startupFile_extents_blockCount7;
|
||||
// 0x210
|
||||
}
|
||||
}
|
||||
}
|
||||
272
DiscImageChef/Plugins/AppleMFS.cs
Normal file
272
DiscImageChef/Plugins/AppleMFS.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : AppleMFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies the Macintosh FileSystem and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class AppleMFS : Plugin
|
||||
{
|
||||
const UInt16 MFS_MAGIC = 0xD2D7;
|
||||
// "LK"
|
||||
const UInt16 MFSBB_MAGIC = 0x4C4B;
|
||||
|
||||
public AppleMFS(PluginBase Core)
|
||||
{
|
||||
Name = "Apple Macintosh File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt16 drSigWord;
|
||||
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
||||
|
||||
return drSigWord == MFS_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
MFS_MasterDirectoryBlock MDB = new MFS_MasterDirectoryBlock();
|
||||
MFS_BootBlock BB = new MFS_BootBlock();
|
||||
|
||||
byte[] pString = new byte[16];
|
||||
byte[] variable_size;
|
||||
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
byte[] bb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
||||
if (MDB.drSigWord != MFS_MAGIC)
|
||||
return;
|
||||
|
||||
MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdb_sector, 0x002);
|
||||
MDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdb_sector, 0x006);
|
||||
MDB.drAtrb = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00A);
|
||||
MDB.drNmFls = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00C);
|
||||
MDB.drDirSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00E);
|
||||
MDB.drBlLen = 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.drNxtFNum = BigEndianBitConverter.ToUInt32(mdb_sector, 0x01E);
|
||||
MDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x022);
|
||||
MDB.drVNSiz = mdb_sector[0x024];
|
||||
variable_size = new byte[MDB.drVNSiz];
|
||||
Array.Copy(mdb_sector, 0x025, variable_size, 0, MDB.drVNSiz);
|
||||
MDB.drVN = Encoding.ASCII.GetString(variable_size);
|
||||
|
||||
BB.signature = BigEndianBitConverter.ToUInt16(bb_sector, 0x000);
|
||||
|
||||
if (BB.signature == MFSBB_MAGIC)
|
||||
{
|
||||
BB.branch = BigEndianBitConverter.ToUInt32(bb_sector, 0x002);
|
||||
BB.boot_flags = bb_sector[0x006];
|
||||
BB.boot_version = bb_sector[0x007];
|
||||
|
||||
BB.sec_sv_pages = BigEndianBitConverter.ToInt16(bb_sector, 0x008);
|
||||
|
||||
Array.Copy(mdb_sector, 0x00A, pString, 0, 16);
|
||||
BB.system_name = StringHandlers.PascalToString(pString);
|
||||
Array.Copy(mdb_sector, 0x01A, pString, 0, 16);
|
||||
BB.finder_name = StringHandlers.PascalToString(pString);
|
||||
Array.Copy(mdb_sector, 0x02A, pString, 0, 16);
|
||||
BB.debug_name = StringHandlers.PascalToString(pString);
|
||||
Array.Copy(mdb_sector, 0x03A, pString, 0, 16);
|
||||
BB.disasm_name = StringHandlers.PascalToString(pString);
|
||||
Array.Copy(mdb_sector, 0x04A, pString, 0, 16);
|
||||
BB.stupscr_name = StringHandlers.PascalToString(pString);
|
||||
Array.Copy(mdb_sector, 0x05A, pString, 0, 16);
|
||||
BB.bootup_name = StringHandlers.PascalToString(pString);
|
||||
Array.Copy(mdb_sector, 0x06A, pString, 0, 16);
|
||||
BB.clipbrd_name = StringHandlers.PascalToString(pString);
|
||||
|
||||
BB.max_files = BigEndianBitConverter.ToUInt16(bb_sector, 0x07A);
|
||||
BB.queue_size = BigEndianBitConverter.ToUInt16(bb_sector, 0x07C);
|
||||
BB.heap_128k = BigEndianBitConverter.ToUInt32(bb_sector, 0x07E);
|
||||
BB.heap_256k = BigEndianBitConverter.ToUInt32(bb_sector, 0x082);
|
||||
BB.heap_512k = BigEndianBitConverter.ToUInt32(bb_sector, 0x086);
|
||||
}
|
||||
else
|
||||
BB.signature = 0x0000;
|
||||
|
||||
sb.AppendLine("Apple Macintosh File System");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Master Directory Block:");
|
||||
sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine();
|
||||
sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(MDB.drLsBkUp)).AppendLine();
|
||||
if ((MDB.drAtrb & 0x80) == 0x80)
|
||||
sb.AppendLine("Volume is locked by hardware.");
|
||||
if ((MDB.drAtrb & 0x8000) == 0x8000)
|
||||
sb.AppendLine("Volume is locked by software.");
|
||||
sb.AppendFormat("{0} files on volume", MDB.drNmFls).AppendLine();
|
||||
sb.AppendFormat("First directory block: {0}", MDB.drDirSt).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in directory.", MDB.drBlLen).AppendLine();
|
||||
sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine();
|
||||
sb.AppendFormat("Size of allocation blocks: {0}", MDB.drAlBlkSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate.", MDB.drClpSiz).AppendLine();
|
||||
sb.AppendFormat("{0} first allocation block.", MDB.drAlBlSt).AppendLine();
|
||||
sb.AppendFormat("Next unused file number: {0}", MDB.drNxtFNum).AppendLine();
|
||||
sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", MDB.drVN).AppendLine();
|
||||
|
||||
if (BB.signature == MFSBB_MAGIC)
|
||||
{
|
||||
sb.AppendLine("Volume is bootable.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Boot Block:");
|
||||
if ((BB.boot_flags & 0x40) == 0x40)
|
||||
sb.AppendLine("Boot block should be executed.");
|
||||
if ((BB.boot_flags & 0x80) == 0x80)
|
||||
{
|
||||
sb.AppendLine("Boot block is in new unknown format.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BB.sec_sv_pages > 0)
|
||||
sb.AppendLine("Allocate secondary sound buffer at boot.");
|
||||
else if (BB.sec_sv_pages < 0)
|
||||
sb.AppendLine("Allocate secondary sound and video buffers at boot.");
|
||||
|
||||
sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine();
|
||||
sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine();
|
||||
sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine();
|
||||
sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine();
|
||||
sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine();
|
||||
sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine();
|
||||
sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine();
|
||||
sb.AppendFormat("Maximum opened files: {0}", BB.max_files * 4).AppendLine();
|
||||
sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine();
|
||||
sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
sb.AppendLine("Volume is not bootable.");
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct MFS_MasterDirectoryBlock // Should be offset 0x0400 bytes in volume
|
||||
{
|
||||
// 0x000, Signature, 0xD2D7
|
||||
public UInt16 drSigWord;
|
||||
// 0x002, Volume creation date
|
||||
public UInt32 drCrDate;
|
||||
// 0x006, Volume last backup date
|
||||
public UInt32 drLsBkUp;
|
||||
// 0x00A, Volume attributes
|
||||
public UInt16 drAtrb;
|
||||
// 0x00C, Volume number of files
|
||||
public UInt16 drNmFls;
|
||||
// 0x00E, First directory block
|
||||
public UInt16 drDirSt;
|
||||
// 0x010, Length of directory in blocks
|
||||
public UInt16 drBlLen;
|
||||
// 0x012, Volume allocation blocks
|
||||
public UInt16 drNmAlBlks;
|
||||
// 0x014, Size of allocation blocks
|
||||
public UInt32 drAlBlkSiz;
|
||||
// 0x018, Number of bytes to allocate
|
||||
public UInt32 drClpSiz;
|
||||
// 0x01C, First allocation block in block map
|
||||
public UInt16 drAlBlSt;
|
||||
// 0x01E. Next unused file number
|
||||
public UInt32 drNxtFNum;
|
||||
// 0x022, Number of unused allocation blocks
|
||||
public UInt16 drFreeBks;
|
||||
// 0x024, Length of volume name
|
||||
public byte drVNSiz;
|
||||
// 0x025, Characters of volume name
|
||||
public string drVN;
|
||||
}
|
||||
|
||||
struct MFS_BootBlock // Should be offset 0x0000 bytes in volume
|
||||
{
|
||||
public UInt16 signature;
|
||||
// 0x000, Signature, 0x4C4B if bootable
|
||||
public UInt32 branch;
|
||||
// 0x002, Branch
|
||||
public byte boot_flags;
|
||||
// 0x006, Boot block flags
|
||||
public byte boot_version;
|
||||
// 0x007, Boot block version
|
||||
public short sec_sv_pages;
|
||||
// 0x008, Allocate secondary buffers
|
||||
public string system_name;
|
||||
// 0x00A, System file name (16 bytes)
|
||||
public string finder_name;
|
||||
// 0x01A, Finder file name (16 bytes)
|
||||
public string debug_name;
|
||||
// 0x02A, Debugger file name (16 bytes)
|
||||
public string disasm_name;
|
||||
// 0x03A, Disassembler file name (16 bytes)
|
||||
public string stupscr_name;
|
||||
// 0x04A, Startup screen file name (16 bytes)
|
||||
public string bootup_name;
|
||||
// 0x05A, First program to execute on boot (16 bytes)
|
||||
public string clipbrd_name;
|
||||
// 0x06A, Clipboard file name (16 bytes)
|
||||
public UInt16 max_files;
|
||||
// 0x07A, 1/4 of maximum opened at a time files
|
||||
public UInt16 queue_size;
|
||||
// 0x07C, Event queue size
|
||||
public UInt32 heap_128k;
|
||||
// 0x07E, Heap size on a Mac with 128KiB of RAM
|
||||
public UInt32 heap_256k;
|
||||
// 0x082, Heap size on a Mac with 256KiB of RAM
|
||||
public UInt32 heap_512k;
|
||||
// 0x086, Heap size on a Mac with 512KiB of RAM or more
|
||||
}
|
||||
// Follows boot code
|
||||
}
|
||||
}
|
||||
251
DiscImageChef/Plugins/BFS.cs
Normal file
251
DiscImageChef/Plugins/BFS.cs
Normal file
@@ -0,0 +1,251 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : BFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies BeOS' filesystem and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from Practical Filesystem Design, ISBN 1-55860-497-9
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class BeFS : Plugin
|
||||
{
|
||||
// Little endian constants (that is, as read by .NET :p)
|
||||
const UInt32 BEFS_MAGIC1 = 0x42465331;
|
||||
const UInt32 BEFS_MAGIC2 = 0xDD121031;
|
||||
const UInt32 BEFS_MAGIC3 = 0x15B6830E;
|
||||
const UInt32 BEFS_ENDIAN = 0x42494745;
|
||||
// Big endian constants
|
||||
const UInt32 BEFS_CIGAM1 = 0x31534642;
|
||||
const UInt32 BEFS_NAIDNE = 0x45474942;
|
||||
// Common constants
|
||||
const UInt32 BEFS_CLEAN = 0x434C454E;
|
||||
const UInt32 BEFS_DIRTY = 0x44495254;
|
||||
|
||||
public BeFS(PluginBase Core)
|
||||
{
|
||||
Name = "Be Filesystem";
|
||||
PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic;
|
||||
UInt32 magic_be;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x20);
|
||||
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
|
||||
if (magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1)
|
||||
return true;
|
||||
sb_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x20);
|
||||
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
|
||||
if (magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
byte[] name_bytes = new byte[32];
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BeSuperBlock besb = new BeSuperBlock();
|
||||
|
||||
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
|
||||
{
|
||||
BigEndianBitConverter.IsLittleEndian &= besb.magic1 != BEFS_CIGAM1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
|
||||
if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
|
||||
{
|
||||
BigEndianBitConverter.IsLittleEndian &= besb.magic1 != BEFS_CIGAM1;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
Array.Copy(sb_sector, 0x000, name_bytes, 0, 0x20);
|
||||
besb.name = StringHandlers.CToString(name_bytes);
|
||||
besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.fs_byte_order = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.block_size = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.block_shift = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.num_blocks = BigEndianBitConverter.ToInt64(sb_sector, 0x20);
|
||||
besb.used_blocks = BigEndianBitConverter.ToInt64(sb_sector, 0x20);
|
||||
besb.inode_size = BigEndianBitConverter.ToInt32(sb_sector, 0x20);
|
||||
besb.magic2 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.blocks_per_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20);
|
||||
besb.ag_shift = BigEndianBitConverter.ToInt32(sb_sector, 0x20);
|
||||
besb.num_ags = BigEndianBitConverter.ToInt32(sb_sector, 0x20);
|
||||
besb.flags = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.log_blocks_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20);
|
||||
besb.log_blocks_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x20);
|
||||
besb.log_blocks_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x20);
|
||||
besb.log_start = BigEndianBitConverter.ToInt64(sb_sector, 0x20);
|
||||
besb.log_end = BigEndianBitConverter.ToInt64(sb_sector, 0x20);
|
||||
besb.magic3 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.root_dir_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20);
|
||||
besb.root_dir_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x20);
|
||||
besb.root_dir_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x20);
|
||||
besb.indices_ag = BigEndianBitConverter.ToInt32(sb_sector, 0x20);
|
||||
besb.indices_start = BigEndianBitConverter.ToUInt16(sb_sector, 0x20);
|
||||
besb.indices_len = BigEndianBitConverter.ToUInt16(sb_sector, 0x20);
|
||||
|
||||
if (!BigEndianBitConverter.IsLittleEndian) // Big-endian filesystem
|
||||
sb.AppendLine("Big-endian BeFS");
|
||||
else
|
||||
sb.AppendLine("Little-endian BeFS");
|
||||
|
||||
if (besb.magic1 != BEFS_MAGIC1 || besb.fs_byte_order != BEFS_ENDIAN ||
|
||||
besb.magic2 != BEFS_MAGIC2 || besb.magic3 != BEFS_MAGIC3 ||
|
||||
besb.root_dir_len != 1 || besb.indices_len != 1 ||
|
||||
(1 << (int)besb.block_shift) != besb.block_size)
|
||||
{
|
||||
sb.AppendLine("Superblock seems corrupt, following information may be incorrect");
|
||||
sb.AppendFormat("Magic 1: 0x{0:X8} (Should be 0x42465331)", besb.magic1).AppendLine();
|
||||
sb.AppendFormat("Magic 2: 0x{0:X8} (Should be 0xDD121031)", besb.magic2).AppendLine();
|
||||
sb.AppendFormat("Magic 3: 0x{0:X8} (Should be 0x15B6830E)", besb.magic3).AppendLine();
|
||||
sb.AppendFormat("Filesystem endianness: 0x{0:X8} (Should be 0x42494745)", besb.fs_byte_order).AppendLine();
|
||||
sb.AppendFormat("Root folder's i-node size: {0} blocks (Should be 1)", besb.root_dir_len).AppendLine();
|
||||
sb.AppendFormat("Indices' i-node size: {0} blocks (Should be 1)", besb.indices_len).AppendLine();
|
||||
sb.AppendFormat("1 << block_shift == block_size => 1 << {0} == {1} (Should be {2})", besb.block_shift,
|
||||
1 << (int)besb.block_shift, besb.block_size).AppendLine();
|
||||
}
|
||||
|
||||
if (besb.flags == BEFS_CLEAN)
|
||||
{
|
||||
if (besb.log_start == besb.log_end)
|
||||
sb.AppendLine("Filesystem is clean");
|
||||
else
|
||||
sb.AppendLine("Filesystem is dirty");
|
||||
}
|
||||
else if (besb.flags == BEFS_DIRTY)
|
||||
sb.AppendLine("Filesystem is dirty");
|
||||
else
|
||||
sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume name: {0}", besb.name).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per block", besb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume ({1} bytes)", besb.num_blocks, besb.num_blocks * besb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} used blocks ({1} bytes)", besb.used_blocks, besb.used_blocks * besb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per i-node", besb.inode_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", besb.blocks_per_ag, besb.blocks_per_ag * besb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} allocation groups in volume", besb.num_ags).AppendLine();
|
||||
sb.AppendFormat("Journal resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", besb.log_blocks_start,
|
||||
besb.log_blocks_ag, besb.log_blocks_len, besb.log_blocks_len * besb.block_size).AppendLine();
|
||||
sb.AppendFormat("Journal starts in byte {0} and ends in byte {1}", besb.log_start, besb.log_end).AppendLine();
|
||||
sb.AppendFormat("Root folder's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", besb.root_dir_start,
|
||||
besb.root_dir_ag, besb.root_dir_len, besb.root_dir_len * besb.block_size).AppendLine();
|
||||
sb.AppendFormat("Indices' i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", besb.indices_start,
|
||||
besb.indices_ag, besb.indices_len, besb.indices_len * besb.block_size).AppendLine();
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
struct BeSuperBlock
|
||||
{
|
||||
public string name;
|
||||
// 0x000, Volume name, 32 bytes
|
||||
public UInt32 magic1;
|
||||
// 0x020, "BFS1", 0x42465331
|
||||
public UInt32 fs_byte_order;
|
||||
// 0x024, "BIGE", 0x42494745
|
||||
public UInt32 block_size;
|
||||
// 0x028, Bytes per block
|
||||
public UInt32 block_shift;
|
||||
// 0x02C, 1 << block_shift == block_size
|
||||
public Int64 num_blocks;
|
||||
// 0x030, Blocks in volume
|
||||
public Int64 used_blocks;
|
||||
// 0x038, Used blocks in volume
|
||||
public Int32 inode_size;
|
||||
// 0x040, Bytes per inode
|
||||
public UInt32 magic2;
|
||||
// 0x044, 0xDD121031
|
||||
public Int32 blocks_per_ag;
|
||||
// 0x048, Blocks per allocation group
|
||||
public Int32 ag_shift;
|
||||
// 0x04C, 1 << ag_shift == blocks_per_ag
|
||||
public Int32 num_ags;
|
||||
// 0x050, Allocation groups in volume
|
||||
public UInt32 flags;
|
||||
// 0x054, 0x434c454e if clean, 0x44495254 if dirty
|
||||
public Int32 log_blocks_ag;
|
||||
// 0x058, Allocation group of journal
|
||||
public UInt16 log_blocks_start;
|
||||
// 0x05C, Start block of journal, inside ag
|
||||
public UInt16 log_blocks_len;
|
||||
// 0x05E, Length in blocks of journal, inside ag
|
||||
public Int64 log_start;
|
||||
// 0x060, Start of journal
|
||||
public Int64 log_end;
|
||||
// 0x068, End of journal
|
||||
public UInt32 magic3;
|
||||
// 0x070, 0x15B6830E
|
||||
public Int32 root_dir_ag;
|
||||
// 0x074, Allocation group where root folder's i-node resides
|
||||
public UInt16 root_dir_start;
|
||||
// 0x078, Start in ag of root folder's i-node
|
||||
public UInt16 root_dir_len;
|
||||
// 0x07A, As this is part of inode_addr, this is 1
|
||||
public Int32 indices_ag;
|
||||
// 0x07C, Allocation group where indices' i-node resides
|
||||
public UInt16 indices_start;
|
||||
// 0x080, Start in ag of indices' i-node
|
||||
public UInt16 indices_len;
|
||||
// 0x082, As this is part of inode_addr, this is 1
|
||||
}
|
||||
}
|
||||
}
|
||||
463
DiscImageChef/Plugins/FAT.cs
Normal file
463
DiscImageChef/Plugins/FAT.cs
Normal file
@@ -0,0 +1,463 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : FAT.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies FAT12/16/32 filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// TODO: Implement detecting DOS bootable disks
|
||||
// TODO: Implement detecting Atari TOS bootable disks and printing corresponding fields
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class FAT : Plugin
|
||||
{
|
||||
public FAT(PluginBase Core)
|
||||
{
|
||||
Name = "Microsoft File Allocation Table";
|
||||
PluginUUID = new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry
|
||||
byte fats_no; // Must be 1 or 2. Dunno if it can be 0 in the wild, but it CANNOT BE bigger than 2
|
||||
byte[] fat32_signature = new byte[8]; // "FAT32 "
|
||||
UInt32 first_fat_entry; // No matter FAT size we read 4 bytes for checking
|
||||
UInt16 bps, rsectors;
|
||||
|
||||
byte[] bpb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
byte[] fat_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
bool bpb_found = true;
|
||||
|
||||
fats_no = bpb_sector[0x010]; // FATs, 1 or 2, maybe 0, never bigger
|
||||
media_descriptor = bpb_sector[0x015]; // Media Descriptor if present is in 0x15
|
||||
Array.Copy(bpb_sector, 0x52, fat32_signature, 0, 8); // FAT32 signature, if present, is in 0x52
|
||||
bps = BitConverter.ToUInt16(bpb_sector, 0x00B); // Bytes per sector
|
||||
if (bps == 0)
|
||||
bps = 0x200;
|
||||
rsectors = BitConverter.ToUInt16(bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT)
|
||||
if (rsectors == 0)
|
||||
rsectors = 1;
|
||||
if (imagePlugin.GetSectors() > ((ulong)rsectors + partitionOffset))
|
||||
fat_sector = imagePlugin.ReadSector(rsectors + partitionOffset); // First FAT entry
|
||||
else
|
||||
bpb_found=false;
|
||||
|
||||
if (bpb_found)
|
||||
{
|
||||
first_fat_entry = BitConverter.ToUInt32(fat_sector, 0); // Easier to manage
|
||||
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (FAT plugin): fats_no = {0}", fats_no);
|
||||
Console.WriteLine("DEBUG (FAT plugin): media_descriptor = 0x{0:X2}", media_descriptor);
|
||||
Console.WriteLine("DEBUG (FAT plugin): fat32_signature = {0}", StringHandlers.CToString(fat32_signature));
|
||||
Console.WriteLine("DEBUG (FAT plugin): bps = {0}", bps);
|
||||
Console.WriteLine("DEBUG (FAT plugin): first_fat_entry = 0x{0:X8}", first_fat_entry);
|
||||
}
|
||||
|
||||
if (fats_no > 2) // Must be 1 or 2, but as TOS makes strange things and I have not checked if it puts this to 0, ignore if 0. MUST NOT BE BIGGER THAN 2!
|
||||
return false;
|
||||
|
||||
// Let's start the fun
|
||||
if (Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
|
||||
return true; // Seems easy, check reading
|
||||
|
||||
if ((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16
|
||||
{
|
||||
if ((first_fat_entry & 0xFF) == media_descriptor)
|
||||
return true; // It MUST be FAT16, or... maybe not :S
|
||||
}
|
||||
else if ((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0)
|
||||
{
|
||||
//if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is !=
|
||||
return true; // It MUST be FAT12, or... maybe not :S
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This may create a lot of false positives, need to do extensive checkins...
|
||||
fat_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
first_fat_entry = BitConverter.ToUInt32(fat_sector, 0);
|
||||
byte fat_id = fat_sector[0];
|
||||
|
||||
if ((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0)
|
||||
{
|
||||
if (fat_id == 0xFF)
|
||||
{
|
||||
if (imagePlugin.GetSectorSize() == 512 && imagePlugin.GetSectors() == 640)
|
||||
return true;
|
||||
if (imagePlugin.GetSectorSize() == 128)
|
||||
{
|
||||
if(imagePlugin.GetSectors() == 2002)
|
||||
return true;
|
||||
if(imagePlugin.GetSectors() == 4004)
|
||||
return true;
|
||||
}
|
||||
if (imagePlugin.GetSectorSize() == 1024)
|
||||
{
|
||||
if(imagePlugin.GetSectors() == 616)
|
||||
return true;
|
||||
if(imagePlugin.GetSectors() == 1232)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
if (fat_id == 0xFE)
|
||||
{
|
||||
if (imagePlugin.GetSectorSize() == 512 && imagePlugin.GetSectors() == 320)
|
||||
return true;
|
||||
if (imagePlugin.GetSectorSize() == 128)
|
||||
{
|
||||
if(imagePlugin.GetSectors() == 2002)
|
||||
return true;
|
||||
if(imagePlugin.GetSectors() == 4004)
|
||||
return true;
|
||||
}
|
||||
if (imagePlugin.GetSectorSize() == 1024)
|
||||
{
|
||||
if(imagePlugin.GetSectors() == 616)
|
||||
return true;
|
||||
if(imagePlugin.GetSectors() == 1232)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
if (fat_id == 0xFD && imagePlugin.GetSectors() == 2002)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
byte[] dosString; // Space-padded
|
||||
bool isFAT32 = false;
|
||||
UInt32 first_fat_entry;
|
||||
byte media_descriptor, fats_no;
|
||||
string fat32_signature;
|
||||
UInt16 bps, rsectors;
|
||||
|
||||
byte[] bpb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
byte[] fat_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
bool bpb_found = true;
|
||||
|
||||
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;
|
||||
rsectors = BitConverter.ToUInt16(bpb_sector, 0x00E); // Sectors between BPB and FAT, including the BPB sector => [BPB,FAT)
|
||||
if (rsectors == 0)
|
||||
rsectors = 1;
|
||||
if (imagePlugin.GetSectors() > ((ulong)rsectors + partitionOffset))
|
||||
fat_sector = imagePlugin.ReadSector(rsectors + partitionOffset); // First FAT entry
|
||||
else
|
||||
bpb_found=false;
|
||||
|
||||
if (bpb_found)
|
||||
{
|
||||
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;
|
||||
|
||||
// Let's start the fun
|
||||
if (fat32_signature == "FAT32 ")
|
||||
{
|
||||
sb.AppendLine("Microsoft FAT32"); // Seems easy, check reading
|
||||
isFAT32 = true;
|
||||
}
|
||||
else if ((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16
|
||||
{
|
||||
if ((first_fat_entry & 0xFF) == media_descriptor)
|
||||
sb.AppendLine("Microsoft FAT16"); // It MUST be FAT16, or... maybe not :S
|
||||
}
|
||||
else if ((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0)
|
||||
{
|
||||
//if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is !=
|
||||
sb.AppendLine("Microsoft FAT12"); // It MUST be FAT12, or... maybe not :S
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
BIOSParameterBlock BPB = new BIOSParameterBlock();
|
||||
ExtendedParameterBlock EPB = new ExtendedParameterBlock();
|
||||
FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock();
|
||||
|
||||
dosString = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x03, dosString, 0, 8);
|
||||
BPB.OEMName = Encoding.ASCII.GetString(dosString);
|
||||
BPB.bps = BitConverter.ToUInt16(bpb_sector, 0x0B);
|
||||
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 = 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 = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x52, dosString, 0, 8);
|
||||
FAT32PB.fs_type = Encoding.ASCII.GetString(dosString);
|
||||
}
|
||||
else
|
||||
{
|
||||
EPB.drive_no = bpb_sector[0x24];
|
||||
EPB.nt_flags = bpb_sector[0x25];
|
||||
EPB.signature = bpb_sector[0x26];
|
||||
EPB.serial_no = BitConverter.ToUInt32(bpb_sector, 0x27);
|
||||
dosString = new byte[11];
|
||||
Array.Copy(bpb_sector, 0x2B, dosString, 0, 11);
|
||||
EPB.volume_label = Encoding.ASCII.GetString(dosString);
|
||||
dosString = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x36, dosString, 0, 8);
|
||||
EPB.fs_type = Encoding.ASCII.GetString(dosString);
|
||||
}
|
||||
|
||||
sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector.", BPB.bps).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster.", BPB.spc).AppendLine();
|
||||
sb.AppendFormat("{0} sectors reserved between BPB and FAT.", BPB.rsectors).AppendLine();
|
||||
sb.AppendFormat("{0} FATs.", BPB.fats_no).AppendLine();
|
||||
sb.AppendFormat("{0} entries on root directory.", BPB.root_ent).AppendLine();
|
||||
if (BPB.sectors == 0)
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.big_sectors, BPB.big_sectors * BPB.bps).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.sectors, BPB.sectors * BPB.bps).AppendLine();
|
||||
if ((BPB.media & 0xF0) == 0xF0)
|
||||
sb.AppendFormat("Media format: 0x{0:X2}", BPB.media).AppendLine();
|
||||
if (fat32_signature == "FAT32 ")
|
||||
sb.AppendFormat("{0} sectors per FAT.", FAT32PB.spfat).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} sectors per FAT.", BPB.spfat).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track.", BPB.sptrk).AppendLine();
|
||||
sb.AppendFormat("{0} heads.", BPB.heads).AppendLine();
|
||||
sb.AppendFormat("{0} hidden sectors before BPB.", BPB.hsectors).AppendLine();
|
||||
|
||||
if (isFAT32)
|
||||
{
|
||||
sb.AppendFormat("Cluster of root directory: {0}", FAT32PB.root_cluster).AppendLine();
|
||||
sb.AppendFormat("Sector of FSINFO structure: {0}", FAT32PB.fsinfo_sector).AppendLine();
|
||||
sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", FAT32PB.backup_sector).AppendLine();
|
||||
sb.AppendFormat("Drive number: 0x{0:X2}", FAT32PB.drive_no).AppendLine();
|
||||
sb.AppendFormat("Volume Serial Number: 0x{0:X8}", FAT32PB.serial_no).AppendLine();
|
||||
if ((FAT32PB.nt_flags & 0x01) == 0x01)
|
||||
{
|
||||
sb.AppendLine("Volume should be checked on next mount.");
|
||||
if ((EPB.nt_flags & 0x02) == 0x02)
|
||||
sb.AppendLine("Disk surface should be checked also.");
|
||||
}
|
||||
|
||||
sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine();
|
||||
sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine();
|
||||
}
|
||||
else if (EPB.signature == 0x28 || EPB.signature == 0x29)
|
||||
{
|
||||
sb.AppendFormat("Drive number: 0x{0:X2}", EPB.drive_no).AppendLine();
|
||||
sb.AppendFormat("Volume Serial Number: 0x{0:X8}", EPB.serial_no).AppendLine();
|
||||
if (EPB.signature == 0x29)
|
||||
{
|
||||
if ((EPB.nt_flags & 0x01) == 0x01)
|
||||
{
|
||||
sb.AppendLine("Volume should be checked on next mount.");
|
||||
if ((EPB.nt_flags & 0x02) == 0x02)
|
||||
sb.AppendLine("Disk surface should be checked also.");
|
||||
}
|
||||
|
||||
sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine();
|
||||
sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("Pre-DOS 2.0 Microsoft FAT12.");
|
||||
sb.AppendLine("***WARNING***");
|
||||
sb.AppendLine("This may be a false positive.");
|
||||
sb.AppendFormat("Disk image identifies disk type as {0}.", imagePlugin.GetDiskType()).AppendLine();
|
||||
}
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>FAT's BIOS Parameter Block.</summary>
|
||||
public struct BIOSParameterBlock
|
||||
{
|
||||
/// <summary>0x03, OEM Name, 8 bytes, space-padded</summary>
|
||||
public string OEMName;
|
||||
/// <summary>0x0B, Bytes per sector</summary>
|
||||
public UInt16 bps;
|
||||
/// <summary>0x0D, Sectors per cluster</summary>
|
||||
public byte spc;
|
||||
/// <summary>0x0E, Reserved sectors between BPB and FAT</summary>
|
||||
public UInt16 rsectors;
|
||||
/// <summary>0x10, Number of FATs</summary>
|
||||
public byte fats_no;
|
||||
/// <summary>0x11, Number of entries on root directory</summary>
|
||||
public UInt16 root_ent;
|
||||
/// <summary>0x13, Sectors in volume</summary>
|
||||
public UInt16 sectors;
|
||||
/// <summary>0x15, Media descriptor</summary>
|
||||
public byte media;
|
||||
/// <summary>0x16, Sectors per FAT</summary>
|
||||
public UInt16 spfat;
|
||||
/// <summary>0x18, Sectors per track</summary>
|
||||
public UInt16 sptrk;
|
||||
/// <summary>0x1A, Heads</summary>
|
||||
public UInt16 heads;
|
||||
/// <summary>0x1C, Hidden sectors before BPB</summary>
|
||||
public UInt32 hsectors;
|
||||
/// <summary>0x20, Sectors in volume if > 65535</summary>
|
||||
public UInt32 big_sectors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atari Boot Block.
|
||||
/// This only applies for bootable disks
|
||||
/// From http://info-coach.fr/atari/software/FD-Soft.php
|
||||
/// </summary>
|
||||
public struct AtariBootBlock
|
||||
{
|
||||
/// <summary>0x01C, Atari ST use 16 bit for hidden sectors, probably so did old DOS</summary>
|
||||
public UInt16 hsectors;
|
||||
/// <summary>0x01E, indicates if COMMAND.PRG must be executed after OS load</summary>
|
||||
public UInt16 xflag;
|
||||
/// <summary>0x020, load mode for, or 0 if fname indicates boot file</summary>
|
||||
public UInt16 ldmode;
|
||||
/// <summary>0x022, sector from which to boot</summary>
|
||||
public UInt16 bsect;
|
||||
/// <summary>0x024, how many sectors to boot</summary>
|
||||
public UInt16 bsects_no;
|
||||
/// <summary>0x026, RAM address where boot should be located</summary>
|
||||
public UInt32 ldaddr;
|
||||
/// <summary>0x02A, RAM address to copy the FAT and root directory</summary>
|
||||
public UInt32 fatbuf;
|
||||
/// <summary>0x02E, 11 bytes, name of boot file</summary>
|
||||
public string fname;
|
||||
/// <summary>0x039, unused</summary>
|
||||
public UInt16 reserved;
|
||||
/// <summary>0x03B, 451 bytes boot code</summary>
|
||||
public byte[] boot_code;
|
||||
/// <summary>0x1FE, the sum of all the BPB+ABB must be 0x1234, so this bigendian value works as adjustment</summary>
|
||||
public UInt16 checksum;
|
||||
}
|
||||
|
||||
/// <summary>DOS Extended Parameter Block</summary>
|
||||
public struct ExtendedParameterBlock
|
||||
{
|
||||
/// <summary>0x24, Drive number<summary>
|
||||
public byte drive_no;
|
||||
/// <summary>0x25, Volume flags if NT (must be 0x29 signature)<summary>
|
||||
public byte nt_flags;
|
||||
/// <summary>0x26, EPB signature, 0x28 or 0x29<summary>
|
||||
public byte signature;
|
||||
/// <summary>0x27, Volume serial number<summary>
|
||||
public UInt32 serial_no;
|
||||
/// <summary>0x2B, Volume label, 11 bytes, space-padded
|
||||
/// Present only if signature == 0x29<summary>
|
||||
public string volume_label;
|
||||
/// <summary>0x36, Filesystem type, 8 bytes, space-padded
|
||||
/// Present only if signature == 0x29<summary>
|
||||
public string fs_type;
|
||||
}
|
||||
|
||||
/// <summary>FAT32 Parameter Block</summary>
|
||||
public struct FAT32ParameterBlock
|
||||
{
|
||||
/// <summary>0x24, Sectors per FAT</summary>
|
||||
public UInt32 spfat;
|
||||
/// <summary>0x28, FAT flags</summary>
|
||||
public UInt16 fat_flags;
|
||||
/// <summary>0x2A, FAT32 version</summary>
|
||||
public UInt16 version;
|
||||
/// <summary>0x2C, Cluster of root directory</summary>
|
||||
public UInt32 root_cluster;
|
||||
/// <summary>0x30, Sector of FSINFO structure</summary>
|
||||
public UInt16 fsinfo_sector;
|
||||
/// <summary>0x32, Sector of FAT32PB backup</summary>
|
||||
public UInt16 backup_sector;
|
||||
/// <summary>0x34, 12 reserved bytes</summary>
|
||||
byte[] reserved;
|
||||
/// <summary>0x40, Drive number</summary>
|
||||
public byte drive_no;
|
||||
/// <summary>0x41, Volume flags</summary>
|
||||
public byte nt_flags;
|
||||
/// <summary>0x42, FAT32PB signature, should be 0x29</summary>
|
||||
public byte signature;
|
||||
/// <summary>0x43, Volume serial number</summary>
|
||||
public UInt32 serial_no;
|
||||
/// <summary>0x47, Volume label, 11 bytes, space-padded</summary>
|
||||
public string volume_label;
|
||||
/// <summary>0x52, Filesystem type, 8 bytes, space-padded, must be "FAT32 "</summary>
|
||||
public string fs_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
1071
DiscImageChef/Plugins/FFS.cs
Normal file
1071
DiscImageChef/Plugins/FFS.cs
Normal file
File diff suppressed because it is too large
Load Diff
379
DiscImageChef/Plugins/HPFS.cs
Normal file
379
DiscImageChef/Plugins/HPFS.cs
Normal file
@@ -0,0 +1,379 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : HPFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies OS/2 HPFS filesystems and shows information.
|
||||
No pinball playing allowed.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from an old unnamed document
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class HPFS : Plugin
|
||||
{
|
||||
public HPFS(PluginBase Core)
|
||||
{
|
||||
Name = "OS/2 High Performance File System";
|
||||
PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic1, magic2;
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
HPFS_BIOSParameterBlock hpfs_bpb = new HPFS_BIOSParameterBlock();
|
||||
HPFS_SuperBlock hpfs_sb = new HPFS_SuperBlock();
|
||||
HPFS_SpareBlock hpfs_sp = new HPFS_SpareBlock();
|
||||
|
||||
byte[] oem_name = new byte[8];
|
||||
byte[] volume_name = new byte[11];
|
||||
|
||||
byte[] hpfs_bpb_sector = imagePlugin.ReadSector(0 + partitionOffset); // Seek to BIOS parameter block, on logical sector 0
|
||||
byte[] hpfs_sb_sector = imagePlugin.ReadSector(16 + partitionOffset); // Seek to superblock, on logical sector 16
|
||||
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 = 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);
|
||||
Array.Copy(hpfs_bpb_sector, 0x03A, oem_name, 0, 8);
|
||||
hpfs_bpb.fs_type = StringHandlers.CToString(oem_name);
|
||||
|
||||
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);
|
||||
|
||||
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 ||
|
||||
hpfs_sp.magic1 != 0xF9911849 || hpfs_sp.magic2 != 0xFA5229C5)
|
||||
{
|
||||
sb.AppendLine("This may not be HPFS, following information may be not correct.");
|
||||
sb.AppendFormat("File system type: \"{0}\" (Should be \"HPFS \")", hpfs_bpb.fs_type).AppendLine();
|
||||
sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfs_sb.magic1).AppendLine();
|
||||
sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfs_sb.magic2).AppendLine();
|
||||
sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", hpfs_sp.magic1).AppendLine();
|
||||
sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", hpfs_sp.magic2).AppendLine();
|
||||
}
|
||||
|
||||
sb.AppendFormat("OEM name: {0}", hpfs_bpb.OEMName).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", hpfs_bpb.bps).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine();
|
||||
// sb.AppendFormat("{0} reserved sectors", hpfs_bpb.rsectors).AppendLine();
|
||||
// sb.AppendFormat("{0} FATs", hpfs_bpb.fats_no).AppendLine();
|
||||
// sb.AppendFormat("{0} entries on root directory", hpfs_bpb.root_ent).AppendLine();
|
||||
// sb.AppendFormat("{0} mini sectors on volume", hpfs_bpb.sectors).AppendLine();
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", hpfs_bpb.media).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors per FAT", hpfs_bpb.spfat).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors per track", hpfs_bpb.sptrk).AppendLine();
|
||||
// sb.AppendFormat("{0} heads", hpfs_bpb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} sectors hidden before BPB", hpfs_bpb.hsectors).AppendLine();
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_bpb.big_sectors, hpfs_bpb.big_sectors * hpfs_bpb.bps).AppendLine();
|
||||
sb.AppendFormat("BIOS Drive Number: 0x{0:X2}", hpfs_bpb.drive_no).AppendLine();
|
||||
// sb.AppendFormat("NT Flags: 0x{0:X2}", hpfs_bpb.nt_flags).AppendLine();
|
||||
sb.AppendFormat("Signature: 0x{0:X2}", hpfs_bpb.signature).AppendLine();
|
||||
sb.AppendFormat("Serial number: 0x{0:X8}", hpfs_bpb.serial_no).AppendLine();
|
||||
sb.AppendFormat("Volume label: {0}", hpfs_bpb.volume_label).AppendLine();
|
||||
// sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine();
|
||||
|
||||
DateTime last_chk = DateHandlers.UNIXToDateTime(hpfs_sb.last_chkdsk);
|
||||
DateTime last_optim = DateHandlers.UNIXToDateTime(hpfs_sb.last_optim);
|
||||
|
||||
sb.AppendFormat("HPFS version: {0}", hpfs_sb.version).AppendLine();
|
||||
sb.AppendFormat("Functional version: {0}", hpfs_sb.func_version).AppendLine();
|
||||
sb.AppendFormat("Sector of root directory FNode: {0}", hpfs_sb.root_fnode).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors on volume", hpfs_sb.sectors).AppendLine();
|
||||
sb.AppendFormat("{0} sectors are marked bad", hpfs_sb.badblocks).AppendLine();
|
||||
sb.AppendFormat("Sector of free space bitmaps: {0}", hpfs_sb.bitmap_lsn).AppendLine();
|
||||
sb.AppendFormat("Sector of bad blocks list: {0}", hpfs_sb.badblock_lsn).AppendLine();
|
||||
sb.AppendFormat("Date of last integrity check: {0}", last_chk).AppendLine();
|
||||
if (hpfs_sb.last_optim > 0)
|
||||
sb.AppendFormat("Date of last optimization {0}", last_optim).AppendLine();
|
||||
else
|
||||
sb.AppendLine("Filesystem has never been optimized");
|
||||
sb.AppendFormat("Directory band has {0} sectors", hpfs_sb.dband_sectors).AppendLine();
|
||||
sb.AppendFormat("Directory band starts at sector {0}", hpfs_sb.dband_start).AppendLine();
|
||||
sb.AppendFormat("Directory band ends at sector {0}", hpfs_sb.dband_last).AppendLine();
|
||||
sb.AppendFormat("Sector of directory band bitmap: {0}", hpfs_sb.dband_bitmap).AppendLine();
|
||||
sb.AppendFormat("Sector of ACL directory: {0}", hpfs_sb.acl_start).AppendLine();
|
||||
|
||||
sb.AppendFormat("Sector of Hotfix directory: {0}", hpfs_sp.hotfix_start).AppendLine();
|
||||
sb.AppendFormat("{0} used Hotfix entries", hpfs_sp.hotfix_used).AppendLine();
|
||||
sb.AppendFormat("{0} total Hotfix entries", hpfs_sp.hotfix_entries).AppendLine();
|
||||
sb.AppendFormat("{0} free spare DNodes", hpfs_sp.spare_dnodes_free).AppendLine();
|
||||
sb.AppendFormat("{0} total spare DNodes", hpfs_sp.spare_dnodes).AppendLine();
|
||||
sb.AppendFormat("Sector of codepage directory: {0}", hpfs_sp.codepage_lsn).AppendLine();
|
||||
sb.AppendFormat("{0} codepages used in the volume", hpfs_sp.codepages).AppendLine();
|
||||
sb.AppendFormat("SuperBlock CRC32: {0:X8}", hpfs_sp.sb_crc32).AppendLine();
|
||||
sb.AppendFormat("SpareBlock CRC32: {0:X8}", hpfs_sp.sp_crc32).AppendLine();
|
||||
|
||||
sb.AppendLine("Flags:");
|
||||
if ((hpfs_sp.flags1 & 0x01) == 0x01)
|
||||
sb.AppendLine("Filesystem is dirty.");
|
||||
else
|
||||
sb.AppendLine("Filesystem is clean.");
|
||||
if ((hpfs_sp.flags1 & 0x02) == 0x02)
|
||||
sb.AppendLine("Spare directory blocks are in use");
|
||||
if ((hpfs_sp.flags1 & 0x04) == 0x04)
|
||||
sb.AppendLine("Hotfixes are in use");
|
||||
if ((hpfs_sp.flags1 & 0x08) == 0x08)
|
||||
sb.AppendLine("Disk contains bad sectors");
|
||||
if ((hpfs_sp.flags1 & 0x10) == 0x10)
|
||||
sb.AppendLine("Disk has a bad bitmap");
|
||||
if ((hpfs_sp.flags1 & 0x20) == 0x20)
|
||||
sb.AppendLine("Filesystem was formatted fast");
|
||||
if ((hpfs_sp.flags1 & 0x40) == 0x40)
|
||||
sb.AppendLine("Unknown flag 0x40 on flags1 is active");
|
||||
if ((hpfs_sp.flags1 & 0x80) == 0x80)
|
||||
sb.AppendLine("Filesystem has been mounted by an old IFS");
|
||||
if ((hpfs_sp.flags2 & 0x01) == 0x01)
|
||||
sb.AppendLine("Install DASD limits");
|
||||
if ((hpfs_sp.flags2 & 0x02) == 0x02)
|
||||
sb.AppendLine("Resync DASD limits");
|
||||
if ((hpfs_sp.flags2 & 0x04) == 0x04)
|
||||
sb.AppendLine("DASD limits are operational");
|
||||
if ((hpfs_sp.flags2 & 0x08) == 0x08)
|
||||
sb.AppendLine("Multimedia is active");
|
||||
if ((hpfs_sp.flags2 & 0x10) == 0x10)
|
||||
sb.AppendLine("DCE ACLs are active");
|
||||
if ((hpfs_sp.flags2 & 0x20) == 0x20)
|
||||
sb.AppendLine("DASD limits are dirty");
|
||||
if ((hpfs_sp.flags2 & 0x40) == 0x40)
|
||||
sb.AppendLine("Unknown flag 0x40 on flags2 is active");
|
||||
if ((hpfs_sp.flags2 & 0x80) == 0x80)
|
||||
sb.AppendLine("Unknown flag 0x80 on flags2 is active");
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
struct HPFS_BIOSParameterBlock // Sector 0
|
||||
{
|
||||
public byte jmp1;
|
||||
// 0x000, Jump to boot code
|
||||
public UInt16 jmp2;
|
||||
// 0x001, ...;
|
||||
public string OEMName;
|
||||
// 0x003, OEM Name, 8 bytes, space-padded
|
||||
public UInt16 bps;
|
||||
// 0x00B, Bytes per sector
|
||||
public byte spc;
|
||||
// 0x00D, Sectors per cluster
|
||||
public UInt16 rsectors;
|
||||
// 0x00E, Reserved sectors between BPB and... does it have sense in HPFS?
|
||||
public byte fats_no;
|
||||
// 0x010, Number of FATs... seriously?
|
||||
public UInt16 root_ent;
|
||||
// 0x011, Number of entries on root directory... ok
|
||||
public UInt16 sectors;
|
||||
// 0x013, Sectors in volume... doubt it
|
||||
public byte media;
|
||||
// 0x015, Media descriptor
|
||||
public UInt16 spfat;
|
||||
// 0x016, Sectors per FAT... again
|
||||
public UInt16 sptrk;
|
||||
// 0x018, Sectors per track... you're kidding
|
||||
public UInt16 heads;
|
||||
// 0x01A, Heads... stop!
|
||||
public UInt32 hsectors;
|
||||
// 0x01C, Hidden sectors before BPB
|
||||
public UInt32 big_sectors;
|
||||
// 0x024, Sectors in volume if > 65535...
|
||||
public byte drive_no;
|
||||
// 0x028, Drive number
|
||||
public byte nt_flags;
|
||||
// 0x029, Volume flags?
|
||||
public byte signature;
|
||||
// 0x02A, EPB signature, 0x29
|
||||
public UInt32 serial_no;
|
||||
// 0x02B, Volume serial number
|
||||
public string volume_label;
|
||||
// 0x02F, Volume label, 11 bytes, space-padded
|
||||
public string fs_type;
|
||||
// 0x03A, Filesystem type, 8 bytes, space-padded ("HPFS ")
|
||||
}
|
||||
|
||||
struct HPFS_SuperBlock // Sector 16
|
||||
{
|
||||
public UInt32 magic1;
|
||||
// 0x000, 0xF995E849
|
||||
public UInt32 magic2;
|
||||
// 0x004, 0xFA53E9C5
|
||||
public byte version;
|
||||
// 0x008, HPFS version
|
||||
public byte func_version;
|
||||
// 0x009, 2 if <= 4 GiB, 3 if > 4 GiB
|
||||
public UInt16 dummy;
|
||||
// 0x00A, Alignment
|
||||
public UInt32 root_fnode;
|
||||
// 0x00C, LSN pointer to root fnode
|
||||
public UInt32 sectors;
|
||||
// 0x010, Sectors on volume
|
||||
public UInt32 badblocks;
|
||||
// 0x014, Bad blocks on volume
|
||||
public UInt32 bitmap_lsn;
|
||||
// 0x018, LSN pointer to volume bitmap
|
||||
public UInt32 zero1;
|
||||
// 0x01C, 0
|
||||
public UInt32 badblock_lsn;
|
||||
// 0x020, LSN pointer to badblock directory
|
||||
public UInt32 zero2;
|
||||
// 0x024, 0
|
||||
public Int32 last_chkdsk;
|
||||
// 0x028, Time of last CHKDSK
|
||||
public Int32 last_optim;
|
||||
// 0x02C, Time of last optimization
|
||||
public UInt32 dband_sectors;
|
||||
// 0x030, Sectors of dir band
|
||||
public UInt32 dband_start;
|
||||
// 0x034, Start sector of dir band
|
||||
public UInt32 dband_last;
|
||||
// 0x038, Last sector of dir band
|
||||
public UInt32 dband_bitmap;
|
||||
// 0x03C, LSN of free space bitmap
|
||||
public UInt64 zero3;
|
||||
// 0x040, Can be used for volume name (32 bytes)
|
||||
public UInt64 zero4;
|
||||
// 0x048, ...
|
||||
public UInt64 zero5;
|
||||
// 0x04C, ...
|
||||
public UInt64 zero6;
|
||||
// 0x050, ...;
|
||||
public UInt32 acl_start;
|
||||
// 0x058, LSN pointer to ACLs (only HPFS386)
|
||||
}
|
||||
|
||||
struct HPFS_SpareBlock // Sector 17
|
||||
{
|
||||
public UInt32 magic1;
|
||||
// 0x000, 0xF9911849
|
||||
public UInt32 magic2;
|
||||
// 0x004, 0xFA5229C5
|
||||
public byte flags1;
|
||||
// 0x008, HPFS flags
|
||||
public byte flags2;
|
||||
// 0x009, HPFS386 flags
|
||||
public UInt16 dummy;
|
||||
// 0x00A, Alignment
|
||||
public UInt32 hotfix_start;
|
||||
// 0x00C, LSN of hotfix directory
|
||||
public UInt32 hotfix_used;
|
||||
// 0x010, Used hotfixes
|
||||
public UInt32 hotfix_entries;
|
||||
// 0x014, Total hotfixes available
|
||||
public UInt32 spare_dnodes_free;
|
||||
// 0x018, Unused spare dnodes
|
||||
public UInt32 spare_dnodes;
|
||||
// 0x01C, Length of spare dnodes list
|
||||
public UInt32 codepage_lsn;
|
||||
// 0x020, LSN of codepage directory
|
||||
public UInt32 codepages;
|
||||
// 0x024, Number of codepages used
|
||||
public UInt32 sb_crc32;
|
||||
// 0x028, SuperBlock CRC32 (only HPFS386)
|
||||
public UInt32 sp_crc32;
|
||||
// 0x02C, SpareBlock CRC32 (only HPFS386)
|
||||
}
|
||||
}
|
||||
}
|
||||
899
DiscImageChef/Plugins/ISO9660.cs
Normal file
899
DiscImageChef/Plugins/ISO9660.cs
Normal file
@@ -0,0 +1,899 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ISO9660.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies ISO9660/ECMA-119 filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// 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 DiscImageChef.Plugins
|
||||
{
|
||||
class ISO9660Plugin : Plugin
|
||||
{
|
||||
static bool alreadyLaunched;
|
||||
|
||||
public ISO9660Plugin(PluginBase Core)
|
||||
{
|
||||
Name = "ISO9660 Filesystem";
|
||||
PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
alreadyLaunched = false;
|
||||
}
|
||||
|
||||
struct DecodedVolumeDescriptor
|
||||
{
|
||||
public string SystemIdentifier;
|
||||
public string VolumeIdentifier;
|
||||
public string VolumeSetIdentifier;
|
||||
public string PublisherIdentifier;
|
||||
public string DataPreparerIdentifier;
|
||||
public string ApplicationIdentifier;
|
||||
public DateTime CreationTime;
|
||||
public bool HasModificationTime;
|
||||
public DateTime ModificationTime;
|
||||
public bool HasExpirationTime;
|
||||
public DateTime ExpirationTime;
|
||||
public bool HasEffectiveTime;
|
||||
public DateTime EffectiveTime;
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
if (alreadyLaunched)
|
||||
return false;
|
||||
alreadyLaunched = true;
|
||||
|
||||
byte VDType;
|
||||
|
||||
// ISO9660 is designed for 2048 bytes/sector devices
|
||||
if (imagePlugin.GetSectorSize() < 2048)
|
||||
return false;
|
||||
|
||||
// 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;
|
||||
|
||||
Array.Copy(vd_sector, 0x001, VDMagic, 0, 5);
|
||||
|
||||
return Encoding.ASCII.GetString(VDMagic) == "CD001";
|
||||
}
|
||||
|
||||
public override void GetInformation (ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder ISOMetadata = new StringBuilder();
|
||||
bool Joliet = false;
|
||||
bool Bootable = false;
|
||||
bool RockRidge = false;
|
||||
byte VDType; // Volume Descriptor Type, should be 1 or 2.
|
||||
byte[] VDMagic = new byte[5]; // Volume Descriptor magic "CD001"
|
||||
byte[] VDSysId = new byte[32]; // System Identifier
|
||||
byte[] VDVolId = new byte[32]; // Volume Identifier
|
||||
byte[] VDVolSetId = new byte[128]; // Volume Set Identifier
|
||||
byte[] VDPubId = new byte[128]; // Publisher Identifier
|
||||
byte[] VDDataPrepId = new byte[128]; // Data Preparer Identifier
|
||||
byte[] VDAppId = new byte[128]; // Application Identifier
|
||||
byte[] VCTime = new byte[17]; // Volume Creation Date and Time
|
||||
byte[] VMTime = new byte[17]; // Volume Modification Date and Time
|
||||
byte[] VXTime = new byte[17]; // Volume Expiration Date and Time
|
||||
byte[] VETime = new byte[17]; // Volume Effective Date and Time
|
||||
|
||||
byte[] JolietMagic = new byte[3];
|
||||
byte[] JolietSysId = new byte[32]; // System Identifier
|
||||
byte[] JolietVolId = new byte[32]; // Volume Identifier
|
||||
byte[] JolietVolSetId = new byte[128]; // Volume Set Identifier
|
||||
byte[] JolietPubId = new byte[128]; // Publisher Identifier
|
||||
byte[] JolietDataPrepId = new byte[128]; // Data Preparer Identifier
|
||||
byte[] JolietAppId = new byte[128]; // Application Identifier
|
||||
byte[] JolietCTime = new byte[17]; // Volume Creation Date and Time
|
||||
byte[] JolietMTime = new byte[17]; // Volume Modification Date and Time
|
||||
byte[] JolietXTime = new byte[17]; // Volume Expiration Date and Time
|
||||
byte[] JolietETime = new byte[17]; // Volume Effective Date and Time
|
||||
|
||||
byte[] BootSysId = new byte[32];
|
||||
string BootSpec = "";
|
||||
|
||||
byte[] VDPathTableStart = new byte[4];
|
||||
byte[] RootDirectoryLocation = new byte[4];
|
||||
|
||||
// ISO9660 is designed for 2048 bytes/sector devices
|
||||
if (imagePlugin.GetSectorSize() < 2048)
|
||||
return;
|
||||
|
||||
// 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
|
||||
byte[] vd_sector = imagePlugin.ReadSector(16 + counter + partitionOffset);
|
||||
|
||||
VDType = vd_sector[0];
|
||||
|
||||
if (VDType == 255) // Supposedly we are in the PVD.
|
||||
{
|
||||
if (counter == 0)
|
||||
return;
|
||||
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.
|
||||
{
|
||||
if (counter == 0)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(VDType)
|
||||
{
|
||||
case 0: // TODO
|
||||
{
|
||||
Bootable = true;
|
||||
BootSpec = "Unknown";
|
||||
|
||||
// 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";
|
||||
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// Read first identifiers
|
||||
Array.Copy(vd_sector, 0x008, VDSysId, 0, 32);
|
||||
Array.Copy(vd_sector, 0x028, VDVolId, 0, 32);
|
||||
|
||||
// Get path table start
|
||||
Array.Copy(vd_sector, 0x08C, VDPathTableStart, 0, 4);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
Array.Copy(vd_sector, 0x058, JolietMagic, 0, 3);
|
||||
if (JolietMagic[0] == '%' && JolietMagic[1] == '/')
|
||||
{
|
||||
if (JolietMagic[2] == '@' || JolietMagic[2] == 'C' || JolietMagic[2] == 'E')
|
||||
{
|
||||
Joliet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
// Read first identifiers
|
||||
Array.Copy(vd_sector, 0x008, JolietSysId, 0, 32);
|
||||
Array.Copy(vd_sector, 0x028, JolietVolId, 0, 32);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor();
|
||||
DecodedVolumeDescriptor decodedJolietVD = new DecodedVolumeDescriptor();
|
||||
|
||||
decodedVD = DecodeVolumeDescriptor(VDSysId, VDVolId, VDVolSetId, VDPubId, VDDataPrepId, VDAppId, VCTime, VMTime, VXTime, VETime);
|
||||
if(Joliet)
|
||||
decodedJolietVD = DecodeJolietDescriptor(JolietSysId, JolietVolId, JolietVolSetId, JolietPubId, JolietDataPrepId, JolietAppId, JolietCTime, JolietMTime, JolietXTime, JolietETime);
|
||||
|
||||
|
||||
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
|
||||
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")
|
||||
{
|
||||
Array.Copy(root_dir, 0x29, RRMagic, 0, 2);
|
||||
RockRidge |= Encoding.ASCII.GetString(RRMagic) == "RR";
|
||||
}
|
||||
|
||||
#region SEGA IP.BIN Read and decoding
|
||||
|
||||
bool SegaCD = false;
|
||||
bool Saturn = false;
|
||||
bool Dreamcast = false;
|
||||
StringBuilder IPBinInformation = new StringBuilder();
|
||||
|
||||
byte[] SegaHardwareID = new byte[16];
|
||||
byte[] ipbin_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
Array.Copy(ipbin_sector, 0x000, SegaHardwareID, 0, 16);
|
||||
|
||||
switch (Encoding.ASCII.GetString(SegaHardwareID))
|
||||
{
|
||||
case "SEGADISCSYSTEM ":
|
||||
case "SEGADATADISC ":
|
||||
case "SEGAOS ":
|
||||
{
|
||||
SegaCD = true; // Ok, this contains SegaCD IP.BIN
|
||||
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:");
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Definitions following
|
||||
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
|
||||
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;
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "MMddyyyy", provider);
|
||||
|
||||
/*
|
||||
switch (Encoding.ASCII.GetString(application_type))
|
||||
{
|
||||
case "GM":
|
||||
IPBinInformation.AppendLine("Disc is a game.");
|
||||
break;
|
||||
case "AI":
|
||||
IPBinInformation.AppendLine("Disc is an application.");
|
||||
break;
|
||||
default:
|
||||
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();
|
||||
//IPBinInformation.AppendFormat("{0}", Encoding.ASCII.GetString(volume_type)).AppendLine();
|
||||
IPBinInformation.AppendFormat("System name: {0}", Encoding.ASCII.GetString(system_name)).AppendLine();
|
||||
//IPBinInformation.AppendFormat("System version: {0}", Encoding.ASCII.GetString(system_version)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program address: 0x{0}", BitConverter.ToInt32(ip_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program load size: {0} bytes", BitConverter.ToInt32(ip_loadsize, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program entry address: 0x{0}", BitConverter.ToInt32(ip_entry_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program work RAM: {0} bytes", BitConverter.ToInt32(ip_work_ram_size, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program address: 0x{0}", BitConverter.ToInt32(sp_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program load size: {0} bytes", BitConverter.ToInt32(sp_loadsize, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program entry address: 0x{0}", BitConverter.ToInt32(sp_entry_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program work RAM: {0} bytes", BitConverter.ToInt32(sp_work_ram_size, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date (other format): {0}", Encoding.ASCII.GetString(release_date2)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Hardware ID: {0}", Encoding.ASCII.GetString(hardware_id)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Developer code: {0}", Encoding.ASCII.GetString(developer_code)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Domestic title: {0}", Encoding.ASCII.GetString(domestic_title)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Overseas title: {0}", Encoding.ASCII.GetString(overseas_title)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product code: {0}", Encoding.ASCII.GetString(product_code)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Peripherals:").AppendLine();
|
||||
foreach(byte peripheral in peripherals)
|
||||
{
|
||||
switch((char)peripheral)
|
||||
{
|
||||
case 'A':
|
||||
IPBinInformation.AppendLine("Game supports analog controller.");
|
||||
break;
|
||||
case 'B':
|
||||
IPBinInformation.AppendLine("Game supports trackball.");
|
||||
break;
|
||||
case 'G':
|
||||
IPBinInformation.AppendLine("Game supports light gun.");
|
||||
break;
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Game supports JoyPad.");
|
||||
break;
|
||||
case 'K':
|
||||
IPBinInformation.AppendLine("Game supports keyboard.");
|
||||
break;
|
||||
case 'M':
|
||||
IPBinInformation.AppendLine("Game supports mouse.");
|
||||
break;
|
||||
case 'O':
|
||||
IPBinInformation.AppendLine("Game supports Master System's JoyPad.");
|
||||
break;
|
||||
case 'P':
|
||||
IPBinInformation.AppendLine("Game supports printer interface.");
|
||||
break;
|
||||
case 'R':
|
||||
IPBinInformation.AppendLine("Game supports serial (RS-232C) interface.");
|
||||
break;
|
||||
case 'T':
|
||||
IPBinInformation.AppendLine("Game supports tablet interface.");
|
||||
break;
|
||||
case 'V':
|
||||
IPBinInformation.AppendLine("Game supports paddle controller.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
IPBinInformation.AppendLine("Regions supported:");
|
||||
foreach (byte region in region_codes)
|
||||
{
|
||||
switch ((char)region)
|
||||
{
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Japanese NTSC.");
|
||||
break;
|
||||
case 'U':
|
||||
IPBinInformation.AppendLine("USA NTSC.");
|
||||
break;
|
||||
case 'E':
|
||||
IPBinInformation.AppendLine("Europe PAL.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "SEGA SEGASATURN ":
|
||||
{
|
||||
Saturn = true;
|
||||
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:");
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Definitions following
|
||||
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
|
||||
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;
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "yyyyMMdd", provider);
|
||||
IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(product_name)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product number: {0}", Encoding.ASCII.GetString(product_no)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(product_version)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine();
|
||||
IPBinInformation.AppendFormat("Disc number {0} of {1}", Encoding.ASCII.GetString(disc_no), Encoding.ASCII.GetString(disc_total_nos)).AppendLine();
|
||||
|
||||
IPBinInformation.AppendFormat("Peripherals:").AppendLine();
|
||||
foreach (byte peripheral in peripherals)
|
||||
{
|
||||
switch ((char)peripheral)
|
||||
{
|
||||
case 'A':
|
||||
IPBinInformation.AppendLine("Game supports analog controller.");
|
||||
break;
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Game supports JoyPad.");
|
||||
break;
|
||||
case 'K':
|
||||
IPBinInformation.AppendLine("Game supports keyboard.");
|
||||
break;
|
||||
case 'M':
|
||||
IPBinInformation.AppendLine("Game supports mouse.");
|
||||
break;
|
||||
case 'S':
|
||||
IPBinInformation.AppendLine("Game supports analog steering controller.");
|
||||
break;
|
||||
case 'T':
|
||||
IPBinInformation.AppendLine("Game supports multitap.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
IPBinInformation.AppendLine("Regions supported:");
|
||||
foreach (byte region in region_codes)
|
||||
{
|
||||
switch ((char)region)
|
||||
{
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Japanese NTSC.");
|
||||
break;
|
||||
case 'U':
|
||||
IPBinInformation.AppendLine("North America NTSC.");
|
||||
break;
|
||||
case 'E':
|
||||
IPBinInformation.AppendLine("Europe PAL.");
|
||||
break;
|
||||
case 'T':
|
||||
IPBinInformation.AppendLine("Asia NTSC.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "SEGA SEGAKATANA ":
|
||||
{
|
||||
Dreamcast = true;
|
||||
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:");
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Declarations following
|
||||
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
|
||||
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;
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "yyyyMMdd", provider);
|
||||
IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(product_name)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(product_version)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Producer: {0}", Encoding.ASCII.GetString(producer)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Disc media: {0}", Encoding.ASCII.GetString(dreamcast_media)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Disc number {0} of {1}", Encoding.ASCII.GetString(disc_no), Encoding.ASCII.GetString(disc_total_nos)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine();
|
||||
switch (Encoding.ASCII.GetString(boot_filename))
|
||||
{
|
||||
case "1ST_READ.BIN":
|
||||
IPBinInformation.AppendLine("Disc boots natively.");
|
||||
break;
|
||||
case "0WINCE.BIN ":
|
||||
IPBinInformation.AppendLine("Disc boots using Windows CE.");
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Disc boots using unknown loader: {0}.", Encoding.ASCII.GetString(boot_filename)).AppendLine();
|
||||
break;
|
||||
}
|
||||
IPBinInformation.AppendLine("Regions supported:");
|
||||
foreach (byte region in region_codes)
|
||||
{
|
||||
switch ((char)region)
|
||||
{
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Japanese NTSC.");
|
||||
break;
|
||||
case 'U':
|
||||
IPBinInformation.AppendLine("North America NTSC.");
|
||||
break;
|
||||
case 'E':
|
||||
IPBinInformation.AppendLine("Europe PAL.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int iPeripherals = BitConverter.ToInt32(peripherals, 0);
|
||||
|
||||
if((iPeripherals & 0x00000010) == 0x00000010)
|
||||
IPBinInformation.AppendLine("Game uses Windows CE.");
|
||||
|
||||
IPBinInformation.AppendFormat("Peripherals:").AppendLine();
|
||||
|
||||
if ((iPeripherals & 0x00000100) == 0x00000100)
|
||||
IPBinInformation.AppendLine("Game supports the VGA Box.");
|
||||
if ((iPeripherals & 0x00001000) == 0x00001000)
|
||||
IPBinInformation.AppendLine("Game supports other expansion.");
|
||||
if ((iPeripherals & 0x00002000) == 0x00002000)
|
||||
IPBinInformation.AppendLine("Game supports Puru Puru pack.");
|
||||
if ((iPeripherals & 0x00004000) == 0x00004000)
|
||||
IPBinInformation.AppendLine("Game supports Mike Device.");
|
||||
if ((iPeripherals & 0x00008000) == 0x00008000)
|
||||
IPBinInformation.AppendLine("Game supports Memory Card.");
|
||||
if ((iPeripherals & 0x00010000) == 0x00010000)
|
||||
IPBinInformation.AppendLine("Game requires A + B + Start buttons and D-Pad.");
|
||||
if ((iPeripherals & 0x00020000) == 0x00020000)
|
||||
IPBinInformation.AppendLine("Game requires C button.");
|
||||
if ((iPeripherals & 0x00040000) == 0x00040000)
|
||||
IPBinInformation.AppendLine("Game requires D button.");
|
||||
if ((iPeripherals & 0x00080000) == 0x00080000)
|
||||
IPBinInformation.AppendLine("Game requires X button.");
|
||||
if ((iPeripherals & 0x00100000) == 0x00100000)
|
||||
IPBinInformation.AppendLine("Game requires Y button.");
|
||||
if ((iPeripherals & 0x00200000) == 0x00200000)
|
||||
IPBinInformation.AppendLine("Game requires Z button.");
|
||||
if ((iPeripherals & 0x00400000) == 0x00400000)
|
||||
IPBinInformation.AppendLine("Game requires expanded direction buttons.");
|
||||
if ((iPeripherals & 0x00800000) == 0x00800000)
|
||||
IPBinInformation.AppendLine("Game requires analog R trigger.");
|
||||
if ((iPeripherals & 0x01000000) == 0x01000000)
|
||||
IPBinInformation.AppendLine("Game requires analog L trigger.");
|
||||
if ((iPeripherals & 0x02000000) == 0x02000000)
|
||||
IPBinInformation.AppendLine("Game requires analog horizontal controller.");
|
||||
if ((iPeripherals & 0x04000000) == 0x04000000)
|
||||
IPBinInformation.AppendLine("Game requires analog vertical controller.");
|
||||
if ((iPeripherals & 0x08000000) == 0x08000000)
|
||||
IPBinInformation.AppendLine("Game requires expanded analog horizontal controller.");
|
||||
if ((iPeripherals & 0x10000000) == 0x10000000)
|
||||
IPBinInformation.AppendLine("Game requires expanded analog vertical controller.");
|
||||
if ((iPeripherals & 0x20000000) == 0x20000000)
|
||||
IPBinInformation.AppendLine("Game supports Gun.");
|
||||
if ((iPeripherals & 0x40000000) == 0x40000000)
|
||||
IPBinInformation.AppendLine("Game supports Keyboard.");
|
||||
if ((iPeripherals & 0x80000000) == 0x80000000)
|
||||
IPBinInformation.AppendLine("Game supports Mouse.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
ISOMetadata.AppendFormat("ISO9660 file system").AppendLine();
|
||||
if(Joliet)
|
||||
ISOMetadata.AppendFormat("Joliet extensions present.").AppendLine();
|
||||
if (RockRidge)
|
||||
ISOMetadata.AppendFormat("Rock Ridge Interchange Protocol present.").AppendLine();
|
||||
if (Bootable)
|
||||
ISOMetadata.AppendFormat("Disc bootable following {0} specifications.", BootSpec).AppendLine();
|
||||
if (SegaCD)
|
||||
{
|
||||
ISOMetadata.AppendLine("This is a SegaCD / MegaCD disc.");
|
||||
ISOMetadata.AppendLine(IPBinInformation.ToString());
|
||||
}
|
||||
if (Saturn)
|
||||
{
|
||||
ISOMetadata.AppendLine("This is a Sega Saturn disc.");
|
||||
ISOMetadata.AppendLine(IPBinInformation.ToString());
|
||||
}
|
||||
if (Dreamcast)
|
||||
{
|
||||
ISOMetadata.AppendLine("This is a Sega Dreamcast disc.");
|
||||
ISOMetadata.AppendLine(IPBinInformation.ToString());
|
||||
}
|
||||
ISOMetadata.AppendLine("--------------------------------");
|
||||
ISOMetadata.AppendLine("VOLUME DESCRIPTOR INFORMATION:");
|
||||
ISOMetadata.AppendLine("--------------------------------");
|
||||
ISOMetadata.AppendFormat("System identifier: {0}", decodedVD.SystemIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume identifier: {0}", decodedVD.VolumeIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume set identifier: {0}", decodedVD.VolumeSetIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Publisher identifier: {0}", decodedVD.PublisherIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Data preparer identifier: {0}", decodedVD.DataPreparerIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Application identifier: {0}", decodedVD.ApplicationIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume creation date: {0}", decodedVD.CreationTime).AppendLine();
|
||||
if (decodedVD.HasModificationTime)
|
||||
ISOMetadata.AppendFormat("Volume modification date: {0}", decodedVD.ModificationTime).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume has not been modified.").AppendLine();
|
||||
if (decodedVD.HasExpirationTime)
|
||||
ISOMetadata.AppendFormat("Volume expiration date: {0}", decodedVD.ExpirationTime).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume does not expire.").AppendLine();
|
||||
if (decodedVD.HasEffectiveTime)
|
||||
ISOMetadata.AppendFormat("Volume effective date: {0}", decodedVD.EffectiveTime).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume has always been effective.").AppendLine();
|
||||
|
||||
if(Joliet)
|
||||
{
|
||||
ISOMetadata.AppendLine("---------------------------------------");
|
||||
ISOMetadata.AppendLine("JOLIET VOLUME DESCRIPTOR INFORMATION:");
|
||||
ISOMetadata.AppendLine("---------------------------------------");
|
||||
ISOMetadata.AppendFormat("System identifier: {0}", decodedJolietVD.SystemIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume identifier: {0}", decodedJolietVD.VolumeIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume set identifier: {0}", decodedJolietVD.VolumeSetIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Publisher identifier: {0}", decodedJolietVD.PublisherIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Data preparer identifier: {0}", decodedJolietVD.DataPreparerIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Application identifier: {0}", decodedJolietVD.ApplicationIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume creation date: {0}", decodedJolietVD.CreationTime).AppendLine();
|
||||
if (decodedJolietVD.HasModificationTime)
|
||||
ISOMetadata.AppendFormat("Volume modification date: {0}", decodedJolietVD.ModificationTime).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume has not been modified.").AppendLine();
|
||||
if (decodedJolietVD.HasExpirationTime)
|
||||
ISOMetadata.AppendFormat("Volume expiration date: {0}", decodedJolietVD.ExpirationTime).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume does not expire.").AppendLine();
|
||||
if (decodedJolietVD.HasEffectiveTime)
|
||||
ISOMetadata.AppendFormat("Volume effective date: {0}", decodedJolietVD.EffectiveTime).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume has always been effective.").AppendLine();
|
||||
}
|
||||
|
||||
information = ISOMetadata.ToString();
|
||||
}
|
||||
|
||||
static DecodedVolumeDescriptor DecodeJolietDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime)
|
||||
{
|
||||
DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor();
|
||||
|
||||
decodedVD.SystemIdentifier = Encoding.BigEndianUnicode.GetString(VDSysId);
|
||||
decodedVD.VolumeIdentifier = Encoding.BigEndianUnicode.GetString(VDVolId);
|
||||
decodedVD.VolumeSetIdentifier = Encoding.BigEndianUnicode.GetString(VDVolSetId);
|
||||
decodedVD.PublisherIdentifier = Encoding.BigEndianUnicode.GetString(VDPubId);
|
||||
decodedVD.DataPreparerIdentifier = Encoding.BigEndianUnicode.GetString(VDDataPrepId);
|
||||
decodedVD.ApplicationIdentifier = Encoding.BigEndianUnicode.GetString(VDAppId);
|
||||
if (VCTime[0] == '0' || VCTime[0] == 0x00)
|
||||
decodedVD.CreationTime = DateTime.MinValue;
|
||||
else
|
||||
decodedVD.CreationTime = DateHandlers.ISO9660ToDateTime(VCTime);
|
||||
|
||||
if (VMTime[0] == '0' || VMTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasModificationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasModificationTime = true;
|
||||
decodedVD.ModificationTime = DateHandlers.ISO9660ToDateTime(VMTime);
|
||||
}
|
||||
|
||||
if (VXTime[0] == '0' || VXTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasExpirationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasExpirationTime = true;
|
||||
decodedVD.ExpirationTime = DateHandlers.ISO9660ToDateTime(VXTime);
|
||||
}
|
||||
|
||||
if (VETime[0] == '0' || VETime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasEffectiveTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasEffectiveTime = true;
|
||||
decodedVD.EffectiveTime = DateHandlers.ISO9660ToDateTime(VETime);
|
||||
}
|
||||
|
||||
return decodedVD;
|
||||
}
|
||||
|
||||
static DecodedVolumeDescriptor DecodeVolumeDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime)
|
||||
{
|
||||
DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor();
|
||||
|
||||
decodedVD.SystemIdentifier = Encoding.ASCII.GetString(VDSysId);
|
||||
decodedVD.VolumeIdentifier = Encoding.ASCII.GetString(VDVolId);
|
||||
decodedVD.VolumeSetIdentifier = Encoding.ASCII.GetString(VDVolSetId);
|
||||
decodedVD.PublisherIdentifier = Encoding.ASCII.GetString(VDPubId);
|
||||
decodedVD.DataPreparerIdentifier = Encoding.ASCII.GetString(VDDataPrepId);
|
||||
decodedVD.ApplicationIdentifier = Encoding.ASCII.GetString(VDAppId);
|
||||
if (VCTime[0] == '0' || VCTime[0] == 0x00)
|
||||
decodedVD.CreationTime = DateTime.MinValue;
|
||||
else
|
||||
decodedVD.CreationTime = DateHandlers.ISO9660ToDateTime(VCTime);
|
||||
|
||||
if (VMTime[0] == '0' || VMTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasModificationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasModificationTime = true;
|
||||
decodedVD.ModificationTime = DateHandlers.ISO9660ToDateTime(VMTime);
|
||||
}
|
||||
|
||||
if (VXTime[0] == '0' || VXTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasExpirationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasExpirationTime = true;
|
||||
decodedVD.ExpirationTime = DateHandlers.ISO9660ToDateTime(VXTime);
|
||||
}
|
||||
|
||||
if (VETime[0] == '0' || VETime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasEffectiveTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasEffectiveTime = true;
|
||||
decodedVD.EffectiveTime = DateHandlers.ISO9660ToDateTime(VETime);
|
||||
}
|
||||
|
||||
return decodedVD;
|
||||
}
|
||||
}
|
||||
}
|
||||
572
DiscImageChef/Plugins/LisaFS.cs
Normal file
572
DiscImageChef/Plugins/LisaFS.cs
Normal file
@@ -0,0 +1,572 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : LisaFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies Apple Lisa filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
|
||||
// All information by Natalia Portillo
|
||||
// Variable names from Lisa API
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class LisaFS : Plugin
|
||||
{
|
||||
const byte LisaFSv1 = 0x0E;
|
||||
const byte LisaFSv2 = 0x0F;
|
||||
const byte LisaFSv3 = 0x11;
|
||||
const uint E_NAME = 32;
|
||||
// Maximum string size in LisaFS
|
||||
const UInt16 FILEID_FREE = 0x0000;
|
||||
const UInt16 FILEID_BOOT = 0xAAAA;
|
||||
const UInt16 FILEID_LOADER = 0xBBBB;
|
||||
const UInt16 FILEID_MDDF = 0x0001;
|
||||
const UInt16 FILEID_BITMAP = 0x0002;
|
||||
const UInt16 FILEID_SRECORD = 0x0003;
|
||||
const UInt16 FILEID_DIRECTORY = 0x0004;
|
||||
// "Catalog file"
|
||||
const UInt16 FILEID_ERASED = 0x7FFF;
|
||||
const UInt16 FILEID_MAX = FILEID_ERASED;
|
||||
|
||||
public LisaFS(PluginBase Core)
|
||||
{
|
||||
Name = "Apple Lisa File System";
|
||||
PluginUUID = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
try
|
||||
{
|
||||
// LisaOS is big-endian
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
// Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
|
||||
if (imagePlugin.GetSectors() < 800)
|
||||
return false;
|
||||
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
byte[] tag = imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
UInt16 fileid = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): Sector {0}, file ID 0x{1:X4}", i, fileid);
|
||||
|
||||
if (fileid == FILEID_MDDF)
|
||||
{
|
||||
byte[] sector = imagePlugin.ReadSector((ulong)i);
|
||||
Lisa_MDDF mddf = new Lisa_MDDF();
|
||||
|
||||
mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
|
||||
mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
|
||||
mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
|
||||
mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78);
|
||||
mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C);
|
||||
mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E);
|
||||
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): Current sector = {0}", i);
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): mddf.mddf_block = {0}", mddf.mddf_block);
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): Disk size = {0} sectors", imagePlugin.GetSectors());
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): mddf.vol_size = {0} sectors", mddf.vol_size);
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): mddf.vol_size - 1 = {0}", mddf.volsize_minus_one);
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): mddf.vol_size - mddf.mddf_block -1 = {0}", mddf.volsize_minus_mddf_minus_one);
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): Disk sector = {0} bytes", imagePlugin.GetSectorSize());
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): mddf.blocksize = {0} bytes", mddf.blocksize);
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): mddf.datasize = {0} bytes", mddf.datasize);
|
||||
}
|
||||
|
||||
if (mddf.mddf_block != i)
|
||||
return false;
|
||||
|
||||
if (mddf.vol_size > imagePlugin.GetSectors())
|
||||
return false;
|
||||
|
||||
if (mddf.vol_size - 1 != mddf.volsize_minus_one)
|
||||
return false;
|
||||
|
||||
if (mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one)
|
||||
return false;
|
||||
|
||||
if (mddf.datasize > mddf.blocksize)
|
||||
return false;
|
||||
|
||||
if (mddf.blocksize < imagePlugin.GetSectorSize())
|
||||
return false;
|
||||
|
||||
if (mddf.datasize != imagePlugin.GetSectorSize())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): Exception {0}, {1}, {2}", ex.Message, ex.InnerException, ex.StackTrace);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try
|
||||
{
|
||||
// LisaOS is big-endian
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
// Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
|
||||
if (imagePlugin.GetSectors() < 800)
|
||||
return;
|
||||
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
byte[] tag = imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag);
|
||||
UInt16 fileid = BigEndianBitConverter.ToUInt16(tag, 0x04);
|
||||
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): Sector {0}, file ID 0x{1:X4}", i, fileid);
|
||||
|
||||
if (fileid == FILEID_MDDF)
|
||||
{
|
||||
byte[] sector = imagePlugin.ReadSector((ulong)i);
|
||||
Lisa_MDDF mddf = new Lisa_MDDF();
|
||||
byte[] pString = new byte[33];
|
||||
UInt32 lisa_time;
|
||||
|
||||
mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
|
||||
mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02);
|
||||
mddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A);
|
||||
Array.Copy(sector, 0x0C, pString, 0, 33);
|
||||
mddf.volname = StringHandlers.PascalToString(pString);
|
||||
mddf.unknown1 = sector[0x2D];
|
||||
Array.Copy(sector, 0x2E, pString, 0, 33);
|
||||
// Prevent garbage
|
||||
if (pString[0] <= 32)
|
||||
mddf.password = StringHandlers.PascalToString(pString);
|
||||
else
|
||||
mddf.password = "";
|
||||
mddf.unknown2 = sector[0x4F];
|
||||
mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50);
|
||||
mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x58);
|
||||
mddf.dtvc = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x5C);
|
||||
mddf.dtcc = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x60);
|
||||
mddf.dtvb = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x64);
|
||||
mddf.dtvs = DateHandlers.LisaToDateTime(lisa_time);
|
||||
mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68);
|
||||
mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
|
||||
mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
|
||||
mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
|
||||
mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78);
|
||||
mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C);
|
||||
mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E);
|
||||
mddf.unknown4 = BigEndianBitConverter.ToUInt16(sector, 0x80);
|
||||
mddf.unknown5 = BigEndianBitConverter.ToUInt32(sector, 0x82);
|
||||
mddf.unknown6 = BigEndianBitConverter.ToUInt32(sector, 0x86);
|
||||
mddf.clustersize = BigEndianBitConverter.ToUInt16(sector, 0x8A);
|
||||
mddf.fs_size = BigEndianBitConverter.ToUInt32(sector, 0x8C);
|
||||
mddf.unknown7 = BigEndianBitConverter.ToUInt32(sector, 0x90);
|
||||
mddf.unknown8 = BigEndianBitConverter.ToUInt32(sector, 0x94);
|
||||
mddf.unknown9 = BigEndianBitConverter.ToUInt32(sector, 0x98);
|
||||
mddf.unknown10 = BigEndianBitConverter.ToUInt32(sector, 0x9C);
|
||||
mddf.unknown11 = BigEndianBitConverter.ToUInt32(sector, 0xA0);
|
||||
mddf.unknown12 = BigEndianBitConverter.ToUInt32(sector, 0xA4);
|
||||
mddf.unknown13 = BigEndianBitConverter.ToUInt32(sector, 0xA8);
|
||||
mddf.unknown14 = BigEndianBitConverter.ToUInt32(sector, 0xAC);
|
||||
mddf.filecount = BigEndianBitConverter.ToUInt16(sector, 0xB0);
|
||||
mddf.unknown15 = BigEndianBitConverter.ToUInt32(sector, 0xB2);
|
||||
mddf.unknown16 = BigEndianBitConverter.ToUInt32(sector, 0xB6);
|
||||
mddf.freecount = BigEndianBitConverter.ToUInt32(sector, 0xBA);
|
||||
mddf.unknown17 = BigEndianBitConverter.ToUInt16(sector, 0xBE);
|
||||
mddf.unknown18 = BigEndianBitConverter.ToUInt32(sector, 0xC0);
|
||||
mddf.overmount_stamp = BigEndianBitConverter.ToUInt64(sector, 0xC4);
|
||||
mddf.serialization = BigEndianBitConverter.ToUInt32(sector, 0xCC);
|
||||
mddf.unknown19 = BigEndianBitConverter.ToUInt32(sector, 0xD0);
|
||||
mddf.unknown_timestamp = BigEndianBitConverter.ToUInt32(sector, 0xD4);
|
||||
mddf.unknown20 = BigEndianBitConverter.ToUInt32(sector, 0xD8);
|
||||
mddf.unknown21 = BigEndianBitConverter.ToUInt32(sector, 0xDC);
|
||||
mddf.unknown22 = BigEndianBitConverter.ToUInt32(sector, 0xE0);
|
||||
mddf.unknown23 = BigEndianBitConverter.ToUInt32(sector, 0xE4);
|
||||
mddf.unknown24 = BigEndianBitConverter.ToUInt32(sector, 0xE8);
|
||||
mddf.unknown25 = BigEndianBitConverter.ToUInt32(sector, 0xEC);
|
||||
mddf.unknown26 = BigEndianBitConverter.ToUInt32(sector, 0xF0);
|
||||
mddf.unknown27 = BigEndianBitConverter.ToUInt32(sector, 0xF4);
|
||||
mddf.unknown28 = BigEndianBitConverter.ToUInt32(sector, 0xF8);
|
||||
mddf.unknown29 = BigEndianBitConverter.ToUInt32(sector, 0xFC);
|
||||
mddf.unknown30 = BigEndianBitConverter.ToUInt32(sector, 0x100);
|
||||
mddf.unknown31 = BigEndianBitConverter.ToUInt32(sector, 0x104);
|
||||
mddf.unknown32 = BigEndianBitConverter.ToUInt32(sector, 0x108);
|
||||
mddf.unknown33 = BigEndianBitConverter.ToUInt32(sector, 0x10C);
|
||||
mddf.unknown34 = BigEndianBitConverter.ToUInt32(sector, 0x110);
|
||||
mddf.unknown35 = BigEndianBitConverter.ToUInt32(sector, 0x114);
|
||||
mddf.backup_volid = BigEndianBitConverter.ToUInt64(sector, 0x118);
|
||||
mddf.label_size = BigEndianBitConverter.ToUInt16(sector, 0x120);
|
||||
mddf.fs_overhead = BigEndianBitConverter.ToUInt16(sector, 0x122);
|
||||
mddf.result_scavenge = BigEndianBitConverter.ToUInt16(sector, 0x124);
|
||||
mddf.boot_code = BigEndianBitConverter.ToUInt16(sector, 0x126);
|
||||
mddf.boot_environ = BigEndianBitConverter.ToUInt16(sector, 0x6C);
|
||||
mddf.unknown36 = BigEndianBitConverter.ToUInt32(sector, 0x12A);
|
||||
mddf.unknown37 = BigEndianBitConverter.ToUInt32(sector, 0x12E);
|
||||
mddf.unknown38 = BigEndianBitConverter.ToUInt32(sector, 0x132);
|
||||
mddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136);
|
||||
mddf.vol_left_mounted = sector[0x138];
|
||||
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("mddf.unknown1 = 0x{0:X2} ({0})", mddf.unknown1);
|
||||
Console.WriteLine("mddf.unknown2 = 0x{0:X2} ({0})", mddf.unknown2);
|
||||
Console.WriteLine("mddf.unknown3 = 0x{0:X8} ({0})", mddf.unknown3);
|
||||
Console.WriteLine("mddf.unknown4 = 0x{0:X4} ({0})", mddf.unknown4);
|
||||
Console.WriteLine("mddf.unknown5 = 0x{0:X8} ({0})", mddf.unknown5);
|
||||
Console.WriteLine("mddf.unknown6 = 0x{0:X8} ({0})", mddf.unknown6);
|
||||
Console.WriteLine("mddf.unknown7 = 0x{0:X8} ({0})", mddf.unknown7);
|
||||
Console.WriteLine("mddf.unknown8 = 0x{0:X8} ({0})", mddf.unknown8);
|
||||
Console.WriteLine("mddf.unknown9 = 0x{0:X8} ({0})", mddf.unknown9);
|
||||
Console.WriteLine("mddf.unknown10 = 0x{0:X8} ({0})", mddf.unknown10);
|
||||
Console.WriteLine("mddf.unknown11 = 0x{0:X8} ({0})", mddf.unknown11);
|
||||
Console.WriteLine("mddf.unknown12 = 0x{0:X8} ({0})", mddf.unknown12);
|
||||
Console.WriteLine("mddf.unknown13 = 0x{0:X8} ({0})", mddf.unknown13);
|
||||
Console.WriteLine("mddf.unknown14 = 0x{0:X8} ({0})", mddf.unknown14);
|
||||
Console.WriteLine("mddf.unknown15 = 0x{0:X8} ({0})", mddf.unknown15);
|
||||
Console.WriteLine("mddf.unknown16 = 0x{0:X8} ({0})", mddf.unknown16);
|
||||
Console.WriteLine("mddf.unknown17 = 0x{0:X4} ({0})", mddf.unknown17);
|
||||
Console.WriteLine("mddf.unknown18 = 0x{0:X8} ({0})", mddf.unknown18);
|
||||
Console.WriteLine("mddf.unknown19 = 0x{0:X8} ({0})", mddf.unknown19);
|
||||
Console.WriteLine("mddf.unknown20 = 0x{0:X8} ({0})", mddf.unknown20);
|
||||
Console.WriteLine("mddf.unknown21 = 0x{0:X8} ({0})", mddf.unknown21);
|
||||
Console.WriteLine("mddf.unknown22 = 0x{0:X8} ({0})", mddf.unknown22);
|
||||
Console.WriteLine("mddf.unknown23 = 0x{0:X8} ({0})", mddf.unknown23);
|
||||
Console.WriteLine("mddf.unknown24 = 0x{0:X8} ({0})", mddf.unknown24);
|
||||
Console.WriteLine("mddf.unknown25 = 0x{0:X8} ({0})", mddf.unknown25);
|
||||
Console.WriteLine("mddf.unknown26 = 0x{0:X8} ({0})", mddf.unknown26);
|
||||
Console.WriteLine("mddf.unknown27 = 0x{0:X8} ({0})", mddf.unknown27);
|
||||
Console.WriteLine("mddf.unknown28 = 0x{0:X8} ({0})", mddf.unknown28);
|
||||
Console.WriteLine("mddf.unknown29 = 0x{0:X8} ({0})", mddf.unknown29);
|
||||
Console.WriteLine("mddf.unknown30 = 0x{0:X8} ({0})", mddf.unknown30);
|
||||
Console.WriteLine("mddf.unknown31 = 0x{0:X8} ({0})", mddf.unknown31);
|
||||
Console.WriteLine("mddf.unknown32 = 0x{0:X8} ({0})", mddf.unknown32);
|
||||
Console.WriteLine("mddf.unknown33 = 0x{0:X8} ({0})", mddf.unknown33);
|
||||
Console.WriteLine("mddf.unknown34 = 0x{0:X8} ({0})", mddf.unknown34);
|
||||
Console.WriteLine("mddf.unknown35 = 0x{0:X8} ({0})", mddf.unknown35);
|
||||
Console.WriteLine("mddf.unknown36 = 0x{0:X8} ({0})", mddf.unknown36);
|
||||
Console.WriteLine("mddf.unknown37 = 0x{0:X8} ({0})", mddf.unknown37);
|
||||
Console.WriteLine("mddf.unknown38 = 0x{0:X8} ({0})", mddf.unknown38);
|
||||
Console.WriteLine("mddf.unknown_timestamp = 0x{0:X8} ({0}, {1})", mddf.unknown_timestamp, DateHandlers.LisaToDateTime(mddf.unknown_timestamp));
|
||||
}
|
||||
|
||||
if (mddf.mddf_block != i)
|
||||
return;
|
||||
|
||||
if (mddf.vol_size > imagePlugin.GetSectors())
|
||||
return;
|
||||
|
||||
if (mddf.vol_size - 1 != mddf.volsize_minus_one)
|
||||
return;
|
||||
|
||||
if (mddf.vol_size - i - 1 != mddf.volsize_minus_mddf_minus_one)
|
||||
return;
|
||||
|
||||
if (mddf.datasize > mddf.blocksize)
|
||||
return;
|
||||
|
||||
if (mddf.blocksize < imagePlugin.GetSectorSize())
|
||||
return;
|
||||
|
||||
if (mddf.datasize != imagePlugin.GetSectorSize())
|
||||
return;
|
||||
|
||||
switch (mddf.fsversion)
|
||||
{
|
||||
case LisaFSv1:
|
||||
sb.AppendLine("LisaFS v1");
|
||||
break;
|
||||
case LisaFSv2:
|
||||
sb.AppendLine("LisaFS v2");
|
||||
break;
|
||||
case LisaFSv3:
|
||||
sb.AppendLine("LisaFS v3");
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Uknown LisaFS version {0}", mddf.fsversion).AppendLine();
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("Volume name: \"{0}\"", mddf.volname).AppendLine();
|
||||
sb.AppendFormat("Volume password: \"{0}\"", mddf.password).AppendLine();
|
||||
sb.AppendFormat("Volume ID: 0x{0:X16}", mddf.volid).AppendLine();
|
||||
sb.AppendFormat("Backup volume ID: 0x{0:X16}", mddf.backup_volid).AppendLine();
|
||||
|
||||
sb.AppendFormat("Master copy ID: 0x{0:X8}", mddf.master_copy_id).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume is number {0} of {1}", mddf.volnum, mddf.vol_sequence).AppendLine();
|
||||
|
||||
sb.AppendFormat("Serial number of Lisa computer that created this volume: {0}", mddf.machine_id).AppendLine();
|
||||
sb.AppendFormat("Serial number of Lisa computer that can use this volume's software {0}", mddf.serialization).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume created on {0}", mddf.dtvc).AppendLine();
|
||||
sb.AppendFormat("Some timestamp, says {0}", mddf.dtcc).AppendLine();
|
||||
sb.AppendFormat("Volume backed up on {0}", mddf.dtvb).AppendLine();
|
||||
sb.AppendFormat("Volume scavenged on {0}", mddf.dtvs).AppendLine();
|
||||
sb.AppendFormat("MDDF is in block {0}", mddf.mddf_block).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one", mddf.volsize_minus_one).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one minus MDDF offset", mddf.volsize_minus_mddf_minus_one).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", mddf.vol_size).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector (uncooked)", mddf.blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", mddf.datasize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per cluster", mddf.clustersize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in filesystem", mddf.fs_size).AppendLine();
|
||||
sb.AppendFormat("{0} files in volume", mddf.filecount).AppendLine();
|
||||
sb.AppendFormat("{0} blocks free", mddf.freecount).AppendLine();
|
||||
sb.AppendFormat("{0} bytes in LisaInfo", mddf.label_size).AppendLine();
|
||||
sb.AppendFormat("Filesystem overhead: {0}", mddf.fs_overhead).AppendLine();
|
||||
sb.AppendFormat("Scanvenger result code: 0x{0:X8}", mddf.result_scavenge).AppendLine();
|
||||
sb.AppendFormat("Boot code: 0x{0:X8}", mddf.boot_code).AppendLine();
|
||||
sb.AppendFormat("Boot environment: 0x{0:X8}", mddf.boot_environ).AppendLine();
|
||||
sb.AppendFormat("Overmount stamp: 0x{0:X16}", mddf.overmount_stamp).AppendLine();
|
||||
|
||||
if (mddf.vol_left_mounted == 0)
|
||||
sb.AppendLine("Volume is clean");
|
||||
else
|
||||
sb.AppendLine("Volume is dirty");
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (LisaFS plugin): Exception {0}, {1}, {2}", ex.Message, ex.InnerException, ex.StackTrace);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct Lisa_MDDF
|
||||
{
|
||||
// 0x00, Filesystem version
|
||||
public UInt16 fsversion;
|
||||
// 0x02, Volume ID
|
||||
public UInt64 volid;
|
||||
// 0x0A, Volume sequence number
|
||||
public UInt16 volnum;
|
||||
// 0x0C, Pascal string, 32+1 bytes, volume name
|
||||
public string volname;
|
||||
// 0x2D, unknown, possible padding
|
||||
public byte unknown1;
|
||||
// 0x2E, Pascal string, 32+1 bytes, password
|
||||
public string password;
|
||||
// 0x4F, unknown, possible padding
|
||||
public byte unknown2;
|
||||
// 0x50, Lisa serial number that init'ed this disk
|
||||
public UInt32 machine_id;
|
||||
// 0x54, ID of the master copy ? no idea really
|
||||
public UInt32 master_copy_id;
|
||||
// 0x58, Date of volume creation
|
||||
public DateTime dtvc;
|
||||
// 0x5C, Date...
|
||||
public DateTime dtcc;
|
||||
// 0x60, Date of volume backup
|
||||
public DateTime dtvb;
|
||||
// 0x64, Date of volume scavenging
|
||||
public DateTime dtvs;
|
||||
// 0x68, unknown
|
||||
public UInt32 unknown3;
|
||||
// 0x6C, block the MDDF is residing on
|
||||
public UInt32 mddf_block;
|
||||
// 0x70, volsize-1
|
||||
public UInt32 volsize_minus_one;
|
||||
// 0x74, volsize-1-mddf_block
|
||||
public UInt32 volsize_minus_mddf_minus_one;
|
||||
// 0x78, Volume size in blocks
|
||||
public UInt32 vol_size;
|
||||
// 0x7C, Blocks size of underlying drive (data+tags)
|
||||
public UInt16 blocksize;
|
||||
// 0x7E, Data only block size
|
||||
public UInt16 datasize;
|
||||
// 0x80, unknown
|
||||
public UInt16 unknown4;
|
||||
// 0x82, unknown
|
||||
public UInt32 unknown5;
|
||||
// 0x86, unknown
|
||||
public UInt32 unknown6;
|
||||
// 0x8A, Size in sectors of filesystem clusters
|
||||
public UInt16 clustersize;
|
||||
// 0x8C, Filesystem size in blocks
|
||||
public UInt32 fs_size;
|
||||
// 0x90, unknown
|
||||
public UInt32 unknown7;
|
||||
// 0x94, unknown
|
||||
public UInt32 unknown8;
|
||||
// 0x98, unknown
|
||||
public UInt32 unknown9;
|
||||
// 0x9C, unknown
|
||||
public UInt32 unknown10;
|
||||
// 0xA0, unknown
|
||||
public UInt32 unknown11;
|
||||
// 0xA4, unknown
|
||||
public UInt32 unknown12;
|
||||
// 0xA8, unknown
|
||||
public UInt32 unknown13;
|
||||
// 0xAC, unknown
|
||||
public UInt32 unknown14;
|
||||
// 0xB0, Files in volume
|
||||
public UInt16 filecount;
|
||||
// 0xB2, unknown
|
||||
public UInt32 unknown15;
|
||||
// 0xB6, unknown
|
||||
public UInt32 unknown16;
|
||||
// 0xBA, Free blocks
|
||||
public UInt32 freecount;
|
||||
// 0xBE, unknown
|
||||
public UInt16 unknown17;
|
||||
// 0xC0, unknown
|
||||
public UInt32 unknown18;
|
||||
// 0xC4, no idea
|
||||
public UInt64 overmount_stamp;
|
||||
// 0xCC, serialization, lisa serial number authorized to use blocked software on this volume
|
||||
public UInt32 serialization;
|
||||
// 0xD0, unknown
|
||||
public UInt32 unknown19;
|
||||
// 0xD4, unknown, possible timestamp
|
||||
public UInt32 unknown_timestamp;
|
||||
// 0xD8, unknown
|
||||
public UInt32 unknown20;
|
||||
// 0xDC, unknown
|
||||
public UInt32 unknown21;
|
||||
// 0xE0, unknown
|
||||
public UInt32 unknown22;
|
||||
// 0xE4, unknown
|
||||
public UInt32 unknown23;
|
||||
// 0xE8, unknown
|
||||
public UInt32 unknown24;
|
||||
// 0xEC, unknown
|
||||
public UInt32 unknown25;
|
||||
// 0xF0, unknown
|
||||
public UInt32 unknown26;
|
||||
// 0xF4, unknown
|
||||
public UInt32 unknown27;
|
||||
// 0xF8, unknown
|
||||
public UInt32 unknown28;
|
||||
// 0xFC, unknown
|
||||
public UInt32 unknown29;
|
||||
// 0x100, unknown
|
||||
public UInt32 unknown30;
|
||||
// 0x104, unknown
|
||||
public UInt32 unknown31;
|
||||
// 0x108, unknown
|
||||
public UInt32 unknown32;
|
||||
// 0x10C, unknown
|
||||
public UInt32 unknown33;
|
||||
// 0x110, unknown
|
||||
public UInt32 unknown34;
|
||||
// 0x114, unknown
|
||||
public UInt32 unknown35;
|
||||
// 0x118, ID of volume where this volume was backed up
|
||||
public UInt64 backup_volid;
|
||||
// 0x120, Size of LisaInfo label
|
||||
public UInt16 label_size;
|
||||
// 0x122, not clear
|
||||
public UInt16 fs_overhead;
|
||||
// 0x124, Return code of Scavenger
|
||||
public UInt16 result_scavenge;
|
||||
// 0x126, No idea
|
||||
public UInt16 boot_code;
|
||||
// 0x128, No idea
|
||||
public UInt16 boot_environ;
|
||||
// 0x12A, unknown
|
||||
public UInt32 unknown36;
|
||||
// 0x12E, unknown
|
||||
public UInt32 unknown37;
|
||||
// 0x132, unknown
|
||||
public UInt32 unknown38;
|
||||
// 0x136, Total volumes in sequence
|
||||
public UInt16 vol_sequence;
|
||||
// 0x138, Volume is dirty?
|
||||
public byte vol_left_mounted;
|
||||
// Is password present? (On-disk position unknown)
|
||||
public byte passwd_present;
|
||||
// Opened files (memory-only?) (On-disk position unknown)
|
||||
public UInt32 opencount;
|
||||
// No idea (On-disk position unknown)
|
||||
public UInt32 copy_thread;
|
||||
// Flags are boolean, but Pascal seems to use them as full unsigned 8 bit values
|
||||
// No idea (On-disk position unknown)
|
||||
public byte privileged;
|
||||
// Read-only volume (On-disk position unknown)
|
||||
public byte write_protected;
|
||||
// Master disk (On-disk position unknown)
|
||||
public byte master;
|
||||
// Copy disk (On-disk position unknown)
|
||||
public byte copy;
|
||||
// No idea (On-disk position unknown)
|
||||
public byte copy_flag;
|
||||
// No idea (On-disk position unknown)
|
||||
public byte scavenge_flag;
|
||||
}
|
||||
|
||||
struct Lisa_Tag
|
||||
{
|
||||
// 0x00 Unknown
|
||||
public UInt32 unknown1;
|
||||
// 0x04 File ID
|
||||
public UInt16 fileID;
|
||||
// 0x06 Unknown
|
||||
public UInt16 unknown2;
|
||||
// 0x08 Unknown
|
||||
public UInt32 unknown3;
|
||||
}
|
||||
}
|
||||
}
|
||||
283
DiscImageChef/Plugins/MinixFS.cs
Normal file
283
DiscImageChef/Plugins/MinixFS.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : MinixFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies Minix v1, v2 and v3 filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from the Linux kernel
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class MinixFS : Plugin
|
||||
{
|
||||
const UInt16 MINIX_MAGIC = 0x137F;
|
||||
// Minix v1, 14 char filenames
|
||||
const UInt16 MINIX_MAGIC2 = 0x138F;
|
||||
// Minix v1, 30 char filenames
|
||||
const UInt16 MINIX2_MAGIC = 0x2468;
|
||||
// Minix v2, 14 char filenames
|
||||
const UInt16 MINIX2_MAGIC2 = 0x2478;
|
||||
// Minix v2, 30 char filenames
|
||||
const UInt16 MINIX3_MAGIC = 0x4D5A;
|
||||
// Minix v3, 60 char filenames
|
||||
// Byteswapped
|
||||
const UInt16 MINIX_CIGAM = 0x7F13;
|
||||
// Minix v1, 14 char filenames
|
||||
const UInt16 MINIX_CIGAM2 = 0x8F13;
|
||||
// Minix v1, 30 char filenames
|
||||
const UInt16 MINIX2_CIGAM = 0x6824;
|
||||
// Minix v2, 14 char filenames
|
||||
const UInt16 MINIX2_CIGAM2 = 0x7824;
|
||||
// Minix v2, 30 char filenames
|
||||
const UInt16 MINIX3_CIGAM = 0x5A4D;
|
||||
// Minix v3, 60 char filenames
|
||||
|
||||
public MinixFS(PluginBase Core)
|
||||
{
|
||||
Name = "Minix Filesystem";
|
||||
PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt16 magic;
|
||||
byte[] minix_sb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
|
||||
magic = BitConverter.ToUInt16(minix_sb_sector, 0x010); // Here should reside magic number on Minix V1 & V2
|
||||
|
||||
if (magic == MINIX_MAGIC || magic == MINIX_MAGIC2 || magic == MINIX2_MAGIC || magic == MINIX2_MAGIC2 ||
|
||||
magic == MINIX_CIGAM || magic == MINIX_CIGAM2 || magic == MINIX2_CIGAM || magic == MINIX2_CIGAM2)
|
||||
return true;
|
||||
magic = BitConverter.ToUInt16(minix_sb_sector, 0x018); // Here should reside magic number on Minix V3
|
||||
|
||||
if (magic == MINIX3_MAGIC || magic == MINIX3_CIGAM)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
bool minix3 = false;
|
||||
int filenamesize;
|
||||
string minixVersion;
|
||||
UInt16 magic;
|
||||
byte[] minix_sb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
|
||||
magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x018);
|
||||
|
||||
if (magic == MINIX3_MAGIC || magic == MINIX3_CIGAM)
|
||||
{
|
||||
filenamesize = 60;
|
||||
minixVersion = "Minix V3 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = magic != MINIX3_CIGAM;
|
||||
|
||||
minix3 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x010);
|
||||
|
||||
switch (magic)
|
||||
{
|
||||
case MINIX_MAGIC:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX_MAGIC2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX2_MAGIC:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX2_MAGIC2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
case MINIX_CIGAM:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
case MINIX_CIGAM2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V1 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
case MINIX2_CIGAM:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
case MINIX2_CIGAM2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix V2 filesystem";
|
||||
BigEndianBitConverter.IsLittleEndian = false;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (minix3)
|
||||
{
|
||||
Minix3SuperBlock mnx_sb = new Minix3SuperBlock();
|
||||
|
||||
mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt32(minix_sb_sector, 0x00);
|
||||
mnx_sb.s_pad0 = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x04);
|
||||
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();
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * mnx_sb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} bytes/block", mnx_sb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, mnx_sb.s_imap_blocks * mnx_sb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, mnx_sb.s_zmap_blocks * mnx_sb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", mnx_sb.s_firstdatazone).AppendLine();
|
||||
//sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0
|
||||
sb.AppendFormat("{0} bytes maximum per file", mnx_sb.s_max_size).AppendLine();
|
||||
sb.AppendFormat("On-disk filesystem version: {0}", mnx_sb.s_disk_version).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
MinixSuperBlock mnx_sb = new MinixSuperBlock();
|
||||
|
||||
mnx_sb.s_ninodes = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x00);
|
||||
mnx_sb.s_nzones = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x02);
|
||||
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();
|
||||
if (mnx_sb.s_zones > 0) // On V2
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * 1024).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_nzones, mnx_sb.s_nzones * 1024).AppendLine();
|
||||
sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, mnx_sb.s_imap_blocks * 1024).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, mnx_sb.s_zmap_blocks * 1024).AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", mnx_sb.s_firstdatazone).AppendLine();
|
||||
//sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0
|
||||
sb.AppendFormat("{0} bytes maximum per file", mnx_sb.s_max_size).AppendLine();
|
||||
sb.AppendFormat("Filesystem state: {0:X4}", mnx_sb.s_state).AppendLine();
|
||||
}
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
public struct MinixSuperBlock
|
||||
{
|
||||
public UInt16 s_ninodes;
|
||||
// 0x00, inodes on volume
|
||||
public UInt16 s_nzones;
|
||||
// 0x02, zones on volume
|
||||
public UInt16 s_imap_blocks;
|
||||
// 0x04, blocks on inode map
|
||||
public UInt16 s_zmap_blocks;
|
||||
// 0x06, blocks on zone map
|
||||
public UInt16 s_firstdatazone;
|
||||
// 0x08, first data zone
|
||||
public UInt16 s_log_zone_size;
|
||||
// 0x0A, log2 of blocks/zone
|
||||
public UInt32 s_max_size;
|
||||
// 0x0C, max file size
|
||||
public UInt16 s_magic;
|
||||
// 0x10, magic
|
||||
public UInt16 s_state;
|
||||
// 0x12, filesystem state
|
||||
public UInt32 s_zones;
|
||||
// 0x14, number of zones
|
||||
}
|
||||
|
||||
public struct Minix3SuperBlock
|
||||
{
|
||||
public UInt32 s_ninodes;
|
||||
// 0x00, inodes on volume
|
||||
public UInt16 s_pad0;
|
||||
// 0x04, padding
|
||||
public UInt16 s_imap_blocks;
|
||||
// 0x06, blocks on inode map
|
||||
public UInt16 s_zmap_blocks;
|
||||
// 0x08, blocks on zone map
|
||||
public UInt16 s_firstdatazone;
|
||||
// 0x0A, first data zone
|
||||
public UInt16 s_log_zone_size;
|
||||
// 0x0C, log2 of blocks/zone
|
||||
public UInt16 s_pad1;
|
||||
// 0x0E, padding
|
||||
public UInt32 s_max_size;
|
||||
// 0x10, max file size
|
||||
public UInt32 s_zones;
|
||||
// 0x14, number of zones
|
||||
public UInt16 s_magic;
|
||||
// 0x18, magic
|
||||
public UInt16 s_pad2;
|
||||
// 0x1A, padding
|
||||
public UInt16 s_blocksize;
|
||||
// 0x1C, bytes in a block
|
||||
public byte s_disk_version;
|
||||
// 0x1E, on-disk structures version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
238
DiscImageChef/Plugins/NTFS.cs
Normal file
238
DiscImageChef/Plugins/NTFS.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : NTFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies Windows NT FileSystem (aka NTFS) and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from Inside Windows NT
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class NTFS : Plugin
|
||||
{
|
||||
public NTFS(PluginBase Core)
|
||||
{
|
||||
Name = "New Technology File System (NTFS)";
|
||||
PluginUUID = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] eigth_bytes = new byte[8];
|
||||
byte signature1, fats_no;
|
||||
UInt16 spfat, signature2;
|
||||
string oem_name;
|
||||
|
||||
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
Array.Copy(ntfs_bpb, 0x003, eigth_bytes, 0, 8);
|
||||
oem_name = StringHandlers.CToString(eigth_bytes);
|
||||
|
||||
if (oem_name != "NTFS ")
|
||||
return false;
|
||||
|
||||
fats_no = ntfs_bpb[0x010];
|
||||
|
||||
if (fats_no != 0)
|
||||
return false;
|
||||
|
||||
spfat = BitConverter.ToUInt16(ntfs_bpb, 0x016);
|
||||
|
||||
if (spfat != 0)
|
||||
return false;
|
||||
|
||||
signature1 = ntfs_bpb[0x026];
|
||||
|
||||
if (signature1 != 0x80)
|
||||
return false;
|
||||
|
||||
signature2 = BitConverter.ToUInt16(ntfs_bpb, 0x1FE);
|
||||
|
||||
return signature2 == 0xAA55;
|
||||
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
NTFS_BootBlock ntfs_bb = new NTFS_BootBlock();
|
||||
|
||||
byte[] oem_name = new byte[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 = 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();
|
||||
// sb.AppendFormat("{0} reserved sectors", ntfs_bb.rsectors).AppendLine();
|
||||
// sb.AppendFormat("{0} FATs", ntfs_bb.fats_no).AppendLine();
|
||||
// sb.AppendFormat("{0} entries in the root folder", ntfs_bb.root_ent).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors on volume (small)", ntfs_bb.sml_sectors).AppendLine();
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", ntfs_bb.media).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors per FAT", ntfs_bb.spfat).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track", ntfs_bb.sptrk).AppendLine();
|
||||
sb.AppendFormat("{0} heads", ntfs_bb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} hidden sectors before filesystem", ntfs_bb.hsectors).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors on volume (big)", ntfs_bb.big_sectors).AppendLine();
|
||||
sb.AppendFormat("BIOS drive number: 0x{0:X2}", ntfs_bb.drive_no).AppendLine();
|
||||
// sb.AppendFormat("NT flags: 0x{0:X2}", ntfs_bb.nt_flags).AppendLine();
|
||||
// sb.AppendFormat("Signature 1: 0x{0:X2}", ntfs_bb.signature1).AppendLine();
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", ntfs_bb.sectors, ntfs_bb.sectors * ntfs_bb.bps).AppendLine();
|
||||
sb.AppendFormat("Sectors where $MFT starts: {0}", ntfs_bb.mft_lsn).AppendLine();
|
||||
sb.AppendFormat("Sectors where $MFTMirr starts: {0}", ntfs_bb.mftmirror_lsn).AppendLine();
|
||||
|
||||
if (ntfs_bb.mft_rc_clusters > 0)
|
||||
sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfs_bb.mft_rc_clusters,
|
||||
ntfs_bb.mft_rc_clusters * ntfs_bb.bps * ntfs_bb.spc).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfs_bb.mft_rc_clusters).AppendLine();
|
||||
if (ntfs_bb.index_blk_cts > 0)
|
||||
sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfs_bb.index_blk_cts,
|
||||
ntfs_bb.index_blk_cts * ntfs_bb.bps * ntfs_bb.spc).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} bytes per Index block", 1 << -ntfs_bb.index_blk_cts).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume serial number: {0:X16}", ntfs_bb.serial_no).AppendLine();
|
||||
// sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine();
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
struct NTFS_BootBlock // Sector 0
|
||||
{
|
||||
// BIOS Parameter Block
|
||||
public byte jmp1;
|
||||
// 0x000, Jump to boot code
|
||||
public UInt16 jmp2;
|
||||
// 0x001, ...;
|
||||
public string OEMName;
|
||||
// 0x003, OEM Name, 8 bytes, space-padded, must be "NTFS "
|
||||
public UInt16 bps;
|
||||
// 0x00B, Bytes per sector
|
||||
public byte spc;
|
||||
// 0x00D, Sectors per cluster
|
||||
public UInt16 rsectors;
|
||||
// 0x00E, Reserved sectors, seems 0
|
||||
public byte fats_no;
|
||||
// 0x010, Number of FATs... obviously, 0
|
||||
public UInt16 root_ent;
|
||||
// 0x011, Number of entries on root directory... 0
|
||||
public UInt16 sml_sectors;
|
||||
// 0x013, Sectors in volume... 0
|
||||
public byte media;
|
||||
// 0x015, Media descriptor
|
||||
public UInt16 spfat;
|
||||
// 0x016, Sectors per FAT... 0
|
||||
public UInt16 sptrk;
|
||||
// 0x018, Sectors per track, required to boot
|
||||
public UInt16 heads;
|
||||
// 0x01A, Heads... required to boot
|
||||
public UInt32 hsectors;
|
||||
// 0x01C, Hidden sectors before BPB
|
||||
public UInt32 big_sectors;
|
||||
// 0x020, Sectors in volume if > 65535... 0
|
||||
public byte drive_no;
|
||||
// 0x024, Drive number
|
||||
public byte nt_flags;
|
||||
// 0x025, 0
|
||||
public byte signature1;
|
||||
// 0x026, EPB signature, 0x80
|
||||
public byte dummy;
|
||||
// 0x027, Alignment
|
||||
// End of BIOS Parameter Block
|
||||
// NTFS real superblock
|
||||
public Int64 sectors;
|
||||
// 0x028, Sectors on volume
|
||||
public Int64 mft_lsn;
|
||||
// 0x030, LSN of $MFT
|
||||
public Int64 mftmirror_lsn;
|
||||
// 0x038, LSN of $MFTMirror
|
||||
public sbyte mft_rc_clusters;
|
||||
// 0x040, Clusters per MFT record
|
||||
public byte dummy2;
|
||||
// 0x041, Alignment
|
||||
public UInt16 dummy3;
|
||||
// 0x042, Alignment
|
||||
public sbyte index_blk_cts;
|
||||
// 0x044, Clusters per index block
|
||||
public byte dummy4;
|
||||
// 0x045, Alignment
|
||||
public UInt16 dummy5;
|
||||
// 0x046, Alignment
|
||||
public UInt64 serial_no;
|
||||
// 0x048, Volume serial number
|
||||
// End of NTFS superblock, followed by 430 bytes of boot code
|
||||
public UInt16 signature2;
|
||||
// 0x1FE, 0xAA55
|
||||
}
|
||||
}
|
||||
}
|
||||
356
DiscImageChef/Plugins/ODS.cs
Normal file
356
DiscImageChef/Plugins/ODS.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ODS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies VMS filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from VMS File System Internals by Kirby McCoy
|
||||
// ISBN: 1-55558-056-4
|
||||
// With some hints from http://www.decuslib.com/DECUS/vmslt97b/gnusoftware/gccaxp/7_1/vms/hm2def.h
|
||||
// Expects the home block to be always in sector #1 (does not check deltas)
|
||||
// Assumes a sector size of 512 bytes (VMS does on HDDs and optical drives, dunno about M.O.)
|
||||
// Book only describes ODS-2. Need to test ODS-1 and ODS-5
|
||||
// There is an ODS with signature "DECFILES11A", yet to be seen
|
||||
// Time is a 64 bit unsigned integer, tenths of microseconds since 1858/11/17 00:00:00.
|
||||
// TODO: Implement checksum
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class ODS : Plugin
|
||||
{
|
||||
public ODS(PluginBase Core)
|
||||
{
|
||||
Name = "Files-11 On-Disk Structure";
|
||||
PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
if (imagePlugin.GetSectorSize() < 512)
|
||||
return false;
|
||||
|
||||
byte[] magic_b = new byte[12];
|
||||
string magic;
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
Array.Copy(hb_sector, 0x1F0, magic_b, 0, 12);
|
||||
magic = Encoding.ASCII.GetString(magic_b);
|
||||
|
||||
return magic == "DECFILE11A " || magic == "DECFILE11B ";
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ODSHomeBlock homeblock = new ODSHomeBlock();
|
||||
byte[] temp_string = new byte[12];
|
||||
homeblock.min_class = new byte[20];
|
||||
homeblock.max_class = new byte[20];
|
||||
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
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);
|
||||
Array.Copy(hb_sector, 0x1D8, temp_string, 0, 12);
|
||||
homeblock.volname = StringHandlers.CToString(temp_string);
|
||||
Array.Copy(hb_sector, 0x1E4, temp_string, 0, 12);
|
||||
homeblock.ownername = StringHandlers.CToString(temp_string);
|
||||
Array.Copy(hb_sector, 0x1F0, temp_string, 0, 12);
|
||||
homeblock.format = StringHandlers.CToString(temp_string);
|
||||
homeblock.checksum2 = BitConverter.ToUInt16(hb_sector, 0x1FE);
|
||||
|
||||
if ((homeblock.struclev & 0xFF00) != 0x0200 || (homeblock.struclev & 0xFF) != 1 || homeblock.format != "DECFILE11B ")
|
||||
sb.AppendLine("The following information may be incorrect for this volume.");
|
||||
if (homeblock.resfiles < 5 || homeblock.devtype != 0)
|
||||
sb.AppendLine("This volume may be corrupted.");
|
||||
|
||||
sb.AppendFormat("Volume format is {0}", homeblock.format).AppendLine();
|
||||
sb.AppendFormat("Volume is Level {0} revision {1}", (homeblock.struclev & 0xFF00) >> 8, homeblock.struclev & 0xFF).AppendLine();
|
||||
sb.AppendFormat("Lowest structure in the volume is Level {0}, revision {1}", (homeblock.lowstruclev & 0xFF00) >> 8, homeblock.lowstruclev & 0xFF).AppendLine();
|
||||
sb.AppendFormat("Highest structure in the volume is Level {0}, revision {1}", (homeblock.highstruclev & 0xFF00) >> 8, homeblock.highstruclev & 0xFF).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", homeblock.cluster, homeblock.cluster * 512).AppendLine();
|
||||
sb.AppendFormat("This home block is on sector {0} (cluster {1})", homeblock.homelbn, homeblock.homevbn).AppendLine();
|
||||
sb.AppendFormat("Secondary home block is on sector {0} (cluster {1})", homeblock.alhomelbn, homeblock.alhomevbn).AppendLine();
|
||||
sb.AppendFormat("Volume bitmap starts in sector {0} (cluster {1})", homeblock.ibmaplbn, homeblock.ibmapvbn).AppendLine();
|
||||
sb.AppendFormat("Volume bitmap runs for {0} sectors ({1} bytes)", homeblock.ibmapsize, homeblock.ibmapsize * 512).AppendLine();
|
||||
sb.AppendFormat("Backup INDEXF.SYS;1 is in sector {0} (cluster {1})", homeblock.altidxlbn, homeblock.altidxvbn).AppendLine();
|
||||
sb.AppendFormat("{0} maximum files on the volume", homeblock.maxfiles).AppendLine();
|
||||
sb.AppendFormat("{0} reserved files", homeblock.resfiles).AppendLine();
|
||||
if (homeblock.rvn > 0 && homeblock.setcount > 0 && homeblock.strucname != " ")
|
||||
sb.AppendFormat("Volume is {0} of {1} in set \"{2}\".", homeblock.rvn, homeblock.setcount, homeblock.strucname).AppendLine();
|
||||
sb.AppendFormat("Volume owner is \"{0}\" (ID 0x{1:X8})", homeblock.ownername, homeblock.volowner).AppendLine();
|
||||
sb.AppendFormat("Volume label: \"{0}\"", homeblock.volname).AppendLine();
|
||||
sb.AppendFormat("Drive serial number: 0x{0:X8}", homeblock.serialnum).AppendLine();
|
||||
sb.AppendFormat("Volume was created on {0}", DateHandlers.VMSToDateTime(homeblock.credate)).AppendLine();
|
||||
if (homeblock.revdate > 0)
|
||||
sb.AppendFormat("Volume was last modified on {0}", DateHandlers.VMSToDateTime(homeblock.revdate)).AppendLine();
|
||||
if (homeblock.copydate > 0)
|
||||
sb.AppendFormat("Volume copied on {0}", DateHandlers.VMSToDateTime(homeblock.copydate)).AppendLine();
|
||||
sb.AppendFormat("Checksums: 0x{0:X4} and 0x{1:X4}", homeblock.checksum1, homeblock.checksum2).AppendLine();
|
||||
sb.AppendLine("Flags:");
|
||||
sb.AppendFormat("Window: {0}", homeblock.window).AppendLine();
|
||||
sb.AppendFormat("Cached directores: {0}", homeblock.lru_lim).AppendLine();
|
||||
sb.AppendFormat("Default allocation: {0} blocks", homeblock.extend).AppendLine();
|
||||
if ((homeblock.volchar & 0x01) == 0x01)
|
||||
sb.AppendLine("Readings should be verified");
|
||||
if ((homeblock.volchar & 0x02) == 0x02)
|
||||
sb.AppendLine("Writings should be verified");
|
||||
if ((homeblock.volchar & 0x04) == 0x04)
|
||||
sb.AppendLine("Files should be erased or overwritten when deleted");
|
||||
if ((homeblock.volchar & 0x08) == 0x08)
|
||||
sb.AppendLine("Highwater mark is to be disabled");
|
||||
if ((homeblock.volchar & 0x10) == 0x10)
|
||||
sb.AppendLine("Classification checks are enabled");
|
||||
sb.AppendLine("Volume permissions (r = read, w = write, c = create, d = delete)");
|
||||
sb.AppendLine("System, owner, group, world");
|
||||
// System
|
||||
if ((homeblock.protect & 0x1000) == 0x1000)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("r");
|
||||
if ((homeblock.protect & 0x2000) == 0x2000)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("w");
|
||||
if ((homeblock.protect & 0x4000) == 0x4000)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("c");
|
||||
if ((homeblock.protect & 0x8000) == 0x8000)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("d");
|
||||
// Owner
|
||||
if ((homeblock.protect & 0x100) == 0x100)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("r");
|
||||
if ((homeblock.protect & 0x200) == 0x200)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("w");
|
||||
if ((homeblock.protect & 0x400) == 0x400)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("c");
|
||||
if ((homeblock.protect & 0x800) == 0x800)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("d");
|
||||
// Group
|
||||
if ((homeblock.protect & 0x10) == 0x10)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("r");
|
||||
if ((homeblock.protect & 0x20) == 0x20)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("w");
|
||||
if ((homeblock.protect & 0x40) == 0x40)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("c");
|
||||
if ((homeblock.protect & 0x80) == 0x80)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("d");
|
||||
// World (other)
|
||||
if ((homeblock.protect & 0x1) == 0x1)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("r");
|
||||
if ((homeblock.protect & 0x2) == 0x2)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("w");
|
||||
if ((homeblock.protect & 0x4) == 0x4)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("c");
|
||||
if ((homeblock.protect & 0x8) == 0x8)
|
||||
sb.Append("-");
|
||||
else
|
||||
sb.Append("d");
|
||||
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendLine("Unknown structures:");
|
||||
sb.AppendFormat("Security mask: 0x{0:X8}", homeblock.sec_mask).AppendLine();
|
||||
sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine();
|
||||
sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine();
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
struct ODSHomeBlock
|
||||
{
|
||||
public UInt32 homelbn;
|
||||
// 0x000, LBN of THIS home block
|
||||
public UInt32 alhomelbn;
|
||||
// 0x004, LBN of the secondary home block
|
||||
public UInt32 altidxlbn;
|
||||
// 0x008, LBN of backup INDEXF.SYS;1
|
||||
public UInt16 struclev;
|
||||
// 0x00C, High byte contains filesystem version (1, 2 or 5), low byte contains revision (1)
|
||||
public UInt16 cluster;
|
||||
// 0x00E, Number of blocks each bit of the volume bitmap represents
|
||||
public UInt16 homevbn;
|
||||
// 0x010, VBN of THIS home block
|
||||
public UInt16 alhomevbn;
|
||||
// 0x012, VBN of the secondary home block
|
||||
public UInt16 altidxvbn;
|
||||
// 0x014, VBN of backup INDEXF.SYS;1
|
||||
public UInt16 ibmapvbn;
|
||||
// 0x016, VBN of the bitmap
|
||||
public UInt32 ibmaplbn;
|
||||
// 0x018, LBN of the bitmap
|
||||
public UInt32 maxfiles;
|
||||
// 0x01C, Max files on volume
|
||||
public UInt16 ibmapsize;
|
||||
// 0x020, Bitmap size in sectors
|
||||
public UInt16 resfiles;
|
||||
// 0x022, Reserved files, 5 at minimum
|
||||
public UInt16 devtype;
|
||||
// 0x024, Device type, ODS-2 defines it as always 0
|
||||
public UInt16 rvn;
|
||||
// 0x026, Relative volume number (number of the volume in a set)
|
||||
public UInt16 setcount;
|
||||
// 0x028, Total number of volumes in the set this volume is
|
||||
public UInt16 volchar;
|
||||
// 0x02A, Flags
|
||||
public UInt32 volowner;
|
||||
// 0x02C, User ID of the volume owner
|
||||
public UInt32 sec_mask;
|
||||
// 0x030, Security mask (??)
|
||||
public UInt16 protect;
|
||||
// 0x034, Volume permissions (system, owner, group and other)
|
||||
public UInt16 fileprot;
|
||||
// 0x036, Default file protection, unsupported in ODS-2
|
||||
public UInt16 recprot;
|
||||
// 0x038, Default file record protection
|
||||
public UInt16 checksum1;
|
||||
// 0x03A, Checksum of all preceding entries
|
||||
public UInt64 credate;
|
||||
// 0x03C, Creation date
|
||||
public byte window;
|
||||
// 0x044, Window size (pointers for the window)
|
||||
public byte lru_lim;
|
||||
// 0x045, Directories to be stored in cache
|
||||
public UInt16 extend;
|
||||
// 0x046, Default allocation size in blocks
|
||||
public UInt64 retainmin;
|
||||
// 0x048, Minimum file retention period
|
||||
public UInt64 retainmax;
|
||||
// 0x050, Maximum file retention period
|
||||
public UInt64 revdate;
|
||||
// 0x058, Last modification date
|
||||
public byte[] min_class;
|
||||
// 0x060, Minimum security class, 20 bytes
|
||||
public byte[] max_class;
|
||||
// 0x074, Maximum security class, 20 bytes
|
||||
public UInt16 filetab_fid1;
|
||||
// 0x088, File lookup table FID
|
||||
public UInt16 filetab_fid2;
|
||||
// 0x08A, File lookup table FID
|
||||
public UInt16 filetab_fid3;
|
||||
// 0x08C, File lookup table FID
|
||||
public UInt16 lowstruclev;
|
||||
// 0x08E, Lowest structure level on the volume
|
||||
public UInt16 highstruclev;
|
||||
// 0x090, Highest structure level on the volume
|
||||
public UInt64 copydate;
|
||||
// 0x092, Volume copy date (??)
|
||||
public byte[] reserved1;
|
||||
// 0x09A, 302 bytes
|
||||
public UInt32 serialnum;
|
||||
// 0x1C8, Physical drive serial number
|
||||
public string strucname;
|
||||
// 0x1CC, Name of the volume set, 12 bytes
|
||||
public string volname;
|
||||
// 0x1D8, Volume label, 12 bytes
|
||||
public string ownername;
|
||||
// 0x1E4, Name of the volume owner, 12 bytes
|
||||
public string format;
|
||||
// 0x1F0, ODS-2 defines it as "DECFILE11B", 12 bytes
|
||||
public UInt16 reserved2;
|
||||
// 0x1FC, Reserved
|
||||
public UInt16 checksum2;
|
||||
// 0x1FE, Checksum of preceding 255 words (16 bit units)
|
||||
}
|
||||
}
|
||||
}
|
||||
163
DiscImageChef/Plugins/Opera.cs
Normal file
163
DiscImageChef/Plugins/Opera.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : Opera.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies 3DO filesystems (aka Opera) and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class OperaFS : Plugin
|
||||
{
|
||||
public OperaFS(PluginBase Core)
|
||||
{
|
||||
Name = "Opera Filesystem Plugin";
|
||||
PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
byte record_type;
|
||||
byte[] sync_bytes = new byte[5];
|
||||
byte record_version;
|
||||
|
||||
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;
|
||||
return Encoding.ASCII.GetString(sync_bytes) == "ZZZZZ";
|
||||
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder SuperBlockMetadata = new StringBuilder();
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
OperaSuperBlock sb = new OperaSuperBlock();
|
||||
byte[] cString = new byte[32];
|
||||
sb.sync_bytes = new byte[5];
|
||||
|
||||
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);
|
||||
Array.Copy(sb_sector, 0x028, cString, 0, 32);
|
||||
sb.volume_label = StringHandlers.CToString(cString);
|
||||
sb.volume_id = BigEndianBitConverter.ToInt32(sb_sector, 0x048);
|
||||
sb.block_size = BigEndianBitConverter.ToInt32(sb_sector, 0x04C);
|
||||
sb.block_count = BigEndianBitConverter.ToInt32(sb_sector, 0x050);
|
||||
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;
|
||||
if (Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ")
|
||||
return;
|
||||
|
||||
if (sb.volume_comment.Length == 0)
|
||||
sb.volume_comment = "Not set.";
|
||||
|
||||
if (sb.volume_label.Length == 0)
|
||||
sb.volume_label = "Not set.";
|
||||
|
||||
SuperBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume label: {0}", sb.volume_label).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume comment: {0}", sb.volume_comment).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine();
|
||||
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();
|
||||
SuperBlockMetadata.AppendFormat("Last root directory copy: {0}", sb.last_root_copy).AppendLine();
|
||||
|
||||
information = SuperBlockMetadata.ToString();
|
||||
}
|
||||
|
||||
struct OperaSuperBlock
|
||||
{
|
||||
public byte record_type;
|
||||
// 0x000, Record type, must be 1
|
||||
public byte[] sync_bytes;
|
||||
// 0x001, 5 bytes, "ZZZZZ" = new byte[5];
|
||||
public byte record_version;
|
||||
// 0x006, Record version, must be 1
|
||||
public byte volume_flags;
|
||||
// 0x007, Volume flags
|
||||
public string volume_comment;
|
||||
// 0x008, 32 bytes, volume comment
|
||||
public string volume_label;
|
||||
// 0x028, 32 bytes, volume label
|
||||
public Int32 volume_id;
|
||||
// 0x048, Volume ID
|
||||
public Int32 block_size;
|
||||
// 0x04C, Block size in bytes
|
||||
public Int32 block_count;
|
||||
// 0x050, Blocks in volume
|
||||
public Int32 root_dirid;
|
||||
// 0x054, Root directory ID
|
||||
public Int32 rootdir_blocks;
|
||||
// 0x058, Root directory blocks
|
||||
public Int32 rootdir_bsize;
|
||||
// 0x05C, Root directory block size
|
||||
public Int32 last_root_copy;
|
||||
// 0x060, Last root directory copy
|
||||
}
|
||||
}
|
||||
}
|
||||
68
DiscImageChef/Plugins/PCEngine.cs
Normal file
68
DiscImageChef/Plugins/PCEngine.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : PCEngine.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies PC-Engine CDs.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class PCEnginePlugin : Plugin
|
||||
{
|
||||
public PCEnginePlugin(PluginBase Core)
|
||||
{
|
||||
Name = "PC Engine CD Plugin";
|
||||
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] system_descriptor = new byte[23];
|
||||
byte[] sector = imagePlugin.ReadSector(1 + partitionOffset);
|
||||
|
||||
Array.Copy(sector, 0x20, system_descriptor, 0, 23);
|
||||
|
||||
return Encoding.ASCII.GetString(system_descriptor) == "PC Engine CD-ROM SYSTEM";
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
74
DiscImageChef/Plugins/Plugin.cs
Normal file
74
DiscImageChef/Plugins/Plugin.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : Plugin.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Defines functions to be used by filesystem plugins and several constants.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class to implement filesystem plugins.
|
||||
/// </summary>
|
||||
public abstract class Plugin
|
||||
{
|
||||
/// <summary>Plugin name.</summary>
|
||||
public string Name;
|
||||
/// <summary>Plugin UUID.</summary>
|
||||
public Guid PluginUUID;
|
||||
|
||||
protected Plugin()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the filesystem in the specified LBA
|
||||
/// </summary>
|
||||
/// <param name="imagePlugin">Disk image.</param>
|
||||
/// <param name="partitionOffset">Partition offset (LBA).</param>
|
||||
/// <returns><c>true</c>, if the filesystem is recognized, <c>false</c> otherwise.</returns>
|
||||
public abstract bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset);
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about the identified filesystem.
|
||||
/// </summary>
|
||||
/// <param name="imagePlugin">Disk image.</param>
|
||||
/// <param name="partitionOffset">Partition offset (LBA).</param>
|
||||
/// <param name="information">Filesystem information.</param>
|
||||
public abstract void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information);
|
||||
}
|
||||
}
|
||||
|
||||
188
DiscImageChef/Plugins/SolarFS.cs
Normal file
188
DiscImageChef/Plugins/SolarFS.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : SolarFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies SolarOS filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Based on FAT's BPB, cannot find a FAT or directory
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class SolarFS : Plugin
|
||||
{
|
||||
public SolarFS(PluginBase Core)
|
||||
{
|
||||
Name = "Solar_OS filesystem";
|
||||
PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte signature; // 0x29
|
||||
string fs_type; // "SOL_FS "
|
||||
|
||||
byte[] bpb = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
byte[] bpb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
byte[] bpb_strings;
|
||||
|
||||
SolarOSParameterBlock BPB = new SolarOSParameterBlock();
|
||||
|
||||
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);
|
||||
Console.WriteLine("(SolarFS) BPB.unk1: 0x{0:X2}", BPB.unk1);
|
||||
Console.WriteLine("(SolarFS) BPB.unk2: 0x{0:X4}", BPB.unk2);
|
||||
Console.WriteLine("(SolarFS) BPB.root_ent: {0}", BPB.root_ent);
|
||||
Console.WriteLine("(SolarFS) BPB.sectors: {0}", BPB.sectors);
|
||||
Console.WriteLine("(SolarFS) BPB.media: 0x{0:X2}", BPB.media);
|
||||
Console.WriteLine("(SolarFS) BPB.spfat: {0}", BPB.spfat);
|
||||
Console.WriteLine("(SolarFS) BPB.sptrk: {0}", BPB.sptrk);
|
||||
Console.WriteLine("(SolarFS) BPB.heads: {0}", BPB.heads);
|
||||
Console.WriteLine("(SolarFS) BPB.unk3: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}", BPB.unk3[0], BPB.unk3[1], BPB.unk3[2], BPB.unk3[3], BPB.unk3[4], BPB.unk3[5], BPB.unk3[6], BPB.unk3[7], BPB.unk3[8], BPB.unk3[9]);
|
||||
Console.WriteLine("(SolarFS) BPB.signature: 0x{0:X2}", BPB.signature);
|
||||
Console.WriteLine("(SolarFS) BPB.unk4: 0x{0:X8}", BPB.unk4);
|
||||
Console.WriteLine("(SolarFS) BPB.vol_name: \"{0}\"", BPB.vol_name);
|
||||
Console.WriteLine("(SolarFS) BPB.fs_type: \"{0}\"", BPB.fs_type);
|
||||
}
|
||||
|
||||
sb.AppendLine("Solar_OS filesystem");
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", BPB.media).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", BPB.bps).AppendLine();
|
||||
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();
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
public struct SolarOSParameterBlock
|
||||
{
|
||||
public byte[] x86_jump;
|
||||
// 0x00, x86 jump (3 bytes), jumps to 0x60
|
||||
public string OEMName;
|
||||
// 0x03, 8 bytes, "SOLAR_OS"
|
||||
public UInt16 bps;
|
||||
// 0x0B, Bytes per sector
|
||||
public byte unk1;
|
||||
// 0x0D, unknown, 0x01
|
||||
public UInt16 unk2;
|
||||
// 0x0E, unknown, 0x0201
|
||||
public UInt16 root_ent;
|
||||
// 0x10, Number of entries on root directory ? (no root directory found)
|
||||
public UInt16 sectors;
|
||||
// 0x12, Sectors in volume
|
||||
public byte media;
|
||||
// 0x14, Media descriptor
|
||||
public UInt16 spfat;
|
||||
// 0x15, Sectors per FAT ? (no FAT found)
|
||||
public UInt16 sptrk;
|
||||
// 0x17, Sectors per track
|
||||
public UInt16 heads;
|
||||
// 0x19, Heads
|
||||
public byte[] unk3;
|
||||
// 0x1B, unknown, 10 bytes, zero-filled
|
||||
public byte signature;
|
||||
// 0x25, 0x29
|
||||
public UInt32 unk4;
|
||||
// 0x26, unknown, zero-filled
|
||||
public string vol_name;
|
||||
// 0x2A, 11 bytes, volume name, space-padded
|
||||
public string fs_type;
|
||||
// 0x35, 8 bytes, "SOL_FS "
|
||||
}
|
||||
}
|
||||
}
|
||||
373
DiscImageChef/Plugins/Symbian.cs
Normal file
373
DiscImageChef/Plugins/Symbian.cs
Normal file
@@ -0,0 +1,373 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : Symbian.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies Symbian installer (.sis) packages and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
using System.Collections.Generic;
|
||||
|
||||
// Information from http://www.thoukydides.webspace.virginmedia.com/software/psifs/sis.html
|
||||
// TODO: Implement support for disc images
|
||||
/*
|
||||
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class SymbianIS : Plugin
|
||||
{
|
||||
// Magics
|
||||
private const UInt32 SymbianMagic = 0x10000419;
|
||||
private const UInt32 EPOCMagic = 0x1000006D;
|
||||
private const UInt32 EPOC6Magic = 0x10003A12;
|
||||
private const UInt32 Symbian9Magic = 0x10201A7A;
|
||||
|
||||
// Options
|
||||
private const UInt16 IsUnicode = 0x0001;
|
||||
private const UInt16 IsDistributable = 0x0002;
|
||||
private const UInt16 NoCompress = 0x0008;
|
||||
private const UInt16 ShutdownApps = 0x0010;
|
||||
|
||||
// Types
|
||||
private const UInt16 SISApp = 0x0000; // Application
|
||||
private const UInt16 SISSystem = 0x0001; // System component (library)
|
||||
private const UInt16 SISOption = 0x0002; // Optional component
|
||||
private const UInt16 SISConfig = 0x0003; // Configures an application
|
||||
private const UInt16 SISPatch = 0x0004; // Patch
|
||||
private const UInt16 SISUpgrade = 0x0005; // Upgrade
|
||||
|
||||
private enum LanguageCodes
|
||||
{
|
||||
Test,
|
||||
EN,
|
||||
FR,
|
||||
GE,
|
||||
SP,
|
||||
IT,
|
||||
SW,
|
||||
DA,
|
||||
NO,
|
||||
FI,
|
||||
AM,
|
||||
SF,
|
||||
SG,
|
||||
PO,
|
||||
TU,
|
||||
IC,
|
||||
RU,
|
||||
HU,
|
||||
DU,
|
||||
BL,
|
||||
AU,
|
||||
BF,
|
||||
AS,
|
||||
NZ,
|
||||
IF,
|
||||
CS,
|
||||
SK,
|
||||
PL,
|
||||
SL,
|
||||
TC,
|
||||
HK,
|
||||
ZH,
|
||||
JA,
|
||||
TH,
|
||||
AF,
|
||||
SQ,
|
||||
AH,
|
||||
AR,
|
||||
HY,
|
||||
TL,
|
||||
BE,
|
||||
BN,
|
||||
BG,
|
||||
MY,
|
||||
CA,
|
||||
HR,
|
||||
CE,
|
||||
IE,
|
||||
ZA,
|
||||
ET,
|
||||
FA,
|
||||
CF,
|
||||
GD,
|
||||
KA,
|
||||
EL,
|
||||
CG,
|
||||
GU,
|
||||
HE,
|
||||
HI,
|
||||
IN,
|
||||
GA,
|
||||
SZ,
|
||||
KN,
|
||||
KK,
|
||||
KM,
|
||||
KO,
|
||||
LO,
|
||||
LV,
|
||||
LT,
|
||||
MK,
|
||||
MS,
|
||||
ML,
|
||||
MR,
|
||||
MO,
|
||||
MN,
|
||||
NN,
|
||||
BP,
|
||||
PA,
|
||||
RO,
|
||||
SR,
|
||||
SI,
|
||||
SO,
|
||||
OS,
|
||||
LS,
|
||||
SH,
|
||||
FS,
|
||||
TA,
|
||||
TE,
|
||||
BO,
|
||||
TI,
|
||||
CT,
|
||||
TK,
|
||||
UK,
|
||||
UR,
|
||||
VI,
|
||||
CY,
|
||||
ZU
|
||||
};
|
||||
|
||||
public SymbianIS(PluginBase Core)
|
||||
{
|
||||
base.Name = "Symbian Installation File Plugin";
|
||||
base.PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe48dbd");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream fileStream, long offset)
|
||||
{
|
||||
UInt32 uid1, uid2, uid3;
|
||||
BinaryReader br = new BinaryReader(fileStream);
|
||||
|
||||
br.BaseStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
|
||||
uid1 = br.ReadUInt32();
|
||||
uid2 = br.ReadUInt32();
|
||||
uid3 = br.ReadUInt32();
|
||||
|
||||
if(uid1 == Symbian9Magic)
|
||||
return true;
|
||||
else if(uid3 == SymbianMagic)
|
||||
{
|
||||
if(uid2 == EPOCMagic || uid2 == EPOC6Magic)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream fileStream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder description = new StringBuilder();
|
||||
List<string> languages = new List<string>();
|
||||
Dictionary<UInt32, UInt32> capabilities = new Dictionary<UInt32, UInt32>();
|
||||
int ENpos = 0;
|
||||
UInt32 comp_len;
|
||||
UInt32 comp_name_ptr;
|
||||
byte[] ComponentName_b;
|
||||
string ComponentName = "";
|
||||
|
||||
SymbianHeader sh = new SymbianHeader();
|
||||
BinaryReader br = new BinaryReader(fileStream);
|
||||
|
||||
br.BaseStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
|
||||
sh.uid1 = br.ReadUInt32();
|
||||
sh.uid2 = br.ReadUInt32();
|
||||
sh.uid3 = br.ReadUInt32();
|
||||
sh.uid4 = br.ReadUInt32();
|
||||
sh.crc16 = br.ReadUInt16();
|
||||
sh.languages = br.ReadUInt16();
|
||||
sh.files = br.ReadUInt16();
|
||||
sh.requisites = br.ReadUInt16();
|
||||
sh.inst_lang = br.ReadUInt16();
|
||||
sh.inst_files = br.ReadUInt16();
|
||||
sh.inst_drive = br.ReadUInt16();
|
||||
sh.capabilities = br.ReadUInt16();
|
||||
sh.inst_version = br.ReadUInt32();
|
||||
sh.options = br.ReadUInt16();
|
||||
sh.type = br.ReadUInt16();
|
||||
sh.major = br.ReadUInt16();
|
||||
sh.minor = br.ReadUInt16();
|
||||
sh.variant = br.ReadUInt32();
|
||||
sh.lang_ptr = br.ReadUInt32();
|
||||
sh.files_ptr = br.ReadUInt32();
|
||||
sh.reqs_ptr = br.ReadUInt32();
|
||||
sh.certs_ptr = br.ReadUInt32();
|
||||
sh.comp_ptr = br.ReadUInt32();
|
||||
sh.sig_ptr = br.ReadUInt32();
|
||||
sh.caps_ptr = br.ReadUInt32();
|
||||
sh.instspace = br.ReadUInt32();
|
||||
sh.maxinsspc = br.ReadUInt32();
|
||||
sh.reserved1 = br.ReadUInt64();
|
||||
sh.reserved2 = br.ReadUInt64();
|
||||
|
||||
// Go to enumerate languages
|
||||
br.BaseStream.Seek(sh.lang_ptr + offset, SeekOrigin.Begin);
|
||||
for(int i = 0; i < sh.languages; i++)
|
||||
{
|
||||
UInt16 language = br.ReadUInt16();
|
||||
if(language == 0x0001)
|
||||
ENpos = i;
|
||||
languages.Add(((LanguageCodes)language).ToString("G"));
|
||||
}
|
||||
|
||||
// Go to component record
|
||||
br.BaseStream.Seek(sh.comp_ptr + offset, SeekOrigin.Begin);
|
||||
for(int i = 0; i < sh.languages; i++)
|
||||
{
|
||||
comp_len = br.ReadUInt32();
|
||||
comp_name_ptr = br.ReadUInt32();
|
||||
if(i == ENpos)
|
||||
{
|
||||
br.BaseStream.Seek(comp_name_ptr + offset, SeekOrigin.Begin);
|
||||
ComponentName_b = new byte[comp_len];
|
||||
ComponentName_b = br.ReadBytes((int)comp_len);
|
||||
ComponentName = Encoding.ASCII.GetString(ComponentName_b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Go to capabilities (???)
|
||||
br.BaseStream.Seek(sh.caps_ptr + offset, SeekOrigin.Begin);
|
||||
for(int i = 0; i < sh.capabilities; i++)
|
||||
{
|
||||
UInt32 cap_key = br.ReadUInt32();
|
||||
UInt32 cap_value = br.ReadUInt32();
|
||||
capabilities.Add(cap_key, cap_value);
|
||||
}
|
||||
|
||||
if(sh.uid1 == Symbian9Magic)
|
||||
{
|
||||
description.AppendLine("Symbian Installation File");
|
||||
description.AppendLine("SymbianOS 9.1 or later");
|
||||
description.AppendFormat("Application ID: 0x{0:X8}", sh.uid3).AppendLine();
|
||||
description.AppendFormat("UIDs checksum: 0x{0:X8}", sh.uid4).AppendLine();
|
||||
}
|
||||
else if(sh.uid3 == SymbianMagic)
|
||||
{
|
||||
description.AppendLine("Symbian Installation File");
|
||||
|
||||
if(sh.uid2 == EPOCMagic)
|
||||
description.AppendLine("SymbianOS 3 or later");
|
||||
else if (sh.uid2 == EPOC6Magic)
|
||||
description.AppendLine("SymbianOS 6 or later");
|
||||
else
|
||||
description.AppendFormat("Unknown EPOC magic 0x{0:X8}", sh.uid2).AppendLine();
|
||||
|
||||
description.AppendFormat("Application ID: 0x{0:X8}", sh.uid1).AppendLine();
|
||||
description.AppendFormat("UIDs checksum: 0x{0:X8}", sh.uid4).AppendLine();
|
||||
description.AppendFormat("CRC16 of header: 0x{0:X4}", sh.crc16).AppendLine();
|
||||
description.AppendLine();
|
||||
|
||||
switch(sh.type)
|
||||
{
|
||||
case SISApp:
|
||||
description.AppendLine("SIS contains an application");
|
||||
break;
|
||||
}
|
||||
|
||||
description.AppendFormat("Component: {0} v{1}.{2}", ComponentName, sh.major, sh.minor).AppendLine();
|
||||
|
||||
description.AppendFormat("File contains {0} languages:", sh.languages).AppendLine();
|
||||
for(int i = 0; i < languages.Count; i++)
|
||||
{
|
||||
if(i>0)
|
||||
description.Append(", ");
|
||||
description.AppendFormat("{0}", languages[i]);
|
||||
}
|
||||
description.AppendLine();
|
||||
|
||||
description.AppendFormat("File contains {0} files (pointer: {1})", sh.files, sh.files_ptr).AppendLine();
|
||||
description.AppendFormat("File contains {0} requisites", sh.requisites).AppendLine();
|
||||
// description.AppendLine("Capabilities:");
|
||||
// foreach(KeyValuePair<UInt32, UInt32> kvp in capabilities)
|
||||
// description.AppendFormat("{0} = {1}", kvp.Key, kvp.Value).AppendLine();
|
||||
}
|
||||
|
||||
information = description.ToString();
|
||||
}
|
||||
|
||||
private struct SymbianHeader
|
||||
{
|
||||
public UInt32 uid1; // Application UID before SymbianOS 9, magic after
|
||||
public UInt32 uid2; // EPOC release magic before SOS 9, NULLs after
|
||||
public UInt32 uid3; // Application UID after SOS 9, magic before
|
||||
public UInt32 uid4; // Checksum of UIDs 1 to 3
|
||||
public UInt16 crc16; // CRC16 of all header
|
||||
public UInt16 languages; // Number of languages
|
||||
public UInt16 files; // Number of files
|
||||
public UInt16 requisites; // Number of requisites
|
||||
public UInt16 inst_lang; // Installed language (only residual SIS)
|
||||
public UInt16 inst_files; // Installed files (only residual SIS)
|
||||
public UInt16 inst_drive; // Installed drive (only residual SIS), NULL or 0x0021
|
||||
public UInt16 capabilities; // Number of capabilities
|
||||
public UInt32 inst_version; // Version of Symbian Installer required
|
||||
public UInt16 options; // Option flags
|
||||
public UInt16 type; // Type
|
||||
public UInt16 major; // Major version of application
|
||||
public UInt16 minor; // Minor version of application
|
||||
public UInt32 variant; // Variant when SIS is a prerequisite for other SISs
|
||||
public UInt32 lang_ptr; // Pointer to language records
|
||||
public UInt32 files_ptr; // Pointer to file records
|
||||
public UInt32 reqs_ptr; // Pointer to requisite records
|
||||
public UInt32 certs_ptr; // Pointer to certificate records
|
||||
public UInt32 comp_ptr; // Pointer to component name record
|
||||
// From EPOC Release 6
|
||||
public UInt32 sig_ptr; // Pointer to signature record
|
||||
public UInt32 caps_ptr; // Pointer to capability records
|
||||
public UInt32 instspace; // Installed space (only residual SIS)
|
||||
public UInt32 maxinsspc; // Space required
|
||||
public UInt64 reserved1; // Reserved
|
||||
public UInt64 reserved2; // Reserved
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
809
DiscImageChef/Plugins/SysV.cs
Normal file
809
DiscImageChef/Plugins/SysV.cs
Normal file
@@ -0,0 +1,809 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : SysV.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies UNIX System V filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from the Linux kernel
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class SysVfs : Plugin
|
||||
{
|
||||
const UInt32 XENIX_MAGIC = 0x002B5544;
|
||||
const UInt32 XENIX_CIGAM = 0x44552B00;
|
||||
const UInt32 SYSV_MAGIC = 0xFD187E20;
|
||||
const UInt32 SYSV_CIGAM = 0xFD187E20;
|
||||
// Rest have no magic.
|
||||
// Per a Linux kernel, Coherent fs has following:
|
||||
const string COH_FNAME = "nonamexxxxx ";
|
||||
const string COH_FPACK = "nopackxxxxx\n";
|
||||
// SCO AFS
|
||||
const UInt16 SCO_NFREE = 0xFFFF;
|
||||
// UNIX 7th Edition has nothing to detect it, so check for a valid filesystem is a must :(
|
||||
const UInt16 V7_NICINOD = 100;
|
||||
const UInt16 V7_NICFREE = 50;
|
||||
const UInt32 V7_MAXSIZE = 0x00FFFFFF;
|
||||
|
||||
public SysVfs(PluginBase Core)
|
||||
{
|
||||
Name = "UNIX System V filesystem";
|
||||
PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic;
|
||||
string s_fname, s_fpack;
|
||||
UInt16 s_nfree, s_ninode;
|
||||
UInt32 s_fsize;
|
||||
|
||||
/*for(int j = 0; j<=(br.BaseStream.Length/0x200); j++)
|
||||
{
|
||||
br.BaseStream.Seek(offset + j*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
magic = br.ReadUInt32();
|
||||
|
||||
if(magic == SYSV_MAGIC || magic == SYSV_CIGAM)
|
||||
Console.WriteLine("0x{0:X8}: 0x{1:X8} FOUND", br.BaseStream.Position-4, magic);
|
||||
else
|
||||
Console.WriteLine("0x{0:X8}: 0x{1:X8}", br.BaseStream.Position-4, magic);
|
||||
}*/
|
||||
|
||||
/*UInt32 number;
|
||||
br.BaseStream.Seek(offset+0x3A00, SeekOrigin.Begin);
|
||||
while((br.BaseStream.Position) <= (offset+0x3C00))
|
||||
{
|
||||
number = br.ReadUInt32();
|
||||
|
||||
Console.WriteLine("@{0:X8}: 0x{1:X8} ({1})", br.BaseStream.Position-offset-4, number);
|
||||
}*/
|
||||
|
||||
byte sb_size_in_sectors;
|
||||
|
||||
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;
|
||||
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x1F8); // System V magic location
|
||||
|
||||
if (magic == SYSV_MAGIC || magic == SYSV_CIGAM)
|
||||
return true;
|
||||
|
||||
byte[] coherent_string = new byte[6];
|
||||
Array.Copy(sb_sector, 0x1E8, coherent_string, 0, 6); // Coherent UNIX s_fname location
|
||||
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
|
||||
s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize
|
||||
s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree
|
||||
s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode
|
||||
|
||||
if (s_fsize > 0 && s_fsize < 0xFFFFFFFF && s_nfree > 0 && s_nfree < 0xFFFF && s_ninode > 0 && s_ninode < 0xFFFF)
|
||||
{
|
||||
if ((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00)
|
||||
{
|
||||
// Byteswap
|
||||
s_fsize = ((s_fsize & 0xFF) << 24) + ((s_fsize & 0xFF00) << 8) + ((s_fsize & 0xFF0000) >> 8) + ((s_fsize & 0xFF000000) >> 24);
|
||||
s_nfree = (UInt16)(s_nfree >> 8);
|
||||
s_ninode = (UInt16)(s_ninode >> 8);
|
||||
}
|
||||
|
||||
if ((s_fsize & 0xFF000000) == 0x00 && (s_nfree & 0xFF00) == 0x00 && (s_ninode & 0xFF00) == 0x00)
|
||||
{
|
||||
if (s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD)
|
||||
{
|
||||
if ((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Start in little endian until we know what are we handling here
|
||||
int start;
|
||||
UInt32 magic;
|
||||
string s_fname, s_fpack;
|
||||
UInt16 s_nfree, s_ninode;
|
||||
UInt32 s_fsize;
|
||||
bool xenix = false;
|
||||
bool sysv = false;
|
||||
bool sysvr4 = false;
|
||||
bool sys7th = false;
|
||||
bool coherent = false;
|
||||
byte[] sb_sector;
|
||||
byte sb_size_in_sectors;
|
||||
|
||||
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++)
|
||||
{
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8); // XENIX magic location
|
||||
|
||||
if (magic == XENIX_MAGIC)
|
||||
{
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Little endian
|
||||
xenix = true;
|
||||
break;
|
||||
}
|
||||
if (magic == XENIX_CIGAM)
|
||||
{
|
||||
BigEndianBitConverter.IsLittleEndian = false; // Big endian
|
||||
xenix = true;
|
||||
break;
|
||||
}
|
||||
|
||||
magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F8); // XENIX magic location
|
||||
|
||||
if (magic == SYSV_MAGIC)
|
||||
{
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Little endian
|
||||
sysv = true;
|
||||
break;
|
||||
}
|
||||
if (magic == SYSV_CIGAM)
|
||||
{
|
||||
BigEndianBitConverter.IsLittleEndian = false; // Big endian
|
||||
sysv = true;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
BigEndianBitConverter.IsLittleEndian = true; // Coherent is in PDP endianness, use helper for that
|
||||
coherent = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Now try to identify 7th edition
|
||||
s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize
|
||||
s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree
|
||||
s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode
|
||||
|
||||
if (s_fsize > 0 && s_fsize < 0xFFFFFFFF && s_nfree > 0 && s_nfree < 0xFFFF && s_ninode > 0 && s_ninode < 0xFFFF)
|
||||
{
|
||||
if ((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00)
|
||||
{
|
||||
// Byteswap
|
||||
s_fsize = ((s_fsize & 0xFF) << 24) + ((s_fsize & 0xFF00) << 8) + ((s_fsize & 0xFF0000) >> 8) + ((s_fsize & 0xFF000000) >> 24);
|
||||
s_nfree = (UInt16)(s_nfree >> 8);
|
||||
s_ninode = (UInt16)(s_ninode >> 8);
|
||||
}
|
||||
|
||||
if ((s_fsize & 0xFF000000) == 0x00 && (s_nfree & 0xFF00) == 0x00 && (s_ninode & 0xFF00) == 0x00)
|
||||
{
|
||||
if (s_fsize < V7_MAXSIZE && s_nfree < V7_NICFREE && s_ninode < V7_NICINOD)
|
||||
{
|
||||
if ((s_fsize * 1024) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) || (s_fsize * 512) <= (imagePlugin.GetSectors() * imagePlugin.GetSectorSize()))
|
||||
{
|
||||
sys7th = true;
|
||||
BigEndianBitConverter.IsLittleEndian = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!sys7th && !sysv && !coherent && !xenix)
|
||||
return;
|
||||
|
||||
if (xenix)
|
||||
{
|
||||
byte[] xenix_strings = new byte[6];
|
||||
XenixSuperBlock xnx_sb = new XenixSuperBlock();
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
|
||||
xnx_sb.s_isize = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
|
||||
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");
|
||||
switch (xnx_sb.s_type)
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("512 bytes per block");
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("1024 bytes per block");
|
||||
bs = 1024;
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("2048 bytes per block");
|
||||
bs = 2048;
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine();
|
||||
break;
|
||||
}
|
||||
if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448)
|
||||
{
|
||||
if (bs != 2048)
|
||||
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();
|
||||
sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", xnx_sb.s_cylblks, xnx_sb.s_cylblks * bs).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per gap ({1} bytes)", xnx_sb.s_gapblks, xnx_sb.s_gapblks * bs).AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", xnx_sb.s_isize).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on volume", xnx_sb.s_tinode).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on list", xnx_sb.s_ninode).AppendLine();
|
||||
if (xnx_sb.s_flock > 0)
|
||||
sb.AppendLine("Free block list is locked");
|
||||
if (xnx_sb.s_ilock > 0)
|
||||
sb.AppendLine("inode cache is locked");
|
||||
if (xnx_sb.s_fmod > 0)
|
||||
sb.AppendLine("Superblock is being modified");
|
||||
if (xnx_sb.s_ronly > 0)
|
||||
sb.AppendLine("Volume is mounted read-only");
|
||||
sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(xnx_sb.s_time)).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine();
|
||||
sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine();
|
||||
if (xnx_sb.s_clean == 0x46)
|
||||
sb.AppendLine("Volume is clean");
|
||||
else
|
||||
sb.AppendLine("Volume is dirty");
|
||||
}
|
||||
|
||||
if (sysv)
|
||||
{
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
UInt16 pad0, pad1, pad2;
|
||||
byte[] sysv_strings = new byte[6];
|
||||
|
||||
pad0 = BigEndianBitConverter.ToUInt16(sb_sector, 0x002); // First padding
|
||||
pad1 = BigEndianBitConverter.ToUInt16(sb_sector, 0x00A); // Second padding
|
||||
pad2 = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D6); // Third padding
|
||||
|
||||
// This detection is not working as expected
|
||||
sysvr4 |= pad0 == 0 && pad1 == 0 && pad2 == 0;
|
||||
|
||||
SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock();
|
||||
|
||||
// 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)
|
||||
sb.AppendLine("System V Release 4 filesystem");
|
||||
else
|
||||
sb.AppendLine("System V Release 2 filesystem");
|
||||
switch (sysv_sb.s_type)
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("512 bytes per block");
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("1024 bytes per block");
|
||||
bs = 1024;
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("2048 bytes per block");
|
||||
bs = 2048;
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine();
|
||||
break;
|
||||
}
|
||||
if (imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448)
|
||||
{
|
||||
if (bs != 2048)
|
||||
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();
|
||||
sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", sysv_sb.s_cylblks, sysv_sb.s_cylblks * bs).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per gap ({1} bytes)", sysv_sb.s_gapblks, sysv_sb.s_gapblks * bs).AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", sysv_sb.s_isize).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on volume", sysv_sb.s_tinode).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on list", sysv_sb.s_ninode).AppendLine();
|
||||
if (sysv_sb.s_flock > 0)
|
||||
sb.AppendLine("Free block list is locked");
|
||||
if (sysv_sb.s_ilock > 0)
|
||||
sb.AppendLine("inode cache is locked");
|
||||
if (sysv_sb.s_fmod > 0)
|
||||
sb.AppendLine("Superblock is being modified");
|
||||
if (sysv_sb.s_ronly > 0)
|
||||
sb.AppendLine("Volume is mounted read-only");
|
||||
sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time)).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine();
|
||||
sb.AppendFormat("Pack name: {0}", sysv_sb.s_fpack).AppendLine();
|
||||
if (sysv_sb.s_state == (0x7C269D38 - sysv_sb.s_time))
|
||||
sb.AppendLine("Volume is clean");
|
||||
else
|
||||
sb.AppendLine("Volume is dirty");
|
||||
}
|
||||
|
||||
if (coherent)
|
||||
{
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partitionOffset, sb_size_in_sectors);
|
||||
CoherentSuperBlock coh_sb = new CoherentSuperBlock();
|
||||
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();
|
||||
sb.AppendFormat("First data zone: {0}", coh_sb.s_isize).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on volume", coh_sb.s_tinode).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on list", coh_sb.s_ninode).AppendLine();
|
||||
if (coh_sb.s_flock > 0)
|
||||
sb.AppendLine("Free block list is locked");
|
||||
if (coh_sb.s_ilock > 0)
|
||||
sb.AppendLine("inode cache is locked");
|
||||
if (coh_sb.s_fmod > 0)
|
||||
sb.AppendLine("Superblock is being modified");
|
||||
if (coh_sb.s_ronly > 0)
|
||||
sb.AppendLine("Volume is mounted read-only");
|
||||
sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time)).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine();
|
||||
sb.AppendFormat("Pack name: {0}", coh_sb.s_fpack).AppendLine();
|
||||
}
|
||||
|
||||
if (sys7th)
|
||||
{
|
||||
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();
|
||||
sb.AppendFormat("First data zone: {0}", v7_sb.s_isize).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on volume", v7_sb.s_tinode).AppendLine();
|
||||
sb.AppendFormat("{0} free inodes on list", v7_sb.s_ninode).AppendLine();
|
||||
if (v7_sb.s_flock > 0)
|
||||
sb.AppendLine("Free block list is locked");
|
||||
if (v7_sb.s_ilock > 0)
|
||||
sb.AppendLine("inode cache is locked");
|
||||
if (v7_sb.s_fmod > 0)
|
||||
sb.AppendLine("Superblock is being modified");
|
||||
if (v7_sb.s_ronly > 0)
|
||||
sb.AppendLine("Volume is mounted read-only");
|
||||
sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time)).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine();
|
||||
sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine();
|
||||
}
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = false; // Return to default (bigendian)
|
||||
}
|
||||
|
||||
struct XenixSuperBlock
|
||||
{
|
||||
public UInt16 s_isize;
|
||||
// 0x000, index of first data zone
|
||||
public UInt32 s_fsize;
|
||||
// 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree;
|
||||
// 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free;
|
||||
// 0x008, 100 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode;
|
||||
// 0x198, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode;
|
||||
// 0x19A, 100 entries, some free inodes
|
||||
public byte s_flock;
|
||||
// 0x262, free block list manipulation lock
|
||||
public byte s_ilock;
|
||||
// 0x263, inode cache manipulation lock
|
||||
public byte s_fmod;
|
||||
// 0x264, superblock modification flag
|
||||
public byte s_ronly;
|
||||
// 0x265, read-only mounted flag
|
||||
public UInt32 s_time;
|
||||
// 0x266, time of last superblock update
|
||||
public UInt32 s_tfree;
|
||||
// 0x26A, total number of free zones
|
||||
public UInt16 s_tinode;
|
||||
// 0x26E, total number of free inodes
|
||||
public UInt16 s_cylblks;
|
||||
// 0x270, blocks per cylinder
|
||||
public UInt16 s_gapblks;
|
||||
// 0x272, blocks per gap
|
||||
public UInt16 s_dinfo0;
|
||||
// 0x274, device information ??
|
||||
public UInt16 s_dinfo1;
|
||||
// 0x276, device information ??
|
||||
public string s_fname;
|
||||
// 0x278, 6 bytes, volume name
|
||||
public string s_fpack;
|
||||
// 0x27E, 6 bytes, pack name
|
||||
public byte s_clean;
|
||||
// 0x284, 0x46 if volume is clean
|
||||
public byte[] s_fill;
|
||||
// 0x285, 371 bytes
|
||||
public UInt32 s_magic;
|
||||
// 0x3F8, magic
|
||||
public UInt32 s_type;
|
||||
// 0x3FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk, 3 = 2048 bytes/blk)
|
||||
}
|
||||
|
||||
struct SystemVRelease4SuperBlock
|
||||
{
|
||||
public UInt16 s_isize;
|
||||
// 0x000, index of first data zone
|
||||
public UInt16 s_pad0;
|
||||
// 0x002, padding
|
||||
public UInt32 s_fsize;
|
||||
// 0x004, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree;
|
||||
// 0x008, blocks in s_free, <=100
|
||||
public UInt16 s_pad1;
|
||||
// 0x00A, padding
|
||||
public UInt32[] s_free;
|
||||
// 0x00C, 50 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode;
|
||||
// 0x0D4, number of inodes in s_inode, <= 100
|
||||
public UInt16 s_pad2;
|
||||
// 0x0D6, padding
|
||||
public UInt16[] s_inode;
|
||||
// 0x0D8, 100 entries, some free inodes
|
||||
public byte s_flock;
|
||||
// 0x1A0, free block list manipulation lock
|
||||
public byte s_ilock;
|
||||
// 0x1A1, inode cache manipulation lock
|
||||
public byte s_fmod;
|
||||
// 0x1A2, superblock modification flag
|
||||
public byte s_ronly;
|
||||
// 0x1A3, read-only mounted flag
|
||||
public UInt32 s_time;
|
||||
// 0x1A4, time of last superblock update
|
||||
public UInt16 s_cylblks;
|
||||
// 0x1A8, blocks per cylinder
|
||||
public UInt16 s_gapblks;
|
||||
// 0x1AA, blocks per gap
|
||||
public UInt16 s_dinfo0;
|
||||
// 0x1AC, device information ??
|
||||
public UInt16 s_dinfo1;
|
||||
// 0x1AE, device information ??
|
||||
public UInt32 s_tfree;
|
||||
// 0x1B0, total number of free zones
|
||||
public UInt16 s_tinode;
|
||||
// 0x1B4, total number of free inodes
|
||||
public UInt16 s_pad3;
|
||||
// 0x1B6, padding
|
||||
public string s_fname;
|
||||
// 0x1B8, 6 bytes, volume name
|
||||
public string s_fpack;
|
||||
// 0x1BE, 6 bytes, pack name
|
||||
public byte[] s_fill;
|
||||
// 0x1C4, 48 bytes
|
||||
public UInt32 s_state;
|
||||
// 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean
|
||||
public UInt32 s_magic;
|
||||
// 0x1F8, magic
|
||||
public UInt32 s_type;
|
||||
// 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk)
|
||||
}
|
||||
|
||||
struct SystemVRelease2SuperBlock
|
||||
{
|
||||
public UInt16 s_isize;
|
||||
// 0x000, index of first data zone
|
||||
public UInt32 s_fsize;
|
||||
// 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree;
|
||||
// 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free;
|
||||
// 0x008, 50 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode;
|
||||
// 0x0D0, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode;
|
||||
// 0x0D2, 100 entries, some free inodes
|
||||
public byte s_flock;
|
||||
// 0x19A, free block list manipulation lock
|
||||
public byte s_ilock;
|
||||
// 0x19B, inode cache manipulation lock
|
||||
public byte s_fmod;
|
||||
// 0x19C, superblock modification flag
|
||||
public byte s_ronly;
|
||||
// 0x19D, read-only mounted flag
|
||||
public UInt32 s_time;
|
||||
// 0x19E, time of last superblock update
|
||||
public UInt16 s_cylblks;
|
||||
// 0x1A2, blocks per cylinder
|
||||
public UInt16 s_gapblks;
|
||||
// 0x1A4, blocks per gap
|
||||
public UInt16 s_dinfo0;
|
||||
// 0x1A6, device information ??
|
||||
public UInt16 s_dinfo1;
|
||||
// 0x1A8, device information ??
|
||||
public UInt32 s_tfree;
|
||||
// 0x1AA, total number of free zones
|
||||
public UInt16 s_tinode;
|
||||
// 0x1AE, total number of free inodes
|
||||
public string s_fname;
|
||||
// 0x1B0, 6 bytes, volume name
|
||||
public string s_fpack;
|
||||
// 0x1B6, 6 bytes, pack name
|
||||
public byte[] s_fill;
|
||||
// 0x1BC, 56 bytes
|
||||
public UInt32 s_state;
|
||||
// 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean
|
||||
public UInt32 s_magic;
|
||||
// 0x1F8, magic
|
||||
public UInt32 s_type;
|
||||
// 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk)
|
||||
}
|
||||
|
||||
struct UNIX7thEditionSuperBlock
|
||||
{
|
||||
public UInt16 s_isize;
|
||||
// 0x000, index of first data zone
|
||||
public UInt32 s_fsize;
|
||||
// 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree;
|
||||
// 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free;
|
||||
// 0x008, 50 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode;
|
||||
// 0x0D0, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode;
|
||||
// 0x0D2, 100 entries, some free inodes
|
||||
public byte s_flock;
|
||||
// 0x19A, free block list manipulation lock
|
||||
public byte s_ilock;
|
||||
// 0x19B, inode cache manipulation lock
|
||||
public byte s_fmod;
|
||||
// 0x19C, superblock modification flag
|
||||
public byte s_ronly;
|
||||
// 0x19D, read-only mounted flag
|
||||
public UInt32 s_time;
|
||||
// 0x19E, time of last superblock update
|
||||
public UInt32 s_tfree;
|
||||
// 0x1A2, total number of free zones
|
||||
public UInt16 s_tinode;
|
||||
// 0x1A6, total number of free inodes
|
||||
public UInt16 s_int_m;
|
||||
// 0x1A8, interleave factor
|
||||
public UInt16 s_int_n;
|
||||
// 0x1AA, interleave factor
|
||||
public string s_fname;
|
||||
// 0x1AC, 6 bytes, volume name
|
||||
public string s_fpack;
|
||||
// 0x1B2, 6 bytes, pack name
|
||||
}
|
||||
|
||||
struct CoherentSuperBlock
|
||||
{
|
||||
public UInt16 s_isize;
|
||||
// 0x000, index of first data zone
|
||||
public UInt32 s_fsize;
|
||||
// 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree;
|
||||
// 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free;
|
||||
// 0x008, 64 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode;
|
||||
// 0x108, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode;
|
||||
// 0x10A, 100 entries, some free inodes
|
||||
public byte s_flock;
|
||||
// 0x1D2, free block list manipulation lock
|
||||
public byte s_ilock;
|
||||
// 0x1D3, inode cache manipulation lock
|
||||
public byte s_fmod;
|
||||
// 0x1D4, superblock modification flag
|
||||
public byte s_ronly;
|
||||
// 0x1D5, read-only mounted flag
|
||||
public UInt32 s_time;
|
||||
// 0x1D6, time of last superblock update
|
||||
public UInt32 s_tfree;
|
||||
// 0x1DE, total number of free zones
|
||||
public UInt16 s_tinode;
|
||||
// 0x1E2, total number of free inodes
|
||||
public UInt16 s_int_m;
|
||||
// 0x1E4, interleave factor
|
||||
public UInt16 s_int_n;
|
||||
// 0x1E6, interleave factor
|
||||
public string s_fname;
|
||||
// 0x1E8, 6 bytes, volume name
|
||||
public string s_fpack;
|
||||
// 0x1EE, 6 bytes, pack name
|
||||
public UInt32 s_unique;
|
||||
// 0x1F4, zero-filled
|
||||
}
|
||||
}
|
||||
}
|
||||
130
DiscImageChef/Plugins/UNIXBFS.cs
Normal file
130
DiscImageChef/Plugins/UNIXBFS.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : UNIXBFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies UnixWare boot filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from the Linux kernel
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class BFS : Plugin
|
||||
{
|
||||
const UInt32 BFS_MAGIC = 0x1BADFACE;
|
||||
|
||||
public BFS(PluginBase Core)
|
||||
{
|
||||
Name = "UNIX Boot filesystem";
|
||||
PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
UInt32 magic;
|
||||
|
||||
magic = BitConverter.ToUInt32(imagePlugin.ReadSector(0 + partitionOffset), 0);
|
||||
|
||||
return magic == BFS_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
byte[] bfs_sb_sector = imagePlugin.ReadSector(0 + partitionOffset);
|
||||
byte[] sb_strings = new byte[6];
|
||||
|
||||
BFSSuperBlock bfs_sb = new BFSSuperBlock();
|
||||
|
||||
bfs_sb.s_magic = BitConverter.ToUInt32(bfs_sb_sector, 0x00);
|
||||
bfs_sb.s_start = BitConverter.ToUInt32(bfs_sb_sector, 0x04);
|
||||
bfs_sb.s_end = BitConverter.ToUInt32(bfs_sb_sector, 0x08);
|
||||
bfs_sb.s_from = BitConverter.ToUInt32(bfs_sb_sector, 0x0C);
|
||||
bfs_sb.s_to = BitConverter.ToUInt32(bfs_sb_sector, 0x10);
|
||||
bfs_sb.s_bfrom = BitConverter.ToInt32(bfs_sb_sector, 0x14);
|
||||
bfs_sb.s_bto = BitConverter.ToInt32(bfs_sb_sector, 0x18);
|
||||
Array.Copy(bfs_sb_sector, 0x1C, sb_strings, 0, 6);
|
||||
bfs_sb.s_fsname = StringHandlers.CToString(sb_strings);
|
||||
Array.Copy(bfs_sb_sector, 0x22, sb_strings, 0, 6);
|
||||
bfs_sb.s_volume = StringHandlers.CToString(sb_strings);
|
||||
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("(BFS) bfs_sb.s_magic: 0x{0:X8}", bfs_sb.s_magic);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_start: 0x{0:X8}", bfs_sb.s_start);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_end: 0x{0:X8}", bfs_sb.s_end);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_from: 0x{0:X8}", bfs_sb.s_from);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_to: 0x{0:X8}", bfs_sb.s_to);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_bfrom: 0x{0:X8}", bfs_sb.s_bfrom);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_bto: 0x{0:X8}", bfs_sb.s_bto);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_fsname: 0x{0}", bfs_sb.s_fsname);
|
||||
Console.WriteLine("(BFS) bfs_sb.s_volume: 0x{0}", bfs_sb.s_volume);
|
||||
}
|
||||
|
||||
sb.AppendLine("UNIX Boot filesystem");
|
||||
sb.AppendFormat("Volume goes from byte {0} to byte {1}, for {2} bytes", bfs_sb.s_start, bfs_sb.s_end, bfs_sb.s_end - bfs_sb.s_start).AppendLine();
|
||||
sb.AppendFormat("Filesystem name: {0}", bfs_sb.s_fsname).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", bfs_sb.s_volume).AppendLine();
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
struct BFSSuperBlock
|
||||
{
|
||||
public UInt32 s_magic;
|
||||
// 0x00, 0x1BADFACE
|
||||
public UInt32 s_start;
|
||||
// 0x04, start in bytes of volume
|
||||
public UInt32 s_end;
|
||||
// 0x08, end in bytes of volume
|
||||
public UInt32 s_from;
|
||||
// 0x0C, unknown :p
|
||||
public UInt32 s_to;
|
||||
// 0x10, unknown :p
|
||||
public Int32 s_bfrom;
|
||||
// 0x14, unknown :p
|
||||
public Int32 s_bto;
|
||||
// 0x18, unknown :p
|
||||
public string s_fsname;
|
||||
// 0x1C, 6 bytes, filesystem name
|
||||
public string s_volume;
|
||||
// 0x22, 6 bytes, volume name
|
||||
}
|
||||
}
|
||||
}
|
||||
875
DiscImageChef/Plugins/ext2FS.cs
Normal file
875
DiscImageChef/Plugins/ext2FS.cs
Normal file
@@ -0,0 +1,875 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ext2FS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies ext2, ext3 and ext4 filesystems and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from the Linux kernel
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class ext2FS : Plugin
|
||||
{
|
||||
public ext2FS(PluginBase Core)
|
||||
{
|
||||
Name = "Linux extended Filesystem 2, 3 and 4";
|
||||
PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] sb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
|
||||
UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038);
|
||||
|
||||
if (magic == ext2FSMagic || magic == ext2OldFSMagic)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
ext2FSSuperBlock supblk = new ext2FSSuperBlock();
|
||||
byte[] forstrings;
|
||||
bool new_ext2 = false;
|
||||
bool ext3 = false;
|
||||
bool ext4 = false;
|
||||
|
||||
byte[] guid_a = new byte[16];
|
||||
byte[] guid_b = new byte[16];
|
||||
|
||||
uint sb_size_in_sectors;
|
||||
|
||||
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 = BitConverter.ToUInt32(sb_sector, 0x048);
|
||||
supblk.revision = BitConverter.ToUInt32(sb_sector, 0x04C);
|
||||
supblk.default_uid = BitConverter.ToUInt16(sb_sector, 0x050);
|
||||
supblk.default_gid = BitConverter.ToUInt16(sb_sector, 0x052);
|
||||
// From 0.5b onward
|
||||
supblk.first_inode = BitConverter.ToUInt32(sb_sector, 0x054);
|
||||
supblk.inode_size = BitConverter.ToUInt16(sb_sector, 0x058);
|
||||
supblk.block_group_no = BitConverter.ToUInt16(sb_sector, 0x05A);
|
||||
supblk.ftr_compat = BitConverter.ToUInt32(sb_sector, 0x05C);
|
||||
supblk.ftr_incompat = BitConverter.ToUInt32(sb_sector, 0x060);
|
||||
supblk.ftr_ro_compat = BitConverter.ToUInt32(sb_sector, 0x064);
|
||||
// Volume UUID
|
||||
Array.Copy(sb_sector, 0x068, guid_a, 0, 16);
|
||||
guid_b[0] = guid_a[3];
|
||||
guid_b[1] = guid_a[2];
|
||||
guid_b[2] = guid_a[1];
|
||||
guid_b[3] = guid_a[0];
|
||||
guid_b[4] = guid_a[5];
|
||||
guid_b[5] = guid_a[4];
|
||||
guid_b[6] = guid_a[7];
|
||||
guid_b[7] = guid_a[6];
|
||||
guid_b[8] = guid_a[8];
|
||||
guid_b[9] = guid_a[9];
|
||||
guid_b[10] = guid_a[10];
|
||||
guid_b[11] = guid_a[11];
|
||||
guid_b[12] = guid_a[12];
|
||||
guid_b[13] = guid_a[13];
|
||||
guid_b[14] = guid_a[14];
|
||||
guid_b[15] = guid_a[15];
|
||||
supblk.uuid = new Guid(guid_b);
|
||||
// End of volume UUID
|
||||
forstrings = new byte[16];
|
||||
Array.Copy(sb_sector, 0x078, forstrings, 0, 16);
|
||||
supblk.volume_name = StringHandlers.CToString(forstrings);
|
||||
forstrings = new byte[64];
|
||||
Array.Copy(sb_sector, 0x088, forstrings, 0, 64);
|
||||
supblk.last_mount_dir = StringHandlers.CToString(forstrings);
|
||||
supblk.algo_usage_bmp = BitConverter.ToUInt32(sb_sector, 0x0C8);
|
||||
supblk.prealloc_blks = sb_sector[0x0CC];
|
||||
supblk.prealloc_dir_blks = sb_sector[0x0CD];
|
||||
supblk.rsrvd_gdt_blocks = BitConverter.ToUInt16(sb_sector, 0x0CE);
|
||||
// ext3
|
||||
Array.Copy(sb_sector, 0x0D0, guid_a, 0, 16);
|
||||
guid_b[0] = guid_a[3];
|
||||
guid_b[1] = guid_a[2];
|
||||
guid_b[2] = guid_a[1];
|
||||
guid_b[3] = guid_a[0];
|
||||
guid_b[4] = guid_a[5];
|
||||
guid_b[5] = guid_a[4];
|
||||
guid_b[6] = guid_a[7];
|
||||
guid_b[7] = guid_a[6];
|
||||
guid_b[8] = guid_a[8];
|
||||
guid_b[9] = guid_a[9];
|
||||
guid_b[10] = guid_a[10];
|
||||
guid_b[11] = guid_a[11];
|
||||
guid_b[12] = guid_a[12];
|
||||
guid_b[13] = guid_a[13];
|
||||
guid_b[14] = guid_a[14];
|
||||
guid_b[15] = guid_a[15];
|
||||
supblk.journal_uuid = new Guid(guid_b);
|
||||
supblk.journal_inode = BitConverter.ToUInt32(sb_sector, 0x0E0);
|
||||
supblk.journal_dev = BitConverter.ToUInt32(sb_sector, 0x0E4);
|
||||
supblk.last_orphan = BitConverter.ToUInt32(sb_sector, 0x0E8);
|
||||
supblk.hash_seed_1 = BitConverter.ToUInt32(sb_sector, 0x0EC);
|
||||
supblk.hash_seed_2 = BitConverter.ToUInt32(sb_sector, 0x0F0);
|
||||
supblk.hash_seed_3 = BitConverter.ToUInt32(sb_sector, 0x0F4);
|
||||
supblk.hash_seed_4 = BitConverter.ToUInt32(sb_sector, 0x0F8);
|
||||
supblk.hash_version = sb_sector[0x0FC];
|
||||
supblk.jnl_backup_type = sb_sector[0x0FD];
|
||||
supblk.desc_grp_size = BitConverter.ToUInt16(sb_sector, 0x0FE);
|
||||
supblk.default_mnt_opts = BitConverter.ToUInt32(sb_sector, 0x100);
|
||||
supblk.first_meta_bg = BitConverter.ToUInt32(sb_sector, 0x104);
|
||||
// ext4
|
||||
supblk.mkfs_t = BitConverter.ToUInt32(sb_sector, 0x108);
|
||||
supblk.blocks_hi = BitConverter.ToUInt32(sb_sector, 0x14C);
|
||||
supblk.reserved_blocks_hi = BitConverter.ToUInt32(sb_sector, 0x150);
|
||||
supblk.free_blocks_hi = BitConverter.ToUInt32(sb_sector, 0x154);
|
||||
supblk.min_inode_size = BitConverter.ToUInt16(sb_sector, 0x158);
|
||||
supblk.rsv_inode_size = BitConverter.ToUInt16(sb_sector, 0x15A);
|
||||
supblk.flags = BitConverter.ToUInt32(sb_sector, 0x15C);
|
||||
supblk.raid_stride = BitConverter.ToUInt16(sb_sector, 0x160);
|
||||
supblk.mmp_interval = BitConverter.ToUInt16(sb_sector, 0x162);
|
||||
supblk.mmp_block = BitConverter.ToUInt64(sb_sector, 0x164);
|
||||
supblk.raid_stripe_width = BitConverter.ToUInt32(sb_sector, 0x16C);
|
||||
supblk.flex_bg_grp_size = sb_sector[0x170];
|
||||
supblk.kbytes_written = BitConverter.ToUInt64(sb_sector, 0x174);
|
||||
supblk.snapshot_inum = BitConverter.ToUInt32(sb_sector, 0x17C);
|
||||
supblk.snapshot_id = BitConverter.ToUInt32(sb_sector, 0x180);
|
||||
supblk.snapshot_blocks = BitConverter.ToUInt64(sb_sector, 0x184);
|
||||
supblk.snapshot_list = BitConverter.ToUInt32(sb_sector, 0x18C);
|
||||
supblk.error_count = BitConverter.ToUInt32(sb_sector, 0x190);
|
||||
supblk.first_error_t = BitConverter.ToUInt32(sb_sector, 0x194);
|
||||
supblk.first_error_inode = BitConverter.ToUInt32(sb_sector, 0x198);
|
||||
supblk.first_error_block = BitConverter.ToUInt64(sb_sector, 0x19C);
|
||||
forstrings = new byte[32];
|
||||
Array.Copy(sb_sector, 0x1A0, forstrings, 0, 32);
|
||||
supblk.first_error_func = StringHandlers.CToString(forstrings);
|
||||
supblk.first_error_line = BitConverter.ToUInt32(sb_sector, 0x1B0);
|
||||
supblk.last_error_t = BitConverter.ToUInt32(sb_sector, 0x1B4);
|
||||
supblk.last_error_inode = BitConverter.ToUInt32(sb_sector, 0x1B8);
|
||||
supblk.last_error_line = BitConverter.ToUInt32(sb_sector, 0x1BC);
|
||||
supblk.last_error_block = BitConverter.ToUInt64(sb_sector, 0x1C0);
|
||||
forstrings = new byte[32];
|
||||
Array.Copy(sb_sector, 0x1C8, forstrings, 0, 32);
|
||||
supblk.last_error_func = StringHandlers.CToString(forstrings);
|
||||
forstrings = new byte[64];
|
||||
Array.Copy(sb_sector, 0x1D8, forstrings, 0, 64);
|
||||
supblk.mount_options = StringHandlers.CToString(forstrings);
|
||||
|
||||
if (supblk.magic == ext2OldFSMagic)
|
||||
{
|
||||
sb.AppendLine("ext2 (old) filesystem");
|
||||
}
|
||||
else if (supblk.magic == ext2FSMagic)
|
||||
{
|
||||
ext3 |= (supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL || (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER || (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
|
||||
|
||||
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE ||
|
||||
(supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM ||
|
||||
(supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK ||
|
||||
(supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE ||
|
||||
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT ||
|
||||
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP ||
|
||||
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG ||
|
||||
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE ||
|
||||
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA)
|
||||
{
|
||||
ext3 = false;
|
||||
ext4 = true;
|
||||
}
|
||||
|
||||
new_ext2 |= !ext3 && !ext4;
|
||||
|
||||
if (new_ext2)
|
||||
sb.AppendLine("ext2 filesystem");
|
||||
if (ext3)
|
||||
sb.AppendLine("ext3 filesystem");
|
||||
if (ext4)
|
||||
sb.AppendLine("ext4 filesystem");
|
||||
}
|
||||
else
|
||||
{
|
||||
information = "Not a ext2/3/4 filesystem" + Environment.NewLine;
|
||||
return;
|
||||
}
|
||||
|
||||
string ext_os;
|
||||
switch (supblk.creator_os)
|
||||
{
|
||||
case EXT2_OS_FREEBSD:
|
||||
ext_os = "FreeBSD";
|
||||
break;
|
||||
case EXT2_OS_HURD:
|
||||
ext_os = "Hurd";
|
||||
break;
|
||||
case EXT2_OS_LINUX:
|
||||
ext_os = "Linux";
|
||||
break;
|
||||
case EXT2_OS_LITES:
|
||||
ext_os = "Lites";
|
||||
break;
|
||||
case EXT2_OS_MASIX:
|
||||
ext_os = "MasIX";
|
||||
break;
|
||||
default:
|
||||
ext_os = string.Format("Unknown OS ({0})", supblk.creator_os);
|
||||
break;
|
||||
}
|
||||
|
||||
if (supblk.mkfs_t > 0)
|
||||
sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t), ext_os).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("Volume was created for {0}", ext_os).AppendLine();
|
||||
|
||||
byte[] temp_lo, temp_hi;
|
||||
byte[] temp_bytes = new byte[8];
|
||||
UInt64 blocks, reserved, free;
|
||||
|
||||
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
|
||||
{
|
||||
temp_lo = BitConverter.GetBytes(supblk.blocks);
|
||||
temp_hi = BitConverter.GetBytes(supblk.blocks_hi);
|
||||
temp_bytes[0] = temp_lo[0];
|
||||
temp_bytes[1] = temp_lo[1];
|
||||
temp_bytes[2] = temp_lo[2];
|
||||
temp_bytes[3] = temp_lo[3];
|
||||
temp_bytes[4] = temp_hi[0];
|
||||
temp_bytes[5] = temp_hi[1];
|
||||
temp_bytes[6] = temp_hi[2];
|
||||
temp_bytes[7] = temp_hi[3];
|
||||
blocks = BitConverter.ToUInt64(temp_bytes, 0);
|
||||
|
||||
temp_lo = BitConverter.GetBytes(supblk.reserved_blocks);
|
||||
temp_hi = BitConverter.GetBytes(supblk.reserved_blocks_hi);
|
||||
temp_bytes[0] = temp_lo[0];
|
||||
temp_bytes[1] = temp_lo[1];
|
||||
temp_bytes[2] = temp_lo[2];
|
||||
temp_bytes[3] = temp_lo[3];
|
||||
temp_bytes[4] = temp_hi[0];
|
||||
temp_bytes[5] = temp_hi[1];
|
||||
temp_bytes[6] = temp_hi[2];
|
||||
temp_bytes[7] = temp_hi[3];
|
||||
reserved = BitConverter.ToUInt64(temp_bytes, 0);
|
||||
|
||||
temp_lo = BitConverter.GetBytes(supblk.free_blocks);
|
||||
temp_hi = BitConverter.GetBytes(supblk.free_blocks_hi);
|
||||
temp_bytes[0] = temp_lo[0];
|
||||
temp_bytes[1] = temp_lo[1];
|
||||
temp_bytes[2] = temp_lo[2];
|
||||
temp_bytes[3] = temp_lo[3];
|
||||
temp_bytes[4] = temp_hi[0];
|
||||
temp_bytes[5] = temp_hi[1];
|
||||
temp_bytes[6] = temp_hi[2];
|
||||
temp_bytes[7] = temp_hi[3];
|
||||
free = BitConverter.ToUInt64(temp_bytes, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks = supblk.blocks;
|
||||
reserved = supblk.reserved_blocks;
|
||||
free = supblk.free_blocks;
|
||||
}
|
||||
|
||||
if (supblk.block_size == 0) // Then it is 1024 bytes
|
||||
supblk.block_size = 1024;
|
||||
|
||||
sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks, 1024<<(int)supblk.block_size, blocks * (ulong)(1024<<(int)supblk.block_size)).AppendLine();
|
||||
if (supblk.mount_t > 0 || supblk.mount_c > 0)
|
||||
{
|
||||
if (supblk.mount_t > 0)
|
||||
sb.AppendFormat("Last mounted on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.mount_t)).AppendLine();
|
||||
if (supblk.max_mount_c != -1)
|
||||
sb.AppendFormat("Volume has been mounted {0} times of a maximum of {1} mounts before checking", supblk.mount_c, supblk.max_mount_c).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("Volume has been mounted {0} times with no maximum no. of mounts before checking", supblk.mount_c).AppendLine();
|
||||
if (supblk.last_mount_dir != "")
|
||||
sb.AppendFormat("Last mounted on: \"{0}\"", supblk.last_mount_dir).AppendLine();
|
||||
if (supblk.mount_options != "")
|
||||
sb.AppendFormat("Last used mount options were: {0}", supblk.mount_options).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("Volume has never been mounted");
|
||||
if (supblk.max_mount_c != -1)
|
||||
sb.AppendFormat("Volume can be mounted {0} times before checking", supblk.max_mount_c).AppendLine();
|
||||
else
|
||||
sb.AppendLine("Volume has no maximum no. of mounts before checking");
|
||||
}
|
||||
|
||||
if (supblk.check_t > 0)
|
||||
{
|
||||
if (supblk.check_inv > 0)
|
||||
sb.AppendFormat("Last checked on {0} (should check every {1} seconds)", DateHandlers.UNIXUnsignedToDateTime(supblk.check_t), supblk.check_inv).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("Last checked on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.check_t)).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (supblk.check_inv > 0)
|
||||
sb.AppendFormat("Volume has never been checked (should check every {0})", supblk.check_inv).AppendLine();
|
||||
else
|
||||
sb.AppendLine("Volume has never been checked");
|
||||
}
|
||||
|
||||
if (supblk.write_t > 0)
|
||||
sb.AppendFormat("Last written on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.write_t)).AppendLine();
|
||||
else
|
||||
sb.AppendLine("Volume has never been written");
|
||||
|
||||
switch (supblk.state)
|
||||
{
|
||||
case EXT2_VALID_FS:
|
||||
sb.AppendLine("Volume is clean");
|
||||
break;
|
||||
case EXT2_ERROR_FS:
|
||||
sb.AppendLine("Volume is dirty");
|
||||
break;
|
||||
case EXT3_ORPHAN_FS:
|
||||
sb.AppendLine("Volume is recovering orphan files");
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Volume is in an unknown state ({0})", supblk.state).AppendLine();
|
||||
break;
|
||||
}
|
||||
|
||||
if (supblk.volume_name != "")
|
||||
sb.AppendFormat("Volume name: \"{0}\"", supblk.volume_name).AppendLine();
|
||||
|
||||
switch (supblk.err_behaviour)
|
||||
{
|
||||
case EXT2_ERRORS_CONTINUE:
|
||||
sb.AppendLine("On errors, filesystem should continue");
|
||||
break;
|
||||
case EXT2_ERRORS_RO:
|
||||
sb.AppendLine("On errors, filesystem should remount read-only");
|
||||
break;
|
||||
case EXT2_ERRORS_PANIC:
|
||||
sb.AppendLine("On errors, filesystem should panic");
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("On errors filesystem will do an unknown thing ({0})", supblk.err_behaviour).AppendLine();
|
||||
break;
|
||||
}
|
||||
|
||||
if (supblk.revision > 0)
|
||||
sb.AppendFormat("Filesystem revision: {0}.{1}", supblk.revision, supblk.minor_revision).AppendLine();
|
||||
|
||||
if (supblk.uuid != Guid.Empty)
|
||||
sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine();
|
||||
|
||||
if (supblk.kbytes_written > 0)
|
||||
sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine();
|
||||
sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes, supblk.free_inodes * 100 / supblk.inodes).AppendLine();
|
||||
if (supblk.first_inode > 0)
|
||||
sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine();
|
||||
if (supblk.frag_size > 0)
|
||||
sb.AppendFormat("{0} bytes per fragment", supblk.frag_size).AppendLine();
|
||||
if (supblk.blocks_per_grp > 0 && supblk.flags_per_grp > 0 && supblk.inodes_per_grp > 0)
|
||||
sb.AppendFormat("{0} blocks, {1} flags and {2} inodes per group", supblk.blocks_per_grp, supblk.flags_per_grp, supblk.inodes_per_grp).AppendLine();
|
||||
if (supblk.first_block > 0)
|
||||
sb.AppendFormat("{0} is first data block", supblk.first_block).AppendLine();
|
||||
sb.AppendFormat("Default UID: {0}, GID: {1}", supblk.default_uid, supblk.default_gid).AppendLine();
|
||||
if (supblk.block_group_no > 0)
|
||||
sb.AppendFormat("Block group number is {0}", supblk.block_group_no).AppendLine();
|
||||
if (supblk.desc_grp_size > 0)
|
||||
sb.AppendFormat("Group descriptor size is {0} bytes", supblk.desc_grp_size).AppendLine();
|
||||
if (supblk.first_meta_bg > 0)
|
||||
sb.AppendFormat("First metablock group is {0}", supblk.first_meta_bg).AppendLine();
|
||||
if (supblk.raid_stride > 0)
|
||||
sb.AppendFormat("RAID stride: {0}", supblk.raid_stride).AppendLine();
|
||||
if (supblk.raid_stripe_width > 0)
|
||||
sb.AppendFormat("{0} blocks on all data disks", supblk.raid_stripe_width).AppendLine();
|
||||
if (supblk.mmp_interval > 0 && supblk.mmp_block > 0)
|
||||
sb.AppendFormat("{0} seconds for multi-mount protection wait, on block {1}", supblk.mmp_interval, supblk.mmp_block).AppendLine();
|
||||
if (supblk.flex_bg_grp_size > 0)
|
||||
sb.AppendFormat("{0} Flexible block group size", supblk.flex_bg_grp_size).AppendLine();
|
||||
if (supblk.hash_seed_1 > 0 && supblk.hash_seed_2 > 0 && supblk.hash_seed_3 > 0 && supblk.hash_seed_4 > 0)
|
||||
sb.AppendFormat("Hash seed: {0:X8}{1:X8}{2:X8}{3:X8}, version {4}", supblk.hash_seed_1, supblk.hash_seed_2, supblk.hash_seed_3, supblk.hash_seed_4, supblk.hash_version).AppendLine();
|
||||
|
||||
if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL ||
|
||||
(supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
{
|
||||
sb.AppendLine("Volume is journaled");
|
||||
if (supblk.journal_uuid != Guid.Empty)
|
||||
sb.AppendFormat("Journal UUID: {0}", supblk.journal_uuid).AppendLine();
|
||||
sb.AppendFormat("Journal has inode {0}", supblk.journal_inode).AppendLine();
|
||||
if ((supblk.ftr_compat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV && supblk.journal_dev > 0)
|
||||
sb.AppendFormat("Journal is on device {0}", supblk.journal_dev).AppendLine();
|
||||
if (supblk.jnl_backup_type > 0)
|
||||
sb.AppendFormat("Journal backup type: {0}", supblk.jnl_backup_type).AppendLine();
|
||||
if (supblk.last_orphan > 0)
|
||||
sb.AppendFormat("Last orphaned inode is {0}", supblk.last_orphan).AppendLine();
|
||||
else
|
||||
sb.AppendLine("There are no orphaned inodes");
|
||||
}
|
||||
|
||||
if (ext4)
|
||||
{
|
||||
if (supblk.snapshot_id > 0)
|
||||
sb.AppendFormat("Active snapshot has ID {0}, on inode {1}, with {2} blocks reserved, list starting on block {3}", supblk.snapshot_id,
|
||||
supblk.snapshot_inum, supblk.snapshot_blocks, supblk.snapshot_list).AppendLine();
|
||||
|
||||
if (supblk.error_count > 0)
|
||||
{
|
||||
sb.AppendFormat("{0} errors registered", supblk.error_count).AppendLine();
|
||||
sb.AppendFormat("First error occurred on {0}, last on {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.first_error_t), DateHandlers.UNIXUnsignedToDateTime(supblk.last_error_t)).AppendLine();
|
||||
sb.AppendFormat("First error inode is {0}, last is {1}", supblk.first_error_inode, supblk.last_error_inode).AppendLine();
|
||||
sb.AppendFormat("First error block is {0}, last is {1}", supblk.first_error_block, supblk.last_error_block).AppendLine();
|
||||
sb.AppendFormat("First error function is \"{0}\", last is \"{1}\"", supblk.first_error_func, supblk.last_error_func).AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendFormat("Flags…:").AppendLine();
|
||||
if ((supblk.flags & EXT2_FLAGS_SIGNED_HASH) == EXT2_FLAGS_SIGNED_HASH)
|
||||
sb.AppendLine("Signed directory hash is in use");
|
||||
if ((supblk.flags & EXT2_FLAGS_UNSIGNED_HASH) == EXT2_FLAGS_UNSIGNED_HASH)
|
||||
sb.AppendLine("Unsigned directory hash is in use");
|
||||
if ((supblk.flags & EXT2_FLAGS_TEST_FILESYS) == EXT2_FLAGS_TEST_FILESYS)
|
||||
sb.AppendLine("Volume is testing development code");
|
||||
if ((supblk.flags & 0xFFFFFFF8) != 0)
|
||||
sb.AppendFormat("Unknown set flags: {0:X8}", supblk.flags);
|
||||
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendFormat("Default mount options…:").AppendLine();
|
||||
if ((supblk.default_mnt_opts & EXT2_DEFM_DEBUG) == EXT2_DEFM_DEBUG)
|
||||
sb.AppendLine("(debug): Enable debugging code");
|
||||
if ((supblk.default_mnt_opts & EXT2_DEFM_BSDGROUPS) == EXT2_DEFM_BSDGROUPS)
|
||||
sb.AppendLine("(bsdgroups): Emulate BSD behaviour when creating new files");
|
||||
if ((supblk.default_mnt_opts & EXT2_DEFM_XATTR_USER) == EXT2_DEFM_XATTR_USER)
|
||||
sb.AppendLine("(user_xattr): Enable user-specified extended attributes");
|
||||
if ((supblk.default_mnt_opts & EXT2_DEFM_ACL) == EXT2_DEFM_ACL)
|
||||
sb.AppendLine("(acl): Enable POSIX ACLs");
|
||||
if ((supblk.default_mnt_opts & EXT2_DEFM_UID16) == EXT2_DEFM_UID16)
|
||||
sb.AppendLine("(uid16): Disable 32bit UIDs and GIDs");
|
||||
if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_DATA) == EXT3_DEFM_JMODE_DATA)
|
||||
sb.AppendLine("(journal_data): Journal data and metadata");
|
||||
if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_ORDERED) == EXT3_DEFM_JMODE_ORDERED)
|
||||
sb.AppendLine("(journal_data_ordered): Write data before journaling metadata");
|
||||
if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_WBACK) == EXT3_DEFM_JMODE_WBACK)
|
||||
sb.AppendLine("(journal_data_writeback): Write journal before data");
|
||||
if ((supblk.default_mnt_opts & 0xFFFFFE20) != 0)
|
||||
sb.AppendFormat("Unknown set default mount options: {0:X8}", supblk.default_mnt_opts);
|
||||
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendFormat("Compatible features…:").AppendLine();
|
||||
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_PREALLOC) == EXT2_FEATURE_COMPAT_DIR_PREALLOC)
|
||||
sb.AppendLine("Pre-allocate directories");
|
||||
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES) == EXT2_FEATURE_COMPAT_IMAGIC_INODES)
|
||||
sb.AppendLine("imagic inodes ?");
|
||||
if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL)
|
||||
sb.AppendLine("Has journal (ext3)");
|
||||
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) == EXT2_FEATURE_COMPAT_EXT_ATTR)
|
||||
sb.AppendLine("Has extended attribute blocks");
|
||||
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) == EXT2_FEATURE_COMPAT_RESIZE_INO)
|
||||
sb.AppendLine("Has online filesystem resize reservations");
|
||||
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) == EXT2_FEATURE_COMPAT_DIR_INDEX)
|
||||
sb.AppendLine("Can use hashed indexes on directories");
|
||||
if ((supblk.ftr_compat & 0xFFFFFFC0) != 0)
|
||||
sb.AppendFormat("Unknown compatible features: {0:X8}", supblk.ftr_compat);
|
||||
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendFormat("Compatible features if read-only…:").AppendLine();
|
||||
if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) == EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
|
||||
sb.AppendLine("Reduced number of superblocks");
|
||||
if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
|
||||
sb.AppendLine("Can have files bigger than 2GiB");
|
||||
if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_BTREE_DIR) == EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
||||
sb.AppendLine("Uses B-Tree for directories");
|
||||
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
|
||||
sb.AppendLine("Can have files bigger than 2TiB (ext4)");
|
||||
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
|
||||
sb.AppendLine("Group descriptor checksums and sparse inode table (ext4)");
|
||||
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
|
||||
sb.AppendLine("More than 32000 directory entries (ext4)");
|
||||
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
|
||||
sb.AppendLine("Supports nanosecond timestamps and creation time (ext4)");
|
||||
if ((supblk.ftr_ro_compat & 0xFFFFFF80) != 0)
|
||||
sb.AppendFormat("Unknown read-only compatible features: {0:X8}", supblk.ftr_ro_compat);
|
||||
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendFormat("Incompatible features…:").AppendLine();
|
||||
if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION) == EXT2_FEATURE_INCOMPAT_COMPRESSION)
|
||||
sb.AppendLine("Uses compression");
|
||||
if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) == EXT2_FEATURE_INCOMPAT_FILETYPE)
|
||||
sb.AppendLine("Filetype in directory entries");
|
||||
if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER)
|
||||
sb.AppendLine("Journal needs recovery (ext3)");
|
||||
if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
sb.AppendLine("Has journal on another device (ext3)");
|
||||
if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_META_BG) == EXT2_FEATURE_INCOMPAT_META_BG)
|
||||
sb.AppendLine("Reduced block group backups");
|
||||
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS) == EXT4_FEATURE_INCOMPAT_EXTENTS)
|
||||
sb.AppendLine("Volume use extents (ext4)");
|
||||
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
|
||||
sb.AppendLine("Supports volumes bigger than 2^32 blocks (ext4)");
|
||||
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP)
|
||||
sb.AppendLine("Multi-mount protection (ext4)");
|
||||
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG)
|
||||
sb.AppendLine("Flexible block group metadata location (ext4)");
|
||||
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE)
|
||||
sb.AppendLine("Extended attributes can reside in inode (ext4)");
|
||||
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA)
|
||||
sb.AppendLine("Data can reside in directory entry (ext4)");
|
||||
if ((supblk.ftr_incompat & 0xFFFFF020) != 0)
|
||||
sb.AppendFormat("Unknown incompatible features: {0:X8}", supblk.ftr_incompat);
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
public const UInt16 ext2FSMagic = 0xEF53;
|
||||
// Same for ext3 and ext4
|
||||
public const UInt16 ext2OldFSMagic = 0xEF51;
|
||||
// Size = 536 bytes
|
||||
public struct ext2FSSuperBlock
|
||||
{
|
||||
public UInt32 inodes;
|
||||
// 0x000, inodes on volume
|
||||
public UInt32 blocks;
|
||||
// 0x004, blocks on volume
|
||||
public UInt32 reserved_blocks;
|
||||
// 0x008, reserved blocks
|
||||
public UInt32 free_blocks;
|
||||
// 0x00C, free blocks count
|
||||
public UInt32 free_inodes;
|
||||
// 0x010, free inodes count
|
||||
public UInt32 first_block;
|
||||
// 0x014, first data block
|
||||
public UInt32 block_size;
|
||||
// 0x018, block size
|
||||
public Int32 frag_size;
|
||||
// 0x01C, fragment size
|
||||
public UInt32 blocks_per_grp;
|
||||
// 0x020, blocks per group
|
||||
public UInt32 flags_per_grp;
|
||||
// 0x024, fragments per group
|
||||
public UInt32 inodes_per_grp;
|
||||
// 0x028, inodes per group
|
||||
public UInt32 mount_t;
|
||||
// 0x02C, last mount time
|
||||
public UInt32 write_t;
|
||||
// 0x030, last write time
|
||||
public UInt16 mount_c;
|
||||
// 0x034, mounts count
|
||||
public Int16 max_mount_c;
|
||||
// 0x036, max mounts
|
||||
public UInt16 magic;
|
||||
// 0x038, (little endian)
|
||||
public UInt16 state;
|
||||
// 0x03A, filesystem state
|
||||
public UInt16 err_behaviour;
|
||||
// 0x03C, behaviour on errors
|
||||
public UInt16 minor_revision;
|
||||
// 0x03E, From 0.5b onward
|
||||
public UInt32 check_t;
|
||||
// 0x040, last check time
|
||||
public UInt32 check_inv;
|
||||
// 0x044, max time between checks
|
||||
// From 0.5a onward
|
||||
public UInt32 creator_os;
|
||||
// 0x048, Creation OS
|
||||
public UInt32 revision;
|
||||
// 0x04C, Revison level
|
||||
public UInt16 default_uid;
|
||||
// 0x050, Default UID for reserved blocks
|
||||
public UInt16 default_gid;
|
||||
// 0x052, Default GID for reserved blocks
|
||||
// From 0.5b onward
|
||||
public UInt32 first_inode;
|
||||
// 0x054, First unreserved inode
|
||||
public UInt16 inode_size;
|
||||
// 0x058, inode size
|
||||
public UInt16 block_group_no;
|
||||
// 0x05A, Block group number of THIS superblock
|
||||
public UInt32 ftr_compat;
|
||||
// 0x05C, Compatible features set
|
||||
public UInt32 ftr_incompat;
|
||||
// 0x060, Incompatible features set
|
||||
// Found on Linux 2.0.40
|
||||
public UInt32 ftr_ro_compat;
|
||||
// 0x064, Read-only compatible features set
|
||||
// Found on Linux 2.1.132
|
||||
public Guid uuid;
|
||||
// 0x068, 16 bytes, UUID
|
||||
public string volume_name;
|
||||
// 0x078, 16 bytes, volume name
|
||||
public string last_mount_dir;
|
||||
// 0x088, 64 bytes, where last mounted
|
||||
public UInt32 algo_usage_bmp;
|
||||
// 0x0C8, Usage bitmap algorithm, for compression
|
||||
public byte prealloc_blks;
|
||||
// 0x0CC, Block to try to preallocate
|
||||
public byte prealloc_dir_blks;
|
||||
// 0x0CD, Blocks to try to preallocate for directories
|
||||
public UInt16 rsrvd_gdt_blocks;
|
||||
// 0x0CE, Per-group desc for online growth
|
||||
// Found on Linux 2.4
|
||||
// ext3
|
||||
public Guid journal_uuid;
|
||||
// 0x0D0, 16 bytes, UUID of journal superblock
|
||||
public UInt32 journal_inode;
|
||||
// 0x0E0, inode no. of journal file
|
||||
public UInt32 journal_dev;
|
||||
// 0x0E4, device no. of journal file
|
||||
public UInt32 last_orphan;
|
||||
// 0x0E8, Start of list of inodes to delete
|
||||
public UInt32 hash_seed_1;
|
||||
// 0x0EC, First byte of 128bit HTREE hash seed
|
||||
public UInt32 hash_seed_2;
|
||||
// 0x0F0, Second byte of 128bit HTREE hash seed
|
||||
public UInt32 hash_seed_3;
|
||||
// 0x0F4, Third byte of 128bit HTREE hash seed
|
||||
public UInt32 hash_seed_4;
|
||||
// 0x0F8, Fourth byte of 128bit HTREE hash seed
|
||||
public byte hash_version;
|
||||
// 0x0FC, Hash version
|
||||
public byte jnl_backup_type;
|
||||
// 0x0FD, Journal backup type
|
||||
public UInt16 desc_grp_size;
|
||||
// 0x0FE, Size of group descriptor
|
||||
public UInt32 default_mnt_opts;
|
||||
// 0x100, Default mount options
|
||||
public UInt32 first_meta_bg;
|
||||
// 0x104, First metablock block group
|
||||
// Introduced with ext4, some can be ext3
|
||||
public UInt32 mkfs_t;
|
||||
// 0x108, Filesystem creation time
|
||||
// Follows 17 uint32 (68 bytes) of journal inode backup
|
||||
// Following 3 fields are valid if EXT4_FEATURE_COMPAT_64BIT is set
|
||||
public UInt32 blocks_hi;
|
||||
// 0x14C, High 32bits of blocks no.
|
||||
public UInt32 reserved_blocks_hi;
|
||||
// 0x150, High 32bits of reserved blocks no.
|
||||
public UInt32 free_blocks_hi;
|
||||
// 0x154, High 32bits of free blocks no.
|
||||
public UInt16 min_inode_size;
|
||||
// 0x158, inodes minimal size in bytes
|
||||
public UInt16 rsv_inode_size;
|
||||
// 0x15A, Bytes reserved by new inodes
|
||||
public UInt32 flags;
|
||||
// 0x15C, Flags
|
||||
public UInt16 raid_stride;
|
||||
// 0x160, RAID stride
|
||||
public UInt16 mmp_interval;
|
||||
// 0x162, Waiting seconds in MMP check
|
||||
public UInt64 mmp_block;
|
||||
// 0x164, Block for multi-mount protection
|
||||
public UInt32 raid_stripe_width;
|
||||
// 0x16C, Blocks on all data disks (N*stride)
|
||||
public byte flex_bg_grp_size;
|
||||
// 0x170, FLEX_BG group size
|
||||
public byte padding;
|
||||
// 0x171
|
||||
public UInt16 padding2;
|
||||
// 0x172
|
||||
// Following are introduced with ext4
|
||||
public UInt64 kbytes_written;
|
||||
// 0x174, Kibibytes written in volume lifetime
|
||||
public UInt32 snapshot_inum;
|
||||
// 0x17C, Active snapshot inode number
|
||||
public UInt32 snapshot_id;
|
||||
// 0x180, Active snapshot sequential ID
|
||||
public UInt64 snapshot_blocks;
|
||||
// 0x184, Reserved blocks for active snapshot's future use
|
||||
public UInt32 snapshot_list;
|
||||
// 0x18C, inode number of the on-disk start of the snapshot list
|
||||
// Optional ext4 error-handling features
|
||||
public UInt32 error_count;
|
||||
// 0x190, total registered filesystem errors
|
||||
public UInt32 first_error_t;
|
||||
// 0x194, time on first error
|
||||
public UInt32 first_error_inode;
|
||||
// 0x198, inode involved in first error
|
||||
public UInt64 first_error_block;
|
||||
// 0x19C, block involved of first error
|
||||
public string first_error_func;
|
||||
// 0x1A0, 32 bytes, function where the error happened
|
||||
public UInt32 first_error_line;
|
||||
// 0x1B0, line number where error happened
|
||||
public UInt32 last_error_t;
|
||||
// 0x1B4, time of most recent error
|
||||
public UInt32 last_error_inode;
|
||||
// 0x1B8, inode involved in last error
|
||||
public UInt32 last_error_line;
|
||||
// 0x1BC, line number where error happened
|
||||
public UInt64 last_error_block;
|
||||
// 0x1C0, block involved of last error
|
||||
public string last_error_func;
|
||||
// 0x1C8, 32 bytes, function where the error happened
|
||||
// End of optional error-handling features
|
||||
public string mount_options;
|
||||
// 0x1D8, 64 bytes, last used mount options
|
||||
}
|
||||
// ext? filesystem states
|
||||
public const UInt16 EXT2_VALID_FS = 0x0001;
|
||||
// Cleanly-unmounted volume
|
||||
public const UInt16 EXT2_ERROR_FS = 0x0002;
|
||||
// Dirty volume
|
||||
public const UInt16 EXT3_ORPHAN_FS = 0x0004;
|
||||
// Recovering orphan files
|
||||
// ext? default mount flags
|
||||
public const UInt32 EXT2_DEFM_DEBUG = 0x000001;
|
||||
// Enable debugging messages
|
||||
public const UInt32 EXT2_DEFM_BSDGROUPS = 0x000002;
|
||||
// Emulates BSD behaviour on new file creation
|
||||
public const UInt32 EXT2_DEFM_XATTR_USER = 0x000004;
|
||||
// Enable user xattrs
|
||||
public const UInt32 EXT2_DEFM_ACL = 0x000008;
|
||||
// Enable POSIX ACLs
|
||||
public const UInt32 EXT2_DEFM_UID16 = 0x000010;
|
||||
// Use 16bit UIDs
|
||||
public const UInt32 EXT3_DEFM_JMODE_DATA = 0x000040;
|
||||
// Journal data mode
|
||||
public const UInt32 EXT3_DEFM_JMODE_ORDERED = 0x000080;
|
||||
// Journal ordered mode
|
||||
public const UInt32 EXT3_DEFM_JMODE_WBACK = 0x000100;
|
||||
// Journal writeback mode
|
||||
// Behaviour on errors
|
||||
public const UInt16 EXT2_ERRORS_CONTINUE = 1;
|
||||
// Continue execution
|
||||
public const UInt16 EXT2_ERRORS_RO = 2;
|
||||
// Remount fs read-only
|
||||
public const UInt16 EXT2_ERRORS_PANIC = 3;
|
||||
// Panic
|
||||
// OS codes
|
||||
public const UInt32 EXT2_OS_LINUX = 0;
|
||||
public const UInt32 EXT2_OS_HURD = 1;
|
||||
public const UInt32 EXT2_OS_MASIX = 2;
|
||||
public const UInt32 EXT2_OS_FREEBSD = 3;
|
||||
public const UInt32 EXT2_OS_LITES = 4;
|
||||
// Revision levels
|
||||
public const UInt32 EXT2_GOOD_OLD_REV = 0;
|
||||
/* The good old (original) format */
|
||||
public const UInt32 EXT2_DYNAMIC_REV = 1;
|
||||
/* V2 format w/ dynamic inode sizes */
|
||||
// Compatible features
|
||||
public const UInt32 EXT2_FEATURE_COMPAT_DIR_PREALLOC = 0x00000001;
|
||||
// Pre-allocate directories
|
||||
public const UInt32 EXT2_FEATURE_COMPAT_IMAGIC_INODES = 0x00000002;
|
||||
// imagic inodes ?
|
||||
public const UInt32 EXT3_FEATURE_COMPAT_HAS_JOURNAL = 0x00000004;
|
||||
// Has journal (it's ext3)
|
||||
public const UInt32 EXT2_FEATURE_COMPAT_EXT_ATTR = 0x00000008;
|
||||
// EA blocks
|
||||
public const UInt32 EXT2_FEATURE_COMPAT_RESIZE_INO = 0x00000010;
|
||||
// Online filesystem resize reservations
|
||||
public const UInt32 EXT2_FEATURE_COMPAT_DIR_INDEX = 0x00000020;
|
||||
// Can use hashed indexes on directories
|
||||
// Read-only compatible features
|
||||
public const UInt32 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x00000001;
|
||||
// Reduced number of superblocks
|
||||
public const UInt32 EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x00000002;
|
||||
// Can have files bigger than 2GiB
|
||||
public const UInt32 EXT2_FEATURE_RO_COMPAT_BTREE_DIR = 0x00000004;
|
||||
// Use B-Tree for directories
|
||||
public const UInt32 EXT4_FEATURE_RO_COMPAT_HUGE_FILE = 0x00000008;
|
||||
// Can have files bigger than 2TiB *ext4*
|
||||
public const UInt32 EXT4_FEATURE_RO_COMPAT_GDT_CSUM = 0x00000010;
|
||||
// Group descriptor checksums and sparse inode table *ext4*
|
||||
public const UInt32 EXT4_FEATURE_RO_COMPAT_DIR_NLINK = 0x00000020;
|
||||
// More than 32000 directory entries *ext4*
|
||||
public const UInt32 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE = 0x00000040;
|
||||
// Nanosecond timestamps and creation time *ext4*
|
||||
// Incompatible features
|
||||
public const UInt32 EXT2_FEATURE_INCOMPAT_COMPRESSION = 0x00000001;
|
||||
// Uses compression
|
||||
public const UInt32 EXT2_FEATURE_INCOMPAT_FILETYPE = 0x00000002;
|
||||
// Filetype in directory entries
|
||||
public const UInt32 EXT3_FEATURE_INCOMPAT_RECOVER = 0x00000004;
|
||||
// Journal needs recovery *ext3*
|
||||
public const UInt32 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV = 0x00000008;
|
||||
// Has journal on another device *ext3*
|
||||
public const UInt32 EXT2_FEATURE_INCOMPAT_META_BG = 0x00000010;
|
||||
// Reduced block group backups
|
||||
public const UInt32 EXT4_FEATURE_INCOMPAT_EXTENTS = 0x00000040;
|
||||
// Volume use extents *ext4*
|
||||
public const UInt32 EXT4_FEATURE_INCOMPAT_64BIT = 0x00000080;
|
||||
// Supports volumes bigger than 2^32 blocks *ext4*
|
||||
public const UInt32 EXT4_FEATURE_INCOMPAT_MMP = 0x00000100;
|
||||
// Multi-mount protection *ext4*
|
||||
public const UInt32 EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x00000200;
|
||||
// Flexible block group metadata location *ext4*
|
||||
public const UInt32 EXT4_FEATURE_INCOMPAT_EA_INODE = 0x00000400;
|
||||
// EA in inode *ext4*
|
||||
public const UInt32 EXT4_FEATURE_INCOMPAT_DIRDATA = 0x00001000;
|
||||
// Data can reside in directory entry *ext4*
|
||||
// Miscellaneous filesystem flags
|
||||
public const UInt32 EXT2_FLAGS_SIGNED_HASH = 0x00000001;
|
||||
// Signed dirhash in use
|
||||
public const UInt32 EXT2_FLAGS_UNSIGNED_HASH = 0x00000002;
|
||||
// Unsigned dirhash in use
|
||||
public const UInt32 EXT2_FLAGS_TEST_FILESYS = 0x00000004;
|
||||
// Testing development code
|
||||
}
|
||||
}
|
||||
131
DiscImageChef/Plugins/extFS.cs
Normal file
131
DiscImageChef/Plugins/extFS.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : extFS.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Filesystem plugins
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Identifies Linux extended filesystem and shows information.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef;
|
||||
|
||||
// Information from the Linux kernel
|
||||
namespace DiscImageChef.Plugins
|
||||
{
|
||||
class extFS : Plugin
|
||||
{
|
||||
public extFS(PluginBase Core)
|
||||
{
|
||||
Name = "Linux extended Filesystem";
|
||||
PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
||||
{
|
||||
byte[] sb_sector = imagePlugin.ReadSector(2 + partitionOffset); // Superblock resides at 0x400
|
||||
|
||||
UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038); // Here should reside magic number
|
||||
|
||||
return magic == extFSMagic;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(2 + partitionOffset); // Superblock resides at 0x400
|
||||
extFSSuperBlock ext_sb = new extFSSuperBlock();
|
||||
|
||||
ext_sb.inodes = BitConverter.ToUInt32(sb_sector, 0x000);
|
||||
ext_sb.zones = BitConverter.ToUInt32(sb_sector, 0x004);
|
||||
ext_sb.firstfreeblk = BitConverter.ToUInt32(sb_sector, 0x008);
|
||||
ext_sb.freecountblk = BitConverter.ToUInt32(sb_sector, 0x00C);
|
||||
ext_sb.firstfreeind = BitConverter.ToUInt32(sb_sector, 0x010);
|
||||
ext_sb.freecountind = BitConverter.ToUInt32(sb_sector, 0x014);
|
||||
ext_sb.firstdatazone = BitConverter.ToUInt32(sb_sector, 0x018);
|
||||
ext_sb.logzonesize = BitConverter.ToUInt32(sb_sector, 0x01C);
|
||||
ext_sb.maxsize = BitConverter.ToUInt32(sb_sector, 0x020);
|
||||
|
||||
sb.AppendLine("ext filesystem");
|
||||
sb.AppendFormat("{0} zones on volume", ext_sb.zones);
|
||||
sb.AppendFormat("{0} free blocks ({1} bytes)", ext_sb.freecountblk, ext_sb.freecountblk * 1024);
|
||||
sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", ext_sb.inodes, ext_sb.freecountind, ext_sb.freecountind * 100 / ext_sb.inodes);
|
||||
sb.AppendFormat("First free inode is {0}", ext_sb.firstfreeind);
|
||||
sb.AppendFormat("First free block is {0}", ext_sb.firstfreeblk);
|
||||
sb.AppendFormat("First data zone is {0}", ext_sb.firstdatazone);
|
||||
sb.AppendFormat("Log zone size: {0}", ext_sb.logzonesize);
|
||||
sb.AppendFormat("Max zone size: {0}", ext_sb.maxsize);
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
public const UInt16 extFSMagic = 0x137D;
|
||||
|
||||
public struct extFSSuperBlock
|
||||
{
|
||||
public UInt32 inodes;
|
||||
// 0x000, inodes on volume
|
||||
public UInt32 zones;
|
||||
// 0x004, zones on volume
|
||||
public UInt32 firstfreeblk;
|
||||
// 0x008, first free block
|
||||
public UInt32 freecountblk;
|
||||
// 0x00C, free blocks count
|
||||
public UInt32 firstfreeind;
|
||||
// 0x010, first free inode
|
||||
public UInt32 freecountind;
|
||||
// 0x014, free inodes count
|
||||
public UInt32 firstdatazone;
|
||||
// 0x018, first data zone
|
||||
public UInt32 logzonesize;
|
||||
// 0x01C, log zone size
|
||||
public UInt32 maxsize;
|
||||
// 0x020, max zone size
|
||||
public UInt32 reserved1;
|
||||
// 0x024, reserved
|
||||
public UInt32 reserved2;
|
||||
// 0x028, reserved
|
||||
public UInt32 reserved3;
|
||||
// 0x02C, reserved
|
||||
public UInt32 reserved4;
|
||||
// 0x030, reserved
|
||||
public UInt32 reserved5;
|
||||
// 0x034, reserved
|
||||
public UInt16 magic;
|
||||
// 0x038, 0x137D (little endian)
|
||||
}
|
||||
}
|
||||
}
|
||||
84
DiscImageChef/PrintHex.cs
Normal file
84
DiscImageChef/PrintHex.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : PrintHex.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Helpers
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Prints a byte array as hexadecimal in console.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
using System;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
public static class PrintHex
|
||||
{
|
||||
public static void PrintHexArray(byte[] array, int width)
|
||||
{
|
||||
int counter = 0;
|
||||
int subcounter = 0;
|
||||
for (long i = 0; i < array.LongLength; i++)
|
||||
{
|
||||
if (counter == 0)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.Write("{0:X16} ", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (subcounter == 3 )
|
||||
{
|
||||
Console.Write(" ");
|
||||
subcounter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write(" ");
|
||||
subcounter++;
|
||||
}
|
||||
}
|
||||
|
||||
Console.Write("{0:X2}", array[i]);
|
||||
|
||||
if (counter == width - 1)
|
||||
{
|
||||
counter = 0;
|
||||
subcounter = 0;
|
||||
}
|
||||
else
|
||||
counter++;
|
||||
}
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
33
DiscImageChef/README.md
Normal file
33
DiscImageChef/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
DiscImageChef v1.10
|
||||
===================
|
||||
|
||||
Filesystem identifier and checker.
|
||||
|
||||
Copyright © 2011-2014 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
DiscImageChef.exe
|
||||
|
||||
And read help.
|
||||
|
||||
Works under any operating system where there is Mono or .NET Framework. Tested with Mono 2.0.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
* Supports reading CDRWin cue/bin cuesheets, Apple DiskCopy 4.2 and TeleDisk disk images.
|
||||
* Supports reading all raw (sector by sector copy) disk images with a multiple of 512 bytes/sector, and a few known formats that are 256, 128 and variable bytes per sector.
|
||||
* Supports traversing MBR, Apple and NeXT partitioning schemes.
|
||||
* Identifies HFS, HFS+, MFS, BeFS, ext/2/3/4, FAT12/16/32, FFS/UFS/UFS2, HPFS, ISO9660, LisaFS, MinixFS, NTFS, ODS11, Opera, PCEngine, SolarFS, System V and UnixWare boot filesystem.
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
See Changelog file.
|
||||
|
||||
To-Do
|
||||
=====
|
||||
|
||||
See TODO file.
|
||||
76
DiscImageChef/StringHandlers.cs
Normal file
76
DiscImageChef/StringHandlers.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : StringHandlers.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Program tools
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Convert byte arrays to C# strings.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
public static class StringHandlers
|
||||
{
|
||||
public static string CToString(byte[] CString)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < CString.Length; i++)
|
||||
{
|
||||
if (CString[i] == 0)
|
||||
break;
|
||||
|
||||
sb.Append(Encoding.ASCII.GetString(CString, i, 1));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string PascalToString(byte[] PascalString)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
byte length = PascalString[0];
|
||||
|
||||
for (int i = 1; i < length + 1; i++)
|
||||
{
|
||||
sb.Append(Encoding.ASCII.GetString(PascalString, i, 1));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
111
DiscImageChef/Swapping.cs
Normal file
111
DiscImageChef/Swapping.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : Swapping.cs
|
||||
Version : 1.0
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : Program tools
|
||||
|
||||
Revision : $Revision$
|
||||
Last change by : $Author$
|
||||
Date : $Date$
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Byte-swapping methods
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2014 Claunia.com
|
||||
****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
using System;
|
||||
|
||||
namespace DiscImageChef
|
||||
{
|
||||
static class Swapping
|
||||
{
|
||||
public static byte[] SwapTenBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[8];
|
||||
|
||||
destination[0] = source[9];
|
||||
destination[1] = source[8];
|
||||
destination[2] = source[7];
|
||||
destination[3] = source[6];
|
||||
destination[4] = source[5];
|
||||
destination[5] = source[4];
|
||||
destination[6] = source[3];
|
||||
destination[7] = source[2];
|
||||
destination[8] = source[1];
|
||||
destination[9] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static byte[] SwapEightBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[8];
|
||||
|
||||
destination[0] = source[7];
|
||||
destination[1] = source[6];
|
||||
destination[2] = source[5];
|
||||
destination[3] = source[4];
|
||||
destination[4] = source[3];
|
||||
destination[5] = source[2];
|
||||
destination[6] = source[1];
|
||||
destination[7] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static byte[] SwapFourBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[4];
|
||||
|
||||
destination[0] = source[3];
|
||||
destination[1] = source[2];
|
||||
destination[2] = source[1];
|
||||
destination[3] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static byte[] SwapTwoBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[2];
|
||||
|
||||
destination[0] = source[1];
|
||||
destination[1] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static UInt32 PDPFromLittleEndian(UInt32 x)
|
||||
{
|
||||
return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
|
||||
}
|
||||
|
||||
public static UInt32 PDPFromBigEndian(UInt32 x)
|
||||
{
|
||||
return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
71
DiscImageChef/TODO
Normal file
71
DiscImageChef/TODO
Normal file
@@ -0,0 +1,71 @@
|
||||
Disc image plugins:
|
||||
--- Add support for BlindWrite images
|
||||
--- Add support for CloneCD images
|
||||
--- Add support for DiscJuggler images
|
||||
--- Add support for Alcohol images
|
||||
--- Add support for Nero images
|
||||
--- Add support for cdrdao images
|
||||
--- Add support for dump(8) images
|
||||
--- Add support for IMD images
|
||||
--- Add support for Kryoflux images
|
||||
--- Add support for DiscFerret images
|
||||
--- Add support for MAME CHDs
|
||||
--- Add support for Apple NDIF images
|
||||
--- Add support for Apple UDIF images
|
||||
--- Add support for XPACK images
|
||||
--- Add support for QEMU QCOW and QCOW2 images
|
||||
--- Add support for VHD and VHDX images
|
||||
--- Add support for VirtualBox images
|
||||
--- Add support for VMWare images
|
||||
--- Add support foe QEMU QED images
|
||||
|
||||
Filesystem plugins:
|
||||
--- Add support for AmigaOS filesystems
|
||||
--- Add support for SFS filesystem
|
||||
--- Add support for PFS3 filesystem
|
||||
--- Add support for Acorn filesystems
|
||||
--- Add support for Apple DOS filesystems
|
||||
--- Add support for Apple ProDOS filesystem
|
||||
--- Add support for UCSD/Pascal filesystem
|
||||
--- Add support for AMSDOS filesystem
|
||||
--- Add support for CP/M filesystem
|
||||
--- Add support for CBM filesystem
|
||||
--- Add support for btrfs
|
||||
--- Add support for ZFS
|
||||
--- Add support for UDF
|
||||
--- Add support for CramFS
|
||||
--- Add support for VxFS
|
||||
--- Add support for VMWare filesystem
|
||||
--- Add support for NwFS
|
||||
--- Add support for JFS
|
||||
--- Add support for Reiser filesystems
|
||||
--- Add support for QNX filesystems
|
||||
--- Add support for Squashfs
|
||||
--- Add support for X-Box filesystems
|
||||
--- Add support for exFAT
|
||||
--- Add support for FAT+
|
||||
--- Add support for ReFS
|
||||
--- Add support for ECMA-67
|
||||
|
||||
Partitioning scheme plugins:
|
||||
--- Add support for Acorn partitions
|
||||
--- Add support for Amiga's RDB
|
||||
--- Add support for Atari partitions
|
||||
--- Add support for AIX partitions
|
||||
--- Add support for EFI GPT
|
||||
--- Add support for SGI partitions
|
||||
--- Add support for Sun partitions
|
||||
--- Add support for Ultrix partitions
|
||||
|
||||
Things to test/debug:
|
||||
--- After moving to disc images, HFS CDs with 512 bytes/sector are not detected anymore
|
||||
|
||||
Other things:
|
||||
--- Surprise!
|
||||
|
||||
Teledisk plugin:
|
||||
--- Add support for "advanced compression"
|
||||
--- Handle variable sectors per track situation. Teledisk seems to be able to read garbage from previous formattings.
|
||||
|
||||
RAW plugin:
|
||||
--- Finish support for reading sectors of variable bytes/sector images
|
||||
Reference in New Issue
Block a user