mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Full rewrite, adding support for pdinfo and vtoc in several
revisions and a lot of debug.
This commit is contained in:
@@ -34,14 +34,19 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using DiscImageChef.CommonTypes;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
|
||||
namespace DiscImageChef.PartPlugins
|
||||
{
|
||||
public class VTOC : PartPlugin
|
||||
{
|
||||
public const uint UNIXDiskLabel_MAGIC = 0xCA5E600D;
|
||||
public const uint UNIXVTOC_MAGIC = 0x600DDEEE;
|
||||
const uint PD_MAGIC = 0xCA5E600D;
|
||||
const uint VTOC_SANE = 0x600DDEEE;
|
||||
const uint PD_CIGAM = 0x0D605ECA;
|
||||
const uint VTOC_ENAS = 0xEEDE0D60;
|
||||
const int V_NUMPAR = 16;
|
||||
const uint XPDVERS = 3; /* 1st version of extended pdinfo */
|
||||
|
||||
public VTOC()
|
||||
{
|
||||
@@ -53,8 +58,9 @@ namespace DiscImageChef.PartPlugins
|
||||
{
|
||||
partitions = new List<Partition>();
|
||||
|
||||
uint magic;
|
||||
byte[] unix_dl_sector = null;
|
||||
uint magic = 0;
|
||||
ulong pdloc = 0;
|
||||
byte[] pdsector = null;
|
||||
bool magic_found = false;
|
||||
|
||||
foreach(ulong i in new ulong[] {0, 1, 8, 29})
|
||||
@@ -62,11 +68,13 @@ namespace DiscImageChef.PartPlugins
|
||||
if(i + sectorOffset >= imagePlugin.GetSectors())
|
||||
break;
|
||||
|
||||
unix_dl_sector = imagePlugin.ReadSector(i + sectorOffset);
|
||||
magic = BitConverter.ToUInt32(unix_dl_sector, 4);
|
||||
if(magic == UNIXDiskLabel_MAGIC)
|
||||
pdsector = imagePlugin.ReadSector(i + sectorOffset);
|
||||
magic = BitConverter.ToUInt32(pdsector, 4);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "sanity at {0} is 0x{1:X8} (should be 0x{2:X8} or 0x{3:X8})", i + sectorOffset, magic, PD_MAGIC, PD_CIGAM);
|
||||
if(magic == PD_MAGIC || magic == PD_CIGAM)
|
||||
{
|
||||
magic_found = true;
|
||||
pdloc = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -74,261 +82,484 @@ namespace DiscImageChef.PartPlugins
|
||||
if(!magic_found)
|
||||
return false;
|
||||
|
||||
UNIXDiskLabel dl = new UNIXDiskLabel();
|
||||
UNIXVTOC vtoc = new UNIXVTOC(); // old/new
|
||||
bool isNewDL = false;
|
||||
int vtocoffset = 0;
|
||||
ulong counter = 0;
|
||||
PDInfo pd;
|
||||
PDInfoOld pdold;
|
||||
GCHandle handle;
|
||||
|
||||
vtoc.magic = BitConverter.ToUInt32(unix_dl_sector, 172);
|
||||
if(vtoc.magic == UNIXVTOC_MAGIC)
|
||||
if(magic == PD_MAGIC)
|
||||
{
|
||||
isNewDL = true;
|
||||
vtocoffset = 72;
|
||||
handle = GCHandle.Alloc(pdsector, GCHandleType.Pinned);
|
||||
pd = (PDInfo)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PDInfo));
|
||||
pdold = (PDInfoOld)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PDInfoOld));
|
||||
handle.Free();
|
||||
}
|
||||
else
|
||||
{
|
||||
vtoc.magic = BitConverter.ToUInt32(unix_dl_sector, 172);
|
||||
if(vtoc.magic != UNIXDiskLabel_MAGIC)
|
||||
pd = BigEndianMarshal.ByteArrayToStructureBigEndian<PDInfo>(pdsector);
|
||||
pdold = BigEndianMarshal.ByteArrayToStructureBigEndian<PDInfoOld>(pdsector);
|
||||
}
|
||||
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.driveid = {0}", pd.driveid);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.sanity = 0x{0:X8} (should be 0x{1:X8})", pd.sanity, PD_MAGIC);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.version = {0}", pd.version);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.serial = \"{0}\"", StringHandlers.CToString(pd.serial));
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.cyls = {0}", pd.cyls);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.tracks = {0}", pd.tracks);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.sectors = {0}", pd.sectors);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.bytes = {0}", pd.bytes);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.logicalst = {0}", pd.logicalst);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.errlogst = {0}", pd.errlogst);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.errlogsz = {0}", pd.errlogsz);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.mfgst = {0}", pd.mfgst);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.mfgsz = {0}", pd.mfgsz);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.defectst = {0}", pd.defectst);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.defectsz = {0}", pd.defectsz);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relno = {0}", pd.relno);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relst = {0}", pd.relst);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relsz = {0}", pd.relsz);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relnext = {0}", pd.relnext);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.allcstrt = {0}", pdold.allcstrt);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.allcend = {0}", pdold.allcend);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_ptr = {0}", pd.vtoc_ptr);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_len = {0}", pd.vtoc_len);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_pad = {0}", pd.vtoc_pad);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.alt_ptr = {0}", pd.alt_ptr);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.alt_len = {0}", pd.alt_len);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pcyls = {0}", pd.pcyls);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.ptracks = {0}", pd.ptracks);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.psectors = {0}", pd.psectors);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pbytes = {0}", pd.pbytes);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.secovhd = {0}", pd.secovhd);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.interleave = {0}", pd.interleave);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.skew = {0}", pd.skew);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[0] = {0}", pd.pad[0]);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[1] = {0}", pd.pad[1]);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[2] = {0}", pd.pad[2]);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[3] = {0}", pd.pad[3]);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[4] = {0}", pd.pad[4]);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[5] = {0}", pd.pad[5]);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[6] = {0}", pd.pad[6]);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[7] = {0}", pd.pad[7]);
|
||||
|
||||
magic_found = false;
|
||||
bool useOld = false;
|
||||
byte[] vtocsector = imagePlugin.ReadSector(pdloc + sectorOffset + 1);
|
||||
vtoc vtoc = new vtoc();
|
||||
vtocold vtocOld = new vtocold();
|
||||
magic = BitConverter.ToUInt32(vtocsector, 0);
|
||||
|
||||
if(magic == VTOC_SANE || magic == VTOC_ENAS)
|
||||
{
|
||||
magic_found = true;
|
||||
useOld = false;
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "New VTOC found at {0}", pdloc + sectorOffset + 1);
|
||||
if(magic == VTOC_SANE)
|
||||
{
|
||||
return false;
|
||||
handle = GCHandle.Alloc(vtocsector, GCHandleType.Pinned);
|
||||
vtoc = (vtoc)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(vtoc));
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
dl.version = BitConverter.ToUInt32(unix_dl_sector, 8); // 8
|
||||
byte[] dl_serial = new byte[12];
|
||||
Array.Copy(unix_dl_sector, 12, dl_serial, 0, 12);
|
||||
dl.serial = StringHandlers.CToString(dl_serial); // 12
|
||||
dl.cyls = BitConverter.ToUInt32(unix_dl_sector, 24); // 24
|
||||
dl.trks = BitConverter.ToUInt32(unix_dl_sector, 28); // 28
|
||||
dl.secs = BitConverter.ToUInt32(unix_dl_sector, 32); // 32
|
||||
dl.bps = BitConverter.ToUInt32(unix_dl_sector, 36); // 36
|
||||
dl.start = BitConverter.ToUInt32(unix_dl_sector, 40); // 40
|
||||
dl.alt_tbl = BitConverter.ToUInt32(unix_dl_sector, 92); // 92
|
||||
dl.alt_len = BitConverter.ToUInt32(unix_dl_sector, 96); // 96
|
||||
|
||||
if(isNewDL) // Old version VTOC starts here
|
||||
{
|
||||
dl.phys_cyl = BitConverter.ToUInt32(unix_dl_sector, 100); // 100
|
||||
dl.phys_trk = BitConverter.ToUInt32(unix_dl_sector, 104); // 104
|
||||
dl.phys_sec = BitConverter.ToUInt32(unix_dl_sector, 108); // 108
|
||||
dl.phys_bytes = BitConverter.ToUInt32(unix_dl_sector, 112); // 112
|
||||
dl.unknown2 = BitConverter.ToUInt32(unix_dl_sector, 116); // 116
|
||||
dl.unknown3 = BitConverter.ToUInt32(unix_dl_sector, 120); // 120
|
||||
}
|
||||
|
||||
if(vtoc.magic == UNIXVTOC_MAGIC)
|
||||
{
|
||||
vtoc.version = BitConverter.ToUInt32(unix_dl_sector, 104 + vtocoffset); // 104/176
|
||||
byte[] vtoc_name = new byte[8];
|
||||
Array.Copy(unix_dl_sector, 108 + vtocoffset, vtoc_name, 0, 8);
|
||||
vtoc.name = StringHandlers.CToString(vtoc_name); // 108/180
|
||||
vtoc.slices = BitConverter.ToUInt16(unix_dl_sector, 116 + vtocoffset); // 116/188
|
||||
vtoc.unknown = BitConverter.ToUInt16(unix_dl_sector, 118 + vtocoffset); // 118/190
|
||||
|
||||
// TODO: What if number of slices overlaps sector (>23)?
|
||||
for(int j = 0; j < vtoc.slices; j++)
|
||||
else
|
||||
{
|
||||
UNIXVTOCEntry vtoc_ent = new UNIXVTOCEntry
|
||||
vtoc = BigEndianMarshal.ByteArrayToStructureBigEndian<vtoc>(vtocsector);
|
||||
for(int i = 0; i < vtoc.v_part.Length; i++)
|
||||
{
|
||||
tag = (UNIX_TAG)BitConverter.ToUInt16(unix_dl_sector, 160 + vtocoffset + j * 12 + 0), // 160/232 + j*12
|
||||
flags = BitConverter.ToUInt16(unix_dl_sector, 160 + vtocoffset + j * 12 + 2), // 162/234 + j*12
|
||||
start = BitConverter.ToUInt32(unix_dl_sector, 160 + vtocoffset + j * 12 + 6), // 166/238 + j*12
|
||||
length = BitConverter.ToUInt32(unix_dl_sector, 160 + vtocoffset + j * 12 + 10) // 170/242 + j*12
|
||||
};
|
||||
if((vtoc_ent.flags & 0x200) == 0x200 && vtoc_ent.tag != UNIX_TAG.EMPTY && vtoc_ent.tag != UNIX_TAG.WHOLE)
|
||||
{
|
||||
Partition part = new Partition
|
||||
{
|
||||
Start = vtoc_ent.start,
|
||||
Length = vtoc_ent.length,
|
||||
Offset = vtoc_ent.start * dl.bps,
|
||||
Size = vtoc_ent.length * dl.bps,
|
||||
Sequence = counter,
|
||||
Type = string.Format("UNIX: {0}", decodeUNIXTAG(vtoc_ent.tag, isNewDL)),
|
||||
Scheme = Name
|
||||
};
|
||||
string info = "";
|
||||
|
||||
if((vtoc_ent.flags & 0x01) == 0x01)
|
||||
info += " (do not mount)";
|
||||
if((vtoc_ent.flags & 0x10) == 0x10)
|
||||
info += " (do not mount)";
|
||||
|
||||
part.Description = "UNIX slice" + info + ".";
|
||||
|
||||
partitions.Add(part);
|
||||
counter++;
|
||||
vtoc.v_part[i].p_tag = (pTag)Swapping.Swap((ushort)vtoc.v_part[i].p_tag);
|
||||
vtoc.v_part[i].p_flag = (pFlag)Swapping.Swap((ushort)vtoc.v_part[i].p_flag);
|
||||
vtoc.v_part[i].p_start = Swapping.Swap(vtoc.v_part[i].p_start);
|
||||
vtoc.v_part[i].p_size = Swapping.Swap(vtoc.v_part[i].p_size);
|
||||
vtoc.timestamp[i] = Swapping.Swap(vtoc.timestamp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if(!magic_found && pd.version < XPDVERS)
|
||||
{
|
||||
magic = BitConverter.ToUInt32(vtocsector, 12);
|
||||
|
||||
if(magic == VTOC_SANE || magic == VTOC_ENAS)
|
||||
{
|
||||
magic_found = true;
|
||||
useOld = true;
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "Old VTOC found at {0}", pdloc + sectorOffset + 1);
|
||||
if(magic == VTOC_SANE)
|
||||
{
|
||||
handle = GCHandle.Alloc(vtocsector, GCHandleType.Pinned);
|
||||
vtocOld = (vtocold)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(vtocold));
|
||||
handle.Free();
|
||||
}
|
||||
else
|
||||
{
|
||||
vtocOld = BigEndianMarshal.ByteArrayToStructureBigEndian<vtocold>(vtocsector);
|
||||
for(int i = 0; i < vtocOld.v_part.Length; i++)
|
||||
{
|
||||
vtocOld.v_part[i].p_tag = (pTag)Swapping.Swap((ushort)vtocOld.v_part[i].p_tag);
|
||||
vtocOld.v_part[i].p_flag = (pFlag)Swapping.Swap((ushort)vtocOld.v_part[i].p_flag);
|
||||
vtocOld.v_part[i].p_start = Swapping.Swap(vtocOld.v_part[i].p_start);
|
||||
vtocOld.v_part[i].p_size = Swapping.Swap(vtocOld.v_part[i].p_size);
|
||||
vtocOld.timestamp[i] = Swapping.Swap(vtocOld.timestamp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!magic_found)
|
||||
{
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "Searching for VTOC on relative byte {0}", pd.vtoc_ptr);
|
||||
ulong rel_sec_ptr = pd.vtoc_ptr / imagePlugin.GetSectorSize();
|
||||
uint rel_sec_off =pd.vtoc_ptr % imagePlugin.GetSectorSize();
|
||||
uint sec_count = (rel_sec_off + pd.vtoc_len) / imagePlugin.GetSectorSize();
|
||||
if((rel_sec_off + pd.vtoc_len) % imagePlugin.GetSectorSize() > 0)
|
||||
sec_count++;
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "Going to read {0} sectors from sector {1}, getting VTOC from byte {2}", sec_count, rel_sec_ptr + sectorOffset, rel_sec_off);
|
||||
if(rel_sec_ptr + sectorOffset + sec_count >= imagePlugin.GetSectors())
|
||||
{
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "Going to read past device size, aborting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] tmp = imagePlugin.ReadSectors(rel_sec_ptr + sectorOffset, sec_count);
|
||||
vtocsector = new byte[pd.vtoc_len];
|
||||
Array.Copy(tmp, rel_sec_off, vtocsector, 0, pd.vtoc_len);
|
||||
magic = BitConverter.ToUInt32(vtocsector, 0);
|
||||
|
||||
if(magic == VTOC_SANE || magic == VTOC_ENAS)
|
||||
{
|
||||
magic_found = true;
|
||||
useOld = false;
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "New VTOC found.");
|
||||
if(magic == VTOC_SANE)
|
||||
{
|
||||
handle = GCHandle.Alloc(vtocsector, GCHandleType.Pinned);
|
||||
vtoc = (vtoc)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(vtoc));
|
||||
handle.Free();
|
||||
}
|
||||
else
|
||||
{
|
||||
vtoc = BigEndianMarshal.ByteArrayToStructureBigEndian<vtoc>(vtocsector);
|
||||
for(int i = 0; i < vtoc.v_part.Length; i++)
|
||||
{
|
||||
vtoc.v_part[i].p_tag = (pTag)Swapping.Swap((ushort)vtoc.v_part[i].p_tag);
|
||||
vtoc.v_part[i].p_flag = (pFlag)Swapping.Swap((ushort)vtoc.v_part[i].p_flag);
|
||||
vtoc.v_part[i].p_start = Swapping.Swap(vtoc.v_part[i].p_start);
|
||||
vtoc.v_part[i].p_size = Swapping.Swap(vtoc.v_part[i].p_size);
|
||||
vtoc.timestamp[i] = Swapping.Swap(vtoc.timestamp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!magic_found)
|
||||
{
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "Cannot find VTOC.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(useOld)
|
||||
{
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_sanity = 0x{0:X8} (should be 0x{1:X8})", vtocOld.v_sanity, VTOC_SANE);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_version = {0}", vtocOld.v_version);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_volume = \"{0}\"", StringHandlers.CToString(vtocOld.v_volume));
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_sectorsz = {0}", vtocOld.v_sectorsz);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_nparts = {0}", vtocOld.v_nparts);
|
||||
for(int i = 0; i < V_NUMPAR; i++)
|
||||
{
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_tag = {1} ({2})", i, vtocOld.v_part[i].p_tag, (ushort)vtocOld.v_part[i].p_tag);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_flag = {1} ({2})", i, vtocOld.v_part[i].p_flag, (ushort)vtocOld.v_part[i].p_flag);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_start = {1}", i, vtocOld.v_part[i].p_start);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_size = {1}", i, vtocOld.v_part[i].p_size);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.timestamp[{0}] = {1}", i, DateHandlers.UNIXToDateTime(vtocOld.timestamp[i]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_sanity = 0x{0:X8} (should be 0x{1:X8})", vtoc.v_sanity, VTOC_SANE);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_version = {0}", vtoc.v_version);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_volume = \"{0}\"", StringHandlers.CToString(vtoc.v_volume));
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_pad = {0}", vtoc.v_pad);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_nparts = {0}", vtoc.v_nparts);
|
||||
for(int i = 0; i < V_NUMPAR; i++)
|
||||
{
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_tag = {1} ({2})", i, vtoc.v_part[i].p_tag, (ushort)vtoc.v_part[i].p_tag);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_flag = {1} ({2})", i, vtoc.v_part[i].p_flag, (ushort)vtoc.v_part[i].p_flag);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_start = {1}", i, vtoc.v_part[i].p_start);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_size = {1}", i, vtoc.v_part[i].p_size);
|
||||
DicConsole.DebugWriteLine("VTOC plugin", "vtoc.timestamp[{0}] = {1}", i, DateHandlers.UNIXToDateTime(vtoc.timestamp[i]));
|
||||
}
|
||||
}
|
||||
|
||||
uint bps;
|
||||
partition[] parts;
|
||||
int[] timestamps;
|
||||
|
||||
if(useOld)
|
||||
{
|
||||
bps = vtocOld.v_sectorsz;
|
||||
parts = vtocOld.v_part;
|
||||
timestamps = vtocOld.timestamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
bps = pd.bytes;
|
||||
parts = vtoc.v_part;
|
||||
timestamps = vtoc.timestamp;
|
||||
}
|
||||
|
||||
for(int i = 0; i < V_NUMPAR; i++)
|
||||
{
|
||||
if(parts[i].p_tag != pTag.V_UNUSED)
|
||||
{
|
||||
Partition part = new Partition
|
||||
{
|
||||
Start = ((ulong)(parts[i].p_start * bps) / imagePlugin.GetSectorSize()),
|
||||
Length = (ulong)(parts[i].p_size * bps) / imagePlugin.GetSectorSize(),
|
||||
Offset = (ulong)(parts[i].p_start * bps),
|
||||
Size = (ulong)(parts[i].p_size * bps),
|
||||
Sequence = (ulong)i,
|
||||
Type = string.Format("UNIX: {0}", decodeUNIXTAG(parts[i].p_tag, !useOld)),
|
||||
Scheme = Name
|
||||
};
|
||||
string info = "";
|
||||
|
||||
// Apparently old ones are absolute :?
|
||||
if(!useOld)
|
||||
{
|
||||
part.Start += sectorOffset;
|
||||
part.Offset += sectorOffset * imagePlugin.GetSectorSize();
|
||||
}
|
||||
|
||||
if(parts[i].p_flag.HasFlag(pFlag.V_VALID))
|
||||
info += " (valid)";
|
||||
if(parts[i].p_flag.HasFlag(pFlag.V_UNMNT))
|
||||
info += " (unmountable)";
|
||||
if(parts[i].p_flag.HasFlag(pFlag.V_OPEN))
|
||||
info += " (open)";
|
||||
if(parts[i].p_flag.HasFlag(pFlag.V_REMAP))
|
||||
info += " (alternate sector mapping)";
|
||||
if(parts[i].p_flag.HasFlag(pFlag.V_RONLY))
|
||||
info += " (read-only)";
|
||||
if(timestamps[i] != 0)
|
||||
info += string.Format(" created on {0}", DateHandlers.UNIXToDateTime(timestamps[i]));
|
||||
|
||||
part.Description = "UNIX slice" + info + ".";
|
||||
|
||||
if(part.End < imagePlugin.GetSectors())
|
||||
partitions.Add(part);
|
||||
}
|
||||
}
|
||||
|
||||
return partitions.Count > 0;
|
||||
}
|
||||
|
||||
// Same as Solaris VTOC
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct UNIXDiskLabel
|
||||
public struct PDInfo
|
||||
{
|
||||
/// <summary>Drive type, seems always 0</summary>
|
||||
public uint type;
|
||||
/// <summary>UNIXDiskLabel_MAGIC</summary>
|
||||
public uint magic;
|
||||
/// <summary>Only seen 1</summary>
|
||||
public uint version;
|
||||
/// <summary>12 bytes, serial number of the device</summary>
|
||||
public uint driveid; /*identifies the device type*/
|
||||
public uint sanity; /*verifies device sanity*/
|
||||
public uint version; /*version number*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public string serial;
|
||||
/// <summary>data cylinders per device</summary>
|
||||
public uint cyls;
|
||||
/// <summary>data tracks per cylinder</summary>
|
||||
public uint trks;
|
||||
/// <summary>data sectors per track</summary>
|
||||
public uint secs;
|
||||
/// <summary>data bytes per sector</summary>
|
||||
public uint bps;
|
||||
/// <summary>first sector of this partition</summary>
|
||||
public uint start;
|
||||
/// <summary>48 bytes</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
|
||||
public byte[] unknown1;
|
||||
/// <summary>byte offset of alternate table</summary>
|
||||
public uint alt_tbl;
|
||||
/// <summary>byte length of alternate table</summary>
|
||||
public uint alt_len;
|
||||
// From onward here, is not on old version
|
||||
/// <summary>physical cylinders per device</summary>
|
||||
public uint phys_cyl;
|
||||
/// <summary>physical tracks per cylinder</summary>
|
||||
public uint phys_trk;
|
||||
/// <summary>physical sectors per track</summary>
|
||||
public uint phys_sec;
|
||||
/// <summary>physical bytes per sector</summary>
|
||||
public uint phys_bytes;
|
||||
/// <summary></summary>
|
||||
public uint unknown2;
|
||||
/// <summary></summary>
|
||||
public uint unknown3;
|
||||
/// <summary>32bytes</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public byte[] pad;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct UNIXVTOC
|
||||
{
|
||||
/// <summary>UNIXVTOC_MAGIC</summary>
|
||||
public uint magic;
|
||||
/// <summary>1</summary>
|
||||
public uint version;
|
||||
/// <summary>8 bytes</summary>
|
||||
public byte[] serial; /*serial number of the device*/
|
||||
public uint cyls; /*number of cylinders per drive*/
|
||||
public uint tracks; /*number tracks per cylinder*/
|
||||
public uint sectors; /*number sectors per track*/
|
||||
public uint bytes; /*number of bytes per sector*/
|
||||
public uint logicalst; /*sector address of logical sector 0*/
|
||||
public uint errlogst; /*sector address of error log area*/
|
||||
public uint errlogsz; /*size in bytes of error log area*/
|
||||
public uint mfgst; /*sector address of mfg. defect info*/
|
||||
public uint mfgsz; /*size in bytes of mfg. defect info*/
|
||||
public uint defectst; /*sector address of the defect map*/
|
||||
public uint defectsz; /*size in bytes of defect map*/
|
||||
public uint relno; /*number of relocation areas*/
|
||||
public uint relst; /*sector address of relocation area*/
|
||||
public uint relsz; /*size in sectors of relocation area*/
|
||||
public uint relnext; /*address of next avail reloc sector*/
|
||||
/* the previous items are left intact from AT&T's 3b2 pdinfo. Following
|
||||
are added for the 80386 port */
|
||||
public uint vtoc_ptr; /*byte offset of vtoc block*/
|
||||
public ushort vtoc_len; /*byte length of vtoc block*/
|
||||
public ushort vtoc_pad; /* pad for 16-bit machine alignment */
|
||||
public uint alt_ptr; /*byte offset of alternates table*/
|
||||
public ushort alt_len; /*byte length of alternates table*/
|
||||
/* new in version 3 */
|
||||
public uint pcyls; /*physical cylinders per drive*/
|
||||
public uint ptracks; /*physical tracks per cylinder*/
|
||||
public uint psectors; /*physical sectors per track*/
|
||||
public uint pbytes; /*physical bytes per sector*/
|
||||
public uint secovhd; /*sector overhead bytes per sector*/
|
||||
public ushort interleave; /*interleave factor*/
|
||||
public ushort skew; /*skew factor*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public string name;
|
||||
/// <summary># of slices</summary>
|
||||
public ushort slices;
|
||||
/// <summary></summary>
|
||||
public ushort unknown;
|
||||
/// <summary>40 bytes</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
|
||||
public byte[] reserved;
|
||||
public uint[] pad; /*space for more stuff*/
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct UNIXVTOCEntry
|
||||
public struct PDInfoOld
|
||||
{
|
||||
/// <summary>TAG</summary>
|
||||
public UNIX_TAG tag;
|
||||
public ushort flags;
|
||||
/// <summary>Flags (see below)</summary>
|
||||
public uint start;
|
||||
/// <summary>Start sector</summary>
|
||||
public uint length;
|
||||
/// <summary>Length of slice in sectors</summary>
|
||||
public uint driveid; /*identifies the device type*/
|
||||
public uint sanity; /*verifies device sanity*/
|
||||
public uint version; /*version number*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] serial; /*serial number of the device*/
|
||||
public uint cyls; /*number of cylinders per drive*/
|
||||
public uint tracks; /*number tracks per cylinder*/
|
||||
public uint sectors; /*number sectors per track*/
|
||||
public uint bytes; /*number of bytes per sector*/
|
||||
public uint logicalst; /*sector address of logical sector 0*/
|
||||
public uint errlogst; /*sector address of error log area*/
|
||||
public uint errlogsz; /*size in bytes of error log area*/
|
||||
public uint mfgst; /*sector address of mfg. defect info*/
|
||||
public uint mfgsz; /*size in bytes of mfg. defect info*/
|
||||
public uint defectst; /*sector address of the defect map*/
|
||||
public uint defectsz; /*size in bytes of defect map*/
|
||||
public uint relno; /*number of relocation areas*/
|
||||
public uint relst; /*sector address of relocation area*/
|
||||
public uint relsz; /*size in sectors of relocation area*/
|
||||
public uint relnext; /*address of next avail reloc sector*/
|
||||
public uint allcstrt; /*start of the allocatable disk*/
|
||||
public uint allcend; /*end of allocatable disk*/
|
||||
}
|
||||
|
||||
public enum UNIX_TAG : ushort
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct vtocold
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public uint[] v_bootinfo; /*info needed by mboot*/
|
||||
public uint v_sanity; /*to verify vtoc sanity*/
|
||||
public uint v_version; /*layout version*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] v_volume; /*volume name*/
|
||||
public ushort v_sectorsz; /*sector size in bytes*/
|
||||
public ushort v_nparts; /*number of partitions*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||
public uint[] v_reserved; /*free space*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)]
|
||||
public partition[] v_part; /*partition headers*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)]
|
||||
public int[] timestamp; /* SCSI time stamp */
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct vtoc
|
||||
{
|
||||
public uint v_sanity; /*to verify vtoc sanity*/
|
||||
public uint v_version; /*layout version*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] v_volume; /*volume name*/
|
||||
public ushort v_nparts; /*number of partitions*/
|
||||
public ushort v_pad; /*pad for 286 compiler*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||
public uint[] v_reserved; /*free space*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)]
|
||||
public partition[] v_part; /*partition headers*/
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)]
|
||||
public int[] timestamp; /* SCSI time stamp */
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct partition
|
||||
{
|
||||
public pTag p_tag; /*ID tag of partition*/
|
||||
public pFlag p_flag; /*permision flags*/
|
||||
public int p_start; /*start sector no of partition*/
|
||||
public int p_size; /*# of blocks in partition*/
|
||||
};
|
||||
|
||||
public enum pTag : ushort
|
||||
{
|
||||
/// <summary>empty</summary>
|
||||
EMPTY = 0x0000,
|
||||
V_UNUSED = 0x0000,
|
||||
/// <summary>boot</summary>
|
||||
BOOT = 0x0001,
|
||||
V_BOOT = 0x0001,
|
||||
/// <summary>root</summary>
|
||||
ROOT = 0x0002,
|
||||
V_ROOT = 0x0002,
|
||||
/// <summary>swap</summary>
|
||||
SWAP = 0x0003,
|
||||
V_SWAP = 0x0003,
|
||||
/// <summary>/usr</summary>
|
||||
USER = 0x0004,
|
||||
V_USER = 0x0004,
|
||||
/// <summary>whole disk</summary>
|
||||
WHOLE = 0x0005,
|
||||
V_BACKUP = 0x0005,
|
||||
/// <summary>stand partition ??</summary>
|
||||
STAND = 0x0006,
|
||||
V_STAND_OLD = 0x0006,
|
||||
/// <summary>alternate sector space</summary>
|
||||
ALT_S = 0x0006,
|
||||
V_ALTS_OLD = 0x0006,
|
||||
/// <summary>/var</summary>
|
||||
VAR = 0x0007,
|
||||
V_VAR_OLD = 0x0007,
|
||||
/// <summary>non UNIX</summary>
|
||||
OTHER = 0x0007,
|
||||
V_OTHER = 0x0007,
|
||||
/// <summary>/home</summary>
|
||||
HOME = 0x0008,
|
||||
V_HOME_OLD = 0x0008,
|
||||
/// <summary>alternate track space</summary>
|
||||
ALT_T = 0x0008,
|
||||
V_ALTS = 0x0008,
|
||||
/// <summary>alternate sector track</summary>
|
||||
ALT_ST = 0x0009,
|
||||
V_ALTSCTR_OLD = 0x0009,
|
||||
/// <summary>stand partition ??</summary>
|
||||
NEW_STAND = 0x0009,
|
||||
V_STAND = 0x0009,
|
||||
/// <summary>cache</summary>
|
||||
CACHE = 0x000A,
|
||||
V_CACHE = 0x000A,
|
||||
/// <summary>/var</summary>
|
||||
NEW_VAR = 0x000A,
|
||||
V_VAR = 0x000A,
|
||||
/// <summary>reserved</summary>
|
||||
RESERVED = 0x000B,
|
||||
V_RESERVED = 0x000B,
|
||||
/// <summary>/home</summary>
|
||||
NEW_HOME = 0x000B,
|
||||
V_HOME = 0x000B,
|
||||
/// <summary>dump partition</summary>
|
||||
DUMP = 0x000C,
|
||||
V_DUMP = 0x000C,
|
||||
/// <summary>alternate sector track</summary>
|
||||
NEW_ALT_ST = 0x000D,
|
||||
V_ALTSCTR = 0x000D,
|
||||
/// <summary>volume mgt public partition</summary>
|
||||
VM_PUBLIC = 0x000E,
|
||||
V_VMPUBLIC = 0x000E,
|
||||
/// <summary>volume mgt private partition</summary>
|
||||
VM_PRIVATE = 0x000F
|
||||
V_VMPRIVATE = 0x000F
|
||||
}
|
||||
|
||||
public static string decodeUNIXTAG(UNIX_TAG type, bool isNew)
|
||||
[Flags]
|
||||
enum pFlag : ushort
|
||||
{
|
||||
/* Partition permission flags */
|
||||
V_UNMNT = 0x01, /* Unmountable partition */
|
||||
V_RONLY = 0x10, /* Read only */
|
||||
V_REMAP = 0x20, /* do alternate sector mapping */
|
||||
V_OPEN = 0x100, /* Partition open (for driver use) */
|
||||
V_VALID = 0x200, /* Partition is valid to use */
|
||||
V_VOMASK = 0x300 /* mask for open and valid */
|
||||
}
|
||||
|
||||
public static string decodeUNIXTAG(pTag type, bool isNew)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case UNIX_TAG.EMPTY:
|
||||
case pTag.V_UNUSED:
|
||||
return "Unused";
|
||||
case UNIX_TAG.BOOT:
|
||||
case pTag.V_BOOT:
|
||||
return "Boot";
|
||||
case UNIX_TAG.ROOT:
|
||||
case pTag.V_ROOT:
|
||||
return "/";
|
||||
case UNIX_TAG.SWAP:
|
||||
case pTag.V_SWAP:
|
||||
return "Swap";
|
||||
case UNIX_TAG.USER:
|
||||
case pTag.V_USER:
|
||||
return "/usr";
|
||||
case UNIX_TAG.WHOLE:
|
||||
case pTag.V_BACKUP:
|
||||
return "Whole disk";
|
||||
case UNIX_TAG.STAND:
|
||||
case pTag.V_STAND_OLD:
|
||||
return isNew ? "Stand" : "Alternate sector space";
|
||||
case UNIX_TAG.VAR:
|
||||
case pTag.V_VAR_OLD:
|
||||
return isNew ? "/var" : "non UNIX";
|
||||
case UNIX_TAG.HOME:
|
||||
case pTag.V_HOME_OLD:
|
||||
return isNew ? "/home" : "Alternate track space";
|
||||
case UNIX_TAG.ALT_ST:
|
||||
case pTag.V_ALTSCTR_OLD:
|
||||
return isNew ? "Alternate sector track" : "Stand";
|
||||
case UNIX_TAG.CACHE:
|
||||
case pTag.V_CACHE:
|
||||
return isNew ? "Cache" : "/var";
|
||||
case UNIX_TAG.RESERVED:
|
||||
case pTag.V_RESERVED:
|
||||
return isNew ? "Reserved" : "/home";
|
||||
case UNIX_TAG.DUMP:
|
||||
case pTag.V_DUMP:
|
||||
return "dump";
|
||||
case UNIX_TAG.NEW_ALT_ST:
|
||||
case pTag.V_ALTSCTR:
|
||||
return "Alternate sector track";
|
||||
case UNIX_TAG.VM_PUBLIC:
|
||||
case pTag.V_VMPUBLIC:
|
||||
return "volume mgt public partition";
|
||||
case UNIX_TAG.VM_PRIVATE:
|
||||
case pTag.V_VMPRIVATE:
|
||||
return "volume mgt private partition";
|
||||
default:
|
||||
return string.Format("Unknown TAG: 0x{0:X4}", type);
|
||||
|
||||
Reference in New Issue
Block a user