From 5ab1896b321577b741d6b04708e13f533c8beb75 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 15 Jul 2017 01:39:48 +0100 Subject: [PATCH] Moved superblock to a sequential do-it-all structure, and use marshalling with it. --- DiscImageChef.Filesystems/FFS.cs | 1051 ++++++++++-------------------- 1 file changed, 342 insertions(+), 709 deletions(-) diff --git a/DiscImageChef.Filesystems/FFS.cs b/DiscImageChef.Filesystems/FFS.cs index 473969890..cf85582cc 100644 --- a/DiscImageChef.Filesystems/FFS.cs +++ b/DiscImageChef.Filesystems/FFS.cs @@ -34,6 +34,9 @@ using System; using System.Text; using System.Collections.Generic; using DiscImageChef.Console; +using ufs_daddr_t = System.Int32; +using time_t = System.Int32; +using System.Runtime.InteropServices; namespace DiscImageChef.Filesystems { @@ -227,207 +230,38 @@ namespace DiscImageChef.Filesystems break; } - BigEndianBitConverter.IsLittleEndian = magic != UFS_CIGAM; // 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; ufs_sb_sectors = imagePlugin.ReadSectors(sb_offset, sb_size_in_sectors); - ufs_sb.fs_link_42bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); /// 0x0000 - ufs_sb.fs_state_sun = ufs_sb.fs_link_42bsd; - ufs_sb.fs_rlink = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0004); /// 0x0004 UNUSED - ufs_sb.fs_sblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0008); /// 0x0008 addr of super-block in filesys - ufs_sb.fs_cblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x000C); /// 0x000C offset of cyl-block in filesys - ufs_sb.fs_iblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0010); /// 0x0010 offset of inode-blocks in filesys - ufs_sb.fs_dblkno = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0014); /// 0x0014 offset of first data after cg - ufs_sb.fs_cgoffset = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0018); /// 0x0018 cylinder group offset in cylinder - ufs_sb.fs_cgmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x001C); /// 0x001C used to calc mod fs_ntrak - ufs_sb.fs_time_t = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0020); /// 0x0020 last time written -- time_t - ufs_sb.fs_size = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0024); /// 0x0024 number of blocks in fs - ufs_sb.fs_dsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0028); /// 0x0028 number of data blocks in fs - ufs_sb.fs_ncg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x002C); /// 0x002C number of cylinder groups - ufs_sb.fs_bsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0030); /// 0x0030 size of basic blocks in fs - ufs_sb.fs_fsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0034); /// 0x0034 size of frag blocks in fs - ufs_sb.fs_frag = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0038); /// 0x0038 number of frags in a block in fs - // these are configuration parameters - ufs_sb.fs_minfree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x003C); /// 0x003C minimum percentage of free blocks - ufs_sb.fs_rotdelay = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0040); /// 0x0040 num of ms for optimal next block - ufs_sb.fs_rps = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0044); /// 0x0044 disk revolutions per second - // these fields can be computed from the others - ufs_sb.fs_bmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0048); /// 0x0048 ``blkoff'' calc of blk offsets - ufs_sb.fs_fmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x004C); /// 0x004C ``fragoff'' calc of frag offsets - ufs_sb.fs_bshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0050); /// 0x0050 ``lblkno'' calc of logical blkno - ufs_sb.fs_fshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0054); /// 0x0054 ``numfrags'' calc number of frags - // these are configuration parameters - ufs_sb.fs_maxcontig = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0058); /// 0x0058 max number of contiguous blks - ufs_sb.fs_maxbpg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x005C); /// 0x005C max number of blks per cyl group - // these fields can be computed from the others - ufs_sb.fs_fragshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0060); /// 0x0060 block to frag shift - ufs_sb.fs_fsbtodb = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0064); /// 0x0064 fsbtodb and dbtofsb shift constant - ufs_sb.fs_sbsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0068); /// 0x0068 actual size of super block - ufs_sb.fs_csmask = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x006C); /// 0x006C csum block offset - ufs_sb.fs_csshift = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0070); /// 0x0070 csum block number - ufs_sb.fs_nindir = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0074); /// 0x0074 value of NINDIR - ufs_sb.fs_inopb = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0078); /// 0x0078 value of INOPB - ufs_sb.fs_nspf = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x007C); /// 0x007C value of NSPF - // yet another configuration parameter - ufs_sb.fs_optim = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0080); /// 0x0080 optimization preference, see below - // these fields are derived from the hardware - #region Sun - ufs_sb.fs_npsect_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0084); /// 0x0084 # sectors/track including spares - #endregion Sun - #region Sunx86 - ufs_sb.fs_state_t_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0084); /// 0x0084 file system state time stamp - #endregion Sunx86 - #region COMMON - ufs_sb.fs_interleave = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0088); /// 0x0088 hardware sector interleave - ufs_sb.fs_trackskew = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x008C); /// 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 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0090); /// 0x0090 - ufs_sb.fs_id_2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0094); /// 0x0094 - #endregion COMMON - #region 43BSD - ufs_sb.fs_headswitch_43bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0090); /// 0x0090 - ufs_sb.fs_trkseek_43bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0094); /// 0x0094 - #endregion 43BSD - #region COMMON - // sizes determined by number of cylinder groups and their sizes - ufs_sb.fs_csaddr = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0098); /// 0x0098 blk addr of cyl grp summary area - ufs_sb.fs_cssize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x009C); /// 0x009C size of cyl grp summary area - ufs_sb.fs_cgsize = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00A0); /// 0x00A0 cylinder group size - // these fields are derived from the hardware - ufs_sb.fs_ntrak = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00A4); /// 0x00A4 tracks per cylinder - ufs_sb.fs_nsect = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00A8); /// 0x00A8 sectors per track - ufs_sb.fs_spc = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00AC); /// 0x00AC sectors per cylinder - // this comes from the disk driver partitioning - ufs_sb.fs_ncyl = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00B0); /// 0x00B0 cylinders in file system - // these fields can be computed from the others - ufs_sb.fs_cpg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00B4); /// 0x00B4 cylinders per group - ufs_sb.fs_ipg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00B8); /// 0x00B8 inodes per cylinder group - ufs_sb.fs_fpg = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00BC); /// 0x00BC blocks per group * fs_frag - // this data must be re-computed after crashes - // struct ufs_csum fs_cstotal = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); // cylinder summary information - ufs_sb.fs_cstotal_ndir = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00C0); /// 0x00C0 number of directories - ufs_sb.fs_cstotal_nbfree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00C4); /// 0x00C4 number of free blocks - ufs_sb.fs_cstotal_nifree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00C8); /// 0x00C8 number of free inodes - ufs_sb.fs_cstotal_nffree = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x00CC); /// 0x00CC number of free frags - // these fields are cleared at mount time - ufs_sb.fs_fmod = ufs_sb_sectors[0x00D0]; /// 0x00D0 super block modified flag - ufs_sb.fs_clean = ufs_sb_sectors[0x00D1]; /// 0x00D1 file system is clean flag - ufs_sb.fs_ronly = ufs_sb_sectors[0x00D2]; /// 0x00D2 mounted read-only flag - ufs_sb.fs_flags = ufs_sb_sectors[0x00D3]; /// 0x00D3 - #endregion COMMON - #region UFS1 - strings_b = new byte[512]; - Array.Copy(ufs_sb_sectors, 0x00D4, strings_b, 0, 512); - ufs_sb.fs_fsmnt_ufs1 = StringHandlers.CToString(strings_b, CurrentEncoding); /// 0x00D4, 512 bytes, name mounted on - ufs_sb.fs_cgrotor_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0000); /// 0x02D4 last cg searched - ufs_sb.fs_cs_ufs1 = new byte[124]; - Array.Copy(ufs_sb_sectors, 0x02D8, ufs_sb.fs_cs_ufs1, 0, 124); /// 0x02D8, 124 bytes, uints, list of fs_cs info buffers - ufs_sb.fs_maxcluster_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0354); /// 0x0354 - ufs_sb.fs_cpc_ufs1 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0358); /// 0x0358 cyl per cycle in postbl - ufs_sb.fs_opostbl_ufs1 = new byte[256]; - Array.Copy(ufs_sb_sectors, 0x035C, ufs_sb.fs_opostbl_ufs1, 0, 256); /// 0x035C, 256 bytes, [16][8] matrix of ushorts, old rotation block list head - #endregion UFS1 - #region UFS2 - strings_b = new byte[468]; - Array.Copy(ufs_sb_sectors, 0x00D4, strings_b, 0, 468); - ufs_sb.fs_fsmnt_ufs2 = StringHandlers.CToString(strings_b, CurrentEncoding); /// 0x00D4, 468 bytes, name mounted on - strings_b = new byte[32]; - Array.Copy(ufs_sb_sectors, 0x02A8, strings_b, 0, 32); - ufs_sb.fs_volname_ufs2 = StringHandlers.CToString(strings_b, CurrentEncoding); /// 0x02A8, 32 bytes, volume name - ufs_sb.fs_swuid_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02C8); /// 0x02C8 system-wide uid - ufs_sb.fs_pad_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02D0); /// 0x02D0 due to alignment of fs_swuid - ufs_sb.fs_cgrotor_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x02D4); /// 0x02D4 last cg searched - ufs_sb.fs_ocsp_ufs2 = new byte[112]; - Array.Copy(ufs_sb_sectors, 0x02D8, ufs_sb.fs_ocsp_ufs2, 0, 112); /// 0x02D8, 112 bytes, uints, list of fs_cs info buffers - ufs_sb.fs_contigdirs_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0348); /// 0x0348 # of contiguously allocated dirs - ufs_sb.fs_csp_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x034C); /// 0x034C cg summary info buffer for fs_cs - ufs_sb.fs_maxcluster_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0350); /// 0x0350 - ufs_sb.fs_active_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0354); /// 0x0354 used by snapshots to track fs - ufs_sb.fs_old_cpc_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0358); /// 0x0358 cyl per cycle in postbl - ufs_sb.fs_maxbsize_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x035C); /// 0x035C maximum blocking factor permitted - ufs_sb.fs_sparecon64_ufs2 = new byte[136]; - Array.Copy(ufs_sb_sectors, 0x0360, ufs_sb.fs_sparecon64_ufs2, 0, 136); /// 0x0360, 136 bytes, ulongs, old rotation block list head - ufs_sb.fs_sblockloc_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x03E8); /// 0x03E8 byte offset of standard superblock - //cylinder summary information*/ - ufs_sb.fs_cstotal_ndir_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x03F0); /// 0x03F0 number of directories - ufs_sb.fs_cstotal_nbfree_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x03F8); /// 0x03F8 number of free blocks - ufs_sb.fs_cstotal_nifree_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0400); /// 0x0400 number of free inodes - ufs_sb.fs_cstotal_nffree_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0408); /// 0x0408 number of free frags - ufs_sb.fs_cstotal_numclusters_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0410); /// 0x0410 number of free clusters - ufs_sb.fs_cstotal_spare0_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0418); /// 0x0418 future expansion - ufs_sb.fs_cstotal_spare1_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0420); /// 0x0420 future expansion - ufs_sb.fs_cstotal_spare2_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0428); /// 0x0428 future expansion - ufs_sb.fs_time_sec_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0430); /// 0x0430 last time written - ufs_sb.fs_time_usec_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0434); /// 0x0434 last time written - ufs_sb.fs_size_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0438); /// 0x0438 number of blocks in fs - ufs_sb.fs_dsize_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0440); /// 0x0440 number of data blocks in fs - ufs_sb.fs_csaddr_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0448); /// 0x0448 blk addr of cyl grp summary area - ufs_sb.fs_pendingblocks_ufs2 = BigEndianBitConverter.ToUInt64(ufs_sb_sectors, 0x0450); /// 0x0450 blocks in process of being freed - ufs_sb.fs_pendinginodes_ufs2 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0458); /// 0x0458 inodes in process of being freed - #endregion UFS2 - #region Sun - ufs_sb.fs_sparecon_sun = new byte[212]; - Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_sun, 0, 212); /// 0x045C, 212 bytes, reserved for future constants - ufs_sb.fs_reclaim_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); /// 0x0530 - ufs_sb.fs_sparecon2_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); /// 0x0534 - ufs_sb.fs_state_t_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0538); /// 0x0538 file system state time stamp - ufs_sb.fs_qbmask0_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x053C); /// 0x053C ~usb_bmask - ufs_sb.fs_qbmask1_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0540); /// 0x0540 ~usb_bmask - ufs_sb.fs_qfmask0_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0544); /// 0x0544 ~usb_fmask - ufs_sb.fs_qfmask1_sun = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); /// 0x0548 ~usb_fmask - #endregion Sun - #region Sunx86 - ufs_sb.fs_sparecon_sun86 = new byte[212]; - Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_sun86, 0, 212); /// 0x045C, 212 bytes, reserved for future constants - ufs_sb.fs_reclaim_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); /// 0x0530 - ufs_sb.fs_sparecon2_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); /// 0x0534 - ufs_sb.fs_npsect_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0538); /// 0x0538 # sectors/track including spares - ufs_sb.fs_qbmask0_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x053C); /// 0x053C ~usb_bmask - ufs_sb.fs_qbmask1_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0540); /// 0x0540 ~usb_bmask - ufs_sb.fs_qfmask0_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0544); /// 0x0544 ~usb_fmask - ufs_sb.fs_qfmask1_sun86 = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); /// 0x0548 ~usb_fmask - #endregion Sunx86 - #region 44BSD - ufs_sb.fs_sparecon_44bsd = new byte[200]; - Array.Copy(ufs_sb_sectors, 0x045C, ufs_sb.fs_sparecon_44bsd, 0, 200); /// 0x045C, 200 bytes - ufs_sb.fs_contigsumsize_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0524); /// 0x0524 size of cluster summary array - ufs_sb.fs_maxsymlinklen_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0528); /// 0x0528 max length of an internal symlink - ufs_sb.fs_inodefmt_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x052C); /// 0x052C format of on-disk inodes - ufs_sb.fs_maxfilesize0_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0530); /// 0x0530 max representable file size - ufs_sb.fs_maxfilesize1_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0534); /// 0x0534 max representable file size - ufs_sb.fs_qbmask0_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0538); /// 0x0538 ~usb_bmask - ufs_sb.fs_qbmask1_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x053C); /// 0x053C ~usb_bmask - ufs_sb.fs_qfmask0_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0540); /// 0x0540 ~usb_fmask - ufs_sb.fs_qfmask1_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0544); /// 0x0544 ~usb_fmask - ufs_sb.fs_state_t_44bsd = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0548); /// 0x0548 file system state time stamp - #endregion 44BSD - ufs_sb.fs_postblformat = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x054C); /// 0x054C format of positional layout tables - ufs_sb.fs_nrpos = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0550); /// 0x0550 number of rotational positions - ufs_sb.fs_postbloff = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0554); /// 0x0554 (__s16) rotation block list head - ufs_sb.fs_rotbloff = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x0558); /// 0x0558 (__u8) blocks for each rotation - ufs_sb.fs_magic = BigEndianBitConverter.ToUInt32(ufs_sb_sectors, 0x055C); /// 0x055C magic number - ufs_sb.fs_space = ufs_sb_sectors[0x0560]; /// 0x0560 list of blocks for each rotation + IntPtr sbPtr = Marshal.AllocHGlobal(ufs_sb_sectors.Length); + Marshal.Copy(ufs_sb_sectors, 0, sbPtr, ufs_sb_sectors.Length); + UFSSuperBlock ufs_sb = (UFSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(UFSSuperBlock)); + Marshal.FreeHGlobal(sbPtr); + + UFSSuperBlock bs_sfu = BigEndianMarshal.ByteArrayToStructureBigEndian(ufs_sb_sectors); + if(bs_sfu.fs_magic == UFS_MAGIC && ufs_sb.fs_magic == UFS_CIGAM) + { + ufs_sb = bs_sfu; + ufs_sb.fs_old_cstotal.cs_nbfree = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nbfree); + ufs_sb.fs_old_cstotal.cs_ndir = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_ndir); + ufs_sb.fs_old_cstotal.cs_nffree = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nffree); + ufs_sb.fs_old_cstotal.cs_nifree = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nifree); + ufs_sb.fs_cstotal.cs_numclusters = Swapping.Swap(ufs_sb.fs_cstotal.cs_numclusters); + ufs_sb.fs_cstotal.cs_nbfree = Swapping.Swap(ufs_sb.fs_cstotal.cs_nbfree); + ufs_sb.fs_cstotal.cs_ndir = Swapping.Swap(ufs_sb.fs_cstotal.cs_ndir); + ufs_sb.fs_cstotal.cs_nffree = Swapping.Swap(ufs_sb.fs_cstotal.cs_nffree); + ufs_sb.fs_cstotal.cs_nifree = Swapping.Swap(ufs_sb.fs_cstotal.cs_nifree); + ufs_sb.fs_cstotal.cs_spare[0] = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[0]); + ufs_sb.fs_cstotal.cs_spare[1] = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[1]); + ufs_sb.fs_cstotal.cs_spare[2] = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[2]); + } DicConsole.DebugWriteLine("FFS plugin", "ufs_sb offset: 0x{0:X8}", sb_offset); - DicConsole.DebugWriteLine("FFS plugin", "fs_link_42bsd: 0x{0:X8}", ufs_sb.fs_link_42bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_state_sun: 0x{0:X8}", ufs_sb.fs_state_sun); DicConsole.DebugWriteLine("FFS plugin", "fs_rlink: 0x{0:X8}", ufs_sb.fs_rlink); DicConsole.DebugWriteLine("FFS plugin", "fs_sblkno: 0x{0:X8}", ufs_sb.fs_sblkno); DicConsole.DebugWriteLine("FFS plugin", "fs_cblkno: 0x{0:X8}", ufs_sb.fs_cblkno); DicConsole.DebugWriteLine("FFS plugin", "fs_iblkno: 0x{0:X8}", ufs_sb.fs_iblkno); DicConsole.DebugWriteLine("FFS plugin", "fs_dblkno: 0x{0:X8}", ufs_sb.fs_dblkno); - DicConsole.DebugWriteLine("FFS plugin", "fs_cgoffset: 0x{0:X8}", ufs_sb.fs_cgoffset); - DicConsole.DebugWriteLine("FFS plugin", "fs_cgmask: 0x{0:X8}", ufs_sb.fs_cgmask); - DicConsole.DebugWriteLine("FFS plugin", "fs_time_t: 0x{0:X8}", ufs_sb.fs_time_t); DicConsole.DebugWriteLine("FFS plugin", "fs_size: 0x{0:X8}", ufs_sb.fs_size); DicConsole.DebugWriteLine("FFS plugin", "fs_dsize: 0x{0:X8}", ufs_sb.fs_dsize); DicConsole.DebugWriteLine("FFS plugin", "fs_ncg: 0x{0:X8}", ufs_sb.fs_ncg); @@ -435,8 +269,6 @@ namespace DiscImageChef.Filesystems DicConsole.DebugWriteLine("FFS plugin", "fs_fsize: 0x{0:X8}", ufs_sb.fs_fsize); DicConsole.DebugWriteLine("FFS plugin", "fs_frag: 0x{0:X8}", ufs_sb.fs_frag); DicConsole.DebugWriteLine("FFS plugin", "fs_minfree: 0x{0:X8}", ufs_sb.fs_minfree); - DicConsole.DebugWriteLine("FFS plugin", "fs_rotdelay: 0x{0:X8}", ufs_sb.fs_rotdelay); - DicConsole.DebugWriteLine("FFS plugin", "fs_rps: 0x{0:X8}", ufs_sb.fs_rps); DicConsole.DebugWriteLine("FFS plugin", "fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask); DicConsole.DebugWriteLine("FFS plugin", "fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask); DicConsole.DebugWriteLine("FFS plugin", "fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift); @@ -450,102 +282,19 @@ namespace DiscImageChef.Filesystems DicConsole.DebugWriteLine("FFS plugin", "fs_csshift: 0x{0:X8}", ufs_sb.fs_csshift); DicConsole.DebugWriteLine("FFS plugin", "fs_nindir: 0x{0:X8}", ufs_sb.fs_nindir); DicConsole.DebugWriteLine("FFS plugin", "fs_inopb: 0x{0:X8}", ufs_sb.fs_inopb); - DicConsole.DebugWriteLine("FFS plugin", "fs_nspf: 0x{0:X8}", ufs_sb.fs_nspf); DicConsole.DebugWriteLine("FFS plugin", "fs_optim: 0x{0:X8}", ufs_sb.fs_optim); - DicConsole.DebugWriteLine("FFS plugin", "fs_npsect_sun: 0x{0:X8}", ufs_sb.fs_npsect_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_state_t_sun86: 0x{0:X8}", ufs_sb.fs_state_t_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_interleave: 0x{0:X8}", ufs_sb.fs_interleave); - DicConsole.DebugWriteLine("FFS plugin", "fs_trackskew: 0x{0:X8}", ufs_sb.fs_trackskew); DicConsole.DebugWriteLine("FFS plugin", "fs_id_1: 0x{0:X8}", ufs_sb.fs_id_1); DicConsole.DebugWriteLine("FFS plugin", "fs_id_2: 0x{0:X8}", ufs_sb.fs_id_2); - DicConsole.DebugWriteLine("FFS plugin", "fs_headswitch_43bsd: 0x{0:X8}", ufs_sb.fs_headswitch_43bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_trkseek_43bsd: 0x{0:X8}", ufs_sb.fs_trkseek_43bsd); DicConsole.DebugWriteLine("FFS plugin", "fs_csaddr: 0x{0:X8}", ufs_sb.fs_csaddr); DicConsole.DebugWriteLine("FFS plugin", "fs_cssize: 0x{0:X8}", ufs_sb.fs_cssize); DicConsole.DebugWriteLine("FFS plugin", "fs_cgsize: 0x{0:X8}", ufs_sb.fs_cgsize); - DicConsole.DebugWriteLine("FFS plugin", "fs_ntrak: 0x{0:X8}", ufs_sb.fs_ntrak); - DicConsole.DebugWriteLine("FFS plugin", "fs_nsect: 0x{0:X8}", ufs_sb.fs_nsect); - DicConsole.DebugWriteLine("FFS plugin", "fs_spc: 0x{0:X8}", ufs_sb.fs_spc); - DicConsole.DebugWriteLine("FFS plugin", "fs_ncyl: 0x{0:X8}", ufs_sb.fs_ncyl); - DicConsole.DebugWriteLine("FFS plugin", "fs_cpg: 0x{0:X8}", ufs_sb.fs_cpg); DicConsole.DebugWriteLine("FFS plugin", "fs_ipg: 0x{0:X8}", ufs_sb.fs_ipg); DicConsole.DebugWriteLine("FFS plugin", "fs_fpg: 0x{0:X8}", ufs_sb.fs_fpg); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_ndir: 0x{0:X8}", ufs_sb.fs_cstotal_ndir); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_nbfree: 0x{0:X8}", ufs_sb.fs_cstotal_nbfree); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_nifree: 0x{0:X8}", ufs_sb.fs_cstotal_nifree); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_nffree: 0x{0:X8}", ufs_sb.fs_cstotal_nffree); DicConsole.DebugWriteLine("FFS plugin", "fs_fmod: 0x{0:X2}", ufs_sb.fs_fmod); DicConsole.DebugWriteLine("FFS plugin", "fs_clean: 0x{0:X2}", ufs_sb.fs_clean); DicConsole.DebugWriteLine("FFS plugin", "fs_ronly: 0x{0:X2}", ufs_sb.fs_ronly); DicConsole.DebugWriteLine("FFS plugin", "fs_flags: 0x{0:X2}", ufs_sb.fs_flags); - DicConsole.DebugWriteLine("FFS plugin", "fs_fsmnt_ufs1: {0}", ufs_sb.fs_fsmnt_ufs1); - DicConsole.DebugWriteLine("FFS plugin", "fs_cgrotor_ufs1: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs1); - DicConsole.DebugWriteLine("FFS plugin", "fs_cs_ufs1: 0x{0:X}", ufs_sb.fs_cs_ufs1); - DicConsole.DebugWriteLine("FFS plugin", "fs_maxcluster_ufs1: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs1); - DicConsole.DebugWriteLine("FFS plugin", "fs_cpc_ufs1: 0x{0:X8}", ufs_sb.fs_cpc_ufs1); - DicConsole.DebugWriteLine("FFS plugin", "fs_opostbl_ufs1: 0x{0:X}", ufs_sb.fs_opostbl_ufs1); - DicConsole.DebugWriteLine("FFS plugin", "fs_fsmnt_ufs2: {0}", ufs_sb.fs_fsmnt_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_volname_ufs2: {0}", ufs_sb.fs_volname_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_swuid_ufs2: 0x{0:X16}", ufs_sb.fs_swuid_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_pad_ufs2: 0x{0:X8}", ufs_sb.fs_pad_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cgrotor_ufs2: 0x{0:X8}", ufs_sb.fs_cgrotor_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_ocsp_ufs2: 0x{0:X}", ufs_sb.fs_ocsp_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_contigdirs_ufs2: 0x{0:X8}", ufs_sb.fs_contigdirs_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_csp_ufs2: 0x{0:X8}", ufs_sb.fs_csp_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_maxcluster_ufs2: 0x{0:X8}", ufs_sb.fs_maxcluster_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_active_ufs2: 0x{0:X8}", ufs_sb.fs_active_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_old_cpc_ufs2: 0x{0:X8}", ufs_sb.fs_old_cpc_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_maxbsize_ufs2: 0x{0:X8}", ufs_sb.fs_maxbsize_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_sparecon64_ufs2: 0x{0:X}", ufs_sb.fs_sparecon64_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_sblockloc_ufs2: 0x{0:X16}", ufs_sb.fs_sblockloc_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_ndir_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_ndir_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_nbfree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nbfree_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_nifree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nifree_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_nffree_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_nffree_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_numclusters_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_numclusters_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_spare0_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare0_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_spare1_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare1_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_cstotal_spare2_ufs2: 0x{0:X16}", ufs_sb.fs_cstotal_spare2_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_time_sec_ufs2: 0x{0:X8}", ufs_sb.fs_time_sec_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_time_usec_ufs2: 0x{0:X8}", ufs_sb.fs_time_usec_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_size_ufs2: 0x{0:X16}", ufs_sb.fs_size_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_dsize_ufs2: 0x{0:X16}", ufs_sb.fs_dsize_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_csaddr_ufs2: 0x{0:X16}", ufs_sb.fs_csaddr_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_pendingblocks_ufs2: 0x{0:X16}", ufs_sb.fs_pendingblocks_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_pendinginodes_ufs2: 0x{0:X8}", ufs_sb.fs_pendinginodes_ufs2); - DicConsole.DebugWriteLine("FFS plugin", "fs_sparecon_sun: 0x{0:X}", ufs_sb.fs_sparecon_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_reclaim_sun: 0x{0:X8}", ufs_sb.fs_reclaim_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_sparecon2_sun: 0x{0:X8}", ufs_sb.fs_sparecon2_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_state_t_sun: 0x{0:X8}", ufs_sb.fs_state_t_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_qbmask0_sun: 0x{0:X8}", ufs_sb.fs_qbmask0_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_qbmask1_sun: 0x{0:X8}", ufs_sb.fs_qbmask1_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_qfmask0_sun: 0x{0:X8}", ufs_sb.fs_qfmask0_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_qfmask1_sun: 0x{0:X8}", ufs_sb.fs_qfmask1_sun); - DicConsole.DebugWriteLine("FFS plugin", "fs_sparecon_sun86: 0x{0:X}", ufs_sb.fs_sparecon_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_reclaim_sun86: 0x{0:X8}", ufs_sb.fs_reclaim_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_sparecon2_sun86: 0x{0:X8}", ufs_sb.fs_sparecon2_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_npsect_sun86: 0x{0:X8}", ufs_sb.fs_npsect_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_qbmask0_sun86: 0x{0:X8}", ufs_sb.fs_qbmask0_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_qbmask1_sun86: 0x{0:X8}", ufs_sb.fs_qbmask1_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_qfmask0_sun86: 0x{0:X8}", ufs_sb.fs_qfmask0_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_qfmask1_sun86: 0x{0:X8}", ufs_sb.fs_qfmask1_sun86); - DicConsole.DebugWriteLine("FFS plugin", "fs_sparecon_44bsd: 0x{0:X}", ufs_sb.fs_sparecon_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_contigsumsize_44bsd: 0x{0:X8}", ufs_sb.fs_contigsumsize_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_maxsymlinklen_44bsd: 0x{0:X8}", ufs_sb.fs_maxsymlinklen_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_inodefmt_44bsd: 0x{0:X8}", ufs_sb.fs_inodefmt_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_maxfilesize0_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize0_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_maxfilesize1_44bsd: 0x{0:X8}", ufs_sb.fs_maxfilesize1_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_qbmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask0_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_qbmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qbmask1_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_qfmask0_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask0_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_qfmask1_44bsd: 0x{0:X8}", ufs_sb.fs_qfmask1_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_state_t_44bsd: 0x{0:X8}", ufs_sb.fs_state_t_44bsd); - DicConsole.DebugWriteLine("FFS plugin", "fs_postblformat: 0x{0:X8}", ufs_sb.fs_postblformat); - DicConsole.DebugWriteLine("FFS plugin", "fs_nrpos: 0x{0:X8}", ufs_sb.fs_nrpos); - DicConsole.DebugWriteLine("FFS plugin", "fs_postbloff: 0x{0:X8}", ufs_sb.fs_postbloff); - DicConsole.DebugWriteLine("FFS plugin", "fs_rotbloff: 0x{0:X8}", ufs_sb.fs_rotbloff); DicConsole.DebugWriteLine("FFS plugin", "fs_magic: 0x{0:X8}", ufs_sb.fs_magic); - DicConsole.DebugWriteLine("FFS plugin", "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"); @@ -560,13 +309,13 @@ namespace DiscImageChef.Filesystems 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) + if(ufs_sb.fs_link > 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) + if((ufs_sb.fs_maxfilesize & 0xFFFFFFFF) > SunOSEpoch && DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_maxfilesize & 0xFFFFFFFF) < DateTime.Now) { fs_type_42bsd = false; fs_type_sun = true; @@ -574,7 +323,7 @@ namespace DiscImageChef.Filesystems } // 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) + if(ufs_sb.fs_old_npsect > SunOSEpoch && DateHandlers.UNIXToDateTime(ufs_sb.fs_old_npsect) < DateTime.Now) { fs_type_42bsd = false; fs_type_sun86 = true; @@ -582,7 +331,7 @@ namespace DiscImageChef.Filesystems fs_type_43bsd = false; } - if(ufs_sb.fs_cgrotor_ufs1 > 0x00000000 && ufs_sb.fs_cgrotor_ufs1 < 0xFFFFFFFF) + if(ufs_sb.fs_cgrotor > 0x00000000 && (uint)ufs_sb.fs_cgrotor < 0xFFFFFFFF) { fs_type_42bsd = false; fs_type_sun = false; @@ -592,10 +341,10 @@ namespace DiscImageChef.Filesystems } // 4.3BSD code does not use these fields, they are always set up to 0 - fs_type_43bsd &= ufs_sb.fs_trkseek_43bsd == 0 && ufs_sb.fs_headswitch_43bsd == 0; + fs_type_43bsd &= ufs_sb.fs_id_2 == 0 && ufs_sb.fs_id_1 == 0; // This is the only 4.4BSD inode format - fs_type_44bsd |= ufs_sb.fs_inodefmt_44bsd == 2; + fs_type_44bsd |= ufs_sb.fs_old_inodefmt == 2; } if(fs_type_42bsd) @@ -614,26 +363,24 @@ namespace DiscImageChef.Filesystems 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("Linked list of filesystems: 0x{0:X8}", ufs_sb.fs_link).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 * 1024L).AppendLine(); - xmlFSType.Clusters = ufs_sb.fs_size; - xmlFSType.ClusterSize = (int)ufs_sb.fs_bsize; - sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * 1024L).AppendLine(); + sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_old_cgoffset).AppendLine(); + sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_old_time)).AppendLine(); + sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_old_size, (long)ufs_sb.fs_old_size * ufs_sb.fs_fsize).AppendLine(); + xmlFSType.Clusters = ufs_sb.fs_old_size; + xmlFSType.ClusterSize = (int)ufs_sb.fs_fsize; + sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_old_dsize, (long)ufs_sb.fs_old_dsize * ufs_sb.fs_fsize).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("{0}ms for optimal next block", ufs_sb.fs_old_rotdelay).AppendLine(); + sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", ufs_sb.fs_old_rps, ufs_sb.fs_old_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(); @@ -643,7 +390,7 @@ namespace DiscImageChef.Filesystems 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(); + sbInformation.AppendFormat("NSPF: 0x{0:X8}", ufs_sb.fs_old_nspf).AppendLine(); if(ufs_sb.fs_optim == 0) sbInformation.AppendLine("Filesystem will minimize allocation time"); else if(ufs_sb.fs_optim == 1) @@ -651,37 +398,37 @@ namespace DiscImageChef.Filesystems 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(); + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_npsect).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(); + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_old_npsect)).AppendLine(); + sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_old_interleave).AppendLine(); + sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_old_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(); xmlFSType.VolumeSerial = string.Format("{0:X8}{1:x8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2); } - else if(fs_type_43bsd && ufs_sb.fs_headswitch_43bsd > 0 && ufs_sb.fs_trkseek_43bsd > 0) + else if(fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 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("{0} µsec for head switch", ufs_sb.fs_id_1).AppendLine(); + sbInformation.AppendFormat("{0} µsec for track-to-track seek", ufs_sb.fs_id_2).AppendLine(); } - sbInformation.AppendFormat("Cylinder group summary LBA: {0}", ufs_sb.fs_csaddr).AppendLine(); + sbInformation.AppendFormat("Cylinder group summary LBA: {0}", ufs_sb.fs_old_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} tracks/cylinder", ufs_sb.fs_old_ntrak).AppendLine(); + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_nsect).AppendLine(); + sbInformation.AppendFormat("{0} sectors/cylinder", ufs_sb.fs_old_spc).AppendLine(); + sbInformation.AppendFormat("{0} cylinder in volume", ufs_sb.fs_old_ncyl).AppendLine(); + sbInformation.AppendFormat("{0} cylinders/group", ufs_sb.fs_old_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(); - xmlFSType.FreeClusters = ufs_sb.fs_cstotal_nbfree; + sbInformation.AppendFormat("{0} directories", ufs_sb.fs_old_cstotal.cs_ndir).AppendLine(); + sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_old_cstotal.cs_nbfree, (long)ufs_sb.fs_old_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine(); + xmlFSType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree; xmlFSType.FreeClustersSpecified = true; - sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree).AppendLine(); - sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree).AppendLine(); + sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_old_cstotal.cs_nifree).AppendLine(); + sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_old_cstotal.cs_nffree).AppendLine(); if(ufs_sb.fs_fmod == 1) { sbInformation.AppendLine("Superblock is under modification"); @@ -693,55 +440,53 @@ namespace DiscImageChef.Filesystems 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(); - } + sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(ufs_sb.fs_fsmnt)).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(); - xmlFSType.VolumeName = ufs_sb.fs_volname_ufs2; - sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid_ufs2).AppendLine(); - xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid_ufs2); - 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(); - xmlFSType.FreeClusters = (long)ufs_sb.fs_cstotal_nbfree_ufs2; + sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(ufs_sb.fs_fsmnt)).AppendLine(); + sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(ufs_sb.fs_volname)).AppendLine(); + xmlFSType.VolumeName = StringHandlers.CToString(ufs_sb.fs_volname); + sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid).AppendLine(); + xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid); + sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor).AppendLine(); + sbInformation.AppendFormat("{0} contiguously allocated directories", ufs_sb.fs_contigdirs).AppendLine(); + sbInformation.AppendFormat("Standard superblock LBA: {0}", ufs_sb.fs_sblkno).AppendLine(); + sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal.cs_ndir).AppendLine(); + sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal.cs_nbfree, ufs_sb.fs_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine(); + xmlFSType.FreeClusters = (long)ufs_sb.fs_cstotal.cs_nbfree; xmlFSType.FreeClustersSpecified = true; - 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(); - xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_sec_ufs2); + sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal.cs_nifree).AppendLine(); + sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal.cs_nffree).AppendLine(); + sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal.cs_numclusters).AppendLine(); + sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_time)).AppendLine(); + xmlFSType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_time); xmlFSType.ModificationDateSpecified = true; - sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size_ufs2, ufs_sb.fs_size_ufs2 * ufs_sb.fs_bsize).AppendLine(); - xmlFSType.Clusters = (long)ufs_sb.fs_dsize_ufs2; - 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(); + sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_fsize).AppendLine(); + xmlFSType.Clusters = (long)ufs_sb.fs_size; + sbInformation.AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_fsize).AppendLine(); + sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", ufs_sb.fs_csaddr).AppendLine(); + sbInformation.AppendFormat("{0} blocks pending of being freed", ufs_sb.fs_pendingblocks).AppendLine(); + sbInformation.AppendFormat("{0} inodes pending of being freed", ufs_sb.fs_pendinginodes).AppendLine(); } if(fs_type_sun) { - sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_state_t_sun)).AppendLine(); + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_old_npsect)).AppendLine(); } else if(fs_type_sun86) { - sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_npsect_sun86).AppendLine(); + sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_state).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} blocks on cluster summary array", ufs_sb.fs_contigsumsize).AppendLine(); + sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", ufs_sb.fs_maxsymlinklen).AppendLine(); + sbInformation.AppendFormat("A file can be {0} bytes at max", ufs_sb.fs_maxfilesize).AppendLine(); + sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_state)).AppendLine(); } - sbInformation.AppendFormat("{0} rotational positions", ufs_sb.fs_nrpos).AppendLine(); - sbInformation.AppendFormat("{0} blocks per rotation", ufs_sb.fs_rotbloff).AppendLine(); + if(ufs_sb.fs_old_nrpos > 0) + sbInformation.AppendFormat("{0} rotational positions", ufs_sb.fs_old_nrpos).AppendLine(); + if(ufs_sb.fs_old_rotbloff > 0) + sbInformation.AppendFormat("{0} blocks per rotation", ufs_sb.fs_old_rotbloff).AppendLine(); information = sbInformation.ToString(); } @@ -772,373 +517,261 @@ namespace DiscImageChef.Filesystems // Incomplete newfs const uint UFS_BAD_MAGIC = 0x19960408; - /// - /// 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 - /// Biggest sized supleblock would be 1377 bytes - /// - public struct UFSSuperBlock + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct csum { - #region 42BSD + /// number of directories + public int cs_ndir; + /// number of free blocks + public int cs_nbfree; + /// number of free inodes + public int cs_nifree; + /// number of free frags + public int cs_nffree; + } - /// 0x0000 linked list of file systems - public uint fs_link_42bsd; + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct csum_total + { + /// number of directories + public long cs_ndir; + /// number of free blocks + public long cs_nbfree; + /// number of free inodes + public long cs_nifree; + /// number of free frags + public long cs_nffree; + /// number of free clusters + public long cs_numclusters; + /// future expansion + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public long[] cs_spare; + } - #endregion - - #region Sun - - /// 0x0000 file system state flag - public uint fs_state_sun; - - #endregion - - #region COMMON - - /// 0x0004 used for incore super blocks + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct UFSSuperBlock + { + /// linked list of file systems + public uint fs_link; + /// used for incore super blocks + /// on Sun: uint fs_rolled; // logging only: fs fully rolled public uint fs_rlink; - /// 0x0008 addr of super-block in filesys - public uint fs_sblkno; - /// 0x000C offset of cyl-block in filesys - public uint fs_cblkno; - /// 0x0010 offset of inode-blocks in filesys - public uint fs_iblkno; - /// 0x0014 offset of first data after cg - public uint fs_dblkno; - /// 0x0018 cylinder group offset in cylinder - public uint fs_cgoffset; - /// 0x001C used to calc mod fs_ntrak - public uint fs_cgmask; - /// 0x0020 last time written -- time_t - public uint fs_time_t; - /// 0x0024 number of blocks in fs - public uint fs_size; - /// 0x0028 number of data blocks in fs - public uint fs_dsize; - /// 0x002C number of cylinder groups - public uint fs_ncg; - /// 0x0030 size of basic blocks in fs - public uint fs_bsize; - /// 0x0034 size of frag blocks in fs - public uint fs_fsize; - /// 0x0038 number of frags in a block in fs - public uint fs_frag; - - // these are configuration parameters - /// 0x003C minimum percentage of free blocks - public uint fs_minfree; - /// 0x0040 num of ms for optimal next block - public uint fs_rotdelay; - /// 0x0044 disk revolutions per second - public uint fs_rps; - - // these fields can be computed from the others - /// 0x0048 ``blkoff'' calc of blk offsets - public uint fs_bmask; - /// 0x004C ``fragoff'' calc of frag offsets - public uint fs_fmask; - /// 0x0050 ``lblkno'' calc of logical blkno - public uint fs_bshift; - /// 0x0054 ``numfrags'' calc number of frags - public uint fs_fshift; - - // these are configuration parameters - /// 0x0058 max number of contiguous blks - public uint fs_maxcontig; - /// 0x005C max number of blks per cyl group - public uint fs_maxbpg; - - // these fields can be computed from the others - /// 0x0060 block to frag shift - public uint fs_fragshift; - /// 0x0064 fsbtodb and dbtofsb shift constant - public uint fs_fsbtodb; - /// 0x0068 actual size of super block - public uint fs_sbsize; - /// 0x006C csum block offset - public uint fs_csmask; - /// 0x0070 csum block number - public uint fs_csshift; - /// 0x0074 value of NINDIR - public uint fs_nindir; - /// 0x0078 value of INOPB + /// addr of super-block in filesys + public ufs_daddr_t fs_sblkno; + /// offset of cyl-block in filesys + public ufs_daddr_t fs_cblkno; + /// offset of inode-blocks in filesys + public ufs_daddr_t fs_iblkno; + /// offset of first data after cg + public ufs_daddr_t fs_dblkno; + /// cylinder group offset in cylinder + public int fs_old_cgoffset; + /// used to calc mod fs_ntrak + public int fs_old_cgmask; + /// last time written + public time_t fs_old_time; + /// number of blocks in fs + public int fs_old_size; + /// number of data blocks in fs + public int fs_old_dsize; + /// number of cylinder groups + public int fs_ncg; + /// size of basic blocks in fs + public int fs_bsize; + /// size of frag blocks in fs + public int fs_fsize; + /// number of frags in a block in fs + public int fs_frag; + /* these are configuration parameters */ + /// minimum percentage of free blocks + public int fs_minfree; + /// num of ms for optimal next block + public int fs_old_rotdelay; + /// disk revolutions per second + public int fs_old_rps; + /* these fields can be computed from the others */ + /// ``blkoff'' calc of blk offsets + public int fs_bmask; + /// ``fragoff'' calc of frag offsets + public int fs_fmask; + /// ``lblkno'' calc of logical blkno + public int fs_bshift; + /// ``numfrags'' calc number of frags + public int fs_fshift; + /* these are configuration parameters */ + /// max number of contiguous blks + public int fs_maxcontig; + /// max number of blks per cyl group + public int fs_maxbpg; + /* these fields can be computed from the others */ + /// block to frag shift + public int fs_fragshift; + /// fsbtodb and dbtofsb shift constant + public int fs_fsbtodb; + /// actual size of super block + public int fs_sbsize; + /// csum block offset + public int fs_csmask; + /// csum block number + public int fs_csshift; + /// value of NINDIR + public int fs_nindir; + /// value of INOPB public uint fs_inopb; - /// 0x007C value of NSPF - public uint fs_nspf; - - // yet another configuration parameter - /// 0x0080 optimization preference, see below - public uint fs_optim; - - #endregion COMMON - - - #region Sun - - // these fields are derived from the hardware - /// 0x0084 # sectors/track including spares - public uint fs_npsect_sun; - - #endregion Sun - - #region Sunx86 - - /// 0x0084 file system state time stamp - public uint fs_state_t_sun86; - - #endregion Sunx86 - - #region COMMON - - /// 0x0088 hardware sector interleave - public uint fs_interleave; - /// 0x008C sector 0 skew, per track - public uint fs_trackskew; - - #endregion COMMON - - - #region 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. - - /// 0x0090 - public uint fs_id_1; - /// 0x0094 - public uint fs_id_2; - - #endregion COMMON - - #region 43BSD - - /// 0x0090 head switch time, usec - public uint fs_headswitch_43bsd; - /// 0x0094 track-to-track seek, usec - public uint fs_trkseek_43bsd; - - #endregion 43BSD - - #region COMMON - - // sizes determined by number of cylinder groups and their sizes - /// 0x0098 blk addr of cyl grp summary area - public uint fs_csaddr; - /// 0x009C size of cyl grp summary area - public uint fs_cssize; - /// 0x00A0 cylinder group size - public uint fs_cgsize; - - // these fields are derived from the hardware - /// 0x00A4 tracks per cylinder - public uint fs_ntrak; - /// 0x00A8 sectors per track - public uint fs_nsect; - /// 0x00AC sectors per cylinder - public uint fs_spc; - - // this comes from the disk driver partitioning - /// 0x00B0 cylinders in file system - public uint fs_ncyl; - - // these fields can be computed from the others - /// 0x00B4 cylinders per group - public uint fs_cpg; - /// 0x00B8 inodes per cylinder group - public uint fs_ipg; - /// 0x00BC blocks per group * fs_frag - public uint fs_fpg; - - // this data must be re-computed after crashes - // struct ufs_csum fs_cstotal; // cylinder summary information - /// 0x00C0 number of directories - public uint fs_cstotal_ndir; - /// 0x00C4 number of free blocks - public uint fs_cstotal_nbfree; - /// 0x00C8 number of free inodes - public uint fs_cstotal_nifree; - /// 0x00CC number of free frags - public uint fs_cstotal_nffree; - - // these fields are cleared at mount time - /// 0x00D0 super block modified flag - public byte fs_fmod; - /// 0x00D1 file system is clean flag - public byte fs_clean; - /// 0x00D2 mounted read-only flag - public byte fs_ronly; - /// 0x00D3 - public byte fs_flags; - - #endregion common - - #region UFS1 - - /// 0x00D4, 512 bytes, name mounted on - public string fs_fsmnt_ufs1; - /// 0x02D4 last cg searched - public uint fs_cgrotor_ufs1; - /// 0x02D8, 124 bytes, uints, list of fs_cs info buffers - public byte[] fs_cs_ufs1; - /// 0x0354 - public uint fs_maxcluster_ufs1; - /// 0x0358 cyl per cycle in postbl - public uint fs_cpc_ufs1; - /// 0x035C, 256 bytes, [16][8] matrix of ushorts, old rotation block list head - public byte[] fs_opostbl_ufs1; - - #endregion UFS1 - - #region UFS2 - - /// 0x00D4, 468 bytes, name mounted on - public string fs_fsmnt_ufs2; - /// 0x02A8, 32 bytes, volume name - public string fs_volname_ufs2; - /// 0x02C8 system-wide uid - public ulong fs_swuid_ufs2; - /// 0x02D0 due to alignment of fs_swuid - public uint fs_pad_ufs2; - /// 0x02D4 last cg searched - public uint fs_cgrotor_ufs2; - /// 0x02D8, 112 bytes, uints, list of fs_cs info buffers - public byte[] fs_ocsp_ufs2; - /// 0x0348 # of contiguously allocated dirs - public uint fs_contigdirs_ufs2; - /// 0x034C cg summary info buffer for fs_cs - public uint fs_csp_ufs2; - /// 0x0350 - public uint fs_maxcluster_ufs2; - /// 0x0354 used by snapshots to track fs - public uint fs_active_ufs2; - /// 0x0358 cyl per cycle in postbl - public uint fs_old_cpc_ufs2; - /// 0x035C maximum blocking factor permitted - public uint fs_maxbsize_ufs2; - /// 0x0360, 136 bytes, ulongs, old rotation block list head - public byte[] fs_sparecon64_ufs2; - /// 0x03E8 byte offset of standard superblock - public ulong fs_sblockloc_ufs2; - - /// 0x03F0 number of directories - public ulong fs_cstotal_ndir_ufs2; - /// 0x03F8 number of free blocks - public ulong fs_cstotal_nbfree_ufs2; - /// 0x0400 number of free inodes - public ulong fs_cstotal_nifree_ufs2; - /// 0x0408 number of free frags - public ulong fs_cstotal_nffree_ufs2; - /// 0x0410 number of free clusters - public ulong fs_cstotal_numclusters_ufs2; - /// 0x0418 future expansion - public ulong fs_cstotal_spare0_ufs2; - /// 0x0420 future expansion - public ulong fs_cstotal_spare1_ufs2; - /// 0x0428 future expansion - public ulong fs_cstotal_spare2_ufs2; - /// 0x0430 last time written - public uint fs_time_sec_ufs2; - /// 0x0434 last time written - public uint fs_time_usec_ufs2; - /// 0x0438 number of blocks in fs - public ulong fs_size_ufs2; - /// 0x0440 number of data blocks in fs - public ulong fs_dsize_ufs2; - /// 0x0448 blk addr of cyl grp summary area - public ulong fs_csaddr_ufs2; - /// 0x0450 blocks in process of being freed - public ulong fs_pendingblocks_ufs2; - /// 0x0458 inodes in process of being freed - public uint fs_pendinginodes_ufs2; - - #endregion UFS2 - - #region Sun - - /// 0x045C, 212 bytes, reserved for future constants - public byte[] fs_sparecon_sun; - /// 0x0530 - public uint fs_reclaim_sun; - /// 0x0534 - public uint fs_sparecon2_sun; - /// 0x0538 file system state time stamp - public uint fs_state_t_sun; - /// 0x053C ~usb_bmask - public uint fs_qbmask0_sun; - /// 0x0540 ~usb_bmask - public uint fs_qbmask1_sun; - /// 0x0544 ~usb_fmask - public uint fs_qfmask0_sun; - /// 0x0548 ~usb_fmask - public uint fs_qfmask1_sun; - - #endregion Sun - - #region Sunx86 - - /// 0x045C, 212 bytes, reserved for future constants - public byte[] fs_sparecon_sun86; - /// 0x0530 - public uint fs_reclaim_sun86; - /// 0x0534 - public uint fs_sparecon2_sun86; - /// 0x0538 # sectors/track including spares - public uint fs_npsect_sun86; - /// 0x053C ~usb_bmask - public uint fs_qbmask0_sun86; - /// 0x0540 ~usb_bmask - public uint fs_qbmask1_sun86; - /// 0x0544 ~usb_fmask - public uint fs_qfmask0_sun86; - /// 0x0548 ~usb_fmask - public uint fs_qfmask1_sun86; - - #endregion Sunx86 - - #region 44BSD - - /// 0x045C, 200 bytes - public byte[] fs_sparecon_44bsd; - /// 0x0524 size of cluster summary array - public uint fs_contigsumsize_44bsd; - /// 0x0528 max length of an internal symlink - public uint fs_maxsymlinklen_44bsd; - /// 0x052C format of on-disk inodes - public uint fs_inodefmt_44bsd; - /// 0x0530 max representable file size - public uint fs_maxfilesize0_44bsd; - /// 0x0534 max representable file size - public uint fs_maxfilesize1_44bsd; - /// 0x0538 ~usb_bmask - public uint fs_qbmask0_44bsd; - /// 0x053C ~usb_bmask - public uint fs_qbmask1_44bsd; - /// 0x0540 ~usb_fmask - public uint fs_qfmask0_44bsd; - /// 0x0544 ~usb_fmask - public uint fs_qfmask1_44bsd; - /// 0x0548 file system state time stamp - public uint fs_state_t_44bsd; - - #endregion 44BSD - - /// 0x054C format of positional layout tables - public uint fs_postblformat; - /// 0x0550 number of rotational positions - public uint fs_nrpos; - /// 0x0554 (__s16) rotation block list head - public uint fs_postbloff; - /// 0x0558 (__u8) blocks for each rotation - public uint fs_rotbloff; - /// 0x055C magic number - public uint fs_magic; - /// 0x0560 list of blocks for each rotation - public byte fs_space; - // 0x0561 + /// value of NSPF + public int fs_old_nspf; + /* yet another configuration parameter */ + /// optimization preference, see below + /// On SVR: int fs_state; // file system state + public int fs_optim; + /// # sectors/track including spares + public int fs_old_npsect; + /// hardware sector interleave + public int fs_old_interleave; + /// sector 0 skew, per track + /// On A/UX: int fs_state; // file system state + public int fs_old_trackskew; + /// unique filesystem id + /// On old: int fs_headswitch; // head switch time, usec + public int fs_id_1; + /// unique filesystem id + /// On old: int fs_trkseek; // track-to-track seek, usec + public int fs_id_2; + /* sizes determined by number of cylinder groups and their sizes */ + /// blk addr of cyl grp summary area + public ufs_daddr_t fs_old_csaddr; + /// size of cyl grp summary area + public int fs_cssize; + /// cylinder group size + public int fs_cgsize; + /* these fields are derived from the hardware */ + /// tracks per cylinder + public int fs_old_ntrak; + /// sectors per track + public int fs_old_nsect; + /// sectors per cylinder + public int fs_old_spc; + /* this comes from the disk driver partitioning */ + /// cylinders in filesystem + public int fs_old_ncyl; + /* these fields can be computed from the others */ + /// cylinders per group + public int fs_old_cpg; + /// inodes per group + public int fs_ipg; + /// blocks per group * fs_frag + public int fs_fpg; + /* this data must be re-computed after crashes */ + /// cylinder summary information + public csum fs_old_cstotal; + /* these fields are cleared at mount time */ + /// super block modified flag + public sbyte fs_fmod; + /// filesystem is clean flag + public sbyte fs_clean; + /// mounted read-only flag + public sbyte fs_ronly; + /// old FS_ flags + public sbyte fs_old_flags; + /// name mounted on + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 468)] + public byte[] fs_fsmnt; + /// volume name + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] fs_volname; + /// system-wide uid + public ulong fs_swuid; + /// due to alignment of fs_swuid + public int fs_pad; + /* these fields retain the current block allocation info */ + /// last cg searched + public int fs_cgrotor; + /// padding; was list of fs_cs buffers + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] + public uint[] fs_ocsp; + /// (u) # of contig. allocated dirs + public uint fs_contigdirs; + /// (u) cg summary info buffer + public uint fs_csp; + /// (u) max cluster in each cyl group + public uint fs_maxcluster; + /// (u) used by snapshots to track fs + public uint fs_active; + /// cyl per cycle in postbl + public int fs_old_cpc; + /// maximum blocking factor permitted + public int fs_maxbsize; + /// number of unreferenced inodes + public long fs_unrefs; + /// size of underlying GEOM provider + public long fs_providersize; + /// size of area reserved for metadata + public long fs_metaspace; + /// old rotation block list head + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] + public long[] fs_sparecon64; + /// byte offset of standard superblock + public long fs_sblockloc; + /// (u) cylinder summary information + public csum_total fs_cstotal; + /// last time written + public long fs_time; + /// number of blocks in fs + public long fs_size; + /// number of data blocks in fs + public long fs_dsize; + /// blk addr of cyl grp summary area + public long fs_csaddr; + /// (u) blocks being freed + public long fs_pendingblocks; + /// (u) inodes being freed + public uint fs_pendinginodes; + /// list of snapshot inode numbers + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + public uint[] fs_snapinum; + /// expected average file size + public uint fs_avgfilesize; + /// expected # of files per directory + public uint fs_avgfpdir; + /// save real cg size to use fs_bsize + public int fs_save_cgsize; + /// Last mount or fsck time. + public long fs_mtime; + /// SUJ free list + public int fs_sujfree; + /// reserved for future constants + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 23)] + public int[] fs_sparecon32; + /// see FS_ flags below + public int fs_flags; + /// size of cluster summary array + public int fs_contigsumsize; + /// max length of an internal symlink + public int fs_maxsymlinklen; + /// format of on-disk inodes + public int fs_old_inodefmt; + /// maximum representable file size + public ulong fs_maxfilesize; + /// ~fs_bmask for use with 64-bit size + public long fs_qbmask; + /// ~fs_fmask for use with 64-bit size + public long fs_qfmask; + /// validate fs_clean field + public int fs_state; + /// format of positional layout tables + public int fs_old_postblformat; + /// number of rotational positions + public int fs_old_nrpos; + /// (short) rotation block list head + public int fs_old_postbloff; + /// (uchar_t) blocks for each rotation + public int fs_old_rotbloff; + /// magic number + public int fs_magic; + /// list of blocks for each rotation + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public byte[] fs_rotbl; } public override Errno Mount()