diff --git a/FileSystemIDandChk/ChangeLog b/FileSystemIDandChk/ChangeLog index 896176948..1bd770b92 100644 --- a/FileSystemIDandChk/ChangeLog +++ b/FileSystemIDandChk/ChangeLog @@ -1,3 +1,23 @@ +2012-08-05 Natalia Portillo + + * 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 * Plugins/ODS.cs: diff --git a/FileSystemIDandChk/PartPlugins/AppleMap.cs b/FileSystemIDandChk/PartPlugins/AppleMap.cs index fd7038a3d..42341d629 100644 --- a/FileSystemIDandChk/PartPlugins/AppleMap.cs +++ b/FileSystemIDandChk/PartPlugins/AppleMap.cs @@ -8,6 +8,10 @@ namespace FileSystemIDandChk.PartPlugins { class AppleMap : PartPlugin { + private const UInt16 APM_MAGIC = 0x4552; // "ER" + private const UInt16 APM_ENTRY = 0x504D; // "PM" + private const UInt16 APM_OLDENT = 0x5453; // "TS", old entry magic + public AppleMap (PluginBase Core) { base.Name = "Apple Partition Map"; @@ -16,10 +20,7 @@ namespace FileSystemIDandChk.PartPlugins public override bool GetInformation (FileStream stream, out List partitions) { - byte[] sixteen_bits = new byte[2]; - byte[] thirtytwo_bits = new byte[4]; - byte[] sixteen_bytes = new byte[16]; - byte[] thirtytwo_bytes = new byte[32]; + byte[] cString; ulong apm_entries; @@ -27,42 +28,60 @@ namespace FileSystemIDandChk.PartPlugins AppleMapBootEntry APMB = new AppleMapBootEntry(); AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry(); + EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian + + eabr.BaseStream.Seek(0, SeekOrigin.Begin); + APMB.signature = eabr.ReadUInt16(); - stream.Seek(0, SeekOrigin.Begin); - stream.Read(sixteen_bits, 0, 2); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - APMB.signature = BitConverter.ToUInt16(sixteen_bits, 0); - - if(APMB.signature == 0x4552) + if(APMB.signature == APM_MAGIC) { - stream.Read(sixteen_bits, 0, 2); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - APMB.sector_size = BitConverter.ToUInt16(sixteen_bits, 0); + APMB.sector_size = eabr.ReadUInt16(); } else APMB.sector_size = 512; // Some disks omit the boot entry - -// stream.Seek(APMB.sector_size, SeekOrigin.Begin); // Seek to first entry - stream.Seek(0x200, SeekOrigin.Begin); // Seek to first entry - stream.Read(sixteen_bits, 0, 2); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - APMEntry.signature = BitConverter.ToUInt16(sixteen_bits, 0); - if(APMEntry.signature != 0x504D && APMEntry.signature != 0x5453) // It should have partition entry signature - return false; - - stream.Seek(2, SeekOrigin.Current); // Skip reserved1 - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - APMEntry.entries = BitConverter.ToUInt32(thirtytwo_bits, 0); + + if(APMB.sector_size == 2048) // A CD, search if buggy (aligns in 512 bytes blocks) first + { + eabr.BaseStream.Seek(512, SeekOrigin.Begin); // Seek to first entry + APMEntry.signature = eabr.ReadUInt16(); + if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) // It should have partition entry signature if buggy + { + eabr.BaseStream.Seek(2048, SeekOrigin.Begin); // Seek to first entry considering 2048 bytes blocks. Unbuggy. + APMEntry.signature = eabr.ReadUInt16(); + if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) + return false; + else + APMB.sector_size = 2048; + } + else + APMB.sector_size = 512; + } + else + { + eabr.BaseStream.Seek(APMB.sector_size, SeekOrigin.Begin); // Seek to first entry + APMEntry.signature = eabr.ReadUInt16(); + if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) // It should have partition entry signature if buggy + { + eabr.BaseStream.Seek(512, SeekOrigin.Begin); // Seek to first entry considering 512 bytes blocks. Buggy. + APMEntry.signature = eabr.ReadUInt16(); + if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) + return false; + else + APMB.sector_size = 512; + } + } + + eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip reserved1 + APMEntry.entries = eabr.ReadUInt32(); if(APMEntry.entries <= 1) // It should have more than one entry return false; -// stream.Seek(4, SeekOrigin.Current); // Skip start, we don't need it -// stream.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(4, SeekOrigin.Current); // Skip start, we don't need it +// eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip sectors, we don't need it +// eabr.BaseStream.Seek(32, SeekOrigin.Current); // Skip name, we don't ned it -// stream.Read(thirtytwo_bytes, 0, 32); -// APMEntry.type = StringHandlers.CToString(thirtytwo_bytes); +// cString = eabr.ReadBytes(32); +// APMEntry.type = StringHandlers.CToString(cString); // if(APMEntry.type != "Apple_partition_map") // APM self-describes, if not, this is incorrect // return false; @@ -72,66 +91,44 @@ namespace FileSystemIDandChk.PartPlugins { APMEntry = new AppleMapPartitionEntry(); - //stream.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)(APMB.sector_size*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); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - APMEntry.signature = BitConverter.ToUInt16(sixteen_bits, 0); - if(APMEntry.signature == 0x504D || APMEntry.signature == 0x5453) // It should have partition entry signature + APMEntry.signature = eabr.ReadUInt16(); + if(APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature { Partition _partition = new Partition(); StringBuilder sb = new StringBuilder(); - stream.Seek(2, SeekOrigin.Current); // Skip reserved1 - stream.Seek(4, SeekOrigin.Current); // Skip entries + eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip reserved1 + eabr.BaseStream.Seek(4, SeekOrigin.Current); // Skip entries - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - APMEntry.start = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - APMEntry.sectors = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(thirtytwo_bytes, 0, 32); - APMEntry.name = StringHandlers.CToString(thirtytwo_bytes); - stream.Read(thirtytwo_bytes, 0, 32); - APMEntry.type = StringHandlers.CToString(thirtytwo_bytes); - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - APMEntry.first_data_block = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - APMEntry.data_sectors = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - 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); + APMEntry.start = eabr.ReadUInt32(); + APMEntry.sectors = eabr.ReadUInt32(); + cString = eabr.ReadBytes(32); + APMEntry.name = StringHandlers.CToString(cString); + cString = eabr.ReadBytes(32); + APMEntry.type = StringHandlers.CToString(cString); + APMEntry.first_data_block = eabr.ReadUInt32(); + APMEntry.data_sectors = eabr.ReadUInt32(); + APMEntry.status = eabr.ReadUInt32(); + APMEntry.first_boot_block = eabr.ReadUInt32(); + APMEntry.boot_size = eabr.ReadUInt32(); + APMEntry.load_address = eabr.ReadUInt32(); + eabr.BaseStream.Seek(4, SeekOrigin.Current); + APMEntry.entry_point = eabr.ReadUInt32(); + eabr.BaseStream.Seek(4, SeekOrigin.Current); + APMEntry.checksum = eabr.ReadUInt32(); + cString = eabr.ReadBytes(16); + APMEntry.processor = StringHandlers.CToString(cString); _partition.PartitionSequence = i; _partition.PartitionType = APMEntry.type; _partition.PartitionName = APMEntry.name; - _partition.PartitionStart = APMEntry.start * 0x200; // This seems to be hardcoded -// _partition.PartitionStart = APMEntry.start * APMB.sector_size; - _partition.PartitionLength = APMEntry.sectors * 0x200; // This seems to be hardcoded -// _partition.PartitionLength = APMEntry.sectors * APMB.sector_size; +// _partition.PartitionStart = APMEntry.start * 0x200; // This seems to be hardcoded + _partition.PartitionStart = APMEntry.start * APMB.sector_size; +// _partition.PartitionLength = APMEntry.sectors * 0x200; // This seems to be hardcoded + _partition.PartitionLength = APMEntry.sectors * APMB.sector_size; sb.AppendLine("Partition flags:"); if((APMEntry.status & 0x01) == 0x01) diff --git a/FileSystemIDandChk/PartPlugins/NeXT.cs b/FileSystemIDandChk/PartPlugins/NeXT.cs index af6878cee..2d67b8ca6 100644 --- a/FileSystemIDandChk/PartPlugins/NeXT.cs +++ b/FileSystemIDandChk/PartPlugins/NeXT.cs @@ -8,6 +8,10 @@ namespace FileSystemIDandChk.PartPlugins { class NeXTDisklabel : PartPlugin { + public const UInt32 NEXT_MAGIC1 = 0x4E655854; // "NeXT" + public const UInt32 NEXT_MAGIC2 = 0x646C5632; // "dlV2" + public const UInt32 NEXT_MAGIC3 = 0x646C5633; // "dlV3" + public NeXTDisklabel (PluginBase Core) { base.Name = "NeXT Disklabel"; @@ -16,10 +20,7 @@ namespace FileSystemIDandChk.PartPlugins public override bool GetInformation (FileStream stream, out List partitions) { - byte[] sixteen_bits = new byte[2]; - byte[] thirtytwo_bits = new byte[4]; - byte[] eight_bytes = new byte[8]; - byte[] sixteen_bytes = new byte[16]; + byte[] cString; bool magic_found = false; UInt32 magic; @@ -27,31 +28,27 @@ namespace FileSystemIDandChk.PartPlugins UInt16 front_porch; partitions = new List(); + + EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, false); // BigEndian - stream.Seek(0, SeekOrigin.Begin); // Starts on sector 0 on NeXT machines, CDs and floppies - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - magic = BitConverter.ToUInt32(thirtytwo_bits, 0); + eabr.BaseStream.Seek(0, SeekOrigin.Begin); // Starts on sector 0 on NeXT machines, CDs and floppies + magic = eabr.ReadUInt32(); - if(magic == 0x4E655854 || magic == 0x646C5632 || magic == 0x646C5633) + if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3) magic_found = true; else { - stream.Seek(0x1E00, SeekOrigin.Begin); // Starts on sector 15 on MBR machines - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - magic = BitConverter.ToUInt32(thirtytwo_bits, 0); + eabr.BaseStream.Seek(0x1E00, SeekOrigin.Begin); // Starts on sector 15 on MBR machines + magic = eabr.ReadUInt32(); - if(magic == 0x4E655854 || magic == 0x646C5632 || magic == 0x646C5633) + if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3) magic_found = true; else { - stream.Seek(0x2000, SeekOrigin.Begin); // Starts on sector 16 (4 on CD) on RISC disks - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - magic = BitConverter.ToUInt32(thirtytwo_bits, 0); + eabr.BaseStream.Seek(0x2000, SeekOrigin.Begin); // Starts on sector 16 (4 on CD) on RISC disks + magic = eabr.ReadUInt32(); - if(magic == 0x4E655854 || magic == 0x646C5632 || magic == 0x646C5633) + if(magic == NEXT_MAGIC1 || magic == NEXT_MAGIC2 || magic == NEXT_MAGIC3) magic_found = true; else return false; @@ -60,49 +57,33 @@ namespace FileSystemIDandChk.PartPlugins if(magic_found) { - stream.Seek(88, SeekOrigin.Current); // Seek to sector size - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - sector_size = BitConverter.ToUInt32(thirtytwo_bits, 0); - 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); + eabr.BaseStream.Seek(88, SeekOrigin.Current); // Seek to sector size + sector_size = eabr.ReadUInt32(); + eabr.BaseStream.Seek(16, SeekOrigin.Current); // Seek to front porch + front_porch = eabr.ReadUInt16(); - stream.Seek(76, SeekOrigin.Current); // Seek to first partition entry - - NeXTEntry entry = new NeXTEntry(); + eabr.BaseStream.Seek(76, SeekOrigin.Current); // Seek to first partition entry for(int i = 0; i < 8; i ++) { - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - entry.start = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(thirtytwo_bits, 0, 4); - thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits); - entry.sectors = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(sixteen_bits, 0, 2); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - entry.block_size = BitConverter.ToUInt16(sixteen_bits, 0); - stream.Read(sixteen_bits, 0, 2); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - entry.frag_size = BitConverter.ToUInt16(sixteen_bits, 0); - entry.optimization = (byte)stream.ReadByte(); - stream.Read(sixteen_bits, 0, 2); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - entry.cpg = BitConverter.ToUInt16(sixteen_bits, 0); - stream.Read(sixteen_bits, 0, 2); - sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits); - 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(); + NeXTEntry entry = new NeXTEntry(); + + entry.start = eabr.ReadUInt32(); + entry.sectors = eabr.ReadUInt32(); + entry.block_size = eabr.ReadUInt16(); + entry.frag_size = eabr.ReadUInt16(); + entry.optimization = eabr.ReadByte(); + entry.cpg = eabr.ReadUInt16(); + entry.bpi = eabr.ReadUInt16(); + entry.freemin = eabr.ReadByte(); + entry.unknown = eabr.ReadByte(); + entry.newfs = eabr.ReadByte(); + cString = eabr.ReadBytes(16); + entry.mount_point = StringHandlers.CToString(cString); + entry.automount = eabr.ReadByte(); + cString = eabr.ReadBytes(8); + entry.type = StringHandlers.CToString(cString); + entry.unknown2 = eabr.ReadByte(); if(entry.sectors > 0 && entry.sectors < 0xFFFFFFFF && entry.start < 0xFFFFFFFF) { diff --git a/FileSystemIDandChk/Plugins/BFS.cs b/FileSystemIDandChk/Plugins/BFS.cs index 362f7bc9c..41f1ec28d 100644 --- a/FileSystemIDandChk/Plugins/BFS.cs +++ b/FileSystemIDandChk/Plugins/BFS.cs @@ -122,7 +122,7 @@ namespace FileSystemIDandChk.Plugins besb.indices_start = eabr.ReadUInt16(); besb.indices_len = eabr.ReadUInt16(); - if(littleendian) // Big-endian filesystem + if(!littleendian) // Big-endian filesystem sb.AppendLine("Big-endian BeFS"); else sb.AppendLine("Little-endian BeFS"); diff --git a/FileSystemIDandChk/Plugins/FAT.cs b/FileSystemIDandChk/Plugins/FAT.cs index ca3bca747..bfcf24047 100644 --- a/FileSystemIDandChk/Plugins/FAT.cs +++ b/FileSystemIDandChk/Plugins/FAT.cs @@ -18,19 +18,24 @@ namespace FileSystemIDandChk.Plugins 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 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[] first_fat_entry_b = new byte[4]; // No matter FAT size we read 2 bytes for checking - ulong first_fat_entry; - - stream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15 - media_descriptor = (byte)stream.ReadByte(); - stream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52 - stream.Read(fat32_signature, 0, 8); - stream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32 - stream.Read(first_fat_entry_b, 0, 4); - - first_fat_entry = BitConverter.ToUInt32(first_fat_entry_b, 0); // Easier to manage - + UInt32 first_fat_entry; // No matter FAT size we read 4 bytes for checking + + BinaryReader br = new BinaryReader(stream); + + 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 = br.ReadByte(); + br.BaseStream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52 + fat32_signature = br.ReadBytes(8); + 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 if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") return true; // Seems easy, check reading @@ -54,24 +59,33 @@ namespace FileSystemIDandChk.Plugins information = ""; StringBuilder sb = new StringBuilder(); - - byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry - 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 - ulong first_fat_entry; - - stream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15 + BinaryReader br = new BinaryReader(stream); + + byte[] dosString; // Space-padded + bool isFAT32 = false; + UInt32 first_fat_entry; + byte media_descriptor, fats_no; + 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(); - stream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52 - stream.Read(fat32_signature, 0, 8); - stream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32 - stream.Read(first_fat_entry_b, 0, 4); - - first_fat_entry = BitConverter.ToUInt32(first_fat_entry_b, 0); // Easier to manage - + br.BaseStream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52 + dosString = br.ReadBytes(8); + fat32_signature = Encoding.ASCII.GetString(dosString); + br.BaseStream.Seek(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; + // Let's start the fun - if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ") + 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) @@ -89,71 +103,50 @@ namespace FileSystemIDandChk.Plugins ExtendedParameterBlock EPB = new ExtendedParameterBlock(); FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock(); - byte[] eight_bytes = new byte[8]; - byte[] eleven_bytes = new byte[11]; - byte[] sixteen_bits = new byte[2]; - byte[] thirtytwo_bits = new byte[4]; + + br.BaseStream.Seek(3 + offset, SeekOrigin.Begin); + dosString = br.ReadBytes(8); + BPB.OEMName = Encoding.ASCII.GetString(dosString); + BPB.bps = br.ReadUInt16(); + BPB.spc = br.ReadByte(); + BPB.rsectors = br.ReadUInt16(); + BPB.fats_no = br.ReadByte(); + BPB.root_ent = br.ReadUInt16(); + BPB.sectors = br.ReadUInt16(); + BPB.media = br.ReadByte(); + BPB.spfat = br.ReadUInt16(); + BPB.sptrk = br.ReadUInt16(); + BPB.heads = br.ReadUInt16(); + BPB.hsectors = br.ReadUInt32(); + BPB.big_sectors = br.ReadUInt32(); - stream.Seek(3 + offset, SeekOrigin.Begin); - 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 ") + if(isFAT32) { - stream.Read(thirtytwo_bits, 0, 4); - FAT32PB.spfat = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(sixteen_bits, 0, 2); - FAT32PB.fat_flags = BitConverter.ToUInt16(sixteen_bits, 0); - stream.Read(sixteen_bits, 0, 2); - FAT32PB.version = BitConverter.ToUInt16(sixteen_bits, 0); - stream.Read(thirtytwo_bits, 0, 4); - FAT32PB.root_cluster = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(sixteen_bits, 0, 2); - FAT32PB.fsinfo_sector = BitConverter.ToUInt16(sixteen_bits, 0); - stream.Read(sixteen_bits, 0, 2); - FAT32PB.backup_sector = BitConverter.ToUInt16(sixteen_bits, 0); - FAT32PB.drive_no = (byte)stream.ReadByte(); - FAT32PB.nt_flags = (byte)stream.ReadByte(); - 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); + FAT32PB.spfat = br.ReadUInt32(); + FAT32PB.fat_flags = br.ReadUInt16(); + FAT32PB.version = br.ReadUInt16(); + FAT32PB.root_cluster = br.ReadUInt32(); + FAT32PB.fsinfo_sector = br.ReadUInt16(); + FAT32PB.backup_sector = br.ReadUInt16(); + FAT32PB.drive_no = br.ReadByte(); + FAT32PB.nt_flags = br.ReadByte(); + FAT32PB.signature = br.ReadByte(); + FAT32PB.serial_no = br.ReadUInt32(); + dosString = br.ReadBytes(11); + FAT32PB.volume_label = Encoding.ASCII.GetString(dosString); + dosString = br.ReadBytes(8); + FAT32PB.fs_type = Encoding.ASCII.GetString(dosString); } else { - EPB.drive_no = (byte)stream.ReadByte(); - EPB.nt_flags = (byte)stream.ReadByte(); - EPB.signature = (byte)stream.ReadByte(); - stream.Read(thirtytwo_bits, 0, 4); - EPB.serial_no = BitConverter.ToUInt32(thirtytwo_bits, 0); - stream.Read(eleven_bytes, 0, 11); - EPB.volume_label = Encoding.ASCII.GetString(eleven_bytes); - stream.Read(eight_bytes, 0, 8); - EPB.fs_type = Encoding.ASCII.GetString(eight_bytes); + EPB.drive_no = br.ReadByte(); + EPB.nt_flags = br.ReadByte(); + EPB.signature = br.ReadByte(); + EPB.serial_no = br.ReadUInt32(); + dosString = br.ReadBytes(11); + EPB.volume_label = Encoding.ASCII.GetString(dosString); + dosString = br.ReadBytes(8); + EPB.fs_type = Encoding.ASCII.GetString(dosString); } sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine(); @@ -168,7 +161,7 @@ namespace FileSystemIDandChk.Plugins sb.AppendFormat("{0} sectors on volume.", BPB.sectors).AppendLine(); if((BPB.media & 0xF0) == 0xF0) 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(); else 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} 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("Sector of FSINFO structure: {0}", FAT32PB.fsinfo_sector).AppendLine(); @@ -216,19 +209,19 @@ namespace FileSystemIDandChk.Plugins public struct BIOSParameterBlock { - public string OEMName; // OEM Name, 8 bytes, space-padded - public UInt16 bps; // Bytes per sector - public byte spc; // Sectors per cluster - public UInt16 rsectors; // Reserved sectors between BPB and FAT - public byte fats_no; // Number of FATs - public UInt16 root_ent; // Number of entries on root directory - public UInt16 sectors; // Sectors in volume - public byte media; // Media descriptor - public UInt16 spfat; // Sectors per FAT - public UInt16 sptrk; // Sectors per track - public UInt16 heads; // Heads - public UInt32 hsectors; // Hidden sectors before BPB - public UInt32 big_sectors; // Sectors in volume if > 65535 + public string OEMName; // 0x03, OEM Name, 8 bytes, space-padded + public UInt16 bps; // 0x0B, Bytes per sector + public byte spc; // 0x0D, Sectors per cluster + public UInt16 rsectors; // 0x0E, Reserved sectors between BPB and FAT + public byte fats_no; // 0x10, Number of FATs + public UInt16 root_ent; // 0x11, Number of entries on root directory + public UInt16 sectors; // 0x13, Sectors in volume + public byte media; // 0x15, Media descriptor + public UInt16 spfat; // 0x16, Sectors per FAT + public UInt16 sptrk; // 0x18, Sectors per track + public UInt16 heads; // 0x1A, Heads + public UInt32 hsectors; // 0x1C, Hidden sectors before BPB + public UInt32 big_sectors; // 0x20, Sectors in volume if > 65535 } public struct ExtendedParameterBlock @@ -244,17 +237,17 @@ namespace FileSystemIDandChk.Plugins public struct FAT32ParameterBlock { - public UInt32 spfat; // Sectors per FAT + public UInt32 spfat; // Sectors per FAT public UInt16 fat_flags; // FAT flags 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 backup_sector; // Secfor of FAT32PB bacup byte[] reserved; // 12 reserved bytes public byte drive_no; // Drive number public byte nt_flags; // Volume flags 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 fs_type; // Filesystem type, 8 bytes, space-padded, must be "FAT32 " } diff --git a/FileSystemIDandChk/Plugins/ISO9660.cs b/FileSystemIDandChk/Plugins/ISO9660.cs index b9480a34b..79a19b2de 100644 --- a/FileSystemIDandChk/Plugins/ISO9660.cs +++ b/FileSystemIDandChk/Plugins/ISO9660.cs @@ -12,10 +12,13 @@ namespace FileSystemIDandChk.Plugins { class ISO9660Plugin : Plugin { + private static bool alreadyLaunched; + public ISO9660Plugin(PluginBase Core) { base.Name = "ISO9660 Filesystem"; base.PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); + alreadyLaunched = false; } private struct DecodedVolumeDescriptor @@ -37,6 +40,11 @@ namespace FileSystemIDandChk.Plugins public override bool Identify(FileStream fileStream, long offset) { + if(alreadyLaunched) + return false; + else + alreadyLaunched = true; + byte VDType; // ISO9660 Primary Volume Descriptor starts at 32768, so that's minimal size.