* FileSystemIDandChk/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.

	* FileSystemIDandChk/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.

	* FileSystemIDandChk/Plugins/BFS.cs:
	  Missed negation operand

	* FileSystemIDandChk/PartPlugins/NeXT.cs:
	* FileSystemIDandChk/PartPlugins/AppleMap.cs:
	  Added constants and modified for EndianAwareBinaryReader
	  class.

git-svn-id: svn://claunia.com/FileSystemIDandChk@16 17725271-3d32-4980-a8cb-9ff532f270ba
This commit is contained in:
2012-08-05 03:02:55 +00:00
parent 9d446877b4
commit a20dbb709a
6 changed files with 244 additions and 245 deletions

View File

@@ -1,3 +1,23 @@
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> 2012-08-05 Natalia Portillo <claunia@claunia.com>
* Plugins/ODS.cs: * Plugins/ODS.cs:

View File

@@ -8,6 +8,10 @@ namespace FileSystemIDandChk.PartPlugins
{ {
class AppleMap : PartPlugin class AppleMap : PartPlugin
{ {
private const UInt16 APM_MAGIC = 0x4552; // "ER"
private const UInt16 APM_ENTRY = 0x504D; // "PM"
private const UInt16 APM_OLDENT = 0x5453; // "TS", old entry magic
public AppleMap (PluginBase Core) public AppleMap (PluginBase Core)
{ {
base.Name = "Apple Partition Map"; base.Name = "Apple Partition Map";
@@ -16,10 +20,7 @@ namespace FileSystemIDandChk.PartPlugins
public override bool GetInformation (FileStream stream, out List<Partition> partitions) public override bool GetInformation (FileStream stream, out List<Partition> partitions)
{ {
byte[] sixteen_bits = new byte[2]; byte[] cString;
byte[] thirtytwo_bits = new byte[4];
byte[] sixteen_bytes = new byte[16];
byte[] thirtytwo_bytes = new byte[32];
ulong apm_entries; ulong apm_entries;
@@ -27,42 +28,60 @@ namespace FileSystemIDandChk.PartPlugins
AppleMapBootEntry APMB = new AppleMapBootEntry(); AppleMapBootEntry APMB = new AppleMapBootEntry();
AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry(); AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry();
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
eabr.BaseStream.Seek(0, SeekOrigin.Begin);
APMB.signature = eabr.ReadUInt16();
stream.Seek(0, SeekOrigin.Begin); if(APMB.signature == APM_MAGIC)
stream.Read(sixteen_bits, 0, 2);
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits);
APMB.signature = BitConverter.ToUInt16(sixteen_bits, 0);
if(APMB.signature == 0x4552)
{ {
stream.Read(sixteen_bits, 0, 2); APMB.sector_size = eabr.ReadUInt16();
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits);
APMB.sector_size = BitConverter.ToUInt16(sixteen_bits, 0);
} }
else else
APMB.sector_size = 512; // Some disks omit the boot entry APMB.sector_size = 512; // Some disks omit the boot entry
// stream.Seek(APMB.sector_size, SeekOrigin.Begin); // Seek to first entry if(APMB.sector_size == 2048) // A CD, search if buggy (aligns in 512 bytes blocks) first
stream.Seek(0x200, SeekOrigin.Begin); // Seek to first entry {
stream.Read(sixteen_bits, 0, 2); eabr.BaseStream.Seek(512, SeekOrigin.Begin); // Seek to first entry
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); APMEntry.signature = eabr.ReadUInt16();
APMEntry.signature = BitConverter.ToUInt16(sixteen_bits, 0); if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) // It should have partition entry signature if buggy
if(APMEntry.signature != 0x504D && APMEntry.signature != 0x5453) // It should have partition entry signature {
return false; eabr.BaseStream.Seek(2048, SeekOrigin.Begin); // Seek to first entry considering 2048 bytes blocks. Unbuggy.
APMEntry.signature = eabr.ReadUInt16();
stream.Seek(2, SeekOrigin.Current); // Skip reserved1 if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
stream.Read(thirtytwo_bits, 0, 4); return false;
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); else
APMEntry.entries = BitConverter.ToUInt32(thirtytwo_bits, 0); APMB.sector_size = 2048;
}
else
APMB.sector_size = 512;
}
else
{
eabr.BaseStream.Seek(APMB.sector_size, SeekOrigin.Begin); // Seek to first entry
APMEntry.signature = eabr.ReadUInt16();
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) // It should have partition entry signature if buggy
{
eabr.BaseStream.Seek(512, SeekOrigin.Begin); // Seek to first entry considering 512 bytes blocks. Buggy.
APMEntry.signature = eabr.ReadUInt16();
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
return false;
else
APMB.sector_size = 512;
}
}
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip reserved1
APMEntry.entries = eabr.ReadUInt32();
if(APMEntry.entries <= 1) // It should have more than one entry if(APMEntry.entries <= 1) // It should have more than one entry
return false; return false;
// stream.Seek(4, SeekOrigin.Current); // Skip start, we don't need it // eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip start, we don't need it
// stream.Seek(4, SeekOrigin.Current); // Skip sectors, we don't need it // eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip sectors, we don't need it
// stream.Seek(32, SeekOrigin.Current); // Skip name, we don't ned it // eabr.BaseStream.Seek(32, SeekOrigin.Current); // Skip name, we don't ned it
// stream.Read(thirtytwo_bytes, 0, 32); // cString = eabr.ReadBytes(32);
// APMEntry.type = StringHandlers.CToString(thirtytwo_bytes); // APMEntry.type = StringHandlers.CToString(cString);
// if(APMEntry.type != "Apple_partition_map") // APM self-describes, if not, this is incorrect // if(APMEntry.type != "Apple_partition_map") // APM self-describes, if not, this is incorrect
// return false; // return false;
@@ -72,66 +91,44 @@ namespace FileSystemIDandChk.PartPlugins
{ {
APMEntry = new AppleMapPartitionEntry(); APMEntry = new AppleMapPartitionEntry();
//stream.Seek((long)(APMB.sector_size*i), SeekOrigin.Begin); // Seek to partition descriptor eabr.BaseStream.Seek((long)(APMB.sector_size*i), SeekOrigin.Begin); // Seek to partition descriptor
stream.Seek((long)(0x200*i), SeekOrigin.Begin); // Seek to partition descriptor //eabr.BaseStream.Seek((long)(0x200*i), SeekOrigin.Begin); // Seek to partition descriptor
stream.Read(sixteen_bits, 0, 2); APMEntry.signature = eabr.ReadUInt16();
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); if(APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature
APMEntry.signature = BitConverter.ToUInt16(sixteen_bits, 0);
if(APMEntry.signature == 0x504D || APMEntry.signature == 0x5453) // It should have partition entry signature
{ {
Partition _partition = new Partition(); Partition _partition = new Partition();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
stream.Seek(2, SeekOrigin.Current); // Skip reserved1 eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip reserved1
stream.Seek(4, SeekOrigin.Current); // Skip entries eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip entries
stream.Read(thirtytwo_bits, 0, 4); APMEntry.start = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); APMEntry.sectors = eabr.ReadUInt32();
APMEntry.start = BitConverter.ToUInt32(thirtytwo_bits, 0); cString = eabr.ReadBytes(32);
stream.Read(thirtytwo_bits, 0, 4); APMEntry.name = StringHandlers.CToString(cString);
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); cString = eabr.ReadBytes(32);
APMEntry.sectors = BitConverter.ToUInt32(thirtytwo_bits, 0); APMEntry.type = StringHandlers.CToString(cString);
stream.Read(thirtytwo_bytes, 0, 32); APMEntry.first_data_block = eabr.ReadUInt32();
APMEntry.name = StringHandlers.CToString(thirtytwo_bytes); APMEntry.data_sectors = eabr.ReadUInt32();
stream.Read(thirtytwo_bytes, 0, 32); APMEntry.status = eabr.ReadUInt32();
APMEntry.type = StringHandlers.CToString(thirtytwo_bytes); APMEntry.first_boot_block = eabr.ReadUInt32();
stream.Read(thirtytwo_bits, 0, 4); APMEntry.boot_size = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); APMEntry.load_address = eabr.ReadUInt32();
APMEntry.first_data_block = BitConverter.ToUInt32(thirtytwo_bits, 0); eabr.BaseStream.Seek(4, SeekOrigin.Current);
stream.Read(thirtytwo_bits, 0, 4); APMEntry.entry_point = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); eabr.BaseStream.Seek(4, SeekOrigin.Current);
APMEntry.data_sectors = BitConverter.ToUInt32(thirtytwo_bits, 0); APMEntry.checksum = eabr.ReadUInt32();
stream.Read(thirtytwo_bits, 0, 4); cString = eabr.ReadBytes(16);
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); APMEntry.processor = StringHandlers.CToString(cString);
APMEntry.status = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Read(thirtytwo_bits, 0, 4);
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
APMEntry.first_boot_block = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Read(thirtytwo_bits, 0, 4);
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
APMEntry.boot_size = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Read(thirtytwo_bits, 0, 4);
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
APMEntry.load_address = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Seek(4, SeekOrigin.Current);
stream.Read(thirtytwo_bits, 0, 4);
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
APMEntry.entry_point = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Seek(4, SeekOrigin.Current);
stream.Read(thirtytwo_bits, 0, 4);
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
APMEntry.checksum = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Read(sixteen_bytes, 0, 16);
APMEntry.processor = StringHandlers.CToString(sixteen_bytes);
_partition.PartitionSequence = i; _partition.PartitionSequence = i;
_partition.PartitionType = APMEntry.type; _partition.PartitionType = APMEntry.type;
_partition.PartitionName = APMEntry.name; _partition.PartitionName = APMEntry.name;
_partition.PartitionStart = APMEntry.start * 0x200; // This seems to be hardcoded // _partition.PartitionStart = APMEntry.start * 0x200; // This seems to be hardcoded
// _partition.PartitionStart = APMEntry.start * APMB.sector_size; _partition.PartitionStart = APMEntry.start * APMB.sector_size;
_partition.PartitionLength = APMEntry.sectors * 0x200; // This seems to be hardcoded // _partition.PartitionLength = APMEntry.sectors * 0x200; // This seems to be hardcoded
// _partition.PartitionLength = APMEntry.sectors * APMB.sector_size; _partition.PartitionLength = APMEntry.sectors * APMB.sector_size;
sb.AppendLine("Partition flags:"); sb.AppendLine("Partition flags:");
if((APMEntry.status & 0x01) == 0x01) if((APMEntry.status & 0x01) == 0x01)

View File

@@ -8,6 +8,10 @@ namespace FileSystemIDandChk.PartPlugins
{ {
class NeXTDisklabel : PartPlugin class NeXTDisklabel : PartPlugin
{ {
public const UInt32 NEXT_MAGIC1 = 0x4E655854; // "NeXT"
public const UInt32 NEXT_MAGIC2 = 0x646C5632; // "dlV2"
public const UInt32 NEXT_MAGIC3 = 0x646C5633; // "dlV3"
public NeXTDisklabel (PluginBase Core) public NeXTDisklabel (PluginBase Core)
{ {
base.Name = "NeXT Disklabel"; base.Name = "NeXT Disklabel";
@@ -16,10 +20,7 @@ namespace FileSystemIDandChk.PartPlugins
public override bool GetInformation (FileStream stream, out List<Partition> partitions) public override bool GetInformation (FileStream stream, out List<Partition> partitions)
{ {
byte[] sixteen_bits = new byte[2]; byte[] cString;
byte[] thirtytwo_bits = new byte[4];
byte[] eight_bytes = new byte[8];
byte[] sixteen_bytes = new byte[16];
bool magic_found = false; bool magic_found = false;
UInt32 magic; UInt32 magic;
@@ -27,31 +28,27 @@ namespace FileSystemIDandChk.PartPlugins
UInt16 front_porch; UInt16 front_porch;
partitions = new List<Partition>(); partitions = new List<Partition>();
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian
stream.Seek(0, SeekOrigin.Begin); // Starts on sector 0 on NeXT machines, CDs and floppies eabr.BaseStream.Seek(0, SeekOrigin.Begin); // Starts on sector 0 on NeXT machines, CDs and floppies
stream.Read(thirtytwo_bits, 0, 4); magic = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
magic = BitConverter.ToUInt32(thirtytwo_bits, 0);
if(magic == 0x4E655854 || magic == 0x646C5632 || magic == 0x646C5633) if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
magic_found = true; magic_found = true;
else else
{ {
stream.Seek(0x1E00, SeekOrigin.Begin); // Starts on sector 15 on MBR machines eabr.BaseStream.Seek(0x1E00, SeekOrigin.Begin); // Starts on sector 15 on MBR machines
stream.Read(thirtytwo_bits, 0, 4); magic = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
magic = BitConverter.ToUInt32(thirtytwo_bits, 0);
if(magic == 0x4E655854 || magic == 0x646C5632 || magic == 0x646C5633) if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
magic_found = true; magic_found = true;
else else
{ {
stream.Seek(0x2000, SeekOrigin.Begin); // Starts on sector 16 (4 on CD) on RISC disks eabr.BaseStream.Seek(0x2000, SeekOrigin.Begin); // Starts on sector 16 (4 on CD) on RISC disks
stream.Read(thirtytwo_bits, 0, 4); magic = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
magic = BitConverter.ToUInt32(thirtytwo_bits, 0);
if(magic == 0x4E655854 || magic == 0x646C5632 || magic == 0x646C5633) if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3)
magic_found = true; magic_found = true;
else else
return false; return false;
@@ -60,49 +57,33 @@ namespace FileSystemIDandChk.PartPlugins
if(magic_found) if(magic_found)
{ {
stream.Seek(88, SeekOrigin.Current); // Seek to sector size eabr.BaseStream.Seek(88, SeekOrigin.Current); // Seek to sector size
stream.Read(thirtytwo_bits, 0, 4); sector_size = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); eabr.BaseStream.Seek(16, SeekOrigin.Current); // Seek to front porch
sector_size = BitConverter.ToUInt32(thirtytwo_bits, 0); front_porch = eabr.ReadUInt16();
stream.Seek(16, SeekOrigin.Current); // Seek to front porch
stream.Read(sixteen_bits, 0, 2);
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits);
front_porch = BitConverter.ToUInt16(sixteen_bits, 0);
stream.Seek(76, SeekOrigin.Current); // Seek to first partition entry eabr.BaseStream.Seek(76, SeekOrigin.Current); // Seek to first partition entry
NeXTEntry entry = new NeXTEntry();
for(int i = 0; i < 8; i ++) for(int i = 0; i < 8; i ++)
{ {
stream.Read(thirtytwo_bits, 0, 4); NeXTEntry entry = new NeXTEntry();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
entry.start = BitConverter.ToUInt32(thirtytwo_bits, 0); entry.start = eabr.ReadUInt32();
stream.Read(thirtytwo_bits, 0, 4); entry.sectors = eabr.ReadUInt32();
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); entry.block_size = eabr.ReadUInt16();
entry.sectors = BitConverter.ToUInt32(thirtytwo_bits, 0); entry.frag_size = eabr.ReadUInt16();
stream.Read(sixteen_bits, 0, 2); entry.optimization = eabr.ReadByte();
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); entry.cpg = eabr.ReadUInt16();
entry.block_size = BitConverter.ToUInt16(sixteen_bits, 0); entry.bpi = eabr.ReadUInt16();
stream.Read(sixteen_bits, 0, 2); entry.freemin = eabr.ReadByte();
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); entry.unknown = eabr.ReadByte();
entry.frag_size = BitConverter.ToUInt16(sixteen_bits, 0); entry.newfs = eabr.ReadByte();
entry.optimization = (byte)stream.ReadByte(); cString = eabr.ReadBytes(16);
stream.Read(sixteen_bits, 0, 2); entry.mount_point = StringHandlers.CToString(cString);
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); entry.automount = eabr.ReadByte();
entry.cpg = BitConverter.ToUInt16(sixteen_bits, 0); cString = eabr.ReadBytes(8);
stream.Read(sixteen_bits, 0, 2); entry.type = StringHandlers.CToString(cString);
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); entry.unknown2 = eabr.ReadByte();
entry.bpi = BitConverter.ToUInt16(sixteen_bits, 0);
entry.freemin = (byte)stream.ReadByte();
entry.unknown = (byte)stream.ReadByte();
entry.newfs = (byte)stream.ReadByte();
stream.Read(sixteen_bytes, 0, 16);
entry.mount_point = StringHandlers.CToString(sixteen_bytes);
entry.automount = (byte)stream.ReadByte();
stream.Read(eight_bytes, 0, 8);
entry.type = StringHandlers.CToString(eight_bytes);
entry.unknown2 = (byte)stream.ReadByte();
if(entry.sectors > 0 && entry.sectors < 0xFFFFFFFF && entry.start < 0xFFFFFFFF) if(entry.sectors > 0 && entry.sectors < 0xFFFFFFFF && entry.start < 0xFFFFFFFF)
{ {

View File

@@ -122,7 +122,7 @@ namespace FileSystemIDandChk.Plugins
besb.indices_start = eabr.ReadUInt16(); besb.indices_start = eabr.ReadUInt16();
besb.indices_len = eabr.ReadUInt16(); besb.indices_len = eabr.ReadUInt16();
if(littleendian) // Big-endian filesystem if(!littleendian) // Big-endian filesystem
sb.AppendLine("Big-endian BeFS"); sb.AppendLine("Big-endian BeFS");
else else
sb.AppendLine("Little-endian BeFS"); sb.AppendLine("Little-endian BeFS");

View File

@@ -18,19 +18,24 @@ namespace FileSystemIDandChk.Plugins
public override bool Identify(FileStream stream, long offset) public override bool Identify(FileStream stream, long offset)
{ {
byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry 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 " byte[] fat32_signature = new byte[8]; // "FAT32 "
byte[] first_fat_entry_b = new byte[4]; // No matter FAT size we read 2 bytes for checking UInt32 first_fat_entry; // No matter FAT size we read 4 bytes for checking
ulong first_fat_entry;
BinaryReader br = new BinaryReader(stream);
stream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
media_descriptor = (byte)stream.ReadByte(); br.BaseStream.Seek(0x10 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
stream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52 fats_no = br.ReadByte();
stream.Read(fat32_signature, 0, 8); br.BaseStream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
stream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32 media_descriptor = br.ReadByte();
stream.Read(first_fat_entry_b, 0, 4); br.BaseStream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52
fat32_signature = br.ReadBytes(8);
first_fat_entry = BitConverter.ToUInt32(first_fat_entry_b, 0); // Easier to manage br.BaseStream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32
first_fat_entry = br.ReadUInt32(); // 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 false;
// Let's start the fun // Let's start the fun
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
return true; // Seems easy, check reading return true; // Seems easy, check reading
@@ -54,24 +59,33 @@ namespace FileSystemIDandChk.Plugins
information = ""; information = "";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
BinaryReader br = new BinaryReader(stream);
byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry
byte[] fat32_signature = new byte[8]; // "FAT32 " byte[] dosString; // Space-padded
byte[] first_fat_entry_b = new byte[4]; // No matter FAT size we read 2 bytes for checking bool isFAT32 = false;
ulong first_fat_entry; UInt32 first_fat_entry;
byte media_descriptor, fats_no;
stream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15 string fat32_signature;
br.BaseStream.Seek(0x10 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
fats_no = br.ReadByte();
br.BaseStream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
media_descriptor =(byte) stream.ReadByte(); media_descriptor =(byte) stream.ReadByte();
stream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52 br.BaseStream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52
stream.Read(fat32_signature, 0, 8); dosString = br.ReadBytes(8);
stream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32 fat32_signature = Encoding.ASCII.GetString(dosString);
stream.Read(first_fat_entry_b, 0, 4); br.BaseStream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32
first_fat_entry = br.ReadUInt32(); // Easier to manage
first_fat_entry = BitConverter.ToUInt32(first_fat_entry_b, 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 // Let's start the fun
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") if(fat32_signature == "FAT32 ")
{
sb.AppendLine("Microsoft FAT32"); // Seems easy, check reading sb.AppendLine("Microsoft FAT32"); // Seems easy, check reading
isFAT32 = true;
}
else if((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16 else if((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16
{ {
if((first_fat_entry & 0xFF) == media_descriptor) if((first_fat_entry & 0xFF) == media_descriptor)
@@ -89,71 +103,50 @@ namespace FileSystemIDandChk.Plugins
ExtendedParameterBlock EPB = new ExtendedParameterBlock(); ExtendedParameterBlock EPB = new ExtendedParameterBlock();
FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock(); FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock();
byte[] eight_bytes = new byte[8];
byte[] eleven_bytes = new byte[11]; br.BaseStream.Seek(3 + offset, SeekOrigin.Begin);
byte[] sixteen_bits = new byte[2]; dosString = br.ReadBytes(8);
byte[] thirtytwo_bits = new byte[4]; BPB.OEMName = Encoding.ASCII.GetString(dosString);
BPB.bps = br.ReadUInt16();
BPB.spc = br.ReadByte();
BPB.rsectors = br.ReadUInt16();
BPB.fats_no = br.ReadByte();
BPB.root_ent = br.ReadUInt16();
BPB.sectors = br.ReadUInt16();
BPB.media = br.ReadByte();
BPB.spfat = br.ReadUInt16();
BPB.sptrk = br.ReadUInt16();
BPB.heads = br.ReadUInt16();
BPB.hsectors = br.ReadUInt32();
BPB.big_sectors = br.ReadUInt32();
stream.Seek(3 + offset, SeekOrigin.Begin); if(isFAT32)
stream.Read(eight_bytes, 0, 8);
BPB.OEMName = Encoding.ASCII.GetString(eight_bytes);
stream.Read(sixteen_bits, 0, 2);
BPB.bps = BitConverter.ToUInt16(sixteen_bits, 0);
BPB.spc = (byte)stream.ReadByte();
stream.Read(sixteen_bits, 0, 2);
BPB.rsectors = BitConverter.ToUInt16(sixteen_bits, 0);
BPB.fats_no = (byte)stream.ReadByte();
stream.Read(sixteen_bits, 0, 2);
BPB.root_ent = BitConverter.ToUInt16(sixteen_bits, 0);
stream.Read(sixteen_bits, 0, 2);
BPB.sectors = BitConverter.ToUInt16(sixteen_bits, 0);
BPB.media = (byte)stream.ReadByte();
stream.Read(sixteen_bits, 0, 2);
BPB.spfat = BitConverter.ToUInt16(sixteen_bits, 0);
stream.Read(sixteen_bits, 0, 2);
BPB.sptrk = BitConverter.ToUInt16(sixteen_bits, 0);
stream.Read(sixteen_bits, 0, 2);
BPB.heads = BitConverter.ToUInt16(sixteen_bits, 0);
stream.Read(thirtytwo_bits, 0, 4);
BPB.hsectors = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Read(thirtytwo_bits, 0, 4);
BPB.big_sectors = BitConverter.ToUInt32(thirtytwo_bits, 0);
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
{ {
stream.Read(thirtytwo_bits, 0, 4); FAT32PB.spfat = br.ReadUInt32();
FAT32PB.spfat = BitConverter.ToUInt32(thirtytwo_bits, 0); FAT32PB.fat_flags = br.ReadUInt16();
stream.Read(sixteen_bits, 0, 2); FAT32PB.version = br.ReadUInt16();
FAT32PB.fat_flags = BitConverter.ToUInt16(sixteen_bits, 0); FAT32PB.root_cluster = br.ReadUInt32();
stream.Read(sixteen_bits, 0, 2); FAT32PB.fsinfo_sector = br.ReadUInt16();
FAT32PB.version = BitConverter.ToUInt16(sixteen_bits, 0); FAT32PB.backup_sector = br.ReadUInt16();
stream.Read(thirtytwo_bits, 0, 4); FAT32PB.drive_no = br.ReadByte();
FAT32PB.root_cluster = BitConverter.ToUInt32(thirtytwo_bits, 0); FAT32PB.nt_flags = br.ReadByte();
stream.Read(sixteen_bits, 0, 2); FAT32PB.signature = br.ReadByte();
FAT32PB.fsinfo_sector = BitConverter.ToUInt16(sixteen_bits, 0); FAT32PB.serial_no = br.ReadUInt32();
stream.Read(sixteen_bits, 0, 2); dosString = br.ReadBytes(11);
FAT32PB.backup_sector = BitConverter.ToUInt16(sixteen_bits, 0); FAT32PB.volume_label = Encoding.ASCII.GetString(dosString);
FAT32PB.drive_no = (byte)stream.ReadByte(); dosString = br.ReadBytes(8);
FAT32PB.nt_flags = (byte)stream.ReadByte(); FAT32PB.fs_type = Encoding.ASCII.GetString(dosString);
FAT32PB.signature = (byte)stream.ReadByte();
stream.Read(thirtytwo_bits, 0, 4);
FAT32PB.serial_no = BitConverter.ToUInt32(thirtytwo_bits, 0);
stream.Read(eleven_bytes, 0, 11);
FAT32PB.volume_label = Encoding.ASCII.GetString(eleven_bytes);
stream.Read(eight_bytes, 0, 8);
FAT32PB.fs_type = Encoding.ASCII.GetString(eight_bytes);
} }
else else
{ {
EPB.drive_no = (byte)stream.ReadByte(); EPB.drive_no = br.ReadByte();
EPB.nt_flags = (byte)stream.ReadByte(); EPB.nt_flags = br.ReadByte();
EPB.signature = (byte)stream.ReadByte(); EPB.signature = br.ReadByte();
stream.Read(thirtytwo_bits, 0, 4); EPB.serial_no = br.ReadUInt32();
EPB.serial_no = BitConverter.ToUInt32(thirtytwo_bits, 0); dosString = br.ReadBytes(11);
stream.Read(eleven_bytes, 0, 11); EPB.volume_label = Encoding.ASCII.GetString(dosString);
EPB.volume_label = Encoding.ASCII.GetString(eleven_bytes); dosString = br.ReadBytes(8);
stream.Read(eight_bytes, 0, 8); EPB.fs_type = Encoding.ASCII.GetString(dosString);
EPB.fs_type = Encoding.ASCII.GetString(eight_bytes);
} }
sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine(); sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine();
@@ -168,7 +161,7 @@ namespace FileSystemIDandChk.Plugins
sb.AppendFormat("{0} sectors on volume.", BPB.sectors).AppendLine(); sb.AppendFormat("{0} sectors on volume.", BPB.sectors).AppendLine();
if((BPB.media & 0xF0) == 0xF0) if((BPB.media & 0xF0) == 0xF0)
sb.AppendFormat("Media format: 0x{0:X2}", BPB.media).AppendLine(); sb.AppendFormat("Media format: 0x{0:X2}", BPB.media).AppendLine();
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") if(fat32_signature == "FAT32 ")
sb.AppendFormat("{0} sectors per FAT.", FAT32PB.spfat).AppendLine(); sb.AppendFormat("{0} sectors per FAT.", FAT32PB.spfat).AppendLine();
else else
sb.AppendFormat("{0} sectors per FAT.", BPB.spfat).AppendLine(); sb.AppendFormat("{0} sectors per FAT.", BPB.spfat).AppendLine();
@@ -176,7 +169,7 @@ namespace FileSystemIDandChk.Plugins
sb.AppendFormat("{0} heads.", BPB.heads).AppendLine(); sb.AppendFormat("{0} heads.", BPB.heads).AppendLine();
sb.AppendFormat("{0} hidden sectors before BPB.", BPB.hsectors).AppendLine(); sb.AppendFormat("{0} hidden sectors before BPB.", BPB.hsectors).AppendLine();
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") if(isFAT32)
{ {
sb.AppendFormat("Cluster of root directory: {0}", FAT32PB.root_cluster).AppendLine(); 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 FSINFO structure: {0}", FAT32PB.fsinfo_sector).AppendLine();
@@ -216,19 +209,19 @@ namespace FileSystemIDandChk.Plugins
public struct BIOSParameterBlock public struct BIOSParameterBlock
{ {
public string OEMName; // OEM Name, 8 bytes, space-padded public string OEMName; // 0x03, OEM Name, 8 bytes, space-padded
public UInt16 bps; // Bytes per sector public UInt16 bps; // 0x0B, Bytes per sector
public byte spc; // Sectors per cluster public byte spc; // 0x0D, Sectors per cluster
public UInt16 rsectors; // Reserved sectors between BPB and FAT public UInt16 rsectors; // 0x0E, Reserved sectors between BPB and FAT
public byte fats_no; // Number of FATs public byte fats_no; // 0x10, Number of FATs
public UInt16 root_ent; // Number of entries on root directory public UInt16 root_ent; // 0x11, Number of entries on root directory
public UInt16 sectors; // Sectors in volume public UInt16 sectors; // 0x13, Sectors in volume
public byte media; // Media descriptor public byte media; // 0x15, Media descriptor
public UInt16 spfat; // Sectors per FAT public UInt16 spfat; // 0x16, Sectors per FAT
public UInt16 sptrk; // Sectors per track public UInt16 sptrk; // 0x18, Sectors per track
public UInt16 heads; // Heads public UInt16 heads; // 0x1A, Heads
public UInt32 hsectors; // Hidden sectors before BPB public UInt32 hsectors; // 0x1C, Hidden sectors before BPB
public UInt32 big_sectors; // Sectors in volume if > 65535 public UInt32 big_sectors; // 0x20, Sectors in volume if > 65535
} }
public struct ExtendedParameterBlock public struct ExtendedParameterBlock
@@ -244,17 +237,17 @@ namespace FileSystemIDandChk.Plugins
public struct FAT32ParameterBlock public struct FAT32ParameterBlock
{ {
public UInt32 spfat; // Sectors per FAT public UInt32 spfat; // Sectors per FAT
public UInt16 fat_flags; // FAT flags public UInt16 fat_flags; // FAT flags
public UInt16 version; // FAT32 version public UInt16 version; // FAT32 version
public UInt32 root_cluster; // Cluster of root directory public UInt32 root_cluster; // Cluster of root directory
public UInt16 fsinfo_sector; // Sector of FSINFO structure public UInt16 fsinfo_sector; // Sector of FSINFO structure
public UInt16 backup_sector; // Secfor of FAT32PB bacup public UInt16 backup_sector; // Secfor of FAT32PB bacup
byte[] reserved; // 12 reserved bytes byte[] reserved; // 12 reserved bytes
public byte drive_no; // Drive number public byte drive_no; // Drive number
public byte nt_flags; // Volume flags public byte nt_flags; // Volume flags
public byte signature; // FAT32PB signature, should be 0x29 public byte signature; // FAT32PB signature, should be 0x29
public UInt32 serial_no; // Volume serial number public UInt32 serial_no; // Volume serial number
public string volume_label; // Volume label, 11 bytes, space-padded public string volume_label; // Volume label, 11 bytes, space-padded
public string fs_type; // Filesystem type, 8 bytes, space-padded, must be "FAT32 " public string fs_type; // Filesystem type, 8 bytes, space-padded, must be "FAT32 "
} }

View File

@@ -12,10 +12,13 @@ namespace FileSystemIDandChk.Plugins
{ {
class ISO9660Plugin : Plugin class ISO9660Plugin : Plugin
{ {
private static bool alreadyLaunched;
public ISO9660Plugin(PluginBase Core) public ISO9660Plugin(PluginBase Core)
{ {
base.Name = "ISO9660 Filesystem"; base.Name = "ISO9660 Filesystem";
base.PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); base.PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
alreadyLaunched = false;
} }
private struct DecodedVolumeDescriptor private struct DecodedVolumeDescriptor
@@ -37,6 +40,11 @@ namespace FileSystemIDandChk.Plugins
public override bool Identify(FileStream fileStream, long offset) public override bool Identify(FileStream fileStream, long offset)
{ {
if(alreadyLaunched)
return false;
else
alreadyLaunched = true;
byte VDType; byte VDType;
// ISO9660 Primary Volume Descriptor starts at 32768, so that's minimal size. // ISO9660 Primary Volume Descriptor starts at 32768, so that's minimal size.