From 9ae0530b9075429984aacdcda0b3ee2558fbce46 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 4 Aug 2012 15:11:36 +0000 Subject: [PATCH] * FileSystemIDandChk.sln: Updated solution version to VS2010 * Packages.mdproj: * FFS.cs: Added code for detecting 42BSD, 43BSD, 44BSD, SunOS, SunOS/x86, UFS and UFS2 filesystems. Block size is incorrect on NeXTStep's CD UFSs, but there is no way to check for it. * Main.cs: Disable debug by default * FileSystemIDandChk.csproj: Moved to .NET 4 and added EndianAwareBinaryReader class * EndianAwareBinaryReader.cs: Override of BinaryReader class with the ability to automatically swap endianness git-svn-id: svn://claunia.com/FileSystemIDandChk@13 17725271-3d32-4980-a8cb-9ff532f270ba --- FileSystemIDandChk.sln | 4 +- FileSystemIDandChk/ChangeLog | 17 + FileSystemIDandChk/EndianAwareBinaryReader.cs | 127 +++ FileSystemIDandChk/FileSystemIDandChk.csproj | 4 +- FileSystemIDandChk/Main.cs | 2 +- FileSystemIDandChk/Plugins/FFS.cs | 858 +++++++++++++++++- Packages.mdproj | 46 +- 7 files changed, 1042 insertions(+), 16 deletions(-) create mode 100644 FileSystemIDandChk/EndianAwareBinaryReader.cs diff --git a/FileSystemIDandChk.sln b/FileSystemIDandChk.sln index 905c56a05..650187371 100644 --- a/FileSystemIDandChk.sln +++ b/FileSystemIDandChk.sln @@ -1,6 +1,6 @@  -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileSystemIDandChk", "FileSystemIDandChk\FileSystemIDandChk.csproj", "{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}" EndProject Project("{9344bdbb-3e7f-41fc-a0dd-8665d75ee146}") = "Packages", "Packages.mdproj", "{8996EF59-09B9-4920-A3DE-2F8EA2EBBCFF}" diff --git a/FileSystemIDandChk/ChangeLog b/FileSystemIDandChk/ChangeLog index 56f722c8f..08d3db96e 100644 --- a/FileSystemIDandChk/ChangeLog +++ b/FileSystemIDandChk/ChangeLog @@ -1,3 +1,20 @@ +2012-08-04 Natalia Portillo + + * Plugins/FFS.cs: + Added code for detecting 42BSD, 43BSD, 44BSD, SunOS, + SunOS/x86, UFS and UFS2 filesystems. Block size is incorrect + on NeXTStep's CD UFSs, but there is no way to check for it. + + * Main.cs: + Disable debug by default + + * FileSystemIDandChk.csproj: + Moved to .NET 4 and added EndianAwareBinaryReader class + + * EndianAwareBinaryReader.cs: + Override of BinaryReader class with the ability to + automatically swap endianness + 2012-08-03 Natalia Portillo * Plugins/ISO9660.cs: diff --git a/FileSystemIDandChk/EndianAwareBinaryReader.cs b/FileSystemIDandChk/EndianAwareBinaryReader.cs new file mode 100644 index 000000000..d2c1d4741 --- /dev/null +++ b/FileSystemIDandChk/EndianAwareBinaryReader.cs @@ -0,0 +1,127 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; + +namespace FileSystemIDandChk +{ + public class EndianAwareBinaryReader : BinaryReader + { + private bool isLittleEndian; + private byte[] buffer = new byte[8]; + + public EndianAwareBinaryReader(Stream input, Encoding encoding, bool isLittleEndian) + : base(input, encoding) + { + this.isLittleEndian = isLittleEndian; + } + + public EndianAwareBinaryReader(Stream input, bool isLittleEndian) + : this(input, Encoding.UTF8, isLittleEndian) + { + } + + public bool IsLittleEndian + { + get { return isLittleEndian; } + set { isLittleEndian = value; } + } + + + public override double ReadDouble() + { + if (isLittleEndian) + return base.ReadDouble(); + FillMyBuffer(8); + return BitConverter.ToDouble(buffer.Take(8).Reverse().ToArray(), 0); + } + + public override short ReadInt16() + { + if (isLittleEndian) + return base.ReadInt16(); + FillMyBuffer(2); + return BitConverter.ToInt16(buffer.Take(2).Reverse().ToArray(), 0); + + } + + public override int ReadInt32() + { + if (isLittleEndian) + return base.ReadInt32(); + FillMyBuffer(4); + return BitConverter.ToInt32(buffer.Take(4).Reverse().ToArray(), 0); + + } + + public override long ReadInt64() + { + if (isLittleEndian) + return base.ReadInt64(); + FillMyBuffer(8); + return BitConverter.ToInt64(buffer.Take(8).Reverse().ToArray(), 0); + + } + + public override float ReadSingle() + { + if (isLittleEndian) + return base.ReadSingle(); + FillMyBuffer(4); + return BitConverter.ToSingle(buffer.Take(4).Reverse().ToArray(), 0); + } + + public override ushort ReadUInt16() + { + if (isLittleEndian) + return base.ReadUInt16(); + FillMyBuffer(2); + return BitConverter.ToUInt16(buffer.Take(2).Reverse().ToArray(), 0); + } + + + public override uint ReadUInt32() + { + if (isLittleEndian) + return base.ReadUInt32(); + FillMyBuffer(4); + return BitConverter.ToUInt32(buffer.Take(4).Reverse().ToArray(), 0); + } + + public override ulong ReadUInt64() + { + if (isLittleEndian) + return base.ReadUInt64(); + FillMyBuffer(8); + return BitConverter.ToUInt64(buffer.Take(8).Reverse().ToArray(), 0); + } + + private void FillMyBuffer(int numBytes) + { + int offset = 0; + int num2 = 0; + if (numBytes == 1) + { + num2 = BaseStream.ReadByte(); + if (num2 == -1) + { + throw new EndOfStreamException("Attempted to read past the end of the stream."); + } + buffer[0] = (byte)num2; + } + else + { + do + { + num2 = BaseStream.Read(buffer, offset, numBytes - offset); + if (num2 == 0) + { + throw new EndOfStreamException("Attempted to read past the end of the stream."); + } + offset += num2; + } + while (offset < numBytes); + } + } + } +} \ No newline at end of file diff --git a/FileSystemIDandChk/FileSystemIDandChk.csproj b/FileSystemIDandChk/FileSystemIDandChk.csproj index a8d4f0d81..01b1a4955 100644 --- a/FileSystemIDandChk/FileSystemIDandChk.csproj +++ b/FileSystemIDandChk/FileSystemIDandChk.csproj @@ -1,5 +1,5 @@ - + Debug x86 @@ -33,6 +33,7 @@ + @@ -61,6 +62,7 @@ + diff --git a/FileSystemIDandChk/Main.cs b/FileSystemIDandChk/Main.cs index 3c3c1803f..fbb7e896b 100644 --- a/FileSystemIDandChk/Main.cs +++ b/FileSystemIDandChk/Main.cs @@ -19,7 +19,7 @@ namespace FileSystemIDandChk chkPartitions = true; chkFilesystems = true; - isDebug = true; + isDebug = false; Console.WriteLine ("Filesystem Identifier and Checker"); Console.WriteLine ("Copyright (C) Natalia Portillo, All Rights Reserved"); diff --git a/FileSystemIDandChk/Plugins/FFS.cs b/FileSystemIDandChk/Plugins/FFS.cs index fabf9964e..3012c8b52 100644 --- a/FileSystemIDandChk/Plugins/FFS.cs +++ b/FileSystemIDandChk/Plugins/FFS.cs @@ -1,20 +1,856 @@ -/*using System; +using System; using System.IO; using System.Text; using FileSystemIDandChk; -namespace FileSystemIDandChk +// Using information from Linux kernel headers + +namespace FileSystemIDandChk.Plugins { - public class FFS + public class FFSPlugin : Plugin { - private DateTime UNIXDateDelta = new DateTime(1970, 01, 01, 00, 00, 00); - - public FFS () + public FFSPlugin (PluginBase Core) { - base.Name = "Apple Hierarchical File System"; - base.PluginUUID = new Guid("8f4ee9d5-6820-4d7a-ae6b-3a4a49e7a88f"); + base.Name = "BSD Fast File System (aka UNIX File System, UFS)"; + base.PluginUUID = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3"); + } + + public override bool Identify(FileStream fileStream, long offset) + { + UInt32 magic; + BinaryReader br = new BinaryReader(fileStream); + + if(fileStream.Length > (offset + sb_start_floppy + 0x055C)) + { + br.BaseStream.Seek(offset + sb_start_floppy + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } + + if(fileStream.Length > (offset + sb_start_ufs1 + 0x055C)) + { + br.BaseStream.Seek(offset + sb_start_ufs1 + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } + + if(fileStream.Length > (offset + sb_start_ufs2 + 0x055C)) + { + br.BaseStream.Seek(offset + sb_start_ufs2 + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } + + if(fileStream.Length > (offset + sb_start_piggy + 0x055C)) + { + br.BaseStream.Seek(offset + sb_start_piggy + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + return true; + } + + return false; + } + + public override void GetInformation (FileStream fileStream, long offset, out string information) + { + information = ""; + StringBuilder sbInformation = new StringBuilder(); + + UInt32 magic = 0; + BinaryReader br = new BinaryReader(fileStream); + long sb_offset = offset; + bool fs_type_42bsd = false; + bool fs_type_43bsd = false; + bool fs_type_44bsd = false; + bool fs_type_ufs = false; + bool fs_type_ufs2 = false; + bool fs_type_sun = false; + bool fs_type_sun86 = false; + + if(fileStream.Length > (offset + sb_start_floppy + 0x055C) && magic == 0) + { + br.BaseStream.Seek(offset + sb_start_floppy + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + sb_offset = offset + sb_start_floppy; + else + magic = 0; + } + + if(fileStream.Length > (offset + sb_start_ufs1 + 0x055C) && magic == 0) + { + br.BaseStream.Seek(offset + sb_start_ufs1 + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + sb_offset = offset + sb_start_ufs1; + else + magic = 0; + } + + if(fileStream.Length > (offset + sb_start_ufs2 + 0x055C) && magic == 0) + { + br.BaseStream.Seek(offset + sb_start_ufs2 + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + sb_offset = offset + sb_start_ufs2; + else + magic = 0; + } + + if(fileStream.Length > (offset + sb_start_piggy + 0x055C) && magic == 0) + { + br.BaseStream.Seek(offset + sb_start_piggy + 0x055C, SeekOrigin.Begin); + magic = br.ReadUInt32(); + + if (magic == UFS_MAGIC || magic == UFS_MAGIC_BW || magic == UFS2_MAGIC || magic == UFS_CIGAM || magic == UFS_BAD_MAGIC) + sb_offset = offset + sb_start_piggy; + else + magic = 0; + } + + if(magic == 0) + { + information = "Not a UFS filesystem, I shouldn't have arrived here!"; + return; + } + + switch(magic) + { + case UFS_MAGIC: + sbInformation.AppendLine("UFS filesystem"); + break; + case UFS_MAGIC_BW: + sbInformation.AppendLine("BorderWare UFS filesystem"); + break; + case UFS2_MAGIC: + sbInformation.AppendLine("UFS2 filesystem"); + break; + case UFS_CIGAM: + sbInformation.AppendLine("Big-endian UFS filesystem"); + break; + case UFS_BAD_MAGIC: + sbInformation.AppendLine("Incompletely initialized UFS filesystem"); + sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); + break; + default: + break; + } + + EndianAwareBinaryReader eabr; + if(magic == UFS_CIGAM) + eabr = new EndianAwareBinaryReader(fileStream, false); // Big-endian UFS + else + eabr = new EndianAwareBinaryReader(fileStream, true); // Little-endian UFS + // Are there any other cases to detect big-endian UFS? + + // Fun with seeking follows on superblock reading! + UFSSuperBlock ufs_sb = new UFSSuperBlock(); + byte[] strings_b; + eabr.BaseStream.Seek(sb_offset, SeekOrigin.Begin); + + ufs_sb.fs_link_42bsd = eabr.ReadUInt32(); + ufs_sb.fs_state_sun = ufs_sb.fs_link_42bsd; + ufs_sb.fs_rlink = eabr.ReadUInt32(); // 0x0004 UNUSED + ufs_sb.fs_sblkno = eabr.ReadUInt32(); // 0x0008 addr of super-block in filesys + ufs_sb.fs_cblkno = eabr.ReadUInt32(); // 0x000C offset of cyl-block in filesys + ufs_sb.fs_iblkno = eabr.ReadUInt32(); // 0x0010 offset of inode-blocks in filesys + ufs_sb.fs_dblkno = eabr.ReadUInt32(); // 0x0014 offset of first data after cg + ufs_sb.fs_cgoffset = eabr.ReadUInt32(); // 0x0018 cylinder group offset in cylinder + ufs_sb.fs_cgmask = eabr.ReadUInt32(); // 0x001C used to calc mod fs_ntrak + ufs_sb.fs_time_t = eabr.ReadUInt32(); // 0x0020 last time written -- time_t + ufs_sb.fs_size = eabr.ReadUInt32(); // 0x0024 number of blocks in fs + ufs_sb.fs_dsize = eabr.ReadUInt32(); // 0x0028 number of data blocks in fs + ufs_sb.fs_ncg = eabr.ReadUInt32(); // 0x002C number of cylinder groups + ufs_sb.fs_bsize = eabr.ReadUInt32(); // 0x0030 size of basic blocks in fs + ufs_sb.fs_fsize = eabr.ReadUInt32(); // 0x0034 size of frag blocks in fs + ufs_sb.fs_frag = eabr.ReadUInt32(); // 0x0038 number of frags in a block in fs + // these are configuration parameters + ufs_sb.fs_minfree = eabr.ReadUInt32(); // 0x003C minimum percentage of free blocks + ufs_sb.fs_rotdelay = eabr.ReadUInt32(); // 0x0040 num of ms for optimal next block + ufs_sb.fs_rps = eabr.ReadUInt32(); // 0x0044 disk revolutions per second + // these fields can be computed from the others + ufs_sb.fs_bmask = eabr.ReadUInt32(); // 0x0048 ``blkoff'' calc of blk offsets + ufs_sb.fs_fmask = eabr.ReadUInt32(); // 0x004C ``fragoff'' calc of frag offsets + ufs_sb.fs_bshift = eabr.ReadUInt32(); // 0x0050 ``lblkno'' calc of logical blkno + ufs_sb.fs_fshift = eabr.ReadUInt32(); // 0x0054 ``numfrags'' calc number of frags + // these are configuration parameters + ufs_sb.fs_maxcontig = eabr.ReadUInt32(); // 0x0058 max number of contiguous blks + ufs_sb.fs_maxbpg = eabr.ReadUInt32(); // 0x005C max number of blks per cyl group + // these fields can be computed from the others + ufs_sb.fs_fragshift = eabr.ReadUInt32(); // 0x0060 block to frag shift + ufs_sb.fs_fsbtodb = eabr.ReadUInt32(); // 0x0064 fsbtodb and dbtofsb shift constant + ufs_sb.fs_sbsize = eabr.ReadUInt32(); // 0x0068 actual size of super block + ufs_sb.fs_csmask = eabr.ReadUInt32(); // 0x006C csum block offset + ufs_sb.fs_csshift = eabr.ReadUInt32(); // 0x0070 csum block number + ufs_sb.fs_nindir = eabr.ReadUInt32(); // 0x0074 value of NINDIR + ufs_sb.fs_inopb = eabr.ReadUInt32(); // 0x0078 value of INOPB + ufs_sb.fs_nspf = eabr.ReadUInt32(); // 0x007C value of NSPF + // yet another configuration parameter + ufs_sb.fs_optim = eabr.ReadUInt32(); // 0x0080 optimization preference, see below + // these fields are derived from the hardware + #region Sun + ufs_sb.fs_npsect_sun = eabr.ReadUInt32(); // 0x0084 # sectors/track including spares + #endregion Sun + #region Sunx86 + eabr.BaseStream.Seek(sb_offset + 0x0084, SeekOrigin.Begin); + ufs_sb.fs_state_t_sun86 = eabr.ReadUInt32(); // 0x0084 file system state time stamp + #endregion Sunx86 + #region COMMON + ufs_sb.fs_interleave = eabr.ReadUInt32(); // 0x0088 hardware sector interleave + ufs_sb.fs_trackskew = eabr.ReadUInt32(); // 0x008C sector 0 skew, per track + #endregion COMMON + // a unique id for this filesystem (currently unused and unmaintained) + // In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek + // Neither of those fields is used in the Tahoe code right now but + // there could be problems if they are. + #region COMMON + ufs_sb.fs_id_1 = eabr.ReadUInt32(); // 0x0090 + ufs_sb.fs_id_2 = eabr.ReadUInt32(); // 0x0094 + #endregion COMMON + #region 43BSD + eabr.BaseStream.Seek(sb_offset + 0x0090, SeekOrigin.Begin); + ufs_sb.fs_headswitch_43bsd = eabr.ReadUInt32(); // 0x0090 + ufs_sb.fs_trkseek_43bsd = eabr.ReadUInt32(); // 0x0094 + #endregion 43BSD + #region COMMON + // sizes determined by number of cylinder groups and their sizes + ufs_sb.fs_csaddr = eabr.ReadUInt32(); // 0x0098 blk addr of cyl grp summary area + ufs_sb.fs_cssize = eabr.ReadUInt32(); // 0x009C size of cyl grp summary area + ufs_sb.fs_cgsize = eabr.ReadUInt32(); // 0x00A0 cylinder group size + // these fields are derived from the hardware + ufs_sb.fs_ntrak = eabr.ReadUInt32(); // 0x00A4 tracks per cylinder + ufs_sb.fs_nsect = eabr.ReadUInt32(); // 0x00A8 sectors per track + ufs_sb.fs_spc = eabr.ReadUInt32(); // 0x00AC sectors per cylinder + // this comes from the disk driver partitioning + ufs_sb.fs_ncyl = eabr.ReadUInt32(); // 0x00B0 cylinders in file system + // these fields can be computed from the others + ufs_sb.fs_cpg = eabr.ReadUInt32(); // 0x00B4 cylinders per group + ufs_sb.fs_ipg = eabr.ReadUInt32(); // 0x00B8 inodes per cylinder group + ufs_sb.fs_fpg = eabr.ReadUInt32(); // 0x00BC blocks per group * fs_frag + // this data must be re-computed after crashes + // struct ufs_csum fs_cstotal = eabr.ReadUInt32(); // cylinder summary information + ufs_sb.fs_cstotal_ndir = eabr.ReadUInt32(); // 0x00C0 number of directories + ufs_sb.fs_cstotal_nbfree = eabr.ReadUInt32(); // 0x00C4 number of free blocks + ufs_sb.fs_cstotal_nifree = eabr.ReadUInt32(); // 0x00C8 number of free inodes + ufs_sb.fs_cstotal_nffree = eabr.ReadUInt32(); // 0x00CC number of free frags + // these fields are cleared at mount time + ufs_sb.fs_fmod = eabr.ReadByte(); // 0x00D0 super block modified flag + ufs_sb.fs_clean = eabr.ReadByte(); // 0x00D1 file system is clean flag + ufs_sb.fs_ronly = eabr.ReadByte(); // 0x00D2 mounted read-only flag + ufs_sb.fs_flags = eabr.ReadByte(); // 0x00D3 + #endregion COMMON + #region UFS1 + strings_b = eabr.ReadBytes(512); + ufs_sb.fs_fsmnt_ufs1 = StringHandlers.CToString(strings_b); // 0x00D4, 512 bytes, name mounted on + ufs_sb.fs_cgrotor_ufs1 = eabr.ReadUInt32(); // 0x02D4 last cg searched + ufs_sb.fs_cs_ufs1 = eabr.ReadBytes(124); // 0x02D8, 124 bytes, UInt32s, list of fs_cs info buffers + ufs_sb.fs_maxcluster_ufs1 = eabr.ReadUInt32(); // 0x0354 + ufs_sb.fs_cpc_ufs1 = eabr.ReadUInt32(); // 0x0358 cyl per cycle in postbl + ufs_sb.fs_opostbl_ufs1 = eabr.ReadBytes(256); // 0x035C, 256 bytes, [16][8] matrix of UInt16s, old rotation block list head + #endregion UFS1 + #region UFS2 + eabr.BaseStream.Seek(sb_offset + 0x00D4, SeekOrigin.Begin); + strings_b = eabr.ReadBytes(468); + ufs_sb.fs_fsmnt_ufs2 = StringHandlers.CToString(strings_b); // 0x00D4, 468 bytes, name mounted on + strings_b = eabr.ReadBytes(32); + ufs_sb.fs_volname_ufs2 = StringHandlers.CToString(strings_b); // 0x02A8, 32 bytes, volume name + ufs_sb.fs_swuid_ufs2 = eabr.ReadUInt32(); // 0x02C8 system-wide uid + ufs_sb.fs_pad_ufs2 = eabr.ReadUInt32(); // 0x02D0 due to alignment of fs_swuid + ufs_sb.fs_cgrotor_ufs2 = eabr.ReadUInt32(); // 0x02D4 last cg searched + ufs_sb.fs_ocsp_ufs2 = eabr.ReadBytes(112); // 0x02D8, 112 bytes, UInt32s, list of fs_cs info buffers + ufs_sb.fs_contigdirs_ufs2 = eabr.ReadUInt32(); // 0x0348 # of contiguously allocated dirs + ufs_sb.fs_csp_ufs2 = eabr.ReadUInt32(); // 0x034C cg summary info buffer for fs_cs + ufs_sb.fs_maxcluster_ufs2 = eabr.ReadUInt32(); // 0x0350 + ufs_sb.fs_active_ufs2 = eabr.ReadUInt32(); // 0x0354 used by snapshots to track fs + ufs_sb.fs_old_cpc_ufs2 = eabr.ReadUInt32(); // 0x0358 cyl per cycle in postbl + ufs_sb.fs_maxbsize_ufs2 = eabr.ReadUInt32(); // 0x035C maximum blocking factor permitted + ufs_sb.fs_sparecon64_ufs2 = eabr.ReadBytes(136); // 0x0360, 136 bytes, UInt64s, old rotation block list head + ufs_sb.fs_sblockloc_ufs2 = eabr.ReadUInt64(); // 0x03E8 byte offset of standard superblock + //cylinder summary information*/ + ufs_sb.fs_cstotal_ndir_ufs2 = eabr.ReadUInt64(); // 0x03F0 number of directories + ufs_sb.fs_cstotal_nbfree_ufs2 = eabr.ReadUInt64(); // 0x03F8 number of free blocks + ufs_sb.fs_cstotal_nifree_ufs2 = eabr.ReadUInt64(); // 0x0400 number of free inodes + ufs_sb.fs_cstotal_nffree_ufs2 = eabr.ReadUInt64(); // 0x0408 number of free frags + ufs_sb.fs_cstotal_numclusters_ufs2 = eabr.ReadUInt64(); // 0x0410 number of free clusters + ufs_sb.fs_cstotal_spare0_ufs2 = eabr.ReadUInt64(); // 0x0418 future expansion + ufs_sb.fs_cstotal_spare1_ufs2 = eabr.ReadUInt64(); // 0x0420 future expansion + ufs_sb.fs_cstotal_spare2_ufs2 = eabr.ReadUInt64(); // 0x0428 future expansion + ufs_sb.fs_time_sec_ufs2 = eabr.ReadUInt32(); // 0x0430 last time written + ufs_sb.fs_time_usec_ufs2 = eabr.ReadUInt32(); // 0x0434 last time written + ufs_sb.fs_size_ufs2 = eabr.ReadUInt64(); // 0x0438 number of blocks in fs + ufs_sb.fs_dsize_ufs2 = eabr.ReadUInt64(); // 0x0440 number of data blocks in fs + ufs_sb.fs_csaddr_ufs2 = eabr.ReadUInt64(); // 0x0448 blk addr of cyl grp summary area + ufs_sb.fs_pendingblocks_ufs2 = eabr.ReadUInt64(); // 0x0450 blocks in process of being freed + ufs_sb.fs_pendinginodes_ufs2 = eabr.ReadUInt32(); // 0x0458 inodes in process of being freed + #endregion UFS2 + #region Sun + ufs_sb.fs_sparecon_sun = eabr.ReadBytes(212); // 0x045C, 212 bytes, reserved for future constants + ufs_sb.fs_reclaim_sun = eabr.ReadUInt32(); // 0x0530 + ufs_sb.fs_sparecon2_sun = eabr.ReadUInt32(); // 0x0534 + ufs_sb.fs_state_t_sun = eabr.ReadUInt32(); // 0x0538 file system state time stamp + ufs_sb.fs_qbmask0_sun = eabr.ReadUInt32(); // 0x053C ~usb_bmask + ufs_sb.fs_qbmask1_sun = eabr.ReadUInt32(); // 0x0540 ~usb_bmask + ufs_sb.fs_qfmask0_sun = eabr.ReadUInt32(); // 0x0544 ~usb_fmask + ufs_sb.fs_qfmask1_sun = eabr.ReadUInt32(); // 0x0548 ~usb_fmask + #endregion Sun + #region Sunx86 + eabr.BaseStream.Seek(sb_offset + 0x045C, SeekOrigin.Begin); + ufs_sb.fs_sparecon_sun86 = eabr.ReadBytes(212); // 0x045C, 212 bytes, reserved for future constants + ufs_sb.fs_reclaim_sun86 = eabr.ReadUInt32(); // 0x0530 + ufs_sb.fs_sparecon2_sun86 = eabr.ReadUInt32(); // 0x0534 + ufs_sb.fs_npsect_sun86 = eabr.ReadUInt32(); // 0x0538 # sectors/track including spares + ufs_sb.fs_qbmask0_sun86 = eabr.ReadUInt32(); // 0x053C ~usb_bmask + ufs_sb.fs_qbmask1_sun86 = eabr.ReadUInt32(); // 0x0540 ~usb_bmask + ufs_sb.fs_qfmask0_sun86 = eabr.ReadUInt32(); // 0x0544 ~usb_fmask + ufs_sb.fs_qfmask1_sun86 = eabr.ReadUInt32(); // 0x0548 ~usb_fmask + #endregion Sunx86 + #region 44BSD + eabr.BaseStream.Seek(sb_offset + 0x045C, SeekOrigin.Begin); + ufs_sb.fs_sparecon_44bsd = eabr.ReadBytes(200); // 0x045C, 200 bytes + ufs_sb.fs_contigsumsize_44bsd = eabr.ReadUInt32(); // 0x0524 size of cluster summary array + ufs_sb.fs_maxsymlinklen_44bsd = eabr.ReadUInt32(); // 0x0528 max length of an internal symlink + ufs_sb.fs_inodefmt_44bsd = eabr.ReadUInt32(); // 0x052C format of on-disk inodes + ufs_sb.fs_maxfilesize0_44bsd = eabr.ReadUInt32(); // 0x0530 max representable file size + ufs_sb.fs_maxfilesize1_44bsd = eabr.ReadUInt32(); // 0x0534 max representable file size + ufs_sb.fs_qbmask0_44bsd = eabr.ReadUInt32(); // 0x0538 ~usb_bmask + ufs_sb.fs_qbmask1_44bsd = eabr.ReadUInt32(); // 0x053C ~usb_bmask + ufs_sb.fs_qfmask0_44bsd = eabr.ReadUInt32(); // 0x0540 ~usb_fmask + ufs_sb.fs_qfmask1_44bsd = eabr.ReadUInt32(); // 0x0544 ~usb_fmask + ufs_sb.fs_state_t_44bsd = eabr.ReadUInt32(); // 0x0548 file system state time stamp + #endregion 44BSD + ufs_sb.fs_postblformat = eabr.ReadUInt32(); // 0x054C format of positional layout tables + ufs_sb.fs_nrpos = eabr.ReadUInt32(); // 0x0550 number of rotational positions + ufs_sb.fs_postbloff = eabr.ReadUInt32(); // 0x0554 (__s16) rotation block list head + ufs_sb.fs_rotbloff = eabr.ReadUInt32(); // 0x0558 (__u8) blocks for each rotation + ufs_sb.fs_magic = eabr.ReadUInt32(); // 0x055C magic number + ufs_sb.fs_space = eabr.ReadByte(); // 0x0560 list of blocks for each rotation + if(eabr.BaseStream.Position != (sb_offset + 0x0561) && MainClass.isDebug) + Console.WriteLine("Error reading superblock, out of alignment 0x{0:X8}, expected 0x{1:X8}", eabr.BaseStream.Position, (sb_offset + 0x0561)); + + if(MainClass.isDebug) + { + Console.WriteLine("ufs_sb offset: 0x{0:X8}", sb_offset); + Console.WriteLine("fs_link_42bsd: 0x{0:X8}", ufs_sb.fs_link_42bsd); + Console.WriteLine("fs_state_sun: 0x{0:X8}", ufs_sb.fs_state_sun); + Console.WriteLine("fs_rlink: 0x{0:X8}", ufs_sb.fs_rlink); + Console.WriteLine("fs_sblkno: 0x{0:X8}", ufs_sb.fs_sblkno); + Console.WriteLine("fs_cblkno: 0x{0:X8}", ufs_sb.fs_cblkno); + Console.WriteLine("fs_iblkno: 0x{0:X8}", ufs_sb.fs_iblkno); + Console.WriteLine("fs_dblkno: 0x{0:X8}", ufs_sb.fs_dblkno); + Console.WriteLine("fs_cgoffset: 0x{0:X8}", ufs_sb.fs_cgoffset); + Console.WriteLine("fs_cgmask: 0x{0:X8}", ufs_sb.fs_cgmask); + Console.WriteLine("fs_time_t: 0x{0:X8}", ufs_sb.fs_time_t); + Console.WriteLine("fs_size: 0x{0:X8}", ufs_sb.fs_size); + Console.WriteLine("fs_dsize: 0x{0:X8}", ufs_sb.fs_dsize); + Console.WriteLine("fs_ncg: 0x{0:X8}", ufs_sb.fs_ncg); + Console.WriteLine("fs_bsize: 0x{0:X8}", ufs_sb.fs_bsize); + Console.WriteLine("fs_fsize: 0x{0:X8}", ufs_sb.fs_fsize); + Console.WriteLine("fs_frag: 0x{0:X8}", ufs_sb.fs_frag); + Console.WriteLine("fs_minfree: 0x{0:X8}", ufs_sb.fs_minfree); + Console.WriteLine("fs_rotdelay: 0x{0:X8}", ufs_sb.fs_rotdelay); + Console.WriteLine("fs_rps: 0x{0:X8}", ufs_sb.fs_rps); + Console.WriteLine("fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask); + Console.WriteLine("fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask); + Console.WriteLine("fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift); + Console.WriteLine("fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift); + Console.WriteLine("fs_maxcontig: 0x{0:X8}", ufs_sb.fs_maxcontig); + Console.WriteLine("fs_maxbpg: 0x{0:X8}", ufs_sb.fs_maxbpg); + Console.WriteLine("fs_fragshift: 0x{0:X8}", ufs_sb.fs_fragshift); + Console.WriteLine("fs_fsbtodb: 0x{0:X8}", ufs_sb.fs_fsbtodb); + Console.WriteLine("fs_sbsize: 0x{0:X8}", ufs_sb.fs_sbsize); + Console.WriteLine("fs_csmask: 0x{0:X8}", ufs_sb.fs_csmask); + Console.WriteLine("fs_csshift: 0x{0:X8}", ufs_sb.fs_csshift); + Console.WriteLine("fs_nindir: 0x{0:X8}", ufs_sb.fs_nindir); + Console.WriteLine("fs_inopb: 0x{0:X8}", ufs_sb.fs_inopb); + Console.WriteLine("fs_nspf: 0x{0:X8}", ufs_sb.fs_nspf); + Console.WriteLine("fs_optim: 0x{0:X8}", ufs_sb.fs_optim); + Console.WriteLine("fs_npsect_sun: 0x{0:X8}", ufs_sb.fs_npsect_sun); + Console.WriteLine("fs_state_t_sun86: 0x{0:X8}", ufs_sb.fs_state_t_sun86); + Console.WriteLine("fs_interleave: 0x{0:X8}", ufs_sb.fs_interleave); + Console.WriteLine("fs_trackskew: 0x{0:X8}", ufs_sb.fs_trackskew); + Console.WriteLine("fs_id_1: 0x{0:X8}", ufs_sb.fs_id_1); + Console.WriteLine("fs_id_2: 0x{0:X8}", ufs_sb.fs_id_2); + Console.WriteLine("fs_headswitch_43bsd: 0x{0:X8}", ufs_sb.fs_headswitch_43bsd); + Console.WriteLine("fs_trkseek_43bsd: 0x{0:X8}", ufs_sb.fs_trkseek_43bsd); + Console.WriteLine("fs_csaddr: 0x{0:X8}", ufs_sb.fs_csaddr); + Console.WriteLine("fs_cssize: 0x{0:X8}", ufs_sb.fs_cssize); + Console.WriteLine("fs_cgsize: 0x{0:X8}", ufs_sb.fs_cgsize); + Console.WriteLine("fs_ntrak: 0x{0:X8}", ufs_sb.fs_ntrak); + Console.WriteLine("fs_nsect: 0x{0:X8}", ufs_sb.fs_nsect); + Console.WriteLine("fs_spc: 0x{0:X8}", ufs_sb.fs_spc); + Console.WriteLine("fs_ncyl: 0x{0:X8}", ufs_sb.fs_ncyl); + Console.WriteLine("fs_cpg: 0x{0:X8}", ufs_sb.fs_cpg); + Console.WriteLine("fs_ipg: 0x{0:X8}", ufs_sb.fs_ipg); + Console.WriteLine("fs_fpg: 0x{0:X8}", ufs_sb.fs_fpg); + Console.WriteLine("fs_cstotal_ndir: 0x{0:X8}", ufs_sb.fs_cstotal_ndir); + Console.WriteLine("fs_cstotal_nbfree: 0x{0:X8}", ufs_sb.fs_cstotal_nbfree); + Console.WriteLine("fs_cstotal_nifree: 0x{0:X8}", ufs_sb.fs_cstotal_nifree); + Console.WriteLine("fs_cstotal_nffree: 0x{0:X8}", ufs_sb.fs_cstotal_nffree); + Console.WriteLine("fs_fmod: 0x{0:X2}", ufs_sb.fs_fmod); + Console.WriteLine("fs_clean: 0x{0:X2}", ufs_sb.fs_clean); + Console.WriteLine("fs_ronly: 0x{0:X2}", ufs_sb.fs_ronly); + Console.WriteLine("fs_flags: 0x{0:X2}", ufs_sb.fs_flags); + Console.WriteLine("fs_fsmnt_ufs1: {0}", ufs_sb.fs_fsmnt_ufs1); + Console.WriteLine("fs_cgrotor_ufs1: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs1); + Console.WriteLine("fs_cs_ufs1: 0x{0:X}", ufs_sb.fs_cs_ufs1); + Console.WriteLine("fs_maxcluster_ufs1: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs1); + Console.WriteLine("fs_cpc_ufs1: 0x{0:X8}", ufs_sb.fs_cpc_ufs1); + Console.WriteLine("fs_opostbl_ufs1: 0x{0:X}", ufs_sb.fs_opostbl_ufs1); + Console.WriteLine("fs_fsmnt_ufs2: {0}", ufs_sb.fs_fsmnt_ufs2); + Console.WriteLine("fs_volname_ufs2: {0}", ufs_sb.fs_volname_ufs2); + Console.WriteLine("fs_swuid_ufs2: 0x{0:X16}", ufs_sb.fs_swuid_ufs2); + Console.WriteLine("fs_pad_ufs2: 0x{0:X8}", ufs_sb.fs_pad_ufs2); + Console.WriteLine("fs_cgrotor_ufs2: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs2); + Console.WriteLine("fs_ocsp_ufs2: 0x{0:X}", ufs_sb.fs_ocsp_ufs2); + Console.WriteLine("fs_contigdirs_ufs2: 0x{0:X8}", ufs_sb.fs_contigdirs_ufs2); + Console.WriteLine("fs_csp_ufs2: 0x{0:X8}", ufs_sb.fs_csp_ufs2); + Console.WriteLine("fs_maxcluster_ufs2: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs2); + Console.WriteLine("fs_active_ufs2: 0x{0:X8}", ufs_sb.fs_active_ufs2); + Console.WriteLine("fs_old_cpc_ufs2: 0x{0:X8}", ufs_sb.fs_old_cpc_ufs2); + Console.WriteLine("fs_maxbsize_ufs2: 0x{0:X8}", ufs_sb.fs_maxbsize_ufs2); + Console.WriteLine("fs_sparecon64_ufs2: 0x{0:X}", ufs_sb.fs_sparecon64_ufs2); + Console.WriteLine("fs_sblockloc_ufs2: 0x{0:X16}", ufs_sb.fs_sblockloc_ufs2); + Console.WriteLine("fs_cstotal_ndir_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_ndir_ufs2); + Console.WriteLine("fs_cstotal_nbfree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nbfree_ufs2); + Console.WriteLine("fs_cstotal_nifree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nifree_ufs2); + Console.WriteLine("fs_cstotal_nffree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nffree_ufs2); + Console.WriteLine("fs_cstotal_numclusters_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_numclusters_ufs2); + Console.WriteLine("fs_cstotal_spare0_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare0_ufs2); + Console.WriteLine("fs_cstotal_spare1_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare1_ufs2); + Console.WriteLine("fs_cstotal_spare2_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare2_ufs2); + Console.WriteLine("fs_time_sec_ufs2: 0x{0:X8}", ufs_sb.fs_time_sec_ufs2); + Console.WriteLine("fs_time_usec_ufs2: 0x{0:X8}", ufs_sb.fs_time_usec_ufs2); + Console.WriteLine("fs_size_ufs2: 0x{0:X16}", ufs_sb.fs_size_ufs2); + Console.WriteLine("fs_dsize_ufs2: 0x{0:X16}", ufs_sb.fs_dsize_ufs2); + Console.WriteLine("fs_csaddr_ufs2: 0x{0:X16}", ufs_sb.fs_csaddr_ufs2); + Console.WriteLine("fs_pendingblocks_ufs2: 0x{0:X16}", ufs_sb.fs_pendingblocks_ufs2); + Console.WriteLine("fs_pendinginodes_ufs2: 0x{0:X8}", ufs_sb.fs_pendinginodes_ufs2); + Console.WriteLine("fs_sparecon_sun: 0x{0:X}", ufs_sb.fs_sparecon_sun); + Console.WriteLine("fs_reclaim_sun: 0x{0:X8}", ufs_sb.fs_reclaim_sun); + Console.WriteLine("fs_sparecon2_sun: 0x{0:X8}", ufs_sb.fs_sparecon2_sun); + Console.WriteLine("fs_state_t_sun: 0x{0:X8}", ufs_sb.fs_state_t_sun); + Console.WriteLine("fs_qbmask0_sun: 0x{0:X8}", ufs_sb.fs_qbmask0_sun); + Console.WriteLine("fs_qbmask1_sun: 0x{0:X8}", ufs_sb.fs_qbmask1_sun); + Console.WriteLine("fs_qfmask0_sun: 0x{0:X8}", ufs_sb.fs_qfmask0_sun); + Console.WriteLine("fs_qfmask1_sun: 0x{0:X8}", ufs_sb.fs_qfmask1_sun); + Console.WriteLine("fs_sparecon_sun86: 0x{0:X}", ufs_sb.fs_sparecon_sun86); + Console.WriteLine("fs_reclaim_sun86: 0x{0:X8}", ufs_sb.fs_reclaim_sun86); + Console.WriteLine("fs_sparecon2_sun86: 0x{0:X8}", ufs_sb.fs_sparecon2_sun86); + Console.WriteLine("fs_npsect_sun86: 0x{0:X8}", ufs_sb.fs_npsect_sun86); + Console.WriteLine("fs_qbmask0_sun86: 0x{0:X8}", ufs_sb.fs_qbmask0_sun86); + Console.WriteLine("fs_qbmask1_sun86: 0x{0:X8}", ufs_sb.fs_qbmask1_sun86); + Console.WriteLine("fs_qfmask0_sun86: 0x{0:X8}", ufs_sb.fs_qfmask0_sun86); + Console.WriteLine("fs_qfmask1_sun86: 0x{0:X8}", ufs_sb.fs_qfmask1_sun86); + Console.WriteLine("fs_sparecon_44bsd: 0x{0:X}", ufs_sb.fs_sparecon_44bsd); + Console.WriteLine("fs_contigsumsize_44bsd: 0x{0:X8}", ufs_sb.fs_contigsumsize_44bsd); + Console.WriteLine("fs_maxsymlinklen_44bsd: 0x{0:X8}", ufs_sb.fs_maxsymlinklen_44bsd); + Console.WriteLine("fs_inodefmt_44bsd: 0x{0:X8}", ufs_sb.fs_inodefmt_44bsd); + Console.WriteLine("fs_maxfilesize0_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize0_44bsd); + Console.WriteLine("fs_maxfilesize1_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize1_44bsd); + Console.WriteLine("fs_qbmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask0_44bsd); + Console.WriteLine("fs_qbmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask1_44bsd); + Console.WriteLine("fs_qfmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask0_44bsd); + Console.WriteLine("fs_qfmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask1_44bsd); + Console.WriteLine("fs_state_t_44bsd: 0x{0:X8}", ufs_sb.fs_state_t_44bsd); + Console.WriteLine("fs_postblformat: 0x{0:X8}", ufs_sb.fs_postblformat); + Console.WriteLine("fs_nrpos: 0x{0:X8}", ufs_sb.fs_nrpos); + Console.WriteLine("fs_postbloff: 0x{0:X8}", ufs_sb.fs_postbloff); + Console.WriteLine("fs_rotbloff: 0x{0:X8}", ufs_sb.fs_rotbloff); + Console.WriteLine("fs_magic: 0x{0:X8}", ufs_sb.fs_magic); + Console.WriteLine("fs_space: 0x{0:X2}", ufs_sb.fs_space); + } + + sbInformation.AppendLine("There are a lot of variants of UFS using overlapped values on same fields"); + sbInformation.AppendLine("I will try to guess which one it is, but unless it's UFS2, I may be surely wrong"); + + if(ufs_sb.fs_magic == UFS2_MAGIC) + { + fs_type_ufs2 = true; + } + else + { + UInt32 SunOSEpoch = 0x1A54C580; // We are supposing there cannot be a Sun's fs created before 1/1/1982 00:00:00 + + fs_type_43bsd = true; // There is no way of knowing this is the version, but there is of knowing it is not. + + if(ufs_sb.fs_link_42bsd > 0) + { + fs_type_42bsd = true; // It was used in 4.2BSD + fs_type_43bsd = false; + } + + if(ufs_sb.fs_state_t_sun > SunOSEpoch && DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun) < DateTime.Now) + { + fs_type_42bsd = false; + fs_type_sun = true; + fs_type_43bsd = false; + } + + // This is for sure, as it is shared with a sectors/track with non-x86 SunOS, Epoch is absurdly high for that + if(ufs_sb.fs_state_t_sun86 > SunOSEpoch && DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun) < DateTime.Now) + { + fs_type_42bsd = false; + fs_type_sun86 = true; + fs_type_sun = false; + fs_type_43bsd = false; + } + + if(ufs_sb.fs_cgrotor_ufs1 > 0x00000000 && ufs_sb.fs_cgrotor_ufs1 < 0xFFFFFFFF) + { + fs_type_42bsd = false; + fs_type_sun = false; + fs_type_sun86 = false; + fs_type_ufs = true; + fs_type_43bsd = false; + } + + // 4.3BSD code does not use these fields, they are always set up to 0 + if(ufs_sb.fs_trkseek_43bsd != 0 || ufs_sb.fs_headswitch_43bsd != 0) + fs_type_43bsd = false; + + // This is the only 4.4BSD inode format + if(ufs_sb.fs_inodefmt_44bsd == 2) + fs_type_44bsd = true; + } + + if(fs_type_42bsd) + sbInformation.AppendLine("Guessed as 42BSD FFS"); + if(fs_type_43bsd) + sbInformation.AppendLine("Guessed as 43BSD FFS"); + if(fs_type_44bsd) + sbInformation.AppendLine("Guessed as 44BSD FFS"); + if(fs_type_sun) + sbInformation.AppendLine("Guessed as SunOS FFS"); + if(fs_type_sun86) + sbInformation.AppendLine("Guessed as SunOS/x86 FFS"); + if(fs_type_ufs) + sbInformation.AppendLine("Guessed as UFS"); + if(fs_type_ufs2) + sbInformation.AppendLine("Guessed as UFS2"); + + if(fs_type_42bsd) + sbInformation.AppendFormat("Linked list of filesystems: 0x{0:X8}", ufs_sb.fs_link_42bsd).AppendLine(); + else if(fs_type_sun) + sbInformation.AppendFormat("Filesystem state flag: 0x{0:X8}", ufs_sb.fs_state_sun).AppendLine(); + sbInformation.AppendFormat("Superblock LBA: {0}", ufs_sb.fs_sblkno).AppendLine(); + sbInformation.AppendFormat("Cylinder-block LBA: {0}", ufs_sb.fs_cblkno).AppendLine(); + sbInformation.AppendFormat("inode-block LBA: {0}", ufs_sb.fs_iblkno).AppendLine(); + sbInformation.AppendFormat("First data block LBA: {0}", ufs_sb.fs_dblkno).AppendLine(); + sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_cgoffset).AppendLine(); + sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_t)).AppendLine(); + sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size*ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize*ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} cylinder groups in volume", ufs_sb.fs_ncg).AppendLine(); + sbInformation.AppendFormat("{0} bytes in a basic block", ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} bytes in a frag block", ufs_sb.fs_fsize).AppendLine(); + sbInformation.AppendFormat("{0} frags in a block", ufs_sb.fs_frag).AppendLine(); + sbInformation.AppendFormat("{0}% of blocks must be free", ufs_sb.fs_minfree).AppendLine(); + sbInformation.AppendFormat("{0}ms for optimal next block", ufs_sb.fs_rotdelay).AppendLine(); + sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", ufs_sb.fs_rps, ufs_sb.fs_rps*60).AppendLine(); +/* sbInformation.AppendFormat("fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask).AppendLine(); + sbInformation.AppendFormat("fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask).AppendLine(); + sbInformation.AppendFormat("fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift).AppendLine(); + sbInformation.AppendFormat("fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift).AppendLine();*/ + sbInformation.AppendFormat("{0} contiguous blocks at maximum", ufs_sb.fs_maxcontig).AppendLine(); + sbInformation.AppendFormat("{0} blocks per cylinder group at maximum", ufs_sb.fs_maxbpg).AppendLine(); + sbInformation.AppendFormat("Superblock is {0} bytes", ufs_sb.fs_sbsize).AppendLine(); + sbInformation.AppendFormat("NINDIR: 0x{0:X8}", ufs_sb.fs_nindir).AppendLine(); + sbInformation.AppendFormat("INOPB: 0x{0:X8}", ufs_sb.fs_inopb).AppendLine(); + sbInformation.AppendFormat("NSPF: 0x{0:X8}", ufs_sb.fs_nspf).AppendLine(); + if(ufs_sb.fs_optim == 0) + sbInformation.AppendLine("Filesystem will minimize allocation time"); + else if(ufs_sb.fs_optim == 1) + sbInformation.AppendLine("Filesystem will minimize volume fragmentation"); + else + sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine(); + if(fs_type_sun) + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_npsect_sun).AppendLine(); + else if(fs_type_sun86) + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun86)).AppendLine(); + sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_interleave).AppendLine(); + sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_trackskew).AppendLine(); + if(!fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0) + sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2).AppendLine(); + else if(fs_type_43bsd && ufs_sb.fs_headswitch_43bsd > 0 && ufs_sb.fs_trkseek_43bsd > 0) + { + sbInformation.AppendFormat("{0} µsec for head switch", ufs_sb.fs_headswitch_43bsd).AppendLine(); + sbInformation.AppendFormat("{0} µsec for track-to-track seek", ufs_sb.fs_trkseek_43bsd).AppendLine(); + } + sbInformation.AppendFormat("Cylinder group summary LBA: {0}", ufs_sb.fs_csaddr).AppendLine(); + sbInformation.AppendFormat("{0} bytes in cylinder group summary", ufs_sb.fs_cssize).AppendLine(); + sbInformation.AppendFormat("{0} bytes in cylinder group", ufs_sb.fs_cgsize).AppendLine(); + sbInformation.AppendFormat("{0} tracks/cylinder", ufs_sb.fs_ntrak).AppendLine(); + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_nsect).AppendLine(); + sbInformation.AppendFormat("{0} sectors/cylinder", ufs_sb.fs_spc).AppendLine(); + sbInformation.AppendFormat("{0} cylinder in volume", ufs_sb.fs_ncyl).AppendLine(); + sbInformation.AppendFormat("{0} cylinders/group", ufs_sb.fs_cpg).AppendLine(); + sbInformation.AppendFormat("{0} inodes per cylinder group", ufs_sb.fs_ipg).AppendLine(); + sbInformation.AppendFormat("{0} blocks per group", ufs_sb.fs_fpg/ufs_sb.fs_frag).AppendLine(); + sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal_ndir).AppendLine(); + sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree, ufs_sb.fs_cstotal_nbfree*ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree).AppendLine(); + sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree).AppendLine(); + if(ufs_sb.fs_fmod == 1) + sbInformation.AppendLine("Superblock is under modification"); + if(ufs_sb.fs_clean == 1) + sbInformation.AppendLine("Volume is clean"); + if(ufs_sb.fs_ronly == 1) + sbInformation.AppendLine("Volume is read-only"); + sbInformation.AppendFormat("Volume flags: 0x{0:X2}", ufs_sb.fs_flags).AppendLine(); + if(fs_type_ufs) + { + sbInformation.AppendFormat("Volume last mounted on \"{0}\"", ufs_sb.fs_fsmnt_ufs1).AppendLine(); + sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor_ufs1).AppendLine(); + } + else if(fs_type_ufs2) + { + sbInformation.AppendFormat("Volume last mounted on \"{0}\"", ufs_sb.fs_fsmnt_ufs2).AppendLine(); + sbInformation.AppendFormat("Volume name: \"{0}\"", ufs_sb.fs_volname_ufs2).AppendLine(); + sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid_ufs2).AppendLine(); + sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} contiguously allocated directories", ufs_sb.fs_contigdirs_ufs2).AppendLine(); + sbInformation.AppendFormat("Standard superblock LBA: {0}", ufs_sb.fs_sblockloc_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal_ndir_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree_ufs2, ufs_sb.fs_cstotal_nbfree_ufs2*ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal_numclusters_ufs2).AppendLine(); + sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_sec_ufs2)).AppendLine(); + sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size_ufs2, ufs_sb.fs_size_ufs2*ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize_ufs2, ufs_sb.fs_dsize_ufs2*ufs_sb.fs_bsize).AppendLine(); + sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", ufs_sb.fs_csaddr_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} blocks pending of being freed", ufs_sb.fs_pendingblocks_ufs2).AppendLine(); + sbInformation.AppendFormat("{0} inodes pending of being freed", ufs_sb.fs_pendinginodes_ufs2).AppendLine(); + } + if(fs_type_sun) + { + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun)).AppendLine(); + } + else if(fs_type_sun86) + { + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_npsect_sun86).AppendLine(); + } + else if(fs_type_44bsd) + { + sbInformation.AppendFormat("{0} blocks on cluster summary array", ufs_sb.fs_contigsumsize_44bsd).AppendLine(); + sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", ufs_sb.fs_maxsymlinklen_44bsd).AppendLine(); + ulong bsd44_maxfilesize = ((ulong)ufs_sb.fs_maxfilesize0_44bsd)*0x100000000 + ufs_sb.fs_maxfilesize1_44bsd; + sbInformation.AppendFormat("A file can be {0} bytes at max", bsd44_maxfilesize).AppendLine(); + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_44bsd)).AppendLine(); + } + sbInformation.AppendFormat("{0} rotational positions", ufs_sb.fs_nrpos).AppendLine(); + sbInformation.AppendFormat("{0} blocks per rotation", ufs_sb.fs_rotbloff).AppendLine(); + + information = sbInformation.ToString(); + } + + private const int block_size = 8192; + + // As specified in FreeBSD source code, FFS/UFS can start in any of four places + private const long sb_start_floppy = 0; // For floppies, start at offset 0 + private const long sb_start_ufs1 = block_size; // For normal devices, start at offset 8192 + private const long sb_start_ufs2 = block_size*8; // For UFS2, start at offset 65536 + private const long sb_start_piggy = block_size*32; // For piggy devices (?), start at offset 262144 + + // MAGICs + private const UInt32 UFS_MAGIC = 0x00011954; // UFS magic + private const UInt32 UFS_MAGIC_BW = 0x0f242697; // BorderWare UFS + private const UInt32 UFS2_MAGIC = 0x19540119; // UFS2 magic + private const UInt32 UFS_CIGAM = 0x54190100; // byteswapped + private const UInt32 UFS_BAD_MAGIC = 0x19960408; // Incomplete newfs + + // On-disk superblock is quite a mixture of all the UFS/FFS variants + // There is no clear way to detect which one is correct + // And as C# does not support unions this struct will clearly appear quite dirty :p + // To clean up things a little, comment starts with relative superblock offset of field + public struct UFSSuperBlock + { + #region 42BSD + public UInt32 fs_link_42bsd; // 0x0000 linked list of file systems + #endregion + #region Sun + public UInt32 fs_state_sun; // 0x0000 file system state flag + #endregion + #region COMMON + public UInt32 fs_rlink; // 0x0004 used for incore super blocks + public UInt32 fs_sblkno; // 0x0008 addr of super-block in filesys + public UInt32 fs_cblkno; // 0x000C offset of cyl-block in filesys + public UInt32 fs_iblkno; // 0x0010 offset of inode-blocks in filesys + public UInt32 fs_dblkno; // 0x0014 offset of first data after cg + public UInt32 fs_cgoffset; // 0x0018 cylinder group offset in cylinder + public UInt32 fs_cgmask; // 0x001C used to calc mod fs_ntrak + public UInt32 fs_time_t; // 0x0020 last time written -- time_t + public UInt32 fs_size; // 0x0024 number of blocks in fs + public UInt32 fs_dsize; // 0x0028 number of data blocks in fs + public UInt32 fs_ncg; // 0x002C number of cylinder groups + public UInt32 fs_bsize; // 0x0030 size of basic blocks in fs + public UInt32 fs_fsize; // 0x0034 size of frag blocks in fs + public UInt32 fs_frag; // 0x0038 number of frags in a block in fs + // these are configuration parameters + public UInt32 fs_minfree; // 0x003C minimum percentage of free blocks + public UInt32 fs_rotdelay; // 0x0040 num of ms for optimal next block + public UInt32 fs_rps; // 0x0044 disk revolutions per second + // these fields can be computed from the others + public UInt32 fs_bmask; // 0x0048 ``blkoff'' calc of blk offsets + public UInt32 fs_fmask; // 0x004C ``fragoff'' calc of frag offsets + public UInt32 fs_bshift; // 0x0050 ``lblkno'' calc of logical blkno + public UInt32 fs_fshift; // 0x0054 ``numfrags'' calc number of frags + // these are configuration parameters + public UInt32 fs_maxcontig; // 0x0058 max number of contiguous blks + public UInt32 fs_maxbpg; // 0x005C max number of blks per cyl group + // these fields can be computed from the others + public UInt32 fs_fragshift; // 0x0060 block to frag shift + public UInt32 fs_fsbtodb; // 0x0064 fsbtodb and dbtofsb shift constant + public UInt32 fs_sbsize; // 0x0068 actual size of super block + public UInt32 fs_csmask; // 0x006C csum block offset + public UInt32 fs_csshift; // 0x0070 csum block number + public UInt32 fs_nindir; // 0x0074 value of NINDIR + public UInt32 fs_inopb; // 0x0078 value of INOPB + public UInt32 fs_nspf; // 0x007C value of NSPF + // yet another configuration parameter + public UInt32 fs_optim; // 0x0080 optimization preference, see below + #endregion COMMON + // these fields are derived from the hardware + #region Sun + public UInt32 fs_npsect_sun; // 0x0084 # sectors/track including spares + #endregion Sun + #region Sunx86 + public UInt32 fs_state_t_sun86; // 0x0084 file system state time stamp + #endregion Sunx86 + #region COMMON + public UInt32 fs_interleave; // 0x0088 hardware sector interleave + public UInt32 fs_trackskew; // 0x008C sector 0 skew, per track + #endregion COMMON + // a unique id for this filesystem (currently unused and unmaintained) + // In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek + // Neither of those fields is used in the Tahoe code right now but + // there could be problems if they are. + #region COMMON + public UInt32 fs_id_1; // 0x0090 + public UInt32 fs_id_2; // 0x0094 + #endregion COMMON + #region 43BSD + public UInt32 fs_headswitch_43bsd; // 0x0090 head switch time, usec + public UInt32 fs_trkseek_43bsd; // 0x0094 track-to-track seek, usec + #endregion 43BSD + #region COMMON + // sizes determined by number of cylinder groups and their sizes + public UInt32 fs_csaddr; // 0x0098 blk addr of cyl grp summary area + public UInt32 fs_cssize; // 0x009C size of cyl grp summary area + public UInt32 fs_cgsize; // 0x00A0 cylinder group size + // these fields are derived from the hardware + public UInt32 fs_ntrak; // 0x00A4 tracks per cylinder + public UInt32 fs_nsect; // 0x00A8 sectors per track + public UInt32 fs_spc; // 0x00AC sectors per cylinder + // this comes from the disk driver partitioning + public UInt32 fs_ncyl; // 0x00B0 cylinders in file system + // these fields can be computed from the others + public UInt32 fs_cpg; // 0x00B4 cylinders per group + public UInt32 fs_ipg; // 0x00B8 inodes per cylinder group + public UInt32 fs_fpg; // 0x00BC blocks per group * fs_frag + // this data must be re-computed after crashes + // struct ufs_csum fs_cstotal; // cylinder summary information + public UInt32 fs_cstotal_ndir; // 0x00C0 number of directories + public UInt32 fs_cstotal_nbfree; // 0x00C4 number of free blocks + public UInt32 fs_cstotal_nifree; // 0x00C8 number of free inodes + public UInt32 fs_cstotal_nffree; // 0x00CC number of free frags + // these fields are cleared at mount time + public byte fs_fmod; // 0x00D0 super block modified flag + public byte fs_clean; // 0x00D1 file system is clean flag + public byte fs_ronly; // 0x00D2 mounted read-only flag + public byte fs_flags; // 0x00D3 + #endregion common + #region UFS1 + public string fs_fsmnt_ufs1; // 0x00D4, 512 bytes, name mounted on + public UInt32 fs_cgrotor_ufs1; // 0x02D4 last cg searched + public byte[] fs_cs_ufs1; // 0x02D8, 124 bytes, UInt32s, list of fs_cs info buffers + public UInt32 fs_maxcluster_ufs1; // 0x0354 + public UInt32 fs_cpc_ufs1; // 0x0358 cyl per cycle in postbl + public byte[] fs_opostbl_ufs1; // 0x035C, 256 bytes, [16][8] matrix of UInt16s, old rotation block list head + #endregion UFS1 + #region UFS2 + public string fs_fsmnt_ufs2; // 0x00D4, 468 bytes, name mounted on + public string fs_volname_ufs2; // 0x02A8, 32 bytes, volume name + public UInt64 fs_swuid_ufs2; // 0x02C8 system-wide uid + public UInt32 fs_pad_ufs2; // 0x02D0 due to alignment of fs_swuid + public UInt32 fs_cgrotor_ufs2; // 0x02D4 last cg searched + public byte[] fs_ocsp_ufs2; // 0x02D8, 112 bytes, UInt32s, list of fs_cs info buffers + public UInt32 fs_contigdirs_ufs2; // 0x0348 # of contiguously allocated dirs + public UInt32 fs_csp_ufs2; // 0x034C cg summary info buffer for fs_cs + public UInt32 fs_maxcluster_ufs2; // 0x0350 + public UInt32 fs_active_ufs2; // 0x0354 used by snapshots to track fs + public UInt32 fs_old_cpc_ufs2; // 0x0358 cyl per cycle in postbl + public UInt32 fs_maxbsize_ufs2; // 0x035C maximum blocking factor permitted + public byte[] fs_sparecon64_ufs2; // 0x0360, 136 bytes, UInt64s, old rotation block list head + public UInt64 fs_sblockloc_ufs2; // 0x03E8 byte offset of standard superblock + //cylinder summary information*/ + public UInt64 fs_cstotal_ndir_ufs2; // 0x03F0 number of directories + public UInt64 fs_cstotal_nbfree_ufs2; // 0x03F8 number of free blocks + public UInt64 fs_cstotal_nifree_ufs2; // 0x0400 number of free inodes + public UInt64 fs_cstotal_nffree_ufs2; // 0x0408 number of free frags + public UInt64 fs_cstotal_numclusters_ufs2; // 0x0410 number of free clusters + public UInt64 fs_cstotal_spare0_ufs2; // 0x0418 future expansion + public UInt64 fs_cstotal_spare1_ufs2; // 0x0420 future expansion + public UInt64 fs_cstotal_spare2_ufs2; // 0x0428 future expansion + public UInt32 fs_time_sec_ufs2; // 0x0430 last time written + public UInt32 fs_time_usec_ufs2; // 0x0434 last time written + public UInt64 fs_size_ufs2; // 0x0438 number of blocks in fs + public UInt64 fs_dsize_ufs2; // 0x0440 number of data blocks in fs + public UInt64 fs_csaddr_ufs2; // 0x0448 blk addr of cyl grp summary area + public UInt64 fs_pendingblocks_ufs2; // 0x0450 blocks in process of being freed + public UInt32 fs_pendinginodes_ufs2; // 0x0458 inodes in process of being freed + #endregion UFS2 + #region Sun + public byte[] fs_sparecon_sun; // 0x045C, 212 bytes, reserved for future constants + public UInt32 fs_reclaim_sun; // 0x0530 + public UInt32 fs_sparecon2_sun; // 0x0534 + public UInt32 fs_state_t_sun; // 0x0538 file system state time stamp + public UInt32 fs_qbmask0_sun; // 0x053C ~usb_bmask + public UInt32 fs_qbmask1_sun; // 0x0540 ~usb_bmask + public UInt32 fs_qfmask0_sun; // 0x0544 ~usb_fmask + public UInt32 fs_qfmask1_sun; // 0x0548 ~usb_fmask + #endregion Sun + #region Sunx86 + public byte[] fs_sparecon_sun86; // 0x045C, 212 bytes, reserved for future constants + public UInt32 fs_reclaim_sun86; // 0x0530 + public UInt32 fs_sparecon2_sun86; // 0x0534 + public UInt32 fs_npsect_sun86; // 0x0538 # sectors/track including spares + public UInt32 fs_qbmask0_sun86; // 0x053C ~usb_bmask + public UInt32 fs_qbmask1_sun86; // 0x0540 ~usb_bmask + public UInt32 fs_qfmask0_sun86; // 0x0544 ~usb_fmask + public UInt32 fs_qfmask1_sun86; // 0x0548 ~usb_fmask + #endregion Sunx86 + #region 44BSD + public byte[] fs_sparecon_44bsd; // 0x045C, 200 bytes + public UInt32 fs_contigsumsize_44bsd; // 0x0524 size of cluster summary array + public UInt32 fs_maxsymlinklen_44bsd; // 0x0528 max length of an internal symlink + public UInt32 fs_inodefmt_44bsd; // 0x052C format of on-disk inodes + public UInt32 fs_maxfilesize0_44bsd; // 0x0530 max representable file size + public UInt32 fs_maxfilesize1_44bsd; // 0x0534 max representable file size + public UInt32 fs_qbmask0_44bsd; // 0x0538 ~usb_bmask + public UInt32 fs_qbmask1_44bsd; // 0x053C ~usb_bmask + public UInt32 fs_qfmask0_44bsd; // 0x0540 ~usb_fmask + public UInt32 fs_qfmask1_44bsd; // 0x0544 ~usb_fmask + public UInt32 fs_state_t_44bsd; // 0x0548 file system state time stamp + #endregion 44BSD + public UInt32 fs_postblformat; // 0x054C format of positional layout tables + public UInt32 fs_nrpos; // 0x0550 number of rotational positions + public UInt32 fs_postbloff; // 0x0554 (__s16) rotation block list head + public UInt32 fs_rotbloff; // 0x0558 (__u8) blocks for each rotation + public UInt32 fs_magic; // 0x055C magic number + public byte fs_space; // 0x0560 list of blocks for each rotation + // 0x0561 } } -} - -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/Packages.mdproj b/Packages.mdproj index 9ea6e64c3..6b41f032b 100644 --- a/Packages.mdproj +++ b/Packages.mdproj @@ -1 +1,45 @@ - PackagingProject 9.0.21022 2.0 {8996EF59-09B9-4920-A3DE-2F8EA2EBBCFF} \ No newline at end of file + + + + PackagingProject + 9.0.21022 + 2.0 + {8996EF59-09B9-4920-A3DE-2F8EA2EBBCFF} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file