mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
* SysV.cs:
* FileSystemIDandChk.csproj: Added support for System V filesystem * 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) git-svn-id: svn://claunia.com/FileSystemIDandChk@22 17725271-3d32-4980-a8cb-9ff532f270ba
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
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:
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
<Compile Include="Plugins\MinixFS.cs" />
|
||||
<Compile Include="Plugins\SolarFS.cs" />
|
||||
<Compile Include="Plugins\UNIXBFS.cs" />
|
||||
<Compile Include="Plugins\SysV.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
||||
@@ -135,33 +135,83 @@ namespace FileSystemIDandChk.PartPlugins
|
||||
valid=true;
|
||||
break;
|
||||
}
|
||||
case 0x63: // UnixWare disklabel
|
||||
case 0x63: // UNIX disklabel
|
||||
{
|
||||
UInt32 magic;
|
||||
br.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
br.BaseStream.Seek(29*0x200 + 4, SeekOrigin.Current); // Starts on sector 29 of partition
|
||||
magic = br.ReadUInt32();
|
||||
|
||||
if(magic == 0xCA5E600D)
|
||||
if(magic == UNIXDiskLabel_MAGIC)
|
||||
{
|
||||
br.BaseStream.Seek(164, SeekOrigin.Current);
|
||||
Int16 no_parts = br.ReadInt16();
|
||||
br.BaseStream.Seek(42, SeekOrigin.Current);
|
||||
|
||||
for(int j = 0; j < no_parts; j++)
|
||||
UNIXDiskLabel dl = new UNIXDiskLabel();
|
||||
bool isNewDL = false;
|
||||
|
||||
dl.version = br.ReadUInt32();
|
||||
dl.serial = StringHandlers.CToString(br.ReadBytes(12));
|
||||
dl.cyls = br.ReadUInt32();
|
||||
dl.trks = br.ReadUInt32();
|
||||
dl.secs = br.ReadUInt32();
|
||||
dl.bps = br.ReadUInt32();
|
||||
dl.start = br.ReadUInt32();
|
||||
dl.unknown1 = br.ReadBytes(48);
|
||||
dl.alt_tbl = br.ReadUInt32();
|
||||
dl.alt_len = br.ReadUInt32();
|
||||
dl.phys_cyl = br.ReadUInt32();
|
||||
|
||||
if(dl.phys_cyl != UNIXVTOC_MAGIC) // Old version VTOC starts here
|
||||
{
|
||||
Int16 unx_type = br.ReadInt16();
|
||||
br.BaseStream.Seek(2, SeekOrigin.Current);
|
||||
Partition part = new Partition();
|
||||
part.PartitionStart = br.ReadInt32() * 512;
|
||||
part.PartitionLength = br.ReadInt32() * 512;
|
||||
part.PartitionSequence = counter;
|
||||
part.PartitionType = String.Format("Unixware: {0}", unx_type);
|
||||
part.PartitionDescription = "UnixWare slice.";
|
||||
isNewDL = true;
|
||||
dl.phys_trk = br.ReadUInt32();
|
||||
dl.phys_sec = br.ReadUInt32();
|
||||
dl.phys_bytes = br.ReadUInt32();
|
||||
dl.unknown2 = br.ReadUInt32();
|
||||
dl.unknown3 = br.ReadUInt32();
|
||||
dl.pad = br.ReadBytes(48);
|
||||
}
|
||||
else
|
||||
br.BaseStream.Seek(-4, SeekOrigin.Current); // Return to old VTOC magic
|
||||
|
||||
UNIXVTOC vtoc = new UNIXVTOC();
|
||||
|
||||
vtoc.magic = br.ReadUInt32();
|
||||
|
||||
if(unx_type!=0)
|
||||
if(vtoc.magic == UNIXVTOC_MAGIC)
|
||||
{
|
||||
vtoc.version = br.ReadUInt32();
|
||||
vtoc.name = StringHandlers.CToString(br.ReadBytes(8));
|
||||
vtoc.slices = br.ReadUInt16();
|
||||
vtoc.unknown = br.ReadUInt16();
|
||||
vtoc.reserved = br.ReadBytes(40);
|
||||
|
||||
for(int j = 0; j < vtoc.slices; j++)
|
||||
{
|
||||
partitions.Add(part);
|
||||
counter++;
|
||||
UNIXVTOCEntry vtoc_ent = new UNIXVTOCEntry();
|
||||
|
||||
vtoc_ent.tag = br.ReadUInt16();
|
||||
vtoc_ent.flags = br.ReadUInt16();
|
||||
vtoc_ent.start = br.ReadUInt32();
|
||||
vtoc_ent.length = br.ReadUInt32();
|
||||
|
||||
if((vtoc_ent.flags & 0x200) == 0x200 && vtoc_ent.tag != UNIX_TAG_EMPTY && vtoc_ent.tag != UNIX_TAG_WHOLE)
|
||||
{
|
||||
Partition part = new Partition();
|
||||
part.PartitionStart = vtoc_ent.start * dl.bps;
|
||||
part.PartitionLength = vtoc_ent.length * dl.bps;
|
||||
part.PartitionSequence = counter;
|
||||
part.PartitionType = String.Format("UNIX: {0}", decodeUNIXTAG(vtoc_ent.tag, isNewDL));
|
||||
|
||||
string info = "";
|
||||
|
||||
if((vtoc_ent.flags & 0x01) == 0x01)
|
||||
info += " (do not mount)";
|
||||
if((vtoc_ent.flags & 0x10) == 0x10)
|
||||
info += " (do not mount)";
|
||||
|
||||
part.PartitionDescription = "UNIX slice" + info + ".";
|
||||
|
||||
partitions.Add(part);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -386,38 +436,88 @@ namespace FileSystemIDandChk.PartPlugins
|
||||
ext_valid=true;
|
||||
break;
|
||||
}
|
||||
case 0x63: // UnixWare disklabel
|
||||
case 0x63: // UNIX disklabel
|
||||
{
|
||||
UInt32 magic;
|
||||
br.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
br.BaseStream.Seek(29*0x200 + 4, SeekOrigin.Current); // Starts on sector 29 of partition
|
||||
magic = br.ReadUInt32();
|
||||
|
||||
if(magic == 0xCA5E600D)
|
||||
{
|
||||
br.BaseStream.Seek(164, SeekOrigin.Current);
|
||||
Int16 no_parts = br.ReadInt16();
|
||||
br.BaseStream.Seek(42, SeekOrigin.Current);
|
||||
|
||||
for(int j = 0; j < no_parts; j++)
|
||||
{
|
||||
Int16 unx_type = br.ReadInt16();
|
||||
br.BaseStream.Seek(2, SeekOrigin.Current);
|
||||
Partition part = new Partition();
|
||||
part.PartitionStart = br.ReadInt32() * 512;
|
||||
part.PartitionLength = br.ReadInt32() * 512;
|
||||
part.PartitionSequence = counter;
|
||||
part.PartitionType = String.Format("Unixware: {0}", unx_type);
|
||||
part.PartitionDescription = "UnixWare slice.";
|
||||
if(magic == UNIXDiskLabel_MAGIC)
|
||||
{
|
||||
UNIXDiskLabel dl = new UNIXDiskLabel();
|
||||
bool isNewDL = false;
|
||||
|
||||
if(unx_type!=0)
|
||||
dl.version = br.ReadUInt32();
|
||||
dl.serial = StringHandlers.CToString(br.ReadBytes(12));
|
||||
dl.cyls = br.ReadUInt32();
|
||||
dl.trks = br.ReadUInt32();
|
||||
dl.secs = br.ReadUInt32();
|
||||
dl.bps = br.ReadUInt32();
|
||||
dl.start = br.ReadUInt32();
|
||||
dl.unknown1 = br.ReadBytes(48);
|
||||
dl.alt_tbl = br.ReadUInt32();
|
||||
dl.alt_len = br.ReadUInt32();
|
||||
dl.phys_cyl = br.ReadUInt32();
|
||||
|
||||
if(dl.phys_cyl != UNIXVTOC_MAGIC) // Old version VTOC starts here
|
||||
{
|
||||
isNewDL = true;
|
||||
dl.phys_trk = br.ReadUInt32();
|
||||
dl.phys_sec = br.ReadUInt32();
|
||||
dl.phys_bytes = br.ReadUInt32();
|
||||
dl.unknown2 = br.ReadUInt32();
|
||||
dl.unknown3 = br.ReadUInt32();
|
||||
dl.pad = br.ReadBytes(48);
|
||||
}
|
||||
else
|
||||
br.BaseStream.Seek(-4, SeekOrigin.Current); // Return to old VTOC magic
|
||||
|
||||
UNIXVTOC vtoc = new UNIXVTOC();
|
||||
|
||||
vtoc.magic = br.ReadUInt32();
|
||||
|
||||
if(vtoc.magic == UNIXVTOC_MAGIC)
|
||||
{
|
||||
vtoc.version = br.ReadUInt32();
|
||||
vtoc.name = StringHandlers.CToString(br.ReadBytes(8));
|
||||
vtoc.slices = br.ReadUInt16();
|
||||
vtoc.unknown = br.ReadUInt16();
|
||||
vtoc.reserved = br.ReadBytes(40);
|
||||
|
||||
for(int j = 0; j < vtoc.slices; j++)
|
||||
{
|
||||
partitions.Add(part);
|
||||
counter++;
|
||||
UNIXVTOCEntry vtoc_ent = new UNIXVTOCEntry();
|
||||
|
||||
vtoc_ent.tag = br.ReadUInt16();
|
||||
vtoc_ent.flags = br.ReadUInt16();
|
||||
vtoc_ent.start = br.ReadUInt32();
|
||||
vtoc_ent.length = br.ReadUInt32();
|
||||
|
||||
if((vtoc_ent.flags & 0x200) == 0x200 && vtoc_ent.tag != UNIX_TAG_EMPTY && vtoc_ent.tag != UNIX_TAG_WHOLE)
|
||||
{
|
||||
Partition part = new Partition();
|
||||
part.PartitionStart = vtoc_ent.start * dl.bps;
|
||||
part.PartitionLength = vtoc_ent.length * dl.bps;
|
||||
part.PartitionSequence = counter;
|
||||
part.PartitionType = String.Format("UNIX: {0}", decodeUNIXTAG(vtoc_ent.tag, isNewDL));
|
||||
|
||||
string info = "";
|
||||
|
||||
if((vtoc_ent.flags & 0x01) == 0x01)
|
||||
info += " (do not mount)";
|
||||
if((vtoc_ent.flags & 0x10) == 0x10)
|
||||
info += " (do not mount)";
|
||||
|
||||
part.PartitionDescription = "UNIX slice" + info + ".";
|
||||
|
||||
partitions.Add(part);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
valid = true;
|
||||
ext_valid = true;
|
||||
break;
|
||||
}
|
||||
case 0x82:
|
||||
@@ -912,5 +1012,132 @@ namespace FileSystemIDandChk.PartPlugins
|
||||
public UInt32 lba_start; // Starting absolute sector
|
||||
public UInt32 lba_sectors; // Total sectors
|
||||
}
|
||||
|
||||
private const UInt32 UNIXDiskLabel_MAGIC = 0xCA5E600D;
|
||||
private const UInt32 UNIXVTOC_MAGIC = 0x600DDEEE; // Same as Solaris VTOC
|
||||
|
||||
private struct UNIXDiskLabel
|
||||
{
|
||||
public UInt32 type; // Drive type, seems always 0
|
||||
public UInt32 magic; // UNIXDiskLabel_MAGIC
|
||||
public UInt32 version; // Only seen 1
|
||||
public string serial; // 12 bytes, serial number of the device
|
||||
public UInt32 cyls; // data cylinders per device
|
||||
public UInt32 trks; // data tracks per cylinder
|
||||
public UInt32 secs; // data sectors per track
|
||||
public UInt32 bps; // data bytes per sector
|
||||
public UInt32 start; // first sector of this partition
|
||||
public byte[] unknown1; // 48 bytes
|
||||
public UInt32 alt_tbl; // byte offset of alternate table
|
||||
public UInt32 alt_len; // byte length of alternate table
|
||||
// From onward here, is not on old version
|
||||
public UInt32 phys_cyl; // physical cylinders per device
|
||||
public UInt32 phys_trk; // physical tracks per cylinder
|
||||
public UInt32 phys_sec; // physical sectors per track
|
||||
public UInt32 phys_bytes; // physical bytes per sector
|
||||
public UInt32 unknown2; //
|
||||
public UInt32 unknown3; //
|
||||
public byte[] pad; // 32bytes
|
||||
}
|
||||
|
||||
private struct UNIXVTOC
|
||||
{
|
||||
public UInt32 magic; // UNIXVTOC_MAGIC
|
||||
public UInt32 version; // 1
|
||||
public string name; // 8 bytes
|
||||
public UInt32 slices; // # of slices
|
||||
public UInt32 unknown; //
|
||||
public byte[] reserved; // 40 bytes
|
||||
}
|
||||
|
||||
private struct UNIXVTOCEntry
|
||||
{
|
||||
public UInt16 tag; // TAG
|
||||
public UInt16 flags; // Flags (see below)
|
||||
public UInt32 start; // Start sector
|
||||
public UInt32 length; // Length of slice in sectors
|
||||
}
|
||||
|
||||
private const UInt16 UNIX_TAG_EMPTY = 0x0000; // empty
|
||||
private const UInt16 UNIX_TAG_BOOT = 0x0001; // boot
|
||||
private const UInt16 UNIX_TAG_ROOT = 0x0002; // root
|
||||
private const UInt16 UNIX_TAG_SWAP = 0x0003; // swap
|
||||
private const UInt16 UNIX_TAG_USER = 0x0004; // /usr
|
||||
private const UInt16 UNIX_TAG_WHOLE = 0x0005; // whole disk
|
||||
private const UInt16 UNIX_TAG_STAND = 0x0006; // stand partition ??
|
||||
private const UInt16 UNIX_TAG_ALT_S = 0x0006; // alternate sector space
|
||||
private const UInt16 UNIX_TAG_VAR = 0x0007; // /var
|
||||
private const UInt16 UNIX_TAG_OTHER = 0x0007; // non UNIX
|
||||
private const UInt16 UNIX_TAG_HOME = 0x0008; // /home
|
||||
private const UInt16 UNIX_TAG_ALT_T = 0x0008; // alternate track space
|
||||
private const UInt16 UNIX_TAG_ALT_ST = 0x0009; // alternate sector track
|
||||
private const UInt16 UNIX_TAG_NEW_STAND = 0x0009; // stand partition ??
|
||||
private const UInt16 UNIX_TAG_CACHE = 0x000A; // cache
|
||||
private const UInt16 UNIX_TAG_NEW_VAR = 0x000A; // /var
|
||||
private const UInt16 UNIX_TAG_RESERVED = 0x000B; // reserved
|
||||
private const UInt16 UNIX_TAG_NEW_HOME = 0x000B; // /home
|
||||
private const UInt16 UNIX_TAG_DUMP = 0x000C; // dump partition
|
||||
private const UInt16 UNIX_TAG_NEW_ALT_ST = 0x000D; // alternate sector track
|
||||
private const UInt16 UNIX_TAG_VM_PUBLIC = 0x000E; // volume mgt public partition
|
||||
private const UInt16 UNIX_TAG_VM_PRIVATE = 0x000F; // volume mgt private partition
|
||||
|
||||
private string decodeUNIXTAG(UInt16 type, bool isNew)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case UNIX_TAG_EMPTY:
|
||||
return "Unused";
|
||||
case UNIX_TAG_BOOT:
|
||||
return "Boot";
|
||||
case UNIX_TAG_ROOT:
|
||||
return "/";
|
||||
case UNIX_TAG_SWAP:
|
||||
return "Swap";
|
||||
case UNIX_TAG_USER:
|
||||
return "/usr";
|
||||
case UNIX_TAG_WHOLE:
|
||||
return "Whole disk";
|
||||
case UNIX_TAG_STAND:
|
||||
if(isNew)
|
||||
return "Stand";
|
||||
else
|
||||
return "Alternate sector space";
|
||||
case UNIX_TAG_VAR:
|
||||
if(isNew)
|
||||
return "/var";
|
||||
else
|
||||
return "non UNIX";
|
||||
case UNIX_TAG_HOME:
|
||||
if(isNew)
|
||||
return "/home";
|
||||
else
|
||||
return "Alternate track space";
|
||||
case UNIX_TAG_ALT_ST:
|
||||
if(isNew)
|
||||
return "Alternate sector track";
|
||||
else
|
||||
return "Stand";
|
||||
case UNIX_TAG_CACHE:
|
||||
if(isNew)
|
||||
return "Cache";
|
||||
else
|
||||
return "/var";
|
||||
case UNIX_TAG_RESERVED:
|
||||
if(isNew)
|
||||
return "Reserved";
|
||||
else
|
||||
return "/home";
|
||||
case UNIX_TAG_DUMP:
|
||||
return "dump";
|
||||
case UNIX_TAG_NEW_ALT_ST:
|
||||
return "Alternate sector track";
|
||||
case UNIX_TAG_VM_PUBLIC:
|
||||
return "volume mgt public partition";
|
||||
case UNIX_TAG_VM_PRIVATE:
|
||||
return "volume mgt private partition";
|
||||
default:
|
||||
return String.Format ("Unknown TAG: 0x{0:X4}", type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
624
FileSystemIDandChk/Plugins/SysV.cs
Normal file
624
FileSystemIDandChk/Plugins/SysV.cs
Normal file
@@ -0,0 +1,624 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class SysVfs : Plugin
|
||||
{
|
||||
private const UInt32 XENIX_MAGIC = 0x002B5544;
|
||||
private const UInt32 XENIX_CIGAM = 0x44552B00;
|
||||
private const UInt32 SYSV_MAGIC = 0xFD187E20;
|
||||
private const UInt32 SYSV_CIGAM = 0xFD187E20;
|
||||
// Rest have no magic.
|
||||
// Per a Linux kernel, Coherent fs has following:
|
||||
private const string COH_FNAME = "nonamexxxxx ";
|
||||
private const string COH_FPACK = "nopackxxxxx\n";
|
||||
// SCO AFS
|
||||
private const UInt16 SCO_NFREE = 0xFFFF;
|
||||
// UNIX 7th Edition has nothing to detect it, so check for a valid filesystem is a must :(
|
||||
private const UInt16 V7_NICINOD = 100;
|
||||
private const UInt16 V7_NICFREE = 50;
|
||||
private const UInt32 V7_MAXSIZE = 0x00FFFFFF;
|
||||
|
||||
public SysVfs(PluginBase Core)
|
||||
{
|
||||
base.Name = "UNIX System V filesystem";
|
||||
base.PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
{
|
||||
UInt32 magic;
|
||||
string s_fname, s_fpack;
|
||||
UInt16 s_nfree, s_ninode;
|
||||
UInt32 s_fsize;
|
||||
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
|
||||
/*for(int j = 0; j<=(br.BaseStream.Length/0x200); j++)
|
||||
{
|
||||
br.BaseStream.Seek(offset + j*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
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);
|
||||
}*/
|
||||
|
||||
for(int i = 0; i<=4; i++) // Check on 0x0000, 0x0200, 0x0600, 0x0800 + offset
|
||||
{
|
||||
if((ulong)br.BaseStream.Length <= (ulong)(offset + i*0x200 + 0x400)) // Stream must be bigger than SB location + SB size + offset
|
||||
return false;
|
||||
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x3F8, SeekOrigin.Begin); // XENIX magic location
|
||||
magic = br.ReadUInt32();
|
||||
|
||||
if(magic == XENIX_MAGIC || magic == XENIX_CIGAM)
|
||||
return true;
|
||||
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
magic = br.ReadUInt32();
|
||||
|
||||
if(magic == SYSV_MAGIC || magic == SYSV_CIGAM)
|
||||
return true;
|
||||
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x1E8, SeekOrigin.Begin); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(br.ReadBytes(6));
|
||||
s_fpack = StringHandlers.CToString(br.ReadBytes(6));
|
||||
|
||||
if(s_fname == COH_FNAME || s_fpack == COH_FPACK)
|
||||
return true;
|
||||
|
||||
// Now try to identify 7th edition
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x002, SeekOrigin.Begin);
|
||||
s_fsize = br.ReadUInt32();
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x006, SeekOrigin.Begin);
|
||||
s_nfree = br.ReadUInt16();
|
||||
br.BaseStream.Seek(offset + i*0x200 + 0x0D0, SeekOrigin.Begin);
|
||||
s_ninode = br.ReadUInt16();
|
||||
|
||||
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) <= (br.BaseStream.Length-offset) || (s_fsize * 512) <= (br.BaseStream.Length-offset))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
bool littleendian = true;
|
||||
EndianAwareBinaryReader eabr = new EndianAwareBinaryReader(stream, littleendian); // Start in little endian until we know what are we handling here
|
||||
int start;
|
||||
UInt32 magic;
|
||||
string s_fname, s_fpack;
|
||||
UInt16 s_nfree, s_ninode;
|
||||
UInt32 s_fsize;
|
||||
bool xenix = false;
|
||||
bool sysv = false;
|
||||
bool sysvr2 = false;
|
||||
bool sysvr4 = false;
|
||||
bool sys7th = false;
|
||||
bool coherent = false;
|
||||
|
||||
for(start = 0; start<=4; start++) // Check on 0x0000, 0x0200, 0x0600, 0x0800 + offset
|
||||
{
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x3F8, SeekOrigin.Begin); // XENIX magic location
|
||||
magic = eabr.ReadUInt32();
|
||||
|
||||
if(magic == XENIX_MAGIC)
|
||||
{
|
||||
littleendian = true;
|
||||
xenix = true;
|
||||
break;
|
||||
}
|
||||
else if(magic == XENIX_CIGAM)
|
||||
{
|
||||
littleendian = false;
|
||||
xenix = true;
|
||||
break;
|
||||
}
|
||||
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
magic = eabr.ReadUInt32();
|
||||
|
||||
if(magic == SYSV_MAGIC)
|
||||
{
|
||||
littleendian = true;
|
||||
sysv = true;
|
||||
break;
|
||||
}
|
||||
else if(magic == SYSV_CIGAM)
|
||||
{
|
||||
littleendian = false;
|
||||
sysv = true;
|
||||
break;
|
||||
}
|
||||
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x1E8, SeekOrigin.Begin); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
|
||||
if(s_fname == COH_FNAME || s_fpack == COH_FPACK)
|
||||
{
|
||||
littleendian = true; // Coherent is in PDP endianness, use helper for that
|
||||
coherent = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Now try to identify 7th edition
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x002, SeekOrigin.Begin);
|
||||
s_fsize = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x006, SeekOrigin.Begin);
|
||||
s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x0D0, SeekOrigin.Begin);
|
||||
s_ninode = eabr.ReadUInt16();
|
||||
|
||||
if(s_fsize > 0 && s_fsize < 0xFFFFFFFF && s_nfree > 0 && s_nfree < 0xFFFF && s_ninode > 0 && s_ninode < 0xFFFF)
|
||||
{
|
||||
bool byteswapped = false;
|
||||
if((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00)
|
||||
{
|
||||
// Byteswap
|
||||
s_fsize = ((s_fsize & 0xFF)<<24) + ((s_fsize & 0xFF00)<<8) + ((s_fsize & 0xFF0000)>>8) + ((s_fsize & 0xFF000000)>>24);
|
||||
s_nfree = (UInt16)(s_nfree>>8);
|
||||
s_ninode = (UInt16)(s_ninode>>8);
|
||||
byteswapped = true;
|
||||
}
|
||||
|
||||
if((s_fsize & 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) <= (eabr.BaseStream.Length-offset) || (s_fsize * 512) <= (eabr.BaseStream.Length-offset))
|
||||
{
|
||||
sys7th = true;
|
||||
littleendian = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!sys7th && !sysv && !coherent && !xenix)
|
||||
return;
|
||||
|
||||
if(xenix)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
XenixSuperBlock xnx_sb = new XenixSuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
xnx_sb.s_isize = eabr.ReadUInt16();
|
||||
xnx_sb.s_fsize = eabr.ReadUInt32();
|
||||
xnx_sb.s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(400, SeekOrigin.Current); // Skip free block list
|
||||
xnx_sb.s_ninode = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
xnx_sb.s_flock = eabr.ReadByte();
|
||||
xnx_sb.s_ilock = eabr.ReadByte();
|
||||
xnx_sb.s_fmod = eabr.ReadByte();
|
||||
xnx_sb.s_ronly = eabr.ReadByte();
|
||||
xnx_sb.s_time = eabr.ReadUInt32();
|
||||
xnx_sb.s_tfree = eabr.ReadUInt32();
|
||||
xnx_sb.s_tinode = eabr.ReadUInt16();
|
||||
xnx_sb.s_cylblks = eabr.ReadUInt16();
|
||||
xnx_sb.s_gapblks = eabr.ReadUInt16();
|
||||
xnx_sb.s_dinfo0 = eabr.ReadUInt16();
|
||||
xnx_sb.s_dinfo1 = eabr.ReadUInt16();
|
||||
xnx_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
xnx_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
xnx_sb.s_clean = eabr.ReadByte();
|
||||
xnx_sb.s_magic = eabr.ReadUInt32();
|
||||
eabr.BaseStream.Seek(371, SeekOrigin.Current); // Skip fill zone
|
||||
xnx_sb.s_type = eabr.ReadUInt32();
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
UInt16 pad0, pad1, pad2, pad3;
|
||||
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x002, SeekOrigin.Begin); // First padding
|
||||
pad0 = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x00A, SeekOrigin.Begin); // Second padding
|
||||
pad1 = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x0D6, SeekOrigin.Begin); // Third padding
|
||||
pad2 = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(offset + start*0x200 + 0x1B6, SeekOrigin.Begin); // Fourth padding
|
||||
pad3 = eabr.ReadUInt16();
|
||||
|
||||
// This detection is not working as expected
|
||||
if(pad0 == 0 && pad1 == 0 && pad2 == 0)
|
||||
sysvr4 = true;
|
||||
else
|
||||
sysvr2 = true;
|
||||
|
||||
SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
sysv_sb.s_isize = eabr.ReadUInt16();
|
||||
if(sysvr4)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
sysv_sb.s_fsize = eabr.ReadUInt32();
|
||||
sysv_sb.s_nfree = eabr.ReadUInt16();
|
||||
if(sysvr4)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free block list
|
||||
sysv_sb.s_ninode = eabr.ReadUInt16();
|
||||
if(sysvr4)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
sysv_sb.s_flock = eabr.ReadByte();
|
||||
sysv_sb.s_ilock = eabr.ReadByte();
|
||||
sysv_sb.s_fmod = eabr.ReadByte();
|
||||
sysv_sb.s_ronly = eabr.ReadByte();
|
||||
sysv_sb.s_time = eabr.ReadUInt32();
|
||||
sysv_sb.s_cylblks = eabr.ReadUInt16();
|
||||
sysv_sb.s_gapblks = eabr.ReadUInt16();
|
||||
sysv_sb.s_dinfo0 = eabr.ReadUInt16();
|
||||
sysv_sb.s_dinfo1 = eabr.ReadUInt16();
|
||||
sysv_sb.s_tfree = eabr.ReadUInt32();
|
||||
sysv_sb.s_tinode = eabr.ReadUInt16();
|
||||
if(sysvr4 && pad3 == 0)
|
||||
eabr.BaseStream.Seek(2, SeekOrigin.Current); // Skip padding
|
||||
sysv_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
sysv_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
if(sysvr4 && pad3 == 0)
|
||||
eabr.BaseStream.Seek(50, SeekOrigin.Current); // Skip fill zone
|
||||
else if(sysvr4)
|
||||
eabr.BaseStream.Seek(50, SeekOrigin.Current); // Skip fill zone
|
||||
else
|
||||
eabr.BaseStream.Seek(56, SeekOrigin.Current); // Skip fill zone
|
||||
sysv_sb.s_state = eabr.ReadUInt32();
|
||||
sysv_sb.s_magic = eabr.ReadUInt32();
|
||||
sysv_sb.s_type = eabr.ReadUInt32();
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, true);
|
||||
CoherentSuperBlock coh_sb = new CoherentSuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
coh_sb.s_isize = eabr.ReadUInt16();
|
||||
coh_sb.s_fsize = Swapping.PDPFromLittleEndian(eabr.ReadUInt32());
|
||||
coh_sb.s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(256, SeekOrigin.Current); // Skip free block list
|
||||
coh_sb.s_ninode = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
coh_sb.s_flock = eabr.ReadByte();
|
||||
coh_sb.s_ilock = eabr.ReadByte();
|
||||
coh_sb.s_fmod = eabr.ReadByte();
|
||||
coh_sb.s_ronly = eabr.ReadByte();
|
||||
coh_sb.s_time = Swapping.PDPFromLittleEndian(eabr.ReadUInt32());
|
||||
coh_sb.s_tfree = Swapping.PDPFromLittleEndian(eabr.ReadUInt32());
|
||||
coh_sb.s_tinode = eabr.ReadUInt16();
|
||||
coh_sb.s_int_m = eabr.ReadUInt16();
|
||||
coh_sb.s_int_n = eabr.ReadUInt16();
|
||||
coh_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
coh_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
|
||||
sb.AppendLine("Coherent UNIX filesystem");
|
||||
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)
|
||||
{
|
||||
eabr = new EndianAwareBinaryReader(stream, littleendian);
|
||||
UNIX7thEditionSuperBlock v7_sb = new UNIX7thEditionSuperBlock();
|
||||
eabr.BaseStream.Seek(offset + start*0x200, SeekOrigin.Begin);
|
||||
v7_sb.s_isize = eabr.ReadUInt16();
|
||||
v7_sb.s_fsize = eabr.ReadUInt32();
|
||||
v7_sb.s_nfree = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free block list
|
||||
v7_sb.s_ninode = eabr.ReadUInt16();
|
||||
eabr.BaseStream.Seek(200, SeekOrigin.Current); // Skip free inode list
|
||||
v7_sb.s_flock = eabr.ReadByte();
|
||||
v7_sb.s_ilock = eabr.ReadByte();
|
||||
v7_sb.s_fmod = eabr.ReadByte();
|
||||
v7_sb.s_ronly = eabr.ReadByte();
|
||||
v7_sb.s_time = eabr.ReadUInt32();
|
||||
v7_sb.s_tfree = eabr.ReadUInt32();
|
||||
v7_sb.s_tinode = eabr.ReadUInt16();
|
||||
v7_sb.s_int_m = eabr.ReadUInt16();
|
||||
v7_sb.s_int_n = eabr.ReadUInt16();
|
||||
v7_sb.s_fname = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
v7_sb.s_fpack = StringHandlers.CToString(eabr.ReadBytes(6));
|
||||
|
||||
sb.AppendLine("UNIX 7th Edition filesystem");
|
||||
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();
|
||||
}
|
||||
|
||||
private struct XenixSuperBlock
|
||||
{
|
||||
public UInt16 s_isize; // 0x000, index of first data zone
|
||||
public UInt32 s_fsize; // 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree; // 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free; // 0x008, 100 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode; // 0x198, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode; // 0x19A, 100 entries, some free inodes
|
||||
public byte s_flock; // 0x262, free block list manipulation lock
|
||||
public byte s_ilock; // 0x263, inode cache manipulation lock
|
||||
public byte s_fmod; // 0x264, superblock modification flag
|
||||
public byte s_ronly; // 0x265, read-only mounted flag
|
||||
public UInt32 s_time; // 0x266, time of last superblock update
|
||||
public UInt32 s_tfree; // 0x26A, total number of free zones
|
||||
public UInt16 s_tinode; // 0x26E, total number of free inodes
|
||||
public UInt16 s_cylblks; // 0x270, blocks per cylinder
|
||||
public UInt16 s_gapblks; // 0x272, blocks per gap
|
||||
public UInt16 s_dinfo0; // 0x274, device information ??
|
||||
public UInt16 s_dinfo1; // 0x276, device information ??
|
||||
public string s_fname; // 0x278, 6 bytes, volume name
|
||||
public string s_fpack; // 0x27E, 6 bytes, pack name
|
||||
public byte s_clean; // 0x284, 0x46 if volume is clean
|
||||
public byte[] s_fill; // 0x285, 371 bytes
|
||||
public UInt32 s_magic; // 0x3F8, magic
|
||||
public UInt32 s_type; // 0x3FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk, 3 = 2048 bytes/blk)
|
||||
}
|
||||
|
||||
private struct SystemVRelease4SuperBlock
|
||||
{
|
||||
public UInt16 s_isize; // 0x000, index of first data zone
|
||||
public UInt16 s_pad0; // 0x002, padding
|
||||
public UInt32 s_fsize; // 0x004, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree; // 0x008, blocks in s_free, <=100
|
||||
public UInt16 s_pad1; // 0x00A, padding
|
||||
public UInt32[] s_free; // 0x00C, 50 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode; // 0x0D4, number of inodes in s_inode, <= 100
|
||||
public UInt16 s_pad2; // 0x0D6, padding
|
||||
public UInt16[] s_inode; // 0x0D8, 100 entries, some free inodes
|
||||
public byte s_flock; // 0x1A0, free block list manipulation lock
|
||||
public byte s_ilock; // 0x1A1, inode cache manipulation lock
|
||||
public byte s_fmod; // 0x1A2, superblock modification flag
|
||||
public byte s_ronly; // 0x1A3, read-only mounted flag
|
||||
public UInt32 s_time; // 0x1A4, time of last superblock update
|
||||
public UInt16 s_cylblks; // 0x1A8, blocks per cylinder
|
||||
public UInt16 s_gapblks; // 0x1AA, blocks per gap
|
||||
public UInt16 s_dinfo0; // 0x1AC, device information ??
|
||||
public UInt16 s_dinfo1; // 0x1AE, device information ??
|
||||
public UInt32 s_tfree; // 0x1B0, total number of free zones
|
||||
public UInt16 s_tinode; // 0x1B4, total number of free inodes
|
||||
public UInt16 s_pad3; // 0x1B6, padding
|
||||
public string s_fname; // 0x1B8, 6 bytes, volume name
|
||||
public string s_fpack; // 0x1BE, 6 bytes, pack name
|
||||
public byte[] s_fill; // 0x1C4, 48 bytes
|
||||
public UInt32 s_state; // 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean
|
||||
public UInt32 s_magic; // 0x1F8, magic
|
||||
public UInt32 s_type; // 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk)
|
||||
}
|
||||
|
||||
private struct SystemVRelease2SuperBlock
|
||||
{
|
||||
public UInt16 s_isize; // 0x000, index of first data zone
|
||||
public UInt32 s_fsize; // 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree; // 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free; // 0x008, 50 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode; // 0x0D0, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode; // 0x0D2, 100 entries, some free inodes
|
||||
public byte s_flock; // 0x19A, free block list manipulation lock
|
||||
public byte s_ilock; // 0x19B, inode cache manipulation lock
|
||||
public byte s_fmod; // 0x19C, superblock modification flag
|
||||
public byte s_ronly; // 0x19D, read-only mounted flag
|
||||
public UInt32 s_time; // 0x19E, time of last superblock update
|
||||
public UInt16 s_cylblks; // 0x1A2, blocks per cylinder
|
||||
public UInt16 s_gapblks; // 0x1A4, blocks per gap
|
||||
public UInt16 s_dinfo0; // 0x1A6, device information ??
|
||||
public UInt16 s_dinfo1; // 0x1A8, device information ??
|
||||
public UInt32 s_tfree; // 0x1AA, total number of free zones
|
||||
public UInt16 s_tinode; // 0x1AE, total number of free inodes
|
||||
public string s_fname; // 0x1B0, 6 bytes, volume name
|
||||
public string s_fpack; // 0x1B6, 6 bytes, pack name
|
||||
public byte[] s_fill; // 0x1BC, 56 bytes
|
||||
public UInt32 s_state; // 0x1F4, if s_state == (0x7C269D38 - s_time) then filesystem is clean
|
||||
public UInt32 s_magic; // 0x1F8, magic
|
||||
public UInt32 s_type; // 0x1FC, filesystem type (1 = 512 bytes/blk, 2 = 1024 bytes/blk)
|
||||
}
|
||||
|
||||
private struct UNIX7thEditionSuperBlock
|
||||
{
|
||||
public UInt16 s_isize; // 0x000, index of first data zone
|
||||
public UInt32 s_fsize; // 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree; // 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free; // 0x008, 50 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode; // 0x0D0, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode; // 0x0D2, 100 entries, some free inodes
|
||||
public byte s_flock; // 0x19A, free block list manipulation lock
|
||||
public byte s_ilock; // 0x19B, inode cache manipulation lock
|
||||
public byte s_fmod; // 0x19C, superblock modification flag
|
||||
public byte s_ronly; // 0x19D, read-only mounted flag
|
||||
public UInt32 s_time; // 0x19E, time of last superblock update
|
||||
public UInt32 s_tfree; // 0x1A2, total number of free zones
|
||||
public UInt16 s_tinode; // 0x1A6, total number of free inodes
|
||||
public UInt16 s_int_m; // 0x1A8, interleave factor
|
||||
public UInt16 s_int_n; // 0x1AA, interleave factor
|
||||
public string s_fname; // 0x1AC, 6 bytes, volume name
|
||||
public string s_fpack; // 0x1B2, 6 bytes, pack name
|
||||
}
|
||||
|
||||
private struct CoherentSuperBlock
|
||||
{
|
||||
public UInt16 s_isize; // 0x000, index of first data zone
|
||||
public UInt32 s_fsize; // 0x002, total number of zones of this volume
|
||||
// the start of the free block list:
|
||||
public UInt16 s_nfree; // 0x006, blocks in s_free, <=100
|
||||
public UInt32[] s_free; // 0x008, 64 entries, first free block list chunk
|
||||
// the cache of free inodes:
|
||||
public UInt16 s_ninode; // 0x108, number of inodes in s_inode, <= 100
|
||||
public UInt16[] s_inode; // 0x10A, 100 entries, some free inodes
|
||||
public byte s_flock; // 0x1D2, free block list manipulation lock
|
||||
public byte s_ilock; // 0x1D3, inode cache manipulation lock
|
||||
public byte s_fmod; // 0x1D4, superblock modification flag
|
||||
public byte s_ronly; // 0x1D5, read-only mounted flag
|
||||
public UInt32 s_time; // 0x1D6, time of last superblock update
|
||||
public UInt32 s_tfree; // 0x1DE, total number of free zones
|
||||
public UInt16 s_tinode; // 0x1E2, total number of free inodes
|
||||
public UInt16 s_int_m; // 0x1E4, interleave factor
|
||||
public UInt16 s_int_n; // 0x1E6, interleave factor
|
||||
public string s_fname; // 0x1E8, 6 bytes, volume name
|
||||
public string s_fpack; // 0x1EE, 6 bytes, pack name
|
||||
public UInt32 s_unique; // 0x1F4, zero-filled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,5 +59,15 @@ namespace FileSystemIDandChk
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user