mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 11:14:25 +00:00
875 lines
44 KiB
C#
875 lines
44 KiB
C#
/***************************************************************************
|
|
FileSystem identifier and checker
|
|
----------------------------------------------------------------------------
|
|
|
|
Filename : ext2FS.cs
|
|
Version : 1.0
|
|
Author(s) : Natalia Portillo
|
|
|
|
Component : Filesystem plugins
|
|
|
|
Revision : $Revision$
|
|
Last change by : $Author$
|
|
Date : $Date$
|
|
|
|
--[ Description ] ----------------------------------------------------------
|
|
|
|
Identifies ext2, ext3 and ext4 filesystems and shows information.
|
|
|
|
--[ License ] --------------------------------------------------------------
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
----------------------------------------------------------------------------
|
|
Copyright (C) 2011-2014 Claunia.com
|
|
****************************************************************************/
|
|
//$Id$
|
|
|
|
using System;
|
|
using System.Text;
|
|
using FileSystemIDandChk;
|
|
|
|
// Information from the Linux kernel
|
|
namespace FileSystemIDandChk.Plugins
|
|
{
|
|
class ext2FS : Plugin
|
|
{
|
|
public ext2FS(PluginBase Core)
|
|
{
|
|
Name = "Linux extended Filesystem 2, 3 and 4";
|
|
PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
|
}
|
|
|
|
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset)
|
|
{
|
|
byte[] sb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
|
|
|
UInt16 magic = BitConverter.ToUInt16(sb_sector, 0x038);
|
|
|
|
if (magic == ext2FSMagic || magic == ext2OldFSMagic)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionOffset, out string information)
|
|
{
|
|
information = "";
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
ext2FSSuperBlock supblk = new ext2FSSuperBlock();
|
|
byte[] forstrings;
|
|
bool new_ext2 = false;
|
|
bool ext3 = false;
|
|
bool ext4 = false;
|
|
|
|
byte[] guid_a = new byte[16];
|
|
byte[] guid_b = new byte[16];
|
|
|
|
uint sb_size_in_sectors;
|
|
|
|
if (imagePlugin.GetSectorSize() < 1024)
|
|
sb_size_in_sectors = 1024 / imagePlugin.GetSectorSize();
|
|
else
|
|
sb_size_in_sectors = 1;
|
|
|
|
if (sb_size_in_sectors == 0)
|
|
{
|
|
information = "Error calculating size in sectors of ext2/3/4 superblocks";
|
|
return;
|
|
}
|
|
|
|
byte[] sb_sector = imagePlugin.ReadSectors(2 + partitionOffset, sb_size_in_sectors);
|
|
supblk.inodes = BitConverter.ToUInt32(sb_sector, 0x000);
|
|
supblk.blocks = BitConverter.ToUInt32(sb_sector, 0x004);
|
|
supblk.reserved_blocks = BitConverter.ToUInt32(sb_sector, 0x008);
|
|
supblk.free_blocks = BitConverter.ToUInt32(sb_sector, 0x00C);
|
|
supblk.free_inodes = BitConverter.ToUInt32(sb_sector, 0x010);
|
|
supblk.first_block = BitConverter.ToUInt32(sb_sector, 0x014);
|
|
supblk.block_size = BitConverter.ToUInt32(sb_sector, 0x018);
|
|
supblk.frag_size = BitConverter.ToInt32(sb_sector, 0x01C);
|
|
supblk.blocks_per_grp = BitConverter.ToUInt32(sb_sector, 0x020);
|
|
supblk.flags_per_grp = BitConverter.ToUInt32(sb_sector, 0x024);
|
|
supblk.inodes_per_grp = BitConverter.ToUInt32(sb_sector, 0x028);
|
|
supblk.mount_t = BitConverter.ToUInt32(sb_sector, 0x02C);
|
|
supblk.write_t = BitConverter.ToUInt32(sb_sector, 0x030);
|
|
supblk.mount_c = BitConverter.ToUInt16(sb_sector, 0x034);
|
|
supblk.max_mount_c = BitConverter.ToInt16(sb_sector, 0x036);
|
|
supblk.magic = BitConverter.ToUInt16(sb_sector, 0x038);
|
|
supblk.state = BitConverter.ToUInt16(sb_sector, 0x03A);
|
|
supblk.err_behaviour = BitConverter.ToUInt16(sb_sector, 0x03C);
|
|
supblk.minor_revision = BitConverter.ToUInt16(sb_sector, 0x03E);
|
|
supblk.check_t = BitConverter.ToUInt32(sb_sector, 0x040);
|
|
supblk.check_inv = BitConverter.ToUInt32(sb_sector, 0x044);
|
|
// From 0.5a onward
|
|
supblk.creator_os = BitConverter.ToUInt32(sb_sector, 0x048);
|
|
supblk.revision = BitConverter.ToUInt32(sb_sector, 0x04C);
|
|
supblk.default_uid = BitConverter.ToUInt16(sb_sector, 0x050);
|
|
supblk.default_gid = BitConverter.ToUInt16(sb_sector, 0x052);
|
|
// From 0.5b onward
|
|
supblk.first_inode = BitConverter.ToUInt32(sb_sector, 0x054);
|
|
supblk.inode_size = BitConverter.ToUInt16(sb_sector, 0x058);
|
|
supblk.block_group_no = BitConverter.ToUInt16(sb_sector, 0x05A);
|
|
supblk.ftr_compat = BitConverter.ToUInt32(sb_sector, 0x05C);
|
|
supblk.ftr_incompat = BitConverter.ToUInt32(sb_sector, 0x060);
|
|
supblk.ftr_ro_compat = BitConverter.ToUInt32(sb_sector, 0x064);
|
|
// Volume UUID
|
|
Array.Copy(sb_sector, 0x068, guid_a, 0, 16);
|
|
guid_b[0] = guid_a[3];
|
|
guid_b[1] = guid_a[2];
|
|
guid_b[2] = guid_a[1];
|
|
guid_b[3] = guid_a[0];
|
|
guid_b[4] = guid_a[5];
|
|
guid_b[5] = guid_a[4];
|
|
guid_b[6] = guid_a[7];
|
|
guid_b[7] = guid_a[6];
|
|
guid_b[8] = guid_a[8];
|
|
guid_b[9] = guid_a[9];
|
|
guid_b[10] = guid_a[10];
|
|
guid_b[11] = guid_a[11];
|
|
guid_b[12] = guid_a[12];
|
|
guid_b[13] = guid_a[13];
|
|
guid_b[14] = guid_a[14];
|
|
guid_b[15] = guid_a[15];
|
|
supblk.uuid = new Guid(guid_b);
|
|
// End of volume UUID
|
|
forstrings = new byte[16];
|
|
Array.Copy(sb_sector, 0x078, forstrings, 0, 16);
|
|
supblk.volume_name = StringHandlers.CToString(forstrings);
|
|
forstrings = new byte[64];
|
|
Array.Copy(sb_sector, 0x088, forstrings, 0, 64);
|
|
supblk.last_mount_dir = StringHandlers.CToString(forstrings);
|
|
supblk.algo_usage_bmp = BitConverter.ToUInt32(sb_sector, 0x0C8);
|
|
supblk.prealloc_blks = sb_sector[0x0CC];
|
|
supblk.prealloc_dir_blks = sb_sector[0x0CD];
|
|
supblk.rsrvd_gdt_blocks = BitConverter.ToUInt16(sb_sector, 0x0CE);
|
|
// ext3
|
|
Array.Copy(sb_sector, 0x0D0, guid_a, 0, 16);
|
|
guid_b[0] = guid_a[3];
|
|
guid_b[1] = guid_a[2];
|
|
guid_b[2] = guid_a[1];
|
|
guid_b[3] = guid_a[0];
|
|
guid_b[4] = guid_a[5];
|
|
guid_b[5] = guid_a[4];
|
|
guid_b[6] = guid_a[7];
|
|
guid_b[7] = guid_a[6];
|
|
guid_b[8] = guid_a[8];
|
|
guid_b[9] = guid_a[9];
|
|
guid_b[10] = guid_a[10];
|
|
guid_b[11] = guid_a[11];
|
|
guid_b[12] = guid_a[12];
|
|
guid_b[13] = guid_a[13];
|
|
guid_b[14] = guid_a[14];
|
|
guid_b[15] = guid_a[15];
|
|
supblk.journal_uuid = new Guid(guid_b);
|
|
supblk.journal_inode = BitConverter.ToUInt32(sb_sector, 0x0E0);
|
|
supblk.journal_dev = BitConverter.ToUInt32(sb_sector, 0x0E4);
|
|
supblk.last_orphan = BitConverter.ToUInt32(sb_sector, 0x0E8);
|
|
supblk.hash_seed_1 = BitConverter.ToUInt32(sb_sector, 0x0EC);
|
|
supblk.hash_seed_2 = BitConverter.ToUInt32(sb_sector, 0x0F0);
|
|
supblk.hash_seed_3 = BitConverter.ToUInt32(sb_sector, 0x0F4);
|
|
supblk.hash_seed_4 = BitConverter.ToUInt32(sb_sector, 0x0F8);
|
|
supblk.hash_version = sb_sector[0x0FC];
|
|
supblk.jnl_backup_type = sb_sector[0x0FD];
|
|
supblk.desc_grp_size = BitConverter.ToUInt16(sb_sector, 0x0FE);
|
|
supblk.default_mnt_opts = BitConverter.ToUInt32(sb_sector, 0x100);
|
|
supblk.first_meta_bg = BitConverter.ToUInt32(sb_sector, 0x104);
|
|
// ext4
|
|
supblk.mkfs_t = BitConverter.ToUInt32(sb_sector, 0x108);
|
|
supblk.blocks_hi = BitConverter.ToUInt32(sb_sector, 0x14C);
|
|
supblk.reserved_blocks_hi = BitConverter.ToUInt32(sb_sector, 0x150);
|
|
supblk.free_blocks_hi = BitConverter.ToUInt32(sb_sector, 0x154);
|
|
supblk.min_inode_size = BitConverter.ToUInt16(sb_sector, 0x158);
|
|
supblk.rsv_inode_size = BitConverter.ToUInt16(sb_sector, 0x15A);
|
|
supblk.flags = BitConverter.ToUInt32(sb_sector, 0x15C);
|
|
supblk.raid_stride = BitConverter.ToUInt16(sb_sector, 0x160);
|
|
supblk.mmp_interval = BitConverter.ToUInt16(sb_sector, 0x162);
|
|
supblk.mmp_block = BitConverter.ToUInt64(sb_sector, 0x164);
|
|
supblk.raid_stripe_width = BitConverter.ToUInt32(sb_sector, 0x16C);
|
|
supblk.flex_bg_grp_size = sb_sector[0x170];
|
|
supblk.kbytes_written = BitConverter.ToUInt64(sb_sector, 0x174);
|
|
supblk.snapshot_inum = BitConverter.ToUInt32(sb_sector, 0x17C);
|
|
supblk.snapshot_id = BitConverter.ToUInt32(sb_sector, 0x180);
|
|
supblk.snapshot_blocks = BitConverter.ToUInt64(sb_sector, 0x184);
|
|
supblk.snapshot_list = BitConverter.ToUInt32(sb_sector, 0x18C);
|
|
supblk.error_count = BitConverter.ToUInt32(sb_sector, 0x190);
|
|
supblk.first_error_t = BitConverter.ToUInt32(sb_sector, 0x194);
|
|
supblk.first_error_inode = BitConverter.ToUInt32(sb_sector, 0x198);
|
|
supblk.first_error_block = BitConverter.ToUInt64(sb_sector, 0x19C);
|
|
forstrings = new byte[32];
|
|
Array.Copy(sb_sector, 0x1A0, forstrings, 0, 32);
|
|
supblk.first_error_func = StringHandlers.CToString(forstrings);
|
|
supblk.first_error_line = BitConverter.ToUInt32(sb_sector, 0x1B0);
|
|
supblk.last_error_t = BitConverter.ToUInt32(sb_sector, 0x1B4);
|
|
supblk.last_error_inode = BitConverter.ToUInt32(sb_sector, 0x1B8);
|
|
supblk.last_error_line = BitConverter.ToUInt32(sb_sector, 0x1BC);
|
|
supblk.last_error_block = BitConverter.ToUInt64(sb_sector, 0x1C0);
|
|
forstrings = new byte[32];
|
|
Array.Copy(sb_sector, 0x1C8, forstrings, 0, 32);
|
|
supblk.last_error_func = StringHandlers.CToString(forstrings);
|
|
forstrings = new byte[64];
|
|
Array.Copy(sb_sector, 0x1D8, forstrings, 0, 64);
|
|
supblk.mount_options = StringHandlers.CToString(forstrings);
|
|
|
|
if (supblk.magic == ext2OldFSMagic)
|
|
{
|
|
sb.AppendLine("ext2 (old) filesystem");
|
|
}
|
|
else if (supblk.magic == ext2FSMagic)
|
|
{
|
|
ext3 |= (supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL || (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER || (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
|
|
|
|
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE ||
|
|
(supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM ||
|
|
(supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK ||
|
|
(supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE ||
|
|
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT ||
|
|
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP ||
|
|
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG ||
|
|
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE ||
|
|
(supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA)
|
|
{
|
|
ext3 = false;
|
|
ext4 = true;
|
|
}
|
|
|
|
new_ext2 |= !ext3 && !ext4;
|
|
|
|
if (new_ext2)
|
|
sb.AppendLine("ext2 filesystem");
|
|
if (ext3)
|
|
sb.AppendLine("ext3 filesystem");
|
|
if (ext4)
|
|
sb.AppendLine("ext4 filesystem");
|
|
}
|
|
else
|
|
{
|
|
information = "Not a ext2/3/4 filesystem" + Environment.NewLine;
|
|
return;
|
|
}
|
|
|
|
string ext_os;
|
|
switch (supblk.creator_os)
|
|
{
|
|
case EXT2_OS_FREEBSD:
|
|
ext_os = "FreeBSD";
|
|
break;
|
|
case EXT2_OS_HURD:
|
|
ext_os = "Hurd";
|
|
break;
|
|
case EXT2_OS_LINUX:
|
|
ext_os = "Linux";
|
|
break;
|
|
case EXT2_OS_LITES:
|
|
ext_os = "Lites";
|
|
break;
|
|
case EXT2_OS_MASIX:
|
|
ext_os = "MasIX";
|
|
break;
|
|
default:
|
|
ext_os = string.Format("Unknown OS ({0})", supblk.creator_os);
|
|
break;
|
|
}
|
|
|
|
if (supblk.mkfs_t > 0)
|
|
sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t), ext_os).AppendLine();
|
|
else
|
|
sb.AppendFormat("Volume was created for {0}", ext_os).AppendLine();
|
|
|
|
byte[] temp_lo, temp_hi;
|
|
byte[] temp_bytes = new byte[8];
|
|
UInt64 blocks, reserved, free;
|
|
|
|
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
|
|
{
|
|
temp_lo = BitConverter.GetBytes(supblk.blocks);
|
|
temp_hi = BitConverter.GetBytes(supblk.blocks_hi);
|
|
temp_bytes[0] = temp_lo[0];
|
|
temp_bytes[1] = temp_lo[1];
|
|
temp_bytes[2] = temp_lo[2];
|
|
temp_bytes[3] = temp_lo[3];
|
|
temp_bytes[4] = temp_hi[0];
|
|
temp_bytes[5] = temp_hi[1];
|
|
temp_bytes[6] = temp_hi[2];
|
|
temp_bytes[7] = temp_hi[3];
|
|
blocks = BitConverter.ToUInt64(temp_bytes, 0);
|
|
|
|
temp_lo = BitConverter.GetBytes(supblk.reserved_blocks);
|
|
temp_hi = BitConverter.GetBytes(supblk.reserved_blocks_hi);
|
|
temp_bytes[0] = temp_lo[0];
|
|
temp_bytes[1] = temp_lo[1];
|
|
temp_bytes[2] = temp_lo[2];
|
|
temp_bytes[3] = temp_lo[3];
|
|
temp_bytes[4] = temp_hi[0];
|
|
temp_bytes[5] = temp_hi[1];
|
|
temp_bytes[6] = temp_hi[2];
|
|
temp_bytes[7] = temp_hi[3];
|
|
reserved = BitConverter.ToUInt64(temp_bytes, 0);
|
|
|
|
temp_lo = BitConverter.GetBytes(supblk.free_blocks);
|
|
temp_hi = BitConverter.GetBytes(supblk.free_blocks_hi);
|
|
temp_bytes[0] = temp_lo[0];
|
|
temp_bytes[1] = temp_lo[1];
|
|
temp_bytes[2] = temp_lo[2];
|
|
temp_bytes[3] = temp_lo[3];
|
|
temp_bytes[4] = temp_hi[0];
|
|
temp_bytes[5] = temp_hi[1];
|
|
temp_bytes[6] = temp_hi[2];
|
|
temp_bytes[7] = temp_hi[3];
|
|
free = BitConverter.ToUInt64(temp_bytes, 0);
|
|
}
|
|
else
|
|
{
|
|
blocks = supblk.blocks;
|
|
reserved = supblk.reserved_blocks;
|
|
free = supblk.free_blocks;
|
|
}
|
|
|
|
if (supblk.block_size == 0) // Then it is 1024 bytes
|
|
supblk.block_size = 1024;
|
|
|
|
sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks, supblk.block_size, blocks * supblk.block_size).AppendLine();
|
|
if (supblk.mount_t > 0 || supblk.mount_c > 0)
|
|
{
|
|
if (supblk.mount_t > 0)
|
|
sb.AppendFormat("Last mounted on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.mount_t)).AppendLine();
|
|
if (supblk.max_mount_c != -1)
|
|
sb.AppendFormat("Volume has been mounted {0} times of a maximum of {1} mounts before checking", supblk.mount_c, supblk.max_mount_c).AppendLine();
|
|
else
|
|
sb.AppendFormat("Volume has been mounted {0} times with no maximum no. of mounts before checking", supblk.mount_c).AppendLine();
|
|
if (supblk.last_mount_dir != "")
|
|
sb.AppendFormat("Last mounted on: \"{0}\"", supblk.last_mount_dir).AppendLine();
|
|
if (supblk.mount_options != "")
|
|
sb.AppendFormat("Last used mount options were: {0}", supblk.mount_options).AppendLine();
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine("Volume has never been mounted");
|
|
if (supblk.max_mount_c != -1)
|
|
sb.AppendFormat("Volume can be mounted {0} times before checking", supblk.max_mount_c).AppendLine();
|
|
else
|
|
sb.AppendLine("Volume has no maximum no. of mounts before checking");
|
|
}
|
|
|
|
if (supblk.check_t > 0)
|
|
{
|
|
if (supblk.check_inv > 0)
|
|
sb.AppendFormat("Last checked on {0} (should check every {1} seconds)", DateHandlers.UNIXUnsignedToDateTime(supblk.check_t), supblk.check_inv).AppendLine();
|
|
else
|
|
sb.AppendFormat("Last checked on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.check_t)).AppendLine();
|
|
}
|
|
else
|
|
{
|
|
if (supblk.check_inv > 0)
|
|
sb.AppendFormat("Volume has never been checked (should check every {0})", supblk.check_inv).AppendLine();
|
|
else
|
|
sb.AppendLine("Volume has never been checked");
|
|
}
|
|
|
|
if (supblk.write_t > 0)
|
|
sb.AppendFormat("Last written on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.write_t)).AppendLine();
|
|
else
|
|
sb.AppendLine("Volume has never been written");
|
|
|
|
switch (supblk.state)
|
|
{
|
|
case EXT2_VALID_FS:
|
|
sb.AppendLine("Volume is clean");
|
|
break;
|
|
case EXT2_ERROR_FS:
|
|
sb.AppendLine("Volume is dirty");
|
|
break;
|
|
case EXT3_ORPHAN_FS:
|
|
sb.AppendLine("Volume is recovering orphan files");
|
|
break;
|
|
default:
|
|
sb.AppendFormat("Volume is in an unknown state ({0})", supblk.state).AppendLine();
|
|
break;
|
|
}
|
|
|
|
if (supblk.volume_name != "")
|
|
sb.AppendFormat("Volume name: \"{0}\"", supblk.volume_name).AppendLine();
|
|
|
|
switch (supblk.err_behaviour)
|
|
{
|
|
case EXT2_ERRORS_CONTINUE:
|
|
sb.AppendLine("On errors, filesystem should continue");
|
|
break;
|
|
case EXT2_ERRORS_RO:
|
|
sb.AppendLine("On errors, filesystem should remount read-only");
|
|
break;
|
|
case EXT2_ERRORS_PANIC:
|
|
sb.AppendLine("On errors, filesystem should panic");
|
|
break;
|
|
default:
|
|
sb.AppendFormat("On errors filesystem will do an unknown thing ({0})", supblk.err_behaviour).AppendLine();
|
|
break;
|
|
}
|
|
|
|
if (supblk.revision > 0)
|
|
sb.AppendFormat("Filesystem revision: {0}.{1}", supblk.revision, supblk.minor_revision).AppendLine();
|
|
|
|
if (supblk.uuid != Guid.Empty)
|
|
sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine();
|
|
|
|
if (supblk.kbytes_written > 0)
|
|
sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine();
|
|
|
|
sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine();
|
|
sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes, supblk.free_inodes * 100 / supblk.inodes).AppendLine();
|
|
if (supblk.first_inode > 0)
|
|
sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine();
|
|
if (supblk.frag_size > 0)
|
|
sb.AppendFormat("{0} bytes per fragment", supblk.frag_size).AppendLine();
|
|
if (supblk.blocks_per_grp > 0 && supblk.flags_per_grp > 0 && supblk.inodes_per_grp > 0)
|
|
sb.AppendFormat("{0} blocks, {1} flags and {2} inodes per group", supblk.blocks_per_grp, supblk.flags_per_grp, supblk.inodes_per_grp).AppendLine();
|
|
if (supblk.first_block > 0)
|
|
sb.AppendFormat("{0} is first data block", supblk.first_block).AppendLine();
|
|
sb.AppendFormat("Default UID: {0}, GID: {1}", supblk.default_uid, supblk.default_gid).AppendLine();
|
|
if (supblk.block_group_no > 0)
|
|
sb.AppendFormat("Block group number is {0}", supblk.block_group_no).AppendLine();
|
|
if (supblk.desc_grp_size > 0)
|
|
sb.AppendFormat("Group descriptor size is {0} bytes", supblk.desc_grp_size).AppendLine();
|
|
if (supblk.first_meta_bg > 0)
|
|
sb.AppendFormat("First metablock group is {0}", supblk.first_meta_bg).AppendLine();
|
|
if (supblk.raid_stride > 0)
|
|
sb.AppendFormat("RAID stride: {0}", supblk.raid_stride).AppendLine();
|
|
if (supblk.raid_stripe_width > 0)
|
|
sb.AppendFormat("{0} blocks on all data disks", supblk.raid_stripe_width).AppendLine();
|
|
if (supblk.mmp_interval > 0 && supblk.mmp_block > 0)
|
|
sb.AppendFormat("{0} seconds for multi-mount protection wait, on block {1}", supblk.mmp_interval, supblk.mmp_block).AppendLine();
|
|
if (supblk.flex_bg_grp_size > 0)
|
|
sb.AppendFormat("{0} Flexible block group size", supblk.flex_bg_grp_size).AppendLine();
|
|
if (supblk.hash_seed_1 > 0 && supblk.hash_seed_2 > 0 && supblk.hash_seed_3 > 0 && supblk.hash_seed_4 > 0)
|
|
sb.AppendFormat("Hash seed: {0:X8}{1:X8}{2:X8}{3:X8}, version {4}", supblk.hash_seed_1, supblk.hash_seed_2, supblk.hash_seed_3, supblk.hash_seed_4, supblk.hash_version).AppendLine();
|
|
|
|
if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL ||
|
|
(supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
|
{
|
|
sb.AppendLine("Volume is journaled");
|
|
if (supblk.journal_uuid != Guid.Empty)
|
|
sb.AppendFormat("Journal UUID: {0}", supblk.journal_uuid).AppendLine();
|
|
sb.AppendFormat("Journal has inode {0}", supblk.journal_inode).AppendLine();
|
|
if ((supblk.ftr_compat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV && supblk.journal_dev > 0)
|
|
sb.AppendFormat("Journal is on device {0}", supblk.journal_dev).AppendLine();
|
|
if (supblk.jnl_backup_type > 0)
|
|
sb.AppendFormat("Journal backup type: {0}", supblk.jnl_backup_type).AppendLine();
|
|
if (supblk.last_orphan > 0)
|
|
sb.AppendFormat("Last orphaned inode is {0}", supblk.last_orphan).AppendLine();
|
|
else
|
|
sb.AppendLine("There are no orphaned inodes");
|
|
}
|
|
|
|
if (ext4)
|
|
{
|
|
if (supblk.snapshot_id > 0)
|
|
sb.AppendFormat("Active snapshot has ID {0}, on inode {1}, with {2} blocks reserved, list starting on block {3}", supblk.snapshot_id,
|
|
supblk.snapshot_inum, supblk.snapshot_blocks, supblk.snapshot_list).AppendLine();
|
|
|
|
if (supblk.error_count > 0)
|
|
{
|
|
sb.AppendFormat("{0} errors registered", supblk.error_count).AppendLine();
|
|
sb.AppendFormat("First error occurred on {0}, last on {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.first_error_t), DateHandlers.UNIXUnsignedToDateTime(supblk.last_error_t)).AppendLine();
|
|
sb.AppendFormat("First error inode is {0}, last is {1}", supblk.first_error_inode, supblk.last_error_inode).AppendLine();
|
|
sb.AppendFormat("First error block is {0}, last is {1}", supblk.first_error_block, supblk.last_error_block).AppendLine();
|
|
sb.AppendFormat("First error function is \"{0}\", last is \"{1}\"", supblk.first_error_func, supblk.last_error_func).AppendLine();
|
|
}
|
|
}
|
|
|
|
sb.AppendFormat("Flags…:").AppendLine();
|
|
if ((supblk.flags & EXT2_FLAGS_SIGNED_HASH) == EXT2_FLAGS_SIGNED_HASH)
|
|
sb.AppendLine("Signed directory hash is in use");
|
|
if ((supblk.flags & EXT2_FLAGS_UNSIGNED_HASH) == EXT2_FLAGS_UNSIGNED_HASH)
|
|
sb.AppendLine("Unsigned directory hash is in use");
|
|
if ((supblk.flags & EXT2_FLAGS_TEST_FILESYS) == EXT2_FLAGS_TEST_FILESYS)
|
|
sb.AppendLine("Volume is testing development code");
|
|
if ((supblk.flags & 0xFFFFFFF8) != 0)
|
|
sb.AppendFormat("Unknown set flags: {0:X8}", supblk.flags);
|
|
|
|
sb.AppendLine();
|
|
|
|
sb.AppendFormat("Default mount options…:").AppendLine();
|
|
if ((supblk.default_mnt_opts & EXT2_DEFM_DEBUG) == EXT2_DEFM_DEBUG)
|
|
sb.AppendLine("(debug): Enable debugging code");
|
|
if ((supblk.default_mnt_opts & EXT2_DEFM_BSDGROUPS) == EXT2_DEFM_BSDGROUPS)
|
|
sb.AppendLine("(bsdgroups): Emulate BSD behaviour when creating new files");
|
|
if ((supblk.default_mnt_opts & EXT2_DEFM_XATTR_USER) == EXT2_DEFM_XATTR_USER)
|
|
sb.AppendLine("(user_xattr): Enable user-specified extended attributes");
|
|
if ((supblk.default_mnt_opts & EXT2_DEFM_ACL) == EXT2_DEFM_ACL)
|
|
sb.AppendLine("(acl): Enable POSIX ACLs");
|
|
if ((supblk.default_mnt_opts & EXT2_DEFM_UID16) == EXT2_DEFM_UID16)
|
|
sb.AppendLine("(uid16): Disable 32bit UIDs and GIDs");
|
|
if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_DATA) == EXT3_DEFM_JMODE_DATA)
|
|
sb.AppendLine("(journal_data): Journal data and metadata");
|
|
if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_ORDERED) == EXT3_DEFM_JMODE_ORDERED)
|
|
sb.AppendLine("(journal_data_ordered): Write data before journaling metadata");
|
|
if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_WBACK) == EXT3_DEFM_JMODE_WBACK)
|
|
sb.AppendLine("(journal_data_writeback): Write journal before data");
|
|
if ((supblk.default_mnt_opts & 0xFFFFFE20) != 0)
|
|
sb.AppendFormat("Unknown set default mount options: {0:X8}", supblk.default_mnt_opts);
|
|
|
|
sb.AppendLine();
|
|
|
|
sb.AppendFormat("Compatible features…:").AppendLine();
|
|
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_PREALLOC) == EXT2_FEATURE_COMPAT_DIR_PREALLOC)
|
|
sb.AppendLine("Pre-allocate directories");
|
|
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES) == EXT2_FEATURE_COMPAT_IMAGIC_INODES)
|
|
sb.AppendLine("imagic inodes ?");
|
|
if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL)
|
|
sb.AppendLine("Has journal (ext3)");
|
|
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) == EXT2_FEATURE_COMPAT_EXT_ATTR)
|
|
sb.AppendLine("Has extended attribute blocks");
|
|
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) == EXT2_FEATURE_COMPAT_RESIZE_INO)
|
|
sb.AppendLine("Has online filesystem resize reservations");
|
|
if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) == EXT2_FEATURE_COMPAT_DIR_INDEX)
|
|
sb.AppendLine("Can use hashed indexes on directories");
|
|
if ((supblk.ftr_compat & 0xFFFFFFC0) != 0)
|
|
sb.AppendFormat("Unknown compatible features: {0:X8}", supblk.ftr_compat);
|
|
|
|
sb.AppendLine();
|
|
|
|
sb.AppendFormat("Compatible features if read-only…:").AppendLine();
|
|
if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) == EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
|
|
sb.AppendLine("Reduced number of superblocks");
|
|
if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
|
|
sb.AppendLine("Can have files bigger than 2GiB");
|
|
if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_BTREE_DIR) == EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
|
sb.AppendLine("Uses B-Tree for directories");
|
|
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
|
|
sb.AppendLine("Can have files bigger than 2TiB (ext4)");
|
|
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
|
|
sb.AppendLine("Group descriptor checksums and sparse inode table (ext4)");
|
|
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
|
|
sb.AppendLine("More than 32000 directory entries (ext4)");
|
|
if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
|
|
sb.AppendLine("Supports nanosecond timestamps and creation time (ext4)");
|
|
if ((supblk.ftr_ro_compat & 0xFFFFFF80) != 0)
|
|
sb.AppendFormat("Unknown read-only compatible features: {0:X8}", supblk.ftr_ro_compat);
|
|
|
|
sb.AppendLine();
|
|
|
|
sb.AppendFormat("Incompatible features…:").AppendLine();
|
|
if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION) == EXT2_FEATURE_INCOMPAT_COMPRESSION)
|
|
sb.AppendLine("Uses compression");
|
|
if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) == EXT2_FEATURE_INCOMPAT_FILETYPE)
|
|
sb.AppendLine("Filetype in directory entries");
|
|
if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER)
|
|
sb.AppendLine("Journal needs recovery (ext3)");
|
|
if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
|
sb.AppendLine("Has journal on another device (ext3)");
|
|
if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_META_BG) == EXT2_FEATURE_INCOMPAT_META_BG)
|
|
sb.AppendLine("Reduced block group backups");
|
|
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS) == EXT4_FEATURE_INCOMPAT_EXTENTS)
|
|
sb.AppendLine("Volume use extents (ext4)");
|
|
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
|
|
sb.AppendLine("Supports volumes bigger than 2^32 blocks (ext4)");
|
|
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP)
|
|
sb.AppendLine("Multi-mount protection (ext4)");
|
|
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG)
|
|
sb.AppendLine("Flexible block group metadata location (ext4)");
|
|
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE)
|
|
sb.AppendLine("Extended attributes can reside in inode (ext4)");
|
|
if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA)
|
|
sb.AppendLine("Data can reside in directory entry (ext4)");
|
|
if ((supblk.ftr_incompat & 0xFFFFF020) != 0)
|
|
sb.AppendFormat("Unknown incompatible features: {0:X8}", supblk.ftr_incompat);
|
|
|
|
information = sb.ToString();
|
|
}
|
|
|
|
public const UInt16 ext2FSMagic = 0xEF53;
|
|
// Same for ext3 and ext4
|
|
public const UInt16 ext2OldFSMagic = 0xEF51;
|
|
// Size = 536 bytes
|
|
public struct ext2FSSuperBlock
|
|
{
|
|
public UInt32 inodes;
|
|
// 0x000, inodes on volume
|
|
public UInt32 blocks;
|
|
// 0x004, blocks on volume
|
|
public UInt32 reserved_blocks;
|
|
// 0x008, reserved blocks
|
|
public UInt32 free_blocks;
|
|
// 0x00C, free blocks count
|
|
public UInt32 free_inodes;
|
|
// 0x010, free inodes count
|
|
public UInt32 first_block;
|
|
// 0x014, first data block
|
|
public UInt32 block_size;
|
|
// 0x018, block size
|
|
public Int32 frag_size;
|
|
// 0x01C, fragment size
|
|
public UInt32 blocks_per_grp;
|
|
// 0x020, blocks per group
|
|
public UInt32 flags_per_grp;
|
|
// 0x024, fragments per group
|
|
public UInt32 inodes_per_grp;
|
|
// 0x028, inodes per group
|
|
public UInt32 mount_t;
|
|
// 0x02C, last mount time
|
|
public UInt32 write_t;
|
|
// 0x030, last write time
|
|
public UInt16 mount_c;
|
|
// 0x034, mounts count
|
|
public Int16 max_mount_c;
|
|
// 0x036, max mounts
|
|
public UInt16 magic;
|
|
// 0x038, (little endian)
|
|
public UInt16 state;
|
|
// 0x03A, filesystem state
|
|
public UInt16 err_behaviour;
|
|
// 0x03C, behaviour on errors
|
|
public UInt16 minor_revision;
|
|
// 0x03E, From 0.5b onward
|
|
public UInt32 check_t;
|
|
// 0x040, last check time
|
|
public UInt32 check_inv;
|
|
// 0x044, max time between checks
|
|
// From 0.5a onward
|
|
public UInt32 creator_os;
|
|
// 0x048, Creation OS
|
|
public UInt32 revision;
|
|
// 0x04C, Revison level
|
|
public UInt16 default_uid;
|
|
// 0x050, Default UID for reserved blocks
|
|
public UInt16 default_gid;
|
|
// 0x052, Default GID for reserved blocks
|
|
// From 0.5b onward
|
|
public UInt32 first_inode;
|
|
// 0x054, First unreserved inode
|
|
public UInt16 inode_size;
|
|
// 0x058, inode size
|
|
public UInt16 block_group_no;
|
|
// 0x05A, Block group number of THIS superblock
|
|
public UInt32 ftr_compat;
|
|
// 0x05C, Compatible features set
|
|
public UInt32 ftr_incompat;
|
|
// 0x060, Incompatible features set
|
|
// Found on Linux 2.0.40
|
|
public UInt32 ftr_ro_compat;
|
|
// 0x064, Read-only compatible features set
|
|
// Found on Linux 2.1.132
|
|
public Guid uuid;
|
|
// 0x068, 16 bytes, UUID
|
|
public string volume_name;
|
|
// 0x078, 16 bytes, volume name
|
|
public string last_mount_dir;
|
|
// 0x088, 64 bytes, where last mounted
|
|
public UInt32 algo_usage_bmp;
|
|
// 0x0C8, Usage bitmap algorithm, for compression
|
|
public byte prealloc_blks;
|
|
// 0x0CC, Block to try to preallocate
|
|
public byte prealloc_dir_blks;
|
|
// 0x0CD, Blocks to try to preallocate for directories
|
|
public UInt16 rsrvd_gdt_blocks;
|
|
// 0x0CE, Per-group desc for online growth
|
|
// Found on Linux 2.4
|
|
// ext3
|
|
public Guid journal_uuid;
|
|
// 0x0D0, 16 bytes, UUID of journal superblock
|
|
public UInt32 journal_inode;
|
|
// 0x0E0, inode no. of journal file
|
|
public UInt32 journal_dev;
|
|
// 0x0E4, device no. of journal file
|
|
public UInt32 last_orphan;
|
|
// 0x0E8, Start of list of inodes to delete
|
|
public UInt32 hash_seed_1;
|
|
// 0x0EC, First byte of 128bit HTREE hash seed
|
|
public UInt32 hash_seed_2;
|
|
// 0x0F0, Second byte of 128bit HTREE hash seed
|
|
public UInt32 hash_seed_3;
|
|
// 0x0F4, Third byte of 128bit HTREE hash seed
|
|
public UInt32 hash_seed_4;
|
|
// 0x0F8, Fourth byte of 128bit HTREE hash seed
|
|
public byte hash_version;
|
|
// 0x0FC, Hash version
|
|
public byte jnl_backup_type;
|
|
// 0x0FD, Journal backup type
|
|
public UInt16 desc_grp_size;
|
|
// 0x0FE, Size of group descriptor
|
|
public UInt32 default_mnt_opts;
|
|
// 0x100, Default mount options
|
|
public UInt32 first_meta_bg;
|
|
// 0x104, First metablock block group
|
|
// Introduced with ext4, some can be ext3
|
|
public UInt32 mkfs_t;
|
|
// 0x108, Filesystem creation time
|
|
// Follows 17 uint32 (68 bytes) of journal inode backup
|
|
// Following 3 fields are valid if EXT4_FEATURE_COMPAT_64BIT is set
|
|
public UInt32 blocks_hi;
|
|
// 0x14C, High 32bits of blocks no.
|
|
public UInt32 reserved_blocks_hi;
|
|
// 0x150, High 32bits of reserved blocks no.
|
|
public UInt32 free_blocks_hi;
|
|
// 0x154, High 32bits of free blocks no.
|
|
public UInt16 min_inode_size;
|
|
// 0x158, inodes minimal size in bytes
|
|
public UInt16 rsv_inode_size;
|
|
// 0x15A, Bytes reserved by new inodes
|
|
public UInt32 flags;
|
|
// 0x15C, Flags
|
|
public UInt16 raid_stride;
|
|
// 0x160, RAID stride
|
|
public UInt16 mmp_interval;
|
|
// 0x162, Waiting seconds in MMP check
|
|
public UInt64 mmp_block;
|
|
// 0x164, Block for multi-mount protection
|
|
public UInt32 raid_stripe_width;
|
|
// 0x16C, Blocks on all data disks (N*stride)
|
|
public byte flex_bg_grp_size;
|
|
// 0x170, FLEX_BG group size
|
|
public byte padding;
|
|
// 0x171
|
|
public UInt16 padding2;
|
|
// 0x172
|
|
// Following are introduced with ext4
|
|
public UInt64 kbytes_written;
|
|
// 0x174, Kibibytes written in volume lifetime
|
|
public UInt32 snapshot_inum;
|
|
// 0x17C, Active snapshot inode number
|
|
public UInt32 snapshot_id;
|
|
// 0x180, Active snapshot sequential ID
|
|
public UInt64 snapshot_blocks;
|
|
// 0x184, Reserved blocks for active snapshot's future use
|
|
public UInt32 snapshot_list;
|
|
// 0x18C, inode number of the on-disk start of the snapshot list
|
|
// Optional ext4 error-handling features
|
|
public UInt32 error_count;
|
|
// 0x190, total registered filesystem errors
|
|
public UInt32 first_error_t;
|
|
// 0x194, time on first error
|
|
public UInt32 first_error_inode;
|
|
// 0x198, inode involved in first error
|
|
public UInt64 first_error_block;
|
|
// 0x19C, block involved of first error
|
|
public string first_error_func;
|
|
// 0x1A0, 32 bytes, function where the error happened
|
|
public UInt32 first_error_line;
|
|
// 0x1B0, line number where error happened
|
|
public UInt32 last_error_t;
|
|
// 0x1B4, time of most recent error
|
|
public UInt32 last_error_inode;
|
|
// 0x1B8, inode involved in last error
|
|
public UInt32 last_error_line;
|
|
// 0x1BC, line number where error happened
|
|
public UInt64 last_error_block;
|
|
// 0x1C0, block involved of last error
|
|
public string last_error_func;
|
|
// 0x1C8, 32 bytes, function where the error happened
|
|
// End of optional error-handling features
|
|
public string mount_options;
|
|
// 0x1D8, 64 bytes, last used mount options
|
|
}
|
|
// ext? filesystem states
|
|
public const UInt16 EXT2_VALID_FS = 0x0001;
|
|
// Cleanly-unmounted volume
|
|
public const UInt16 EXT2_ERROR_FS = 0x0002;
|
|
// Dirty volume
|
|
public const UInt16 EXT3_ORPHAN_FS = 0x0004;
|
|
// Recovering orphan files
|
|
// ext? default mount flags
|
|
public const UInt32 EXT2_DEFM_DEBUG = 0x000001;
|
|
// Enable debugging messages
|
|
public const UInt32 EXT2_DEFM_BSDGROUPS = 0x000002;
|
|
// Emulates BSD behaviour on new file creation
|
|
public const UInt32 EXT2_DEFM_XATTR_USER = 0x000004;
|
|
// Enable user xattrs
|
|
public const UInt32 EXT2_DEFM_ACL = 0x000008;
|
|
// Enable POSIX ACLs
|
|
public const UInt32 EXT2_DEFM_UID16 = 0x000010;
|
|
// Use 16bit UIDs
|
|
public const UInt32 EXT3_DEFM_JMODE_DATA = 0x000040;
|
|
// Journal data mode
|
|
public const UInt32 EXT3_DEFM_JMODE_ORDERED = 0x000080;
|
|
// Journal ordered mode
|
|
public const UInt32 EXT3_DEFM_JMODE_WBACK = 0x000100;
|
|
// Journal writeback mode
|
|
// Behaviour on errors
|
|
public const UInt16 EXT2_ERRORS_CONTINUE = 1;
|
|
// Continue execution
|
|
public const UInt16 EXT2_ERRORS_RO = 2;
|
|
// Remount fs read-only
|
|
public const UInt16 EXT2_ERRORS_PANIC = 3;
|
|
// Panic
|
|
// OS codes
|
|
public const UInt32 EXT2_OS_LINUX = 0;
|
|
public const UInt32 EXT2_OS_HURD = 1;
|
|
public const UInt32 EXT2_OS_MASIX = 2;
|
|
public const UInt32 EXT2_OS_FREEBSD = 3;
|
|
public const UInt32 EXT2_OS_LITES = 4;
|
|
// Revision levels
|
|
public const UInt32 EXT2_GOOD_OLD_REV = 0;
|
|
/* The good old (original) format */
|
|
public const UInt32 EXT2_DYNAMIC_REV = 1;
|
|
/* V2 format w/ dynamic inode sizes */
|
|
// Compatible features
|
|
public const UInt32 EXT2_FEATURE_COMPAT_DIR_PREALLOC = 0x00000001;
|
|
// Pre-allocate directories
|
|
public const UInt32 EXT2_FEATURE_COMPAT_IMAGIC_INODES = 0x00000002;
|
|
// imagic inodes ?
|
|
public const UInt32 EXT3_FEATURE_COMPAT_HAS_JOURNAL = 0x00000004;
|
|
// Has journal (it's ext3)
|
|
public const UInt32 EXT2_FEATURE_COMPAT_EXT_ATTR = 0x00000008;
|
|
// EA blocks
|
|
public const UInt32 EXT2_FEATURE_COMPAT_RESIZE_INO = 0x00000010;
|
|
// Online filesystem resize reservations
|
|
public const UInt32 EXT2_FEATURE_COMPAT_DIR_INDEX = 0x00000020;
|
|
// Can use hashed indexes on directories
|
|
// Read-only compatible features
|
|
public const UInt32 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x00000001;
|
|
// Reduced number of superblocks
|
|
public const UInt32 EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x00000002;
|
|
// Can have files bigger than 2GiB
|
|
public const UInt32 EXT2_FEATURE_RO_COMPAT_BTREE_DIR = 0x00000004;
|
|
// Use B-Tree for directories
|
|
public const UInt32 EXT4_FEATURE_RO_COMPAT_HUGE_FILE = 0x00000008;
|
|
// Can have files bigger than 2TiB *ext4*
|
|
public const UInt32 EXT4_FEATURE_RO_COMPAT_GDT_CSUM = 0x00000010;
|
|
// Group descriptor checksums and sparse inode table *ext4*
|
|
public const UInt32 EXT4_FEATURE_RO_COMPAT_DIR_NLINK = 0x00000020;
|
|
// More than 32000 directory entries *ext4*
|
|
public const UInt32 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE = 0x00000040;
|
|
// Nanosecond timestamps and creation time *ext4*
|
|
// Incompatible features
|
|
public const UInt32 EXT2_FEATURE_INCOMPAT_COMPRESSION = 0x00000001;
|
|
// Uses compression
|
|
public const UInt32 EXT2_FEATURE_INCOMPAT_FILETYPE = 0x00000002;
|
|
// Filetype in directory entries
|
|
public const UInt32 EXT3_FEATURE_INCOMPAT_RECOVER = 0x00000004;
|
|
// Journal needs recovery *ext3*
|
|
public const UInt32 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV = 0x00000008;
|
|
// Has journal on another device *ext3*
|
|
public const UInt32 EXT2_FEATURE_INCOMPAT_META_BG = 0x00000010;
|
|
// Reduced block group backups
|
|
public const UInt32 EXT4_FEATURE_INCOMPAT_EXTENTS = 0x00000040;
|
|
// Volume use extents *ext4*
|
|
public const UInt32 EXT4_FEATURE_INCOMPAT_64BIT = 0x00000080;
|
|
// Supports volumes bigger than 2^32 blocks *ext4*
|
|
public const UInt32 EXT4_FEATURE_INCOMPAT_MMP = 0x00000100;
|
|
// Multi-mount protection *ext4*
|
|
public const UInt32 EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x00000200;
|
|
// Flexible block group metadata location *ext4*
|
|
public const UInt32 EXT4_FEATURE_INCOMPAT_EA_INODE = 0x00000400;
|
|
// EA in inode *ext4*
|
|
public const UInt32 EXT4_FEATURE_INCOMPAT_DIRDATA = 0x00001000;
|
|
// Data can reside in directory entry *ext4*
|
|
// Miscellaneous filesystem flags
|
|
public const UInt32 EXT2_FLAGS_SIGNED_HASH = 0x00000001;
|
|
// Signed dirhash in use
|
|
public const UInt32 EXT2_FLAGS_UNSIGNED_HASH = 0x00000002;
|
|
// Unsigned dirhash in use
|
|
public const UInt32 EXT2_FLAGS_TEST_FILESYS = 0x00000004;
|
|
// Testing development code
|
|
}
|
|
} |