Full rewrite, adding support for pdinfo and vtoc in several

revisions and a lot of debug.
This commit is contained in:
2017-08-01 13:36:03 +01:00
parent eff67bb1b2
commit aabd8996d9

View File

@@ -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);